コード例 #1
0
ファイル: apr_xml.c プロジェクト: Ga-vin/apache
/* convert the whole document to EBCDIC */
APU_DECLARE(apr_status_t) apr_xml_parser_convert_doc(apr_pool_t *pool,
        apr_xml_doc *pdoc,
        apr_xlate_t *convset)
{
    apr_status_t status;
    /* Don't convert the namespaces: they are constant! */
    if (pdoc->namespaces != NULL) {
        int i;
        apr_array_header_t *namespaces;
        namespaces = apr_array_make(pool, pdoc->namespaces->nelts, sizeof(const char *));
        if (namespaces == NULL)
            return APR_ENOMEM;
        for (i = 0; i < pdoc->namespaces->nelts; i++) {
            apr_size_t inbytes_left, outbytes_left;
            char *ptr = (char *) APR_XML_GET_URI_ITEM(pdoc->namespaces, i);
            ptr = apr_pstrdup(pool, ptr);
            if ( ptr == NULL)
                return APR_ENOMEM;
            inbytes_left = outbytes_left = strlen(ptr);
            status = apr_xlate_conv_buffer(convset, ptr, &inbytes_left, ptr, &outbytes_left);
            if (status) {
                return status;
            }
            apr_xml_insert_uri(namespaces, ptr);
        }
        pdoc->namespaces = namespaces;
    }
    return apr_xml_parser_convert_elem(pdoc->root, convset);
}
コード例 #2
0
ファイル: apr_xml.c プロジェクト: Ga-vin/apache
/* return the URI's (existing) index, or insert it and return a new index */
APU_DECLARE(int) apr_xml_insert_uri(apr_array_header_t *uri_array,
                                    const char *uri)
{
    int i;
    const char **pelt;

    /* never insert an empty URI; this index is always APR_XML_NS_NONE */
    if (*uri == '\0')
        return APR_XML_NS_NONE;

    for (i = uri_array->nelts; i--;) {
        if (strcmp(uri, APR_XML_GET_URI_ITEM(uri_array, i)) == 0)
            return i;
    }

    pelt = apr_array_push(uri_array);
    *pelt = uri;		/* assume uri is const or in a pool */
    return uri_array->nelts - 1;
}
コード例 #3
0
static void dav_find_liveprop(dav_propdb *propdb, apr_xml_elem *elem)
{
    const char *ns_uri;
    dav_elem_private *priv = elem->priv;
    const dav_hooks_liveprop *hooks;


    if (elem->ns == APR_XML_NS_NONE)
        ns_uri = NULL;
    else if (elem->ns == APR_XML_NS_DAV_ID)
        ns_uri = "DAV:";
    else
        ns_uri = APR_XML_GET_URI_ITEM(propdb->ns_xlate, elem->ns);

    priv->propid = dav_find_liveprop_provider(propdb, ns_uri, elem->name,
                                              &hooks);

    /* ### this test seems redundant... */
    if (priv->propid != DAV_PROPID_CORE_UNKNOWN) {
        priv->provider = hooks;
    }
}
コード例 #4
0
DAV_DECLARE_NONSTD(void) dav_prop_exec(dav_prop_ctx *ctx)
{
    dav_propdb *propdb = ctx->propdb;
    dav_error *err = NULL;
    dav_elem_private *priv = ctx->prop->priv;

    ctx->rollback = apr_pcalloc(propdb->p, sizeof(*ctx->rollback));

    if (ctx->is_liveprop) {
        err = (*priv->provider->patch_exec)(propdb->resource,
                                            ctx->prop, ctx->operation,
                                            ctx->liveprop_ctx,
                                            &ctx->rollback->liveprop);
    }
    else {
        dav_prop_name name;

        if (ctx->prop->ns == APR_XML_NS_NONE)
            name.ns = "";
        else
            name.ns = APR_XML_GET_URI_ITEM(propdb->ns_xlate, ctx->prop->ns);
        name.name = ctx->prop->name;

        /* save the old value so that we can do a rollback. */
        if ((err = (*propdb->db_hooks
                    ->get_rollback)(propdb->db, &name,
                                    &ctx->rollback->deadprop)) != NULL)
            goto error;

        if (ctx->operation == DAV_PROP_OP_SET) {

            /* Note: propdb->mapping was set in dav_prop_validate() */
            err = (*propdb->db_hooks->store)(propdb->db, &name, ctx->prop,
                                             propdb->mapping);

            /*
            ** If an error occurred, then assume that we didn't change the
            ** value. Remove the rollback item so that we don't try to set
            ** its value during the rollback.
            */
            /* ### euh... where is the removal? */
        }
        else if (ctx->operation == DAV_PROP_OP_DELETE) {

            /*
            ** Delete the property. Ignore errors -- the property is there, or
            ** we are deleting it for a second time.
            */
            /* ### but what about other errors? */
            (void) (*propdb->db_hooks->remove)(propdb->db, &name);
        }
    }

  error:
    /* push a more specific error here */
    if (err != NULL) {
        /*
        ** Use HTTP_INTERNAL_SERVER_ERROR because we shouldn't have seen
        ** any errors at this point.
        */
        ctx->err = dav_push_error(propdb->p, HTTP_INTERNAL_SERVER_ERROR,
                                  DAV_ERR_PROP_EXEC,
                                  "Could not execute PROPPATCH.", err);
    }
}
コード例 #5
0
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;
}
コード例 #6
0
ファイル: props.c プロジェクト: tolsen/limestone-httpd
DAV_DECLARE_NONSTD(void) dav_prop_exec(dav_prop_ctx *ctx)
{
    dav_propdb *propdb = ctx->propdb;
    dav_error *err = NULL;
    dav_elem_private *priv = ctx->prop->priv;
    const dav_hooks_acl *acl_hooks = dav_get_acl_hooks(ctx->r);
    dav_prop_name name;

    ctx->rollback = apr_pcalloc(propdb->p, sizeof(*ctx->rollback));

    if (ctx->prop->ns == APR_XML_NS_NONE)
        name.ns = "";
    else
        name.ns = APR_XML_GET_URI_ITEM(propdb->ns_xlate, ctx->prop->ns);
    name.name = ctx->prop->name;


    if (ctx->is_liveprop) {
        err = (*priv->provider->patch_exec)(propdb->resource,
                                            ctx->prop, ctx->operation,
                                            ctx->liveprop_ctx,
                                            &ctx->rollback->liveprop);
    }
    else {
        /* save the old value so that we can do a rollback. */
        if ((err = (*propdb->db_hooks
                    ->get_rollback)(propdb->db, &name,
                                    &ctx->rollback->deadprop)) != NULL)
            goto error;

        if (ctx->operation == DAV_PROP_OP_SET) {

            /* Note: propdb->mapping was set in dav_prop_validate() */
            err = (*propdb->db_hooks->store)(propdb->db, &name, ctx->prop,
                                             propdb->mapping);

            /*
            ** If an error occurred, then assume that we didn't change the
            ** value. Remove the rollback item so that we don't try to set
            ** its value during the rollback.
            */
            /* ### euh... where is the removal? */
        }
        else if (ctx->operation == DAV_PROP_OP_DELETE) {

            /*
            ** Delete the property. Ignore errors -- the property is there, or
            ** we are deleting it for a second time.
            */
            /* ### but what about other errors? */
            (void) (*propdb->db_hooks->remove)(propdb->db, &name);
        }
    }

    if(acl_hooks) {

        /* update any DAV:property ACE(s) that depend on this property */
        const char *newval = 
            dav_xml_get_cdata(dav_find_child(ctx->prop, "href"), propdb->p, 1);

        /* @NOTE: works only in presence of transactions,
         * currently no rollback state being stored for ACE changes */
        /* assuming cdata is NULL for D:remove prop elem */
        if(newval)
            (*acl_hooks->update_principal_property_aces)(
                (dav_resource *)propdb->resource, &name, newval);
    }

error:
    /* push a more specific error here */
    if (err != NULL) {
        if (err->status == HTTP_CONFLICT) {
            /* semantics of the value are not appropriate for the property */
            ctx->err = err;
        } else {
            /*
            ** Use HTTP_INTERNAL_SERVER_ERROR because we shouldn't have seen
            ** any other errors at this point.
            */
            ctx->err = dav_push_error(propdb->p, HTTP_INTERNAL_SERVER_ERROR,
                                      DAV_ERR_PROP_EXEC,
                                      "Could not execute PROPPATCH.", err);
        }
    }
}
コード例 #7
0
ファイル: apr_xml.c プロジェクト: Ga-vin/apache
static char *write_elem(char *s, const apr_xml_elem *elem, int style,
                        apr_array_header_t *namespaces, int *ns_map)
{
    const apr_xml_elem *child;
    apr_size_t len;
    int ns;

    if (style == APR_XML_X2T_FULL || style == APR_XML_X2T_FULL_NS_LANG) {
        int empty = APR_XML_ELEM_IS_EMPTY(elem);
        const apr_xml_attr *attr;

        if (elem->ns == APR_XML_NS_NONE) {
            len = sprintf(s, "<%s", elem->name);
        }
        else {
            ns = ns_map ? ns_map[elem->ns] : elem->ns;
            len = sprintf(s, "<ns%d:%s", ns, elem->name);
        }
        s += len;

        for (attr = elem->attr; attr; attr = attr->next) {
            if (attr->ns == APR_XML_NS_NONE)
                len = sprintf(s, " %s=\"%s\"", attr->name, attr->value);
            else {
                ns = ns_map ? ns_map[attr->ns] : attr->ns;
                len = sprintf(s, " ns%d:%s=\"%s\"", ns, attr->name, attr->value);
            }
            s += len;
        }

        /* add the xml:lang value if necessary */
        if (elem->lang != NULL &&
                (style == APR_XML_X2T_FULL_NS_LANG ||
                 elem->parent == NULL ||
                 elem->lang != elem->parent->lang)) {
            len = sprintf(s, " xml:lang=\"%s\"", elem->lang);
            s += len;
        }

        /* add namespace definitions, if required */
        if (style == APR_XML_X2T_FULL_NS_LANG) {
            int i;

            for (i = namespaces->nelts; i--;) {
                len = sprintf(s, " xmlns:ns%d=\"%s\"", i,
                              APR_XML_GET_URI_ITEM(namespaces, i));
                s += len;
            }
        }

        /* no more to do. close it up and go. */
        if (empty) {
            *s++ = '/';
            *s++ = '>';
            return s;
        }

        /* just close it */
        *s++ = '>';
    }
    else if (style == APR_XML_X2T_LANG_INNER) {
        /* prepend the xml:lang value */
        if (elem->lang != NULL) {
            len = strlen(elem->lang);
            memcpy(s, elem->lang, len);
            s += len;
        }
        *s++ = '\0';
    }

    s = write_text(s, elem->first_cdata.first);

    for (child = elem->first_child; child; child = child->next) {
        s = write_elem(s, child, APR_XML_X2T_FULL, NULL, ns_map);
        s = write_text(s, child->following_cdata.first);
    }

    if (style == APR_XML_X2T_FULL || style == APR_XML_X2T_FULL_NS_LANG) {
        if (elem->ns == APR_XML_NS_NONE) {
            len = sprintf(s, "</%s>", elem->name);
        }
        else {
            ns = ns_map ? ns_map[elem->ns] : elem->ns;
            len = sprintf(s, "</ns%d:%s>", ns, elem->name);
        }
        s += len;
    }

    return s;
}
コード例 #8
0
ファイル: apr_xml.c プロジェクト: Ga-vin/apache
static apr_size_t elem_size(const apr_xml_elem *elem, int style,
                            apr_array_header_t *namespaces, int *ns_map)
{
    apr_size_t size;

    if (style == APR_XML_X2T_FULL || style == APR_XML_X2T_FULL_NS_LANG) {
        const apr_xml_attr *attr;

        size = 0;

        if (style == APR_XML_X2T_FULL_NS_LANG) {
            int i;

            /*
            ** The outer element will contain xmlns:ns%d="%s" attributes
            ** and an xml:lang attribute, if applicable.
            */

            for (i = namespaces->nelts; i--;) {
                /* compute size of: ' xmlns:ns%d="%s"' */
                size += (9 + APR_XML_NS_LEN(i) + 2 +
                         strlen(APR_XML_GET_URI_ITEM(namespaces, i)) + 1);
            }

            if (elem->lang != NULL) {
                /* compute size of: ' xml:lang="%s"' */
                size += 11 + strlen(elem->lang) + 1;
            }
        }

        if (elem->ns == APR_XML_NS_NONE) {
            /* compute size of: <%s> */
            size += 1 + strlen(elem->name) + 1;
        }
        else {
            int ns = ns_map ? ns_map[elem->ns] : elem->ns;

            /* compute size of: <ns%d:%s> */
            size += 3 + APR_XML_NS_LEN(ns) + 1 + strlen(elem->name) + 1;
        }

        if (APR_XML_ELEM_IS_EMPTY(elem)) {
            /* insert a closing "/" */
            size += 1;
        }
        else {
            /*
             * two of above plus "/":
             *     <ns%d:%s> ... </ns%d:%s>
             * OR  <%s> ... </%s>
             */
            size = 2 * size + 1;
        }

        for (attr = elem->attr; attr; attr = attr->next) {
            if (attr->ns == APR_XML_NS_NONE) {
                /* compute size of: ' %s="%s"' */
                size += 1 + strlen(attr->name) + 2 + strlen(attr->value) + 1;
            }
            else {
                /* compute size of: ' ns%d:%s="%s"' */
                int ns = ns_map ? ns_map[attr->ns] : attr->ns;
                size += 3 + APR_XML_NS_LEN(ns) + 1 + strlen(attr->name) + 2 + strlen(attr->value) + 1;
            }
        }

        /*
        ** If the element has an xml:lang value that is *different* from
        ** its parent, then add the thing in: ' xml:lang="%s"'.
        **
        ** NOTE: we take advantage of the pointer equality established by
        ** the parsing for "inheriting" the xml:lang values from parents.
        */
        if (elem->lang != NULL &&
                (elem->parent == NULL || elem->lang != elem->parent->lang)) {
            size += 11 + strlen(elem->lang) + 1;
        }
    }
    else if (style == APR_XML_X2T_LANG_INNER) {
        /*
         * This style prepends the xml:lang value plus a null terminator.
         * If a lang value is not present, then we insert a null term.
         */
        size = elem->lang ? strlen(elem->lang) + 1 : 1;
    }
    else
        size = 0;

    size += text_size(elem->first_cdata.first);

    for (elem = elem->first_child; elem; elem = elem->next) {
        /* the size of the child element plus the CDATA that follows it */
        size += (elem_size(elem, APR_XML_X2T_FULL, NULL, ns_map) +
                 text_size(elem->following_cdata.first));
    }

    return size;
}