Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenuri.c
Go to the documentation of this file.
00001 00011 #define IN_LIBXML 00012 #include "libxml.h" 00013 00014 #include <string.h> 00015 00016 #include <libxml/xmlmemory.h> 00017 #include <libxml/uri.h> 00018 #include <libxml/globals.h> 00019 #include <libxml/xmlerror.h> 00020 00021 static void xmlCleanURI(xmlURIPtr uri); 00022 00023 /* 00024 * Old rule from 2396 used in legacy handling code 00025 * alpha = lowalpha | upalpha 00026 */ 00027 #define IS_ALPHA(x) (IS_LOWALPHA(x) || IS_UPALPHA(x)) 00028 00029 00030 /* 00031 * lowalpha = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | 00032 * "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" | 00033 * "u" | "v" | "w" | "x" | "y" | "z" 00034 */ 00035 00036 #define IS_LOWALPHA(x) (((x) >= 'a') && ((x) <= 'z')) 00037 00038 /* 00039 * upalpha = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | 00040 * "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" | 00041 * "U" | "V" | "W" | "X" | "Y" | "Z" 00042 */ 00043 #define IS_UPALPHA(x) (((x) >= 'A') && ((x) <= 'Z')) 00044 00045 #ifdef IS_DIGIT 00046 #undef IS_DIGIT 00047 #endif 00048 /* 00049 * digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" 00050 */ 00051 #define IS_DIGIT(x) (((x) >= '0') && ((x) <= '9')) 00052 00053 /* 00054 * alphanum = alpha | digit 00055 */ 00056 00057 #define IS_ALPHANUM(x) (IS_ALPHA(x) || IS_DIGIT(x)) 00058 00059 /* 00060 * mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")" 00061 */ 00062 00063 #define IS_MARK(x) (((x) == '-') || ((x) == '_') || ((x) == '.') || \ 00064 ((x) == '!') || ((x) == '~') || ((x) == '*') || ((x) == '\'') || \ 00065 ((x) == '(') || ((x) == ')')) 00066 00067 /* 00068 * unwise = "{" | "}" | "|" | "\" | "^" | "`" 00069 */ 00070 00071 #define IS_UNWISE(p) \ 00072 (((*(p) == '{')) || ((*(p) == '}')) || ((*(p) == '|')) || \ 00073 ((*(p) == '\\')) || ((*(p) == '^')) || ((*(p) == '[')) || \ 00074 ((*(p) == ']')) || ((*(p) == '`'))) 00075 /* 00076 * reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | "," | 00077 * "[" | "]" 00078 */ 00079 00080 #define IS_RESERVED(x) (((x) == ';') || ((x) == '/') || ((x) == '?') || \ 00081 ((x) == ':') || ((x) == '@') || ((x) == '&') || ((x) == '=') || \ 00082 ((x) == '+') || ((x) == '$') || ((x) == ',') || ((x) == '[') || \ 00083 ((x) == ']')) 00084 00085 /* 00086 * unreserved = alphanum | mark 00087 */ 00088 00089 #define IS_UNRESERVED(x) (IS_ALPHANUM(x) || IS_MARK(x)) 00090 00091 /* 00092 * Skip to next pointer char, handle escaped sequences 00093 */ 00094 00095 #define NEXT(p) ((*p == '%')? p += 3 : p++) 00096 00097 /* 00098 * Productions from the spec. 00099 * 00100 * authority = server | reg_name 00101 * reg_name = 1*( unreserved | escaped | "$" | "," | 00102 * ";" | ":" | "@" | "&" | "=" | "+" ) 00103 * 00104 * path = [ abs_path | opaque_part ] 00105 */ 00106 00107 #define STRNDUP(s, n) (char *) xmlStrndup((const xmlChar *)(s), (n)) 00108 00109 /************************************************************************ 00110 * * 00111 * RFC 3986 parser * 00112 * * 00113 ************************************************************************/ 00114 00115 #define ISA_DIGIT(p) ((*(p) >= '0') && (*(p) <= '9')) 00116 #define ISA_ALPHA(p) (((*(p) >= 'a') && (*(p) <= 'z')) || \ 00117 ((*(p) >= 'A') && (*(p) <= 'Z'))) 00118 #define ISA_HEXDIG(p) \ 00119 (ISA_DIGIT(p) || ((*(p) >= 'a') && (*(p) <= 'f')) || \ 00120 ((*(p) >= 'A') && (*(p) <= 'F'))) 00121 00122 /* 00123 * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" 00124 * / "*" / "+" / "," / ";" / "=" 00125 */ 00126 #define ISA_SUB_DELIM(p) \ 00127 (((*(p) == '!')) || ((*(p) == '$')) || ((*(p) == '&')) || \ 00128 ((*(p) == '(')) || ((*(p) == ')')) || ((*(p) == '*')) || \ 00129 ((*(p) == '+')) || ((*(p) == ',')) || ((*(p) == ';')) || \ 00130 ((*(p) == '=')) || ((*(p) == '\''))) 00131 00132 /* 00133 * gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" 00134 */ 00135 #define ISA_GEN_DELIM(p) \ 00136 (((*(p) == ':')) || ((*(p) == '/')) || ((*(p) == '?')) || \ 00137 ((*(p) == '#')) || ((*(p) == '[')) || ((*(p) == ']')) || \ 00138 ((*(p) == '@'))) 00139 00140 /* 00141 * reserved = gen-delims / sub-delims 00142 */ 00143 #define ISA_RESERVED(p) (ISA_GEN_DELIM(p) || (ISA_SUB_DELIM(p))) 00144 00145 /* 00146 * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" 00147 */ 00148 #define ISA_UNRESERVED(p) \ 00149 ((ISA_ALPHA(p)) || (ISA_DIGIT(p)) || ((*(p) == '-')) || \ 00150 ((*(p) == '.')) || ((*(p) == '_')) || ((*(p) == '~'))) 00151 00152 /* 00153 * pct-encoded = "%" HEXDIG HEXDIG 00154 */ 00155 #define ISA_PCT_ENCODED(p) \ 00156 ((*(p) == '%') && (ISA_HEXDIG(p + 1)) && (ISA_HEXDIG(p + 2))) 00157 00158 /* 00159 * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" 00160 */ 00161 #define ISA_PCHAR(p) \ 00162 (ISA_UNRESERVED(p) || ISA_PCT_ENCODED(p) || ISA_SUB_DELIM(p) || \ 00163 ((*(p) == ':')) || ((*(p) == '@'))) 00164 00176 static int 00177 xmlParse3986Scheme(xmlURIPtr uri, const char **str) { 00178 const char *cur; 00179 00180 if (str == NULL) 00181 return(-1); 00182 00183 cur = *str; 00184 if (!ISA_ALPHA(cur)) 00185 return(2); 00186 cur++; 00187 while (ISA_ALPHA(cur) || ISA_DIGIT(cur) || 00188 (*cur == '+') || (*cur == '-') || (*cur == '.')) cur++; 00189 if (uri != NULL) { 00190 if (uri->scheme != NULL) xmlFree(uri->scheme); 00191 uri->scheme = STRNDUP(*str, cur - *str); 00192 } 00193 *str = cur; 00194 return(0); 00195 } 00196 00212 static int 00213 xmlParse3986Fragment(xmlURIPtr uri, const char **str) 00214 { 00215 const char *cur; 00216 00217 if (str == NULL) 00218 return (-1); 00219 00220 cur = *str; 00221 00222 while ((ISA_PCHAR(cur)) || (*cur == '/') || (*cur == '?') || 00223 (*cur == '[') || (*cur == ']') || 00224 ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur)))) 00225 NEXT(cur); 00226 if (uri != NULL) { 00227 if (uri->fragment != NULL) 00228 xmlFree(uri->fragment); 00229 if (uri->cleanup & 2) 00230 uri->fragment = STRNDUP(*str, cur - *str); 00231 else 00232 uri->fragment = xmlURIUnescapeString(*str, cur - *str, NULL); 00233 } 00234 *str = cur; 00235 return (0); 00236 } 00237 00249 static int 00250 xmlParse3986Query(xmlURIPtr uri, const char **str) 00251 { 00252 const char *cur; 00253 00254 if (str == NULL) 00255 return (-1); 00256 00257 cur = *str; 00258 00259 while ((ISA_PCHAR(cur)) || (*cur == '/') || (*cur == '?') || 00260 ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur)))) 00261 NEXT(cur); 00262 if (uri != NULL) { 00263 if (uri->query != NULL) 00264 xmlFree(uri->query); 00265 if (uri->cleanup & 2) 00266 uri->query = STRNDUP(*str, cur - *str); 00267 else 00268 uri->query = xmlURIUnescapeString(*str, cur - *str, NULL); 00269 00270 /* Save the raw bytes of the query as well. 00271 * See: http://mail.gnome.org/archives/xml/2007-April/thread.html#00114 00272 */ 00273 if (uri->query_raw != NULL) 00274 xmlFree (uri->query_raw); 00275 uri->query_raw = STRNDUP (*str, cur - *str); 00276 } 00277 *str = cur; 00278 return (0); 00279 } 00280 00293 static int 00294 xmlParse3986Port(xmlURIPtr uri, const char **str) 00295 { 00296 const char *cur = *str; 00297 00298 if (ISA_DIGIT(cur)) { 00299 if (uri != NULL) 00300 uri->port = 0; 00301 while (ISA_DIGIT(cur)) { 00302 if (uri != NULL) 00303 uri->port = uri->port * 10 + (*cur - '0'); 00304 cur++; 00305 } 00306 *str = cur; 00307 return(0); 00308 } 00309 return(1); 00310 } 00311 00324 static int 00325 xmlParse3986Userinfo(xmlURIPtr uri, const char **str) 00326 { 00327 const char *cur; 00328 00329 cur = *str; 00330 while (ISA_UNRESERVED(cur) || ISA_PCT_ENCODED(cur) || 00331 ISA_SUB_DELIM(cur) || (*cur == ':')) 00332 NEXT(cur); 00333 if (*cur == '@') { 00334 if (uri != NULL) { 00335 if (uri->user != NULL) xmlFree(uri->user); 00336 if (uri->cleanup & 2) 00337 uri->user = STRNDUP(*str, cur - *str); 00338 else 00339 uri->user = xmlURIUnescapeString(*str, cur - *str, NULL); 00340 } 00341 *str = cur; 00342 return(0); 00343 } 00344 return(1); 00345 } 00346 00361 static int 00362 xmlParse3986DecOctet(const char **str) { 00363 const char *cur = *str; 00364 00365 if (!(ISA_DIGIT(cur))) 00366 return(1); 00367 if (!ISA_DIGIT(cur+1)) 00368 cur++; 00369 else if ((*cur != '0') && (ISA_DIGIT(cur + 1)) && (!ISA_DIGIT(cur+2))) 00370 cur += 2; 00371 else if ((*cur == '1') && (ISA_DIGIT(cur + 1)) && (ISA_DIGIT(cur + 2))) 00372 cur += 3; 00373 else if ((*cur == '2') && (*(cur + 1) >= '0') && 00374 (*(cur + 1) <= '4') && (ISA_DIGIT(cur + 2))) 00375 cur += 3; 00376 else if ((*cur == '2') && (*(cur + 1) == '5') && 00377 (*(cur + 2) >= '0') && (*(cur + 1) <= '5')) 00378 cur += 3; 00379 else 00380 return(1); 00381 *str = cur; 00382 return(0); 00383 } 00399 static int 00400 xmlParse3986Host(xmlURIPtr uri, const char **str) 00401 { 00402 const char *cur = *str; 00403 const char *host; 00404 00405 host = cur; 00406 /* 00407 * IPv6 and future adressing scheme are enclosed between brackets 00408 */ 00409 if (*cur == '[') { 00410 cur++; 00411 while ((*cur != ']') && (*cur != 0)) 00412 cur++; 00413 if (*cur != ']') 00414 return(1); 00415 cur++; 00416 goto found; 00417 } 00418 /* 00419 * try to parse an IPv4 00420 */ 00421 if (ISA_DIGIT(cur)) { 00422 if (xmlParse3986DecOctet(&cur) != 0) 00423 goto not_ipv4; 00424 if (*cur != '.') 00425 goto not_ipv4; 00426 cur++; 00427 if (xmlParse3986DecOctet(&cur) != 0) 00428 goto not_ipv4; 00429 if (*cur != '.') 00430 goto not_ipv4; 00431 if (xmlParse3986DecOctet(&cur) != 0) 00432 goto not_ipv4; 00433 if (*cur != '.') 00434 goto not_ipv4; 00435 if (xmlParse3986DecOctet(&cur) != 0) 00436 goto not_ipv4; 00437 goto found; 00438 not_ipv4: 00439 cur = *str; 00440 } 00441 /* 00442 * then this should be a hostname which can be empty 00443 */ 00444 while (ISA_UNRESERVED(cur) || ISA_PCT_ENCODED(cur) || ISA_SUB_DELIM(cur)) 00445 NEXT(cur); 00446 found: 00447 if (uri != NULL) { 00448 if (uri->authority != NULL) xmlFree(uri->authority); 00449 uri->authority = NULL; 00450 if (uri->server != NULL) xmlFree(uri->server); 00451 if (cur != host) { 00452 if (uri->cleanup & 2) 00453 uri->server = STRNDUP(host, cur - host); 00454 else 00455 uri->server = xmlURIUnescapeString(host, cur - host, NULL); 00456 } else 00457 uri->server = NULL; 00458 } 00459 *str = cur; 00460 return(0); 00461 } 00462 00475 static int 00476 xmlParse3986Authority(xmlURIPtr uri, const char **str) 00477 { 00478 const char *cur; 00479 int ret; 00480 00481 cur = *str; 00482 /* 00483 * try to parse an userinfo and check for the trailing @ 00484 */ 00485 ret = xmlParse3986Userinfo(uri, &cur); 00486 if ((ret != 0) || (*cur != '@')) 00487 cur = *str; 00488 else 00489 cur++; 00490 ret = xmlParse3986Host(uri, &cur); 00491 if (ret != 0) return(ret); 00492 if (*cur == ':') { 00493 cur++; 00494 ret = xmlParse3986Port(uri, &cur); 00495 if (ret != 0) return(ret); 00496 } 00497 *str = cur; 00498 return(0); 00499 } 00500 00517 static int 00518 xmlParse3986Segment(const char **str, char forbid, int empty) 00519 { 00520 const char *cur; 00521 00522 cur = *str; 00523 if (!ISA_PCHAR(cur)) { 00524 if (empty) 00525 return(0); 00526 return(1); 00527 } 00528 while (ISA_PCHAR(cur) && (*cur != forbid)) 00529 NEXT(cur); 00530 *str = cur; 00531 return (0); 00532 } 00533 00546 static int 00547 xmlParse3986PathAbEmpty(xmlURIPtr uri, const char **str) 00548 { 00549 const char *cur; 00550 int ret; 00551 00552 cur = *str; 00553 00554 while (*cur == '/') { 00555 cur++; 00556 ret = xmlParse3986Segment(&cur, 0, 1); 00557 if (ret != 0) return(ret); 00558 } 00559 if (uri != NULL) { 00560 if (uri->path != NULL) xmlFree(uri->path); 00561 if (*str != cur) { 00562 if (uri->cleanup & 2) 00563 uri->path = STRNDUP(*str, cur - *str); 00564 else 00565 uri->path = xmlURIUnescapeString(*str, cur - *str, NULL); 00566 } else { 00567 uri->path = NULL; 00568 } 00569 } 00570 *str = cur; 00571 return (0); 00572 } 00573 00586 static int 00587 xmlParse3986PathAbsolute(xmlURIPtr uri, const char **str) 00588 { 00589 const char *cur; 00590 int ret; 00591 00592 cur = *str; 00593 00594 if (*cur != '/') 00595 return(1); 00596 cur++; 00597 ret = xmlParse3986Segment(&cur, 0, 0); 00598 if (ret == 0) { 00599 while (*cur == '/') { 00600 cur++; 00601 ret = xmlParse3986Segment(&cur, 0, 1); 00602 if (ret != 0) return(ret); 00603 } 00604 } 00605 if (uri != NULL) { 00606 if (uri->path != NULL) xmlFree(uri->path); 00607 if (cur != *str) { 00608 if (uri->cleanup & 2) 00609 uri->path = STRNDUP(*str, cur - *str); 00610 else 00611 uri->path = xmlURIUnescapeString(*str, cur - *str, NULL); 00612 } else { 00613 uri->path = NULL; 00614 } 00615 } 00616 *str = cur; 00617 return (0); 00618 } 00619 00632 static int 00633 xmlParse3986PathRootless(xmlURIPtr uri, const char **str) 00634 { 00635 const char *cur; 00636 int ret; 00637 00638 cur = *str; 00639 00640 ret = xmlParse3986Segment(&cur, 0, 0); 00641 if (ret != 0) return(ret); 00642 while (*cur == '/') { 00643 cur++; 00644 ret = xmlParse3986Segment(&cur, 0, 1); 00645 if (ret != 0) return(ret); 00646 } 00647 if (uri != NULL) { 00648 if (uri->path != NULL) xmlFree(uri->path); 00649 if (cur != *str) { 00650 if (uri->cleanup & 2) 00651 uri->path = STRNDUP(*str, cur - *str); 00652 else 00653 uri->path = xmlURIUnescapeString(*str, cur - *str, NULL); 00654 } else { 00655 uri->path = NULL; 00656 } 00657 } 00658 *str = cur; 00659 return (0); 00660 } 00661 00674 static int 00675 xmlParse3986PathNoScheme(xmlURIPtr uri, const char **str) 00676 { 00677 const char *cur; 00678 int ret; 00679 00680 cur = *str; 00681 00682 ret = xmlParse3986Segment(&cur, ':', 0); 00683 if (ret != 0) return(ret); 00684 while (*cur == '/') { 00685 cur++; 00686 ret = xmlParse3986Segment(&cur, 0, 1); 00687 if (ret != 0) return(ret); 00688 } 00689 if (uri != NULL) { 00690 if (uri->path != NULL) xmlFree(uri->path); 00691 if (cur != *str) { 00692 if (uri->cleanup & 2) 00693 uri->path = STRNDUP(*str, cur - *str); 00694 else 00695 uri->path = xmlURIUnescapeString(*str, cur - *str, NULL); 00696 } else { 00697 uri->path = NULL; 00698 } 00699 } 00700 *str = cur; 00701 return (0); 00702 } 00703 00719 static int 00720 xmlParse3986HierPart(xmlURIPtr uri, const char **str) 00721 { 00722 const char *cur; 00723 int ret; 00724 00725 cur = *str; 00726 00727 if ((*cur == '/') && (*(cur + 1) == '/')) { 00728 cur += 2; 00729 ret = xmlParse3986Authority(uri, &cur); 00730 if (ret != 0) return(ret); 00731 ret = xmlParse3986PathAbEmpty(uri, &cur); 00732 if (ret != 0) return(ret); 00733 *str = cur; 00734 return(0); 00735 } else if (*cur == '/') { 00736 ret = xmlParse3986PathAbsolute(uri, &cur); 00737 if (ret != 0) return(ret); 00738 } else if (ISA_PCHAR(cur)) { 00739 ret = xmlParse3986PathRootless(uri, &cur); 00740 if (ret != 0) return(ret); 00741 } else { 00742 /* path-empty is effectively empty */ 00743 if (uri != NULL) { 00744 if (uri->path != NULL) xmlFree(uri->path); 00745 uri->path = NULL; 00746 } 00747 } 00748 *str = cur; 00749 return (0); 00750 } 00751 00768 static int 00769 xmlParse3986RelativeRef(xmlURIPtr uri, const char *str) { 00770 int ret; 00771 00772 if ((*str == '/') && (*(str + 1) == '/')) { 00773 str += 2; 00774 ret = xmlParse3986Authority(uri, &str); 00775 if (ret != 0) return(ret); 00776 ret = xmlParse3986PathAbEmpty(uri, &str); 00777 if (ret != 0) return(ret); 00778 } else if (*str == '/') { 00779 ret = xmlParse3986PathAbsolute(uri, &str); 00780 if (ret != 0) return(ret); 00781 } else if (ISA_PCHAR(str)) { 00782 ret = xmlParse3986PathNoScheme(uri, &str); 00783 if (ret != 0) return(ret); 00784 } else { 00785 /* path-empty is effectively empty */ 00786 if (uri != NULL) { 00787 if (uri->path != NULL) xmlFree(uri->path); 00788 uri->path = NULL; 00789 } 00790 } 00791 00792 if (*str == '?') { 00793 str++; 00794 ret = xmlParse3986Query(uri, &str); 00795 if (ret != 0) return(ret); 00796 } 00797 if (*str == '#') { 00798 str++; 00799 ret = xmlParse3986Fragment(uri, &str); 00800 if (ret != 0) return(ret); 00801 } 00802 if (*str != 0) { 00803 xmlCleanURI(uri); 00804 return(1); 00805 } 00806 return(0); 00807 } 00808 00809 00822 static int 00823 xmlParse3986URI(xmlURIPtr uri, const char *str) { 00824 int ret; 00825 00826 ret = xmlParse3986Scheme(uri, &str); 00827 if (ret != 0) return(ret); 00828 if (*str != ':') { 00829 return(1); 00830 } 00831 str++; 00832 ret = xmlParse3986HierPart(uri, &str); 00833 if (ret != 0) return(ret); 00834 if (*str == '?') { 00835 str++; 00836 ret = xmlParse3986Query(uri, &str); 00837 if (ret != 0) return(ret); 00838 } 00839 if (*str == '#') { 00840 str++; 00841 ret = xmlParse3986Fragment(uri, &str); 00842 if (ret != 0) return(ret); 00843 } 00844 if (*str != 0) { 00845 xmlCleanURI(uri); 00846 return(1); 00847 } 00848 return(0); 00849 } 00850 00863 static int 00864 xmlParse3986URIReference(xmlURIPtr uri, const char *str) { 00865 int ret; 00866 00867 if (str == NULL) 00868 return(-1); 00869 xmlCleanURI(uri); 00870 00871 /* 00872 * Try first to parse absolute refs, then fallback to relative if 00873 * it fails. 00874 */ 00875 ret = xmlParse3986URI(uri, str); 00876 if (ret != 0) { 00877 xmlCleanURI(uri); 00878 ret = xmlParse3986RelativeRef(uri, str); 00879 if (ret != 0) { 00880 xmlCleanURI(uri); 00881 return(ret); 00882 } 00883 } 00884 return(0); 00885 } 00886 00897 xmlURIPtr 00898 xmlParseURI(const char *str) { 00899 xmlURIPtr uri; 00900 int ret; 00901 00902 if (str == NULL) 00903 return(NULL); 00904 uri = xmlCreateURI(); 00905 if (uri != NULL) { 00906 ret = xmlParse3986URIReference(uri, str); 00907 if (ret) { 00908 xmlFreeURI(uri); 00909 return(NULL); 00910 } 00911 } 00912 return(uri); 00913 } 00914 00927 int 00928 xmlParseURIReference(xmlURIPtr uri, const char *str) { 00929 return(xmlParse3986URIReference(uri, str)); 00930 } 00931 00943 xmlURIPtr 00944 xmlParseURIRaw(const char *str, int raw) { 00945 xmlURIPtr uri; 00946 int ret; 00947 00948 if (str == NULL) 00949 return(NULL); 00950 uri = xmlCreateURI(); 00951 if (uri != NULL) { 00952 if (raw) { 00953 uri->cleanup |= 2; 00954 } 00955 ret = xmlParseURIReference(uri, str); 00956 if (ret) { 00957 xmlFreeURI(uri); 00958 return(NULL); 00959 } 00960 } 00961 return(uri); 00962 } 00963 00964 /************************************************************************ 00965 * * 00966 * Generic URI structure functions * 00967 * * 00968 ************************************************************************/ 00969 00977 xmlURIPtr 00978 xmlCreateURI(void) { 00979 xmlURIPtr ret; 00980 00981 ret = (xmlURIPtr) xmlMalloc(sizeof(xmlURI)); 00982 if (ret == NULL) { 00983 xmlGenericError(xmlGenericErrorContext, 00984 "xmlCreateURI: out of memory\n"); 00985 return(NULL); 00986 } 00987 memset(ret, 0, sizeof(xmlURI)); 00988 return(ret); 00989 } 00990 00999 xmlChar * 01000 xmlSaveUri(xmlURIPtr uri) { 01001 xmlChar *ret = NULL; 01002 xmlChar *temp; 01003 const char *p; 01004 int len; 01005 int max; 01006 01007 if (uri == NULL) return(NULL); 01008 01009 01010 max = 80; 01011 ret = (xmlChar *) xmlMallocAtomic((max + 1) * sizeof(xmlChar)); 01012 if (ret == NULL) { 01013 xmlGenericError(xmlGenericErrorContext, 01014 "xmlSaveUri: out of memory\n"); 01015 return(NULL); 01016 } 01017 len = 0; 01018 01019 if (uri->scheme != NULL) { 01020 p = uri->scheme; 01021 while (*p != 0) { 01022 if (len >= max) { 01023 max *= 2; 01024 temp = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar)); 01025 if (temp == NULL) { 01026 xmlGenericError(xmlGenericErrorContext, 01027 "xmlSaveUri: out of memory\n"); 01028 xmlFree(ret); 01029 return(NULL); 01030 } 01031 ret = temp; 01032 } 01033 ret[len++] = *p++; 01034 } 01035 if (len >= max) { 01036 max *= 2; 01037 temp = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar)); 01038 if (temp == NULL) { 01039 xmlGenericError(xmlGenericErrorContext, 01040 "xmlSaveUri: out of memory\n"); 01041 xmlFree(ret); 01042 return(NULL); 01043 } 01044 ret = temp; 01045 } 01046 ret[len++] = ':'; 01047 } 01048 if (uri->opaque != NULL) { 01049 p = uri->opaque; 01050 while (*p != 0) { 01051 if (len + 3 >= max) { 01052 max *= 2; 01053 temp = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar)); 01054 if (temp == NULL) { 01055 xmlGenericError(xmlGenericErrorContext, 01056 "xmlSaveUri: out of memory\n"); 01057 xmlFree(ret); 01058 return(NULL); 01059 } 01060 ret = temp; 01061 } 01062 if (IS_RESERVED(*(p)) || IS_UNRESERVED(*(p))) 01063 ret[len++] = *p++; 01064 else { 01065 int val = *(unsigned char *)p++; 01066 int hi = val / 0x10, lo = val % 0x10; 01067 ret[len++] = '%'; 01068 ret[len++] = hi + (hi > 9? 'A'-10 : '0'); 01069 ret[len++] = lo + (lo > 9? 'A'-10 : '0'); 01070 } 01071 } 01072 } else { 01073 if (uri->server != NULL) { 01074 if (len + 3 >= max) { 01075 max *= 2; 01076 temp = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar)); 01077 if (temp == NULL) { 01078 xmlGenericError(xmlGenericErrorContext, 01079 "xmlSaveUri: out of memory\n"); 01080 xmlFree(ret); 01081 return(NULL); 01082 } 01083 ret = temp; 01084 } 01085 ret[len++] = '/'; 01086 ret[len++] = '/'; 01087 if (uri->user != NULL) { 01088 p = uri->user; 01089 while (*p != 0) { 01090 if (len + 3 >= max) { 01091 max *= 2; 01092 temp = (xmlChar *) xmlRealloc(ret, 01093 (max + 1) * sizeof(xmlChar)); 01094 if (temp == NULL) { 01095 xmlGenericError(xmlGenericErrorContext, 01096 "xmlSaveUri: out of memory\n"); 01097 xmlFree(ret); 01098 return(NULL); 01099 } 01100 ret = temp; 01101 } 01102 if ((IS_UNRESERVED(*(p))) || 01103 ((*(p) == ';')) || ((*(p) == ':')) || 01104 ((*(p) == '&')) || ((*(p) == '=')) || 01105 ((*(p) == '+')) || ((*(p) == '$')) || 01106 ((*(p) == ','))) 01107 ret[len++] = *p++; 01108 else { 01109 int val = *(unsigned char *)p++; 01110 int hi = val / 0x10, lo = val % 0x10; 01111 ret[len++] = '%'; 01112 ret[len++] = hi + (hi > 9? 'A'-10 : '0'); 01113 ret[len++] = lo + (lo > 9? 'A'-10 : '0'); 01114 } 01115 } 01116 if (len + 3 >= max) { 01117 max *= 2; 01118 temp = (xmlChar *) xmlRealloc(ret, 01119 (max + 1) * sizeof(xmlChar)); 01120 if (temp == NULL) { 01121 xmlGenericError(xmlGenericErrorContext, 01122 "xmlSaveUri: out of memory\n"); 01123 xmlFree(ret); 01124 return(NULL); 01125 } 01126 ret = temp; 01127 } 01128 ret[len++] = '@'; 01129 } 01130 p = uri->server; 01131 while (*p != 0) { 01132 if (len >= max) { 01133 max *= 2; 01134 temp = (xmlChar *) xmlRealloc(ret, 01135 (max + 1) * sizeof(xmlChar)); 01136 if (temp == NULL) { 01137 xmlGenericError(xmlGenericErrorContext, 01138 "xmlSaveUri: out of memory\n"); 01139 xmlFree(ret); 01140 return(NULL); 01141 } 01142 ret = temp; 01143 } 01144 ret[len++] = *p++; 01145 } 01146 if (uri->port > 0) { 01147 if (len + 10 >= max) { 01148 max *= 2; 01149 temp = (xmlChar *) xmlRealloc(ret, 01150 (max + 1) * sizeof(xmlChar)); 01151 if (temp == NULL) { 01152 xmlGenericError(xmlGenericErrorContext, 01153 "xmlSaveUri: out of memory\n"); 01154 xmlFree(ret); 01155 return(NULL); 01156 } 01157 ret = temp; 01158 } 01159 len += snprintf((char *) &ret[len], max - len, ":%d", uri->port); 01160 } 01161 } else if (uri->authority != NULL) { 01162 if (len + 3 >= max) { 01163 max *= 2; 01164 temp = (xmlChar *) xmlRealloc(ret, 01165 (max + 1) * sizeof(xmlChar)); 01166 if (temp == NULL) { 01167 xmlGenericError(xmlGenericErrorContext, 01168 "xmlSaveUri: out of memory\n"); 01169 xmlFree(ret); 01170 return(NULL); 01171 } 01172 ret = temp; 01173 } 01174 ret[len++] = '/'; 01175 ret[len++] = '/'; 01176 p = uri->authority; 01177 while (*p != 0) { 01178 if (len + 3 >= max) { 01179 max *= 2; 01180 temp = (xmlChar *) xmlRealloc(ret, 01181 (max + 1) * sizeof(xmlChar)); 01182 if (temp == NULL) { 01183 xmlGenericError(xmlGenericErrorContext, 01184 "xmlSaveUri: out of memory\n"); 01185 xmlFree(ret); 01186 return(NULL); 01187 } 01188 ret = temp; 01189 } 01190 if ((IS_UNRESERVED(*(p))) || 01191 ((*(p) == '$')) || ((*(p) == ',')) || ((*(p) == ';')) || 01192 ((*(p) == ':')) || ((*(p) == '@')) || ((*(p) == '&')) || 01193 ((*(p) == '=')) || ((*(p) == '+'))) 01194 ret[len++] = *p++; 01195 else { 01196 int val = *(unsigned char *)p++; 01197 int hi = val / 0x10, lo = val % 0x10; 01198 ret[len++] = '%'; 01199 ret[len++] = hi + (hi > 9? 'A'-10 : '0'); 01200 ret[len++] = lo + (lo > 9? 'A'-10 : '0'); 01201 } 01202 } 01203 } else if (uri->scheme != NULL) { 01204 if (len + 3 >= max) { 01205 max *= 2; 01206 temp = (xmlChar *) xmlRealloc(ret, 01207 (max + 1) * sizeof(xmlChar)); 01208 if (temp == NULL) { 01209 xmlGenericError(xmlGenericErrorContext, 01210 "xmlSaveUri: out of memory\n"); 01211 xmlFree(ret); 01212 return(NULL); 01213 } 01214 ret = temp; 01215 } 01216 ret[len++] = '/'; 01217 ret[len++] = '/'; 01218 } 01219 if (uri->path != NULL) { 01220 p = uri->path; 01221 /* 01222 * the colon in file:///d: should not be escaped or 01223 * Windows accesses fail later. 01224 */ 01225 if ((uri->scheme != NULL) && 01226 (p[0] == '/') && 01227 (((p[1] >= 'a') && (p[1] <= 'z')) || 01228 ((p[1] >= 'A') && (p[1] <= 'Z'))) && 01229 (p[2] == ':') && 01230 (xmlStrEqual(BAD_CAST uri->scheme, BAD_CAST "file"))) { 01231 if (len + 3 >= max) { 01232 max *= 2; 01233 ret = (xmlChar *) xmlRealloc(ret, 01234 (max + 1) * sizeof(xmlChar)); 01235 if (ret == NULL) { 01236 xmlGenericError(xmlGenericErrorContext, 01237 "xmlSaveUri: out of memory\n"); 01238 return(NULL); 01239 } 01240 } 01241 ret[len++] = *p++; 01242 ret[len++] = *p++; 01243 ret[len++] = *p++; 01244 } 01245 while (*p != 0) { 01246 if (len + 3 >= max) { 01247 max *= 2; 01248 temp = (xmlChar *) xmlRealloc(ret, 01249 (max + 1) * sizeof(xmlChar)); 01250 if (temp == NULL) { 01251 xmlGenericError(xmlGenericErrorContext, 01252 "xmlSaveUri: out of memory\n"); 01253 xmlFree(ret); 01254 return(NULL); 01255 } 01256 ret = temp; 01257 } 01258 if ((IS_UNRESERVED(*(p))) || ((*(p) == '/')) || 01259 ((*(p) == ';')) || ((*(p) == '@')) || ((*(p) == '&')) || 01260 ((*(p) == '=')) || ((*(p) == '+')) || ((*(p) == '$')) || 01261 ((*(p) == ','))) 01262 ret[len++] = *p++; 01263 else { 01264 int val = *(unsigned char *)p++; 01265 int hi = val / 0x10, lo = val % 0x10; 01266 ret[len++] = '%'; 01267 ret[len++] = hi + (hi > 9? 'A'-10 : '0'); 01268 ret[len++] = lo + (lo > 9? 'A'-10 : '0'); 01269 } 01270 } 01271 } 01272 if (uri->query_raw != NULL) { 01273 if (len + 1 >= max) { 01274 max *= 2; 01275 temp = (xmlChar *) xmlRealloc(ret, 01276 (max + 1) * sizeof(xmlChar)); 01277 if (temp == NULL) { 01278 xmlGenericError(xmlGenericErrorContext, 01279 "xmlSaveUri: out of memory\n"); 01280 xmlFree(ret); 01281 return(NULL); 01282 } 01283 ret = temp; 01284 } 01285 ret[len++] = '?'; 01286 p = uri->query_raw; 01287 while (*p != 0) { 01288 if (len + 1 >= max) { 01289 max *= 2; 01290 temp = (xmlChar *) xmlRealloc(ret, 01291 (max + 1) * sizeof(xmlChar)); 01292 if (temp == NULL) { 01293 xmlGenericError(xmlGenericErrorContext, 01294 "xmlSaveUri: out of memory\n"); 01295 xmlFree(ret); 01296 return(NULL); 01297 } 01298 ret = temp; 01299 } 01300 ret[len++] = *p++; 01301 } 01302 } else if (uri->query != NULL) { 01303 if (len + 3 >= max) { 01304 max *= 2; 01305 temp = (xmlChar *) xmlRealloc(ret, 01306 (max + 1) * sizeof(xmlChar)); 01307 if (temp == NULL) { 01308 xmlGenericError(xmlGenericErrorContext, 01309 "xmlSaveUri: out of memory\n"); 01310 xmlFree(ret); 01311 return(NULL); 01312 } 01313 ret = temp; 01314 } 01315 ret[len++] = '?'; 01316 p = uri->query; 01317 while (*p != 0) { 01318 if (len + 3 >= max) { 01319 max *= 2; 01320 temp = (xmlChar *) xmlRealloc(ret, 01321 (max + 1) * sizeof(xmlChar)); 01322 if (temp == NULL) { 01323 xmlGenericError(xmlGenericErrorContext, 01324 "xmlSaveUri: out of memory\n"); 01325 xmlFree(ret); 01326 return(NULL); 01327 } 01328 ret = temp; 01329 } 01330 if ((IS_UNRESERVED(*(p))) || (IS_RESERVED(*(p)))) 01331 ret[len++] = *p++; 01332 else { 01333 int val = *(unsigned char *)p++; 01334 int hi = val / 0x10, lo = val % 0x10; 01335 ret[len++] = '%'; 01336 ret[len++] = hi + (hi > 9? 'A'-10 : '0'); 01337 ret[len++] = lo + (lo > 9? 'A'-10 : '0'); 01338 } 01339 } 01340 } 01341 } 01342 if (uri->fragment != NULL) { 01343 if (len + 3 >= max) { 01344 max *= 2; 01345 temp = (xmlChar *) xmlRealloc(ret, 01346 (max + 1) * sizeof(xmlChar)); 01347 if (temp == NULL) { 01348 xmlGenericError(xmlGenericErrorContext, 01349 "xmlSaveUri: out of memory\n"); 01350 xmlFree(ret); 01351 return(NULL); 01352 } 01353 ret = temp; 01354 } 01355 ret[len++] = '#'; 01356 p = uri->fragment; 01357 while (*p != 0) { 01358 if (len + 3 >= max) { 01359 max *= 2; 01360 temp = (xmlChar *) xmlRealloc(ret, 01361 (max + 1) * sizeof(xmlChar)); 01362 if (temp == NULL) { 01363 xmlGenericError(xmlGenericErrorContext, 01364 "xmlSaveUri: out of memory\n"); 01365 xmlFree(ret); 01366 return(NULL); 01367 } 01368 ret = temp; 01369 } 01370 if ((IS_UNRESERVED(*(p))) || (IS_RESERVED(*(p)))) 01371 ret[len++] = *p++; 01372 else { 01373 int val = *(unsigned char *)p++; 01374 int hi = val / 0x10, lo = val % 0x10; 01375 ret[len++] = '%'; 01376 ret[len++] = hi + (hi > 9? 'A'-10 : '0'); 01377 ret[len++] = lo + (lo > 9? 'A'-10 : '0'); 01378 } 01379 } 01380 } 01381 if (len >= max) { 01382 max *= 2; 01383 temp = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar)); 01384 if (temp == NULL) { 01385 xmlGenericError(xmlGenericErrorContext, 01386 "xmlSaveUri: out of memory\n"); 01387 xmlFree(ret); 01388 return(NULL); 01389 } 01390 ret = temp; 01391 } 01392 ret[len] = 0; 01393 return(ret); 01394 } 01395 01403 void 01404 xmlPrintURI(FILE *stream, xmlURIPtr uri) { 01405 xmlChar *out; 01406 01407 out = xmlSaveUri(uri); 01408 if (out != NULL) { 01409 fprintf(stream, "%s", (char *) out); 01410 xmlFree(out); 01411 } 01412 } 01413 01420 static void 01421 xmlCleanURI(xmlURIPtr uri) { 01422 if (uri == NULL) return; 01423 01424 if (uri->scheme != NULL) xmlFree(uri->scheme); 01425 uri->scheme = NULL; 01426 if (uri->server != NULL) xmlFree(uri->server); 01427 uri->server = NULL; 01428 if (uri->user != NULL) xmlFree(uri->user); 01429 uri->user = NULL; 01430 if (uri->path != NULL) xmlFree(uri->path); 01431 uri->path = NULL; 01432 if (uri->fragment != NULL) xmlFree(uri->fragment); 01433 uri->fragment = NULL; 01434 if (uri->opaque != NULL) xmlFree(uri->opaque); 01435 uri->opaque = NULL; 01436 if (uri->authority != NULL) xmlFree(uri->authority); 01437 uri->authority = NULL; 01438 if (uri->query != NULL) xmlFree(uri->query); 01439 uri->query = NULL; 01440 if (uri->query_raw != NULL) xmlFree(uri->query_raw); 01441 uri->query_raw = NULL; 01442 } 01443 01450 void 01451 xmlFreeURI(xmlURIPtr uri) { 01452 if (uri == NULL) return; 01453 01454 if (uri->scheme != NULL) xmlFree(uri->scheme); 01455 if (uri->server != NULL) xmlFree(uri->server); 01456 if (uri->user != NULL) xmlFree(uri->user); 01457 if (uri->path != NULL) xmlFree(uri->path); 01458 if (uri->fragment != NULL) xmlFree(uri->fragment); 01459 if (uri->opaque != NULL) xmlFree(uri->opaque); 01460 if (uri->authority != NULL) xmlFree(uri->authority); 01461 if (uri->query != NULL) xmlFree(uri->query); 01462 if (uri->query_raw != NULL) xmlFree(uri->query_raw); 01463 xmlFree(uri); 01464 } 01465 01466 /************************************************************************ 01467 * * 01468 * Helper functions * 01469 * * 01470 ************************************************************************/ 01471 01483 int 01484 xmlNormalizeURIPath(char *path) { 01485 char *cur, *out; 01486 01487 if (path == NULL) 01488 return(-1); 01489 01490 /* Skip all initial "/" chars. We want to get to the beginning of the 01491 * first non-empty segment. 01492 */ 01493 cur = path; 01494 while (cur[0] == '/') 01495 ++cur; 01496 if (cur[0] == '\0') 01497 return(0); 01498 01499 /* Keep everything we've seen so far. */ 01500 out = cur; 01501 01502 /* 01503 * Analyze each segment in sequence for cases (c) and (d). 01504 */ 01505 while (cur[0] != '\0') { 01506 /* 01507 * c) All occurrences of "./", where "." is a complete path segment, 01508 * are removed from the buffer string. 01509 */ 01510 if ((cur[0] == '.') && (cur[1] == '/')) { 01511 cur += 2; 01512 /* '//' normalization should be done at this point too */ 01513 while (cur[0] == '/') 01514 cur++; 01515 continue; 01516 } 01517 01518 /* 01519 * d) If the buffer string ends with "." as a complete path segment, 01520 * that "." is removed. 01521 */ 01522 if ((cur[0] == '.') && (cur[1] == '\0')) 01523 break; 01524 01525 /* Otherwise keep the segment. */ 01526 while (cur[0] != '/') { 01527 if (cur[0] == '\0') 01528 goto done_cd; 01529 (out++)[0] = (cur++)[0]; 01530 } 01531 /* nomalize // */ 01532 while ((cur[0] == '/') && (cur[1] == '/')) 01533 cur++; 01534 01535 (out++)[0] = (cur++)[0]; 01536 } 01537 done_cd: 01538 out[0] = '\0'; 01539 01540 /* Reset to the beginning of the first segment for the next sequence. */ 01541 cur = path; 01542 while (cur[0] == '/') 01543 ++cur; 01544 if (cur[0] == '\0') 01545 return(0); 01546 01547 /* 01548 * Analyze each segment in sequence for cases (e) and (f). 01549 * 01550 * e) All occurrences of "<segment>/../", where <segment> is a 01551 * complete path segment not equal to "..", are removed from the 01552 * buffer string. Removal of these path segments is performed 01553 * iteratively, removing the leftmost matching pattern on each 01554 * iteration, until no matching pattern remains. 01555 * 01556 * f) If the buffer string ends with "<segment>/..", where <segment> 01557 * is a complete path segment not equal to "..", that 01558 * "<segment>/.." is removed. 01559 * 01560 * To satisfy the "iterative" clause in (e), we need to collapse the 01561 * string every time we find something that needs to be removed. Thus, 01562 * we don't need to keep two pointers into the string: we only need a 01563 * "current position" pointer. 01564 */ 01565 while (1) { 01566 char *segp, *tmp; 01567 01568 /* At the beginning of each iteration of this loop, "cur" points to 01569 * the first character of the segment we want to examine. 01570 */ 01571 01572 /* Find the end of the current segment. */ 01573 segp = cur; 01574 while ((segp[0] != '/') && (segp[0] != '\0')) 01575 ++segp; 01576 01577 /* If this is the last segment, we're done (we need at least two 01578 * segments to meet the criteria for the (e) and (f) cases). 01579 */ 01580 if (segp[0] == '\0') 01581 break; 01582 01583 /* If the first segment is "..", or if the next segment _isn't_ "..", 01584 * keep this segment and try the next one. 01585 */ 01586 ++segp; 01587 if (((cur[0] == '.') && (cur[1] == '.') && (segp == cur+3)) 01588 || ((segp[0] != '.') || (segp[1] != '.') 01589 || ((segp[2] != '/') && (segp[2] != '\0')))) { 01590 cur = segp; 01591 continue; 01592 } 01593 01594 /* If we get here, remove this segment and the next one and back up 01595 * to the previous segment (if there is one), to implement the 01596 * "iteratively" clause. It's pretty much impossible to back up 01597 * while maintaining two pointers into the buffer, so just compact 01598 * the whole buffer now. 01599 */ 01600 01601 /* If this is the end of the buffer, we're done. */ 01602 if (segp[2] == '\0') { 01603 cur[0] = '\0'; 01604 break; 01605 } 01606 /* Valgrind complained, strcpy(cur, segp + 3); */ 01607 /* string will overlap, do not use strcpy */ 01608 tmp = cur; 01609 segp += 3; 01610 while ((*tmp++ = *segp++) != 0); 01611 01612 /* If there are no previous segments, then keep going from here. */ 01613 segp = cur; 01614 while ((segp > path) && ((--segp)[0] == '/')) 01615 ; 01616 if (segp == path) 01617 continue; 01618 01619 /* "segp" is pointing to the end of a previous segment; find it's 01620 * start. We need to back up to the previous segment and start 01621 * over with that to handle things like "foo/bar/../..". If we 01622 * don't do this, then on the first pass we'll remove the "bar/..", 01623 * but be pointing at the second ".." so we won't realize we can also 01624 * remove the "foo/..". 01625 */ 01626 cur = segp; 01627 while ((cur > path) && (cur[-1] != '/')) 01628 --cur; 01629 } 01630 out[0] = '\0'; 01631 01632 /* 01633 * g) If the resulting buffer string still begins with one or more 01634 * complete path segments of "..", then the reference is 01635 * considered to be in error. Implementations may handle this 01636 * error by retaining these components in the resolved path (i.e., 01637 * treating them as part of the final URI), by removing them from 01638 * the resolved path (i.e., discarding relative levels above the 01639 * root), or by avoiding traversal of the reference. 01640 * 01641 * We discard them from the final path. 01642 */ 01643 if (path[0] == '/') { 01644 cur = path; 01645 while ((cur[0] == '/') && (cur[1] == '.') && (cur[2] == '.') 01646 && ((cur[3] == '/') || (cur[3] == '\0'))) 01647 cur += 3; 01648 01649 if (cur != path) { 01650 out = path; 01651 while (cur[0] != '\0') 01652 (out++)[0] = (cur++)[0]; 01653 out[0] = 0; 01654 } 01655 } 01656 01657 return(0); 01658 } 01659 01660 static int is_hex(char c) { 01661 if (((c >= '0') && (c <= '9')) || 01662 ((c >= 'a') && (c <= 'f')) || 01663 ((c >= 'A') && (c <= 'F'))) 01664 return(1); 01665 return(0); 01666 } 01667 01682 char * 01683 xmlURIUnescapeString(const char *str, int len, char *target) { 01684 char *ret, *out; 01685 const char *in; 01686 01687 if (str == NULL) 01688 return(NULL); 01689 if (len <= 0) len = strlen(str); 01690 if (len < 0) return(NULL); 01691 01692 if (target == NULL) { 01693 ret = (char *) xmlMallocAtomic(len + 1); 01694 if (ret == NULL) { 01695 xmlGenericError(xmlGenericErrorContext, 01696 "xmlURIUnescapeString: out of memory\n"); 01697 return(NULL); 01698 } 01699 } else 01700 ret = target; 01701 in = str; 01702 out = ret; 01703 while(len > 0) { 01704 if ((len > 2) && (*in == '%') && (is_hex(in[1])) && (is_hex(in[2]))) { 01705 in++; 01706 if ((*in >= '0') && (*in <= '9')) 01707 *out = (*in - '0'); 01708 else if ((*in >= 'a') && (*in <= 'f')) 01709 *out = (*in - 'a') + 10; 01710 else if ((*in >= 'A') && (*in <= 'F')) 01711 *out = (*in - 'A') + 10; 01712 in++; 01713 if ((*in >= '0') && (*in <= '9')) 01714 *out = *out * 16 + (*in - '0'); 01715 else if ((*in >= 'a') && (*in <= 'f')) 01716 *out = *out * 16 + (*in - 'a') + 10; 01717 else if ((*in >= 'A') && (*in <= 'F')) 01718 *out = *out * 16 + (*in - 'A') + 10; 01719 in++; 01720 len -= 3; 01721 out++; 01722 } else { 01723 *out++ = *in++; 01724 len--; 01725 } 01726 } 01727 *out = 0; 01728 return(ret); 01729 } 01730 01741 xmlChar * 01742 xmlURIEscapeStr(const xmlChar *str, const xmlChar *list) { 01743 xmlChar *ret, ch; 01744 xmlChar *temp; 01745 const xmlChar *in; 01746 01747 unsigned int len, out; 01748 01749 if (str == NULL) 01750 return(NULL); 01751 if (str[0] == 0) 01752 return(xmlStrdup(str)); 01753 len = xmlStrlen(str); 01754 if (!(len > 0)) return(NULL); 01755 01756 len += 20; 01757 ret = (xmlChar *) xmlMallocAtomic(len); 01758 if (ret == NULL) { 01759 xmlGenericError(xmlGenericErrorContext, 01760 "xmlURIEscapeStr: out of memory\n"); 01761 return(NULL); 01762 } 01763 in = (const xmlChar *) str; 01764 out = 0; 01765 while(*in != 0) { 01766 if (len - out <= 3) { 01767 len += 20; 01768 temp = (xmlChar *) xmlRealloc(ret, len); 01769 if (temp == NULL) { 01770 xmlGenericError(xmlGenericErrorContext, 01771 "xmlURIEscapeStr: out of memory\n"); 01772 xmlFree(ret); 01773 return(NULL); 01774 } 01775 ret = temp; 01776 } 01777 01778 ch = *in; 01779 01780 if ((ch != '@') && (!IS_UNRESERVED(ch)) && (!xmlStrchr(list, ch))) { 01781 unsigned char val; 01782 ret[out++] = '%'; 01783 val = ch >> 4; 01784 if (val <= 9) 01785 ret[out++] = '0' + val; 01786 else 01787 ret[out++] = 'A' + val - 0xA; 01788 val = ch & 0xF; 01789 if (val <= 9) 01790 ret[out++] = '0' + val; 01791 else 01792 ret[out++] = 'A' + val - 0xA; 01793 in++; 01794 } else { 01795 ret[out++] = *in++; 01796 } 01797 01798 } 01799 ret[out] = 0; 01800 return(ret); 01801 } 01802 01818 xmlChar * 01819 xmlURIEscape(const xmlChar * str) 01820 { 01821 xmlChar *ret, *segment = NULL; 01822 xmlURIPtr uri; 01823 int ret2; 01824 01825 #define NULLCHK(p) if(!p) { \ 01826 xmlGenericError(xmlGenericErrorContext, \ 01827 "xmlURIEscape: out of memory\n"); \ 01828 xmlFreeURI(uri); \ 01829 return NULL; } \ 01830 01831 if (str == NULL) 01832 return (NULL); 01833 01834 uri = xmlCreateURI(); 01835 if (uri != NULL) { 01836 /* 01837 * Allow escaping errors in the unescaped form 01838 */ 01839 uri->cleanup = 1; 01840 ret2 = xmlParseURIReference(uri, (const char *)str); 01841 if (ret2) { 01842 xmlFreeURI(uri); 01843 return (NULL); 01844 } 01845 } 01846 01847 if (!uri) 01848 return NULL; 01849 01850 ret = NULL; 01851 01852 if (uri->scheme) { 01853 segment = xmlURIEscapeStr(BAD_CAST uri->scheme, BAD_CAST "+-."); 01854 NULLCHK(segment) 01855 ret = xmlStrcat(ret, segment); 01856 ret = xmlStrcat(ret, BAD_CAST ":"); 01857 xmlFree(segment); 01858 } 01859 01860 if (uri->authority) { 01861 segment = 01862 xmlURIEscapeStr(BAD_CAST uri->authority, BAD_CAST "/?;:@"); 01863 NULLCHK(segment) 01864 ret = xmlStrcat(ret, BAD_CAST "//"); 01865 ret = xmlStrcat(ret, segment); 01866 xmlFree(segment); 01867 } 01868 01869 if (uri->user) { 01870 segment = xmlURIEscapeStr(BAD_CAST uri->user, BAD_CAST ";:&=+$,"); 01871 NULLCHK(segment) 01872 ret = xmlStrcat(ret,BAD_CAST "//"); 01873 ret = xmlStrcat(ret, segment); 01874 ret = xmlStrcat(ret, BAD_CAST "@"); 01875 xmlFree(segment); 01876 } 01877 01878 if (uri->server) { 01879 segment = xmlURIEscapeStr(BAD_CAST uri->server, BAD_CAST "/?;:@"); 01880 NULLCHK(segment) 01881 if (uri->user == NULL) 01882 ret = xmlStrcat(ret, BAD_CAST "//"); 01883 ret = xmlStrcat(ret, segment); 01884 xmlFree(segment); 01885 } 01886 01887 if (uri->port) { 01888 xmlChar port[10]; 01889 01890 snprintf((char *) port, 10, "%d", uri->port); 01891 ret = xmlStrcat(ret, BAD_CAST ":"); 01892 ret = xmlStrcat(ret, port); 01893 } 01894 01895 if (uri->path) { 01896 segment = 01897 xmlURIEscapeStr(BAD_CAST uri->path, BAD_CAST ":@&=+$,/?;"); 01898 NULLCHK(segment) 01899 ret = xmlStrcat(ret, segment); 01900 xmlFree(segment); 01901 } 01902 01903 if (uri->query_raw) { 01904 ret = xmlStrcat(ret, BAD_CAST "?"); 01905 ret = xmlStrcat(ret, BAD_CAST uri->query_raw); 01906 } 01907 else if (uri->query) { 01908 segment = 01909 xmlURIEscapeStr(BAD_CAST uri->query, BAD_CAST ";/?:@&=+,$"); 01910 NULLCHK(segment) 01911 ret = xmlStrcat(ret, BAD_CAST "?"); 01912 ret = xmlStrcat(ret, segment); 01913 xmlFree(segment); 01914 } 01915 01916 if (uri->opaque) { 01917 segment = xmlURIEscapeStr(BAD_CAST uri->opaque, BAD_CAST ""); 01918 NULLCHK(segment) 01919 ret = xmlStrcat(ret, segment); 01920 xmlFree(segment); 01921 } 01922 01923 if (uri->fragment) { 01924 segment = xmlURIEscapeStr(BAD_CAST uri->fragment, BAD_CAST "#"); 01925 NULLCHK(segment) 01926 ret = xmlStrcat(ret, BAD_CAST "#"); 01927 ret = xmlStrcat(ret, segment); 01928 xmlFree(segment); 01929 } 01930 01931 xmlFreeURI(uri); 01932 #undef NULLCHK 01933 01934 return (ret); 01935 } 01936 01937 /************************************************************************ 01938 * * 01939 * Public functions * 01940 * * 01941 ************************************************************************/ 01942 01958 xmlChar * 01959 xmlBuildURI(const xmlChar *URI, const xmlChar *base) { 01960 xmlChar *val = NULL; 01961 int ret, len, indx, cur, out; 01962 xmlURIPtr ref = NULL; 01963 xmlURIPtr bas = NULL; 01964 xmlURIPtr res = NULL; 01965 01966 /* 01967 * 1) The URI reference is parsed into the potential four components and 01968 * fragment identifier, as described in Section 4.3. 01969 * 01970 * NOTE that a completely empty URI is treated by modern browsers 01971 * as a reference to "." rather than as a synonym for the current 01972 * URI. Should we do that here? 01973 */ 01974 if (URI == NULL) 01975 ret = -1; 01976 else { 01977 if (*URI) { 01978 ref = xmlCreateURI(); 01979 if (ref == NULL) 01980 goto done; 01981 ret = xmlParseURIReference(ref, (const char *) URI); 01982 } 01983 else 01984 ret = 0; 01985 } 01986 if (ret != 0) 01987 goto done; 01988 if ((ref != NULL) && (ref->scheme != NULL)) { 01989 /* 01990 * The URI is absolute don't modify. 01991 */ 01992 val = xmlStrdup(URI); 01993 goto done; 01994 } 01995 if (base == NULL) 01996 ret = -1; 01997 else { 01998 bas = xmlCreateURI(); 01999 if (bas == NULL) 02000 goto done; 02001 ret = xmlParseURIReference(bas, (const char *) base); 02002 } 02003 if (ret != 0) { 02004 if (ref) 02005 val = xmlSaveUri(ref); 02006 goto done; 02007 } 02008 if (ref == NULL) { 02009 /* 02010 * the base fragment must be ignored 02011 */ 02012 if (bas->fragment != NULL) { 02013 xmlFree(bas->fragment); 02014 bas->fragment = NULL; 02015 } 02016 val = xmlSaveUri(bas); 02017 goto done; 02018 } 02019 02020 /* 02021 * 2) If the path component is empty and the scheme, authority, and 02022 * query components are undefined, then it is a reference to the 02023 * current document and we are done. Otherwise, the reference URI's 02024 * query and fragment components are defined as found (or not found) 02025 * within the URI reference and not inherited from the base URI. 02026 * 02027 * NOTE that in modern browsers, the parsing differs from the above 02028 * in the following aspect: the query component is allowed to be 02029 * defined while still treating this as a reference to the current 02030 * document. 02031 */ 02032 res = xmlCreateURI(); 02033 if (res == NULL) 02034 goto done; 02035 if ((ref->scheme == NULL) && (ref->path == NULL) && 02036 ((ref->authority == NULL) && (ref->server == NULL))) { 02037 if (bas->scheme != NULL) 02038 res->scheme = xmlMemStrdup(bas->scheme); 02039 if (bas->authority != NULL) 02040 res->authority = xmlMemStrdup(bas->authority); 02041 else if (bas->server != NULL) { 02042 res->server = xmlMemStrdup(bas->server); 02043 if (bas->user != NULL) 02044 res->user = xmlMemStrdup(bas->user); 02045 res->port = bas->port; 02046 } 02047 if (bas->path != NULL) 02048 res->path = xmlMemStrdup(bas->path); 02049 if (ref->query_raw != NULL) 02050 res->query_raw = xmlMemStrdup (ref->query_raw); 02051 else if (ref->query != NULL) 02052 res->query = xmlMemStrdup(ref->query); 02053 else if (bas->query_raw != NULL) 02054 res->query_raw = xmlMemStrdup(bas->query_raw); 02055 else if (bas->query != NULL) 02056 res->query = xmlMemStrdup(bas->query); 02057 if (ref->fragment != NULL) 02058 res->fragment = xmlMemStrdup(ref->fragment); 02059 goto step_7; 02060 } 02061 02062 /* 02063 * 3) If the scheme component is defined, indicating that the reference 02064 * starts with a scheme name, then the reference is interpreted as an 02065 * absolute URI and we are done. Otherwise, the reference URI's 02066 * scheme is inherited from the base URI's scheme component. 02067 */ 02068 if (ref->scheme != NULL) { 02069 val = xmlSaveUri(ref); 02070 goto done; 02071 } 02072 if (bas->scheme != NULL) 02073 res->scheme = xmlMemStrdup(bas->scheme); 02074 02075 if (ref->query_raw != NULL) 02076 res->query_raw = xmlMemStrdup(ref->query_raw); 02077 else if (ref->query != NULL) 02078 res->query = xmlMemStrdup(ref->query); 02079 if (ref->fragment != NULL) 02080 res->fragment = xmlMemStrdup(ref->fragment); 02081 02082 /* 02083 * 4) If the authority component is defined, then the reference is a 02084 * network-path and we skip to step 7. Otherwise, the reference 02085 * URI's authority is inherited from the base URI's authority 02086 * component, which will also be undefined if the URI scheme does not 02087 * use an authority component. 02088 */ 02089 if ((ref->authority != NULL) || (ref->server != NULL)) { 02090 if (ref->authority != NULL) 02091 res->authority = xmlMemStrdup(ref->authority); 02092 else { 02093 res->server = xmlMemStrdup(ref->server); 02094 if (ref->user != NULL) 02095 res->user = xmlMemStrdup(ref->user); 02096 res->port = ref->port; 02097 } 02098 if (ref->path != NULL) 02099 res->path = xmlMemStrdup(ref->path); 02100 goto step_7; 02101 } 02102 if (bas->authority != NULL) 02103 res->authority = xmlMemStrdup(bas->authority); 02104 else if (bas->server != NULL) { 02105 res->server = xmlMemStrdup(bas->server); 02106 if (bas->user != NULL) 02107 res->user = xmlMemStrdup(bas->user); 02108 res->port = bas->port; 02109 } 02110 02111 /* 02112 * 5) If the path component begins with a slash character ("/"), then 02113 * the reference is an absolute-path and we skip to step 7. 02114 */ 02115 if ((ref->path != NULL) && (ref->path[0] == '/')) { 02116 res->path = xmlMemStrdup(ref->path); 02117 goto step_7; 02118 } 02119 02120 02121 /* 02122 * 6) If this step is reached, then we are resolving a relative-path 02123 * reference. The relative path needs to be merged with the base 02124 * URI's path. Although there are many ways to do this, we will 02125 * describe a simple method using a separate string buffer. 02126 * 02127 * Allocate a buffer large enough for the result string. 02128 */ 02129 len = 2; /* extra / and 0 */ 02130 if (ref->path != NULL) 02131 len += strlen(ref->path); 02132 if (bas->path != NULL) 02133 len += strlen(bas->path); 02134 res->path = (char *) xmlMallocAtomic(len); 02135 if (res->path == NULL) { 02136 xmlGenericError(xmlGenericErrorContext, 02137 "xmlBuildURI: out of memory\n"); 02138 goto done; 02139 } 02140 res->path[0] = 0; 02141 02142 /* 02143 * a) All but the last segment of the base URI's path component is 02144 * copied to the buffer. In other words, any characters after the 02145 * last (right-most) slash character, if any, are excluded. 02146 */ 02147 cur = 0; 02148 out = 0; 02149 if (bas->path != NULL) { 02150 while (bas->path[cur] != 0) { 02151 while ((bas->path[cur] != 0) && (bas->path[cur] != '/')) 02152 cur++; 02153 if (bas->path[cur] == 0) 02154 break; 02155 02156 cur++; 02157 while (out < cur) { 02158 res->path[out] = bas->path[out]; 02159 out++; 02160 } 02161 } 02162 } 02163 res->path[out] = 0; 02164 02165 /* 02166 * b) The reference's path component is appended to the buffer 02167 * string. 02168 */ 02169 if (ref->path != NULL && ref->path[0] != 0) { 02170 indx = 0; 02171 /* 02172 * Ensure the path includes a '/' 02173 */ 02174 if ((out == 0) && (bas->server != NULL)) 02175 res->path[out++] = '/'; 02176 while (ref->path[indx] != 0) { 02177 res->path[out++] = ref->path[indx++]; 02178 } 02179 } 02180 res->path[out] = 0; 02181 02182 /* 02183 * Steps c) to h) are really path normalization steps 02184 */ 02185 xmlNormalizeURIPath(res->path); 02186 02187 step_7: 02188 02189 /* 02190 * 7) The resulting URI components, including any inherited from the 02191 * base URI, are recombined to give the absolute form of the URI 02192 * reference. 02193 */ 02194 val = xmlSaveUri(res); 02195 02196 done: 02197 if (ref != NULL) 02198 xmlFreeURI(ref); 02199 if (bas != NULL) 02200 xmlFreeURI(bas); 02201 if (res != NULL) 02202 xmlFreeURI(res); 02203 return(val); 02204 } 02205 02238 xmlChar * 02239 xmlBuildRelativeURI (const xmlChar * URI, const xmlChar * base) 02240 { 02241 xmlChar *val = NULL; 02242 int ret; 02243 int ix; 02244 int pos = 0; 02245 int nbslash = 0; 02246 int len; 02247 xmlURIPtr ref = NULL; 02248 xmlURIPtr bas = NULL; 02249 xmlChar *bptr, *uptr, *vptr; 02250 int remove_path = 0; 02251 02252 if ((URI == NULL) || (*URI == 0)) 02253 return NULL; 02254 02255 /* 02256 * First parse URI into a standard form 02257 */ 02258 ref = xmlCreateURI (); 02259 if (ref == NULL) 02260 return NULL; 02261 /* If URI not already in "relative" form */ 02262 if (URI[0] != '.') { 02263 ret = xmlParseURIReference (ref, (const char *) URI); 02264 if (ret != 0) 02265 goto done; /* Error in URI, return NULL */ 02266 } else 02267 ref->path = (char *)xmlStrdup(URI); 02268 02269 /* 02270 * Next parse base into the same standard form 02271 */ 02272 if ((base == NULL) || (*base == 0)) { 02273 val = xmlStrdup (URI); 02274 goto done; 02275 } 02276 bas = xmlCreateURI (); 02277 if (bas == NULL) 02278 goto done; 02279 if (base[0] != '.') { 02280 ret = xmlParseURIReference (bas, (const char *) base); 02281 if (ret != 0) 02282 goto done; /* Error in base, return NULL */ 02283 } else 02284 bas->path = (char *)xmlStrdup(base); 02285 02286 /* 02287 * If the scheme / server on the URI differs from the base, 02288 * just return the URI 02289 */ 02290 if ((ref->scheme != NULL) && 02291 ((bas->scheme == NULL) || 02292 (xmlStrcmp ((xmlChar *)bas->scheme, (xmlChar *)ref->scheme)) || 02293 (xmlStrcmp ((xmlChar *)bas->server, (xmlChar *)ref->server)))) { 02294 val = xmlStrdup (URI); 02295 goto done; 02296 } 02297 if (xmlStrEqual((xmlChar *)bas->path, (xmlChar *)ref->path)) { 02298 val = xmlStrdup(BAD_CAST ""); 02299 goto done; 02300 } 02301 if (bas->path == NULL) { 02302 val = xmlStrdup((xmlChar *)ref->path); 02303 goto done; 02304 } 02305 if (ref->path == NULL) { 02306 ref->path = (char *) "/"; 02307 remove_path = 1; 02308 } 02309 02310 /* 02311 * At this point (at last!) we can compare the two paths 02312 * 02313 * First we take care of the special case where either of the 02314 * two path components may be missing (bug 316224) 02315 */ 02316 if (bas->path == NULL) { 02317 if (ref->path != NULL) { 02318 uptr = (xmlChar *) ref->path; 02319 if (*uptr == '/') 02320 uptr++; 02321 /* exception characters from xmlSaveUri */ 02322 val = xmlURIEscapeStr(uptr, BAD_CAST "/;&=+$,"); 02323 } 02324 goto done; 02325 } 02326 bptr = (xmlChar *)bas->path; 02327 if (ref->path == NULL) { 02328 for (ix = 0; bptr[ix] != 0; ix++) { 02329 if (bptr[ix] == '/') 02330 nbslash++; 02331 } 02332 uptr = NULL; 02333 len = 1; /* this is for a string terminator only */ 02334 } else { 02335 /* 02336 * Next we compare the two strings and find where they first differ 02337 */ 02338 if ((ref->path[pos] == '.') && (ref->path[pos+1] == '/')) 02339 pos += 2; 02340 if ((*bptr == '.') && (bptr[1] == '/')) 02341 bptr += 2; 02342 else if ((*bptr == '/') && (ref->path[pos] != '/')) 02343 bptr++; 02344 while ((bptr[pos] == ref->path[pos]) && (bptr[pos] != 0)) 02345 pos++; 02346 02347 if (bptr[pos] == ref->path[pos]) { 02348 val = xmlStrdup(BAD_CAST ""); 02349 goto done; /* (I can't imagine why anyone would do this) */ 02350 } 02351 02352 /* 02353 * In URI, "back up" to the last '/' encountered. This will be the 02354 * beginning of the "unique" suffix of URI 02355 */ 02356 ix = pos; 02357 if ((ref->path[ix] == '/') && (ix > 0)) 02358 ix--; 02359 else if ((ref->path[ix] == 0) && (ix > 1) && (ref->path[ix - 1] == '/')) 02360 ix -= 2; 02361 for (; ix > 0; ix--) { 02362 if (ref->path[ix] == '/') 02363 break; 02364 } 02365 if (ix == 0) { 02366 uptr = (xmlChar *)ref->path; 02367 } else { 02368 ix++; 02369 uptr = (xmlChar *)&ref->path[ix]; 02370 } 02371 02372 /* 02373 * In base, count the number of '/' from the differing point 02374 */ 02375 if (bptr[pos] != ref->path[pos]) {/* check for trivial URI == base */ 02376 for (; bptr[ix] != 0; ix++) { 02377 if (bptr[ix] == '/') 02378 nbslash++; 02379 } 02380 } 02381 len = xmlStrlen (uptr) + 1; 02382 } 02383 02384 if (nbslash == 0) { 02385 if (uptr != NULL) 02386 /* exception characters from xmlSaveUri */ 02387 val = xmlURIEscapeStr(uptr, BAD_CAST "/;&=+$,"); 02388 goto done; 02389 } 02390 02391 /* 02392 * Allocate just enough space for the returned string - 02393 * length of the remainder of the URI, plus enough space 02394 * for the "../" groups, plus one for the terminator 02395 */ 02396 val = (xmlChar *) xmlMalloc (len + 3 * nbslash); 02397 if (val == NULL) { 02398 xmlGenericError(xmlGenericErrorContext, 02399 "xmlBuildRelativeURI: out of memory\n"); 02400 goto done; 02401 } 02402 vptr = val; 02403 /* 02404 * Put in as many "../" as needed 02405 */ 02406 for (; nbslash>0; nbslash--) { 02407 *vptr++ = '.'; 02408 *vptr++ = '.'; 02409 *vptr++ = '/'; 02410 } 02411 /* 02412 * Finish up with the end of the URI 02413 */ 02414 if (uptr != NULL) { 02415 if ((vptr > val) && (len > 0) && 02416 (uptr[0] == '/') && (vptr[-1] == '/')) { 02417 memcpy (vptr, uptr + 1, len - 1); 02418 vptr[len - 2] = 0; 02419 } else { 02420 memcpy (vptr, uptr, len); 02421 vptr[len - 1] = 0; 02422 } 02423 } else { 02424 vptr[len - 1] = 0; 02425 } 02426 02427 /* escape the freshly-built path */ 02428 vptr = val; 02429 /* exception characters from xmlSaveUri */ 02430 val = xmlURIEscapeStr(vptr, BAD_CAST "/;&=+$,"); 02431 xmlFree(vptr); 02432 02433 done: 02434 /* 02435 * Free the working variables 02436 */ 02437 if (remove_path != 0) 02438 ref->path = NULL; 02439 if (ref != NULL) 02440 xmlFreeURI (ref); 02441 if (bas != NULL) 02442 xmlFreeURI (bas); 02443 02444 return val; 02445 } 02446 02458 #define IS_WINDOWS_PATH(p) \ 02459 ((p != NULL) && \ 02460 (((p[0] >= 'a') && (p[0] <= 'z')) || \ 02461 ((p[0] >= 'A') && (p[0] <= 'Z'))) && \ 02462 (p[1] == ':') && ((p[2] == '/') || (p[2] == '\\'))) 02463 xmlChar * 02464 xmlCanonicPath(const xmlChar *path) 02465 { 02466 /* 02467 * For Windows implementations, additional work needs to be done to 02468 * replace backslashes in pathnames with "forward slashes" 02469 */ 02470 #if defined(_WIN32) && !defined(__CYGWIN__) 02471 int len = 0; 02472 int i = 0; 02473 xmlChar *p = NULL; 02474 #endif 02475 xmlURIPtr uri; 02476 xmlChar *ret; 02477 const xmlChar *absuri; 02478 02479 if (path == NULL) 02480 return(NULL); 02481 02482 /* sanitize filename starting with // so it can be used as URI */ 02483 if ((path[0] == '/') && (path[1] == '/') && (path[2] != '/')) 02484 path++; 02485 02486 if ((uri = xmlParseURI((const char *) path)) != NULL) { 02487 xmlFreeURI(uri); 02488 return xmlStrdup(path); 02489 } 02490 02491 /* Check if this is an "absolute uri" */ 02492 absuri = xmlStrstr(path, BAD_CAST "://"); 02493 if (absuri != NULL) { 02494 int l, j; 02495 unsigned char c; 02496 xmlChar *escURI; 02497 02498 /* 02499 * this looks like an URI where some parts have not been 02500 * escaped leading to a parsing problem. Check that the first 02501 * part matches a protocol. 02502 */ 02503 l = absuri - path; 02504 /* Bypass if first part (part before the '://') is > 20 chars */ 02505 if ((l <= 0) || (l > 20)) 02506 goto path_processing; 02507 /* Bypass if any non-alpha characters are present in first part */ 02508 for (j = 0;j < l;j++) { 02509 c = path[j]; 02510 if (!(((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')))) 02511 goto path_processing; 02512 } 02513 02514 /* Escape all except the characters specified in the supplied path */ 02515 escURI = xmlURIEscapeStr(path, BAD_CAST ":/?_.#&;="); 02516 if (escURI != NULL) { 02517 /* Try parsing the escaped path */ 02518 uri = xmlParseURI((const char *) escURI); 02519 /* If successful, return the escaped string */ 02520 if (uri != NULL) { 02521 xmlFreeURI(uri); 02522 return escURI; 02523 } 02524 } 02525 } 02526 02527 path_processing: 02528 /* For Windows implementations, replace backslashes with 'forward slashes' */ 02529 #if defined(_WIN32) && !defined(__CYGWIN__) 02530 /* 02531 * Create a URI structure 02532 */ 02533 uri = xmlCreateURI(); 02534 if (uri == NULL) { /* Guard against 'out of memory' */ 02535 return(NULL); 02536 } 02537 02538 len = xmlStrlen(path); 02539 if ((len > 2) && IS_WINDOWS_PATH(path)) { 02540 /* make the scheme 'file' */ 02541 uri->scheme = xmlStrdup(BAD_CAST "file"); 02542 /* allocate space for leading '/' + path + string terminator */ 02543 uri->path = xmlMallocAtomic(len + 2); 02544 if (uri->path == NULL) { 02545 xmlFreeURI(uri); /* Guard agains 'out of memory' */ 02546 return(NULL); 02547 } 02548 /* Put in leading '/' plus path */ 02549 uri->path[0] = '/'; 02550 p = uri->path + 1; 02551 strncpy(p, path, len + 1); 02552 } else { 02553 uri->path = xmlStrdup(path); 02554 if (uri->path == NULL) { 02555 xmlFreeURI(uri); 02556 return(NULL); 02557 } 02558 p = uri->path; 02559 } 02560 /* Now change all occurences of '\' to '/' */ 02561 while (*p != '\0') { 02562 if (*p == '\\') 02563 *p = '/'; 02564 p++; 02565 } 02566 02567 if (uri->scheme == NULL) { 02568 ret = xmlStrdup((const xmlChar *) uri->path); 02569 } else { 02570 ret = xmlSaveUri(uri); 02571 } 02572 02573 xmlFreeURI(uri); 02574 #else 02575 ret = xmlStrdup((const xmlChar *) path); 02576 #endif 02577 return(ret); 02578 } 02579 02591 xmlChar * 02592 xmlPathToURI(const xmlChar *path) 02593 { 02594 xmlURIPtr uri; 02595 xmlURI temp; 02596 xmlChar *ret, *cal; 02597 02598 if (path == NULL) 02599 return(NULL); 02600 02601 if ((uri = xmlParseURI((const char *) path)) != NULL) { 02602 xmlFreeURI(uri); 02603 return xmlStrdup(path); 02604 } 02605 cal = xmlCanonicPath(path); 02606 if (cal == NULL) 02607 return(NULL); 02608 #if defined(_WIN32) && !defined(__CYGWIN__) 02609 /* xmlCanonicPath can return an URI on Windows (is that the intended behaviour?) 02610 If 'cal' is a valid URI allready then we are done here, as continuing would make 02611 it invalid. */ 02612 if ((uri = xmlParseURI((const char *) cal)) != NULL) { 02613 xmlFreeURI(uri); 02614 return cal; 02615 } 02616 /* 'cal' can contain a relative path with backslashes. If that is processed 02617 by xmlSaveURI, they will be escaped and the external entity loader machinery 02618 will fail. So convert them to slashes. Misuse 'ret' for walking. */ 02619 ret = cal; 02620 while (*ret != '\0') { 02621 if (*ret == '\\') 02622 *ret = '/'; 02623 ret++; 02624 } 02625 #endif 02626 memset(&temp, 0, sizeof(temp)); 02627 temp.path = (char *) cal; 02628 ret = xmlSaveUri(&temp); 02629 xmlFree(cal); 02630 return(ret); 02631 } 02632 #define bottom_uri 02633 #include "elfgcchack.h" Generated on Sat May 26 2012 04:25:17 for ReactOS by
1.7.6.1
|