Exemple #1
0
/*
    Check if the layout has changed. Returns false if the layout does not exist.
 */
static bool layoutIsStale(EspRoute *eroute, cchar *source, cchar *module)
{
    char    *data, *lpath, *quote;
    cchar   *layout, *layoutsDir;
    ssize   len;
    bool    stale;
    int     recompile;

    stale = 0;
    layoutsDir = httpGetDir(eroute->route, "LAYOUTS");
    if ((data = mprReadPathContents(source, &len)) != 0) {
        if ((lpath = scontains(data, "@ layout \"")) != 0) {
            lpath = strim(&lpath[10], " ", MPR_TRIM_BOTH);
            if ((quote = schr(lpath, '"')) != 0) {
                *quote = '\0';
            }
            layout = (layoutsDir && *lpath) ? mprJoinPath(layoutsDir, lpath) : 0;
        } else {
            layout = (layoutsDir) ? mprJoinPath(layoutsDir, "default.esp") : 0;
        }
        if (layout) {
            stale = espModuleIsStale(layout, module, &recompile);
            if (stale) {
                mprLog("info esp", 4, "esp layout %s is newer than module %s", layout, module);
            }
        }
    }
    return stale;
}
Exemple #2
0
static int mdbLoad(Edi *edi, cchar *path)
{
    cchar       *data;
    ssize       len;

    if ((data = mprReadPathContents(path, &len)) == 0) {
        return MPR_ERR_CANT_READ;
    }
    return mdbLoadFromString(edi, data);
}
Exemple #3
0
PUBLIC int httpSetGroupAccount(cchar *newGroup)
{
    Http    *http;

    http = HTTP;
    if (smatch(newGroup, "HTTP") || smatch(newGroup, "APPWEB")) {
#if ME_UNIX_LIKE
        /* Only change group if root */
        if (getuid() != 0) {
            return 0;
        }
#endif
#if MACOSX || FREEBSD
        newGroup = "_www";
#elif LINUX || ME_UNIX_LIKE
{
        char    *buf;
        newGroup = "nobody";
        /*
            Debian has nogroup, Fedora has nobody. Ugh!
         */
        if ((buf = mprReadPathContents("/etc/group", NULL)) != 0) {
            if (scontains(buf, "nogroup:")) {
                newGroup = "nogroup";
            }
        }
}
#elif WINDOWS
        newGroup = "Administrator";
#endif
    }
#if ME_UNIX_LIKE
    struct group    *gp;

    if (snumber(newGroup)) {
        http->gid = atoi(newGroup);
        if ((gp = getgrgid(http->gid)) == 0) {
            mprLog("critical http", 0, "Bad group id: %d", http->gid);
            return MPR_ERR_CANT_ACCESS;
        }
        newGroup = gp->gr_name;

    } else {
        if ((gp = getgrnam(newGroup)) == 0) {
            mprLog("critical http", 0, "Bad group name: %s", newGroup);
            return MPR_ERR_CANT_ACCESS;
        }
        http->gid = gp->gr_gid;
    }
    http->groupChanged = 1;
#endif
    http->group = sclone(newGroup);
    return 0;
}
Exemple #4
0
static int setKeyFile(SSL_CTX *ctx, cchar *keyFile)
{
    RSA     *key;
    BIO     *bio;
    char    *buf;
    int     rc;

    assert(ctx);
    assert(keyFile);

    key = 0;
    bio = 0;
    buf = 0;
    rc = -1;

    if (ctx == NULL || keyFile == NULL) {
        ;

    } else if ((buf = mprReadPathContents(keyFile, NULL)) == 0) {
        mprLog("error openssl", 0, "Unable to read certificate %s", keyFile);

    } else if ((bio = BIO_new_mem_buf(buf, -1)) == 0) {
        mprLog("error openssl", 0, "Unable to allocate memory for key %s", keyFile);

    } else if ((key = PEM_read_bio_RSAPrivateKey(bio, NULL, 0, NULL)) == 0) {
        mprLog("error openssl", 0, "Unable to parse key %s", keyFile);

    } else if (SSL_CTX_use_RSAPrivateKey(ctx, key) != 1) {
        mprLog("error openssl", 0, "Unable to use key %s", keyFile);

    } else {
        rc = 0;
    }
    if (bio) {
        BIO_free(bio);
    }
    if (key) {
        RSA_free(key);
    }
    return rc;
}
Exemple #5
0
static int setCertFile(SSL_CTX *ctx, cchar *certFile)
{
    X509    *cert;
    BIO     *bio;
    char    *buf;
    int     rc;

    assert(ctx);
    assert(certFile);

    rc = -1;
    bio = 0;
    buf = 0;
    cert = 0;

    if (ctx == NULL) {
        return rc;
    }
    if ((buf = mprReadPathContents(certFile, NULL)) == 0) {
        mprLog("error openssl", 0, "Unable to read certificate %s", certFile);

    } else if ((bio = BIO_new_mem_buf(buf, -1)) == 0) {
        mprLog("error openssl", 0, "Unable to allocate memory for certificate %s", certFile);

    } else if ((cert = PEM_read_bio_X509(bio, NULL, 0, NULL)) == 0) {
        mprLog("error openssl", 0, "Unable to parse certificate %s", certFile);

    } else if (SSL_CTX_use_certificate(ctx, cert) != 1) {
        mprLog("error openssl", 0, "Unable to use certificate %s", certFile);
        
    } else {
        rc = 0;
    }
    if (bio) {
        BIO_free(bio);
    }
    if (cert) {
        X509_free(cert);
    }
    return rc;
}
Exemple #6
0
int APIENTRY WinMain(HINSTANCE inst, HINSTANCE junk, char *command, int junk2) {
    char    **argv;
    cchar   *documents, *home, *logs, *port, *ssl, *argp, *path, *contents, *revised;
    cchar   *user, *group, *cache, *modules, *bak;
    int     argc, err, nextArg;
    static void logHandler(int flags, int level, cchar *msg);

    if (mprCreate(0, NULL, MPR_USER_EVENTS_THREAD) == NULL) {
        exit(1);
    }
    if ((argc = mprMakeArgv(command, &argv, MPR_ARGV_ARGS_ONLY)) < 0) {
        return FALSE;
    }
    mprSetLogHandler(logHandler);
#else
int main(int argc, char **argv) {
    cchar   *documents, *home, *logs, *port, *ssl, *argp, *path, *contents, *revised;
    cchar   *user, *group, *cache, *modules, *bak;
    int     err, nextArg;
    if (mprCreate(argc, argv, MPR_USER_EVENTS_THREAD) == NULL) {
        exit(1);
    }
#endif
    documents = home = port = ssl = logs = user = group = cache = modules = 0;
    for (err = 0, nextArg = 1; nextArg < argc; nextArg++) {
        argp = argv[nextArg];
        if (*argp != '-') {
            break;
        }
        if (smatch(argp, "--documents") && nextArg < argc) {
            documents = argv[++nextArg];
        } else if (smatch(argp, "--home") && nextArg < argc) {
            home = argv[++nextArg];
        } else if (smatch(argp, "--logs") && nextArg < argc) {
            logs = argv[++nextArg];
        } else if (smatch(argp, "--port") && nextArg < argc) {
            port = argv[++nextArg];
        } else if (smatch(argp, "--ssl") && nextArg < argc) {
            ssl = argv[++nextArg];
        } else if (smatch(argp, "--user") && nextArg < argc) {
            user = argv[++nextArg];
        } else if (smatch(argp, "--group") && nextArg < argc) {
            group = argv[++nextArg];
        } else if (smatch(argp, "--cache") && nextArg < argc) {
            cache = argv[++nextArg];
        } else if (smatch(argp, "--modules") && nextArg < argc) {
            modules = argv[++nextArg];
        } else {
            err++;
        }
    }
    if (nextArg != (argc - 1)) {
        err++;
    }
    if (err) {
#if BIT_WIN_LIKE
        mprUserError("Bad command line:");
#else
        mprUserError("Bad command line:\n"
            "  Usage: pathConfig [options]\n"
            "  Switches:\n"
            "    --cache dir          # Cache dir"
            "    --documents dir      # Static documents directory"
            "    --group groupname    # Group name"
            "    --home dir           # Server home directory"
            "    --logs dir           # Log directory"
            "    --modules dir        # moduels dir"
            "    --port number        # HTTP port number"
            "    --user username      # User name");
#endif
        return 1;
    }
    path = argv[nextArg++];

    if ((contents = mprReadPathContents(path, NULL)) == 0) {
        mprUserError("Cannot read %s", path);
        return 1;
    }
	if (port) {
	    contents = replace(contents, "Listen 80", "Listen %s", port);
	}
	if (ssl) {
	    contents = replace(contents, "443", ssl);
	}
    if (documents) {
        contents = replace(contents, "DocumentRoot", "DocumentRoot \"%s\"", documents);
    }
    if (home) {
        contents = replace(contents, "ServerRoot", "ServerRoot \"%s\"", home);
    }
    if (logs) {
        contents = replace(contents, "ErrorLog", "ErrorLog \"%s\"", mprJoinPath(logs, "error.log"));
        contents = replace(contents, "AccessLog", "AccessLog \"%s\"", mprJoinPath(logs, "access.log"));
    }
    if (user) {
        contents = replace(contents, "UserAccount", "UserAccount %s", user);
    }
    if (group) {
        contents = replace(contents, "GroupAccount", "GroupAccount %s", group);
    }
    if (cache) {
        contents = replace(contents, "EspDir cache", "EspDir cache \"%s\"", cache);
    }
    if (modules) {
        contents = replace(contents, "LoadModulePath", "LoadModulePath \"%s\"", modules);
    }
    revised = mprGetTempPath(mprGetPathDir(path));
    if (mprWritePathContents(revised, contents, -1, 0644) < 0) {
        mprUserError("Cannot write %s", revised);
    }
	bak = sfmt("%s.bak", path);
	mprDeletePath(bak);
	if (rename(path, bak) < 0) {
        mprUserError("Cannot save %s to %s: 0x%x", path, bak, mprGetError());
	}
	mprDeletePath(path);
    if (rename(revised, path) < 0) {
        mprUserError("Cannot rename %s to %s: 0x%x", revised, path, mprGetError());
		rename(bak, path);
    }
    return 0;
}
Exemple #7
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;
}
Exemple #8
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;
}
Exemple #9
0
/*
    Compile a view or controller

    cacheName   MD5 cache name (not a full path)
    source      ESP source file name
    module      Module file name
 */
bool espCompile(HttpConn *conn, cchar *source, cchar *module, cchar *cacheName, int isView)
{
    MprFile     *fp;
    HttpRx      *rx;
    HttpRoute   *route;
    EspRoute    *eroute;
    cchar       *csource;
    char        *layout, *script, *page, *err;
    ssize       len;

    rx = conn->rx;
    route = rx->route;
    eroute = route->eroute;
    layout = 0;

    if (isView) {
        if ((page = mprReadPathContents(source, &len)) == 0) {
            httpError(conn, HTTP_CODE_INTERNAL_SERVER_ERROR, "Can't read %s", source);
            return 0;
        }
        /*
            Use layouts iff there is a source defined on the route. Only MVC/controllers based apps do this.
         */
        if (eroute->layoutsDir) {
#if UNUSED
        layout = mprSamePath(eroute->layoutsDir, route->dir) ? 0 : mprJoinPath(eroute->layoutsDir, "default.esp");
#else
        layout = mprJoinPath(eroute->layoutsDir, "default.esp");
#endif
        }
        if ((script = espBuildScript(route, page, source, cacheName, layout, &err)) == 0) {
            httpError(conn, HTTP_CODE_INTERNAL_SERVER_ERROR, "Can't build %s, error %s", source, err);
            return 0;
        }
        csource = mprJoinPathExt(mprTrimPathExt(module), ".c");
        if ((fp = mprOpenFile(csource, O_WRONLY | O_TRUNC | O_CREAT | O_BINARY, 0664)) == 0) {
            httpError(conn, HTTP_CODE_INTERNAL_SERVER_ERROR, "Can't open compiled script file %s", csource);
            return 0;
        }
        len = slen(script);
        if (mprWriteFile(fp, script, len) != len) {
            httpError(conn, HTTP_CODE_INTERNAL_SERVER_ERROR, "Can't write compiled script file %s", csource);
            mprCloseFile(fp);
            return 0;
        }
        mprCloseFile(fp);
    } else {
        csource = source;
    }
    mprMakeDir(eroute->cacheDir, 0775, -1, -1, 1);
    /*
        WARNING: GC yield here
     */
    if (runCommand(conn, eroute->compile, csource, module) < 0) {
        return 0;
    }
    if (eroute->link) {
        /*
            WARNING: GC yield here
         */
        if (runCommand(conn, eroute->link, csource, module) < 0) {
            return 0;
        }
#if !(BLD_DEBUG && MACOSX)
        /*
            MAC needs the object for debug information
         */
        mprDeletePath(mprJoinPathExt(mprTrimPathExt(module), BLD_OBJ));
#endif
    }
#if BLD_WIN_LIKE
    {
        /*
            Windows leaves intermediate object in the current directory
         */
        cchar   *obj;
        obj = mprReplacePathExt(mprGetPathBase(csource), BLD_OBJ);
        if (mprPathExists(obj, F_OK)) {
            mprDeletePath(obj);
        }
    }
#endif
    if (!eroute->keepSource && isView) {
        mprDeletePath(csource);
    }
    return 1;
}