/* Test if the version is acceptable based on the supplied critera. The acceptable formats for criteria are: VER Allows prereleases 1.2.[*xX] Wild card version portion. (allows prereleases). ~VER Compatible with VER at the least significant level. ~1.2.3 == (>=1.2.3 <1.3.0) Compatible at the patch level ~1.2 == 1.2.x Compatible at the minor level ~1 == 1.x Compatible at the major level ^VER Compatible with VER at the most significant level. ^0.2.3 == 0.2.3 <= VER < 0.3.0 ^1.2.3 == 1.2.3 <= VER < 2.0.0 [>, >=, <, <=, ==, !=]VER Create range relative to given version EXPR1 - EXPR2 <=EXPR1 <=EXPR2 EXPR1 || EXPR2 ... EXPR1 OR EXPR2 EXPR1 && EXPR2 ... EXPR1 AND EXPR2 EXPR1 EXPR2 ... EXPR1 AND EXPR2 Pre-release versions will only match if the criteria contains a "-.*" prerelease suffix */ PUBLIC bool mprIsVersionObjAcceptable(MprVersion *vp, cchar *criteria) { char *expr, *exprTok, *range, *rangeTok, *low, *high; bool allMatched; if (!vp->ok) { return 0; } if (!criteria || *criteria == '\0') { return 1; } criteria = cleanVersion(criteria); for (range = (char*) criteria; stok(range, "||", &rangeTok) != 0; range = rangeTok) { range = strim(range, " \t", 0); allMatched = 1; for (expr = (char*) range; sptok(expr, "&&", &exprTok) != 0; expr = exprTok) { if (scontains(expr, " - ")) { low = sptok(expr, " - ", &high); return inRange(vp, sjoin(">=", low, NULL)) && inRange(vp, sjoin("<=", high, NULL)); } if (!inRange(vp, expr)) { allMatched = 0; break; } } if (allMatched) { return 1; } } return 0; }
static void defineFileFields(HttpQueue *q, Upload *up) { HttpConn *conn; HttpUploadFile *file; char *key; conn = q->conn; if (conn->tx->handler == conn->http->ejsHandler) { /* Ejscript manages this for itself */ return; } up = q->queueData; file = up->currentFile; key = sjoin("FILE_CLIENT_FILENAME_", up->name, NULL); httpSetParam(conn, key, file->clientFilename); key = sjoin("FILE_CONTENT_TYPE_", up->name, NULL); httpSetParam(conn, key, file->contentType); key = sjoin("FILE_FILENAME_", up->name, NULL); httpSetParam(conn, key, file->filename); key = sjoin("FILE_SIZE_", up->name, NULL); httpSetIntParam(conn, key, (int) file->size); }
/* Render a document by mapping a URL target to a document. The target is interpreted relative to route->documents. If target exists, then serve that. If target + extension exists, serve that. If target is a directory and an index.esp, return the index.esp without a redirect. If target is a directory without a trailing "/" but with an index.esp, do an external redirect to "URI/". If target does not end with ".esp", then do not serve that. */ PUBLIC void espRenderDocument(HttpConn *conn, cchar *target) { HttpUri *up; MprKey *kp; cchar *dest; assert(target); for (ITERATE_KEYS(conn->rx->route->extensions, kp)) { if (kp->key && *kp->key) { if ((dest = checkView(conn, target, 0, kp->key)) != 0) { espRenderView(conn, dest, 0); return; } } } if ((dest = checkView(conn, target, 0, "esp")) != 0) { espRenderView(conn, dest, 0); return; } if ((dest = checkView(conn, target, "index", "esp")) != 0) { /* Must do external redirect first if URL does not end with "/" */ if (!sends(conn->rx->parsedUri->path, "/")) { up = conn->rx->parsedUri; httpRedirect(conn, HTTP_CODE_MOVED_PERMANENTLY, httpFormatUri(up->scheme, up->host, up->port, sjoin(up->path, "/", NULL), up->reference, up->query, 0)); return; } espRenderView(conn, dest, 0); return; } /* Remove in version 6 */ #if DEPRECATED || 1 if ((dest = checkView(conn, sjoin("app/", target, NULL), 0, "esp")) != 0) { espRenderView(conn, dest, 0); return; } #endif /* Last chance, forward to the file handler ... not an ESP request. This enables static file requests within ESP routes. */ httpTrace(conn, "esp.handler", "context", "msg: 'Relay to the fileHandler"); conn->rx->target = &conn->rx->pathInfo[1]; httpMapFile(conn); if (conn->tx->fileInfo.isDir) { httpHandleDirectory(conn); } httpSetFileHandler(conn, 0); }
/* Calculate a qualified route name. The form is: /{app}/{controller}/action */ static char *actionRoute(HttpRoute *route, cchar *controller, cchar *action) { cchar *controllerPrefix; if (action == 0 || *action == '\0') { action = "default"; } if (controller) { controllerPrefix = (controller && smatch(controller, "{controller}")) ? "*" : controller; return sjoin("^", route->prefix, "/", controllerPrefix, "/", action, NULL); } else { return sjoin("^", route->prefix, "/", action, NULL); } }
PUBLIC void mprSetModuleSearchPath(char *searchPath) { MprModuleService *ms; ms = MPR->moduleService; if (searchPath == 0) { #ifdef ME_VAPP_PREFIX ms->searchPath = sjoin(mprGetAppDir(), MPR_SEARCH_SEP, mprGetAppDir(), MPR_SEARCH_SEP, ME_VAPP_PREFIX "/bin", NULL); #else ms->searchPath = sjoin(mprGetAppDir(), MPR_SEARCH_SEP, mprGetAppDir(), NULL); #endif } else { ms->searchPath = sclone(searchPath); } }
PUBLIC void espDefineAction(HttpRoute *route, cchar *target, void *callback) { EspRoute *eroute; char *action, *controller; assert(route); assert(target && *target); assert(callback); eroute = ((EspRoute*) route->eroute)->top; if (target) { #if DEPRECATED || 1 /* Keep till version 6 */ if (scontains(target, "-cmd-")) { target = sreplace(target, "-cmd-", "/"); } else if (schr(target, '-')) { controller = ssplit(sclone(target), "-", (char**) &action); target = sjoin(controller, "/", action, NULL); } #endif if (!eroute->actions) { eroute->actions = mprCreateHash(-1, MPR_HASH_STATIC_VALUES); } mprAddKey(eroute->actions, target, callback); } }
/* Set the current working directory function chdir(value: String|Path): void */ static EjsObj *app_chdir(Ejs *ejs, EjsObj *unused, int argc, EjsObj **argv) { cchar *path; assert(argc == 1); if (ejsIs(ejs, argv[0], Path)) { path = ((EjsPath*) argv[0])->value; } else if (ejsIs(ejs, argv[0], String)) { path = ejsToMulti(ejs, argv[0]); } else { ejsThrowIOError(ejs, "Bad path"); return NULL; } #if WINDOWS { MprFileSystem *fs; fs = mprLookupFileSystem(path); if (!mprPathExists(path, X_OK) && *path == '/') { path = sjoin(fs->cygwin, path, NULL); } } #endif if (chdir((char*) path) < 0) { ejsThrowIOError(ejs, "Cannot change the current directory"); } return 0; }
/* Initialize the upload filter for a new request */ static int openUpload(HttpQueue *q) { HttpConn *conn; HttpRx *rx; Upload *up; cchar *uploadDir; char *boundary; conn = q->conn; rx = conn->rx; if ((up = mprAllocObj(Upload, manageUpload)) == 0) { return MPR_ERR_MEMORY; } q->queueData = up; up->contentState = HTTP_UPLOAD_BOUNDARY; rx->autoDelete = rx->route->autoDelete; rx->renameUploads = rx->route->renameUploads; uploadDir = getUploadDir(rx->route); httpSetParam(conn, "UPLOAD_DIR", uploadDir); if ((boundary = strstr(rx->mimeType, "boundary=")) != 0) { boundary += 9; up->boundary = sjoin("--", boundary, NULL); up->boundaryLen = strlen(up->boundary); } if (up->boundaryLen == 0 || *up->boundary == '\0') { httpError(conn, HTTP_CODE_BAD_REQUEST, "Bad boundary"); return MPR_ERR_BAD_ARGS; } return 0; }
PUBLIC void espScript(HttpConn *conn, cchar *uri, cchar *optionString) { MprHash *options; cchar *indent, *newline, *path; EspScript *sp; EspRoute *eroute; bool minified; eroute = conn->rx->route->eroute; options = httpGetOptions(optionString); if (uri) { espRender(conn, "<script src='%s' type='text/javascript'></script>", httpUri(conn, uri)); } else { minified = smatch(httpGetOption(options, "minified", 0), "true"); indent = ""; for (sp = defaultScripts; sp->name; sp++) { if (sp->option && !smatch(httpGetOption(options, sp->option, "false"), "true")) { continue; } if (sp->flags & SCRIPT_IE) { espRender(conn, "%s<!-- [if lt IE 9]>\n", indent); } path = sjoin("~/", mprGetPathBase(eroute->clientDir), sp->name, minified ? ".min.js" : ".js", NULL); uri = httpUri(conn, path); newline = sp[1].name ? "\r\n" : ""; espRender(conn, "%s<script src='%s' type='text/javascript'></script>%s", indent, uri, newline); if (sp->flags & SCRIPT_IE) { espRender(conn, "%s<![endif]-->\n", indent); } indent = " "; } } }
/* Load a module. Returns 0 if the modules is successfully loaded (may have already been loaded). */ int maLoadModule(MaAppweb *appweb, cchar *name, cchar *libname) { MprModule *module; char entryPoint[MPR_MAX_FNAME]; char *path; if (strcmp(name, "authFilter") == 0 || strcmp(name, "rangeFilter") == 0 || strcmp(name, "uploadFilter") == 0 || strcmp(name, "fileHandler") == 0 || strcmp(name, "dirHandler") == 0) { mprLog(1, "The %s module is now builtin. No need to use LoadModule", name); return 0; } if (libname == 0) { path = sjoin("mod_", name, BLD_SHOBJ, NULL); } else { path = sclone(libname); } if ((module = mprLookupModule(path)) != 0) { mprLog(MPR_CONFIG, "Activating module (Builtin) %s", name); return 0; } mprSprintf(entryPoint, sizeof(entryPoint), "ma%sInit", name); entryPoint[2] = toupper((int) entryPoint[2]); if ((module = mprCreateModule(name, path, entryPoint, MPR->httpService)) == 0) { return 0; } if (mprLoadModule(module) < 0) { return MPR_ERR_CANT_CREATE; } return 0; }
/* 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; }
/* Security checks. Make sure we are staring with a safe environment */ static int checkEnvironment(cchar *program) { #if BIT_UNIX_LIKE app->pathVar = sjoin("PATH=", getenv("PATH"), ":", mprGetAppDir(), NULL); putenv(app->pathVar); #endif return 0; }
/* Start the command to run (stdIn and stdOut are named from the client's perspective) */ PUBLIC int startProcess(MprCmd *cmd) { MprCmdTaskFn entryFn; MprModule *mp; char *entryPoint, *program, *pair; int pri, next; mprLog("info mpr cmd", 4, "Program %s", cmd->program); entryPoint = 0; if (cmd->env) { for (ITERATE_ITEMS(cmd->env, pair, next)) { if (sncmp(pair, "entryPoint=", 11) == 0) { entryPoint = sclone(&pair[11]); } } } program = mprGetPathBase(cmd->program); if (entryPoint == 0) { program = mprTrimPathExt(program); entryPoint = program; } #if ME_CPU_ARCH == MPR_CPU_IX86 || ME_CPU_ARCH == MPR_CPU_IX64 || ME_CPU_ARCH == MPR_CPU_SH /* A leading underscore is required on some architectures */ entryPoint = sjoin("_", entryPoint, NULL); #endif if (mprFindVxSym(sysSymTbl, entryPoint, (char**) (void*) &entryFn) < 0) { if ((mp = mprCreateModule(cmd->program, cmd->program, NULL, NULL)) == 0) { mprLog("error mpr cmd", 0, "Cannot create module"); return MPR_ERR_CANT_CREATE; } if (mprLoadModule(mp) < 0) { mprLog("error mpr cmd", 0, "Cannot load DLL %s, errno %d", program, mprGetOsError()); return MPR_ERR_CANT_READ; } if (mprFindVxSym(sysSymTbl, entryPoint, (char**) (void*) &entryFn) < 0) { mprLog("error mpr cmd", 0, "Cannot find symbol %s, errno %d", entryPoint, mprGetOsError()); return MPR_ERR_CANT_ACCESS; } } taskPriorityGet(taskIdSelf(), &pri); cmd->pid = taskSpawn(entryPoint, pri, VX_FP_TASK | VX_PRIVATE_ENV, ME_STACK_SIZE, (FUNCPTR) cmdTaskEntry, (int) cmd->program, (int) entryFn, (int) cmd, 0, 0, 0, 0, 0, 0, 0); if (cmd->pid < 0) { mprLog("error mpr cmd", 0, "Cannot create task %s, errno %d", entryPoint, mprGetOsError()); return MPR_ERR_CANT_CREATE; } if (semTake(cmd->startCond, MPR_TIMEOUT_START_TASK) != OK) { mprLog("error mpr cmd", 0, "Child %s did not initialize, errno %d", cmd->program, mprGetOsError()); return MPR_ERR_CANT_CREATE; } semDelete(cmd->startCond); cmd->startCond = 0; return 0; }
static void setAppDefaults() { app->appName = mprGetAppName(); app->serviceProgram = sjoin(mprGetAppDir(), "/", BLD_PRODUCT, ".exe", NULL); app->serviceName = sclone(BLD_COMPANY "-" BLD_PRODUCT); app->serviceHome = mprGetNativePath(SERVICE_HOME); app->serviceTitle = sclone(BLD_NAME); app->serviceStopped = 0; }
/* Start the request (and complete it) */ static void startDir(HttpQueue *q) { HttpConn *conn; HttpTx *tx; HttpRx *rx; MprList *list; MprDirEntry *dp; HttpDir *dir; cchar *path; uint nameSize; int next; conn = q->conn; rx = conn->rx; tx = conn->tx; if ((dir = conn->reqData) == 0) { httpError(conn, HTTP_CODE_INTERNAL_SERVER_ERROR, "Cannot get directory listing"); return; } assert(tx->filename); if (!(rx->flags & (HTTP_GET | HTTP_HEAD))) { httpError(conn, HTTP_CODE_BAD_METHOD, "Bad method"); return; } httpSetContentType(conn, "text/html"); httpSetHeaderString(conn, "Cache-Control", "no-cache"); httpSetHeaderString(conn, "Last-Modified", conn->http->currentDate); parseQuery(conn); if ((list = mprGetPathFiles(tx->filename, MPR_PATH_RELATIVE)) == 0) { httpWrite(q, "<h2>Cannot get file list</h2>\r\n"); outputFooter(q); return; } if (dir->pattern) { filterDirList(conn, list); } sortList(conn, list); /* Get max filename size */ nameSize = 0; for (next = 0; (dp = mprGetNextItem(list, &next)) != 0; ) { nameSize = max((int) strlen(dp->name), nameSize); } nameSize = max(nameSize, 22); path = rx->route->prefix ? sjoin(rx->route->prefix, rx->pathInfo, NULL) : rx->pathInfo; outputHeader(q, path, nameSize); for (next = 0; (dp = mprGetNextItem(list, &next)) != 0; ) { outputLine(q, dp, tx->filename, nameSize); } outputFooter(q); httpFinalize(conn); }
/* Set lifespan < 0 to delete the cookie in the client. Set lifespan == 0 for no expiry. WARNING: Some browsers (Chrome, Firefox) do not delete session cookies when you exit the browser. */ PUBLIC void httpSetCookie(HttpConn *conn, cchar *name, cchar *value, cchar *path, cchar *cookieDomain, MprTicks lifespan, int flags) { HttpRx *rx; char *cp, *expiresAtt, *expires, *domainAtt, *domain, *secure, *httponly; rx = conn->rx; if (path == 0) { path = "/"; } domain = (char*) cookieDomain; if (!domain) { domain = sclone(rx->hostHeader); if ((cp = strchr(domain, ':')) != 0) { *cp = '\0'; } if (*domain && domain[strlen(domain) - 1] == '.') { domain[strlen(domain) - 1] = '\0'; } } domainAtt = domain ? "; domain=" : ""; if (domain && !strchr(domain, '.')) { if (smatch(domain, "localhost")) { domainAtt = domain = ""; } else { domain = sjoin(".", domain, NULL); } } if (lifespan) { expiresAtt = "; expires="; expires = mprFormatUniversalTime(MPR_HTTP_DATE, mprGetTime() + lifespan); } else { expires = expiresAtt = ""; } secure = (conn->secure & (flags & HTTP_COOKIE_SECURE)) ? "; secure" : ""; httponly = (flags & HTTP_COOKIE_HTTP) ? "; httponly" : ""; /* Allow multiple cookie headers. Even if the same name. Later definitions take precedence. */ httpAppendHeader(conn, "Set-Cookie", sjoin(name, "=", value, "; path=", path, domainAtt, domain, expiresAtt, expires, secure, httponly, NULL)); httpAppendHeader(conn, "Cache-Control", "no-cache=\"set-cookie\""); }
/* Limited expansion of route names. Support ~ and ${app} at the start of the route name */ static cchar *expandRouteName(HttpConn *conn, cchar *routeName) { HttpRoute *route; route = conn->rx->route; if (routeName[0] == '~') { return sjoin(httpGetRouteTop(conn), &routeName[1], NULL); } if (sstarts(routeName, "${app}")) { return sjoin(httpGetRouteTop(conn), &routeName[6], NULL); } #if DEPRECATED || 1 // DEPRECATED in version 6 if (routeName[0] == '|') { assert(routeName[0] != '|'); return sjoin(route->prefix, &routeName[1], NULL); } #endif return routeName; }
void mprSetModuleSearchPath(char *searchPath) { MprModuleService *ms; ms = MPR->moduleService; if (searchPath == 0) { ms->searchPath = sjoin(mprGetAppDir(), MPR_SEARCH_SEP, mprGetAppDir(), MPR_SEARCH_SEP, BIT_BIN_PREFIX, NULL); } else { ms->searchPath = sclone(searchPath); } }
/* Make the version a full three version numbers by adding ".0" */ static char *completeVersion(cchar *version, cchar *fill) { char *pre, *result; int count; if (!version || smatch(version, "*")) { version = fill; } count = partCount(version); result = sclone(version); if ((pre = schr(result, '-')) != 0) { *pre++ = '\0'; } while (count++ < 3) { result = sjoin(result, ".", fill, NULL); } if (pre) { result = sjoin(result, "-", pre, NULL); } return result; }
/* Security checks. Make sure we are staring with a safe environment */ static int checkEnvironment(cchar *program) { #if ME_UNIX_LIKE char *home; home = mprGetCurrentPath(); if (unixSecurityChecks(program, home) < 0) { return -1; } app->pathVar = sjoin("PATH=", getenv("PATH"), ":", mprGetAppDir(), NULL); putenv(app->pathVar); #endif return 0; }
/* Map options to an attribute string. Remove all internal control specific options and transparently handle URI link options. WARNING: this returns a non-cloned reference and relies on no GC yield until the returned value is used or cloned. This is done as an optimization to reduce memeory allocations. */ static cchar *map(HttpConn *conn, MprHash *options) { Esp *esp; EspReq *req; MprHash *params; MprKey *kp; MprBuf *buf; cchar *value; char *pstr; if (options == 0 || mprGetHashLength(options) == 0) { return MPR->emptyString; } req = conn->data; if (httpGetOption(options, EDATA("refresh"), 0) && !httpGetOption(options, "id", 0)) { httpAddOption(options, "id", sfmt("id_%d", req->lastDomID++)); } esp = MPR->espService; buf = mprCreateBuf(-1, -1); for (kp = 0; (kp = mprGetNextKey(options, kp)) != 0; ) { if (kp->type != MPR_JSON_OBJ && kp->type != MPR_JSON_ARRAY && !mprLookupKey(esp->internalOptions, kp->key)) { mprPutCharToBuf(buf, ' '); value = kp->data; /* Support link template resolution for these options */ if (smatch(kp->key, EDATA("click")) || smatch(kp->key, EDATA("remote")) || smatch(kp->key, EDATA("refresh"))) { value = httpUriEx(conn, value, options); if ((params = httpGetOptionHash(options, "params")) != 0) { pstr = (char*) ""; for (kp = 0; (kp = mprGetNextKey(params, kp)) != 0; ) { pstr = sjoin(pstr, mprUriEncode(kp->key, MPR_ENCODE_URI_COMPONENT), "=", mprUriEncode(kp->data, MPR_ENCODE_URI_COMPONENT), "&", NULL); } if (pstr[0]) { /* Trim last "&" */ pstr[strlen(pstr) - 1] = '\0'; } mprPutToBuf(buf, "%s-params='%s", params); } } mprPutStringToBuf(buf, kp->key); mprPutStringToBuf(buf, "='"); mprPutStringToBuf(buf, value); mprPutCharToBuf(buf, '\''); } } mprAddNullToBuf(buf); return mprGetBufStart(buf); }
/* Set the Uri extension static function set extension(ext: String?): Void */ static EjsObj *uri_set_extension(Ejs *ejs, EjsUri *up, int argc, EjsObj **argv) { HttpUri *uri; uri = up->uri; if (argv[0] == ESV(null)) { uri->ext = 0; uri->path = mprTrimPathExt(uri->path); } else { uri->ext = ejsToMulti(ejs, argv[0]); uri->path = sjoin(mprTrimPathExt(uri->path), uri->ext, NULL); } return 0; }
PUBLIC HttpUri *httpJoinUriPath(HttpUri *result, HttpUri *base, HttpUri *other) { char *sep; if (other->path) { if (other->path[0] == '/') { result->path = sclone(other->path); } else { sep = ((base->path[0] == '\0' || base->path[slen(base->path) - 1] == '/') || (other->path[0] == '\0' || other->path[0] == '/')) ? "" : "/"; result->path = sjoin(base->path, sep, other->path, NULL); } } return result; }
static void copyInner(HttpConn *conn, cchar **envv, int index, cchar *key, cchar *value, cchar *prefix) { char *cp; if (prefix) { cp = sjoin(prefix, key, "=", value, NULL); } else { cp = sjoin(key, "=", value, NULL); } if (conn->rx->route->flags & HTTP_ROUTE_ENV_ESCAPE) { /* This will escape: &;`'\"|*?~<>^()[]{}$\\\n and also on windows \r% */ cp = mprEscapeCmd(cp, 0); } envv[index] = cp; for (; *cp != '='; cp++) { if (*cp == '-') { *cp = '_'; } else { *cp = toupper((uchar) *cp); } } }
PUBLIC void espIcon(HttpConn *conn, cchar *uri, cchar *optionString) { MprHash *options; EspRoute *eroute; eroute = conn->rx->route->eroute; options = httpGetOptions(optionString); if (uri == 0) { /* Suppress favicon */ uri = "data:image/x-icon;,"; } else if (*uri == 0) { uri = sjoin("~/", mprGetPathBase(eroute->clientDir), "/images/favicon.ico", NULL); } espRender(conn, "<link href='%s' rel='shortcut icon'%s />", httpUri(conn, uri), map(conn, options)); }
static void go_dir(int *cs, char *root, char const *cur, char *dir) { char *t[2]; t[0] = sjoin(cur, "/"); t[1] = sjoin(t[0], dir); free(t[0]); if (!chdir(t[1])) { if (!scmp(root, get_cwd(), slen(root))) sc(cs, 0); else { if (chdir(root) == -1) free(t[1]), sc(cs, -2), error(ROOT_DIR_DENIED); else sc(cs, -1); } } else sc(cs, -3), err_msg("No such directory !\n"); free(t[1]); }
/* Join extension function joinExt(ext: String): Uri */ static EjsUri *uri_joinExt(Ejs *ejs, EjsUri *up, int argc, EjsObj **argv) { EjsUri *np; HttpUri *nuri; char *ext; np = cloneUri(ejs, up, 1); nuri = np->uri; ext = ejsToMulti(ejs, argv[0]); if (ext && *ext == '.') { ext++; } nuri->ext = ext; nuri->path = sjoin(mprTrimPathExt(nuri->path), ".", nuri->ext, NULL); return np; }
/* Return true if the shared library in "file" can be found. Return the actual path in *path. The filename may not have a shared library extension which is typical so calling code can be cross platform. */ static char *probe(cchar *filename) { char *path; assert(filename && *filename); if (mprPathExists(filename, R_OK)) { return sclone(filename); } if (strstr(filename, ME_SHOBJ) == 0) { path = sjoin(filename, ME_SHOBJ, NULL); if (mprPathExists(path, R_OK)) { return path; } } return 0; }
PUBLIC void espSetFeedbackv(HttpConn *conn, cchar *kind, cchar *fmt, va_list args) { EspReq *req; cchar *prior, *msg; req = conn->data; msg = sfmtv(fmt, args); if (req->feedback == 0) { req->feedback = mprCreateHash(0, MPR_HASH_STABLE); } if ((prior = mprLookupKey(req->feedback, kind)) != 0) { mprAddKey(req->feedback, kind, sjoin(prior, "\n", msg, NULL)); } else { mprAddKey(req->feedback, kind, sclone(msg)); } }
/* Prepare form data using json encoding. The objects are json encoded then URI encoded to be safe. */ static void prepForm(Ejs *ejs, EjsHttp *hp, char *prefix, EjsObj *data) { EjsName qname; EjsObj *vp; EjsString *value; cchar *key, *sep; char *encodedKey, *encodedValue, *newPrefix, *newKey; int i, count; jdata = ejsToJSON(ejs, data, NULL); if (prefix) { newKey = sjoin(prefix, ".", key, NULL); encodedKey = mprUriEncode(newKey, MPR_ENCODE_URI_COMPONENT); } else { encodedKey = mprUriEncode(key, MPR_ENCODE_URI_COMPONENT); } encodedValue = mprUriEncode(value->value, MPR_ENCODE_URI_COMPONENT); mprPutToBuf(hp->requestContent, "%s%s=%s", sep, encodedKey, encodedValue); }