PUBLIC HttpUri *httpNormalizeUri(HttpUri *uri) { if (!uri) { return 0; } uri->path = httpNormalizeUriPath(uri->path); return uri; }
/* function get normalize(): Uri */ static EjsUri *uri_normalize(Ejs *ejs, EjsUri *up, int argc, EjsObj **argv) { EjsUri *np; np = cloneUri(ejs, up, 0); np->uri->path = httpNormalizeUriPath(up->uri->path); return np; }
PUBLIC HttpUri *httpResolveUri(HttpConn *conn, HttpUri *base, HttpUri *other) { HttpHost *host; HttpEndpoint *endpoint; HttpUri *current; if (!base || !base->valid) { return other; } if (!other || !other->valid) { return base; } current = httpCloneUri(base, 0); /* Must not inherit the query or reference */ current->query = 0; current->reference = 0; if (other->scheme && !smatch(current->scheme, other->scheme)) { current->scheme = sclone(other->scheme); /* If the scheme is changed (test above), then accept an explict port. If no port, then must not use the current port as the scheme has changed. */ if (other->port) { current->port = other->port; } else { host = conn ? conn->host : httpGetDefaultHost(); endpoint = smatch(current->scheme, "https") ? host->secureEndpoint : host->defaultEndpoint; if (endpoint) { current->port = endpoint->port; } else { current->port = 0; } } } if (other->host) { current->host = sclone(other->host); } if (other->port) { current->port = other->port; } if (other->path) { trimPathToDirname(current); httpJoinUriPath(current, current, other); current->path = httpNormalizeUriPath(current->path); } if (other->reference) { current->reference = sclone(other->reference); } if (other->query) { current->query = sclone(other->query); } current->ext = mprGetPathExt(current->path); return current; }
/* Set the path portion static function set path(path: String?): Void */ static EjsObj *uri_set_path(Ejs *ejs, EjsUri *up, int argc, EjsObj **argv) { if (argv[0] == ESV(null)) { up->uri->path = 0; up->uri->ext = 0; } else { up->uri->path = httpNormalizeUriPath(ejsToMulti(ejs, argv[0])); up->uri->ext = mprGetPathExt(up->uri->path); } return 0; }
static bool normalize(MprTestGroup *gp, char *uri, char *expectedUri) { char *validated; validated = httpNormalizeUriPath(uri); if (strcmp(expectedUri, validated) == 0) { return 1; } else { mprLog(0, "Uri \"%s\" validated to \"%s\" instead of \"%s\"\n", uri, validated, expectedUri); return 0; } }
/* Validate a URI path for use in a HTTP request line The URI must contain only valid characters and must being with "/" both before and after decoding. A decoded, normalized URI path is returned. */ PUBLIC char *httpValidateUriPath(cchar *uri) { char *up; if (uri == 0 || *uri != '/') { return 0; } if (!httpValidUriChars(uri)) { return 0; } up = mprUriDecode(uri); if ((up = httpNormalizeUriPath(up)) == 0) { return 0; } if (*up != '/' || strchr(up, '\\')) { return 0; } return up; }
/* This returns a URI relative to the base for the given target uri = target.relative(base) */ PUBLIC HttpUri *httpGetRelativeUri(HttpUri *base, HttpUri *target, int clone) { HttpUri *uri; char *basePath, *bp, *cp, *tp, *startDiff; int i, baseSegments, commonSegments; if (base == 0) { return clone ? httpCloneUri(target, 0) : target; } if (target == 0) { return clone ? httpCloneUri(base, 0) : base; } if (!(target->path && target->path[0] == '/') || !((base->path && base->path[0] == '/'))) { /* If target is relative, just use it. If base is relative, cannot use it because we don't know where it is */ return (clone) ? httpCloneUri(target, 0) : target; } if (base->scheme && target->scheme && scmp(base->scheme, target->scheme) != 0) { return (clone) ? httpCloneUri(target, 0) : target; } if (base->host && target->host && (base->host && scmp(base->host, target->host) != 0)) { return (clone) ? httpCloneUri(target, 0) : target; } if (getPort(base) != getPort(target)) { return (clone) ? httpCloneUri(target, 0) : target; } if ((basePath = httpNormalizeUriPath(base->path)) == 0) { return 0; } /* Count trailing "/" */ for (baseSegments = 0, bp = basePath; *bp; bp++) { if (*bp == '/') { baseSegments++; } } /* Find portion of path that matches the base, if any. */ commonSegments = 0; for (bp = base->path, tp = startDiff = target->path; *bp && *tp; bp++, tp++) { if (*bp == '/') { if (*tp == '/') { commonSegments++; startDiff = tp; } } else { if (*bp != *tp) { break; } } } if (*startDiff == '/') { startDiff++; } if ((uri = httpCloneUri(target, 0)) == 0) { return 0; } uri->host = 0; uri->scheme = 0; uri->port = 0; uri->path = cp = mprAlloc(baseSegments * 3 + (int) slen(target->path) + 2); for (i = commonSegments; i < baseSegments; i++) { *cp++ = '.'; *cp++ = '.'; *cp++ = '/'; } if (*startDiff) { strcpy(cp, startDiff); } else if (cp > uri->path) { /* Cleanup trailing separators ("../" is the end of the new path) */ cp[-1] = '\0'; } else { strcpy(uri->path, "."); } return uri; }