Exemple #1
0
static int blockingFileCopy(HttpConn *conn, cchar *path)
{
    MprFile     *file;
    char        buf[ME_MAX_BUFFER];
    ssize       bytes, nbytes, offset;

    file = mprOpenFile(path, O_RDONLY | O_BINARY, 0);
    if (file == 0) {
        mprLog("error http client", 0, "Cannot open %s", path);
        return MPR_ERR_CANT_OPEN;
    }
    mprAddRoot(file);
    while ((bytes = mprReadFile(file, buf, sizeof(buf))) > 0) {
        offset = 0;
        while (bytes > 0) {
            if ((nbytes = httpWriteBlock(conn->writeq, &buf[offset], bytes, HTTP_BLOCK)) < 0) {
                mprCloseFile(file);
                mprRemoveRoot(file);
                return MPR_ERR_CANT_WRITE;
            }
            bytes -= nbytes;
            offset += nbytes;
            assert(bytes >= 0);
        }
    }
    httpFlushQueue(conn->writeq, HTTP_BLOCK);
    mprCloseFile(file);
    mprRemoveRoot(file);
    return 0;
}
Exemple #2
0
/*
    Initialize the send connector for a request
 */
PUBLIC int httpSendOpen(HttpQueue *q)
{
    HttpConn    *conn;
    HttpTx      *tx;

    conn = q->conn;
    tx = conn->tx;

    if (tx->connector != conn->http->sendConnector) {
        httpAssignQueue(q, tx->connector, HTTP_QUEUE_TX);
        tx->connector->open(q);
        return 0;
    }
    if (!(tx->flags & HTTP_TX_NO_BODY)) {
        assert(tx->fileInfo.valid);
        if (tx->fileInfo.size > conn->limits->txBodySize && 
                conn->limits->txBodySize < HTTP_UNLIMITED) {
            httpLimitError(conn, HTTP_ABORT | HTTP_CODE_REQUEST_TOO_LARGE,
                "Http transmission aborted. File size exceeds max body of %lld bytes", conn->limits->txBodySize);
            return MPR_ERR_CANT_OPEN;
        }
        tx->file = mprOpenFile(tx->filename, O_RDONLY | O_BINARY, 0);
        if (tx->file == 0) {
            httpError(conn, HTTP_CODE_NOT_FOUND, "Cannot open document: %s, err %d", tx->filename, mprGetError());
        }
    }
    return 0;
}
Exemple #3
0
static EjsObj *loadXml(Ejs *ejs, EjsXML *xml, int argc, EjsObj **argv)
{
    MprFile     *file;
    MprXml      *xp;
    cchar       *filename;

    assert(argc == 1 && ejsIs(ejs, argv[0], String));

    filename = ejsToMulti(ejs, argv[0]);
    file = mprOpenFile(filename, O_RDONLY, 0664);
    if (file == 0) {
        ejsThrowIOError(ejs, "Cannot open: %s", filename);
        return 0;
    }
    //  TODO - convert to open/close
    xp = ejsCreateXmlParser(ejs, xml, filename);
    if (xp == 0) {
        ejsThrowMemoryError(ejs);
        mprCloseFile(file);
        return 0;
    }
    mprXmlSetInputStream(xp, readFileData, (void*) file);

    if (mprXmlParse(xp) < 0 && !ejsHasException(ejs)) {
        ejsThrowIOError(ejs, "Cannot parse XML file: %s\nDetails %s",  filename, mprXmlGetErrorMsg(xp));
    }
    mprCloseFile(file);
    return 0;
}
Exemple #4
0
/*
    Action to run in response to the "test/output" URI
 */
static void output_action() 
{ 
    Output  *output;

    /*
        Don't automatically finalize (complete) the request when this routine returns. This keeps the connection open.
     */
    dontAutoFinalize();

    /*
        Define the event notifier. We're interested in WRITABLE events
     */
    setNotifier(output_callback);

    /*
        Open a file for output. Could use open/write, but we use the MPR equivalents for cross-platform I/O.
     */
    output = mprAllocObj(Output, manageOutput);
    if ((output->file = mprOpenFile(OUTPUT_FILE, O_RDONLY, 0)) == 0) {
        httpError(getConn(), HTTP_CODE_INTERNAL_SERVER_ERROR, "Cannot open huge.txt");
        return;
    }
    mprGetPathInfo(OUTPUT_FILE, &output->info);
    /*
        Save a reference to our output state
     */ 
    setData(output);
}
Exemple #5
0
static int blockingFileCopy(HttpConn *conn, cchar *path)
{
    MprFile     *file;
    char        buf[MPR_BUFSIZE];
    ssize       bytes, nbytes, offset;
    int         oldMode;

    file = mprOpenFile(path, O_RDONLY | O_BINARY, 0);
    if (file == 0) {
        mprError("Can't open %s", path);
        return MPR_ERR_CANT_OPEN;
    }
    mprAddRoot(file);
    oldMode = mprSetSocketBlockingMode(conn->sock, 1);
    while ((bytes = mprReadFile(file, buf, sizeof(buf))) > 0) {
        offset = 0;
        while (bytes > 0) {
            if ((nbytes = httpWriteBlock(conn->writeq, &buf[offset], bytes)) < 0) {
                mprCloseFile(file);
                mprRemoveRoot(file);
                return MPR_ERR_CANT_WRITE;
            }
            bytes -= nbytes;
            offset += nbytes;
            mprAssert(bytes >= 0);
        }
        mprYield(0);
    }
    httpFlushQueue(conn->writeq, 1);
    mprSetSocketBlockingMode(conn->sock, oldMode);
    mprCloseFile(file);
    mprRemoveRoot(file);
    return 0;
}
Exemple #6
0
PUBLIC int ecOpenFileStream(EcCompiler *cp, cchar *path)
{
    EcFileStream    *fs;
    MprPath         info;
    char            *contents;

    if ((fs = ecCreateStream(cp, sizeof(EcFileStream), path, manageFileStream)) == 0) {
        return MPR_ERR_MEMORY;
    }
    if ((fs->file = mprOpenFile(path, O_RDONLY | O_BINARY, 0666)) == 0) {
        return MPR_ERR_CANT_OPEN;
    }
    if (mprGetPathInfo(path, &info) < 0 || info.size < 0) {
        mprCloseFile(fs->file);
        return MPR_ERR_CANT_ACCESS;
    }
    if ((contents = mprAlloc((int) info.size + 1)) == 0) {
        mprCloseFile(fs->file);
        return MPR_ERR_MEMORY;
    }
    if (mprReadFile(fs->file, contents, (int) info.size) != (int) info.size) {
        mprCloseFile(fs->file);
        return MPR_ERR_CANT_READ;
    }
    contents[info.size] = '\0';
    ecSetStreamBuf((EcStream*) fs, contents, (ssize) info.size);
    mprCloseFile(fs->file);
    fs->file = 0;
    return 0;
}
Exemple #7
0
static int process(EjsMod *mp, cchar *output, int argc, char **argv)
{
    Ejs         *ejs;
    EjsModule   *module;
    MprFile     *outfile;
    MprList     *depends;
    int         count, i, next, moduleCount;

    ejs = mp->ejs;

    if (output) {
        outfile = mprOpenFile(output, O_CREAT | O_WRONLY | O_TRUNC | O_BINARY, 0664);
    } else {
        outfile = 0;
    }
    ejs->loaderCallback = (mp->listing) ? emListingLoadCallback : 0;
    mp->firstGlobal = ejsGetLength(ejs, ejs->global);

    /*
        For each module on the command line
     */
    for (i = 0; i < argc && !mp->fatalError; i++) {
        moduleCount = mprGetListLength(ejs->modules);
        ejs->loadData = mp;
        if (!mprPathExists(argv[i], R_OK)) {
            mprError("Can't access module %s", argv[i]);
            return EJS_ERR;
        }
        if ((ejsLoadModule(ejs, ejsCreateStringFromAsc(ejs, argv[i]), -1, -1, EJS_LOADER_NO_INIT)) < 0) {
            ejs->loaderCallback = NULL;
            mprError("Can't load module %s\n%s", argv[i], ejsGetErrorMsg(ejs, 0));
            return EJS_ERR;
        }
        if (mp->genSlots) {
            for (next = moduleCount; (module = mprGetNextItem(ejs->modules, &next)) != 0; ) {
                emCreateSlotFiles(mp, module, outfile);
            }
        }
        if (mp->depends) {
            depends = mprCreateList(-1, 0);
            for (next = moduleCount; (module = mprGetNextItem(ejs->modules, &next)) != 0; ) {
                getDepends(ejs, depends, module);
            }
            count = mprGetListLength(depends);
            for (next = 1; (module = mprGetNextItem(depends, &next)) != 0; ) {
                int version = module->version;
                mprPrintf("%@-%d.%d.%d%s", module->name, EJS_MAJOR(version), EJS_MINOR(version), EJS_PATCH(version),
                          (next >= count) ? "" : " ");
            }
            printf("\n");
        }
    }
    if (mp->html || mp->xml) {
        emCreateDoc(mp);
    }
    mprCloseFile(outfile);
    return 0;
}
Exemple #8
0
/*  
    Constructor
    function open(options: Object = null): File
    NOTE: options can be an options hash or as mode string
 */
static EjsObj *openFile(Ejs *ejs, EjsFile *fp, int argc, EjsObj **argv)
{
    EjsObj  *options;
    cchar   *mode;
    int     perms, omode;

    if (argc < 0 || argc > 1) {
        ejsThrowArgError(ejs, "Bad args");
        return 0;
    }
    options = argv[0];
    if (argc == 0 || !ejsIsDefined(ejs, options)) {
        omode = O_RDONLY | O_BINARY;
        perms = EJS_FILE_PERMS;
        fp->mode = EJS_FILE_READ;
        mode = "r";
    } else {
        if (ejsIs(ejs, options, String)) {
            mode = ejsToMulti(ejs, options);
            perms = EJS_FILE_PERMS;
        } else {
            perms = ejsGetNumOption(ejs, options, "permissions", EJS_FILE_PERMS, 1);
            mode = getStrOption(ejs, options, "mode", "r", 1);
            if (ejs->exception) {
                return 0;
            }
        }
        omode = mapMode(mode);
        if (!(omode & O_WRONLY)) {
            fp->mode |= EJS_FILE_READ;
        }
        if (omode & (O_WRONLY | O_RDWR)) {
            fp->mode |= EJS_FILE_WRITE;
        }
    }
    fp->modeString = sclone(mode);
    fp->perms = perms;

    if (fp->file) {
        mprCloseFile(fp->file);
    }
    fp->file = mprOpenFile(fp->path, omode, perms);
    if (fp->file == 0) {
        ejsThrowIOError(ejs, "Cannot open %s", fp->path);
        return 0;
    }
    if (options) {
        ejsSetPathAttributes(ejs, fp->path, options);
    }
#if ME_CC_MMU && FUTURE
    mprGetPathInfo(&fp->info);
    fp->mapped = mapFile(fp, fp->info.size, MPR_MAP_READ | MPR_MAP_WRITE);
#endif
    fp->mode |= EJS_FILE_OPEN;
    return (EjsObj*) fp;
}
Exemple #9
0
/*  
    This is called to setup for a HTTP PUT request. It is called before receiving the post data via incomingFileData
 */
static void handlePutRequest(HttpQueue *q)
{
    HttpConn    *conn;
    HttpTx      *tx;
    MprFile     *file;
    char        *path;

    assure(q->pair->queueData == 0);

    conn = q->conn;
    tx = conn->tx;
    assure(tx->filename);
    assure(tx->fileInfo.checked);

    path = tx->filename;
    if (tx->outputRanges) {
        /*  
            Open an existing file with fall-back to create
         */
        if ((file = mprOpenFile(path, O_BINARY | O_WRONLY, 0644)) == 0) {
            if ((file = mprOpenFile(path, O_CREAT | O_TRUNC | O_BINARY | O_WRONLY, 0644)) == 0) {
                httpError(conn, HTTP_CODE_INTERNAL_SERVER_ERROR, "Can't create the put URI");
                return;
            }
        } else {
            mprSeekFile(file, SEEK_SET, 0);
        }
    } else {
        if ((file = mprOpenFile(path, O_CREAT | O_TRUNC | O_BINARY | O_WRONLY, 0644)) == 0) {
            httpError(conn, HTTP_CODE_INTERNAL_SERVER_ERROR, "Can't create the put URI");
            return;
        }
    }
    if (!tx->fileInfo.isReg) {
        httpSetHeader(conn, "Location", conn->rx->uri);
    }
    httpSetStatus(conn, tx->fileInfo.isReg ? HTTP_CODE_NO_CONTENT : HTTP_CODE_CREATED);
    q->pair->queueData = (void*) file;
}
Exemple #10
0
static int doRequest(HttpConn *conn, cchar *url, MprList *files)
{
    MprTicks        mark, remaining;
    HttpLimits      *limits;
    MprFile         *outFile;
    cchar           *path;

    assert(url && *url);
    limits = conn->limits;

    mprTrace(4, "fetch: %s %s", app->method, url);
    mark = mprGetTicks();

    if (issueRequest(conn, url, files) < 0) {
        return MPR_ERR_CANT_CONNECT;
    }
    remaining = limits->requestTimeout;

    if (app->outFilename) {
        path = app->loadThreads > 1 ? sfmt("%s-%s.tmp", app->outFilename, mprGetCurrentThreadName()): app->outFilename;
        if ((outFile = mprOpenFile(path, O_CREAT | O_WRONLY | O_TRUNC | O_TEXT, 0664)) == 0) {
            mprError("Cannot open %s", path);
            return MPR_ERR_CANT_OPEN;
        }
    } else {
        outFile = mprGetStdout();
    }
    mprAddRoot(outFile);
    while (!conn->tx->finalized && conn->state < HTTP_STATE_COMPLETE && remaining > 0) {
        remaining = mprGetRemainingTicks(mark, limits->requestTimeout);
        readBody(conn, outFile);
        httpWait(conn, 0, remaining);
    }
    if (conn->state < HTTP_STATE_COMPLETE && !conn->error) {
        httpError(conn, HTTP_ABORT | HTTP_CODE_REQUEST_TIMEOUT,
            "Inactive request timed out, exceeded request timeout %d", app->timeout);
    } else {
        readBody(conn, outFile);
    }
    if (app->outFilename) {
        mprCloseFile(outFile);
    }
    mprRemoveRoot(outFile);
    reportResponse(conn, url, mprGetTicks() - mark);
    httpDestroyRx(conn->rx);
    httpDestroyTx(conn->tx);
    return 0;
}
Exemple #11
0
static void showOutput(HttpConn *conn, cchar *buf, ssize count)
{
    HttpRx      *rx;
    int         i, c;
    
    rx = conn->rx;

    if (app->noout) {
        return;
    }
    if (rx->status == 401 || (conn->followRedirects && (301 <= rx->status && rx->status <= 302))) {
        return;
    }
    if (app->outFile == 0) {
        if (app->outFilename) {
            if ((app->outFile = mprOpenFile(app->outFilename, O_CREAT | O_WRONLY | O_TRUNC | O_TEXT, 0664)) == 0) {
                mprError("Can't open %s", app->outFile);
                return;
            }
        } else {
            app->outFile = mprGetStdout();
        }
    }
    if (!app->printable) {
        mprWriteFile(app->outFile, buf, count);
        return;
    }
    for (i = 0; i < count; i++) {
        if (!isprint((uchar) buf[i]) && buf[i] != '\n' && buf[i] != '\r' && buf[i] != '\t') {
            app->isBinary = 1;
            break;
        }
    }
    if (!app->isBinary) {
        mprWriteFile(app->outFile, buf, count);
        return;
    }
    for (i = 0; i < count; i++) {
        c = (uchar) buf[i];
        if (app->printable && app->isBinary) {
            mprFprintf(app->outFile, "%02x ", c & 0xff);
        } else {
            mprFprintf(app->outFile, "%c", (uchar) buf[i]);
        }
    }
}
Exemple #12
0
ssize espRenderFile(HttpConn *conn, cchar *path)
{
    MprFile     *from;
    ssize       count, written, nbytes;
    char        buf[MPR_BUFSIZE];

    if ((from = mprOpenFile(path, O_RDONLY | O_BINARY, 0)) == 0) {
        return MPR_ERR_CANT_OPEN;
    }
    written = 0;
    while ((count = mprReadFile(from, buf, sizeof(buf))) > 0) {
        if ((nbytes = espRenderBlock(conn, buf, count)) < 0) {
            return nbytes;
        }
        written += nbytes;
    }
    mprCloseFile(from);
    return written;
}
Exemple #13
0
static void testCopyPath(MprTestGroup *gp)
{
    MprFile     *file;
    char        *from, *to;

    from = sfmt("copyTest-%s.tmp", mprGetCurrentThreadName(gp));
    assert(from != 0);
    file = mprOpenFile(from, O_CREAT | O_TRUNC | O_WRONLY, 0664);
    assert(file != 0);
    mprWriteFileString(file, "Hello World");
    mprCloseFile(file);

    to = sfmt("newTest-%s.tmp", mprGetCurrentThreadName(gp));
    assert(mprPathExists(from, F_OK));
    mprCopyPath(from, to, 0664);
    assert(mprPathExists(to, F_OK));
    mprDeletePath(from);
    mprDeletePath(to);
}
Exemple #14
0
static int lstOpen(EjsMod *mp, char *moduleFilename, EjsModuleHdr *hdr)
{
    char    *path, *name, *ext;

    mprAssert(mp);

    name = mprGetPathBase(moduleFilename);
    if ((ext = strstr(name, EJS_MODULE_EXT)) != 0) {
        *ext = '\0';
    }
    path = sjoin(name, EJS_LISTING_EXT, NULL);
    path = mprJoinPath(mp->outputDir, path);
    if ((mp->file = mprOpenFile(path,  O_CREAT | O_WRONLY | O_TRUNC | O_BINARY, 0664)) == 0) {
        mprError("Can't create %s", path);
        return EJS_ERR;
    }
    mprEnableFileBuffering(mp->file, 0, 0);
    mprFprintf(mp->file, "#\n#  %s -- Module Listing for %s\n#\n", path, moduleFilename);
    return 0;
}
Exemple #15
0
static int doRequest(HttpConn *conn, cchar *url, MprList *files)
{
    MprFile     *outFile;
    cchar       *path;

    assert(url && *url);

    if (issueRequest(conn, url, files) < 0) {
        if (conn->rx && conn->rx->status) {
            reportResponse(conn, url);
        }
        return MPR_ERR_CANT_CONNECT;
    }
    if (app->outFilename) {
        path = app->loadThreads > 1 ? sfmt("%s-%s.tmp", app->outFilename, mprGetCurrentThreadName()): app->outFilename;
        if ((outFile = mprOpenFile(path, O_CREAT | O_WRONLY | O_TRUNC | O_TEXT, 0664)) == 0) {
            mprLog("error http", 0, "Cannot open %s", path);
            return MPR_ERR_CANT_OPEN;
        }
    } else {
        outFile = mprGetStdout();
    }
    mprAddRoot(outFile);
    readBody(conn, outFile);
    while (conn->state < HTTP_STATE_COMPLETE && !httpRequestExpired(conn, -1)) {
        readBody(conn, outFile);
        httpWait(conn, 0, -1);
    }
    if (conn->state < HTTP_STATE_COMPLETE && !conn->error) {
        httpError(conn, HTTP_ABORT | HTTP_CODE_REQUEST_TIMEOUT, "Request timed out");
    }
    if (app->outFilename) {
        mprCloseFile(outFile);
    }
    mprRemoveRoot(outFile);
    reportResponse(conn, url);
    httpDestroyRx(conn->rx);
    httpDestroyTx(conn->tx);
    return 0;
}
Exemple #16
0
static void genByteCodeHeader(Mpr *mpr, cchar *dir)
{
    MprFile     *file;
    EjsOptable  *op;
    char        *path;

    path = mprJoinPath(mpr, dir, "ejsByteCode.h");
    file = mprOpenFile(mpr, path, O_WRONLY | O_CREAT | O_TRUNC, 0664);
    if (file == 0) {
        mprError(mpr, "Cannot open %s", path);
        return;
    } 
    header(file, "ejsByteCode", "Ejscript VM Byte Code");

    mprFprintf(file, "typedef enum EjsOpCode {\n");
    for (op = ejsOptable; op->name; op++) {
        mprFprintf(file, "    EJS_OP_%s,\n", op->name);
    }
    mprFprintf(file, "} EjsOpCode;\n");
    footer(file);
    mprCloseFile(file);
}
Exemple #17
0
static void genByteGotoHeader(Mpr *mpr, cchar *dir)
{
    MprFile     *file;
    EjsOptable  *op;
    char        *path;

    path = mprJoinPath(mpr, dir, "ejsByteGoto.h");
    file = mprOpenFile(mpr, path, O_WRONLY | O_CREAT | O_TRUNC, 0664);
    if (file == 0) {
        mprError(mpr, "Cannot open %s", path);
        return;
    } 
    // header(file, "ejsByteGoto", "Ejscript Byte Code Jump Labels");

    mprFprintf(file, "static void *opcodeJump[] = {\n");
    for (op = ejsOptable; op->name; op++) {
        mprFprintf(file, "    &&EJS_OP_%s,\n", op->name);
    }
    mprFprintf(file, "};\n");
    // footer(file);
    mprCloseFile(file);
}
Exemple #18
0
static EjsObj *saveXml(Ejs *ejs, EjsXML *xml, int argc, EjsObj **argv)
{
    MprBuf      *buf;
    MprFile     *file;
    char        *filename;
    ssize       bytes, len;

    if (argc != 1 || !ejsIs(ejs, argv[0], String)) {
        ejsThrowArgError(ejs, "Bad args. Usage: save(filename);");
        return 0;
    }
    filename = awtom(((EjsString*) argv[0])->value, NULL);

    /*
        Create a buffer to hold the output. All in memory.
     */
    buf = mprCreateBuf(ME_MAX_BUFFER, -1);
    mprPutStringToBuf(buf, "<?xml version=\"1.0\"?>\n");

    if (ejsXMLToBuf(ejs, buf, xml, 0) < 0) {
        return 0;
    }
    file = mprOpenFile(filename,  O_CREAT | O_TRUNC | O_WRONLY | O_TEXT, 0664);
    if (file == 0) {
        ejsThrowIOError(ejs, "Cannot open: %s, %d", filename, mprGetOsError(ejs));
        return 0;
    }
    len = mprGetBufLength(buf);
    bytes = mprWriteFile(file, buf->start, len);
    if (bytes != len) {
        ejsThrowIOError(ejs, "Cannot write to: %s", filename);
        mprCloseFile(file);
        return 0;
    }
    mprWriteFile(file, "\n", 1);
    mprCloseFile(file);
    return 0;
}
Exemple #19
0
/*
    uncompress(src: Path, dest: Path = null)
 */
static EjsObj *zlib_uncompress(Ejs *ejs, EjsObj *unused, int argc, EjsObj **argv)
{
    MprFile     *out;
    gzFile      in;
    cchar       *src, *dest;
    uchar       inbuf[MPR_BUFSIZE];
    ssize       nbytes;

    src = ((EjsPath*) argv[0])->value;
    dest = (argc >= 2) ? ejsToMulti(ejs, argv[1]) : 0;
    if (!dest) {
        dest = sjoin(src, ".gz", NULL);
    }
    if ((in = gzopen(src, "rb")) == 0) {
        ejsThrowIOError(ejs, "Cannot open from %s", src);
        return 0;
    }
    if ((out = mprOpenFile(dest, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644)) == 0) {
        ejsThrowIOError(ejs, "Cannot open destination %s", dest);
        return 0;
    }
    while (1) {
        if ((nbytes = gzread(in, inbuf, sizeof(inbuf))) < 0) {
            ejsThrowIOError(ejs, "Cannot read from %s", src);
            return 0;
        } else if (nbytes == 0) {
            break;
        }
        if (mprWriteFile(out, inbuf, (int) nbytes) != nbytes) {
            ejsThrowIOError(ejs, "Cannot write to %s", dest);
            return 0;
        }
    }
    mprCloseFile(out);
    gzclose(in);
    return 0;
}
Exemple #20
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;
}
Exemple #21
0
/*
    Expecting content headers. A blank line indicates the start of the data.
    Returns  < 0  Request or state error
    Returns == 0  Successfully parsed the input line.
 */
static int processUploadHeader(HttpQueue *q, char *line)
{
    HttpConn        *conn;
    HttpRx          *rx;
    HttpUploadFile  *file;
    Upload          *up;
    cchar           *uploadDir;
    char            *key, *headerTok, *rest, *nextPair, *value;

    conn = q->conn;
    rx = conn->rx;
    up = q->queueData;

    if (line[0] == '\0') {
        up->contentState = HTTP_UPLOAD_CONTENT_DATA;
        return 0;
    }

    headerTok = line;
    stok(line, ": ", &rest);

    if (scaselesscmp(headerTok, "Content-Disposition") == 0) {
        /*
            The content disposition header describes either a form
            variable or an uploaded file.

            Content-Disposition: form-data; name="field1"
            >>blank line
            Field Data
            ---boundary

            Content-Disposition: form-data; name="field1" ->
                filename="user.file"
            >>blank line
            File data
            ---boundary
         */
        key = rest;
        up->name = up->clientFilename = 0;
        while (key && stok(key, ";\r\n", &nextPair)) {

            key = strim(key, " ", MPR_TRIM_BOTH);
            stok(key, "= ", &value);
            value = strim(value, "\"", MPR_TRIM_BOTH);

            if (scaselesscmp(key, "form-data") == 0) {
                /* Nothing to do */

            } else if (scaselesscmp(key, "name") == 0) {
                up->name = sclone(value);

            } else if (scaselesscmp(key, "filename") == 0) {
                if (up->name == 0) {
                    httpError(conn, HTTP_CODE_BAD_REQUEST, "Bad upload state. Missing name field");
                    return MPR_ERR_BAD_STATE;
                }
                /*
                    Client filenames must be simple filenames without illegal characters or path separators.
                    We are deliberately restrictive here to assist users that may use the clientFilename in shell scripts.
                    They MUST still sanitize for their environment, but some extra caution is worthwhile.
                 */
                value = mprNormalizePath(value);
                if (*value == '.' || !httpValidUriChars(value) || strpbrk(value, "\\/:*?<>|~\"'%`^\n\r\t\f")) {
                    httpError(conn, HTTP_CODE_BAD_REQUEST, "Bad upload client filename.");
                    return MPR_ERR_BAD_STATE;
                }
                up->clientFilename = sclone(value);
                /*
                    Create the file to hold the uploaded data
                 */
                uploadDir = getUploadDir(rx->route);
                up->tmpPath = mprGetTempPath(uploadDir);
                if (up->tmpPath == 0) {
                    if (!mprPathExists(uploadDir, X_OK)) {
                        mprLog("http error", 0, "Cannot access upload directory %s", uploadDir);
                    }
                    httpError(conn, HTTP_CODE_INTERNAL_SERVER_ERROR,
                        "Cannot create upload temp file %s. Check upload temp dir %s", up->tmpPath, uploadDir);
                    return MPR_ERR_CANT_OPEN;
                }
                httpTrace(conn, "request.upload.file", "context", "clientFilename:'%s',filename:'%s'", 
                    up->clientFilename, up->tmpPath);

                up->file = mprOpenFile(up->tmpPath, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0600);
                if (up->file == 0) {
                    httpError(conn, HTTP_CODE_INTERNAL_SERVER_ERROR, "Cannot open upload temp file %s", up->tmpPath);
                    return MPR_ERR_BAD_STATE;
                }
                /*
                    Create the files[id]
                 */
                file = up->currentFile = mprAllocObj(HttpUploadFile, manageHttpUploadFile);
                file->clientFilename = up->clientFilename;
                file->filename = up->tmpPath;
                file->name = up->name;
                addUploadFile(conn, file);
            }
            key = nextPair;
        }

    } else if (scaselesscmp(headerTok, "Content-Type") == 0) {
        if (up->clientFilename) {
            up->currentFile->contentType = sclone(rest);
        }
    }
    return 0;
}
Exemple #22
0
static ssize writeBody(HttpConn *conn, MprList *files)
{
    MprFile     *file;
    char        buf[HTTP_BUFSIZE], *path, *pair;
    ssize       bytes, len, count, nbytes, sofar;
    int         next, oldMode;

    if (app->upload) {
        if (httpWriteUploadData(conn, app->files, app->formData) < 0) {
            mprError("Can't write upload data %s", httpGetError(conn));
            return MPR_ERR_CANT_WRITE;
        }
    } else {
        if (app->formData) {
            count = mprGetListLength(app->formData);
            for (next = 0; (pair = mprGetNextItem(app->formData, &next)) != 0; ) {
                len = strlen(pair);
                if (next < count) {
                    len = slen(pair);
                    if (httpWrite(conn->writeq, pair, len) != len || httpWrite(conn->writeq, "&", 1) != 1) {
                        return MPR_ERR_CANT_WRITE;
                    }
                } else {
                    if (httpWrite(conn->writeq, pair, len) != len) {
                        return MPR_ERR_CANT_WRITE;
                    }
                }
            }
        }
        if (files) {
            mprAssert(mprGetListLength(files) == 1);
            for (next = 0; (path = mprGetNextItem(files, &next)) != 0; ) {
                if (strcmp(path, "-") == 0) {
                    file = mprAttachFileFd(0, "stdin", O_RDONLY | O_BINARY);
                } else {
                    file = mprOpenFile(path, O_RDONLY | O_BINARY, 0);
                }
                if (file == 0) {
                    mprError("Can't open \"%s\"", path);
                    return MPR_ERR_CANT_OPEN;
                }
                app->inFile = file;
                if (app->verbose) {
                    mprPrintf("uploading: %s\n", path);
                }
                oldMode = mprSetSocketBlockingMode(conn->sock, 1);
                while ((bytes = mprReadFile(file, buf, sizeof(buf))) > 0) {
                    sofar = 0;
                    while (bytes > 0) {
                        if ((nbytes = httpWriteBlock(conn->writeq, &buf[sofar], bytes)) < 0) {
                            mprCloseFile(file);
                            return MPR_ERR_CANT_WRITE;
                        }
                        bytes -= nbytes;
                        sofar += nbytes;
                        mprAssert(bytes >= 0);
                    }
                    mprYield(0);
                }
                httpFlushQueue(conn->writeq, 1);
                mprSetSocketBlockingMode(conn->sock, oldMode);
                mprCloseFile(file);
                app->inFile = 0;
            }
        }
        if (app->bodyData) {
            mprAddNullToBuf(app->bodyData);
            len = mprGetBufLength(app->bodyData);
            if (httpWriteBlock(conn->writeq, mprGetBufStart(app->bodyData), len) != len) {
                return MPR_ERR_CANT_WRITE;
            }
        }
    }
    return 0;
}
Exemple #23
0
/*
    Determine the windows program to invoke.
    Support UNIX style "#!/program" bang directives on windows.
    Also supports ".cmd" and ".bat" alternatives.
 */
static void prepWinProgram(MprCmd *cmd)
{
#if ME_WIN_LIKE
    MprFile     *file;
    cchar       *bat, *ext, *shell, *cp, *start;
    char        bang[ME_MAX_FNAME + 1], *path, *pp;

    /*
        Map separators, convert carriage-returns and newlines to spaces and remove quotes on the command
     */
    path = mprAlloc(slen(cmd->argv[0]) * 2 + 1);
    strcpy(path, cmd->argv[0]);
    for (pp = path; *pp; pp++) {
        if (*pp == '/') {
            *pp = '\\';
        } else if (*pp == '\r' || *pp == '\n') {
            *pp = ' ';
        }
    }
    if (*path == '\"') {
        if ((pp = strrchr(++path, '"')) != 0) {
            *pp = '\0';
        }
        path = sclone(path);
    }
    cmd->argv[0] = path;

    /*
        Support ".cmd" and ".bat" files that take precedence
     */
    if ((ext = mprGetPathExt(path)) == 0) {
        if ((bat = mprSearchPath(mprJoinPathExt(path, ".cmd"), MPR_SEARCH_EXE, cmd->searchPath, NULL)) == 0) {
            bat = mprSearchPath(mprJoinPathExt(path, ".bat"), MPR_SEARCH_EXE, cmd->searchPath, NULL);
        }
        if (bat) {
            if ((shell = getenv("COMSPEC")) == 0) {
                shell = "cmd.exe";
            }
            cmd->argv = mprRealloc((void*) cmd->argv, (cmd->argc + 4) * sizeof(char*));
            memmove((void*) &cmd->argv[3], (void*) cmd->argv, sizeof(char*) * (cmd->argc + 1));
            cmd->argv[0] = sclone(shell);
            cmd->argv[1] = sclone("/Q");
            cmd->argv[2] = sclone("/C");
            cmd->argv[3] = bat;
            cmd->argc += 3;
            cmd->argv[cmd->argc] = 0;
            return;
        }
    }
    if ((file = mprOpenFile(path, O_RDONLY, 0)) != 0) {
        if (mprReadFile(file, bang, ME_MAX_FNAME) > 0) {
            mprCloseFile(file);
            bang[ME_MAX_FNAME] = '\0';
            if (bang[0] == '#' && bang[1] == '!') {
                cp = start = &bang[2];
                shell = ssplit(&bang[2], "\r\n", NULL);
                if (!mprIsPathAbs(shell)) {
                    /*
                        If we cannot access the command shell and the command is not an absolute path,
                        look in the same directory as the script.
                     */
                    if (mprPathExists(shell, X_OK)) {
                        shell = mprJoinPath(mprGetPathDir(path), shell);
                    }
                }
                /*
                    Get length of argv with NULL and add one
                 */
                assert(cmd->argv[cmd->argc] == 0);
                cmd->argv = mprRealloc((void*) cmd->argv, (cmd->argc + 2) * sizeof(char*));
                cmd->argv[cmd->argc + 1] = 0;

                /*
                    Copy up to make room to insert the shell argument. This copies the original NULL
                 */
                memmove((void*) &cmd->argv[1], (void*) cmd->argv, sizeof(char*) * cmd->argc);
                cmd->argv[0] = sclone(shell);
                cmd->argv[1] = path;
                cmd->argc += 1;
                assert(cmd->argv[cmd->argc] == 0);
            }
        } else {
            mprCloseFile(file);
        }
    }
#endif
}
Exemple #24
0
static ssize writeBody(HttpConn *conn, MprList *files)
{
    MprFile     *file;
    char        buf[ME_MAX_BUFFER], *path, *pair;
    ssize       bytes, len, count, nbytes, sofar;
    int         next;

    if (app->upload) {
        if (httpWriteUploadData(conn, app->files, app->formData) < 0) {
            return MPR_ERR_CANT_WRITE;
        }
    } else {
        if (app->formData) {
            count = mprGetListLength(app->formData);
            for (next = 0; (pair = mprGetNextItem(app->formData, &next)) != 0; ) {
                len = strlen(pair);
                if (next < count) {
                    len = slen(pair);
                    if (httpWriteString(conn->writeq, pair) != len || httpWriteString(conn->writeq, "&") != 1) {
                        return MPR_ERR_CANT_WRITE;
                    }
                } else {
                    if (httpWrite(conn->writeq, pair, len) != len) {
                        return MPR_ERR_CANT_WRITE;
                    }
                }
            }
        }
        if (files) {
            assert(mprGetListLength(files) == 1);
            for (next = 0; (path = mprGetNextItem(files, &next)) != 0; ) {
                if (strcmp(path, "-") == 0) {
                    file = mprAttachFileFd(0, "stdin", O_RDONLY | O_BINARY);
                } else {
                    file = mprOpenFile(path, O_RDONLY | O_BINARY, 0);
                }
                if (file == 0) {
                    mprLog("error http", 0, "Cannot open \"%s\"", path);
                    return MPR_ERR_CANT_OPEN;
                }
                app->inFile = file;
                if (app->verbose) {
                    mprPrintf("uploading: %s\n", path);
                }
                while ((bytes = mprReadFile(file, buf, sizeof(buf))) > 0) {
                    sofar = 0;
                    while (bytes > 0) {
                        if ((nbytes = httpWriteBlock(conn->writeq, &buf[sofar], bytes, HTTP_BLOCK)) < 0) {
                            mprCloseFile(file);
                            return MPR_ERR_CANT_WRITE;
                        }
                        bytes -= nbytes;
                        sofar += nbytes;
                        assert(bytes >= 0);
                    }
                }
                httpFlushQueue(conn->writeq, HTTP_BLOCK);
                mprCloseFile(file);
                app->inFile = 0;
            }
        }
        if (app->bodyData) {
            len = mprGetBufLength(app->bodyData);
            if (httpWriteBlock(conn->writeq, mprGetBufStart(app->bodyData), len, HTTP_BLOCK) != len) {
                return MPR_ERR_CANT_WRITE;
            }
        }
    }
    return 0;
}
Exemple #25
0
/*
    If the program has a UNIX style "#!/program" string at the start of the file that program will be selected 
    and the original program will be passed as the first arg to that program with argv[] appended after that. If 
    the program is not found, this routine supports a safe intelligent search for the command. If all else fails, 
    we just return in program the fileName we were passed in. script will be set if we are modifying the program 
    to run and we have extracted the name of the file to run as a script.
 */
static void findExecutable(HttpConn *conn, char **program, char **script, char **bangScript, cchar *fileName)
{
    HttpRx      *rx;
    HttpTx      *tx;
    HttpRoute   *route;
    MprKey      *kp;
    MprFile     *file;
    cchar       *actionProgram, *ext, *cmdShell, *cp, *start, *path;
    char        buf[ME_MAX_FNAME + 1];

    rx = conn->rx;
    tx = conn->tx;
    route = rx->route;

    *bangScript = 0;
    *script = 0;
    *program = 0;
    path = 0;

    actionProgram = mprGetMimeProgram(rx->route->mimeTypes, rx->mimeType);
    ext = tx->ext;

    /*
        If not found, go looking for the fileName with the extensions defined in appweb.conf. 
        NOTE: we don't use PATH deliberately!!!
     */
    if (access(fileName, X_OK) < 0) {
        for (kp = 0; (kp = mprGetNextKey(route->extensions, kp)) != 0; ) {
            path = sjoin(fileName, ".", kp->key, NULL);
            if (access(path, X_OK) == 0) {
                break;
            }
            path = 0;
        }
        if (kp) {
            ext = kp->key;
        } else {
            path = fileName;
        }

    } else {
        path = fileName;
    }
    assert(path && *path);

#if ME_WIN_LIKE
    if (ext && (strcmp(ext, ".bat") == 0 || strcmp(ext, ".cmd") == 0)) {
        /*
            Let a mime action override COMSPEC
         */
        if (actionProgram) {
            cmdShell = actionProgram;
        } else {
            cmdShell = getenv("COMSPEC");
        }
        if (cmdShell == 0) {
            cmdShell = "cmd.exe";
        }
        *script = sclone(path);
        *program = sclone(cmdShell);
        return;
    }
#endif

    if (actionProgram) {
        *program = sclone(actionProgram);

    } else if ((file = mprOpenFile(path, O_RDONLY, 0)) != 0) {
        if (mprReadFile(file, buf, ME_MAX_FNAME) > 0) {
            mprCloseFile(file);
            buf[ME_MAX_FNAME] = '\0';
            if (buf[0] == '#' && buf[1] == '!') {
                cp = start = &buf[2];
                cmdShell = ssplit(&buf[2], "\r\n", NULL);
                if (!mprIsPathAbs(cmdShell)) {
                    /*
                        If we cannot access the command shell and the command is not an absolute path, 
                        look in the same directory as the script.
                     */
                    if (mprPathExists(cmdShell, X_OK)) {
                        cmdShell = mprJoinPath(mprGetPathDir(path), cmdShell);
                    }
                }
                *program = sclone(cmdShell);
                *bangScript = sclone(path);
                return;
            }
        } else {
            mprCloseFile(file);
        }
    }

    if (actionProgram) {
        *program = sclone(actionProgram);
        *bangScript = sclone(path);
    } else {
        *program = sclone(path);
    }
    return;
}
Exemple #26
0
static void openFileHandler(HttpQueue *q)
{
    HttpRx      *rx;
    HttpTx      *tx;
    HttpRoute   *route;
    HttpConn    *conn;
    MprPath     *info;
    char        *date;

    conn = q->conn;
    tx = conn->tx;
    rx = conn->rx;
    route = rx->route;
    info = &tx->fileInfo;

    if (rx->flags & (HTTP_PUT | HTTP_DELETE)) {
        if (!(route->flags & HTTP_ROUTE_PUT_DELETE_METHODS)) {
            httpError(q->conn, HTTP_CODE_BAD_METHOD, "The \"%s\" method is not supported by file handler", rx->method);
        }
    } else {
        if (rx->flags & (HTTP_GET | HTTP_HEAD | HTTP_POST)) {
            if (!(info->valid || info->isDir)) {
                if (rx->referrer) {
                    mprLog(2, "fileHandler: Cannot find filename %s from referrer %s", tx->filename, rx->referrer);
                } else {
                    mprLog(2, "fileHandler: Cannot find filename %s", tx->filename);
                }
                httpError(conn, HTTP_CODE_NOT_FOUND, "Cannot find %s", rx->uri);

            } else if (info->valid) {
                if (!tx->etag) {
                    /* Set the etag for caching in the client */
                    tx->etag = sfmt("\"%Lx-%Lx-%Lx\"", (int64) info->inode, (int64) info->size, (int64) info->mtime);
                }
            }
        }
        if (rx->flags & (HTTP_GET | HTTP_HEAD | HTTP_POST) && !conn->error) {
            if (tx->fileInfo.valid && tx->fileInfo.mtime) {
                //  TODO - OPT could cache this
                date = httpGetDateString(&tx->fileInfo);
                httpSetHeader(conn, "Last-Modified", date);
            }
            if (httpContentNotModified(conn)) {
                httpSetStatus(conn, HTTP_CODE_NOT_MODIFIED);
                httpOmitBody(conn);
                tx->length = -1;
            }
            if (!tx->fileInfo.isReg && !tx->fileInfo.isLink) {
                httpError(conn, HTTP_CODE_NOT_FOUND, "Cannot locate document: %s", rx->uri);
                
            } else if (tx->fileInfo.size > conn->limits->transmissionBodySize) {
                httpError(conn, HTTP_ABORT | HTTP_CODE_REQUEST_TOO_LARGE,
                    "Http transmission aborted. File size exceeds max body of %,Ld bytes", 
                        conn->limits->transmissionBodySize);
                
            } else if (!(tx->connector == conn->http->sendConnector)) {
                /*
                    If using the net connector, open the file if a body must be sent with the response. The file will be
                    automatically closed when the request completes.
                 */
                if (!(tx->flags & HTTP_TX_NO_BODY)) {
                    tx->file = mprOpenFile(tx->filename, O_RDONLY | O_BINARY, 0);
                    if (tx->file == 0) {
                        if (rx->referrer) {
                            httpError(conn, HTTP_CODE_NOT_FOUND, "Cannot open document: %s from %s", 
                                tx->filename, rx->referrer);
                        } else {
                            httpError(conn, HTTP_CODE_NOT_FOUND, "Cannot open document: %s from %s", tx->filename);
                        }
                    }
                }
            }

        } else if (rx->flags & (HTTP_OPTIONS | HTTP_TRACE)) {
            if (route->flags & HTTP_ROUTE_PUT_DELETE_METHODS) {
                httpHandleOptionsTrace(q->conn, "DELETE,GET,HEAD,POST,PUT");
            } else {
                httpHandleOptionsTrace(q->conn, "GET,HEAD,POST");
            }
        }
    }

	
}
Exemple #27
0
/* 
    Encode the files as C code
 */
static int binToC(MprList *files, char *romName, char *prefix)
{
    MprPath         info;
    MprFile         *file;
    char            buf[512];
    char            *filename, *cp, *sl, *p;
    ssize           len;
    int             next, i, j;

    mprPrintf("/*\n    %s -- Compiled Files\n */\n", romName);

    mprPrintf("#include \"mpr.h\"\n\n");
    mprPrintf("#if BIT_FEATURE_ROMFS\n");

    /*
        Open each input file and compile
     */
    for (next = 0; (filename = mprGetNextItem(files, &next)) != 0; ) {
        if (mprGetPathInfo(filename, &info) == 0 && info.isDir) {
            continue;
        } 
        if ((file = mprOpenFile(filename, O_RDONLY | O_BINARY, 0666)) < 0) {
            mprError("Can't open file %s\n", filename);
            return -1;
        }
        mprPrintf("static uchar _file_%d[] = {\n", next);

        while ((len = mprReadFile(file, buf, sizeof(buf))) > 0) {
            p = buf;
            for (i = 0; i < len; ) {
                mprPrintf("    ");
                for (j = 0; p < &buf[len] && j < 16; j++, p++) {
                    mprPrintf("%3d,", (unsigned char) *p);
                }
                i += j;
                mprPrintf("\n");
            }
        }
        mprPrintf("    0 };\n\n");
        mprCloseFile(file);
    }

    /*
        Now output the page index
     */ 
    mprPrintf("MprRomInode %s[] = {\n", romName);

    for (next = 0; (filename = mprGetNextItem(files, &next)) != 0; ) {
        /*
            Replace the prefix with a leading "/"
         */ 
        if (strncmp(filename, prefix, strlen(prefix)) == 0) {
            cp = &filename[strlen(prefix)];
        } else {
            cp = filename;
        }
        while((sl = strchr(filename, '\\')) != NULL) {
            *sl = '/';
        }
        if (*cp == '/') {
            cp++;
        }
        if (*cp == '.' && cp[1] == '\0') {
            cp++;
        }
        if (mprGetPathInfo(filename, &info) == 0 && info.isDir) {
            mprPrintf("    { \"%s\", 0, 0, 0 },\n", cp);
            continue;
        }
        mprPrintf("    { \"%s\", _file_%d, %d, %d },\n", cp, next, (int) info.size, next);
    }
    
    mprPrintf("    { 0, 0, 0, 0 },\n");
    mprPrintf("};\n");
    mprPrintf("#endif /* BIT_FEATURE_ROMFS */\n");
    return 0;
}
Exemple #28
0
static int openFileHandler(HttpQueue *q)
{
    HttpRx      *rx;
    HttpTx      *tx;
    HttpConn    *conn;
    MprPath     *info;
    char        *date, dbuf[16];
    MprHash     *dateCache;

    conn = q->conn;
    tx = conn->tx;
    rx = conn->rx;
    info = &tx->fileInfo;

    if (conn->error) {
        return MPR_ERR_CANT_OPEN;
    }
    if (rx->flags & (HTTP_GET | HTTP_HEAD | HTTP_POST)) {
        if (!(info->valid || info->isDir)) {
            httpError(conn, HTTP_CODE_NOT_FOUND, "Cannot find document");
            return 0;
        } 
        if (!tx->etag) {
            /* Set the etag for caching in the client */
            tx->etag = sfmt("\"%llx-%llx-%llx\"", (int64) info->inode, (int64) info->size, (int64) info->mtime);
        }
        if (info->mtime) {
            dateCache = conn->http->dateCache;
            if ((date = mprLookupKey(dateCache, itosbuf(dbuf, sizeof(dbuf), (int64) info->mtime, 10))) == 0) {
                if (!dateCache || mprGetHashLength(dateCache) > 128) {
                    conn->http->dateCache = dateCache = mprCreateHash(0, 0);
                }
                date = httpGetDateString(&tx->fileInfo);
                mprAddKey(dateCache, itosbuf(dbuf, sizeof(dbuf), (int64) info->mtime, 10), date);
            }
            httpSetHeaderString(conn, "Last-Modified", date);
        }
        if (httpContentNotModified(conn)) {
            httpSetStatus(conn, HTTP_CODE_NOT_MODIFIED);
            httpOmitBody(conn);
            tx->length = -1;
        }
        if (!tx->fileInfo.isReg && !tx->fileInfo.isLink) {
            httpTrace(conn, "request.document.error", "error", "msg: 'Document is not a regular file', filename: '%s'", 
                tx->filename);
            httpError(conn, HTTP_CODE_NOT_FOUND, "Cannot serve document");
            
        } else if (tx->fileInfo.size > conn->limits->transmissionBodySize) {
            httpError(conn, HTTP_ABORT | HTTP_CODE_REQUEST_TOO_LARGE,
                "Http transmission aborted. File size exceeds max body of %'lld bytes",
                    conn->limits->transmissionBodySize);
            
        } else if (!(tx->connector == conn->http->sendConnector)) {
            /*
                If using the net connector, open the file if a body must be sent with the response. The file will be
                automatically closed when the request completes.
             */
            if (!(tx->flags & HTTP_TX_NO_BODY)) {
                tx->file = mprOpenFile(tx->filename, O_RDONLY | O_BINARY, 0);
                if (tx->file == 0) {
                    if (rx->referrer && *rx->referrer) {
                        httpTrace(conn, "request.document.error", "error", 
                            "msg: 'Cannot open document', filename: '%s', referrer: '%s'", 
                            tx->filename, rx->referrer);
                    } else {
                        httpTrace(conn, "request.document.error", "error", 
                            "msg: 'Cannot open document', filename: '%s'", tx->filename);
                    }
                    httpError(conn, HTTP_CODE_NOT_FOUND, "Cannot open document");
                }
            }
        }
    } else if (rx->flags & (HTTP_DELETE | HTTP_OPTIONS | HTTP_PUT)) {
        ;
    } else {
        httpError(conn, HTTP_CODE_BAD_METHOD, "Unsupported method");
    }
    return 0;
}