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; }
/* Check if the target/filename.ext is registered as a view or exists as a file */ static cchar *checkView(HttpConn *conn, cchar *target, cchar *filename, cchar *ext) { MprPath info; EspRoute *eroute; cchar *path; if (filename) { target = mprJoinPath(target, filename); } if (ext && *ext) { if (!smatch(mprGetPathExt(target), ext)) { target = sjoin(target, ".", ext, NULL); } } eroute = conn->rx->route->eroute; if (mprLookupKey(eroute->views, target)) { return target; } path = mprJoinPath(conn->rx->route->documents, target); if (mprGetPathInfo(path, &info) == 0 && !info.isDir) { return target; } if (conn->rx->route->map && !(conn->tx->flags & HTTP_TX_NO_MAP)) { path = httpMapContent(conn, path); if (mprGetPathInfo(path, &info) == 0 && !info.isDir) { return target; } } return 0; }
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; }
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; }
static void outputLine(HttpQueue *q, MprDirEntry *ep, cchar *path, int nameSize) { MprPath info; MprTime when; Dir *dir; char *newPath, sizeBuf[16], timeBuf[48], *icon; struct tm tm; bool isDir; int len; cchar *ext, *mimeType; char *dirSuffix; char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; path = mprEscapeHtml(path); dir = q->conn->data; if (ep->size >= (1024 * 1024 * 1024)) { fmtNum(sizeBuf, sizeof(sizeBuf), (int) ep->size, 1024 * 1024 * 1024, "G"); } else if (ep->size >= (1024 * 1024)) { fmtNum(sizeBuf, sizeof(sizeBuf), (int) ep->size, 1024 * 1024, "M"); } else if (ep->size >= 1024) { fmtNum(sizeBuf, sizeof(sizeBuf), (int) ep->size, 1024, "K"); } else { fmt(sizeBuf, sizeof(sizeBuf), "%6d", (int) ep->size); } newPath = mprJoinPath(path, ep->name); if (mprGetPathInfo(newPath, &info) < 0) { when = mprGetTime(); isDir = 0; } else { isDir = info.isDir ? 1 : 0; when = (MprTime) info.mtime * MPR_TICKS_PER_SEC; } if (isDir) { icon = "folder"; dirSuffix = "/"; } else { ext = mprGetPathExt(ep->name); if (ext && (mimeType = mprLookupMime(q->conn->rx->route->mimeTypes, ext)) != 0) { if (strcmp(ext, "es") == 0 || strcmp(ext, "ejs") == 0 || strcmp(ext, "php") == 0) { icon = "text"; } else if (strstr(mimeType, "text") != 0) { icon = "text"; } else { icon = "compressed"; } } else { icon = "compressed"; } dirSuffix = ""; } mprDecodeLocalTime(&tm, when); fmt(timeBuf, sizeof(timeBuf), "%02d-%3s-%4d %02d:%02d", tm.tm_mday, months[tm.tm_mon], tm.tm_year + 1900, tm.tm_hour, tm.tm_min); len = (int) strlen(ep->name) + (int) strlen(dirSuffix); if (dir->fancyIndexing == 2) { httpWrite(q, "<tr><td valign=\"top\">"); httpWrite(q, "<img src=\"/icons/%s.gif\" alt=\"[ ]\", /></td>", icon); httpWrite(q, "<td><a href=\"%s%s\">%s%s</a></td>", ep->name, dirSuffix, ep->name, dirSuffix); httpWrite(q, "<td>%s</td><td>%s</td></tr>\r\n", timeBuf, sizeBuf); } else if (dir->fancyIndexing == 1) { httpWrite(q, "<img src=\"/icons/%s.gif\" alt=\"[ ]\", /> ", icon); httpWrite(q, "<a href=\"%s%s\">%s%s</a>%-*s %17s %4s\r\n", ep->name, dirSuffix, ep->name, dirSuffix, nameSize - len, "", timeBuf, sizeBuf); } else { httpWrite(q, "<li><a href=\"%s%s\"> %s%s</a></li>\r\n", ep->name, dirSuffix, ep->name, dirSuffix); } }
/* Determine the windows program to invoke. Support UNIX style "#!/program" bang directives on windows. Also supports ".cmd" and ".bat" alternatives. */ static void prepWinProgram(MprCmd *cmd) { #if ME_WIN_LIKE MprFile *file; cchar *bat, *ext, *shell, *cp, *start; char bang[ME_MAX_FNAME + 1], *path, *pp; /* Map separators, convert carriage-returns and newlines to spaces and remove quotes on the command */ path = mprAlloc(slen(cmd->argv[0]) * 2 + 1); strcpy(path, cmd->argv[0]); for (pp = path; *pp; pp++) { if (*pp == '/') { *pp = '\\'; } else if (*pp == '\r' || *pp == '\n') { *pp = ' '; } } if (*path == '\"') { if ((pp = strrchr(++path, '"')) != 0) { *pp = '\0'; } path = sclone(path); } cmd->argv[0] = path; /* Support ".cmd" and ".bat" files that take precedence */ if ((ext = mprGetPathExt(path)) == 0) { if ((bat = mprSearchPath(mprJoinPathExt(path, ".cmd"), MPR_SEARCH_EXE, cmd->searchPath, NULL)) == 0) { bat = mprSearchPath(mprJoinPathExt(path, ".bat"), MPR_SEARCH_EXE, cmd->searchPath, NULL); } if (bat) { if ((shell = getenv("COMSPEC")) == 0) { shell = "cmd.exe"; } cmd->argv = mprRealloc((void*) cmd->argv, (cmd->argc + 4) * sizeof(char*)); memmove((void*) &cmd->argv[3], (void*) cmd->argv, sizeof(char*) * (cmd->argc + 1)); cmd->argv[0] = sclone(shell); cmd->argv[1] = sclone("/Q"); cmd->argv[2] = sclone("/C"); cmd->argv[3] = bat; cmd->argc += 3; cmd->argv[cmd->argc] = 0; return; } } if ((file = mprOpenFile(path, O_RDONLY, 0)) != 0) { if (mprReadFile(file, bang, ME_MAX_FNAME) > 0) { mprCloseFile(file); bang[ME_MAX_FNAME] = '\0'; if (bang[0] == '#' && bang[1] == '!') { cp = start = &bang[2]; shell = ssplit(&bang[2], "\r\n", NULL); if (!mprIsPathAbs(shell)) { /* If we cannot access the command shell and the command is not an absolute path, look in the same directory as the script. */ if (mprPathExists(shell, X_OK)) { shell = mprJoinPath(mprGetPathDir(path), shell); } } /* Get length of argv with NULL and add one */ assert(cmd->argv[cmd->argc] == 0); cmd->argv = mprRealloc((void*) cmd->argv, (cmd->argc + 2) * sizeof(char*)); cmd->argv[cmd->argc + 1] = 0; /* Copy up to make room to insert the shell argument. This copies the original NULL */ memmove((void*) &cmd->argv[1], (void*) cmd->argv, sizeof(char*) * cmd->argc); cmd->argv[0] = sclone(shell); cmd->argv[1] = path; cmd->argc += 1; assert(cmd->argv[cmd->argc] == 0); } } else { mprCloseFile(file); } } #endif }
/* <% stylesheets(patterns); %> Where patterns may contain *, ** and !pattern for exclusion */ PUBLIC void stylesheets(cchar *patterns) { HttpStream *stream; HttpRx *rx; HttpRoute *route; EspRoute *eroute; MprList *files; cchar *filename, *ext, *uri, *path, *kind, *version, *clientDir; int next; stream = getStream(); rx = stream->rx; route = rx->route; eroute = route->eroute; patterns = httpExpandRouteVars(route, patterns); clientDir = httpGetDir(route, "documents"); if (!patterns || !*patterns) { version = espGetConfig(route, "version", "1.0.0"); if (eroute->combineSheet) { /* Previously computed combined stylesheet filename */ stylesheets(eroute->combineSheet); } else if (espGetConfig(route, "http.content.combine[@=css]", 0)) { if (espGetConfig(route, "http.content.minify[@=css]", 0)) { eroute->combineSheet = sfmt("css/all-%s.min.css", version); } else { eroute->combineSheet = sfmt("css/all-%s.css", version); } stylesheets(eroute->combineSheet); } else { /* Not combining into a single stylesheet, so give priority to all.less over all.css if present Load a pure CSS incase some styles need to be applied before the lesssheet is parsed */ ext = espGetConfig(route, "http.content.stylesheets", "css"); filename = mprJoinPathExt("css/all", ext); path = mprJoinPath(clientDir, filename); if (mprPathExists(path, R_OK)) { stylesheets(filename); } else if (!smatch(ext, "less")) { path = mprJoinPath(clientDir, "css/all.less"); if (mprPathExists(path, R_OK)) { stylesheets("css/all.less"); } } } } else { if (sends(patterns, "all.less")) { path = mprJoinPath(clientDir, "css/fix.css"); if (mprPathExists(path, R_OK)) { stylesheets("css/fix.css"); } } if ((files = mprGlobPathFiles(clientDir, patterns, MPR_PATH_RELATIVE)) == 0 || mprGetListLength(files) == 0) { files = mprCreateList(0, 0); mprAddItem(files, patterns); } for (ITERATE_ITEMS(files, path, next)) { path = sjoin("~/", strim(path, ".gz", MPR_TRIM_END), NULL); uri = httpLink(stream, path); kind = mprGetPathExt(path); if (smatch(kind, "css")) { espRender(stream, "<link rel='stylesheet' type='text/css' href='%s' />\n", uri); } else { espRender(stream, "<link rel='stylesheet/%s' type='text/css' href='%s' />\n", kind, uri); } } } }
static int compileInner(EcCompiler *cp, int argc, char **argv) { Ejs *ejs; EjsModule *mp; MprList *nodes; EjsBlock *block; EcLocation loc; cchar *ext; char *msg; int next, i, j, nextModule, lflags, rc, paused; ejs = cp->ejs; if ((nodes = mprCreateList(-1, 0)) == 0) { return EJS_ERR; } cp->nodes = nodes; /* Warn about source files mentioned multiple times. TODO OPT. This is slow. */ for (i = 0; i < argc; i++) { for (j = 0; j < argc; j++) { if (i == j) { continue; } if (mprSamePath(argv[i], argv[j])) { compileError(cp, "Loading source %s multiple times. Ignoring extra copies.", argv[i]); return EJS_ERR; } } if (cp->outputFile && mprSamePath(cp->outputFile, argv[i])) { compileError(cp, "Output file is the same as input file: %s", argv[i]); return EJS_ERR; } } /* Compile source files and load any module files */ for (i = 0; i < argc && !cp->fatalError; i++) { ext = mprGetPathExt(argv[i]); if (scasecmp(ext, "mod") == 0 || scasecmp(ext, BIT_SHOBJ) == 0) { nextModule = mprGetListLength(ejs->modules); lflags = cp->strict ? EJS_LOADER_STRICT : 0; if ((rc = ejsLoadModule(cp->ejs, ejsCreateStringFromAsc(ejs, argv[i]), -1, -1, lflags)) < 0) { msg = sfmt("Error initializing module %s\n%s", argv[i], ejsGetErrorMsg(cp->ejs, 1)); memset(&loc, 0, sizeof(EcLocation)); loc.filename = sclone(argv[i]); if (rc == MPR_ERR_CANT_INITIALIZE) { ecError(cp, "Error", &loc, msg); } else { ecError(cp, "Error", &loc, msg); } cp->nodes = NULL; return EJS_ERR; } if (cp->merge) { /* If merging, we must emit the loaded module into the output. So add to the compiled modules list. */ for (next = nextModule; (mp = mprGetNextItem(ejs->modules, &next)) != 0; ) { if (mprLookupItem(cp->modules, mp) < 0 && mprAddItem(cp->modules, mp) < 0) { compileError(cp, "Can't add module %s", mp->name); } } } mprAddItem(nodes, 0); } else { mprAssert(!MPR->marking); paused = ejsBlockGC(ejs); mprAddItem(nodes, ecParseFile(cp, argv[i])); ejsUnblockGC(ejs, paused); } mprAssert(!MPR->marking); } mprAssert(ejs->result == 0 || (MPR_GET_GEN(MPR_GET_MEM(ejs->result)) != MPR->heap->dead)); /* Allocate the eval frame stack. This is used for property lookups. We have one dummy block at the top always. */ block = ejsCreateBlock(ejs, 0); mprSetName(block, "Compiler"); ejsPushBlock(ejs, block); /* Process the internal representation and generate code */ paused = ejsBlockGC(ejs); if (!cp->parseOnly && cp->errorCount == 0) { ecResetParser(cp); if (ecAstProcess(cp) < 0) { ejsPopBlock(ejs); cp->nodes = NULL; ejsUnblockGC(ejs, paused); return EJS_ERR; } if (cp->errorCount == 0) { ecResetParser(cp); if (ecCodeGen(cp) < 0) { ejsPopBlock(ejs); cp->nodes = NULL; ejsUnblockGC(ejs, paused); return EJS_ERR; } } } ejsPopBlock(ejs); mprAssert(ejs->result == 0 || (MPR_GET_GEN(MPR_GET_MEM(ejs->result)) != MPR->heap->dead)); /* Add compiled modules to the interpreter */ for (next = 0; ((mp = (EjsModule*) mprGetNextItem(cp->modules, &next)) != 0); ) { ejsAddModule(cp->ejs, mp); } cp->nodes = NULL; ejsUnblockGC(ejs, paused); if (!paused) { mprYield(0); } mprAssert(ejs->result == 0 || (MPR_GET_GEN(MPR_GET_MEM(ejs->result)) != MPR->heap->dead)); return (cp->errorCount > 0) ? EJS_ERR: 0; }