Alien-SVN

 view release on metacpan or  search on metacpan

src/subversion/subversion/mod_dav_svn/repos.c  view on Meta::CPAN


        *cp++ = '\0';           /* Delimit var */
        while (*cp && (svn_ctype_isspace(*cp) || *cp == '='))
          {
            ++cp;
          }

        if (*cp == '"')
          {
            ++cp;
            for (end = cp;
                 (*end && *end != '\n' && *end != '\r' && *end != '\"');
                 end++);
          }
        else
          {
            for (end = cp; (*end && !svn_ctype_isspace(*end)); end++);
          }
        if (*end)
          {
            *end = '\0';        /* strip ending quote or return */
          }
        ap_str_tolower(cp);

        if (parm[0] == 'q'
            && (parm[1] == '\0' || (parm[1] == 's' && parm[2] == '\0')))
          {
            result->quality = (float) atof(cp);
          }
      }

    if (*accept_line == ',')
      {
        ++accept_line;
      }

    return accept_line;
}

/* @a accept_line is the Accept-Encoding header, which is of the
   format:

     Accept-Encoding: name; q=N;

   This function will return an array of accept_rec structures that
   contain the accepted encodings and the quality each one has
   associated with them.
*/
static apr_array_header_t *do_header_line(apr_pool_t *p,
                                          const char *accept_line)
{
    apr_array_header_t *accept_recs;

    if (!accept_line)
      return NULL;

    accept_recs = apr_array_make(p, 10, sizeof(accept_rec));

    while (*accept_line)
      {
        accept_rec *prefs = (accept_rec *) apr_array_push(accept_recs);
        accept_line = get_entry(p, prefs, accept_line);
      }

    return accept_recs;
}

/* ---------------------------------------------------------------------- */


/* qsort comparison function for the quality field of the accept_rec
   structure */
static int sort_encoding_pref(const void *accept_rec1, const void *accept_rec2)
{
  float diff = ((const accept_rec *) accept_rec1)->quality -
      ((const accept_rec *) accept_rec2)->quality;
  return (diff == 0 ? 0 : (diff > 0 ? -1 : 1));
}

/* Parse and handle any possible Accept-Encoding header that has been
   sent as part of the request.  */
static void
negotiate_encoding_prefs(request_rec *r, int *svndiff_version)
{
  /* It would be nice if mod_negotiation
     <http://httpd.apache.org/docs-2.1/mod/mod_negotiation.html> could
     handle the Accept-Encoding header parsing for us.  Sadly, it
     looks like its data structures and routines are private (see
     httpd/modules/mappers/mod_negotiation.c).  Thus, we duplicate the
     necessary ones in this file. */
  int i;
  const apr_array_header_t *encoding_prefs;
  encoding_prefs = do_header_line(r->pool,
                                  apr_table_get(r->headers_in,
                                                "Accept-Encoding"));

  if (!encoding_prefs || apr_is_empty_array(encoding_prefs))
    {
      *svndiff_version = 0;
      return;
    }

  *svndiff_version = 0;
  qsort(encoding_prefs->elts, (size_t) encoding_prefs->nelts,
        sizeof(accept_rec), sort_encoding_pref);
  for (i = 0; i < encoding_prefs->nelts; i++)
    {
      struct accept_rec rec = APR_ARRAY_IDX(encoding_prefs, i,
                                            struct accept_rec);
      if (strcmp(rec.name, "svndiff1") == 0)
        {
          *svndiff_version = 1;
          break;
        }
      else if (strcmp(rec.name, "svndiff") == 0)
        {
          *svndiff_version = 0;
          break;
        }
    }
}


/* The only two possible values for a capability. */
static const char *capability_yes = "yes";
static const char *capability_no = "no";

/* Convert CAPABILITIES, a hash table mapping 'const char *' keys to
 * "yes" or "no" values, to a list of all keys whose value is "yes".
 * Return the list, allocated in POOL, and use POOL for all temporary
 * allocation.
 */
static apr_array_header_t *
capabilities_as_list(apr_hash_t *capabilities, apr_pool_t *pool)
{
  apr_array_header_t *list = apr_array_make(pool, apr_hash_count(capabilities),
                                            sizeof(char *));
  apr_hash_index_t *hi;

  for (hi = apr_hash_first(pool, capabilities); hi; hi = apr_hash_next(hi))
    {
      const void *key;
      void *val;
      apr_hash_this(hi, &key, NULL, &val);
      if (strcmp((const char *) val, "yes") == 0)
        APR_ARRAY_PUSH(list, const char *) = key;
    }

  return list;
}


/* Given a non-NULL QUERY string of the form "key1=val1&key2=val2&...",
 * parse the keys and values into an apr table.  Allocate the table in
 * POOL;  dup all keys and values into POOL as well.
 *
 * Note that repeating the same key will cause table overwrites
 * (e.g. "r=3&r=5"), and that a lack of value ("p=") is legal, but
 * equivalent to not specifying the key at all.
 */
static apr_table_t *
querystring_to_table(const char *query, apr_pool_t *pool)
{
  apr_table_t *table = apr_table_make(pool, 2);
  apr_array_header_t *array = svn_cstring_split(query, "&", TRUE, pool);
  int i;
  for (i = 0; i < array->nelts; i++)
    {

src/subversion/subversion/mod_dav_svn/repos.c  view on Meta::CPAN

          /* Marshall the error back to the client by generating by
           * way of the dav_svn__error_response_tag trick. */
          err = dav_svn__new_error(r->pool, HTTP_METHOD_NOT_ALLOWED,
                                   SVN_ERR_APMOD_MALFORMED_URI,
                                   "The URI does not contain the name "
                                   "of a repository.");
          /* can't use r->allowed since the default handler isn't called */
          apr_table_setn(r->headers_out, "Allow", "GET,HEAD");
          status = dav_svn__error_response_tag(r, err);

          return dav_push_error(r->pool, status, err->error_id, NULL, err);
        }

      err = get_parentpath_resource(r, resource);
      if (err)
        return err;
      return NULL;
    }

  /* This does all the work of interpreting/splitting the request uri. */
  err = dav_svn_split_uri(r, r->uri, root_path,
                          &cleaned_uri, &had_slash,
                          &repo_basename, &relative, &repos_path);
  if (err)
    return err;

  /* The path that we will eventually try to open as an svn
     repository.  Normally defined by the SVNPath directive. */
  fs_path = dav_svn__get_fs_path(r);

  /* If the SVNParentPath directive was used instead... */
  if (fs_parent_path != NULL)
    {
      /* ...then the URL to the repository is actually one implicit
         component longer... */
      root_path = svn_urlpath__join(root_path, repo_basename, r->pool);
      /* ...and we need to specify exactly what repository to open. */
      fs_path = svn_dirent_join(fs_parent_path, repo_basename, r->pool);
    }

  /* Start building and filling a 'combination' object. */
  comb = apr_pcalloc(r->pool, sizeof(*comb));
  comb->res.info = &comb->priv;
  comb->res.hooks = &dav_svn__hooks_repository;
  comb->res.pool = r->pool;
  comb->res.uri = cleaned_uri;

  /* Original request, off which to generate subrequests later. */
  comb->priv.r = r;

  /* ### ugly hack to carry over Content-Type data to the open_stream, which
     ### does not have access to the request headers. */
  {
    const char *ct = apr_table_get(r->headers_in, "content-type");

    comb->priv.is_svndiff =
      ct != NULL
      && strcmp(ct, SVN_SVNDIFF_MIME_TYPE) == 0;
  }

  negotiate_encoding_prefs(r, &comb->priv.svndiff_version);

  /* ### and another hack for computing diffs to send to the client */
  comb->priv.delta_base = apr_table_get(r->headers_in,
                                        SVN_DAV_DELTA_BASE_HEADER);

  /* Gather any options requested by an svn client. */
  comb->priv.svn_client_options = apr_table_get(r->headers_in,
                                                SVN_DAV_OPTIONS_HEADER);

  /* See if the client sent a custom 'version name' request header. */
  version_name = apr_table_get(r->headers_in, SVN_DAV_VERSION_NAME_HEADER);
  comb->priv.version_name
    = version_name ? SVN_STR_TO_REV(version_name): SVN_INVALID_REVNUM;

  /* Remember checksums, if any. */
  comb->priv.base_checksum =
    apr_table_get(r->headers_in, SVN_DAV_BASE_FULLTEXT_MD5_HEADER);
  comb->priv.result_checksum =
    apr_table_get(r->headers_in, SVN_DAV_RESULT_FULLTEXT_MD5_HEADER);

  /* "relative" is part of the "uri" string, so it has the proper
     lifetime to store here. */
  /* ### that comment no longer applies. we're creating a string with its
     ### own lifetime now. so WHY are we using a string? hmm... */
  comb->priv.uri_path = svn_stringbuf_create(relative, r->pool);

  /* initialize this until we put something real here */
  comb->priv.root.rev = SVN_INVALID_REVNUM;

  /* create the repository structure and stash it away */
  repos = apr_pcalloc(r->pool, sizeof(*repos));
  repos->pool = r->pool;

  comb->priv.repos = repos;

  /* We are assuming the root_path will live at least as long as this
     resource. Considering that it typically comes from the per-dir
     config in mod_dav, this is valid for now. */
  repos->root_path = svn_path_uri_encode(root_path, r->pool);

  /* where is the SVN FS for this resource? */
  repos->fs_path = fs_path;

  /* A name for the repository */
  repos->repo_name = repo_name;

  /* The repository filesystem basename */
  repos->repo_basename = repo_basename;

  /* An XSL transformation */
  repos->xslt_uri = xslt_uri;

  /* Is autoversioning active in this repos? */
  repos->autoversioning = dav_svn__get_autoversioning_flag(r);

  /* Are bulk updates allowed in this repos? */
  repos->bulk_updates = dav_svn__get_bulk_updates_flag(r);

  /* Are we advertising HTTP v2 protocol support? */
  repos->v2_protocol = dav_svn__check_httpv2_support(r);



( run in 2.131 seconds using v1.01-cache-2.11-cpan-0bb4e1dffa6 )