📄 esp.c
字号:
/* * @file esp.c * @brief Embedded Server Pages (ESP) core processing. * @overview Embedded Server Pages 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, "%s", 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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -