/* * Create an initialize the Ejscript Web Framework control block */ static int initControlBlock() { control = mprAllocZeroed(mpr, sizeof(EjsWebControl)); if (control == 0) { return MPR_ERR_NO_MEMORY; } /* * These are the callbacks from the web framework into the gateway */ control->defineParams = defineParams; control->discardOutput = discardOutput; control->error = error; control->getHeader = getHeader; control->getVar = getVar; control->redirect = redirect; control->setCookie = setCookie; control->setHeader = setHeader; control->setHttpCode = setHttpCode; control->setMimeType = setMimeType; control->setVar = setVar; control->write = writeBlock; if (ejsOpenWebFramework(control, 0) < 0) { return EJS_ERR; } output = mprCreateBuf(mpr, EJS_CGI_MIN_BUF, EJS_CGI_MAX_BUF); headerOutput = mprCreateBuf(mpr, MPR_BUFSIZE, -1); if (output == 0 || headerOutput == 0) { return EJS_ERR; } return 0; }
MprXml *mprXmlOpen(ssize initialSize, ssize maxSize) { MprXml *xp; xp = mprAllocObj(MprXml, manageXml); xp->inBuf = mprCreateBuf(MPR_XML_BUFSIZE, MPR_XML_BUFSIZE); xp->tokBuf = mprCreateBuf(initialSize, maxSize); return xp; }
MprXml *mprXmlOpen(MprCtx ctx, int initialSize, int maxSize) { MprXml *xp; xp = mprAllocObjZeroed(ctx, MprXml); xp->inBuf = mprCreateBuf(xp, MPR_XML_BUFSIZE, MPR_XML_BUFSIZE); xp->tokBuf = mprCreateBuf(xp, initialSize, maxSize); return xp; }
/* Expand a template with {word} tokens from the given options objects function template(pattern: String, ...options): Uri */ static EjsUri *uri_template(Ejs *ejs, EjsUri *up, int argc, EjsObj **argv) { EjsArray *options; EjsObj *obj, *value; MprBuf *buf; cchar *pattern, *cp, *ep, *str; char *token; int i, len; pattern = ejsToMulti(ejs, argv[0]); options = (EjsArray*) argv[1]; buf = mprCreateBuf(-1, -1); for (cp = pattern; *cp; cp++) { if (*cp == '~' && (cp == pattern || cp[-1] != '\\')) { for (i = 0; i < options->length; i++) { obj = options->data[i]; if ((value = ejsGetPropertyByName(ejs, obj, N(NULL, "scriptName"))) != 0 && ejsIsDefined(ejs, value)) { str = ejsToMulti(ejs, value); if (str && *str) { mprPutStringToBuf(buf, str); break; } else { value = 0; } } } } else if (*cp == '{' && (cp == pattern || cp[-1] != '\\')) { if ((ep = strchr(++cp, '}')) != 0) { len = (int) (ep - cp); token = mprMemdup(cp, len + 1); token[len] = '\0'; value = 0; for (i = 0; i < options->length; i++) { obj = options->data[i]; if ((value = ejsGetPropertyByName(ejs, obj, N(NULL, token))) != 0 && ejsIsDefined(ejs, value)) { str = ejsToMulti(ejs, value); if (str && *str) { mprPutStringToBuf(buf, str); break; } else { value = 0; } } } if (!ejsIsDefined(ejs, value)) { // MOB - remove this. Should not be erasing the prior "/" if (cp >= &pattern[2] && cp[-2] == '/') { mprAdjustBufEnd(buf, -1); } } cp = ep; } } else { mprPutCharToBuf(buf, *cp); } } mprAddNullToBuf(buf); return ejsCreateUriFromAsc(ejs, mprGetBufStart(buf)); }
/* Get a character from the file. This will put the file into buffered mode. */ PUBLIC int mprGetFileChar(MprFile *file) { MprBuf *bp; ssize len; assert(file); if (file == 0) { return MPR_ERR; } if (file->buf == 0) { file->buf = mprCreateBuf(ME_MAX_BUFFER, ME_MAX_BUFFER); } bp = file->buf; if (mprGetBufLength(bp) == 0) { len = fillBuf(file); if (len <= 0) { return -1; } } if (mprGetBufLength(bp) == 0) { return 0; } file->pos++; return mprGetCharFromBuf(bp); }
/* This replace will replace the given pattern and the next word on the same line with the given replacement. */ static char *replace(cchar *str, cchar *pattern, cchar *fmt, ...) { va_list args; MprBuf *buf; cchar *s, *replacement; ssize plen; va_start(args, fmt); replacement = sfmtv(fmt, args); buf = mprCreateBuf(-1, -1); plen = slen(pattern); for (s = str; *s; s++) { if (*s == *pattern && sncmp(s, pattern, plen) == 0) { mprPutStringToBuf(buf, replacement); for (s += plen; *s && isspace((uchar) *s) && *s != '\n'; s++) ; for (; *s && !isspace((uchar) *s) && *s != '\n' && *s != '>'; s++) ; } #if BIT_WIN_LIKE if (*s == '\n' && s[-1] != '\r') { mprPutCharToBuf(buf, '\r'); } #endif mprPutCharToBuf(buf, *s); } va_end(args); mprAddNullToBuf(buf); return sclone(mprGetBufStart(buf)); }
/* Peek at a character from the file without disturbing the read position. This will put the file into buffered mode. */ PUBLIC int mprPeekFileChar(MprFile *file) { MprBuf *bp; ssize len; assert(file); if (file == 0) { return MPR_ERR; } if (file->buf == 0) { file->buf = mprCreateBuf(ME_MAX_BUFFER, ME_MAX_BUFFER); } bp = file->buf; if (mprGetBufLength(bp) == 0) { len = fillBuf(file); if (len <= 0) { return -1; } } if (mprGetBufLength(bp) == 0) { return 0; } return ((uchar*) mprGetBufStart(bp))[0]; }
/* See if there is acceptable cached content to serve */ static int matchCacheHandler(HttpConn *conn, HttpRoute *route, int dir) { HttpCache *cache; mprAssert(route->caching); if ((cache = conn->tx->cache = lookupCacheControl(conn)) == 0) { /* Caching not configured for this route */ return HTTP_ROUTE_REJECT; } if (cache->flags & HTTP_CACHE_CLIENT) { cacheAtClient(conn); } if (cache->flags & HTTP_CACHE_SERVER) { if (!(cache->flags & HTTP_CACHE_MANUAL) && fetchCachedResponse(conn)) { /* Found cached content */ return HTTP_ROUTE_OK; } /* Caching is configured but no acceptable cached content. Create a capture buffer for the cacheFilter. */ conn->tx->cacheBuffer = mprCreateBuf(-1, -1); } return HTTP_ROUTE_REJECT; }
/* Populate a packet with file data. Return the number of bytes read or a negative error code. Will not return with a short read. */ static ssize readFileData(HttpQueue *q, HttpPacket *packet, MprOff pos, ssize size) { HttpConn *conn; HttpTx *tx; ssize nbytes; // int btint = 0; conn = q->conn; tx = conn->tx; if (packet->content == 0 && (packet->content = mprCreateBuf(size, -1)) == 0) { return MPR_ERR_MEMORY; } assure(size <= mprGetBufSpace(packet->content)); mprLog(7, "readFileData size %d, pos %Ld", size, pos); if (pos >= 0) { mprSeekFile(tx->file, SEEK_SET, pos); } if ((nbytes = mprReadFile(tx->file, mprGetBufStart(packet->content), size)) != size) { /* As we may have sent some data already to the client, the only thing we can do is abort and hope the client notices the short data. */ httpError(conn, HTTP_CODE_SERVICE_UNAVAILABLE, "Can't read file %s", tx->filename); return MPR_ERR_CANT_READ; } mprAdjustBufEnd(packet->content, nbytes); packet->esize -= nbytes; assure(packet->esize == 0); return nbytes; }
/* Read a line from the file. This will put the file into buffered mode. Return NULL on eof. */ PUBLIC char *mprReadLine(MprFile *file, ssize maxline, ssize *lenp) { MprBuf *bp; MprFileSystem *fs; ssize size, len, nlen, consumed; cchar *eol, *newline, *start; char *result; assert(file); if (file == 0) { return NULL; } if (lenp) { *lenp = 0; } if (maxline <= 0) { maxline = ME_MAX_BUFFER; } fs = file->fileSystem; newline = fs->newline; if (file->buf == 0) { file->buf = mprCreateBuf(maxline, maxline); } bp = file->buf; result = NULL; size = 0; do { if (mprGetBufLength(bp) == 0) { if (fillBuf(file) <= 0) { return result; } } start = mprGetBufStart(bp); len = mprGetBufLength(bp); if ((eol = findNewline(start, newline, len, &nlen)) != 0) { len = eol - start; consumed = len + nlen; } else { consumed = len; } file->pos += (MprOff) consumed; if (lenp) { *lenp += len; } if ((result = mprRealloc(result, size + len + 1)) == 0) { return NULL; } memcpy(&result[size], start, len); size += len; result[size] = '\0'; mprAdjustBufStart(bp, consumed); } while (!eol); return result; }
/* function Http(uri: Uri = null) */ static EjsHttp *httpConstructor(Ejs *ejs, EjsHttp *hp, int argc, EjsObj **argv) { ejsLoadHttpService(ejs); hp->ejs = ejs; if ((hp->conn = httpCreateConn(ejs->http, NULL, ejs->dispatcher)) == 0) { ejsThrowMemoryError(ejs); return 0; } httpPrepClientConn(hp->conn, 0); httpSetConnNotifier(hp->conn, httpEventChange); httpSetConnContext(hp->conn, hp); if (argc == 1 && ejsIs(ejs, argv[0], Null)) { hp->uri = httpUriToString(((EjsUri*) argv[0])->uri, HTTP_COMPLETE_URI); } hp->method = sclone("GET"); hp->requestContent = mprCreateBuf(BIT_MAX_BUFFER, -1); hp->responseContent = mprCreateBuf(BIT_MAX_BUFFER, -1); return hp; }
/* Cast the object operand to a primitive type */ static EjsObj *xlCast(Ejs *ejs, EjsXML *vp, EjsType *type) { MprBuf *buf; EjsObj *result; EjsXML *elt, *item; int next; if (type == ESV(XML)) { return (EjsObj*) vp; } switch (type->sid) { case S_Object: case S_Boolean: return (EjsObj*) ejsCreateBoolean(ejs, 1); case S_Number: result = xlCast(ejs, vp, ESV(String)); result = (EjsObj*) ejsToNumber(ejs, result); return result; case S_String: buf = mprCreateBuf(MPR_BUFSIZE, -1); if (mprGetListLength(vp->elements) == 1) { elt = mprGetFirstItem(vp->elements); if (elt->kind == EJS_XML_ELEMENT) { if (elt->elements == 0) { return (EjsObj*) ESV(empty); } if (elt->elements && mprGetListLength(elt->elements) == 1) { // TODO - what about PI and comments? item = mprGetFirstItem(elt->elements); if (item->kind == EJS_XML_TEXT) { return (EjsObj*) item->value; } } } } for (next = 0; (elt = mprGetNextItem(vp->elements, &next)) != 0; ) { if (ejsXMLToBuf(ejs, buf, elt, -1) < 0) { return 0; } if (next < vp->elements->length) { mprPutStringToBuf(buf, " "); } } return (EjsObj*) ejsCreateStringFromAsc(ejs, (char*) buf->start); default: ejsThrowTypeError(ejs, "Cannot cast to this type"); return 0; } }
PUBLIC char *httpStatsReport(int flags) { MprTime now; MprBuf *buf; HttpStats s; double elapsed; static MprTime lastTime; static HttpStats last; double mb; mb = 1024.0 * 1024; now = mprGetTime(); elapsed = (now - lastTime) / 1000.0; httpGetStats(&s); buf = mprCreateBuf(0, 0); mprPutToBuf(buf, "\nHttp Report: at %s\n\n", mprGetDate("%D %T")); if (flags & HTTP_STATS_MEMORY) { mprPutToBuf(buf, "Memory %8.1f MB, %5.1f%% max\n", s.mem / mb, s.mem / (double) s.memMax * 100.0); mprPutToBuf(buf, "Heap %8.1f MB, %5.1f%% mem\n", s.heap / mb, s.heap / (double) s.mem * 100.0); mprPutToBuf(buf, "Heap-peak %8.1f MB\n", s.heapPeak / mb); mprPutToBuf(buf, "Heap-used %8.1f MB, %5.1f%% used\n", s.heapUsed / mb, s.heapUsed / (double) s.heap * 100.0); mprPutToBuf(buf, "Heap-free %8.1f MB, %5.1f%% free\n", s.heapFree / mb, s.heapFree / (double) s.heap * 100.0); if (s.memMax == (size_t) -1) { mprPutToBuf(buf, "Heap limit -\n"); mprPutToBuf(buf, "Heap readline -\n"); } else { mprPutToBuf(buf, "Heap limit %8.1f MB\n", s.memMax / mb); mprPutToBuf(buf, "Heap redline %8.1f MB\n", s.memRedline / mb); } } mprPutToBuf(buf, "Connections %8.1f per/sec\n", (s.totalConnections - last.totalConnections) / elapsed); mprPutToBuf(buf, "Requests %8.1f per/sec\n", (s.totalRequests - last.totalRequests) / elapsed); mprPutToBuf(buf, "Sweeps %8.1f per/sec\n", (s.totalSweeps - last.totalSweeps) / elapsed); mprPutCharToBuf(buf, '\n'); mprPutToBuf(buf, "Clients %8d active\n", s.activeClients); mprPutToBuf(buf, "Connections %8d active\n", s.activeConnections); mprPutToBuf(buf, "Processes %8d active\n", s.activeProcesses); mprPutToBuf(buf, "Requests %8d active\n", s.activeRequests); mprPutToBuf(buf, "Sessions %8d active\n", s.activeSessions); mprPutToBuf(buf, "Workers %8d busy - %d yielded, %d idle, %d max\n", s.workersBusy, s.workersYielded, s.workersIdle, s.workersMax); mprPutToBuf(buf, "Sessions %8.1f MB\n", s.memSessions / mb); mprPutCharToBuf(buf, '\n'); last = s; lastTime = now; mprAddNullToBuf(buf); return sclone(mprGetBufStart(buf)); }
/* uncompressString(data: String): String */ static EjsString *zlib_uncompressString(Ejs *ejs, EjsObj *unused, int argc, EjsObj **argv) { EjsString *in; MprBuf *out; z_stream zs; uchar outbuf[ZBUFSIZE]; ssize nbytes, size; int rc; in = (EjsString*) argv[0]; if ((out = mprCreateBuf(ZBUFSIZE, -1)) == 0) { return 0; } if ((size = in->length) == 0) { return ESV(empty); } zs.zalloc = Z_NULL; zs.zfree = Z_NULL; zs.opaque = Z_NULL; zs.avail_in = 0; rc = inflateInit(&zs); zs.next_in = (uchar*) in->value; zs.avail_in = (int) size; do { if (zs.avail_in == 0) { break; } do { zs.avail_out = ZBUFSIZE; zs.next_out = outbuf; if ((rc = inflate(&zs, Z_NO_FLUSH)) == Z_NEED_DICT) { inflateEnd(&zs); return 0; } else if (rc == Z_DATA_ERROR || rc == Z_MEM_ERROR) { inflateEnd(&zs); return 0; } else { nbytes = ZBUFSIZE - zs.avail_out; } if (mprPutBlockToBuf(out, (char*) outbuf, nbytes) != nbytes) { ejsThrowIOError(ejs, "Cannot copy to byte array"); inflateEnd(&zs); return 0; } } while (zs.avail_out == 0); assure(zs.avail_in == 0); } while (rc != Z_STREAM_END); deflateEnd(&zs); return ejsCreateStringFromBytes(ejs, mprGetBufStart(out), mprGetBufLength(out)); }
bool httpPamVerifyUser(HttpConn *conn) { MprBuf *abilities; pam_handle_t *pamh; UserInfo info; struct pam_conv conv = { pamChat, &info }; struct group *gp; int res, i; mprAssert(conn->username); mprAssert(conn->password); mprAssert(!conn->encoded); info.name = (char*) conn->username; info.password = (char*) conn->password; pamh = NULL; if ((res = pam_start("login", info.name, &conv, &pamh)) != PAM_SUCCESS) { return 0; } if ((res = pam_authenticate(pamh, PAM_DISALLOW_NULL_AUTHTOK)) != PAM_SUCCESS) { pam_end(pamh, PAM_SUCCESS); mprLog(5, "httpPamVerifyUser failed to verify %s", conn->username); return 0; } pam_end(pamh, PAM_SUCCESS); mprLog(5, "httpPamVerifyUser verified %s", conn->username); if (!conn->user) { conn->user = mprLookupKey(conn->rx->route->auth->users, conn->username); } if (!conn->user) { Gid groups[32]; int ngroups; /* Create a temporary user with a abilities set to the groups */ ngroups = sizeof(groups) / sizeof(Gid); if ((i = getgrouplist(conn->username, 99999, groups, &ngroups)) >= 0) { abilities = mprCreateBuf(0, 0); for (i = 0; i < ngroups; i++) { if ((gp = getgrgid(groups[i])) != 0) { mprPutFmtToBuf(abilities, "%s ", gp->gr_name); } } mprAddNullToBuf(abilities); mprLog(5, "Create temp user \"%s\" with abilities: %s", conn->username, mprGetBufStart(abilities)); conn->user = httpCreateUser(conn->rx->route->auth, conn->username, 0, mprGetBufStart(abilities)); } } return 1; }
int mprPuts(MprFile *file, const char *writeBuf, uint count) { MprBuf *bp; char *buf; int total, bytes, len; mprAssert(file); /* * Buffer output and flush when full. */ if (file->buf == 0) { file->buf = mprCreateBuf(file, MPR_BUFSIZE, 0); if (file->buf == 0) { return MPR_ERR_CANT_ALLOCATE; } } bp = file->buf; if (mprGetBufLength(bp) > 0 && mprGetBufSpace(bp) < (int) count) { len = mprGetBufLength(bp); if (mprWrite(file, mprGetBufStart(bp), len) != len) { return MPR_ERR_CANT_WRITE; } mprFlushBuf(bp); } total = 0; buf = (char*) writeBuf; while (count > 0) { bytes = mprPutBlockToBuf(bp, buf, count); if (bytes <= 0) { return MPR_ERR_CANT_ALLOCATE; } count -= bytes; buf += bytes; total += bytes; mprAddNullToBuf(bp); if (count > 0) { len = mprGetBufLength(bp); if (mprWrite(file, mprGetBufStart(bp), len) != len) { return MPR_ERR_CANT_WRITE; } mprFlushBuf(bp); } } return total; }
/* Map options to an attribute string. Remove all internal control specific options and transparently handle URI link options. WARNING: this returns a non-cloned reference and relies on no GC yield until the returned value is used or cloned. This is done as an optimization to reduce memeory allocations. */ static cchar *map(HttpConn *conn, MprHash *options) { Esp *esp; EspReq *req; MprHash *params; MprKey *kp; MprBuf *buf; cchar *value; char *pstr; if (options == 0 || mprGetHashLength(options) == 0) { return MPR->emptyString; } req = conn->data; if (httpGetOption(options, EDATA("refresh"), 0) && !httpGetOption(options, "id", 0)) { httpAddOption(options, "id", sfmt("id_%d", req->lastDomID++)); } esp = MPR->espService; buf = mprCreateBuf(-1, -1); for (kp = 0; (kp = mprGetNextKey(options, kp)) != 0; ) { if (kp->type != MPR_JSON_OBJ && kp->type != MPR_JSON_ARRAY && !mprLookupKey(esp->internalOptions, kp->key)) { mprPutCharToBuf(buf, ' '); value = kp->data; /* Support link template resolution for these options */ if (smatch(kp->key, EDATA("click")) || smatch(kp->key, EDATA("remote")) || smatch(kp->key, EDATA("refresh"))) { value = httpUriEx(conn, value, options); if ((params = httpGetOptionHash(options, "params")) != 0) { pstr = (char*) ""; for (kp = 0; (kp = mprGetNextKey(params, kp)) != 0; ) { pstr = sjoin(pstr, mprUriEncode(kp->key, MPR_ENCODE_URI_COMPONENT), "=", mprUriEncode(kp->data, MPR_ENCODE_URI_COMPONENT), "&", NULL); } if (pstr[0]) { /* Trim last "&" */ pstr[strlen(pstr) - 1] = '\0'; } mprPutToBuf(buf, "%s-params='%s", params); } } mprPutStringToBuf(buf, kp->key); mprPutStringToBuf(buf, "='"); mprPutStringToBuf(buf, value); mprPutCharToBuf(buf, '\''); } } mprAddNullToBuf(buf); return mprGetBufStart(buf); }
/* Expand ${token} references in a path or string. */ static char *stemplateInner(cchar *str, void *keys, int json) { MprBuf *buf; cchar *value; char *src, *result, *cp, *tok; if (str) { if (schr(str, '$') == 0) { return sclone(str); } buf = mprCreateBuf(0, 0); for (src = (char*) str; *src; ) { if (*src == '$') { if (*++src == '{') { for (cp = ++src; *cp && *cp != '}'; cp++) ; tok = snclone(src, cp - src); } else { for (cp = src; *cp && (isalnum((uchar) *cp) || *cp == '_'); cp++) ; tok = snclone(src, cp - src); } if (json) { value = mprGetJson(keys, tok); } else { value = mprLookupKey(keys, tok); } if (value != 0) { mprPutStringToBuf(buf, value); if (src > str && src[-1] == '{') { src = cp + 1; } else { src = cp; } } else { mprPutCharToBuf(buf, '$'); if (src > str && src[-1] == '{') { mprPutCharToBuf(buf, '{'); } mprPutCharToBuf(buf, *src++); } } else { mprPutCharToBuf(buf, *src++); } } mprAddNullToBuf(buf); result = sclone(mprGetBufStart(buf)); } else { result = MPR->emptyString; } return result; }
static EjsString *joinArray(Ejs *ejs, EjsArray *ap, int argc, EjsObj **argv) { EjsString *sep, *sp; MprBuf *buf; ssize len; int i, nonString; sep = (argc == 1) ? (EjsString*) argv[0] : NULL; if (sep == ESV(empty) && ap->length == 1 && ejsIs(ejs, ap->data[0], String)) { /* Optimized path for joining [string]. This happens frequently with fun(...args) */ return (EjsString*) ap->data[0]; } /* Get an estimate of the string length */ len = 0; nonString = 0; for (i = 0; i < ap->length; i++) { sp = (EjsString*) ap->data[i]; if (!ejsIs(ejs, sp, String)) { nonString = 1; continue; } len += sp->length; } if (sep) { len += (ap->length * sep->length); } if (nonString) { len += ME_MAX_BUFFER; } buf = mprCreateBuf(len + 1, -1); for (i = 0; i < ap->length; i++) { sp = (EjsString*) ap->data[i]; if (!ejsIsDefined(ejs, sp)) { continue; } sp = ejsToString(ejs, sp); if (!ejsIsDefined(ejs, sp)) { continue; } if (i > 0 && sep) { mprPutBlockToBuf(buf, sep->value, sep->length); } mprPutBlockToBuf(buf, sp->value, sp->length); } mprAddNullToBuf(buf); return ejsCreateStringFromBytes(ejs, mprGetBufStart(buf), mprGetBufLength(buf)); }
static void setChunkPrefix(MaQueue *q, MaPacket *packet) { if (packet->prefix) { return; } packet->prefix = mprCreateBuf(packet, 32, 32); /* * NOTE: prefixes don't count in the queue length. No need to adjust q->count */ if (maGetPacketLength(packet)) { mprPutFmtToBuf(packet->prefix, "\r\n%x\r\n", maGetPacketLength(packet)); } else { mprPutStringToBuf(packet->prefix, "\r\n0\r\n\r\n"); } }
static void setChunkPrefix(MaQueue *q, MaPacket *packet) { MaConn *conn; conn = q->conn; if (packet->prefix) { return; } packet->prefix = mprCreateBuf(packet, 32, 32); if (packet->count) { mprPutFmtToBuf(packet->prefix, "\r\n%x\r\n", packet->count); } else { mprPutStringToBuf(packet->prefix, "\r\n0\r\n\r\n"); } }
/* Cast the object operand to a primitive type */ static EjsAny *castXml(Ejs *ejs, EjsXML *xml, EjsType *type) { EjsXML *item; EjsObj *result; MprBuf *buf; assert(ejsIsXML(ejs, xml)); if (type == ESV(XMLList)) { return xml; } switch (type->sid) { case S_Object: case S_Boolean: return ejsCreateBoolean(ejs, 1); case S_Number: result = castXml(ejs, xml, ESV(String)); return ejsToNumber(ejs, result); case S_String: if (xml->kind == EJS_XML_ELEMENT) { if (xml->elements == 0) { return ESV(empty); } if (xml->elements && mprGetListLength(xml->elements) == 1) { // TODO - what about PI and comments? item = mprGetFirstItem(xml->elements); if (item->kind == EJS_XML_TEXT) { return item->value; } } } buf = mprCreateBuf(BIT_MAX_BUFFER, -1); if (ejsXMLToBuf(ejs, buf, xml, -1) < 0) { return 0; } return ejsCreateStringFromAsc(ejs, (char*) buf->start); default: ejsThrowTypeError(ejs, "Cannot cast to this type"); return 0; } return 0; }
PUBLIC cchar *sjoinArgs(int argc, cchar **argv, cchar *sep) { MprBuf *buf; int i; if (sep == 0) { sep = ""; } buf = mprCreateBuf(0, 0); for (i = 0; i < argc; i++) { mprPutToBuf(buf, "%s%s", argv[i], sep); } if (argc > 0) { mprAdjustBufEnd(buf, -1); } return mprBufToString(buf); }
/* * Create a new packet. If size is -1, then also create a default growable buffer -- used for incoming body content. If * size > 0, then create a non-growable buffer of the requested size. */ MaPacket *maCreatePacket(MprCtx ctx, int size) { MaPacket *packet; packet = mprAllocObjZeroed(ctx, MaPacket); if (packet == 0) { return 0; } if (size != 0) { packet->content = mprCreateBuf(packet, size < 0 ? MA_BUFSIZE: size, -1); if (packet->content == 0) { mprFree(packet); return 0; } } return packet; }
/* Put a string to the file. This will put the file into buffered mode. */ PUBLIC ssize mprPutFileString(MprFile *file, cchar *str) { MprBuf *bp; ssize total, bytes, count; char *buf; assert(file); count = slen(str); /* Buffer output and flush when full. */ if (file->buf == 0) { file->buf = mprCreateBuf(ME_MAX_BUFFER, 0); if (file->buf == 0) { return MPR_ERR_CANT_ALLOCATE; } } bp = file->buf; if (mprGetBufLength(bp) > 0 && mprGetBufSpace(bp) < count) { mprFlushFile(file); } total = 0; buf = (char*) str; while (count > 0) { bytes = mprPutBlockToBuf(bp, buf, count); if (bytes < 0) { return MPR_ERR_CANT_ALLOCATE; } else if (bytes == 0) { if (mprFlushFile(file) < 0) { return MPR_ERR_CANT_WRITE; } continue; } count -= bytes; buf += bytes; total += bytes; file->pos += (MprOff) bytes; } return total; }
PUBLIC int httpApplyUserGroup() { #if ME_UNIX_LIKE Http *http; http = HTTP; if (http->userChanged || http->groupChanged) { if (!smatch(MPR->logPath, "stdout") && !smatch(MPR->logPath, "stderr")) { if (chown(MPR->logPath, http->uid, http->gid) < 0) { mprLog("critical http", 0, "Cannot change ownership on %s", MPR->logPath); } } } if (httpApplyChangedGroup() < 0 || httpApplyChangedUser() < 0) { return MPR_ERR_CANT_COMPLETE; } if (http->userChanged || http->groupChanged) { struct group *gp; gid_t glist[64], gid; MprBuf *gbuf = mprCreateBuf(0, 0); cchar *groups; int i, ngroup; gid = getgid(); ngroup = getgroups(sizeof(glist) / sizeof(gid_t), glist); if (ngroup > 1) { mprPutStringToBuf(gbuf, ", groups: "); for (i = 0; i < ngroup; i++) { if (glist[i] == gid) continue; if ((gp = getgrgid(glist[i])) != 0) { mprPutToBuf(gbuf, "%s (%d) ", gp->gr_name, glist[i]); } else { mprPutToBuf(gbuf, "(%d) ", glist[i]); } } } groups = mprGetBufStart(gbuf); mprLog("info http", 2, "Running as user \"%s\" (%d), group \"%s\" (%d)%s", http->user, http->uid, http->group, http->gid, groups); } #endif return 0; }
static int toStringMethod(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) { MprBuf *bp; int saveMaxDepth, saveDepth, saveFlags; saveMaxDepth = ep->maxDepth; if (argc >= 1) { ep->maxDepth = ejsVarToInteger(argv[0]); } else if (ep->maxDepth == 0) { ep->maxDepth = MAXINT; } saveFlags = ep->flags; if (argc >= 2) { if (ejsVarToBoolean(argv[1])) { ep->flags |= EJS_FLAGS_ENUM_HIDDEN; } } if (argc == 3) { if (ejsVarToBoolean(argv[2])) { ep->flags |= EJS_FLAGS_ENUM_BASE; } } bp = mprCreateBuf(ep, 0, 0); saveDepth = ep->depth; formatVar(ep, bp, thisObj); ep->depth = saveDepth; ep->maxDepth = saveMaxDepth; mprAddNullToBuf(bp); ejsWriteVarAsString(ep, ep->result, mprGetBufStart(bp)); mprFree(bp); ep->flags = saveFlags; return 0; }
/* Get the SSL state of the socket in a buffer */ static char *getOssState(MprSocket *sp) { OpenSocket *osp; MprBuf *buf; X509 *cert; char subject[512], issuer[512]; osp = sp->sslSocket; buf = mprCreateBuf(0, 0); mprPutToBuf(buf, "{\"provider\":\"openssl\",\"cipher\":\"%s\",\"session\":\"%s\",", SSL_get_cipher(osp->handle), sp->session); mprPutToBuf(buf, "\"peer\":\"%s\",", sp->peerName); mprPutToBuf(buf, "\"%s\":{", sp->acceptIp ? "client" : "server"); if ((cert = SSL_get_peer_certificate(osp->handle)) != 0) { X509_NAME_oneline(X509_get_issuer_name(cert), issuer, sizeof(issuer) -1); mprPutToBuf(buf, "\"issuer\": {"); parseCertFields(buf, &issuer[1]); mprPutToBuf(buf, "},"); X509_NAME_oneline(X509_get_subject_name(cert), subject, sizeof(subject) -1); mprPutToBuf(buf, "\"subject\": {"); parseCertFields(buf, &subject[1]); mprPutToBuf(buf, "},"); X509_free(cert); } if ((cert = SSL_get_certificate(osp->handle)) != 0) { mprPutToBuf(buf, "\"issuer\": {"); X509_NAME_oneline(X509_get_issuer_name(cert), issuer, sizeof(issuer) -1); parseCertFields(buf, &issuer[1]); mprPutToBuf(buf, "},"); mprPutToBuf(buf, "\"subject\": {"); X509_NAME_oneline(X509_get_subject_name(cert), subject, sizeof(subject) -1); parseCertFields(buf, &subject[1]); mprPutToBuf(buf, "},"); /* Don't call X509_free on own cert */ } mprAdjustBufEnd(buf, -1); mprPutToBuf(buf, "}}"); return mprBufToString(buf); }
/* compressString(data: String): String */ static EjsString *zlib_compressString(Ejs *ejs, EjsObj *unused, int argc, EjsObj **argv) { EjsString *in; MprBuf *out; z_stream zs; uchar outbuf[ZBUFSIZE]; ssize size, nbytes; int level, flush; in = (EjsString*) argv[0]; if ((size = in->length) == 0) { return ESV(empty); } if ((out = mprCreateBuf(in->length, 0)) == 0) { return 0; } zs.zalloc = Z_NULL; zs.zfree = Z_NULL; zs.opaque = Z_NULL; level = Z_DEFAULT_COMPRESSION; deflateInit(&zs, level); zs.next_in = (uchar*) in->value; zs.avail_in = (int) size; do { flush = (zs.avail_in == 0) ? Z_FINISH : Z_NO_FLUSH; do { zs.avail_out = ZBUFSIZE; zs.next_out = outbuf; deflate(&zs, flush); nbytes = ZBUFSIZE - zs.avail_out; if (mprPutBlockToBuf(out, (char*) outbuf, nbytes) != nbytes) { ejsThrowIOError(ejs, "Cannot copy to output buffer"); deflateEnd(&zs); return 0; } } while (zs.avail_out == 0); assure(zs.avail_in == 0); } while (flush != Z_FINISH); deflateEnd(&zs); return ejsCreateStringFromBytes(ejs, mprGetBufStart(out), mprGetBufLength(out)); }
static char *hashToString(MprHash *hash, cchar *sep) { MprBuf *buf; cchar *data; char key[8]; int i, len; len = mprGetHashLength(hash); buf = mprCreateBuf(0, 0); mprPutCharToBuf(buf, '{'); for (i = 0; i < len; ) { data = mprLookupKey(hash, itosbuf(key, sizeof(key), i, 10)); mprPutStringToBuf(buf, data); if (++i < len) { mprPutStringToBuf(buf, sep ? sep : ","); } } mprPutCharToBuf(buf, '}'); mprAddNullToBuf(buf); return mprGetBufStart(buf); }