static dav_error * __build_chunk_full_path(const dav_resource *resource, char **full_path) { const request_rec *r = resource->info->request; dav_rawx_server_conf *conf = request_get_server_config(r); if(strlen(r->uri) < 65) return server_create_and_stat_error(request_get_server_config(r), r->pool, HTTP_BAD_REQUEST, 0, apr_pstrcat(r->pool, "Cannot parse request uri ", r->uri, NULL)); char *p = NULL; uint i_p = 1; uint i_uri = 1; p = apr_palloc(r->pool, (65 + 1 + (conf->hash_depth * conf->hash_width) + conf->hash_depth)); p[0] = '/'; for (int i = 0; i < conf->hash_depth ; i++) { for (int j = 0; j < conf->hash_width ; j++) p[i_p++] = r->uri[i_uri++]; p[i_p++] = '/'; } memcpy(p + i_p, r->uri + 1, 64); i_p += 64; p[i_p] = '\0'; *full_path = apr_pstrcat(r->pool, conf->docroot, p, NULL); return NULL; }
static dav_error * _load_request_info(const dav_resource *resource, char **full_path, struct storage_policy_s **sp) { dav_error *e = NULL; const request_rec *r = resource->info->request; /* configure full path */ e = __build_chunk_full_path(resource, full_path); if (NULL != e) return e; DAV_DEBUG_REQ(r, 0, "Chunk path build from request: %s", *full_path); /* init loaded storage policy */ const char *pol_name = apr_table_get(r->headers_in, "storage-policy"); if (!pol_name) { return server_create_and_stat_error(request_get_server_config(r), r->pool, HTTP_BAD_REQUEST, 0, "No storage-policy specified"); } DAV_DEBUG_REQ(r, 0, "Policy found in request: %s", pol_name); dav_rawx_server_conf *conf = resource_get_server_config(resource); *sp = storage_policy_init(conf->rawx_conf->ni, pol_name); apr_pool_cleanup_register(r->pool, *sp, apr_storage_policy_clean, apr_pool_cleanup_null); return NULL; }
static dav_error * _update_chunk_storage(const dav_resource *resource, const char *path, const struct data_treatments_s *dt, GHashTable *comp_opt) { GError *e = NULL; dav_error *de = NULL; const char *c = NULL; const request_rec *r = resource->info->request; c = g_hash_table_lookup(comp_opt, NS_COMPRESSION_OPTION); if(NULL != c && 0 == g_ascii_strcasecmp(c, NS_COMPRESSION_ON)) { DAV_DEBUG_REQ(r, 0, "In place chunk is compressed, uncompress it"); if(1 != uncompress_chunk(path, TRUE, &e)) { de = server_create_and_stat_error(request_get_server_config(r), r->pool, HTTP_INTERNAL_SERVER_ERROR, 0, apr_pstrcat(r->pool, "Failed to uncompress chunk : ", ((NULL != e)? e->message : "No error specified"), NULL)); if(NULL != e) g_clear_error(&e); return de; } DAV_DEBUG_REQ(r, 0, "Chunk uncompressed"); } if(COMPRESSION == data_treatments_get_type(dt)) { DAV_DEBUG_REQ(r, 0, "Re compressing chunk"); const char *algo = data_treatments_get_param(dt, DT_KEY_ALGO); const char *bs = data_treatments_get_param(dt, DT_KEY_BLOCKSIZE); if(!algo || !bs) { return server_create_and_stat_error(request_get_server_config(r), r->pool, HTTP_INTERNAL_SERVER_ERROR, 0, apr_pstrcat(r->pool, "Cannot compress chunk, missing info: ", algo, "|", bs, NULL)); } if(1 != compress_chunk(path, algo, g_ascii_strtoll(bs, NULL, 10), TRUE, &e)) { de = server_create_and_stat_error(request_get_server_config(r), r->pool, HTTP_INTERNAL_SERVER_ERROR, 0, apr_pstrcat(r->pool, "Failed to compress chunk : ", ((NULL != e)? e->message : "No error specified"), NULL)); if(NULL != e) g_clear_error(&e); return de; } } return NULL; }
dav_error * dav_rainx_info_get_resource(request_rec *r, const char *root_dir, const char *label, int use_checked_in, dav_resource **result_resource) { (void) root_dir; (void) label; (void) use_checked_in; DAV_XDEBUG_REQ(r, 0, "%s(...)", __FUNCTION__); *result_resource = NULL; if (r->method_number != M_GET) return server_create_and_stat_error(request_get_server_config(r), r->pool, HTTP_BAD_REQUEST, 0, apr_pstrdup(r->pool, "Invalid request method, only GET")); *result_resource = __build_req_resource(r, &dav_hooks_repository_rainxinfo, __gen_info); (*result_resource)->info->type = INFO; return NULL; }
static dav_resource* __get_chunkupdate_resource(const request_rec *r, const dav_hooks_repository *hooks) { dav_resource *resource; DAV_XDEBUG_REQ(r, 0, "%s(...)", __FUNCTION__); resource = apr_pcalloc(r->pool, sizeof(*resource)); resource->type = DAV_RESOURCE_TYPE_PRIVATE; resource->hooks = hooks; resource->pool = r->pool; resource->exists = 1; resource->collection = 0; resource->info = apr_pcalloc(r->pool, sizeof(struct dav_resource_private)); resource->info->pool = r->pool; resource->info->conf = request_get_server_config(r); resource->info->request = r; return resource; }
dav_rawx_server_conf* resource_get_server_config(const dav_resource *resource) { return request_get_server_config(resource->info->request); }
static dav_error * dav_rawx_get_resource(request_rec *r, const char *root_dir, const char *label, int use_checked_in, dav_resource **result_resource) { (void) use_checked_in; *result_resource = NULL; dav_rawx_server_conf *conf = request_get_server_config(r); /* Check if client allowed to work with us */ if (conf->enabled_acl) { #if MODULE_MAGIC_COOKIE == 0x41503234UL /* "AP24" */ if (!authorized_personal_only(r->connection->client_ip, conf->rawx_conf->acl)) #else if (!authorized_personal_only(r->connection->remote_ip, conf->rawx_conf->acl)) #endif { return server_create_and_stat_error(conf, r->pool, HTTP_UNAUTHORIZED, 0, "Permission Denied (APO)"); } } /* Create private resource context descriptor */ dav_resource_private ctx = {0}; ctx.pool = r->pool; ctx.request = r; dav_error *e = rawx_repo_check_request(r, root_dir, label, use_checked_in, &ctx, result_resource); /* Return in case we have an error or * if result_resource != null because it was an info request */ if (e || *result_resource) { return e; } /* Build the hashed path */ if (conf->hash_width <= 0 || conf->hash_depth <= 0) { apr_snprintf(ctx.dirname, sizeof(ctx.dirname), "%.*s", (int)sizeof(conf->docroot), conf->docroot); } else { e = rawx_repo_configure_hash_dir(r, &ctx); if ( NULL != e) { return e; } } DAV_DEBUG_REQ(r, 0, "Hashed directory: %.*s", (int)sizeof(ctx.dirname), ctx.dirname); /* All the checks on the URL have passed, now build a resource */ dav_resource *resource = apr_pcalloc(r->pool, sizeof(*resource)); resource->type = DAV_RESOURCE_TYPE_REGULAR; resource->info = apr_pcalloc(r->pool, sizeof(ctx));; memcpy(resource->info, &ctx, sizeof(ctx)); resource->hooks = &dav_hooks_repository_rawx; resource->pool = r->pool; memset(&(resource->info->comp_ctx), 0, sizeof(struct compression_ctx_s)); resource->info->fullpath = apr_pstrcat(resource->pool, resource->info->dirname, resource->info->hex_chunkid, resource->info->file_extension, NULL); /* init compression context structure if we are in get method */ if (r->method_number == M_GET && !ctx.update_only) { resource_init_decompression(resource, conf); } /* Check the chunk's existence */ int flags = (r->method_number == M_GET || r->method_number == M_OPTIONS || r->method_number == M_DELETE)? RESOURCE_STAT_CHUNK_READ_ATTRS : 0; if (r->method_number == M_PUT || r->method_number == M_POST) flags |= RESOURCE_STAT_CHUNK_PENDING; resource_stat_chunk(resource, flags); if (r->method_number == M_PUT || r->method_number == M_POST || r->method_number == M_MOVE || (r->method_number == M_GET && ctx.update_only)) { request_load_chunk_info_from_headers(r, &(resource->info->chunk)); const char *missing = check_chunk_info(&resource->info->chunk); if (missing != NULL) { return server_create_and_stat_error(request_get_server_config(r), r->pool, HTTP_BAD_REQUEST, 0, apr_pstrcat(r->pool, "missing or invalid header ", missing, NULL)); } } if (r->method_number == M_POST || r->method_number == M_PUT) { if (resource->info->chunk.chunk_id) { if (0 != apr_strnatcasecmp(resource->info->chunk.chunk_id, resource->info->hex_chunkid)) return server_create_and_stat_error(request_get_server_config(r), r->pool, HTTP_BAD_REQUEST, 0, "chunk-id mismatch"); } if (resource->exists) return server_create_and_stat_error(request_get_server_config(r), r->pool, HTTP_CONFLICT, 0, "Resource busy or already exists"); request_parse_query(r, resource); } *result_resource = resource; return NULL; }