static void dav_quota_insert_all_liveprops(request_rec * r, const dav_resource * resource, dav_prop_insert what, apr_text_header * phdr) { const char *s; /* don't try to find any liveprops if this isn't "our" resource */ if (resource->hooks != &dav_repos_hooks_repos) return; TRACE(); if (!resource->exists || resource->type != DAV_RESOURCE_TYPE_REGULAR) return; if (what == DAV_PROP_INSERT_VALUE) return; s = apr_psprintf(r->pool, "<D:quota-available-bytes/>" DEBUG_CR "<D:quota-used-bytes/>"); if (what == DAV_PROP_INSERT_NAME) { apr_text_append(r->pool, phdr, s); } else if (what == DAV_PROP_INSERT_SUPPORTED) { s = apr_psprintf(r->pool, "<D:supported-live-property><D:prop>" DEBUG_CR "%s" DEBUG_CR "</D:prop></D:supported-live-property>", s); apr_text_append(r->pool, phdr, s); } }
/* 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>"); }
static void cdata_handler(void *userdata, const char *data, int len) { apr_xml_parser *parser = userdata; apr_xml_elem *elem; apr_text_header *hdr; const char *s; /* punt once we find an error */ if (parser->error) return; elem = parser->cur_elem; s = apr_pstrndup(parser->p, data, len); if (elem->last_child == NULL) { /* no children yet. this cdata follows the start tag */ hdr = &elem->first_cdata; } else { /* child elements exist. this cdata follows the last child. */ hdr = &elem->last_child->following_cdata; } apr_text_append(parser->p, hdr, s); }
static void dav_acl_insert_all_liveprops(request_rec * r, const dav_resource * resource, dav_prop_insert what, apr_text_header * phdr) { const char *s, *val = ""; /* don't try to find any liveprops if this isn't "our" resource */ if (resource->hooks != &dav_repos_hooks_repos) return; TRACE(); if (!resource->exists || resource->type != DAV_RESOURCE_TYPE_REGULAR) return; if (what == DAV_PROP_INSERT_VALUE) return; s = list_all_liveprops(r->pool, dav_acl_props); if (what == DAV_PROP_INSERT_NAME) val = s; else if (what == DAV_PROP_INSERT_SUPPORTED) val = apr_pstrcat(r->pool, "<D:supported-live-property><D:prop>", s, "</D:prop></D:supported-live-property>", NULL); apr_text_append(r->pool, phdr, val); }
/** * 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; }
static void dav_insert_xmlns(apr_pool_t *p, const char *pre_prefix, long ns, const char *ns_uri, apr_text_header *phdr) { const char *s; s = apr_psprintf(p, " xmlns:%s%ld=\"%s\"", pre_prefix, ns, ns_uri); apr_text_append(p, phdr, s); }
static void dav_deltav_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(); if (what == DAV_PROP_INSERT_VALUE) return; db_r = (dav_repos_resource *) resource->info->db_r; if (!resource->exists) return; sabridge_build_vpr_hash(resource->info->db, db_r); if (db_r->vpr_hash == NULL) return; if (what == DAV_PROP_INSERT_SUPPORTED) apr_text_append(r->pool, phdr, "<D:supported-live-property>" DEBUG_CR "<D:prop>" DEBUG_CR); /* Read live props from hash */ for (hindex = apr_hash_first(r->pool, db_r->vpr_hash); hindex; hindex = apr_hash_next(hindex)) { apr_hash_this(hindex, (void *) &key, &klen, (void *) &val); s = apr_psprintf(r->pool, "<D:%s/>" DEBUG_CR, key); apr_text_append(r->pool, phdr, s); } if (what == DAV_PROP_INSERT_SUPPORTED) apr_text_append(r->pool, phdr, "</D:prop>" DEBUG_CR "</D:supported-live-property>" DEBUG_CR); }
static dav_prop_insert dav_deltav_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(); if (!resource->exists) return DAV_PROP_INSERT_NOTDEF; /* find propname using prop id */ spec = get_livepropspec_from_id(dav_deltav_props, propid); name = spec->name; /* ### what the heck was this property? */ if (name == NULL) return DAV_PROP_INSERT_NOTDEF; /* Build version property hash and get value */ if (!dbr->vpr_hash) sabridge_build_vpr_hash(resource->info->db, dbr); if (dbr->vpr_hash) value = apr_hash_get(dbr->vpr_hash, name, APR_HASH_KEY_STRING); /* ### Not found in the hash */ if (value == NULL) return DAV_PROP_INSERT_NOTSUPP; /* Do something according to what */ if (what == DAV_PROP_INSERT_VALUE) { s = apr_psprintf(pool, "<D:%s>%s</D:%s>" DEBUG_CR, name, value, 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>" DEBUG_CR "<D:%s/>" DEBUG_CR "</D:prop></D:supported-live-property>" DEBUG_CR, name); } apr_text_append(pool, phdr, s); /* we inserted what was asked for */ return what; }
static dav_prop_insert dav_quota_insert_prop(const dav_resource * resource, int propid, dav_prop_insert what, apr_text_header * phdr) { dav_repos_db *db = resource->info->db; dav_repos_resource *db_r = resource->info->db_r; const dav_liveprop_spec *spec; apr_pool_t *pool = db_r->p; const char *name; const char *s = ""; TRACE(); if (propid != DAV_PROPID_quota_available_bytes && propid != DAV_PROPID_quota_used_bytes) return DAV_PROP_INSERT_NOTDEF; if (!resource->exists || resource->type != DAV_RESOURCE_TYPE_REGULAR) return DAV_PROP_INSERT_NOTDEF; spec = get_livepropspec_from_id(dav_quota_props, propid); name = spec->name; if (what == DAV_PROP_INSERT_VALUE) { long nbytes = 0; switch (propid) { case DAV_PROPID_quota_available_bytes: dbms_get_available_bytes (db_r->p, db, db_r->owner_id, &nbytes); break; case DAV_PROPID_quota_used_bytes: nbytes = sabridge_get_used_bytes (db, db_r, 1); break; } s = apr_psprintf(pool, "<D:%s>%ld</D:%s>", name, nbytes, name); } else if (what == DAV_PROP_INSERT_SUPPORTED) { s = apr_psprintf(pool, "<D:supported-live-property><D:prop>" DEBUG_CR "<D:%s/>" DEBUG_CR "</D:prop></D:supported-live-property>" DEBUG_CR, name); } apr_text_append(pool, phdr, s); /* we inserted what was asked for */ return what; }
static void dav_output_prop_name(apr_pool_t *pool, const dav_prop_name *name, dav_xmlns_info *xi, apr_text_header *phdr) { const char *s; if (*name->ns == '\0') s = apr_psprintf(pool, "<%s/>" DEBUG_CR, name->name); else { const char *prefix = dav_xmlns_add_uri(xi, name->ns); s = apr_psprintf(pool, "<%s:%s/>" DEBUG_CR, prefix, name->name); } apr_text_append(pool, phdr, s); }
static void dav_append_prop(apr_pool_t *pool, const char *name, const char *value, apr_text_header *phdr) { const char *s; const char *lang = value; /* skip past the xml:lang value */ value += strlen(lang) + 1; if (*value == '\0') { /* the property is an empty value */ if (*name == ':') { /* "no namespace" case */ s = apr_psprintf(pool, "<%s/>" DEBUG_CR, name+1); } else { s = apr_psprintf(pool, "<ns%s/>" DEBUG_CR, name); } } else if (*lang != '\0') { if (*name == ':') { /* "no namespace" case */ s = apr_psprintf(pool, "<%s xml:lang=\"%s\">%s</%s>" DEBUG_CR, name+1, lang, value, name+1); } else { s = apr_psprintf(pool, "<ns%s xml:lang=\"%s\">%s</ns%s>" DEBUG_CR, name, lang, value, name); } } else if (*name == ':') { /* "no namespace" case */ s = apr_psprintf(pool, "<%s>%s</%s>" DEBUG_CR, name+1, value, name+1); } else { s = apr_psprintf(pool, "<ns%s>%s</ns%s>" DEBUG_CR, name, value, name); } apr_text_append(pool, phdr, s); }
DAV_DECLARE(dav_get_props_result) dav_get_allprops(dav_propdb *propdb, dav_prop_insert what) { const dav_hooks_db *db_hooks = propdb->db_hooks; apr_text_header hdr = { 0 }; apr_text_header hdr_ns = { 0 }; dav_get_props_result result = { 0 }; int found_contenttype = 0; int found_contentlang = 0; dav_prop_insert unused_inserted; /* if not just getting supported live properties, * scan all properties in the dead prop database */ if (what != DAV_PROP_INSERT_SUPPORTED) { if (propdb->deferred) { /* ### what to do with db open error? */ (void) dav_really_open_db(propdb, 1 /*ro*/); } /* initialize the result with some start tags... */ apr_text_append(propdb->p, &hdr, "<D:propstat>" DEBUG_CR "<D:prop>" DEBUG_CR); /* if there ARE properties, then scan them */ if (propdb->db != NULL) { dav_xmlns_info *xi = dav_xmlns_create(propdb->p); dav_prop_name name; dav_error *err; /* define (up front) any namespaces the db might need */ (void) (*db_hooks->define_namespaces)(propdb->db, xi); /* get the first property name, beginning the scan */ err = (*db_hooks->first_name)(propdb->db, &name); while (!err && name.ns) { /* ** We also look for <DAV:getcontenttype> and ** <DAV:getcontentlanguage>. If they are not stored as dead ** properties, then we need to perform a subrequest to get ** their values (if any). */ if (*name.ns == 'D' && strcmp(name.ns, "DAV:") == 0 && *name.name == 'g') { if (strcmp(name.name, "getcontenttype") == 0) { found_contenttype = 1; } else if (strcmp(name.name, "getcontentlanguage") == 0) { found_contentlang = 1; } } if (what == DAV_PROP_INSERT_VALUE) { int found; if ((err = (*db_hooks->output_value)(propdb->db, &name, xi, &hdr, &found)) != NULL) { /* ### anything better to do? */ /* ### probably should enter a 500 error */ goto next_key; } /* assert: found == 1 */ } else { /* the value was not requested, so just add an empty tag specifying the property name. */ dav_output_prop_name(propdb->p, &name, xi, &hdr); } next_key: err = (*db_hooks->next_name)(propdb->db, &name); } /* all namespaces have been entered into xi. generate them into the output now. */ dav_xmlns_generate(xi, &hdr_ns); } /* propdb->db != NULL */ /* add namespaces for all the liveprop providers */ dav_add_all_liveprop_xmlns(propdb->p, &hdr_ns); } /* ask the liveprop providers to insert their properties */ dav_run_insert_all_liveprops(propdb->r, propdb->resource, what, &hdr); /* insert the standard properties */ /* ### should be handling the return errors here */ (void)dav_insert_coreprop(propdb, DAV_PROPID_CORE_supportedlock, "supportedlock", what, &hdr, &unused_inserted); (void)dav_insert_coreprop(propdb, DAV_PROPID_CORE_lockdiscovery, "lockdiscovery", what, &hdr, &unused_inserted); /* if we didn't find these, then do the whole subreq thing. */ if (!found_contenttype) { /* ### should be handling the return error here */ (void)dav_insert_coreprop(propdb, DAV_PROPID_CORE_getcontenttype, "getcontenttype", what, &hdr, &unused_inserted); } if (!found_contentlang) { /* ### should be handling the return error here */ (void)dav_insert_coreprop(propdb, DAV_PROPID_CORE_getcontentlanguage, "getcontentlanguage", what, &hdr, &unused_inserted); } /* if not just reporting on supported live props, * terminate the result */ if (what != DAV_PROP_INSERT_SUPPORTED) { apr_text_append(propdb->p, &hdr, "</D:prop>" DEBUG_CR "<D:status>HTTP/1.1 200 OK</D:status>" DEBUG_CR "</D:propstat>" DEBUG_CR); } result.propstats = hdr.first; result.xmlns = hdr_ns.first; return result; }
DAV_DECLARE(dav_get_props_result) dav_get_props(dav_propdb *propdb, apr_xml_doc *doc) { const dav_hooks_db *db_hooks = propdb->db_hooks; apr_xml_elem *elem = dav_find_child(doc->root, "prop"); apr_text_header hdr_good = { 0 }; apr_text_header hdr_bad = { 0 }; apr_text_header hdr_ns = { 0 }; int have_good = 0; dav_get_props_result result = { 0 }; char *marks_liveprop; dav_xmlns_info *xi; int xi_filled = 0; /* ### NOTE: we should pass in TWO buffers -- one for keys, one for the marks */ /* we will ALWAYS provide a "good" result, even if it is EMPTY */ apr_text_append(propdb->p, &hdr_good, "<D:propstat>" DEBUG_CR "<D:prop>" DEBUG_CR); /* ### the marks should be in a buffer! */ /* allocate zeroed-memory for the marks. These marks indicate which liveprop namespaces we've generated into the output xmlns buffer */ /* same for the liveprops */ marks_liveprop = apr_pcalloc(propdb->p, dav_get_liveprop_ns_count() + 1); xi = dav_xmlns_create(propdb->p); for (elem = elem->first_child; elem; elem = elem->next) { dav_elem_private *priv; dav_error *err; dav_prop_insert inserted; dav_prop_name name; /* ** First try live property providers; if they don't handle ** the property, then try looking it up in the propdb. */ if (elem->priv == NULL) { elem->priv = apr_pcalloc(propdb->p, sizeof(*priv)); } priv = elem->priv; /* cache the propid; dav_get_props() could be called many times */ if (priv->propid == 0) dav_find_liveprop(propdb, elem); if (priv->propid != DAV_PROPID_CORE_UNKNOWN) { /* insert the property. returns 1 if an insertion was done. */ if ((err = dav_insert_liveprop(propdb, elem, DAV_PROP_INSERT_VALUE, &hdr_good, &inserted)) != NULL) { /* ### need to propagate the error to the caller... */ /* ### skip it for now, as if nothing was inserted */ } if (inserted == DAV_PROP_INSERT_VALUE) { have_good = 1; /* ** Add the liveprop's namespace URIs. Note that provider==NULL ** for core properties. */ if (priv->provider != NULL) { const char * const * scan_ns_uri; for (scan_ns_uri = priv->provider->namespace_uris; *scan_ns_uri != NULL; ++scan_ns_uri) { long ns; ns = dav_get_liveprop_ns_index(*scan_ns_uri); if (marks_liveprop[ns]) continue; marks_liveprop[ns] = 1; dav_insert_xmlns(propdb->p, "lp", ns, *scan_ns_uri, &hdr_ns); } } /* property added. move on to the next property. */ continue; } else if (inserted == DAV_PROP_INSERT_NOTDEF) { /* nothing to do. fall thru to allow property to be handled as a dead property */ } #if DAV_DEBUG else { #if 0 /* ### need to change signature to return an error */ return dav_new_error(propdb->p, HTTP_INTERNAL_SERVER_ERROR, 0, 0, "INTERNAL DESIGN ERROR: insert_liveprop " "did not insert what was asked for."); #endif } #endif } /* The property wasn't a live property, so look in the dead property database. */ /* make sure propdb is really open */ if (propdb->deferred) { /* ### what to do with db open error? */ (void) dav_really_open_db(propdb, 1 /*ro*/); } if (elem->ns == APR_XML_NS_NONE) name.ns = ""; else name.ns = APR_XML_GET_URI_ITEM(propdb->ns_xlate, elem->ns); name.name = elem->name; /* only bother to look if a database exists */ if (propdb->db != NULL) { int found; if ((err = (*db_hooks->output_value)(propdb->db, &name, xi, &hdr_good, &found)) != NULL) { /* ### what to do? continue doesn't seem right... */ continue; } if (found) { have_good = 1; /* if we haven't added the db's namespaces, then do so... */ if (!xi_filled) { (void) (*db_hooks->define_namespaces)(propdb->db, xi); xi_filled = 1; } continue; } } /* not found as a live OR dead property. add a record to the "bad" propstats */ /* make sure we've started our "bad" propstat */ if (hdr_bad.first == NULL) { apr_text_append(propdb->p, &hdr_bad, "<D:propstat>" DEBUG_CR "<D:prop>" DEBUG_CR); } /* output this property's name (into the bad propstats) */ dav_output_prop_name(propdb->p, &name, xi, &hdr_bad); } apr_text_append(propdb->p, &hdr_good, "</D:prop>" DEBUG_CR "<D:status>HTTP/1.1 200 OK</D:status>" DEBUG_CR "</D:propstat>" DEBUG_CR); /* default to start with the good */ result.propstats = hdr_good.first; /* we may not have any "bad" results */ if (hdr_bad.first != NULL) { /* "close" the bad propstat */ apr_text_append(propdb->p, &hdr_bad, "</D:prop>" DEBUG_CR "<D:status>HTTP/1.1 404 Not Found</D:status>" DEBUG_CR "</D:propstat>" DEBUG_CR); /* if there are no good props, then just return the bad */ if (!have_good) { result.propstats = hdr_bad.first; } else { /* hook the bad propstat to the end of the good one */ hdr_good.last->next = hdr_bad.first; } } /* add in all the various namespaces, and return them */ dav_xmlns_generate(xi, &hdr_ns); result.xmlns = hdr_ns.first; return result; }
static dav_prop_insert dav_core_insert_prop(const dav_resource *resource, int propid, dav_prop_insert what, apr_text_header *phdr) { const char *value = NULL; const char *s; apr_pool_t *p = resource->pool; const dav_liveprop_spec *info; long global_ns; switch (propid) { case DAV_PROPID_resourcetype: { /* additional type info provided by external modules ? */ int i; apr_array_header_t *extensions = ap_list_provider_names(p, DAV_RESOURCE_TYPE_GROUP, "0"); ap_list_provider_names_t *entry = (ap_list_provider_names_t *)extensions->elts; for (i = 0; i < extensions->nelts; i++, entry++) { const dav_resource_type_provider *res_hooks = dav_get_resource_type_providers(entry->provider_name); const char *name = NULL, *uri = NULL; if (!res_hooks || !res_hooks->get_resource_type) continue; if (!res_hooks->get_resource_type(resource, &name, &uri) && name) { if (!uri || !strcasecmp(uri, "DAV:")) value = apr_pstrcat(p, value ? value : "", "<D:", name, "/>", NULL); else value = apr_pstrcat(p, value ? value : "", "<x:", name, " xmlns:x=\"", uri, "\"/>", NULL); } } } switch (resource->type) { case DAV_RESOURCE_TYPE_VERSION: if (resource->baselined) { value = apr_pstrcat(p, value ? value : "", "<D:baseline/>", NULL); break; } /* fall through */ case DAV_RESOURCE_TYPE_REGULAR: case DAV_RESOURCE_TYPE_WORKING: if (resource->collection) { value = apr_pstrcat(p, value ? value : "", "<D:collection/>", NULL); } else { /* ### should we denote lock-null resources? */ if (value == NULL) { value = ""; /* becomes: <D:resourcetype/> */ } } break; case DAV_RESOURCE_TYPE_HISTORY: value = apr_pstrcat(p, value ? value : "", "<D:version-history/>", NULL); break; case DAV_RESOURCE_TYPE_WORKSPACE: value = apr_pstrcat(p, value ? value : "", "<D:collection/>", NULL); break; case DAV_RESOURCE_TYPE_ACTIVITY: value = apr_pstrcat(p, value ? value : "", "<D:activity/>", NULL); break; default: /* ### bad juju */ return DAV_PROP_INSERT_NOTDEF; } break; case DAV_PROPID_comment: case DAV_PROPID_creator_displayname: case DAV_PROPID_displayname: case DAV_PROPID_source: default: /* ** This property is known, but not defined as a liveprop. However, ** it may be a dead 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_core_liveprop_group, &info); /* assert: info != NULL && info->name != NULL */ if (what == DAV_PROP_INSERT_SUPPORTED) { s = apr_psprintf(p, "<D:supported-live-property D:name=\"%s\" " "D:namespace=\"%s\"/>" DEBUG_CR, info->name, dav_core_namespace_uris[info->ns]); } else if (what == DAV_PROP_INSERT_VALUE && *value != '\0') { s = apr_psprintf(p, "<lp%ld:%s>%s</lp%ld:%s>" DEBUG_CR, global_ns, info->name, value, global_ns, info->name); } else { s = apr_psprintf(p, "<lp%ld:%s/>" DEBUG_CR, global_ns, info->name); } apr_text_append(p, phdr, s); /* we inserted what was asked for */ return what; }
static dav_prop_insert dav_rawx_insert_prop(const dav_resource *resource, int propid, dav_prop_insert what, apr_text_header *phdr) { const char *value; const char *s; apr_pool_t *p = resource->info->pool; const dav_liveprop_spec *info; int global_ns; /* an HTTP-date can be 29 chars plus a null term */ /* a 64-bit size can be 20 chars plus a null term */ char buf[DAV_TIMEBUF_SIZE]; /* ** 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 (!resource->exists) return DAV_PROP_INSERT_NOTDEF; switch (propid) { case DAV_PROPID_creationdate: /* ** Closest thing to a creation date. since we don't actually ** perform the operations that would modify ctime (after we ** create the file), then we should be pretty safe here. */ dav_format_time(DAV_STYLE_ISO8601, resource->info->finfo.ctime, buf); value = buf; break; case DAV_PROPID_getcontentlength: /* our property, but not defined on collection resources */ if (resource->collection) return DAV_PROP_INSERT_NOTDEF; (void) sprintf(buf, "%" APR_OFF_T_FMT, resource->info->finfo.size); value = buf; break; case DAV_PROPID_getetag: value = dav_rawx_getetag(resource); break; case DAV_PROPID_getlastmodified: dav_format_time(DAV_STYLE_RFC822, resource->info->finfo.mtime, buf); value = buf; break; case DAV_PROPID_FS_executable: /* our property, but not defined on collection resources */ if (resource->collection) return DAV_PROP_INSERT_NOTDEF; /* our property, but not defined on this platform */ if (!(resource->info->finfo.valid & APR_FINFO_UPROT)) return DAV_PROP_INSERT_NOTDEF; /* the files are "ours" so we only need to check owner exec privs */ if (resource->info->finfo.protection & APR_UEXECUTE) value = "T"; else value = "F"; 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_rawx_liveprop_group, &info); /* assert: info != NULL && info->name != NULL */ /* DBG3("FS: inserting lp%d:%s (local %d)", ns, scan->name, scan->ns); */ if (what == DAV_PROP_INSERT_VALUE) { s = apr_psprintf(p, "<lp%d:%s>%s</lp%d:%s>" DEBUG_CR, global_ns, info->name, value, global_ns, info->name); } else if (what == DAV_PROP_INSERT_NAME) { s = apr_psprintf(p, "<lp%d:%s/>" DEBUG_CR, global_ns, info->name); } else { /* assert: what == DAV_PROP_INSERT_SUPPORTED */ s = apr_psprintf(p, "<D:supported-live-property D:name=\"%s\" " "D:namespace=\"%s\"/>" DEBUG_CR, info->name, dav_rawx_namespace_uris[info->ns]); } apr_text_append(p, phdr, s); /* we inserted what was asked for */ return what; }
static dav_error * dav_insert_coreprop(dav_propdb *propdb, int propid, const char *name, dav_prop_insert what, apr_text_header *phdr, dav_prop_insert *inserted) { const char *value = NULL; dav_error *err; *inserted = DAV_PROP_INSERT_NOTDEF; /* fast-path the common case */ if (propid == DAV_PROPID_CORE_UNKNOWN) return NULL; switch (propid) { case DAV_PROPID_CORE_lockdiscovery: if (propdb->lockdb != NULL) { dav_lock *locks; if ((err = dav_lock_query(propdb->lockdb, propdb->resource, &locks)) != NULL) { return dav_push_error(propdb->p, err->status, 0, "DAV:lockdiscovery could not be " "determined due to a problem fetching " "the locks for this resource.", err); } /* fast-path the no-locks case */ if (locks == NULL) { value = ""; } else { /* ** This may modify the buffer. value may point to ** wb_lock.pbuf or a string constant. */ value = dav_lock_get_activelock(propdb->r, locks, &propdb->wb_lock); /* make a copy to isolate it from changes to wb_lock */ value = apr_pstrdup(propdb->p, propdb->wb_lock.buf); } } break; case DAV_PROPID_CORE_supportedlock: if (propdb->lockdb != NULL) { value = (*propdb->lockdb->hooks->get_supportedlock)(propdb->resource); } break; case DAV_PROPID_CORE_getcontenttype: if (propdb->subreq == NULL) { dav_do_prop_subreq(propdb); } if (propdb->subreq->content_type != NULL) { value = propdb->subreq->content_type; } break; case DAV_PROPID_CORE_getcontentlanguage: { const char *lang; if (propdb->subreq == NULL) { dav_do_prop_subreq(propdb); } if ((lang = apr_table_get(propdb->subreq->headers_out, "Content-Language")) != NULL) { value = lang; } break; } default: /* fall through to interpret as a dead property */ break; } /* if something was supplied, then insert it */ if (value != NULL) { const char *s; if (what == DAV_PROP_INSERT_SUPPORTED) { /* use D: prefix to refer to the DAV: namespace URI, * and let the namespace attribute default to "DAV:" */ s = apr_psprintf(propdb->p, "<D:supported-live-property D:name=\"%s\"/>" DEBUG_CR, name); } else if (what == DAV_PROP_INSERT_VALUE && *value != '\0') { /* use D: prefix to refer to the DAV: namespace URI */ s = apr_psprintf(propdb->p, "<D:%s>%s</D:%s>" DEBUG_CR, name, value, name); } else { /* use D: prefix to refer to the DAV: namespace URI */ s = apr_psprintf(propdb->p, "<D:%s/>" DEBUG_CR, name); } apr_text_append(propdb->p, phdr, s); *inserted = what; } return NULL; }
static dav_prop_insert dav_acl_insert_prop(const dav_resource *resource, int propid, dav_prop_insert what, apr_text_header *phdr) { const char *value = NULL; const char *s = NULL; apr_pool_t *p = resource->pool; const dav_liveprop_spec *info; int global_ns, rc; if (!resource->exists) return DAV_PROP_INSERT_NOTDEF; /* ### we may want to respond to DAV_PROPID_resourcetype for PRIVATE ### resources. need to think on "proper" interaction with mod_dav */ switch (propid) { case ACL_PROPID_acl: if (what == DAV_PROP_INSERT_VALUE) { /* request_rec *r = resource->hooks->get_request_rec(resource) */; xmlBufferPtr buf = NULL; const char *pch = NULL; xmlDocPtr doc; xmlNodePtr node; rc = dav_acl_get_acl(resource, &pch, &rc); if (rc < 0) return DAV_PROP_INSERT_NOTDEF; doc = xmlParseMemory(pch, rc); node = doc && doc->children ? doc->children : NULL; buf = xmlBufferCreate(); xmlNodeDump(buf, doc, node, 0, 1); xmlFreeDoc(doc); apr_text_append(p, phdr, apr_psprintf (p, "%s" DEBUG_CR, buf->content)); /* we inserted whatever was asked for */ xmlBufferFree(buf); return what; } break; case ACL_PROPID_acl_restrictions: value = "<D:required-principal>" "<D:authenticated/>" "<D:unauthenticated/>" "<D:self/>" "<D:all/>" "<D:href/>" "<D:property><D:owner/></D:property>" "<D:property><D:group/></D:property>" "</D:required-principal>"; break; case ACL_PROPID_supported_privilege_set: if (what == DAV_PROP_INSERT_VALUE) { xmlBufferPtr buf = NULL; xmlDocPtr doc = xmlNewDoc((const xmlChar *) XML_VERSION); xmlNsPtr ns; xmlNodePtr cur, child, node; int acl, cups; dav_acl_get_aggregated(resource, &acl, &cups); doc->children = xmlNewDocNode(doc, NULL, (const xmlChar *) "root", NULL); xmlSetNs(doc->children, ns = xmlNewNs(doc->children, (const xmlChar *) "DAV:", (const xmlChar *) "D")); node = xmlNewChild(doc->children, ns, (const xmlChar *) "supported-privilege-set", NULL); cur = add_supported(node, ns, "all", 0, "All privileges"); child = add_supported(cur, ns, "read", 0, "Read"); add_supported(acl ? child : cur, ns, "read-acl", 0, "Read ACL"); add_supported(cups ? child : cur, ns, "read-current-user-privilege-set", 0, "Read Current User"); child = add_supported(cur, ns, "write", 0, "Write"); add_supported(child, ns, "write-acl", 0, "Write ACL"); add_supported(child, ns, "write-content", 0, "Write content"); add_supported(child, ns, "write-properties", 0, "Write properties"); if (resource->collection) { add_supported(child, ns, "bind", 0, "Create a collection"); add_supported(child, ns, "unbind", 0, "Remove a collection"); } add_supported(cur, ns, "unlock", 0, "Unlock"); buf = xmlBufferCreate(); xmlNodeDump(buf, doc, node, 0, 1); xmlFreeDoc(doc); apr_text_append(p, phdr, apr_psprintf(p, "%s" DEBUG_CR, buf->content)); /* we inserted whatever was asked for */ xmlBufferFree(buf); return what; } break; case ACL_PROPID_group_membership: value = dav_acl_get_group_membership(resource); if (value == NULL) return DAV_PROP_INSERT_NOTDEF; break; case ACL_PROPID_owner: value = dav_acl_get_owner(resource); if (value == NULL) return DAV_PROP_INSERT_NOTDEF; break; case ACL_PROPID_alternate_uri_set: value = ""; /* may be empty */ break; case ACL_PROPID_inherited_acl_set: value = ""; /* not supported because of complexity... */ break; case ACL_PROPID_current_user_privilege_set: value = dav_acl_get_privs(resource); break; case ACL_PROPID_principal_collection_set: { request_rec *r = resource->hooks->get_request_rec(resource); const char *pcsz = dav_acl_get_principals(r); value = apr_psprintf(p, "<D:href>%s/</D:href>", pcsz ? pcsz : ""); } break; case ACL_PROPID_current_user_principal: value = dav_acl_get_auth_principal(resource); if (value) value = apr_psprintf(p, "<D:href>%s</D:href>", value); else value = "<D:unauthenticated/>"; 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_acl_liveprop_group, &info); /* assert: info != NULL && info->name != NULL */ if (what == DAV_PROP_INSERT_VALUE) s = apr_psprintf(p, "<lp%d:%s>%s</lp%d:%s>" DEBUG_CR, global_ns, info->name, value, global_ns, info->name); else if (what == DAV_PROP_INSERT_NAME) s = apr_psprintf(p, "<lp%d:%s/>" DEBUG_CR, global_ns, info->name); else /* assert: what == DAV_PROP_INSERT_SUPPORTED */ s = apr_psprintf(p, "<D:supported-live-property D:name=\"%s\" " "D:namespace=\"%s\"/>" DEBUG_CR, info->name, dav_acl_namespace_uris[info->ns]); apr_text_append(p, phdr, s); /* we inserted whatever was asked for */ return what; }
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; }
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; }
static dav_prop_insert dav_acl_insert_prop(const dav_resource * resource, int propid, dav_prop_insert what, apr_text_header * phdr) { dav_repos_db *db = resource->info->db; dav_repos_resource *db_r = resource->info->db_r; apr_pool_t *pool = db_r->p; const dav_liveprop_spec *spec; const char *s, *name, *owner, *val = ""; dav_principal *principal; request_rec *r = resource->info->rec; TRACE(); spec = get_livepropspec_from_id(dav_acl_props, propid); name = spec->name; /* ACL liveprops are not defined for locknull resources */ if(db_r->resourcetype == dav_repos_LOCKNULL) return DAV_PROP_INSERT_NOTDEF; if (what == DAV_PROP_INSERT_SUPPORTED) { s = apr_psprintf(pool, "<D:supported-live-property><D:prop>" DEBUG_CR "<D:%s/>" DEBUG_CR "</D:prop></D:supported-live-property>" DEBUG_CR, name); apr_text_append(pool, phdr, s); return what; } else if (what != DAV_PROP_INSERT_VALUE) return what; switch (propid) { case DAV_PROPID_owner: owner = dbms_lookup_prin_id(pool, db, db_r->owner_id); principal = dav_repos_get_prin_by_name(db_r->resource->info->rec, owner); val = apr_psprintf(pool, "<D:href>%s</D:href>", dav_repos_principal_to_s(principal)); break; case DAV_PROPID_supported_privilege_set: val = acl_supported_privilege_set(resource); break; case DAV_PROPID_current_user_privilege_set: principal = dav_principal_make_from_request(resource->info->rec); if (!dav_repos_is_allow(principal, (dav_resource *)resource, DAV_PERMISSION_READ_CURRENT_USER_PRIVILEGE_SET)) return DAV_PROP_INSERT_FORBIDDEN; val = acl_current_user_privilege_set(resource); break; case DAV_PROPID_acl: principal = dav_principal_make_from_request(resource->info->rec); if (!dav_repos_is_allow(principal, (dav_resource *)resource, DAV_PERMISSION_READ_ACL)) return DAV_PROP_INSERT_FORBIDDEN; val = acl_build_propfind_output(resource); break; case DAV_PROPID_acl_restrictions: val = acl_restrictions(resource); break; case DAV_PROPID_inherited_acl_set: val = acl_inherited_acl_set(resource); break; case DAV_PROPID_principal_collection_set: if (db_r->resourcetype != dav_repos_GROUP) return DAV_PROP_INSERT_NOTSUPP; val = apr_psprintf(pool, "<D:href>%s%s</D:href><D:href>%s%s</D:href>", principal_href_prefix(r), PRINCIPAL_USER_PREFIX, principal_href_prefix(r), PRINCIPAL_GROUP_PREFIX); break; case DAV_PROPID_group_member_set: val = get_group_member_set(resource); break; } s = apr_psprintf(pool, "<D:%s>%s</D:%s>", name, val, name); apr_text_append(pool, phdr, s); return what; }