diff options
Diffstat (limited to 'subversion/libsvn_subr/dirent_uri.c')
| -rw-r--r-- | subversion/libsvn_subr/dirent_uri.c | 94 | 
1 files changed, 61 insertions, 33 deletions
| diff --git a/subversion/libsvn_subr/dirent_uri.c b/subversion/libsvn_subr/dirent_uri.c index 6886a3e7550e..a009145eb946 100644 --- a/subversion/libsvn_subr/dirent_uri.c +++ b/subversion/libsvn_subr/dirent_uri.c @@ -1294,6 +1294,29 @@ svn_relpath_split(const char **dirpath,      *base_name = svn_relpath_basename(relpath, pool);  } +const char * +svn_relpath_prefix(const char *relpath, +                   int max_components, +                   apr_pool_t *result_pool) +{ +  const char *end; +  assert(relpath_is_canonical(relpath)); + +  if (max_components <= 0) +    return ""; + +  for (end = relpath; *end; end++) +    { +      if (*end == '/') +        { +          if (!--max_components) +            break; +        } +    } + +  return apr_pstrmemdup(result_pool, relpath, end-relpath); +} +  char *  svn_uri_dirname(const char *uri, apr_pool_t *pool)  { @@ -1689,7 +1712,9 @@ svn_dirent_is_canonical(const char *dirent, apr_pool_t *scratch_pool)  static svn_boolean_t  relpath_is_canonical(const char *relpath)  { -  const char *ptr = relpath, *seg = relpath; +  const char *dot_pos, *ptr = relpath; +  apr_size_t i, len; +  unsigned pattern = 0;    /* RELPATH is canonical if it has:     *  - no '.' segments @@ -1697,35 +1722,38 @@ relpath_is_canonical(const char *relpath)     *  - no '//'     */ -  if (*relpath == '\0') -    return TRUE; - +  /* invalid beginnings */    if (*ptr == '/')      return FALSE; -  /* Now validate the rest of the path. */ -  while(1) -    { -      apr_size_t seglen = ptr - seg; - -      if (seglen == 1 && *seg == '.') -        return FALSE;  /*  /./   */ - -      if (*ptr == '/' && *(ptr+1) == '/') -        return FALSE;  /*  //    */ +  if (ptr[0] == '.' && (ptr[1] == '/' || ptr[1] == '\0')) +    return FALSE; -      if (! *ptr && *(ptr - 1) == '/') -        return FALSE;  /* foo/  */ +  /* valid special cases */ +  len = strlen(ptr); +  if (len < 2) +    return TRUE; -      if (! *ptr) -        break; +  /* invalid endings */ +  if (ptr[len-1] == '/' || (ptr[len-1] == '.' && ptr[len-2] == '/')) +    return FALSE; -      if (*ptr == '/') -        ptr++; -      seg = ptr; +  /* '.' are rare. So, search for them globally. There will often be no +   * more than one hit.  Also note that we already checked for invalid +   * starts and endings, i.e. we only need to check for "/./" +   */ +  for (dot_pos = memchr(ptr, '.', len); +       dot_pos; +       dot_pos = strchr(dot_pos+1, '.')) +    if (dot_pos > ptr && dot_pos[-1] == '/' && dot_pos[1] == '/') +      return FALSE; -      while (*ptr && (*ptr != '/')) -        ptr++; +  /* Now validate the rest of the path. */ +  for (i = 0; i < len - 1; ++i) +    { +      pattern = ((pattern & 0xff) << 8) + (unsigned char)ptr[i]; +      if (pattern == 0x101 * (unsigned char)('/')) +        return FALSE;      }    return TRUE; @@ -2315,7 +2343,7 @@ svn_uri_get_dirent_from_file_url(const char **dirent,                                 "prefix"), url);    /* Find the HOSTNAME portion and the PATH portion of the URL.  The host -     name is between the "file://" prefix and the next occurence of '/'.  We +     name is between the "file://" prefix and the next occurrence of '/'.  We       are considering everything from that '/' until the end of the URL to be       the absolute path portion of the URL.       If we got just "file://", treat it the same as "file:///". */ @@ -2394,7 +2422,7 @@ svn_uri_get_dirent_from_file_url(const char **dirent,                                       "no path"), url);          /* We still know that the path starts with a slash. */ -        *dirent = apr_pstrcat(pool, "//", hostname, dup_path, NULL); +        *dirent = apr_pstrcat(pool, "//", hostname, dup_path, SVN_VA_NULL);        }      else        *dirent = dup_path; @@ -2427,18 +2455,18 @@ svn_uri_get_file_url_from_dirent(const char **url,    if (dirent[0] == '/' && dirent[1] == '\0')      dirent = NULL; /* "file://" is the canonical form of "file:///" */ -  *url = apr_pstrcat(pool, "file://", dirent, (char *)NULL); +  *url = apr_pstrcat(pool, "file://", dirent, SVN_VA_NULL);  #else    if (dirent[0] == '/')      {        /* Handle UNC paths //server/share -> file://server/share */        assert(dirent[1] == '/'); /* Expect UNC, not non-absolute */ -      *url = apr_pstrcat(pool, "file:", dirent, NULL); +      *url = apr_pstrcat(pool, "file:", dirent, SVN_VA_NULL);      }    else      { -      char *uri = apr_pstrcat(pool, "file:///", dirent, NULL); +      char *uri = apr_pstrcat(pool, "file:///", dirent, SVN_VA_NULL);        apr_size_t len = 8 /* strlen("file:///") */ + strlen(dirent);        /* "C:/" is a canonical dirent on Windows, @@ -2472,7 +2500,7 @@ svn_fspath__canonicalize(const char *fspath,      return "/";    return apr_pstrcat(pool, "/", svn_relpath_canonicalize(fspath, pool), -                     (char *)NULL); +                     SVN_VA_NULL);  } @@ -2505,7 +2533,7 @@ svn_fspath__dirname(const char *fspath,      return apr_pstrdup(pool, fspath);    else      return apr_pstrcat(pool, "/", svn_relpath_dirname(fspath + 1, pool), -                       (char *)NULL); +                       SVN_VA_NULL);  } @@ -2549,9 +2577,9 @@ svn_fspath__join(const char *fspath,    if (relpath[0] == '\0')      result = apr_pstrdup(result_pool, fspath);    else if (fspath[1] == '\0') -    result = apr_pstrcat(result_pool, "/", relpath, (char *)NULL); +    result = apr_pstrcat(result_pool, "/", relpath, SVN_VA_NULL);    else -    result = apr_pstrcat(result_pool, fspath, "/", relpath, (char *)NULL); +    result = apr_pstrcat(result_pool, fspath, "/", relpath, SVN_VA_NULL);    assert(svn_fspath__is_canonical(result));    return result; @@ -2570,7 +2598,7 @@ svn_fspath__get_longest_ancestor(const char *fspath1,                         svn_relpath_get_longest_ancestor(fspath1 + 1,                                                          fspath2 + 1,                                                          result_pool), -                       (char *)NULL); +                       SVN_VA_NULL);    assert(svn_fspath__is_canonical(result));    return result; | 
