Example #1
0
/*
    Start the request. At this stage, body data may not have been fully received unless
    the request is a form (POST method and content type is application/x-www-form-urlencoded).
    Forms are a special case and delay invoking the start callback until all body data is received.
    WARNING: GC yield
 */
static void startEsp(HttpQueue *q)
{
    HttpConn    *conn;
    HttpRx      *rx;
    EspReq      *req;

    conn = q->conn;
    rx = conn->rx;
    req = conn->reqData;

#if ME_WIN_LIKE
    rx->target = mprGetPortablePath(rx->target);
#endif

    if (req) {
        mprSetThreadData(req->esp->local, conn);
        /* WARNING: GC yield */
        if (!runAction(conn)) {
            pruneFlash(conn);
        } else {
            if (!conn->error && req->autoFinalize) {
                if (!conn->tx->responded) {
                    /* WARNING: GC yield */
                    espRenderDocument(conn, rx->target);
                }
                if (req->autoFinalize) {
                    espFinalize(conn);
                }
            }
            pruneFlash(conn);
        }
        finalizeFlash(conn);
        mprSetThreadData(req->esp->local, NULL);
    }
}
Example #2
0
/*
    Path should be an app-relative path to the view file (relative-path.esp)
 */
void espDefineView(HttpRoute *route, cchar *path, void *view)
{
    Esp         *esp;

    mprAssert(path && *path);
    mprAssert(view);

    esp = MPR->espService;
	path = mprGetPortablePath(mprJoinPath(route->dir, path));
    mprAddKey(esp->views, path, view);
}
Example #3
0
/*
    Path should be an app-relative path to the view file (relative-path.esp)
 */
PUBLIC void espDefineView(HttpRoute *route, cchar *path, void *view)
{
    Esp         *esp;

    assert(path && *path);
    assert(view);

    if (!route) {
        mprError("Route not defined for view %s", path);
        return;
    }
    esp = MPR->espService;
    path = mprGetPortablePath(mprJoinPath(route->documents, path));
    mprAddKey(esp->views, path, view);
}
Example #4
0
/*
    Path should be a relative path from route->documents to the view file (relative-path.esp)
 */
PUBLIC void espDefineView(HttpRoute *route, cchar *path, void *view)
{
    EspRoute    *eroute;

    assert(path && *path);
    assert(view);

    eroute = ((EspRoute*) route->eroute)->top;
    if (route) {
        path = mprGetPortablePath(path);
    }
    if (!eroute->views) {
        eroute->views = mprCreateHash(-1, MPR_HASH_STATIC_VALUES);
    }
    mprAddKey(eroute->views, path, view);
}
Example #5
0
static void testTransform(MprTestGroup *gp)
{
    char    *path;

    path = mprTransformPath("/", MPR_PATH_ABS);
    assert(mprIsPathAbs(path));

    path = mprTransformPath("/", MPR_PATH_REL);
    assert(mprIsPathRel(path));
    assert(path[0] == '.');

    path = mprTransformPath("/", 0);
    assert(strcmp(path, "/") == 0);

    path = mprTransformPath("/", MPR_PATH_ABS);
    mprAssert(mprIsPathAbs(path));

#if BIT_WIN_LIKE || CYGWIN
    /* Test MapSeparators */
    path = sclone("\\a\\b\\c\\d");
    mprMapSeparators(path, '/');
    assert(*path == '/');
    assert(strchr(path, '\\') == 0);

    /* Test PortablePath */
    path = sclone("\\a\\b\\c\\d");
    path = mprGetPortablePath(path);
    mprAssert(*path == '/');
    assert(strchr(path, '\\') == 0);
    assert(mprIsPathAbs(path));
#endif

#if CYGWIN
    path = mprGetAbsPath("c:/a/b");
    assert(smatch(path, "/cygdrive/c/a/b"));
    path = mprGetAbsPath("/a/b");
    assert(smatch(path, "/a/b"));
    path = mprGetAbsPath("c:/cygwin/a/b");
    assert(smatch(path, "/a/b"));
    path = mprGetWinPath("c:/a/b");
    assert(smatch(path, "C:\\a\\b"));
    path = mprGetWinPath("/cygdrive/c/a/b");
    assert(smatch(path, "C:\\a\\b"));
#endif
}
Example #6
0
/*
    Tokens:
    ARCH        Build architecture (x86_64)
    CC          Compiler (cc)
    DEBUG       Debug compilation options (-g, -Zi -Od)
    INC         Include directory out/inc
    LIB         Library directory (out/lib, xcode/VS: out/bin)
    LIBS        Libraries required to link with ESP
    OBJ         Name of compiled source (out/lib/view-MD5.o)
    OUT         Output module (view_MD5.dylib)
    SHLIB       Host Shared library (.lib, .so)
    SHOBJ       Host Shared Object (.dll, .so)
    SRC         Source code for view or controller (already templated)
    TMP         Temp directory
    VS          Visual Studio directory
    WINSDK      Windows SDK directory
 */
char *espExpandCommand(cchar *command, cchar *source, cchar *module)
{
    MprBuf      *buf;
    MaAppweb    *appweb;
    cchar       *cp, *out;
    char        *tmp;
    
#if BLD_WIN_LIKE
    cchar   *path;
    path = 0;
#endif

    if (command == 0) {
        return 0;
    }
    out = mprTrimPathExt(module);
    buf = mprCreateBuf(-1, -1);
    appweb = MPR->appwebService;

    for (cp = command; *cp; ) {
		if (*cp == '$') {
            if (matchToken(&cp, "${ARCH}")) {
                /* Build architecture */
                mprPutStringToBuf(buf, appweb->hostArch);

#if BLD_WIN_LIKE
            } else if (matchToken(&cp, "${WINSDK}")) {
                path = mprReadRegistry("HKLM\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows", "CurrentInstallFolder");
				path = strim(path, "\\", MPR_TRIM_END);
                mprPutStringToBuf(buf, path);

            } else if (matchToken(&cp, "${VS}")) {
                path = mprGetPathParent(mprGetPathParent(getenv("VS100COMNTOOLS")));
                mprPutStringToBuf(buf, mprGetPortablePath(path));
#endif
                
            } else if (matchToken(&cp, "${CC}")) {
                /* Compiler */
#if BLD_WIN_LIKE
                //  MOB - what about cross compilation
                path = mprJoinPath(mprGetPathParent(mprGetPathParent(getenv("VS100COMNTOOLS"))), "VC/bin/cl.exe");
                mprPutStringToBuf(buf, mprGetPortablePath(path));
#else
                mprPutStringToBuf(buf, BLD_CC);
#endif
            } else if (matchToken(&cp, "${DEBUG}")) {
                mprPutStringToBuf(buf, ESP_DEBUG);

            } else if (matchToken(&cp, "${INC}")) {
                /* Include directory (out/inc) */
                mprPutStringToBuf(buf, mprResolvePath(mprGetAppDir(), "inc"));

            } else if (matchToken(&cp, "${LIB}")) {
                /* Library directory. IDE's use bin dir */
                mprPutStringToBuf(buf, getOutDir(BLD_LIB_NAME));

            } else if (matchToken(&cp, "${LIBS}")) {
                /* Required libraries to link. These may have nested ${TOKENS} */
                mprPutStringToBuf(buf, espExpandCommand(ESP_LIBS, source, module));

            } else if (matchToken(&cp, "${OBJ}")) {
                /* Output object with extension (.o) */
                mprPutStringToBuf(buf, mprJoinPathExt(out, BLD_OBJ));

            } else if (matchToken(&cp, "${OUT}")) {
                /* Output modules */
                mprPutStringToBuf(buf, out);

            } else if (matchToken(&cp, "${SHLIB}")) {
                /* .lib */
                mprPutStringToBuf(buf, appweb->hostOs);

            } else if (matchToken(&cp, "${SHOBJ}")) {
                /* .dll */
#ifdef BLD_HOST_SHOBJ
                //  MOB - need this for bit
                mprPutStringToBuf(buf, BLD_HOST_SHOBJ);
#else
                mprPutStringToBuf(buf, BLD_SHOBJ);
#endif

            } else if (matchToken(&cp, "${SRC}")) {
                /* View (already parsed into C code) or controller source */
                mprPutStringToBuf(buf, source);

            } else if (matchToken(&cp, "${TMP}")) {
#if BLD_WIN_LIKE
                if ((tmp = getenv("TMP")) == 0) {
                    tmp = getenv("TEMP");
                }
#else
                tmp = getenv("TMPDIR");
#endif
                mprPutStringToBuf(buf, tmp ? tmp : ".");
#ifdef WIND_BASE
            } else if (matchToken(&cp, "${WIND_BASE}")) {
                mprPutStringToBuf(buf, WIND_BASE);
#endif
#ifdef WIND_HOME
            } else if (matchToken(&cp, "${WIND_HOME}")) {
                mprPutStringToBuf(buf, WIND_HOME);
#endif
#ifdef WIND_HOST_TYPE

            } else if (matchToken(&cp, "${WIND_HOST_TYPE}")) {
                mprPutStringToBuf(buf, WIND_HOST_TYPE);
#endif
#ifdef WIND_PLATFORM
            } else if (matchToken(&cp, "${WIND_PLATFORM}")) {
                mprPutStringToBuf(buf, WIND_PLATFORM);

#endif
#ifdef WIND_GNU_PATH
            } else if (matchToken(&cp, "${WIND_GNU_PATH}")) {
                mprPutStringToBuf(buf, WIND_GNU_PATH);
#endif

            } else {
                mprPutCharToBuf(buf, *cp++);
            }
        } else {
            mprPutCharToBuf(buf, *cp++);
        }
    }
    mprAddNullToBuf(buf);
    return sclone(mprGetBufStart(buf));
}
Example #7
0
/*
    Convert an ESP web page into C code
    Directives:

        <%@ include "file"  Include an esp file
        <%@ layout "file"   Specify a layout page to use. Use layout "" to disable layout management
        <%@ content         Mark the location to substitute content in a layout pag

        <%                  Begin esp section containing C code
        <%^ global          Put esp code at the global level
        <%^ start           Put esp code at the start of the function
        <%^ end             Put esp code at the end of the function

        <%=                 Begin esp section containing an expression to evaluate and substitute
        <%= [%fmt]          Begin a formatted expression to evaluate and substitute. Format is normal printf format.
                            Use %S for safe HTML escaped output.
        %>                  End esp section
        -%>                 End esp section and trim trailing newline

        @@var               Substitue the value of a variable. Var can also be simple expressions (without spaces)
        @#field             Lookup the current record for the value of the field.

 */
char *espBuildScript(HttpRoute *route, cchar *page, cchar *path, cchar *cacheName, cchar *layout, char **err)
{
    EspParse    parse;
    char        *control, *incBuf, *incText, *global, *token, *body, *where;
    char        *rest, *start, *end, *include, *line, *fmt, *layoutPage, *layoutBuf;
    ssize       len;
    int         tid;

    mprAssert(page);

    body = start = end = global = "";
    *err = 0;

    memset(&parse, 0, sizeof(parse));
    parse.data = (char*) page;
    parse.next = parse.data;

    if ((parse.token = mprCreateBuf(-1, -1)) == 0) {
        return 0;
    }
    tid = getEspToken(&parse);
    while (tid != ESP_TOK_EOF) {
        token = mprGetBufStart(parse.token);
#if FUTURE
        if (parse.lineNumber != lastLine) {
            body = sfmt("\n# %d \"%s\"\n", parse.lineNumber, path);
        }
#endif
        switch (tid) {
        case ESP_TOK_CODE:
            if (*token == '^') {
                for (token++; *token && isspace((int) *token); token++) ;
                where = stok(token, " \t\r\n", &rest);
                if (rest == 0) {
                    ;
                } else if (scmp(where, "global") == 0) {
                    global = sjoin(global, rest, NULL);

                } else if (scmp(where, "start") == 0) {
                    if (*start == '\0') {
                        start = "  ";
                    }
                    start = sjoin(start, rest, NULL);

                } else if (scmp(where, "end") == 0) {
                    if (*end == '\0') {
                        end = "  ";
                    }
                    end = sjoin(end, rest, NULL);
                }
            } else {
                body = sjoin(body, token, NULL);
            }
            break;

        case ESP_TOK_CONTROL:
            /* NOTE: layout parsing not supported */
            control = stok(token, " \t\r\n", &token);
            if (scmp(control, "content") == 0) {
                body = sjoin(body, CONTENT_MARKER, NULL);

            } else if (scmp(control, "include") == 0) {
                if (token == 0) {
                    token = "";
                }
                token = strim(token, " \t\r\n\"", MPR_TRIM_BOTH);
                token = mprNormalizePath(token);
                if (token[0] == '/') {
                    include = sclone(token);
                } else {
                    include = mprJoinPath(mprGetPathDir(path), token);
                }
                if ((incText = mprReadPathContents(include, &len)) == 0) {
                    *err = sfmt("Can't read include file: %s", include);
                    return 0;
                }
                /* Recurse and process the include script */
                incBuf = 0;
                if ((incBuf = espBuildScript(route, incText, include, NULL, NULL, err)) == 0) {
                    return 0;
                }
                body = sjoin(body, incBuf, NULL);

            } else if (scmp(control, "layout") == 0) {
                token = strim(token, " \t\r\n\"", MPR_TRIM_BOTH);
                if (*token == '\0') {
                    layout = 0;
                } else {
                    token = mprNormalizePath(token);
                    if (token[0] == '/') {
                        layout = sclone(token);
                    } else {
                        layout = mprJoinPath(mprGetPathDir(path), token);
                    }
                    if (!mprPathExists(layout, F_OK)) {
                        *err = sfmt("Can't access layout page %s", layout);
                        return 0;
                    }
                }

            } else {
                *err = sfmt("Unknown control %s at line %d", control, parse.lineNumber);
                return 0;                
            }
            break;

        case ESP_TOK_ERR:
            return 0;

        case ESP_TOK_EXPR:
            /* <%= expr %> */
            if (*token == '%') {
                fmt = stok(token, ": \t\r\n", &token);
                if (token == 0) { 
                    token = "";
                }
            } else {
                fmt = "%s";
            }
            token = strim(token, " \t\r\n;", MPR_TRIM_BOTH);
            body = sjoin(body, "  espRender(conn, \"", fmt, "\", ", token, ");\n", NULL);
            break;

        case ESP_TOK_FIELD:
            /* @#field */
            token = strim(token, " \t\r\n;", MPR_TRIM_BOTH);
            body = sjoin(body, "  espRender(conn, getField(\"", token, "\"));\n", NULL);
            break;

        case ESP_TOK_LITERAL:
            line = joinLine(token, &len);
            body = sfmt("%s  espRenderBlock(conn, \"%s\", %d);\n", body, line, len);
            break;

        case ESP_TOK_VAR:
            /* @@var */
            token = strim(token, " \t\r\n;", MPR_TRIM_BOTH);
            /* espRenderParam uses espRenderSafeString */
            body = sjoin(body, "  espRenderParam(conn, \"", token, "\");\n", NULL);
            break;

        default:
            return 0;
        }
        tid = getEspToken(&parse);
    }
    if (cacheName) {
        /*
            CacheName will only be set for the outermost invocation
         */
        if (layout && mprPathExists(layout, R_OK)) {
            if ((layoutPage = mprReadPathContents(layout, &len)) == 0) {
                *err = sfmt("Can't read layout page: %s", layout);
                return 0;
            }
            layoutBuf = 0;
            if ((layoutBuf = espBuildScript(route, layoutPage, layout, NULL, NULL, err)) == 0) {
                return 0;
            }
            body = sreplace(layoutBuf, CONTENT_MARKER, body);
        }
        if (start && start[slen(start) - 1] != '\n') {
            start = sjoin(start, "\n", NULL);
        }
        if (end && end[slen(end) - 1] != '\n') {
            end = sjoin(end, "\n", NULL);
        }
        mprAssert(slen(path) > slen(route->dir));
        mprAssert(sncmp(path, route->dir, slen(route->dir)) == 0);
        if (sncmp(path, route->dir, slen(route->dir)) == 0) {
            path = &path[slen(route->dir) + 1];
        }
        body = sfmt(\
            "/*\n   Generated from %s\n */\n"\
            "#include \"esp-app.h\"\n"\
            "%s\n"\
            "static void %s(HttpConn *conn) {\n"\
            "%s%s%s"\
            "}\n\n"\
            "%s int esp_%s(HttpRoute *route, MprModule *module) {\n"\
            "   espDefineView(route, \"%s\", %s);\n"\
            "   return 0;\n"\
            "}\n",
            path, global, cacheName, start, body, end, ESP_EXPORT_STRING, cacheName, mprGetPortablePath(path), cacheName);
        mprLog(6, "Create ESP script: \n%s\n", body);
    }
    return body;
}
Example #8
0
/*
    WARNING: GC yield
 */
PUBLIC int espLoadModule(HttpRoute *route, MprDispatcher *dispatcher, cchar *kind, cchar *source, cchar **errMsg)
{
    EspRoute    *eroute;
    MprModule   *mp;
    cchar       *appName, *cache, *cacheName, *canonical, *entry, *module;
    int         isView, recompile;

    eroute = route->eroute;
    *errMsg = "";

#if VXWORKS
    /*
        Trim the drive for VxWorks where simulated host drives only exist on the target
     */
    source = mprTrimPathDrive(source);
#endif
    canonical = mprGetPortablePath(mprGetRelPath(source, route->home));

    appName = eroute->appName;
    if (eroute->combine) {
        cacheName = appName;
    } else {
        cacheName = mprGetMD5WithPrefix(sfmt("%s:%s", appName, canonical), -1, sjoin(kind, "_", NULL));
    }
    if ((cache = httpGetDir(route, "CACHE")) == 0) {
        cache = "cache";
    }
    module = mprJoinPathExt(mprJoinPaths(route->home, cache, cacheName, NULL), ME_SHOBJ);

    lock(esp);
    if (route->update) {
        if (mprPathExists(source, R_OK)) {
            isView = smatch(kind, "view");
            if (espModuleIsStale(source, module, &recompile) || (isView && layoutIsStale(eroute, source, module))) {
                if (recompile) {
                    mprHoldBlocks(source, module, cacheName, NULL);
                    if (!espCompile(route, dispatcher, source, module, cacheName, isView, (char**) errMsg)) {
                        mprReleaseBlocks(source, module, cacheName, NULL);
                        unlock(esp);
                        return MPR_ERR_CANT_WRITE;
                    }
                    mprReleaseBlocks(source, module, cacheName, NULL);
                }
            }
        }
    }
    if (mprLookupModule(source) == 0) {
        if (!mprPathExists(module, R_OK)) {
            *errMsg = "Module does not exist";
            unlock(esp);
            return MPR_ERR_CANT_FIND;
        }
        entry = getModuleEntry(eroute, kind, source, cacheName);
        if ((mp = mprCreateModule(source, module, entry, route)) == 0) {
            *errMsg = "Memory allocation error loading module";
            unlock(esp);
            return MPR_ERR_MEMORY;
        }
        if (mprLoadModule(mp) < 0) {
            *errMsg = "Cannot load compiled esp module";
            unlock(esp);
            return MPR_ERR_CANT_READ;
        }
    }
    unlock(esp);
    return 0;
}