static void propfind_results_recursive(void *userdata, const ne_uri *uri, const ne_prop_result_set *set) { struct resource *newres = 0; const char *clength, *modtime, *file_id = NULL; const char *resourcetype = NULL; const char *md5sum = NULL; const ne_status *status = NULL; char *path = ne_path_unescape( uri->path ); char *parentPath; char *propfindRootUri = (char*) userdata; propfind_recursive_element_t *element = NULL; propfind_recursive_element_t *pElement = NULL; int depth = 0; (void) status; (void) propfindRootUri; if (!propfind_recursive_cache) { c_rbtree_create(&propfind_recursive_cache, _key_cmp, _data_cmp); } /* Fill the resource structure with the data about the file */ newres = c_malloc(sizeof(struct resource)); ZERO_STRUCTP(newres); newres->uri = path; /* no need to strdup because ne_path_unescape already allocates */ newres->name = c_basename( path ); modtime = ne_propset_value( set, &ls_props[0] ); clength = ne_propset_value( set, &ls_props[1] ); resourcetype = ne_propset_value( set, &ls_props[2] ); md5sum = ne_propset_value( set, &ls_props[3] ); file_id = ne_propset_value( set, &ls_props[4] ); newres->type = resr_normal; if( resourcetype && strncmp( resourcetype, "<DAV:collection>", 16 ) == 0) { newres->type = resr_collection; propfind_recursive_cache_folder_count++; } else { /* DEBUG_WEBDAV("propfind_results_recursive %s [%d]", newres->uri, newres->type); */ propfind_recursive_cache_file_count++; } if (modtime) { newres->modtime = oc_httpdate_parse(modtime); } /* DEBUG_WEBDAV("Parsing Modtime: %s -> %llu", modtime, (unsigned long long) newres->modtime ); */ newres->size = 0; if (clength) { newres->size = atoll(clength); /* DEBUG_WEBDAV("Parsed File size for %s from %s: %lld", newres->name, clength, (long long)newres->size ); */ } if( md5sum ) { newres->md5 = csync_normalize_etag(md5sum); } csync_vio_set_file_id(newres->file_id, file_id); /* DEBUG_WEBDAV("propfind_results_recursive %s [%s] %s", newres->uri, newres->type == resr_collection ? "collection" : "file", newres->md5); */ /* Create new item in rb tree */ if (newres->type == resr_collection) { DEBUG_WEBDAV("propfind_results_recursive %s is a folder", newres->uri); /* Check if in rb tree */ element = c_rbtree_node_data(c_rbtree_find(propfind_recursive_cache,uri->path)); /* If not, create a new item and insert it */ if (!element) { element = c_malloc(sizeof(propfind_recursive_element_t)); element->self = resource_dup(newres); element->children = NULL; element->parent = NULL; c_rbtree_insert(propfind_recursive_cache, element); /* DEBUG_WEBDAV("results_recursive Added collection %s", newres->uri); */ } } /* Check for parent in tree. If exists: Insert it into the children elements there */ parentPath = ne_path_parent(uri->path); if (parentPath) { propfind_recursive_element_t *parentElement = NULL; parentElement = c_rbtree_node_data(c_rbtree_find(propfind_recursive_cache,parentPath)); free(parentPath); if (parentElement) { newres->next = parentElement->children; parentElement->children = newres; /* If the current result is a collection we also need to set its parent */ if (element) element->parent = parentElement; pElement = element; while (pElement) { depth++; pElement = pElement->parent; } if (depth > propfind_recursive_cache_depth) { DEBUG_WEBDAV("propfind_results_recursive %s new maximum tree depth %d", newres->uri, depth); propfind_recursive_cache_depth = depth; } /* DEBUG_WEBDAV("results_recursive Added child %s to collection %s", newres->uri, element->self->uri); */ } else { /* DEBUG_WEBDAV("results_recursive No parent %s found for child %s", parentPath, newres->uri); */ resource_free(newres); newres = NULL; } } }
/* * result parsing list. * This function is called to parse the result of the propfind request * to list directories on the WebDAV server. I takes a single resource * and fills a resource struct and stores it to the result list which * is stored in the listdir_context. */ static void results(void *userdata, const ne_uri *uri, const ne_prop_result_set *set) { struct listdir_context *fetchCtx = userdata; struct resource *newres = 0; const char *clength, *modtime = NULL; const char *resourcetype = NULL; const char *md5sum = NULL; const char *file_id = NULL; const ne_status *status = NULL; char *path = ne_path_unescape( uri->path ); (void) status; if( ! fetchCtx ) { DEBUG_WEBDAV("No valid fetchContext"); return; } if( ! fetchCtx->target ) { DEBUG_WEBDAV("error: target must not be zero!" ); return; } /* Fill the resource structure with the data about the file */ newres = c_malloc(sizeof(struct resource)); ZERO_STRUCTP(newres); newres->uri = path; /* no need to strdup because ne_path_unescape already allocates */ newres->name = c_basename( path ); modtime = ne_propset_value( set, &ls_props[0] ); clength = ne_propset_value( set, &ls_props[1] ); resourcetype = ne_propset_value( set, &ls_props[2] ); md5sum = ne_propset_value( set, &ls_props[3] ); file_id = ne_propset_value( set, &ls_props[4] ); newres->type = resr_normal; if( clength == NULL && resourcetype && strncmp( resourcetype, "<DAV:collection>", 16 ) == 0) { newres->type = resr_collection; } if (modtime) { newres->modtime = oc_httpdate_parse(modtime); } /* DEBUG_WEBDAV("Parsing Modtime: %s -> %llu", modtime, (unsigned long long) newres->modtime ); */ newres->size = 0; if (clength) { newres->size = atoll(clength); /* DEBUG_WEBDAV("Parsed File size for %s from %s: %lld", newres->name, clength, (long long)newres->size ); */ } if( md5sum ) { newres->md5 = csync_normalize_etag(md5sum); } csync_vio_set_file_id(newres->file_id, file_id); /* prepend the new resource to the result list */ newres->next = fetchCtx->list; fetchCtx->list = newres; fetchCtx->result_count = fetchCtx->result_count + 1; /* DEBUG_WEBDAV( "results for URI %s: %d %d", newres->name, (int)newres->size, (int)newres->type ); */ }
void fill_webdav_properties_into_resource(struct resource* newres, const ne_prop_result_set *set) { const char *clength, *modtime, *file_id = NULL; const char *directDownloadUrl = NULL; const char *directDownloadCookies = NULL; const char *resourcetype = NULL; const char *etag = NULL; const char *perm = NULL; modtime = ne_propset_value( set, &ls_props[0] ); clength = ne_propset_value( set, &ls_props[1] ); resourcetype = ne_propset_value( set, &ls_props[2] ); etag = ne_propset_value( set, &ls_props[3] ); file_id = ne_propset_value( set, &ls_props[4] ); directDownloadUrl = ne_propset_value( set, &ls_props[5] ); directDownloadCookies = ne_propset_value( set, &ls_props[6] ); perm = ne_propset_value( set, &ls_props[7] ); if( resourcetype && strncmp( resourcetype, "<DAV:collection>", 16 ) == 0) { newres->type = resr_collection; } else { newres->type = resr_normal; } if (modtime) { newres->modtime = oc_httpdate_parse(modtime); } /* DEBUG_WEBDAV("Parsing Modtime: %s -> %llu", modtime, (unsigned long long) newres->modtime ); */ newres->size = 0; if (clength) { newres->size = atoll(clength); /* DEBUG_WEBDAV("Parsed File size for %s from %s: %lld", newres->name, clength, (long long)newres->size ); */ } if( etag ) { newres->md5 = csync_normalize_etag(etag); } csync_vio_set_file_id(newres->file_id, file_id); /* DEBUG_WEBDAV("propfind_results_recursive %s [%s] %s", newres->uri, newres->type == resr_collection ? "collection" : "file", newres->md5); */ if (directDownloadUrl) { newres->directDownloadUrl = c_strdup(directDownloadUrl); } if (directDownloadCookies) { newres->directDownloadCookies = c_strdup(directDownloadCookies); } if (perm && strlen(perm) < sizeof(newres->remotePerm)) { strncpy(newres->remotePerm, perm, sizeof(newres->remotePerm)); } else if (perm && strlen(perm) == 0) { // special meaning for our code: server returned permissions but are empty // meaning only reading is allowed for this resource newres->remotePerm[0] = ' '; // see _csync_detect_update() } else { // old server, keep NULL in newres->remotePerm } }
static const char* owncloud_get_etag( const char *path ) { ne_request *req = NULL; const char *header = NULL; char *uri = _cleanPath(path); char *cbuf = NULL; csync_vio_file_stat_t *fs = NULL; bool doHeadRequest = false; if (_id_cache.uri && c_streq(path, _id_cache.uri)) { header = _id_cache.id; } doHeadRequest= false; /* ownCloud server doesn't have good support for HEAD yet */ if( !header && doHeadRequest ) { int neon_stat; /* Perform an HEAD request to the resource. HEAD delivers the * ETag header back. */ req = ne_request_create(dav_session.ctx, "HEAD", uri); neon_stat = ne_request_dispatch(req); set_errno_from_neon_errcode( neon_stat ); header = ne_get_response_header(req, "etag"); } /* If the request went wrong or the server did not respond correctly * (that can happen for collections) a stat call is done which translates * into a PROPFIND request. */ if( ! header ) { /* ... and do a stat call. */ fs = csync_vio_file_stat_new(); if(fs == NULL) { DEBUG_WEBDAV( "owncloud_get_etag: memory fault."); errno = ENOMEM; return NULL; } if( owncloud_stat( path, fs ) == 0 ) { header = fs->etag; } } /* In case the result is surrounded by "" cut them away. */ if( header ) { cbuf = csync_normalize_etag(header); } /* fix server problem: If we end up with an empty string, set something strange... */ if( c_streq(cbuf, "") || c_streq(cbuf, "\"\"") ) { SAFE_FREE(cbuf); cbuf = c_strdup("empty_etag"); } DEBUG_WEBDAV("Get file ID for %s: %s", path, cbuf ? cbuf:"<null>"); if( fs ) csync_vio_file_stat_destroy(fs); if( req ) ne_request_destroy(req); SAFE_FREE(uri); return cbuf; }