* xmlNormalizePath: * @path: pointer to the path string * @isFile: true for filesystem paths, false for URIs * * Normalize a filesystem path or URI. * * Returns 0 or an error code */
| 1487 | * Returns 0 or an error code |
| 1488 | */ |
| 1489 | static int |
| 1490 | xmlNormalizePath(char *path, int isFile) { |
| 1491 | char *cur, *out; |
| 1492 | int numSeg = 0; |
| 1493 | |
| 1494 | if (path == NULL) |
| 1495 | return(-1); |
| 1496 | |
| 1497 | cur = path; |
| 1498 | out = path; |
| 1499 | |
| 1500 | if (*cur == 0) |
| 1501 | return(0); |
| 1502 | |
| 1503 | if (xmlIsPathSeparator(*cur, isFile)) { |
| 1504 | cur++; |
| 1505 | *out++ = '/'; |
| 1506 | } |
| 1507 | |
| 1508 | while (*cur != 0) { |
| 1509 | /* |
| 1510 | * At this point, out is either empty or ends with a separator. |
| 1511 | * Collapse multiple separators first. |
| 1512 | */ |
| 1513 | while (xmlIsPathSeparator(*cur, isFile)) { |
| 1514 | #if defined(_WIN32) || defined(__CYGWIN__) |
| 1515 | /* Allow two separators at start of path */ |
| 1516 | if ((isFile) && (out == path + 1)) |
| 1517 | *out++ = '/'; |
| 1518 | #endif |
| 1519 | cur++; |
| 1520 | } |
| 1521 | |
| 1522 | if (*cur == '.') { |
| 1523 | if (cur[1] == 0) { |
| 1524 | /* Ignore "." at end of path */ |
| 1525 | break; |
| 1526 | } else if (xmlIsPathSeparator(cur[1], isFile)) { |
| 1527 | /* Skip "./" */ |
| 1528 | cur += 2; |
| 1529 | continue; |
| 1530 | } else if ((cur[1] == '.') && |
| 1531 | ((cur[2] == 0) || xmlIsPathSeparator(cur[2], isFile))) { |
| 1532 | if (numSeg > 0) { |
| 1533 | /* Handle ".." by removing last segment */ |
| 1534 | do { |
| 1535 | out--; |
| 1536 | } while ((out > path) && |
| 1537 | !xmlIsPathSeparator(out[-1], isFile)); |
| 1538 | numSeg--; |
| 1539 | |
| 1540 | if (cur[2] == 0) |
| 1541 | break; |
| 1542 | cur += 3; |
| 1543 | continue; |
| 1544 | } else if (out[0] == '/') { |
| 1545 | /* Ignore extraneous ".." in absolute paths */ |
| 1546 | if (cur[2] == 0) |
no test coverage detected