📄 repos.c
字号:
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)
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;
}
static dav_error * dav_svn_get_resource(request_rec *r,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -