PUBLIC void httpNetError(HttpNet *net, cchar *fmt, ...) { va_list args; HttpStream *stream; cchar *msg; int next; if (net == 0 || fmt == 0) { return; } va_start(args, fmt); if (!net->error) { net->error = 1; net->errorMsg = msg = sfmtv(fmt, args); #if ME_HTTP_HTTP2 if (net->protocol >= 2 && !net->eof) { httpSendGoAway(net, HTTP2_INTERNAL_ERROR, "%s", msg); } #endif if (httpIsServer(net)) { for (ITERATE_ITEMS(net->streams, stream, next)) { httpError(stream, HTTP_ABORT | HTTP_CODE_COMMS_ERROR, "%s", msg); } // TODO httpMonitorNetEvent(net, HTTP_COUNTER_BAD_REQUEST_ERRORS, 1); } }
static void cleanUploadedFiles(HttpConn *conn) { HttpRx *rx; HttpUploadFile *file; cchar *path, *uploadDir; int index; rx = conn->rx; uploadDir = getUploadDir(rx->route); for (ITERATE_ITEMS(rx->files, file, index)) { if (file->filename) { if (rx->autoDelete) { mprDeletePath(file->filename); } else if (rx->renameUploads) { path = mprJoinPath(uploadDir, file->clientFilename); if (rename(file->filename, path) != 0) { mprLog("http error", 0, "Cannot rename %s to %s", file->filename, path); } } file->filename = 0; } } }
/* Start the command to run (stdIn and stdOut are named from the client's perspective) */ PUBLIC int startProcess(MprCmd *cmd) { MprCmdTaskFn entryFn; MprModule *mp; char *entryPoint, *program, *pair; int pri, next; mprLog("info mpr cmd", 4, "Program %s", cmd->program); entryPoint = 0; if (cmd->env) { for (ITERATE_ITEMS(cmd->env, pair, next)) { if (sncmp(pair, "entryPoint=", 11) == 0) { entryPoint = sclone(&pair[11]); } } } program = mprGetPathBase(cmd->program); if (entryPoint == 0) { program = mprTrimPathExt(program); entryPoint = program; } #if ME_CPU_ARCH == MPR_CPU_IX86 || ME_CPU_ARCH == MPR_CPU_IX64 || ME_CPU_ARCH == MPR_CPU_SH /* A leading underscore is required on some architectures */ entryPoint = sjoin("_", entryPoint, NULL); #endif if (mprFindVxSym(sysSymTbl, entryPoint, (char**) (void*) &entryFn) < 0) { if ((mp = mprCreateModule(cmd->program, cmd->program, NULL, NULL)) == 0) { mprLog("error mpr cmd", 0, "Cannot create module"); return MPR_ERR_CANT_CREATE; } if (mprLoadModule(mp) < 0) { mprLog("error mpr cmd", 0, "Cannot load DLL %s, errno %d", program, mprGetOsError()); return MPR_ERR_CANT_READ; } if (mprFindVxSym(sysSymTbl, entryPoint, (char**) (void*) &entryFn) < 0) { mprLog("error mpr cmd", 0, "Cannot find symbol %s, errno %d", entryPoint, mprGetOsError()); return MPR_ERR_CANT_ACCESS; } } taskPriorityGet(taskIdSelf(), &pri); cmd->pid = taskSpawn(entryPoint, pri, VX_FP_TASK | VX_PRIVATE_ENV, ME_STACK_SIZE, (FUNCPTR) cmdTaskEntry, (int) cmd->program, (int) entryFn, (int) cmd, 0, 0, 0, 0, 0, 0, 0); if (cmd->pid < 0) { mprLog("error mpr cmd", 0, "Cannot create task %s, errno %d", entryPoint, mprGetOsError()); return MPR_ERR_CANT_CREATE; } if (semTake(cmd->startCond, MPR_TIMEOUT_START_TASK) != OK) { mprLog("error mpr cmd", 0, "Child %s did not initialize, errno %d", cmd->program, mprGetOsError()); return MPR_ERR_CANT_CREATE; } semDelete(cmd->startCond); cmd->startCond = 0; return 0; }
PUBLIC int maSetPlatform(cchar *platformPath) { MaAppweb *appweb; MprDirEntry *dp; cchar *platform, *dir, *junk, *appwebExe; int next, i, notrace; appweb = MPR->appwebService; notrace = !platformPath; if (!platformPath) { platformPath = appweb->localPlatform; } appweb->platform = appweb->platformDir = 0; platform = mprGetPathBase(platformPath); if (mprPathExists(platformPath, X_OK) && mprIsPathDir(platformPath)) { appweb->platform = platform; appweb->platformDir = sclone(platformPath); } else if (smatch(platform, appweb->localPlatform)) { /* If running inside an appweb source tree, locate the platform directory */ appwebExe = mprJoinPath(mprGetAppDir(), "appweb" BIT_EXE); if (mprPathExists(appwebExe, R_OK)) { appweb->platform = appweb->localPlatform; appweb->platformDir = mprGetPathParent(mprGetAppDir()); } else { /* Check installed appweb */ appwebExe = BIT_VAPP_PREFIX "/bin/appweb" BIT_EXE; if (mprPathExists(appwebExe, R_OK)) { appweb->platform = appweb->localPlatform; appweb->platformDir = sclone(BIT_VAPP_PREFIX); } } } /* Last chance. Search up the tree for a similar platform directory. This permits specifying a partial platform like "vxworks" without architecture and profile. */ if (!appweb->platformDir) { dir = mprGetCurrentPath(); for (i = 0; !mprSamePath(dir, "/") && i < 64; i++) { for (ITERATE_ITEMS(mprGetPathFiles(dir, 0), dp, next)) { if (dp->isDir && sstarts(mprGetPathBase(dp->name), platform)) { appweb->platform = mprGetPathBase(dp->name); appweb->platformDir = mprJoinPath(dir, dp->name); break; } } dir = mprGetPathParent(dir); } }
/* The base procedure is invoked prior to calling any and all actions on this route */ PUBLIC void espDefineBase(HttpRoute *route, EspProc baseProc) { HttpRoute *rp; EspRoute *eroute, *er; int next; eroute = route->eroute; for (ITERATE_ITEMS(route->host->routes, rp, next)) { if ((er = route->eroute) != 0 && smatch(er->controllersDir, eroute->controllersDir)) { er->commonController = baseProc; } } }
void httpStopEndpoint(HttpEndpoint *endpoint) { HttpHost *host; int next; for (ITERATE_ITEMS(endpoint->hosts, host, next)) { httpStopHost(host); } if (endpoint->sock) { mprCloseSocket(endpoint->sock, 0); endpoint->sock = 0; } }
static EdiGrid *mdbReadWhere(Edi *edi, cchar *tableName, cchar *columnName, cchar *operation, cchar *value) { Mdb *mdb; EdiGrid *grid; MdbTable *table; MdbCol *col; MdbRow *row; int nrows, next, op, r, count; assert(edi); assert(tableName && *tableName); mdb = (Mdb*) edi; lock(mdb); if ((table = lookupTable(mdb, tableName)) == 0) { unlock(mdb); return 0; } nrows = mprGetListLength(table->rows); if ((grid = ediCreateBareGrid(edi, tableName, nrows)) == 0) { unlock(mdb); return 0; } grid->flags = EDI_GRID_READ_ONLY; if (columnName) { if ((col = lookupColumn(table, columnName)) == 0) { unlock(mdb); return 0; } if ((op = parseOperation(operation)) < 0) { unlock(mdb); return 0; } if (col->flags & EDI_INDEX && (op & OP_EQ)) { if ((r = lookupRow(table, value)) != 0) { row = getRow(table, r); grid->records[0] = createRecFromRow(edi, row); grid->nrecords = 1; } } else { grid->nrecords = count = 0; for (ITERATE_ITEMS(table->rows, row, next)) { if (!matchRow(col, row->fields[col->cid], op, value)) { continue; } grid->records[count++] = createRecFromRow(edi, row); grid->nrecords = count; } } } else { for (ITERATE_ITEMS(table->rows, row, next)) {
/* The base procedure is invoked prior to calling any and all actions on this route */ PUBLIC void espDefineBase(HttpRoute *route, EspProc baseProc) { HttpRoute *rp; EspRoute *eroute; int next; for (ITERATE_ITEMS(route->host->routes, rp, next)) { if ((eroute = route->eroute) != 0) { if (smatch(httpGetDir(rp, "CONTROLLERS"), httpGetDir(route, "CONTROLLERS"))) { eroute->commonController = baseProc; } } } }
static int blendEnv(MprCmd *cmd, cchar **env, int flags) { cchar **ep, *prior; int next; cmd->env = 0; if ((cmd->env = mprCreateList(128, MPR_LIST_STATIC_VALUES | MPR_LIST_STABLE)) == 0) { return MPR_ERR_MEMORY; } #if !VXWORKS /* Add prior environment to the list */ if (!(flags & MPR_CMD_EXACT_ENV)) { for (ep = (cchar**) environ; ep && *ep; ep++) { #if MACOSX if (sstarts(*ep, "DYLD_LIBRARY_PATH=")) { continue; } #endif mprAddItem(cmd->env, *ep); } } #endif /* Add new env keys. Detect and overwrite duplicates */ for (ep = env; ep && *ep; ep++) { prior = 0; for (ITERATE_ITEMS(cmd->env, prior, next)) { if (matchEnvKey(*ep, prior)) { mprSetItem(cmd->env, next - 1, *ep); break; } } if (prior == 0) { mprAddItem(cmd->env, *ep); } } #if ME_WIN_LIKE /* Windows requires a caseless sort with two trailing nulls */ mprSortList(cmd->env, (MprSortProc) sortEnv, 0); #endif mprAddItem(cmd->env, NULL); return 0; }
void ejsRemoveModuleFromAll(EjsModule *mp) { Ejs *ejs; EjsService *sp; int next; if ((sp = MPR->ejsService) == 0) { return; } lock(sp); for (ITERATE_ITEMS(sp->vmlist, ejs, next)) { mprRemoveItem(ejs->modules, mp); } unlock(sp); }
static cchar *makeWinEnvBlock(MprCmd *cmd) { char *item, *dp, *ep, *env; ssize len; int next; for (len = 2, ITERATE_ITEMS(cmd->env, item, next)) { len += slen(item) + 1; } if ((env = mprAlloc(len)) == 0) { return 0; } ep = &env[len]; dp = env; for (ITERATE_ITEMS(cmd->env, item, next)) { strcpy(dp, item); dp += slen(item) + 1; } /* Windows requires two nulls */ *dp++ = '\0'; *dp++ = '\0'; assert(dp <= ep); return env; }
static MprWaitHandler *initWaitHandler(MprWaitHandler *wp, int fd, int mask, MprDispatcher *dispatcher, void *proc, void *data, int flags) { MprWaitService *ws; assert(fd >= 0); ws = MPR->waitService; #if ME_DEBUG { MprWaitHandler *op; int index; for (ITERATE_ITEMS(ws->handlers, op, index)) { if (op->fd == fd) { mprLog("error mpr event", 0, "Duplicate fd in wait handlers"); } } } #endif wp->fd = fd; wp->notifierIndex = -1; wp->dispatcher = dispatcher; wp->proc = proc; wp->flags = 0; wp->handlerData = data; wp->service = ws; wp->flags = flags; if (mprGetListLength(ws->handlers) >= FD_SETSIZE) { mprLog("error mpr event", 0, "Too many io handlers: %d", FD_SETSIZE); return 0; } #if ME_UNIX_LIKE || VXWORKS #if ME_EVENT_NOTIFIER == MPR_EVENT_SELECT if (fd >= FD_SETSIZE) { mprLog("error mpr event", 0, "File descriptor %d exceeds max io of %d", fd, FD_SETSIZE); } #endif #endif if (mask) { if (mprAddItem(ws->handlers, wp) < 0) { return 0; } mprNotifyOn(wp, mask); } return wp; }
/* Event callback. Invoked for incoming web socket messages and other events of interest. */ static void chat_callback(HttpConn *conn, int event, int arg) { HttpPacket *packet; HttpConn *client; Msg *msg; int next; if (event == HTTP_EVENT_READABLE) { packet = httpGetPacket(conn->readq); if (packet->type == WS_MSG_TEXT || packet->type == WS_MSG_BINARY) { for (ITERATE_ITEMS(clients, client, next)) { msg = mprAllocObj(Msg, manageMsg); msg->conn = client; msg->packet = packet; mprCreateEvent(client->dispatcher, "chat", 0, chat, msg, 0); } } } else if (event == HTTP_EVENT_APP_CLOSE) {
static void filterDirList(HttpConn *conn, MprList *list) { Dir *dir; MprDirEntry *dp; int next; dir = conn->data; /* Do pattern matching. Entries that don't match, free the name to mark */ for (ITERATE_ITEMS(list, dp, next)) { if (!matchDirPattern(dir->pattern, dp->name)) { mprRemoveItem(list, dp); next--; } } }
PUBLIC int httpStartEndpoints() { HttpEndpoint *endpoint; int next; if (!HTTP) { return MPR_ERR_BAD_STATE; } for (ITERATE_ITEMS(HTTP->endpoints, endpoint, next)) { if (httpStartEndpoint(endpoint) < 0) { return MPR_ERR_CANT_OPEN; } } if (httpApplyUserGroup() < 0) { httpStopEndpoints(); return MPR_ERR_CANT_OPEN; } return 0; }
int httpStartEndpoint(HttpEndpoint *endpoint) { HttpHost *host; cchar *proto, *ip; int next; if (!validateEndpoint(endpoint)) { return MPR_ERR_BAD_ARGS; } for (ITERATE_ITEMS(endpoint->hosts, host, next)) { httpStartHost(host); } if ((endpoint->sock = mprCreateSocket(endpoint->ssl)) == 0) { return MPR_ERR_MEMORY; } if (mprListenOnSocket(endpoint->sock, endpoint->ip, endpoint->port, MPR_SOCKET_NODELAY | MPR_SOCKET_THREAD) < 0) { mprError("Can't open a socket on %s:%d", *endpoint->ip ? endpoint->ip : "*", endpoint->port); return MPR_ERR_CANT_OPEN; } if (endpoint->http->listenCallback && (endpoint->http->listenCallback)(endpoint) < 0) { return MPR_ERR_CANT_OPEN; } if (endpoint->async && !endpoint->sock->handler) { mprAddSocketHandler(endpoint->sock, MPR_SOCKET_READABLE, endpoint->dispatcher, httpAcceptConn, endpoint, (endpoint->dispatcher) ? 0 : MPR_WAIT_NEW_DISPATCHER); } else { mprSetSocketBlockingMode(endpoint->sock, 1); } proto = endpoint->ssl ? "HTTPS" : "HTTP "; ip = *endpoint->ip ? endpoint->ip : "*"; if (mprIsSocketV6(endpoint->sock)) { mprLog(2, "Started %s service on \"[%s]:%d\"", proto, ip, endpoint->port); } else { mprLog(2, "Started %s service on \"%s:%d\"", proto, ip, endpoint->port); } return 0; }
/* Set headers for httpWriteHeaders. This defines standard headers. */ static void setHeaders(HttpConn *conn, HttpPacket *packet) { HttpRx *rx; HttpTx *tx; HttpRoute *route; HttpRange *range; MprKeyValue *item; MprOff length; cchar *mimeType; int next; assert(packet->flags == HTTP_PACKET_HEADER); rx = conn->rx; tx = conn->tx; route = rx->route; /* Mandatory headers that must be defined here use httpSetHeader which overwrites existing values. */ httpAddHeaderString(conn, "Date", conn->http->currentDate); if (tx->ext && route) { if ((mimeType = (char*) mprLookupMime(route->mimeTypes, tx->ext)) != 0) { if (conn->error) { httpAddHeaderString(conn, "Content-Type", "text/html"); } else { httpAddHeaderString(conn, "Content-Type", mimeType); } } } if (tx->etag) { httpAddHeader(conn, "ETag", "%s", tx->etag); } length = tx->length > 0 ? tx->length : 0; if (rx->flags & HTTP_HEAD) { conn->tx->flags |= HTTP_TX_NO_BODY; httpDiscardData(conn, HTTP_QUEUE_TX); if (tx->chunkSize <= 0) { httpAddHeader(conn, "Content-Length", "%Ld", length); } } else if (tx->length < 0 && tx->chunkSize > 0) { httpSetHeaderString(conn, "Transfer-Encoding", "chunked"); } else if (conn->endpoint) { /* Server must not emit a content length header for 1XX, 204 and 304 status */ if (!((100 <= tx->status && tx->status <= 199) || tx->status == 204 || tx->status == 304 || tx->flags & HTTP_TX_NO_LENGTH)) { httpAddHeader(conn, "Content-Length", "%Ld", length); } } else if (tx->length > 0) { /* client with body */ httpAddHeader(conn, "Content-Length", "%Ld", length); } if (tx->outputRanges) { if (tx->outputRanges->next == 0) { range = tx->outputRanges; if (tx->entityLength > 0) { httpSetHeader(conn, "Content-Range", "bytes %Ld-%Ld/%Ld", range->start, range->end - 1, tx->entityLength); } else { httpSetHeader(conn, "Content-Range", "bytes %Ld-%Ld/*", range->start, range->end - 1); } } else { httpSetHeader(conn, "Content-Type", "multipart/byteranges; boundary=%s", tx->rangeBoundary); } httpSetHeader(conn, "Accept-Ranges", "bytes"); } if (conn->endpoint) { if (!(route->flags & HTTP_ROUTE_STEALTH)) { httpAddHeaderString(conn, "Server", conn->http->software); } /* If keepAliveCount == 1 */ if (--conn->keepAliveCount > 0) { assert(conn->keepAliveCount >= 1); httpAddHeaderString(conn, "Connection", "Keep-Alive"); httpAddHeader(conn, "Keep-Alive", "timeout=%Ld, max=%d", conn->limits->inactivityTimeout / 1000, conn->keepAliveCount); } else { /* Tell the peer to close the connection */ httpAddHeaderString(conn, "Connection", "close"); } if (route->flags & HTTP_ROUTE_CORS) { setCorsHeaders(conn); } /* Apply response headers */ for (ITERATE_ITEMS(route->headers, item, next)) { if (item->flags == HTTP_ROUTE_ADD_HEADER) { httpAddHeaderString(conn, item->key, item->value); } else if (item->flags == HTTP_ROUTE_APPEND_HEADER) { httpAppendHeaderString(conn, item->key, item->value); } else if (item->flags == HTTP_ROUTE_REMOVE_HEADER) { httpRemoveHeader(conn, item->key); } else if (item->flags == HTTP_ROUTE_SET_HEADER) { httpSetHeaderString(conn, item->key, item->value); } } } }
/* Start the command to run (stdIn and stdOut are named from the client's perspective). This is the lower-level way to run a command. The caller needs to do code like mprRunCmd() themselves to wait for completion and to send/receive data. The routine does not wait. Callers must call mprWaitForCmd to wait for the command to complete. */ PUBLIC int mprStartCmd(MprCmd *cmd, int argc, cchar **argv, cchar **envp, int flags) { MprPath info; cchar *pair; int rc, next, i; assert(cmd); assert(argv); if (argc <= 0 || argv == NULL || argv[0] == NULL) { return MPR_ERR_BAD_ARGS; } resetCmd(cmd, 0); cmd->flags = flags; cmd->argc = argc; cmd->argv = mprAlloc((argc + 1) * sizeof(char*)); for (i = 0; i < argc; i++) { cmd->argv[i] = sclone(argv[i]); } cmd->argv[i] = 0; prepWinProgram(cmd); if ((cmd->program = mprSearchPath(cmd->argv[0], MPR_SEARCH_EXE, cmd->searchPath, NULL)) == 0) { mprLog("error mpr cmd", 0, "Cannot access %s, errno %d", cmd->argv[0], mprGetOsError()); return MPR_ERR_CANT_ACCESS; } if (mprGetPathInfo(cmd->program, &info) == 0 && info.isDir) { mprLog("error mpr cmd", 0, "Program \"%s\", is a directory", cmd->program); return MPR_ERR_CANT_ACCESS; } mprLog("info mpr cmd", 6, "Program: %s", cmd->program); cmd->argv[0] = cmd->program; prepWinCommand(cmd); if (envp == 0) { envp = cmd->defaultEnv; } if (blendEnv(cmd, envp, flags) < 0) { return MPR_ERR_MEMORY; } for (i = 0; i < cmd->argc; i++) { mprLog("info mpr cmd", 6, " arg[%d]: %s", i, cmd->argv[i]); } for (ITERATE_ITEMS(cmd->env, pair, next)) { mprLog("info mpr cmd", 6, " env[%d]: %s", next, pair); } slock(cmd); if (makeCmdIO(cmd) < 0) { sunlock(cmd); return MPR_ERR_CANT_OPEN; } /* Determine how many end-of-files will be seen when the child dies */ cmd->requiredEof = 0; if (cmd->flags & MPR_CMD_OUT) { cmd->requiredEof++; } if (cmd->flags & MPR_CMD_ERR) { cmd->requiredEof++; } if (addCmdHandlers(cmd) < 0) { mprLog("error mpr cmd", 0, "Cannot open command handlers - insufficient I/O handles"); return MPR_ERR_CANT_OPEN; } rc = startProcess(cmd); cmd->originalPid = cmd->pid; mprAddItem(MPR->cmdService->cmds, cmd); sunlock(cmd); #if ME_WIN_LIKE if (!rc) { mprCreateTimerEvent(cmd->dispatcher, "pollWinTimer", 10, pollWinTimer, cmd, 0); } #endif return rc; }
/* Executed by the child process */ static void cmdTaskEntry(char *program, MprCmdTaskFn entry, int cmdArg) { MprCmd *cmd; MprCmdFile *files; WIND_TCB *tcb; char *item; int inFd, outFd, errFd, id, next; cmd = (MprCmd*) cmdArg; /* Open standard I/O files (in/out are from the server's perspective) */ files = cmd->files; inFd = open(files[MPR_CMD_STDIN].name, O_RDONLY, 0666); outFd = open(files[MPR_CMD_STDOUT].name, O_WRONLY, 0666); errFd = open(files[MPR_CMD_STDERR].name, O_WRONLY, 0666); if (inFd < 0 || outFd < 0 || errFd < 0) { exit(255); } id = taskIdSelf(); ioTaskStdSet(id, 0, inFd); ioTaskStdSet(id, 1, outFd); ioTaskStdSet(id, 2, errFd); /* Now that we have opened the stdin and stdout, wakeup our parent. */ semGive(cmd->startCond); /* Create the environment */ if (envPrivateCreate(id, -1) < 0) { exit(254); } for (ITERATE_ITEMS(cmd->env, item, next)) { putenv(item); } #if !VXWORKS { char *dir; int rc; /* Set current directory if required WARNING: Setting working directory on VxWorks is global */ if (cmd->dir) { rc = chdir(cmd->dir); } else { dir = mprGetPathDir(cmd->program); rc = chdir(dir); } if (rc < 0) { mprLog("error mpr cmd", 0, "Cannot change directory to %s", cmd->dir); exit(255); } } #endif /* Call the user's entry point */ (entry)(cmd->argc, (char**) cmd->argv, (char**) cmd->env); tcb = taskTcb(id); cmd->status = tcb->exitCode; /* Cleanup */ envPrivateDestroy(id); close(inFd); close(outFd); close(errFd); semGive(cmd->exitCond); }
PUBLIC int espEmail(HttpConn *conn, cchar *to, cchar *from, cchar *subject, MprTime date, cchar *mime, cchar *message, MprList *files) { MprList *lines; MprCmd *cmd; cchar *body, *boundary, *contents, *encoded, *file; char *out, *err; ssize length; int i, next, status; if (!from || !*from) { from = "anonymous"; } if (!subject || !*subject) { subject = "Mail message"; } if (!mime || !*mime) { mime = "text/plain"; } if (!date) { date = mprGetTime(); } boundary = sjoin("esp.mail=", mprGetMD5("BOUNDARY"), NULL); lines = mprCreateList(0, 0); mprAddItem(lines, sfmt("To: %s", to)); mprAddItem(lines, sfmt("From: %s", from)); mprAddItem(lines, sfmt("Date: %s", mprFormatLocalTime(0, date))); mprAddItem(lines, sfmt("Subject: %s", subject)); mprAddItem(lines, "MIME-Version: 1.0"); mprAddItem(lines, sfmt("Content-Type: multipart/mixed; boundary=%s", boundary)); mprAddItem(lines, ""); boundary = sjoin("--", boundary, NULL); mprAddItem(lines, boundary); mprAddItem(lines, sfmt("Content-Type: %s", mime)); mprAddItem(lines, ""); mprAddItem(lines, ""); mprAddItem(lines, message); for (ITERATE_ITEMS(files, file, next)) { mprAddItem(lines, boundary); if ((mime = mprLookupMime(NULL, file)) == 0) { mime = "application/octet-stream"; } mprAddItem(lines, "Content-Transfer-Encoding: base64"); mprAddItem(lines, sfmt("Content-Disposition: inline; filename=\"%s\"", mprGetPathBase(file))); mprAddItem(lines, sfmt("Content-Type: %s; name=\"%s\"", mime, mprGetPathBase(file))); mprAddItem(lines, ""); contents = mprReadPathContents(file, &length); encoded = mprEncode64Block(contents, length); for (i = 0; i < length; i += 76) { mprAddItem(lines, snclone(&encoded[i], i + 76)); } } mprAddItem(lines, sfmt("%s--", boundary)); body = mprListToString(lines, "\n"); httpTraceContent(conn, "esp.email", "context", body, slen(body), 0); cmd = mprCreateCmd(conn->dispatcher); if (mprRunCmd(cmd, "sendmail -t", NULL, body, &out, &err, -1, 0) < 0) { mprDestroyCmd(cmd); return MPR_ERR_CANT_OPEN; } if (mprWaitForCmd(cmd, ME_ESP_EMAIL_TIMEOUT) < 0) { httpTrace(conn, "esp.email.error", "error", "msg=\"Timeout waiting for command to complete\", timeout=%d, command=\"%s\"", ME_ESP_EMAIL_TIMEOUT, cmd->argv[0]); mprDestroyCmd(cmd); return MPR_ERR_CANT_COMPLETE; } if ((status = mprGetCmdExitStatus(cmd)) != 0) { httpTrace(conn, "esp.email.error", "error", "msg=\"Sendmail failed\", status=%d, error=\"%s\"", status, err); mprDestroyCmd(cmd); return MPR_ERR_CANT_WRITE; } mprDestroyCmd(cmd); return 0; }
/* Test if the request matches. This may delegate the request to the dirHandler if a directory listing is required. */ static int matchFileHandler(HttpConn *conn, HttpRoute *route, int dir) { HttpRx *rx; HttpTx *tx; HttpUri *prior; MprPath *info, zipInfo; cchar *index; char *path, *pathInfo, *uri, *zipfile; int next; printf("\n matchFileHandler \n"); rx = conn->rx; tx = conn->tx; rx = conn->rx; prior = rx->parsedUri; info = &tx->fileInfo; httpMapFile(conn, route); assure(info->checked); if (rx->flags & (HTTP_DELETE | HTTP_PUT)) { return HTTP_ROUTE_OK; } if (info->isDir) { /* Manage requests for directories */ if (!sends(rx->pathInfo, "/")) { /* Append "/" and do an external redirect */ pathInfo = sjoin(rx->pathInfo, "/", NULL); uri = httpFormatUri(prior->scheme, prior->host, prior->port, pathInfo, prior->reference, prior->query, 0); httpRedirect(conn, HTTP_CODE_MOVED_PERMANENTLY, uri); return HTTP_ROUTE_OK; } if (route->indicies) { /* Ends with a "/" so do internal redirection to an index file */ for (ITERATE_ITEMS(route->indicies, index, next)) { /* Internal directory redirections. Transparently append index. Test indicies in order. */ path = mprJoinPath(tx->filename, index); if (mprPathExists(path, R_OK)) { pathInfo = sjoin(rx->scriptName, rx->pathInfo, index, NULL); uri = httpFormatUri(prior->scheme, prior->host, prior->port, pathInfo, prior->reference, prior->query, 0); httpSetUri(conn, uri); tx->filename = path; tx->ext = httpGetExt(conn); mprGetPathInfo(tx->filename, info); return HTTP_ROUTE_REROUTE; } } } /* If a directory, test if a directory listing should be rendered. If so, delegate to the dirHandler. Cannot use the sendFile handler and must use the netConnector. */ if (info->isDir && maRenderDirListing(conn)) { tx->handler = conn->http->dirHandler; tx->connector = conn->http->netConnector; return HTTP_ROUTE_OK; } } if (!info->valid && (route->flags & HTTP_ROUTE_GZIP) && rx->acceptEncoding && strstr(rx->acceptEncoding, "gzip") != 0) { /* If the route accepts zipped data and a zipped file exists, then transparently respond with it. */ zipfile = sfmt("%s.gz", tx->filename); if (mprGetPathInfo(zipfile, &zipInfo) == 0) { tx->filename = zipfile; tx->fileInfo = zipInfo; httpSetHeader(conn, "Content-Encoding", "gzip"); } } if (rx->flags & (HTTP_GET | HTTP_HEAD | HTTP_POST) && info->valid && !info->isDir && tx->length < 0) { /* The sendFile connector is optimized on some platforms to use the sendfile() system call. Set the entity length for the sendFile connector to utilize. */ httpSetEntityLength(conn, tx->fileInfo.size); } printf("\n-------------------------\n"); printf("tx->filename:\t%s",tx->filename); printf("\n-------------------------\n"); return HTTP_ROUTE_OK; }
static int handleDirectory(HttpConn *conn) { HttpRx *rx; HttpTx *tx; HttpRoute *route; HttpUri *req; MprPath *info; cchar *index, *pathInfo, *uri; char *path; int next; rx = conn->rx; tx = conn->tx; req = rx->parsedUri; route = rx->route; info = &tx->fileInfo; /* Manage requests for directories */ if (!sends(req->path, "/")) { /* Append "/" and do an external redirect. Use the original request URI. */ pathInfo = sjoin(req->path, "/", NULL); uri = httpFormatUri(req->scheme, req->host, req->port, pathInfo, req->reference, req->query, 0); httpRedirect(conn, HTTP_CODE_MOVED_PERMANENTLY, uri); return HTTP_ROUTE_OK; } if (route->indexes) { /* Ends with a "/" so do internal redirection to an index file */ for (ITERATE_ITEMS(route->indexes, index, next)) { /* Internal directory redirections. Transparently append index. Test indexes in order. */ path = mprJoinPath(tx->filename, index); if (mprPathExists(path, R_OK)) { pathInfo = sjoin(rx->scriptName, rx->pathInfo, index, NULL); uri = httpFormatUri(req->scheme, req->host, req->port, pathInfo, req->reference, req->query, 0); httpSetUri(conn, uri); tx->filename = path; tx->ext = httpGetExt(conn); mprGetPathInfo(tx->filename, info); return HTTP_ROUTE_REROUTE; } } } #if ME_COM_DIR /* Directory Listing. If a directory, test if a directory listing should be rendered. If so, delegate to the dirHandler. Cannot use the sendFile handler and must use the netConnector. */ if (info->isDir && httpRenderDirListing(conn)) { tx->handler = conn->http->dirHandler; tx->connector = conn->http->netConnector; return HTTP_ROUTE_OK; } #endif return HTTP_ROUTE_OK; }
/* <% stylesheets(patterns); %> Where patterns may contain *, ** and !pattern for exclusion */ PUBLIC void stylesheets(cchar *patterns) { HttpStream *stream; HttpRx *rx; HttpRoute *route; EspRoute *eroute; MprList *files; cchar *filename, *ext, *uri, *path, *kind, *version, *clientDir; int next; stream = getStream(); rx = stream->rx; route = rx->route; eroute = route->eroute; patterns = httpExpandRouteVars(route, patterns); clientDir = httpGetDir(route, "documents"); if (!patterns || !*patterns) { version = espGetConfig(route, "version", "1.0.0"); if (eroute->combineSheet) { /* Previously computed combined stylesheet filename */ stylesheets(eroute->combineSheet); } else if (espGetConfig(route, "http.content.combine[@=css]", 0)) { if (espGetConfig(route, "http.content.minify[@=css]", 0)) { eroute->combineSheet = sfmt("css/all-%s.min.css", version); } else { eroute->combineSheet = sfmt("css/all-%s.css", version); } stylesheets(eroute->combineSheet); } else { /* Not combining into a single stylesheet, so give priority to all.less over all.css if present Load a pure CSS incase some styles need to be applied before the lesssheet is parsed */ ext = espGetConfig(route, "http.content.stylesheets", "css"); filename = mprJoinPathExt("css/all", ext); path = mprJoinPath(clientDir, filename); if (mprPathExists(path, R_OK)) { stylesheets(filename); } else if (!smatch(ext, "less")) { path = mprJoinPath(clientDir, "css/all.less"); if (mprPathExists(path, R_OK)) { stylesheets("css/all.less"); } } } } else { if (sends(patterns, "all.less")) { path = mprJoinPath(clientDir, "css/fix.css"); if (mprPathExists(path, R_OK)) { stylesheets("css/fix.css"); } } if ((files = mprGlobPathFiles(clientDir, patterns, MPR_PATH_RELATIVE)) == 0 || mprGetListLength(files) == 0) { files = mprCreateList(0, 0); mprAddItem(files, patterns); } for (ITERATE_ITEMS(files, path, next)) { path = sjoin("~/", strim(path, ".gz", MPR_TRIM_END), NULL); uri = httpLink(stream, path); kind = mprGetPathExt(path); if (smatch(kind, "css")) { espRender(stream, "<link rel='stylesheet' type='text/css' href='%s' />\n", uri); } else { espRender(stream, "<link rel='stylesheet/%s' type='text/css' href='%s' />\n", kind, uri); } } } }