PUBLIC void httpCreateRxPipeline(HttpConn *conn, HttpRoute *route) { HttpTx *tx; HttpRx *rx; HttpQueue *q; HttpStage *stage, *filter; int next; assert(conn); assert(route); rx = conn->rx; tx = conn->tx; rx->inputPipeline = mprCreateList(-1, MPR_LIST_STABLE); if (route) { for (next = 0; (filter = mprGetNextItem(route->inputStages, &next)) != 0; ) { if (matchFilter(conn, filter, route, HTTP_STAGE_RX) == HTTP_ROUTE_OK) { mprAddItem(rx->inputPipeline, filter); } } } mprAddItem(rx->inputPipeline, tx->handler ? tx->handler : conn->http->clientHandler); /* Create the incoming queue heads and open the queues. */ q = tx->queue[HTTP_QUEUE_RX]; for (next = 0; (stage = mprGetNextItem(rx->inputPipeline, &next)) != 0; ) { q = httpCreateQueue(conn, stage, HTTP_QUEUE_RX, q); } if (httpClientConn(conn)) { pairQueues(conn); openQueues(conn); } }
/* Write upload data. This routine blocks. If you need non-blocking ... cut and paste. */ ssize httpWriteUploadData(HttpConn *conn, MprList *fileData, MprList *formData) { char *path, *pair, *key, *value, *name; ssize rc; int next; rc = 0; if (formData) { for (rc = next = 0; rc >= 0 && (pair = mprGetNextItem(formData, &next)) != 0; ) { key = stok(sclone(pair), "=", &value); rc += httpWrite(conn->writeq, "%s\r\nContent-Disposition: form-data; name=\"%s\";\r\n", conn->boundary, key); rc += httpWrite(conn->writeq, "Content-Type: application/x-www-form-urlencoded\r\n\r\n%s\r\n", value); } } if (fileData) { for (rc = next = 0; rc >= 0 && (path = mprGetNextItem(fileData, &next)) != 0; ) { name = mprGetPathBase(path); rc += httpWrite(conn->writeq, "%s\r\nContent-Disposition: form-data; name=\"file%d\"; filename=\"%s\"\r\n", conn->boundary, next - 1, name); rc += httpWrite(conn->writeq, "Content-Type: %s\r\n\r\n", mprLookupMime(MPR->mimeTypes, path)); rc += blockingFileCopy(conn, path); rc += httpWrite(conn->writeq, "\r\n"); } } rc += httpWrite(conn->writeq, "%s--\r\n--", conn->boundary); httpFinalize(conn); return rc; }
static int setContentLength(MprHttp *http, MprList *fields, MprList *files) { MprPath info; char *path, *pair; int64 len; int next; len = 0; if (upload) { /* Easier to use chunking than to calculate the full multipart-mime upload content */ mprSetHttpChunked(http, 1); mprEnableHttpUpload(http); return 0; } else { for (next = 0; (path = mprGetNextItem(files, &next)) != 0; ) { if (mprGetPathInfo(http, path, &info) < 0) { mprError(http, "Can't access file %s", path); return MPR_ERR_CANT_ACCESS; } len += info.size; } if (fields) { for (next = 0; (pair = mprGetNextItem(fields, &next)) != 0; ) { len += strlen(pair); } len += mprGetListCount(fields) - 1; } } if (len > (16 * MPR_HTTP_BUFSIZE)) { mprSetHttpChunked(http, 1); } else { mprSetHttpBody(http, NULL, (int) len); } return 0; }
static void testListIterate(MprTestGroup *gp) { MprList *lp; int max, i, item, next; max = 50; lp = mprCreateList(max, 0); tassert(lp != 0); for (i = 0; i < max; i++) { mprAddItem(lp, (void*) (long) (i + 1)); } i = next = 0; item = (int) (long) mprGetNextItem(lp, &next); while (item > 0) { i++; item = (int) (long) mprGetNextItem(lp, &next); } tassert(i == max); /* Abbreviated form with no GetFirst */ i = 0; next = 0; while ((item = (int) (long) mprGetNextItem(lp, &next)) != 0) { i++; } tassert(i == max); }
static void testOrderedInserts(MprTestGroup *gp) { MprList *lp; int i, item, next; lp = mprCreateList(0, 0); tassert(lp != 0); /* Add items such that the final list is ordered */ mprAddItem(lp, (void*) (long) 4); mprAddItem(lp, (void*) (long) 5); mprInsertItemAtPos(lp, 0, (void*) 2); mprInsertItemAtPos(lp, 0, (void*) 1); mprInsertItemAtPos(lp, 2, (void*) 3); mprAddItem(lp, (void*) (long) 6); i = 1; next = 0; item = (int) (long) mprGetNextItem(lp, &next); while (item > 0) { tassert(item == i); i++; item = (int) (long) mprGetNextItem(lp, &next); } }
static int setContentLength(HttpConn *conn, MprList *files) { MprPath info; MprOff len; char *path, *pair; int next; len = 0; if (app->upload) { httpEnableUpload(conn); return 0; } for (next = 0; (path = mprGetNextItem(files, &next)) != 0; ) { if (strcmp(path, "-") != 0) { if (mprGetPathInfo(path, &info) < 0) { mprError("Can't access file %s", path); return MPR_ERR_CANT_ACCESS; } len += info.size; } } if (app->formData) { for (next = 0; (pair = mprGetNextItem(app->formData, &next)) != 0; ) { len += slen(pair); } len += mprGetListLength(app->formData) - 1; } if (app->bodyData) { len += mprGetBufLength(app->bodyData); } if (len > 0) { httpSetContentLength(conn, len); } return 0; }
void httpCreateRxPipeline(HttpConn *conn, HttpRoute *route) { HttpTx *tx; HttpRx *rx; HttpQueue *q; HttpStage *stage, *filter; int next; mprAssert(conn); mprAssert(route); rx = conn->rx; tx = conn->tx; rx->inputPipeline = mprCreateList(-1, 0); if (route) { for (next = 0; (filter = mprGetNextItem(route->inputStages, &next)) != 0; ) { if (matchFilter(conn, filter, route, HTTP_STAGE_RX) == HTTP_ROUTE_OK) { mprAddItem(rx->inputPipeline, filter); } } } mprAddItem(rx->inputPipeline, tx->handler); /* Create the incoming queue heads and open the queues. */ q = tx->queue[HTTP_QUEUE_RX]; for (next = 0; (stage = mprGetNextItem(rx->inputPipeline, &next)) != 0; ) { q = httpCreateQueue(conn, stage, HTTP_QUEUE_RX, q); } conn->readq = tx->queue[HTTP_QUEUE_RX]->prevQ; if (!conn->endpoint) { pairQueues(conn); openQueues(conn); } }
static bool appwebIsIdle(MprCtx ctx) { MaHost *host; MaConn *conn; MaHttp *http; MprTime now; int nextHost, next; static MprTime lastTrace = 0; now = mprGetTime(ctx); http = (MaHttp*) mprGetMpr(ctx)->appwebHttpService; for (nextHost = 0; (host = mprGetNextItem(http->defaultServer->hosts, &nextHost)) != 0; ) { lock(host); for (next = 0; (conn = mprGetNextItem(host->connections, &next)) != 0; ) { if (conn->state != MPR_HTTP_STATE_BEGIN) { if (lastTrace < now) { mprLog(ctx, 0, "Waiting for request %s to complete", *conn->request->url ? conn->request->url : conn->request->pathInfo); lastTrace = now; } unlock(host); return 0; } } unlock(host); } if (!mprServicesAreIdle(ctx)) { if (lastTrace < now) { mprLog(ctx, 0, "Waiting for MPR services complete"); lastTrace = now; } return 0; } return 1; }
static int writeBody(MprHttp *http, MprList *fields, MprList *files) { MprFile *file; char buf[MPR_HTTP_BUFSIZE], *path, *pair; int bytes, next, count, rc, len; rc = 0; mprSetSocketBlockingMode(http->sock, 1); if (upload) { if (mprWriteHttpUploadData(http, files, fields) < 0) { mprError(http, "Can't write upload data %s", mprGetHttpError(http)); mprSetSocketBlockingMode(http->sock, 0); return MPR_ERR_CANT_WRITE; } } else { if (fields) { count = mprGetListCount(fields); for (next = 0; !rc && (pair = mprGetNextItem(fields, &next)) != 0; ) { len = (int) strlen(pair); if (next < count) { len = (int) strlen(pair); if (mprWriteSocket(http->sock, pair, len) != len || mprWriteSocket(http->sock, "&", 1) != 1) { return MPR_ERR_CANT_WRITE; } } else { if (mprWriteSocket(http->sock, pair, len) != len) { return MPR_ERR_CANT_WRITE; } } } } if (files) { mprAssert(mprGetListCount(files) == 1); for (rc = next = 0; !rc && (path = mprGetNextItem(files, &next)) != 0; ) { file = mprOpen(http, path, O_RDONLY | O_BINARY, 0); if (file == 0) { mprError(http, "Can't open \"%s\"", path); return MPR_ERR_CANT_OPEN; } if (verbose && upload) { mprPrintf(http, "uploading: %s\n", path); } while ((bytes = mprRead(file, buf, sizeof(buf))) > 0) { if (mprWriteHttp(http, buf, bytes) != bytes) { mprFree(file); return MPR_ERR_CANT_WRITE; } } mprFree(file); } } if (mprFinalizeHttpWriting(http) < 0) { return MPR_ERR_CANT_WRITE; } } mprSetSocketBlockingMode(http->sock, 0); return rc; }
static void runDir(MaQueue *q) { MaConn *conn; MaResponse *resp; MaRequest *req; MprList *list; MprDirEntry *dp; Dir *dir; cchar *filename; uint nameSize; int next; conn = q->conn; req = conn->request; resp = conn->response; dir = q->stage->stageData; filename = resp->filename; mprAssert(filename); maDontCacheResponse(conn); maSetHeader(conn, 0, "Last-Modified", req->host->currentDate); maPutForService(q, maCreateHeaderPacket(q), 0); parseQuery(conn); list = mprGetPathFiles(conn, filename, 1); if (list == 0) { maWrite(q, "<h2>Can't get file list</h2>\r\n"); outputFooter(q); return; } if (dir->pattern) { filterDirList(conn, list); } sortList(conn, list); /* * Get max filename */ nameSize = 0; for (next = 0; (dp = mprGetNextItem(list, &next)) != 0; ) { nameSize = max((int) strlen(dp->name), nameSize); } nameSize = max(nameSize, 22); outputHeader(q, req->url, nameSize); for (next = 0; (dp = mprGetNextItem(list, &next)) != 0; ) { outputLine(q, dp, filename, nameSize); } outputFooter(q); maPutForService(q, maCreateEndPacket(conn), 1); mprFree(list); }
static int process(EjsMod *mp, cchar *output, int argc, char **argv) { Ejs *ejs; EjsModule *module; MprFile *outfile; MprList *depends; int count, i, next, moduleCount; ejs = mp->ejs; if (output) { outfile = mprOpenFile(output, O_CREAT | O_WRONLY | O_TRUNC | O_BINARY, 0664); } else { outfile = 0; } ejs->loaderCallback = (mp->listing) ? emListingLoadCallback : 0; mp->firstGlobal = ejsGetLength(ejs, ejs->global); /* For each module on the command line */ for (i = 0; i < argc && !mp->fatalError; i++) { moduleCount = mprGetListLength(ejs->modules); ejs->loadData = mp; if (!mprPathExists(argv[i], R_OK)) { mprError("Can't access module %s", argv[i]); return EJS_ERR; } if ((ejsLoadModule(ejs, ejsCreateStringFromAsc(ejs, argv[i]), -1, -1, EJS_LOADER_NO_INIT)) < 0) { ejs->loaderCallback = NULL; mprError("Can't load module %s\n%s", argv[i], ejsGetErrorMsg(ejs, 0)); return EJS_ERR; } if (mp->genSlots) { for (next = moduleCount; (module = mprGetNextItem(ejs->modules, &next)) != 0; ) { emCreateSlotFiles(mp, module, outfile); } } if (mp->depends) { depends = mprCreateList(-1, 0); for (next = moduleCount; (module = mprGetNextItem(ejs->modules, &next)) != 0; ) { getDepends(ejs, depends, module); } count = mprGetListLength(depends); for (next = 1; (module = mprGetNextItem(depends, &next)) != 0; ) { int version = module->version; mprPrintf("%@-%d.%d.%d%s", module->name, EJS_MAJOR(version), EJS_MINOR(version), EJS_PATCH(version), (next >= count) ? "" : " "); } printf("\n"); } } if (mp->html || mp->xml) { emCreateDoc(mp); } mprCloseFile(outfile); return 0; }
/* Lookup a property by name. There are 7 kinds of lookups: prop, @att, [prop], *, @*, .name, .@name */ static EjsObj *getXmlPropertyByName(Ejs *ejs, EjsXML *xml, EjsName qname) { EjsXML *item, *result, *list; int next, nextList; result = 0; assert(xml->kind < 5); if (isdigit((uchar) qname.name->value[0]) && allDigitsForXml(qname.name)) { /* Consider xml as a list with only one entry == xml. Then return the 0'th entry */ return (EjsObj*) xml; } if (qname.name->value[0] == '@') { /* @ and @* */ result = ejsCreateXMLList(ejs, xml, qname); if (xml->attributes) { for (next = 0; (item = mprGetNextItem(xml->attributes, &next)) != 0; ) { assert(qname.name->value[0] == '@'); if (qname.name->value[1] == '*' || wcmp(item->qname.name->value, &qname.name->value[1]) == 0) { result = ejsAppendToXML(ejs, result, item); } } } } else if (qname.name->value[0] == '.') { /* Decenders (do ..@ also) */ result = ejsGetXMLDescendants(ejs, xml, qname); } else { /* name and * */ result = ejsCreateXMLList(ejs, xml, qname); if (xml->elements) { for (next = 0; (item = mprGetNextItem(xml->elements, &next)) != 0; ) { if (item->kind == EJS_XML_LIST) { list = item; for (nextList = 0; (item = mprGetNextItem(list->elements, &nextList)) != 0; ) { assert(item->qname.name); if (qname.name->value[0] == '*' || ejsCompareString(ejs, item->qname.name, qname.name) == 0) { result = ejsAppendToXML(ejs, result, item); } } } else if (item->qname.name) { assert(item->qname.name); if (qname.name->value[0] == '*' || ejsCompareString(ejs, item->qname.name, qname.name) == 0) { result = ejsAppendToXML(ejs, result, item); } } } } } return (EjsObj*) result; }
/* Start the request (and complete it) */ static void startDir(HttpQueue *q) { HttpConn *conn; HttpTx *tx; HttpRx *rx; MprList *list; MprDirEntry *dp; HttpDir *dir; cchar *path; uint nameSize; int next; conn = q->conn; rx = conn->rx; tx = conn->tx; if ((dir = conn->reqData) == 0) { httpError(conn, HTTP_CODE_INTERNAL_SERVER_ERROR, "Cannot get directory listing"); return; } assert(tx->filename); if (!(rx->flags & (HTTP_GET | HTTP_HEAD))) { httpError(conn, HTTP_CODE_BAD_METHOD, "Bad method"); return; } httpSetContentType(conn, "text/html"); httpSetHeaderString(conn, "Cache-Control", "no-cache"); httpSetHeaderString(conn, "Last-Modified", conn->http->currentDate); parseQuery(conn); if ((list = mprGetPathFiles(tx->filename, MPR_PATH_RELATIVE)) == 0) { httpWrite(q, "<h2>Cannot get file list</h2>\r\n"); outputFooter(q); return; } if (dir->pattern) { filterDirList(conn, list); } sortList(conn, list); /* Get max filename size */ nameSize = 0; for (next = 0; (dp = mprGetNextItem(list, &next)) != 0; ) { nameSize = max((int) strlen(dp->name), nameSize); } nameSize = max(nameSize, 22); path = rx->route->prefix ? sjoin(rx->route->prefix, rx->pathInfo, NULL) : rx->pathInfo; outputHeader(q, path, nameSize); for (next = 0; (dp = mprGetNextItem(list, &next)) != 0; ) { outputLine(q, dp, tx->filename, nameSize); } outputFooter(q); httpFinalize(conn); }
static void processDir(HttpQueue *q) { HttpConn *conn; HttpTx *tx; HttpRx *rx; MprList *list; MprDirEntry *dp; Dir *dir; uint nameSize; int next; conn = q->conn; rx = conn->rx; tx = conn->tx; dir = conn->data; mprLog(5, "processDir"); mprAssert(tx->filename); httpSetHeaderString(conn, "Cache-Control", "no-cache"); httpSetHeaderString(conn, "Last-Modified", conn->http->currentDate); parseQuery(conn); list = mprGetPathFiles(tx->filename, 1); if (list == 0) { httpWrite(q, "<h2>Can't get file list</h2>\r\n"); outputFooter(q); return; } if (dir->pattern) { filterDirList(conn, list); } sortList(conn, list); /* Get max filename */ nameSize = 0; for (next = 0; (dp = mprGetNextItem(list, &next)) != 0; ) { nameSize = max((int) strlen(dp->name), nameSize); } nameSize = max(nameSize, 22); outputHeader(q, rx->pathInfo, nameSize); for (next = 0; (dp = mprGetNextItem(list, &next)) != 0; ) { outputLine(q, dp, tx->filename, nameSize); } outputFooter(q); httpFinalize(conn); }
/* * Stop the server and stop listening on all ports */ int maStopServer(MaServer *server) { MaHost *host; MaListen *listen; int next; for (next = 0; (listen = mprGetNextItem(server->listens, &next)) != 0; ) { maStopListening(listen); } for (next = 0; (host = mprGetNextItem(server->hosts, &next)) != 0; ) { maStopHost(host); } return 0; }
int maStartServer(MaServer *server) { MaHost *host; MaListen *listen; int next, count, warned; /* * Start the hosts */ for (next = 0; (host = mprGetNextItem(server->hosts, &next)) != 0; ) { mprLog(server, 1, "Starting host named: \"%s\"", host->name); if (maStartHost(host) < 0) { return MPR_ERR_CANT_INITIALIZE; } } /* * Listen to all required ipAddr:ports */ warned = 0; count = 0; for (next = 0; (listen = mprGetNextItem(server->listens, &next)) != 0; ) { if (maStartListening(listen) < 0) { mprError(server, "Can't listen for HTTP on %s:%d", listen->ipAddr, listen->port); warned++; break; } else { count++; } } if (count == 0) { if (! warned) { mprError(server, "Server is not listening on any addresses"); } return MPR_ERR_CANT_OPEN; } /* * Now change user and group to the desired identities (user must be last) */ if (maApplyChangedGroup(server->http) < 0 || maApplyChangedUser(server->http) < 0) { return MPR_ERR_CANT_COMPLETE; } return 0; }
static int deleteXmlListPropertyByName(Ejs *ejs, EjsXML *list, EjsName qname) { EjsXML *elt; int index, next; if (isdigit((uchar) qname.name->value[0]) && allDigitsForXmlList(qname.name)) { index = ejsAtoi(ejs, qname.name, 10); elt = (EjsXML*) mprGetItem(list->elements, index); if (elt) { if (elt->parent) { if (elt->kind == EJS_XML_ATTRIBUTE) { ejsDeletePropertyByName(ejs, (EjsObj*) elt->parent, elt->qname); } else { // TODO - let q be the property of parent where parent[q] == x[i] mprRemoveItem(elt->parent->elements, elt); elt->parent = 0; } } } // Spec says return true even if index is out of range. We return 0 for true and < 0 for false. // TODO - should ejs throw? return 0; } for (next = 0; (elt = mprGetNextItem(list->elements, &next)) != 0; ) { if (elt->kind == EJS_XML_ELEMENT /* && elt->parent */) { ejsDeletePropertyByName(ejs, (EjsObj*) elt /* TODO was elt->parent */, qname); } } return 0; }
void maSecureHost(MaHost *host, struct MprSsl *ssl) { MaListen *lp; cchar *hostIp; char *ipAddr; int port, next; host->secure = 1; hostIp = host->ipAddrPort; if (mprStrcmpAnyCase(hostIp, "_default_") == 0) { hostIp = (char*) "*:*"; } mprParseIp(host, hostIp, &ipAddr, &port, -1); for (next = 0; (lp = mprGetNextItem(host->server->listens, &next)) != 0; ) { if (port > 0 && port != lp->port) { continue; } if (*lp->ipAddr && ipAddr && ipAddr[0] != '*' && strcmp(ipAddr, lp->ipAddr) != 0) { continue; } #if BLD_FEATURE_SSL if (host->secure) { if (host->flags & MA_HOST_NAMED_VHOST) { mprError(host, "SSL does not support named virtual hosts"); return; } lp->ssl = ssl; } #endif } }
int maInsertAlias(MaHost *host, MaAlias *newAlias) { MaAlias *alias, *old; int rc, next, index; if (mprGetParent(host->aliases) == host->parent) { host->aliases = mprDupList(host, host->parent->aliases); } /* * Sort in reverse collating sequence. Must make sure that /abc/def sorts before /abc. But we sort redirects with * status codes first. */ for (next = 0; (alias = mprGetNextItem(host->aliases, &next)) != 0; ) { rc = strcmp(newAlias->prefix, alias->prefix); if (rc == 0) { index = mprLookupItem(host->aliases, alias); old = (MaAlias*) mprGetItem(host->aliases, index); mprRemoveItem(host->aliases, alias); mprInsertItemAtPos(host->aliases, next - 1, newAlias); return 0; } else if (rc > 0) { if (newAlias->redirectCode >= alias->redirectCode) { mprInsertItemAtPos(host->aliases, next - 1, newAlias); return 0; } } } mprAddItem(host->aliases, newAlias); return 0; }
int maInsertDir(MaHost *host, MaDir *newDir) { MaDir *dir; int rc, next; mprAssert(newDir); mprAssert(newDir->path); if (mprGetParent(host->dirs) == host->parent) { host->dirs = mprDupList(host, host->parent->dirs); } /* * Sort in reverse collating sequence. Must make sure that /abc/def sorts before /abc */ for (next = 0; (dir = mprGetNextItem(host->dirs, &next)) != 0; ) { mprAssert(dir->path); rc = strcmp(newDir->path, dir->path); if (rc == 0) { mprRemoveItem(host->dirs, dir); mprInsertItemAtPos(host->dirs, next, newDir); return 0; } else if (rc > 0) { mprInsertItemAtPos(host->dirs, next - 1, newDir); return 0; } } mprAddItem(host->dirs, newDir); return 0; }
PUBLIC EjsXML *ejsAppendToXML(Ejs *ejs, EjsXML *xml, EjsXML *node) { EjsXML *elt; int next; if (xml == 0 || node == 0) { return 0; } if (xml->elements == 0) { xml->elements = mprCreateList(-1, 0); } if (node->kind == EJS_XML_LIST) { for (next = 0; (elt = mprGetNextItem(node->elements, &next)) != 0; ) { if (xml->kind != EJS_XML_LIST) { elt->parent = xml; } mprAddItem(xml->elements, elt); } xml->targetObject = node->targetObject; xml->targetProperty = node->targetProperty; } else { if (xml->kind != EJS_XML_LIST) { node->parent = xml; } mprAddItem(xml->elements, node); } return xml; }
int maAddLocation(MaHost *host, MaLocation *newLocation) { MaLocation *location; int next, rc; mprAssert(newLocation); mprAssert(newLocation->prefix); if (mprGetParent(host->locations) == host->parent) { host->locations = mprDupList(host, host->parent->locations); } /* * Sort in reverse collating sequence. Must make sure that /abc/def sorts before /abc */ for (next = 0; (location = mprGetNextItem(host->locations, &next)) != 0; ) { rc = strcmp(newLocation->prefix, location->prefix); if (rc == 0) { mprRemoveItem(host->locations, location); mprInsertItemAtPos(host->locations, next - 1, newLocation); return 0; } if (strcmp(newLocation->prefix, location->prefix) > 0) { mprInsertItemAtPos(host->locations, next - 1, newLocation); return 0; } } mprAddItem(host->locations, newLocation); return 0; }
/* Test if the http service (including MPR) is idle with no running requests */ static bool isIdle(bool traceRequests) { HttpConn *conn; Http *http; MprTicks now; int next; static MprTicks lastTrace = 0; if ((http = MPR->httpService) != 0) { now = http->now; lock(http->connections); for (next = 0; (conn = mprGetNextItem(http->connections, &next)) != 0; ) { if (conn->state != HTTP_STATE_BEGIN && conn->state != HTTP_STATE_COMPLETE) { if (traceRequests && lastTrace < now) { if (conn->rx) { mprLog("info http", 2, "Request for \"%s\" is still active", conn->rx->uri ? conn->rx->uri : conn->rx->pathInfo); } lastTrace = now; } unlock(http->connections); return 0; } } unlock(http->connections); } else { now = mprGetTicks(); } return mprServicesAreIdle(traceRequests); }
/* * Find an exact dir match. May be called with raw file names. ie. D:\myDir */ MaDir *maLookupDir(MaHost *host, cchar *path) { MaDir *dir; char *absPath, buf[MPR_MAX_FNAME]; int next, len; /* * Cannonicalize and ensure path has a trailing "/" */ absPath = mprGetAbsFilename(host, path); mprStrcpy(buf, sizeof(buf), absPath); len = (int) strlen(buf); if (buf[len - 1] != '/') { buf[len] = '/'; buf[++len] = '\0'; } for (next = 0; (dir = mprGetNextItem(host->dirs, &next)) != 0; ) { if (dir->path != 0) { #if WIN if (mprStrcmpAnyCase(dir->path, buf) == 0) #else if (strcmp(dir->path, buf) == 0) #endif return dir; } } return 0; }
/* * Find the directory entry that this file (path) resides in. path is a physical file path. We find the most specific * (longest) directory that matches. The directory must match or be a parent of path. Not called with raw files names. * They will be lower case and only have forward slashes. For windows, the will be in cannonical format with drive * specifiers. */ MaDir *maLookupBestDir(MaHost *host, cchar *path) { MaDir *dir; int next, len, dlen; len = (int) strlen(path); for (next = 0; (dir = mprGetNextItem(host->dirs, &next)) != 0; ) { dlen = dir->pathLen; /* * Special case where the Directory has a trailing "/" and we match all the letters before that. */ if (len == (dlen - 1) && dir->path[len] == '/') { dlen--; } #if WIN // TODO - must make this generic and use something like: host->caseMatters // TODO - but this must be per-file system. if (mprCompareFilename(host, dir->path, path, dlen) == 0) #else if (strncmp(dir->path, path, dlen) == 0) #endif { if (dlen >= 0) { return dir; } } } return 0; }
static EjsXML *shallowCopy(Ejs *ejs, EjsXML *xml) { EjsXML *root, *elt; int next; assure(xml->kind == EJS_XML_LIST); if (xml == 0) { return 0; } if ((root = ejsCreateXMLList(ejs, xml->targetObject, xml->targetProperty)) == NULL) { return 0; } if (xml->elements) { root->elements = mprCreateList(-1, 0); for (next = 0; (elt = mprGetNextItem(xml->elements, &next)) != 0; ) { assure(ejsIsXML(ejs, elt)); if (elt) { mprAddItem(root->elements, elt); } } } if (mprHasMemError(ejs)) { return 0; } return root; }
/* Lookup a property by name. There are 7 kinds of lookups: prop, @att, [prop], *, @*, .name, .@name */ static EjsObj *getXmlListPropertyByName(Ejs *ejs, EjsXML *list, EjsName qname) { EjsXML *result, *subList, *item; int nextItem; /* Get the n'th item in the list */ if (isdigit((uchar) qname.name->value[0]) && allDigitsForXmlList(qname.name)) { return mprGetItem(list->elements, ejsAtoi(ejs, qname.name, 10)); } result = ejsCreateXMLList(ejs, list, qname); /* Build a list of all the elements that themselves have a property qname */ for (nextItem = 0; (item = mprGetNextItem(list->elements, &nextItem)) != 0; ) { if (item->kind == EJS_XML_ELEMENT) { subList = ejsGetPropertyByName(ejs, (EjsObj*) item, qname); assure(ejsIsXML(ejs, subList)); ejsAppendToXML(ejs, result, subList); } else { // TODO - do we ever get a list in a list? assure(0); } } return (EjsObj*) result; }
/* * Find an exact dir match */ MaDir *maLookupDir(MaHost *host, cchar *pathArg) { MaDir *dir; char *path, *tmpPath; int next, len; if (!mprIsAbsPath(host, pathArg)) { path = tmpPath = mprGetAbsPath(host, pathArg); } else { path = (char*) pathArg; tmpPath = 0; } len = (int) strlen(path); for (next = 0; (dir = mprGetNextItem(host->dirs, &next)) != 0; ) { if (dir->path != 0) { if (mprSamePath(host, dir->path, path)) { mprFree(tmpPath); return dir; } } } mprFree(tmpPath); return 0; }
static int prepRequest(HttpConn *conn, MprList *files, int retry) { MprKeyValue *header; char *seq; int next; httpPrepClientConn(conn, retry); for (next = 0; (header = mprGetNextItem(app->headers, &next)) != 0; ) { if (scaselessmatch(header->key, "User-Agent")) { httpSetHeader(conn, header->key, header->value); } else { httpAppendHeader(conn, header->key, header->value); } } if (app->text) { httpSetHeader(conn, "Accept", "text/plain"); } if (app->sequence) { static int next = 0; seq = itos(next++); httpSetHeader(conn, "X-Http-Seq", seq); } if (app->ranges) { httpSetHeader(conn, "Range", app->ranges); } if (app->formData) { httpSetHeader(conn, "Content-Type", "application/x-www-form-urlencoded"); } if (setContentLength(conn, files) < 0) { return MPR_ERR_CANT_OPEN; } return 0; }
static int processThread(HttpConn *conn, MprEvent *event) { ThreadData *td; cchar *path; char *url; int next; td = mprGetCurrentThread()->data; httpFollowRedirects(conn, !app->nofollow); httpSetTimeout(conn, app->timeout, app->timeout); if (strcmp(app->protocol, "HTTP/1.0") == 0) { httpSetKeepAliveCount(conn, 0); httpSetProtocol(conn, "HTTP/1.0"); } if (app->username) { if (app->password == 0 && !strchr(app->username, ':')) { app->password = getPassword(); } httpSetCredentials(conn, app->username, app->password); } while (!mprShouldDenyNewRequests(conn) && (app->success || app->continueOnErrors)) { if (app->singleStep) waitForUser(); if (app->files && !app->upload) { for (next = 0; (path = mprGetNextItem(app->files, &next)) != 0; ) { /* If URL ends with "/", assume it is a directory on the target and append each file name */ if (app->target[strlen(app->target) - 1] == '/') { url = mprJoinPath(app->target, mprGetPathBase(path)); } else { url = app->target; } app->requestFiles = mprCreateList(-1, MPR_LIST_STATIC_VALUES); mprAddItem(app->requestFiles, path); td->url = url = resolveUrl(conn, url); if (app->verbose) { mprPrintf("putting: %s to %s\n", path, url); } if (doRequest(conn, url, app->requestFiles) < 0) { app->success = 0; break; } } } else { td->url = url = resolveUrl(conn, app->target); if (doRequest(conn, url, app->files) < 0) { app->success = 0; break; } } if (iterationsComplete()) { break; } } httpDestroyConn(conn); finishThread((MprThread*) event->data); return -1; }