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

📄 util.c

📁 linux网络服务器工具
💻 C
📖 第 1 页 / 共 5 页
字号:
                                                     "Invalid \"If:\" "                                                     "header: Unexpected "                                                     "character encountered "                                                     "(0x%02x, '%c').",                                                     *list, *list));                }                list++;            }            break;        case ' ':        case '\t':            break;        default:            return dav_new_error(r->pool, HTTP_BAD_REQUEST,                                 DAV_ERR_IF_UNK_CHAR,                                 apr_psprintf(r->pool,                                             "Invalid \"If:\" header: "                                             "Unexpected character "                                             "encountered (0x%02x, '%c').",                                             *str, *str));        }        str++;    }    *p_ih = ih;    return NULL;}static int dav_find_submitted_locktoken(const dav_if_header *if_header,                                        const dav_lock *lock_list,                                        const dav_hooks_locks *locks_hooks){    for (; if_header != NULL; if_header = if_header->next) {        const dav_if_state_list *state_list;        for (state_list = if_header->state;             state_list != NULL;             state_list = state_list->next) {            if (state_list->type == dav_if_opaquelock) {                const dav_lock *lock;                /* given state_list->locktoken, match it */                /*                ** The resource will have one or more lock tokens. We only                ** need to match one of them against any token in the                ** If: header.                **                ** One token case: It is an exclusive or shared lock. Either                **                 way, we must find it.                **                ** N token case: They are shared locks. By policy, we need                **               to match only one. The resource's other                **               tokens may belong to somebody else (so we                **               shouldn't see them in the If: header anyway)                */                for (lock = lock_list; lock != NULL; lock = lock->next) {                    if (!(*locks_hooks->compare_locktoken)(state_list->locktoken, lock->locktoken)) {                        return 1;                    }                }            }        }    }    return 0;}/* dav_validate_resource_state: *    Returns NULL if path/uri meets if-header and lock requirements */static dav_error * dav_validate_resource_state(apr_pool_t *p,                                               const dav_resource *resource,                                               dav_lockdb *lockdb,                                               const dav_if_header *if_header,                                               int flags,                                               dav_buffer *pbuf,                                               request_rec *r){    dav_error *err;    const char *uri;    const char *etag;    const dav_hooks_locks *locks_hooks = (lockdb ? lockdb->hooks : NULL);    const dav_if_header *ifhdr_scan;    dav_if_state_list *state_list;    dav_lock *lock_list;    dav_lock *lock;    int num_matched;    int num_that_apply;    int seen_locktoken;    apr_size_t uri_len;    const char *reason = NULL;    /* DBG1("validate: <%s>", resource->uri); */    /*    ** The resource will have one of three states:    **    ** 1) No locks. We have no special requirements that the user supply    **    specific locktokens. One of the state lists must match, and    **    we're done.    **    ** 2) One exclusive lock. The locktoken must appear *anywhere* in the    **    If: header. Of course, asserting the token in a "Not" term will    **    quickly fail that state list :-). If the locktoken appears in    **    one of the state lists *and* one state list matches, then we're    **    done.    **    ** 3) One or more shared locks. One of the locktokens must appear    **    *anywhere* in the If: header. If one of the locktokens appears,    **    and we match one state list, then we are done.    **    ** The <seen_locktoken> variable determines whether we have seen one    ** of this resource's locktokens in the If: header.    */    /*    ** If this is a new lock request, <flags> will contain the requested    ** lock scope.  Three rules apply:    **    ** 1) Do not require a (shared) locktoken to be seen (when we are    **    applying another shared lock)    ** 2) If the scope is exclusive and we see any locks, fail.    ** 3) If the scope is shared and we see an exclusive lock, fail.    */    if (lockdb == NULL) {        /* we're in State 1. no locks. */        lock_list = NULL;    }    else {        /*        ** ### hrm... we don't need to have these fully        ** ### resolved since we're only looking at the        ** ### locktokens...        **        ** ### use get_locks w/ calltype=PARTIAL        */        if ((err = dav_lock_query(lockdb, resource, &lock_list)) != NULL) {            return dav_push_error(p,                                  HTTP_INTERNAL_SERVER_ERROR, 0,                                  "The locks could not be queried for "                                  "verification against a possible \"If:\" "                                  "header.",                                  err);        }        /* lock_list now determines whether we're in State 1, 2, or 3. */    }    /*    ** For a new, exclusive lock: if any locks exist, fail.    ** For a new, shared lock:    if an exclusive lock exists, fail.    **                            else, do not require a token to be seen.    */    if (flags & DAV_LOCKSCOPE_EXCLUSIVE) {        if (lock_list != NULL) {            return dav_new_error(p, HTTP_LOCKED, 0,                                 "Existing lock(s) on the requested resource "                                 "prevent an exclusive lock.");        }        /*        ** There are no locks, so we can pretend that we've already met        ** any requirement to find the resource's locks in an If: header.        */        seen_locktoken = 1;    }    else if (flags & DAV_LOCKSCOPE_SHARED) {        /*        ** Strictly speaking, we don't need this loop. Either the first        ** (and only) lock will be EXCLUSIVE, or none of them will be.        */        for (lock = lock_list; lock != NULL; lock = lock->next) {            if (lock->scope == DAV_LOCKSCOPE_EXCLUSIVE) {                return dav_new_error(p, HTTP_LOCKED, 0,                                     "The requested resource is already "                                     "locked exclusively.");            }        }        /*        ** The locks on the resource (if any) are all shared. Set the        ** <seen_locktoken> flag to indicate that we do not need to find        ** the locks in an If: header.        */        seen_locktoken = 1;    }    else {        /*        ** For methods other than LOCK:        **        ** If we have no locks, then <seen_locktoken> can be set to true --        ** pretending that we've already met the requirement of seeing one        ** of the resource's locks in the If: header.        **        ** Otherwise, it must be cleared and we'll look for one.        */        seen_locktoken = (lock_list == NULL);    }    /*    ** If there is no If: header, then we can shortcut some logic:    **    ** 1) if we do not need to find a locktoken in the (non-existent) If:    **    header, then we are successful.    **    ** 2) if we must find a locktoken in the (non-existent) If: header, then    **    we fail.    */    if (if_header == NULL) {        if (seen_locktoken)            return NULL;        return dav_new_error(p, HTTP_LOCKED, 0,                             "This resource is locked and an \"If:\" header "                             "was not supplied to allow access to the "                             "resource.");    }    /* the If: header is present */    /*    ** If a dummy header is present (because of a Lock-Token: header), then    ** we are required to find that token in this resource's set of locks.    ** If we have no locks, then we immediately fail.    **    ** This is a 400 (Bad Request) since they should only submit a locktoken    ** that actually exists.    **    ** Don't issue this response if we're talking about the parent resource.    ** It is okay for that resource to NOT have this locktoken.    ** (in fact, it certainly will not: a dummy_header only occurs for the    **  UNLOCK method, the parent is checked only for locknull resources,    **  and the parent certainly does not have the (locknull's) locktoken)    */    if (lock_list == NULL && if_header->dummy_header) {        if (flags & DAV_VALIDATE_IS_PARENT)            return NULL;        return dav_new_error(p, HTTP_BAD_REQUEST, 0,                             "The locktoken specified in the \"Lock-Token:\" "                             "header is invalid because this resource has no "                             "outstanding locks.");    }    /*    ** Prepare the input URI. We want the URI to never have a trailing slash.    **    ** When URIs are placed into the dav_if_header structure, they are    ** guaranteed to never have a trailing slash. If the URIs are equivalent,    ** then it doesn't matter if they both lack a trailing slash -- they're    ** still equivalent.    **    ** Note: we could also ensure that a trailing slash is present on both    ** URIs, but the majority of URIs provided to us via a resource walk    ** will not contain that trailing slash.    */    uri = resource->uri;    uri_len = strlen(uri);    if (uri[uri_len - 1] == '/') {        dav_set_bufsize(p, pbuf, uri_len);        memcpy(pbuf->buf, uri, uri_len);        pbuf->buf[--uri_len] = '\0';        uri = pbuf->buf;    }    /* get the resource's etag; we may need it during the checks */    etag = (*resource->hooks->getetag)(resource);    /* how many state_lists apply to this URI? */    num_that_apply = 0;    /* If there are if-headers, fail if this resource     * does not match at least one state_list.     */    for (ifhdr_scan = if_header;         ifhdr_scan != NULL;         ifhdr_scan = ifhdr_scan->next) {        /* DBG2("uri=<%s>  if_uri=<%s>", uri, ifhdr_scan->uri ? ifhdr_scan->uri : "(no uri)"); */        if (ifhdr_scan->uri != NULL            && (uri_len != ifhdr_scan->uri_len                || memcmp(uri, ifhdr_scan->uri, uri_len) != 0)) {            /*            ** A tagged-list's URI doesn't match this resource's URI.            ** Skip to the next state_list to see if it will match.            */            continue;        }        /* this state_list applies to this resource */        /*        ** ### only one state_list should ever apply! a no-tag, or a tagged        ** ### where S9.4.2 states only one can match.        **        ** ### revamp this code to loop thru ifhdr_scan until we find the        ** ### matching state_list. process it. stop.        */        ++num_that_apply;        /* To succeed, resource must match *all* of the states         * specified in the state_list.         */        for (state_list = ifhdr_scan->state;             state_list != NULL;             state_list = state_list->next) {            switch(state_list->type) {            case dav_if_etag:            {                const char *given_etag, *current_etag;                int mismatch;                /* Do a weak entity comparison function as defined in                 * RFC 2616 13.3.3.                 */                if (state_list->etag[0] == 'W' &&                    state_list->etag[1] == '/') {                    given_etag = state_list->etag + 2;                }                else {                    given_etag = state_list->etag;                }                if (etag[0] == 'W' &&                    etag[1] == '/') {                    current_etag = etag + 2;                }                else {                    current_etag = etag;                }                mismatch = strcmp(given_etag, current_etag);                if (state_list->condition == DAV_IF_COND_NORMAL && mismatch) {                    /*                    ** The specified entity-tag does not match the                    ** entity-tag on the resource. This state_list is                    ** not going to match. Bust outta here.                    */                    reason =                        "an entity-tag was specified, but the resource's "                        "actual ETag does not match.";                    goto state_list_failed;                }                else if (state_list->condition == DAV_IF_COND_NOT                         && !mismatch) {                    /*                    ** The specified entity-tag DOES match the                    ** entity-tag on the resource. This state_list is                    ** not going to match. Bust outta here.                    */                    reason =                        "an entity-tag was specified using the \"Not\" form, "                        "but the resource's actual ETag matches the provided "

⌨️ 快捷键说明

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