예제 #1
0
static const char *
SVNMasterURI_cmd(cmd_parms *cmd, void *config, const char *arg1)
{
  dir_conf_t *conf = config;
  apr_uri_t parsed_uri;
  const char *uri_base_name = "";

  /* SVNMasterURI requires mod_proxy and mod_proxy_http
   * (r->handler = "proxy-server" in mirror.c), make sure
   * they are present. */
  if (ap_find_linked_module("mod_proxy.c") == NULL)
    return "module mod_proxy not loaded, required for SVNMasterURI";
  if (ap_find_linked_module("mod_proxy_http.c") == NULL)
    return "module mod_proxy_http not loaded, required for SVNMasterURI";
  if (APR_SUCCESS != apr_uri_parse(cmd->pool, arg1, &parsed_uri))
    return "unable to parse SVNMasterURI value";
  if (parsed_uri.path)
    uri_base_name = svn_urlpath__basename(
                        svn_urlpath__canonicalize(parsed_uri.path, cmd->pool),
                        cmd->pool);
  if (! *uri_base_name)
    return "SVNMasterURI value must not be a server root";

  conf->master_uri = apr_pstrdup(cmd->pool, arg1);

  return NULL;
}
예제 #2
0
파일: util.c 프로젝트: DJEX93/dsploit
svn_error_t *
svn_ra_neon__copy_href(svn_stringbuf_t *dst, const char *src,
                       apr_pool_t *pool)
{
  /* parse the PATH element out of the URL and store it.

     ### do we want to verify the rest matches the current session?

     Note: mod_dav does not (currently) use an absolute URL, but simply a
     server-relative path (i.e. this uri_parse is effectively a no-op).
  */

  apr_uri_t uri;
  apr_status_t apr_status;

  /* SRC can have trailing '/' */
  if (svn_path_is_url(src))
    src = svn_uri_canonicalize(src, pool);
  else
    src = svn_urlpath__canonicalize(src, pool);
  apr_status = apr_uri_parse(pool, src, &uri);

  if (apr_status != APR_SUCCESS)
    return svn_error_wrap_apr(apr_status,
                              _("Unable to parse URL '%s'"),
                              src);

  svn_stringbuf_setempty(dst);
  svn_stringbuf_appendcstr(dst, uri.path);

  return SVN_NO_ERROR;
}
예제 #3
0
파일: util.c 프로젝트: DJEX93/dsploit
const char *
svn_ra_neon__request_get_location(svn_ra_neon__request_t *request,
                                  apr_pool_t *pool)
{
  const char *val = ne_get_response_header(request->ne_req, "Location");
  return val ? svn_urlpath__canonicalize(val, pool) : NULL;
}
예제 #4
0
파일: property.c 프로젝트: 2asoft/freebsd
/* For HTTPv1 servers, do a PROPFIND dance on the VCC to fetch the youngest
   revnum. If BASECOLL_URL is non-NULL, then the corresponding baseline
   collection URL is also returned.

   Do the work over CONN.

   *BASECOLL_URL (if requested) will be allocated in RESULT_POOL. All
   temporary allocations will be made in SCRATCH_POOL.  */
static svn_error_t *
v1_get_youngest_revnum(svn_revnum_t *youngest,
                       const char **basecoll_url,
                       svn_ra_serf__session_t *session,
                       const char *vcc_url,
                       apr_pool_t *result_pool,
                       apr_pool_t *scratch_pool)
{
  const char *baseline_url;
  const char *bc_url;

  /* Fetching DAV:checked-in from the VCC (with no Label: to specify a
     revision) will return the latest Baseline resource's URL.  */
  SVN_ERR(svn_ra_serf__fetch_dav_prop(&baseline_url, session, vcc_url,
                                      SVN_INVALID_REVNUM,
                                      "checked-in",
                                      scratch_pool, scratch_pool));
  if (!baseline_url)
    {
      return svn_error_create(SVN_ERR_RA_DAV_OPTIONS_REQ_FAILED, NULL,
                              _("The OPTIONS response did not include "
                                "the requested checked-in value"));
    }
  baseline_url = svn_urlpath__canonicalize(baseline_url, scratch_pool);

  /* From the Baseline resource, we can fetch the DAV:baseline-collection
     and DAV:version-name properties. The latter is the revision number,
     which is formally the name used in Label: headers.  */

  /* First check baseline information cache. */
  SVN_ERR(svn_ra_serf__blncache_get_baseline_info(&bc_url,
                                                  youngest,
                                                  session->blncache,
                                                  baseline_url,
                                                  scratch_pool));
  if (!bc_url)
    {
      SVN_ERR(retrieve_baseline_info(youngest, &bc_url, session,
                                     baseline_url, SVN_INVALID_REVNUM,
                                     scratch_pool, scratch_pool));
      SVN_ERR(svn_ra_serf__blncache_set(session->blncache,
                                        baseline_url, *youngest,
                                        bc_url, scratch_pool));
    }

  if (basecoll_url != NULL)
    *basecoll_url = apr_pstrdup(result_pool, bc_url);

  return SVN_NO_ERROR;
}
예제 #5
0
파일: property.c 프로젝트: 2asoft/freebsd
/*
 * Contact the server (using CONN) to calculate baseline
 * information for BASELINE_URL at REVISION (which may be
 * SVN_INVALID_REVNUM to query the HEAD revision).
 *
 * If ACTUAL_REVISION is non-NULL, set *ACTUAL_REVISION to revision
 * retrieved from the server as part of this process (which should
 * match REVISION when REVISION is valid).  Set *BASECOLL_URL_P to the
 * baseline collection URL.
 */
static svn_error_t *
retrieve_baseline_info(svn_revnum_t *actual_revision,
                       const char **basecoll_url_p,
                       svn_ra_serf__session_t *session,
                       const char *baseline_url,
                       svn_revnum_t revision,
                       apr_pool_t *result_pool,
                       apr_pool_t *scratch_pool)
{
  apr_hash_t *props;
  apr_hash_t *dav_props;
  const char *basecoll_url;

  SVN_ERR(svn_ra_serf__fetch_node_props(&props, session,
                                        baseline_url, revision,
                                        baseline_props,
                                        scratch_pool, scratch_pool));
  dav_props = apr_hash_get(props, "DAV:", 4);
  /* If DAV_PROPS is NULL, then svn_prop_get_value() will return NULL.  */

  basecoll_url = svn_prop_get_value(dav_props, "baseline-collection");
  if (!basecoll_url)
    {
      return svn_error_create(SVN_ERR_RA_DAV_PROPS_NOT_FOUND, NULL,
                              _("The PROPFIND response did not include "
                                "the requested baseline-collection value"));
    }
  *basecoll_url_p = svn_urlpath__canonicalize(basecoll_url, result_pool);

  if (actual_revision)
    {
      const char *version_name;

      version_name = svn_prop_get_value(dav_props, SVN_DAV__VERSION_NAME);
      if (version_name)
        {
          apr_int64_t rev;

          SVN_ERR(svn_cstring_atoi64(&rev, version_name));
          *actual_revision = (svn_revnum_t)rev;
        }

      if (!version_name || !SVN_IS_VALID_REVNUM(*actual_revision))
        return svn_error_create(SVN_ERR_RA_DAV_PROPS_NOT_FOUND, NULL,
                                _("The PROPFIND response did not include "
                                  "the requested version-name value"));
    }

  return SVN_NO_ERROR;
}
예제 #6
0
/* Implements the #create_dir_config method of Apache's #module vtable. */
static void *
create_dir_config(apr_pool_t *p, char *dir)
{
  /* NOTE: dir==NULL creates the default per-dir config */
  dir_conf_t *conf = apr_pcalloc(p, sizeof(*conf));

  /* In subversion context dir is always considered to be coming from
     <Location /blah> directive. So we treat it as a urlpath. */
  if (dir)
    conf->root_dir = svn_urlpath__canonicalize(dir, p);
  conf->bulk_updates = CONF_FLAG_ON;
  conf->v2_protocol = CONF_FLAG_ON;

  return conf;
}
예제 #7
0
/* Conforms to svn_ra_serf__xml_closed_t  */
static svn_error_t *
options_closed(svn_ra_serf__xml_estate_t *xes,
               void *baton,
               int leaving_state,
               const svn_string_t *cdata,
               apr_hash_t *attrs,
               apr_pool_t *scratch_pool)
{
  options_context_t *opt_ctx = baton;

  SVN_ERR_ASSERT(leaving_state == HREF);
  SVN_ERR_ASSERT(cdata != NULL);

  opt_ctx->activity_collection = svn_urlpath__canonicalize(cdata->data,
                                                           opt_ctx->pool);

  return SVN_NO_ERROR;
}
예제 #8
0
/* This implements serf_bucket_headers_do_callback_fn_t.
 */
static int
capabilities_headers_iterator_callback(void *baton,
                                       const char *key,
                                       const char *val)
{
  options_context_t *opt_ctx = baton;
  svn_ra_serf__session_t *session = opt_ctx->session;

  if (svn_cstring_casecmp(key, "dav") == 0)
    {
      /* Each header may contain multiple values, separated by commas, e.g.:
           DAV: version-control,checkout,working-resource
           DAV: merge,baseline,activity,version-controlled-collection
           DAV: http://subversion.tigris.org/xmlns/dav/svn/depth */
      apr_array_header_t *vals = svn_cstring_split(val, ",", TRUE,
                                                   opt_ctx->pool);

      opt_ctx->received_dav_header = TRUE;

      /* Right now we only have a few capabilities to detect, so just
         seek for them directly.  This could be written slightly more
         efficiently, but that wouldn't be worth it until we have many
         more capabilities. */

      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_DEPTH, vals))
        {
          svn_hash_sets(session->capabilities,
                        SVN_RA_CAPABILITY_DEPTH, capability_yes);
        }
      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_MERGEINFO, vals))
        {
          /* The server doesn't know what repository we're referring
             to, so it can't just say capability_yes. */
          if (!svn_hash_gets(session->capabilities,
                             SVN_RA_CAPABILITY_MERGEINFO))
            {
              svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_MERGEINFO,
                            capability_server_yes);
            }
        }
      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_LOG_REVPROPS, vals))
        {
          svn_hash_sets(session->capabilities,
                        SVN_RA_CAPABILITY_LOG_REVPROPS, capability_yes);
        }
      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_ATOMIC_REVPROPS, vals))
        {
          svn_hash_sets(session->capabilities,
                        SVN_RA_CAPABILITY_ATOMIC_REVPROPS, capability_yes);
        }
      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_PARTIAL_REPLAY, vals))
        {
          svn_hash_sets(session->capabilities,
                        SVN_RA_CAPABILITY_PARTIAL_REPLAY, capability_yes);
        }
      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_INHERITED_PROPS, vals))
        {
          svn_hash_sets(session->capabilities,
                        SVN_RA_CAPABILITY_INHERITED_PROPS, capability_yes);
        }
      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_REVERSE_FILE_REVS,
                                 vals))
        {
          svn_hash_sets(session->capabilities,
                        SVN_RA_CAPABILITY_GET_FILE_REVS_REVERSE,
                        capability_yes);
        }
      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_EPHEMERAL_TXNPROPS, vals))
        {
          svn_hash_sets(session->capabilities,
                        SVN_RA_CAPABILITY_EPHEMERAL_TXNPROPS, capability_yes);
        }
      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_INLINE_PROPS, vals))
        {
          session->supports_inline_props = TRUE;
        }
      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_REPLAY_REV_RESOURCE, vals))
        {
          session->supports_rev_rsrc_replay = TRUE;
        }
      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_SVNDIFF1, vals))
        {
          /* Use compressed svndiff1 format for servers that properly
             advertise this capability (Subversion 1.10 and greater). */
          session->supports_svndiff1 = TRUE;
        }
      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_LIST, vals))
        {
          svn_hash_sets(session->capabilities,
                        SVN_RA_CAPABILITY_LIST, capability_yes);
        }
      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_SVNDIFF2, vals))
        {
          /* Same for svndiff2. */
          session->supports_svndiff2 = TRUE;
        }
      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_PUT_RESULT_CHECKSUM, vals))
        {
          session->supports_put_result_checksum = TRUE;
        }
    }

  /* SVN-specific headers -- if present, server supports HTTP protocol v2 */
  else if (!svn_ctype_casecmp(key[0], 'S')
           && !svn_ctype_casecmp(key[1], 'V')
           && !svn_ctype_casecmp(key[2], 'N'))
    {
      /* If we've not yet seen any information about supported POST
         requests, we'll initialize the list/hash with "create-txn"
         (which we know is supported by virtue of the server speaking
         HTTPv2 at all. */
      if (! session->supported_posts)
        {
          session->supported_posts = apr_hash_make(session->pool);
          apr_hash_set(session->supported_posts, "create-txn", 10, (void *)1);
        }

      if (svn_cstring_casecmp(key, SVN_DAV_ROOT_URI_HEADER) == 0)
        {
          session->repos_root = session->session_url;
          session->repos_root.path =
            (char *)svn_fspath__canonicalize(val, session->pool);
          session->repos_root_str =
            svn_urlpath__canonicalize(
                apr_uri_unparse(session->pool, &session->repos_root, 0),
                session->pool);
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_ME_RESOURCE_HEADER) == 0)
        {
#ifdef SVN_DEBUG
          char *ignore_v2_env_var = getenv(SVN_IGNORE_V2_ENV_VAR);

          if (!(ignore_v2_env_var
                && apr_strnatcasecmp(ignore_v2_env_var, "yes") == 0))
            session->me_resource = apr_pstrdup(session->pool, val);
#else
          session->me_resource = apr_pstrdup(session->pool, val);
#endif
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_REV_STUB_HEADER) == 0)
        {
          session->rev_stub = apr_pstrdup(session->pool, val);
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_REV_ROOT_STUB_HEADER) == 0)
        {
          session->rev_root_stub = apr_pstrdup(session->pool, val);
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_TXN_STUB_HEADER) == 0)
        {
          session->txn_stub = apr_pstrdup(session->pool, val);
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_TXN_ROOT_STUB_HEADER) == 0)
        {
          session->txn_root_stub = apr_pstrdup(session->pool, val);
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_VTXN_STUB_HEADER) == 0)
        {
          session->vtxn_stub = apr_pstrdup(session->pool, val);
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_VTXN_ROOT_STUB_HEADER) == 0)
        {
          session->vtxn_root_stub = apr_pstrdup(session->pool, val);
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_REPOS_UUID_HEADER) == 0)
        {
          session->uuid = apr_pstrdup(session->pool, val);
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_YOUNGEST_REV_HEADER) == 0)
        {
          opt_ctx->youngest_rev = SVN_STR_TO_REV(val);
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_ALLOW_BULK_UPDATES) == 0)
        {
          session->server_allows_bulk = apr_pstrdup(session->pool, val);
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_SUPPORTED_POSTS_HEADER) == 0)
        {
          /* May contain multiple values, separated by commas. */
          int i;
          apr_array_header_t *vals = svn_cstring_split(val, ",", TRUE,
                                                       session->pool);

          for (i = 0; i < vals->nelts; i++)
            {
              const char *post_val = APR_ARRAY_IDX(vals, i, const char *);

              svn_hash_sets(session->supported_posts, post_val, (void *)1);
            }
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_REPOSITORY_MERGEINFO) == 0)
예제 #9
0
파일: property.c 프로젝트: 2asoft/freebsd
/* Conforms to svn_ra_serf__xml_closed_t  */
static svn_error_t *
propfind_closed(svn_ra_serf__xml_estate_t *xes,
                void *baton,
                int leaving_state,
                const svn_string_t *cdata,
                apr_hash_t *attrs,
                apr_pool_t *scratch_pool)
{
  propfind_context_t *ctx = baton;

  if (leaving_state == MULTISTATUS)
    {
      /* We've gathered all the data from the reponse. Add this item
         onto the "done list". External callers will then know this
         request has been completed (tho stray response bytes may still
         arrive).  */
    }
  else if (leaving_state == HREF)
    {
      const char *path;

      if (strcmp(ctx->depth, "1") == 0)
        path = svn_urlpath__canonicalize(cdata->data, scratch_pool);
      else
        path = ctx->path;

      svn_ra_serf__xml_note(xes, RESPONSE, "path", path);

      SVN_ERR(ctx->prop_func(ctx->prop_func_baton,
                             path,
                             D_, "href",
                             cdata, scratch_pool));
    }
  else if (leaving_state == COLLECTION)
    {
      svn_ra_serf__xml_note(xes, PROPVAL, "altvalue", "collection");
    }
  else if (leaving_state == HREF_VALUE)
    {
      svn_ra_serf__xml_note(xes, PROPVAL, "altvalue", cdata->data);
    }
  else if (leaving_state == STATUS)
    {
      /* Parse the status field, and remember if this is a property
         that we wish to ignore.  (Typically, if it's not a 200, the
         status will be 404 to indicate that a property we
         specifically requested from the server doesn't exist.)  */
      apr_int64_t status = parse_status_code(cdata->data);
      if (status != 200)
        svn_ra_serf__xml_note(xes, PROPSTAT, "ignore-prop", "*");
    }
  else if (leaving_state == PROPVAL)
    {
      const char *encoding;
      const svn_string_t *val_str;
      const char *ns;
      const char *name;
      const char *altvalue;

      if ((altvalue = svn_hash_gets(attrs, "altvalue")) != NULL)
        {
          val_str = svn_string_create(altvalue, scratch_pool);
        }
      else if ((encoding = svn_hash_gets(attrs, "V:encoding")) != NULL)
        {
          if (strcmp(encoding, "base64") != 0)
            return svn_error_createf(SVN_ERR_RA_DAV_MALFORMED_DATA,
                                     NULL,
                                     _("Got unrecognized encoding '%s'"),
                                     encoding);

          /* Decode into the right pool.  */
          val_str = svn_base64_decode_string(cdata, scratch_pool);
        }
      else
        {
          /* Copy into the right pool.  */
          val_str = cdata;
        }

      /* The current path sits on the RESPONSE state.

         Now, it would be nice if we could, at this point, know that
         the status code for this property indicated a problem -- then
         we could simply bail out here and ignore the property.
         Sadly, though, we might get the status code *after* we get
         the property value.  So we'll carry on with our processing
         here, setting the property and value as expected.  Once we
         know for sure the status code associate with the property,
         we'll decide its fate.  */

      ns = svn_hash_gets(attrs, "ns");
      name = svn_hash_gets(attrs, "name");

      set_ns_prop(ctx->ps_props, ns, name, val_str,
                  apr_hash_pool_get(ctx->ps_props));
    }
  else
    {
      apr_hash_t *gathered;

      SVN_ERR_ASSERT(leaving_state == PROPSTAT);

      gathered = svn_ra_serf__xml_gather_since(xes, RESPONSE);

      /* If we've squirreled away a note that says we want to ignore
         these properties, we'll do so.  Otherwise, we need to copy
         them from the temporary hash into the ctx->ret_props hash. */
      if (! svn_hash_gets(gathered, "ignore-prop"))
        {
          apr_hash_index_t *hi_ns;
          const char *path;
          apr_pool_t *iterpool = svn_pool_create(scratch_pool);


          path = svn_hash_gets(gathered, "path");
          if (!path)
            path = ctx->path;

          for (hi_ns = apr_hash_first(scratch_pool, ctx->ps_props);
               hi_ns;
               hi_ns = apr_hash_next(hi_ns))
            {
              const char *ns = apr_hash_this_key(hi_ns);
              apr_hash_t *props = apr_hash_this_val(hi_ns);
              apr_hash_index_t *hi_prop;

              svn_pool_clear(iterpool);

              for (hi_prop = apr_hash_first(iterpool, props);
                   hi_prop;
                   hi_prop = apr_hash_next(hi_prop))
                {
                  const char *name = apr_hash_this_key(hi_prop);
                  const svn_string_t *value = apr_hash_this_val(hi_prop);

                  SVN_ERR(ctx->prop_func(ctx->prop_func_baton, path,
                                         ns, name, value, iterpool));
                }
            }

          svn_pool_destroy(iterpool);
        }

      ctx->ps_props = NULL; /* Allocated in PROPSTAT state pool */
    }

  return SVN_NO_ERROR;
}
예제 #10
0
static svn_error_t *
multistatus_closed(svn_ra_serf__xml_estate_t *xes,
                   void *baton,
                   int leaving_state,
                   const svn_string_t *cdata,
                   apr_hash_t *attrs,
                   apr_pool_t *scratch_pool)
{
  struct svn_ra_serf__server_error_t *server_error = baton;
  const char *errcode;
  const char *status;

  switch (leaving_state)
    {
      case MS_RESPONSE_HREF:
        {
          apr_status_t result;
          apr_uri_t uri;

          result = apr_uri_parse(scratch_pool, cdata->data, &uri);
          if (result)
            return svn_ra_serf__wrap_err(result, NULL);
          svn_ra_serf__xml_note(xes, MS_RESPONSE, "path",
                                svn_urlpath__canonicalize(uri.path, scratch_pool));
        }
        break;
      case MS_RESPONSE_STATUS:
        svn_ra_serf__xml_note(xes, MS_RESPONSE, "status", cdata->data);
        break;
      case MS_RESPONSE_ERROR_HUMANREADABLE:
        svn_ra_serf__xml_note(xes, MS_RESPONSE, "human-readable", cdata->data);
        errcode = svn_hash_gets(attrs, "errcode");
        if (errcode)
          svn_ra_serf__xml_note(xes, MS_RESPONSE, "errcode", errcode);
        break;
      case MS_RESPONSE:
        if ((status = svn_hash__get_cstring(attrs, "status", NULL)) != NULL)
          {
            error_item_t *item;

            item = apr_pcalloc(server_error->pool, sizeof(*item));

            item->path = apr_pstrdup(server_error->pool,
                                     svn_hash_gets(attrs, "path"));

            SVN_ERR(parse_status_line(&item->http_status,
                                      &item->http_reason,
                                      status,
                                      server_error->pool,
                                      scratch_pool));

            /* Do we have a mod_dav specific message? */
            item->message = svn_hash_gets(attrs, "human-readable");

            if (item->message)
              {
                if ((errcode = svn_hash_gets(attrs, "errcode")) != NULL)
                  {
                    apr_int64_t val;

                    SVN_ERR(svn_cstring_atoi64(&val, errcode));
                    item->apr_err = (apr_status_t)val;
                  }

                item->message = apr_pstrdup(server_error->pool, item->message);
              }
            else
              item->message = apr_pstrdup(server_error->pool,
                                          svn_hash_gets(attrs, "description"));

            APR_ARRAY_PUSH(server_error->items, error_item_t *) = item;
          }
        break;


      case MS_PROPSTAT_STATUS:
        svn_ra_serf__xml_note(xes, MS_PROPSTAT, "status", cdata->data);
        break;
      case MS_PROPSTAT_ERROR_HUMANREADABLE:
        svn_ra_serf__xml_note(xes, MS_PROPSTAT, "human-readable", cdata->data);
        errcode = svn_hash_gets(attrs, "errcode");
        if (errcode)
          svn_ra_serf__xml_note(xes, MS_PROPSTAT, "errcode", errcode);
        break;
      case MS_PROPSTAT_RESPONSEDESCRIPTION:
        svn_ra_serf__xml_note(xes, MS_PROPSTAT, "description",
                              cdata->data);
        break;

      case MS_PROPSTAT:
        if ((status = svn_hash__get_cstring(attrs, "status", NULL)) != NULL)
          {
            apr_hash_t *response_attrs;
            error_item_t *item;

            response_attrs = svn_ra_serf__xml_gather_since(xes, MS_RESPONSE);
            item = apr_pcalloc(server_error->pool, sizeof(*item));

            item->path = apr_pstrdup(server_error->pool,
                                     svn_hash_gets(response_attrs, "path"));
            item->propname = apr_pstrdup(server_error->pool,
                                         svn_hash_gets(attrs, "propname"));

            SVN_ERR(parse_status_line(&item->http_status,
                                      &item->http_reason,
                                      status,
                                      server_error->pool,
                                      scratch_pool));

            /* Do we have a mod_dav specific message? */
            item->message = svn_hash_gets(attrs, "human-readable");

            if (item->message)
              {
                if ((errcode = svn_hash_gets(attrs, "errcode")) != NULL)
                  {
                    apr_int64_t val;

                    SVN_ERR(svn_cstring_atoi64(&val, errcode));
                    item->apr_err = (apr_status_t)val;
                  }

                item->message = apr_pstrdup(server_error->pool, item->message);
              }
            else
              item->message = apr_pstrdup(server_error->pool,
                                          svn_hash_gets(attrs, "description"));


            APR_ARRAY_PUSH(server_error->items, error_item_t *) = item;
          }
예제 #11
0
apr_status_t dav_svn__location_body_filter(ap_filter_t *f,
                                           apr_bucket_brigade *bb)
{
    request_rec *r = f->r;
    locate_ctx_t *ctx = f->ctx;
    apr_bucket *bkt;
    const char *master_uri, *root_dir, *canonicalized_uri;
    apr_uri_t uri;

    /* Don't filter if we're in a subrequest or we aren't setup to
       proxy anything. */
    master_uri = dav_svn__get_master_uri(r);
    if (r->main || !master_uri) {
        ap_remove_output_filter(f);
        return ap_pass_brigade(f->next, bb);
    }

    /* And don't filter if our search-n-replace would be a noop anyway
       (that is, if our root path matches that of the master server). */
    apr_uri_parse(r->pool, master_uri, &uri);
    root_dir = dav_svn__get_root_dir(r);
    canonicalized_uri = svn_urlpath__canonicalize(uri.path, r->pool);
    if (strcmp(canonicalized_uri, root_dir) == 0) {
        ap_remove_output_filter(f);
        return ap_pass_brigade(f->next, bb);
    }

    /* ### FIXME: GET and PROPFIND requests that make it here must be
       ### referring to data inside commit transactions-in-progress.
       ### We've got to be careful not to munge the versioned data
       ### they return in the process of trying to do URI fix-ups.
       ### See issue #3445 for details. */

    /* We are url encoding the current url and the master url
       as incoming(from master) request body has it encoded already. */
    canonicalized_uri = svn_path_uri_encode(canonicalized_uri, r->pool);
    root_dir = svn_path_uri_encode(root_dir, r->pool);
    if (!f->ctx) {
        ctx = f->ctx = apr_pcalloc(r->pool, sizeof(*ctx));
        ctx->remotepath = canonicalized_uri;
        ctx->remotepath_len = strlen(ctx->remotepath);
        ctx->localpath = root_dir;
        ctx->localpath_len = strlen(ctx->localpath);
        ctx->pattern = apr_strmatch_precompile(r->pool, ctx->remotepath, 1);
        ctx->pattern_len = ctx->remotepath_len;
    }

    bkt = APR_BRIGADE_FIRST(bb);
    while (bkt != APR_BRIGADE_SENTINEL(bb)) {

        const char *data, *match;
        apr_size_t len;

        /* read */
        apr_bucket_read(bkt, &data, &len, APR_BLOCK_READ);
        match = apr_strmatch(ctx->pattern, data, len);
        if (match) {
            apr_bucket *next_bucket;
            apr_bucket_split(bkt, match - data);
            next_bucket = APR_BUCKET_NEXT(bkt);
            apr_bucket_split(next_bucket, ctx->pattern_len);
            bkt = APR_BUCKET_NEXT(next_bucket);
            apr_bucket_delete(next_bucket);
            next_bucket = apr_bucket_pool_create(ctx->localpath,
                                                 ctx->localpath_len,
                                                 r->pool, bb->bucket_alloc);
            APR_BUCKET_INSERT_BEFORE(bkt, next_bucket);
        }
        else {
            bkt = APR_BUCKET_NEXT(bkt);
        }
    }
    return ap_pass_brigade(f->next, bb);
}
예제 #12
0
apr_status_t dav_svn__location_in_filter(ap_filter_t *f,
                                         apr_bucket_brigade *bb,
                                         ap_input_mode_t mode,
                                         apr_read_type_e block,
                                         apr_off_t readbytes)
{
    request_rec *r = f->r;
    locate_ctx_t *ctx = f->ctx;
    apr_status_t rv;
    apr_bucket *bkt;
    const char *master_uri, *root_dir, *canonicalized_uri;
    apr_uri_t uri;

    /* Don't filter if we're in a subrequest or we aren't setup to
       proxy anything. */
    master_uri = dav_svn__get_master_uri(r);
    if (r->main || !master_uri) {
        ap_remove_input_filter(f);
        return ap_get_brigade(f->next, bb, mode, block, readbytes);
    }

    /* And don't filter if our search-n-replace would be a noop anyway
       (that is, if our root path matches that of the master server). */
    apr_uri_parse(r->pool, master_uri, &uri);
    root_dir = dav_svn__get_root_dir(r);
    canonicalized_uri = svn_urlpath__canonicalize(uri.path, r->pool);
    if (strcmp(canonicalized_uri, root_dir) == 0) {
        ap_remove_input_filter(f);
        return ap_get_brigade(f->next, bb, mode, block, readbytes);
    }

    /* ### FIXME: While we want to fix up any locations in proxied XML
       ### requests, we do *not* want to be futzing with versioned (or
       ### to-be-versioned) data, such as the file contents present in
       ### PUT requests and properties in PROPPATCH requests.
       ### See issue #3445 for details. */

    /* We are url encoding the current url and the master url
       as incoming(from client) request body has it encoded already. */
    canonicalized_uri = svn_path_uri_encode(canonicalized_uri, r->pool);
    root_dir = svn_path_uri_encode(root_dir, r->pool);
    if (!f->ctx) {
        ctx = f->ctx = apr_pcalloc(r->pool, sizeof(*ctx));
        ctx->remotepath = canonicalized_uri;
        ctx->remotepath_len = strlen(ctx->remotepath);
        ctx->localpath = root_dir;
        ctx->localpath_len = strlen(ctx->localpath);
        ctx->pattern = apr_strmatch_precompile(r->pool, ctx->localpath, 1);
        ctx->pattern_len = ctx->localpath_len;
    }

    rv = ap_get_brigade(f->next, bb, mode, block, readbytes);
    if (rv) {
        return rv;
    }

    bkt = APR_BRIGADE_FIRST(bb);
    while (bkt != APR_BRIGADE_SENTINEL(bb)) {

        const char *data, *match;
        apr_size_t len;

        if (APR_BUCKET_IS_METADATA(bkt)) {
            bkt = APR_BUCKET_NEXT(bkt);
            continue;
        }

        /* read */
        apr_bucket_read(bkt, &data, &len, APR_BLOCK_READ);
        match = apr_strmatch(ctx->pattern, data, len);
        if (match) {
            apr_bucket *next_bucket;
            apr_bucket_split(bkt, match - data);
            next_bucket = APR_BUCKET_NEXT(bkt);
            apr_bucket_split(next_bucket, ctx->pattern_len);
            bkt = APR_BUCKET_NEXT(next_bucket);
            apr_bucket_delete(next_bucket);
            next_bucket = apr_bucket_pool_create(ctx->remotepath,
                                                 ctx->remotepath_len,
                                                 r->pool, bb->bucket_alloc);
            APR_BUCKET_INSERT_BEFORE(bkt, next_bucket);
        }
        else {
            bkt = APR_BUCKET_NEXT(bkt);
        }
    }
    return APR_SUCCESS;
}
예제 #13
0
/* Conforms to svn_ra_serf__xml_closed_t  */
static svn_error_t *
merge_closed(svn_ra_serf__xml_estate_t *xes,
             void *baton,
             int leaving_state,
             const svn_string_t *cdata,
             apr_hash_t *attrs,
             apr_pool_t *scratch_pool)
{
  merge_context_t *merge_ctx = baton;

  if (leaving_state == RESPONSE)
    {
      const char *rtype;

      rtype = svn_hash_gets(attrs, "resourcetype");

      /* rtype can only be "baseline" or "collection" (or NULL). We can
         keep this check simple.  */
      if (rtype && *rtype == 'b')
        {
          const char *rev_str;

          rev_str = svn_hash_gets(attrs, "revision");
          if (rev_str)
            {
              apr_int64_t rev;

              SVN_ERR(svn_cstring_atoi64(&rev, rev_str));
              merge_ctx->commit_info->revision = (svn_revnum_t)rev;
            }
          else
            merge_ctx->commit_info->revision = SVN_INVALID_REVNUM;

          merge_ctx->commit_info->date =
              apr_pstrdup(merge_ctx->pool,
                          svn_hash_gets(attrs, "date"));

          merge_ctx->commit_info->author =
              apr_pstrdup(merge_ctx->pool,
                          svn_hash_gets(attrs, "author"));

          merge_ctx->commit_info->post_commit_err =
             apr_pstrdup(merge_ctx->pool,
                         svn_hash_gets(attrs, "post-commit-err"));
        }
      else
        {
          const char *href;

          href = svn_urlpath__skip_ancestor(
                   merge_ctx->merge_url,
                   svn_hash_gets(attrs, "href"));

          if (href == NULL)
            return svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
                                     _("A MERGE response for '%s' is not "
                                       "a child of the destination ('%s')"),
                                     href, merge_ctx->merge_url);

          /* We now need to dive all the way into the WC to update the
             base VCC url.  */
          if (!SVN_RA_SERF__HAVE_HTTPV2_SUPPORT(merge_ctx->session)
              && merge_ctx->session->wc_callbacks->push_wc_prop)
            {
              const char *checked_in;
              svn_string_t checked_in_str;

              checked_in = svn_hash_gets(attrs, "checked-in");
              checked_in_str.data = checked_in;
              checked_in_str.len = strlen(checked_in);

              SVN_ERR(merge_ctx->session->wc_callbacks->push_wc_prop(
                        merge_ctx->session->wc_callback_baton,
                        href,
                        SVN_RA_SERF__WC_CHECKED_IN_URL,
                        &checked_in_str,
                        scratch_pool));
            }
        }
    }
  else if (leaving_state == BASELINE)
    {
      svn_ra_serf__xml_note(xes, RESPONSE, "resourcetype", "baseline");
    }
  else if (leaving_state == COLLECTION)
    {
      svn_ra_serf__xml_note(xes, RESPONSE, "resourcetype", "collection");
    }
  else
    {
      const char *name;
      const char *value = cdata->data;

      if (leaving_state == HREF)
        {
          name = "href";
          value = svn_urlpath__canonicalize(value, scratch_pool);
        }
      else if (leaving_state == CHECKED_IN)
        {
          name = "checked-in";
          value = svn_urlpath__canonicalize(value, scratch_pool);
        }
      else if (leaving_state == VERSION_NAME)
        name = "revision";
      else if (leaving_state == DATE)
        name = "date";
      else if (leaving_state == AUTHOR)
        name = "author";
      else if (leaving_state == POST_COMMIT_ERR)
        name = "post-commit-err";
      else
        SVN_ERR_MALFUNCTION();

      svn_ra_serf__xml_note(xes, RESPONSE, name, value);
    }

  return SVN_NO_ERROR;
}
예제 #14
0
/* This implements serf_bucket_headers_do_callback_fn_t.
 */
static int
capabilities_headers_iterator_callback(void *baton,
                                       const char *key,
                                       const char *val)
{
  options_context_t *opt_ctx = baton;
  svn_ra_serf__session_t *session = opt_ctx->session;

  if (svn_cstring_casecmp(key, "dav") == 0)
    {
      /* Each header may contain multiple values, separated by commas, e.g.:
           DAV: version-control,checkout,working-resource
           DAV: merge,baseline,activity,version-controlled-collection
           DAV: http://subversion.tigris.org/xmlns/dav/svn/depth */
      apr_array_header_t *vals = svn_cstring_split(val, ",", TRUE,
                                                   opt_ctx->pool);

      /* Right now we only have a few capabilities to detect, so just
         seek for them directly.  This could be written slightly more
         efficiently, but that wouldn't be worth it until we have many
         more capabilities. */

      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_DEPTH, vals))
        {
          apr_hash_set(session->capabilities,
                       SVN_RA_CAPABILITY_DEPTH, APR_HASH_KEY_STRING,
                       capability_yes);
        }
      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_MERGEINFO, vals))
        {
          /* The server doesn't know what repository we're referring
             to, so it can't just say capability_yes. */
          apr_hash_set(session->capabilities,
                       SVN_RA_CAPABILITY_MERGEINFO, APR_HASH_KEY_STRING,
                       capability_server_yes);
        }
      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_LOG_REVPROPS, vals))
        {
          apr_hash_set(session->capabilities,
                       SVN_RA_CAPABILITY_LOG_REVPROPS, APR_HASH_KEY_STRING,
                       capability_yes);
        }
      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_ATOMIC_REVPROPS, vals))
        {
          apr_hash_set(session->capabilities,
                       SVN_RA_CAPABILITY_ATOMIC_REVPROPS, APR_HASH_KEY_STRING,
                       capability_yes);
        }
      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_PARTIAL_REPLAY, vals))
        {
          apr_hash_set(session->capabilities,
                       SVN_RA_CAPABILITY_PARTIAL_REPLAY, APR_HASH_KEY_STRING,
                       capability_yes);
        }
    }

  /* SVN-specific headers -- if present, server supports HTTP protocol v2 */
  else if (strncmp(key, "SVN", 3) == 0)
    {
      /* If we've not yet seen any information about supported POST
         requests, we'll initialize the list/hash with "create-txn"
         (which we know is supported by virtue of the server speaking
         HTTPv2 at all. */
      if (! session->supported_posts)
        {
          session->supported_posts = apr_hash_make(session->pool);
          apr_hash_set(session->supported_posts, "create-txn", 10, (void *)1);
        }

      if (svn_cstring_casecmp(key, SVN_DAV_ROOT_URI_HEADER) == 0)
        {
          session->repos_root = session->session_url;
          session->repos_root.path =
            (char *)svn_fspath__canonicalize(val, session->pool);
          session->repos_root_str =
            svn_urlpath__canonicalize(
                apr_uri_unparse(session->pool, &session->repos_root, 0),
                session->pool);
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_ME_RESOURCE_HEADER) == 0)
        {
#ifdef SVN_DEBUG
          char *ignore_v2_env_var = getenv(SVN_IGNORE_V2_ENV_VAR);

          if (!(ignore_v2_env_var
                && apr_strnatcasecmp(ignore_v2_env_var, "yes") == 0))
            session->me_resource = apr_pstrdup(session->pool, val);
#else
          session->me_resource = apr_pstrdup(session->pool, val);
#endif
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_REV_STUB_HEADER) == 0)
        {
          session->rev_stub = apr_pstrdup(session->pool, val);
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_REV_ROOT_STUB_HEADER) == 0)
        {
          session->rev_root_stub = apr_pstrdup(session->pool, val);
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_TXN_STUB_HEADER) == 0)
        {
          session->txn_stub = apr_pstrdup(session->pool, val);
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_TXN_ROOT_STUB_HEADER) == 0)
        {
          session->txn_root_stub = apr_pstrdup(session->pool, val);
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_VTXN_STUB_HEADER) == 0)
        {
          session->vtxn_stub = apr_pstrdup(session->pool, val);
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_VTXN_ROOT_STUB_HEADER) == 0)
        {
          session->vtxn_root_stub = apr_pstrdup(session->pool, val);
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_REPOS_UUID_HEADER) == 0)
        {
          session->uuid = apr_pstrdup(session->pool, val);
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_YOUNGEST_REV_HEADER) == 0)
        {
          opt_ctx->youngest_rev = SVN_STR_TO_REV(val);
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_SUPPORTED_POSTS_HEADER) == 0)
        {
          /* May contain multiple values, separated by commas. */
          int i;
          apr_array_header_t *vals = svn_cstring_split(val, ",", TRUE,
                                                       opt_ctx->pool);

          for (i = 0; i < vals->nelts; i++)
            {
              const char *post_val = APR_ARRAY_IDX(vals, i, const char *);

              apr_hash_set(session->supported_posts, post_val,
                           APR_HASH_KEY_STRING, (void *)1);
            }
        }
    }