static int parseCgi(MaHttp *http, cchar *key, char *value, MaConfigState *state) { MaLocation *location; MaServer *server; MaHost *host; MaAlias *alias; MaDir *dir, *parent; char *program, *mimeType, *prefix, *path; host = state->host; server = state->server; location = state->location; if (mprStrcmpAnyCase(key, "Action") == 0) { if (maSplitConfigValue(http, &mimeType, &program, value, 1) < 0) { return MPR_ERR_BAD_SYNTAX; } maSetMimeActionProgram(host, mimeType, program); return 1; } else if (mprStrcmpAnyCase(key, "ScriptAlias") == 0) { if (maSplitConfigValue(server, &prefix, &path, value, 1) < 0 || path == 0 || prefix == 0) { return MPR_ERR_BAD_SYNTAX; } /* Create an alias and location with a cgiHandler and pathInfo processing */ path = maMakePath(host, path); dir = maLookupDir(host, path); if (maLookupDir(host, path) == 0) { parent = mprGetFirstItem(host->dirs); dir = maCreateDir(host, path, parent); } alias = maCreateAlias(host, prefix, path, 0); mprLog(server, 4, "ScriptAlias \"%s\" for \"%s\"", prefix, path); mprFree(path); maInsertAlias(host, alias); if ((location = maLookupLocation(host, prefix)) == 0) { location = maCreateLocation(host, state->location); maSetLocationAuth(location, state->dir->auth); maSetLocationPrefix(location, prefix); maAddLocation(host, location); } else { maSetLocationPrefix(location, prefix); } maSetHandler(http, host, location, "cgiHandler"); return 1; } return 0; }
/* * Find an exact dir match. May be called with raw file names. ie. D:\myDir */ MaDir *maLookupDir(MaHost *host, cchar *path) { MaDir *dir; char *absPath, buf[MPR_MAX_FNAME]; int next, len; /* * Cannonicalize and ensure path has a trailing "/" */ absPath = mprGetAbsFilename(host, path); mprStrcpy(buf, sizeof(buf), absPath); len = (int) strlen(buf); if (buf[len - 1] != '/') { buf[len] = '/'; buf[++len] = '\0'; } for (next = 0; (dir = mprGetNextItem(host->dirs, &next)) != 0; ) { if (dir->path != 0) { #if WIN if (mprStrcmpAnyCase(dir->path, buf) == 0) #else if (strcmp(dir->path, buf) == 0) #endif return dir; } } return 0; }
void maSecureHost(MaHost *host, struct MprSsl *ssl) { MaListen *lp; cchar *hostIp; char *ipAddr; int port, next; host->secure = 1; hostIp = host->ipAddrPort; if (mprStrcmpAnyCase(hostIp, "_default_") == 0) { hostIp = (char*) "*:*"; } mprParseIp(host, hostIp, &ipAddr, &port, -1); for (next = 0; (lp = mprGetNextItem(host->server->listens, &next)) != 0; ) { if (port > 0 && port != lp->port) { continue; } if (*lp->ipAddr && ipAddr && ipAddr[0] != '*' && strcmp(ipAddr, lp->ipAddr) != 0) { continue; } #if BLD_FEATURE_SSL if (host->secure) { if (host->flags & MA_HOST_NAMED_VHOST) { mprError(host, "SSL does not support named virtual hosts"); return; } lp->ssl = ssl; } #endif } }
static int parseSimple(MaHttp *http, cchar *key, char *value, MaConfigState *state) { if (mprStrcmpAnyCase(key, "CustomConfigKey") == 0) { /* * Do something with value. Return true to indicate we understood and accepted the directive. */ return 1; } return 0; }
/* * Determine the registry hive by the first portion of the path. Return * a pointer to the rest of key path after the hive portion. */ static cchar *getHive(cchar *keyPath, HKEY *hive) { char key[MPR_MAX_STRING], *cp; int len; mprAssert(keyPath && *keyPath); *hive = 0; mprStrcpy(key, sizeof(key), keyPath); key[sizeof(key) - 1] = '\0'; if (cp = strchr(key, '\\')) { *cp++ = '\0'; } if (cp == 0 || *cp == '\0') { return 0; } if (!mprStrcmpAnyCase(key, "HKEY_LOCAL_MACHINE")) { *hive = HKEY_LOCAL_MACHINE; } else if (!mprStrcmpAnyCase(key, "HKEY_CURRENT_USER")) { *hive = HKEY_CURRENT_USER; } else if (!mprStrcmpAnyCase(key, "HKEY_USERS")) { *hive = HKEY_USERS; } else if (!mprStrcmpAnyCase(key, "HKEY_CLASSES_ROOT")) { *hive = HKEY_CLASSES_ROOT; } else { return 0; } if (*hive == 0) { return 0; } len = (int) strlen(key) + 1; return keyPath + len; }
int main(int argc, char **argv) { Mpr *mpr; EcCompiler *cp; EjsService *vmService; Ejs *ejs; MprList *useModules, *files; cchar *cmd, *className, *methodName; char *argp, *searchPath, *modules, *name, *tok, *extraFiles, *spec; int nextArg, err, ejsFlags, ecFlags, stats, run, merge, bind, noout, debug, optimizeLevel, nobind, warnLevel; int compilerMode, lang; /* * Create the Embedthis Portable Runtime (MPR) and setup a memory failure handler */ mpr = mprCreate(argc, argv, ejsMemoryFailure); mprSetAppName(mpr, argv[0], 0, 0); if (mprStart(mpr, 0) < 0) { mprError(mpr, "Can't start mpr services"); return EJS_ERR; } err = 0; className = 0; cmd = 0; methodName = 0; searchPath = 0; stats = 0; run = 1; merge = 0; bind = 1; nobind = 0; noout = 1; debug = 1; warnLevel = 1; optimizeLevel = 9; compilerMode = PRAGMA_MODE_STANDARD; lang = BLD_FEATURE_EJS_LANG; useModules = mprCreateList(mpr); files = mprCreateList(mpr); ejsFlags = EJS_FLAG_COMPILER; for (nextArg = 1; nextArg < argc; nextArg++) { argp = argv[nextArg]; if (*argp != '-') { break; } if (strcmp(argp, "--bind") == 0) { /* Ignore. Not required and only here for compatibility with ec */ } else if (strcmp(argp, "--class") == 0) { if (nextArg >= argc) { err++; } else { className = argv[++nextArg]; } } else if (strcmp(argp, "--cmd") == 0 || strcmp(argp, "-c") == 0) { if (nextArg >= argc) { err++; } else { cmd = argv[++nextArg]; } } else if (strcmp(argp, "--debug") == 0) { debug = 1; } else if (strcmp(argp, "--lang") == 0) { if (nextArg >= argc) { err++; } else { spec = argv[++nextArg]; if (mprStrcmpAnyCase(spec, "ecma") == 0) { lang = EJS_SPEC_ECMA; } else if (mprStrcmpAnyCase(spec, "plus") == 0) { lang = EJS_SPEC_PLUS; } else if (mprStrcmpAnyCase(spec, "fixed") == 0) { lang = EJS_SPEC_FIXED; } } } else if (strcmp(argp, "--files") == 0 || strcmp(argp, "-f") == 0) { if (nextArg >= argc) { err++; } else { extraFiles = mprStrdup(mpr, argv[++nextArg]); name = mprStrTok(extraFiles, " \t", &tok); while (name != NULL) { mprAddItem(files, name); name = mprStrTok(NULL, " \t", &tok); } } } else if (strcmp(argp, "--log") == 0) { if (nextArg >= argc) { err++; } else { ejsStartLogging(mpr, argv[++nextArg]); } } else if (strcmp(argp, "--method") == 0) { if (nextArg >= argc) { err++; } else { methodName = argv[++nextArg]; } } else if (strcmp(argp, "--nobind") == 0) { /* * This is a hidden switch just for the compiler developers */ nobind = 1; bind = 0; } else if (strcmp(argp, "--nodebug") == 0) { debug = 0; } else if (strcmp(argp, "--optimize") == 0) { if (nextArg >= argc) { err++; } else { optimizeLevel = atoi(argv[++nextArg]); } } else if (strcmp(argp, "--searchpath") == 0) { if (nextArg >= argc) { err++; } else { searchPath = argv[++nextArg]; } } else if (strcmp(argp, "--standard") == 0) { compilerMode = PRAGMA_MODE_STANDARD; } else if (strcmp(argp, "--stats") == 0) { stats = 1; } else if (strcmp(argp, "--strict") == 0) { compilerMode = PRAGMA_MODE_STRICT; } else if (strcmp(argp, "--use") == 0) { if (nextArg >= argc) { err++; } else { modules = mprStrdup(mpr, argv[++nextArg]); name = mprStrTok(modules, " \t", &tok); while (name != NULL) { mprAddItem(useModules, name); name = mprStrTok(NULL, " \t", &tok); } } } else if (strcmp(argp, "--version") == 0 || strcmp(argp, "-V") == 0) { mprErrorPrintf(mpr, "%s %s\n" "Copyright (C) Embedthis Software 2003-2009\n" "Copyright (C) Michael O'Brien 2003-2009\n", BLD_NAME, BLD_VERSION); exit(0); } else if (strcmp(argp, "--warn") == 0) { if (nextArg >= argc) { err++; } else { warnLevel = atoi(argv[++nextArg]); } } else { err++; break; } } if (err) { /* * If --method or --class is specified, then the named class.method will be run (method defaults to "main", class * defaults to first class with a "main"). * * Examples: * ejs * ejs script.es arg1 arg2 arg3 * ejs --class "Customer" --method "start" --files "script1.es script2.es" main.es */ mprErrorPrintf(mpr, "Usage: %s [options] script.es [arguments] ...\n" " Ejscript shell program options:\n" " --class className # Name of class containing method to run\n" " --cmd ejscriptCode # Literal ejscript statements to execute\n" " --debug # Include symbolic debugging information in output\n" " --lang # Language compliance (ecma|plus|fixed)\n" " --files \"files..\" # Extra source to compile\n" " --log logSpec # Internal compiler diagnostics logging\n" " --method methodName # Name of method to run. Defaults to main\n" " --nodebug # Omit symbolic debugging information in output\n" " --optimize level # Set the optimization level (0-9 default is 9)\n" " --searchpath ejsPath # Module search path\n" " --standard # Default compilation mode to standard (default)\n" " --stats # Print stats on exit\n" " --strict # Default compilation mode to strict\n" " --use 'module, ...' # List of modules to pre-load\n" " --version # Emit the compiler version information\n" " --warn level # Set the warning message level (0-9 default is 0)\n\n", mpr->name); return -1; } vmService = ejsCreateService(mpr); if (vmService == 0) { return MPR_ERR_NO_MEMORY; } if (searchPath) { ejsSetSearchPath(vmService, searchPath); } ejs = ejsCreate(vmService, 0, ejsFlags); if (ejs == 0) { return MPR_ERR_NO_MEMORY; } ecFlags = 0; ecFlags |= (run) ? EC_FLAGS_RUN: 0; ecFlags |= (merge) ? EC_FLAGS_MERGE: 0; ecFlags |= (bind) ? EC_FLAGS_BIND_GLOBALS: 0; ecFlags |= (nobind) ? EC_FLAGS_NO_BIND: 0; ecFlags |= (noout) ? EC_FLAGS_NO_OUT: 0; ecFlags |= (debug) ? EC_FLAGS_DEBUG: 0; cp = ecCreateCompiler(ejs, ecFlags, lang); if (cp == 0) { return MPR_ERR_NO_MEMORY; } ecSetOptimizeLevel(cp, optimizeLevel); ecSetWarnLevel(cp, warnLevel); ecSetDefaultMode(cp, compilerMode); if (preloadModules(cp, useModules) < 0) { return EJS_ERR; } if (cmd) { if (interpretCommands(cp, cmd) < 0) { err++; } } else if (nextArg < argc) { name = argv[nextArg]; mprAddItem(files, argv[nextArg]); if (interpretFiles(cp, files, argc - nextArg, &argv[nextArg], className, methodName) < 0) { err++; } } else { /* * No args - run as an interactive shell */ if (interpretCommands(cp, NULL) < 0) { err++; } } #if BLD_DEBUG if (stats) { mprSetLogLevel(ejs, 1); ejsPrintAllocReport(ejs); } #endif mprFree(mpr); return err; }
/* * Parse the request headers. Return true if the header parsed. */ static bool parseHeaders(MaConn *conn, MaPacket *packet) { MaHostAddress *address; MaRequest *req; MaHost *host, *hp; MaLimits *limits; MprBuf *content; char keyBuf[MPR_MAX_STRING]; char *key, *value, *cp, *tok; int count, keepAlive; req = conn->request; host = req->host; content = packet->content; conn->request->headerPacket = packet; limits = &conn->http->limits; keepAlive = 0; strcpy(keyBuf, "HTTP_"); mprAssert(strstr((char*) content->start, "\r\n")); for (count = 0; content->start[0] != '\r' && !conn->connectionFailed; count++) { if (count >= limits->maxNumHeaders) { maFailConnection(conn, MPR_HTTP_CODE_BAD_REQUEST, "Too many headers"); return 0; } if ((key = getToken(conn, ":")) == 0 || *key == '\0') { maFailConnection(conn, MPR_HTTP_CODE_BAD_REQUEST, "Bad header format"); return 0; } value = getToken(conn, "\r\n"); while (isspace((int) *value)) { value++; } if (conn->requestFailed) { continue; } mprStrUpper(key); for (cp = key; *cp; cp++) { if (*cp == '-') { *cp = '_'; } } mprLog(req, 8, "Key %s, value %s", key, value); if (strspn(key, "%<>/\\") > 0) { maFailConnection(conn, MPR_HTTP_CODE_BAD_REQUEST, "Bad header key value"); continue; } /* * Define the header with a "HTTP_" prefix */ mprStrcpy(&keyBuf[5], sizeof(keyBuf) - 5, key); mprAddDuplicateHash(req->headers, keyBuf, value); switch (key[0]) { case 'A': if (strcmp(key, "AUTHORIZATION") == 0) { value = mprStrdup(req, value); req->authType = mprStrTok(value, " \t", &tok); req->authDetails = tok; } else if (strcmp(key, "ACCEPT_CHARSET") == 0) { req->acceptCharset = value; } else if (strcmp(key, "ACCEPT") == 0) { req->accept = value; } else if (strcmp(key, "ACCEPT_ENCODING") == 0) { req->acceptEncoding = value; } break; case 'C': if (strcmp(key, "CONTENT_LENGTH") == 0) { if (req->length >= 0) { maFailConnection(conn, MPR_HTTP_CODE_BAD_REQUEST, "Mulitple content length headers"); continue; } req->length = mprAtoi(value, 10); if (req->length < 0) { maFailConnection(conn, MPR_HTTP_CODE_BAD_REQUEST, "Bad content length"); continue; } if (req->length >= host->limits->maxBody) { maFailConnection(conn, MPR_HTTP_CODE_REQUEST_TOO_LARGE, "Request content length %Ld is too big. Limit %Ld", req->length, host->limits->maxBody); continue; } mprAssert(req->length >= 0); req->remainingContent = req->length; req->contentLengthStr = value; } else if (strcmp(key, "CONTENT_RANGE") == 0) { /* * This headers specifies the range of any posted body data * Format is: Content-Range: bytes n1-n2/length * Where n1 is first byte pos and n2 is last byte pos */ char *sp; int start, end, size; start = end = size = -1; sp = value; while (*sp && !isdigit((int) *sp)) { sp++; } if (*sp) { start = (int) mprAtoi(sp, 10); if ((sp = strchr(sp, '-')) != 0) { end = (int) mprAtoi(++sp, 10); } if ((sp = strchr(sp, '/')) != 0) { /* * Note this is not the content length transmitted, but the original size of the input of which * the client is transmitting only a portion. */ size = (int) mprAtoi(++sp, 10); } } if (start < 0 || end < 0 || size < 0 || end <= start) { maFailRequest(conn, MPR_HTTP_CODE_RANGE_NOT_SATISFIABLE, "Bad content range"); continue; } req->inputRange = maCreateRange(conn, start, end); } else if (strcmp(key, "CONTENT_TYPE") == 0) { req->mimeType = value; req->form = strstr(value, "application/x-www-form-urlencoded") != 0; } else if (strcmp(key, "COOKIE") == 0) { if (req->cookie && *req->cookie) { req->cookie = mprStrcat(req, -1, req->cookie, "; ", value, NULL); } else { req->cookie = value; } } else if (strcmp(key, "CONNECTION") == 0) { req->connection = value; if (mprStrcmpAnyCase(value, "KEEP-ALIVE") == 0) { keepAlive++; } else if (mprStrcmpAnyCase(value, "CLOSE") == 0) { conn->keepAliveCount = 0; } if (!host->keepAlive) { conn->keepAliveCount = 0; } } break; case 'F': req->forwarded = value; break; case 'H': if (strcmp(key, "HOST") == 0) { req->hostName = value; address = conn->address; if (maIsNamedVirtualHostAddress(address)) { hp = maLookupVirtualHost(address, value); if (hp == 0) { maFailRequest(conn, 404, "No host to serve request. Searching for %s", value); mprLog(conn, 1, "Can't find virtual host %s", value); continue; } req->host = hp; /* * Reassign this request to a new host */ maRemoveConn(host, conn); host = hp; conn->host = hp; maAddConn(hp, conn); } } break; case 'I': if ((strcmp(key, "IF_MODIFIED_SINCE") == 0) || (strcmp(key, "IF_UNMODIFIED_SINCE") == 0)) { MprTime newDate = 0; char *cp; bool ifModified = (key[3] == 'M'); if ((cp = strchr(value, ';')) != 0) { *cp = '\0'; } if (mprParseTime(conn, &newDate, value, MPR_UTC_TIMEZONE, NULL) < 0) { mprAssert(0); break; } if (newDate) { setIfModifiedDate(conn, newDate, ifModified); req->flags |= MA_REQ_IF_MODIFIED; } } else if ((strcmp(key, "IF_MATCH") == 0) || (strcmp(key, "IF_NONE_MATCH") == 0)) { char *word, *tok; bool ifMatch = key[3] == 'M'; if ((tok = strchr(value, ';')) != 0) { *tok = '\0'; } req->ifMatch = ifMatch; req->flags |= MA_REQ_IF_MODIFIED; value = mprStrdup(conn, value); word = mprStrTok(value, " ,", &tok); while (word) { addMatchEtag(conn, word); word = mprStrTok(0, " ,", &tok); } } else if (strcmp(key, "IF_RANGE") == 0) { char *word, *tok; if ((tok = strchr(value, ';')) != 0) { *tok = '\0'; } req->ifMatch = 1; req->flags |= MA_REQ_IF_MODIFIED; value = mprStrdup(conn, value); word = mprStrTok(value, " ,", &tok); while (word) { addMatchEtag(conn, word); word = mprStrTok(0, " ,", &tok); } } break; case 'P': if (strcmp(key, "PRAGMA") == 0) { req->pragma = value; } break; case 'R': if (strcmp(key, "RANGE") == 0) { if (!parseRange(conn, value)) { maFailRequest(conn, MPR_HTTP_CODE_RANGE_NOT_SATISFIABLE, "Bad range"); } } else if (strcmp(key, "REFERER") == 0) { /* NOTE: yes the header is misspelt in the spec */ req->referer = value; } break; case 'T': if (strcmp(key, "TRANSFER_ENCODING") == 0) { mprStrLower(value); if (strcmp(value, "chunked") == 0) { req->flags |= MA_REQ_CHUNKED; /* * This will be revised by the chunk filter as chunks are processed and will be set to zero when the * last chunk has been received. */ req->remainingContent = MAXINT; } } break; #if BLD_DEBUG case 'X': if (strcmp(key, "X_APPWEB_CHUNK_SIZE") == 0) { mprStrUpper(value); conn->response->chunkSize = atoi(value); if (conn->response->chunkSize <= 0) { conn->response->chunkSize = 0; } else if (conn->response->chunkSize > conn->http->limits.maxChunkSize) { conn->response->chunkSize = conn->http->limits.maxChunkSize; } } break; #endif case 'U': if (strcmp(key, "USER_AGENT") == 0) { req->userAgent = value; } break; } } if (conn->protocol == 0 && !keepAlive) { conn->keepAliveCount = 0; } if (!(req->flags & MA_REQ_CHUNKED)) { /* * Step over "\r\n" after headers. As an optimization, don't do this if chunked so chunking can parse a single * chunk delimiter of "\r\nSIZE ...\r\n" */ mprAdjustBufStart(content, 2); } mprLog(conn, 3, "Select host \"%s\"", conn->host->name); if (maSetRequestUri(conn, req->url, "") < 0) { maFailConnection(conn, MPR_HTTP_CODE_BAD_REQUEST, "Bad URI format"); return 0; } if (conn->host->secure) { req->parsedUri->scheme = mprStrdup(req, "https"); } req->parsedUri->port = conn->sock->port; req->parsedUri->host = req->hostName ? req->hostName : conn->host->name; return 1; }
/* * Create the host addresses for a host. Called for hosts or for NameVirtualHost directives (host == 0). */ int maCreateHostAddresses(MaServer *server, MaHost *host, cchar *configValue) { MaListen *listen; MaHostAddress *address; char *ipAddrPort, *ipAddr, *value, *tok; char addrBuf[MPR_MAX_IP_ADDR_PORT]; int next, port; address = 0; value = mprStrdup(server, configValue); ipAddrPort = mprStrTok(value, " \t", &tok); while (ipAddrPort) { if (mprStrcmpAnyCase(ipAddrPort, "_default_") == 0) { mprAssert(0); ipAddrPort = "*:*"; } if (mprParseIp(server, ipAddrPort, &ipAddr, &port, -1) < 0) { mprError(server, "Can't parse ipAddr %s", ipAddrPort); continue; } mprAssert(ipAddr && *ipAddr); if (ipAddr[0] == '*') { ipAddr = mprStrdup(server, ""); } /* * For each listening endpiont, */ for (next = 0; (listen = mprGetNextItem(server->listens, &next)) != 0; ) { if (port > 0 && port != listen->port) { continue; } if (listen->ipAddr[0] != '\0' && ipAddr[0] != '\0' && strcmp(ipAddr, listen->ipAddr) != 0) { continue; } /* * Find the matching host address or create a new one */ if ((address = maLookupHostAddress(server, listen->ipAddr, listen->port)) == 0) { address = maCreateHostAddress(server, listen->ipAddr, listen->port); mprAddItem(server->hostAddresses, address); } /* * If a host is specified */ if (host == 0) { maSetNamedVirtualHostAddress(address); } else { maInsertVirtualHost(address, host); if (listen->ipAddr[0] != '\0') { mprSprintf(addrBuf, sizeof(addrBuf), "%s:%d", listen->ipAddr, listen->port); } else { mprSprintf(addrBuf, sizeof(addrBuf), "%s:%d", ipAddr, listen->port); } maSetHostName(host, addrBuf); } } mprFree(ipAddr); ipAddrPort = mprStrTok(0, " \t", &tok); } if (host) { if (address == 0) { mprError(server, "No valid IP address for host %s", host->name); mprFree(value); return MPR_ERR_CANT_INITIALIZE; } if (maIsNamedVirtualHostAddress(address)) { maSetNamedVirtualHost(host); } } mprFree(value); return 0; }
static int parseDir(MaHttp *http, cchar *key, char *value, MaConfigState *state) { MaStage *handler; Dir *dir; char *name, *extensions, *option, *nextTok, *junk; handler = maLookupStage(http, "dirHandler"); dir = handler->stageData; mprAssert(dir); if (mprStrcmpAnyCase(key, "AddIcon") == 0) { /* AddIcon file ext ext ext */ /* Not yet supported */ name = mprStrTok(value, " \t", &extensions); parseWords(dir->extList, extensions); return 1; } else if (mprStrcmpAnyCase(key, "DefaultIcon") == 0) { /* DefaultIcon file */ /* Not yet supported */ dir->defaultIcon = mprStrTok(value, " \t", &junk); return 1; } else if (mprStrcmpAnyCase(key, "IndexOrder") == 0) { /* IndexOrder ascending|descending name|date|size */ mprFree(dir->sortField); dir->sortField = 0; option = mprStrTok(value, " \t", &dir->sortField); if (mprStrcmpAnyCase(option, "ascending") == 0) { dir->sortOrder = 1; } else { dir->sortOrder = -1; } if (dir->sortField) { dir->sortField = mprStrdup(dir, dir->sortField); } return 1; } else if (mprStrcmpAnyCase(key, "IndexIgnore") == 0) { /* IndexIgnore pat ... */ /* Not yet supported */ parseWords(dir->ignoreList, value); return 1; } else if (mprStrcmpAnyCase(key, "IndexOptions") == 0) { /* IndexOptions FancyIndexing|FoldersFirst ... (set of options) */ option = mprStrTok(value, " \t", &nextTok); while (option) { if (mprStrcmpAnyCase(option, "FancyIndexing") == 0) { dir->fancyIndexing = 1; } else if (mprStrcmpAnyCase(option, "HTMLTable") == 0) { dir->fancyIndexing = 2; } else if (mprStrcmpAnyCase(option, "FoldersFirst") == 0) { dir->foldersFirst = 1; } option = mprStrTok(nextTok, " \t", &nextTok); } return 1; } else if (mprStrcmpAnyCase(key, "Options") == 0) { /* Options Indexes */ option = mprStrTok(value, " \t", &nextTok); while (option) { if (mprStrcmpAnyCase(option, "Indexes") == 0) { dir->enabled = 1; } option = mprStrTok(nextTok, " \t", &nextTok); } return 1; } return 0; }
static void sortList(MaConn *conn, MprList *list) { MaRequest *req; MaResponse *resp; MprDirEntry *tmp, **items; Dir *dir; int count, i, j, rc; req = conn->request; resp = conn->response; dir = resp->handler->stageData; if (dir->sortField == 0) { return; } count = mprGetListCount(list); items = (MprDirEntry**) list->items; if (mprStrcmpAnyCase(dir->sortField, "Name") == 0) { for (i = 1; i < count; i++) { for (j = 0; j < i; j++) { rc = strcmp(items[i]->name, items[j]->name); if (dir->foldersFirst) { if (items[i]->isDir && !items[j]->isDir) { rc = -dir->sortOrder; } else if (items[j]->isDir && !items[i]->isDir) { rc = dir->sortOrder; } } rc *= dir->sortOrder; if (rc < 0) { tmp = items[i]; items[i] = items[j]; items[j] = tmp; } } } } else if (mprStrcmpAnyCase(dir->sortField, "Size") == 0) { for (i = 1; i < count; i++) { for (j = 0; j < i; j++) { rc = (items[i]->size < items[j]->size) ? -1 : 1; if (dir->foldersFirst) { if (items[i]->isDir && !items[j]->isDir) { rc = -dir->sortOrder; } else if (items[j]->isDir && !items[i]->isDir) { rc = dir->sortOrder; } } rc *= dir->sortOrder; if (rc < 0) { tmp = items[i]; items[i] = items[j]; items[j] = tmp; } } } } else if (mprStrcmpAnyCase(dir->sortField, "Date") == 0) { for (i = 1; i < count; i++) { for (j = 0; j < i; j++) { rc = (items[i]->lastModified < items[j]->lastModified) ? -1: 1; if (dir->foldersFirst) { if (items[i]->isDir && !items[j]->isDir) { rc = -dir->sortOrder; } else if (items[j]->isDir && !items[i]->isDir) { rc = dir->sortOrder; } } rc *= dir->sortOrder; if (rc < 0) { tmp = items[i]; items[i] = items[j]; items[j] = tmp; } } } } }
MAIN(ejscMain, int argc, char **argv) #endif { Mpr *mpr; Ejs *ejs; EcCompiler *cp; EjsService *vmService; MprList *useModules; char *argp, *searchPath, *outputFile, *certFile, *name, *tok, *modules, *spec; int nextArg, err, ejsFlags, ecFlags, bind, debug, doc, empty, merge; int warnLevel, noout, parseOnly, tabWidth, optimizeLevel, compilerMode, lang; /* * Create the Embedthis Portable Runtime (MPR) and setup a memory failure handler */ mpr = mprCreate(argc, argv, ejsMemoryFailure); mprSetAppName(mpr, argv[0], 0, 0); if (mprStart(mpr, 0) < 0) { mprError(mpr, "Can't start mpr services"); return EJS_ERR; } err = 0; searchPath = 0; compilerMode = PRAGMA_MODE_STANDARD; certFile = 0; ecFlags = 0; bind = 0; debug = 0; doc = 0; empty = 0; merge = 0; noout = 0; parseOnly = 0; tabWidth = 4; warnLevel = 1; outputFile = 0; optimizeLevel = 9; lang = BLD_FEATURE_EJS_LANG; useModules = mprCreateList(mpr); for (nextArg = 1; nextArg < argc; nextArg++) { argp = argv[nextArg]; if (*argp != '-') { break; } if (strcmp(argp, "--bind") == 0) { bind = 1; } else if (strcmp(argp, "--debug") == 0) { debug = 1; } else if (strcmp(argp, "--doc") == 0) { doc = 1; } else if (strcmp(argp, "--lang") == 0) { if (nextArg >= argc) { err++; } else { spec = argv[++nextArg]; if (mprStrcmpAnyCase(spec, "ecma") == 0) { lang = EJS_SPEC_ECMA; } else if (mprStrcmpAnyCase(spec, "plus") == 0) { lang = EJS_SPEC_PLUS; } else if (mprStrcmpAnyCase(spec, "fixed") == 0) { lang = EJS_SPEC_FIXED; } } } else if (strcmp(argp, "--empty") == 0) { empty = 1; } else if (strcmp(argp, "--log") == 0) { /* * Undocumented logging switch */ if (nextArg >= argc) { err++; } else { ejsStartLogging(mpr, argv[++nextArg]); } } else if (strcmp(argp, "--merge") == 0) { merge = 1; } else if (strcmp(argp, "--nobind") == 0) { bind = 0; } else if (strcmp(argp, "--noout") == 0) { noout = 1; } else if (strcmp(argp, "--standard") == 0) { compilerMode = PRAGMA_MODE_STANDARD; } else if (strcmp(argp, "--strict") == 0) { compilerMode = PRAGMA_MODE_STRICT; } else if (strcmp(argp, "--optimize") == 0) { if (nextArg >= argc) { err++; } else { optimizeLevel = atoi(argv[++nextArg]); } } else if (strcmp(argp, "--out") == 0) { /* * Create a single output module file containing all modules */ if (nextArg >= argc) { err++; } else { outputFile = argv[++nextArg]; } } else if (strcmp(argp, "--parse") == 0) { parseOnly = 1; } else if (strcmp(argp, "--search") == 0 || strcmp(argp, "--searchpath") == 0) { if (nextArg >= argc) { err++; } else { searchPath = argv[++nextArg]; } } else if (strcmp(argp, "--sign") == 0) { if (nextArg >= argc) { err++; } else { certFile = argv[++nextArg]; } } else if (strcmp(argp, "--tabWidth") == 0) { if (nextArg >= argc) { err++; } else { tabWidth = atoi(argv[++nextArg]); } } else if (strcmp(argp, "--use") == 0) { if (nextArg >= argc) { err++; } else { modules = mprStrdup(mpr, argv[++nextArg]); name = mprStrTok(modules, " \t", &tok); while (name != NULL) { mprAddItem(useModules, name); name = mprStrTok(NULL, " \t", &tok); } } } else if (strcmp(argp, "--version") == 0 || strcmp(argp, "-V") == 0) { mprPrintfError(mpr, "%s %s-%s\n", BLD_NAME, BLD_VERSION, BLD_VERSION); return 0; } else if (strcmp(argp, "--warn") == 0) { if (nextArg >= argc) { err++; } else { warnLevel = atoi(argv[++nextArg]); } #if BLD_FEATURE_EJS_WEB } else if (strcmp(argp, "--web") == 0) { #if BLD_FEATURE_EJS_DB mprAddItem(useModules, "ejs.db"); #endif mprAddItem(useModules, "ejs.web"); #endif } else { err++; break; } } if (noout || merge) { bind = 1; } if (outputFile && noout) { mprPrintfError(mpr, "Can't use --out and --noout\n"); err++; } if (argc == nextArg) { err++; } if (err) { /* * Usage Examples: * ejsc Person.es User.es Customer.es * ejsc --out group.mod Person.es User.es Customer.es * ejsc --out group.mod Person.es User.es Customer.es */ mprPrintfError(mpr, "Usage: %s [options] files...\n" " Ejscript compiler options:\n" " --bind # Bind global properties to slots. Requires --out.\n" " --debug # Include symbolic debugging information in output\n" " --doc # Include documentation strings in output\n" " --lang # Language compliance (ecma|plus|fixed)\n" " --empty # Create empty interpreter\n" " --merge # Merge dependent input modules into the output\n" " --noout # Do not generate any output\n" " --optimize level # Set optimization level (0-9)\n" " --out filename # Name a single output module (default: \"default.mod\")\n" " --parse # Just parse source. No output\n" " --search ejsPath # Module search path\n" " --standard # Default compilation mode to standard (default)\n" " --strict # Default compilation mode to strict\n" #if FUTURE " --sign certFile # Sign the module file (not implemented) \n" " --tabwidth # Tab width for '^' error reporting\n" #endif " --use 'module, ...' # List of modules to pre-load\n" " --version # Emit the compiler version information\n" " --warn level # Set the warning message level (0-9)\n\n", mpr->name); return -1; } /* * Need an interpreter when compiling */ vmService = ejsCreateService(mpr); if (vmService == 0) { return MPR_ERR_NO_MEMORY; } ejsFlags = EJS_FLAG_NO_EXE; if (empty) { ejsFlags |= EJS_FLAG_EMPTY; } if (doc) { ejsFlags |= EJS_FLAG_DOC; } ejs = ejsCreate(vmService, NULL, searchPath, ejsFlags); if (ejs == 0) { return MPR_ERR_NO_MEMORY; } ecFlags = 0; ecFlags |= (debug) ? EC_FLAGS_DEBUG: 0; ecFlags |= (empty) ? EC_FLAGS_EMPTY: 0; ecFlags |= (merge) ? EC_FLAGS_MERGE: 0; ecFlags |= (bind) ? EC_FLAGS_BIND: 0; ecFlags |= (noout) ? EC_FLAGS_NO_OUT: 0; ecFlags |= (parseOnly) ? EC_FLAGS_PARSE_ONLY: 0; cp = ecCreateCompiler(ejs, ecFlags, lang); if (cp == 0) { return MPR_ERR_NO_MEMORY; } ecSetOptimizeLevel(cp, optimizeLevel); ecSetWarnLevel(cp, warnLevel); ecSetDefaultMode(cp, compilerMode); ecSetTabWidth(cp, tabWidth); ecSetOutputFile(cp, outputFile); ecSetCertFile(cp, certFile); if (preloadModules(cp, useModules) < 0) { return EJS_ERR; } if (nextArg < argc) { /* * Compile the source files supplied on the command line. This will compile in-memory and * optionally also save to module files. */ if (ecCompile(cp, argc - nextArg, &argv[nextArg], 0) < 0) { err++; } } if (cp->errorCount > 0) { err++; } #if VXWORKS mprFree(cp); mprFree(ejs); if (mprStop(mpr)) { mprFree(mpr); } #endif return err; }
/* * Match the request for authorization. This implements basic and digest authentication. */ static bool matchAuth(MaConn *conn, MaStage *stage, cchar *url) { MaRequest *req; MaAuth *auth; AuthData *ad; cchar *requiredPassword; char *msg; int actualAuthType; req = conn->request; auth = req->auth; if (auth == 0) { maFailRequest(conn, MPR_HTTP_CODE_UNAUTHORIZED, "Access Denied, Authorization enabled."); return 1; } if ((ad = mprAllocObjZeroed(req, AuthData)) == 0) { maFailRequest(conn, MPR_HTTP_CODE_UNAUTHORIZED, "Access Denied, Server Error."); return 1; } if (auth->type == 0) { formatAuthResponse(conn, auth, MPR_HTTP_CODE_UNAUTHORIZED, "Access Denied, Authorization required.", 0); return 1; } if (req->authDetails == 0) { formatAuthResponse(conn, auth, MPR_HTTP_CODE_UNAUTHORIZED, "Access Denied, Missing authorization details.", 0); return 1; } if (mprStrcmpAnyCase(req->authType, "basic") == 0) { decodeBasicAuth(conn, ad); actualAuthType = MA_AUTH_BASIC; #if BLD_FEATURE_AUTH_DIGEST } else if (mprStrcmpAnyCase(req->authType, "digest") == 0) { if (decodeDigestDetails(conn, ad) < 0) { maFailRequest(conn, 400, "Bad authorization header"); return 1; } actualAuthType = MA_AUTH_DIGEST; #endif } else { actualAuthType = MA_AUTH_UNKNOWN; } mprLog(conn, 4, "openAuth: type %d, url %s\nDetails %s\n", auth->type, req->url, req->authDetails); if (ad->userName == 0) { formatAuthResponse(conn, auth, MPR_HTTP_CODE_UNAUTHORIZED, "Access Denied, Missing user name.", 0); return 1; } if (auth->type != actualAuthType) { formatAuthResponse(conn, auth, MPR_HTTP_CODE_UNAUTHORIZED, "Access Denied, Wrong authentication protocol.", 0); return 1; } /* * Some backend methods can't return the password and will simply do everything in validateUserCredentials. * In this case, they and will return "". That is okay. */ if ((requiredPassword = getPassword(conn, auth->requiredRealm, ad->userName)) == 0) { formatAuthResponse(conn, auth, MPR_HTTP_CODE_UNAUTHORIZED, "Access Denied, authentication error.", "User not defined"); return 1; } #if BLD_FEATURE_AUTH_DIGEST if (auth->type == MA_AUTH_DIGEST) { char *requiredDigest; if (strcmp(ad->qop, auth->qop) != 0) { formatAuthResponse(conn, auth, MPR_HTTP_CODE_UNAUTHORIZED, "Access Denied, Quality of protection does not match.", 0); return 1; } mprCalcDigest(req, &requiredDigest, 0, requiredPassword, ad->realm, req->url, ad->nonce, ad->qop, ad->nc, ad->cnonce, req->methodName); requiredPassword = requiredDigest; } #endif if (!validateUserCredentials(conn, auth->requiredRealm, ad->userName, ad->password, requiredPassword, &msg)) { formatAuthResponse(conn, auth, MPR_HTTP_CODE_UNAUTHORIZED, "Access denied, authentication error", msg); return 1; } return 0; }
/* * Parse the appweb.conf directives for authorization */ static int parseAuth(MaHttp *http, cchar *key, char *value, MaConfigState *state) { MaServer *server; MaHost *host; MaAuth *auth; MaAcl acl; char *path, *names, *tok, *type, *aclSpec; server = state->server; host = state->host; auth = state->auth; if (mprStrcmpAnyCase(key, "AuthGroupFile") == 0) { path = maMakePath(host, mprStrTrim(value, "\"")); if (maReadGroupFile(server, auth, path) < 0) { mprError(http, "Can't open AuthGroupFile %s", path); return MPR_ERR_BAD_SYNTAX; } mprFree(path); return 1; } else if (mprStrcmpAnyCase(key, "AuthMethod") == 0) { value = mprStrTrim(value, "\""); if (mprStrcmpAnyCase(value, "pam") == 0) { auth->method = MA_AUTH_METHOD_PAM; return 1; } else if (mprStrcmpAnyCase(value, "file") == 0) { auth->method = MA_AUTH_METHOD_FILE; return 1; } else { return MPR_ERR_BAD_SYNTAX; } } else if (mprStrcmpAnyCase(key, "AuthName") == 0) { maSetAuthRealm(auth, mprStrTrim(value, "\"")); return 1; } else if (mprStrcmpAnyCase(key, "AuthType") == 0) { value = mprStrTrim(value, "\""); if (mprStrcmpAnyCase(value, "Basic") == 0) { auth->type = MA_AUTH_BASIC; } else if (mprStrcmpAnyCase(value, "None") == 0) { auth->type = 0; #if BLD_FEATURE_AUTH_DIGEST } else if (mprStrcmpAnyCase(value, "Digest") == 0) { auth->type = MA_AUTH_DIGEST; #endif } else { mprError(http, "Unsupported authorization protocol"); return MPR_ERR_BAD_SYNTAX; } return 1; } else if (mprStrcmpAnyCase(key, "AuthUserFile") == 0) { path = maMakePath(host, mprStrTrim(value, "\"")); if (maReadUserFile(server, auth, path) < 0) { mprError(http, "Can't open AuthUserFile %s", path); return MPR_ERR_BAD_SYNTAX; } mprFree(path); return 1; #if BLD_FEATURE_AUTH_DIGEST } else if (mprStrcmpAnyCase(key, "AuthDigestQop") == 0) { value = mprStrTrim(value, "\""); mprStrLower(value); if (strcmp(value, "none") != 0 && strcmp(value, "auth") != 0 && strcmp(value, "auth-int") != 0) { return MPR_ERR_BAD_SYNTAX; } maSetAuthQop(auth, value); return 1; } else if (mprStrcmpAnyCase(key, "AuthDigestAlgorithm") == 0) { return 1; } else if (mprStrcmpAnyCase(key, "AuthDigestDomain") == 0) { return 1; } else if (mprStrcmpAnyCase(key, "AuthDigestNonceLifetime") == 0) { return 1; #endif } else if (mprStrcmpAnyCase(key, "Require") == 0) { if (maGetConfigValue(http, &type, value, &tok, 1) < 0) { return MPR_ERR_BAD_SYNTAX; } if (mprStrcmpAnyCase(type, "acl") == 0) { aclSpec = mprStrTrim(tok, "\""); acl = maParseAcl(auth, aclSpec); maSetRequiredAcl(auth, acl); } else if (mprStrcmpAnyCase(type, "valid-user") == 0) { maSetAuthAnyValidUser(auth); } else { names = mprStrTrim(tok, "\""); if (mprStrcmpAnyCase(type, "user") == 0) { maSetAuthRequiredUsers(auth, names); } else if (mprStrcmpAnyCase(type, "group") == 0) { maSetAuthRequiredGroups(auth, names); } else { mprError(http, "Bad Require syntax: %s", type); return MPR_ERR_BAD_SYNTAX; } } return 1; } return 0; }
/* * Decode the digest authentication details. */ static int decodeDigestDetails(MaConn *conn, AuthData *ad) { MaRequest *req; char *authDetails, *value, *tok, *key, *dp, *sp; int seenComma; req = conn->request; key = authDetails = mprStrdup(req, req->authDetails); while (*key) { while (*key && isspace((int) *key)) { key++; } tok = key; while (*tok && !isspace((int) *tok) && *tok != ',' && *tok != '=') { tok++; } *tok++ = '\0'; while (isspace((int) *tok)) { tok++; } seenComma = 0; if (*tok == '\"') { value = ++tok; while (*tok != '\"' && *tok != '\0') { tok++; } } else { value = tok; while (*tok != ',' && *tok != '\0') { tok++; } seenComma++; } *tok++ = '\0'; /* * Handle back-quoting */ if (strchr(value, '\\')) { for (dp = sp = value; *sp; sp++) { if (*sp == '\\') { sp++; } *dp++ = *sp++; } *dp = '\0'; } /* * username, response, oqaque, uri, realm, nonce, nc, cnonce, qop */ switch (tolower((int) *key)) { case 'a': if (mprStrcmpAnyCase(key, "algorithm") == 0) { break; } else if (mprStrcmpAnyCase(key, "auth-param") == 0) { break; } break; case 'c': if (mprStrcmpAnyCase(key, "cnonce") == 0) { ad->cnonce = mprStrdup(req, value); } break; case 'd': if (mprStrcmpAnyCase(key, "domain") == 0) { break; } break; case 'n': if (mprStrcmpAnyCase(key, "nc") == 0) { ad->nc = mprStrdup(req, value); } else if (mprStrcmpAnyCase(key, "nonce") == 0) { ad->nonce = mprStrdup(req, value); } break; case 'o': if (mprStrcmpAnyCase(key, "opaque") == 0) { ad->opaque = mprStrdup(req, value); } break; case 'q': if (mprStrcmpAnyCase(key, "qop") == 0) { ad->qop = mprStrdup(req, value); } break; case 'r': if (mprStrcmpAnyCase(key, "realm") == 0) { ad->realm = mprStrdup(req, value); } else if (mprStrcmpAnyCase(key, "response") == 0) { /* Store the response digest in the password field */ ad->password = mprStrdup(req, value); } break; case 's': if (mprStrcmpAnyCase(key, "stale") == 0) { break; } case 'u': if (mprStrcmpAnyCase(key, "uri") == 0) { ad->uri = mprStrdup(req, value); } else if (mprStrcmpAnyCase(key, "username") == 0) { ad->userName = mprStrdup(req, value); } break; default: /* Just ignore keywords we don't understand */ ; } key = tok; if (!seenComma) { while (*key && *key != ',') { key++; } if (*key) { key++; } } } mprFree(authDetails); if (ad->userName == 0 || ad->realm == 0 || ad->nonce == 0 || ad->uri == 0 || ad->password == 0) { return MPR_ERR_BAD_ARGS; } if (ad->qop && (ad->cnonce == 0 || ad->nc == 0)) { return MPR_ERR_BAD_ARGS; } if (ad->qop == 0) { ad->qop = mprStrdup(req, ""); } maSetRequestUser(conn, ad->userName); return 0; }
static int parseEjs(MaHttp *http, cchar *key, char *value, MaConfigState *state) { MaLocation *location; MaServer *server; MaHost *host; char *prefix, *path; int flags; host = state->host; server = state->server; location = state->location; flags = location->flags & (MA_LOC_BROWSER | MA_LOC_AUTO_SESSION); #if UNUSED MaStage *ejsHandler; EjsWebControl *web; if (mprStrcmpAnyCase(key, "Ejs") == 0) { path = mprStrTrim(value, "\""); mprCleanFilename(http, path); if (!mprAccess(http, path, X_OK)) { mprError(http, "Can't access Ejs path %s", path); return MPR_ERR_BAD_SYNTAX; } if ((ejsHandler = maLookupStage(http, "ejsHandler")) == 0) { mprError(http, "Ejscript module is not loaded"); return MPR_ERR_BAD_SYNTAX; } web = (EjsWebControl*) ejsHandler->stageData; web->ejsLibDir = path; } else #endif if (mprStrcmpAnyCase(key, "EjsApp") == 0) { if (mprStrcmpAnyCase(value, "on") == 0) { location->flags |= MA_LOC_APP; } else { location->flags &= ~MA_LOC_APP; } return 1; } else if (mprStrcmpAnyCase(key, "EjsAppDir") == 0) { if (mprStrcmpAnyCase(value, "on") == 0) { location->flags |= MA_LOC_APP_DIR; } else { location->flags &= ~MA_LOC_APP_DIR; } return 1; } else if (mprStrcmpAnyCase(key, "EjsAppAlias") == 0) { if (maSplitConfigValue(server, &prefix, &path, value, 1) < 0 || path == 0 || prefix == 0) { return MPR_ERR_BAD_SYNTAX; } location = maCreateLocationAlias(http, state, prefix, path, "ejsHandler", MA_LOC_APP | flags); if (location == 0) { return MPR_ERR_BAD_SYNTAX; } return 1; } else if (mprStrcmpAnyCase(key, "EjsAppDirAlias") == 0) { if (maSplitConfigValue(server, &prefix, &path, value, 1) < 0 || path == 0 || prefix == 0) { return MPR_ERR_BAD_SYNTAX; } location = maCreateLocationAlias(http, state, prefix, path, "ejsHandler", MA_LOC_APP_DIR | flags); if (location == 0) { return MPR_ERR_BAD_SYNTAX; } return 1; } else if (mprStrcmpAnyCase(key, "EjsErrors") == 0) { if (mprStrcmpAnyCase(value, "browser") == 0) { location->flags |= MA_LOC_BROWSER; } else { location->flags &= ~MA_LOC_BROWSER; } return 1; } else if (mprStrcmpAnyCase(key, "EjsSessionTimeout") == 0) { if (value == 0) { return MPR_ERR_BAD_SYNTAX; } if (! mprGetDebugMode(http)) { location->sessionTimeout = atoi(mprStrTrim(value, "\"")); } return 1; } else if (mprStrcmpAnyCase(key, "EjsSession") == 0) { if (mprStrcmpAnyCase(value, "on") == 0) { location->flags |= MA_LOC_AUTO_SESSION; } else { location->flags &= ~MA_LOC_AUTO_SESSION; } return 1; } return 0; }
static int parseEjs(MaHttp *http, cchar *key, char *value, MaConfigState *state) { MaLocation *location; MaServer *server; MaHost *host; char *prefix, *path; int flags; host = state->host; server = state->server; location = state->location; flags = location->flags & (MA_LOC_BROWSER | MA_LOC_AUTO_SESSION); if (mprStrcmpAnyCase(key, "EjsApp") == 0) { if (mprStrcmpAnyCase(value, "on") == 0) { location->flags |= MA_LOC_APP; } else { location->flags &= ~MA_LOC_APP; } return 1; } else if (mprStrcmpAnyCase(key, "EjsAppDir") == 0) { if (mprStrcmpAnyCase(value, "on") == 0) { location->flags |= MA_LOC_APP_DIR; } else { location->flags &= ~MA_LOC_APP_DIR; } return 1; } else if (mprStrcmpAnyCase(key, "EjsAppAlias") == 0) { if (maSplitConfigValue(server, &prefix, &path, value, 1) < 0 || path == 0 || prefix == 0) { return MPR_ERR_BAD_SYNTAX; } location = maCreateLocationAlias(http, state, prefix, path, "ejsHandler", MA_LOC_APP | flags); if (location == 0) { return MPR_ERR_BAD_SYNTAX; } return 1; } else if (mprStrcmpAnyCase(key, "EjsAppDirAlias") == 0) { if (maSplitConfigValue(server, &prefix, &path, value, 1) < 0 || path == 0 || prefix == 0) { return MPR_ERR_BAD_SYNTAX; } location = maCreateLocationAlias(http, state, prefix, path, "ejsHandler", MA_LOC_APP_DIR | flags); if (location == 0) { return MPR_ERR_BAD_SYNTAX; } return 1; } else if (mprStrcmpAnyCase(key, "EjsErrors") == 0) { if (mprStrcmpAnyCase(value, "browser") == 0) { location->flags |= MA_LOC_BROWSER; } else { location->flags &= ~MA_LOC_BROWSER; } return 1; } else if (mprStrcmpAnyCase(key, "EjsSessionTimeout") == 0) { if (value == 0) { return MPR_ERR_BAD_SYNTAX; } if (! mprGetDebugMode(http)) { location->sessionTimeout = atoi(mprStrTrim(value, "\"")); } return 1; } else if (mprStrcmpAnyCase(key, "EjsSession") == 0) { if (mprStrcmpAnyCase(value, "on") == 0) { location->flags |= MA_LOC_AUTO_SESSION; } else { location->flags &= ~MA_LOC_AUTO_SESSION; } return 1; } return 0; }