Example #1
0
/*
 *  Run the Ejscript request. The routine runs when all input data has been received.
 */
static void runEjs(MaQueue *q)
{
    MaConn      *conn;
    MaRequest   *req;
    EjsWeb      *web;
    char        msg[MPR_MAX_STRING];

    conn = q->conn;
    req = conn->request;
    web = q->queueData = conn->response->handlerData;

    maSetHeader(conn, 0, "Last-Modified", req->host->currentDate);
    maDontCacheResponse(conn);

    maPutForService(q, maCreateHeaderPacket(conn), 0);

    if (ejsRunWebRequest(web) < 0) {
        //  TODO - refactor. Want request failed to have an option which says send this output to the client also.
        if (web->flags & EJS_WEB_FLAG_BROWSER_ERRORS) {
            //  TODO - this API should allocate a buffer and not use a static buffer
            mprEscapeHtml(msg, sizeof(msg), web->error);
            maFormatBody(conn, "Request Failed", 
                "<h1>Ejscript error for \"%s\"</h1>\r\n<h2>%s</h2>\r\n"
                "<p>To prevent errors being displayed in the browser, "
                "use <b>\"EjsErrors log\"</b> in the config file.</p>\r\n",
            web->url, web->error);
        }
        maFailRequest(conn, MPR_HTTP_CODE_BAD_GATEWAY, web->error);
    }
    maPutForService(q, maCreateEndPacket(conn), 1);
}
Example #2
0
static void openPhp(MaQueue *q)
{
    MaRequest       *req;
    MaResponse      *resp;
    MaConn          *conn;

    conn = q->conn;
    if (!q->stage->stageData) {
        if (initializePhp(conn->http) < 0) {
            maFailRequest(conn, MPR_HTTP_CODE_INTERNAL_SERVER_ERROR, "PHP initialization failed");
        }
        q->stage->stageData = (void*) 1;
    }
    resp = conn->response;
    req = conn->request;

    switch (req->method) {
    case MA_REQ_GET:
    case MA_REQ_HEAD:
    case MA_REQ_POST:
    case MA_REQ_PUT:
        q->queueData = mprAllocObjZeroed(resp, MaPhp);
        maDontCacheResponse(conn);
        maSetHeader(conn, 0, "Last-Modified", req->host->currentDate);
        break;
                
    case MA_REQ_DELETE:
    default:
        maFailRequest(q->conn, MPR_HTTP_CODE_BAD_METHOD, "Method not supported by file handler: %s", req->methodName);
        break;
    }
}
Example #3
0
static void upload(MaQueue *q)
{
    MaConn      *conn;
    char        *sw;
    char        *newLocation;
    int         responseStatus;

    conn = q->conn;
    newLocation = 0;
    responseStatus = 0;

    sw = (char*) strstr(maGetFormVar(conn, "QUERY_STRING", ""), "SWITCHES=");
    if (sw) {
        sw = mprStrdup(q, sw + 9);
        mprUrlDecode(sw, (int) strlen(sw) + 1, sw);
        if (*sw == '-') {
            if (sw[1] == 'l') {
                newLocation = sw + 3;
            } else if (sw[1] == 's') {
                responseStatus = atoi(sw + 3);
            }
        }
    }

    maSetResponseCode(conn, 200);
    maSetResponseMimeType(conn, "text/html");
    maDontCacheResponse(conn);

    /*
     *  Test writing headers. The Server header overwrote the "Server" header
     *
     *  maSetHeader(conn, "MyCustomHeader: true");
     *  maSetHeader(conn, "Server: private");
     */

    if (maGetCookies(conn) == 0) {
        maSetCookie(conn, "appwebTest", "Testing can be fun", 43200, "/", 0);
    }

    if (newLocation) {
        maRedirect(conn, 302, newLocation);

    } else if (responseStatus) {
        maFailRequest(conn, responseStatus, "Custom Status");

    } else {
        maWrite(q, "<HTML><TITLE>egiProgram: EGI Output</TITLE><BODY>\r\n");

        printRequestHeaders(q);
        printQueryData(q);
        printBodyData(q);

        maWrite(q, "</BODY></HTML>\r\n");
    }
    if (sw) {
        mprFree(sw);
    }
}
Example #4
0
static void runDir(MaQueue *q)
{
    MaConn          *conn;
    MaResponse      *resp;
    MaRequest       *req;
    MprList         *list;
    MprDirEntry     *dp;
    Dir             *dir;
    cchar           *filename;
    uint            nameSize;
    int             next;

    conn = q->conn;
    req = conn->request;
    resp = conn->response;
    dir = q->stage->stageData;

    filename = resp->filename;
    mprAssert(filename);

    maDontCacheResponse(conn);
    maSetHeader(conn, 0, "Last-Modified", req->host->currentDate);
    maPutForService(q, maCreateHeaderPacket(q), 0);

    parseQuery(conn);

    list = mprGetPathFiles(conn, filename, 1);
    if (list == 0) {
        maWrite(q, "<h2>Can't get file list</h2>\r\n");
        outputFooter(q);
        return;
    }

    if (dir->pattern) {
        filterDirList(conn, list);
    }

    sortList(conn, list);

    /*
     *  Get max filename
     */
    nameSize = 0;
    for (next = 0; (dp = mprGetNextItem(list, &next)) != 0; ) {
        nameSize = max((int) strlen(dp->name), nameSize);
    }
    nameSize = max(nameSize, 22);

    outputHeader(q, req->url, nameSize);
    for (next = 0; (dp = mprGetNextItem(list, &next)) != 0; ) {
        outputLine(q, dp, filename, nameSize);
    }
    outputFooter(q);

    maPutForService(q, maCreateEndPacket(conn), 1);

    mprFree(list);
}
Example #5
0
static void myEgi(MaQueue *q)
{
	MaConn	*conn;

	conn = q->conn;

	maSetResponseCode(conn, 200);
	maWrite(q, "<HTML><TITLE>simpleEgi</TITLE><BODY>\r\n");
	maWrite(q, "<p>Name: %s</p>\n", maGetFormVar(conn, "name", "-"));
	maWrite(q, "<p>Address: %s</p>\n", maGetFormVar(conn, "address", "-"));
	maWrite(q, "</BODY></HTML>\r\n");

#if POSSIBLE
	/*
	 *	Useful things to do in egi forms
	 */
	maSetResponseCode(conn, 200);
	maSetResponseMimeType(conn, "text/plain");
	maDontCacheResponse(conn);
	maRedirect(conn, 302, "/myURl");
	maFailRequest(conn, 409, "My message : %d", 5);
#endif
}
Example #6
0
/*
 *  This runs when all input data has been received. The egi form must write all the data.
 *  It currently does not support forms that return before writing all the data.
 */
static void runEgi(MaQueue *q)
{
    MaConn          *conn;
    MaRequest       *req;
    MaEgiForm       *form;
    MaEgi           *egi;

    conn = q->conn;
    req = conn->request;
    egi = (MaEgi*) q->stage->stageData;
    
    maSetHeader(conn, 0, "Last-Modified", req->host->currentDate);
    maDontCacheResponse(conn);
    maPutForService(q, maCreateHeaderPacket(conn), 0);

    form = (MaEgiForm*) mprLookupHash(egi->forms, req->url);
    if (form == 0) {
        maFailRequest(conn, MPR_HTTP_CODE_NOT_FOUND, "Egi Form: \"%s\" is not defined", req->url);
        
    } else {
        (*form)(q);
    }
    maPutForService(q, maCreateEndPacket(conn), 1);
}
Example #7
0
static void reportFailure(MaConn *conn, int code, cchar *fmt, va_list args)
{
    MaResponse  *resp;
    MaRequest   *req;
    cchar       *url, *status;
    char        *emsg, *msg, *filename;

    mprAssert(fmt);
    
    if (conn->requestFailed) {
        return;
    }
    conn->requestFailed = 1;
    if (fmt == 0) {
        fmt = "";
    }
    req = conn->request;
    resp = conn->response;
    maDontCacheResponse(conn);

    msg = mprVasprintf(conn, MA_BUFSIZE, fmt, args);

    if (resp == 0 || req == 0) {
        mprLog(conn, 2, "\"%s\", code %d: %s.", mprGetHttpCodeString(conn, code), code, msg);

    } else {
        resp->code = code;
        filename = resp->filename ? resp->filename : 0;
        /* 711 is a custom error used by the test suite. */
        if (code != 711) {
            mprLog(resp, 2, "Error: \"%s\", code %d for URI \"%s\", file \"%s\": %s.", 
                mprGetHttpCodeString(conn, code), code, req->url ? req->url : "", filename ? filename : "", msg);
        }
        /*
         *  Use an error document rather than standard error boilerplate.
         */
        if (req->location) {
            url = maLookupErrorDocument(req->location, code);
            if (url && *url) {
                maRedirect(conn, 302, url);
                mprFree(msg);
                return;
            }
        }

        /*
         *  If the headers have already been filled, this alternate response body will be ignored.
         */
        if (resp->altBody == 0) {
            status = mprGetHttpCodeString(conn, code);
            /*
             *  For security, escape the message
             */
            emsg = mprEscapeHtml(resp, msg);
            resp->altBody = mprAsprintf(resp, -1, 
                "<!DOCTYPE html>\r\n"
                "<html><head><title>Document Error: %s</title></head>\r\n"
                "<body><h2>Access Error: %d -- %s</h2>\r\n<p>%s</p>\r\n</body>\r\n</html>\r\n",
                status, code, status, emsg);
        }
        resp->flags |= MA_RESP_NO_BODY;
    }
    mprFree(msg);
}
Example #8
0
static void startCgi(MaQueue *q)
{
    MaRequest       *req;
    MaConn          *conn;
    MprCmd          *cmd;
    MprHash         *hp;
    cchar           *baseName;
    char            **argv, **envv, *fileName;
    int             index, argc, varCount;

    argv = 0;
    argc = 0;
    conn = q->conn;
    req = conn->request;
    if ((req->form || req->flags & MA_REQ_UPLOADING) && conn->state <= MPR_HTTP_STATE_CONTENT) {
        /*
            Delay starting the CGI process if uploading files or a form request. This enables env vars to be defined
            with file upload and form data before starting the CGI gateway.
         */
        return;
    }

    cmd = q->queueData = mprCreateCmd(req);
    if (conn->http->forkCallback) {
        cmd->forkCallback = conn->http->forkCallback;
        cmd->forkData = conn->http->forkData;
    }
    /*
        Build the commmand line arguments
     */
    argc = 1;                                   /* argv[0] == programName */
    buildArgs(conn, cmd, &argc, &argv);
    fileName = argv[0];

    baseName = mprGetPathBase(q, fileName);
    if (strncmp(baseName, "nph-", 4) == 0 || 
            (strlen(baseName) > 4 && strcmp(&baseName[strlen(baseName) - 4], "-nph") == 0)) {
        /*
            Pretend we've seen the header for Non-parsed Header CGI programs
         */
        cmd->userFlags |= MA_CGI_SEEN_HEADER;
    }

    /*
        Build environment variables
     */
    varCount = mprGetHashCount(req->headers) + mprGetHashCount(req->formVars);
    envv = (char**) mprAlloc(cmd, (varCount + 1) * (int) sizeof(char*));

    index = 0;
    hp = mprGetFirstHash(req->headers);
    while (hp) {
        if (hp->data) {
            envv[index] = mprStrcat(cmd, -1, hp->key, "=", (char*) hp->data, NULL);
            index++;
        }
        hp = mprGetNextHash(req->headers, hp);
    }
    hp = mprGetFirstHash(req->formVars);
    while (hp) {
        if (hp->data) {
            envv[index] = mprStrcat(cmd, -1, hp->key, "=", (char*) hp->data, NULL);
            index++;
        }
        hp = mprGetNextHash(req->formVars, hp);
    }
    envv[index] = 0;
    mprAssert(index <= varCount);

    cmd->stdoutBuf = mprCreateBuf(cmd, MA_BUFSIZE, -1);
    cmd->stderrBuf = mprCreateBuf(cmd, MA_BUFSIZE, -1);
    cmd->lastActivity = mprGetTime(cmd);

    mprSetCmdDir(cmd, mprGetPathDir(q, fileName));
    mprSetCmdCallback(cmd, cgiCallback, conn);

    maSetHeader(conn, 0, "Last-Modified", req->host->currentDate);
    maDontCacheResponse(conn);
    maPutForService(q, maCreateHeaderPacket(q), 0);

    if (mprStartCmd(cmd, argc, argv, envv, MPR_CMD_IN | MPR_CMD_OUT | MPR_CMD_ERR) < 0) {
        maFailRequest(conn, MPR_HTTP_CODE_SERVICE_UNAVAILABLE, "Can't run CGI process: %s, URI %s", fileName, req->url);
        return;
    }
    /*
        This will dedicate this thread to the connection. It will also put the socket into blocking mode.
     */
    maDedicateThreadToConn(conn);
}
Example #9
0
/*
 *  When we come here, we've already matched either a location block or an extension
 */
static int run(request_rec *r) 
{
    EjsDirConfig        *dir;
    EjsServerConfig     *server;
    cchar               *ext;

    MaRequest       *req;
    MaResponse      *resp;
    MaConn          *conn;
    MaAlias         *alias;
    MaLocation      *location;
    EjsWeb          *web;
    cchar           *sep, *prefix;
    char            *urlBase, *dir, *app, *url, *cp;
    int             flags, locFlags;

    if (!r->handler || strcasecmp(r->handler, "ejs") != 0) {
        return DECLINED;
    }

    dir = getDir(r)
    server = getServer(r->XXX);

    //  EjsAlias should probably be creating a directory block. These flags should probably be in a directory
    if (loc->flags & (MA_LOC_APP | MA_LOC_APP_DIR)) {

        /*
         *  Send non-ejs content under web to another handler, typically the file handler.
         */
        if (strncmp(&req->url[loc->prefixLen], "web/", 4) == 0) {
            if (!(ext && strcmp(ext, "ejs") == 0)) {
                return DECLINED;
            }

        } else {
            if (ext && strcmp(ext, "ejs") == 0) {
                maFormatBody(conn, "Bad Request", "Can't serve *.ejs files outside web directory");
                maFailRequest(conn, MPR_HTTP_CODE_BAD_REQUEST, "Can't server *.ejs files outside web directory");
                return HTTP_XXX;
            }
        }
    }

    flags = 0;
    url = 0;

    locFlags = location->flags;
    
    if (locFlags & MA_LOC_APP) {
        app = mprStrTrim(mprStrdup(q, prefix), "/");
        url = &req->url[alias->prefixLen];
        dir = mprStrdup(resp, alias->filename);
        if (*url != '/') {
            url--;
        }
        urlBase = mprStrdup(resp, prefix);
        
    } else if (locFlags & MA_LOC_APP_DIR) {
        url = &req->url[alias->prefixLen];
        app = mprStrdup(resp, url);
        if ((cp = strchr(app, '/')) != 0) {
            url = mprStrdup(resp, cp);
            *cp = '\0';
        }
        sep = prefix[strlen(prefix) - 1] == '/' ? "" : "/";
        dir = mprStrcat(resp, &dir, alias->filename, sep, app, NULL);
        urlBase = mprStrcat(resp, prefix, sep, app, NULL);

    } else {
        app = 0;
        dir = mprStrdup(resp, alias->filename);
        url = &req->url[alias->prefixLen];
        flags |= EJS_WEB_FLAG_SOLO;
        if (*url != '/') {
            url--;
        }        
        urlBase = mprStrdup(resp, prefix);
    }
    mprStrTrim(urlBase, "/");
    mprStrTrim(dir, "/");
    
    if (location->flags & MA_LOC_BROWSER) {
        flags |= EJS_WEB_FLAG_BROWSER_ERRORS;
    }
    if (location->flags & MA_LOC_AUTO_SESSION) {
        flags |= EJS_WEB_FLAG_SESSION;
    }

    /*
     *  Var         Stand-Alone             App                         AppDir
     *  app         0                       carmen                      carmen
     *  dir         /Users/mob/....         /Users/mob/hg/carmen        /Users/mob/hg/carmen
     *  urlBase                             /xg/carmen                  /carmen
     *  url                                 stock                       stock
     */
    web = ejsCreateWebRequest(req, q->stage->stageData, conn, app, dir, urlBase, url, req->cookie, flags);
    if (web == 0) {
        maFailRequest(conn, MPR_HTTP_CODE_INTERNAL_SERVER_ERROR, "Can't create Ejs web object for %s", req->url);
        return;
    }
    q->queueData = web;
    maSetHeader(conn, 0, "Last-Modified", req->host->currentDate);
    maDontCacheResponse(conn);

    if (r->method_number != M_GET) {
        return HTTP_METHOD_NOT_ALLOWED;
    }

    if (ejsProcessWebRequest((EjsWeb*) r, &msg) < 0) {
        if (web->flags & EJS_WEB_FLAG_BROWSER_ERRORS) {
            maFormatBody(conn, "Request Failed", "%s", msg);
        }
        maFailRequest(conn, MPR_HTTP_CODE_BAD_GATEWAY, msg);
        mprFree(msg);
    }

    ap_set_content_type(r, "text/html");
    ap_rputs("<html><title>Hello World!</title><body><p>Hello World</p></body></html>\r\n", r);

#if 0
    if ((err = set_content_length(r, r->finfo.st_stize)) || (err = set_last_modified(r, r->finfo.st_mtime)))
        return err;
    if (r->finof.st_mode == 0) 
        return NOT_FOUND;
    fopen(r->filename, "r");

    if (!r->main) {
        /* Not internal redirect */
        apr_table_set(r->headers_out, "X-ejs", "Under construction");
    }
    register_timeout("send", r);
    send_http_header(r);
    if (!r->header_only)
        send_fd(f, r);
    pfclose(r->pool, f);
#endif

    return OK;
}