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

📄 path.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 3 页
字号:
          return FALSE;
        }
      else if (! uri_char_validity[((unsigned char)path[i])])
        {
          return FALSE;
        }
    } 

  return TRUE;
}
  
/* 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 int 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 int 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 int 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)
{
  /* We call svn_path_canonicalize() on the input data, rather
     than the output, so that `buffer' can be returned directly
     without const vs non-const issues. */
  /* ### This comment seems totally wrong, what? --xbc */

  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'", 
                                 relative);
    }

  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",
                               path);
    }

  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 shema if present. */
  src = skip_uri_schema (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);
}

⌨️ 快捷键说明

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