You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@subversion.apache.org by Martin Hauner <ma...@gmx.net> on 2006/11/20 21:07:54 UTC
[PATCH] Re: preparing a path or url for an svn api call....
Hi,
here is a small patch for a new function svn_path_from_user_input that
helps any svn client to pass a well formed and escaped path/url to the
api.
There is a small change in the handling of the administrative dir. In
the old code the administrative dir was skipped. In the new code it
reports an error.
I don't think it is worth to check the error of the new function to
mimic the old behavior.
[[[
Moved path and url preparation code from svn_opt_args_to_target_array2
to its own function so it is available to any subversion api client.
* subversion/include/svn_error_codes.h
(SVN_ERR_WC_BAD_PATH_ADM_DIR): new error.
* subversion/include/svn_path.h
subversion/libsvn_subr/path.c
(svn_path_from_user_input): new function, extracted from
svn_opt_args_to_target_array2.
* subversion/libsvn_subr/opt.c
(svn_opt_args_to_target_array2): use the new function.
]]]
Max Bowsher wrote:
> Martin Hauner wrote:
>> Hi,
>>
>> I received a bug report for subcommander that it doesn't properly
>> handle urls with spaces.
>>
>> Grepping through the subversion code the magic trick (which is well
>> hidden for someone who is working with the svn_client api ;-) seems
>> to be in the loop of svn_opt_args_to_target_array2.
>>
>> The code is basically:
>>
>> if( svn_path_is_url(pathOrUrl) )
>> {
>> // do anything necessary to create a proper url
>> path = svn_path_uri_from_iri( );
>> path = svn_path_uri_autoescape( );
>> path = svn_path_canonicalize( );
>>
>> ... some additional checks if it is a valid url
>> ... error if not
>> }
>> else
>> {
>> path = svn_path_canonicalize( );
>> ...
>> }
>>
>> I also found a nearly 1:1 copy of this code in the java bindings and a
>> stripped down version in mucc.
>>
>> It looks like that i have to prepare any path or url i pass to the
>> subversion api (talking about svn_client here..) with the above code.
>>
>> If that is the case, I would like to move the above code into its own
>> function (named svn_path_prepare?) so it is available to any subversion
>> client without copy and paste.
>>
>> What do you think?
>
> svn_path_from_user_input() perhaps? Yes, this is clearly a good idea to
> abstract the standard logic to a reusable function.
>
> Max.
>
--
Martin
Subcommander 1.2.1 - http://subcommander.tigris.org
a cross platform Win32/Unix/MacOSX subversion GUI client & diff/merge tool.
Re: [PATCH] Re: preparing a path or url for an svn api call....
Posted by "Hyrum K. Wright" <hy...@mail.utexas.edu>.
Hyrum K. Wright wrote:
> Martin Hauner wrote:
>> Hi,
>>
>> here is a small patch for a new function svn_path_from_user_input that
>> helps any svn client to pass a well formed and escaped path/url to the
>> api.
>>
>> There is a small change in the handling of the administrative dir. In
>> the old code the administrative dir was skipped. In the new code it
>> reports an error.
>> I don't think it is worth to check the error of the new function to
>> mimic the old behavior.
>
> Ping...
>
> Has a committer had a chance to look at this patch? If nothing happens
> with it in a few days, I'll file an issue.
Posted as issue 2676.
-Hyrum
>> [[[
>> Moved path and url preparation code from svn_opt_args_to_target_array2
>> to its own function so it is available to any subversion api client.
>>
>> * subversion/include/svn_error_codes.h
>> (SVN_ERR_WC_BAD_PATH_ADM_DIR): new error.
>>
>> * subversion/include/svn_path.h
>> subversion/libsvn_subr/path.c
>> (svn_path_from_user_input): new function, extracted from
>> svn_opt_args_to_target_array2.
>>
>> * subversion/libsvn_subr/opt.c
>> (svn_opt_args_to_target_array2): use the new function.
>> ]]]
>>
>>
>> Max Bowsher wrote:
>>> Martin Hauner wrote:
>>>> Hi,
>>>>
>>>> I received a bug report for subcommander that it doesn't properly
>>>> handle urls with spaces.
>>>>
>>>> Grepping through the subversion code the magic trick (which is well
>>>> hidden for someone who is working with the svn_client api ;-) seems
>>>> to be in the loop of svn_opt_args_to_target_array2.
>>>>
>>>> The code is basically:
>>>>
>>>> if( svn_path_is_url(pathOrUrl) )
>>>> {
>>>> // do anything necessary to create a proper url
>>>> path = svn_path_uri_from_iri( );
>>>> path = svn_path_uri_autoescape( );
>>>> path = svn_path_canonicalize( );
>>>>
>>>> ... some additional checks if it is a valid url
>>>> ... error if not
>>>> }
>>>> else
>>>> {
>>>> path = svn_path_canonicalize( );
>>>> ...
>>>> }
>>>>
>>>> I also found a nearly 1:1 copy of this code in the java bindings and a
>>>> stripped down version in mucc.
>>>>
>>>> It looks like that i have to prepare any path or url i pass to the
>>>> subversion api (talking about svn_client here..) with the above code.
>>>>
>>>> If that is the case, I would like to move the above code into its own
>>>> function (named svn_path_prepare?) so it is available to any subversion
>>>> client without copy and paste.
>>>>
>>>> What do you think?
>>> svn_path_from_user_input() perhaps? Yes, this is clearly a good idea to
>>> abstract the standard logic to a reusable function.
>>>
>>> Max.
>>>
>>
>>
>> ------------------------------------------------------------------------
>>
>> Index: D:/dev/src/subversion/svn-trunk/subversion/include/svn_error_codes.h
>> ===================================================================
>> --- D:/dev/src/subversion/svn-trunk/subversion/include/svn_error_codes.h (Revision 22335)
>> +++ D:/dev/src/subversion/svn-trunk/subversion/include/svn_error_codes.h (Arbeitskopie)
>> @@ -391,6 +391,11 @@
>> SVN_ERR_WC_CATEGORY_START + 25,
>> "Invalid switch")
>>
>> + /** @since New in 1.5. */
>> + SVN_ERRDEF(SVN_ERR_WC_BAD_PATH_ADM_DIR,
>> + SVN_ERR_WC_CATEGORY_START + 26,
>> + "Operation is not allowed on administrative dir")
>> +
>> /* fs errors */
>>
>> SVN_ERRDEF(SVN_ERR_FS_GENERAL,
>> Index: D:/dev/src/subversion/svn-trunk/subversion/include/svn_path.h
>> ===================================================================
>> --- D:/dev/src/subversion/svn-trunk/subversion/include/svn_path.h (Revision 22335)
>> +++ D:/dev/src/subversion/svn-trunk/subversion/include/svn_path.h (Arbeitskopie)
>> @@ -1,7 +1,7 @@
>> /**
>> * @copyright
>> * ====================================================================
>> - * Copyright (c) 2000-2004 CollabNet. All rights reserved.
>> + * Copyright (c) 2000-2006 CollabNet. All rights reserved.
>> *
>> * This software is licensed as described in the file COPYING, which
>> * you should have received as part of this distribution. The terms
>> @@ -46,6 +46,27 @@
>>
>>
>>
>> +/**
>> + * Prepare the given UTF-8 encoded @a path_or_url_utf8 so it can be passed
>> + * to a subversion api call. You are expected to call this before entering
>> + * the svn api universe if @a path_or_url_utf8 is based on user input (gui
>> + * or console).
>> + *
>> + * A working copy path is canonicalized. A repository URL is canonicalized
>> + * and converted to a well formed, autoescaped URL.
>> + *
>> + * An error is returned if the transformation failed or if the result is not
>> + * safe to use (eg. an url is not uri safe or it contains a backpath element
>> + * '..'). @a path_svn is undefined if an error is returned.
>> + *
>> + * @since New in 1.5.
>> + */
>> +svn_error_t *
>> +svn_path_from_user_input(const char **path_svn,
>> + const char *path_or_url_utf8,
>> + apr_pool_t *pool);
>> +
>> +
>> /** Convert @a path from the local style to the canonical internal style. */
>> const char *svn_path_internal_style(const char *path, apr_pool_t *pool);
>>
>> Index: D:/dev/src/subversion/svn-trunk/subversion/libsvn_subr/opt.c
>> ===================================================================
>> --- D:/dev/src/subversion/svn-trunk/subversion/libsvn_subr/opt.c (Revision 22335)
>> +++ D:/dev/src/subversion/svn-trunk/subversion/libsvn_subr/opt.c (Arbeitskopie)
>> @@ -819,79 +819,10 @@
>> for (i = 0; i < input_targets->nelts; i++)
>> {
>> const char *utf8_target = APR_ARRAY_IDX(input_targets, i, const char *);
>> - const char *target; /* after all processing is finished */
>> + const char *target;
>>
>> - /* URLs and wc-paths get treated differently. */
>> - if (svn_path_is_url(utf8_target))
>> - {
>> - /* No need to canonicalize a URL's case or path separators. */
>> + SVN_ERR(svn_path_from_user_input(&target, utf8_target, pool));
>>
>> - /* Convert to URI. */
>> - target = svn_path_uri_from_iri(utf8_target, pool);
>> - /* Auto-escape some ASCII characters. */
>> - target = svn_path_uri_autoescape(target, pool);
>> -
>> - /* The above doesn't guarantee a valid URI. */
>> - if (! svn_path_is_uri_safe(target))
>> - return svn_error_createf(SVN_ERR_BAD_URL, 0,
>> - _("URL '%s' is not properly URI-encoded"),
>> - utf8_target);
>> -
>> - /* Verify that no backpaths are present in the URL. */
>> - if (svn_path_is_backpath_present(target))
>> - return svn_error_createf(SVN_ERR_BAD_URL, 0,
>> - _("URL '%s' contains a '..' element"),
>> - utf8_target);
>> -
>> - /* strip any trailing '/' */
>> - target = svn_path_canonicalize(target, pool);
>> - }
>> - else /* not a url, so treat as a path */
>> - {
>> - const char *apr_target;
>> - const char *base_name;
>> - char *truenamed_target; /* APR-encoded */
>> - apr_status_t apr_err;
>> -
>> - /* canonicalize case, and change all separators to '/'. */
>> - SVN_ERR(svn_path_cstring_from_utf8(&apr_target, utf8_target,
>> - pool));
>> - apr_err = apr_filepath_merge(&truenamed_target, "", apr_target,
>> - APR_FILEPATH_TRUENAME, pool);
>> -
>> - if (!apr_err)
>> - /* We have a canonicalized APR-encoded target now. */
>> - apr_target = truenamed_target;
>> - else if (APR_STATUS_IS_ENOENT(apr_err))
>> - /* It's okay for the file to not exist, that just means we
>> - have to accept the case given to the client. We'll use
>> - the original APR-encoded target. */
>> - ;
>> - else
>> - return svn_error_createf(apr_err, NULL,
>> - _("Error resolving case of '%s'"),
>> - svn_path_local_style(utf8_target,
>> - pool));
>> -
>> - /* convert back to UTF-8. */
>> - SVN_ERR(svn_path_cstring_to_utf8(&target, apr_target, pool));
>> - target = svn_path_canonicalize(target, pool);
>> -
>> - /* If the target has the same name as a Subversion
>> - working copy administrative dir, skip it. */
>> - base_name = svn_path_basename(target, pool);
>> - /* FIXME:
>> - The canonical list of administrative directory names is
>> - maintained in libsvn_wc/adm_files.c:svn_wc_set_adm_dir().
>> - That list can't be used here, because that use would
>> - create a circular dependency between libsvn_wc and
>> - libsvn_subr. Make sure changes to the lists are always
>> - synchronized! */
>> - if (0 == strcmp(base_name, ".svn")
>> - || 0 == strcmp(base_name, "_svn"))
>> - continue;
>> - }
>> -
>> (*((const char **) apr_array_push(output_targets))) = target;
>> }
>>
>> Index: D:/dev/src/subversion/svn-trunk/subversion/libsvn_subr/path.c
>> ===================================================================
>> --- D:/dev/src/subversion/svn-trunk/subversion/libsvn_subr/path.c (Revision 22335)
>> +++ D:/dev/src/subversion/svn-trunk/subversion/libsvn_subr/path.c (Arbeitskopie)
>> @@ -2,7 +2,7 @@
>> * paths.c: a path manipulation library using svn_stringbuf_t
>> *
>> * ====================================================================
>> - * Copyright (c) 2000-2004 CollabNet. All rights reserved.
>> + * Copyright (c) 2000-2006 CollabNet. All rights reserved.
>> *
>> * This software is licensed as described in the file COPYING, which
>> * you should have received as part of this distribution. The terms
>> @@ -1364,3 +1364,82 @@
>>
>> return SVN_NO_ERROR;
>> }
>> +
>> +svn_error_t *
>> +svn_path_from_user_input(const char **path_svn,
>> + const char *path_or_url_utf8,
>> + apr_pool_t *pool)
>> +{
>> + const char *target; /* after all processing is finished */
>> +
>> + /* URLs and wc-paths get treated differently. */
>> + if (svn_path_is_url(path_or_url_utf8))
>> + {
>> + /* No need to canonicalize a URL's case or path separators. */
>> +
>> + /* Convert to URI. */
>> + target = svn_path_uri_from_iri(path_or_url_utf8, pool);
>> + /* Auto-escape some ASCII characters. */
>> + target = svn_path_uri_autoescape(target, pool);
>> +
>> + /* The above doesn't guarantee a valid URI. */
>> + if (! svn_path_is_uri_safe(target))
>> + return svn_error_createf(SVN_ERR_BAD_URL, 0,
>> + _("URL '%s' is not properly URI-encoded"), path_or_url_utf8);
>> +
>> + /* Verify that no backpaths are present in the URL. */
>> + if (svn_path_is_backpath_present(target))
>> + return svn_error_createf(SVN_ERR_BAD_URL, 0,
>> + _("URL '%s' contains a '..' element"), path_or_url_utf8);
>> +
>> + /* strip any trailing '/' */
>> + target = svn_path_canonicalize(target, pool);
>> + }
>> + else /* not a url, so treat as a path */
>> + {
>> + const char *apr_target;
>> + char *truenamed_target; /* APR-encoded */
>> + apr_status_t apr_err;
>> +
>> + /* canonicalize case, and change all separators to '/'. */
>> + SVN_ERR(svn_path_cstring_from_utf8(&apr_target, path_or_url_utf8,
>> + pool));
>> + apr_err = apr_filepath_merge(&truenamed_target, "", path_or_url_utf8,
>> + APR_FILEPATH_TRUENAME, pool);
>> +
>> + if (!apr_err)
>> + /* We have a canonicalized APR-encoded target now. */
>> + apr_target = truenamed_target;
>> + else if (APR_STATUS_IS_ENOENT(apr_err))
>> + /* It's okay for the file to not exist, that just means we
>> + have to accept the case given to the client. We'll use
>> + the original APR-encoded target. */
>> + ;
>> + else
>> + return svn_error_createf(apr_err, NULL,
>> + _("Error resolving case of '%s'"),
>> + svn_path_local_style(path_or_url_utf8, pool));
>> +
>> + /* convert back to UTF-8. */
>> + SVN_ERR(svn_path_cstring_to_utf8(&target, apr_target, pool));
>> + target = svn_path_canonicalize(target, pool);
>> +
>> + /* If the target has the same name as a Subversion
>> + working copy administrative dir, skip it. */
>> + base_name = svn_path_basename(target, pool);
>> + /* FIXME:
>> + The canonical list of administrative directory names is
>> + maintained in libsvn_wc/adm_files.c:svn_wc_set_adm_dir().
>> + That list can't be used here, because that use would
>> + create a circular dependency between libsvn_wc and
>> + libsvn_subr. Make sure changes to the lists are always
>> + synchronized! */
>> + if (0 == strcmp(base_name, ".svn")
>> + || 0 == strcmp(base_name, "_svn"))
>> + return svn_error_createf(SVN_ERR_WC_BAD_PATH_ADM_DIR, 0,
>> + _("Path '%s' is the administrative directory"), base_name);
>> + }
>> +
>> + *path_svn = target;
>> + return SVN_NO_ERROR;
>> +}
>
Re: [PATCH] Re: preparing a path or url for an svn api call....
Posted by "Hyrum K. Wright" <hy...@mail.utexas.edu>.
Martin Hauner wrote:
> Hi,
>
> here is a small patch for a new function svn_path_from_user_input that
> helps any svn client to pass a well formed and escaped path/url to the
> api.
>
> There is a small change in the handling of the administrative dir. In
> the old code the administrative dir was skipped. In the new code it
> reports an error.
> I don't think it is worth to check the error of the new function to
> mimic the old behavior.
Ping...
Has a committer had a chance to look at this patch? If nothing happens
with it in a few days, I'll file an issue.
Thanks,
-Hyrum
> [[[
> Moved path and url preparation code from svn_opt_args_to_target_array2
> to its own function so it is available to any subversion api client.
>
> * subversion/include/svn_error_codes.h
> (SVN_ERR_WC_BAD_PATH_ADM_DIR): new error.
>
> * subversion/include/svn_path.h
> subversion/libsvn_subr/path.c
> (svn_path_from_user_input): new function, extracted from
> svn_opt_args_to_target_array2.
>
> * subversion/libsvn_subr/opt.c
> (svn_opt_args_to_target_array2): use the new function.
> ]]]
>
>
> Max Bowsher wrote:
>> Martin Hauner wrote:
>>> Hi,
>>>
>>> I received a bug report for subcommander that it doesn't properly
>>> handle urls with spaces.
>>>
>>> Grepping through the subversion code the magic trick (which is well
>>> hidden for someone who is working with the svn_client api ;-) seems
>>> to be in the loop of svn_opt_args_to_target_array2.
>>>
>>> The code is basically:
>>>
>>> if( svn_path_is_url(pathOrUrl) )
>>> {
>>> // do anything necessary to create a proper url
>>> path = svn_path_uri_from_iri( );
>>> path = svn_path_uri_autoescape( );
>>> path = svn_path_canonicalize( );
>>>
>>> ... some additional checks if it is a valid url
>>> ... error if not
>>> }
>>> else
>>> {
>>> path = svn_path_canonicalize( );
>>> ...
>>> }
>>>
>>> I also found a nearly 1:1 copy of this code in the java bindings and a
>>> stripped down version in mucc.
>>>
>>> It looks like that i have to prepare any path or url i pass to the
>>> subversion api (talking about svn_client here..) with the above code.
>>>
>>> If that is the case, I would like to move the above code into its own
>>> function (named svn_path_prepare?) so it is available to any subversion
>>> client without copy and paste.
>>>
>>> What do you think?
>>
>> svn_path_from_user_input() perhaps? Yes, this is clearly a good idea to
>> abstract the standard logic to a reusable function.
>>
>> Max.
>>
>
>
>
> ------------------------------------------------------------------------
>
> Index: D:/dev/src/subversion/svn-trunk/subversion/include/svn_error_codes.h
> ===================================================================
> --- D:/dev/src/subversion/svn-trunk/subversion/include/svn_error_codes.h (Revision 22335)
> +++ D:/dev/src/subversion/svn-trunk/subversion/include/svn_error_codes.h (Arbeitskopie)
> @@ -391,6 +391,11 @@
> SVN_ERR_WC_CATEGORY_START + 25,
> "Invalid switch")
>
> + /** @since New in 1.5. */
> + SVN_ERRDEF(SVN_ERR_WC_BAD_PATH_ADM_DIR,
> + SVN_ERR_WC_CATEGORY_START + 26,
> + "Operation is not allowed on administrative dir")
> +
> /* fs errors */
>
> SVN_ERRDEF(SVN_ERR_FS_GENERAL,
> Index: D:/dev/src/subversion/svn-trunk/subversion/include/svn_path.h
> ===================================================================
> --- D:/dev/src/subversion/svn-trunk/subversion/include/svn_path.h (Revision 22335)
> +++ D:/dev/src/subversion/svn-trunk/subversion/include/svn_path.h (Arbeitskopie)
> @@ -1,7 +1,7 @@
> /**
> * @copyright
> * ====================================================================
> - * Copyright (c) 2000-2004 CollabNet. All rights reserved.
> + * Copyright (c) 2000-2006 CollabNet. All rights reserved.
> *
> * This software is licensed as described in the file COPYING, which
> * you should have received as part of this distribution. The terms
> @@ -46,6 +46,27 @@
>
>
>
> +/**
> + * Prepare the given UTF-8 encoded @a path_or_url_utf8 so it can be passed
> + * to a subversion api call. You are expected to call this before entering
> + * the svn api universe if @a path_or_url_utf8 is based on user input (gui
> + * or console).
> + *
> + * A working copy path is canonicalized. A repository URL is canonicalized
> + * and converted to a well formed, autoescaped URL.
> + *
> + * An error is returned if the transformation failed or if the result is not
> + * safe to use (eg. an url is not uri safe or it contains a backpath element
> + * '..'). @a path_svn is undefined if an error is returned.
> + *
> + * @since New in 1.5.
> + */
> +svn_error_t *
> +svn_path_from_user_input(const char **path_svn,
> + const char *path_or_url_utf8,
> + apr_pool_t *pool);
> +
> +
> /** Convert @a path from the local style to the canonical internal style. */
> const char *svn_path_internal_style(const char *path, apr_pool_t *pool);
>
> Index: D:/dev/src/subversion/svn-trunk/subversion/libsvn_subr/opt.c
> ===================================================================
> --- D:/dev/src/subversion/svn-trunk/subversion/libsvn_subr/opt.c (Revision 22335)
> +++ D:/dev/src/subversion/svn-trunk/subversion/libsvn_subr/opt.c (Arbeitskopie)
> @@ -819,79 +819,10 @@
> for (i = 0; i < input_targets->nelts; i++)
> {
> const char *utf8_target = APR_ARRAY_IDX(input_targets, i, const char *);
> - const char *target; /* after all processing is finished */
> + const char *target;
>
> - /* URLs and wc-paths get treated differently. */
> - if (svn_path_is_url(utf8_target))
> - {
> - /* No need to canonicalize a URL's case or path separators. */
> + SVN_ERR(svn_path_from_user_input(&target, utf8_target, pool));
>
> - /* Convert to URI. */
> - target = svn_path_uri_from_iri(utf8_target, pool);
> - /* Auto-escape some ASCII characters. */
> - target = svn_path_uri_autoescape(target, pool);
> -
> - /* The above doesn't guarantee a valid URI. */
> - if (! svn_path_is_uri_safe(target))
> - return svn_error_createf(SVN_ERR_BAD_URL, 0,
> - _("URL '%s' is not properly URI-encoded"),
> - utf8_target);
> -
> - /* Verify that no backpaths are present in the URL. */
> - if (svn_path_is_backpath_present(target))
> - return svn_error_createf(SVN_ERR_BAD_URL, 0,
> - _("URL '%s' contains a '..' element"),
> - utf8_target);
> -
> - /* strip any trailing '/' */
> - target = svn_path_canonicalize(target, pool);
> - }
> - else /* not a url, so treat as a path */
> - {
> - const char *apr_target;
> - const char *base_name;
> - char *truenamed_target; /* APR-encoded */
> - apr_status_t apr_err;
> -
> - /* canonicalize case, and change all separators to '/'. */
> - SVN_ERR(svn_path_cstring_from_utf8(&apr_target, utf8_target,
> - pool));
> - apr_err = apr_filepath_merge(&truenamed_target, "", apr_target,
> - APR_FILEPATH_TRUENAME, pool);
> -
> - if (!apr_err)
> - /* We have a canonicalized APR-encoded target now. */
> - apr_target = truenamed_target;
> - else if (APR_STATUS_IS_ENOENT(apr_err))
> - /* It's okay for the file to not exist, that just means we
> - have to accept the case given to the client. We'll use
> - the original APR-encoded target. */
> - ;
> - else
> - return svn_error_createf(apr_err, NULL,
> - _("Error resolving case of '%s'"),
> - svn_path_local_style(utf8_target,
> - pool));
> -
> - /* convert back to UTF-8. */
> - SVN_ERR(svn_path_cstring_to_utf8(&target, apr_target, pool));
> - target = svn_path_canonicalize(target, pool);
> -
> - /* If the target has the same name as a Subversion
> - working copy administrative dir, skip it. */
> - base_name = svn_path_basename(target, pool);
> - /* FIXME:
> - The canonical list of administrative directory names is
> - maintained in libsvn_wc/adm_files.c:svn_wc_set_adm_dir().
> - That list can't be used here, because that use would
> - create a circular dependency between libsvn_wc and
> - libsvn_subr. Make sure changes to the lists are always
> - synchronized! */
> - if (0 == strcmp(base_name, ".svn")
> - || 0 == strcmp(base_name, "_svn"))
> - continue;
> - }
> -
> (*((const char **) apr_array_push(output_targets))) = target;
> }
>
> Index: D:/dev/src/subversion/svn-trunk/subversion/libsvn_subr/path.c
> ===================================================================
> --- D:/dev/src/subversion/svn-trunk/subversion/libsvn_subr/path.c (Revision 22335)
> +++ D:/dev/src/subversion/svn-trunk/subversion/libsvn_subr/path.c (Arbeitskopie)
> @@ -2,7 +2,7 @@
> * paths.c: a path manipulation library using svn_stringbuf_t
> *
> * ====================================================================
> - * Copyright (c) 2000-2004 CollabNet. All rights reserved.
> + * Copyright (c) 2000-2006 CollabNet. All rights reserved.
> *
> * This software is licensed as described in the file COPYING, which
> * you should have received as part of this distribution. The terms
> @@ -1364,3 +1364,82 @@
>
> return SVN_NO_ERROR;
> }
> +
> +svn_error_t *
> +svn_path_from_user_input(const char **path_svn,
> + const char *path_or_url_utf8,
> + apr_pool_t *pool)
> +{
> + const char *target; /* after all processing is finished */
> +
> + /* URLs and wc-paths get treated differently. */
> + if (svn_path_is_url(path_or_url_utf8))
> + {
> + /* No need to canonicalize a URL's case or path separators. */
> +
> + /* Convert to URI. */
> + target = svn_path_uri_from_iri(path_or_url_utf8, pool);
> + /* Auto-escape some ASCII characters. */
> + target = svn_path_uri_autoescape(target, pool);
> +
> + /* The above doesn't guarantee a valid URI. */
> + if (! svn_path_is_uri_safe(target))
> + return svn_error_createf(SVN_ERR_BAD_URL, 0,
> + _("URL '%s' is not properly URI-encoded"), path_or_url_utf8);
> +
> + /* Verify that no backpaths are present in the URL. */
> + if (svn_path_is_backpath_present(target))
> + return svn_error_createf(SVN_ERR_BAD_URL, 0,
> + _("URL '%s' contains a '..' element"), path_or_url_utf8);
> +
> + /* strip any trailing '/' */
> + target = svn_path_canonicalize(target, pool);
> + }
> + else /* not a url, so treat as a path */
> + {
> + const char *apr_target;
> + char *truenamed_target; /* APR-encoded */
> + apr_status_t apr_err;
> +
> + /* canonicalize case, and change all separators to '/'. */
> + SVN_ERR(svn_path_cstring_from_utf8(&apr_target, path_or_url_utf8,
> + pool));
> + apr_err = apr_filepath_merge(&truenamed_target, "", path_or_url_utf8,
> + APR_FILEPATH_TRUENAME, pool);
> +
> + if (!apr_err)
> + /* We have a canonicalized APR-encoded target now. */
> + apr_target = truenamed_target;
> + else if (APR_STATUS_IS_ENOENT(apr_err))
> + /* It's okay for the file to not exist, that just means we
> + have to accept the case given to the client. We'll use
> + the original APR-encoded target. */
> + ;
> + else
> + return svn_error_createf(apr_err, NULL,
> + _("Error resolving case of '%s'"),
> + svn_path_local_style(path_or_url_utf8, pool));
> +
> + /* convert back to UTF-8. */
> + SVN_ERR(svn_path_cstring_to_utf8(&target, apr_target, pool));
> + target = svn_path_canonicalize(target, pool);
> +
> + /* If the target has the same name as a Subversion
> + working copy administrative dir, skip it. */
> + base_name = svn_path_basename(target, pool);
> + /* FIXME:
> + The canonical list of administrative directory names is
> + maintained in libsvn_wc/adm_files.c:svn_wc_set_adm_dir().
> + That list can't be used here, because that use would
> + create a circular dependency between libsvn_wc and
> + libsvn_subr. Make sure changes to the lists are always
> + synchronized! */
> + if (0 == strcmp(base_name, ".svn")
> + || 0 == strcmp(base_name, "_svn"))
> + return svn_error_createf(SVN_ERR_WC_BAD_PATH_ADM_DIR, 0,
> + _("Path '%s' is the administrative directory"), base_name);
> + }
> +
> + *path_svn = target;
> + return SVN_NO_ERROR;
> +}