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