1 /*
2 * Copyright (c) 2006-2007 Creative Sphere Limited.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 *
10 * Creative Sphere - initial API and implementation
11 *
12 */
13 package org.abstracthorizon.danube.webdav.util;
14
15 import org.abstracthorizon.danube.http.HTTPConnection;
16 import org.abstracthorizon.danube.webdav.ResourceAdapter;
17 import org.abstracthorizon.danube.webdav.lock.LockingMechanism;
18
19 import java.util.HashSet;
20 import java.util.Set;
21
22 /**
23 * This object represents "If" header of WebDAV specification.
24 *
25 * @author Daniel Sendula
26 */
27 public class IF {
28
29 /** Collected token of a main resource. May be <code>null</code> */
30 public String token;
31
32 /** Collected token of a parent resource. May be <code>null</code> */
33 public String parentToken;
34
35 /** Collection of resource that was cleared. May be <code>null</code> */
36 public Set<Object> clearedResources;
37
38 /** <code>true<code> if header parsing wasn't successful */
39 public boolean error;
40
41 /**
42 * Parses "if" header and checks if values correspond
43 * to given resource.
44 *
45 * It returns lock token of supplied main resource. If it failed
46 * <code>null</code> will be returned.
47 *
48 * @param httpConnection http connection
49 * @param adapter resource adapter
50 * @param mainResource main resource
51 * @param parentResource parent resource. May be null.
52 * @param header if header
53 * @return lock token of supplied main resource or <code>null</code>
54 */
55 public boolean parse(HTTPConnection httpConnection, ResourceAdapter adapter, Object mainResource, Object parentResource) {
56 String[] ifs = httpConnection.getRequestHeaders().getAsArray("If");
57 if ((ifs == null) || (ifs.length == 0)) {
58 return true;
59 // if (adapter.getLockingMechanism().isLocked(mainResource)) {
60 // error = true;
61 // return false;
62 // } else {
63 // return true;
64 // }
65 }
66 int len = 0;
67 for (String s : ifs) {
68 len = len + s.length() + 1;
69 }
70 char[] header = new char[len];
71 len = 0;
72 for (String s : ifs) {
73 s.getChars(0, s.length(), header, len);
74 len = len + s.length();
75 header[len] = ' ';
76 len = len + 1;
77 }
78 return parse(httpConnection, adapter, mainResource, parentResource, header);
79 }
80
81 /**
82 * Parses "if" header and checks if values correspond
83 * to given resource.
84 *
85 * It returns lock token of supplied main resource. If it failed
86 * <code>null</code> will be returned.
87 *
88 * @param httpConnection http connection
89 * @param adapter resource adapter
90 * @param mainResource main resource
91 * @param parentResource parent resource. May be null.
92 * @param header if header
93 * @return lock token of supplied main resource or <code>null</code>
94 */
95 public boolean parse(HTTPConnection httpConnection, ResourceAdapter adapter, Object mainResource, Object parentResource, char[] buf) {
96 boolean orResult = false;
97 boolean andResult = true;
98 boolean parentCleared = (parentResource == null);
99
100 char[] temp = new char[buf.length];
101 int tp = 0;
102 int p = 0;
103 int state = 0;
104 Object currentResource = null;
105 boolean not = false;
106
107 while (p < buf.length) {
108 char c = buf[p];
109 if (state == 0) {
110 if (c == ' ') {
111 // ignore spaces
112 } else if (c == '<') {
113 if ((currentResource != null) && !orResult) {
114 // it is not first resource and result is still false.
115 error = true;
116 return false;
117 }
118 tp = 0;
119 state = 1;
120 } else if (c == '(') {
121 andResult = true;
122 if (currentResource == null) {
123 currentResource = mainResource;
124 }
125 not = false;
126 state = 4;
127 } else {
128 p = buf.length;
129 }
130 } else if (state == 1) {
131 if (c == '>') {
132 if (tp == 0) {
133 error = true;
134 return false;
135 }
136 String uriString = new String(temp, 0, tp);
137 tp = 0;
138 currentResource = URIUtils.uriToResource(httpConnection, adapter, uriString);
139 if (currentResource == null) {
140 error = true;
141 return false;
142 }
143 state = 3;
144 } else {
145 temp[tp] = c;
146 tp++;
147 }
148 } else if (state == 3) {
149 if (c == ' ') {
150 } else if (c == '(') {
151 andResult = true;
152 not = false;
153 state = 4;
154 } else {
155 error = true;
156 return false;
157 }
158 } else if (state == 4) {
159 if (c == ' ') {
160 // ignore
161 } else if (c == 'N') {
162 state = 5;
163 } else if (c == '<') {
164 not = false;
165 state = 8;
166 tp = 0;
167 } else if (c == '[') {
168 not = false;
169 tp = 0;
170 state = 9;
171 } else if (c == ')') {
172 orResult = orResult || andResult;
173 state = 0;
174 } else {
175 error = true;
176 return false;
177 }
178 } else if (state == 5) {
179 if (c == 'o') {
180 state = 6;
181 } else {
182 return false;
183 }
184 } else if (state == 6) {
185 if (c == 't') {
186 not = true;
187 state = 7;
188 } else {
189 return false;
190 }
191 } else if (state == 7) {
192 if (c == ' ') {
193 // ignore
194 } else if (c == '<') {
195 tp = 0;
196 state = 8;
197 } else if (c == '[') {
198 tp = 0;
199 state = 9;
200 }
201 } else if (state == 8) {
202 if (c == '>') {
203 if (tp == 0) {
204 return false;
205 }
206 String tokenString = new String(temp, 0, tp);
207 tp = 0;
208
209 LockingMechanism lockingMechanism = adapter.getLockingMechanism();
210 if (lockingMechanism.isAccessAllowed(currentResource, tokenString)) {
211 if (not) {
212 andResult = false;
213 } else {
214 if (currentResource == mainResource) {
215 token = tokenString;
216 } else if (currentResource == parentResource) {
217 parentCleared = true;
218 parentToken = tokenString;
219 } else if (currentResource.equals(mainResource)) {
220 token = tokenString;
221 } else if ((parentResource != null) && parentResource.equals(currentResource)) {
222 parentCleared = true;
223 parentToken = tokenString;
224 } else {
225 if (clearedResources == null) {
226 clearedResources = new HashSet<Object>();
227 }
228 clearedResources.add(currentResource);
229 }
230 }
231 } else {
232 if (!not) {
233 andResult = false;
234 }
235 }
236
237 not = false;
238 state = 4;
239 } else {
240 temp[tp] = c;
241 tp++;
242 }
243 } else if (state == 9) {
244 if (c == ']') {
245 if (tp == 0) {
246 error = true;
247 return false;
248 }
249 String etagToken = new String(temp, 0, tp);
250 tp = 0;
251
252 String etag = adapter.getResourceETag(currentResource);
253 if ((etag != null) && etag.equals(etagToken)) {
254 if (not) {
255 andResult = false;
256 }
257 } else {
258 if (!not) {
259 andResult = false;
260 }
261 }
262
263 not = false;
264 state = 4;
265 } else {
266 temp[tp] = c;
267 tp++;
268 }
269 }
270
271 p = p + 1;
272 }
273
274 return ((state == 0) && orResult && parentCleared);
275 }
276 }