static HttpUri *toHttpUri(Ejs *ejs, EjsObj *arg, int dup) { HttpUri *uri; if (ejsIs(ejs, arg, String)) { uri = httpCreateUri(ejsToMulti(ejs, arg), 0); } else if (ejsIs(ejs, arg, Uri)) { if (dup) { uri = httpCloneUri(((EjsUri*) arg)->uri, 0); } else { uri = ((EjsUri*) arg)->uri; } } else if (ejsIs(ejs, arg, Path)) { uri = httpCreateUri(((EjsPath*) arg)->value, 0); } else if (ejsGetLength(ejs, arg) > 0) { uri = createHttpUriFromHash(ejs, arg, 0); } else { arg = (EjsObj*) ejsToString(ejs, arg); uri = httpCreateUri(ejsToMulti(ejs, arg), 0); } return uri; }
PUBLIC HttpUri *httpJoinUri(HttpUri *uri, int argc, HttpUri **others) { HttpUri *other; int i; if ((uri = httpCloneUri(uri, 0)) == 0) { return 0; } if (!uri->valid) { return 0; } for (i = 0; i < argc; i++) { other = others[i]; if (other->scheme) { uri->scheme = sclone(other->scheme); uri->port = other->port; } if (other->host) { uri->host = sclone(other->host); uri->port = other->port; } if (other->path) { httpJoinUriPath(uri, uri, other); } if (other->reference) { uri->reference = sclone(other->reference); } if (other->query) { uri->query = sclone(other->query); } } uri->ext = mprGetPathExt(uri->path); return uri; }
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; }
static EjsUri *cloneUri(Ejs *ejs, EjsUri *src, bool deep) { EjsUri *dest; if ((dest = ejsCreateObj(ejs, TYPE(src), 0)) == 0) { return 0; } /* NOTE: a deep copy will complete the uri */ dest->uri = httpCloneUri(src->uri, deep ? HTTP_COMPLETE_URI : 0); return dest; }
PUBLIC HttpUri *httpResolveUri(HttpUri *base, int argc, HttpUri **others, bool local) { HttpUri *current, *other; int i; if ((current = httpCloneUri(base, 0)) == 0) { return 0; } if (local) { current->host = 0; current->scheme = 0; current->port = 0; } /* Must not inherit the query or reference */ current->query = 0; current->reference = 0; for (i = 0; i < argc; i++) { other = others[i]; 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 if (current->port) { 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); } if (other->reference) { current->reference = sclone(other->reference); } if (other->query) { current->query = sclone(other->query); } } current->ext = mprGetPathExt(current->path); return current; }
/* function resolve(target): Uri */ static EjsUri *uri_resolve(Ejs *ejs, EjsUri *up, int argc, EjsObj **argv) { EjsUri *result; HttpUri *uri, *target; uri = up->uri; target = toHttpUri(ejs, argv[0], 0); result = ejsCreateObj(ejs, ESV(Uri), 0); uri = httpResolveUri(uri, 1, &target, 0); if (up->uri == uri) { uri = httpCloneUri(uri, 0); } result->uri = uri; return result; }
/* Convert an arg to a URI. Can handle strings, paths, URIs and object hashes. Will cast all else to strings and then parse. */ static EjsUri *castToUri(Ejs *ejs, EjsObj *arg) { EjsUri *up; up = ejsCreateObj(ejs, ESV(Uri), 0); if (ejsIs(ejs, arg, String)) { up->uri = httpCreateUri(up, ejsToMulti(ejs, arg), 0); } else if (ejsIs(ejs, arg, Uri)) { up->uri = httpCloneUri(((EjsUri*) arg)->uri, 0); } else if (ejsIs(ejs, arg, Path)) { ustr = ((EjsPath*) arg)->path; up->uri = httpCreateUri(up, ustr, 0); } else if (ejsGetLength(ejs, arg) > 0) { up->uri = createHttpUriFromHash(ejs, up, arg, 0); } else { arg = (EjsObj) ejsToString(ejs, arg); up->uri = httpCreateUri(up, ejsToMulti(ejs, arg), 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; }