📄 repos.c
字号:
serr = svn_fs_set_access(baton->fs, NULL); if (serr) { ap_log_perror(APLOG_MARK, APLOG_ERR, serr->apr_err, baton->pool, "cleanup_fs_access: error clearing fs access context"); svn_error_clear(serr); } return APR_SUCCESS;}/* Helper func to construct a special 'parentpath' private resource. */static dav_error *get_parentpath_resource(request_rec *r, const char *root_path, dav_resource **resource){ const char *new_uri; dav_svn_root *droot = apr_pcalloc(r->pool, sizeof(*droot)); dav_svn_repos *repos = apr_pcalloc(r->pool, sizeof(*repos)); dav_resource_combined *comb = apr_pcalloc(r->pool, sizeof(*comb)); apr_size_t len = strlen(r->uri); comb->res.exists = TRUE; comb->res.collection = TRUE; comb->res.uri = apr_pstrdup(r->pool, r->uri); comb->res.info = &comb->priv; comb->res.hooks = &dav_svn_hooks_repos; comb->res.pool = r->pool; comb->res.type = DAV_RESOURCE_TYPE_PRIVATE; comb->priv.restype = DAV_SVN_RESTYPE_PARENTPATH_COLLECTION; comb->priv.r = r; comb->priv.repos_path = "Collection of Repositories"; comb->priv.root = *droot; droot->rev = SVN_INVALID_REVNUM; comb->priv.repos = repos; repos->pool = r->pool; repos->xslt_uri = dav_svn_get_xslt_uri(r); repos->autoversioning = dav_svn_get_autoversioning_flag(r); repos->base_url = ap_construct_url(r->pool, "", r); repos->special_uri = dav_svn_get_special_uri(r); repos->username = r->user; /* Make sure this type of resource always has a trailing slash; if not, redirect to a URI that does. */ if (r->uri[len-1] != '/') { new_uri = apr_pstrcat(r->pool, ap_escape_uri(r->pool, r->uri), "/", NULL); apr_table_setn(r->headers_out, "Location", ap_construct_url(r->pool, new_uri, r)); return dav_new_error(r->pool, HTTP_MOVED_PERMANENTLY, 0, "Requests for a collection must have a " "trailing slash on the URI."); } /* No other "prepping" of resource needs to happen -- no opening of a repository or anything like that, because, well, there's no repository to open. */ *resource = &comb->res; return NULL;}/* --------------- Borrowed from httpd's mod_negotiation.c -------------- */typedef struct accept_rec { char *name; /* MUST be lowercase */ float quality;} accept_rec;/* * Get a single Accept-encoding line from ACCEPT_LINE, and place the * information we have parsed out of it into RESULT. */static const char *get_entry(apr_pool_t *p, accept_rec *result, const char *accept_line){ result->quality = 1.0f; /* * Note that this handles what I gather is the "old format", * * Accept: text/html text/plain moo/zot * * without any compatibility kludges --- if the token after the * MIME type begins with a semicolon, we know we're looking at parms, * otherwise, we know we aren't. (So why all the pissing and moaning * in the CERN server code? I must be missing something). */ result->name = ap_get_token(p, &accept_line, 0); ap_str_tolower(result->name); /* You want case insensitive, * you'll *get* case insensitive. */ while (*accept_line == ';') { /* Parameters ... */ char *parm; char *cp; char *end; ++accept_line; parm = ap_get_token(p, &accept_line, 1); /* Look for 'var = value' --- and make sure the var is in lcase. */ for (cp = parm; (*cp && !apr_isspace(*cp) && *cp != '='); ++cp) { *cp = apr_tolower(*cp); } if (!*cp) { continue; /* No '='; just ignore it. */ } *cp++ = '\0'; /* Delimit var */ while (*cp && (apr_isspace(*cp) || *cp == '=')) { ++cp; } if (*cp == '"') { ++cp; for (end = cp; (*end && *end != '\n' && *end != '\r' && *end != '\"'); end++); } else { for (end = cp; (*end && !apr_isspace(*end)); end++); } if (*end) { *end = '\0'; /* strip ending quote or return */ } ap_str_tolower(cp); if (parm[0] == 'q' && (parm[1] == '\0' || (parm[1] == 's' && parm[2] == '\0'))) { result->quality = (float) atof(cp); } } if (*accept_line == ',') { ++accept_line; } return accept_line;}/* @a accept_line is the Accept-Encoding header, which is of the format: Accept-Encoding: name; q=N; This function will return an array of accept_rec structures that contain the accepted encodings and the quality each one has associated with them.*/static apr_array_header_t *do_header_line(apr_pool_t *p, const char *accept_line){ apr_array_header_t *accept_recs; if (!accept_line) return NULL; accept_recs = apr_array_make(p, 10, sizeof(accept_rec)); while (*accept_line) { accept_rec *prefs = (accept_rec *) apr_array_push(accept_recs); accept_line = get_entry(p, prefs, accept_line); } return accept_recs;}/* ---------------------------------------------------------------------- *//* qsort comparison function for the quality field of the accept_rec structure */static int sort_encoding_pref(const void *accept_rec1, const void *accept_rec2){ float diff = ((const accept_rec *) accept_rec1)->quality - ((const accept_rec *) accept_rec2)->quality; return (diff == 0 ? 0 : (diff > 0 ? -1 : 1));}/* Parse and handle any possible Accept-Encoding header that has been sent as part of the request. */static voidsvn_dav__negotiate_encoding_prefs(request_rec *r, int *svndiff_version){ /* It would be nice if mod_negotiation <http://httpd.apache.org/docs-2.1/mod/mod_negotiation.html> could handle the Accept-Encoding header parsing for us. Sadly, it looks like its data structures and routines are private (see httpd/modules/mappers/mod_negotiation.c). Thus, we duplicate the necessary ones in this file. */ int i; const apr_array_header_t *encoding_prefs; encoding_prefs = do_header_line(r->pool, apr_table_get(r->headers_in, "Accept-Encoding")); if (!encoding_prefs || apr_is_empty_array(encoding_prefs)) { *svndiff_version = 0; return; } *svndiff_version = 0; qsort(encoding_prefs->elts, (size_t) encoding_prefs->nelts, sizeof(accept_rec), sort_encoding_pref); for (i = 0; i < encoding_prefs->nelts; i++) { struct accept_rec rec = APR_ARRAY_IDX(encoding_prefs, i, struct accept_rec); if (strcmp(rec.name, "svndiff1") == 0) { *svndiff_version = 1; break; } else if (strcmp(rec.name, "svndiff") == 0) { *svndiff_version = 0; break; } } }static dav_error * dav_svn_get_resource(request_rec *r, const char *root_path, const char *label, int use_checked_in, dav_resource **resource){ const char *fs_path; const char *repo_name; const char *xslt_uri; const char *fs_parent_path; dav_resource_combined *comb; dav_svn_repos *repos; const char *cleaned_uri; const char *repos_name; const char *relative; const char *repos_path; const char *repos_key; const char *version_name; svn_error_t *serr; dav_error *err; int had_slash; dav_locktoken_list *ltl; struct cleanup_fs_access_baton *cleanup_baton; void *userdata; repo_name = dav_svn_get_repo_name(r); xslt_uri = dav_svn_get_xslt_uri(r); fs_parent_path = dav_svn_get_fs_parent_path(r); /* Special case: detect and build the SVNParentPath as a unique type of private resource, iff the SVNListParentPath directive is 'on'. */ if (fs_parent_path && dav_svn_get_list_parentpath_flag(r)) { char *uri = apr_pstrdup(r->pool, r->uri); char *parentpath = apr_pstrdup(r->pool, root_path); apr_size_t uri_len = strlen(uri); apr_size_t parentpath_len = strlen(parentpath); if (uri[uri_len-1] == '/') uri[uri_len-1] = '\0'; if (parentpath[parentpath_len-1] == '/') parentpath[parentpath_len-1] = '\0'; if (strcmp(parentpath, uri) == 0) { err = get_parentpath_resource(r, root_path, resource); if (err) return err; return NULL; } } /* This does all the work of interpreting/splitting the request uri. */ err = dav_svn_split_uri(r, r->uri, root_path, &cleaned_uri, &had_slash, &repos_name, &relative, &repos_path); if (err) return err; /* The path that we will eventually try to open as an svn repository. Normally defined by the SVNPath directive. */ fs_path = dav_svn_get_fs_path(r); /* If the SVNParentPath directive was used instead... */ if (fs_parent_path != NULL) { /* ...then the URL to the repository is actually one implicit component longer... */ root_path = svn_path_join(root_path, repos_name, r->pool); /* ...and we need to specify exactly what repository to open. */ fs_path = svn_path_join(fs_parent_path, repos_name, r->pool); } /* Start building and filling a 'combination' object. */ comb = apr_pcalloc(r->pool, sizeof(*comb)); comb->res.info = &comb->priv; comb->res.hooks = &dav_svn_hooks_repos; comb->res.pool = r->pool; comb->res.uri = cleaned_uri; /* Original request, off which to generate subrequests later. */ comb->priv.r = r; /* ### ugly hack to carry over Content-Type data to the open_stream, which ### does not have access to the request headers. */ { const char *ct = apr_table_get(r->headers_in, "content-type"); comb->priv.is_svndiff = ct != NULL && strcmp(ct, SVN_SVNDIFF_MIME_TYPE) == 0; } svn_dav__negotiate_encoding_prefs(r, &comb->priv.svndiff_version); /* ### and another hack for computing diffs to send to the client */ comb->priv.delta_base = apr_table_get(r->headers_in, SVN_DAV_DELTA_BASE_HEADER); /* Gather any options requested by an svn client. */ comb->priv.svn_client_options = apr_table_get(r->headers_in, SVN_DAV_OPTIONS_HEADER); /* See if the client sent a custom 'version name' request header. */ version_name = apr_table_get(r->headers_in, SVN_DAV_VERSION_NAME_HEADER); comb->priv.version_name = version_name ? SVN_STR_TO_REV(version_name): SVN_INVALID_REVNUM; /* Remember checksums, if any. */ comb->priv.base_checksum = apr_table_get(r->headers_in, SVN_DAV_BASE_FULLTEXT_MD5_HEADER); comb->priv.result_checksum = apr_table_get(r->headers_in, SVN_DAV_RESULT_FULLTEXT_MD5_HEADER); /* "relative" is part of the "uri" string, so it has the proper lifetime to store here. */ /* ### that comment no longer applies. we're creating a string with its ### own lifetime now. so WHY are we using a string? hmm... */ comb->priv.uri_path = svn_stringbuf_create(relative, r->pool); /* initialize this until we put something real here */ comb->priv.root.rev = SVN_INVALID_REVNUM; /* create the repository structure and stash it away */ repos = apr_pcalloc(r->pool, sizeof(*repos)); repos->pool = r->pool; comb->priv.repos = repos; /* We are assuming the root_path will live at least as long as this resource. Considering that it typically comes from the per-dir config in mod_dav, this is valid for now. */ repos->root_path = svn_path_uri_encode(root_path, r->pool); /* where is the SVN FS for this resource? */ repos->fs_path = fs_path; /* A name for the repository */ repos->repo_name = repo_name; /* An XSL transformation */ repos->xslt_uri = xslt_uri; /* Is autoversioning active in this repos? */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -