/* jst.c -- JavaScript templates Copyright (c) All Rights Reserved. See details at the end of the file. */ /********************************* Includes ***********************************/ #include "goahead.h" #include "js.h" #if ME_GOAHEAD_JAVASCRIPT /********************************** Locals ************************************/ static WebsHash websJstFunctions = -1; /* Symbol table of functions */ /***************************** Forward Declarations ***************************/ static char *strtokcmp(char *s1, char *s2); static char *skipWhite(char *s); /************************************* Code ***********************************/ /* Process requests and expand all scripting commands. We read the entire web page into memory and then process. If you have really big documents, it is better to make them plain HTML files rather than Javascript web pages. Return true to indicate the request was handled, even for errors. */ static bool jstHandler(Webs *wp) { WebsFileInfo sbuf; char *token, *lang, *result, *ep, *cp, *buf, *nextp, *last; ssize len; int rc, jid; assert(websValid(wp)); assert(wp->filename && *wp->filename); assert(wp->ext && *wp->ext); buf = 0; if ((jid = jsOpenEngine(wp->vars, websJstFunctions)) < 0) { websError(wp, HTTP_CODE_INTERNAL_SERVER_ERROR, "Cannot create JavaScript engine"); goto done; } jsSetUserHandle(jid, wp); if (websPageStat(wp, &sbuf) < 0) { websError(wp, HTTP_CODE_NOT_FOUND, "Cannot stat %s", wp->filename); goto done; } if (websPageOpen(wp, O_RDONLY | O_BINARY, 0666) < 0) { websError(wp, HTTP_CODE_NOT_FOUND, "Cannot open URL: %s", wp->filename); goto done; } /* Create a buffer to hold the web page in-memory */ len = sbuf.size; if ((buf = walloc(len + 1)) == NULL) { websError(wp, HTTP_CODE_INTERNAL_SERVER_ERROR, "Cannot get memory"); goto done; } buf[len] = '\0'; if (websPageReadData(wp, buf, len) != len) { websError(wp, HTTP_CODE_NOT_FOUND, "Cannot read %s", wp->filename); goto done; } websPageClose(wp); websWriteHeaders(wp, (ssize) -1, 0); websWriteHeader(wp, "Pragma", "no-cache"); websWriteHeader(wp, "Cache-Control", "no-cache"); websWriteEndHeaders(wp); /* Scan for the next "<%" */ last = buf; for (rc = 0; rc == 0 && *last && ((nextp = strstr(last, "<%")) != NULL); ) { websWriteBlock(wp, last, (nextp - last)); nextp = skipWhite(nextp + 2); /* Decode the language */ token = "language"; if ((lang = strtokcmp(nextp, token)) != NULL) { if ((cp = strtokcmp(lang, "=javascript")) != NULL) { /* Ignore */; } else { cp = nextp; } nextp = cp; } /* Find tailing bracket and then evaluate the script */ if ((ep = strstr(nextp, "%>")) != NULL) { *ep = '\0'; last = ep + 2; nextp = skipWhite(nextp); /* Handle backquoted newlines */ for (cp = nextp; *cp; ) { if (*cp == '\\' && (cp[1] == '\r' || cp[1] == '\n')) { *cp++ = ' '; while (*cp == '\r' || *cp == '\n') { *cp++ = ' '; } } else { cp++; } } if (*nextp) { result = NULL; if (jsEval(jid, nextp, &result) == 0) { /* On an error, discard all output accumulated so far and store the error in the result buffer. Be careful if the user has called websError() already. */ rc = -1; if (websValid(wp)) { if (result) { websWrite(wp, "
%s", nextp); wfree(result); } else { websWrite(wp, "