void maSetHostTraceFilter(MaHost *host, int len, cchar *include, cchar *exclude) { char *word, *tok, *line; host->traceMaxLength = len; if (include && strcmp(include, "*") != 0) { host->traceInclude = mprCreateHash(host, 0); line = mprStrdup(host, include); word = mprStrTok(line, ", \t\r\n", &tok); while (word) { if (word[0] == '*' && word[1] == '.') { word += 2; } mprAddHash(host->traceInclude, word, host); word = mprStrTok(NULL, ", \t\r\n", &tok); } mprFree(line); } if (exclude) { host->traceExclude = mprCreateHash(host, 0); line = mprStrdup(host, exclude); word = mprStrTok(line, ", \t\r\n", &tok); while (word) { if (word[0] == '*' && word[1] == '.') { word += 2; } mprAddHash(host->traceExclude, word, host); word = mprStrTok(NULL, ", \t\r\n", &tok); } mprFree(line); } }
void mprSetModuleSearchPath(char *dirs) { char full[MPR_MAX_FNAME], native[MPR_MAX_FNAME]; char *oldPath, sep, *np, *tok, *newPath, *searchPath, *cp; int len, modified; mprAssert(dirs && *dirs); oldPath = getenv("PATH"); mprAssert(oldPath); if (oldPath == 0 || dirs == 0) { return; } /* * Prepare to tokenize the search path */ searchPath = mprStrdup(dirs); sep = strchr(searchPath, '"') ? '"' : ' '; for (cp = searchPath; *cp; cp++) { if (*cp == sep) { *cp = '\001'; } } len = mprAllocSprintf(&newPath, -1, "PATH=%s", oldPath); mprAssert(len > 0); np = mprStrTok(searchPath, "\001\n", &tok); for (modified = 0; np; ) { mprGetFullPathName(full, sizeof(full), np); mprGetNativePathName(native, sizeof(native), full); // TODO - this should really do a case insensitive scan if ((cp = strstr(oldPath, native)) != 0) { cp = &oldPath[strlen(native)]; if (*cp == ';' || *cp == '\0') { np = mprStrTok(0, "\001\n", &tok); continue; } } len = mprReallocStrcat(&newPath, -1, len, ";", native, 0); mprAssert(len >= 0); np = mprStrTok(0, "\001\n", &tok); modified = 1; } if (modified) { mprLog(7, "Set %s\n", newPath); if (putenv(newPath) < 0) { mprAssert(0); } } mprFree(searchPath); mprFree(newPath); }
static void parseQuery(MaConn *conn) { MaRequest *req; MaResponse *resp; Dir *dir; char *value, *query, *next, *tok; req = conn->request; resp = conn->response; dir = resp->handler->stageData; query = mprStrdup(req, req->parsedUri->query); if (query == 0) { return; } tok = mprStrTok(query, ";&", &next); while (tok) { if ((value = strchr(tok, '=')) != 0) { *value++ = '\0'; if (*tok == 'C') { /* Sort column */ mprFree(dir->sortField); if (*value == 'N') { dir->sortField = "Name"; } else if (*value == 'M') { dir->sortField = "Date"; } else if (*value == 'S') { dir->sortField = "Size"; } dir->sortField = mprStrdup(dir, dir->sortField); } else if (*tok == 'O') { /* Sort order */ if (*value == 'A') { dir->sortOrder = 1; } else if (*value == 'D') { dir->sortOrder = -1; } } else if (*tok == 'F') { /* Format */ if (*value == '0') { dir->fancyIndexing = 0; } else if (*value == '1') { dir->fancyIndexing = 1; } else if (*value == '2') { dir->fancyIndexing = 2; } } else if (*tok == 'P') { /* Pattern */ dir->pattern = mprStrdup(dir, value); } } tok = mprStrTok(next, ";&", &next); } mprFree(query); }
static void addFormVars(MprCtx ctx, cchar *buf) { char *pair, *tok; pair = mprStrTok(mprStrdup(ctx, buf), "&", &tok); while (pair != 0) { mprAddItem(formData, pair); pair = mprStrTok(0, "&", &tok); } }
int maGetConfigValue(MprCtx ctx, char **arg, char *buf, char **nextToken, int quotes) { char *endp; if (buf == 0) { return -1; } while (isspace((int) *buf)) { buf++; } if (quotes && *buf == '\"') { *arg = ++buf; if ((endp = strchr(buf, '\"')) != 0) { *endp++ = '\0'; } else { return MPR_ERR_BAD_SYNTAX; } while ((int) isspace((int) *endp)) { endp++; } *nextToken = endp; } else { *arg = mprStrTok(buf, " \t\n", nextToken); } return 0; }
static void parseWords(MprList *list, cchar *str) { char *word, *tok, *strTok; mprAssert(str); if (str == 0 || *str == '\0') { return; } strTok = mprStrdup(list, str); word = mprStrTok(strTok, " \t\r\n", &tok); while (word) { mprAddItem(list, word); word = mprStrTok(0, " \t\r\n", &tok); } }
static int getVars(MaQueue *q, char ***keys, char *buf, int len) { char** keyList; char *eq, *cp, *pp, *tok; int i, keyCount; *keys = 0; /* * Change all plus signs back to spaces */ keyCount = (len > 0) ? 1 : 0; for (cp = buf; cp < &buf[len]; cp++) { if (*cp == '+') { *cp = ' '; } else if (*cp == '&' && (cp > buf && cp < &buf[len - 1])) { keyCount++; } } if (keyCount == 0) { return 0; } /* * Crack the input into name/value pairs */ keyList = (char**) mprAlloc(q, (keyCount * 2) * sizeof(char**)); i = 0; tok = 0; for (pp = mprStrTok(buf, "&", &tok); pp; pp = mprStrTok(0, "&", &tok)) { if ((eq = strchr(pp, '=')) != 0) { *eq++ = '\0'; mprUrlDecode(pp, (int) strlen(pp) + 1, pp); mprUrlDecode(eq, (int) strlen(eq) + 1, eq); } else { mprUrlDecode(pp, (int) strlen(pp) + 1, pp); } if (i < (keyCount * 2)) { keyList[i++] = pp; keyList[i++] = eq; } } *keys = keyList; return keyCount; }
int MaHost::openMimeTypes(char *path) { MprFile *file; char buf[80], *tok, *ext, *type; int line; mimeFile = mprStrdup(path); mprAssert(mimeTypes == 0); file = server->fileSystem->newFile(); if (mimeTypes == 0) { mimeTypes = new MprHashTable(157); } /* WINCE may need to prepend server root to the path */ if (file->open(path, O_RDONLY | O_TEXT, 0) < 0) { mprError(MPR_L, MPR_LOG, "Can't open mime file %s", path); delete file; return MPR_ERR_CANT_OPEN; } line = 0; while (file->gets(buf, sizeof(buf)) != 0) { line++; if (buf[0] == '#' || isspace((uchar) buf[0])) { continue; } type = mprStrTok(buf, " \t\n\r", &tok); ext = mprStrTok(0, " \t\n\r", &tok); if (type == 0 || ext == 0) { mprError(MPR_L, MPR_LOG, "Bad mime spec in %s at line %d", path, line); continue; } while (ext) { addMimeType(ext, type); ext = mprStrTok(0, " \t\n\r", &tok); } } file->close(); delete file; return 0; }
static int readPassFile(char *passFile) { FILE *fp; char buf[MPR_HTTP_MAX_PASS * 2]; char *tok, *enabledSpec, *user, *realm, *password; bool enabled; int line; fp = fopen(passFile, "r" MPR_TEXT); if (fp == 0) { mprError(MPR_L, MPR_USER, "Can't open %s\n", passFile); return MPR_ERR_CANT_OPEN; } line = 0; while (fgets(buf, sizeof(buf), fp) != 0) { line++; enabledSpec = mprStrTok(buf, ":", &tok); user = mprStrTok(0, ":", &tok); realm = mprStrTok(0, ":", &tok); password = mprStrTok(0, "\n\r", &tok); if (enabledSpec == 0 || user == 0 || realm == 0 || password == 0) { mprError(MPR_L, MPR_USER, "Badly formed password on line %d\n", line); return MPR_ERR_CANT_OPEN; } user = trimWhiteSpace(user); if (*user == '#' || *user == '\0') { continue; } enabled = (enabledSpec[0] == '1'); realm = trimWhiteSpace(realm); password = trimWhiteSpace(password); users.insert(new User(user, realm, password, enabled)); } fclose(fp); return 0; }
int maReadGroupFile(MaServer *server, MaAuth *auth, char *path) { MprFile *file; MaAcl acl; char buf[MPR_MAX_STRING]; char *users, *group, *enabled, *aclSpec, *tok, *cp; mprFree(auth->groupFile); auth->groupFile = mprStrdup(server, path); if ((file = mprOpen(auth, path, O_RDONLY | O_TEXT, 0444)) == 0) { return MPR_ERR_CANT_OPEN; } while (mprGets(file, buf, sizeof(buf))) { enabled = mprStrTok(buf, " :\t", &tok); if (!enabled) { continue; } for (cp = enabled; isspace((int) *cp); cp++) { ; } if (*cp == '\0' || *cp == '#') { continue; } aclSpec = mprStrTok(0, " :\t", &tok); group = mprStrTok(0, " :\t", &tok); users = mprStrTok(0, "\r\n", &tok); acl = maParseAcl(auth, aclSpec); maAddGroup(auth, group, acl, (*enabled == '0') ? 0 : 1); maAddUsersToGroup(auth, group, users); } mprFree(file); maUpdateUserAcls(auth); return 0; }
int maReadUserFile(MaServer *server, MaAuth *auth, char *path) { MprFile *file; char buf[MPR_MAX_STRING]; char *enabled, *user, *password, *realm, *tok, *cp; mprFree(auth->userFile); auth->userFile = mprStrdup(auth, path); if ((file = mprOpen(auth, path, O_RDONLY | O_TEXT, 0444)) == 0) { return MPR_ERR_CANT_OPEN; } while (mprGets(file, buf, sizeof(buf))) { enabled = mprStrTok(buf, " :\t", &tok); if (!enabled) { continue; } for (cp = enabled; isspace((int) *cp); cp++) { ; } if (*cp == '\0' || *cp == '#') { continue; } user = mprStrTok(0, ":", &tok); realm = mprStrTok(0, ":", &tok); password = mprStrTok(0, " \t\r\n", &tok); user = trimWhiteSpace(user); realm = trimWhiteSpace(realm); password = trimWhiteSpace(password); maAddUser(auth, realm, user, password, (*enabled == '0' ? 0 : 1)); } mprFree(file); maUpdateUserAcls(auth); return 0; }
int MaClient::parseFirst(char *line) { char *code, *tok; mprAssert(line && *line); responseProto = mprStrTok(line, " \t", &tok); if (responseProto == 0 || responseProto[0] == '\0') { formatError("Bad HTTP response"); responseCode = MPR_HTTP_CLIENT_ERROR; finishRequest(1); return MPR_ERR_BAD_STATE; } responseProto = mprStrdup(responseProto); if (strncmp(responseProto, "HTTP/1.", 7) != 0) { formatError("Unsupported protocol: %s", responseProto); responseCode = MPR_HTTP_CLIENT_ERROR; finishRequest(1); return MPR_ERR_BAD_STATE; } code = mprStrTok(0, " \t\r\n", &tok); if (code == 0 || *code == '\0') { formatError("Bad HTTP response"); responseCode = MPR_HTTP_CLIENT_ERROR; finishRequest(1); return MPR_ERR_BAD_STATE; } responseCode = atoi(code); responseText = mprStrTok(0, "\r\n", &tok); if (responseText && *responseText) { responseText = mprStrdup(responseText); } return 0; }
/* * 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; }
static void doTests(void *data, void *threadp) #endif { MprBuf post; FILE *fp; MaClient *client; char urlBuf[4096], urlBuf2[4096]; char postBuf[4096]; char *cp, *operation, *url, *tok; int rc, j, line; fp = 0; client = new MaClient(); client->setTimeout(timeout); client->setRetries(retries); if (httpVersion == 0) { client->setKeepAlive(0); } post.setBuf(MPR_HTTP_CLIENT_BUFSIZE, MPR_HTTP_MAX_BODY); while (!mpr->isExiting() && success) { lock(); if (fetchCount >= iterations) { unlock(); break; } unlock(); rc = 0; for (j = 0; j < saveArgc; j++) { url = saveArgv[j]; if (*url == '/') { mprSprintf(urlBuf2, sizeof(urlBuf2), "%s%s", host, url); url = urlBuf2; } rc = fetch(client, method, url, postData, postLen); if (rc < 0 && !continueOnErrors) { success = 0; goto commonExit; } } if (fileList == 0) { continue; } fp = fopen(fileList, "rt"); if (fp == 0) { mprError(MPR_L, MPR_USER, "Can't open %s", fileList); goto commonExit; } line = 0; while (fgets(urlBuf, sizeof(urlBuf), fp) != NULL && !mpr->isExiting()) { lock(); if (fetchCount >= iterations) { unlock(); break; } unlock(); if ((cp = strchr(urlBuf, '\n')) != 0) { *cp = '\0'; } operation = mprStrTok(urlBuf, " \t\n", &tok); url = mprStrTok(0, " \t\n", &tok); if (*url == '/') { mprSprintf(urlBuf2, sizeof(urlBuf2), "%s%s", host, url); url = urlBuf2; } if (strcmp(operation, "GET") == 0) { rc = fetch(client, operation, url, postData, postLen); } else if (strcmp(operation, "HEAD") == 0) { rc = fetch(client, operation, url, postData, postLen); } else if (strcmp(operation, "POST") == 0) { while (fgets(postBuf, sizeof(postBuf), fp) != NULL) { if (postBuf[0] != '\t') { break; } if (strlen(postBuf) == 1) { break; } post.put((uchar*) &postBuf[1], strlen(postBuf) - 2); post.addNull(); if (post.getLength() >= (MPR_HTTP_MAX_BODY - 1)) { mprError(MPR_L, MPR_USER, "Bad post data on line %d", line); if (!continueOnErrors) { success = 0; fclose(fp); fp = 0; goto commonExit; } } } if (post.getLength() > 0) { rc = fetch(client, operation, url, post.getStart(), post.getLength()); } else { rc = fetch(client, operation, url, postBuf, postLen); } post.flush(); } else { rc = -1; mprError(MPR_L, MPR_USER, "Bad operation on line %d", line); } if (rc < 0 && !continueOnErrors) { success = 0; fclose(fp); fp = 0; goto commonExit; } } fclose(fp); fp = 0; } commonExit: #if BLD_FEATURE_MULTITHREAD if (threadp) { lock(); activeLoadThreads--; unlock(); } #endif delete client; }
void MaCgiHandler::parseHeader(MaRequest *rq) { MaDataStream *dynBuf; char *endHeaders, *header, *key, *value, *tok; char *cp, *lp, *saveHeader; int len; header = headerBuf->getStart(); endHeaders = strstr(header, "\r\n\r\n"); if (endHeaders == 0) { endHeaders = strstr(header, "\n\n"); if (endHeaders == 0) { endHeaders = strstr(header, "\r\r\n\r\r\n"); if (endHeaders == 0) { return; } } headerBuf->adjustStart(endHeaders + 2 - header); } else { headerBuf->adjustStart(endHeaders + 4 - header); } *endHeaders = '\0'; mprLog(5, log, "%d: parseHeader: header\n%s\n", rq->getFd(), header); if (endHeaders) { lp = header; tok = lp; while (tok && *tok) { for (cp = tok; *cp && *cp != '\r' && *cp != '\n'; cp++) ; len = cp - tok + 1; mprAssert(len >= 0); mprAllocMemcpy(&saveHeader, len, tok, len); saveHeader[len - 1] = '\0'; if ((key = mprStrTok(lp, ": \t\r\n", &tok)) == 0) { break; } lp = 0; if ((value = mprStrTok(0, "\r\n", &tok)) == 0) { rq->requestError(503, "Bad header format"); rq->finishRequest(); mprFree(saveHeader); return; } while (isspace((uchar) *value)) { value++; } mprStrLower(key); if (strcmp(key, "location") == 0) { mprFree(newLocation); newLocation = mprStrdup(value); } else if (strcmp(key, "status") == 0) { rq->setResponseCode(atoi(value)); } else if (strcmp(key, "content-type") == 0) { rq->setResponseMimeType(value); #if OLD } else if ((key[0] == 'x' || key[0] == 'X') && key[1] == '-') { // // Pass "X-Headers" through to the client // rq->setHeader(saveHeader); } #endif } else { // // Now pass all other headers back to the client // rq->setHeader(saveHeader); } mprFree(saveHeader); }
/* * Format is: Range: bytes=n1-n2,n3-n4,... * Where n1 is first byte pos and n2 is last byte pos * * Examples: * Range: 0-49 first 50 bytes * Range: 50-99,200-249 Two 50 byte ranges from 50 and 200 * Range: -50 Last 50 bytes * Range: 1- Skip first byte then emit the rest * * Return 1 if more ranges, 0 if end of ranges, -1 if bad range. */ static bool parseRange(MaConn *conn, char *value) { MaRequest *req; MaResponse *resp; MaRange *range, *last, *next; char *tok, *ep; req = conn->request; resp = conn->response; value = mprStrdup(conn, value); if (value == 0) { return 0; } /* * Step over the "bytes=" */ tok = mprStrTok(value, "=", &value); for (last = 0; value && *value; ) { range = mprAllocObjZeroed(req, MaRange); if (range == 0) { return 0; } /* * A range "-7" will set the start to -1 and end to 8 */ tok = mprStrTok(value, ",", &value); if (*tok != '-') { range->start = (int) mprAtoi(tok, 10); } else { range->start = -1; } range->end = -1; if ((ep = strchr(tok, '-')) != 0) { if (*++ep != '\0') { /* * End is one beyond the range. Makes the math easier. */ range->end = (int) mprAtoi(ep, 10) + 1; } } if (range->start >= 0 && range->end >= 0) { range->len = range->end - range->start; } if (last == 0) { req->ranges = range; } else { last->next = range; } last = range; } /* * Validate ranges */ for (range = req->ranges; range; range = range->next) { if (range->end != -1 && range->start >= range->end) { return 0; } if (range->start < 0 && range->end < 0) { return 0; } next = range->next; if (range->start < 0 && next) { /* This range goes to the end, so can't have another range afterwards */ return 0; } if (next) { if (next->start >= 0 && range->end > next->start) { return 0; } } } resp->currentRange = req->ranges; return (last) ? 1: 0; }
static int locateServerRoot(char *path) { #if BLD_FEATURE_CONFIG_PARSE && !BLD_FEATURE_ROMFS if (serverRoot == 0) { MprFileInfo info; char searchPath[MPR_MAX_FNAME * 8], pathBuf[MPR_MAX_FNAME]; char cwd[MPR_MAX_FNAME]; char *tok, *searchBuf; // // No explicit server root switch was supplied so search for // "mime.types" in the search path: // . // .. // ../productName // ../../productName // For windows, we also do: // modDir (where the exe was loaded from) // modDir/.. // modDir/../productName // modDir/../../productName // For all: // BLD_PREFIX // #if WIN || WINCE char modDir[MPR_MAX_FNAME], modPath[MPR_MAX_FNAME]; char module[MPR_MAX_FNAME]; // // Initially change directory to where the exe lives // GetModuleFileName(0, module, sizeof(module)); mprGetDirName(modDir, sizeof(modDir), module); mprGetFullPathName(modPath, sizeof(modPath), modDir); #if WIN /* NOTE: use tabs not spaces between items */ mprSprintf(searchPath, sizeof(searchPath), ". .. ../%s ../../%s " "%s %s/.. %s/../%s %s/../../%s %s", BLD_PRODUCT, BLD_PRODUCT, modPath, modPath, modPath, BLD_PRODUCT, modPath, BLD_PRODUCT, BLD_PREFIX); #else /* NOTE: use tabs not spaces between items */ mprSprintf(searchPath, sizeof(searchPath), "%s %s ../%s ../../%s " "%s/.. %s/../%s", MPR_STORAGE, modPath, BLD_PRODUCT, BLD_PRODUCT, modPath, modPath, modPath); #endif #else mprSprintf(searchPath, sizeof(searchPath), ". .. ../%s ../../%s %s", BLD_PRODUCT, BLD_PRODUCT, BLD_PREFIX); #endif getcwd(cwd, sizeof(cwd) - 1); mprLog(3, "Root search path %s, cwd %s\n", searchPath, cwd); searchBuf = mprStrdup(searchPath); path = mprStrTok(searchBuf, "\t", &tok); while (path) { mprSprintf(pathBuf, sizeof(pathBuf), "%s/mime.types", path); mprLog(4, "Searching for %s\n", pathBuf); if (fileSystem->stat(pathBuf, &info) == 0) { break; } path = mprStrTok(0, "\t", &tok); } if (path == 0) { mprError(MPR_L, MPR_USER, "Can't find suitable server root directory\n" "Using search path %s, and current directory %s\n" "Ensure you have adequate permissions to access the required " "directories.\n", searchPath, cwd); mprFree(searchBuf); return MPR_ERR_CANT_ACCESS; } server->setServerRoot(path); mprFree(searchBuf); } else { // // Must program the server up for the server root. It will convert this // path to an absolute path which we reassign to our notion of // serverRoot. // server->setServerRoot(path); } serverRoot = server->getServerRoot(); #endif #if !BLD_FEATURE_ROMFS chdir(serverRoot); #endif return 0; }
/* * 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; }
/* Build the command arguments. NOTE: argv is untrusted input. */ static void buildArgs(MaConn *conn, MprCmd *cmd, int *argcp, char ***argvp) { MaRequest *req; MaResponse *resp; char *fileName, **argv, status[8], *indexQuery, *cp, *tok; cchar *actionProgram; int argc, argind, len; req = conn->request; resp = conn->response; fileName = resp->filename; mprAssert(fileName); actionProgram = 0; argind = 0; argc = *argcp; if (resp->extension) { actionProgram = maGetMimeActionProgram(req->host, resp->extension); if (actionProgram != 0) { argc++; } } /* This is an Apache compatible hack for PHP 5.3 */ mprItoa(status, sizeof(status), MPR_HTTP_CODE_MOVED_TEMPORARILY, 10); mprAddHash(req->headers, "REDIRECT_STATUS", mprStrdup(req, status)); /* Count the args for ISINDEX queries. Only valid if there is not a "=" in the query. If this is so, then we must not have these args in the query env also? */ indexQuery = req->parsedUri->query; if (indexQuery && !strchr(indexQuery, '=')) { argc++; for (cp = indexQuery; *cp; cp++) { if (*cp == '+') { argc++; } } } else { indexQuery = 0; } #if BLD_WIN_LIKE || VXWORKS { char *bangScript, *cmdBuf, *program, *cmdScript; /* On windows we attempt to find an executable matching the fileName. We look for *.exe, *.bat and also do unix style processing "#!/program" */ findExecutable(conn, &program, &cmdScript, &bangScript, fileName); mprAssert(program); if (cmdScript) { /* Cmd/Batch script (.bat | .cmd) Convert the command to the form where there are 4 elements in argv that cmd.exe can interpret. argv[0] = cmd.exe argv[1] = /Q argv[2] = /C argv[3] = ""script" args ..." */ argc = 4; len = (argc + 1) * sizeof(char*); argv = (char**) mprAlloc(cmd, len); memset(argv, 0, len); argv[argind++] = program; /* Duped in findExecutable */ argv[argind++] = mprStrdup(cmd, "/Q"); argv[argind++] = mprStrdup(cmd, "/C"); len = (int) strlen(cmdScript) + 2 + 1; cmdBuf = (char*) mprAlloc(cmd, len); mprSprintf(cmdBuf, len, "\"%s\"", cmdScript); argv[argind++] = cmdBuf; mprSetCmdDir(cmd, cmdScript); mprFree(cmdScript); /* program will get freed when argv[] gets freed */ } else if (bangScript) { /* Script used "#!/program". NOTE: this may be overridden by a mime Action directive. */ argc++; /* Adding bangScript arg */ len = (argc + 1) * sizeof(char*); argv = (char**) mprAlloc(cmd, len); memset(argv, 0, len); argv[argind++] = program; /* Will get freed when argv[] is freed */ argv[argind++] = bangScript; /* Will get freed when argv[] is freed */ mprSetCmdDir(cmd, bangScript); } else { /* Either unknown extension or .exe (.out) program. */ len = (argc + 1) * sizeof(char*); argv = (char**) mprAlloc(cmd, len); memset(argv, 0, len); if (actionProgram) { argv[argind++] = mprStrdup(cmd, actionProgram); } argv[argind++] = program; } } #else len = (argc + 1) * (int) sizeof(char*); argv = (char**) mprAlloc(cmd, len); memset(argv, 0, len); if (actionProgram) { argv[argind++] = mprStrdup(cmd, actionProgram); } argv[argind++] = mprStrdup(cmd, fileName); #endif /* ISINDEX queries. Only valid if there is not a "=" in the query. If this is so, then we must not have these args in the query env also? */ if (indexQuery) { indexQuery = mprStrdup(cmd, indexQuery); cp = mprStrTok(indexQuery, "+", &tok); while (cp) { argv[argind++] = mprEscapeCmd(resp, mprUrlDecode(resp, cp), 0); cp = mprStrTok(NULL, "+", &tok); } } mprAssert(argind <= argc); argv[argind] = 0; *argcp = argc; *argvp = argv; }
/* If the program has a UNIX style "#!/program" string at the start of the file that program will be selected and the original program will be passed as the first arg to that program with argv[] appended after that. If the program is not found, this routine supports a safe intelligent search for the command. If all else fails, we just return in program the fileName we were passed in. script will be set if we are modifying the program to run and we have extracted the name of the file to run as a script. */ static void findExecutable(MaConn *conn, char **program, char **script, char **bangScript, char *fileName) { MaRequest *req; MaResponse *resp; MaLocation *location; MprHash *hp; MprFile *file; cchar *actionProgram, *ext, *cmdShell; char *tok, buf[MPR_MAX_FNAME + 1], *path; req = conn->request; resp = conn->response; location = req->location; *bangScript = 0; *script = 0; *program = 0; path = 0; actionProgram = maGetMimeActionProgram(conn->host, req->mimeType); ext = resp->extension; /* If not found, go looking for the fileName with the extensions defined in appweb.conf. NOTE: we don't use PATH deliberately!!! */ if (access(fileName, X_OK) < 0 /* && *ext == '\0' */) { for (hp = 0; (hp = mprGetNextHash(location->extensions, hp)) != 0; ) { path = mprStrcat(resp, -1, fileName, ".", hp->key, NULL); if (access(path, X_OK) == 0) { break; } mprFree(path); path = 0; } if (hp) { ext = hp->key; } else { path = fileName; } } else { path = fileName; } mprAssert(path && *path); #if BLD_WIN_LIKE if (ext && (strcmp(ext, ".bat") == 0 || strcmp(ext, ".cmd") == 0)) { /* Let a mime action override COMSPEC */ if (actionProgram) { cmdShell = actionProgram; } else { cmdShell = getenv("COMSPEC"); } if (cmdShell == 0) { cmdShell = "cmd.exe"; } *script = mprStrdup(resp, path); *program = mprStrdup(resp, cmdShell); return; } #endif if ((file = mprOpen(resp, path, O_RDONLY, 0)) != 0) { if (mprRead(file, buf, MPR_MAX_FNAME) > 0) { mprFree(file); buf[MPR_MAX_FNAME] = '\0'; if (buf[0] == '#' && buf[1] == '!') { cmdShell = mprStrTok(&buf[2], " \t\r\n", &tok); if (cmdShell[0] != '/' && (cmdShell[0] != '\0' && cmdShell[1] != ':')) { /* If we can't access the command shell and the command is not an absolute path, look in the same directory as the script. */ if (mprPathExists(resp, cmdShell, X_OK)) { cmdShell = mprJoinPath(resp, mprGetPathDir(resp, path), cmdShell); } } if (actionProgram) { *program = mprStrdup(resp, actionProgram); } else { *program = mprStrdup(resp, cmdShell); } *bangScript = mprStrdup(resp, path); return; } } else { mprFree(file); } } if (actionProgram) { *program = mprStrdup(resp, actionProgram); *bangScript = mprStrdup(resp, path); } else { *program = mprStrdup(resp, path); } return; }
int MaSslModule::parseConfig(char *key, char *value, MaServer *server, MaHost *host, MaAuth *auth, MaDir *dir, MaLocation *location) { MaSslConfig *config; char pathBuf[MPR_MAX_FNAME], prefix[MPR_MAX_FNAME]; char *tok, *word, *enable, *provider; int protoMask, mask; mprStrcpy(prefix, sizeof(prefix), key); prefix[3] = '\0'; if (mprStrCmpAnyCase(prefix, "SSL") != 0) { return 0; } if (mprStrCmpAnyCase(key, "SSLEngine") == 0) { enable = mprStrTok(value, " \t", &tok); provider = mprStrTok(0, " \t", &tok); if (mprStrCmpAnyCase(value, "on") == 0) { if (sslProvider == 0) { mprError(MPR_L, MPR_LOG, "Missing an SSL Provider\n"); return MPR_ERR_BAD_SYNTAX; } config = (MaSslConfig*) sslConfigTable->lookup(host->getName()); if (config == 0) { config = sslProvider->newConfig(host); mprAssert(config); sslConfigTable->insert(config); } host->setSecure(1); host->server->setSslListeners(host, config); } return 1; } config = (MaSslConfig*) sslConfigTable->lookup(host->getName()); if (config == 0) { mprError(MPR_L, MPR_LOG, "Missing SSLEngine directive\n"); return MPR_ERR_BAD_SYNTAX; } if (host->makePath(pathBuf, sizeof(pathBuf), mprStrTrim(value, '\"')) == 0) { mprError(MPR_L, MPR_LOG, "SSL path is too long"); return MPR_ERR_BAD_SYNTAX; } if (mprStrCmpAnyCase(key, "SSLCACertificatePath") == 0) { config->setCaPath(pathBuf); return 1; } else if (mprStrCmpAnyCase(key, "SSLCACertificateFile") == 0) { config->setCaFile(pathBuf); return 1; } else if (mprStrCmpAnyCase(key, "SSLCertificateFile") == 0) { config->setCertFile(pathBuf); return 1; } else if (mprStrCmpAnyCase(key, "SSLCertificateKeyFile") == 0) { config->setKeyFile(pathBuf); return 1; } else if (mprStrCmpAnyCase(key, "SSLCipherSuite") == 0) { config->setCipherSuite(value); return 1; } else if (mprStrCmpAnyCase(key, "SSLVerifyClient") == 0) { if (mprStrCmpAnyCase(value, "require") == 0) { config->setVerifyClient(1); } else if (mprStrCmpAnyCase(value, "none") == 0) { config->setVerifyClient(0); } else { return -1; } return 1; } else if (mprStrCmpAnyCase(key, "SSLProtocol") == 0) { protoMask = 0; word = mprStrTok(value, " \t", &tok); while (word) { mask = -1; if (*word == '-') { word++; mask = 0; } else if (*word == '+') { word++; } if (mprStrCmpAnyCase(word, "SSLv2") == 0) { protoMask &= ~(MPR_HTTP_PROTO_SSLV2 & ~mask); protoMask |= (MPR_HTTP_PROTO_SSLV2 & mask); } else if (mprStrCmpAnyCase(word, "SSLv3") == 0) { protoMask &= ~(MPR_HTTP_PROTO_SSLV3 & ~mask); protoMask |= (MPR_HTTP_PROTO_SSLV3 & mask); } else if (mprStrCmpAnyCase(word, "TLSv1") == 0) { protoMask &= ~(MPR_HTTP_PROTO_TLSV1 & ~mask); protoMask |= (MPR_HTTP_PROTO_TLSV1 & mask); } else if (mprStrCmpAnyCase(word, "ALL") == 0) { protoMask &= ~(MPR_HTTP_PROTO_ALL & ~mask); protoMask |= (MPR_HTTP_PROTO_ALL & mask); } word = mprStrTok(0, " \t", &tok); } config->setSslProto(protoMask); return 1; } return 0; }
int MaClient::parseHeader(char *line) { char *key, *value, *tok, *tp; mprAssert(line && *line); if ((key = mprStrTok(line, ": \t\n", &tok)) == 0) { formatError("Bad HTTP header"); responseCode = MPR_HTTP_CLIENT_ERROR; finishRequest(1); return MPR_ERR_BAD_STATE; } if ((value = mprStrTok(0, "\n", &tok)) == 0) { value = ""; } while (isspace((uchar) *value)) { value++; } // Upper to be consistent with Request? mprStrLower(key); headerValues->insert(new MprStringHashEntry(key, value)); if (strcmp("www-authenticate", key) == 0) { tp = value; while (*value && !isspace((uchar) *value)) { value++; } *value++ = '\0'; mprStrLower(tp); mprFree(serverAuthType); serverAuthType = mprStrdup(tp); if (parseAuthenticate(value) < 0) { formatError("Bad Authenticate header"); responseCode = MPR_HTTP_CLIENT_ERROR; finishRequest(1); return MPR_ERR_BAD_STATE; } } else if (strcmp("content-length", key) == 0) { contentLength = atoi(value); if (mprStrCmpAnyCase(method, "HEAD") != 0) { contentRemaining = atoi(value); } } else if (strcmp("connection", key) == 0) { mprStrLower(value); if (strcmp(value, "close") == 0) { flags &= ~MPR_HTTP_KEEP_ALIVE; #if BLD_FEATURE_KEEP_ALIVE } else if (strcmp(value, "keep-alive") == 0) { if (userFlags & MPR_HTTP_KEEP_ALIVE) { flags |= MPR_HTTP_KEEP_ALIVE; } #endif } } else if (strcmp("transfer-encoding", key) == 0) { mprStrLower(value); if (strcmp(value, "chunked") == 0) { flags |= MPR_HTTP_INPUT_CHUNKED; } } return 0; }
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; }
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; }
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; }