Ejemplo n.º 1
0
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);
    }

}
Ejemplo n.º 2
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>");
}
Ejemplo n.º 3
0
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);
}
Ejemplo n.º 4
0
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);
}
Ejemplo n.º 5
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;
}
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);
}
Ejemplo n.º 7
0
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);
}
Ejemplo n.º 8
0
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;
}
Ejemplo n.º 9
0
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);
}
Ejemplo n.º 11
0
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;
}
Ejemplo n.º 14
0
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;
}
Ejemplo n.º 15
0
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;
}
Ejemplo n.º 17
0
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;
}
Ejemplo n.º 18
0
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;
}
Ejemplo n.º 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;
}
Ejemplo n.º 20
0
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;
}