summaryrefslogtreecommitdiff
path: root/source4/web_server/esp/esp.c
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/esp.c
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/esp.c')
-rw-r--r--source4/web_server/esp/esp.c1042
1 files changed, 1042 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
+ */