Beispiel #1
0
static void testInsertAndRemove(MprTestGroup *gp)
{
    MprList     *lp;
    int         index;

    lp = mprCreateList(0, 0);
    tassert(lp != 0);

    /*
        Do one insert and remove 
     */
    index = mprAddItem(lp, (void*) 1);
    tassert(index >= 0);
    tassert(mprGetListLength(lp) == 1);

    mprRemoveItem(lp, (void*) 1);
    tassert(mprGetListLength(lp) == 0);

    /*
        Test remove will compact
     */
    mprAddItem(lp, (void*) 1);
    mprAddItem(lp, (void*) 2);
    mprAddItem(lp, (void*) 3);

    mprRemoveItem(lp, (void*) 2);
    tassert(mprGetListLength(lp) == 2);
    mprRemoveItem(lp, (void*) 3);
    tassert(mprGetListLength(lp) == 1);
}
Beispiel #2
0
/*
    Load the standard ejs modules with an optional override search path and list of required modules.
    If the require list is empty, then ejs->empty will be true. This routine should only be called once for an interpreter.
 */
int ejsLoadModules(Ejs *ejs, cchar *search, MprList *require)
{
    EjsService      *sp;

    sp = ejs->service;
    assure(mprGetListLength(ejs->modules) == 0);

    ejs->empty = !(require == 0 || mprGetListLength(require));
    if (search) {
        initSearchPath(ejs, search);
    }
    lock(sp);
    if (loadRequiredModules(ejs, require) < 0) {
        if (ejs->exception) {
            ejsReportError(ejs, "Cannot initialize interpreter");
        }
        ejsDestroyVM(ejs);
        unlock(sp);
        return MPR_ERR_CANT_READ;
    }
    unlock(sp);
    if (mprHasMemError(ejs)) {
        mprError("Memory allocation error during initialization");
        ejsDestroyVM(ejs);
        return MPR_ERR_MEMORY;
    }
    assure(!ejs->exception);
    return 0;
}
Beispiel #3
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;
}
Beispiel #4
0
/*
    Cast the object operand to a primitive type
 */
static EjsObj *xlCast(Ejs *ejs, EjsXML *vp, EjsType *type)
{
    MprBuf      *buf;
    EjsObj      *result;
    EjsXML      *elt, *item;
    int         next;

    if (type == ESV(XML)) {
        return (EjsObj*) vp;
    }
    switch (type->sid) {
    case S_Object:

    case S_Boolean:
        return (EjsObj*) ejsCreateBoolean(ejs, 1);

    case S_Number:
        result = xlCast(ejs, vp, ESV(String));
        result = (EjsObj*) ejsToNumber(ejs, result);
        return result;

    case S_String:
        buf = mprCreateBuf(MPR_BUFSIZE, -1);
        if (mprGetListLength(vp->elements) == 1) {
            elt = mprGetFirstItem(vp->elements);
            if (elt->kind == EJS_XML_ELEMENT) {
                if (elt->elements == 0) {
                    return (EjsObj*) ESV(empty);
                }
                if (elt->elements && mprGetListLength(elt->elements) == 1) {
                    //  TODO - what about PI and comments?
                    item = mprGetFirstItem(elt->elements);
                    if (item->kind == EJS_XML_TEXT) {
                        return (EjsObj*) item->value;
                    }
                }
            }
        }
        for (next = 0; (elt = mprGetNextItem(vp->elements, &next)) != 0; ) {
            if (ejsXMLToBuf(ejs, buf, elt, -1) < 0) {
                return 0;
            }
            if (next < vp->elements->length) {
                mprPutStringToBuf(buf, " ");
            }
        }
        return (EjsObj*) ejsCreateStringFromAsc(ejs, (char*) buf->start);

    default:
        ejsThrowTypeError(ejs, "Cannot cast to this type");
        return 0;
    }
}
Beispiel #5
0
PUBLIC bool httpConfigure(HttpConfigureProc proc, void *data, MprTicks timeout)
{
    Http        *http;
    MprTicks    mark;

    http = HTTP;
    mark = mprGetTicks();
    if (timeout < 0) {
        timeout = http->serverLimits->requestTimeout;
    } else if (timeout == 0) {
        timeout = MAXINT;
    }
    do {
        lock(http->connections);
        /* Own request will count as 1 */
        if (mprGetListLength(http->connections) == 0) {
            (proc)(data);
            unlock(http->connections);
            return 1;
        }
        unlock(http->connections);
        mprSleep(10);
        /* Defaults to 10 secs */
    } while (mprGetRemainingTicks(mark, timeout) > 0);
    return 0;
}
Beispiel #6
0
static int setContentLength(HttpConn *conn, MprList *files)
{
    MprPath     info;
    MprOff      len;
    char        *path, *pair;
    int         next;

    len = 0;
    if (app->upload) {
        httpEnableUpload(conn);
        return 0;
    }
    for (next = 0; (path = mprGetNextItem(files, &next)) != 0; ) {
        if (strcmp(path, "-") != 0) {
            if (mprGetPathInfo(path, &info) < 0) {
                mprError("Can't access file %s", path);
                return MPR_ERR_CANT_ACCESS;
            }
            len += info.size;
        }
    }
    if (app->formData) {
        for (next = 0; (pair = mprGetNextItem(app->formData, &next)) != 0; ) {
            len += slen(pair);
        }
        len += mprGetListLength(app->formData) - 1;
    }
    if (app->bodyData) {
        len += mprGetBufLength(app->bodyData);
    }
    if (len > 0) {
        httpSetContentLength(conn, len);
    }
    return 0;
}
Beispiel #7
0
/*
    Create a value node. If the value is an XML node already, we are done. Otherwise, cast the value to a string
    and create a text child node containing the string value.
 */
static EjsXML *createValueNode(Ejs *ejs, EjsXML *elt, EjsObj *value)
{
    EjsXML      *text;
    EjsString   *str;

    if (ejsIsXML(ejs, value)) {
        return (EjsXML*) value;
    }
    if ((str = (EjsString*) ejsCast(ejs, value, String)) == NULL) {
        return 0;
    }
    if (mprGetListLength(elt->elements) == 1) {
        /*
            Update an existing text element
         */
        text = mprGetFirstItem(elt->elements);
        if (text->kind == EJS_XML_TEXT) {
            text->value = str;
            return elt;
        }
    }

    /*
        Create a new text element
     */
    if (str->value[0] != '\0') {
        text = ejsCreateXML(ejs, EJS_XML_TEXT, N(NULL, NULL), elt, str);
        elt = ejsAppendToXML(ejs, elt, text);
    }
    return elt;
}
Beispiel #8
0
static void testIsListEmpty(MprTestGroup *gp)
{
    MprList     *lp;

    lp = mprCreateList(0, 0);
    tassert(lp != 0);

    tassert(mprGetListLength(lp) == 0);
    tassert(mprGetFirstItem(lp) == 0);
}
Beispiel #9
0
static EdiGrid *mdbReadWhere(Edi *edi, cchar *tableName, cchar *columnName, cchar *operation, cchar *value)
{
    Mdb         *mdb;
    EdiGrid     *grid;
    MdbTable    *table;
    MdbCol      *col;
    MdbRow      *row;
    int         nrows, next, op, r, count;

    assert(edi);
    assert(tableName && *tableName);

    mdb = (Mdb*) edi;
    lock(mdb);
    if ((table = lookupTable(mdb, tableName)) == 0) {
        unlock(mdb);
        return 0;
    }
    nrows = mprGetListLength(table->rows);
    if ((grid = ediCreateBareGrid(edi, tableName, nrows)) == 0) {
        unlock(mdb);
        return 0;
    }
    grid->flags = EDI_GRID_READ_ONLY;
    if (columnName) {
        if ((col = lookupColumn(table, columnName)) == 0) {
            unlock(mdb);
            return 0;
        }
        if ((op = parseOperation(operation)) < 0) {
            unlock(mdb);
            return 0;
        }
        if (col->flags & EDI_INDEX && (op & OP_EQ)) {
            if ((r = lookupRow(table, value)) != 0) {
                row = getRow(table, r);
                grid->records[0] = createRecFromRow(edi, row);
                grid->nrecords = 1;
            }
        } else {
            grid->nrecords = count = 0;
            for (ITERATE_ITEMS(table->rows, row, next)) {
                if (!matchRow(col, row->fields[col->cid], op, value)) {
                    continue;
                }
                grid->records[count++] = createRecFromRow(edi, row);
                grid->nrecords = count;
            }
        }
    } else {
        for (ITERATE_ITEMS(table->rows, row, next)) {
Beispiel #10
0
/*
    Update an existing element
 */
static int updateElement(Ejs *ejs, EjsXML *list, EjsXML *elt, int index, EjsObj *value)
{
    EjsXML      *node;
    int         i, j;

    if (!ejsIsXML(ejs, value)) {
        /* Not XML or XMLList -- convert to string */
        value = ejsCast(ejs, value, String);                //  TODO - seem to be doing this in too many places
    }
    mprSetItem(list->elements, index, value);

    if (elt->kind == EJS_XML_ATTRIBUTE) {
        assure(ejsIs(ejs, value, String));
        i = mprLookupItem(elt->parent->elements, elt);
        assure(i >= 0);
        ejsSetXMLElement(ejs, elt->parent, i, elt);
        //  TODO - why do this. Doesn't above do this?
        ejsSetPropertyByName(ejs, elt->parent, elt->qname, value);
        elt->value = (EjsString*) value;
    }

    if (ejsIsXML(ejs, value) && ((EjsXML*) value)->kind == EJS_XML_LIST) {
        value = (EjsObj*) shallowCopy(ejs, (EjsXML*) value);
        if (elt->parent) {
            index = mprLookupItem(elt->parent->elements, elt);
            assure(index >= 0);
            for (j = 0; j < mprGetListLength(((EjsXML*) value)->elements); j++) {
                mprInsertItemAtPos(elt->parent->elements, index, value);
            }
        }

    } else if (ejsIsXML(ejs, value) || elt->kind != EJS_XML_ELEMENT) {
        if (elt->parent) {
            index = mprLookupItem(elt->parent->elements, elt);
            assure(index >= 0);
            mprSetItem(elt->parent->elements, index, value);
            ((EjsXML*) value)->parent = elt->parent;
            if (ejsIs(ejs, value, String)) {
                node = ejsCreateXML(ejs, EJS_XML_TEXT, N(NULL, NULL), list, (EjsString*) value);
                mprSetItem(list->elements, index, node);
            } else {
                mprSetItem(list->elements, index, value);
            }
        }

    } else {
        ejsSetPropertyByName(ejs, elt, N(NULL, "*"), value);
    }
    return index;
}
Beispiel #11
0
/*
    Deep compare
 */
static bool deepCompare(EjsXML *lhs, EjsXML *rhs)
{
    EjsXML      *l, *r;
    int         i;

    if (lhs == rhs) {
        return 1;
    }
    //  TODO - must compare all the namespaces?
    if (lhs->kind != rhs->kind) {
        return 0;

    } else  if (lhs->qname.name != rhs->qname.name) {
        return 0;

    } else if (mprGetListLength(lhs->attributes) != mprGetListLength(rhs->attributes)) {
        //  TODO - must compare all the attributes
        return 0;

    } else if (mprGetListLength(lhs->elements) != mprGetListLength(rhs->elements)) {
        //  TODO - must compare all the children
        return 0;

    } else if (lhs->value != rhs->value) {
        return 0;

    } else {
        for (i = 0; i < mprGetListLength(lhs->elements); i++) {
            l = mprGetItem(lhs->elements, i);
            r = mprGetItem(rhs->elements, i);
            if (! deepCompare(l, r)) {
                return 0;
            }
        }
    }
    return 1;
}
Beispiel #12
0
PUBLIC void httpGetStats(HttpStats *sp)
{
    Http                *http;
    HttpAddress         *address;
    MprKey              *kp;
    MprMemStats         *ap;
    MprWorkerStats      wstats;
    ssize               memSessions;

    memset(sp, 0, sizeof(*sp));
    http = HTTP;
    ap = mprGetMemStats();

    sp->cpuUsage = ap->cpuUsage;
    sp->cpuCores = ap->cpuCores;
    sp->ram = ap->ram;
    sp->mem = ap->rss;
    sp->memRedline = ap->warnHeap;
    sp->memMax = ap->maxHeap;

    sp->heap = ap->bytesAllocated;
    sp->heapUsed = ap->bytesAllocated - ap->bytesFree;
    sp->heapPeak = ap->bytesAllocatedPeak;
    sp->heapFree = ap->bytesFree;
    sp->heapRegions = ap->heapRegions;

    mprGetWorkerStats(&wstats);
    sp->workersBusy = wstats.busy;
    sp->workersIdle = wstats.idle;
    sp->workersYielded = wstats.yielded;
    sp->workersMax = wstats.max;

    sp->activeConnections = mprGetListLength(http->connections);
    sp->activeProcesses = http->activeProcesses;

    mprGetCacheStats(http->sessionCache, &sp->activeSessions, &memSessions);
    sp->memSessions = memSessions;

    lock(http->addresses);
    for (ITERATE_KEY_DATA(http->addresses, kp, address)) {
        sp->activeRequests += (int) address->counters[HTTP_COUNTER_ACTIVE_REQUESTS].value;
        sp->activeClients++;
    }
    unlock(http->addresses);

    sp->totalRequests = http->totalRequests;
    sp->totalConnections = http->totalConnections;
    sp->totalSweeps = MPR->heap->stats.sweeps;
}
Beispiel #13
0
static void testLotsOfInserts(MprTestGroup *gp)
{
    MprList     *lp;
    int         i;

    lp = mprCreateList(LIST_MAX_ITEMS, 0);
    tassert(lp != 0);

    /*
        Do lots insertions 
     */
    for (i = 0; i < LIST_MAX_ITEMS; i++) {
        mprAddItem(lp, (void*) (long) i);
        tassert(mprGetListLength(lp) == (i + 1));
    }

    /*
        Now remove
     */
    for (i = LIST_MAX_ITEMS - 1; i >= 0; i--) {
        mprRemoveItem(lp, (void*) (long) i);
        tassert(mprGetListLength(lp) == i);
    }
}
Beispiel #14
0
static MprWaitHandler *initWaitHandler(MprWaitHandler *wp, int fd, int mask, MprDispatcher *dispatcher, void *proc,
    void *data, int flags)
{
    MprWaitService  *ws;

    assert(fd >= 0);
    ws = MPR->waitService;

#if ME_DEBUG
    {
        MprWaitHandler  *op;
        int             index;

        for (ITERATE_ITEMS(ws->handlers, op, index)) {
            if (op->fd == fd) {
                mprLog("error mpr event", 0, "Duplicate fd in wait handlers");
            }
        }
    }
#endif
    wp->fd              = fd;
    wp->notifierIndex   = -1;
    wp->dispatcher      = dispatcher;
    wp->proc            = proc;
    wp->flags           = 0;
    wp->handlerData     = data;
    wp->service         = ws;
    wp->flags           = flags;

    if (mprGetListLength(ws->handlers) >= FD_SETSIZE) {
        mprLog("error mpr event", 0, "Too many io handlers: %d", FD_SETSIZE);
        return 0;
    }
#if ME_UNIX_LIKE || VXWORKS
#if ME_EVENT_NOTIFIER == MPR_EVENT_SELECT
    if (fd >= FD_SETSIZE) {
        mprLog("error mpr event", 0, "File descriptor %d exceeds max io of %d", fd, FD_SETSIZE);
    }
#endif
#endif
    if (mask) {
        if (mprAddItem(ws->handlers, wp) < 0) {
            return 0;
        }
        mprNotifyOn(wp, mask);
    }
    return wp;
}
Beispiel #15
0
/*
    Function to iterate and return the next element name.
    NOTE: this is not a method of Xml. Rather, it is a callback function for Iterator
 */
static EjsObj *nextXmlKey(Ejs *ejs, EjsIterator *ip, int argc, EjsObj **argv)
{
    EjsXML  *xml;

    xml = (EjsXML*) ip->target;
    if (!ejsIsXML(ejs, xml)) {
        ejsThrowReferenceError(ejs, "Wrong type");
        return 0;
    }

    if (ip->index < mprGetListLength(xml->elements)) {
        return (EjsObj*) ejsCreateNumber(ejs, ip->index++);
    }
    ejsThrowStopIteration(ejs);
    return 0;
}
Beispiel #16
0
/*
    Cast the object operand to a primitive type
 */
static EjsAny *castXml(Ejs *ejs, EjsXML *xml, EjsType *type)
{
    EjsXML      *item;
    EjsObj      *result;
    MprBuf      *buf;

    assert(ejsIsXML(ejs, xml));

    if (type == ESV(XMLList)) {
        return xml;
    }

    switch (type->sid) {
    case S_Object:

    case S_Boolean:
        return ejsCreateBoolean(ejs, 1);

    case S_Number:
        result = castXml(ejs, xml, ESV(String));
        return ejsToNumber(ejs, result);

    case S_String:
        if (xml->kind == EJS_XML_ELEMENT) {
            if (xml->elements == 0) {
                return ESV(empty);
            }
            if (xml->elements && mprGetListLength(xml->elements) == 1) {
                //  TODO - what about PI and comments?
                item = mprGetFirstItem(xml->elements);
                if (item->kind == EJS_XML_TEXT) {
                    return item->value;
                }
            }
        }
        buf = mprCreateBuf(BIT_MAX_BUFFER, -1);
        if (ejsXMLToBuf(ejs, buf, xml, -1) < 0) {
            return 0;
        }
        return ejsCreateStringFromAsc(ejs, (char*) buf->start);

    default:
        ejsThrowTypeError(ejs, "Cannot cast to this type");
        return 0;
    }
    return 0;
}
Beispiel #17
0
static MprList *mdbGetTables(Edi *edi)
{
    Mdb         *mdb;
    MprList     *list;
    MdbTable     *table;
    int         tid, ntables;

    mdb = (Mdb*) edi;
    lock(mdb);
    list = mprCreateList(-1, 0);
    ntables = mprGetListLength(mdb->tables);
    for (tid = 0; tid < ntables; tid++) {
        table = mprGetItem(mdb->tables, tid);
        mprAddItem(list, table->name);
    }
    unlock(mdb);
    return list;
}
Beispiel #18
0
/*
    Return true if the join is successful
 */
static int reapJoins(Ejs *ejs, EjsObj *workers)
{
    EjsWorker   *worker;
    EjsArray    *set;
    int         i, completed, joined, count;

    lock(ejs);
    completed = 0;
    joined = 0;

    if (workers == 0 || ejsIs(ejs, workers, Null)) {
        /* Join all */
        count = mprGetListLength(ejs->workers);
        for (i = 0; i < count; i++) {
            worker = mprGetItem(ejs->workers, i);
            if (worker->state >= EJS_WORKER_COMPLETE) {
                completed++;
            }
        }
        if (completed == count) {
            joined = 1;
        }
    } else if (ejsIs(ejs, workers, Array)) {
        /* Join a set */
        set = (EjsArray*) workers;
        for (i = 0; i < set->length; i++) {
            worker = (EjsWorker*) set->data[i];
            if (worker->state >= EJS_WORKER_COMPLETE) {
                completed++;
            }
        }
        if (completed == set->length) {
            joined = 1;
        }
    } else if (TYPE(workers) == ESV(Worker)) {
        /* Join one worker */
        worker = (EjsWorker*) workers;
        if (worker->state >= EJS_WORKER_COMPLETE) {
            joined = 1;
        }
    }
    unlock(ejs);
    return joined;
}
Beispiel #19
0
static int mdbGetTableSchema(Edi *edi, cchar *tableName, int *numRows, int *numCols)
{
    Mdb         *mdb;
    MdbTable    *table;

    mdb = (Mdb*) edi;
    lock(mdb);
    if ((table = lookupTable(mdb, tableName)) == 0) {
        unlock(mdb);
        return MPR_ERR_CANT_FIND;
    }
    if (numRows) {
        *numRows = mprGetListLength(table->rows);
    }
    if (numCols) {
        *numCols = table->schema->ncols;
    }
    unlock(mdb);
    return 0;
}
Beispiel #20
0
/*
    Function to iterate and return the next element value.
    NOTE: this is not a method of Xml. Rather, it is a callback function for Iterator
 */
static EjsObj *nextXmlValue(Ejs *ejs, EjsIterator *ip, int argc, EjsObj **argv)
{
    EjsXML      *xml, *vp;

    xml = (EjsXML*) ip->target;
    if (!ejsIsXML(ejs, xml)) {
        ejsThrowReferenceError(ejs, "Wrong type");
        return 0;
    }

    for (; ip->index < mprGetListLength(xml->elements); ip->index++) {
        vp = (EjsXML*) mprGetItem(xml->elements, ip->index);
        if (vp == 0) {
            continue;
        }
        ip->index++;
        return (EjsObj*) vp;
    }
    ejsThrowStopIteration(ejs);
    return 0;
}
Beispiel #21
0
/*
    Set a property by name.
 */
static int setXmlListPropertyByName(Ejs *ejs, EjsXML *list, EjsName qname, EjsObj *value)
{
    EjsXML      *elt, *targetObject;
    int         index;

    if (!isdigit((uchar) qname.name->value[0])) {
        return setAlphaPropertyByName(ejs, list, qname, value);
    }

    /*
        Numeric property
     */
    targetObject = 0;
    if (list->targetObject) {
        /*
            Find the real underlying target object. May be an XML object or XMLList if it contains multiple elements.
         */
        targetObject = resolve(ejs, list->targetObject);
        if (targetObject == 0) {
            /* Spec says so - TODO why no error? */
            return 0;
        }
    }
    index = ejsAtoi(ejs, qname.name, 10);
    if (index >= mprGetListLength(list->elements)) {
        /*
            Create, then fall through to update
         */
        elt = createElement(ejs, list, targetObject, qname, value);
        if (elt == 0) {
            return 0;
        }

    } else {
        elt = mprGetItem(list->elements, index);
    }
    assure(elt);
    updateElement(ejs, list, elt, index, value);
    return index;
}
Beispiel #22
0
/*
    Resolve empty XML list objects to an actual XML object. This is used by SetPropertyByName to find the actual 
    object to update. This method resolves the value of empty XMLLists. If the XMLList is not empty, the list will 
    be returned. If list is empty, this method attempts to create an element based on the list targetObject and 
    targetProperty.
 */
static EjsXML *resolve(Ejs *ejs, EjsXML *xml)
{
    EjsXML  *targetObject, *targetPropertyList;

    if (!ejsIsXML(ejs, xml) || xml->kind != EJS_XML_LIST) {
        /* Resolved to an XML object */
        return xml;
    }
    if (mprGetListLength(xml->elements) > 0) {
        /* Resolved to a list of items */
        return xml;
    }
    if (xml->targetObject == 0 || xml->targetProperty.name == NULL || xml->targetProperty.name->value[0] == '*') {
        /* End of chain an no more target objects */
        return 0;
    }
    targetObject = resolve(ejs, xml->targetObject);
    if (targetObject == 0) {
        return 0;
    }
    //  TODO - OPT. targetPropertyList is also being created below.
    targetPropertyList = ejsGetPropertyByName(ejs, (EjsObj*) targetObject, xml->targetProperty);
    if (targetPropertyList == 0) {
        return 0;
    }
    if (ejsGetLength(ejs, (EjsObj*) targetPropertyList) == 0) {
        /*
            Property does not exist in the target.
         */
        if (targetObject->kind == EJS_XML_LIST && ejsGetLength(ejs, (EjsObj*) targetObject) > 1) {
            return 0;
        }
        /*
            Create the property as an element (The text value will be optimized away).
         */
        ejsSetPropertyByName(ejs, targetObject, xml->targetProperty, ESV(empty));
        targetPropertyList = ejsGetPropertyByName(ejs, (EjsObj*) targetObject, xml->targetProperty);
    }
    return targetPropertyList;
}
Beispiel #23
0
MAIN(ejsMain, int argc, char **argv, char **envp)
{
    Mpr             *mpr;
    EcCompiler      *cp;
    Ejs             *ejs;
    cchar           *cmd, *className, *method, *homeDir;
    char            *argp, *searchPath, *modules, *name, *tok, *extraFiles;
    int             nextArg, err, ecFlags, stats, merge, bind, noout, debug, optimizeLevel, warnLevel, strict, i, next;

    /*  
        Initialize Multithreaded Portable Runtime (MPR)
     */
    mpr = mprCreate(argc, argv, 0);
    app = mprAllocObj(App, manageApp);
    mprAddRoot(app);
    mprAddStandardSignals();

    if (mprStart(mpr) < 0) {
        mprError("Cannot start mpr services");
        return EJS_ERR;
    }
    err = 0;
    className = 0;
    cmd = 0;
    method = 0;
    searchPath = 0;
    stats = 0;
    merge = 0;
    bind = 1;
    noout = 1;
    debug = 1;
    warnLevel = 1;
    optimizeLevel = 9;
    strict = 0;
    app->files = mprCreateList(-1, 0);
    app->iterations = 1;
    argc = mpr->argc;
    argv = (char**) mpr->argv;

    for (nextArg = 1; nextArg < argc; nextArg++) {
        argp = argv[nextArg];
        if (*argp != '-') {
            break;
        }
        if (smatch(argp, "--bind")) {
            bind = 1;

        } else if (smatch(argp, "--class")) {
            if (nextArg >= argc) {
                err++;
            } else {
                className = argv[++nextArg];
            }

        } else if (smatch(argp, "--chdir") || smatch(argp, "--home") || smatch(argp, "-C")) {
            if (nextArg >= argc) {
                err++;
            } else {
                homeDir = argv[++nextArg];
                if (chdir((char*) homeDir) < 0) {
                    mprError("Cannot change directory to %s", homeDir);
                }
            }

#if BIT_UNIX_LIKE
        } else if (smatch(argp, "--chroot")) {
            /* Not documented or supported */
            if (nextArg >= argc) {
                err++;
            } else {
                homeDir = mprGetAbsPath(argv[++nextArg]);
                if (chroot(homeDir) < 0) {
                    if (errno == EPERM) {
                        mprPrintfError("%s: Must be super user to use the --chroot option", mprGetAppName(mpr));
                    } else {
                        mprPrintfError("%s: Cannot change change root directory to %s, errno %d",
                            mprGetAppName(), homeDir, errno);
                    }
                    return 4;
                }
            }
#endif

        } else if (smatch(argp, "--cmd") || smatch(argp, "-c")) {
            if (nextArg >= argc) {
                err++;
            } else {
                cmd = argv[++nextArg];
            }

#if BIT_WIN_LIKE
        } else if (smatch(argp, "--cygroot")) {
            if (nextArg >= argc) {
                err++;
            } else {
                app->cygroot = sclone(argv[++nextArg]);
            }
#endif
        } else if (smatch(argp, "--debug")) {
            debug = 1;

        } else if (smatch(argp, "--debugger") || smatch(argp, "-D")) {
            mprSetDebugMode(1);

        } else if (smatch(argp, "--files") || smatch(argp, "-f")) {
            /* Compatibility with mozilla shell */
            if (nextArg >= argc) {
                err++;
            } else {
                extraFiles = sclone(argv[++nextArg]);
                name = stok(extraFiles, " \t", &tok);
                while (name != NULL) {
                    mprAddItem(app->files, sclone(name));
                    name = stok(NULL, " \t", &tok);
                }
            }

        } else if (smatch(argp, "--iterations") || smatch(argp, "-i")) {
            if (nextArg >= argc) {
                err++;
            } else {
                app->iterations = atoi(argv[++nextArg]);
            }

        } else if (smatch(argp, "--log")) {
            if (nextArg >= argc) {
                err++;
            } else {
                mprStartLogging(argv[++nextArg], 0);
                mprSetCmdlineLogging(1);
            }

        } else if (smatch(argp, "--method")) {
            if (nextArg >= argc) {
                err++;
            } else {
                method = argv[++nextArg];
            }

        } else if (smatch(argp, "--name")) {
            /* Just ignore. Used to tag commands with a unique command line */ 
            nextArg++;

        } else if (smatch(argp, "--nobind")) {
            bind = 0;

        } else if (smatch(argp, "--nodebug")) {
            debug = 0;

        } else if (smatch(argp, "--optimize")) {
            if (nextArg >= argc) {
                err++;
            } else {
                optimizeLevel = atoi(argv[++nextArg]);
            }

        } else if (smatch(argp, "-s")) {
            /* Compatibility with mozilla shell. Just ignore */

        } else if (smatch(argp, "--search") || smatch(argp, "--searchpath")) {
            if (nextArg >= argc) {
                err++;
            } else {
                searchPath = argv[++nextArg];
            }

        } else if (smatch(argp, "--standard")) {
            strict = 0;

        } else if (smatch(argp, "--stats")) {
            stats = 1;

        } else if (smatch(argp, "--strict")) {
            strict = 1;

        } else if (smatch(argp, "--require")) {
            if (nextArg >= argc) {
                err++;
            } else {
                if (app->modules == 0) {
                    app->modules = mprCreateList(-1, 0);
                }
                modules = sclone(argv[++nextArg]);
                name = stok(modules, " \t", &tok);
                while (name != NULL) {
                    require(name);
                    name = stok(NULL, " \t", &tok);
                }
            }

        } else if (smatch(argp, "--verbose") || smatch(argp, "-v")) {
            mprStartLogging("stderr:2", 0);
            mprSetCmdlineLogging(1);

        } else if (smatch(argp, "--version") || smatch(argp, "-V")) {
            mprPrintf("%s-%s\n", BIT_VERSION, BIT_BUILD_NUMBER);
            return 0;

        } else if (smatch(argp, "--warn")) {
            if (nextArg >= argc) {
                err++;
            } else {
                warnLevel = atoi(argv[++nextArg]);
            }

        } else {
            err++;
            break;
        }
    }

    if (err) {
        /*  
            If --method or --class is specified, then the named class.method will be run (method defaults to "main", class
            defaults to first class with a "main").

            Examples:
                ejs
                ejs script.es arg1 arg2 arg3
                ejs --class "Customer" --method "start" --files "script1.es script2.es" main.es
         */
        mprPrintfError("Usage: %s [options] script.es [arguments] ...\n"
            "  Ejscript shell program options:\n"
            "  --class className        # Name of class containing method to run\n"
            "  --cmd ejscriptCode       # Literal ejscript statements to execute\n"
            "  --cygroot path           # Set cygwin root for resolving script paths\n"
            "  --debug                  # Use symbolic debugging information (default)\n"
            "  --debugger               # Disable timeouts to make using a debugger easier\n"
            "  --files \"files..\"        # Extra source to compile\n"
            "  --log logSpec            # Internal compiler diagnostics logging\n"
            "  --method methodName      # Name of method to run. Defaults to main\n"
            "  --nodebug                # Omit symbolic debugging information\n"
            "  --optimize level         # Set the optimization level (0-9 default is 9)\n"
            "  --require 'module,...'   # Required list of modules to pre-load\n"
            "  --search ejsPath         # Module search path\n"
            "  --standard               # Default compilation mode to standard (default)\n"
            "  --stats                  # Print memory stats on exit\n"
            "  --strict                 # Default compilation mode to strict\n"
            "  --verbose | -v           # Same as --log stderr:2 \n"
            "  --version                # Emit the compiler version information\n"
            "  --warn level             # Set the warning message level (0-9 default is 0)\n\n",
            mpr->name);
        return -1;
    }
    if ((ejs = ejsCreateVM(argc - nextArg, (cchar **) &argv[nextArg], 0)) == 0) {
        return MPR_ERR_MEMORY;
    }
    app->ejs = ejs;
    if (ejsLoadModules(ejs, searchPath, app->modules) < 0) {
        return MPR_ERR_CANT_READ;
    }

    ecFlags = 0;
    ecFlags |= (merge) ? EC_FLAGS_MERGE: 0;
    ecFlags |= (bind) ? EC_FLAGS_BIND: 0;
    ecFlags |= (noout) ? EC_FLAGS_NO_OUT: 0;
    ecFlags |= (debug) ? EC_FLAGS_DEBUG: 0;

    cp = app->compiler = ecCreateCompiler(ejs, ecFlags);
    if (cp == 0) {
        return MPR_ERR_MEMORY;
    }
    ecSetRequire(cp, app->modules);

    ecSetOptimizeLevel(cp, optimizeLevel);
    ecSetWarnLevel(cp, warnLevel);
    ecSetStrictMode(cp, strict);
    if (nextArg < argc) {
        mprAddItem(app->files, sclone(argv[nextArg]));
    }
    if (app->cygroot) {
        /*  
            When cygwin invokes a script with shebang, it passes a cygwin path to the script
            The ejs --cygroot option permits ejscript to conver this to a native path
         */
        for (next = 0; (name = mprGetNextItem(app->files, &next)) != 0; ) {
            if (*name == '/' || *name == '\\') {
                mprSetItem(app->files, next - 1, sjoin(app->cygroot, name, NULL));
            }
        }
    }
    for (i = 0; !err && i < app->iterations; i++) {
        if (cmd) {
            if (interpretCommands(cp, cmd) < 0) {
                err++;
            }
        } else if (mprGetListLength(app->files) > 0) {
            if (interpretFiles(cp, app->files, argc - nextArg, &argv[nextArg], className, method) < 0) {
                err++;
            }
        } else {
            /*  
                No args - run as an interactive shell
             */
            if (interpretCommands(cp, NULL) < 0) {
                err++;
            }
        }
    }
    if (stats) {
#if BIT_DEBUG
        mprSetLogLevel(1);
        mprPrintMem("Memory Usage", 1);
#endif
    }
    if (!err) {
        err = mpr->exitStatus;
    }
    app->ejs = 0;
    mprTerminate(MPR_EXIT_DEFAULT, err);
    ejsDestroyVM(ejs);
    mprDestroy(MPR_EXIT_DEFAULT);
    return err;
}
Beispiel #24
0
static void sortList(HttpConn *conn, MprList *list)
{
    MprDirEntry *tmp, **items;
    Dir         *dir;
    int         count, i, j, rc;

    dir = conn->data;
    
    if (dir->sortField == 0) {
        return;
    }
    count = mprGetListLength(list);
    items = (MprDirEntry**) list->items;
    if (scaselessmatch(dir->sortField, "Name")) {
        for (i = 1; i < count; i++) {
            for (j = 0; j < i; j++) {
                rc = strcmp(items[i]->name, items[j]->name);
                if (dir->foldersFirst) {
                    if (items[i]->isDir && !items[j]->isDir) {
                        rc = -dir->sortOrder;
                    } else if (items[j]->isDir && !items[i]->isDir) {
                        rc = dir->sortOrder;
                    } 
                }
                rc *= dir->sortOrder;
                if (rc < 0) {
                    tmp = items[i];
                    items[i] = items[j];
                    items[j] = tmp;
                }
            }
        }

    } else if (scaselessmatch(dir->sortField, "Size")) {
        for (i = 1; i < count; i++) {
            for (j = 0; j < i; j++) {
                rc = (items[i]->size < items[j]->size) ? -1 : 1;
                if (dir->foldersFirst) {
                    if (items[i]->isDir && !items[j]->isDir) {
                        rc = -dir->sortOrder;
                    } else if (items[j]->isDir && !items[i]->isDir) {
                        rc = dir->sortOrder;
                    }
                }
                rc *= dir->sortOrder;
                if (rc < 0) {
                    tmp = items[i];
                    items[i] = items[j];
                    items[j] = tmp;
                }
            }
        }

    } else if (scaselessmatch(dir->sortField, "Date")) {
        for (i = 1; i < count; i++) {
            for (j = 0; j < i; j++) {
                rc = (items[i]->lastModified < items[j]->lastModified) ? -1: 1;
                if (dir->foldersFirst) {
                    if (items[i]->isDir && !items[j]->isDir) {
                        rc = -dir->sortOrder;
                    } else if (items[j]->isDir && !items[i]->isDir) {
                        rc = dir->sortOrder;
                    }
                }
                rc *= dir->sortOrder;
                if (rc < 0) {
                    tmp = items[i];
                    items[i] = items[j];
                    items[j] = tmp;
                }
            }
        }
    }
}
Beispiel #25
0
PUBLIC ssize mprGetActiveCmdCount()
{
    return mprGetListLength(MPR->cmdService->cmds);
}
Beispiel #26
0
/*
    OPT
 */
bool httpValidateLimits(HttpEndpoint *endpoint, int event, HttpConn *conn)
{
    HttpLimits      *limits;
    Http            *http;
    cchar           *action;
    int             count, level, dir;

    limits = conn->limits;
    dir = HTTP_TRACE_RX;
    action = "unknown";
    mprAssert(conn->endpoint == endpoint);
    http = endpoint->http;

    lock(http);

    switch (event) {
    case HTTP_VALIDATE_OPEN_CONN:
        /*
            This measures active client systems with unique IP addresses.
         */
        if (endpoint->clientCount >= limits->clientMax) {
            unlock(http);
            /*  Abort connection */
            httpError(conn, HTTP_ABORT | HTTP_CODE_SERVICE_UNAVAILABLE, 
                "Too many concurrent clients %d/%d", endpoint->clientCount, limits->clientMax);
            return 0;
        }
        count = (int) PTOL(mprLookupKey(endpoint->clientLoad, conn->ip));
        mprAddKey(endpoint->clientLoad, conn->ip, ITOP(count + 1));
        endpoint->clientCount = (int) mprGetHashLength(endpoint->clientLoad);
        action = "open conn";
        dir = HTTP_TRACE_RX;
        break;

    case HTTP_VALIDATE_CLOSE_CONN:
        count = (int) PTOL(mprLookupKey(endpoint->clientLoad, conn->ip));
        if (count > 1) {
            mprAddKey(endpoint->clientLoad, conn->ip, ITOP(count - 1));
        } else {
            mprRemoveKey(endpoint->clientLoad, conn->ip);
        }
        endpoint->clientCount = (int) mprGetHashLength(endpoint->clientLoad);
        action = "close conn";
        dir = HTTP_TRACE_TX;
        break;
    
    case HTTP_VALIDATE_OPEN_REQUEST:
        mprAssert(conn->rx);
        if (endpoint->requestCount >= limits->requestMax) {
            unlock(http);
            httpError(conn, HTTP_CODE_SERVICE_UNAVAILABLE, "Server overloaded");
            mprLog(2, "Too many concurrent requests %d/%d", endpoint->requestCount, limits->requestMax);
            return 0;
        }
        endpoint->requestCount++;
        conn->rx->flags |= HTTP_LIMITS_OPENED;
        action = "open request";
        dir = HTTP_TRACE_RX;
        break;

    case HTTP_VALIDATE_CLOSE_REQUEST:
        if (conn->rx && conn->rx->flags & HTTP_LIMITS_OPENED) {
            /* Requests incremented only when conn->rx is assigned */
            endpoint->requestCount--;
            mprAssert(endpoint->requestCount >= 0);
            action = "close request";
            dir = HTTP_TRACE_TX;
            conn->rx->flags &= ~HTTP_LIMITS_OPENED;
        }
        break;

    case HTTP_VALIDATE_OPEN_PROCESS:
        if (http->processCount >= limits->processMax) {
            unlock(http);
            httpError(conn, HTTP_CODE_SERVICE_UNAVAILABLE, "Server overloaded");
            mprLog(2, "Too many concurrent processes %d/%d", http->processCount, limits->processMax);
            return 0;
        }
        http->processCount++;
        action = "start process";
        dir = HTTP_TRACE_RX;
        break;

    case HTTP_VALIDATE_CLOSE_PROCESS:
        http->processCount--;
        mprAssert(http->processCount >= 0);
        break;
    }
    if (event == HTTP_VALIDATE_CLOSE_CONN || event == HTTP_VALIDATE_CLOSE_REQUEST) {
        if ((level = httpShouldTrace(conn, dir, HTTP_TRACE_LIMITS, NULL)) >= 0) {
            LOG(4, "Validate request for %s. Active connections %d, active requests: %d/%d, active client IP %d/%d", 
                action, mprGetListLength(http->connections), endpoint->requestCount, limits->requestMax, 
                endpoint->clientCount, limits->clientMax);
        }
    }
    unlock(http);
    return 1;
}
Beispiel #27
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;
}
Beispiel #28
0
/*
    <% stylesheets(patterns); %>

    Where patterns may contain *, ** and !pattern for exclusion
 */
PUBLIC void stylesheets(cchar *patterns)
{
    HttpStream    *stream;
    HttpRx      *rx;
    HttpRoute   *route;
    EspRoute    *eroute;
    MprList     *files;
    cchar       *filename, *ext, *uri, *path, *kind, *version, *clientDir;
    int         next;

    stream = getStream();
    rx = stream->rx;
    route = rx->route;
    eroute = route->eroute;
    patterns = httpExpandRouteVars(route, patterns);
    clientDir = httpGetDir(route, "documents");

    if (!patterns || !*patterns) {
        version = espGetConfig(route, "version", "1.0.0");
        if (eroute->combineSheet) {
            /* Previously computed combined stylesheet filename */
            stylesheets(eroute->combineSheet);

        } else if (espGetConfig(route, "http.content.combine[@=css]", 0)) {
            if (espGetConfig(route, "http.content.minify[@=css]", 0)) {
                eroute->combineSheet = sfmt("css/all-%s.min.css", version);
            } else {
                eroute->combineSheet = sfmt("css/all-%s.css", version);
            }
            stylesheets(eroute->combineSheet);

        } else {
            /*
                Not combining into a single stylesheet, so give priority to all.less over all.css if present
                Load a pure CSS incase some styles need to be applied before the lesssheet is parsed
             */
            ext = espGetConfig(route, "http.content.stylesheets", "css");
            filename = mprJoinPathExt("css/all", ext);
            path = mprJoinPath(clientDir, filename);
            if (mprPathExists(path, R_OK)) {
                stylesheets(filename);
            } else if (!smatch(ext, "less")) {
                path = mprJoinPath(clientDir, "css/all.less");
                if (mprPathExists(path, R_OK)) {
                    stylesheets("css/all.less");
                }
            }
        }
    } else {
        if (sends(patterns, "all.less")) {
            path = mprJoinPath(clientDir, "css/fix.css");
            if (mprPathExists(path, R_OK)) {
                stylesheets("css/fix.css");
            }
        }
        if ((files = mprGlobPathFiles(clientDir, patterns, MPR_PATH_RELATIVE)) == 0 || mprGetListLength(files) == 0) {
            files = mprCreateList(0, 0);
            mprAddItem(files, patterns);
        }
        for (ITERATE_ITEMS(files, path, next)) {
            path = sjoin("~/", strim(path, ".gz", MPR_TRIM_END), NULL);
            uri = httpLink(stream, path);
            kind = mprGetPathExt(path);
            if (smatch(kind, "css")) {
                espRender(stream, "<link rel='stylesheet' type='text/css' href='%s' />\n", uri);
            } else {
                espRender(stream, "<link rel='stylesheet/%s' type='text/css' href='%s' />\n", kind, uri);
            }
        }
    }
}
Beispiel #29
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");
}
Beispiel #30
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");
}