Пример #1
0
APU_DECLARE(void) apr_xml_quote_elem(apr_pool_t *p, apr_xml_elem *elem)
{
    apr_text *scan_txt;
    apr_xml_attr *scan_attr;
    apr_xml_elem *scan_elem;

    /* convert the element's text */
    for (scan_txt = elem->first_cdata.first;
            scan_txt != NULL;
            scan_txt = scan_txt->next) {
        scan_txt->text = apr_xml_quote_string(p, scan_txt->text, 0);
    }
    for (scan_txt = elem->following_cdata.first;
            scan_txt != NULL;
            scan_txt = scan_txt->next) {
        scan_txt->text = apr_xml_quote_string(p, scan_txt->text, 0);
    }

    /* convert the attribute values */
    for (scan_attr = elem->attr;
            scan_attr != NULL;
            scan_attr = scan_attr->next) {
        scan_attr->value = apr_xml_quote_string(p, scan_attr->value, 1);
    }

    /* convert the child elements */
    for (scan_elem = elem->first_child;
            scan_elem != NULL;
            scan_elem = scan_elem->next) {
        apr_xml_quote_elem(p, scan_elem);
    }
}
Пример #2
0
static svn_error_t *
add_file_or_directory(const char *file_or_directory,
                      const char *path,
                      edit_baton_t *eb,
                      const char *copyfrom_path,
                      svn_revnum_t copyfrom_rev,
                      apr_pool_t *pool,
                      void **added_baton)
{
  const char *qname = apr_xml_quote_string(pool, path, 1);
  const char *qcopy =
    copyfrom_path ? apr_xml_quote_string(pool, copyfrom_path, 1) : NULL;

  SVN_ERR(maybe_close_textdelta(eb));

  *added_baton = eb;

  if (! copyfrom_path)
    SVN_ERR(dav_svn__brigade_printf(eb->bb, eb->output,
                                    "<S:add-%s name=\"%s\"/>" DEBUG_CR,
                                    file_or_directory, qname));
  else
    SVN_ERR(dav_svn__brigade_printf(eb->bb, eb->output,
                                    "<S:add-%s name=\"%s\" "
                                    "copyfrom-path=\"%s\" "
                                    "copyfrom-rev=\"%ld\"/>" DEBUG_CR,
                                    file_or_directory, qname,
                                    qcopy, copyfrom_rev));

  return SVN_NO_ERROR;
}
Пример #3
0
static svn_error_t *
change_file_or_dir_prop(const char *file_or_dir,
                        edit_baton_t *eb,
                        const char *name,
                        const svn_string_t *value,
                        apr_pool_t *pool)
{
  const char *qname = apr_xml_quote_string(pool, name, 1);

  SVN_ERR(maybe_close_textdelta(eb));

  if (value)
    {
      const svn_string_t *enc_value = svn_base64_encode_string(value, pool);

      SVN_ERR(dav_svn__send_xml
                (eb->bb, eb->output,
                 "<S:change-%s-prop name=\"%s\">%s</S:change-%s-prop>" DEBUG_CR,
                 file_or_dir, qname, enc_value->data, file_or_dir));
    }
  else
    {
      SVN_ERR(dav_svn__send_xml
                (eb->bb, eb->output,
                 "<S:change-%s-prop name=\"%s\" del=\"true\"/>" DEBUG_CR,
                 file_or_dir, qname));
    }
  return SVN_NO_ERROR;
}
Пример #4
0
static apr_status_t
send_get_locations_report(ap_filter_t *output,
                          apr_bucket_brigade *bb,
                          const dav_resource *resource,
                          apr_hash_t *fs_locations)
{
  apr_hash_index_t *hi;
  apr_pool_t *pool;
  apr_status_t apr_err;

  pool = resource->pool;

  apr_err = ap_fprintf(output, bb, DAV_XML_HEADER DEBUG_CR
                       "<S:get-locations-report xmlns:S=\"" SVN_XML_NAMESPACE
                       "\" xmlns:D=\"DAV:\">" DEBUG_CR);
  if (apr_err)
    return apr_err;

  for (hi = apr_hash_first(pool, fs_locations); hi; hi = apr_hash_next(hi))
    {
      const void *key;
      void *value;
      const char *path_quoted;

      apr_hash_this(hi, &key, NULL, &value);
      path_quoted = apr_xml_quote_string(pool, value, 1);
      apr_err = ap_fprintf(output, bb, "<S:location "
                           "rev=\"%ld\" path=\"%s\"/>" DEBUG_CR,
                           *(const svn_revnum_t *)key, path_quoted);
      if (apr_err)
        return apr_err;
    }
  return ap_fprintf(output, bb, "</S:get-locations-report>" DEBUG_CR);
}
Пример #5
0
/* Implements `svn_location_segment_receiver_t'; helper for
   dav_svn__get_location_segments_report(). */
static svn_error_t *
location_segment_receiver(svn_location_segment_t *segment,
                          void *baton,
                          apr_pool_t *pool)
{
  struct location_segment_baton *b = baton;
  apr_status_t apr_err;

  SVN_ERR(maybe_send_opener(b));

  if (segment->path)
    {
      const char *path_quoted = apr_xml_quote_string(pool, segment->path, 1);
      apr_err = ap_fprintf(b->output, b->bb,
                           "<S:location-segment path=\"%s\" "
                           "range-start=\"%ld\" range-end=\"%ld\"/>" DEBUG_CR,
                           path_quoted,
                           segment->range_start, segment->range_end);
    }
  else
    {
      apr_err = ap_fprintf(b->output, b->bb,
                           "<S:location-segment "
                           "range-start=\"%ld\" range-end=\"%ld\"/>" DEBUG_CR,
                           segment->range_start, segment->range_end);
    }
  if (apr_err)
    return svn_error_create(apr_err, 0, NULL);
  return SVN_NO_ERROR;
}
Пример #6
0
/* Send a property named NAME with value VAL in an element named ELEM_NAME.
   Quote NAME and base64-encode VAL if necessary. */
static svn_error_t *
send_prop(struct file_rev_baton *frb,
          const char *elem_name,
          const char *name,
          const svn_string_t *val,
          apr_pool_t *pool)
{
  name = apr_xml_quote_string(pool, name, 1);

  if (svn_xml_is_xml_safe(val->data, val->len))
    {
      svn_stringbuf_t *tmp = NULL;
      svn_xml_escape_cdata_string(&tmp, val, pool);
      val = svn_string_create(tmp->data, pool);
      SVN_ERR(dav_svn__brigade_printf(frb->bb, frb->output,
                                      "<S:%s name=\"%s\">%s</S:%s>" DEBUG_CR,
                                      elem_name, name, val->data, elem_name));
    }
  else
    {
      val = svn_base64_encode_string2(val, TRUE, pool);
      SVN_ERR(dav_svn__brigade_printf(frb->bb, frb->output,
                                      "<S:%s name=\"%s\" encoding=\"base64\">"
                                      "%s</S:%s>" DEBUG_CR,
                                      elem_name, name, val->data, elem_name));
    }

  return SVN_NO_ERROR;
}
Пример #7
0
/* Utility for log_receiver opening a new XML element in LRB's brigade
   for LOG_ITEM and return the element's name in *ELEMENT.  Use POOL for
   temporary allocations.

   Call this function for items that may have a copy-from */
static svn_error_t *
start_path_with_copy_from(const char **element,
                          struct log_receiver_baton *lrb,
                          svn_log_changed_path2_t *log_item,
                          apr_pool_t *pool)
{
  switch (log_item->action)
    {
      case 'A': *element = "S:added-path";
                break;
      case 'R': *element = "S:replaced-path";
                break;
      default:  /* Caller, you did wrong! */
                SVN_ERR_MALFUNCTION();
    }

  if (log_item->copyfrom_path
      && SVN_IS_VALID_REVNUM(log_item->copyfrom_rev))
    SVN_ERR(dav_svn__brigade_printf
            (lrb->bb, lrb->output,
             "<%s copyfrom-path=\"%s\" copyfrom-rev=\"%ld\"",
             *element,
             apr_xml_quote_string(pool,
                                  log_item->copyfrom_path,
                                  1), /* escape quotes */
             log_item->copyfrom_rev));
  else
    SVN_ERR(dav_svn__brigade_printf(lrb->bb, lrb->output, "<%s", *element));

  return SVN_NO_ERROR;
}
Пример #8
0
/**
 * Insert prop with propid
 * @param resource the resource whose prop needs to be edited
 * @param propid the property identified with propid which needs to be inserted. 
 * @param what the value to be inserted.
 * @param phdr the first piece of text in the list.
*/
static dav_prop_insert dav_repos_insert_prop(const dav_resource * resource,
					     int propid,
					     dav_prop_insert what,
					     apr_text_header * phdr)
{
    const dav_liveprop_spec *spec;
    const char *value = NULL;
    const char *name = NULL;
    const char *s = NULL;
    apr_pool_t *pool = resource->pool;
    dav_repos_resource *dbr = (dav_repos_resource *) resource->info->db_r;

    TRACE();
    DBG1("propid: %d", propid);

    /*
     ** None of FS provider properties are defined if the resource does not
     ** exist. Just bail for this case.
     **
     ** Even though we state that the FS properties are not defined, the
     ** client cannot store dead values -- we deny that thru the is_writable
     ** hook function.
     */
    if (dbr->serialno == 0)
	return DAV_PROP_INSERT_NOTDEF;

    /* find propname using prop id */
    spec = get_livepropspec_from_id(dav_repos_props, propid);
    name = spec->name;

    /* ### what the heck was this property? */
    if (name == NULL)
	return DAV_PROP_INSERT_NOTDEF;

    /* ensure lpr_hash is set */
    if(!dbr->lpr_hash) dav_repos_build_lpr_hash(dbr);

    /* Get value */
    value = apr_hash_get(dbr->lpr_hash, name, APR_HASH_KEY_STRING);

    /* ### Not found in the hash */
    if (value == NULL)
	return DAV_PROP_INSERT_NOTDEF;

    /* Do something according to what */
    if (what == DAV_PROP_INSERT_VALUE)
	s = apr_psprintf(pool, "<D:%s>%s</D:%s>", name, 
                         apr_xml_quote_string(pool, value, 0), name);
    else if (what == DAV_PROP_INSERT_NAME)
	s = apr_psprintf(pool, "<D:%s/>" DEBUG_CR, name);
    else  /* assert: what == DAV_PROP_INSERT_SUPPORTED */
	s = apr_psprintf(pool,
			 "<D:supported-live-property><D:prop><D:%s/>"
			 "</D:prop></D:supported-live-property>", name);
    apr_text_append(pool, phdr, s);

    /* we inserted what was asked for */
    return what;
}
Пример #9
0
/* Insert all live props from live prop hash */
static void dav_repos_insert_all_liveprops(request_rec * r,
                                           const dav_resource * resource,
                                           dav_prop_insert what,
                                           apr_text_header * phdr)
{
    apr_ssize_t klen;
    const char *s = "";
    const char *key, *val;
    apr_hash_index_t *hindex;
    dav_repos_resource *db_r;

    /* don't try to find any liveprops if this isn't "our" resource */
    if (resource->hooks != &dav_repos_hooks_repos)
	return;

    TRACE();

    db_r = (dav_repos_resource *) resource->info->db_r;

    if (!resource->exists) {
	/* a lock-null resource */
	/*
	 ** ### technically, we should insert empty properties. dunno offhand
	 ** ### what part of the spec said this, but it was essentially thus:
	 ** ### "the properties should be defined, but may have no value".
	 */
	apr_text_append(r->pool, phdr, "<D:resourcetype/>");
	return;
    }

    if (what == DAV_PROP_INSERT_SUPPORTED)
        apr_text_append(r->pool, phdr, "<D:supported-live-property><D:prop>");

    /* ensure lpr_hash is set */
    if(!db_r->lpr_hash) dav_repos_build_lpr_hash(db_r);

    /* Read live props from hash */
    for (hindex = apr_hash_first(r->pool, db_r->lpr_hash);
	 hindex; hindex = apr_hash_next(hindex)) {
	apr_hash_this(hindex, (void *) &key, &klen, (void *) &val);
        switch (what) {
        case DAV_PROP_INSERT_VALUE:
            s = apr_psprintf(r->pool, "<D:%s>%s</D:%s>"DEBUG_CR, key, 
                             apr_xml_quote_string(r->pool, val, 0), key);
            break;
        case DAV_PROP_INSERT_NAME:
        case DAV_PROP_INSERT_SUPPORTED:
            s = apr_psprintf(r->pool, "<D:%s/>", key);
            break;
        default:
            break;
        }
	apr_text_append(r->pool, phdr, s);
    }

    if (what == DAV_PROP_INSERT_SUPPORTED)
        apr_text_append(r->pool, phdr, "</D:prop></D:supported-live-property>");
}
Пример #10
0
/* send a response to the client for this baton */
static svn_error_t *
send_response(const dav_svn_repos *repos,
              svn_fs_root_t *root,
              const char *path,
              svn_boolean_t is_dir,
              ap_filter_t *output,
              apr_bucket_brigade *bb,
              apr_pool_t *pool)
{
  const char *href;
  const char *vsn_url;
  apr_status_t status;
  svn_revnum_t rev_to_use;

  href = dav_svn__build_uri(repos, DAV_SVN__BUILD_URI_PUBLIC,
                            SVN_IGNORED_REVNUM, path, 0 /* add_href */, pool);
  rev_to_use = dav_svn__get_safe_cr(root, path, pool);
  vsn_url = dav_svn__build_uri(repos, DAV_SVN__BUILD_URI_VERSION,
                               rev_to_use, path, 0 /* add_href */, pool);
  status = ap_fputstrs(output, bb,
                       "<D:response>" DEBUG_CR
                       "<D:href>",
                       apr_xml_quote_string(pool, href, 1),
                       "</D:href>" DEBUG_CR
                       "<D:propstat><D:prop>" DEBUG_CR,
                       is_dir
                         ? "<D:resourcetype><D:collection/></D:resourcetype>"
                         : "<D:resourcetype/>",
                       DEBUG_CR,
                       "<D:checked-in><D:href>",
                       apr_xml_quote_string(pool, vsn_url, 1),
                       "</D:href></D:checked-in>" DEBUG_CR
                       "</D:prop>" DEBUG_CR
                       "<D:status>HTTP/1.1 200 OK</D:status>" DEBUG_CR
                       "</D:propstat>" DEBUG_CR
                       "</D:response>" DEBUG_CR,
                       NULL);
  if (status != APR_SUCCESS)
    return svn_error_wrap_apr(status, "Can't write response to output");

  return SVN_NO_ERROR;
}
Пример #11
0
static svn_error_t *
delete_entry(const char *path,
             svn_revnum_t revision,
             void *parent_baton,
             apr_pool_t *pool)
{
  edit_baton_t *eb = parent_baton;
  const char *qname = apr_xml_quote_string(pool, path, 1);
  SVN_ERR(maybe_close_textdelta(eb));
  return dav_svn__send_xml(eb->bb, eb->output,
                           "<S:delete-entry name=\"%s\" rev=\"%ld\"/>" DEBUG_CR,
                            qname, revision);
}
Пример #12
0
static svn_error_t *
open_file_or_directory(const char *file_or_directory,
                       const char *path,
                       edit_baton_t *eb,
                       svn_revnum_t base_revision,
                       apr_pool_t *pool,
                       void **opened_baton)
{
  const char *qname = apr_xml_quote_string(pool, path, 1);
  SVN_ERR(maybe_close_textdelta(eb));
  *opened_baton = (void *)eb;
  return dav_svn__send_xml(eb->bb, eb->output,
                           "<S:open-%s name=\"%s\" rev=\"%ld\"/>" DEBUG_CR,
                           file_or_directory, qname, base_revision);
}
Пример #13
0
static svn_error_t *
change_file_or_dir_prop(const char *file_or_dir,
                        edit_baton_t *eb,
                        const char *name,
                        const svn_string_t *value,
                        apr_pool_t *pool)
{
  const char *qname = apr_xml_quote_string(pool, name, 1);

  SVN_ERR(maybe_close_textdelta(eb));

  if (value)
    {
      const svn_string_t *enc_value =
        svn_base64_encode_string2(value, TRUE, pool);

      /* Some versions of apr_brigade_vprintf() have a buffer overflow
         bug that can be triggered by just the wrong size of a large
         property value.  The bug has been fixed (see
         http://svn.apache.org/viewvc?view=rev&revision=768417), but
         we need a workaround for the buggy APR versions, so we write
         our potentially large block of property data using a
         different underlying function. */
      SVN_ERR(dav_svn__brigade_printf(eb->bb, eb->output,
                                      "<S:change-%s-prop name=\"%s\">",
                                      file_or_dir, qname));
      SVN_ERR(dav_svn__brigade_write(eb->bb, eb->output,
                                     enc_value->data, enc_value->len));
      SVN_ERR(dav_svn__brigade_printf(eb->bb, eb->output,
                                      "</S:change-%s-prop>" DEBUG_CR,
                                      file_or_dir));
    }
  else
    {
      SVN_ERR(dav_svn__brigade_printf
                (eb->bb, eb->output,
                 "<S:change-%s-prop name=\"%s\" del=\"true\"/>" DEBUG_CR,
                 file_or_dir, qname));
    }
  return SVN_NO_ERROR;
}
Пример #14
0
/* Transmit LOCKS (a hash of Subversion filesystem locks keyed by
   path) across OUTPUT using BB.  Use POOL for necessary allocations.

   NOTE:  As written, this function currently returns one of only two
   status values -- "success", and "we had trouble writing out to the
   output stream".  If you need to return something more interesting,
   you'll probably want to generate dav_error's here instead of
   passing back only apr_status_t's.  */
static apr_status_t
send_get_lock_response(apr_hash_t *locks,
                       ap_filter_t *output,
                       apr_bucket_brigade *bb,
                       apr_pool_t *pool)
{
  apr_pool_t *subpool;
  apr_hash_index_t *hi;

  /* start sending report */
  SVN_APR_ERR(ap_fprintf(output, bb,
                         DAV_XML_HEADER DEBUG_CR
                         "<S:get-locks-report xmlns:S=\"" SVN_XML_NAMESPACE
                         "\" xmlns:D=\"DAV:\">" DEBUG_CR));

  /* stream the locks */
  subpool = svn_pool_create(pool);
  for (hi = apr_hash_first(pool, locks); hi; hi = apr_hash_next(hi))
    {
      void *val;
      const svn_lock_t *lock;

      svn_pool_clear(subpool);
      apr_hash_this(hi, NULL, NULL, &val);
      lock = val;

      /* Begin the <S:lock> tag, transmitting the path, token, and
         creation date. */
      SVN_APR_ERR(ap_fprintf(output, bb,
                             "<S:lock>" DEBUG_CR
                             "<S:path>%s</S:path>" DEBUG_CR
                             "<S:token>%s</S:token>" DEBUG_CR
                             "<S:creationdate>%s</S:creationdate>" DEBUG_CR,
                             apr_xml_quote_string(subpool, lock->path, 1),
                             apr_xml_quote_string(subpool, lock->token, 1),
                             svn_time_to_cstring(lock->creation_date,
                                                 subpool)));

      /* Got expiration date?  Tell the client. */
      if (lock->expiration_date)
        SVN_APR_ERR(ap_fprintf(output, bb,
                               "<S:expirationdate>%s</S:expirationdate>"
                               DEBUG_CR,
                               svn_time_to_cstring(lock->expiration_date,
                                                   subpool)));

      /* Transmit the lock ownership information. */
      if (lock->owner)
        {
          const char *owner;
          svn_boolean_t owner_base64 = FALSE;

          if (svn_xml_is_xml_safe(lock->owner, strlen(lock->owner)))
            {
              owner = apr_xml_quote_string(subpool, lock->owner, 1);
            }
          else
            {
              svn_string_t owner_string;
              const svn_string_t *encoded_owner;

              owner_string.data = lock->owner;
              owner_string.len = strlen(lock->owner);
              encoded_owner = svn_base64_encode_string2(&owner_string, TRUE,
                                                        subpool);
              owner = encoded_owner->data;
              owner_base64 = TRUE;
            }
          SVN_APR_ERR(ap_fprintf(output, bb,
                                 "<S:owner %s>%s</S:owner>" DEBUG_CR,
                                 owner_base64 ? "encoding=\"base64\"" : "",
                                 owner));
        }

      /* If the lock carries a comment, transmit that, too. */
      if (lock->comment)
        {
          const char *comment;
          svn_boolean_t comment_base64 = FALSE;

          if (svn_xml_is_xml_safe(lock->comment, strlen(lock->comment)))
            {
              comment = apr_xml_quote_string(subpool, lock->comment, 1);
            }
          else
            {
              svn_string_t comment_string;
              const svn_string_t *encoded_comment;

              comment_string.data = lock->comment;
              comment_string.len = strlen(lock->comment);
              encoded_comment = svn_base64_encode_string2(&comment_string,
                                                          TRUE, subpool);
              comment = encoded_comment->data;
              comment_base64 = TRUE;
            }
          SVN_APR_ERR(ap_fprintf(output, bb,
                                 "<S:comment %s>%s</S:comment>" DEBUG_CR,
                                 comment_base64 ? "encoding=\"base64\"" : "",
                                 comment));
        }

      /* Okay, finish up this lock by closing the <S:lock> tag. */
      SVN_APR_ERR(ap_fprintf(output, bb, "</S:lock>" DEBUG_CR));
    }
  svn_pool_destroy(subpool);

  /* Finish the report */
  SVN_APR_ERR(ap_fprintf(output, bb, "</S:get-locks-report>" DEBUG_CR));

  return APR_SUCCESS;
}
Пример #15
0
dav_error *
dav_svn__merge_response(ap_filter_t *output,
                        const dav_svn_repos *repos,
                        svn_revnum_t new_rev,
                        char *post_commit_err,
                        apr_xml_elem *prop_elem,
                        svn_boolean_t disable_merge_response,
                        apr_pool_t *pool)
{
  apr_bucket_brigade *bb;
  svn_fs_root_t *root;
  svn_error_t *serr;
  const char *vcc;
  const char *rev;
  svn_string_t *creationdate, *creator_displayname;
  const char *post_commit_err_elem = NULL,
             *post_commit_header_info = NULL;

  serr = svn_fs_revision_root(&root, repos->fs, new_rev, pool);
  if (serr != NULL)
    {
      return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                  "Could not open the FS root for the "
                                  "revision just committed.",
                                  repos->pool);
    }

  bb = apr_brigade_create(pool, output->c->bucket_alloc);

  /* prep some strings */

  /* the HREF for the baseline is actually the VCC */
  vcc = dav_svn__build_uri(repos, DAV_SVN__BUILD_URI_VCC, SVN_IGNORED_REVNUM,
                           NULL, 0 /* add_href */, pool);

  /* the version-name of the baseline is the revision number */
  rev = apr_psprintf(pool, "%ld", new_rev);

  /* get the post-commit hook stderr, if any */
  if (post_commit_err)
    {
      post_commit_header_info = apr_psprintf(pool,
                                             " xmlns:S=\"%s\"",
                                             SVN_XML_NAMESPACE);
      post_commit_err_elem = apr_psprintf(pool,
                                          "<S:post-commit-err>%s"
                                          "</S:post-commit-err>",
                                          post_commit_err);
    }
  else
    {
      post_commit_header_info = "" ;
      post_commit_err_elem = "" ;
    }


  /* get the creationdate and creator-displayname of the new revision, too. */
  serr = svn_fs_revision_prop(&creationdate, repos->fs, new_rev,
                              SVN_PROP_REVISION_DATE, pool);
  if (serr != NULL)
    {
      return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                  "Could not get date of newest revision",
                                  repos->pool);
    }
  serr = svn_fs_revision_prop(&creator_displayname, repos->fs, new_rev,
                              SVN_PROP_REVISION_AUTHOR, pool);
  if (serr != NULL)
    {
      return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                  "Could not get author of newest revision",
                                  repos->pool);
    }


  (void) ap_fputstrs(output, bb,
                     DAV_XML_HEADER DEBUG_CR
                     "<D:merge-response xmlns:D=\"DAV:\"",
                     post_commit_header_info,
                     ">" DEBUG_CR
                     "<D:updated-set>" DEBUG_CR

                     /* generate a response for the new baseline */
                     "<D:response>" DEBUG_CR
                     "<D:href>",
                     apr_xml_quote_string(pool, vcc, 1),
                     "</D:href>" DEBUG_CR
                     "<D:propstat><D:prop>" DEBUG_CR
                     /* ### this is wrong. it's a VCC, not a baseline. but
                        ### we need to tell the client to look at *this*
                        ### resource for the version-name. */
                     "<D:resourcetype><D:baseline/></D:resourcetype>" DEBUG_CR,
                     post_commit_err_elem, DEBUG_CR
                     "<D:version-name>", rev, "</D:version-name>" DEBUG_CR,
                     NULL);
  if (creationdate)
    {
      (void) ap_fputstrs(output, bb,
                         "<D:creationdate>",
                         apr_xml_quote_string(pool, creationdate->data, 1),
                         "</D:creationdate>" DEBUG_CR,
                         NULL);
    }
  if (creator_displayname)
    {
      (void) ap_fputstrs(output, bb,
                         "<D:creator-displayname>",
                         apr_xml_quote_string(pool,
                                              creator_displayname->data, 1),
                         "</D:creator-displayname>" DEBUG_CR,
                         NULL);
    }
  (void) ap_fputstrs(output, bb,
                     "</D:prop>" DEBUG_CR
                     "<D:status>HTTP/1.1 200 OK</D:status>" DEBUG_CR
                     "</D:propstat>" DEBUG_CR
                     "</D:response>" DEBUG_CR,

                     NULL);

  /* ONLY have dir_delta drive the editor if the caller asked us to
     generate a full MERGE response.  svn clients can ask us to
     suppress this walk by sending specific request headers. */
  if (! disable_merge_response)
    {
      /* Now we need to generate responses for all the resources which
         changed.  This is done through a delta of the two roots.

         Note that a directory is not marked when open_dir is seen
         (since it typically is used just for changing members in that
         directory); instead, we want for a property change (the only
         reason the client would need to fetch a new directory).

         ### we probably should say something about the dirs, so that
         ### we can pass back the new version URL */

      /* and go make me proud, boy! */
      serr = do_resources(repos, root, new_rev, output, bb, pool);
      if (serr != NULL)
        {
          return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                      "Error constructing resource list.",
                                      repos->pool);
        }
    }

  /* wrap up the merge response */
  (void) ap_fputs(output, bb,
                  "</D:updated-set>" DEBUG_CR
                  "</D:merge-response>" DEBUG_CR);

  /* send whatever is left in the brigade */
  (void) ap_pass_brigade(output, bb);

  return SVN_NO_ERROR;
}
Пример #16
0
dav_error *dav_repos_deliver_principal_match(request_rec * r,
					     const dav_resource * resource,
					     const apr_xml_doc * doc,
					     ap_filter_t * output)
{
    /* this buffers the output for a bit and is automatically flushed,
       at appropriate times, by the Apache filter system. */
    apr_bucket_brigade *bb;

    apr_pool_t *pool = resource->pool;
    dav_repos_db *db = resource->info->db;
    dav_repos_resource *db_r = (dav_repos_resource *) resource->info->db_r;
    apr_xml_elem *principal_properties;
    char *req_username = r->user;
    long principal_id;
    dav_error *err = NULL;

    TRACE();

    if (!req_username) req_username = "******";

    if((err = dbms_get_principal_id_from_name(pool, db, req_username, 
                                              &principal_id))) {
        return err;
    }

    principal_properties =
	dav_find_child(doc->root, "principal-property");

    sabridge_get_collection_children(db, db_r, DAV_INFINITY, "read",
                                     NULL, NULL, NULL);

    bb = apr_brigade_create(pool, output->c->bucket_alloc);
    r->status = HTTP_MULTI_STATUS;
    send_xml(bb, output, "<D:multistatus xmlns:D=\"DAV:\">" DEBUG_CR);

    while ((db_r = db_r->next)) {
	// Currently supporting DAV:owner only
	if ((principal_properties && 
             !strcmp(principal_properties->name, "owner") && 
             db_r->owner_id == principal_id) || 
            (!principal_properties &&	// Found no principal_properties
             !strcmp(db_r->displayname, req_username)))
	{
	    send_xml(bb, output, "<D:response>");
	    const char *str =
		apr_psprintf(pool, "<D:href>%s</D:href>"
			     DEBUG_CR, apr_xml_quote_string(pool, db_r->uri, 0));
	    send_xml(bb, output, str);
	    send_xml(bb, output,
		     "<D:status>HTTP/1.1 200 OK</D:status>" DEBUG_CR);
	    send_xml(bb, output, "</D:response>");
	}
    }

    send_xml(bb, output, "</D:multistatus>");

    /* flush the contents of the brigade */
    ap_fflush(output, bb);
    return NULL;
}
Пример #17
0
/* This implements the svn_repos_file_rev_handler2_t interface. */
static svn_error_t *
file_rev_handler(void *baton,
                 const char *path,
                 svn_revnum_t revnum,
                 apr_hash_t *rev_props,
                 svn_boolean_t merged_revision,
                 svn_txdelta_window_handler_t *window_handler,
                 void **window_baton,
                 apr_array_header_t *props,
                 apr_pool_t *pool)
{
  struct file_rev_baton *frb = baton;
  apr_pool_t *subpool = svn_pool_create(pool);
  apr_hash_index_t *hi;
  int i;

  SVN_ERR(maybe_send_header(frb));

  SVN_ERR(dav_svn__brigade_printf(frb->bb, frb->output,
                                  "<S:file-rev path=\"%s\" rev=\"%ld\">"
                                  DEBUG_CR,
                                  apr_xml_quote_string(pool, path, 1),
                                  revnum));

  /* Send rev props. */
  for (hi = apr_hash_first(pool, rev_props); hi; hi = apr_hash_next(hi))
    {
      const void *key;
      void *val;
      const char *pname;
      const svn_string_t *pval;

      svn_pool_clear(subpool);
      apr_hash_this(hi, &key, NULL, &val);
      pname = key;
      pval = val;
      SVN_ERR(send_prop(frb, "rev-prop", pname, pval, subpool));
    }

  /* Send file prop changes. */
  for (i = 0; i < props->nelts; ++i)
    {
      const svn_prop_t *prop = &APR_ARRAY_IDX(props, i, svn_prop_t);

      svn_pool_clear(subpool);
      if (prop->value)
        SVN_ERR(send_prop(frb, "set-prop", prop->name, prop->value,
                          subpool));
      else
        {
          /* Property was removed. */
          SVN_ERR(dav_svn__brigade_printf(frb->bb, frb->output,
                                          "<S:remove-prop name=\"%s\"/>"
                                          DEBUG_CR,
                                          apr_xml_quote_string(subpool,
                                                               prop->name,
                                                               1)));
        }
    }

  /* Send whether this was the result of a merge or not. */
  if (merged_revision)
    SVN_ERR(dav_svn__brigade_puts(frb->bb, frb->output,
                                  "<S:merged-revision/>"));

  /* Maybe send text delta. */
  if (window_handler)
    {
      svn_stream_t *base64_stream;

      base64_stream = dav_svn__make_base64_output_stream(frb->bb, frb->output,
                                                         pool);
      svn_txdelta_to_svndiff3(&frb->window_handler, &frb->window_baton,
                              base64_stream, frb->svndiff_version,
                              frb->compression_level, pool);
      *window_handler = delta_window_handler;
      *window_baton = frb;
      /* Start the txdelta element wich will be terminated by the window
         handler together with the file-rev element. */
      SVN_ERR(dav_svn__brigade_puts(frb->bb, frb->output, "<S:txdelta>"));
    }
  else
    /* No txdelta, so terminate the element here. */
    SVN_ERR(dav_svn__brigade_puts(frb->bb, frb->output,
                                  "</S:file-rev>" DEBUG_CR));

  svn_pool_destroy(subpool);

  return SVN_NO_ERROR;
}
Пример #18
0
static dav_error *
save_value(dav_db *db, const dav_prop_name *name,
           const svn_string_t *const *old_value_p,
           const svn_string_t *value)
{
  const char *propname;
  svn_error_t *serr;
  const dav_resource *resource = db->resource;
  apr_pool_t *subpool;

  /* get the repos-local name */
  get_repos_propname(db, name, &propname);

  if (propname == NULL)
    {
      if (db->resource->info->repos->autoversioning)
        /* ignore the unknown namespace of the incoming prop. */
        propname = name->name;
      else
        return dav_svn__new_error(db->p, HTTP_CONFLICT, 0,
                                  "Properties may only be defined in the "
                                  SVN_DAV_PROP_NS_SVN " and "
                                  SVN_DAV_PROP_NS_CUSTOM " namespaces.");
    }

  /* We've got three different types of properties (node, txn, and
     revision), and we've got two different protocol versions to deal
     with.  Let's try to make some sense of this, shall we?

        HTTP v1:
          working baseline ('wbl') resource        -> txn prop change
          non-working, baselined resource ('bln')  -> rev prop change [*]
          working, non-baselined resource ('wrk')  -> node prop change

        HTTP v2:
          transaction resource ('txn')             -> txn prop change
          revision resource ('rev')                -> rev prop change
          transaction root resource ('txr')        -> node prop change

     [*] This is a violation of the DeltaV spec (### see issue #916).

  */

  /* A subpool to cope with mod_dav making multiple calls, e.g. during
     PROPPATCH with multiple values. */
  subpool = svn_pool_create(db->resource->pool);
  if (db->resource->baselined)
    {
      if (db->resource->working)
        {
          serr = svn_repos_fs_change_txn_prop(resource->info->root.txn,
                                              propname, value,
                                              subpool);
        }
      else
        {
          serr = svn_repos_fs_change_rev_prop4(resource->info->repos->repos,
                                               resource->info->root.rev,
                                               resource->info->repos->username,
                                               propname, old_value_p, value,
                                               TRUE, TRUE,
                                               db->authz_read_func,
                                               db->authz_read_baton,
                                               subpool);

          /* Prepare any hook failure message to get sent over the wire */
          if (serr)
            {
              svn_error_t *purged_serr = svn_error_purge_tracing(serr);
              if (purged_serr->apr_err == SVN_ERR_REPOS_HOOK_FAILURE)
                purged_serr->message = apr_xml_quote_string
                                         (purged_serr->pool,
                                          purged_serr->message, 1);

              /* mod_dav doesn't handle the returned error very well, it
                 generates its own generic error that will be returned to
                 the client.  Cache the detailed error here so that it can
                 be returned a second time when the rollback mechanism
                 triggers. */
              resource->info->revprop_error = svn_error_dup(purged_serr);
            }

          /* Tell the logging subsystem about the revprop change. */
          dav_svn__operational_log(resource->info,
                                   svn_log__change_rev_prop(
                                      resource->info->root.rev,
                                      propname, subpool));
        }
    }
  else if (resource->info->restype == DAV_SVN_RESTYPE_TXN_COLLECTION)
    {
      serr = svn_repos_fs_change_txn_prop(resource->info->root.txn,
                                          propname, value, subpool);
    }
  else
    {
      serr = svn_repos_fs_change_node_prop(resource->info->root.root,
                                           get_repos_path(resource->info),
                                           propname, value, subpool);
    }
  svn_pool_destroy(subpool);

  if (serr != NULL)
    return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                NULL, resource->pool);

  /* a change to the props was made; make sure our cached copy is gone */
  db->props = NULL;

  return NULL;
}
Пример #19
0
static dav_prop_insert
insert_prop_internal(const dav_resource *resource,
                     int propid,
                     dav_prop_insert what,
                     apr_text_header *phdr,
                     apr_pool_t *scratch_pool,
                     apr_pool_t *result_pool)
{
  const char *value = NULL;
  const char *s;
  const dav_liveprop_spec *info;
  int global_ns;
  svn_error_t *serr;

  /*
  ** Almost none of the SVN provider properties are defined if the
  ** resource does not exist.  We do need to return the one VCC
  ** property and baseline-relative-path on lock-null resources,
  ** however, so that svn clients can run 'svn unlock' and 'svn info'
  ** on these things.
  **
  ** Even though we state that the SVN properties are not defined, the
  ** client cannot store dead values -- we deny that thru the is_writable
  ** hook function.
  */
  if ((! resource->exists)
      && (propid != DAV_PROPID_version_controlled_configuration)
      && (propid != SVN_PROPID_baseline_relative_path))
    return DAV_PROP_INSERT_NOTSUPP;

  /* ### we may want to respond to DAV_PROPID_resourcetype for PRIVATE
     ### resources. need to think on "proper" interaction with mod_dav */

  switch (propid)
    {
    case DAV_PROPID_getlastmodified:
    case DAV_PROPID_creationdate:
      {
        /* In subversion terms, the date attached to a file's CR is
           the true "last modified" time.  However, we're defining
           creationdate in the same way.  IMO, the "creationdate" is
           really the date attached to the revision in which the item
           *first* came into existence; this would found by tracing
           back through the log of the file -- probably via
           svn_fs_revisions_changed.  gstein, is it a bad thing that
           we're currently using 'creationdate' to mean the same thing
           as 'last modified date'?  */
        const char *datestring;
        apr_time_t timeval;
        enum time_format format;

        /* ### for now, our global VCC has no such property. */
        if (resource->type == DAV_RESOURCE_TYPE_PRIVATE
            && (resource->info->restype == DAV_SVN_RESTYPE_VCC
                || resource->info->restype == DAV_SVN_RESTYPE_ME))
          {
            return DAV_PROP_INSERT_NOTSUPP;
          }

        if (propid == DAV_PROPID_creationdate)
          {
            /* Return an ISO8601 date; this is what the svn client
               expects, and rfc2518 demands it. */
            format = time_format_iso8601;
          }
        else /* propid == DAV_PROPID_getlastmodified */
          {
            format = time_format_rfc1123;
          }

        if (0 != get_last_modified_time(&datestring, &timeval,
                                        resource, format, scratch_pool))
          {
            return DAV_PROP_INSERT_NOTDEF;
          }

        value = apr_xml_quote_string(scratch_pool, datestring, 1);
        break;
      }

    case DAV_PROPID_creator_displayname:
      {
        svn_revnum_t committed_rev = SVN_INVALID_REVNUM;
        svn_string_t *last_author = NULL;

        /* ### for now, our global VCC has no such property. */
        if (resource->type == DAV_RESOURCE_TYPE_PRIVATE
            && (resource->info->restype == DAV_SVN_RESTYPE_VCC
                || resource->info->restype == DAV_SVN_RESTYPE_ME))
          {
            return DAV_PROP_INSERT_NOTSUPP;
          }

        if (resource->baselined && resource->type == DAV_RESOURCE_TYPE_VERSION)
          {
            /* A baseline URI. */
            committed_rev = resource->info->root.rev;
          }
        else if (resource->type == DAV_RESOURCE_TYPE_REGULAR
                 || resource->type == DAV_RESOURCE_TYPE_WORKING
                 || resource->type == DAV_RESOURCE_TYPE_VERSION)
          {
            /* Get the CR field out of the node's skel.  Notice that the
               root object might be an ID root -or- a revision root. */
            serr = svn_fs_node_created_rev(&committed_rev,
                                           resource->info->root.root,
                                           resource->info->repos_path,
                                           scratch_pool);
            if (serr != NULL)
              {
                /* ### what to do? */
                svn_error_clear(serr);
                value = "###error###";
                break;
              }
          }
        else
          {
            return DAV_PROP_INSERT_NOTSUPP;
          }

        serr = get_path_revprop(&last_author,
                                resource,
                                committed_rev,
                                SVN_PROP_REVISION_AUTHOR,
                                scratch_pool);
        if (serr)
          {
            /* ### what to do? */
            svn_error_clear(serr);
            value = "###error###";
            break;
          }

        if (last_author == NULL)
          return DAV_PROP_INSERT_NOTDEF;

        value = apr_xml_quote_string(scratch_pool, last_author->data, 1);
        break;
      }

    case DAV_PROPID_getcontentlanguage:
      /* ### need something here */
      return DAV_PROP_INSERT_NOTSUPP;
      break;

    case DAV_PROPID_getcontentlength:
      {
        svn_filesize_t len = 0;

        /* our property, but not defined on collection resources */
        if (resource->collection || resource->baselined)
          return DAV_PROP_INSERT_NOTSUPP;

        serr = svn_fs_file_length(&len, resource->info->root.root,
                                  resource->info->repos_path, scratch_pool);
        if (serr != NULL)
          {
            svn_error_clear(serr);
            value = "0";  /* ### what to do? */
            break;
          }

        value = apr_psprintf(scratch_pool, "%" SVN_FILESIZE_T_FMT, len);
        break;
      }

    case DAV_PROPID_getcontenttype:
      {
        /* The subversion client assumes that any file without an
           svn:mime-type property is of type text/plain.  So it seems
           safe (and consistent) to assume the same on the server.  */
        svn_string_t *pval;
        const char *mime_type = NULL;

        if (resource->baselined && resource->type == DAV_RESOURCE_TYPE_VERSION)
          return DAV_PROP_INSERT_NOTSUPP;

        if (resource->type == DAV_RESOURCE_TYPE_PRIVATE
            && (resource->info->restype == DAV_SVN_RESTYPE_VCC
                || resource->info->restype == DAV_SVN_RESTYPE_ME))
          {
            return DAV_PROP_INSERT_NOTSUPP;
          }

        if (resource->collection) /* defaults for directories */
          {
            if (resource->info->repos->xslt_uri)
              mime_type = "text/xml";
            else
              mime_type = "text/html; charset=UTF-8";
          }
        else
          {
            if ((serr = svn_fs_node_prop(&pval, resource->info->root.root,
                                         resource->info->repos_path,
                                         SVN_PROP_MIME_TYPE, scratch_pool)))
              {
                svn_error_clear(serr);
                pval = NULL;
              }

            if (pval)
              mime_type = pval->data;
            else if ((! resource->info->repos->is_svn_client)
                     && resource->info->r->content_type)
              mime_type = resource->info->r->content_type;
            else
              mime_type = "text/plain";

            if ((serr = svn_mime_type_validate(mime_type, scratch_pool)))
              {
                /* Probably serr->apr == SVN_ERR_BAD_MIME_TYPE, but
                   there's no point even checking.  No matter what the
                   error is, we can't claim to have a mime type for
                   this resource. */
                ap_log_rerror(APLOG_MARK, APLOG_WARNING, serr->apr_err, 
                              resource->info->r, "%s", serr->message);
                svn_error_clear(serr);
                return DAV_PROP_INSERT_NOTDEF;
              }
          }

        value = mime_type;
        break;
      }

    case DAV_PROPID_getetag:
      if (resource->type == DAV_RESOURCE_TYPE_PRIVATE
          && (resource->info->restype == DAV_SVN_RESTYPE_VCC
              || resource->info->restype == DAV_SVN_RESTYPE_ME))
        {
          return DAV_PROP_INSERT_NOTSUPP;
        }

      value = dav_svn__getetag(resource, scratch_pool);
      break;

    case DAV_PROPID_auto_version:
      /* we only support one autoversioning behavior, and thus only
         return this one static value; someday when we support
         locking, there are other possible values/behaviors for this. */
      if (resource->info->repos->autoversioning)
        value = "DAV:checkout-checkin";
      else
        return DAV_PROP_INSERT_NOTDEF;
      break;

    case DAV_PROPID_baseline_collection:
      /* only defined for Baselines */
      /* ### whoops. also defined for a VCC. deal with it later. */
      if (resource->type != DAV_RESOURCE_TYPE_VERSION || !resource->baselined)
        return DAV_PROP_INSERT_NOTSUPP;
      value = dav_svn__build_uri(resource->info->repos, DAV_SVN__BUILD_URI_BC,
                                 resource->info->root.rev, NULL,
                                 1 /* add_href */, scratch_pool);
      break;

    case DAV_PROPID_checked_in:
      /* only defined for VCRs (in the public space and in a BC space) */
      /* ### note that a VCC (a special VCR) is defined as _PRIVATE for now */
      if (resource->type == DAV_RESOURCE_TYPE_PRIVATE
          && (resource->info->restype == DAV_SVN_RESTYPE_VCC
              || resource->info->restype == DAV_SVN_RESTYPE_ME))
        {
          svn_revnum_t revnum;

          serr = svn_fs_youngest_rev(&revnum, resource->info->repos->fs,
                                     scratch_pool);
          if (serr != NULL)
            {
              /* ### what to do? */
              svn_error_clear(serr);
              value = "###error###";
              break;
            }
          s = dav_svn__build_uri(resource->info->repos,
                                 DAV_SVN__BUILD_URI_BASELINE,
                                 revnum, NULL, 0 /* add_href */, scratch_pool);
          value = apr_psprintf(scratch_pool, "<D:href>%s</D:href>",
                               apr_xml_quote_string(scratch_pool, s, 1));
        }
      else if (resource->type != DAV_RESOURCE_TYPE_REGULAR)
        {
          /* not defined for this resource type */
          return DAV_PROP_INSERT_NOTSUPP;
        }
      else
        {
          svn_revnum_t rev_to_use =
            dav_svn__get_safe_cr(resource->info->root.root,
                                 resource->info->repos_path, scratch_pool);

          s = dav_svn__build_uri(resource->info->repos,
                                 DAV_SVN__BUILD_URI_VERSION,
                                 rev_to_use, resource->info->repos_path,
                                0 /* add_href */, scratch_pool);
          value = apr_psprintf(scratch_pool, "<D:href>%s</D:href>",
                               apr_xml_quote_string(scratch_pool, s, 1));
        }
      break;

    case DAV_PROPID_version_controlled_configuration:
      /* only defined for VCRs */
      /* ### VCRs within the BC should not have this property! */
      /* ### note that a VCC (a special VCR) is defined as _PRIVATE for now */
      if (resource->type != DAV_RESOURCE_TYPE_REGULAR)
        return DAV_PROP_INSERT_NOTSUPP;
      value = dav_svn__build_uri(resource->info->repos, DAV_SVN__BUILD_URI_VCC,
                                 SVN_IGNORED_REVNUM, NULL,
                                 1 /* add_href */, scratch_pool);
      break;

    case DAV_PROPID_version_name:
      /* only defined for Version Resources and Baselines */
      /* ### whoops. also defined for VCRs. deal with it later. */
      if ((resource->type != DAV_RESOURCE_TYPE_VERSION)
          && (! resource->versioned))
        return DAV_PROP_INSERT_NOTSUPP;

      if (resource->type == DAV_RESOURCE_TYPE_PRIVATE
          && (resource->info->restype == DAV_SVN_RESTYPE_VCC
              || resource->info->restype == DAV_SVN_RESTYPE_ME))
        {
          return DAV_PROP_INSERT_NOTSUPP;
        }

      if (resource->baselined)
        {
          /* just the revision number for baselines */
          value = apr_psprintf(scratch_pool, "%ld",
                               resource->info->root.rev);
        }
      else
        {
          svn_revnum_t committed_rev = SVN_INVALID_REVNUM;

          /* Get the CR field out of the node's skel.  Notice that the
             root object might be an ID root -or- a revision root. */
          serr = svn_fs_node_created_rev(&committed_rev,
                                         resource->info->root.root,
                                         resource->info->repos_path,
                                         scratch_pool);
          if (serr != NULL)
            {
              /* ### what to do? */
              svn_error_clear(serr);
              value = "###error###";
              break;
            }

          /* Convert the revision into a quoted string */
          s = apr_psprintf(scratch_pool, "%ld", committed_rev);
          value = apr_xml_quote_string(scratch_pool, s, 1);
        }
      break;

    case SVN_PROPID_baseline_relative_path:
      /* only defined for VCRs */
      /* ### VCRs within the BC should not have this property! */
      /* ### note that a VCC (a special VCR) is defined as _PRIVATE for now */
      if (resource->type != DAV_RESOURCE_TYPE_REGULAR)
        return DAV_PROP_INSERT_NOTSUPP;

      /* drop the leading slash, so it is relative */
      s = resource->info->repos_path + 1;
      value = apr_xml_quote_string(scratch_pool, s, 1);
      break;

    case SVN_PROPID_md5_checksum:
      if ((! resource->collection)
          && (! resource->baselined)
          && (resource->type == DAV_RESOURCE_TYPE_REGULAR
              || resource->type == DAV_RESOURCE_TYPE_WORKING
              || resource->type == DAV_RESOURCE_TYPE_VERSION))
        {
          svn_checksum_t *checksum;

          serr = svn_fs_file_checksum(&checksum, svn_checksum_md5,
                                      resource->info->root.root,
                                      resource->info->repos_path, TRUE,
                                      scratch_pool);
          if (serr != NULL)
            {
              /* ### what to do? */
              svn_error_clear(serr);
              value = "###error###";
              break;
            }

          value = svn_checksum_to_cstring(checksum, scratch_pool);

          if (! value)
            return DAV_PROP_INSERT_NOTSUPP;
        }
      else
        return DAV_PROP_INSERT_NOTSUPP;

      break;

    case SVN_PROPID_repository_uuid:
      serr = svn_fs_get_uuid(resource->info->repos->fs, &value, scratch_pool);
      if (serr != NULL)
        {
          /* ### what to do? */
          svn_error_clear(serr);
          value = "###error###";
          break;
        }
      break;

    case SVN_PROPID_deadprop_count:
      {
        unsigned int propcount;
        apr_hash_t *proplist;

        if (resource->type != DAV_RESOURCE_TYPE_REGULAR)
          return DAV_PROP_INSERT_NOTSUPP;

        serr = svn_fs_node_proplist(&proplist,
                                    resource->info->root.root,
                                    resource->info->repos_path, scratch_pool);
        if (serr != NULL)
          {
            /* ### what to do? */
            svn_error_clear(serr);
            value = "###error###";
            break;
          }

        propcount = apr_hash_count(proplist);
        value = apr_psprintf(scratch_pool, "%u", propcount);
        break;
      }

    default:
      /* ### what the heck was this property? */
      return DAV_PROP_INSERT_NOTDEF;
    }

  /* assert: value != NULL */

  /* get the information and global NS index for the property */
  global_ns = dav_get_liveprop_info(propid, &dav_svn__liveprop_group, &info);

  /* assert: info != NULL && info->name != NULL */

  if (what == DAV_PROP_INSERT_NAME
      || (what == DAV_PROP_INSERT_VALUE && *value == '\0')) {
    s = apr_psprintf(result_pool, "<lp%d:%s/>" DEBUG_CR, global_ns,
                     info->name);
  }
  else if (what == DAV_PROP_INSERT_VALUE) {
    s = apr_psprintf(result_pool, "<lp%d:%s>%s</lp%d:%s>" DEBUG_CR,
                     global_ns, info->name, value, global_ns, info->name);
  }
  else {
    /* assert: what == DAV_PROP_INSERT_SUPPORTED */
    s = apr_psprintf(result_pool,
                     "<D:supported-live-property D:name=\"%s\" "
                     "D:namespace=\"%s\"/>" DEBUG_CR,
                     info->name, namespace_uris[info->ns]);
  }
  apr_text_append(result_pool, phdr, s);

  /* we inserted whatever was asked for */
  return what;
}
Пример #20
0
dav_error *dav_repos_deliver_acl_principal_prop_set(request_rec * r,
						    const dav_resource *
						    resource,
						    const apr_xml_doc *
						    doc,
						    ap_filter_t * output)
{
    /* this buffers the output for a bit and is automatically flushed,
       at appropriate times, by the Apache filter system. */
    apr_bucket_brigade *bb;

    apr_pool_t *pool = resource->pool;
    dav_repos_db *db = resource->info->db;
    dav_repos_resource *db_r = (dav_repos_resource *) resource->info->db_r;
    apr_xml_elem *props;
    dav_repos_resource *principals = NULL;

    TRACE();

    props = dav_find_child(doc->root, "prop");

    dbms_get_principals(db, pool, db_r, principals);

    bb = apr_brigade_create(pool, output->c->bucket_alloc);
    r->status = HTTP_MULTI_STATUS;
    send_xml(bb, output, "<D:multistatus xmlns:D=\"DAV:\">" DEBUG_CR);

    while (principals != NULL) {
	sabridge_get_property(db, principals);
	dav_repos_build_lpr_hash(principals);
	send_xml(bb, output, "<D:response>");
	send_xml(bb, output, dav_repos_mk_href(pool, principals->uri));
	send_xml(bb, output, "<D:propstat>");
	send_xml(bb, output, "<D:prop>");
	for (props = props->first_child; props; props = props->next) {
	    const char *val;
	    val =
		apr_hash_get(principals->lpr_hash, props->name,
			     APR_HASH_KEY_STRING);
	    const char *str =
		apr_psprintf(pool, "<D:%s>%s</D:%s>" DEBUG_CR,
			     props->name, apr_xml_quote_string(pool, val, 0), 
                             props->name);
	    send_xml(bb, output, str);
	}

	send_xml(bb, output, "</D:prop>");
	send_xml(bb, output,
		 "<D:status>HTTP/1.1 200 OK</D:status>" DEBUG_CR);

	send_xml(bb, output, "</D:propstat>");
	send_xml(bb, output, "</D:response>");

	principals = principals->next;
    }

    send_xml(bb, output, "</D:multistatus>");

    /* flush the contents of the brigade */
    ap_fflush(output, bb);

    return NULL;

}
svn_error_t *
svn_ra_neon__get_location_segments(svn_ra_session_t *session,
                                   const char *path,
                                   svn_revnum_t peg_revision,
                                   svn_revnum_t start_rev,
                                   svn_revnum_t end_rev,
                                   svn_location_segment_receiver_t receiver,
                                   void *receiver_baton,
                                   apr_pool_t *pool)

{
  svn_ra_neon__session_t *ras = session->priv;
  svn_stringbuf_t *request_body;
  svn_error_t *err;
  get_location_segments_baton_t request_baton;
  const char *bc_url;
  const char *bc_relative;
  const char *bc;
  int status_code = 0;
  apr_pool_t *subpool = svn_pool_create(pool);

  /* Build the request body. */
  request_body = svn_stringbuf_create("", subpool);
  svn_stringbuf_appendcstr(request_body,
                           "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
                           DEBUG_CR "<S:get-location-segments xmlns:S=\""
                           SVN_XML_NAMESPACE "\" xmlns:D=\"DAV:\">" DEBUG_CR);

  /* Tack on the path... */
  svn_stringbuf_appendcstr(request_body, "<S:path>");
  svn_stringbuf_appendcstr(request_body, apr_xml_quote_string(subpool, path, 0));
  svn_stringbuf_appendcstr(request_body, "</S:path>" DEBUG_CR);

  /* ...and maybe a peg revision... */
  if (SVN_IS_VALID_REVNUM(peg_revision))
    svn_stringbuf_appendcstr
      (request_body, apr_psprintf(subpool,
                                  "<S:peg-revision>%ld</S:peg-revision>"
                                  DEBUG_CR, peg_revision));

  /* ...and maybe a start revision... */
  if (SVN_IS_VALID_REVNUM(start_rev))
    svn_stringbuf_appendcstr
      (request_body, apr_psprintf(subpool,
                                  "<S:start-revision>%ld</S:start-revision>"
                                  DEBUG_CR, start_rev));

  /* ...and maybe an end revision. */
  if (SVN_IS_VALID_REVNUM(end_rev))
    svn_stringbuf_appendcstr
      (request_body, apr_psprintf(subpool,
                                  "<S:end-revision>%ld</S:end-revision>"
                                  DEBUG_CR, end_rev));

  svn_stringbuf_appendcstr(request_body, "</S:get-location-segments>");

  request_baton.receiver = receiver;
  request_baton.receiver_baton = receiver_baton;
  request_baton.subpool = svn_pool_create(subpool);

  /* ras's URL may not exist in HEAD, and thus it's not safe to send
     it as the main argument to the REPORT request; it might cause
     dav_get_resource() to choke on the server.  So instead, we pass a
     baseline-collection URL, which we get from the PEG_REVISION.  */
  SVN_ERR(svn_ra_neon__get_baseline_info(&bc_url, &bc_relative, NULL, ras,
                                         ras->url->data, peg_revision,
                                         subpool));
  bc = svn_path_url_add_component2(bc_url, bc_relative, subpool);

  err = svn_ra_neon__parsed_request(ras, "REPORT", bc,
                                    request_body->data, NULL, NULL,
                                    gls_start_element, NULL, NULL,
                                    &request_baton, NULL, &status_code,
                                    FALSE, subpool);
  svn_pool_destroy(request_baton.subpool);
  svn_pool_destroy(subpool);

  /* Map status 501: Method Not Implemented to our not implemented error.
     1.0.x servers and older don't support this report. */
  if (status_code == 501)
    return svn_error_createf(SVN_ERR_RA_NOT_IMPLEMENTED, err,
                             _("'%s' REPORT not implemented"),
                             "get-location-segments");

  return err;
}
Пример #22
0
dav_error *
dav_svn__get_inherited_props_report(const dav_resource *resource,
                                    const apr_xml_doc *doc,
                                    ap_filter_t *output)
{
  svn_error_t *serr;
  dav_error *derr = NULL;
  apr_xml_elem *child;
  apr_array_header_t *inherited_props;
  dav_svn__authz_read_baton arb;
  int ns;
  apr_bucket_brigade *bb;
  const char *path = "/";
  svn_fs_root_t *root;
  int i;
  svn_revnum_t rev = SVN_INVALID_REVNUM;
  apr_pool_t *iterpool;

  /* Sanity check. */
  if (!resource->info->repos_path)
    return dav_svn__new_error(resource->pool, HTTP_BAD_REQUEST, 0,
                              "The request does not specify a repository path");
  ns = dav_svn__find_ns(doc->namespaces, SVN_XML_NAMESPACE);
  if (ns == -1)
    {
      return dav_svn__new_error_svn(resource->pool, HTTP_BAD_REQUEST, 0,
                                    "The request does not contain the 'svn:' "
                                    "namespace, so it is not going to have "
                                    "certain required elements");
    }

  iterpool = svn_pool_create(resource->pool);

  for (child = doc->root->first_child;
       child != NULL;
       child = child->next)
    {
      /* if this element isn't one of ours, then skip it */
      if (child->ns != ns)
        continue;

      if (strcmp(child->name, SVN_DAV__REVISION) == 0)
        {
          rev = SVN_STR_TO_REV(dav_xml_get_cdata(child, iterpool, 1));
        }
      else if (strcmp(child->name, SVN_DAV__PATH) == 0)
        {
          path = dav_xml_get_cdata(child, resource->pool, 0);
          if ((derr = dav_svn__test_canonical(path, iterpool)))
            return derr;
          path = svn_fspath__join(resource->info->repos_path, path,
                                  resource->pool);
        }
      /* else unknown element; skip it */
    }

  /* Build authz read baton */
  arb.r = resource->info->r;
  arb.repos = resource->info->repos;

  /* Build inherited property brigade */
  bb = apr_brigade_create(resource->pool, output->c->bucket_alloc);

  serr = svn_fs_revision_root(&root, resource->info->repos->fs,
                              rev, resource->pool);
  if (serr != NULL)
    return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                "couldn't retrieve revision root",
                                resource->pool);

  serr = svn_repos_fs_get_inherited_props(&inherited_props, root, path, NULL,
                                          dav_svn__authz_read_func(&arb),
                                          &arb, resource->pool, iterpool);
  if (serr)
    {
      derr = dav_svn__convert_err(serr, HTTP_BAD_REQUEST, NULL,
                                  resource->pool);
      goto cleanup;
    }

  serr = dav_svn__brigade_puts(bb, output,
                               DAV_XML_HEADER DEBUG_CR
                               "<S:" SVN_DAV__INHERITED_PROPS_REPORT " "
                               "xmlns:S=\"" SVN_XML_NAMESPACE "\" "
                               "xmlns:D=\"DAV:\">" DEBUG_CR);
  if (serr)
    {
      derr = dav_svn__convert_err(serr, HTTP_BAD_REQUEST, NULL,
                                  resource->pool);
      goto cleanup;
    }

  for (i = 0; i < inherited_props->nelts; i++)
    {
      svn_prop_inherited_item_t *elt =
        APR_ARRAY_IDX(inherited_props, i, svn_prop_inherited_item_t *);

      svn_pool_clear(iterpool);

      serr = dav_svn__brigade_printf(
        bb, output,
        "<S:" SVN_DAV__IPROP_ITEM ">"
        DEBUG_CR
        "<S:" SVN_DAV__IPROP_PATH ">%s</S:" SVN_DAV__IPROP_PATH ">"
        DEBUG_CR,
        apr_xml_quote_string(resource->pool, elt->path_or_url, 0));

      if (!serr)
        {
          apr_hash_index_t *hi;

          for (hi = apr_hash_first(resource->pool, elt->prop_hash);
               hi;
               hi = apr_hash_next(hi))
            {
              const char *propname = apr_hash_this_key(hi);
              svn_string_t *propval = apr_hash_this_val(hi);
              const char *xml_safe;

              serr = dav_svn__brigade_printf(
                bb, output,
                "<S:" SVN_DAV__IPROP_PROPNAME ">%s</S:"
                SVN_DAV__IPROP_PROPNAME ">" DEBUG_CR,
                apr_xml_quote_string(iterpool, propname, 0));

              if (!serr)
                {
                  if (svn_xml_is_xml_safe(propval->data, propval->len))
                    {
                      svn_stringbuf_t *tmp = NULL;
                      svn_xml_escape_cdata_string(&tmp, propval,
                                                  iterpool);
                      xml_safe = tmp->data;
                      serr = dav_svn__brigade_printf(
                        bb, output,
                        "<S:" SVN_DAV__IPROP_PROPVAL ">%s</S:"
                        SVN_DAV__IPROP_PROPVAL ">" DEBUG_CR, xml_safe);
                    }
                  else
                    {
                      xml_safe = svn_base64_encode_string2(
                        propval, TRUE, iterpool)->data;
                      serr = dav_svn__brigade_printf(
                        bb, output,
                        "<S:" SVN_DAV__IPROP_PROPVAL
                        " encoding=\"base64\"" ">%s</S:"
                        SVN_DAV__IPROP_PROPVAL ">" DEBUG_CR, xml_safe);
                    }
                }

              if (serr)
                break;
            }
          if (!serr)
            serr = dav_svn__brigade_printf(bb, output,
                                           "</S:" SVN_DAV__IPROP_ITEM ">"
                                           DEBUG_CR);
        }

      if (serr)
        {
          derr = dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                      "Error ending REPORT response.",
                                      resource->pool);
          goto cleanup;
        }
    }

  if ((serr = dav_svn__brigade_puts(bb, output,
                                    "</S:" SVN_DAV__INHERITED_PROPS_REPORT ">"
                                    DEBUG_CR)))
    {
      derr = dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                  "Error ending REPORT response.",
                                  resource->pool);
      goto cleanup;
    }

 cleanup:

  /* Log this 'high level' svn action. */
  dav_svn__operational_log(resource->info,
                           svn_log__get_inherited_props(path, rev,
                                                        resource->pool));
  svn_pool_destroy(iterpool);
  return dav_svn__final_flush_or_error(resource->info->r, bb, output,
                                       derr, resource->pool);
}
Пример #23
0
/* This implements `svn_log_entry_receiver_t'.
   BATON is a `struct log_receiver_baton *'.  */
static svn_error_t *
log_receiver(void *baton,
             svn_log_entry_t *log_entry,
             apr_pool_t *pool)
{
  struct log_receiver_baton *lrb = baton;
  apr_pool_t *iterpool = svn_pool_create(pool);

  SVN_ERR(maybe_send_header(lrb));

  if (log_entry->revision == SVN_INVALID_REVNUM)
    {
      /* If the stack depth is zero, we've seen the last revision, so don't
         send it, just return.  The footer will be sent later. */
      if (lrb->stack_depth == 0)
        return SVN_NO_ERROR;
      else
        lrb->stack_depth--;
    }

  SVN_ERR(dav_svn__brigade_printf(lrb->bb, lrb->output,
                                  "<S:log-item>" DEBUG_CR "<D:version-name>%ld"
                                  "</D:version-name>" DEBUG_CR,
                                  log_entry->revision));

  if (log_entry->revprops)
    {
      apr_hash_index_t *hi;
      for (hi = apr_hash_first(pool, log_entry->revprops);
           hi != NULL;
           hi = apr_hash_next(hi))
        {
          char *name;
          void *val;
          const svn_string_t *value;
          const char *encoding_str = "";

          svn_pool_clear(iterpool);
          apr_hash_this(hi, (void *)&name, NULL, &val);
          value = val;

          /* If the client is okay with us encoding binary (or really,
             any non-XML-safe) property values, do so as necessary. */
          if (lrb->encode_binary_props)
            {
              if (! svn_xml_is_xml_safe(value->data, value->len))
                {
                  value = svn_base64_encode_string2(value, TRUE, iterpool);
                  encoding_str = " encoding=\"base64\"";
                }
            }

          if (strcmp(name, SVN_PROP_REVISION_AUTHOR) == 0)
            SVN_ERR(dav_svn__brigade_printf
                    (lrb->bb, lrb->output,
                     "<D:creator-displayname%s>%s</D:creator-displayname>"
                     DEBUG_CR, encoding_str,
                     apr_xml_quote_string(iterpool, value->data, 0)));
          else if (strcmp(name, SVN_PROP_REVISION_DATE) == 0)
            /* ### this should be DAV:creation-date, but we need to format
               ### that date a bit differently */
            SVN_ERR(dav_svn__brigade_printf
                    (lrb->bb, lrb->output,
                     "<S:date%s>%s</S:date>" DEBUG_CR, encoding_str,
                     apr_xml_quote_string(iterpool, value->data, 0)));
          else if (strcmp(name, SVN_PROP_REVISION_LOG) == 0)
            SVN_ERR(dav_svn__brigade_printf
                    (lrb->bb, lrb->output,
                     "<D:comment%s>%s</D:comment>" DEBUG_CR, encoding_str,
                     apr_xml_quote_string(pool,
                                          svn_xml_fuzzy_escape(value->data,
                                                               iterpool), 0)));
          else
            SVN_ERR(dav_svn__brigade_printf
                    (lrb->bb, lrb->output,
                     "<S:revprop name=\"%s\"%s>%s</S:revprop>" DEBUG_CR,
                     apr_xml_quote_string(iterpool, name, 0), encoding_str,
                     apr_xml_quote_string(iterpool, value->data, 0)));
        }
    }

  if (log_entry->has_children)
    {
      SVN_ERR(dav_svn__brigade_puts(lrb->bb, lrb->output, "<S:has-children/>"));
      lrb->stack_depth++;
    }

  if (log_entry->subtractive_merge)
    SVN_ERR(dav_svn__brigade_puts(lrb->bb, lrb->output,
                                  "<S:subtractive-merge/>"));

  if (log_entry->changed_paths2)
    {
      apr_hash_index_t *hi;
      char *path;

      for (hi = apr_hash_first(pool, log_entry->changed_paths2);
           hi != NULL;
           hi = apr_hash_next(hi))
        {
          void *val;
          svn_log_changed_path2_t *log_item;
          const char *close_element = NULL;

          svn_pool_clear(iterpool);
          apr_hash_this(hi, (void *) &path, NULL, &val);
          log_item = val;

          /* ### todo: is there a D: namespace equivalent for
             `changed-path'?  Should use it if so. */
          switch (log_item->action)
            {
            case 'A':
              if (log_item->copyfrom_path
                  && SVN_IS_VALID_REVNUM(log_item->copyfrom_rev))
                SVN_ERR(dav_svn__brigade_printf
                        (lrb->bb, lrb->output,
                         "<S:added-path copyfrom-path=\"%s\""
                         " copyfrom-rev=\"%ld\"",
                         apr_xml_quote_string(iterpool,
                                              log_item->copyfrom_path,
                                              1), /* escape quotes */
                         log_item->copyfrom_rev));
              else
                SVN_ERR(dav_svn__brigade_puts(lrb->bb, lrb->output,
                                              "<S:added-path"));

              close_element = "S:added-path";
              break;

            case 'R':
              if (log_item->copyfrom_path
                  && SVN_IS_VALID_REVNUM(log_item->copyfrom_rev))
                SVN_ERR(dav_svn__brigade_printf
                        (lrb->bb, lrb->output,
                         "<S:replaced-path copyfrom-path=\"%s\""
                         " copyfrom-rev=\"%ld\"",
                         apr_xml_quote_string(iterpool,
                                              log_item->copyfrom_path,
                                              1), /* escape quotes */
                         log_item->copyfrom_rev));
              else
                SVN_ERR(dav_svn__brigade_puts(lrb->bb, lrb->output,
                                              "<S:replaced-path"));

              close_element = "S:replaced-path";
              break;

            case 'D':
              SVN_ERR(dav_svn__brigade_puts(lrb->bb, lrb->output,
                                            "<S:deleted-path"));
              close_element = "S:deleted-path";
              break;

            case 'M':
              SVN_ERR(dav_svn__brigade_puts(lrb->bb, lrb->output,
                                            "<S:modified-path"));
              close_element = "S:modified-path";
              break;

            default:
              break;
            }

          /* If we need to close the element, then send the attributes
             that apply to all changed items and then close the element. */
          if (close_element)
            SVN_ERR(dav_svn__brigade_printf
                    (lrb->bb, lrb->output,
                     " node-kind=\"%s\""
                     " text-mods=\"%s\""
                     " prop-mods=\"%s\">%s</%s>" DEBUG_CR,
                     svn_node_kind_to_word(log_item->node_kind),
                     svn_tristate__to_word(log_item->text_modified),
                     svn_tristate__to_word(log_item->props_modified),
                     apr_xml_quote_string(iterpool, path, 0),
                     close_element));
        }
    }

  svn_pool_destroy(iterpool);

  SVN_ERR(dav_svn__brigade_puts(lrb->bb, lrb->output,
                                "</S:log-item>" DEBUG_CR));

  return SVN_NO_ERROR;
}
Пример #24
0
static void start_handler(void *userdata, const char *name, const char **attrs)
{
    apr_xml_parser *parser = userdata;
    apr_xml_elem *elem;
    apr_xml_attr *attr;
    apr_xml_attr *prev;
    char *colon;
    const char *quoted;
    char *elem_name;

    /* punt once we find an error */
    if (parser->error)
        return;

    elem = apr_pcalloc(parser->p, sizeof(*elem));

    /* prep the element */
    elem->name = elem_name = apr_pstrdup(parser->p, name);

    /* fill in the attributes (note: ends up in reverse order) */
    while (*attrs) {
        attr = apr_palloc(parser->p, sizeof(*attr));
        attr->name = apr_pstrdup(parser->p, *attrs++);
        attr->value = apr_pstrdup(parser->p, *attrs++);
        attr->next = elem->attr;
        elem->attr = attr;
    }

    /* hook the element into the tree */
    if (parser->cur_elem == NULL) {
        /* no current element; this also becomes the root */
        parser->cur_elem = parser->doc->root = elem;
    }
    else {
        /* this element appeared within the current elem */
        elem->parent = parser->cur_elem;

        /* set up the child/sibling links */
        if (elem->parent->last_child == NULL) {
            /* no first child either */
            elem->parent->first_child = elem->parent->last_child = elem;
        }
        else {
            /* hook onto the end of the parent's children */
            elem->parent->last_child->next = elem;
            elem->parent->last_child = elem;
        }

        /* this element is now the current element */
        parser->cur_elem = elem;
    }

    /* scan the attributes for namespace declarations */
    for (prev = NULL, attr = elem->attr;
            attr;
            attr = attr->next) {
        if (strncmp(attr->name, APR_KW_xmlns, 5) == 0) {
            const char *prefix = &attr->name[5];
            apr_xml_ns_scope *ns_scope;

            /* test for xmlns:foo= form and xmlns= form */
            if (*prefix == 0x3A) {
                /* a namespace prefix declaration must have a
                   non-empty value. */
                if (attr->value[0] == '\0') {
                    parser->error = APR_XML_NS_ERROR_INVALID_DECL;
                    return;
                }
                ++prefix;
            }
            else if (*prefix != '\0') {
                /* advance "prev" since "attr" is still present */
                prev = attr;
                continue;
            }

            /* quote the URI before we ever start working with it */
            quoted = apr_xml_quote_string(parser->p, attr->value, 1);

            /* build and insert the new scope */
            ns_scope = apr_pcalloc(parser->p, sizeof(*ns_scope));
            ns_scope->prefix = prefix;
            ns_scope->ns = apr_xml_insert_uri(parser->doc->namespaces, quoted);
            ns_scope->emptyURI = *quoted == '\0';
            ns_scope->next = elem->ns_scope;
            elem->ns_scope = ns_scope;

            /* remove this attribute from the element */
            if (prev == NULL)
                elem->attr = attr->next;
            else
                prev->next = attr->next;

            /* Note: prev will not be advanced since we just removed "attr" */
        }
        else if (strcmp(attr->name, APR_KW_xmlns_lang) == 0) {
            /* save away the language (in quoted form) */
            elem->lang = apr_xml_quote_string(parser->p, attr->value, 1);

            /* remove this attribute from the element */
            if (prev == NULL)
                elem->attr = attr->next;
            else
                prev->next = attr->next;

            /* Note: prev will not be advanced since we just removed "attr" */
        }
        else {
            /* advance "prev" since "attr" is still present */
            prev = attr;
        }
    }

    /*
    ** If an xml:lang attribute didn't exist (lang==NULL), then copy the
    ** language from the parent element (if present).
    **
    ** NOTE: elem_size() *depends* upon this pointer equality.
    */
    if (elem->lang == NULL && elem->parent != NULL)
        elem->lang = elem->parent->lang;

    /* adjust the element's namespace */
    colon = strchr(elem_name, 0x3A);
    if (colon == NULL) {
        /*
         * The element is using the default namespace, which will always
         * be found. Either it will be "no namespace", or a default
         * namespace URI has been specified at some point.
         */
        elem->ns = find_prefix(parser, "");
    }
    else if (APR_XML_NS_IS_RESERVED(elem->name)) {
        elem->ns = APR_XML_NS_NONE;
    }
    else {
        *colon = '\0';
        elem->ns = find_prefix(parser, elem->name);
        elem->name = colon + 1;

        if (APR_XML_NS_IS_ERROR(elem->ns)) {
            parser->error = elem->ns;
            return;
        }
    }

    /* adjust all remaining attributes' namespaces */
    for (attr = elem->attr; attr; attr = attr->next) {
        /*
         * apr_xml_attr defines this as "const" but we dup'd it, so we
         * know that we can change it. a bit hacky, but the existing
         * structure def is best.
         */
        char *attr_name = (char *)attr->name;

        colon = strchr(attr_name, 0x3A);
        if (colon == NULL) {
            /*
             * Attributes do NOT use the default namespace. Therefore,
             * we place them into the "no namespace" category.
             */
            attr->ns = APR_XML_NS_NONE;
        }
        else if (APR_XML_NS_IS_RESERVED(attr->name)) {
            attr->ns = APR_XML_NS_NONE;
        }
        else {
            *colon = '\0';
            attr->ns = find_prefix(parser, attr->name);
            attr->name = colon + 1;

            if (APR_XML_NS_IS_ERROR(attr->ns)) {
                parser->error = attr->ns;
                return;
            }
        }
    }
}
Пример #25
0
dav_error *dav_repos_deliver_principal_property_search(request_rec * r,
						       const dav_resource *
						       resource,
						       const apr_xml_doc *
						       doc,
						       ap_filter_t *
						       output)
{
    /* this buffers the output for a bit and is automatically flushed,
       at appropriate times, by the Apache filter system. */
    apr_bucket_brigade *bb;

    apr_pool_t *pool = resource->pool;
    dav_repos_db *db = resource->info->db;
    dav_repos_resource *db_r = (dav_repos_resource *) resource->info->db_r;
    apr_xml_elem *principal_property_search;
    apr_xml_elem *elem;
    apr_xml_elem *prop;
    apr_xml_elem *props;
    apr_xml_elem *match;
    int flag;

    TRACE();

    principal_property_search = dav_find_child(doc->root,
					       "principal-property-search");

    props = dav_find_child(doc->root, "prop");

    sabridge_get_collection_children(db, db_r, 1, "read",
                                     NULL, NULL, NULL);

    bb = apr_brigade_create(pool, output->c->bucket_alloc);
    r->status = HTTP_MULTI_STATUS;
    send_xml(bb, output, "<D:multistatus xmlns:D=\"DAV:\">" DEBUG_CR);

    while (db_r != NULL) {
	flag = 1;
	for (elem = principal_property_search->first_child;
	     elem && flag; elem = elem->next) {
	    if (!strcmp(elem->name, "property-search")) {
		prop = dav_find_child(elem, "prop");
		match = dav_find_child(elem, "match");
		dav_repos_build_lpr_hash(db_r);
		const char *val = apr_hash_get(db_r->lpr_hash,
					       prop->first_child->name,
					       APR_HASH_KEY_STRING);
		if (!strstr(val, match->first_cdata.first->text))
		    flag = 0;
	    }
	}
	if (flag) {
	    send_xml(bb, output, "<D:response>");
	    send_xml(bb, output,
		     dav_repos_mk_href(pool, db_r->uri));
	    send_xml(bb, output, "<D:propstat>");
	    send_xml(bb, output, "<D:prop>");
	    for (props = props->first_child; props; props = props->next) {
		const char *val;
		val =
		    apr_hash_get(db_r->lpr_hash, props->name,
				 APR_HASH_KEY_STRING);
		const char *str =
		    apr_psprintf(pool, "<D:%s>%s</D:%s>" DEBUG_CR,
				 props->name, 
                                 apr_xml_quote_string(pool, val, 0), 
                                 props->name);
		send_xml(bb, output, str);
	    }

	    send_xml(bb, output, "</D:prop>");
	    send_xml(bb, output,
		     "<D:status>HTTP/1.1 200 OK</D:status>" DEBUG_CR);

	    send_xml(bb, output, "</D:propstat>");
	    send_xml(bb, output, "</D:response>");
	}

	db_r = db_r->next;
    }

    send_xml(bb, output, "</D:multistatus>");

    /* flush the contents of the brigade */
    ap_fflush(output, bb);

    return NULL;
}
Пример #26
0
/* Request a mergeinfo-report from the URL attached to SESSION,
   and fill in the CATALOG with the results.  */
svn_error_t *
svn_ra_neon__get_mergeinfo(svn_ra_session_t *session,
                           svn_mergeinfo_catalog_t *catalog,
                           const apr_array_header_t *paths,
                           svn_revnum_t revision,
                           svn_mergeinfo_inheritance_t inherit,
                           svn_boolean_t include_descendants,
                           apr_pool_t *pool)
{
  svn_ra_neon__session_t *ras = session->priv;
  svn_stringbuf_t *request_body = svn_stringbuf_create("", pool);
  struct mergeinfo_baton mb;
  const char *bc_url;
  const char *bc_relative;
  const char *final_bc_url;

  static const char minfo_report_head[] =
    "<S:" SVN_DAV__MERGEINFO_REPORT " xmlns:S=\"" SVN_XML_NAMESPACE "\">"
    DEBUG_CR;

  static const char minfo_report_tail[] =
    "</S:" SVN_DAV__MERGEINFO_REPORT ">" DEBUG_CR;

  *catalog = NULL;

  /* Construct the request body. */
  svn_stringbuf_appendcstr(request_body, minfo_report_head);
  svn_stringbuf_appendcstr(request_body,
                           apr_psprintf(pool,
                                        "<S:revision>%ld"
                                        "</S:revision>", revision));
  svn_stringbuf_appendcstr(request_body,
                           apr_psprintf(pool,
                                        "<S:inherit>%s"
                                        "</S:inherit>",
                                        svn_inheritance_to_word(inherit)));

  if (include_descendants)
    {
      /* Send it only if true; server will default to "no". */
      svn_stringbuf_appendcstr(request_body,
                               "<S:include-descendants>yes"
                               "</S:include-descendants>");
    }

  if (paths)
    {
      int i;

      for (i = 0; i < paths->nelts; i++)
        {
          const char *this_path =
            apr_xml_quote_string(pool,
                                 ((const char **)paths->elts)[i],
                                 0);
          svn_stringbuf_appendcstr(request_body, "<S:path>");
          svn_stringbuf_appendcstr(request_body, this_path);
          svn_stringbuf_appendcstr(request_body, "</S:path>");
        }
    }

  svn_stringbuf_appendcstr(request_body, minfo_report_tail);

  mb.pool = pool;
  mb.curr_path = svn_stringbuf_create("", pool);
  mb.curr_info = svn_stringbuf_create("", pool);
  mb.catalog = apr_hash_make(pool);
  mb.err = SVN_NO_ERROR;

  /* ras's URL may not exist in HEAD, and thus it's not safe to send
     it as the main argument to the REPORT request; it might cause
     dav_get_resource() to choke on the server.  So instead, we pass a
     baseline-collection URL, which we get from END. */
  SVN_ERR(svn_ra_neon__get_baseline_info(&bc_url, &bc_relative, NULL, ras,
                                         ras->url->data, revision, pool));
  final_bc_url = svn_path_url_add_component2(bc_url, bc_relative, pool);

  SVN_ERR(svn_ra_neon__parsed_request(ras,
                                      "REPORT",
                                      final_bc_url,
                                      request_body->data,
                                      NULL, NULL,
                                      start_element,
                                      cdata_handler,
                                      end_element,
                                      &mb,
                                      NULL,
                                      NULL,
                                      FALSE,
                                      pool));

  if (mb.err == SVN_NO_ERROR && apr_hash_count(mb.catalog))
    *catalog = mb.catalog;

  return mb.err;
}
Пример #27
0
dav_error *
dav_svn__get_mergeinfo_report(const dav_resource *resource,
                              const apr_xml_doc *doc,
                              ap_filter_t *output)
{
  svn_error_t *serr;
  dav_error *derr = NULL;
  apr_xml_elem *child;
  svn_mergeinfo_catalog_t catalog;
  svn_boolean_t include_descendants = FALSE;
  dav_svn__authz_read_baton arb;
  const dav_svn_repos *repos = resource->info->repos;
  int ns;
  apr_bucket_brigade *bb;
  apr_hash_index_t *hi;

  /* These get determined from the request document. */
  svn_revnum_t rev = SVN_INVALID_REVNUM;
  /* By default look for explicit mergeinfo only. */
  svn_mergeinfo_inheritance_t inherit = svn_mergeinfo_explicit;
  apr_array_header_t *paths
    = apr_array_make(resource->pool, 0, sizeof(const char *));

  /* Sanity check. */
  if (!resource->info->repos_path)
    return dav_svn__new_error(resource->pool, HTTP_BAD_REQUEST, 0,
                              "The request does not specify a repository path");
  ns = dav_svn__find_ns(doc->namespaces, SVN_XML_NAMESPACE);
  if (ns == -1)
    {
      return dav_svn__new_error_tag(resource->pool, HTTP_BAD_REQUEST, 0,
                                    "The request does not contain the 'svn:' "
                                    "namespace, so it is not going to have "
                                    "certain required elements.",
                                    SVN_DAV_ERROR_NAMESPACE,
                                    SVN_DAV_ERROR_TAG);
    }

  for (child = doc->root->first_child; child != NULL; child = child->next)
    {
      /* if this element isn't one of ours, then skip it */
      if (child->ns != ns)
        continue;

      if (strcmp(child->name, SVN_DAV__REVISION) == 0)
        rev = SVN_STR_TO_REV(dav_xml_get_cdata(child, resource->pool, 1));
      else if (strcmp(child->name, SVN_DAV__INHERIT) == 0)
        {
          inherit = svn_inheritance_from_word(
            dav_xml_get_cdata(child, resource->pool, 1));
        }
      else if (strcmp(child->name, SVN_DAV__PATH) == 0)
        {
          const char *target;
          const char *rel_path = dav_xml_get_cdata(child, resource->pool, 0);
          if ((derr = dav_svn__test_canonical(rel_path, resource->pool)))
            return derr;

          /* Force REL_PATH to be a relative path, not an fspath. */
          rel_path = svn_relpath_canonicalize(rel_path, resource->pool);

          /* Append the REL_PATH to the base FS path to get an
             absolute repository path. */
          target = svn_fspath__join(resource->info->repos_path, rel_path,
                                    resource->pool);
          (*((const char **)(apr_array_push(paths)))) = target;
        }
      else if (strcmp(child->name, SVN_DAV__INCLUDE_DESCENDANTS) == 0)
        {
          const char *word = dav_xml_get_cdata(child, resource->pool, 1);
          if (strcmp(word, "yes") == 0)
            include_descendants = TRUE;
          /* Else the client isn't supposed to send anyway, so just
             leave it false. */
        }
      /* else unknown element; skip it */
    }

  /* Build authz read baton */
  arb.r = resource->info->r;
  arb.repos = resource->info->repos;

  /* Build mergeinfo brigade */
  bb = apr_brigade_create(resource->pool, output->c->bucket_alloc);

  serr = svn_repos_fs_get_mergeinfo(&catalog, repos->repos, paths, rev,
                                    inherit, include_descendants,
                                    dav_svn__authz_read_func(&arb),
                                    &arb, resource->pool);
  if (serr)
    {
      derr = dav_svn__convert_err(serr, HTTP_BAD_REQUEST, serr->message,
                                  resource->pool);
      goto cleanup;
    }

  serr = svn_mergeinfo__remove_prefix_from_catalog(&catalog, catalog,
                                                   resource->info->repos_path,
                                                   resource->pool);
  if (serr)
    {
      derr = dav_svn__convert_err(serr, HTTP_BAD_REQUEST, serr->message,
                                  resource->pool);
      goto cleanup;
    }

  /* Ideally, dav_svn__brigade_printf() would set a flag in bb (or rather,
     in r->sent_bodyct, see dav_method_report()), and ap_fflush()
     would not set that flag unless it actually sent something.  But
     we are condemned to live in another universe, so we must keep
     track ourselves of whether we've sent anything or not.  See the
     long comment after the 'cleanup' label for more details. */
  serr = dav_svn__brigade_puts(bb, output,
                               DAV_XML_HEADER DEBUG_CR
                               "<S:" SVN_DAV__MERGEINFO_REPORT " "
                               "xmlns:S=\"" SVN_XML_NAMESPACE "\" "
                               "xmlns:D=\"DAV:\">" DEBUG_CR);
  if (serr)
    {
      derr = dav_svn__convert_err(serr, HTTP_BAD_REQUEST, serr->message,
                                  resource->pool);
      goto cleanup;
    }

  for (hi = apr_hash_first(resource->pool, catalog); hi;
       hi = apr_hash_next(hi))
    {
      const void *key;
      void *value;
      const char *path;
      svn_mergeinfo_t mergeinfo;
      svn_string_t *mergeinfo_string;

      apr_hash_this(hi, &key, NULL, &value);
      path = key;
      mergeinfo = value;
      serr = svn_mergeinfo_to_string(&mergeinfo_string, mergeinfo,
                                     resource->pool);
      if (serr)
        {
          derr = dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                      "Error ending REPORT response.",
                                      resource->pool);
          goto cleanup;
        }
      serr = dav_svn__brigade_printf
        (bb, output,
         "<S:" SVN_DAV__MERGEINFO_ITEM ">"
         DEBUG_CR
         "<S:" SVN_DAV__MERGEINFO_PATH ">%s</S:" SVN_DAV__MERGEINFO_PATH ">"
         DEBUG_CR
         "<S:" SVN_DAV__MERGEINFO_INFO ">%s</S:" SVN_DAV__MERGEINFO_INFO ">"
         DEBUG_CR
         "</S:" SVN_DAV__MERGEINFO_ITEM ">",
         apr_xml_quote_string(resource->pool, path, 0),
         apr_xml_quote_string(resource->pool, mergeinfo_string->data, 0));
      if (serr)
        {
          derr = dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                      "Error ending REPORT response.",
                                      resource->pool);
          goto cleanup;
        }
    }

  if ((serr = dav_svn__brigade_puts(bb, output,
                                    "</S:" SVN_DAV__MERGEINFO_REPORT ">"
                                    DEBUG_CR)))
    {
      derr = dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                  "Error ending REPORT response.",
                                  resource->pool);
      goto cleanup;
    }

 cleanup:

  /* We've detected a 'high level' svn action to log. */
  dav_svn__operational_log(resource->info,
                           svn_log__get_mergeinfo(paths, inherit,
                                                  include_descendants,
                                                  resource->pool));

  return dav_svn__final_flush_or_error(resource->info->r, bb, output,
                                       derr, resource->pool);
}
svn_error_t *
svn_ra_neon__get_locations(svn_ra_session_t *session,
                           apr_hash_t **locations,
                           const char *relative_path,
                           svn_revnum_t peg_revision,
                           const apr_array_header_t *location_revisions,
                           apr_pool_t *pool)
{
  svn_ra_neon__session_t *ras = session->priv;
  svn_stringbuf_t *request_body;
  svn_error_t *err;
  get_locations_baton_t request_baton;
  const char *relative_path_quoted;
  const char *bc_url;
  const char *bc_relative;
  const char *final_bc_url;
  int i;
  int status_code = 0;

  *locations = apr_hash_make(pool);

  request_body = svn_stringbuf_create("", pool);
  svn_stringbuf_appendcstr(request_body,
                           "<?xml version=\"1.0\" encoding=\"utf-8\"?>" DEBUG_CR
                           "<S:get-locations xmlns:S=\"" SVN_XML_NAMESPACE
                           "\" xmlns:D=\"DAV:\">" DEBUG_CR);

  svn_stringbuf_appendcstr(request_body, "<S:path>");
  /* We need to escape the path XML-wise. */
  relative_path_quoted = apr_xml_quote_string(pool, relative_path, 0);
  svn_stringbuf_appendcstr(request_body, relative_path_quoted);
  svn_stringbuf_appendcstr(request_body, "</S:path>" DEBUG_CR);
  svn_stringbuf_appendcstr(request_body,
                           apr_psprintf(pool,
                                        "<S:peg-revision>%ld"
                                        "</S:peg-revision>" DEBUG_CR,
                                        peg_revision));

  for (i = 0; i < location_revisions->nelts; ++i)
    {
      svn_revnum_t rev = APR_ARRAY_IDX(location_revisions, i, svn_revnum_t);
      svn_stringbuf_appendcstr(request_body,
                               apr_psprintf(pool,
                                            "<S:location-revision>%ld"
                                            "</S:location-revision>" DEBUG_CR,
                                            rev));
    }

  svn_stringbuf_appendcstr(request_body, "</S:get-locations>");

  request_baton.ras = ras;
  request_baton.hash = *locations;
  request_baton.pool = pool;

  /* ras's URL may not exist in HEAD, and thus it's not safe to send
     it as the main argument to the REPORT request; it might cause
     dav_get_resource() to choke on the server.  So instead, we pass a
     baseline-collection URL, which we get from the peg revision.  */
  SVN_ERR(svn_ra_neon__get_baseline_info(&bc_url, &bc_relative, NULL, ras,
                                         ras->url->data, peg_revision, pool));
  final_bc_url = svn_path_url_add_component2(bc_url, bc_relative, pool);

  err = svn_ra_neon__parsed_request(ras, "REPORT", final_bc_url,
                                    request_body->data, NULL, NULL,
                                    gloc_start_element, NULL, NULL,
                                    &request_baton, NULL, &status_code,
                                    FALSE, pool);

  /* Map status 501: Method Not Implemented to our not implemented error.
     1.0.x servers and older don't support this report. */
  if (status_code == 501)
    return svn_error_createf(SVN_ERR_RA_NOT_IMPLEMENTED, err,
                             _("'%s' REPORT not implemented"), "get-locations");

  return err;
}
Пример #29
0
/* Helper func:  convert an svn_lock_t to a dav_lock, allocated in
   pool.  EXISTS_P indicates whether slock->path actually exists or not.
   If HIDE_AUTH_USER is set, then do not return the svn lock's 'owner'
   as dlock->auth_user.
 */
static void
svn_lock_to_dav_lock(dav_lock **dlock,
                     const svn_lock_t *slock,
                     svn_boolean_t hide_auth_user,
                     svn_boolean_t exists_p,
                     apr_pool_t *pool)
{
  dav_lock *lock = apr_pcalloc(pool, sizeof(*lock));
  dav_locktoken *token = apr_pcalloc(pool, sizeof(*token));

  lock->rectype = DAV_LOCKREC_DIRECT;
  lock->scope = DAV_LOCKSCOPE_EXCLUSIVE;
  lock->type = DAV_LOCKTYPE_WRITE;
  lock->depth = 0;
  lock->is_locknull = exists_p;

  token->uuid_str = apr_pstrdup(pool, slock->token);
  lock->locktoken = token;

  /* the svn_lock_t 'comment' field maps to the 'DAV:owner' field. */
  if (slock->comment)
    {
      if (! slock->is_dav_comment)
        {
          /* This comment was originally given to us by an svn client,
             so, we need to wrap the naked comment with <DAV:owner>,
             and xml-escape it for safe transport, lest we send back
             an invalid http response.  (mod_dav won't do it for us,
             because it assumes that it personally created every lock
             in the repository.) */
          lock->owner = apr_pstrcat(pool,
                                    "<D:owner xmlns:D=\"DAV:\">",
                                    apr_xml_quote_string(pool,
                                                         slock->comment, 1),
                                    "</D:owner>", (char *)NULL);
        }
      else
        {
          lock->owner = apr_pstrdup(pool, slock->comment);
        }
    }
  else
    lock->owner = NULL;

  /* the svn_lock_t 'owner' is the actual authenticated owner of the
     lock, and maps to the 'auth_user' field in the mod_dav lock. */

  /* (If the client ran 'svn unlock --force', then we don't want to
     return lock->auth_user.  Otherwise mod_dav will throw an error
     when lock->auth_user and r->user don't match.) */
  if (! hide_auth_user)
    lock->auth_user = apr_pstrdup(pool, slock->owner);

  /* This is absurd.  apr_time.h has an apr_time_t->time_t func,
     but not the reverse?? */
  if (slock->expiration_date)
    lock->timeout = (time_t) (slock->expiration_date / APR_USEC_PER_SEC);
  else
    lock->timeout = DAV_TIMEOUT_INFINITE;

  *dlock = lock;
}
Пример #30
0
/** 
 * Returns the propfind XML output for a acl. 
 * @param resource The resource an which the action should be taken.  
 * @return The string with the xml code for the propfind response. 
 */
char *acl_build_propfind_output(const dav_resource * resource)
{
    char *str_xml_acl = "";
    dav_acl *current_acl = NULL;
    dav_repos_resource *db_r;
    request_rec *r = resource->info->rec;
    dav_repos_db *db;
    TRACE();
    if (!resource) {
	return str_xml_acl;
    }
    db = resource->info->db;
    db_r = (dav_repos_resource *) resource->info->db_r;
    current_acl = (*dav_repos_hooks_acl.get_current_acl) (resource);
    if (current_acl) {
	dav_ace_iterator *iter;
	iter = dav_acl_iterate(current_acl);
	while (dav_ace_iterator_more(iter)) {
	    const dav_ace *ace = dav_ace_iterator_next(iter);
	    const dav_principal *ace_principal = dav_get_ace_principal(ace);
            const dav_prop_name *ace_property = dav_get_ace_property(ace);
	    const dav_privileges *ace_privileges = dav_get_ace_privileges(ace);
            const char *principal_url = dav_repos_principal_to_s(ace_principal);

	    /* Build XML. */
	    char *str_tmp = NULL;
	    char *str_acepriv = "";
	    char *str_acehead = NULL;
	    char *str_acebody = NULL;
	    char *grant_deny = NULL;
            char *str_protected = NULL;
	    const char *inherited = NULL;
	    if (dav_is_deny_ace(ace))
		grant_deny = "deny";

	    else
		grant_deny = "grant";

            if(ace_property && !strcmp(ace_property->ns, "") && !strcmp(ace_property->name, "self")) {
                str_acehead = apr_psprintf(db_r->p, "<D:ace>" DEBUG_CR
                                           "<D:principal>" DEBUG_CR
                                           "<D:self/>" DEBUG_CR
                                           "</D:principal>" DEBUG_CR
                                           "<D:%s>", grant_deny);
            }
            else if(ace_property) {
                str_acehead = apr_psprintf(db_r->p, "<D:ace>" DEBUG_CR
                                           "<D:principal>" DEBUG_CR
                                           "<D:property>" DEBUG_CR
                                           "<R:%s xmlns:R=\"%s\"/>" DEBUG_CR
                                           "</D:property>" DEBUG_CR
                                           "</D:principal>" DEBUG_CR
                                           "<D:%s>", ace_property->name,
                                           ace_property->ns, grant_deny);
            } 
            else if(strstr(principal_url, PRINCIPAL_USER_PREFIX) ||
                    strstr(principal_url, PRINCIPAL_GROUP_PREFIX)) {
                str_acehead = 
                    apr_psprintf(db_r->p, 
                        "<D:ace>" DEBUG_CR
			"<D:principal>" DEBUG_CR
			"<D:href>%s</D:href>" DEBUG_CR
			"</D:principal>" DEBUG_CR
			"<D:%s>",
			apr_xml_quote_string(db_r->p, principal_url, 0), 
                        grant_deny);
            }
            else {
                str_acehead = apr_psprintf(db_r->p, "<D:ace>" DEBUG_CR
                                           "  <D:principal>" DEBUG_CR
                                           "    <D:%s/>" DEBUG_CR
				           "  </D:principal>" DEBUG_CR
				           "<D:%s>",
				           principal_url, grant_deny);
            }

	    dav_privilege_iterator *iter;
	    iter = dav_privilege_iterate(ace_privileges);
	    while (dav_privilege_iterator_more(iter)) {
		const dav_privilege *privilege =
		    dav_privilege_iterator_next(iter);
		const char *privilege_name =
		    dav_get_privilege_name(privilege);
		str_tmp =
		    apr_psprintf(db_r->p,
				 "<D:privilege>" DEBUG_CR "<D:%s/>"
				 DEBUG_CR "</D:privilege>",
				 privilege_name);
		str_tmp = apr_pstrcat(db_r->p, str_acepriv, str_tmp, NULL);
		str_acepriv = apr_pstrdup(db_r->p, str_tmp);
	    }

            if(dav_is_protected_ace(ace))
                str_protected = apr_psprintf(db_r->p, "</D:%s><D:protected/>",
                                             grant_deny);
            else str_protected = apr_psprintf(db_r->p, "</D:%s>", grant_deny);

	    inherited = dav_get_ace_inherited(ace);
	    if ((inherited == NULL) || (strcmp(inherited, "") == 0))
		str_acebody = apr_psprintf(db_r->p, "</D:ace>");
	    else str_acebody = 
                apr_psprintf(db_r->p, 
                    "<D:inherited>" DEBUG_CR
                    "<D:href>%s%s</D:href>" DEBUG_CR
                    "</D:inherited>" DEBUG_CR
                    "</D:ace>",
                    principal_href_prefix(r), 
                    apr_xml_quote_string(db_r->p, inherited, 0));

	    str_xml_acl =
		apr_pstrcat(db_r->p, str_xml_acl, str_acehead, str_acepriv,
			    str_protected, str_acebody, NULL);
	}
    }
    return str_xml_acl;
}