PUBLIC void form(EdiRec *record, cchar *optionString) { HttpConn *conn; MprHash *options; cchar *action, *recid, *method, *uri, *token; conn = getConn(); if (record == 0) { record = getRec(); } else { conn->record = record; } options = httpGetOptions(optionString); recid = 0; /* If record provided, get the record id. Can be overridden using options.recid */ if (record) { if (record->id && !httpGetOption(options, "recid", 0)) { httpAddOption(options, "recid", record->id); } recid = httpGetOption(options, "recid", 0); emitFormErrors(conn, record, options); } if ((method = httpGetOption(options, "method", 0)) == 0) { method = (recid) ? "PUT" : "POST"; } if (!scaselessmatch(method, "GET") && !scaselessmatch(method, "POST")) { /* All methods use POST and tunnel method in data-method */ httpAddOption(options, EDATA("method"), method); method = "POST"; } if ((action = httpGetOption(options, "action", 0)) == 0) { action = (recid) ? "@update" : "@create"; } uri = httpUri(conn, action); if (smatch(httpGetOption(options, "remote", 0), "true")) { espRender(conn, "<form method='%s' " EDATA("remote") "='%s'%s >\r\n", method, uri, map(conn, options)); } else { espRender(conn, "<form method='%s' action='%s'%s >\r\n", method, uri, map(conn, options)); } if (recid) { espRender(conn, " <input name='recid' type='hidden' value='%s' />\r\n", recid); } if (!httpGetOption(options, "insecure", 0)) { if ((token = httpGetOption(options, "securityToken", 0)) == 0) { token = httpGetSecurityToken(conn, 0); } espRender(conn, " <input name='%s' type='hidden' value='%s' />\r\n", BIT_XSRF_PARAM, token); } }
/* Dump the file upload details. Don't actually do anything with the uploaded file. */ static void uploadTest(Webs *wp, char *path, char *query) { WebsKey *s; WebsUpload *up; char *upfile; websSetStatus(wp, 200); websWriteHeaders(wp, -1, 0); websWriteHeader(wp, "Content-Type", "text/plain"); websWriteEndHeaders(wp); if (scaselessmatch(wp->method, "POST")) { for (s = hashFirst(wp->files); s; s = hashNext(wp->files, s)) { up = s->content.value.symbol; websWrite(wp, "FILE: %s\r\n", s->name.value.string); websWrite(wp, "FILENAME=%s\r\n", up->filename); websWrite(wp, "CLIENT=%s\r\n", up->clientFilename); websWrite(wp, "TYPE=%s\r\n", up->contentType); websWrite(wp, "SIZE=%d\r\n", up->size); upfile = sfmt("%s/tmp/%s", websGetDocuments(), up->clientFilename); rename(up->filename, upfile); wfree(upfile); } websWrite(wp, "\r\nVARS:\r\n"); for (s = hashFirst(wp->vars); s; s = hashNext(wp->vars, s)) { websWrite(wp, "%s=%s\r\n", s->name.value.string, s->content.value.string); } } websDone(wp); }
static int prepRequest(HttpConn *conn, MprList *files, int retry) { MprKeyValue *header; char *seq; int next; httpPrepClientConn(conn, retry); for (next = 0; (header = mprGetNextItem(app->headers, &next)) != 0; ) { if (scaselessmatch(header->key, "User-Agent")) { httpSetHeader(conn, header->key, header->value); } else { httpAppendHeader(conn, header->key, header->value); } } if (app->text) { httpSetHeader(conn, "Accept", "text/plain"); } if (app->sequence) { static int next = 0; seq = itos(next++); httpSetHeader(conn, "X-Http-Seq", seq); } if (app->ranges) { httpSetHeader(conn, "Range", app->ranges); } if (app->formData) { httpSetHeader(conn, "Content-Type", "application/x-www-form-urlencoded"); } if (setContentLength(conn, files) < 0) { return MPR_ERR_CANT_OPEN; } return 0; }
/* Append a header. If already defined, the value is catenated to the pre-existing value after a ", " separator. As per the HTTP/1.1 spec. Except for Set-Cookie which HTTP permits multiple headers but not of the same cookie. Ugh! */ PUBLIC void httpAppendHeader(HttpConn *conn, cchar *key, cchar *fmt, ...) { va_list vargs; MprKey *kp; char *value; cchar *cookie; if (!conn->tx) { return; } assert(key && *key); assert(fmt && *fmt); va_start(vargs, fmt); value = sfmtv(fmt, vargs); va_end(vargs); /* HTTP permits Set-Cookie to have multiple cookies. Other headers must comma separate multiple values. For Set-Cookie, must allow duplicates but not of the same cookie. */ kp = mprLookupKeyEntry(conn->tx->headers, key); if (kp) { if (scaselessmatch(key, "Set-Cookie")) { cookie = stok(sclone(value), "=", NULL); while (kp) { if (scaselessmatch(kp->key, "Set-Cookie")) { if (sstarts(kp->data, cookie)) { kp->data = value; break; } } kp = kp->next; } if (!kp) { mprAddDuplicateKey(conn->tx->headers, key, value); } } else { addHdr(conn, key, sfmt("%s, %s", kp->data, value)); } } else { addHdr(conn, key, value); } }
/* IndexOptions FancyIndexing|FoldersFirst ... (set of options) */ static int indexOptionsDirective(MaState *state, cchar *key, cchar *value) { Dir *dir; char *option, *tok; dir = getDirObj(state); option = stok(sclone(value), " \t", &tok); while (option) { if (scaselessmatch(option, "FancyIndexing")) { dir->fancyIndexing = 1; } else if (scaselessmatch(option, "HTMLTable")) { dir->fancyIndexing = 2; } else if (scaselessmatch(option, "FoldersFirst")) { dir->foldersFirst = 1; } option = stok(tok, " \t", &tok); } return 0; }
/* checkbox field checkedValue -- Value for which the checkbox will be checked. Defaults to true. Example: checkbox("admin", "true") */ PUBLIC void espCheckbox(HttpConn *conn, cchar *field, cchar *checkedValue, cchar *optionString) { MprHash *options; cchar *value, *checked; options = httpGetOptions(optionString); value = getValue(conn, field, options); checked = scaselessmatch(value, checkedValue) ? " checked='yes'" : ""; espRender(conn, "<input name='%s' type='checkbox'%s%s value='%s' />\r\n", field, map(conn, options), checked, checkedValue); espRender(conn, " <input name='%s' type='hidden'%s value='' />", field, map(conn, options)); }
/* Options Indexes */ static int optionsDirective(MaState *state, cchar *key, cchar *value) { Dir *dir; char *option, *tok; dir = getDirObj(state); option = stok(sclone(value), " \t", &tok); while (option) { if (scaselessmatch(option, "Indexes")) { dir->enabled = 1; } option = stok(tok, " \t", &tok); } return 0; }
static void sessionTest(Webs *wp, char *path, char *query) { char *number; if (scaselessmatch(wp->method, "POST")) { number = websGetVar(wp, "number", 0); websSetSessionVar(wp, "number", number); } else { number = websGetSessionVar(wp, "number", 0); } websSetStatus(wp, 200); websWriteHeaders(wp, -1, 0); websWriteEndHeaders(wp); websWrite(wp, "<html><body><p>Number %s</p></body></html>\n", number); websDone(wp); }
/* IndexOrder ascending|descending name|date|size */ static int indexOrderDirective(MaState *state, cchar *key, cchar *value) { Dir *dir; char *option; dir = getDirObj(state); if (!maTokenize(state, value, "%S %S", &option, &dir->sortField)) { return MPR_ERR_BAD_SYNTAX; } dir->sortField = 0; if (scaselessmatch(option, "ascending")) { dir->sortOrder = 1; } else { dir->sortOrder = -1; } if (dir->sortField) { dir->sortField = sclone(dir->sortField); } return 0; }
/* Append a header string. If already defined, the value is catenated to the pre-existing value after a ", " separator. As per the HTTP/1.1 spec. */ PUBLIC void httpAppendHeaderString(HttpConn *conn, cchar *key, cchar *value) { cchar *oldValue; assert(key && *key); assert(value && *value); if (!conn->tx) { return; } oldValue = mprLookupKey(conn->tx->headers, key); if (oldValue) { if (scaselessmatch(key, "Set-Cookie")) { mprAddDuplicateKey(conn->tx->headers, key, sclone(value)); } else { addHdr(conn, key, sfmt("%s, %s", oldValue, value)); } } else { addHdr(conn, key, sclone(value)); } }
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; } } } } }