/* * Public routine to set the error message. Caller MUST NOT free. */ char *ejsGetErrorMsg(Ejs *ejs, int withStack) { EjsVar *message, *stack, *error; cchar *name; char *buf; if (ejs->flags & EJS_FLAG_EMPTY) { return ""; } error = (EjsVar*) ejs->exception; message = stack = 0; name = 0; if (error) { name = error->type->qname.name; if (ejsIsA(ejs, error, ejs->errorType)) { message = ejsGetProperty(ejs, error, ES_Error_message); stack = ejsGetProperty(ejs, error, ES_Error_stack); } else if (ejsIsString(error)) { name = "Details"; message = error; } else if (error == (EjsVar*) ejs->stopIterationType) { name = "StopIteration"; message = (EjsVar*) ejsCreateString(ejs, "Uncaught StopIteration exception"); } } if (!withStack) { stack = 0; } if (stack && ejsIsString(stack) && message && ejsIsString(message)){ mprAllocSprintf(ejs, &buf, 0, "%s Exception: %s\nStack:\n%s", name, ((EjsString*) message)->value, ((EjsString*) stack)->value); } else if (message && ejsIsString(message)){ mprAllocSprintf(ejs, &buf, 0, "%s: %s", name, ((EjsString*) message)->value); } else { if (error) { buf = mprStrdup(ejs, "Unknown exception object type"); } else { buf = mprStrdup(ejs, ""); } } mprFree(ejs->errorMsg); ejs->errorMsg = buf; return buf; }
void mprBreakpoint(const char *file, int line, const char *cond) { char *buf; mprAllocSprintf(&buf, MPR_MAX_STRING, "esp exception - ASSERT at %s:%d, %s\n", file, line, cond); ejs_exception(buf); }
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); }
/* * Format the stack backtrace */ char *ejsFormatStack(Ejs *ejs) { EjsFrame *frame; EjsType *type; EjsFunction *fun; cchar *typeName, *functionName, *line, *typeSep, *codeSep; char *backtrace, *traceLine; int level, len; mprAssert(ejs); backtrace = 0; len = 0; level = 0; for (frame = ejs->frame; frame; frame = frame->caller) { if (frame->currentLine == 0) { line = ""; } else { for (line = frame->currentLine; *line && isspace((int) *line); line++) { ; } } typeName = ""; functionName = "global"; fun = &frame->function; if (fun) { if (fun->owner) { functionName = ejsGetPropertyName(ejs, fun->owner, fun->slotNum).name; } if (ejsIsType(fun->owner)) { type = (EjsType*) fun->owner; if (type) { typeName = type->qname.name; } } } typeSep = (*typeName) ? "." : ""; codeSep = (*line) ? "->" : ""; if (mprAllocSprintf(ejs, &traceLine, MPR_MAX_STRING, " [%02d] %s, %s%s%s, line %d %s %s\n", level++, frame->fileName ? frame->fileName : "script", typeName, typeSep, functionName, frame->lineNumber, codeSep, line) < 0) { break; } backtrace = (char*) mprRealloc(ejs, backtrace, len + (int) strlen(traceLine) + 1); if (backtrace == 0) { return 0; } memcpy(&backtrace[len], traceLine, strlen(traceLine) + 1); len += (int) strlen(traceLine); mprFree(traceLine); } return backtrace; }
static EjsVar *castVar(Ejs *ejs, EjsVar *vp, EjsType *toType) { EjsString *result; char *buf; /* * TODO - should support cast to Boolean and Number */ mprAllocSprintf(ejs, &buf, 0, "[object %s]", vp->type->qname.name); result = ejsCreateString(ejs, buf); mprFree(buf); return (EjsVar*) result; }
static void setEnv(MaConn *conn) { MaRequest *req; MaResponse *resp; MaStage *handler; MprFileInfo *info; req = conn->request; resp = conn->response; handler = resp->handler; setPathInfo(conn); if (resp->extension == 0) { resp->extension = getExtension(conn); } if (resp->filename == 0) { resp->filename = makeFilename(conn, req->alias, req->url, 1); } if ((resp->mimeType = (char*) maLookupMimeType(conn->host, resp->extension)) == 0) { resp->mimeType = (char*) "text/html"; } if (!(resp->handler->flags & MA_STAGE_VIRTUAL)) { /* * Define an Etag for physical entities. Redo the file info if not valid now that extra path has been removed. */ info = &resp->fileInfo; if (!info->valid) { mprGetFileInfo(conn, resp->filename, info); } if (info->valid) { mprAllocSprintf(resp, &resp->etag, -1, "%x-%Lx-%Lx", info->inode, info->size, info->mtime); } } if (handler->flags & MA_STAGE_FORM_VARS) { req->formVars = mprCreateHash(req, MA_VAR_HASH_SIZE); if (req->parsedUri->query) { maAddFormVars(conn, req->parsedUri->query, (int) strlen(req->parsedUri->query)); } } if (handler->flags & MA_STAGE_ENV_VARS) { maCreateEnvVars(conn); } }
static int configureViaFile() { char *path; mprAllocSprintf(&path, MPR_MAX_FNAME, "%s/%s", serverRoot, configFile); mprLog(MPR_CONFIG, "Using configuration file: \n" " \"%s\"\n", path); // // Configure the http service and hosts specified in the config file. // if (server->configure(path) < 0) { mprError(MPR_L, MPR_USER, "Can't configure server using %s", path); mprFree(path); return MPR_ERR_CANT_INITIALIZE; } mprFree(path); return 0; }
static int buildScript(EspRequest *ep, char **jsBuf, char *input, char **errMsg) { EspParse parse; char path[MPR_MAX_FNAME], dir[MPR_MAX_FNAME], incPath[MPR_MAX_FNAME]; char *incBuf, *incText; int state, tid, len, rc, maxScriptSize, incSize; mprAssert(ep); mprAssert(jsBuf); mprAssert(input); rc = 0; len = 0; state = ESP_STATE_BEGIN; if (errMsg) { *errMsg = 0; } memset(&parse, 0, sizeof(parse)); parse.token = (char*) mprMalloc(ESP_TOK_INCR); if (parse.token == 0) { return MPR_ERR_CANT_ALLOCATE; } parse.token[0] = '\0'; parse.tokLen = ESP_TOK_INCR; parse.endp = &parse.token[parse.tokLen - 1]; parse.tokp = parse.token; parse.inBuf = input; parse.inp = parse.inBuf; maxScriptSize = esp->maxScriptSize; tid = getEspToken(state, &parse); while (tid != ESP_TOK_EOF && len >= 0) { switch (tid) { default: case ESP_TOK_ERR: mprFree(parse.token); return MPR_ERR_BAD_SYNTAX; case ESP_TOK_LITERAL: len = mprReallocStrcat(jsBuf, maxScriptSize, len, 0, "write(\"", parse.token, "\");\n", (void*) 0); break; case ESP_TOK_ATAT: /* * Trick to get undefined variables to evaluate to "". * Catenate with "" to cause toString to run. */ len = mprReallocStrcat(jsBuf, maxScriptSize, len, 0, "write(\"\" + ", parse.token, ");\n", (void*) 0); break; case ESP_TOK_EQUALS: len = mprReallocStrcat(jsBuf, maxScriptSize, len, 0, "write(\"\" + ", parse.token, ");\n", (void*) 0); state = ESP_STATE_IN_ESP_TAG; break; case ESP_TOK_START_ESP: state = ESP_STATE_IN_ESP_TAG; tid = getEspToken(state, &parse); while (tid != ESP_TOK_EOF && tid != ESP_TOK_EOF && tid != ESP_TOK_END_ESP && len >= 0) { len = mprReallocStrcat(jsBuf, maxScriptSize, len, 0, parse.token, (void*) 0); tid = getEspToken(state, &parse); } state = ESP_STATE_BEGIN; break; case ESP_TOK_END_ESP: state = ESP_STATE_BEGIN; break; case ESP_TOK_INCLUDE: if (parse.token[0] == '/') { mprStrcpy(incPath, sizeof(incPath), parse.token); } else { mprGetDirName(dir, sizeof(dir), ep->uri); mprSprintf(incPath, sizeof(incPath), "%s/%s", dir, parse.token); } if (esp->mapToStorage(ep->requestHandle, path, sizeof(path), incPath, 0) < 0) { mprAllocSprintf(errMsg, MPR_MAX_STRING, "Can't find include file: %s", path); rc = MPR_ERR_CANT_OPEN; break; } if (esp->readFile(ep->requestHandle, &incText, &incSize, path) < 0) { mprAllocSprintf(errMsg, MPR_MAX_STRING, "Can't read include file: %s", path); rc = MPR_ERR_CANT_READ; break; } incText[incSize] = '\0'; /* * Recurse and process the include script */ incBuf = 0; if ((rc = buildScript(ep, &incBuf, incText, errMsg)) < 0) { mprFree(incText); mprFree(parse.token); return rc; } len = mprReallocStrcat(jsBuf, maxScriptSize, len, 0, incBuf, (void*) 0); mprFree(incText); mprFree(incBuf); state = ESP_STATE_IN_ESP_TAG; break; } tid = getEspToken(state, &parse); } mprFree(parse.token); if (len < 0) { mprAllocSprintf(errMsg, MPR_MAX_STRING, "Script token is too big in %s.\nConfigured maximum is %d.", path, maxScriptSize); return MPR_ERR_WONT_FIT; } return rc; }
static int configureViaApi() { MaHostAddress *address; MaHost *host; MprList *listens; MaListen *lp; MprHashTable *hostAddresses; MaDir *dir; MaAlias *ap; MaLocation *loc; char *cp, *docRootPath; char addrBuf[MPR_MAX_IP_ADDR_PORT], pathBuf[MPR_MAX_FNAME]; int port; mprLog(MPR_CONFIG, "Configuration via Command Line\n"); #if BLD_FEATURE_ROMFS mprLog(MPR_CONFIG, "Server Root \"%s\" in ROM\n", serverRoot); docRootPath = mprStrdup(docRoot); #else // // Set the document root. Is relative to the server root unless an absolute path is used. // #if WIN if (*docRoot != '/' && docRoot[1] != ':' && docRoot[2] != '/') #elif WINCE if (*docRoot != '\\' && docRoot != '/') #else if (*docRoot != '/') #endif { if (*docRoot) { mprAllocSprintf(&docRootPath, MPR_MAX_FNAME, "%s/%s", serverRoot, docRoot); } else { docRootPath = mprStrdup(serverRoot); } } else { docRootPath = mprStrdup(docRoot); } #endif // BLD_FEATURE_ROMFS mprLog(MPR_CONFIG, "Document Root \"%s\"\n", docRootPath); // // Setup the listening addresses. If only a port is specified, listen on // all interfaces. If only the IP address is specified without a port, // then default to port 80. IF autoScan is on, scan for a free port // starting from the base address. // listens = server->getListens(); port = MA_SERVER_DEFAULT_PORT_NUM; if ((cp = strchr(ipAddr, ':')) != 0) { *cp++ = '\0'; port = atoi(cp); if (port <= 0 || port > 65535) { mprError(MPR_L, MPR_USER, "Bad listen port number %d", port); return MPR_ERR_BAD_SYNTAX; } if (autoScan) { port = findFreePort(ipAddr, port); } listens->insert(new MaListen(ipAddr, port, 0)); } else { if (isdigit((uchar) *ipAddr) && strchr(ipAddr, '.') == 0) { port = atoi(ipAddr); if (port <= 0 || port > 65535) { mprError(MPR_L, MPR_USER, "Bad listen port number %d", port); return MPR_ERR_BAD_SYNTAX; } if (autoScan) { port = findFreePort("", port); } listens->insert(new MaListen("", port)); } else { if (autoScan) { port = findFreePort(ipAddr, MA_SERVER_DEFAULT_PORT_NUM); } listens->insert(new MaListen(ipAddr, port)); } } mprFree(ipAddr); ipAddr = 0; host = server->newHost(docRootPath); if (host == 0) { return MPR_ERR_CANT_OPEN; } // // Add the default server listening addresses to the HostAddress hash. // FUTURE -- this should be moved into newHost // hostAddresses = server->getHostAddresses(); lp = (MaListen*) listens->getFirst(); while (lp) { mprSprintf(addrBuf, sizeof(addrBuf), "%s:%d", lp->getIpAddr(), lp->getPort()); address = (MaHostAddress*) hostAddresses->lookup(addrBuf); if (address == 0) { address = new MaHostAddress(addrBuf); hostAddresses->insert(address); } mprLog(MPR_CONFIG, "Listening for HTTP on %s\n", addrBuf); address->insertVhost(new MaVhost(host)); lp = (MaListen*) listens->getNext(lp); mprFree(ipAddr); ipAddr = mprStrdup(addrBuf); } // // Setup a module search path that works for production and developement. // #if BLD_FEATURE_DLL char searchPath[MPR_MAX_FNAME]; mprSprintf(searchPath, sizeof(searchPath), "./lib ../lib ../lib/modules ../../lib ../../lib/modules %s/lib", BLD_PREFIX); host->setModuleDirs(searchPath); #endif // // Load all possible modules // #if BLD_FEATURE_AUTH_MODULE // // Handler must be added first to authorize all requests. // if (server->loadModule("auth") == 0) { host->addHandler("authHandler", ""); } #endif #if BLD_FEATURE_UPLOAD_MODULE // // Must be after auth and before ESP, EGI. // if (server->loadModule("upload") == 0) { host->addHandler("uploadHandler", ""); } #endif #if BLD_FEATURE_CGI_MODULE if (server->loadModule("cgi") == 0) { host->addHandler("cgiHandler", ".cgi .cgi-nph .bat .cmd .pl .py"); } #endif #if BLD_FEATURE_EGI_MODULE if (server->loadModule("egi") == 0) { host->addHandler("egiHandler", ".egi"); } #endif #if BLD_FEATURE_ESP_MODULE if (server->loadModule("esp") == 0) { host->addHandler("espHandler", ".esp .asp"); } #endif #if BLD_FEATURE_C_API_MODULE server->loadModule("capi"); #endif #if BLD_FEATURE_GACOMPAT_MODULE server->loadModule("compat"); #endif #if BLD_FEATURE_SSL_MODULE server->loadModule("ssl"); #endif // // Only load one of matrixSsl / openssl // #if BLD_FEATURE_OPENSSL_MODULE server->loadModule("openSsl"); #elif BLD_FEATURE_MATRIXSSL_MODULE server->loadModule("matrixSsl"); #endif #if BLD_FEATURE_PHP5_MODULE if (server->loadModule("php5") == 0) { host->addHandler("php5Handler", ".php"); } #endif #if BLD_FEATURE_COPY_MODULE // // Handler must be added last to be the catch all // if (server->loadModule("copy") == 0) { host->addHandler("copyHandler", ""); } #endif // // Create the top level directory // dir = new MaDir(host); dir->setPath(docRootPath); host->insertDir(dir); // // Add cgi-bin // mprSprintf(pathBuf, sizeof(pathBuf), "%s/cgi-bin", serverRoot); ap = new MaAlias("/cgi-bin/", pathBuf); mprLog(4, "ScriptAlias \"/cgi-bin/\":\n\t\t\t\"%s\"\n", pathBuf); host->insertAlias(ap); loc = new MaLocation(dir->getAuth()); loc->setPrefix("/cgi-bin/"); loc->setHandler("cgiHandler"); host->insertLocation(loc); mprFree(docRootPath); return 0; }
static int parseUrl(MaConn *conn) { EjsWeb *web; EjsWebControl *control; MaRequest *req; MaResponse *resp; MaAlias *alias; MaLocation *location; char *baseDir, *cp, *url, *baseUrl; int flags, locFlags; resp = conn->response; req = conn->request; alias = req->alias; location = req->location; locFlags = location->flags; url = req->url; flags = 0; if (locFlags & MA_LOC_APP_DIR) { flags |= EJS_WEB_FLAG_APP; mprAllocSprintf(resp, &baseDir, -1, "%s%s", alias->filename, &req->url[alias->prefixLen]); if ((cp = strchr(&baseDir[strlen(alias->filename) + 1], '/')) != 0) { *cp = '\0'; } mprAllocSprintf(resp, &baseUrl, -1, "%s%s", alias->prefix, &req->url[alias->prefixLen]); if ((cp = strchr(&baseUrl[alias->prefixLen + 1], '/')) != 0) { *cp = '\0'; } if (*url) { /* Step over the directory and app name */ while (*++url != '/') ; if (*url) { while (*++url != '/') ; } } } else { if (locFlags & MA_LOC_APP) { flags |= EJS_WEB_FLAG_APP; } baseDir = alias->filename; if (alias->prefixLen > 0) { /* Step over the application name (same as alias prefix) */ url = &url[alias->prefixLen]; if (*url != '/' && url[-1] == '/') { url--; } } baseUrl = alias->prefix; } if (location->flags & MA_LOC_BROWSER) { flags |= EJS_WEB_FLAG_BROWSER_ERRORS; } if (location->flags & MA_LOC_AUTO_SESSION) { flags |= EJS_WEB_FLAG_SESSION; } control = conn->http->ejsHandler->stageData; web = ejsCreateWebRequest(req, control, conn, baseUrl, url, baseDir, flags); if (web == 0) { maFailRequest(conn, MPR_HTTP_CODE_INTERNAL_SERVER_ERROR, "Can't create Ejs web object for %s", req->url); return EJS_ERR; } resp->handlerData = web; return 0; }
int MaCgiHandler::run(MaRequest *rq) { MprVar *vp, *variables; char **argv, **envv, **ep, *fileName, *baseName; int i, index, argc, numItems; if (rq->getFlags() & MPR_HTTP_POST_REQUEST && rq->getRemainingContent() > 0) { // // When all the post data is received the run method will be recalled // by the postData method. // return MPR_HTTP_HANDLER_FINISHED_PROCESSING; } argv = 0; variables = 0; argc = 0; hitCount++; rq->setResponseCode(200); rq->setHeaderFlags(MPR_HTTP_DONT_CACHE, 0); rq->insertDataStream(rq->getDynBuf()); // // Build the commmand line arguments // argc = 1; // argv[0] == programName buildArgs(&argc, &argv, cmd, rq); fileName = argv[0]; rq->setResponseMimeType("text/html"); baseName = mprGetBaseName(fileName); if (strncmp(baseName, "nph-", 4) == 0) { cgiFlags |= MPR_CGI_NON_PARSED_HEADER; } if (strlen(baseName) > 4 && strcmp(&baseName[strlen(baseName) - 4], "-nph") == 0) { cgiFlags |= MPR_CGI_NON_PARSED_HEADER; } // // Build environment variables // variables = rq->getVariables(); numItems = rq->getNumEnvProperties() + 1; // // Export the PATH and LD_LIBRARY_PATH also if Unix // #if BLD_HOST_UNIX numItems += 2; #endif envv = (char**) mprMalloc((numItems + 1) * sizeof(char*)); index = 0; for (i = 0; i < MA_HTTP_OBJ_MAX; i++) { if (variables[i].type == MPR_TYPE_OBJECT) { vp = mprGetFirstProperty(&variables[i], MPR_ENUM_DATA); while (vp) { mprAllocSprintf(&envv[index], MPR_HTTP_MAX_HEADER, "%s=%s", vp->name, vp->string); index++; vp = mprGetNextProperty(&variables[i], vp, MPR_ENUM_DATA); } } } #if BLD_HOST_UNIX { char *cp; if ((cp = getenv("PATH")) != 0) { mprAllocSprintf(&envv[index++], MPR_MAX_FNAME, "PATH=%s", cp); } if ((cp = getenv("LD_LIBRARY_PATH")) != 0) { mprAllocSprintf(&envv[index++], MPR_MAX_FNAME, "LD_LIBRARY_PATH=%s", cp); } } #endif mprAllocSprintf(&envv[index++], MPR_MAX_FNAME, "REDIRECT_STATUS=302"); envv[index] = 0; mprAssert(index <= numItems); mprLog(4, log, "%d: running program: %s\n", rq->getFd(), fileName); if (cmd->start(fileName, argv, envv, cgiOutputData, (void*) rq, MPR_CMD_CHDIR) < 0) { rq->requestError(503, "Can't run CGI process: %s, URI %s", rq->getScriptName(), rq->getOriginalUri()); rq->finishRequest(); goto exit; } exit: for (i = 0; i < argc; i++) { mprFree(argv[i]); } for (ep = envv; *ep; ep++) { mprFree(*ep); } mprFree(argv); mprFree(envv); return MPR_HTTP_HANDLER_FINISHED_PROCESSING; }