コード例 #1
0
ファイル: split_url.c プロジェクト: aosm/subversion
svn_error_t *
svn_ra_local__split_URL(svn_repos_t **repos,
                        const char **repos_url,
                        const char **fs_path,
                        const char *URL,
                        apr_pool_t *pool)
{
  svn_error_t *err = SVN_NO_ERROR;
  const char *repos_root;
  const char *hostname, *path;
  svn_stringbuf_t *urlbuf;

  /* Verify that the URL is well-formed (loosely) */

  /* First, check for the "file://" prefix. */
  if (strncmp(URL, "file://", 7) != 0)
    return svn_error_createf
      (SVN_ERR_RA_ILLEGAL_URL, NULL,
       _("Local URL '%s' does not contain 'file://' prefix"), URL);

  /* Then, skip what's between the "file://" prefix and the next
     occurance of '/' -- this is the hostname, and 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:///". */
  hostname = URL + 7;
  if (*hostname == '\0')
    {
      path = "/";
      hostname = NULL;
    }
  else
    {
      path = strchr(hostname, '/');
      if (! path)
        return svn_error_createf
          (SVN_ERR_RA_ILLEGAL_URL, NULL,
           _("Local URL '%s' contains only a hostname, no path"), URL);

      /* Treat localhost as an empty hostname. */
      if (hostname != path)
        {
          hostname = svn_path_uri_decode(apr_pstrmemdup(pool, hostname,
                                                        path - hostname), pool);
          if (strncmp(hostname, "localhost", 9) == 0)
            hostname = NULL;
        }
      else
        hostname = NULL;
    }

  /* Duplicate the URL, starting at the top of the path.
     At the same time, we URI-decode the path. */
#if defined(WIN32) || defined(__CYGWIN__)
  /* On Windows, we'll typically have to skip the leading / if the
     path starts with a drive letter.  Like most Web browsers, We
     support two variants of this scheme:

         file:///X:/path    and
         file:///X|/path

    Note that, at least on WinNT and above,  file:////./X:/path  will
    also work, so we must make sure the transformation doesn't break
    that, and  file:///path  (that looks within the current drive
    only) should also keep working.
    If we got a non-empty hostname other than localhost, we convert this
    into an UNC path.  In this case, we obviously don't strip the slash
    even if the path looks like it starts with a drive letter.
    Another thing to remember is that the form file:///\machine/share
    was the only way to access UNC paths in svn before 1.2.  We
    need to support that for compatibility with old working copies.
  */
  {
    static const char valid_drive_letters[] =
      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    /* Casting away const! */
    char *dup_path = (char *)svn_path_uri_decode(path, pool);
    if (!hostname && dup_path[1] && strchr(valid_drive_letters, dup_path[1])
        && (dup_path[2] == ':' || dup_path[2] == '|')
        && dup_path[3] == '/')
      {
        /* Skip the leading slash. */
        ++dup_path;
        /* We're using path below to calculate fs_path, so keep it in sync. */
        ++path;
        if (dup_path[1] == '|')
          dup_path[1] = ':';
      }
    if (hostname)
      /* We still know that the path starts with a slash. */
      repos_root = apr_pstrcat(pool, "//", hostname, path, NULL);
    else
      repos_root = dup_path;
  }
#else
  /* Currently, the only hostnames we are allowing on non-Win32 platforms
     are the empty string and 'localhost'. */
  if (hostname)
    return svn_error_createf
      (SVN_ERR_RA_ILLEGAL_URL, NULL,
       _("Local URL '%s' contains unsupported hostname"), URL);

  repos_root = svn_path_uri_decode(path, pool);
#endif

  /* Search for a repository in the full path. */
  repos_root = svn_repos_find_root_path(repos_root, pool);
  if (!repos_root)
    return svn_error_createf
      (SVN_ERR_RA_LOCAL_REPOS_OPEN_FAILED, NULL,
       _("Unable to open repository '%s'"), URL);

  /* Attempt to open a repository at URL. */
  err = svn_repos_open(repos, repos_root, pool);
  if (err)
    return svn_error_createf
      (SVN_ERR_RA_LOCAL_REPOS_OPEN_FAILED, err,
       _("Unable to open repository '%s'"), URL);

  /* Assert capabilities directly, since client == server. */
  {
    apr_array_header_t *caps = apr_array_make(pool, 1, sizeof(const char *));
    APR_ARRAY_PUSH(caps, const char *) = SVN_RA_CAPABILITY_MERGEINFO;
    SVN_ERR(svn_repos_remember_client_capabilities(*repos, caps));
  }

  /* What remains of URL after being hacked at in the previous step is
     REPOS_URL.  FS_PATH is what we've hacked off in the process.
     Note that path is not encoded and what we gave to svn_root_find_root_path
     may have been destroyed by that function.  So we have to decode it once
     more.  But then, it is ours...
     We want the suffix of path after the repos root part.  Note that
     repos_root may contain //hostname, but path doesn't.  */
  *fs_path = svn_path_uri_decode(path, pool)
    + (strlen(repos_root)
       - (hostname ? strlen(hostname) + 2 : 0));

  /* Ensure that *FS_PATH has its leading slash. */
  if (**fs_path != '/')
    *fs_path = apr_pstrcat(pool, "/", *fs_path, NULL);

  /* Remove the path components in *fs_path from the original URL, to get
     the URL to the repository root. */
  urlbuf = svn_stringbuf_create(URL, pool);
  svn_path_remove_components(urlbuf,
                             svn_path_component_count(*fs_path));
  *repos_url = urlbuf->data;

  return SVN_NO_ERROR;
}
コード例 #2
0
ファイル: split_url.c プロジェクト: Alkzndr/freebsd
svn_error_t *
svn_ra_local__split_URL(svn_repos_t **repos,
                        const char **repos_url,
                        const char **fs_path,
                        const char *URL,
                        apr_pool_t *pool)
{
  svn_error_t *err = SVN_NO_ERROR;
  const char *repos_dirent;
  const char *repos_root_dirent;
  svn_stringbuf_t *urlbuf;
  apr_size_t root_end;

  SVN_ERR(svn_uri_get_dirent_from_file_url(&repos_dirent, URL, pool));

  /* Search for a repository in the full path. */
  repos_root_dirent = svn_repos_find_root_path(repos_dirent, pool);
  if (!repos_root_dirent)
    return svn_error_createf(SVN_ERR_RA_LOCAL_REPOS_OPEN_FAILED, NULL,
                             _("Unable to open repository '%s'"), URL);

  /* Attempt to open a repository at URL. */
  err = svn_repos_open2(repos, repos_root_dirent, NULL, pool);
  if (err)
    return svn_error_createf(SVN_ERR_RA_LOCAL_REPOS_OPEN_FAILED, err,
                             _("Unable to open repository '%s'"), URL);

  /* Assert capabilities directly, since client == server. */
  {
    apr_array_header_t *caps = apr_array_make(pool, 1, sizeof(const char *));
    APR_ARRAY_PUSH(caps, const char *) = SVN_RA_CAPABILITY_MERGEINFO;
    SVN_ERR(svn_repos_remember_client_capabilities(*repos, caps));
  }

  /* = apr_pstrcat(pool,
                   "/",
                   svn_dirent_skip_ancestor(repos_root_dirent, repos_dirent),
                   (const char *)NULL); */
  root_end = strlen(repos_root_dirent);
  if (! repos_dirent[root_end])
    *fs_path = "/";
  else if (repos_dirent[root_end] == '/')
    *fs_path = &repos_dirent[root_end];
  else
    {
      /* On Windows "C:/" is the parent directory of "C:/dir" */
      *fs_path = &repos_dirent[root_end-1];
      SVN_ERR_ASSERT((*fs_path)[0] == '/');
    }

  /* Remove the path components after the root dirent from the original URL,
     to get a URL to the repository root.

     We don't use svn_uri_get_file_url_from_dirent() here as that would
     transform several uris to form a differently formed url than
     svn_uri_canonicalize would.

     E.g. file://localhost/C:/dir -> file:///C:/dir
          (a transform that was originally supported directly by this function,
           before the implementation moved)

          On on Windows:
          file:///dir -> file:///E:/dir  (When E: is the current disk)
     */
  urlbuf = svn_stringbuf_create(URL, pool);
  svn_path_remove_components(urlbuf,
                             svn_path_component_count(repos_dirent)
                             - svn_path_component_count(repos_root_dirent));
  *repos_url = urlbuf->data;

  /* Configure hook script environment variables. */
  SVN_ERR(svn_repos_hooks_setenv(*repos, NULL, pool));

  return SVN_NO_ERROR;
}
コード例 #3
0
ファイル: authz.c プロジェクト: 2asoft/freebsd
/* Retrieve the file at DIRENT (contained in a repo) then parse it as a config
 * file placing the result into CFG_P allocated in POOL.
 *
 * If DIRENT cannot be parsed as a config file then an error is returned.  The
 * contents of CFG_P is then undefined.  If MUST_EXIST is TRUE, a missing
 * authz file is also an error.  The CASE_SENSITIVE controls the lookup
 * behavior for section and option names alike.
 *
 * SCRATCH_POOL will be used for temporary allocations. */
static svn_error_t *
authz_retrieve_config_repo(svn_config_t **cfg_p,
                           const char *dirent,
                           svn_boolean_t must_exist,
                           svn_boolean_t case_sensitive,
                           apr_pool_t *result_pool,
                           apr_pool_t *scratch_pool)
{
  svn_error_t *err;
  svn_repos_t *repos;
  const char *repos_root_dirent;
  const char *fs_path;
  svn_fs_t *fs;
  svn_fs_root_t *root;
  svn_revnum_t youngest_rev;
  svn_node_kind_t node_kind;
  svn_stream_t *contents;

  /* Search for a repository in the full path. */
  repos_root_dirent = svn_repos_find_root_path(dirent, scratch_pool);
  if (!repos_root_dirent)
    return svn_error_createf(SVN_ERR_RA_LOCAL_REPOS_NOT_FOUND, NULL,
                             "Unable to find repository at '%s'", dirent);

  /* Attempt to open a repository at repos_root_dirent. */
  SVN_ERR(svn_repos_open3(&repos, repos_root_dirent, NULL, scratch_pool,
                          scratch_pool));

  fs_path = &dirent[strlen(repos_root_dirent)];

  /* Root path is always a directory so no reason to go any further */
  if (*fs_path == '\0')
    return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
                             "'/' is not a file in repo '%s'",
                             repos_root_dirent);

  /* We skip some things that are non-important for how we're going to use
   * this repo connection.  We do not set any capabilities since none of
   * the current ones are important for what we're doing.  We also do not
   * setup the environment that repos hooks would run under since we won't
   * be triggering any. */

  /* Get the filesystem. */
  fs = svn_repos_fs(repos);

  /* Find HEAD and the revision root */
  SVN_ERR(svn_fs_youngest_rev(&youngest_rev, fs, scratch_pool));
  SVN_ERR(svn_fs_revision_root(&root, fs, youngest_rev, scratch_pool));

  SVN_ERR(svn_fs_check_path(&node_kind, root, fs_path, scratch_pool));
  if (node_kind == svn_node_none)
    {
      if (!must_exist)
        {
          SVN_ERR(svn_config_create2(cfg_p, case_sensitive, case_sensitive,
                                     result_pool));
          return SVN_NO_ERROR;
        }
      else
        {
          return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
                                   "'%s' path not found in repo '%s'", fs_path,
                                   repos_root_dirent);
        }
    }
  else if (node_kind != svn_node_file)
    {
      return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
                               "'%s' is not a file in repo '%s'", fs_path,
                               repos_root_dirent);
    }

  SVN_ERR(svn_fs_file_contents(&contents, root, fs_path, scratch_pool));
  err = svn_config_parse(cfg_p, contents, case_sensitive, case_sensitive,
                         result_pool);

  /* Add the URL to the error stack since the parser doesn't have it. */
  if (err != SVN_NO_ERROR)
    return svn_error_createf(err->apr_err, err,
                             "Error while parsing config file: '%s' in repo '%s':",
                             fs_path, repos_root_dirent);

  return SVN_NO_ERROR;
}