📄 path.c
字号:
/* URI-encode each character c in PATH for which TABLE[c] is 0. If no encoding was needed, return PATH, else return a new string allocated in POOL. */static const char *uri_escape(const char *path, const char table[], apr_pool_t *pool){ svn_stringbuf_t *retstr; apr_size_t i, copied = 0; int c; retstr = svn_stringbuf_create("", pool); for (i = 0; path[i]; i++) { c = (unsigned char)path[i]; if (table[c]) continue; /* If we got here, we're looking at a character that isn't supported by the (or at least, our) URI encoding scheme. We need to escape this character. */ /* First things first, copy all the good stuff that we haven't yet copied into our output buffer. */ if (i - copied) svn_stringbuf_appendbytes(retstr, path + copied, i - copied); /* Now, sprintf() in our escaped character, making sure our buffer is big enough to hold the '%' and two digits. We cast the C to unsigned char here because the 'X' format character will be tempted to treat it as an unsigned int...which causes problem when messing with 0x80-0xFF chars. We also need space for a null as sprintf will write one. */ svn_stringbuf_ensure(retstr, retstr->len + 4); sprintf(retstr->data + retstr->len, "%%%02X", (unsigned char)c); retstr->len += 3; /* Finally, update our copy counter. */ copied = i + 1; } /* If we didn't encode anything, we don't need to duplicate the string. */ if (retstr->len == 0) return path; /* Anything left to copy? */ if (i - copied) svn_stringbuf_appendbytes(retstr, path + copied, i - copied); /* retstr is null-terminated either by sprintf or the svn_stringbuf functions. */ return retstr->data;}const char *svn_path_uri_encode(const char *path, apr_pool_t *pool){ const char *ret; ret = uri_escape(path, uri_char_validity, pool); /* Our interface guarantees a copy. */ if (ret == path) return apr_pstrdup(pool, path); else return ret;}static const char iri_escape_chars[256] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 128 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};const char *svn_path_uri_from_iri(const char *iri, apr_pool_t *pool){ return uri_escape(iri, iri_escape_chars, pool);}const char uri_autoescape_chars[256] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, /* 64 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, /* 128 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 192 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,};const char *svn_path_uri_autoescape(const char *uri, apr_pool_t *pool){ return uri_escape(uri, uri_autoescape_chars, pool);}const char *svn_path_uri_decode(const char *path, apr_pool_t *pool){ svn_stringbuf_t *retstr; apr_size_t i; svn_boolean_t query_start = FALSE; retstr = svn_stringbuf_create("", pool); /* avoid repeated realloc */ svn_stringbuf_ensure(retstr, strlen(path) + 1); retstr->len = 0; for (i = 0; path[i]; i++) { char c = path[i]; if (c == '?') { /* Mark the start of the query string, if it exists. */ query_start = TRUE; } else if (c == '+' && query_start) { /* Only do this if we are into the query string. * RFC 2396, section 3.3 */ c = ' '; } else if (c == '%' && apr_isxdigit(path[i + 1]) && apr_isxdigit(path[i+2])) { char digitz[3]; digitz[0] = path[++i]; digitz[1] = path[++i]; digitz[2] = '\0'; c = (char)(strtol(digitz, NULL, 16)); } retstr->data[retstr->len++] = c; } /* Null-terminate this bad-boy. */ retstr->data[retstr->len] = 0; return retstr->data;}const char *svn_path_url_add_component(const char *url, const char *component, apr_pool_t *pool){ /* URL can have trailing '/' */ url = svn_path_canonicalize(url, pool); return svn_path_join(url, svn_path_uri_encode(component, pool), pool);}svn_error_t *svn_path_get_absolute(const char **pabsolute, const char *relative, apr_pool_t *pool){ char *buffer; apr_status_t apr_err; const char *path_apr; SVN_ERR(svn_path_cstring_from_utf8 (&path_apr, svn_path_canonicalize(relative, pool), pool)); if (svn_path_is_url(path_apr)) { buffer = apr_pstrdup(pool, path_apr); } else { apr_err = apr_filepath_merge(&buffer, NULL, path_apr, (APR_FILEPATH_NOTRELATIVE | APR_FILEPATH_TRUENAME), pool); if (apr_err) return svn_error_createf(SVN_ERR_BAD_FILENAME, NULL, _("Couldn't determine absolute path of '%s'"), svn_path_local_style(relative, pool)); } SVN_ERR(svn_path_cstring_to_utf8(pabsolute, buffer, pool)); *pabsolute = svn_path_canonicalize(*pabsolute, pool); return SVN_NO_ERROR;}svn_error_t *svn_path_split_if_file(const char *path, const char **pdirectory, const char **pfile, apr_pool_t *pool){ apr_finfo_t finfo; svn_error_t *err; /* assert (is_canonical (path, strlen (path))); ### Expensive strlen */ err = svn_io_stat(&finfo, path, APR_FINFO_TYPE, pool); if (err && ! APR_STATUS_IS_ENOENT(err->apr_err)) return err; if (err || finfo.filetype == APR_REG) { if (err) svn_error_clear(err); svn_path_split(path, pdirectory, pfile, pool); } else if (finfo.filetype == APR_DIR) { *pdirectory = path; *pfile = SVN_EMPTY_PATH; } else { return svn_error_createf(SVN_ERR_BAD_FILENAME, NULL, _("'%s' is neither a file nor a directory name"), svn_path_local_style(path, pool)); } return SVN_NO_ERROR;}const char *svn_path_canonicalize(const char *path, apr_pool_t *pool){ char *canon, *dst; const char *src; apr_size_t seglen; apr_size_t canon_segments = 0; svn_boolean_t uri; dst = canon = apr_pcalloc(pool, strlen(path) + 1); /* Copy over the URI scheme if present. */ src = skip_uri_scheme(path); if (src) { uri = TRUE; memcpy(dst, path, src - path); dst += (src - path); } else { uri = FALSE; src = path; } /* If this is an absolute path, then just copy over the initial separator character. */ if (*src == '/') { *(dst++) = *(src++);#if defined(WIN32) || defined(__CYGWIN__) /* On Windows permit two leading separator characters which means an * UNC path. However, a double slash in a URI after the scheme is never * valid. */ if (!uri && *src == '/') *(dst++) = *(src++);#endif /* WIN32 or Cygwin */ } while (*src) { /* Parse each segment, find the closing '/' */ const char *next = src; while (*next && (*next != '/')) ++next; seglen = next - src; if (seglen == 0 || (seglen == 1 && src[0] == '.')) { /* Noop segment, so do nothing. */ } else { /* An actual segment, append it to the destination path */ if (*next) seglen++; memcpy(dst, src, seglen); dst += seglen; canon_segments++; } /* Skip over trailing slash to the next segment. */ src = next; if (*src) src++; } /* Remove the trailing slash. */ if ((canon_segments > 0 || uri) && *(dst - 1) == '/') dst--; *dst = '\0';#if defined(WIN32) || defined(__CYGWIN__) /* Skip leading double slashes when there are less than 2 * canon segments. UNC paths *MUST* have two segments. */ if (canon_segments < 2 && canon[0] == '/' && canon[1] == '/') return canon + 1;#endif /* WIN32 or Cygwin */ return canon;}/** Get APR's internal path encoding. */static svn_error_t *get_path_encoding(svn_boolean_t *path_is_utf8, apr_pool_t *pool){ apr_status_t apr_err; int encoding_style; apr_err = apr_filepath_encoding(&encoding_style, pool); if (apr_err) return svn_error_wrap_apr(apr_err, _("Can't determine the native path encoding")); /* ### What to do about APR_FILEPATH_ENCODING_UNKNOWN? Well, for now we'll just punt to the svn_utf_ functions; those will at least do the ASCII-subset check. */ *path_is_utf8 = (encoding_style == APR_FILEPATH_ENCODING_UTF8); return SVN_NO_ERROR;}svn_error_t *svn_path_cstring_from_utf8(const char **path_apr, const char *path_utf8, apr_pool_t *pool){ svn_boolean_t path_is_utf8; SVN_ERR(get_path_encoding(&path_is_utf8, pool)); if (path_is_utf8) { *path_apr = apr_pstrdup(pool, path_utf8); return SVN_NO_ERROR; } else return svn_utf_cstring_from_utf8(path_apr, path_utf8, pool);}svn_error_t *svn_path_cstring_to_utf8(const char **path_utf8, const char *path_apr, apr_pool_t *pool){ svn_boolean_t path_is_utf8; SVN_ERR(get_path_encoding(&path_is_utf8, pool)); if (path_is_utf8) { *path_utf8 = apr_pstrdup(pool, path_apr); return SVN_NO_ERROR; } else return svn_utf_cstring_to_utf8(path_utf8, path_apr, pool);}svn_error_t *svn_path_check_valid(const char *path, apr_pool_t *pool){ const char *c; for (c = path; *c; c++) { if (svn_ctype_iscntrl(*c)) { return svn_error_createf (SVN_ERR_FS_PATH_SYNTAX, NULL, _("Invalid control character '0x%02x' in path '%s'"), *c, svn_path_local_style(path, pool)); } } return SVN_NO_ERROR;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -