📄 props.c
字号:
/* ### 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) {
int 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,
"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;
}
DAV_DECLARE(void) dav_get_liveprop_supported(dav_propdb *propdb,
const char *ns_uri,
const char *propname,
apr_text_header *body)
{
int propid;
const dav_hooks_liveprop *hooks;
propid = dav_find_liveprop_provider(propdb, ns_uri, propname, &hooks);
if (propid != DAV_PROPID_CORE_UNKNOWN) {
if (hooks == NULL) {
/* this is a "core" property that we define */
dav_prop_insert unused_inserted;
dav_insert_coreprop(propdb, propid, propname,
DAV_PROP_INSERT_SUPPORTED, body, &unused_inserted);
}
else {
(*hooks->insert_prop)(propdb->resource, propid,
DAV_PROP_INSERT_SUPPORTED, body);
}
}
}
DAV_DECLARE_NONSTD(void) dav_prop_validate(dav_prop_ctx *ctx)
{
dav_propdb *propdb = ctx->propdb;
apr_xml_elem *prop = ctx->prop;
dav_elem_private *priv;
priv = ctx->prop->priv = apr_pcalloc(propdb->p, sizeof(*priv));
/*
** Check to see if this is a live property, and fill the fields
** in the XML elem, as appropriate.
**
** Verify that the property is read/write. If not, then it cannot
** be SET or DELETEd.
*/
if (priv->propid == 0) {
dav_find_liveprop(propdb, prop);
/* it's a liveprop if a provider was found */
/* ### actually the "core" props should really be liveprops, but
### there is no "provider" for those and the r/w props are
### treated as dead props anyhow */
ctx->is_liveprop = priv->provider != NULL;
}
if (!dav_rw_liveprop(propdb, priv)) {
ctx->err = dav_new_error(propdb->p, HTTP_CONFLICT,
DAV_ERR_PROP_READONLY,
"Property is read-only.");
return;
}
if (ctx->is_liveprop) {
int defer_to_dead = 0;
ctx->err = (*priv->provider->patch_validate)(propdb->resource,
prop, ctx->operation,
&ctx->liveprop_ctx,
&defer_to_dead);
if (ctx->err != NULL || !defer_to_dead)
return;
/* clear is_liveprop -- act as a dead prop now */
ctx->is_liveprop = 0;
}
/*
** The property is supposed to be stored into the dead-property
** database. Make sure the thing is truly open (and writable).
*/
if (propdb->deferred
&& (ctx->err = dav_really_open_db(propdb, 0 /* ro */)) != NULL) {
return;
}
/*
** There should be an open, writable database in here!
**
** Note: the database would be NULL if it was opened readonly and it
** did not exist.
*/
if (propdb->db == NULL) {
ctx->err = dav_new_error(propdb->p, HTTP_INTERNAL_SERVER_ERROR,
DAV_ERR_PROP_NO_DATABASE,
"Attempted to set/remove a property "
"without a valid, open, read/write "
"property database.");
return;
}
if (ctx->operation == DAV_PROP_OP_SET) {
/*
** Prep the element => propdb namespace index mapping, inserting
** namespace URIs into the propdb that don't exist.
*/
(void) (*propdb->db_hooks->map_namespaces)(propdb->db,
propdb->ns_xlate,
&propdb->mapping);
}
else if (ctx->operation == DAV_PROP_OP_DELETE) {
/*
** There are no checks to perform here. If a property exists, then
** we will delete it. If it does not exist, then it does not matter
** (see S12.13.1).
**
** Note that if a property does not exist, that does not rule out
** that a SET will occur during this PROPPATCH (thusly creating it).
*/
}
}
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);
}
}
DAV_DECLARE_NONSTD(void) dav_prop_commit(dav_prop_ctx *ctx)
{
dav_elem_private *priv = ctx->prop->priv;
/*
** Note that a commit implies ctx->err is NULL. The caller should assume
** a status of HTTP_OK for this case.
*/
if (ctx->is_liveprop) {
(*priv->provider->patch_commit)(ctx->propdb->resource,
ctx->operation,
ctx->liveprop_ctx,
ctx->rollback->liveprop);
}
}
DAV_DECLARE_NONSTD(void) dav_prop_rollback(dav_prop_ctx *ctx)
{
dav_error *err = NULL;
dav_elem_private *priv = ctx->prop->priv;
/* do nothing if there is no rollback information. */
if (ctx->rollback == NULL)
return;
/*
** ### if we have an error, and a rollback occurs, then the namespace
** ### mods should not happen at all. Basically, the namespace management
** ### is simply a bitch.
*/
if (ctx->is_liveprop) {
err = (*priv->provider->patch_rollback)(ctx->propdb->resource,
ctx->operation,
ctx->liveprop_ctx,
ctx->rollback->liveprop);
}
else {
err = (*ctx->propdb->db_hooks
->apply_rollback)(ctx->propdb->db, ctx->rollback->deadprop);
}
if (err != NULL) {
if (ctx->err == NULL)
ctx->err = err;
else {
dav_error *scan = err;
/* hook previous errors at the end of the rollback error */
while (scan->prev != NULL)
scan = scan->prev;
scan->prev = ctx->err;
ctx->err = err;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -