📄 repos.c
字号:
comb->res.exists = (kind == svn_node_none) ? FALSE : TRUE; comb->res.collection = (kind == svn_node_dir) ? TRUE : FALSE; return NULL;}static dav_error * dav_svn_prep_activity(dav_resource_combined *comb){ const char *txn_name = dav_svn_get_txn(comb->priv.repos, comb->priv.root.activity_id); comb->priv.root.txn_name = txn_name; comb->res.exists = txn_name != NULL; return NULL;}static dav_error * dav_svn_prep_private(dav_resource_combined *comb){ if (comb->priv.restype == DAV_SVN_RESTYPE_VCC) { /* ### what to do */ } /* else nothing to do (### for now) */ return NULL;}static const struct res_type_handler{ dav_resource_type type; dav_error * (*prep)(dav_resource_combined *comb);} res_type_handlers[] ={ /* skip UNKNOWN */ { DAV_RESOURCE_TYPE_REGULAR, dav_svn_prep_regular }, { DAV_RESOURCE_TYPE_VERSION, dav_svn_prep_version }, { DAV_RESOURCE_TYPE_HISTORY, dav_svn_prep_history }, { DAV_RESOURCE_TYPE_WORKING, dav_svn_prep_working }, /* skip WORKSPACE */ { DAV_RESOURCE_TYPE_ACTIVITY, dav_svn_prep_activity }, { DAV_RESOURCE_TYPE_PRIVATE, dav_svn_prep_private }, { 0, NULL } /* sentinel */};/*** ### docco...**** Set .exists and .collection** open other, internal bits...*/static dav_error * dav_svn_prep_resource(dav_resource_combined *comb){ const struct res_type_handler *scan; for (scan = res_type_handlers; scan->prep != NULL; ++scan) { if (comb->res.type == scan->type) return (*scan->prep)(comb); } return dav_new_error(comb->res.pool, HTTP_INTERNAL_SERVER_ERROR, 0, "DESIGN FAILURE: unknown resource type");}static dav_resource *dav_svn_create_private_resource( const dav_resource *base, enum dav_svn_private_restype restype){ dav_resource_combined *comb; svn_stringbuf_t *path; const struct special_defn *defn; for (defn = special_subdirs; defn->name != NULL; ++defn) if (defn->restype == restype) break; /* assert: defn->name != NULL */ path = svn_stringbuf_createf(base->pool, "/%s/%s", base->info->repos->special_uri, defn->name); comb = apr_pcalloc(base->pool, sizeof(*comb)); /* ### can/should we leverage dav_svn_prep_resource */ comb->res.type = DAV_RESOURCE_TYPE_PRIVATE; comb->res.exists = TRUE; comb->res.collection = TRUE; /* ### always true? */ /* versioned = baselined = working = FALSE */ comb->res.uri = apr_pstrcat(base->pool, base->info->repos->root_path, path->data, NULL); comb->res.info = &comb->priv; comb->res.hooks = &dav_svn_hooks_repos; comb->res.pool = base->pool; comb->priv.uri_path = path; comb->priv.repos = base->info->repos; comb->priv.root.rev = SVN_INVALID_REVNUM; return &comb->res;}static void log_warning(void *baton, svn_error_t *err){ request_rec *r = baton; /* ### hmm. the FS is cleaned up at request cleanup time. "r" might ### not really be valid. we should probably put the FS into a ### subpool to ensure it gets cleaned before the request. ### is there a good way to create and use a subpool for all ### of our functions ... ?? */ ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, r, "%s", err->message);}AP_MODULE_DECLARE(dav_error *)dav_svn_split_uri(request_rec *r, const char *uri_to_split, const char *root_path, const char **cleaned_uri, int *trailing_slash, const char **repos_name, const char **relative_path, const char **repos_path){ apr_size_t len1; int had_slash; const char *fs_path; const char *fs_parent_path; const char *relative; char *uri; /* one of these is NULL, the other non-NULL. */ fs_path = dav_svn_get_fs_path(r); fs_parent_path = dav_svn_get_fs_parent_path(r); if ((fs_path == NULL) && (fs_parent_path == NULL)) { /* ### are SVN_ERR_APMOD codes within the right numeric space? */ return dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, SVN_ERR_APMOD_MISSING_PATH_TO_FS, "The server is misconfigured: " "either an SVNPath or SVNParentPath " "directive is required to specify the location " "of this resource's repository."); } /* make a copy so that we can do some work on it */ uri = apr_pstrdup(r->pool, uri_to_split); /* remove duplicate slashes, and make sure URI has no trailing '/' */ ap_no2slash(uri); len1 = strlen(uri); had_slash = (len1 > 0 && uri[len1 - 1] == '/'); if (len1 > 1 && had_slash) uri[len1 - 1] = '\0'; if (had_slash) *trailing_slash = TRUE; else *trailing_slash = FALSE; /* return the first item. */ *cleaned_uri = apr_pstrdup(r->pool, uri); /* The URL space defined by the SVN provider is always a virtual space. Construct the path relative to the configured Location (root_path). So... the relative location is simply the URL used, skipping the root_path. Note: mod_dav has canonialized root_path. It will not have a trailing slash (unless it is "/"). Note: given a URI of /something and a root of /some, then it is impossible to be here (and end up with "thing"). This is simply because we control /some and are dispatched to here for its URIs. We do not control /something, so we don't get here. Or, if we *do* control /something, then it is for THAT root. */ relative = ap_stripprefix(uri, root_path); /* We want a leading slash on the path specified by <relative>. This will almost always be the case since root_path does not have a trailing slash. However, if the root is "/", then the slash will be removed from <relative>. Backing up a character will put the leading slash back. Watch out for the empty string! This can happen when URI == ROOT_PATH. We simply turn the path into "/" for this case. */ if (*relative == '\0') relative = "/"; else if (*relative != '/') --relative; /* ### need a better name... it isn't "relative" because of the leading ### slash. something about SVN-private-path */ /* Depending on whether SVNPath or SVNParentPath was used, we need to compute 'relative' and 'repos_name' differently. */ /* Normal case: the SVNPath command was used to specify a particular repository. */ if (fs_path != NULL) { /* the repos_name is the last component of root_path. */ *repos_name = svn_path_basename(root_path, r->pool); /* 'relative' is already correct for SVNPath; the root_path already contains the name of the repository, so relative is everything beyond that. */ } else { /* SVNParentPath was used instead: assume the first component of 'relative' is the name of a repository. */ const char *magic_component, *magic_end; /* A repository name is required here. Remember that 'relative' always starts with a "/". */ if (relative[1] == '\0') { /* ### are SVN_ERR_APMOD codes within the right numeric space? */ return dav_new_error(r->pool, HTTP_FORBIDDEN, SVN_ERR_APMOD_MALFORMED_URI, "The URI does not contain the name " "of a repository."); } magic_end = ap_strchr_c(relative + 1, '/'); if (!magic_end) { /* ### Request was for parent directory with no trailing slash; we probably ought to just redirect to same with trailing slash appended. */ magic_component = relative + 1; relative = "/"; } else { magic_component = apr_pstrndup(r->pool, relative + 1, magic_end - relative - 1); relative = magic_end; } /* return answer */ *repos_name = magic_component; } /* We can return 'relative' at this point too. */ *relative_path = apr_pstrdup(r->pool, relative); /* Code to remove the !svn junk from the front of the relative path, mainly stolen from dav_svn_parse_uri(). This code assumes that the 'relative' string being parsed doesn't start with '/'. */ relative++; { const char *special_uri = dav_svn_get_special_uri(r); apr_size_t len2; char ch; len1 = strlen(relative); len2 = strlen(special_uri); if (len1 > len2 && ((ch = relative[len2]) == '/' || ch == '\0') && memcmp(relative, special_uri, len2) == 0) { if (ch == '\0') { /* relative is just "!svn", which is malformed. */ return dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, SVN_ERR_APMOD_MALFORMED_URI, "Nothing follows the svn special_uri."); } else { const struct special_defn *defn; /* skip past the "!svn/" prefix */ relative += len2 + 1; len1 -= len2 + 1; for (defn = special_subdirs ; defn->name != NULL; ++defn) { apr_size_t len3 = strlen(defn->name); if (len1 >= len3 && memcmp(relative, defn->name, len3) == 0) { /* Found a matching special dir. */ if (relative[len3] == '\0') { /* relative is "!svn/xxx" */ if (defn->numcomponents == 0) *repos_path = NULL; else return dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, SVN_ERR_APMOD_MALFORMED_URI, "Missing info after special_uri."); } else if (relative[len3] == '/') { /* Skip past defn->numcomponents components, return everything beyond that.*/ int j; const char *end = NULL, *start = relative + len3 + 1; for (j = 0; j < defn->numcomponents; j++) { end = ap_strchr_c(start, '/'); if (! end) break; start = end + 1; } if (! end) { /* Did we break from the loop prematurely? */ if (j != (defn->numcomponents - 1)) return dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, SVN_ERR_APMOD_MALFORMED_URI, "Not enough components" " after special_uri."); if (! defn->has_repos_path) /* It's okay to not have found a slash. */ *repos_path = NULL; else *repos_path = "/"; } else { /* Found a slash after the special components. */ *repos_path = apr_pstrdup(r->pool, start); } } else { return dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, SVN_ERR_APMOD_MALFORMED_URI, "Unknown data after special_uri."); } break; } } if (defn->name == NULL) return dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, SVN_ERR_APMOD_MALFORMED_URI, "Couldn't match subdir after special_uri."); } } else { /* There's no "!svn/" at all, so the relative path is already a valid path within the repository. */ *repos_path = apr_pstrdup(r->pool, relative); } } return NULL;}/* Context for cleanup handler. */struct cleanup_fs_access_baton{ svn_fs_t *fs; apr_pool_t *pool;};/* Pool cleanup handler. Make sure fs's access ctx points to NULL when request pool is destroyed. */static apr_status_t cleanup_fs_access(void *data){ svn_error_t *serr; struct cleanup_fs_access_baton *baton = data;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -