📄 props.c
字号:
&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) { 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); } } continue; } else if (inserted == DAV_PROP_INSERT_NOTDEF) { /* allow property to be handled as a dead property */ is_liveprop = 0; } } /* ** If not handled as a live property, look in the dead property ** database. */ if (!is_liveprop) { /* 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 not done yet, * generate all the namespaces that are in the propdb */ if (!propdb_xmlns_done) { dav_get_propdb_xmlns(propdb, &hdr_ns); propdb_xmlns_done = 1; } /* ** Note: the key may be NULL if we have no properties that are in ** a namespace that matches the requested prop's namespace. */ key = dav_gdbm_key(propdb, elem); /* fetch IF we have a db and a key. otherwise, value is NULL */ if (propdb->db != NULL && key.dptr != NULL) { (void) (*db_hooks->fetch)(propdb->db, key, &value); } } if (value.dptr == NULL) { /* not found. add a record to the "bad" propstats */ /* make sure we've started our "bad" propstat */ if (hdr_bad.first == NULL) { ap_text_append(propdb->p, &hdr_bad, "<D:propstat>" DEBUG_CR "<D:prop>" DEBUG_CR); } /* note: key.dptr may be NULL if the propdb doesn't have an equivalent namespace stored */ if (key.dptr == NULL) { const char *s; if (elem->ns == AP_XML_NS_NONE) { /* * elem has a prefix already (xml...:name) or the elem * simply has no namespace. */ s = apr_psprintf(propdb->p, "<%s/>" DEBUG_CR, elem->name); } else { /* ensure that an xmlns is generated for the input namespace */ dav_add_marked_xmlns(propdb, marks_input, elem->ns, propdb->ns_xlate, "i", &hdr_ns); s = apr_psprintf(propdb->p, "<i%d:%s/>" DEBUG_CR, elem->ns, elem->name); } ap_text_append(propdb->p, &hdr_bad, s); } else { /* add in the bad prop using our namespace decl */ dav_append_prop(propdb, key.dptr, DAV_EMPTY_VALUE, &hdr_bad); } } else { /* found it. put the value into the "good" propstats */ have_good = 1; dav_append_prop(propdb, key.dptr, value.dptr, &hdr_good); (*db_hooks->freedatum)(propdb->db, value); } } ap_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) { ap_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; } } result.xmlns = hdr_ns.first; return result;}void dav_get_liveprop_supported(dav_propdb *propdb, const char *ns_uri, const char *propname, ap_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); } }}void dav_prop_validate(dav_prop_ctx *ctx){ dav_propdb *propdb = ctx->propdb; ap_xml_elem *prop = ctx->prop; dav_elem_private *priv; priv = ctx->prop->private = 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. */ dav_prep_ns_map(propdb, 1); } 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). */ }}void dav_prop_exec(dav_prop_ctx *ctx){ dav_propdb *propdb = ctx->propdb; dav_error *err = NULL; dav_rollback_item *rollback; dav_elem_private *priv = ctx->prop->private; rollback = apr_pcalloc(propdb->p, sizeof(*rollback)); ctx->rollback = rollback; if (ctx->is_liveprop) { err = (*priv->provider->patch_exec)(propdb->resource, ctx->prop, ctx->operation, ctx->liveprop_ctx, &ctx->rollback->liveprop); } else { dav_datum key; /* we're going to need the key for all operations */ key = dav_gdbm_key(propdb, ctx->prop); /* save the old value so that we can do a rollback. */ rollback->key = key; if ((err = (*propdb->db_hooks->fetch)(propdb->db, key, &rollback->value)) != NULL) goto error; if (ctx->operation == DAV_PROP_OP_SET) { dav_datum value; /* Note: propdb->ns_map was set in dav_prop_validate() */ /* quote all the values in the element */ ap_xml_quote_elem(propdb->p, ctx->prop); /* generate a text blob for the xml:lang plus the contents */ ap_xml_to_text(propdb->p, ctx->prop, AP_XML_X2T_LANG_INNER, NULL, propdb->ns_map, (const char **)&value.dptr, &value.dsize); err = (*propdb->db_hooks->store)(propdb->db, key, value); /* ** 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. */ } 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, key); } } 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); }}void dav_prop_commit(dav_prop_ctx *ctx){ dav_elem_private *priv = ctx->prop->private; /* ** 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); }}void dav_prop_rollback(dav_prop_ctx *ctx){ dav_error *err = NULL; dav_elem_private *priv = ctx->prop->private; /* 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 if (ctx->rollback->value.dptr == NULL) { /* don't fail if the thing isn't really there */ /* ### but what about other errors? */ (void) (*ctx->propdb->db_hooks->remove)(ctx->propdb->db, ctx->rollback->key); } else { err = (*ctx->propdb->db_hooks->store)(ctx->propdb->db, ctx->rollback->key, ctx->rollback->value); } 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 + -