Exemple #1
0
PUBLIC void httpSetAuthForm(HttpRoute *parent, cchar *loginPage, cchar *loginService, cchar *logoutService, cchar *loggedIn)
{
    HttpAuth    *auth;
    HttpRoute   *route;
    bool        secure;

    secure = 0;
    auth = parent->auth;
    auth->loginPage = sclone(loginPage);
    if (loggedIn) {
        auth->loggedIn = sclone(loggedIn);
    }
    /*
        Create routes without auth for the loginPage, loginService and logoutService
     */
    if ((route = httpCreateInheritedRoute(parent)) != 0) {
        if (sstarts(loginPage, "https:///")) {
            loginPage = &loginPage[8];
            secure = 1;
        }
        httpSetRoutePattern(route, loginPage, 0);
        route->auth->type = 0;
        if (secure) {
            httpAddRouteCondition(route, "secure", 0, 0);
        }
        httpFinalizeRoute(route);
    }
    if (loginService && *loginService) {
        if (sstarts(loginService, "https:///")) {
            loginService = &loginService[8];
            secure = 1;
        }
        route = httpCreateActionRoute(parent, loginService, loginServiceProc);
        httpSetRouteMethods(route, "POST");
        route->auth->type = 0;
        if (secure) {
            httpAddRouteCondition(route, "secure", 0, 0);
        }
    }
    if (logoutService && *logoutService) {
        if (sstarts(logoutService, "https://")) {
            logoutService = &logoutService[8];
            secure = 1;
        }
        httpSetRouteMethods(route, "POST");
        route = httpCreateActionRoute(parent, logoutService, logoutServiceProc);
        route->auth->type = 0;
        if (secure) {
            httpAddRouteCondition(route, "secure", 0, 0);
        }
    }
}
Exemple #2
0
/*  
    function WebSocket(uri: Uri, protocols = null, options)

    options = {
        certificate: Path,
        verify: Boolean,
    }
 */
static EjsWebSocket *wsConstructor(Ejs *ejs, EjsWebSocket *ws, int argc, EjsObj **argv)
{
    EjsAny      *certificate;
    bool        verify;

    assert(ejsIsPot(ejs, ws));

    ejsLoadHttpService(ejs);
    ws->ejs = ejs;
    verify = 0;

    ws->uri = httpUriToString(((EjsUri*) argv[0])->uri, 0);
    if (argc >= 2) {
        if (ejsIs(ejs, argv[1], Array)) {
            ws->protocols = sclone((ejsToString(ejs, argv[1]))->value);
        } else if (ejsIs(ejs, argv[1], String)) {
            ws->protocols = sclone(((EjsString*) argv[1])->value);
        } else {
            ws->protocols = sclone("chat");
        }
    } else {
        ws->protocols = sclone("chat");
    }
    if (*ws->protocols == '\0') {
        ejsThrowArgError(ejs, "Bad protocol");
        return 0;
    }
    if (argc >= 3) {
        ws->frames = ejsGetPropertyByName(ejs, argv[2], EN("frames")) == ESV(true);
        verify = ejsGetPropertyByName(ejs, argv[2], EN("verify")) == ESV(true);
        if ((certificate = ejsGetPropertyByName(ejs, argv[2], EN("certificate"))) != 0) {
            ws->certFile = ejsToMulti(ejs, argv[0]);
        }
    }
    if ((ws->conn = httpCreateConn(MPR->httpService, NULL, ejs->dispatcher)) == 0) {
        ejsThrowMemoryError(ejs);
        return 0;
    }
    httpSetAsync(ws->conn, 1);
    httpPrepClientConn(ws->conn, 0);
    httpSetConnNotifier(ws->conn, webSocketNotify);
    httpSetWebSocketProtocols(ws->conn, ws->protocols);
    httpSetConnContext(ws->conn, ws);
    if (sstarts(ws->uri, "wss")) {
        ws->ssl = mprCreateSsl(0);
        mprVerifySslIssuer(ws->ssl, verify);
        mprVerifySslPeer(ws->ssl, verify);
#if FUTURE
        if (!hp->caFile) {
            //MOB - Some define for this.
            hp->caFile = mprJoinPath(mprGetAppDir(), "http-ca.crt");
        }
        mprSetSslCaFile(hp->ssl, hp->caFile);
        mprSetSslCaFile(hp->ssl, mprJoinPath(mprGetAppDir(), "http-ca.crt"));
#endif
    }
    startWebSocketRequest(ejs, ws);
    return ws;
}
Exemple #3
0
/*
    Get a printable version of a buffer. Return a pointer to the start of printable data.
    This will use the tx or rx mime type if possible.
    Skips UTF encoding prefixes
 */
PUBLIC cchar *httpMakePrintable(HttpTrace *trace, HttpConn *conn, cchar *event, cchar *buf, ssize *lenp)
{
    cchar   *start, *cp, *digits;
    char    *data, *dp;
    ssize   len;
    int     i;

    if (conn) {
        if (smatch(event, "rx.body")) {
            if (sstarts(mprLookupMime(0, conn->rx->mimeType), "text/")) {
                return buf;
            }
        } else if (smatch(event, "tx.body")) {
            if (sstarts(mprLookupMime(0, conn->tx->mimeType), "text/")) {
                return buf;
            }
        }
    }
    start = buf;
    len = *lenp;
    if (len > 3 && start[0] == (char) 0xef && start[1] == (char) 0xbb && start[2] == (char) 0xbf) {
        /* Step over UTF encoding */
        start += 3;
        *lenp -= 3;
    }
    len = min(len, trace->maxContent);

    for (i = 0; i < len; i++) {
        if (!isprint((uchar) start[i]) && start[i] != '\n' && start[i] != '\r' && start[i] != '\t') {
            data = mprAlloc(len * 3 + ((len / 16) + 1) + 1);
            digits = "0123456789ABCDEF";
            for (i = 0, cp = start, dp = data; cp < &start[len]; cp++) {
                *dp++ = digits[(*cp >> 4) & 0x0f];
                *dp++ = digits[*cp & 0x0f];
                *dp++ = ' ';
                if ((++i % 16) == 0) {
                    *dp++ = '\n';
                }
            }
            *dp++ = '\n';
            *dp = '\0';
            start = data;
            *lenp = dp - start;
            break;
        }
    }
Exemple #4
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);
        }
    }
Exemple #5
0
/*
    Common controller run for every action invoked
    This tests if the user is logged in and authenticated.
    Access to certain pages are permitted without authentication so the user can login
 */
static void commonController(HttpConn *conn)
{
    cchar   *uri;

    if (!httpLoggedIn(conn)) {
        uri = getUri();
        if (sstarts(uri, "/public/") || smatch(uri, "/user/login") || smatch(uri, "/user/logout")) {
            return;
        }
        httpError(conn, HTTP_CODE_UNAUTHORIZED, "Access Denied. Login required");
    }
}
Exemple #6
0
PUBLIC cchar *espGetConfig(HttpRoute *route, cchar *key, cchar *defaultValue)
{
    cchar       *value;

    if (sstarts(key, "app.")) {
        mprLog("warn esp", 0, "Using legacy \"app\" configuration property");
    }
    if ((value = mprGetJson(route->config, key)) != 0) {
        return value;
    }
    return defaultValue;
}
Exemple #7
0
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;
}
Exemple #8
0
static HttpRoute *createLoginRoute(HttpRoute *route, cchar *pattern, HttpAction action)
{
    bool    secure;

    secure = 0;
    if (sstarts(pattern, "https:///")) {
        pattern = &pattern[8];
        secure = 1;
    } else if (sstarts(pattern, "http:///")) {
        pattern = &pattern[7];
    }
    if ((route = httpCreateInheritedRoute(route)) != 0) {
        httpSetRoutePattern(route, sjoin("^", pattern, "$", NULL), 0);
        if (secure) {
            httpAddRouteCondition(route, "secure", "https://", HTTP_ROUTE_REDIRECT);
        }
        if (action) {
            route->handler = route->http->actionHandler;
            httpDefineAction(pattern, action);
        }
        httpFinalizeRoute(route);
    }
    return route;
}
Exemple #9
0
/*
    Common base run for every request.
 */
static void commonBase(HttpStream *stream)
{
    cchar   *uri;

    if (!httpIsAuthenticated(stream)) {
        /*
            Access to certain pages are permitted without authentication so the user can login and logout.
         */
        uri = getUri();
        if (sstarts(uri, "/public/") || smatch(uri, "/user/login") || smatch(uri, "/user/logout")) {
            return;
        }
        feedback("error", "Access Denied. Login required.");
        redirect("/public/login.esp");
    }
}
Exemple #10
0
/* 
   Append a header. If already defined, the value is catenated to the pre-existing value after a ", " separator.
   As per the HTTP/1.1 spec. Except for Set-Cookie which HTTP permits multiple headers but not of the same cookie. Ugh!
 */
PUBLIC void httpAppendHeader(HttpConn *conn, cchar *key, cchar *fmt, ...)
{
    va_list     vargs;
    MprKey      *kp;
    char        *value;
    cchar       *cookie;

    if (!conn->tx) {
        return;
    }
    assert(key && *key);
    assert(fmt && *fmt);

    va_start(vargs, fmt);
    value = sfmtv(fmt, vargs);
    va_end(vargs);

    /*
        HTTP permits Set-Cookie to have multiple cookies. Other headers must comma separate multiple values.
        For Set-Cookie, must allow duplicates but not of the same cookie.
     */
    kp = mprLookupKeyEntry(conn->tx->headers, key);
    if (kp) {
        if (scaselessmatch(key, "Set-Cookie")) {
            cookie = stok(sclone(value), "=", NULL);
            while (kp) {
                if (scaselessmatch(kp->key, "Set-Cookie")) {
                    if (sstarts(kp->data, cookie)) {
                        kp->data = value;
                        break;
                    }
                }
                kp = kp->next;
            }
            if (!kp) {
                mprAddDuplicateKey(conn->tx->headers, key, value);
            }
        } else {
            addHdr(conn, key, sfmt("%s, %s", kp->data, value));
        }
    } else {
        addHdr(conn, key, value);
    }
}
Exemple #11
0
static void errorRedirect(HttpConn *conn, cchar *uri)
{
    HttpTx      *tx;

    /*
        If the response has started or it is an external redirect ... do a redirect
     */
    tx = conn->tx;
    if (sstarts(uri, "http") || tx->flags & HTTP_TX_HEADERS_CREATED) {
        httpRedirect(conn, HTTP_CODE_MOVED_PERMANENTLY, uri);
    } else {
        /*
            No response started and it is an internal redirect, so we can rerun the request.
            Set finalized to "cap" any output. processCompletion() in rx.c will rerun the request using the errorDocument.
         */
        tx->errorDocument = uri;
        tx->finalized = tx->finalizedOutput = tx->finalizedConnector = 1;
    }
}
/*
    Start the user's default browser
 */
static int runBrowser(char *page)
{
    PROCESS_INFORMATION procInfo;
    STARTUPINFO         startInfo;
    char                cmdBuf[ME_MAX_BUFFER];
    char                *path;
    char                *pathArg;
    int                 port;

    port = getAppwebPort();
    if (port < 0) {
        mprError("appweb monitor", "Cannot get Appweb listening port");
        return -1;
    }
    path = getBrowserPath(ME_MAX_BUFFER);
    if (path == 0) {
        mprError("appweb monitor", "Cannot get browser startup command");
        return -1;
    }
    pathArg = strstr(path, "\"%1\"");
    if (*page == '/') {
        page++;
    }
    if (sstarts(page, "http")) {
        fmt(cmdBuf, ME_MAX_BUFFER, "%s %s", path, page);
    } else if (pathArg == 0) {
        fmt(cmdBuf, ME_MAX_BUFFER, "%s http://localhost:%d/%s", path, port, page);
    } else {
        *pathArg = '\0';
        fmt(cmdBuf, ME_MAX_BUFFER, "%s \"http://localhost:%d/%s\"", path, port, page);
    }
    mprLog("appweb monitor", 4, "Running %s\n", cmdBuf);
    memset(&startInfo, 0, sizeof(startInfo));
    startInfo.cb = sizeof(startInfo);

    if (! CreateProcess(0, cmdBuf, 0, 0, FALSE, 0, 0, 0, &startInfo, &procInfo)) {
        mprError("appweb monitor", "Cannot create process: %s, %d", cmdBuf, mprGetOsError());
        return -1;
    }
    CloseHandle(procInfo.hProcess);
    return 0;
}
Exemple #13
0
/*
    Limited expansion of route names. Support ~ and ${app} at the start of the route name
 */
static cchar *expandRouteName(HttpConn *conn, cchar *routeName)
{
    HttpRoute   *route;

    route = conn->rx->route;
    if (routeName[0] == '~') {
        return sjoin(httpGetRouteTop(conn), &routeName[1], NULL);
    }
    if (sstarts(routeName, "${app}")) {
        return sjoin(httpGetRouteTop(conn), &routeName[6], NULL);
    }
#if DEPRECATED || 1
    //  DEPRECATED in version 6
    if (routeName[0] == '|') {
        assert(routeName[0] != '|');
        return sjoin(route->prefix, &routeName[1], NULL);
    }
#endif
    return routeName;
}
Exemple #14
0
/*
    Internal convenience: Used for incoming and outgoing packets.
 */
PUBLIC bool httpTraceBody(HttpConn *conn, bool outgoing, HttpPacket *packet, ssize len)
{
    cchar   *event, *type;

    if (!conn) {
        return 0;
    }
    if (len < 0) {
        len = httpGetPacketLength(packet);
    }
    if (outgoing) {
        if (conn->endpoint) {
            type = "body";
            event = "tx.body.data";
        } else {
            if (sstarts(conn->tx->mimeType, "application/x-www-form-urlencoded")) {
                type = "form";
                event = "tx.body.form";
            } else {
                type = "body";
                event = "tx.body.data";
            }
        }
    } else {
        if (conn->endpoint) {
            if (conn->rx->form) {
                type = "form";
                event = "rx.body.form";
            } else {
                type = "body";
                event = "rx.body.data";
            }
        } else {
            type = "body";
            event = "rx.body.data";
        }
    }
    return httpTracePacket(conn, event, type, packet, "length: %zd", len);
}
Exemple #15
0
static void testRelPath(MprTestGroup *gp)
{
    char    *path, *absPath;
    
    path = mprGetRelPath("Makefile", 0);
    assert(strcmp(path, "Makefile") == 0);
    
    path = mprNormalizePath("../a.b");
    assert(strcmp(path, "../a.b") == 0);

    path = mprGetRelPath("/", 0);
    assert(mprIsPathRel(path));
    assert(strncmp(path, "../", 3) == 0);
    
    path = mprGetRelPath("//", 0);
    assert(mprIsPathRel(path));
    assert(strncmp(path, "../", 3) == 0);
    
    path = mprGetRelPath("/tmp", 0);
    assert(mprIsPathRel(path));
    assert(strncmp(path, "../", 3) == 0);

    path = mprGetRelPath("/Unknown/someone/junk", 0);
    assert(mprIsPathRel(path));
    assert(strncmp(path, "../", 3) == 0);
           
    path = mprGetRelPath("/Users/mob/junk", 0);
    assert(mprIsPathRel(path));
    assert(strncmp(path, "../", 3) == 0);
    
    path = mprGetRelPath("/Users/mob/././../mob/junk", 0);
    assert(mprIsPathRel(path));
    assert(strncmp(path, "../", 3) == 0);
    
    path = mprGetRelPath(".", 0);
    assert(strcmp(path, ".") == 0);

    path = mprGetRelPath("..", 0);
    assert(strcmp(path, "..") == 0);

    path = mprGetRelPath("/Users/mob/github/admin", 0);
    assert(sstarts(path, ".."));

    path = mprGetRelPath("/Users/mob/git", 0);
    path = mprGetRelPath("/Users/mob/git/mpr/test", 0);
    /* Can't really test the result of this */

    absPath = mprGetAbsPath("Makefile");
    assert(mprIsPathAbs(absPath));
    path = mprGetRelPath(absPath, 0);
    assert(!mprIsPathAbs(path));
    assert(strcmp(path, "Makefile") == 0);

#if FUTURE
    //  MOB - problem in that we don't know the cwd when testMpr runs
    //  Test relative to an origin

    out = mprGetAbsPath("../../out");
    cwd = mprGetCurrentPath();
    assert(smatch(mprGetRelPath(cwd, out), "../src/test"));
#endif
}