📄 fetch.c
字号:
propval = apr_hash_get(resource->propset, SVN_RA_DAV__PROP_GETCONTENTLENGTH, APR_HASH_KEY_STRING); if (propval == NULL) entry->size = 0; else entry->size = svn__atoui64(propval->data); } if (dirent_fields & SVN_DIRENT_HAS_PROPS) { /* Does this resource contain any 'svn' or 'custom' properties (e.g. ones actually created and set by the user)? */ if (supports_deadprop_count) { propval = apr_hash_get(resource->propset, SVN_RA_DAV__PROP_DEADPROP_COUNT, APR_HASH_KEY_STRING); if (propval == NULL) { /* we thought that the server supported the deadprop-count property. apparently not. */ return svn_error_create(SVN_ERR_INCOMPLETE_DATA, NULL, _("Server response missing the " "expected deadprop-count " "property")); } else { apr_int64_t prop_count = svn__atoui64(propval->data); entry->has_props = (prop_count > 0); } } else { /* The server doesn't support the deadprop_count prop, fallback */ for (h = apr_hash_first(pool, resource->propset); h; h = apr_hash_next(h)) { const void *kkey; void *vval; apr_hash_this(h, &kkey, NULL, &vval); if (strncmp((const char *) kkey, SVN_DAV_PROP_NS_CUSTOM, sizeof(SVN_DAV_PROP_NS_CUSTOM) - 1) == 0 || strncmp((const char *) kkey, SVN_DAV_PROP_NS_SVN, sizeof(SVN_DAV_PROP_NS_SVN) - 1) == 0) entry->has_props = TRUE; } } } if (dirent_fields & SVN_DIRENT_CREATED_REV) { /* created_rev & friends */ propval = apr_hash_get(resource->propset, SVN_RA_DAV__PROP_VERSION_NAME, APR_HASH_KEY_STRING); if (propval != NULL) entry->created_rev = SVN_STR_TO_REV(propval->data); } if (dirent_fields & SVN_DIRENT_TIME) { propval = apr_hash_get(resource->propset, SVN_RA_DAV__PROP_CREATIONDATE, APR_HASH_KEY_STRING); if (propval != NULL) SVN_ERR(svn_time_from_cstring(&(entry->time), propval->data, pool)); } if (dirent_fields & SVN_DIRENT_LAST_AUTHOR) { propval = apr_hash_get(resource->propset, SVN_RA_DAV__PROP_CREATOR_DISPLAYNAME, APR_HASH_KEY_STRING); if (propval != NULL) entry->last_author = propval->data; } apr_hash_set(*dirents, svn_path_uri_decode(svn_path_basename(childname, pool), pool), APR_HASH_KEY_STRING, entry); } } if (props) { SVN_ERR(svn_ra_dav__get_props_resource(&rsrc, ras->sess, final_url, NULL, NULL /* all props */, pool)); *props = apr_hash_make(pool); SVN_ERR(filter_props(*props, rsrc, TRUE, pool)); } return SVN_NO_ERROR;}/* ------------------------------------------------------------------------- */svn_error_t *svn_ra_dav__get_latest_revnum(svn_ra_session_t *session, svn_revnum_t *latest_revnum, apr_pool_t *pool){ svn_ra_dav__session_t *ras = session->priv; /* ### should we perform an OPTIONS to validate the server we're about ### to talk to? */ /* we don't need any of the baseline URLs and stuff, but this does give us the latest revision number */ SVN_ERR(svn_ra_dav__get_baseline_info(NULL, NULL, NULL, latest_revnum, ras->sess, ras->root.path, SVN_INVALID_REVNUM, pool)); SVN_ERR(svn_ra_dav__maybe_store_auth_info(ras, pool)); return NULL;}/* -------------------------------------------------------------------------**** DATED REV REPORT HANDLING**** DeltaV provides no mechanism for mapping a date to a revision, so** we use a custom report, S:dated-rev-report. The request contains a** DAV:creationdate element giving the requested date; the response** contains a DAV:version-name element giving the most recent revision** as of that date.**** Since this report is so simple, we don't bother with validation or** baton structures or anything; we just set the revision number in** the end-element handler for DAV:version-name.*//* This implements the `svn_ra_dav__xml_validate_cb' prototype. */static int drev_validate_element(void *userdata, svn_ra_dav__xml_elmid parent, svn_ra_dav__xml_elmid child){ return SVN_RA_DAV__XML_VALID;}/* This implements the `svn_ra_dav__xml_startelm_cb' prototype. */static int drev_start_element(void *userdata, const svn_ra_dav__xml_elm_t *elm, const char **atts){ return SVN_RA_DAV__XML_VALID;}/* This implements the `svn_ra_dav__xml_endelm_cb' prototype. */static int drev_end_element(void *userdata, const svn_ra_dav__xml_elm_t *elm, const char *cdata){ if (elm->id == ELEM_version_name) *((svn_revnum_t *) userdata) = SVN_STR_TO_REV(cdata); return SVN_RA_DAV__XML_VALID;}svn_error_t *svn_ra_dav__get_dated_revision(svn_ra_session_t *session, svn_revnum_t *revision, apr_time_t timestamp, apr_pool_t *pool){ svn_ra_dav__session_t *ras = session->priv; const char *body; const char *vcc_url; svn_error_t *err; /* Run the 'dated-rev-report' on the VCC url, which is always guaranteed to exist. */ SVN_ERR(svn_ra_dav__get_vcc(&vcc_url, ras->sess, ras->root.path, pool)); body = apr_psprintf(pool, "<?xml version=\"1.0\" encoding=\"utf-8\"?>" "<S:dated-rev-report xmlns:S=\"" SVN_XML_NAMESPACE "\" " "xmlns:D=\"DAV:\">" "<D:creationdate>%s</D:creationdate>" "</S:dated-rev-report>", svn_time_to_cstring(timestamp, pool)); *revision = SVN_INVALID_REVNUM; err = svn_ra_dav__parsed_request_compat(ras->sess, "REPORT", vcc_url, body, NULL, NULL, drev_report_elements, drev_validate_element, drev_start_element, drev_end_element, revision, NULL, NULL, FALSE, pool); if (err && err->apr_err == SVN_ERR_UNSUPPORTED_FEATURE) return svn_error_quick_wrap(err, _("Server does not support date-based " "operations")); else if (err) return err; if (*revision == SVN_INVALID_REVNUM) return svn_error_create(SVN_ERR_INCOMPLETE_DATA, NULL, _("Invalid server response to dated-rev request")); return SVN_NO_ERROR;}typedef struct { svn_ra_dav__session_t *ras; apr_hash_t *hash; apr_pool_t *pool;} get_locations_baton_t;/* * Plan for processing the XML. The XML will be of the form: * * <S:get-locations-report xmlns...> * <S:location rev="..." path="..."/> * ... * </S:get-locations-report> * * We extract what we want at the start of <S:location>. *//* Elements used in a get-locations response */static const svn_ra_dav__xml_elm_t gloc_report_elements[] ={ { SVN_XML_NAMESPACE, "get-locations-report", ELEM_get_locations_report, 0 }, { SVN_XML_NAMESPACE, "location", ELEM_location, 0 }, { NULL }};/* This implements the `ne_xml_startelem_cb' prototype. */static int gloc_start_element(void *userdata, int parent_state, const char *ns, const char *ln, const char **atts){ get_locations_baton_t *baton = userdata; const svn_ra_dav__xml_elm_t *elm; elm = svn_ra_dav__lookup_xml_elem(gloc_report_elements, ns, ln); /* Just skip unknown elements. */ if (!elm) return NE_XML_DECLINE; if (parent_state == ELEM_get_locations_report && elm->id == ELEM_location) { svn_revnum_t rev = SVN_INVALID_REVNUM; const char *path; const char *r; r = svn_xml_get_attr_value("rev", atts); if (r) rev = SVN_STR_TO_REV(r); path = svn_xml_get_attr_value("path", atts); if (SVN_IS_VALID_REVNUM(rev) && path) apr_hash_set(baton->hash, apr_pmemdup(baton->pool, &rev, sizeof(rev)), sizeof(rev), apr_pstrdup(baton->pool, path)); else return NE_XML_ABORT; } return elm->id;}svn_error_t *svn_ra_dav__get_locations(svn_ra_session_t *session, apr_hash_t **locations, const char *relative_path, svn_revnum_t peg_revision, apr_array_header_t *location_revisions, apr_pool_t *pool){ svn_ra_dav__session_t *ras = session->priv; svn_stringbuf_t *request_body; svn_error_t *err; get_locations_baton_t request_baton; const char *relative_path_quoted; svn_string_t bc_url, bc_relative; const char *final_bc_url; int i; int status_code = 0; *locations = apr_hash_make(pool); request_body = svn_stringbuf_create("", pool); svn_stringbuf_appendcstr(request_body, "<?xml version=\"1.0\" encoding=\"utf-8\"?>" DEBUG_CR "<S:get-locations xmlns:S=\"" SVN_XML_NAMESPACE "\" xmlns:D=\"DAV:\">" DEBUG_CR); svn_stringbuf_appendcstr(request_body, "<S:path>"); /* We need to escape the path XML-wise. */ relative_path_quoted = apr_xml_quote_string(pool, relative_path, 0); svn_stringbuf_appendcstr(request_body, relative_path_quoted); svn_stringbuf_appendcstr(request_body, "</S:path>" DEBUG_CR); svn_stringbuf_appendcstr(request_body, apr_psprintf(pool, "<S:peg-revision>%ld" "</S:peg-revision>" DEBUG_CR, peg_revision)); for (i = 0; i < location_revisions->nelts; ++i) { svn_revnum_t rev = APR_ARRAY_IDX(location_revisions, i, svn_revnum_t); svn_stringbuf_appendcstr(request_body, apr_psprintf(pool, "<S:location-revision>%ld" "</S:location-revision>" DEBUG_CR, rev)); } svn_stringbuf_appendcstr(request_body, "</S:get-locations>"); request_baton.ras = ras; request_baton.hash = *locations; request_baton.pool = pool; /* ras's URL may not exist in HEAD, and thus it's not safe to send it as the main argument to the REPORT request; it might cause dav_get_resource() to choke on the server. So instead, we pass a baseline-collection URL, which we get from the peg revision. */ SVN_ERR(svn_ra_dav__get_baseline_info(NULL, &bc_url, &bc_relative, NULL, ras->sess, ras->url->data, peg_revision, pool)); final_bc_url = svn_path_url_add_component(bc_url.data, bc_relative.data, pool); err = svn_ra_dav__parsed_request(ras->sess, "REPORT", final_bc_url, request_body->data, NULL, NULL, gloc_start_element, NULL, NULL, &request_baton, NULL, &status_code, FALSE, pool); /* Map status 501: Method Not Implemented to our not implemented error. 1.0.x servers and older don't support this report. */ if (status_code == 501) return svn_error_create(SVN_ERR_RA_NOT_IMPLEMENTED, err, _("'get-locations' REPORT not implemented")); return err;}/* -------------------------------------------------------------------------**** GET-LOCKS REPORT HANDLING**** DeltaV provides a mechanism for fetching a list of locks below a** path, but it's often unscalable. It requires doing a PROPFIND of** depth infinity, looking for the 'DAV:lockdiscovery' prop on every** resource. But depth-infinity propfinds can sometimes behave like a** DoS attack, and mod_dav even disables them by default!**** So we send a custom 'get-locks' REPORT on a public URI... which is** fine, since all lock queries are always against HEAD anyway. The** response is a just a list of svn_lock_t's. (Generic DAV clients,** of course, are free to do infinite PROPFINDs as they wish, assuming** the server allows it.)*/ /* * The get-locks-report xml request body is super-simple. * The server doesn't need anything but the URI in the REPORT request line. * * <S:get-locks-report xmlns...> * </S:get-locks-report> *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -