Esempio n. 1
0
/*  
    Get a socket address from a host/port combination. If a host provides both IPv4 and IPv6 addresses, 
    prefer the IPv4 address. This routine uses getaddrinfo.
    Caller must free addr.
 */
PUBLIC int socketInfo(char *ip, int port, int *family, int *protocol, struct sockaddr_storage *addr, Socklen *addrlen)
{
    struct addrinfo     hints, *res, *r;
    char                portBuf[16];
    int                 v6;

    assert(addr);
    memset((char*) &hints, '\0', sizeof(hints));

    /*
        Note that IPv6 does not support broadcast, there is no 255.255.255.255 equivalent.
        Multicast can be used over a specific link, but the user must provide that address plus %scope_id.
     */
    if (ip == 0 || ip[0] == '\0') {
        ip = 0;
        hints.ai_flags |= AI_PASSIVE;           /* Bind to 0.0.0.0 and :: */
    }
    v6 = ipv6(ip);
    hints.ai_socktype = SOCK_STREAM;
    if (ip) {
        hints.ai_family = v6 ? AF_INET6 : AF_INET;
    } else {
        hints.ai_family = AF_UNSPEC;
    }
    itosbuf(portBuf, sizeof(portBuf), port, 10);

    /*  
        Try to sleuth the address to avoid duplicate address lookups. Then try IPv4 first then IPv6.
     */
    res = 0;
    if (getaddrinfo(ip, portBuf, &hints, &res) != 0) {
        return -1;
    }
    /*
        Prefer IPv4 if IPv6 not requested
     */
    for (r = res; r; r = r->ai_next) {
        if (v6) {
            if (r->ai_family == AF_INET6) {
                break;
            }
        } else {
            if (r->ai_family == AF_INET) {
                break;
            }
        }
    }
    if (r == NULL) {
        r = res;
    }
    memset(addr, 0, sizeof(*addr));
    memcpy((char*) addr, (char*) r->ai_addr, (int) r->ai_addrlen);

    *addrlen = (int) r->ai_addrlen;
    *family = r->ai_family;
    *protocol = r->ai_protocol;
    freeaddrinfo(res);
    return 0;
}
Esempio n. 2
0
static EdiGrid *hashToGrid(MprHash *hash)
{
    EdiGrid *grid;
    EdiRec  *rec;
    cchar   *data;
    char    key[8];
    int     i, len;

    len = mprGetHashLength(hash);
    grid = ediCreateBareGrid(NULL, "grid", len);
    for (i = 0; i < len; i++) {
        data = mprLookupKey(hash, itosbuf(key, sizeof(key), i, 10));
        grid->records[i] = rec = ediCreateBareRec(NULL, "grid", 1);
        rec->fields[0].name = sclone("value");
        rec->fields[0].type = EDI_TYPE_STRING;
        rec->fields[0].value = data;
    }
    return grid;
}
Esempio n. 3
0
static char *hashToString(MprHash *hash, cchar *sep)
{
    MprBuf  *buf;
    cchar   *data;
    char    key[8];
    int     i, len;

    len = mprGetHashLength(hash);
    buf = mprCreateBuf(0, 0);
    mprPutCharToBuf(buf, '{');
    for (i = 0; i < len; ) {
        data = mprLookupKey(hash, itosbuf(key, sizeof(key), i, 10));
        mprPutStringToBuf(buf, data);
        if (++i < len) {
            mprPutStringToBuf(buf, sep ? sep : ",");
        }
    }
    mprPutCharToBuf(buf, '}');
    mprAddNullToBuf(buf);
    return mprGetBufStart(buf);
}
Esempio n. 4
0
PUBLIC void espTable(HttpConn *conn, EdiGrid *grid, cchar *optionString)
{
    MprHash     *options, *colOptions, *rowOptions, *thisCol;
    MprList     *cols;
    EdiRec      *rec;
    EdiField    *fp;
    cchar       *title, *width, *o, *header, *value, *sortColumn;
    char        index[8];
    int         c, r, ncols, sortOrder;
   
    assert(grid);
    if (grid == 0) {
        return;
    }
    options = httpGetOptions(optionString);
    if (grid->nrecords == 0) {
        espRender(conn, "<p>No Data</p>\r\n");
        return;
    }
    if (grid->flags & EDI_GRID_READ_ONLY) {
        grid = ediCloneGrid(grid);
    }
    if ((sortColumn = httpGetOption(options, "sort", 0)) != 0) {
        sortOrder = httpOption(options, "sortOrder", "ascending", 1);
        ediSortGrid(grid, sortColumn, sortOrder);
    }
    colOptions = httpGetOptionHash(options, "columns");

    filterCols(grid, options, colOptions);

    if (httpOption(options, "pivot", "true", 0) != 0) {
        pivotTable(conn, ediPivotGrid(grid, 1), options);
        return;
    }
    cols = ediGetGridColumns(grid);
    ncols = mprGetListLength(cols);
    rowOptions = mprCreateHash(0, MPR_HASH_STABLE);

    httpSetOption(rowOptions, EDATA("click"), httpGetOption(options, EDATA("click"), 0));
    httpRemoveOption(options, EDATA("click"));
    httpSetOption(rowOptions, EDATA("remote"), httpGetOption(options, EDATA("remote"), 0));
    httpSetOption(rowOptions, EDATA("key"), httpGetOption(options, EDATA("key"), 0));
    httpSetOption(rowOptions, EDATA("params"), httpGetOption(options, EDATA("params"), 0));
    httpSetOption(rowOptions, EDATA("edit"), httpGetOption(options, EDATA("edit"), 0));

    httpInsertOption(options, "class", ESTYLE("table"));
    httpInsertOption(options, "class", ESTYLE("stripe"));
    espRender(conn, "<table%s>\r\n", map(conn, options));

    /*
        Table header
     */
    if (httpOption(options, "showHeader", "true", 1)) {
        espRender(conn, "    <thead>\r\n");
        if ((title = httpGetOption(options, "title", 0)) != 0) {
            espRender(conn, "        <tr class='" ESTYLE("table-title") "'><td colspan='%s'>%s</td></tr>\r\n", 
                mprGetListLength(cols), title);
        }
        espRender(conn, "        <tr class='" ESTYLE("table-header") "'>\r\n");
        rec = grid->records[0];
        for (c = 0; c < ncols; c++) {
            assert(c <= rec->nfields);
            fp = &rec->fields[c];
            width = ((o = httpGetOption(options, "width", 0)) != 0) ? sfmt(" width='%s'", o) : "";
            thisCol = mprLookupKey(colOptions, itosbuf(index, sizeof(index), c, 10));
            header = httpGetOption(thisCol, "header", spascal(fp->name));
            espRender(conn, "            <th%s>%s</th>\r\n", width, header);
        }
        espRender(conn, "        </tr>\r\n    </thead>\r\n");
    }
    espRender(conn, "    <tbody>\r\n");

    /*
        Table body data
     */
    for (r = 0; r < grid->nrecords; r++) {
        rec = grid->records[r];
        httpSetOption(rowOptions, "id", rec->id);
        espRender(conn, "        <tr%s>\r\n", map(conn, rowOptions));
        for (c = 0; c < ncols; c++) {
            fp = &rec->fields[c];
            thisCol = mprLookupKey(colOptions, itosbuf(index, sizeof(index), c, 10));

            if (httpGetOption(thisCol, "align", 0) == 0) {
                if (fp->type == EDI_TYPE_INT || fp->type == EDI_TYPE_FLOAT) {
                    if (!thisCol) {
                        thisCol = mprCreateHash(0, MPR_HASH_STABLE);
                    }
                    httpInsertOption(thisCol, "align", "right");
                }
            }
            value = formatValue(fp, thisCol);
            espRender(conn, "            <td%s>%s</td>\r\n", map(conn, thisCol), value);
        }
        espRender(conn, "        </tr>\r\n");
    }
    espRender(conn, "    </tbody>\r\n</table>\r\n");
}
Esempio n. 5
0
/*
    Render a table from a data grid

    Examples:

        table(grid, "{ refresh:'@update', period:'1000', pivot:'true' }");
        table(grid, "{ click:'@edit' }");
        table(grid, "columns: [ \
            { name: product, header: 'Product', width: '20%' }, \
            { name: date,    format: '%m-%d-%y' }, \
            { name: 'user.name' }, \
        ]");
        table(readTable("users"));
        table(makeGrid("[{'name': 'peter', age: 23 }, {'name': 'mary', age: 22}]")
        table(grid, "{ \
            columns: [ \
                { name: 'speed',         header: 'Speed', dropdown: [100, 1000, 40000] }, \
                { name: 'adminMode',     header: 'Admin Mode', radio: ['Up', 'Down'] }, \
                { name: 'state',         header: 'State', radio: ['Enabled', 'Disabled'] }, \
                { name: 'autoNegotiate', header: 'Auto Negotiate', checkbox: ['enabled'] }, \
                { name: 'type',          header: 'Type' }, \
            ], \
            edit: true, \
            pivot: true, \
            showHeader: false, \
            class: 'esp-pivot', \
        }");

 */
static void pivotTable(HttpConn *conn, EdiGrid *grid, MprHash *options)
{
    MprHash     *colOptions, *rowOptions, *thisCol, *dropdown, *radio;
    MprList     *cols;
    EdiRec      *rec;
    EdiField    *fp;
    cchar       *title, *width, *o, *header, *name, *checkbox;
    char        index[8];
    int         c, r, ncols;
   
    assert(grid);
    if (grid->nrecords == 0) {
        espRender(conn, "<p>No Data</p>\r\n");
        return;
    }
    colOptions = httpGetOptionHash(options, "columns");
    cols = ediGetGridColumns(grid);
    ncols = mprGetListLength(cols);
    rowOptions = mprCreateHash(0, MPR_HASH_STABLE);
    httpSetOption(rowOptions, EDATA("click"), httpGetOption(options, EDATA("click"), 0));
    httpInsertOption(options, "class", ESTYLE("pivot"));
    httpInsertOption(options, "class", ESTYLE("table"));
    espRender(conn, "<table%s>\r\n", map(conn, options));

    /*
        Table header
     */
    if (httpOption(options, "showHeader", "true", 1)) {
        espRender(conn, "    <thead>\r\n");
        if ((title = httpGetOption(options, "title", 0)) != 0) {
            espRender(conn, "        <tr class='" ESTYLE("table-title") "'><td colspan='%s'>%s</td></tr>\r\n", 
                mprGetListLength(cols), title);
        }
        espRender(conn, "        <tr class='" ESTYLE("header") "'>\r\n");
        rec = grid->records[0];
        for (r = 0; r < ncols; r++) {
            assert(r <= grid->nrecords);
            width = ((o = httpGetOption(options, "width", 0)) != 0) ? sfmt(" width='%s'", o) : "";
            thisCol = mprLookupKey(colOptions, itosbuf(index, sizeof(index), r, 10));
            header = httpGetOption(thisCol, "header", spascal(rec->id));
            espRender(conn, "            <th%s>%s</th>\r\n", width, header);
        }
        espRender(conn, "        </tr>\r\n    </thead>\r\n");
    }
    espRender(conn, "    <tbody>\r\n");

    /*
        Table body data
     */
    for (r = 0; r < grid->nrecords; r++) {
        rec = grid->records[r];
        httpSetOption(rowOptions, "id", rec->id);
        espRender(conn, "        <tr%s>\r\n", map(conn, rowOptions));
        for (c = 0; c < ncols; c++) {
            fp = &rec->fields[c];
            thisCol = mprLookupKey(colOptions, itosbuf(index, sizeof(index), r, 10));
            if (httpGetOption(thisCol, "align", 0) == 0) {
                if (fp->type == EDI_TYPE_INT || fp->type == EDI_TYPE_FLOAT) {
                    if (!thisCol) {
                        thisCol = mprCreateHash(0, MPR_HASH_STABLE);
                    }
                    httpInsertOption(thisCol, "align", "right");
                }
            }
            if (c == 0) {
                /* 
                    Render column name
                 */
                name = httpGetOption(thisCol, "header", spascal(rec->id));
                if (httpOption(options, "edit", "true", 0) && httpOption(thisCol, "edit", "true", 1)) {
                    espRender(conn, "            <td%s>%s</td><td>", map(conn, thisCol), name);
                    if ((dropdown = httpGetOption(thisCol, "dropdown", 0)) != 0) {
                        espDropdown(conn, fp->name, hashToGrid(dropdown), 0);
                    } else if ((radio = httpGetOption(thisCol, "radio", 0)) != 0) {
                        espRadio(conn, fp->name, hashToString(radio, 0), 0);
                    } else if ((checkbox = httpGetOption(thisCol, "checkbox", 0)) != 0) {
                        espCheckbox(conn, fp->name, checkbox, 0);
                    } else {
                        input(fp->name, 0);
                    }
                    espRender(conn, "</td>\r\n");
                } else {
                    espRender(conn, "            <td%s>%s</td><td>%s</td>\r\n", map(conn, thisCol), name, fp->value);
                }                
            } else {
                espRender(conn, "            <td%s>%s</td>\r\n", map(conn, thisCol), fp->value);
            }
        }
    }
    espRender(conn, "        </tr>\r\n");
    espRender(conn, "    </tbody>\r\n</table>\r\n");
}
Esempio n. 6
0
/*
    Grid is modified. Columns are removed and sorted as required.
 */
static void filterCols(EdiGrid *grid, MprHash *options, MprHash *colOptions)
{
    MprList     *gridCols;
    MprHash     *cp;
    EdiRec      *rec;
    EdiField    f;
    cchar       *columnName;
    char        key[8];
    int         ncols, r, fnum, currentPos, c, index, *desired, *location, pos, t;

    gridCols = ediGetGridColumns(grid);

    if (colOptions) {
        /*
            Sort grid record columns into the order specified by the column options
         */
        ncols = grid->records[0]->nfields;
        location = mprAlloc(sizeof(int) * ncols);
        for (c = 0; c < ncols; c++) {
            location[c] = c;
        }
        ncols = mprGetHashLength(colOptions);
        desired = mprAlloc(sizeof(int) * ncols);
        for (c = 0; c < ncols; c++) {
            cp = mprLookupKey(colOptions, itosbuf(key, sizeof(key), c, 10));
            if ((columnName = mprLookupKey(cp, "name")) == 0) {
                mprError("Cannot locate \"name\" field for column in table");
                return;
            }
            pos = mprLookupStringItem(gridCols, columnName);
            if (pos < 0) {
                mprError("Cannot find column \"%s\", columns: %s", columnName, mprListToString(gridCols, ", "));
            } else {
                desired[c] = pos;
                location[c] = c;
            }
        }
        for (c = 0; c < ncols; c++) {
            fnum = c;
            for (r = 0; r < grid->nrecords; r++) {
                rec = grid->records[r];
                rec->nfields = ncols;
                fnum = desired[c];
                if (fnum < 0) {
                    continue;
                }
                currentPos = location[fnum];

                f = rec->fields[c];
                rec->fields[c] = rec->fields[currentPos];
                rec->fields[currentPos] = f;
            }
            t = location[c];
            location[c] = location[fnum];
            location[fnum] = t;
        }
        
    } else {
        /*
            If showId is false, remove the "id" column
         */
        if (httpOption(options, "showId", "false", 0) && (index = mprLookupStringItem(gridCols, "id")) >= 0) {
            for (r = 0; r < grid->nrecords; r++) {
                rec = grid->records[r];
                rec->nfields--;
                mprMemcpy(rec->fields, sizeof(EdiField) * rec->nfields, &rec->fields[index],
                    sizeof(EdiField) * (rec->nfields - 1));
            }
        }
    }
}
Esempio n. 7
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;
}