133 } |
155 } |
134 *ns = pns; |
156 *ns = pns; |
135 *name = pname; |
157 *name = pname; |
136 } |
158 } |
137 |
159 |
138 DavSession* dav_session_new(DavContext *context, char *base_url) { |
|
139 if(!base_url) { |
|
140 return NULL; |
|
141 } |
|
142 sstr_t url = sstr(base_url); |
|
143 if(url.length == 0) { |
|
144 return NULL; |
|
145 } |
|
146 DavSession *sn = malloc(sizeof(DavSession)); |
|
147 sn->mp = ucx_mempool_new(1024); |
|
148 sn->key = NULL; |
|
149 sn->errorstr = NULL; |
|
150 sn->error = DAV_OK; |
|
151 sn->flags = 0; |
|
152 if(url.ptr[url.length - 1] == '/') { |
|
153 sstr_t url = sstrdup_a(sn->mp->allocator, sstr(base_url)); |
|
154 sn->base_url = url.ptr; |
|
155 } else { |
|
156 char *url_str = malloc(url.length + 2); |
|
157 memcpy(url_str, base_url, url.length); |
|
158 url_str[url.length] = '/'; |
|
159 url_str[url.length + 1] = '\0'; |
|
160 sn->base_url = url_str; |
|
161 } |
|
162 sn->context = context; |
|
163 sn->handle = curl_easy_init(); |
|
164 //curl_easy_setopt(sn->handle, CURLOPT_VERBOSE, 1L); |
|
165 //curl_easy_setopt(sn->handle, CURLOPT_STDERR, stderr); |
|
166 curl_easy_setopt(sn->handle, CURLOPT_FOLLOWLOCATION, 1L); |
|
167 |
|
168 // set proxy |
|
169 DavProxy *proxy = sstrprefix(url, S("https")) ? context->https_proxy |
|
170 : context->http_proxy; |
|
171 |
|
172 if (proxy->url) { |
|
173 curl_easy_setopt(sn->handle, CURLOPT_PROXY, proxy->url); |
|
174 if (proxy->username) { |
|
175 curl_easy_setopt(sn->handle, CURLOPT_PROXYUSERNAME, |
|
176 proxy->username); |
|
177 if (proxy->password) { |
|
178 curl_easy_setopt(sn->handle, CURLOPT_PROXYPASSWORD, |
|
179 proxy->password); |
|
180 } else { |
|
181 // TODO: prompt |
|
182 } |
|
183 } |
|
184 if(proxy->no_proxy) { |
|
185 curl_easy_setopt(sn->handle, CURLOPT_NOPROXY, |
|
186 proxy->no_proxy); |
|
187 } |
|
188 } |
|
189 |
|
190 // set url |
|
191 curl_easy_setopt(sn->handle, CURLOPT_URL, base_url); |
|
192 |
|
193 context->sessions = ucx_list_append(context->sessions, sn); |
|
194 |
|
195 return sn; |
|
196 } |
|
197 |
|
198 DavSession* dav_session_new_auth( |
|
199 DavContext *context, |
|
200 char *base_url, |
|
201 char *user, |
|
202 char *password) |
|
203 { |
|
204 DavSession *sn = dav_session_new(context, base_url); |
|
205 if(!sn) { |
|
206 return NULL; |
|
207 } |
|
208 dav_session_set_auth(sn, user, password); |
|
209 return sn; |
|
210 } |
|
211 |
|
212 void dav_session_set_auth(DavSession *sn, char *user, char *password) { |
|
213 if(user && password) { |
|
214 size_t ulen = strlen(user); |
|
215 size_t plen = strlen(password); |
|
216 size_t upwdlen = ulen + plen + 2; |
|
217 char *upwdbuf = malloc(upwdlen); |
|
218 snprintf(upwdbuf, upwdlen, "%s:%s\0", user, password); |
|
219 curl_easy_setopt(sn->handle, CURLOPT_USERPWD, upwdbuf); |
|
220 free(upwdbuf); |
|
221 } |
|
222 } |
|
223 |
|
224 void session_set_error(DavSession *sn, CURLcode c, int status) { |
|
225 if(status > 0) { |
|
226 switch(status) { |
|
227 default: sn->error = DAV_ERROR; break; |
|
228 case 401: sn->error = DAV_UNAUTHORIZED; break; |
|
229 case 403: sn->error = DAV_FORBIDDEN; break; |
|
230 case 404: sn->error = DAV_NOT_FOUND; break; |
|
231 case 405: sn->error = DAV_METHOD_NOT_ALLOWED; break; |
|
232 case 409: sn->error = DAV_CONFLICT; break; |
|
233 } |
|
234 } else { |
|
235 sn->error = DAV_ERROR; |
|
236 } |
|
237 if(c != CURLE_OK) { |
|
238 sn->errorstr = curl_easy_strerror(c); |
|
239 } else { |
|
240 sn->errorstr = NULL; |
|
241 } |
|
242 } |
|
243 |
|
244 void dav_session_destroy(DavSession *sn) { |
|
245 // remove session from context |
|
246 UcxList *sessions = sn->context->sessions; |
|
247 ssize_t i = ucx_list_find(sessions, sn, ucx_ptrcmp, NULL); |
|
248 if(i > 0) { |
|
249 UcxList *elm = ucx_list_get(sessions, i); |
|
250 if(elm) { |
|
251 sn->context->sessions = ucx_list_remove(sessions, elm); |
|
252 } |
|
253 } |
|
254 |
|
255 ucx_mempool_destroy(sn->mp); |
|
256 curl_easy_cleanup(sn->handle); |
|
257 free(sn); |
|
258 } |
|
259 |
|
260 |
|
261 void* dav_session_malloc(DavSession *sn, size_t size) { |
|
262 return ucx_mempool_malloc(sn->mp, size); |
|
263 } |
|
264 |
|
265 void* dav_session_calloc(DavSession *sn, size_t nelm, size_t size) { |
|
266 return ucx_mempool_calloc(sn->mp, nelm, size); |
|
267 } |
|
268 |
|
269 void* dav_session_realloc(DavSession *sn, void *ptr, size_t size) { |
|
270 return ucx_mempool_realloc(sn->mp, ptr, size); |
|
271 } |
|
272 |
|
273 void dav_session_free(DavSession *sn, void *ptr) { |
|
274 ucx_mempool_free(sn->mp, ptr); |
|
275 } |
|
276 |
|
277 |
160 |
278 DavResource* dav_get(DavSession *sn, char *path, char *properties) { |
161 DavResource* dav_get(DavSession *sn, char *path, char *properties) { |
279 CURL *handle = sn->handle; |
162 CURL *handle = sn->handle; |
280 util_set_url(sn, path); |
163 char *href = dav_session_get_href(sn, path); |
|
164 util_set_url(sn, href); |
|
165 dav_session_free(sn, href); |
281 |
166 |
282 UcxList *proplist = NULL; |
167 UcxList *proplist = NULL; |
283 if(properties) { |
168 if(properties) { |
284 proplist = parse_properties_string(sn->context, sstr(properties)); |
169 proplist = parse_properties_string(sn->context, sstr(properties)); |
285 } |
170 } |
286 UcxBuffer *rqbuf = create_propfind_request(proplist); |
171 UcxBuffer *rqbuf = create_propfind_request(sn, proplist); |
287 UcxBuffer *rpbuf = ucx_buffer_new(NULL, 4096, UCX_BUFFER_AUTOEXTEND); |
172 UcxBuffer *rpbuf = ucx_buffer_new(NULL, 4096, UCX_BUFFER_AUTOEXTEND); |
288 |
173 |
289 //fwrite(rqbuf->space, 1, rqbuf->size, stdout); |
174 //fwrite(rqbuf->space, 1, rqbuf->size, stdout); |
290 //printf("\n"); |
175 //printf("\n"); |
291 |
176 |
296 if(ret == CURLE_OK && status == 207) { |
181 if(ret == CURLE_OK && status == 207) { |
297 //printf("response\n%s\n", rpbuf->space); |
182 //printf("response\n%s\n", rpbuf->space); |
298 resource = parse_propfind_response(sn, NULL, rpbuf, NULL, 0); |
183 resource = parse_propfind_response(sn, NULL, rpbuf, NULL, 0); |
299 sn->error = DAV_OK; |
184 sn->error = DAV_OK; |
300 } else { |
185 } else { |
301 session_set_error(sn, ret, status); |
186 dav_session_set_error(sn, ret, status); |
302 } |
187 } |
|
188 |
|
189 ucx_buffer_free(rqbuf); |
|
190 ucx_buffer_free(rpbuf); |
|
191 |
303 return resource; |
192 return resource; |
304 } |
193 } |
305 |
194 |
306 DavResource* dav_propfind(DavSession *sn, DavResource *root, UcxBuffer *rqbuf, char *path, DavQOp *cond, size_t len) { |
195 int dav_propfind(DavSession *sn, DavResource *root, UcxBuffer *rqbuf, DavQOp *cond, size_t len) { |
|
196 // clean resource properties |
|
197 DavResourceData *data = root->data; |
|
198 if(data->properties->count > 0) { |
|
199 UcxKey key; |
|
200 void *value; |
|
201 UcxMapIterator i = ucx_map_iterator(data->properties); |
|
202 UCX_MAP_FOREACH(key, value, i) { |
|
203 ucx_map_remove(data->properties, key); |
|
204 } |
|
205 } |
|
206 |
307 CURL *handle = sn->handle; |
207 CURL *handle = sn->handle; |
308 util_set_url(sn, path); |
208 util_set_url(sn, dav_resource_get_href(root)); |
309 |
209 |
310 UcxBuffer *rpbuf = ucx_buffer_new(NULL, 4096, UCX_BUFFER_AUTOEXTEND); |
210 UcxBuffer *rpbuf = ucx_buffer_new(NULL, 4096, UCX_BUFFER_AUTOEXTEND); |
311 DavResource *resource = root; |
211 DavResource *resource = root; |
312 CURLcode ret = do_propfind_request(handle, rqbuf, rpbuf); |
212 CURLcode ret = do_propfind_request(handle, rqbuf, rpbuf); |
313 int status = 0; |
213 int status = 0; |
|
214 int error = 0; |
314 curl_easy_getinfo (handle, CURLINFO_RESPONSE_CODE, &status); |
215 curl_easy_getinfo (handle, CURLINFO_RESPONSE_CODE, &status); |
315 if(ret == CURLE_OK && status == 207) { |
216 if(ret == CURLE_OK && status == 207) { |
316 //printf("response\n%s\n", rpbuf->space); |
217 //printf("response\n%s\n", rpbuf->space); |
317 resource = parse_propfind_response(sn, resource, rpbuf, cond, len); |
218 resource = parse_propfind_response(sn, resource, rpbuf, cond, len); |
318 sn->error = DAV_OK; |
219 sn->error = DAV_OK; |
319 } else { |
220 } else { |
320 session_set_error(sn, ret, status); |
221 dav_session_set_error(sn, ret, status); |
321 resource = NULL; |
222 error = 1; |
322 } |
223 } |
323 ucx_buffer_free(rpbuf); |
224 ucx_buffer_free(rpbuf); |
324 return resource; |
225 return error; |
325 } |
226 } |
326 |
227 |
327 UcxList* propfind_stack_push(UcxList *stack, DavResource *children) { |
228 UcxList* propfind_stack_push(UcxList *stack, DavResource *children) { |
328 while(children) { |
229 while(children) { |
329 if(children->iscollection) { |
230 if(children->iscollection) { |
335 } |
236 } |
336 |
237 |
337 DavResource* dav_query_get(DavSession *sn, DavGetQuery *query) { |
238 DavResource* dav_query_get(DavSession *sn, DavGetQuery *query) { |
338 char *path; |
239 char *path; |
339 int depth = 0; |
240 int depth = 0; |
|
241 /* |
340 if(parse_path_query(query->from, &path, &depth)) { |
242 if(parse_path_query(query->from, &path, &depth)) { |
341 sn->error = DAV_ERROR; |
243 sn->error = DAV_ERROR; |
342 return NULL; |
244 return NULL; |
343 } |
245 } |
|
246 */ |
|
247 path = sstrdup(query->from).ptr; |
344 |
248 |
345 sstr_t ps = query->properties; |
249 sstr_t ps = query->properties; |
346 UcxBuffer *rqbuf; |
250 UcxBuffer *rqbuf; |
347 if(!sstrcmp(ps, S("*"))) { |
251 if(!sstrcmp(ps, S("*"))) { |
348 rqbuf = create_allprop_propfind_request(); |
252 rqbuf = create_allprop_propfind_request(); |
349 } else if(!sstrcmp(ps, S("-"))) { |
253 } else if(!sstrcmp(ps, S("-"))) { |
350 rqbuf = create_propfind_request(NULL); |
254 rqbuf = create_propfind_request(sn, NULL); |
351 } else { |
255 } else { |
352 UcxList *proplist = parse_properties_string(sn->context, ps); |
256 UcxList *proplist = parse_properties_string(sn->context, ps); |
353 rqbuf = create_propfind_request(proplist); |
257 rqbuf = create_propfind_request(sn, proplist); |
354 } |
258 } |
355 |
259 |
356 //fwrite(rqbuf->space, 1, rqbuf->size, stdout); |
260 //fwrite(rqbuf->space, 1, rqbuf->size, stdout); |
357 //printf("\n"); |
261 //printf("\n"); |
358 |
262 |
359 DavResource *resource = dav_propfind(sn, NULL, rqbuf, path, query->condition, query->condlen); |
263 DavResource *resource = dav_resource_new(sn, path); |
360 free(path); |
264 free(path); |
|
265 if(dav_propfind(sn, resource, rqbuf, query->condition, query->condlen)) { |
|
266 dav_resource_free(resource); |
|
267 resource = NULL; |
|
268 } |
|
269 ucx_buffer_free(rqbuf); |
|
270 |
361 int error = 0; |
271 int error = 0; |
362 if(resource && depth == -1) { |
272 if(resource && depth == -1) { |
363 UcxList *stack = NULL; // stack with DavResource* elements |
273 UcxList *stack = NULL; // stack with DavResource* elements |
364 stack = propfind_stack_push(stack, resource->children); |
274 stack = propfind_stack_push(stack, resource->children); |
365 while(stack) { |
275 while(stack) { |
366 DavResource *sr = stack->data; // get first element from the stack |
276 DavResource *sr = stack->data; // get first element from the stack |
367 stack = ucx_list_remove(stack, stack); // remove first element |
277 stack = ucx_list_remove(stack, stack); // remove first element |
368 // do propfind request for sr |
278 // do propfind request for sr |
369 sr = dav_propfind(sn, sr, rqbuf, sr->path, query->condition, query->condlen); |
279 if(dav_propfind(sn, sr, rqbuf, query->condition, query->condlen)) { |
370 if(!sr) { |
|
371 error = 1; |
280 error = 1; |
372 printf("subrequest failed\n"); |
281 printf("subrequest failed\n"); |
373 break; |
282 break; |
374 } |
283 } |
375 stack = propfind_stack_push(stack, sr->children); // add children |
284 stack = propfind_stack_push(stack, sr->children); // add children |