📄 props.c
字号:
size_t l_name = strlen(elem->name); dav_datum key = { 0 }; /* * Convert namespace ID to a string. "no namespace" is an empty string, * so the keys will have the form ":name". Otherwise, the keys will * have the form "#:name". */ if (elem->ns == AP_XML_NS_NONE) { nsbuf[0] = '\0'; l_ns = 0; } else { if (propdb->ns_map == NULL) { /* * Note that we prep the map and do NOT add namespaces. If that * is required, then the caller should have called prep * beforehand, passing the correct values. */ dav_prep_ns_map(propdb, 0); } ns = propdb->ns_map[elem->ns]; if (AP_XML_NS_IS_ERROR(ns)) return key; /* zeroed */ l_ns = sprintf(nsbuf, "%d", ns); } /* assemble: #:name */ dav_set_bufsize(propdb->p, &propdb->wb_key, l_ns + 1 + l_name + 1); memcpy(propdb->wb_key.buf, nsbuf, l_ns); propdb->wb_key.buf[l_ns] = ':'; memcpy(&propdb->wb_key.buf[l_ns + 1], elem->name, l_name + 1); /* build the database key */ key.dsize = l_ns + 1 + l_name + 1; key.dptr = propdb->wb_key.buf; return key;}static dav_error *dav_really_open_db(dav_propdb *propdb, int ro){ dav_error *err; dav_datum key; dav_datum value = { 0 }; /* we're trying to open the db; turn off the 'deferred' flag */ propdb->deferred = 0; /* ask the DB provider to open the thing */ err = (*propdb->db_hooks->open)(propdb->p, propdb->resource, ro, &propdb->db); if (err != NULL) { return dav_push_error(propdb->p, HTTP_INTERNAL_SERVER_ERROR, DAV_ERR_PROP_OPENING, "Could not open the property database.", err); } /* ** NOTE: propdb->db could be NULL if we attempted to open a readonly ** database that doesn't exist. If we require read/write ** access, then a database was created and opened. */ if (propdb->db != NULL) { key.dptr = DAV_GDBM_NS_KEY; key.dsize = DAV_GDBM_NS_KEY_LEN; if ((err = (*propdb->db_hooks->fetch)(propdb->db, key, &value)) != NULL) { /* ### push a higher-level description? */ return err; } } if (value.dptr == NULL) { dav_propdb_metadata m = { DAV_DBVSN_MAJOR, DAV_DBVSN_MINOR, 0 }; if (propdb->db != NULL) { /* * If there is no METADATA key, then the database may be * from versions 0.9.0 .. 0.9.4 (which would be incompatible). * These can be identified by the presence of an NS_TABLE entry. */ key.dptr = "NS_TABLE"; key.dsize = 8; if ((*propdb->db_hooks->exists)(propdb->db, key)) { (*propdb->db_hooks->close)(propdb->db); /* call it a major version error */ return dav_new_error(propdb->p, HTTP_INTERNAL_SERVER_ERROR, DAV_ERR_PROP_BAD_MAJOR, "Prop database has the wrong major " "version number and cannot be used."); } } /* initialize a new metadata structure */ dav_set_bufsize(propdb->p, &propdb->ns_table, sizeof(m)); memcpy(propdb->ns_table.buf, &m, sizeof(m)); } else { dav_propdb_metadata m; dav_set_bufsize(propdb->p, &propdb->ns_table, value.dsize); memcpy(propdb->ns_table.buf, value.dptr, value.dsize); memcpy(&m, value.dptr, sizeof(m)); if (m.major != DAV_DBVSN_MAJOR) { (*propdb->db_hooks->close)(propdb->db); return dav_new_error(propdb->p, HTTP_INTERNAL_SERVER_ERROR, DAV_ERR_PROP_BAD_MAJOR, "Prop database has the wrong major " "version number and cannot be used."); } propdb->version = m.minor; propdb->ns_count = ntohs(m.ns_count); (*propdb->db_hooks->freedatum)(propdb->db, value); } return NULL;}dav_error *dav_open_propdb(request_rec *r, dav_lockdb *lockdb, const dav_resource *resource, int ro, apr_array_header_t * ns_xlate, dav_propdb **p_propdb){ dav_propdb *propdb = apr_pcalloc(r->pool, sizeof(*propdb)); *p_propdb = NULL;#if DAV_DEBUG if (resource->uri == NULL) { return dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0, "INTERNAL DESIGN ERROR: resource must define " "its URI."); }#endif propdb->version = DAV_DBVSN_MINOR; propdb->r = r; propdb->p = r->pool; /* ### get rid of this */ propdb->resource = resource; propdb->ns_xlate = ns_xlate; propdb->db_hooks = DAV_GET_HOOKS_PROPDB(r); propdb->lockdb = lockdb; /* always defer actual open, to avoid expense of accessing db * when only live properties are involved */ propdb->deferred = 1; /* ### what to do about closing the propdb on server failure? */ *p_propdb = propdb; return NULL;}void dav_close_propdb(dav_propdb *propdb){ if (propdb->db == NULL) return; if (propdb->ns_table_dirty) { dav_propdb_metadata m; dav_datum key; dav_datum value; dav_error *err; key.dptr = DAV_GDBM_NS_KEY; key.dsize = DAV_GDBM_NS_KEY_LEN; value.dptr = propdb->ns_table.buf; value.dsize = propdb->ns_table.cur_len; /* fill in the metadata that we store into the prop db. */ m.major = DAV_DBVSN_MAJOR; m.minor = propdb->version; /* ### keep current minor version? */ m.ns_count = htons(propdb->ns_count); memcpy(propdb->ns_table.buf, &m, sizeof(m)); err = (*propdb->db_hooks->store)(propdb->db, key, value); /* ### what to do with the error? */ } (*propdb->db_hooks->close)(propdb->db);}dav_get_props_result dav_get_allprops(dav_propdb *propdb, dav_prop_insert what){ const dav_hooks_db *db_hooks = propdb->db_hooks; ap_text_header hdr = { 0 }; ap_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*/); } /* generate all the namespaces that are in the propdb */ dav_get_propdb_xmlns(propdb, &hdr_ns); /* initialize the result with some start tags... */ ap_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_datum key; int dav_id = dav_find_dav_id(propdb); (void) (*db_hooks->firstkey)(propdb->db, &key); while (key.dptr) { dav_datum prevkey; /* any keys with leading capital letters should be skipped (real keys start with a number or a colon) */ if (*key.dptr >= 'A' && *key.dptr <= 'Z') goto next_key; /* ** 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 (dav_id != -1 && *key.dptr != ':' && dav_id == atoi(key.dptr)) { const char *colon; /* find the colon */ if ( key.dptr[1] == ':' ) { colon = key.dptr + 1; } else { colon = strchr(key.dptr + 2, ':'); } if (colon[1] == 'g') { if (strcmp(colon + 1, "getcontenttype") == 0) { found_contenttype = 1; } else if (strcmp(colon + 1, "getcontentlanguage") == 0) { found_contentlang = 1; } } } if (what == DAV_PROP_INSERT_VALUE) { dav_datum value; (void) (*db_hooks->fetch)(propdb->db, key, &value); if (value.dptr == NULL) { /* ### anything better to do? */ /* ### probably should enter a 500 error */ goto next_key; } /* put the prop name and value into the result */ dav_append_prop(propdb, key.dptr, value.dptr, &hdr); (*db_hooks->freedatum)(propdb->db, value); } else { /* simple, empty element if a value isn't needed */ dav_append_prop(propdb, key.dptr, DAV_EMPTY_VALUE, &hdr); } next_key: prevkey = key; (void) (*db_hooks->nextkey)(propdb->db, &key); (*db_hooks->freedatum)(propdb->db, prevkey); } } /* 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) { ap_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_get_props_result dav_get_props(dav_propdb *propdb, ap_xml_doc *doc){ const dav_hooks_db *db_hooks = propdb->db_hooks; ap_xml_elem *elem = dav_find_child(doc->root, "prop"); ap_text_header hdr_good = { 0 }; ap_text_header hdr_bad = { 0 }; ap_text_header hdr_ns = { 0 }; int have_good = 0; int propdb_xmlns_done = 0; dav_get_props_result result = { 0 }; char *marks_input; char *marks_liveprop; /* ### 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 */ ap_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 input namespaces we've generated into the output xmlns buffer */ marks_input = apr_pcalloc(propdb->p, propdb->ns_xlate->nelts); /* same for the liveprops */ marks_liveprop = apr_pcalloc(propdb->p, dav_get_liveprop_ns_count() + 1); for (elem = elem->first_child; elem; elem = elem->next) { dav_datum key = { 0 }; dav_datum value = { 0 }; dav_elem_private *priv; dav_error *err; dav_prop_insert inserted; int is_liveprop = 0; /* ** First try live property providers; if they don't handle ** the property, then try looking it up in the propdb. */ if (elem->private == NULL) { elem->private = apr_pcalloc(propdb->p, sizeof(*priv)); } priv = elem->private; /* 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) { is_liveprop = 1; /* insert the property. returns 1 if an insertion was done. */ if ((err = dav_insert_liveprop(propdb, elem, DAV_PROP_INSERT_VALUE,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -