/*
|
/*
|
* asp.c -- Active Server Page Support
|
* asp.c -- Active Server Page Support
|
*
|
*
|
* Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.
|
* Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.
|
*
|
*
|
* See the file "license.txt" for usage and redistribution license requirements
|
* See the file "license.txt" for usage and redistribution license requirements
|
*/
|
*/
|
|
|
/******************************** Description *********************************/
|
/******************************** Description *********************************/
|
|
|
/*
|
/*
|
* The ASP module processes ASP pages and executes embedded scripts. It
|
* The ASP module processes ASP pages and executes embedded scripts. It
|
* support an open scripting architecture with in-built support for
|
* support an open scripting architecture with in-built support for
|
* Ejscript(TM).
|
* Ejscript(TM).
|
*/
|
*/
|
|
|
/********************************* Includes ***********************************/
|
/********************************* Includes ***********************************/
|
|
|
#include "wsIntrn.h"
|
#include "wsIntrn.h"
|
|
|
/********************************** Locals ************************************/
|
/********************************** Locals ************************************/
|
|
|
static sym_fd_t websAspFunctions = -1; /* Symbol table of functions */
|
static sym_fd_t websAspFunctions = -1; /* Symbol table of functions */
|
|
|
/***************************** Forward Declarations ***************************/
|
/***************************** Forward Declarations ***************************/
|
|
|
static char_t *strtokcmp(char_t* s1, char_t* s2);
|
static char_t *strtokcmp(char_t* s1, char_t* s2);
|
static char_t *skipWhite(char_t *s);
|
static char_t *skipWhite(char_t *s);
|
|
|
/************************************* Code ***********************************/
|
/************************************* Code ***********************************/
|
/*
|
/*
|
* Create script spaces and commands
|
* Create script spaces and commands
|
*/
|
*/
|
|
|
int websAspOpen()
|
int websAspOpen()
|
{
|
{
|
/*
|
/*
|
* Create the table for ASP functions
|
* Create the table for ASP functions
|
*/
|
*/
|
websAspFunctions = symOpen(128);
|
websAspFunctions = symOpen(128);
|
|
|
/*
|
/*
|
* Create standard ASP commands
|
* Create standard ASP commands
|
*/
|
*/
|
websAspDefine(T("write"), websAspWrite);
|
websAspDefine(T("write"), websAspWrite);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
/************************************* Code ***********************************/
|
/************************************* Code ***********************************/
|
/*
|
/*
|
* Close Asp symbol table.
|
* Close Asp symbol table.
|
*/
|
*/
|
|
|
void websAspClose()
|
void websAspClose()
|
{
|
{
|
if (websAspFunctions != -1) {
|
if (websAspFunctions != -1) {
|
symClose(websAspFunctions, NULL);
|
symClose(websAspFunctions, NULL);
|
}
|
}
|
}
|
}
|
|
|
/******************************************************************************/
|
/******************************************************************************/
|
/*
|
/*
|
* Process ASP requests and expand all scripting commands. We read the
|
* Process ASP requests and expand all scripting commands. We read the
|
* entire ASP page into memory and then process. If you have really big
|
* entire ASP page into memory and then process. If you have really big
|
* documents, it is better to make them plain HTML files rather than ASPs.
|
* documents, it is better to make them plain HTML files rather than ASPs.
|
*/
|
*/
|
|
|
int websAspRequest(webs_t wp, char_t* lpath)
|
int websAspRequest(webs_t wp, char_t* lpath)
|
{
|
{
|
websStatType sbuf;
|
websStatType sbuf;
|
char *rbuf;
|
char *rbuf;
|
char_t *token, *lang, *result, *path, *ep, *cp, *buf, *nextp;
|
char_t *token, *lang, *result, *path, *ep, *cp, *buf, *nextp;
|
char_t *last;
|
char_t *last;
|
int rc, engine, len, ejid;
|
int rc, engine, len, ejid;
|
|
|
a_assert(websValid(wp));
|
a_assert(websValid(wp));
|
a_assert(lpath && *lpath);
|
a_assert(lpath && *lpath);
|
|
|
rc = -1;
|
rc = -1;
|
buf = NULL;
|
buf = NULL;
|
rbuf = NULL;
|
rbuf = NULL;
|
engine = EMF_SCRIPT_EJSCRIPT;
|
engine = EMF_SCRIPT_EJSCRIPT;
|
wp->flags |= WEBS_HEADER_DONE;
|
wp->flags |= WEBS_HEADER_DONE;
|
path = websGetRequestPath(wp);
|
path = websGetRequestPath(wp);
|
|
|
/*
|
/*
|
* Create Ejscript instance incase it is needed
|
* Create Ejscript instance incase it is needed
|
*/
|
*/
|
ejid = ejOpenEngine(wp->cgiVars, websAspFunctions);
|
ejid = ejOpenEngine(wp->cgiVars, websAspFunctions);
|
if (ejid < 0) {
|
if (ejid < 0) {
|
websError(wp, 200, T("Can't create Ejscript engine"));
|
websError(wp, 200, T("Can't create Ejscript engine"));
|
goto done;
|
goto done;
|
}
|
}
|
ejSetUserHandle(ejid, (int) wp);
|
ejSetUserHandle(ejid, (int) wp);
|
|
|
if (websPageStat(wp, lpath, path, &sbuf) < 0) {
|
if (websPageStat(wp, lpath, path, &sbuf) < 0) {
|
websError(wp, 200, T("Can't stat %s"), lpath);
|
websError(wp, 200, T("Can't stat %s"), lpath);
|
goto done;
|
goto done;
|
}
|
}
|
|
|
/*
|
/*
|
* Create a buffer to hold the ASP file in-memory
|
* Create a buffer to hold the ASP file in-memory
|
*/
|
*/
|
len = sbuf.size * sizeof(char);
|
len = sbuf.size * sizeof(char);
|
if ((rbuf = balloc(B_L, len + 1)) == NULL) {
|
if ((rbuf = balloc(B_L, len + 1)) == NULL) {
|
websError(wp, 200, T("Can't get memory"));
|
websError(wp, 200, T("Can't get memory"));
|
goto done;
|
goto done;
|
}
|
}
|
rbuf[len] = '\0';
|
rbuf[len] = '\0';
|
|
|
if (websPageReadData(wp, rbuf, len) != len) {
|
if (websPageReadData(wp, rbuf, len) != len) {
|
websError(wp, 200, T("Cant read %s"), lpath);
|
websError(wp, 200, T("Cant read %s"), lpath);
|
goto done;
|
goto done;
|
}
|
}
|
websCloseFileHandle(wp);
|
websCloseFileHandle(wp);
|
|
|
/*
|
/*
|
* Convert to UNICODE if necessary.
|
* Convert to UNICODE if necessary.
|
*/
|
*/
|
if ((buf = ballocAscToUni(rbuf)) == NULL) {
|
if ((buf = ballocAscToUni(rbuf)) == NULL) {
|
websError(wp, 200, T("Can't get memory"));
|
websError(wp, 200, T("Can't get memory"));
|
goto done;
|
goto done;
|
}
|
}
|
|
|
/*
|
/*
|
* Scan for the next "<%"
|
* Scan for the next "<%"
|
*/
|
*/
|
last = buf;
|
last = buf;
|
rc = 0;
|
rc = 0;
|
while (rc == 0 && *last && ((nextp = gstrstr(last, T("<%"))) != NULL)) {
|
while (rc == 0 && *last && ((nextp = gstrstr(last, T("<%"))) != NULL)) {
|
websWriteBlock(wp, last, (nextp - last));
|
websWriteBlock(wp, last, (nextp - last));
|
nextp = skipWhite(nextp + 2);
|
nextp = skipWhite(nextp + 2);
|
|
|
/*
|
/*
|
* Decode the language
|
* Decode the language
|
*/
|
*/
|
token = T("language");
|
token = T("language");
|
|
|
if ((lang = strtokcmp(nextp, token)) != NULL) {
|
if ((lang = strtokcmp(nextp, token)) != NULL) {
|
if ((cp = strtokcmp(lang, T("=javascript"))) != NULL) {
|
if ((cp = strtokcmp(lang, T("=javascript"))) != NULL) {
|
engine = EMF_SCRIPT_EJSCRIPT;
|
engine = EMF_SCRIPT_EJSCRIPT;
|
} else {
|
} else {
|
cp = nextp;
|
cp = nextp;
|
}
|
}
|
nextp = cp;
|
nextp = cp;
|
}
|
}
|
|
|
/*
|
/*
|
* Find tailing bracket and then evaluate the script
|
* Find tailing bracket and then evaluate the script
|
*/
|
*/
|
if ((ep = gstrstr(nextp, T("%>"))) != NULL) {
|
if ((ep = gstrstr(nextp, T("%>"))) != NULL) {
|
|
|
*ep = '\0';
|
*ep = '\0';
|
last = ep + 2;
|
last = ep + 2;
|
nextp = skipWhite(nextp);
|
nextp = skipWhite(nextp);
|
/*
|
/*
|
* Handle backquoted newlines
|
* Handle backquoted newlines
|
*/
|
*/
|
for (cp = nextp; *cp; ) {
|
for (cp = nextp; *cp; ) {
|
if (*cp == '\\' && (cp[1] == '\r' || cp[1] == '\n')) {
|
if (*cp == '\\' && (cp[1] == '\r' || cp[1] == '\n')) {
|
*cp++ = ' ';
|
*cp++ = ' ';
|
while (*cp == '\r' || *cp == '\n') {
|
while (*cp == '\r' || *cp == '\n') {
|
*cp++ = ' ';
|
*cp++ = ' ';
|
}
|
}
|
} else {
|
} else {
|
cp++;
|
cp++;
|
}
|
}
|
}
|
}
|
|
|
/*
|
/*
|
* Now call the relevant script engine. Output is done directly
|
* Now call the relevant script engine. Output is done directly
|
* by the ASP script procedure by calling websWrite()
|
* by the ASP script procedure by calling websWrite()
|
*/
|
*/
|
if (*nextp) {
|
if (*nextp) {
|
result = NULL;
|
result = NULL;
|
if (engine == EMF_SCRIPT_EJSCRIPT) {
|
if (engine == EMF_SCRIPT_EJSCRIPT) {
|
rc = scriptEval(engine, nextp, &result, ejid);
|
rc = scriptEval(engine, nextp, &result, ejid);
|
} else {
|
} else {
|
rc = scriptEval(engine, nextp, &result, (int) wp);
|
rc = scriptEval(engine, nextp, &result, (int) wp);
|
}
|
}
|
if (rc < 0) {
|
if (rc < 0) {
|
/*
|
/*
|
* On an error, discard all output accumulated so far
|
* On an error, discard all output accumulated so far
|
* and store the error in the result buffer. Be careful if the
|
* and store the error in the result buffer. Be careful if the
|
* user has called websError() already.
|
* user has called websError() already.
|
*/
|
*/
|
if (websValid(wp)) {
|
if (websValid(wp)) {
|
if (result) {
|
if (result) {
|
websWrite(wp, T("<h2><b>ASP Error: %s</b></h2>\n"),
|
websWrite(wp, T("<h2><b>ASP Error: %s</b></h2>\n"),
|
result);
|
result);
|
websWrite(wp, T("<pre>%s</pre>"), nextp);
|
websWrite(wp, T("<pre>%s</pre>"), nextp);
|
bfree(B_L, result);
|
bfree(B_L, result);
|
} else {
|
} else {
|
websWrite(wp, T("<h2><b>ASP Error</b></h2>\n%s\n"),
|
websWrite(wp, T("<h2><b>ASP Error</b></h2>\n%s\n"),
|
nextp);
|
nextp);
|
}
|
}
|
websWrite(wp, T("</body></html>\n"));
|
websWrite(wp, T("</body></html>\n"));
|
rc = 0;
|
rc = 0;
|
}
|
}
|
goto done;
|
goto done;
|
}
|
}
|
}
|
}
|
|
|
} else {
|
} else {
|
websError(wp, 200, T("Unterminated script in %s: \n"), lpath);
|
websError(wp, 200, T("Unterminated script in %s: \n"), lpath);
|
rc = -1;
|
rc = -1;
|
goto done;
|
goto done;
|
}
|
}
|
}
|
}
|
/*
|
/*
|
* Output any trailing HTML page text
|
* Output any trailing HTML page text
|
*/
|
*/
|
if (last && *last && rc == 0) {
|
if (last && *last && rc == 0) {
|
websWriteBlock(wp, last, gstrlen(last));
|
websWriteBlock(wp, last, gstrlen(last));
|
}
|
}
|
rc = 0;
|
rc = 0;
|
|
|
/*
|
/*
|
* Common exit and cleanup
|
* Common exit and cleanup
|
*/
|
*/
|
done:
|
done:
|
if (websValid(wp)) {
|
if (websValid(wp)) {
|
websCloseFileHandle(wp);
|
websCloseFileHandle(wp);
|
if (ejid >= 0) {
|
if (ejid >= 0) {
|
ejCloseEngine(ejid);
|
ejCloseEngine(ejid);
|
}
|
}
|
}
|
}
|
bfreeSafe(B_L, buf);
|
bfreeSafe(B_L, buf);
|
bfreeSafe(B_L, rbuf);
|
bfreeSafe(B_L, rbuf);
|
return rc;
|
return rc;
|
}
|
}
|
|
|
/******************************************************************************/
|
/******************************************************************************/
|
/*
|
/*
|
* Define an ASP Ejscript function. Bind an ASP name to a C procedure.
|
* Define an ASP Ejscript function. Bind an ASP name to a C procedure.
|
*/
|
*/
|
|
|
int websAspDefine(char_t *name,
|
int websAspDefine(char_t *name,
|
int (*fn)(int ejid, webs_t wp, int argc, char_t **argv))
|
int (*fn)(int ejid, webs_t wp, int argc, char_t **argv))
|
{
|
{
|
return ejSetGlobalFunctionDirect(websAspFunctions, name,
|
return ejSetGlobalFunctionDirect(websAspFunctions, name,
|
(int (*)(int, void*, int, char_t**)) fn);
|
(int (*)(int, void*, int, char_t**)) fn);
|
}
|
}
|
|
|
/******************************************************************************/
|
/******************************************************************************/
|
/*
|
/*
|
* Asp write command. This implemements <% write("text"); %> command
|
* Asp write command. This implemements <% write("text"); %> command
|
*/
|
*/
|
|
|
int websAspWrite(int ejid, webs_t wp, int argc, char_t **argv)
|
int websAspWrite(int ejid, webs_t wp, int argc, char_t **argv)
|
{
|
{
|
int i;
|
int i;
|
|
|
a_assert(websValid(wp));
|
a_assert(websValid(wp));
|
a_assert(argv);
|
a_assert(argv);
|
|
|
for (i = 0; i < argc; ) {
|
for (i = 0; i < argc; ) {
|
if (websWriteBlock(wp, argv[i], gstrlen(argv[i])) < 0) {
|
if (websWriteBlock(wp, argv[i], gstrlen(argv[i])) < 0) {
|
return -1;
|
return -1;
|
}
|
}
|
if (++i < argc) {
|
if (++i < argc) {
|
if (websWriteBlock(wp, T(" "), 2) < 0) {
|
if (websWriteBlock(wp, T(" "), 2) < 0) {
|
return -1;
|
return -1;
|
}
|
}
|
}
|
}
|
}
|
}
|
return 0;
|
return 0;
|
}
|
}
|
|
|
/******************************************************************************/
|
/******************************************************************************/
|
/*
|
/*
|
* strtokcmp -- Find s2 in s1. We skip leading white space in s1.
|
* strtokcmp -- Find s2 in s1. We skip leading white space in s1.
|
* Return a pointer to the location in s1 after s2 ends.
|
* Return a pointer to the location in s1 after s2 ends.
|
*/
|
*/
|
|
|
static char_t* strtokcmp(char_t* s1, char_t* s2)
|
static char_t* strtokcmp(char_t* s1, char_t* s2)
|
{
|
{
|
int len;
|
int len;
|
|
|
s1 = skipWhite(s1);
|
s1 = skipWhite(s1);
|
len = gstrlen(s2);
|
len = gstrlen(s2);
|
for (len = gstrlen(s2); len > 0 && (tolower(*s1) == tolower(*s2)); len--) {
|
for (len = gstrlen(s2); len > 0 && (tolower(*s1) == tolower(*s2)); len--) {
|
if (*s2 == '\0') {
|
if (*s2 == '\0') {
|
return s1;
|
return s1;
|
}
|
}
|
s1++;
|
s1++;
|
s2++;
|
s2++;
|
}
|
}
|
if (len == 0) {
|
if (len == 0) {
|
return s1;
|
return s1;
|
}
|
}
|
return NULL;
|
return NULL;
|
}
|
}
|
|
|
/******************************************************************************/
|
/******************************************************************************/
|
/*
|
/*
|
* Skip white space
|
* Skip white space
|
*/
|
*/
|
|
|
static char_t *skipWhite(char_t *s)
|
static char_t *skipWhite(char_t *s)
|
{
|
{
|
a_assert(s);
|
a_assert(s);
|
|
|
if (s == NULL) {
|
if (s == NULL) {
|
return s;
|
return s;
|
}
|
}
|
while (*s && gisspace(*s)) {
|
while (*s && gisspace(*s)) {
|
s++;
|
s++;
|
}
|
}
|
return s;
|
return s;
|
}
|
}
|
|
|
|
|