📄 uri.c
字号:
if ((ref->authority != NULL) || (ref->server != NULL)) { if (ref->authority != NULL) res->authority = xmlMemStrdup(ref->authority); else { res->server = xmlMemStrdup(ref->server); if (ref->user != NULL) res->user = xmlMemStrdup(ref->user); res->port = ref->port; } if (ref->path != NULL) res->path = xmlMemStrdup(ref->path); goto step_7; } if (bas->authority != NULL) res->authority = xmlMemStrdup(bas->authority); else if (bas->server != NULL) { res->server = xmlMemStrdup(bas->server); if (bas->user != NULL) res->user = xmlMemStrdup(bas->user); res->port = bas->port; } /* * 5) If the path component begins with a slash character ("/"), then * the reference is an absolute-path and we skip to step 7. */ if ((ref->path != NULL) && (ref->path[0] == '/')) { res->path = xmlMemStrdup(ref->path); goto step_7; } /* * 6) If this step is reached, then we are resolving a relative-path * reference. The relative path needs to be merged with the base * URI's path. Although there are many ways to do this, we will * describe a simple method using a separate string buffer. * * Allocate a buffer large enough for the result string. */ len = 2; /* extra / and 0 */ if (ref->path != NULL) len += strlen(ref->path); if (bas->path != NULL) len += strlen(bas->path); res->path = (char *) xmlMallocAtomic(len); if (res->path == NULL) { xmlGenericError(xmlGenericErrorContext, "xmlBuildURI: out of memory\n"); goto done; } res->path[0] = 0; /* * a) All but the last segment of the base URI's path component is * copied to the buffer. In other words, any characters after the * last (right-most) slash character, if any, are excluded. */ cur = 0; out = 0; if (bas->path != NULL) { while (bas->path[cur] != 0) { while ((bas->path[cur] != 0) && (bas->path[cur] != '/')) cur++; if (bas->path[cur] == 0) break; cur++; while (out < cur) { res->path[out] = bas->path[out]; out++; } } } res->path[out] = 0; /* * b) The reference's path component is appended to the buffer * string. */ if (ref->path != NULL && ref->path[0] != 0) { indx = 0; /* * Ensure the path includes a '/' */ if ((out == 0) && (bas->server != NULL)) res->path[out++] = '/'; while (ref->path[indx] != 0) { res->path[out++] = ref->path[indx++]; } } res->path[out] = 0; /* * Steps c) to h) are really path normalization steps */ xmlNormalizeURIPath(res->path);step_7: /* * 7) The resulting URI components, including any inherited from the * base URI, are recombined to give the absolute form of the URI * reference. */ val = xmlSaveUri(res);done: if (ref != NULL) xmlFreeURI(ref); if (bas != NULL) xmlFreeURI(bas); if (res != NULL) xmlFreeURI(res); return(val);}/** * xmlBuildRelativeURI: * @URI: the URI reference under consideration * @base: the base value * * Expresses the URI of the reference in terms relative to the * base. Some examples of this operation include: * base = "http://site1.com/docs/book1.html" * URI input URI returned * docs/pic1.gif pic1.gif * docs/img/pic1.gif img/pic1.gif * img/pic1.gif ../img/pic1.gif * http://site1.com/docs/pic1.gif pic1.gif * http://site2.com/docs/pic1.gif http://site2.com/docs/pic1.gif * * base = "docs/book1.html" * URI input URI returned * docs/pic1.gif pic1.gif * docs/img/pic1.gif img/pic1.gif * img/pic1.gif ../img/pic1.gif * http://site1.com/docs/pic1.gif http://site1.com/docs/pic1.gif * * * Note: if the URI reference is really wierd or complicated, it may be * worthwhile to first convert it into a "nice" one by calling * xmlBuildURI (using 'base') before calling this routine, * since this routine (for reasonable efficiency) assumes URI has * already been through some validation. * * Returns a new URI string (to be freed by the caller) or NULL in case * error. */xmlChar *xmlBuildRelativeURI (const xmlChar * URI, const xmlChar * base){ xmlChar *val = NULL; int ret; int ix; int pos = 0; int nbslash = 0; int len; xmlURIPtr ref = NULL; xmlURIPtr bas = NULL; xmlChar *bptr, *uptr, *vptr; int remove_path = 0; if ((URI == NULL) || (*URI == 0)) return NULL; /* * First parse URI into a standard form */ ref = xmlCreateURI (); if (ref == NULL) return NULL; /* If URI not already in "relative" form */ if (URI[0] != '.') { ret = xmlParseURIReference (ref, (const char *) URI); if (ret != 0) goto done; /* Error in URI, return NULL */ } else ref->path = (char *)xmlStrdup(URI); /* * Next parse base into the same standard form */ if ((base == NULL) || (*base == 0)) { val = xmlStrdup (URI); goto done; } bas = xmlCreateURI (); if (bas == NULL) goto done; if (base[0] != '.') { ret = xmlParseURIReference (bas, (const char *) base); if (ret != 0) goto done; /* Error in base, return NULL */ } else bas->path = (char *)xmlStrdup(base); /* * If the scheme / server on the URI differs from the base, * just return the URI */ if ((ref->scheme != NULL) && ((bas->scheme == NULL) || (xmlStrcmp ((xmlChar *)bas->scheme, (xmlChar *)ref->scheme)) || (xmlStrcmp ((xmlChar *)bas->server, (xmlChar *)ref->server)))) { val = xmlStrdup (URI); goto done; } if (xmlStrEqual((xmlChar *)bas->path, (xmlChar *)ref->path)) { val = xmlStrdup(BAD_CAST ""); goto done; } if (bas->path == NULL) { val = xmlStrdup((xmlChar *)ref->path); goto done; } if (ref->path == NULL) { ref->path = (char *) "/"; remove_path = 1; } /* * At this point (at last!) we can compare the two paths * * First we take care of the special case where either of the * two path components may be missing (bug 316224) */ if (bas->path == NULL) { if (ref->path != NULL) { uptr = (xmlChar *) ref->path; if (*uptr == '/') uptr++; val = xmlStrdup(uptr); } goto done; } bptr = (xmlChar *)bas->path; if (ref->path == NULL) { for (ix = 0; bptr[ix] != 0; ix++) { if (bptr[ix] == '/') nbslash++; } uptr = NULL; len = 1; /* this is for a string terminator only */ } else { /* * Next we compare the two strings and find where they first differ */ if ((ref->path[pos] == '.') && (ref->path[pos+1] == '/')) pos += 2; if ((*bptr == '.') && (bptr[1] == '/')) bptr += 2; else if ((*bptr == '/') && (ref->path[pos] != '/')) bptr++; while ((bptr[pos] == ref->path[pos]) && (bptr[pos] != 0)) pos++; if (bptr[pos] == ref->path[pos]) { val = xmlStrdup(BAD_CAST ""); goto done; /* (I can't imagine why anyone would do this) */ } /* * In URI, "back up" to the last '/' encountered. This will be the * beginning of the "unique" suffix of URI */ ix = pos; if ((ref->path[ix] == '/') && (ix > 0)) ix--; else if ((ref->path[ix] == 0) && (ix > 1) && (ref->path[ix - 1] == '/')) ix -= 2; for (; ix > 0; ix--) { if (ref->path[ix] == '/') break; } if (ix == 0) { uptr = (xmlChar *)ref->path; } else { ix++; uptr = (xmlChar *)&ref->path[ix]; } /* * In base, count the number of '/' from the differing point */ if (bptr[pos] != ref->path[pos]) {/* check for trivial URI == base */ for (; bptr[ix] != 0; ix++) { if (bptr[ix] == '/') nbslash++; } } len = xmlStrlen (uptr) + 1; } if (nbslash == 0) { if (uptr != NULL) val = xmlStrdup (uptr); goto done; } /* * Allocate just enough space for the returned string - * length of the remainder of the URI, plus enough space * for the "../" groups, plus one for the terminator */ val = (xmlChar *) xmlMalloc (len + 3 * nbslash); if (val == NULL) { xmlGenericError(xmlGenericErrorContext, "xmlBuildRelativeURI: out of memory\n"); goto done; } vptr = val; /* * Put in as many "../" as needed */ for (; nbslash>0; nbslash--) { *vptr++ = '.'; *vptr++ = '.'; *vptr++ = '/'; } /* * Finish up with the end of the URI */ if (uptr != NULL) { if ((vptr > val) && (len > 0) && (uptr[0] == '/') && (vptr[-1] == '/')) { memcpy (vptr, uptr + 1, len - 1); vptr[len - 2] = 0; } else { memcpy (vptr, uptr, len); vptr[len - 1] = 0; } } else { vptr[len - 1] = 0; }done: /* * Free the working variables */ if (remove_path != 0) ref->path = NULL; if (ref != NULL) xmlFreeURI (ref); if (bas != NULL) xmlFreeURI (bas); return val;}/** * xmlCanonicPath: * @path: the resource locator in a filesystem notation * * Constructs a canonic path from the specified path. * * Returns a new canonic path, or a duplicate of the path parameter if the * construction fails. The caller is responsible for freeing the memory occupied * by the returned string. If there is insufficient memory available, or the * argument is NULL, the function returns NULL. */#define IS_WINDOWS_PATH(p) \ ((p != NULL) && \ (((p[0] >= 'a') && (p[0] <= 'z')) || \ ((p[0] >= 'A') && (p[0] <= 'Z'))) && \ (p[1] == ':') && ((p[2] == '/') || (p[2] == '\\')))xmlChar *xmlCanonicPath(const xmlChar *path){/* * For Windows implementations, additional work needs to be done to * replace backslashes in pathnames with "forward slashes" */#if defined(_WIN32) && !defined(__CYGWIN__) int len = 0; int i = 0; xmlChar *p = NULL;#endif xmlURIPtr uri; xmlChar *ret; const xmlChar *absuri; if (path == NULL) return(NULL); if ((uri = xmlParseURI((const char *) path)) != NULL) { xmlFreeURI(uri); return xmlStrdup(path); } /* Check if this is an "absolute uri" */ absuri = xmlStrstr(path, BAD_CAST "://"); if (absuri != NULL) { int l, j; unsigned char c; xmlChar *escURI; /* * this looks like an URI where some parts have not been * escaped leading to a parsing problem. Check that the first * part matches a protocol. */ l = absuri - path; /* Bypass if first part (part before the '://') is > 20 chars */ if ((l <= 0) || (l > 20)) goto path_processing; /* Bypass if any non-alpha characters are present in first part */ for (j = 0;j < l;j++) { c = path[j]; if (!(((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')))) goto path_processing; } /* Escape all except the characters specified in the supplied path */ escURI = xmlURIEscapeStr(path, BAD_CAST ":/?_.#&;="); if (escURI != NULL) { /* Try parsing the escaped path */ uri = xmlParseURI((const char *) escURI); /* If successful, return the escaped string */ if (uri != NULL) { xmlFreeURI(uri); return escURI; } } }path_processing:/* For Windows implementations, replace backslashes with 'forward slashes' */#if defined(_WIN32) && !defined(__CYGWIN__) /* * Create a URI structure */ uri = xmlCreateURI(); if (uri == NULL) { /* Guard against 'out of memory' */ return(NULL); } len = xmlStrlen(path); if ((len > 2) && IS_WINDOWS_PATH(path)) { /* make the scheme 'file' */ uri->scheme = xmlStrdup(BAD_CAST "file"); /* allocate space for leading '/' + path + string terminator */ uri->path = xmlMallocAtomic(len + 2); if (uri->path == NULL) { xmlFreeURI(uri); /* Guard agains 'out of memory' */ return(NULL); } /* Put in leading '/' plus path */ uri->path[0] = '/'; p = uri->path + 1; strncpy(p, path, len + 1); } else { uri->path = xmlStrdup(path); if (uri->path == NULL) { xmlFreeURI(uri); return(NULL); } p = uri->path; } /* Now change all occurences of '\' to '/' */ while (*p != '\0') { if (*p == '\\') *p = '/'; p++; } if (uri->scheme == NULL) { ret = xmlStrdup((const xmlChar *) uri->path); } else { ret = xmlSaveUri(uri); } xmlFreeURI(uri);#else ret = xmlStrdup((const xmlChar *) path);#endif return(ret);}/** * xmlPathToURI: * @path: the resource locator in a filesystem notation * * Constructs an URI expressing the existing path * * Returns a new URI, or a duplicate of the path parameter if the * construction fails. The caller is responsible for freeing the memory * occupied by the returned string. If there is insufficient memory available, * or the argument is NULL, the function returns NULL. */xmlChar *xmlPathToURI(const xmlChar *path){ xmlURIPtr uri; xmlURI temp; xmlChar *ret, *cal; if (path == NULL) return(NULL); if ((uri = xmlParseURI((const char *) path)) != NULL) { xmlFreeURI(uri); return xmlStrdup(path); } cal = xmlCanonicPath(path); if (cal
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -