summaryrefslogtreecommitdiff
path: root/source4/web_server/esp
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2005-05-26 01:06:32 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:17:01 -0500
commitd70912a26af49db468af7ec88e9689b8176e0576 (patch)
treea52d8b9930fe23eaea47c40b0af34f324e45f854 /source4/web_server/esp
parente5613a3ce9932fb76aef9f721cadabe69bd23be8 (diff)
downloadsamba-d70912a26af49db468af7ec88e9689b8176e0576.tar.gz
samba-d70912a26af49db468af7ec88e9689b8176e0576.tar.bz2
samba-d70912a26af49db468af7ec88e9689b8176e0576.zip
r6981: first version of the builtin web server for Samba4
This includes an embedded server side scripting system called 'esp' (see http://www.appwebserver.org/products/esp/esp.html) and javascript based scripting language called 'esj' (see http://www.appwebserver.org/products/ejs/ejs.html) The justification for including this scripting language is that it should make it much easier to write a high quality web interface for Samba4. The scripting language can call into any Samba4 library code (so for example it will be able to make ldb and loadparm calls), plus it provides easy support for forms, cookies, sessions etc. There is still quite a bit more work to do on the web server, but there is enough here now for people to look at and comment. I will be committing some sample web pages that test esp functionality shortly. (This used to be commit 26f0ba92c0c565ac9e4cb5a079d795d4262497dd)
Diffstat (limited to 'source4/web_server/esp')
-rw-r--r--source4/web_server/esp/esp.c1042
-rw-r--r--source4/web_server/esp/esp.h279
-rw-r--r--source4/web_server/esp/espEnv.h128
-rw-r--r--source4/web_server/esp/espProcs.c230
4 files changed, 1679 insertions, 0 deletions
diff --git a/source4/web_server/esp/esp.c b/source4/web_server/esp/esp.c
new file mode 100644
index 0000000000..26c37385dd
--- /dev/null
+++ b/source4/web_server/esp/esp.c
@@ -0,0 +1,1042 @@
+/*
+ * @file esp.c
+ * @brief Embedded Server Pages (ESP) core processing.
+ * @overview The ESP handler provides an efficient way to generate
+ * dynamic pages using server-side Javascript. This code provides
+ * core processing, and should be called by an associated web
+ * server URL handler.
+ */
+/********************************* Copyright **********************************/
+/*
+ * @copy default
+ *
+ * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved.
+ *
+ * This software is distributed under commercial and open source licenses.
+ * You may use the GPL open source license described below or you may acquire
+ * a commercial license from Mbedthis Software. You agree to be fully bound
+ * by the terms of either license. Consult the LICENSE.TXT distributed with
+ * this software for full details.
+ *
+ * This software is open source; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See the GNU General Public License for more
+ * details at: http://www.mbedthis.com/downloads/gplLicense.html
+ *
+ * This program is distributed WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * This GPL license does NOT permit incorporating this software into
+ * proprietary programs. If you are unable to comply with the GPL, you must
+ * acquire a commercial license to use this software. Commercial licenses
+ * for this software and support services are available from Mbedthis
+ * Software at http://www.mbedthis.com
+ *
+ * @end
+ */
+/********************************** Includes **********************************/
+
+#include "esp.h"
+
+#if BLD_FEATURE_ESP_MODULE
+
+/*********************************** Locals ***********************************/
+/*
+ * Master ESP control interface with the web server
+ */
+
+static Esp *esp;
+
+/***************************** Forward Declarations ***************************/
+
+static int buildScript(EspRequest *ep, char **jsBuf, char *input, char
+ **errMsg);
+
+/************************************ Code ************************************/
+/*
+ * Called at server initialization
+ */
+
+int espOpen(Esp *control)
+{
+ mprAssert(control);
+
+#if BLD_FEATURE_MULTITHREAD
+ ejsOpen(control->lock, control->unlock, control->lockData);
+#else
+ ejsOpen(0, 0, 0);
+#endif
+
+ /*
+ * Register the standard procedures
+ */
+ espRegisterProcs();
+
+ /*
+ * Just for brain dead systems that don't zero global memory
+ */
+ esp = control;
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Called at server termination
+ */
+
+void espClose()
+{
+ ejsClose();
+}
+
+/******************************************************************************/
+/*
+ * Create for new ESP request. Assumed that this is called after all the
+ * HTTP headers have been read but before POST data has been read. It is
+ * expected that any session cookies have been read and that "variables"
+ * contains references to all the environment objects including "session".
+ * requestHandle is the web server request handle.
+ */
+
+EspRequest *espCreateRequest(EspHandle webServerRequestHandle, char *uri,
+ MprVar *variables)
+{
+ EspRequest *ep;
+ MprVar *global;
+#if BLD_FEATURE_LEGACY_API
+ MprVar *np;
+ char keyBuf[ESP_MAX_HEADER];
+ int i;
+#endif
+
+ mprAssert(variables);
+
+ ep = mprMalloc(sizeof(EspRequest));
+ if (ep == 0) {
+ return 0;
+ }
+ memset(ep, 0, sizeof(EspRequest));
+ ep->requestHandle = webServerRequestHandle;
+ ep->esp = esp;
+ ep->uri = mprStrdup(uri);
+ ep->docPath = 0;
+ ep->variables = variables;
+
+ /*
+ * The handle passed to ejsOpenEngine is passed to every C function
+ * called by JavaScript.
+ */
+ ep->eid = ejsOpenEngine((EjsHandle) ep, (EjsHandle) webServerRequestHandle);
+ if (ep->eid < 0) {
+ mprFree(ep);
+ return 0;
+ }
+
+ /*
+ * All these copies and SetProperties will only copy references
+ * They will increments the object ref counts.
+ */
+ mprCopyVar(&variables[ESP_GLOBAL_OBJ], ejsGetGlobalObject(ep->eid),
+ MPR_SHALLOW_COPY);
+ mprCopyVar(&variables[ESP_LOCAL_OBJ], ejsGetLocalObject(ep->eid),
+ MPR_SHALLOW_COPY);
+
+ global = &variables[ESP_GLOBAL_OBJ];
+ mprCreateProperty(global, "application", &variables[ESP_APPLICATION_OBJ]);
+ mprCreateProperty(global, "cookies", &variables[ESP_COOKIES_OBJ]);
+ mprCreateProperty(global, "files", &variables[ESP_FILES_OBJ]);
+ mprCreateProperty(global, "form", &variables[ESP_FORM_OBJ]);
+ mprCreateProperty(global, "headers", &variables[ESP_HEADERS_OBJ]);
+ mprCreateProperty(global, "request", &variables[ESP_REQUEST_OBJ]);
+
+ //
+ // FUTURE -- could server be shared across all requests for a given host
+ // and be made read-only.
+ //
+ mprCreateProperty(global, "server", &variables[ESP_SERVER_OBJ]);
+
+#if BLD_FEATURE_SESSION
+ mprCreateProperty(global, "session", &variables[ESP_SESSION_OBJ]);
+#endif
+
+#if BLD_FEATURE_LEGACY_API
+ /*
+ * DEPRECATED: 2.0
+ * Define variables as globals. headers[] are prefixed with "HTTP_".
+ * NOTE: MaRequest::setVar does not copy into globals, whereas espSetVar
+ * does if legacy_api is defined. So variables pre-defined by MaRequest
+ * must be copied here into globals[].
+ *
+ * NOTE: if a variable is in session[] and in form[], the form[] will
+ * override being later in the variables[] list. Use mprSetProperty
+ * instead of mprCreateProperty to cover for this case.
+ */
+ for (i = 0; i < ESP_OBJ_MAX; i++) {
+ if (i == ESP_GLOBAL_OBJ || i == ESP_LOCAL_OBJ) {
+ continue;
+ }
+ if (variables[i].type != MPR_TYPE_OBJECT) {
+ continue;
+ }
+ np = mprGetFirstProperty(&variables[i], MPR_ENUM_DATA);
+ while (np) {
+ if (i == ESP_HEADERS_OBJ) {
+ mprSprintf(keyBuf, sizeof(keyBuf) - 1, "HTTP_%s", np->name);
+ mprSetProperty(global, keyBuf, np);
+ } else {
+ mprSetProperty(global, np->name, np);
+ }
+ np = mprGetNextProperty(&variables[i], np, MPR_ENUM_DATA);
+ }
+ }
+#endif
+ return ep;
+}
+
+/******************************************************************************/
+
+void espDestroyRequest(EspRequest *ep)
+{
+ mprAssert(ep);
+ mprAssert(ep->eid >= 0);
+
+ mprFree(ep->uri);
+ mprFree(ep->docPath);
+ ejsCloseEngine(ep->eid);
+ mprFree(ep);
+}
+
+/******************************************************************************/
+/*
+ * The callback function will be called:
+ *
+ * (fn)(EjsId eid, EspRequest *ep, argc, argv);
+ *
+ * Callers can get their web server handle by calling:
+ *
+ * rq = (requiredCast) espGetHandle(ep);
+ */
+
+void espDefineCFunction(EspRequest *ep, char *functionName, EspCFunction fn,
+ void *thisPtr)
+{
+ mprAssert(functionName && *functionName);
+ mprAssert(fn);
+
+ if (ep) {
+ ejsDefineCFunction(ep->eid, functionName, (MprCFunction) fn,
+ thisPtr, 0);
+ } else {
+ ejsDefineCFunction(-1, functionName, (MprCFunction) fn, thisPtr, 0);
+ }
+}
+
+/******************************************************************************/
+
+void espDefineStringCFunction(EspRequest *ep, const char *functionName,
+ EspStringCFunction fn, void *thisPtr)
+{
+ mprAssert(functionName && *functionName);
+ mprAssert(fn);
+
+ if (ep) {
+ ejsDefineStringCFunction(ep->eid, functionName, (MprStringCFunction) fn,
+ thisPtr, 0);
+ } else {
+ ejsDefineStringCFunction(-1, functionName, (MprStringCFunction) fn,
+ thisPtr, 0);
+ }
+}
+
+/******************************************************************************/
+
+void *espGetRequestHandle(EspRequest *ep)
+{
+ return ep->requestHandle;
+}
+
+/******************************************************************************/
+
+EjsId espGetScriptHandle(EspRequest *ep)
+{
+ return ep->eid;
+}
+
+/******************************************************************************/
+
+char *espGetStringVar(EspRequest *ep, EspEnvType oType, char *var,
+ char *defaultValue)
+{
+ MprVar value;
+
+ if (espGetVar(ep, oType, var, &value) < 0 ||
+ value.type != MPR_TYPE_STRING) {
+ return defaultValue;
+ }
+ return value.string;
+}
+
+/******************************************************************************/
+
+int espGetVar(EspRequest *ep, EspEnvType oType, char *var, MprVar *value)
+{
+ MprVar *vp;
+
+ mprAssert(ep);
+ mprAssert(var);
+
+ vp = mprGetProperty(&ep->variables[oType], var, 0);
+ if (vp == 0) {
+ return -1;
+ }
+ *value = *vp;
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Process the ESP page. docBuf holds the page already. We expect that
+ * ep->variables holds all the pertinent environment variables.
+ */
+
+int espProcessRequest(EspRequest *ep, const char *docPath, char *docBuf,
+ char **errMsg)
+{
+ char *jsBuf;
+
+ mprAssert(ep);
+
+ ep->docPath = mprStrdup(docPath);
+
+ jsBuf = 0;
+ if (buildScript(ep, &jsBuf, docBuf, errMsg) < 0) {
+ return MPR_ERR_CANT_COMPLETE;
+ }
+
+ if (jsBuf) {
+ mprLog(7, "esp: script is:\n%s\n", jsBuf);
+
+ /*
+ * Now evaluate the entire escript
+ * MOB could cache the script
+ */
+ if (ejsEvalScript(ep->eid, jsBuf, 0, errMsg) < 0) {
+ return MPR_ERR_ABORTED;
+ }
+
+ mprFree(jsBuf);
+ }
+ return 0;
+}
+
+/******************************************************************************/
+
+void espRedirect(EspRequest *ep, int code, char *url)
+{
+ mprAssert(ep);
+ mprAssert(url);
+
+ ep->esp->redirect(ep->requestHandle, code, url);
+}
+
+/******************************************************************************/
+
+void espError(EspRequest *ep, const char *fmt, ...)
+{
+ va_list args;
+ char *buf;
+
+ mprAssert(ep);
+ mprAssert(fmt);
+
+ va_start(args, fmt);
+ mprAllocVsprintf(&buf, MPR_MAX_HEAP_SIZE, fmt, args);
+ ejsSetErrorMsg(ep->eid, buf);
+ mprFree(buf);
+ va_end(args);
+}
+
+/******************************************************************************/
+
+void espSetHeader(EspRequest *ep, char *header, bool allowMultiple)
+{
+ mprAssert(ep);
+
+ ep->esp->setHeader(ep->requestHandle, header, allowMultiple);
+}
+
+/******************************************************************************/
+/*
+ * Caller does not need to destroy the var
+ */
+
+MprVar *espGetResult(EspRequest *ep)
+{
+ mprAssert(ep);
+
+ return ejsGetReturnValue(ep->eid);
+}
+
+/******************************************************************************/
+
+void espSetReturn(EspRequest *ep, MprVar value)
+{
+ mprAssert(ep);
+
+ ejsSetReturnValue(ep->eid, value);
+}
+
+/******************************************************************************/
+
+void espSetReturnString(EspRequest *ep, char *str)
+{
+ mprAssert(ep);
+
+ ejsSetReturnValue(ep->eid, mprCreateStringVar(str, 0));
+}
+
+/******************************************************************************/
+
+void espSetResponseCode(EspRequest *ep, int code)
+{
+ mprAssert(ep);
+
+ ep->esp->setResponseCode(ep->requestHandle, code);
+}
+
+/******************************************************************************/
+
+void espSetVar(EspRequest *ep, EspEnvType oType, char *var, MprVar value)
+{
+ mprCreatePropertyValue(&ep->variables[oType], var, value);
+}
+
+/******************************************************************************/
+
+void espSetStringVar(EspRequest *ep, EspEnvType oType,
+ const char *var, const char *value)
+{
+ /*
+ * Will create or update if already existing
+ */
+ mprCreatePropertyValue(&ep->variables[oType], var,
+ mprCreateStringVar(value, 0));
+}
+
+/******************************************************************************/
+
+int espUnsetVar(EspRequest *ep, EspEnvType oType, char *var)
+{
+ return mprDeleteProperty(&ep->variables[oType], var);
+}
+
+/******************************************************************************/
+
+int espWrite(EspRequest *ep, char *buf, int size)
+{
+ mprAssert(ep);
+ mprAssert(buf);
+ mprAssert(size >= 0);
+
+ return ep->esp->writeBlock(ep->requestHandle, buf, size);
+}
+
+/******************************************************************************/
+
+int espWriteString(EspRequest *ep, char *buf)
+{
+ mprAssert(ep);
+ mprAssert(buf);
+
+ return ep->esp->writeBlock(ep->requestHandle, buf, strlen(buf));
+}
+
+/******************************************************************************/
+
+int espWriteFmt(EspRequest *ep, char *fmt, ...)
+{
+ va_list args;
+ char *buf;
+ int rc, len;
+
+ mprAssert(ep);
+ mprAssert(fmt);
+
+ va_start(args, fmt);
+ len = mprAllocVsprintf(&buf, MPR_MAX_HEAP_SIZE, fmt, args);
+ rc = ep->esp->writeBlock(ep->requestHandle, buf, len);
+ mprFree(buf);
+ va_end(args);
+ return rc;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+/******************************************************************************/
+/*
+ * Get a javascript identifier. Must allow x.y['abc'] or x.y["abc"].
+ * Must be careful about quoting and only allow quotes inside [].
+ */
+
+static int getIdentifier(EspParse *parse)
+{
+ int atQuote, prevC, c;
+
+ mprAssert(parse);
+
+ atQuote = 0;
+ prevC = 0;
+ c = *parse->inp++;
+
+ while (isalnum(c) || c == '_' || c == '.' || c == '[' ||
+ c == ']' || c == '\'' || c == '\"') {
+ if (c == '\'' || c == '\"') {
+ if (c == atQuote) {
+ atQuote = 0;
+ } else if (prevC == '[') {
+ atQuote = c;
+ } else {
+ break;
+ }
+ }
+ if (parse->tokp >= parse->endp) {
+ parse->token = (char*) mprRealloc(parse->token,
+ parse->tokLen + ESP_TOK_INCR);
+ if (parse->token == 0) {
+ return MPR_ERR_CANT_ALLOCATE;
+ }
+ parse->token[parse->tokLen] = '\0';
+ parse->tokLen += ESP_TOK_INCR;
+ parse->endp = &parse->token[parse->tokLen - 1];
+ }
+ *parse->tokp++ = c;
+ prevC = c;
+ c = *parse->inp++;
+ }
+
+ parse->inp--;
+ *parse->tokp = '\0';
+
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Get the next ESP input token. input points to the next input token.
+ * parse->token will hold the parsed token. The function returns the token id.
+ */
+
+static int getEspToken(int state, EspParse *parse)
+{
+ char *cp;
+ int tid, done, c, quoted;
+
+ tid = ESP_TOK_LITERAL;
+ parse->tokp = parse->token;
+ parse->tokp[0] = '\0';
+ quoted = 0;
+
+ c = *parse->inp++;
+ for (done = 0; !done; c = *parse->inp++) {
+
+ /*
+ * Get room for more characters in the token buffer
+ */
+ if (parse->tokp >= parse->endp) {
+ parse->token = (char*) mprRealloc(parse->token,
+ parse->tokLen + ESP_TOK_INCR);
+ if (parse->token == 0) {
+ return ESP_TOK_ERR;
+ }
+ parse->token[parse->tokLen] = '\0';
+ parse->tokp = &parse->token[parse->tokLen - 1];
+ parse->tokLen += ESP_TOK_INCR;
+ parse->endp = &parse->token[parse->tokLen - 1];
+ }
+
+ switch (c) {
+ case 0:
+ if (*parse->token) {
+ done++;
+ parse->inp--;
+ break;
+ }
+ return ESP_TOK_EOF;
+
+ default:
+ if (c == '\"' && state != ESP_STATE_IN_ESP_TAG) {
+ *parse->tokp++ = '\\';
+ }
+ *parse->tokp++ = c;
+ quoted = 0;
+ break;
+
+ case '\\':
+ quoted = 1;
+ *parse->tokp++ = c;
+ break;
+
+ case '@':
+ if (*parse->inp == '@' && state != ESP_STATE_IN_ESP_TAG) {
+ if (quoted) {
+ parse->tokp--;
+ quoted = 0;
+ } else {
+ if (*parse->token) {
+ parse->inp--;
+ } else {
+ parse->inp++;
+ tid = ESP_TOK_ATAT;
+ if (getIdentifier(parse) < 0) {
+ return ESP_TOK_ERR;
+ }
+ }
+ done++;
+ break;
+ }
+ }
+ *parse->tokp++ = c;
+ break;
+
+ case '<':
+ if (*parse->inp == '%' && state != ESP_STATE_IN_ESP_TAG) {
+ if (quoted) {
+ parse->tokp--;
+ quoted = 0;
+ *parse->tokp++ = c;
+ break;
+ }
+ if (*parse->token) {
+ parse->inp--;
+ done++;
+ break;
+ }
+ parse->inp++;
+ while (isspace((int) *parse->inp)) {
+ parse->inp++;
+ }
+ if (*parse->inp == '=') {
+ parse->inp++;
+ while (isspace((int) *parse->inp)) {
+ parse->inp++;
+ }
+ tid = ESP_TOK_EQUALS;
+ if (getIdentifier(parse) < 0) {
+ return ESP_TOK_ERR;
+ }
+ done++;
+ break;
+ }
+ if (*parse->inp == 'i' &&
+ strncmp(parse->inp, "include", 7) == 0 &&
+ isspace((int) parse->inp[7])) {
+ tid = ESP_TOK_INCLUDE;
+ parse->inp += 7;
+ while (isspace((int) *parse->inp)) {
+ parse->inp++;
+ }
+ while (*parse->inp && !isspace((int) *parse->inp) &&
+ *parse->inp != '%' && parse->tokp < parse->endp) {
+ *parse->tokp++ = *parse->inp++;
+ }
+ *parse->tokp = '\0';
+ if (parse->token[0] == '"') {
+ parse->tokp = parse->token;
+ for (cp = &parse->token[1]; *cp; ) {
+ *parse->tokp++ = *cp++;
+ }
+ if (cp[-1] == '"') {
+ parse->tokp--;
+ }
+ *parse->tokp = '\0';
+ }
+
+ } else {
+ tid = ESP_TOK_START_ESP;
+ }
+ done++;
+ break;
+ }
+ *parse->tokp++ = c;
+ break;
+
+ case '%':
+ if (*parse->inp == '>' && state == ESP_STATE_IN_ESP_TAG) {
+ if (quoted) {
+ parse->tokp--;
+ quoted = 0;
+ } else {
+ if (*parse->token) {
+ parse->inp--;
+ } else {
+ tid = ESP_TOK_END_ESP;
+ parse->inp++;
+ }
+ done++;
+ break;
+ }
+ }
+ *parse->tokp++ = c;
+ break;
+ }
+ }
+
+ *parse->tokp = '\0';
+ parse->inp--;
+ return tid;
+}
+
+/******************************************************************************/
+/*
+ * Convert an ESP page into a JavaScript. We also expand include files.
+ */
+
+static int buildScript(EspRequest *ep, char **jsBuf, char *input, char **errMsg)
+{
+ EspParse parse;
+ char path[MPR_MAX_FNAME], dir[MPR_MAX_FNAME], incPath[MPR_MAX_FNAME];
+ char *incBuf, *incText;
+ int state, tid, len, rc, maxScriptSize, incSize;
+
+ mprAssert(ep);
+ mprAssert(jsBuf);
+ mprAssert(input);
+
+ rc = 0;
+ len = 0;
+ state = ESP_STATE_BEGIN;
+ if (errMsg) {
+ *errMsg = 0;
+ }
+
+ memset(&parse, 0, sizeof(parse));
+ parse.token = (char*) mprMalloc(ESP_TOK_INCR);
+ if (parse.token == 0) {
+ return MPR_ERR_CANT_ALLOCATE;
+ }
+ parse.token[0] = '\0';
+ parse.tokLen = ESP_TOK_INCR;
+ parse.endp = &parse.token[parse.tokLen - 1];
+ parse.tokp = parse.token;
+ parse.inBuf = input;
+ parse.inp = parse.inBuf;
+
+ maxScriptSize = esp->maxScriptSize;
+
+ tid = getEspToken(state, &parse);
+ while (tid != ESP_TOK_EOF && len >= 0) {
+
+ switch (tid) {
+ default:
+ case ESP_TOK_ERR:
+ mprFree(parse.token);
+ return MPR_ERR_BAD_SYNTAX;
+
+ case ESP_TOK_LITERAL:
+ len = mprReallocStrcat(jsBuf, maxScriptSize, len, 0,
+ "write(\"", parse.token, "\");\n", 0);
+ break;
+
+ case ESP_TOK_ATAT:
+ /*
+ * Trick to get undefined variables to evaluate to "".
+ * Catenate with "" to cause toString to run.
+ */
+ len = mprReallocStrcat(jsBuf, maxScriptSize, len, 0,
+ "write(\"\" + ", parse.token, ");\n", 0);
+ break;
+
+ case ESP_TOK_EQUALS:
+ len = mprReallocStrcat(jsBuf, maxScriptSize, len, 0,
+ "write(\"\" + ", parse.token, ");\n", 0);
+ state = ESP_STATE_IN_ESP_TAG;
+ break;
+
+ case ESP_TOK_START_ESP:
+ state = ESP_STATE_IN_ESP_TAG;
+ tid = getEspToken(state, &parse);
+ while (tid != ESP_TOK_EOF && tid != ESP_TOK_EOF &&
+ tid != ESP_TOK_END_ESP && len >= 0) {
+ len = mprReallocStrcat(jsBuf, maxScriptSize, len, 0,
+ parse.token, 0);
+ tid = getEspToken(state, &parse);
+ }
+ state = ESP_STATE_BEGIN;
+ break;
+
+ case ESP_TOK_END_ESP:
+ state = ESP_STATE_BEGIN;
+ break;
+
+ case ESP_TOK_INCLUDE:
+ if (parse.token[0] == '/') {
+ mprStrcpy(incPath, sizeof(incPath), parse.token);
+ } else {
+ mprGetDirName(dir, sizeof(dir), ep->uri);
+ mprSprintf(incPath, sizeof(incPath), "%s/%s",
+ dir, parse.token);
+ }
+ if (esp->mapToStorage(ep->requestHandle, path, sizeof(path),
+ incPath, 0) < 0) {
+ mprAllocSprintf(errMsg, MPR_MAX_STRING,
+ "Can't find include file: %s", path);
+ rc = MPR_ERR_CANT_OPEN;
+ break;
+ }
+ if (esp->readFile(ep->requestHandle, &incText, &incSize, path) < 0){
+ mprAllocSprintf(errMsg, MPR_MAX_STRING,
+ "Can't read include file: %s", path);
+ rc = MPR_ERR_CANT_READ;
+ break;
+ }
+ incText[incSize] = '\0';
+
+ /*
+ * Recurse and process the include script
+ */
+ incBuf = 0;
+ if ((rc = buildScript(ep, &incBuf, incText, errMsg)) < 0) {
+ mprFree(incText);
+ mprFree(parse.token);
+ return rc;
+ }
+
+ len = mprReallocStrcat(jsBuf, maxScriptSize, len, 0, incBuf, 0);
+ mprFree(incText);
+ mprFree(incBuf);
+ state = ESP_STATE_IN_ESP_TAG;
+ break;
+ }
+ tid = getEspToken(state, &parse);
+ }
+ mprFree(parse.token);
+ if (len < 0) {
+ mprAllocSprintf(errMsg, MPR_MAX_STRING,
+ "Script token is too big in %s.\nConfigured maximum is %d.",
+ path, maxScriptSize);
+ return MPR_ERR_WONT_FIT;
+ }
+ return rc;
+}
+
+/******************************************************************************/
+/******************************* Wrapped Routines *****************************/
+/******************************************************************************/
+
+int espCopyVar(EspRequest *ep, char *var, MprVar *value, int copyDepth)
+{
+ return ejsCopyVar(ep->eid, var, value, copyDepth);
+}
+
+/******************************************************************************/
+
+MprVar espCreateObjVar(char *name, int hashSize)
+{
+ return ejsCreateObj(name, hashSize);
+}
+
+/******************************************************************************/
+
+MprVar espCreateArrayVar(char *name, int size)
+{
+ return ejsCreateArray(name, size);
+}
+
+/******************************************************************************/
+
+bool espDestroyVar(MprVar *obj)
+{
+ return ejsDestroyVar(obj);
+}
+
+/******************************************************************************/
+
+MprVar *espCreateProperty(MprVar *obj, char *property, MprVar *newValue)
+{
+ return mprCreateProperty(obj, property, newValue);
+}
+
+/******************************************************************************/
+
+MprVar *espCreatePropertyValue(MprVar *obj, char *property, MprVar newValue)
+{
+ return mprCreatePropertyValue(obj, property, newValue);
+}
+
+/******************************************************************************/
+
+void espDefineFunction(EspRequest *ep, char *functionName, char *args, char *body)
+{
+ ejsDefineFunction(ep->eid, functionName, args, body);
+}
+
+/******************************************************************************/
+
+int espDeleteProperty(MprVar *obj, char *property)
+{
+ return mprDeleteProperty(obj, property);
+}
+
+/******************************************************************************/
+
+int espDeleteVar(EspRequest *ep, char *var)
+{
+ return ejsDeleteVar(ep->eid, var);
+}
+
+/******************************************************************************/
+int espEvalFile(EspRequest *ep, char *path, MprVar *result, char **emsg)
+{
+ return ejsEvalFile(ep->eid, path, result, emsg);
+}
+
+/******************************************************************************/
+
+int espEvalScript(EspRequest *ep, char *script, MprVar *result, char **emsg)
+{
+ return ejsEvalScript(ep->eid, script, result, emsg);
+}
+
+/******************************************************************************/
+
+int espGetPropertyCount(MprVar *obj, int includeFlags)
+{
+ if (obj->type != MPR_TYPE_OBJECT) {
+ return MPR_ERR_BAD_STATE;
+ }
+ return mprGetPropertyCount(obj, includeFlags);
+}
+
+/******************************************************************************/
+
+MprVar *espGetFirstProperty(MprVar *obj, int includeFlags)
+{
+ return mprGetFirstProperty(obj, includeFlags);
+}
+
+/******************************************************************************/
+
+MprVar *espGetGlobalObject(EspRequest *ep)
+{
+ return ejsGetGlobalObject(ep->eid);
+}
+
+/******************************************************************************/
+
+MprVar *espGetLocalObject(EspRequest *ep)
+{
+ return ejsGetLocalObject(ep->eid);
+}
+
+/******************************************************************************/
+
+MprVar *espGetNextProperty(MprVar *obj, MprVar *currentProperty,
+ int includeFlags)
+{
+ return mprGetNextProperty(obj, currentProperty, includeFlags);
+}
+
+/******************************************************************************/
+
+MprVar *espGetProperty(MprVar *obj, char *property, MprVar *value)
+{
+ return mprGetProperty(obj, property, value);
+}
+
+/******************************************************************************/
+
+void *espGetThisPtr(EspRequest *ep)
+{
+ return ejsGetThisPtr(ep->eid);
+}
+
+/******************************************************************************/
+#if UNUSED
+
+int espReadProperty(MprVar *dest, MprVar *prop)
+{
+ mprAssert(prop);
+ mprAssert(dest);
+
+ *dest = *prop;
+ return 0;
+}
+
+#endif
+/******************************************************************************/
+
+int espReadVar(EspRequest *ep, char *var, MprVar *value)
+{
+ return ejsReadVar(ep->eid, var, value);
+}
+
+/******************************************************************************/
+
+int espRunFunction(EspRequest *ep, MprVar *obj, char *functionName,
+ MprArray *args)
+{
+ return ejsRunFunction(ep->eid, obj, functionName, args);
+}
+
+/******************************************************************************/
+
+MprVar *espSetProperty(MprVar *obj, char *property, MprVar *newValue)
+{
+ return mprSetProperty(obj, property, newValue);
+}
+
+/******************************************************************************/
+
+MprVar *espSetPropertyValue(MprVar *obj, char *property, MprVar newValue)
+{
+ return mprSetPropertyValue(obj, property, newValue);
+}
+
+/******************************************************************************/
+
+int espWriteVar(EspRequest *ep, char *var, MprVar *value)
+{
+ return ejsWriteVar(ep->eid, var, value);
+}
+
+/******************************************************************************/
+
+int espWriteVarValue(EspRequest *ep, char *var, MprVar value)
+{
+ return ejsWriteVarValue(ep->eid, var, value);
+}
+
+/******************************************************************************/
+#if UNUSED
+
+int espWriteProperty(MprVar *prop, MprVar *newValue)
+{
+ return mprWriteProperty(prop, newValue);
+}
+
+/******************************************************************************/
+
+int espWritePropertyValue(MprVar *prop, MprVar newValue)
+{
+ return mprWritePropertyValue(prop, newValue);
+}
+
+#endif
+/******************************************************************************/
+
+#else /* !BLD_FEATURE_ESP_MODULE */
+void espDummy() {}
+
+/******************************************************************************/
+#endif /* BLD_FEATURE_ESP_MODULE */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim:tw=78
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
+ */
diff --git a/source4/web_server/esp/esp.h b/source4/web_server/esp/esp.h
new file mode 100644
index 0000000000..33ab9d7ac9
--- /dev/null
+++ b/source4/web_server/esp/esp.h
@@ -0,0 +1,279 @@
+/**
+ * @file esp.h
+ * @brief Header for Embedded Server Pages (ESP)
+ */
+/********************************* Copyright **********************************/
+/*
+ * @copy default
+ *
+ * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved.
+ *
+ * This software is distributed under commercial and open source licenses.
+ * You may use the GPL open source license described below or you may acquire
+ * a commercial license from Mbedthis Software. You agree to be fully bound
+ * by the terms of either license. Consult the LICENSE.TXT distributed with
+ * this software for full details.
+ *
+ * This software is open source; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See the GNU General Public License for more
+ * details at: http://www.mbedthis.com/downloads/gplLicense.html
+ *
+ * This program is distributed WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * This GPL license does NOT permit incorporating this software into
+ * proprietary programs. If you are unable to comply with the GPL, you must
+ * acquire a commercial license to use this software. Commercial licenses
+ * for this software and support services are available from Mbedthis
+ * Software at http://www.mbedthis.com
+ *
+ * @end
+ */
+/********************************** Includes **********************************/
+
+#ifndef _h_ESP_h
+#define _h_ESP_h 1
+
+#include "web_server/ejs/ejs.h"
+#include "web_server/esp/espEnv.h"
+#include "web_server/ejs/var.h"
+#include "web_server/ejs/miniMpr.h"
+
+/*********************************** Defines **********************************/
+
+#define ESP_STRING_ARGS MPR_TYPE_STRING_ARGS
+
+#if BLD_FEATURE_SQUEEZE
+#define ESP_TOK_INCR 1024
+#define ESP_MAX_HEADER 1024
+#else
+#define ESP_TOK_INCR 4096
+#define ESP_MAX_HEADER 4096
+#endif
+
+/*
+ * ESP lexical analyser tokens
+ */
+#define ESP_TOK_ERR -1 /* Any input error */
+#define ESP_TOK_EOF 0 /* End of file */
+#define ESP_TOK_START_ESP 1 /* <% */
+#define ESP_TOK_END_ESP 2 /* %> */
+#define ESP_TOK_ATAT 3 /* @@var */
+#define ESP_TOK_LITERAL 4 /* literal HTML */
+#define ESP_TOK_INCLUDE 5 /* include file.esp */
+#define ESP_TOK_EQUALS 6 /* = var */
+
+/*
+ * ESP parser states
+ */
+#define ESP_STATE_BEGIN 1 /* Starting state */
+#define ESP_STATE_IN_ESP_TAG 2 /* Inside a <% %> group */
+
+/*********************************** Types ************************************/
+
+typedef void* EspHandle; /* Opaque Web server handle type */
+
+/*
+ * Per request control block
+ */
+typedef struct EspRequest {
+ MprStr docPath; /* Physical path for ESP page */
+ EjsId eid; /* EJS instance handle */
+ struct Esp *esp; /* Pointer to ESP control block */
+ EspHandle requestHandle; /* Per request web server handle */
+ MprStr uri; /* Request URI */
+ MprVar *variables; /* Pointer to variables */
+} EspRequest;
+
+/*
+ * Master ESP control block. This defines the function callbacks for a
+ * web server handler to implement. ESP will call these functions as
+ * required.
+ */
+typedef struct Esp {
+ int maxScriptSize;
+ void (*createSession)(EspHandle handle, int timeout);
+ void (*destroySession)(EspHandle handle);
+ char *(*getSessionId)(EspHandle handle);
+ int (*mapToStorage)(EspHandle handle, char *path, int len, char *uri,
+ int flags);
+ int (*readFile)(EspHandle handle, char **buf, int *len, char *path);
+ void (*redirect)(EspHandle handle, int code, char *url);
+ void (*setCookie)(EspHandle handle, char *name, char *value,
+ int lifetime, char *path, bool secure);
+ void (*setHeader)(EspHandle handle, const char *value, bool allowMultiple);
+ void (*setResponseCode)(EspHandle handle, int code);
+ int (*writeBlock)(EspHandle handle, char *buf, int size);
+ int (*writeFmt)(EspHandle handle, char *fmt, ...);
+#if BLD_FEATURE_MULTITHREAD
+ void (*lock)(void *lockData);
+ void (*unlock)(void *lockData);
+ void *lockData;
+#endif
+} Esp;
+
+
+/*
+ * ESP parse context
+ */
+typedef struct {
+ char *inBuf; /* Input data to parse */
+ char *inp; /* Next character for input */
+ char *endp; /* End of storage (allow for null) */
+ char *tokp; /* Pointer to current parsed token */
+ char *token; /* Storage buffer for token */
+ int tokLen; /* Length of buffer */
+} EspParse;
+
+
+/******************************** Private APIs ********************************/
+
+extern void espRegisterProcs(void);
+
+/******************************** Published API *******************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Function callback signatures
+ */
+typedef int (*EspCFunction)(EspRequest *ep, int argc,
+ struct MprVar **argv);
+typedef int (*EspStringCFunction)(EspRequest *ep, int argc,
+ char **argv);
+
+/*
+ * APIs for those hosting the ESP module
+ */
+extern int espOpen(Esp *control);
+extern void espClose(void);
+extern EspRequest *espCreateRequest(EspHandle webServerRequestHandle,
+ char *uri, MprVar *envObj);
+extern void espDestroyRequest(EspRequest *ep);
+extern int espProcessRequest(EspRequest *ep, const char *docPath,
+ char *docBuf, char **errMsg);
+
+/*
+ * Method invocation
+ */
+extern void espDefineCFunction(EspRequest *ep, char *functionName,
+ EspCFunction fn, void *thisPtr);
+extern void espDefineFunction(EspRequest *ep, char *functionName,
+ char *args, char *body);
+extern void espDefineStringCFunction(EspRequest *ep,
+ const char *functionName, EspStringCFunction fn,
+ void *thisPtr);
+extern int espRunFunction(EspRequest *ep, MprVar *obj,
+ char *functionName, MprArray *args);
+extern void espSetResponseCode(EspRequest *ep, int code);
+extern void espSetReturn(EspRequest *ep, MprVar value);
+extern void *espGetThisPtr(EspRequest *ep);
+
+/*
+ * Utility routines to use in C methods
+ */
+extern void espError(EspRequest *ep, const char *fmt, ...);
+extern int espEvalFile(EspRequest *ep, char *path, MprVar *result,
+ char **emsg);
+extern int espEvalScript(EspRequest *ep, char *script, MprVar *result,
+ char **emsg);
+extern MprVar *espGetLocalObject(EspRequest *ep);
+extern MprVar *espGetGlobalObject(EspRequest *ep);
+extern EspHandle espGetRequestHandle(EspRequest *ep);
+extern MprVar *espGetResult(EspRequest *ep);
+extern EjsId espGetScriptHandle(EspRequest *ep);
+extern void espRedirect(EspRequest *ep, int code, char *url);
+extern void espSetHeader(EspRequest *ep, char *header,
+ bool allowMultiple);
+extern void espSetReturnString(EspRequest *ep, char *str);
+extern int espWrite(EspRequest *ep, char *buf, int size);
+extern int espWriteString(EspRequest *ep, char *buf);
+extern int espWriteFmt(EspRequest *ep, char *fmt, ...);
+
+/*
+ * ESP array[] variable access (set will update/create)
+ */
+extern int espGetVar(EspRequest *ep, EspEnvType oType, char *var,
+ MprVar *value);
+extern char *espGetStringVar(EspRequest *ep, EspEnvType oType,
+ char *var, char *defaultValue);
+extern void espSetVar(EspRequest *ep, EspEnvType oType, char *var,
+ MprVar value);
+extern void espSetStringVar(EspRequest *ep, EspEnvType oType,
+ const char *var, const char *value);
+extern int espUnsetVar(EspRequest *ep, EspEnvType oType, char *var);
+
+/*
+ * Object creation and management
+ */
+extern MprVar espCreateObjVar(char *name, int hashSize);
+extern MprVar espCreateArrayVar(char *name, int size);
+extern bool espDestroyVar(MprVar *var);
+extern MprVar *espCreateProperty(MprVar *obj, char *property,
+ MprVar *newValue);
+extern MprVar *espCreatePropertyValue(MprVar *obj, char *property,
+ MprVar newValue);
+extern int espDeleteProperty(MprVar *obj, char *property);
+
+/*
+ * JavaScript variable management. Set will create/update a property.
+ * All return a property reference. GetProperty will optionally return the
+ * property in value.
+ */
+extern MprVar *espGetProperty(MprVar *obj, char *property,
+ MprVar *value);
+extern MprVar *espSetProperty(MprVar *obj, char *property,
+ MprVar *newValue);
+extern MprVar *espSetPropertyValue(MprVar *obj, char *property,
+ MprVar newValue);
+
+#if 0
+/*
+ * Low-level direct read and write of properties.
+ * FUTURE: -- Read is not (dest, src). MUST WARN IN DOC ABOUT COPY/READ
+ * Will still cause triggers to run.
+ */
+extern int espReadProperty(MprVar *dest, MprVar *prop);
+extern int espWriteProperty(MprVar *prop, MprVar *newValue);
+extern int espWritePropertyValue(MprVar *prop, MprVar newValue);
+#endif
+
+
+/*
+ * Access JavaScript variables by their full name. Can use "." or "[]". For
+ * example: "global.request['REQUEST_URI']"
+ * For Read/write, the variables must exist.
+ */
+extern int espCopyVar(EspRequest *ep, char *var, MprVar *value,
+ int copyDepth);
+extern int espDeleteVar(EspRequest *ep, char *var);
+extern int espReadVar(EspRequest *ep, char *var, MprVar *value);
+extern int espWriteVar(EspRequest *ep, char *var, MprVar *value);
+extern int espWriteVarValue(EspRequest *ep, char *var, MprVar value);
+
+/*
+ * Object property enumeration
+ */
+extern MprVar *espGetFirstProperty(MprVar *obj, int includeFlags);
+extern MprVar *espGetNextProperty(MprVar *obj, MprVar *currentProperty,
+ int includeFlags);
+extern int espGetPropertyCount(MprVar *obj, int includeFlags);
+
+#ifdef __cplusplus
+}
+#endif
+/******************************************************************************/
+#endif /* _h_ESP_h */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim:tw=78
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
+ */
diff --git a/source4/web_server/esp/espEnv.h b/source4/web_server/esp/espEnv.h
new file mode 100644
index 0000000000..a3c9d9f5c7
--- /dev/null
+++ b/source4/web_server/esp/espEnv.h
@@ -0,0 +1,128 @@
+/*
+ * @file espEnv.h
+ * @brief ESP Environment Variables
+ */
+/********************************* Copyright **********************************/
+/*
+ * @copy default
+ *
+ * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved.
+ *
+ * This software is distributed under commercial and open source licenses.
+ * You may use the GPL open source license described below or you may acquire
+ * a commercial license from Mbedthis Software. You agree to be fully bound
+ * by the terms of either license. Consult the LICENSE.TXT distributed with
+ * this software for full details.
+ *
+ * This software is open source; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See the GNU General Public License for more
+ * details at: http://www.mbedthis.com/downloads/gplLicense.html
+ *
+ * This program is distributed WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * This GPL license does NOT permit incorporating this software into
+ * proprietary programs. If you are unable to comply with the GPL, you must
+ * acquire a commercial license to use this software. Commercial licenses
+ * for this software and support services are available from Mbedthis
+ * Software at http://www.mbedthis.com
+ *
+ * @end
+ */
+
+/******************************************************************************/
+
+#ifndef _h_ESP_ENV_h
+#define _h_ESP_ENV_h 1
+
+/*
+ * @brief Scripting environment variable array types
+ */
+typedef enum EspEnvType {
+ ESP_UNDEFINED_OBJ = -1,
+
+ /**
+ * Elements for server[]:
+ * DOCUMENT_ROOT GATEWAY_INTERFACE SERVER_ADDR SERVER_PORT SERVER_NAME
+ * SERVER_PROTOCOL SERVER_SOFTWARE SERVER_URL UPLOAD_DIR
+ * FUTURE: SERVER_ADMIN
+ * FUTURE: this could be shared across all hosts and be made read-only.
+ */
+ ESP_SERVER_OBJ = 0, /*! server[] data */
+
+ /**
+ * Elements for session[]: are user defined
+ */
+ ESP_SESSION_OBJ = 1, /*! session[] data */
+
+ /**
+ * Elements for request[]:
+ * AUTH_TYPE CONTENT_LENGTH CONTENT_TYPE QUERY_STRING PATH_INFO
+ * PATH_TRANSLATED REMOTE_ADDR REMOTE_HOST REMOTE_USER REQUEST_METHOD
+ * REQUEST_URI SCRIPT_FILENAME SCRIPT_NAME
+ * FUTURE: FILEPATH_INFO REDIRECT_URL SELF REMOTE_PORT AUTH_USER
+ * AUTH_GROUP AUTH_ACL
+ */
+ ESP_REQUEST_OBJ = 2, /*! request[] data */
+
+ /**
+ * Elements for headers[]:
+ * HTTP_ACCEPT HTTP_ACCEPT_CHARSET HTTP_CONNECTION HTTP_HOST
+ * HTTP_REFERER HTTP_USER_AGENT and any other custom headers
+ */
+ ESP_HEADERS_OBJ = 3, /*! header [] data */
+
+ /**
+ * Elements for cookies[]: are defined by the HTTP request
+ */
+ ESP_COOKIES_OBJ = 4, /*! cookies[] data */
+
+ /**
+ * Elements for files[]: are defined by the HTTP request
+ * CLIENT_FILENAME CONTENT_TYPE FILENAME SIZE
+ */
+ ESP_FILES_OBJ = 5, /*! files[] data */
+
+ /**
+ * Elements for form[]: are defined by the HTTP request
+ */
+ ESP_FORM_OBJ = 6, /*! form[] data */
+
+ /**
+ * Elements for application[]: are user defined
+ */
+ ESP_APPLICATION_OBJ = 7, /*! application[] data */
+
+ /**
+ * Elements for global[]: are defined by ESP/EJS
+ */
+ ESP_GLOBAL_OBJ = 8, /*! global [] data */
+
+ /*
+ * Elements for local[]: are defined by ESP/EJS
+ */
+ ESP_LOCAL_OBJ = 9, /*! local [] data */
+} EspEnvType;
+
+#define ESP_OBJ_MAX 10 /* Total objects */
+
+#if BLD_SQUEEZE
+#define ESP_HASH_SIZE 19 /* Size of hash tables */
+#else
+#define ESP_HASH_SIZE 37
+#endif
+
+/******************************************************************************/
+#endif /* _h_ESP_ENV_h */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim:tw=78
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
+ */
diff --git a/source4/web_server/esp/espProcs.c b/source4/web_server/esp/espProcs.c
new file mode 100644
index 0000000000..a8da800213
--- /dev/null
+++ b/source4/web_server/esp/espProcs.c
@@ -0,0 +1,230 @@
+/*
+ * @file espProcs.c
+ * @brief Embedded Server Pages (ESP) Procedures.
+ * @overview These ESP procedures can be used in ESP pages for common tasks.
+ */
+/********************************* Copyright **********************************/
+/*
+ * @copy default
+ *
+ * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved.
+ *
+ * This software is distributed under commercial and open source licenses.
+ * You may use the GPL open source license described below or you may acquire
+ * a commercial license from Mbedthis Software. You agree to be fully bound
+ * by the terms of either license. Consult the LICENSE.TXT distributed with
+ * this software for full details.
+ *
+ * This software is open source; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See the GNU General Public License for more
+ * details at: http://www.mbedthis.com/downloads/gplLicense.html
+ *
+ * This program is distributed WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * This GPL license does NOT permit incorporating this software into
+ * proprietary programs. If you are unable to comply with the GPL, you must
+ * acquire a commercial license to use this software. Commercial licenses
+ * for this software and support services are available from Mbedthis
+ * Software at http://www.mbedthis.com
+ *
+ * @end
+ */
+/********************************** Includes **********************************/
+
+#include "esp.h"
+
+/************************************ Code ************************************/
+#if BLD_FEATURE_ESP_MODULE
+#if BLD_FEATURE_SESSION
+/*
+ * destroySession
+ */
+
+static int destroySessionProc(EspRequest *ep, int argc, char **argv)
+{
+ ep->esp->destroySession(ep->requestHandle);
+ return 0;
+}
+
+#endif /* BLD_FEATURE_SESSION */
+
+/******************************************************************************/
+/*
+ * include
+ *
+ * This includes javascript libraries. For example:
+ *
+ * <% include("file", ...); %>
+ *
+ * Don't confuse with ESP includes:
+ *
+ * <% include file.esp %>
+ *
+ * Filenames are relative to the base document including the file.
+ * FUTURE -- move back to EJS. Only here now because we need ep->readFile.
+ */
+
+static int includeProc(EspRequest *ep, int argc, char **argv)
+{
+ Esp *esp;
+ char path[MPR_MAX_FNAME], dir[MPR_MAX_FNAME];
+ char *emsg, *buf;
+ int size, i;
+
+ esp = ep->esp;
+ mprAssert(argv);
+ for (i = 0; i < argc; i++) {
+ mprGetDirName(dir, sizeof(dir), ep->docPath);
+ mprSprintf(path, sizeof(path), "%s/%s", dir, argv[i]);
+
+ if (esp->readFile(ep->requestHandle, &buf, &size, path) < 0) {
+ espError(ep, "Can't read include file: %s", path);
+ return MPR_ERR_CANT_ACCESS;
+ }
+ buf[size] = '\0';
+
+ if (ejsEvalScript(espGetScriptHandle(ep), buf, 0, &emsg) < 0) {
+ espError(ep, "Cant evaluate script");
+ mprFree(buf);
+ return -1;
+ }
+ mprFree(buf);
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * redirect
+ *
+ * This implemements <% redirect(url, code); %> command. The redirection
+ * code is optional.
+ */
+
+static int redirectProc(EspRequest *ep, int argc, char **argv)
+{
+ char *url;
+ int code;
+
+ if (argc < 1) {
+ espError(ep, "Bad args");
+ return MPR_ERR_BAD_ARGS;
+ }
+ url = argv[0];
+ if (argc == 2) {
+ code = atoi(argv[1]);
+ } else {
+ code = 302;
+ }
+ espRedirect(ep, code, url);
+ return 0;
+}
+
+/******************************************************************************/
+#if BLD_FEATURE_SESSION
+/*
+ * useSession
+ */
+
+static int useSessionProc(EspRequest *ep, int argc, char **argv)
+{
+ int timeout;
+
+ if (argc > 1) {
+ espError(ep, "Bad args");
+ return MPR_ERR_BAD_ARGS;
+
+ } else if (argc == 1) {
+ timeout = atoi(argv[0]);
+ } else {
+ timeout = 0;
+ }
+
+ ep->esp->createSession(ep->requestHandle, timeout);
+ espSetReturnString(ep, ep->esp->getSessionId(ep->requestHandle));
+ return 0;
+}
+
+#endif /* BLD_FEATURE_SESSION */
+/******************************************************************************/
+/*
+ * setHeader
+ *
+ * This implemements <% setHeader("key: value", allowMultiple); %> command.
+ */
+
+static int setHeaderProc(EspRequest *ep, int argc, char **argv)
+{
+ mprAssert(argv);
+ if (argc != 2) {
+ espError(ep, "Bad args");
+ return MPR_ERR_BAD_ARGS;
+ }
+ ep->esp->setHeader(ep->requestHandle, argv[0], atoi(argv[1]));
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * write
+ *
+ * This implemements <% write("text"); %> command.
+ */
+
+static int writeProc(EspRequest *ep, int argc, char **argv)
+{
+ char *s;
+ int i, len;
+
+ mprAssert(argv);
+ for (i = 0; i < argc; i++) {
+ s = argv[i];
+ len = strlen(s);
+ if (len > 0) {
+ if (espWrite(ep, s, len) != len) {
+ espError(ep, "Can't write to client");
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+/******************************************************************************/
+
+void espRegisterProcs()
+{
+ espDefineStringCFunction(0, "write", writeProc, 0);
+ espDefineStringCFunction(0, "setHeader", setHeaderProc, 0);
+ espDefineStringCFunction(0, "redirect", redirectProc, 0);
+ espDefineStringCFunction(0, "include", includeProc, 0);
+
+#if BLD_FEATURE_SESSION
+ /*
+ * Create and use are synonomous
+ */
+ espDefineStringCFunction(0, "useSession", useSessionProc, 0);
+ espDefineStringCFunction(0, "createSession", useSessionProc, 0);
+ espDefineStringCFunction(0, "destroySession", destroySessionProc, 0);
+#endif
+}
+
+/******************************************************************************/
+
+#else
+void mprEspControlsDummy() {}
+
+#endif /* BLD_FEATURE_ESP_MODULE */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim:tw=78
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
+ */