/* 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; }
/* Helper function for svn_ra_neon__do_proppatch() below. */ static void append_setprop(svn_stringbuf_t *body, const char *name, const svn_string_t *value, apr_pool_t *pool) { const char *encoding = ""; const char *xml_safe; const char *xml_tag_name; /* Map property names to namespaces */ #define NSLEN (sizeof(SVN_PROP_PREFIX) - 1) if (strncmp(name, SVN_PROP_PREFIX, NSLEN) == 0) { xml_tag_name = apr_pstrcat(pool, "S:", name + NSLEN, NULL); } #undef NSLEN else { xml_tag_name = apr_pstrcat(pool, "C:", name, NULL); } /* If there is no value, just generate an empty tag and get outta here. */ if (! value) { svn_stringbuf_appendcstr(body, apr_psprintf(pool, "<%s />", xml_tag_name)); return; } /* If a property is XML-safe, XML-encode it. Else, base64-encode it. */ if (svn_xml_is_xml_safe(value->data, value->len)) { svn_stringbuf_t *xml_esc = NULL; svn_xml_escape_cdata_string(&xml_esc, value, pool); xml_safe = xml_esc->data; } else { const svn_string_t *base64ed = svn_base64_encode_string2(value, TRUE, pool); encoding = " V:encoding=\"base64\""; xml_safe = base64ed->data; } svn_stringbuf_appendcstr(body, apr_psprintf(pool,"<%s %s>%s</%s>", xml_tag_name, encoding, xml_safe, xml_tag_name)); return; }
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); }
static dav_error * db_output_value(dav_db *db, const dav_prop_name *name, dav_xmlns_info *xi, apr_text_header *phdr, int *found) { const char *prefix; const char *s; svn_string_t *propval; dav_error *err; apr_pool_t *pool = db->resource->pool; if ((err = get_value(db, name, &propval)) != NULL) return err; /* return whether the prop was found, then punt or handle it. */ *found = (propval != NULL); if (propval == NULL) return NULL; if (strcmp(name->ns, SVN_DAV_PROP_NS_CUSTOM) == 0) prefix = "C:"; else prefix = "S:"; if (propval->len == 0) { /* empty value. add an empty elem. */ s = apr_psprintf(pool, "<%s%s/>" DEBUG_CR, prefix, name->name); apr_text_append(pool, phdr, s); } else { /* add <prefix:name [V:encoding="base64"]>value</prefix:name> */ const char *xml_safe; const char *encoding = ""; /* Ensure XML-safety of our property values before sending them across the wire. */ if (! svn_xml_is_xml_safe(propval->data, propval->len)) { const svn_string_t *enc_propval = svn_base64_encode_string2(propval, TRUE, pool); xml_safe = enc_propval->data; encoding = " V:encoding=\"base64\""; } else { svn_stringbuf_t *xmlval = NULL; svn_xml_escape_cdata_string(&xmlval, propval, pool); xml_safe = xmlval->data; } s = apr_psprintf(pool, "<%s%s%s>", prefix, name->name, encoding); apr_text_append(pool, phdr, s); /* the value is in our pool which means it has the right lifetime. */ /* ### at least, per the current mod_dav architecture/API */ apr_text_append(pool, phdr, xml_safe); s = apr_psprintf(pool, "</%s%s>" DEBUG_CR, prefix, name->name); apr_text_append(pool, phdr, s); } return NULL; }