svn_dirent_uri.h revision 299742
1/**
2 * @copyright
3 * ====================================================================
4 *    Licensed to the Apache Software Foundation (ASF) under one
5 *    or more contributor license agreements.  See the NOTICE file
6 *    distributed with this work for additional information
7 *    regarding copyright ownership.  The ASF licenses this file
8 *    to you under the Apache License, Version 2.0 (the
9 *    "License"); you may not use this file except in compliance
10 *    with the License.  You may obtain a copy of the License at
11 *
12 *      http://www.apache.org/licenses/LICENSE-2.0
13 *
14 *    Unless required by applicable law or agreed to in writing,
15 *    software distributed under the License is distributed on an
16 *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 *    KIND, either express or implied.  See the License for the
18 *    specific language governing permissions and limitations
19 *    under the License.
20 * ====================================================================
21 * @endcopyright
22 *
23 * @file svn_dirent_uri.h
24 * @brief A library to manipulate URIs, relative paths and directory entries.
25 *
26 * This library makes a clear distinction between several path formats:
27 *
28 *  - a dirent is a path on (local) disc or a UNC path (Windows) in
29 *    either relative or absolute format.
30 *    Examples:
31 *       "/foo/bar", "X:/temp", "//server/share", "A:/" (Windows only), ""
32 *    But not:
33 *       "http://server"
34 *
35 *  - a uri, for our purposes, is a percent-encoded, absolute path
36 *    (URI) that starts with a schema definition.  In practice, these
37 *    tend to look like URLs, but never carry query strings.
38 *    Examples:
39 *       "http://server", "file:///path/to/repos",
40 *       "svn+ssh://user@host:123/My%20Stuff/file.doc"
41 *    But not:
42 *       "file", "dir/file", "A:/dir", "/My%20Stuff/file.doc", ""
43 *
44 *  - a relative path (relpath) is an unrooted path that can be joined
45 *    to any other relative path, uri or dirent. A relative path is
46 *    never rooted/prefixed by a '/'.
47 *    Examples:
48 *       "file", "dir/file", "dir/subdir/../file", ""
49 *    But not:
50 *       "/file", "http://server/file"
51 *
52 * This distinction is needed because on Windows we have to handle some
53 * dirents and URIs differently. Since it's not possible to determine from
54 * the path string if it's a dirent or a URI, it's up to the API user to
55 * make this choice. See also issue #2028.
56 *
57 * All incoming and outgoing paths are non-NULL unless otherwise documented.
58 *
59 * All of these functions expect paths passed into them to be in canonical
60 * form, except:
61 *
62 *    - @c svn_dirent_canonicalize()
63 *    - @c svn_dirent_is_canonical()
64 *    - @c svn_dirent_internal_style()
65 *    - @c svn_relpath_canonicalize()
66 *    - @c svn_relpath_is_canonical()
67 *    - @c svn_relpath__internal_style()
68 *    - @c svn_uri_canonicalize()
69 *    - @c svn_uri_is_canonical()
70 *
71 * The Subversion codebase also recognizes some other classes of path:
72 *
73 *  - A Subversion filesystem path (fspath) -- otherwise known as a
74 *    path within a repository -- is a path relative to the root of
75 *    the repository filesystem, that starts with a slash ("/").  The
76 *    rules for a fspath are the same as for a relpath except for the
77 *    leading '/'.  A fspath never ends with '/' except when the whole
78 *    path is just '/'.  The fspath API is private (see
79 *    private/svn_fspath.h).
80 *
81 *  - A URL path (urlpath) is just the path part of a URL (the part
82 *    that follows the schema, username, hostname, and port).  These
83 *    are also like relpaths, except that they have a leading slash
84 *    (like fspaths) and are URI-encoded.  The urlpath API is also
85 *    private (see private/svn_fspath.h)
86 *    Example:
87 *       "/svn/repos/trunk/README",
88 *       "/svn/repos/!svn/bc/45/file%20with%20spaces.txt"
89 *
90 * So, which path API is appropriate for your use-case?
91 *
92 *  - If your path refers to a local file, directory, symlink, etc. of
93 *    the sort that you can examine and operate on with other software
94 *    on your computer, it's a dirent.
95 *
96 *  - If your path is a full URL -- with a schema, hostname (maybe),
97 *    and path portion -- it's a uri.
98 *
99 *  - If your path is relative, and is somewhat ambiguous unless it's
100 *    joined to some other more explicit (possible absolute) base
101 *    (such as a dirent or URL), it's a relpath.
102 *
103 *  - If your path is the virtual path of a versioned object inside a
104 *    Subversion repository, it could be one of two different types of
105 *    paths.  We'd prefer to use relpaths (relative to the root
106 *    directory of the virtual repository filesystem) for that stuff,
107 *    but some legacy code uses fspaths.  You'll need to figure out if
108 *    your code expects repository paths to have a leading '/' or not.
109 *    If so, they are fspaths; otherwise they are relpaths.
110 *
111 *  - If your path refers only to the path part of URL -- as if
112 *    someone hacked off the initial schema and hostname portion --
113 *    it's a urlpath.  To date, the ra_dav modules are the only ones
114 *    within Subversion that make use of urlpaths, and this is because
115 *    WebDAV makes heavy use of that form of path specification.
116 *
117 * When translating between local paths (dirents) and uris code should
118 * always go via the relative path format, perhaps by truncating a
119 * parent portion from a path with svn_*_skip_ancestor(), or by
120 * converting portions to basenames and then joining to existing
121 * paths.
122 *
123 * SECURITY WARNING: If a path that is received from an untrusted
124 * source -- such as from the network -- is converted to a dirent it
125 * should be tested with svn_dirent_is_under_root() before you can
126 * assume the path to be a safe local path.
127 *
128 * MEMORY ALLOCATION: A function documented as allocating the result
129 * in a pool may instead return a static string such as "." or "". If
130 * the result is equal to an input, it will duplicate the input.
131 */
132
133#ifndef SVN_DIRENT_URI_H
134#define SVN_DIRENT_URI_H
135
136#include <apr.h>
137#include <apr_pools.h>
138#include <apr_tables.h>
139
140#include "svn_types.h"
141
142#ifdef __cplusplus
143extern "C" {
144#endif /* __cplusplus */
145
146
147/** Convert @a dirent from the local style to the canonical internal style.
148 * "Local style" means native path separators and "." for the empty path.
149 *
150 * Allocate the result in @a result_pool.
151 *
152 * @since New in 1.6.
153 */
154const char *
155svn_dirent_internal_style(const char *dirent,
156                          apr_pool_t *result_pool);
157
158/** Convert @a dirent from the internal style to the local style.
159 * "Local style" means native path separators and "." for the empty path.
160 * If the input is not canonical, the output may not be canonical.
161 *
162 * Allocate the result in @a result_pool.
163 *
164 * @since New in 1.6.
165 */
166const char *
167svn_dirent_local_style(const char *dirent,
168                       apr_pool_t *result_pool);
169
170/** Convert @a relpath from the local style to the canonical internal style.
171 * "Local style" means native path separators and "." for the empty path.
172 *
173 * Allocate the result in @a result_pool.
174 *
175 * @since New in 1.7.
176 */
177const char *
178svn_relpath__internal_style(const char *relpath,
179                            apr_pool_t *result_pool);
180
181
182/** Join a base dirent (@a base) with a component (@a component).
183 *
184 * If either @a base or @a component is the empty string, then the other
185 * argument will be copied and returned.  If both are the empty string then
186 * empty string is returned.
187 *
188 * If the @a component is an absolute dirent, then it is copied and returned.
189 * The platform specific rules for joining paths are used to join the components.
190 *
191 * This function is NOT appropriate for native (local) file
192 * dirents. Only for "internal" canonicalized dirents, since it uses '/'
193 * for the separator.
194 *
195 * Allocate the result in @a result_pool.
196 *
197 * @since New in 1.6.
198 */
199char *
200svn_dirent_join(const char *base,
201                const char *component,
202                apr_pool_t *result_pool);
203
204/** Join multiple components onto a @a base dirent. The components are
205 * terminated by a @c SVN_VA_NULL.
206 *
207 * If any component is the empty string, it will be ignored.
208 *
209 * If any component is an absolute dirent, then it resets the base and
210 * further components will be appended to it.
211 *
212 * See svn_dirent_join() for further notes about joining dirents.
213 *
214 * Allocate the result in @a result_pool.
215 *
216 * @since New in 1.6.
217 */
218char *
219svn_dirent_join_many(apr_pool_t *result_pool,
220                     const char *base,
221                     ...) SVN_NEEDS_SENTINEL_NULL;
222
223/** Join a base relpath (@a base) with a component (@a component).
224 * @a component need not be a single component.
225 *
226 * If either @a base or @a component is the empty path, then the other
227 * argument will be copied and returned.  If both are the empty path the
228 * empty path is returned.
229 *
230 * Allocate the result in @a result_pool.
231 *
232 * @since New in 1.7.
233 */
234char *
235svn_relpath_join(const char *base,
236                 const char *component,
237                 apr_pool_t *result_pool);
238
239/** Gets the name of the specified canonicalized @a dirent as it is known
240 * within its parent directory. If the @a dirent is root, return "". The
241 * returned value will not have slashes in it.
242 *
243 * Example: svn_dirent_basename("/foo/bar") -> "bar"
244 *
245 * If @a result_pool is NULL, return a pointer to the basename in @a dirent,
246 * otherwise allocate the result in @a result_pool.
247 *
248 * @note If an empty string is passed, then an empty string will be returned.
249 *
250 * @since New in 1.7.
251 */
252const char *
253svn_dirent_basename(const char *dirent,
254                    apr_pool_t *result_pool);
255
256/** Get the dirname of the specified canonicalized @a dirent, defined as
257 * the dirent with its basename removed.
258 *
259 * If @a dirent is root  ("/", "X:/", "//server/share/") or "", it is returned
260 * unchanged.
261 *
262 * Allocate the result in @a result_pool.
263 *
264 * @since New in 1.6.
265 */
266char *
267svn_dirent_dirname(const char *dirent,
268                   apr_pool_t *result_pool);
269
270/** Divide the canonicalized @a dirent into @a *dirpath and @a *base_name.
271 *
272 * If @a dirpath or @a base_name is NULL, then don't set that one.
273 *
274 * Either @a dirpath or @a base_name may be @a dirent's own address, but they
275 * may not both be the same address, or the results are undefined.
276 *
277 * If @a dirent has two or more components, the separator between @a dirpath
278 * and @a base_name is not included in either of the new names.
279 *
280 * Examples:
281 *             - <pre>"/foo/bar/baz"  ==>  "/foo/bar" and "baz"</pre>
282 *             - <pre>"/bar"          ==>  "/"  and "bar"</pre>
283 *             - <pre>"/"             ==>  "/"  and ""</pre>
284 *             - <pre>"bar"           ==>  ""   and "bar"</pre>
285 *             - <pre>""              ==>  ""   and ""</pre>
286 *  Windows:   - <pre>"X:/"           ==>  "X:/" and ""</pre>
287 *             - <pre>"X:/foo"        ==>  "X:/" and "foo"</pre>
288 *             - <pre>"X:foo"         ==>  "X:" and "foo"</pre>
289 *  Posix:     - <pre>"X:foo"         ==>  ""   and "X:foo"</pre>
290 *
291 * Allocate the results in @a result_pool.
292 *
293 * @since New in 1.7.
294 */
295void
296svn_dirent_split(const char **dirpath,
297                 const char **base_name,
298                 const char *dirent,
299                 apr_pool_t *result_pool);
300
301/** Divide the canonicalized @a relpath into @a *dirpath and @a *base_name.
302 *
303 * If @a dirpath or @a base_name is NULL, then don't set that one.
304 *
305 * Either @a dirpath or @a base_name may be @a relpaths's own address, but
306 * they may not both be the same address, or the results are undefined.
307 *
308 * If @a relpath has two or more components, the separator between @a dirpath
309 * and @a base_name is not included in either of the new names.
310 *
311 *   examples:
312 *             - <pre>"foo/bar/baz"  ==>  "foo/bar" and "baz"</pre>
313 *             - <pre>"bar"          ==>  ""  and "bar"</pre>
314 *             - <pre>""              ==>  ""   and ""</pre>
315 *
316 * Allocate the results in @a result_pool.
317 *
318 * @since New in 1.7.
319 */
320void
321svn_relpath_split(const char **dirpath,
322                  const char **base_name,
323                  const char *relpath,
324                  apr_pool_t *result_pool);
325
326/** Get the basename of the specified canonicalized @a relpath.  The
327 * basename is defined as the last component of the relpath.  If the @a
328 * relpath has only one component then that is returned. The returned
329 * value will have no slashes in it.
330 *
331 * Example: svn_relpath_basename("/trunk/foo/bar") -> "bar"
332 *
333 * If @a result_pool is NULL, return a pointer to the basename in @a relpath,
334 * otherwise allocate the result in @a result_pool.
335 *
336 * @note If an empty string is passed, then an empty string will be returned.
337 *
338 * @since New in 1.7.
339 */
340const char *
341svn_relpath_basename(const char *relpath,
342                     apr_pool_t *result_pool);
343
344/** Get the dirname of the specified canonicalized @a relpath, defined as
345 * the relpath with its basename removed.
346 *
347 * If @a relpath is empty, "" is returned.
348 *
349 * Allocate the result in @a result_pool.
350 *
351 * @since New in 1.7.
352 */
353char *
354svn_relpath_dirname(const char *relpath,
355                    apr_pool_t *result_pool);
356
357/** Return a maximum of @a max_components components of @a relpath. This is
358 * an efficient way of calling svn_relpath_dirname() multiple times until only
359 * a specific number of components is left.
360 *
361 * Allocate the result in @a result_pool (or statically in case of 0)
362 *
363 * @since New in 1.9.
364 */
365const char *
366svn_relpath_prefix(const char *relpath,
367                   int max_components,
368                   apr_pool_t *result_pool);
369
370
371/** Divide the canonicalized @a uri into a uri @a *dirpath and a
372 * (URI-decoded) relpath @a *base_name.
373 *
374 * If @a dirpath or @a base_name is NULL, then don't set that one.
375 *
376 * Either @a dirpath or @a base_name may be @a uri's own address, but they
377 * may not both be the same address, or the results are undefined.
378 *
379 * If @a uri has two or more components, the separator between @a dirpath
380 * and @a base_name is not included in either of the new names.
381 *
382 * Examples:
383 *   - <pre>"http://server/foo/bar"  ==>  "http://server/foo" and "bar"</pre>
384 *
385 * Allocate the result in @a result_pool.
386 *
387 * @since New in 1.7.
388 */
389void
390svn_uri_split(const char **dirpath,
391              const char **base_name,
392              const char *uri,
393              apr_pool_t *result_pool);
394
395/** Get the (URI-decoded) basename of the specified canonicalized @a
396 * uri.  The basename is defined as the last component of the uri.  If
397 * the @a uri is root, return "".  The returned value will have no
398 * slashes in it.
399 *
400 * Example: svn_uri_basename("http://server/foo/bar") -> "bar"
401 *
402 * Allocate the result in @a result_pool.
403 *
404 * @since New in 1.7.
405 */
406const char *
407svn_uri_basename(const char *uri,
408                 apr_pool_t *result_pool);
409
410/** Get the dirname of the specified canonicalized @a uri, defined as
411 * the uri with its basename removed.
412 *
413 * If @a uri is root (e.g. "http://server"), it is returned
414 * unchanged.
415 *
416 * Allocate the result in @a result_pool.
417 *
418 * @since New in 1.7.
419 */
420char *
421svn_uri_dirname(const char *uri,
422                apr_pool_t *result_pool);
423
424/** Return TRUE if @a dirent is considered absolute on the platform at
425 * hand. E.g. '/foo' on Posix platforms or 'X:/foo', '//server/share/foo'
426 * on Windows.
427 *
428 * @since New in 1.6.
429 */
430svn_boolean_t
431svn_dirent_is_absolute(const char *dirent);
432
433/** Return TRUE if @a dirent is considered a root directory on the platform
434 * at hand.
435 * E.g.:
436 *  On Posix:   '/'
437 *  On Windows: '/', 'X:/', '//server/share', 'X:'
438 *
439 * Note that on Windows '/' and 'X:' are roots, but paths starting with this
440 * root are not absolute.
441 *
442 * @since New in 1.5.
443 */
444svn_boolean_t
445svn_dirent_is_root(const char *dirent,
446                   apr_size_t len);
447
448/** Return TRUE if @a uri is a root URL (e.g., "http://server").
449 *
450 * @since New in 1.7
451 */
452svn_boolean_t
453svn_uri_is_root(const char *uri,
454                apr_size_t len);
455
456/** Return a new dirent like @a dirent, but transformed such that some types
457 * of dirent specification redundancies are removed.
458 *
459 * This involves:
460 *   - collapsing redundant "/./" elements
461 *   - removing multiple adjacent separator characters
462 *   - removing trailing separator characters
463 *   - converting the server name of a UNC path to lower case (on Windows)
464 *   - converting a drive letter to upper case (on Windows)
465 *
466 * and possibly other semantically inoperative transformations.
467 *
468 * Allocate the result in @a result_pool.
469 *
470 * @since New in 1.6.
471 */
472const char *
473svn_dirent_canonicalize(const char *dirent,
474                        apr_pool_t *result_pool);
475
476
477/** Return a new relpath like @a relpath, but transformed such that some types
478 * of relpath specification redundancies are removed.
479 *
480 * This involves:
481 *   - collapsing redundant "/./" elements
482 *   - removing multiple adjacent separator characters
483 *   - removing trailing separator characters
484 *
485 * and possibly other semantically inoperative transformations.
486 *
487 * Allocate the result in @a result_pool.
488 *
489 * @since New in 1.7.
490 */
491const char *
492svn_relpath_canonicalize(const char *relpath,
493                         apr_pool_t *result_pool);
494
495
496/** Return a new uri like @a uri, but transformed such that some types
497 * of uri specification redundancies are removed.
498 *
499 * This involves:
500 *   - collapsing redundant "/./" elements
501 *   - removing multiple adjacent separator characters
502 *   - removing trailing separator characters
503 *   - normalizing the escaping of the path component by unescaping
504 *     characters that don't need escaping and escaping characters that do
505 *     need escaping but weren't
506 *   - removing the port number if it is the default port number (80 for
507 *     http, 443 for https, 3690 for svn)
508 *
509 * and possibly other semantically inoperative transformations.
510 *
511 * Allocate the result in @a result_pool.
512 *
513 * @since New in 1.7.
514 */
515const char *
516svn_uri_canonicalize(const char *uri,
517                     apr_pool_t *result_pool);
518
519/** Return @c TRUE iff @a dirent is canonical.
520 *
521 * Use @a scratch_pool for temporary allocations.
522 *
523 * @note The test for canonicalization is currently defined as
524 * "looks exactly the same as @c svn_dirent_canonicalize() would make
525 * it look".
526 *
527 * @see svn_dirent_canonicalize()
528 * @since New in 1.6.
529 */
530svn_boolean_t
531svn_dirent_is_canonical(const char *dirent,
532                        apr_pool_t *scratch_pool);
533
534/** Return @c TRUE iff @a relpath is canonical.
535 *
536 * @see svn_relpath_canonicalize()
537 * @since New in 1.7.
538 */
539svn_boolean_t
540svn_relpath_is_canonical(const char *relpath);
541
542/** Return @c TRUE iff @a uri is canonical.
543 *
544 * Use @a scratch_pool for temporary allocations.
545 *
546 * @see svn_uri_canonicalize()
547 * @since New in 1.7.
548 */
549svn_boolean_t
550svn_uri_is_canonical(const char *uri,
551                     apr_pool_t *scratch_pool);
552
553/** Return the longest common dirent shared by two canonicalized dirents,
554 * @a dirent1 and @a dirent2.  If there's no common ancestor, return the
555 * empty path.
556 *
557 * Allocate the result in @a result_pool.
558 *
559 * @since New in 1.6.
560 */
561char *
562svn_dirent_get_longest_ancestor(const char *dirent1,
563                                const char *dirent2,
564                                apr_pool_t *result_pool);
565
566/** Return the longest common path shared by two relative paths,
567 * @a relpath1 and @a relpath2.  If there's no common ancestor, return the
568 * empty path.
569 *
570 * Allocate the result in @a result_pool.
571 *
572 * @since New in 1.7.
573 */
574char *
575svn_relpath_get_longest_ancestor(const char *relpath1,
576                                 const char *relpath2,
577                                 apr_pool_t *result_pool);
578
579/** Return the longest common path shared by two canonicalized uris,
580 * @a uri1 and @a uri2.  If there's no common ancestor, return the
581 * empty path.  In order for two URLs to have a common ancestor, they
582 * must (a) have the same protocol (since two URLs with the same path
583 * but different protocols may point at completely different
584 * resources), and (b) share a common ancestor in their path
585 * component, i.e. 'protocol://' is not a sufficient ancestor.
586 *
587 * Allocate the result in @a result_pool.
588 *
589 * @since New in 1.7.
590 */
591char *
592svn_uri_get_longest_ancestor(const char *uri1,
593                             const char *uri2,
594                             apr_pool_t *result_pool);
595
596/** Convert @a relative canonicalized dirent to an absolute dirent and
597 * return the results in @a *pabsolute.
598 * Raise SVN_ERR_BAD_FILENAME if the absolute dirent cannot be determined.
599 *
600 * Allocate the result in @a result_pool.
601 *
602 * @since New in 1.6.
603 */
604svn_error_t *
605svn_dirent_get_absolute(const char **pabsolute,
606                        const char *relative,
607                        apr_pool_t *result_pool);
608
609/** Similar to svn_dirent_skip_ancestor(), except that if @a child_dirent is
610 * the same as @a parent_dirent, it is not considered a child, so the result
611 * is @c NULL; an empty string is never returned.
612 *
613 * If @a result_pool is NULL, return a pointer into @a child_dirent, otherwise
614 * allocate the result in @a result_pool.
615 *
616 * ### TODO: Deprecate, as the semantics are trivially
617 * obtainable from *_skip_ancestor().
618 *
619 * @since New in 1.6.
620 */
621const char *
622svn_dirent_is_child(const char *parent_dirent,
623                    const char *child_dirent,
624                    apr_pool_t *result_pool);
625
626/** Return TRUE if @a parent_dirent is an ancestor of @a child_dirent or
627 * the dirents are equal, and FALSE otherwise.
628 *
629 * ### TODO: Deprecate, as the semantics are trivially
630 * obtainable from *_skip_ancestor().
631 *
632 * @since New in 1.6.
633 */
634svn_boolean_t
635svn_dirent_is_ancestor(const char *parent_dirent,
636                       const char *child_dirent);
637
638/** Return TRUE if @a parent_uri is an ancestor of @a child_uri or
639 * the uris are equal, and FALSE otherwise.
640 */
641svn_boolean_t
642svn_uri__is_ancestor(const char *parent_uri,
643                     const char *child_uri);
644
645
646/** Return the relative path part of @a child_dirent that is below
647 * @a parent_dirent, or just "" if @a parent_dirent is equal to
648 * @a child_dirent. If @a child_dirent is not below or equal to
649 * @a parent_dirent, return NULL.
650 *
651 * If one of @a parent_dirent and @a child_dirent is absolute and
652 * the other relative, return NULL.
653 *
654 * @since New in 1.7.
655 */
656const char *
657svn_dirent_skip_ancestor(const char *parent_dirent,
658                         const char *child_dirent);
659
660/** Return the relative path part of @a child_relpath that is below
661 * @a parent_relpath, or just "" if @a parent_relpath is equal to
662 * @a child_relpath. If @a child_relpath is not below @a parent_relpath,
663 * return NULL.
664 *
665 * @since New in 1.7.
666 */
667const char *
668svn_relpath_skip_ancestor(const char *parent_relpath,
669                          const char *child_relpath);
670
671/** Return the URI-decoded relative path of @a child_uri that is below
672 * @a parent_uri, or just "" if @a parent_uri is equal to @a child_uri. If
673 * @a child_uri is not below @a parent_uri, return NULL.
674 *
675 * Allocate the result in @a result_pool.
676 *
677 * @since New in 1.7.
678 */
679const char *
680svn_uri_skip_ancestor(const char *parent_uri,
681                      const char *child_uri,
682                      apr_pool_t *result_pool);
683
684/** Find the common prefix of the canonicalized dirents in @a targets
685 * (an array of <tt>const char *</tt>'s), and remove redundant dirents if @a
686 * remove_redundancies is TRUE.
687 *
688 *   - Set @a *pcommon to the absolute dirent of the dirent common to
689 *     all of the targets.  If the targets have no common prefix (e.g.
690 *     "C:/file" and "D:/file" on Windows), set @a *pcommon to the empty
691 *     string.
692 *
693 *   - If @a pcondensed_targets is non-NULL, set @a *pcondensed_targets
694 *     to an array of targets relative to @a *pcommon, and if
695 *     @a remove_redundancies is TRUE, omit any dirents that are
696 *     descendants of another dirent in @a targets.  If *pcommon
697 *     is empty, @a *pcondensed_targets will contain absolute dirents;
698 *     redundancies can still be removed.  If @a pcondensed_targets is NULL,
699 *     leave it alone.
700 *
701 * Else if there is exactly one target, then
702 *
703 *   - Set @a *pcommon to that target, and
704 *
705 *   - If @a pcondensed_targets is non-NULL, set @a *pcondensed_targets
706 *     to an array containing zero elements.  Else if
707 *     @a pcondensed_targets is NULL, leave it alone.
708 *
709 * If there are no items in @a targets, set @a *pcommon and (if
710 * applicable) @a *pcondensed_targets to @c NULL.
711 *
712 * Allocate the results in @a result_pool. Use @a scratch_pool for
713 * temporary allocations.
714 *
715 * @since New in 1.7.
716 */
717svn_error_t *
718svn_dirent_condense_targets(const char **pcommon,
719                            apr_array_header_t **pcondensed_targets,
720                            const apr_array_header_t *targets,
721                            svn_boolean_t remove_redundancies,
722                            apr_pool_t *result_pool,
723                            apr_pool_t *scratch_pool);
724
725/** Find the common prefix of the canonicalized uris in @a targets
726 * (an array of <tt>const char *</tt>'s), and remove redundant uris if @a
727 * remove_redundancies is TRUE.
728 *
729 *   - Set @a *pcommon to the common base uri of all of the targets.
730 *     If the targets have no common prefix (e.g. "http://srv1/file"
731 *     and "http://srv2/file"), set @a *pcommon to the empty
732 *     string.
733 *
734 *   - If @a pcondensed_targets is non-NULL, set @a *pcondensed_targets
735 *     to an array of URI-decoded targets relative to @a *pcommon, and
736 *     if @a remove_redundancies is TRUE, omit any uris that are
737 *     descendants of another uri in @a targets.  If *pcommon is
738 *     empty, @a *pcondensed_targets will contain absolute uris;
739 *     redundancies can still be removed.  If @a pcondensed_targets is
740 *     NULL, leave it alone.
741 *
742 * Else if there is exactly one target, then
743 *
744 *   - Set @a *pcommon to that target, and
745 *
746 *   - If @a pcondensed_targets is non-NULL, set @a *pcondensed_targets
747 *     to an array containing zero elements.  Else if
748 *     @a pcondensed_targets is NULL, leave it alone.
749 *
750 * If there are no items in @a targets, set @a *pcommon and (if
751 * applicable) @a *pcondensed_targets to @c NULL.
752 *
753 * Allocate the results in @a result_pool. Use @a scratch_pool for
754 * temporary allocations.
755 *
756 * @since New in 1.7.
757 */
758svn_error_t *
759svn_uri_condense_targets(const char **pcommon,
760                         apr_array_header_t **pcondensed_targets,
761                         const apr_array_header_t *targets,
762                         svn_boolean_t remove_redundancies,
763                         apr_pool_t *result_pool,
764                         apr_pool_t *scratch_pool);
765
766/** Join @a path onto @a base_path, checking that @a path does not attempt
767 * to traverse above @a base_path. If @a path or any ".." component within
768 * it resolves to a path above @a base_path, or if @a path is an absolute
769 * path, then set @a *under_root to @c FALSE. Otherwise, set @a *under_root
770 * to @c TRUE and, if @a result_path is not @c NULL, set @a *result_path to
771 * the resulting path.
772 *
773 * @a path need not be canonical. @a base_path must be canonical and
774 * @a *result_path will be canonical.
775 *
776 * Allocate the result in @a result_pool.
777 *
778 * @note Use of this function is strongly encouraged. Do not roll your own.
779 * (http://cve.mitre.org/cgi-bin/cvename.cgi?name=2007-3846)
780 *
781 * @since New in 1.7.
782 */
783svn_error_t *
784svn_dirent_is_under_root(svn_boolean_t *under_root,
785                         const char **result_path,
786                         const char *base_path,
787                         const char *path,
788                         apr_pool_t *result_pool);
789
790/** Set @a *dirent to the path corresponding to the file:// URL @a url, using
791 * the platform-specific file:// rules.
792 *
793 * Allocate the result in @a result_pool.
794 *
795 * @since New in 1.7.
796 */
797svn_error_t *
798svn_uri_get_dirent_from_file_url(const char **dirent,
799                                 const char *url,
800                                 apr_pool_t *result_pool);
801
802/** Set @a *url to a file:// URL, corresponding to @a dirent using the
803 * platform specific dirent and file:// rules.
804 *
805 * Allocate the result in @a result_pool.
806 *
807 * @since New in 1.7.
808 */
809svn_error_t *
810svn_uri_get_file_url_from_dirent(const char **url,
811                                 const char *dirent,
812                                 apr_pool_t *result_pool);
813
814#ifdef __cplusplus
815}
816#endif /* __cplusplus */
817
818#endif /* SVN_DIRENT_URI_H */
819