Esempio n. 1
0
/*
    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;
}
Esempio n. 2
0
static int srmatch(cchar *s, void *pattern, ...)
{
    va_list     ap;
    char        **str;
    ssize       len;
    int         count, i, index, matches[64 * 2];

    va_start(ap, pattern);
    count = pcre_exec(pattern, NULL, s, (int) slen(s), 0, 0, matches, sizeof(matches) / sizeof(int));
    for (i = 0, str = 0; i < count; i++) {
        str = va_arg(ap, char**);
        if (str == NULL) {
            break;
        }
        index = i * 2;
        len = matches[index + 1] - matches[index];
        *str = snclone(&s[matches[index]], len);
    }
    if (str) {
        while ((str = va_arg(ap, char**)) != 0) {
            *str = 0;
        }
    }
    va_end(ap);
    return count / 2;
}
Esempio n. 3
0
static void test_snclone(void)
{
	char* clone = snclone("abc", 2);
	PCU_ASSERT_PTR_NOT_NULL(clone);
	PCU_ASSERT_STRING_EQUAL("ab", clone);
	free(clone);
}
Esempio n. 4
0
static void test_snclone_empty(void)
{
	char* clone = snclone("", 0);
	PCU_ASSERT_PTR_NOT_NULL(clone);
	PCU_ASSERT_STRING_EQUAL("", clone);
	free(clone);
}
Esempio n. 5
0
/*
    String to list. This parses the string into space separated arguments. Single and double quotes are supported.
    This returns a stable list.
 */
PUBLIC MprList *stolist(cchar *src)
{
    MprList     *list;
    cchar       *start;
    int         quote;

    list = mprCreateList(0, MPR_LIST_STABLE);
    while (src && *src != '\0') {
        while (isspace((uchar) *src)) {
            src++;
        }
        if (*src == '\0')  {
            break;
        }
        for (quote = 0, start = src; *src; src++) {
            if (*src == '\\') {
                src++;
            } else if (*src == '"' || *src == '\'') {
                if (*src == quote) {
                    src++;
                    break;
                } else if (quote == 0) {
                    quote = *src;
                }
            } else if (isspace((uchar) *src) && !quote) {
                break;
            }
        }
        mprAddItem(list, snclone(start, src - start));
    }
    return list;
}
Esempio n. 6
0
static void traceEvent(HttpConn *conn, int event, int arg)
{
    HttpPacket  *packet;

    if (event == HTTP_EVENT_READABLE) {
        packet = conn->readq->first;
        mprLog(3, "websock.c: read %s event, last %d", packet->type == WS_MSG_TEXT ? "text" : "binary", packet->last);
        mprLog(3, "websock.c: read: (start of data only) \"%s\"", snclone(mprGetBufStart(packet->content), 40));

    } else if (event == HTTP_EVENT_APP_CLOSE) {
        mprLog(3, "websock.c: close event. Status status %d, orderly closed %d, reason %s", arg,
               httpWebSocketOrderlyClosed(conn), httpGetWebSocketCloseReason(conn));

    } else if (event == HTTP_EVENT_ERROR) {
        mprLog(2, "websock.c: error event");
    }
}
Esempio n. 7
0
static void echo_callback(HttpConn *conn, int event, int arg)
{
    HttpPacket      *packet;
    HttpWebSocket   *ws;
    cchar           *data;

    traceEvent(conn, event, arg);
    if (event == HTTP_EVENT_READABLE) {
        packet = httpGetPacket(conn->readq);
        assure(packet);
        /* Ignore precedding packets and just trace the last */
        if (packet->last) {
            ws = conn->rx->webSocket;
            httpSend(conn, "{type: %d, last: %d, length: %d, data: \"%s\"}\n", packet->type, packet->last,
                     ws->messageLength, snclone(mprGetBufStart(packet->content), 10));
        }
    }
}
Esempio n. 8
0
/*
    Parse cached content of the form:  headers \n\n data
    Set headers in the current requeset and return a reference to the data portion
 */
static cchar *setHeadersFromCache(HttpConn *conn, cchar *content)
{
    cchar   *data;
    char    *header, *headers, *key, *value, *tok;

    if ((data = strstr(content, "\n\n")) == 0) {
        data = content;
    } else {
        headers = snclone(content, data - content);
        data += 2;
        for (header = stok(headers, "\n", &tok); header; header = stok(NULL, "\n", &tok)) {
            key = stok(header, ": ", &value);
            if (smatch(key, "X-Status")) {
                conn->tx->status = (int) stoi(value);
            } else {
                httpAddHeader(conn, key, value);
            }
        }
    }
    return data;
}
Esempio n. 9
0
static bool inRange(MprVersion *vp, cchar *expr)
{
    char    *cp, *ver, *op, *base, *pre, *all;
    cchar   *high, *low;
    uint64  factor, min, max, num;

    while (isspace((uchar) *expr)) expr++;

    if (srmatch(expr, semExpr, &all, &op, &ver, NULL) <= 0) {
        mprLog("error", 5, "Bad version expression: %s", expr);
        return 0;
    }
    if (smatch(op, "~")) {
        /*
            ~VER   Compatible with VER at the level of specificity given.
                   ~1.2.3 == (>=1.2.3 <1.3.0) Compatible at the patch level
                   ~1.2 == 1.2.x   Compatible at the minor level
                   ~1 == 1.x   Compatible at the major level
         */
        if (partCount(ver) == 3 && (cp = srchr(ver, '.')) != 0) {
            high = sjoin(snclone(ver, cp - ver), ".", MAX_VER_STR, NULL);
            if ((cp = schr(ver, '-')) != 0) {
                high = sjoin(high, cp, NULL);
            }
            return inRange(vp, sjoin(">=", ver, NULL)) &&
                   inRange(vp, sjoin("<", high, NULL));
        }
        return inRange(vp, completeVersion(ver, "x"));
    } 
    if (smatch(op, "^")) {
        /*
            ^VER  Compatible with VER at the most significant level.
                  ^0.2.3 == 0.2.3 <= VER < 0.3.0
                  ^1.2.3 == 1.2.3 <= VER < 2.0.0
            So convert to a range
         */
        high = ver;
        for (cp = ver, factor = VER_FACTOR * VER_FACTOR; *cp; cp++) {
            if (*cp == '.') {
                factor /= VER_FACTOR;
            } else if (isdigit((uchar) *cp) && *cp != '0') {
                num = (stoi(cp) + 1) * factor;
                high = numberToVersion(num);
                if ((cp = schr(ver, '-')) != 0) {
                    high = sjoin(high, cp, NULL);
                }
                break;
            }
        }
        return inRange(vp, sjoin(">=", ver, NULL)) && inRange(vp, sjoin("<", high, NULL));
    }
    ver = completeVersion(ver, "x");
    if (srmatch(ver, semCriteria, &all, &base, &pre, NULL) <= 0) {
        mprLog("error", 5, "Cannot match version %s", ver);
        return 0;
    }
    if (vp->preVersion) {
        if (!pre) {
            return 0;
        }
        if (snumber(vp->preVersion)) {
            if (stoi(pre) < stoi(vp->preVersion)) {
                return 0;
            }
        } else {
            if (scmp(pre, vp->preVersion) < 0 && !smatch(pre, "-")) {
                return 0;
            }
        }
    }
    min = 0;
    max = MAX_VER * VER_FACTOR * VER_FACTOR;
    if (schr(ver, 'x')) {
        if (smatch(op, ">=")) {
            // 1.2.3 >= 2.x.x ... 1.2.3 >= 2.0.0
            low = sreplace(ver, "x", "0");
            min = versionToNumber(low);
        } else if (smatch(op, "<=")) {
            // 1.2.3 < 2.x.x ... 1.2.3 <2.MAX.MAX
            high = sreplace(ver, "x", MAX_VER_STR);
            max = versionToNumber(high);
        } else if (*op == '>') {
            // 1.2.3 > 2.x.x ... 1.2.3 > 2.0.0
            low = sreplace(ver, "x", "0");
            min = versionToNumber(low) + 1;
        } else if (*op == '<') {
            // 1.2.3 < 2.x.x ... 1.2.3 <2.MAX.MAX
            high = sreplace(ver, "x", MAX_VER_STR);
            max = versionToNumber(high) - 1;
        } else {
            low = sreplace(ver, "x", "0");
            high = sreplace(ver, "x", MAX_VER_STR);
            return inRange(vp, sjoin(">=", low, NULL)) && inRange(vp, sjoin("<", high, NULL));
        }
    } else if (smatch(op, ">=")) {
        min = versionToNumber(base);
    } else if (smatch(op, "<=")) {
        max = versionToNumber(base);
    } else if (*op == '>') {
        min = versionToNumber(base) + 1;
    } else if (*op == '<') {
        max = versionToNumber(base) - 1;
    } else {
        min = max = versionToNumber(base);
    }
    if (min <= vp->numberVersion && vp->numberVersion <= max) {
        return 1;
    }
    return 0;
}
Esempio n. 10
0
File: uri.c Progetto: DavidQuan/http
/*
    Create and initialize a URI. This accepts full URIs with schemes (http:) and partial URLs
    Support IPv4 and [IPv6]. Supported forms:

        SCHEME://[::]:PORT/URI
        SCHEME://HOST:PORT/URI
        [::]:PORT/URI
        :PORT/URI
        HOST:PORT/URI
        PORT/URI
        /URI
        URI

        NOTE: HOST/URI is not supported and requires a scheme prefix. This is because it is ambiguous with a 
        relative uri path.

    Missing fields are null or zero.
 */
PUBLIC HttpUri *httpCreateUri(cchar *uri, int flags)
{
    HttpUri     *up;
    char        *tok, *next;

    if ((up = mprAllocObj(HttpUri, manageUri)) == 0) {
        return 0;
    }
    tok = sclone(uri);

    /*
        [scheme://][hostname[:port]][/path[.ext]][#ref][?query]
        First trim query and then reference from the end
     */
    if ((next = schr(tok, '?')) != 0) {
        *next++ = '\0';
        up->query = sclone(next);
    }
    if ((next = schr(tok, '#')) != 0) {
        *next++ = '\0';
        up->reference = sclone(next);
    }

    /*
        [scheme://][hostname[:port]][/path]
     */
    if ((next = scontains(tok, "://")) != 0) {
        up->scheme = snclone(tok, (next - tok));
        if (smatch(up->scheme, "http")) {
            if (flags & HTTP_COMPLETE_URI) {
                up->port = 80;
            }
        } else if (smatch(up->scheme, "ws")) {
            if (flags & HTTP_COMPLETE_URI) {
                up->port = 80;
            }
            up->webSockets = 1;
        } else if (smatch(up->scheme, "https")) {
            if (flags & HTTP_COMPLETE_URI) {
                up->port = 443;
            }
            up->secure = 1;
        } else if (smatch(up->scheme, "wss")) {
            if (flags & HTTP_COMPLETE_URI) {
                up->port = 443;
            }
            up->secure = 1;
            up->webSockets = 1;
        }
        tok = &next[3];
    }

    /*
        [hostname[:port]][/path]
     */
    if (*tok == '[' && ((next = strchr(tok, ']')) != 0)) {
        /* IPv6  [::]:port/uri */
        up->host = snclone(&tok[1], (next - tok) - 1);
        tok = ++next;

    } else if (*tok && *tok != '/' && *tok != ':' && (up->scheme || strchr(tok, ':'))) {
        /*
            Supported forms:
                scheme://hostname
                hostname:port
         */
        if ((next = spbrk(tok, ":/")) == 0) {
            next = &tok[slen(tok)];
        }
        up->host = snclone(tok, next - tok);
        tok = next;
    }
    assert(tok);

    /* [:port][/path] */
    if (*tok == ':') {
        up->port = atoi(++tok);
        if ((tok = schr(tok, '/')) == 0) {
            tok = "";
        }
    }
    assert(tok);

    /* [/path] */
    if (*tok) {
        up->path = sclone(tok);
        /* path[.ext[/extra]] */
        if ((tok = srchr(up->path, '.')) != 0) {
            if (tok[1]) {
                if ((next = srchr(up->path, '/')) != 0) {
                    if (next < tok) {
                        up->ext = sclone(++tok);
                    }
                } else {
                    up->ext = sclone(++tok);
                }
            }
        }
    }
    if (flags & (HTTP_COMPLETE_URI | HTTP_COMPLETE_URI_PATH)) {
        if (up->path == 0 || *up->path == '\0') {
            up->path = sclone("/");
        }
    }
    up->secure = smatch(up->scheme, "https") || smatch(up->scheme, "wss");
    up->webSockets = (smatch(up->scheme, "ws") || smatch(up->scheme, "wss"));

    if (flags & HTTP_COMPLETE_URI) {
        if (!up->scheme) {
            up->scheme = sclone("http");
        }
        if (!up->host) {
            up->host = sclone("localhost");
        }
        if (!up->port) {
            up->port = up->secure ? 443 : 80;
        }
    }
    up->valid = httpValidUriChars(uri);
    return up;
}
Esempio n. 11
0
File: uri.c Progetto: DavidQuan/http
/*
    Create and initialize a URI. This accepts full URIs with schemes (http:) and partial URLs
 */
PUBLIC HttpUri *httpCreateUriFromParts(cchar *scheme, cchar *host, int port, cchar *path, cchar *reference, cchar *query, 
        int flags)
{
    HttpUri     *up;
    char        *cp, *tok;

    if ((up = mprAllocObj(HttpUri, manageUri)) == 0) {
        up->valid = 0;
        return 0;
    }
    if (!httpValidUriChars(scheme) || !httpValidUriChars(host) || !httpValidUriChars(path) ||
        !httpValidUriChars(reference) || !httpValidUriChars(query)) {
        up->valid = 0;
        return up;
    }
    if (scheme) {
        up->scheme = sclone(scheme);
        up->secure = (smatch(up->scheme, "https") || smatch(up->scheme, "wss"));
        up->webSockets = (smatch(up->scheme, "ws") || smatch(up->scheme, "wss"));

    } else if (flags & HTTP_COMPLETE_URI) {
        up->scheme = "http";
    }
    if (host) {
        if (*host == '[' && ((cp = strchr(host, ']')) != 0)) {
            up->host = snclone(&host[1], (cp - host) - 2);
            if ((cp = schr(++cp, ':')) && port == 0) {
                port = (int) stoi(++cp);
            }
        } else {
            up->host = sclone(host);
            if ((cp = schr(up->host, ':')) && port == 0) {
                port = (int) stoi(++cp);
            }
        }
    } else if (flags & HTTP_COMPLETE_URI) {
        up->host = sclone("localhost");
    }
    if (port) {
        up->port = port;
    }
    if (path) {
        while (path[0] == '/' && path[1] == '/') {
            path++;
        }
        up->path = sclone(path);
    }
    if (flags & (HTTP_COMPLETE_URI | HTTP_COMPLETE_URI_PATH)) {
        if (up->path == 0 || *up->path == '\0') {
            up->path = sclone("/");
        }
    }
    if (reference) {
        up->reference = sclone(reference);
    }
    if (query) {
        up->query = sclone(query);
    }
    if ((tok = srchr(up->path, '.')) != 0) {
        if ((cp = srchr(up->path, '/')) != 0) {
            if (cp <= tok) {
                up->ext = sclone(&tok[1]);
            }
        } else {
            up->ext = sclone(&tok[1]);
        }
    }
    up->valid = 1;
    return up;
}
Esempio n. 12
0
static void test_snclone_null(void)
{
	char *clone = snclone(NULL, 1);
	PCU_ASSERT_PTR_NULL(clone);
}
Esempio n. 13
0
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;
}