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

📄 filepath.c

📁 Apache 2.0.63 is the current stable version of the 2.0 series, and is recommended over any previous
💻 C
📖 第 1 页 / 共 3 页
字号:
                return APR_EBADPATH;

#ifndef NETWARE
            /* This isn't legal unless the unc path is completed
             */
            if (fixunc)
                return APR_EBADPATH;
#endif

            /* backpath (../) when an absolute path is given */
            if (rootlen && (pathlen <= rootlen)) 
            {
                /* Attempt to move above root.  Always die if the 
                 * APR_FILEPATH_SECUREROOTTEST flag is specified.
                 */
                if (flags & APR_FILEPATH_SECUREROOTTEST)
                    return APR_EABOVEROOT;
                
                /* Otherwise this is simply a noop, above root is root.
                 */
            }
            else if (pathlen == 0 
                      || (pathlen >= 3 
                           && (pathlen == 3
                                || path[pathlen - 4] == ':'
                                || path[pathlen - 4] == '/' 
                                || path[pathlen - 4] == '\\')
                           &&  path[pathlen - 3] == '.' 
                           &&  path[pathlen - 2] == '.' 
                           && (path[pathlen - 1] == '/' 
                                || path[pathlen - 1] == '\\')))
            {
                /* Verified path is empty, exactly "..[/\]", or ends
                 * in "[:/\]..[/\]" - these patterns we will not back
                 * over since they aren't 'prior segements'.
                 * 
                 * If APR_FILEPATH_SECUREROOTTEST.was given, die now.
                 */
                if (flags & APR_FILEPATH_SECUREROOTTEST)
                    return APR_EABOVEROOT;

                /* Otherwise append another backpath.
                 */
                if (pathlen + 3 >= sizeof(path))
                    return APR_ENAMETOOLONG;
                path[pathlen++] = '.';
                path[pathlen++] = '.';
                if (addpath[segend]) {
                    path[pathlen++] = ((flags & APR_FILEPATH_NATIVE) 
                                    ? '\\' : ((flags & APR_FILEPATH_TRUENAME)
                                           ? '/' : addpath[segend]));
                }
                /* The 'root' part of this path now includes the ../ path,
                 * because that backpath will not be parsed by the truename
                 * code below.
                 */
                keptlen = pathlen;
            }
            else 
            {
                /* otherwise crop the prior segment 
                 */
                do {
                    --pathlen;
                } while (pathlen && path[pathlen - 1] != '/'
                                 && path[pathlen - 1] != '\\');

                /* Now test if we are above where we started and back up
                 * the keptlen offset to reflect the added/altered path.
                 */
                if (pathlen < keptlen) 
                {
                    if (flags & APR_FILEPATH_SECUREROOTTEST)
                        return APR_EABOVEROOT;
                    keptlen = pathlen;
                }
            }
        }
        else /* not empty or dots */
        {
#ifndef NETWARE
            if (fixunc) {
                const char *testpath = path;
                const char *testroot;
                apr_status_t testtype;
                apr_size_t i = (addpath[segend] != '\0');
                
                /* This isn't legal unless the unc path is complete!
                 */
                if (seglen < segend)
                    return APR_EBADPATH;
                if (pathlen + seglen + 1 >= sizeof(path))
                    return APR_ENAMETOOLONG;
                memcpy(path + pathlen, addpath, seglen + i);
                
                /* Always add the trailing slash to a UNC segment
                 */
                path[pathlen + seglen] = ((flags & APR_FILEPATH_NATIVE) 
                                             ? '\\' : '/');
                pathlen += seglen + 1;

                /* Recanonicalize the UNC root with the new UNC segment,
                 * and if we succeed, reset this test and the rootlen,
                 * and replace our path with the canonical UNC root path
                 */
                path[pathlen] = '\0';
                /* This call _should_ test the path
                 */
                testtype = apr_filepath_root(&testroot, &testpath, 
                                             APR_FILEPATH_TRUENAME
                                             | (flags & APR_FILEPATH_NATIVE),
                                             p);
                if (testtype == APR_SUCCESS) {
                    rootlen = pathlen = (testpath - path);
                    memcpy(path, testroot, pathlen);
                    fixunc = 0;
                }
                else if (testtype != APR_EINCOMPLETE) {
                    /* apr_filepath_root was very unexpected so fail already
                     */
                    return testtype;
                }
            }
            else
#endif
            {
                /* An actual segment, append it to the destination path
                 */
                apr_size_t i = (addpath[segend] != '\0');
                if (pathlen + seglen + i >= sizeof(path))
                    return APR_ENAMETOOLONG;
                memcpy(path + pathlen, addpath, seglen + i);
                if (i)
                    path[pathlen + seglen] = ((flags & APR_FILEPATH_NATIVE) 
                                                 ? '\\' : '/');
                pathlen += seglen + i;
            }
        }

        /* Skip over trailing slash to the next segment
         */
        if (addpath[segend])
            ++segend;

        addpath += segend;
    }
    
    /* keptlen will be the baselen unless the addpath contained
     * backpath elements.  If so, and APR_FILEPATH_NOTABOVEROOT
     * is specified (APR_FILEPATH_SECUREROOTTEST was caught above),
     * compare the string beyond the root to assure the result path 
     * is still within given basepath.  Note that the root path 
     * segment is thoroughly tested prior to path parsing.
     */
    if ((flags & APR_FILEPATH_NOTABOVEROOT) && baselen) {
        if (memcmp(basepath, path + rootlen, baselen) != 0)
            return APR_EABOVEROOT;
 
         /* Ahem... if we have a basepath without a trailing slash,
          * we better be sure that /foo wasn't replaced with /foobar!
          */
        if (basepath[baselen - 1] != '/' && basepath[baselen - 1] != '\\'
              && path[rootlen + baselen] && path[rootlen + baselen] != '/' 
                                         && path[rootlen + baselen] != '\\')
            return APR_EABOVEROOT;
    }

    if (addpath && (flags & APR_FILEPATH_TRUENAME)) {
        /* We can always skip the root, it's already true-named. */
        if (rootlen > keptlen)
            keptlen = rootlen;
        if ((path[keptlen] == '/') || (path[keptlen] == '\\')) {
            /* By rights, keptlen may grown longer than pathlen.
             * we wont' use it again (in that case) so we don't care.
             */
            ++keptlen;
        }
        /* Go through all the new segments */
        while (keptlen < pathlen) {
            apr_finfo_t finfo;
            char saveslash = 0;
            seglen = 0;
            /* find any slash and set it aside for a minute. */
            for (seglen = 0; keptlen + seglen < pathlen; ++seglen) {
                if ((path[keptlen + seglen] == '/')  ||
                    (path[keptlen + seglen] == '\\')) {
                    saveslash = path[keptlen + seglen];
                    break;
                }
            }
            /* Null term for stat! */
            path[keptlen + seglen] = '\0';
            if ((rv = apr_lstat(&finfo, path, 
                                APR_FINFO_TYPE | APR_FINFO_NAME, p))
                == APR_SUCCESS) {
                apr_size_t namelen = strlen(finfo.name);

#if defined(OS2) /* only has case folding, never aliases that change the length */

                if (memcmp(finfo.name, path + keptlen, seglen) != 0) {
                    memcpy(path + keptlen, finfo.name, namelen);
                }
#else /* WIN32 || NETWARE; here there be aliases that gire and gimble and change length */

                if ((namelen != seglen) || 
                    (memcmp(finfo.name, path + keptlen, seglen) != 0)) 
                {
                    if (namelen <= seglen) {
                        memcpy(path + keptlen, finfo.name, namelen);
                        if ((namelen < seglen) && saveslash) {
                            memmove(path + keptlen + namelen + 1,
                                   path + keptlen + seglen + 1,
                                   pathlen - keptlen - seglen);
                            pathlen += namelen - seglen;
                            seglen = namelen;
                        }
                    }
                    else { /* namelen > seglen */
                        if (pathlen + namelen - seglen >= sizeof(path))
                            return APR_ENAMETOOLONG;
                        if (saveslash) {
                            memmove(path + keptlen + namelen + 1,
                                   path + keptlen + seglen + 1,
                                   pathlen - keptlen - seglen);
                        }
                        memcpy(path + keptlen, finfo.name, namelen);
                        pathlen += namelen - seglen;
                        seglen = namelen;
                    }
                }
#endif /* !OS2 (Whatever that alias was we're over it) */

                /* That's it, the rest is path info. 
                 * I don't know how we aught to handle this.  Should
                 * we define a new error to indicate 'more info'?
                 * Should we split out the rest of the path?
                 */
                if ((finfo.filetype != APR_DIR) && 
                    (finfo.filetype != APR_LNK) && saveslash) 
                    rv = APR_ENOTDIR;
#ifdef XXX_FIGURE_THIS_OUT
                {
                    /* the example inserts a null between the end of 
                     * the filename and the next segment, and increments
                     * the path length so we would return both segments.
                     */
                    if (saveslash) {
                        keptlen += seglen;
                        path[keptlen] = saveslash;
                        if (pathlen + 1 >= sizeof(path))
                            return APR_ENAMETOOLONG;
                        memmove(path + keptlen + 1,
                               path + keptlen,
                               pathlen - keptlen);
                        path[keptlen] = '\0';
                        ++pathlen;
                        break;
                    }
                }
#endif
            }

            /* put back the '/' */
            if (saveslash) {
                path[keptlen + seglen] = saveslash;
                ++seglen;
            }
            keptlen += seglen;

            if (rv != APR_SUCCESS) {
                if (APR_STATUS_IS_ENOENT(rv))
                    break;
                if (APR_STATUS_IS_EPATHWILD(rv))
                    /* This path included wildcards.  The path elements
                     * that did not contain wildcards are canonicalized,
                     * so we will return the path, although later elements
                     * don't necessarily exist, and aren't canonical.
                     */
                    break;
                else if (APR_STATUS_IS_ENOTDIR(rv))
                    /* This is a little more serious, we just added a name
                     * onto a filename (think http's PATH_INFO)
                     * If the caller is foolish enough to do this, we expect
                     * the've already canonicalized the root) that they knew
                     * what they are doing :(
                     */
                    break;
                else
                    return rv;
            }
        }
    }

    *newpath = apr_pmemdup(p, path, pathlen + 1);
    (*newpath)[pathlen] = '\0';
    return APR_SUCCESS;
}


APR_DECLARE(apr_status_t) apr_filepath_list_split(apr_array_header_t **pathelts,
                                                  const char *liststr,
                                                  apr_pool_t *p)
{
    return apr_filepath_list_split_impl(pathelts, liststr, ';', p);
}

APR_DECLARE(apr_status_t) apr_filepath_list_merge(char **liststr,
                                                  apr_array_header_t *pathelts,
                                                  apr_pool_t *p)
{
    return apr_filepath_list_merge_impl(liststr, pathelts, ';', p);
}


APR_DECLARE(apr_status_t) apr_filepath_encoding(int *style, apr_pool_t *p)
{
#if APR_HAS_UNICODE_FS
    IF_WIN_OS_IS_UNICODE
    {
        *style = APR_FILEPATH_ENCODING_UTF8;
        return APR_SUCCESS;
    }
#endif

    *style = APR_FILEPATH_ENCODING_LOCALE;
    return APR_SUCCESS;
}

⌨️ 快捷键说明

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