summaryrefslogtreecommitdiff
path: root/source4/lib/appweb/esp
diff options
context:
space:
mode:
Diffstat (limited to 'source4/lib/appweb/esp')
-rw-r--r--source4/lib/appweb/esp/esp.c1042
-rw-r--r--source4/lib/appweb/esp/esp.h279
-rw-r--r--source4/lib/appweb/esp/espEnv.h128
-rw-r--r--source4/lib/appweb/esp/espProcs.c246
4 files changed, 1695 insertions, 0 deletions
diff --git a/source4/lib/appweb/esp/esp.c b/source4/lib/appweb/esp/esp.c
new file mode 100644
index 0000000000..ef20557f93
--- /dev/null
+++ b/source4/lib/appweb/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 const Esp *esp;
+
+/***************************** Forward Declarations ***************************/
+
+static int buildScript(EspRequest *ep, char **jsBuf, char *input, char
+ **errMsg);
+
+/************************************ Code ************************************/
+/*
+ * Called at server initialization
+ */
+
+int espOpen(const 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, const 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, const 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, const 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 XX_UNUSED_XX
+
+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 XX_UNUSED_XX
+
+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/lib/appweb/esp/esp.h b/source4/lib/appweb/esp/esp.h
new file mode 100644
index 0000000000..ee86e8d345
--- /dev/null
+++ b/source4/lib/appweb/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 "lib/appweb/ejs/ejs.h"
+#include "lib/appweb/esp/espEnv.h"
+#include "lib/appweb/ejs/var.h"
+#include "lib/appweb/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 */
+ const 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);
+ const char *(*getSessionId)(EspHandle handle);
+ int (*mapToStorage)(EspHandle handle, char *path, int len, const char *uri,
+ int flags);
+ int (*readFile)(EspHandle handle, char **buf, int *len, const char *path);
+ void (*redirect)(EspHandle handle, int code, char *url);
+ void (*setCookie)(EspHandle handle, const char *name, const char *value,
+ int lifetime, const 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(const 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, const char *functionName,
+ EspCFunction fn, void *thisPtr);
+extern void espDefineFunction(EspRequest *ep, const 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, ...) PRINTF_ATTRIBUTE(2,3);
+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, const 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, ...) PRINTF_ATTRIBUTE(2,3);
+
+/*
+ * 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/lib/appweb/esp/espEnv.h b/source4/lib/appweb/esp/espEnv.h
new file mode 100644
index 0000000000..a3c9d9f5c7
--- /dev/null
+++ b/source4/lib/appweb/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/lib/appweb/esp/espProcs.c b/source4/lib/appweb/esp/espProcs.c
new file mode 100644
index 0000000000..28b69a8a6f
--- /dev/null
+++ b/source4/lib/appweb/esp/espProcs.c
@@ -0,0 +1,246 @@
+/*
+ * @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)
+{
+ const Esp *esp;
+ char path[MPR_MAX_FNAME], dir[MPR_MAX_FNAME];
+ char *emsg=NULL, *buf;
+ int size, i;
+
+ esp = ep->esp;
+ mprAssert(argv);
+ for (i = 0; i < argc; i++) {
+ const char *extension;
+
+ if (argv[i][0] != '/') {
+ mprGetDirName(dir, sizeof(dir), ep->docPath);
+ mprSprintf(path, sizeof(path), "%s/%s", dir, argv[i]);
+ } else {
+ mprSprintf(path, sizeof(path), "%s", 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';
+
+ extension = strrchr(argv[i], '.');
+ /* this makes handling include files in esp scripts much more convenient */
+ if (extension && strcasecmp(extension, ".esp") == 0) {
+ if (espProcessRequest(ep, path, buf, &emsg) != 0) {
+ espError(ep, "Cant evaluate script - %s", emsg?emsg:"");
+ mprFree(buf);
+ return -1;
+ }
+ } else {
+ if (ejsEvalScript(espGetScriptHandle(ep), buf, 0, &emsg) < 0) {
+ espError(ep, "Cant evaluate script - %s", emsg?emsg:"");
+ 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
+ */