⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mod_dav.c

📁 最新apache的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    *range_end = apr_atoi64(dash + 1);    if (*range_end < *range_start        || (slash[1] != '*' && apr_atoi64(slash + 1) <= *range_end)) {        /* invalid range. ignore it (per S14.16 of RFC2616) */        return 0;    }    /* we now have a valid range */    return 1;}/* handle the GET method */static int dav_method_get(request_rec *r){    dav_resource *resource;    dav_error *err;    /* This method should only be called when the resource is not     * visible to Apache. We will fetch the resource from the repository,     * then create a subrequest for Apache to handle.     */    err = dav_get_resource(r, 1 /* label_allowed */, 0 /* use_checked_in */,                           &resource);    if (err != NULL)        return dav_handle_err(r, err, NULL);    if (!resource->exists) {        /* Apache will supply a default error for this. */        return HTTP_NOT_FOUND;    }    /* set up the HTTP headers for the response */    if ((err = (*resource->hooks->set_headers)(r, resource)) != NULL) {        err = dav_push_error(r->pool, err->status, 0,                             "Unable to set up HTTP headers.",                             err);        return dav_handle_err(r, err, NULL);    }    if (r->header_only) {        return DONE;    }    /* okay... time to deliver the content */    if ((err = (*resource->hooks->deliver)(resource,                                           r->output_filters)) != NULL) {        err = dav_push_error(r->pool, err->status, 0,                             "Unable to deliver content.",                             err);        return dav_handle_err(r, err, NULL);    }    return DONE;}/* validate resource/locks on POST, then pass to the default handler */static int dav_method_post(request_rec *r){    dav_resource *resource;    dav_error *err;    /* Ask repository module to resolve the resource */    err = dav_get_resource(r, 0 /* label_allowed */, 0 /* use_checked_in */,                           &resource);    if (err != NULL)        return dav_handle_err(r, err, NULL);    /* Note: depth == 0. Implies no need for a multistatus response. */    if ((err = dav_validate_request(r, resource, 0, NULL, NULL,                                    DAV_VALIDATE_RESOURCE, NULL)) != NULL) {        /* ### add a higher-level description? */        return dav_handle_err(r, err, NULL);    }    return DECLINED;}/* handle the PUT method */static int dav_method_put(request_rec *r){    dav_resource *resource;    int resource_state;    dav_auto_version_info av_info;    const dav_hooks_locks *locks_hooks = DAV_GET_HOOKS_LOCKS(r);    const char *body;    dav_error *err;    dav_error *err2;    dav_stream_mode mode;    dav_stream *stream;    dav_response *multi_response;    int has_range;    apr_off_t range_start;    apr_off_t range_end;    /* Ask repository module to resolve the resource */    err = dav_get_resource(r, 0 /* label_allowed */, 0 /* use_checked_in */,                           &resource);    if (err != NULL)        return dav_handle_err(r, err, NULL);    /* If not a file or collection resource, PUT not allowed */    if (resource->type != DAV_RESOURCE_TYPE_REGULAR        && resource->type != DAV_RESOURCE_TYPE_WORKING) {        body = apr_psprintf(r->pool,                            "Cannot create resource %s with PUT.",                            ap_escape_html(r->pool, r->uri));        return dav_error_response(r, HTTP_CONFLICT, body);    }    /* Cannot PUT a collection */    if (resource->collection) {        return dav_error_response(r, HTTP_CONFLICT,                                  "Cannot PUT to a collection.");    }    resource_state = dav_get_resource_state(r, resource);    /*     * Note: depth == 0 normally requires no multistatus response. However,     * if we pass DAV_VALIDATE_PARENT, then we could get an error on a URI     * other than the Request-URI, thereby requiring a multistatus.     *     * If the resource does not exist (DAV_RESOURCE_NULL), then we must     * check the resource *and* its parent. If the resource exists or is     * a locknull resource, then we check only the resource.     */    if ((err = dav_validate_request(r, resource, 0, NULL, &multi_response,                                    resource_state == DAV_RESOURCE_NULL ?                                    DAV_VALIDATE_PARENT :                                    DAV_VALIDATE_RESOURCE, NULL)) != NULL) {        /* ### add a higher-level description? */        return dav_handle_err(r, err, multi_response);    }    /* make sure the resource can be modified (if versioning repository) */    if ((err = dav_auto_checkout(r, resource,                                 0 /* not parent_only */,                                 &av_info)) != NULL) {        /* ### add a higher-level description? */        return dav_handle_err(r, err, NULL);    }    /* truncate and rewrite the file unless we see a Content-Range */    mode = DAV_MODE_WRITE_TRUNC;    has_range = dav_parse_range(r, &range_start, &range_end);    if (has_range) {        mode = DAV_MODE_WRITE_SEEKABLE;    }    /* Create the new file in the repository */    if ((err = (*resource->hooks->open_stream)(resource, mode,                                               &stream)) != NULL) {        /* ### assuming FORBIDDEN is probably not quite right... */        err = dav_push_error(r->pool, HTTP_FORBIDDEN, 0,                             apr_psprintf(r->pool,                                          "Unable to PUT new contents for %s.",                                          ap_escape_html(r->pool, r->uri)),                             err);    }    if (err == NULL && has_range) {        /* a range was provided. seek to the start */        err = (*resource->hooks->seek_stream)(stream, range_start);    }    if (err == NULL) {        apr_bucket_brigade *bb;        apr_bucket *b;        int seen_eos = 0;        bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);        do {            apr_status_t rc;            rc = ap_get_brigade(r->input_filters, bb, AP_MODE_READBYTES,                                APR_BLOCK_READ, DAV_READ_BLOCKSIZE);            if (rc != APR_SUCCESS) {                err = dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0,                                    "Could not get next bucket brigade");                break;            }            for (b = APR_BRIGADE_FIRST(bb);                 b != APR_BRIGADE_SENTINEL(bb);                 b = APR_BUCKET_NEXT(b))            {                const char *data;                apr_size_t len;                if (APR_BUCKET_IS_EOS(b)) {                    seen_eos = 1;                    break;                }                if (APR_BUCKET_IS_METADATA(b)) {                    continue;                }                rc = apr_bucket_read(b, &data, &len, APR_BLOCK_READ);                if (rc != APR_SUCCESS) {                    err = dav_new_error(r->pool, HTTP_BAD_REQUEST, 0,                                        "An error occurred while reading "                                        "the request body.");                    break;                }                if (err == NULL) {                    /* write whatever we read, until we see an error */                    err = (*resource->hooks->write_stream)(stream, data, len);                }            }            apr_brigade_cleanup(bb);        } while (!seen_eos);        apr_brigade_destroy(bb);        err2 = (*resource->hooks->close_stream)(stream,                                                err == NULL /* commit */);        if (err2 != NULL && err == NULL) {            /* no error during the write, but we hit one at close. use it. */            err = err2;        }    }    /*     * Ensure that we think the resource exists now.     * ### eek. if an error occurred during the write and we did not commit,     * ### then the resource might NOT exist (e.g. dav_fs_repos.c)     */    if (err == NULL) {        resource->exists = 1;    }    /* restore modifiability of resources back to what they were */    err2 = dav_auto_checkin(r, resource, err != NULL /* undo if error */,                            0 /*unlock*/, &av_info);    /* check for errors now */    if (err != NULL) {        return dav_handle_err(r, err, NULL);    }    if (err2 != NULL) {        /* just log a warning */        err2 = dav_push_error(r->pool, err2->status, 0,                              "The PUT was successful, but there "                              "was a problem automatically checking in "                              "the resource or its parent collection.",                              err2);        dav_log_err(r, err2, APLOG_WARNING);    }    /* ### place the Content-Type and Content-Language into the propdb */    if (locks_hooks != NULL) {        dav_lockdb *lockdb;        if ((err = (*locks_hooks->open_lockdb)(r, 0, 0, &lockdb)) != NULL) {            /* The file creation was successful, but the locking failed. */            err = dav_push_error(r->pool, err->status, 0,                                 "The file was PUT successfully, but there "                                 "was a problem opening the lock database "                                 "which prevents inheriting locks from the "                                 "parent resources.",                                 err);            return dav_handle_err(r, err, NULL);        }        /* notify lock system that we have created/replaced a resource */        err = dav_notify_created(r, lockdb, resource, resource_state, 0);        (*locks_hooks->close_lockdb)(lockdb);        if (err != NULL) {            /* The file creation was successful, but the locking failed. */            err = dav_push_error(r->pool, err->status, 0,                                 "The file was PUT successfully, but there "                                 "was a problem updating its lock "                                 "information.",                                 err);            return dav_handle_err(r, err, NULL);        }    }    /* NOTE: WebDAV spec, S8.7.1 states properties should be unaffected */    /* return an appropriate response (HTTP_CREATED or HTTP_NO_CONTENT) */    return dav_created(r, NULL, "Resource", resource_state == DAV_RESOURCE_EXISTS);}/* Use POOL to temporarily construct a dav_response object (from WRES   STATUS, and PROPSTATS) and stream it via WRES's ctx->brigade. */static void dav_stream_response(dav_walk_resource *wres,                                int status,                                dav_get_props_result *propstats,                                apr_pool_t *pool){    dav_response resp = { 0 };    dav_walker_ctx *ctx = wres->walk_ctx;    resp.href = wres->resource->uri;    resp.status = status;    if (propstats) {        resp.propresult = *propstats;    }    dav_send_one_response(&resp, ctx->bb, ctx->r->output_filters, pool);}/* ### move this to dav_util? */DAV_DECLARE(void) dav_add_response(dav_walk_resource *wres,                                   int status, dav_get_props_result *propstats){    dav_response *resp;    /* just drop some data into an dav_response */    resp = apr_pcalloc(wres->pool, sizeof(*resp));    resp->href = apr_pstrdup(wres->pool, wres->resource->uri);    resp->status = status;    if (propstats) {        resp->propresult = *propstats;    }    resp->next = wres->response;    wres->response = resp;}/* handle the DELETE method */static int dav_method_delete(request_rec *r){    dav_resource *resource;    dav_auto_version_info av_info;    dav_error *err;    dav_error *err2;    dav_response *multi_response;    int result;    int depth;    /* We don't use the request body right now, so torch it. */    if ((result = ap_discard_request_body(r)) != OK) {        return result;    }    /* Ask repository module to resolve the resource */    err = dav_get_resource(r, 0 /* label_allowed */, 0 /* use_checked_in */,                           &resource);    if (err != NULL)        return dav_handle_err(r, err, NULL);    if (!resource->exists) {        /* Apache will supply a default error for this. */        return HTTP_NOT_FOUND;    }    /* 2518 says that depth must be infinity only for collections.     * For non-collections, depth is ignored, unless it is an illegal value (1).     */    depth = dav_get_depth(r, DAV_INFINITY);    if (resource->collection && depth != DAV_INFINITY) {        /* This supplies additional information for the default message. */        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                      "Depth must be \"infinity\" for DELETE of a collection.");        return HTTP_BAD_REQUEST;    }    if (!resource->collection && depth == 1) {        /* This supplies additional information for the default message. */        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                      "Depth of \"1\" is not allowed for DELETE.");        return HTTP_BAD_REQUEST;    }    /*    ** If any resources fail the lock/If: conditions, then we must fail    ** the delete. Each of the failing resources will be listed within    ** a DAV:multistatus body, wrapped into a 424 response.    **    ** Note that a failure on the resource itself does not generate a    ** multistatus response -- only internal members/collections.    */    if ((err = dav_validate_request(r, resource, depth, NULL,                                    &multi_response,                                    DAV_VALIDATE_PARENT                                    | DAV_VALIDATE_USE_424, NULL)) != NULL) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -