2000-08-30 Joel Sherrill <joel@OARcorp.com>

* Merged version 2.1 of GoAhead webserver.  This update
	was submitted by Antti P Miettinen <antti.p.miettinen@nokia.com>.
	* NOTES, base64.c, ejIntrn.h, emfdb.c, emfdb.h, md5.h, md5c.c,
	um.c, um.h: New files.
	* wbase64.c: Removed.
	* Makefile.am, asp.c, balloc.c, default.c, ej.h, ejlex.c, ejparse.c,
	form.c, h.c, handler.c, mime.c, misc.c, ringq.c, rom.c, security.c,
	socket.c, sym.c, uemf.c, uemf.h, url.c, value.c, webcomp.c, webmain.c,
	webpage.c, webrom.c, webs.c, webs.h, websuemf.c, wsIntrn.h: Modified.
This commit is contained in:
Joel Sherrill
2000-09-01 10:57:21 +00:00
parent 757e166196
commit a6b4c0df5f
79 changed files with 17588 additions and 3834 deletions

View File

@@ -1,3 +1,15 @@
2000-08-31 Joel Sherrill <joel@OARcorp.com>
* Merged version 2.1 of GoAhead webserver. This update
was submitted by Antti P Miettinen <antti.p.miettinen@nokia.com>.
* NOTES, base64.c, ejIntrn.h, emfdb.c, emfdb.h, md5.h, md5c.c,
um.c, um.h: New files.
* wbase64.c: Removed.
* Makefile.am, asp.c, balloc.c, default.c, ej.h, ejlex.c, ejparse.c,
form.c, h.c, handler.c, mime.c, misc.c, ringq.c, rom.c, security.c,
socket.c, sym.c, uemf.c, uemf.h, url.c, value.c, webcomp.c, webmain.c,
webpage.c, webrom.c, webs.c, webs.h, websuemf.c, wsIntrn.h: Modified.
2000-08-31 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
* netinet/tcp_input.c: Spelling corrections.

View File

@@ -1,3 +1,15 @@
2000-08-31 Joel Sherrill <joel@OARcorp.com>
* Merged version 2.1 of GoAhead webserver. This update
was submitted by Antti P Miettinen <antti.p.miettinen@nokia.com>.
* NOTES, base64.c, ejIntrn.h, emfdb.c, emfdb.h, md5.h, md5c.c,
um.c, um.h: New files.
* wbase64.c: Removed.
* Makefile.am, asp.c, balloc.c, default.c, ej.h, ejlex.c, ejparse.c,
form.c, h.c, handler.c, mime.c, misc.c, ringq.c, rom.c, security.c,
socket.c, sym.c, uemf.c, uemf.h, url.c, value.c, webcomp.c, webmain.c,
webpage.c, webrom.c, webs.c, webs.h, websuemf.c, wsIntrn.h: Modified.
2000-08-31 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
* netinet/tcp_input.c: Spelling corrections.

View File

@@ -7,14 +7,15 @@ AUTOMAKE_OPTIONS = foreign 1.4
LIBNAME = lib.a
LIB = $(ARCH)/$(LIBNAME)
C_FILES = asp.c balloc.c wbase64.c default.c ejlex.c ejparse.c form.c h.c \
handler.c mime.c misc.c webpage.c ringq.c rom.c security.c socket.c \
sym.c uemf.c url.c value.c webrom.c webs.c websuemf.c webmain.c
C_FILES = asp.c balloc.c base64.c default.c ejlex.c ejparse.c emfdb.c \
form.c h.c handler.c md5c.c mime.c misc.c webpage.c ringq.c rom.c \
security.c socket.c sym.c uemf.c um.c url.c value.c webrom.c webs.c \
websuemf.c webmain.c
C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o)
OBJS = $(C_O_FILES)
H_FILES = ej.h uemf.h webs.h wsIntrn.h
H_FILES = ej.h ejIntrn.h emfdb.h md5.h uemf.h um.h webs.h wsIntrn.h
include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
include $(top_srcdir)/../../../automake/lib.am
@@ -52,7 +53,7 @@ endif
EXTRA_DIST = asp.c balloc.c default.c ej.h ejlex.c ejparse.c form.c h.c \
handler.c mime.c misc.c ringq.c rom.c rtems_webserver.h security.c \
socket.c sym.c uemf.c uemf.h url.c value.c wbase64.c webcomp.c webmain.c \
webpage.c webrom.c webs.c webs.h websuemf.c wsIntrn.h
socket.c sym.c uemf.c uemf.h um.h url.c value.c base64.c webcomp.c \
webmain.c webpage.c webrom.c webs.c webs.h websuemf.c wsIntrn.h
include $(top_srcdir)/../../../automake/local.am

View File

@@ -0,0 +1,29 @@
#
# $Id$
#
Notes on merging GoAhead Webs 2.1. Eventually RTEMS should be supported
in their distributions and this directory removed.
Applied patch from Antti P Miettinen <antti.p.miettinen@nokia.com>.
Obtain the original distribution from http://www.goahead.com for
documentation.
Tailoring
=========
socket.c is RTEMS specific
Renames
=======
Distributed as This Directory
============== ================
base64.c wbase64.c
page.c webpage.c
RTEMS Specific Additions
========================
webmain.c
rtems_webserver.h

View File

@@ -1,7 +1,7 @@
/*
* asp.c -- Active Server Page Support
*
* Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
*
* See the file "license.txt" for usage and redistribution license requirements
*/
@@ -20,11 +20,12 @@
/********************************** Locals ************************************/
static sym_fd_t websAspFunctions = -1; /* Symbol table of functions */
static sym_fd_t websAspFunctions = -1; /* Symbol table of functions */
static int aspOpenCount = 0; /* count of apps using this module */
/***************************** 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);
/************************************* Code ***********************************/
@@ -34,15 +35,17 @@ static char_t *skipWhite(char_t *s);
int websAspOpen()
{
if (++aspOpenCount == 1) {
/*
* Create the table for ASP functions
*/
websAspFunctions = symOpen(128);
websAspFunctions = symOpen(WEBS_SYM_INIT * 2);
/*
* Create standard ASP commands
*/
websAspDefine(T("write"), websAspWrite);
websAspDefine(T("write"), websAspWrite);
}
return 0;
}
@@ -53,8 +56,11 @@ int websAspOpen()
void websAspClose()
{
if (websAspFunctions != -1) {
symClose(websAspFunctions, NULL);
if (--aspOpenCount <= 0) {
if (websAspFunctions != -1) {
symClose(websAspFunctions);
websAspFunctions = -1;
}
}
}
@@ -65,7 +71,7 @@ void websAspClose()
* 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;
char *rbuf;
@@ -84,7 +90,7 @@ int websAspRequest(webs_t wp, char_t* lpath)
path = websGetRequestPath(wp);
/*
* Create Ejscript instance incase it is needed
* Create Ejscript instance in case it is needed
*/
ejid = ejOpenEngine(wp->cgiVars, websAspFunctions);
if (ejid < 0) {
@@ -112,12 +118,12 @@ int websAspRequest(webs_t wp, char_t* lpath)
websError(wp, 200, T("Cant read %s"), lpath);
goto done;
}
websCloseFileHandle(wp);
websPageClose(wp);
/*
* Convert to UNICODE if necessary.
*/
if ((buf = ballocAscToUni(rbuf)) == NULL) {
if ((buf = ballocAscToUni(rbuf, len)) == NULL) {
websError(wp, 200, T("Can't get memory"));
goto done;
}
@@ -220,7 +226,7 @@ int websAspRequest(webs_t wp, char_t* lpath)
*/
done:
if (websValid(wp)) {
websCloseFileHandle(wp);
websPageClose(wp);
if (ejid >= 0) {
ejCloseEngine(ejid);
}
@@ -252,9 +258,9 @@ int websAspWrite(int ejid, webs_t wp, int argc, char_t **argv)
int i;
a_assert(websValid(wp));
a_assert(argv);
for (i = 0; i < argc; ) {
a_assert(argv);
if (websWriteBlock(wp, argv[i], gstrlen(argv[i])) < 0) {
return -1;
}
@@ -273,7 +279,7 @@ int websAspWrite(int ejid, webs_t wp, int argc, char_t **argv)
* 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;
@@ -310,4 +316,4 @@ static char_t *skipWhite(char_t *s)
return s;
}
/******************************************************************************/
/******************************************************************************/

View File

@@ -1,7 +1,7 @@
/*
* balloc.c -- Block allocation module
*
* Copyright (c) GoAhead Software Inc., 1995-1999. All Rights Reserved.
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
*
* See the file "license.txt" for usage and redistribution license requirements
*/
@@ -11,7 +11,7 @@
/*
* This module implements a very fast block allocation scheme suitable for
* ROMed environments. It maintains block class queues for rapid allocation
* and minimal fragmentation. This modules does not coalesce blocks. The
* and minimal fragmentation. This module does not coalesce blocks. The
* storage space may be populated statically or via the traditional malloc
* mechanisms. Large blocks greater than the maximum class size may be
* allocated from the O/S or run-time system via malloc. To permit the use
@@ -38,14 +38,6 @@
#if !NO_BALLOC
/********************************* Defines ************************************/
typedef struct {
union {
void *next; /* Pointer to next in q */
int size; /* Actual requested size */
} u;
int flags; /* Per block allocation flags */
} bType;
/*
* Define B_STATS if you wish to track memory block and stack usage
*/
@@ -63,7 +55,9 @@ typedef struct {
char_t file[FNAMESIZE];
long allocated; /* Bytes currently allocated */
long count; /* Current block count */
long allocs; /* Count of alloc attempts */
long times; /* Count of alloc attempts */
long largest; /* largest allocated here */
int q;
} bStatsFileType;
/*
@@ -77,15 +71,26 @@ typedef struct {
static bStatsType bStats[B_MAX_CLASS]; /* Per class stats */
static bStatsFileType bStatsFiles[B_MAX_FILES];/* Per file stats */
static bStatsBlkType bStatsBlks[B_MAX_BLOCKS];/* Per block stats */
static int bStatsBlksMax; /* Max block entry */
static int bStatsFilesMax; /* Max file entry */
static int bStatsMemInUse; /* Memory currently in use */
static int bStatsMemMax; /* Max memory ever used */
static int bStatsBlksMax = 0; /* Max block entry */
static int bStatsFilesMax = 0; /* Max file entry */
static int bStatsMemInUse = 0; /* Memory currently in use */
static int bStatsBallocInUse = 0; /* Memory currently balloced */
static int bStatsMemMax = 0; /* Max memory ever used */
static int bStatsBallocMax = 0; /* Max memory ever balloced */
static void *bStackMin = (void*) -1;/* Miniumum stack position */
static void *bStackStart; /* Starting stack position */
static int bStatsMemMalloc; /* Malloced memory */
static int bStatsMemMalloc = 0; /* Malloced memory */
#endif /* B_STATS */
/*
* ROUNDUP4(size) returns the next higher integer value of size that is
* divisible by 4, or the value of size if size is divisible by 4.
* ROUNDUP4() is used in aligning memory allocations on 4-byte boundaries.
*
* Note: ROUNDUP4() is only required on some operating systems (IRIX).
*/
#define ROUNDUP4(size) ((size) % 4) ? (size) + (4 - ((size) % 4)) : (size)
/********************************** Locals ************************************/
/*
@@ -98,6 +103,7 @@ static char *bFreeNext; /* Pointer to next free mem */
static int bFreeSize; /* Size of free memory */
static int bFreeLeft; /* Size of free left for use */
static int bFlags = B_USE_MALLOC; /* Default to auto-malloc */
static int bopenCount = 0; /* Num tasks using balloc */
/*************************** Forward Declarations *****************************/
@@ -115,9 +121,11 @@ static void bFillBlock(void *buf, int bufsize);
#if B_VERIFY_CAUSES_SEVERE_OVERHEAD
static void verifyUsedBlock(bType *bp, int q);
static void verifyFreeBlock(bType *bp, int q);
static void verifyBallocSpace();
void verifyBallocSpace();
#endif
static int ballocGetSize(int size, int *q);
/********************************** Code **************************************/
/*
* Initialize the balloc module. bopen should be called the very first thing
@@ -133,10 +141,25 @@ int bopen(void *buf, int bufsize, int flags)
{
bFlags = flags;
#if BASTARD_TESTING
srand(time(0L));
#endif /* BASTARD_TESTING */
/*
* If bopen already called by a shared process, just increment the count
* and return;
*/
if (++bopenCount > 1) {
return 0;
}
if (buf == NULL) {
if (bufsize == 0) {
bufsize = B_DEFAULT_MEM;
}
#ifdef IRIX
bufsize = ROUNDUP4(bufsize);
#endif
if ((buf = malloc(bufsize)) == NULL) {
return -1;
}
@@ -149,6 +172,7 @@ int bopen(void *buf, int bufsize, int flags)
bFreeSize = bFreeLeft = bufsize;
bFreeBuf = bFreeNext = buf;
memset(bQhead, 0, sizeof(bQhead));
#if B_FILL || B_VERIFY_CAUSES_SEVERE_OVERHEAD
bFillBlock(buf, bufsize);
#endif
@@ -171,8 +195,9 @@ void bclose()
#if B_VERIFY_CAUSES_SEVERE_OVERHEAD
verifyBallocSpace();
#endif
if (! (bFlags & B_USER_BUF)) {
if (--bopenCount <= 0 && !(bFlags & B_USER_BUF)) {
free(bFreeBuf);
bopenCount = 0;
}
}
@@ -185,13 +210,13 @@ void bclose()
void *balloc(B_ARGS_DEC, int size)
{
bType *bp;
int q, memSize, mask;
int q, memSize;
/*
* Call bopen with default values if the application has not yet done so
*/
if (bFreeBuf == NULL) {
if (bopen(NULL, B_DEFAULT_MEM , 0) < 0) {
if (bopen(NULL, B_DEFAULT_MEM, 0) < 0) {
return NULL;
}
}
@@ -202,17 +227,14 @@ void *balloc(B_ARGS_DEC, int size)
return NULL;
}
/*
* Determine the relevant block queue with a block big enough --
* include room for the block header.
*/
mask = (size + sizeof(bType)) >> B_SHIFT;
for (q = 0; mask; mask >>= 1) {
q++;
#if BASTARD_TESTING
if (rand() == 0x7fff) {
return NULL;
}
#endif /* BASTARD_TESTING */
a_assert(0 <= q && q <= B_MAX_CLASS);
memSize = (1 << (B_SHIFT + q));
memSize = ballocGetSize(size, &q);
if (q >= B_MAX_CLASS) {
/*
@@ -221,11 +243,13 @@ void *balloc(B_ARGS_DEC, int size)
if (bFlags & B_USE_MALLOC) {
#if B_STATS
bstats(0, NULL);
#endif
#ifdef IRIX
memSize = ROUNDUP4(memSize);
#endif
bp = (bType*) malloc(memSize);
if (bp == NULL) {
goahead_trace(0, T("B: malloc failed for %s:%d, size %d\n"),
B_ARGS, memSize);
traceRaw(T("B: malloc failed\n"));
return NULL;
}
#if B_STATS
@@ -236,11 +260,14 @@ void *balloc(B_ARGS_DEC, int size)
#endif
} else {
goahead_trace(0, T("B: balloc failed for %s:%d, size %d\n"),
B_ARGS, memSize);
traceRaw(T("B: malloc failed\n"));
return NULL;
}
bp->u.size = size;
/*
* the u.size is the actual size allocated for data
*/
bp->u.size = memSize - sizeof(bType);
bp->flags = B_MALLOCED;
} else if ((bp = bQhead[q]) != NULL) {
@@ -254,7 +281,7 @@ void *balloc(B_ARGS_DEC, int size)
#if B_FILL || B_VERIFY_CAUSES_SEVERE_OVERHEAD
bFillBlock(bp, memSize);
#endif
bp->u.size = size;
bp->u.size = memSize - sizeof(bType);
bp->flags = 0;
} else {
@@ -272,22 +299,24 @@ void *balloc(B_ARGS_DEC, int size)
#if B_FILL || B_VERIFY_CAUSES_SEVERE_OVERHEAD
bFillBlock(bp, memSize);
#endif
bp->u.size = size;
bp->u.size = memSize - sizeof(bType);
bp->flags = 0;
} else if (bFlags & B_USE_MALLOC) {
static int once = 0;
if (once++ < 20) {
#if B_STATS
static int once = 0;
if (once++ == 0) {
bstats(0, NULL);
#endif
}
#endif
/*
* Nothing left on the primary free list, so malloc a new block
*/
#ifdef IRIX
memSize = ROUNDUP4(memSize);
#endif
if ((bp = (bType*) malloc(memSize)) == NULL) {
goahead_trace(0, T("B: malloc failed for %s:%d size %d\n"),
B_ARGS, memSize);
traceRaw(T("B: malloc failed\n"));
return NULL;
}
#if B_STATS
@@ -296,20 +325,31 @@ void *balloc(B_ARGS_DEC, int size)
#if B_FILL || B_VERIFY_CAUSES_SEVERE_OVERHEAD
bFillBlock(bp, memSize);
#endif
bp->u.size = size;
bp->u.size = memSize - sizeof(bType);
bp->flags = B_MALLOCED;
} else {
goahead_trace(0, T("B: alloc failed for %s:%d size %d\n"), B_ARGS, size);
traceRaw(T("B: malloc failed\n"));
return NULL;
}
}
#if B_STATS
bStatsAlloc(B_ARGS, bp, q, size);
bStatsAlloc(B_ARGS, bp, q, memSize);
#endif
bp->flags |= B_INTEGRITY;
/*
* The following is a good place to put a breakpoint when trying to reduce
* determine and reduce maximum memory use.
*/
#if 0
#if B_STATS
if (bStatsBallocInUse == bStatsBallocMax) {
bstats(0, NULL);
}
#endif
#endif
return (void*) ((char*) bp + sizeof(bType));
}
@@ -323,41 +363,34 @@ void *balloc(B_ARGS_DEC, int size)
void bfree(B_ARGS_DEC, void *mp)
{
bType *bp;
int mask, q;
int q, memSize;
#if B_VERIFY_CAUSES_SEVERE_OVERHEAD
verifyBallocSpace();
#endif
a_assert(mp);
bp = (bType*) ((char*) mp - sizeof(bType));
a_assert((bp->flags & B_INTEGRITY_MASK) == B_INTEGRITY);
if ((bp->flags & B_INTEGRITY_MASK) != B_INTEGRITY) {
return;
}
/*
* Determine the relevant block queue
*/
mask = (bp->u.size + sizeof(bType)) >> B_SHIFT;
for (q = 0; mask; mask >>= 1) {
q++;
}
a_assert(0 <= q && q <= B_MAX_CLASS);
memSize = ballocGetSize(bp->u.size, &q);
#if B_VERIFY_CAUSES_SEVERE_OVERHEAD
verifyUsedBlock(bp,q);
#endif
#if B_STATS
bStatsFree(B_ARGS, bp, q, bp->u.size+sizeof(bType));
#endif
if (bp->flags & B_MALLOCED) {
free(bp);
return;
}
#if B_STATS
bStatsFree(B_ARGS, bp, q, bp->u.size);
#endif
#if B_VERIFY_CAUSES_SEVERE_OVERHEAD
bFillBlock(bp, 1 << (B_SHIFT + q));
bFillBlock(bp, memSize);
#endif
/*
@@ -365,6 +398,8 @@ void bfree(B_ARGS_DEC, void *mp)
*/
bp->u.next = bQhead[q];
bQhead[q] = bp;
bp->flags = B_FILL_WORD;
}
/******************************************************************************/
@@ -432,7 +467,7 @@ char_t *bstrdup(B_ARGS_DEC, char_t *s)
void *brealloc(B_ARGS_DEC, void *mp, int newsize)
{
bType* bp;
bType *bp;
void *newbuf;
if (mp == NULL) {
@@ -440,6 +475,14 @@ void *brealloc(B_ARGS_DEC, void *mp, int newsize)
}
bp = (bType*) ((char*) mp - sizeof(bType));
a_assert((bp->flags & B_INTEGRITY_MASK) == B_INTEGRITY);
/*
* If the allocated memory already has enough room just return the previously
* allocated address.
*/
if (bp->u.size >= newsize) {
return mp;
}
if ((newbuf = balloc(B_ARGS, newsize)) != NULL) {
memcpy(newbuf, mp, bp->u.size);
bfree(B_ARGS, mp);
@@ -447,6 +490,24 @@ void *brealloc(B_ARGS_DEC, void *mp, int newsize)
return newbuf;
}
/******************************************************************************/
/*
* Find the size of the block to be balloc'ed. It takes in a size, finds the
* smallest binary block it fits into, adds an overhead amount and returns.
* q is the binary size used to keep track of block sizes in use. Called
* from both balloc and bfree.
*/
static int ballocGetSize(int size, int *q)
{
int mask;
mask = (size == 0) ? 0 : (size-1) >> B_SHIFT;
for (*q = 0; mask; mask >>= 1) {
*q = *q + 1;
}
return ((1 << (B_SHIFT + *q)) + sizeof(bType));
}
/******************************************************************************/
#if B_FILL || B_VERIFY_CAUSES_SEVERE_OVERHEAD
@@ -464,17 +525,20 @@ static void bFillBlock(void *buf, int bufsize)
#if B_STATS
/*
* Statistics. Do output via calling the writefn callback function with
* "handle" as the output file handle.
* "handle" as the output file handle.
*/
void bstats(int handle, void (*writefn)(int handle, char_t *fmt, ...))
{
bStatsFileType *fp;
bStatsFileType *fp, *files;
bStatsBlkType *blkp;
bType *bp;
int q, count, mem, total;
char_t *cp;
int q, count, mem, total, len;
static int recurseProtect = 0;
if (recurseProtect++ > 0) {
recurseProtect--;
return;
}
@@ -492,19 +556,18 @@ void bstats(int handle, void (*writefn)(int handle, char_t *fmt, ...))
* Q Size Free Bytes Inuse Bytes Allocs
* dd ddddd ddd ddddd dddd ddddd dddd
*/
(*writefn)(handle, " Q Size Free Bytes Inuse Bytes Allocs\n");
(*writefn)(handle, " Q Size Free Bytes Inuse Bytes Allocs\n");
total = 0;
for (q = 0; q < B_MAX_CLASS; q++) {
count = 0;
for (bp = bQhead[q]; bp; bp = bp->u.next) {
a_assert((bp->flags & B_INTEGRITY_MASK) == B_INTEGRITY);
count++;
}
mem = count * (1 << (q + B_SHIFT));
total += mem;
(*writefn)(handle,
T("%2d %5d %3d %5d %4d %5d %4d\n"),
T("%2d %5d %4d %6d %4d %5d %4d\n"),
q, 1 << (q + B_SHIFT), count, mem, bStats[q].inuse,
bStats[q].inuse * (1 << (q + B_SHIFT)), bStats[q].alloc);
}
@@ -513,11 +576,26 @@ void bstats(int handle, void (*writefn)(int handle, char_t *fmt, ...))
/*
* Print summary stats
*
* bFreeSize Initial memory reserved with bopen call
* bStatsMemMalloc memory from calls to system MALLOC
* bStatsMemMax
* bStatsBallocMax largest amount of memory from balloc calls
* bStatsMemInUse
* bStatsBallocInUse present balloced memory being used
* bStatsBlksMax);
* bStackStart
* bStackMin);
* total);
* bFreeLeft);
*
*/
(*writefn)(handle, T("Initial free list size %7d\n"), bFreeSize);
(*writefn)(handle, T("Max memory malloced %7d\n"), bStatsMemMalloc);
(*writefn)(handle, T("Max memory ever used %7d\n"), bStatsMemMax);
(*writefn)(handle, T("Max memory ever balloced %7d\n"), bStatsBallocMax);
(*writefn)(handle, T("Memory currently in use %7d\n"), bStatsMemInUse);
(*writefn)(handle, T("Memory currently balloced %7d\n"), bStatsBallocInUse);
(*writefn)(handle, T("Max blocks allocated %7d\n"), bStatsBlksMax);
(*writefn)(handle, T("Maximum stack used %7d\n"),
(int) bStackStart - (int) bStackMin);
@@ -527,20 +605,49 @@ void bstats(int handle, void (*writefn)(int handle, char_t *fmt, ...))
(*writefn)(handle, T("Total free memory %7d\n"), bFreeLeft + total);
/*
* Print per file allocation stats
* Print per file allocation stats. Sort the copied table.
*/
qsort(bStatsFiles, bStatsFilesMax, sizeof(bStatsFileType), bStatsFileSort);
(*writefn)(handle, T("\nPer File Memory Stats\n"));
len = sizeof(bStatsFileType) * B_MAX_FILES;
files = malloc(len);
if (files == NULL) {
(*writefn)(handle, T("Can't allocate stats memory\n"));
recurseProtect--;
return;
}
memcpy(files, bStatsFiles, len);
qsort(files, bStatsFilesMax, sizeof(bStatsFileType), bStatsFileSort);
(*writefn)(handle, T("\nMemory Currently Allocated\n"));
total = 0;
for (fp = bStatsFiles; fp < &bStatsFiles[bStatsFilesMax]; fp++) {
(*writefn)(handle,
T(" bytes, blocks in use, total times,")
T("largest, q\n"));
for (fp = files; fp < &files[bStatsFilesMax]; fp++) {
if (fp->file[0]) {
(*writefn)(handle,
T("%18s, bytes %7d, blocks in use %5d, total allocs %6d\n"),
fp->file, fp->allocated, fp->count, fp->allocs);
(*writefn)(handle, T("%18s, %7d, %5d, %6d, %7d,%4d\n"),
fp->file, fp->allocated, fp->count, fp->times, fp->largest,
fp->q);
total += fp->allocated;
}
}
(*writefn)(handle, T("\nTotal allocated %7d\n"), total);
(*writefn)(handle, T("\nTotal allocated %7d\n\n"), total);
/*
* Dump the actual strings
*/
(*writefn)(handle, T("\nStrings\n"));
for (blkp = &bStatsBlks[bStatsBlksMax - 1]; blkp >= bStatsBlks; blkp--) {
if (blkp->ptr) {
cp = (char_t*) ((char*) blkp->ptr + sizeof(bType));
fp = blkp->who;
if (gisalnum(*cp)) {
(*writefn)(handle, T("%-50s allocated by %s\n"), cp,
fp->file);
}
}
}
free(files);
recurseProtect--;
}
@@ -563,26 +670,6 @@ static int bStatsFileSort(const void *cp1, const void *cp2)
return 1;
}
/******************************************************************************/
/*
* Default output function. Just send to trace channel.
*/
static void bstatsWrite(int handle, char_t *fmt, ...)
{
va_list args;
char_t *buf;
va_start(args, fmt);
buf = NULL;
gvsnprintf(&buf, VALUE_MAX_STRING, fmt, args);
va_end(args);
goahead_trace(0, buf);
if (buf) {
bfree(B_L, buf);
}
}
/******************************************************************************/
/*
* Accumulate allocation statistics
@@ -590,23 +677,24 @@ static void bstatsWrite(int handle, char_t *fmt, ...)
static void bStatsAlloc(B_ARGS_DEC, void *ptr, int q, int size)
{
int memSize;
bStatsFileType *fp;
bStatsBlkType *bp;
char_t name[FNAMESIZE + 10];
a_assert(file && *file);
a_assert(0 <= q && q <= B_MAX_CLASS);
a_assert(size > 0);
gsprintf(name, T("%s:%d"), B_ARGS);
bStats[q].alloc++;
bStats[q].inuse++;
bStatsMemInUse += size;
if (bStatsMemInUse > bStatsMemMax) {
bStatsMemMax = bStatsMemInUse;
}
memSize = (1 << (B_SHIFT + q)) + sizeof(bType);
bStatsBallocInUse += memSize;
if (bStatsBallocInUse > bStatsBallocMax) {
bStatsBallocMax = bStatsBallocInUse;
}
/*
* Track maximum stack usage. Assumes a stack growth down. Approximate as
@@ -623,13 +711,17 @@ static void bStatsAlloc(B_ARGS_DEC, void *ptr, int q, int size)
if (fp->file[0] == file[0] && gstrcmp(fp->file, name) == 0) {
fp->allocated += size;
fp->count++;
fp->allocs++;
fp->times++;
if (fp->largest < size) {
fp->largest = size;
fp->q = q;
}
break;
}
}
/*
* Find the first free slot for this file and add current block size.
* New entry: find the first free slot and create a new entry
*/
if (fp >= &bStatsFiles[bStatsFilesMax]) {
for (fp = bStatsFiles; fp < &bStatsFiles[B_MAX_FILES]; fp++) {
@@ -637,7 +729,9 @@ static void bStatsAlloc(B_ARGS_DEC, void *ptr, int q, int size)
gstrncpy(fp->file, name, TSZ(fp->file));
fp->allocated += size;
fp->count++;
fp->allocs++;
fp->times++;
fp->largest = size;
fp->q = q;
if ((fp - bStatsFiles) >= bStatsFilesMax) {
bStatsFilesMax = (fp - bStatsFiles) + 1;
}
@@ -668,35 +762,48 @@ static void bStatsAlloc(B_ARGS_DEC, void *ptr, int q, int size)
static void bStatsFree(B_ARGS_DEC, void *ptr, int q, int size)
{
int memSize;
bStatsFileType *fp;
bStatsBlkType *bp;
char_t name[FNAMESIZE + 10];
a_assert(file && *file);
a_assert(0 <= q && q <= B_MAX_CLASS);
a_assert(size > 0);
memSize = (1 << (B_SHIFT + q)) + sizeof(bType);
bStatsMemInUse -= size;
bStatsBallocInUse -= memSize;
bStats[q].inuse--;
gsprintf(name, T("%s:%d"), B_ARGS);
/*
* Update the per block stats
* Update the per block stats. Try from the end first
*/
for (bp = bStatsBlks; bp < &bStatsBlks[bStatsBlksMax]; bp++) {
for (bp = &bStatsBlks[bStatsBlksMax - 1]; bp >= bStatsBlks; bp--) {
if (bp->ptr == ptr) {
bp->ptr = NULL;
fp = bp->who;
bp->who = NULL;
fp->allocated -= size;
fp->count--;
return;
}
}
a_assert(0);
}
/******************************************************************************/
/*
* Default output function. Just send to trace channel.
*/
#undef sprintf
static void bstatsWrite(int handle, char_t *fmt, ...)
{
va_list args;
char_t buf[BUF_MAX];
va_start(args, fmt);
vsprintf(buf, fmt, args);
va_end(args);
traceRaw(buf);
}
#else /* not B_STATS */
/******************************************************************************/
/*
@@ -712,10 +819,10 @@ void bstats(int handle, void (*writefn)(int handle, char_t *fmt, ...))
#if B_VERIFY_CAUSES_SEVERE_OVERHEAD
/*
* The following routines verify the integrity of the balloc memory space.
* These functions depend use the B_FILL feature. Corruption is defined
* These functions use the B_FILL feature. Corruption is defined
* as bad integrity flags in allocated blocks or data other than B_FILL_CHAR
* being found anywhere in the space which is unallocated and that is not a
* next pointer in the free queues. a_assert is called if any corruption is
* next pointer in the free queues. a_assert is called if any corruption is
* found. CAUTION: These functions add severe processing overhead and should
* only be used when searching for a tough corruption problem.
*/
@@ -731,8 +838,8 @@ static void verifyUsedBlock(bType *bp, int q)
int memSize, size;
char *p;
memSize = (1 << (B_SHIFT + q));
a_assert((bp->flags & ~B_MALLOCED) == B_INTEGRITY );
memSize = (1 << (B_SHIFT + q)) + sizeof(bType);
a_assert((bp->flags & ~B_MALLOCED) == B_INTEGRITY);
size = bp->u.size;
for (p = ((char *)bp)+sizeof(bType)+size; p < ((char*)bp)+memSize; p++) {
a_assert(*p == B_FILL_CHAR);
@@ -750,28 +857,41 @@ static void verifyFreeBlock(bType *bp, int q)
int memSize;
char *p;
memSize = (1 << (B_SHIFT + q));
memSize = (1 << (B_SHIFT + q)) + sizeof(bType);
for (p = ((char *)bp)+sizeof(void*); p < ((char*)bp)+memSize; p++) {
a_assert(*p == B_FILL_CHAR);
}
bp = (bType *)p;
a_assert((bp->flags & ~B_MALLOCED) == B_INTEGRITY ||
bp->flags == B_FILL_WORD);
bp->flags == B_FILL_WORD);
}
/******************************************************************************/
/*
* verifyBallocSpace reads through the entire balloc memory space and
* verifies that all allocated blocks are uncorrupted and that with the
* exception of free list next pointers all other unallocated space is
* verifies that all allocated blocks are uncorrupted and that, with the
* exception of free list next pointers, all other unallocated space is
* filled with B_FILL_CHAR.
*/
static void verifyBallocSpace()
void verifyBallocSpace()
{
int q;
char *p;
bType *bp;
/*
* First verify all the free blocks.
*/
for (q = 0; q < B_MAX_CLASS; q++) {
for (bp = bQhead[q]; bp != NULL; bp = bp->u.next) {
verifyFreeBlock(bp, q);
}
}
/*
* Now verify other space
*/
p = bFreeBuf;
while (p < (bFreeBuf + bFreeSize)) {
bp = (bType *)p;
@@ -782,7 +902,7 @@ static void verifyBallocSpace()
}
} else {
a_assert(((bp->flags & ~B_MALLOCED) == B_INTEGRITY) ||
bp->flags == B_FILL_WORD);
bp->flags == B_FILL_WORD);
p += (sizeof(bType) + bp->u.size);
while (p < (bFreeBuf + bFreeSize) && *p == B_FILL_CHAR) {
p++;
@@ -807,19 +927,29 @@ void bclose()
}
/******************************************************************************/
#if UNICODE
char_t* bstrdupNoBalloc(char_t* s)
void bstats(int handle, void (*writefn)(int handle, char_t *fmt, ...))
{
}
/******************************************************************************/
char_t *bstrdupNoBalloc(char_t *s)
{
#if UNICODE
if (s) {
return wcsdup(s);
} else {
return wcsdup(T(""));
}
#else
return bstrdupANoBalloc(s);
#endif
}
#endif /* UNICODE */
/******************************************************************************/
char* bstrdupANoBalloc(char* s)
char *bstrdupANoBalloc(char *s)
{
char* buf;

View File

@@ -1,7 +1,7 @@
/*
* base64.c -- Base64 Mime encoding
*
* Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
*
* See the file "license.txt" for usage and redistribution license requirements
*/
@@ -60,11 +60,10 @@ static char_t alphabet64[] = {
* Decode a buffer from "string" and into "outbuf"
*/
int websDecode64(char_t* outbuf, char_t* string, int outlen)
int websDecode64(char_t *outbuf, char_t *string, int outlen)
{
unsigned long shiftbuf;
char_t* cp;
char_t* op;
char_t *cp, *op;
int c, i, j, shift;
op = outbuf;
@@ -109,11 +108,10 @@ int websDecode64(char_t* outbuf, char_t* string, int outlen)
* Encode a buffer from "string" into "outbuf"
*/
void websEncode64(char_t* outbuf, char_t* string, int outlen)
void websEncode64(char_t *outbuf, char_t *string, int outlen)
{
unsigned long shiftbuf;
char_t* cp;
char_t* op;
char_t *cp, *op;
int x, i, j, shift;
op = outbuf;

View File

@@ -1,9 +1,11 @@
/*
* default.c -- Default URL handler. Includes support for ASP.
*
* Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
*
* See the file "license.txt" for usage and redistribution license requirements
*
* $Id$
*/
/******************************** Description *********************************/
@@ -38,16 +40,15 @@ static void websDefaultWriteEvent(webs_t wp);
*/
int websDefaultHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg,
char_t *url, char_t *path, char_t* query)
char_t *url, char_t *path, char_t *query)
{
websStatType sbuf;
char_t *lpath, *tmp;
char_t *date;
char_t *lpath, *tmp, *date;
int bytes, flags, nchars;
a_assert(websValid(wp));
a_assert(url && *url);
a_assert(path && *path);
a_assert(path);
a_assert(query);
/*
@@ -74,8 +75,7 @@ int websDefaultHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg,
path[--nchars] = '\0';
}
nchars += gstrlen(websDefaultPage) + 2;
tmp = NULL;
gsnprintf(&tmp, nchars, T("%s/%s"), path, websDefaultPage);
fmtAlloc(&tmp, nchars, T("%s/%s"), path, websDefaultPage);
websRedirect(wp, tmp);
bfreeSafe(B_L, tmp);
return 1;
@@ -87,13 +87,13 @@ int websDefaultHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg,
if (websPageOpen(wp, lpath, path, SOCKET_RDONLY | SOCKET_BINARY,
0666) < 0) {
websError(wp, 400,
T("Can't open document <b>%s</b><br>for URL <b>%s</b>"),
lpath, url);
T("Cannot open URL <b>%s</b>"), url);
return 1;
}
if (websPageStat(wp, lpath, path, &sbuf) < 0) {
websError(wp, 400, T("Can't stat page <b>%s</b><br>for URL <b>%s</b>"),
lpath, url);
websError(wp, 400, T("Cannot stat page for URL <b>%s</b>"),
url);
return 1;
}
/*
@@ -107,12 +107,13 @@ int websDefaultHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg,
if (sbuf.mtime <= wp->since) {
websWrite(wp, T("HTTP/1.0 304 Use local copy\r\n"));
/* by license terms the following line of code must
* not be modified.
*/
websWrite(wp, T("Server: GoAhead-Webs\r\n"));
/*
* by license terms the following line of code must
* not be modified.
*/
websWrite(wp, T("Server: %s\r\n"), WEBS_NAME);
if (flags && WEBS_KEEP_ALIVE) {
if (flags & WEBS_KEEP_ALIVE) {
websWrite(wp, T("Connection: keep-alive\r\n"));
}
websWrite(wp, T("\r\n"));
@@ -131,8 +132,8 @@ int websDefaultHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg,
/*
* By license terms the following line of code must not be modified.
*/
websWrite(wp, T("Server: GoAhead-Webs\r\n"));
*/
websWrite(wp, T("Server: %s\r\n"), WEBS_NAME);
bfree(B_L, date);
}
flags |= WEBS_HEADER_DONE;
@@ -164,6 +165,14 @@ int websDefaultHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg,
}
websWrite(wp, T("\r\n"));
/*
* All done if the browser did a HEAD request
*/
if (flags & WEBS_HEAD_REQUEST) {
websDone(wp, 200);
return 1;
}
/*
* Evaluate ASP requests
*/
@@ -175,17 +184,18 @@ int websDefaultHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg,
return 1;
}
/*
* All done if the browser did a HEAD request
*/
if (flags & WEBS_HEAD_REQUEST) {
websDone(wp, 200);
return 1;
#ifdef WEBS_SSL_SUPPORT
if (wp->flags & WEBS_SECURE) {
websDefaultWriteEvent(wp);
} else {
websSetRequestSocketHandler(wp, SOCKET_WRITABLE, websDefaultWriteEvent);
}
#else
/*
* For normal web documents, return the data via background write
*/
websSetRequestSocketHandler(wp, SOCKET_WRITABLE, websDefaultWriteEvent);
#endif
return 1;
}
@@ -240,7 +250,7 @@ int websValidateUrl(webs_t wp, char_t *path)
/*
* Create local path for document. Need extra space all "/" and null.
*/
if (npart) {
if (npart || (gstrcmp(path, T("/")) == 0) || (path[0] == '\0')) {
lpath = balloc(B_L, (gstrlen(dir) + 1 + len + 1) * sizeof(char_t));
gstrcpy(lpath, dir);
@@ -267,15 +277,16 @@ int websValidateUrl(webs_t wp, char_t *path)
static void websDefaultWriteEvent(webs_t wp)
{
int len, wrote, flags, bytes, written;
char * buf;
int len, wrote, flags, bytes, written;
char *buf;
a_assert(websValid(wp));
flags = websGetRequestFlags(wp);
wrote = 0;
bytes = 0;
websMarkTime(wp);
wrote = bytes = 0;
written = websGetRequestWritten(wp);
/*
@@ -284,20 +295,20 @@ static void websDefaultWriteEvent(webs_t wp)
if ( !(flags & WEBS_ASP)) {
bytes = websGetRequestBytes(wp);
/*
* Note: websWriteBlock may return less than we wanted. It will return
* -1 on a socket error
* Note: websWriteDataNonBlock may return less than we wanted. It will
* return -1 on a socket error
*/
if ((buf = balloc(B_L, PAGE_READ_BUFSIZE)) == NULL) {
websError(wp, 200, T("Can't get memory"));
}
else {
while ((len = websPageReadData(wp, buf, PAGE_READ_BUFSIZE)) > 0) {
if ((wrote = websWriteBlockData(wp, buf, len)) < 0) {
if ((wrote = websWriteDataNonBlock(wp, buf, len)) < 0) {
break;
}
written += wrote;
if (wrote != len) {
websPageSeek(wp, - (wrote - len));
websPageSeek(wp, - (len - wrote));
break;
}
}
@@ -330,9 +341,11 @@ void websDefaultClose()
{
if (websDefaultPage) {
bfree(B_L, websDefaultPage);
websDefaultPage = NULL;
}
if (websDefaultDir) {
bfree(B_L, websDefaultDir);
websDefaultDir = NULL;
}
}

View File

@@ -1,7 +1,7 @@
/*
* ej.h -- Ejscript(TM) header
*
* Copyright (c) Go Ahead Software, Inc., 1992-1999
* Copyright (c) GoAhead Software Inc., 1992-2000. All Rights Reserved.
*
* See the file "license.txt" for information on usage and redistribution
*/
@@ -12,214 +12,32 @@
/******************************** Description *********************************/
/*
* Go Ahead Ejscript(TM) header. This defines the Ejscript API and internal
* GoAhead Ejscript(TM) header. This defines the Ejscript API and internal
* structures.
*/
/********************************* Includes ***********************************/
#include <ctype.h>
#include <stdarg.h>
#include <stdlib.h>
#ifndef CE
#include <fcntl.h>
#endif
#if LYNX
#include <unistd.h>
#endif
#ifdef QNX4
#include <dirent.h>
#endif
#if UEMF
#include "uemf.h"
#else
#include <param.h>
#include <stat.h>
#include "basic/basicInternal.h"
#if ! UEMF
#include "basic/basic.h"
#include "emf/emf.h"
#include "webs/webs.h"
#else
#include "uemf.h"
#endif
/********************************** Defines ***********************************/
/*
* Constants
*/
#define EJ_INC 110 /* Growth for tags/tokens */
#define EJ_OFFSET 1 /* hAlloc doesn't like 0 entries */
#define EJ_MAX_RECURSE 100 /* Sanity for maximum recursion */
/*
* Ejscript Lexical analyser tokens
*/
#define TOK_ERR -1 /* Any error */
#define TOK_LPAREN 1 /* ( */
#define TOK_RPAREN 2 /* ) */
#define TOK_IF 3 /* if */
#define TOK_ELSE 4 /* else */
#define TOK_LBRACE 5 /* { */
#define TOK_RBRACE 6 /* } */
#define TOK_LOGICAL 7 /* ||, &&, ! */
#define TOK_EXPR 8 /* +, -, /, % */
#define TOK_SEMI 9 /* ; */
#define TOK_LITERAL 10 /* literal string */
#define TOK_FUNCTION 11 /* function name */
#define TOK_NEWLINE 12 /* newline white space */
#define TOK_ID 13 /* function name */
#define TOK_EOF 14 /* End of script */
#define TOK_COMMA 15 /* Comma */
#define TOK_VAR 16 /* var */
#define TOK_ASSIGNMENT 17 /* = */
#define TOK_FOR 18 /* for */
#define TOK_INC_DEC 19 /* ++, -- */
#define TOK_RETURN 20 /* return */
/*
* Expression operators
*/
#define EXPR_LESS 1 /* < */
#define EXPR_LESSEQ 2 /* <= */
#define EXPR_GREATER 3 /* > */
#define EXPR_GREATEREQ 4 /* >= */
#define EXPR_EQ 5 /* == */
#define EXPR_NOTEQ 6 /* != */
#define EXPR_PLUS 7 /* + */
#define EXPR_MINUS 8 /* - */
#define EXPR_DIV 9 /* / */
#define EXPR_MOD 10 /* % */
#define EXPR_LSHIFT 11 /* << */
#define EXPR_RSHIFT 12 /* >> */
#define EXPR_MUL 13 /* * */
#define EXPR_ASSIGNMENT 14 /* = */
#define EXPR_INC 15 /* ++ */
#define EXPR_DEC 16 /* -- */
/*
* Conditional operators
*/
#define COND_AND 1 /* && */
#define COND_OR 2 /* || */
#define COND_NOT 3 /* ! */
/*
* States
*/
#define STATE_ERR -1 /* Error state */
#define STATE_EOF 1 /* End of file */
#define STATE_COND 2 /* Parsing a "(conditional)" stmt */
#define STATE_COND_DONE 3
#define STATE_RELEXP 4 /* Parsing a relational expr */
#define STATE_RELEXP_DONE 5
#define STATE_EXPR 6 /* Parsing an expression */
#define STATE_EXPR_DONE 7
#define STATE_STMT 8 /* Parsing General statement */
#define STATE_STMT_DONE 9
#define STATE_STMT_BLOCK_DONE 10 /* End of block "}" */
#define STATE_ARG_LIST 11 /* Function arg list */
#define STATE_ARG_LIST_DONE 12
#define STATE_DEC_LIST 16 /* Declaration list */
#define STATE_DEC_LIST_DONE 17
#define STATE_DEC 18
#define STATE_DEC_DONE 19
#define STATE_BEGIN STATE_STMT
/*
* Flags. Used in ej_t and as parameter to parse()
*/
#define FLAGS_EXE 0x1 /* Execute statements */
#define FLAGS_VARIABLES 0x2 /* Allocated variables store */
#define FLAGS_FUNCTIONS 0x4 /* Allocated function store */
/*
* Function call structure
*/
typedef struct {
char_t *fname; /* Function name */
char_t **args; /* Args for function (halloc) */
int nArgs; /* Number of args */
} ejfunc_t;
/*
* EJ evaluation block structure
*/
typedef struct ejEval {
ringq_t tokbuf; /* Current token */
ringq_t script; /* Input script for parsing */
char_t *putBackToken; /* Putback token string */
int putBackTokenId; /* Putback token ID */
char_t *line; /* Current line */
int lineLength; /* Current line length */
int lineNumber; /* Parse line number */
int lineColumn; /* Column in line */
} ejinput_t;
/*
* Per Ejscript session structure
*/
typedef struct ej {
ejinput_t *input; /* Input evaluation block */
sym_fd_t functions; /* Symbol table for functions */
sym_fd_t *variables; /* hAlloc list of variables */
int variableMax; /* Number of entries */
ejfunc_t *func; /* Current function */
char_t *result; /* Current expression result */
char_t *error; /* Error message */
char_t *token; /* Pointer to token string */
int tid; /* Current token id */
int eid; /* Halloc handle */
int flags; /* Flags */
int userHandle; /* User defined handle */
} ej_t;
/******************************** Prototypes **********************************/
extern int ejArgs(int argc, char_t **argv, char_t *fmt, ...);
extern void ejSetResult(int eid, char_t *s);
extern int ejOpenEngine(sym_fd_t variables, sym_fd_t functions);
extern void ejCloseEngine(int eid);
extern int ejOpenBlock(int eid);
extern int ejCloseBlock(int eid, int vid);
extern char_t *ejEval(int eid, char_t *script, char_t **emsg);
extern char_t *ejEvalBlock(int eid, char_t *script, char_t **emsg);
extern char_t *ejEvalFile(int eid, char_t *path, char_t **emsg);
extern int ejSetGlobalFunction(int eid, char_t *name,
int (*fn)(int eid, void *handle, int argc, char_t **argv));
extern void *ejGetGlobalFunction(int eid, char_t *name);
extern int ejSetGlobalFunctionDirect(sym_fd_t functions, char_t *name,
int (*fn)(int eid, void *handle, int argc, char_t **argv));
extern int ejArgs(int argc, char_t **argv, char_t *fmt, ...);
extern void ejError(ej_t* ep, char_t* fmt, ...);
extern void ejSetUserHandle(int eid, int handle);
extern int ejGetUserHandle(int eid);
extern int ejGetLineNumber(int eid);
extern void ejSetResult(int eid, char_t *s);
extern char_t *ejGetResult(int eid);
extern void ejSetVar(int eid, char_t *var, char_t *value);
extern void ejSetLocalVar(int eid, char_t *var, char_t *value);
extern int ejGetVar(int eid, char_t *var, char_t **value);
extern void ejSetGlobalVar(int eid, char_t *var, char_t *value);
extern int ejLexOpen(ej_t* ep);
extern void ejLexClose(ej_t* ep);
extern int ejLexOpenScript(ej_t* ep, char_t *script);
extern void ejLexCloseScript(ej_t* ep);
extern void ejLexSaveInputState(ej_t* ep, ejinput_t* state);
extern void ejLexFreeInputState(ej_t* ep, ejinput_t* state);
extern void ejLexRestoreInputState(ej_t* ep, ejinput_t* state);
extern int ejLexGetToken(ej_t* ep, int state);
extern void ejLexPutbackToken(ej_t* ep, int tid, char_t *string);
extern sym_fd_t ejGetVariableTable(int eid);
extern sym_fd_t ejGetFunctionTable(int eid);
extern int ejEmfOpen(int eid);
extern void ejEmfClose(int eid);
extern int ejEmfDbRead(int eid, void *handle, int argc, char_t **argv);
extern int ejEmfDbReadKeyed(int eid, void *handle, int argc, char_t **argv);
extern int ejEmfDbTableGetNrow(int eid, void *handle, int argc, char_t **argv);
extern int ejEmfTrace(int eid, void *handle, int argc, char_t **argv);
extern int ejEmfDbWrite(int eid, void *handle, int argc, char_t **argv);
extern char_t *ejEval(int eid, char_t *script, char_t **emsg);
#endif /* _h_EJ */

View File

@@ -0,0 +1,228 @@
/*
* ejIntrn.h -- Ejscript(TM) header
*
* Copyright (c) GoAhead Software, Inc., 1992-2000
*
* See the file "license.txt" for information on usage and redistribution
*/
#ifndef _h_EJINTERNAL
#define _h_EJINTERNAL 1
/******************************** Description *********************************/
/*
* GoAhead Ejscript(TM) header. This defines the Ejscript API and internal
* structures.
*/
/********************************* Includes ***********************************/
#include <ctype.h>
#include <stdarg.h>
#include <stdlib.h>
#if CE
#if ! UEMF
#include <io.h>
#endif
#endif
#if LYNX
#include <unistd.h>
#endif
#ifdef QNX4
#include <dirent.h>
#endif
#if UEMF
#include "uemf.h"
#else
#include <param.h>
#include <stat.h>
#include "basic/basicInternal.h"
#include "emf/emfInternal.h"
#endif
#include "ej.h"
/********************************** Defines ***********************************/
/*
* Constants
*/
#define EJ_INC 110 /* Growth for tags/tokens */
#define EJ_SCRIPT_INC 1023 /* Growth for ej scripts */
#define EJ_OFFSET 1 /* hAlloc doesn't like 0 entries */
#define EJ_MAX_RECURSE 100 /* Sanity for maximum recursion */
/*
* Ejscript Lexical analyser tokens
*/
#define TOK_ERR -1 /* Any error */
#define TOK_LPAREN 1 /* ( */
#define TOK_RPAREN 2 /* ) */
#define TOK_IF 3 /* if */
#define TOK_ELSE 4 /* else */
#define TOK_LBRACE 5 /* { */
#define TOK_RBRACE 6 /* } */
#define TOK_LOGICAL 7 /* ||, &&, ! */
#define TOK_EXPR 8 /* +, -, /, % */
#define TOK_SEMI 9 /* ; */
#define TOK_LITERAL 10 /* literal string */
#define TOK_FUNCTION 11 /* function name */
#define TOK_NEWLINE 12 /* newline white space */
#define TOK_ID 13 /* function name */
#define TOK_EOF 14 /* End of script */
#define TOK_COMMA 15 /* Comma */
#define TOK_VAR 16 /* var */
#define TOK_ASSIGNMENT 17 /* = */
#define TOK_FOR 18 /* for */
#define TOK_INC_DEC 19 /* ++, -- */
#define TOK_RETURN 20 /* return */
/*
* Expression operators
*/
#define EXPR_LESS 1 /* < */
#define EXPR_LESSEQ 2 /* <= */
#define EXPR_GREATER 3 /* > */
#define EXPR_GREATEREQ 4 /* >= */
#define EXPR_EQ 5 /* == */
#define EXPR_NOTEQ 6 /* != */
#define EXPR_PLUS 7 /* + */
#define EXPR_MINUS 8 /* - */
#define EXPR_DIV 9 /* / */
#define EXPR_MOD 10 /* % */
#define EXPR_LSHIFT 11 /* << */
#define EXPR_RSHIFT 12 /* >> */
#define EXPR_MUL 13 /* * */
#define EXPR_ASSIGNMENT 14 /* = */
#define EXPR_INC 15 /* ++ */
#define EXPR_DEC 16 /* -- */
#define EXPR_BOOL_COMP 17 /* ! */
/*
* Conditional operators
*/
#define COND_AND 1 /* && */
#define COND_OR 2 /* || */
#define COND_NOT 3 /* ! */
/*
* States
*/
#define STATE_ERR -1 /* Error state */
#define STATE_EOF 1 /* End of file */
#define STATE_COND 2 /* Parsing a "(conditional)" stmt */
#define STATE_COND_DONE 3
#define STATE_RELEXP 4 /* Parsing a relational expr */
#define STATE_RELEXP_DONE 5
#define STATE_EXPR 6 /* Parsing an expression */
#define STATE_EXPR_DONE 7
#define STATE_STMT 8 /* Parsing General statement */
#define STATE_STMT_DONE 9
#define STATE_STMT_BLOCK_DONE 10 /* End of block "}" */
#define STATE_ARG_LIST 11 /* Function arg list */
#define STATE_ARG_LIST_DONE 12
#define STATE_DEC_LIST 16 /* Declaration list */
#define STATE_DEC_LIST_DONE 17
#define STATE_DEC 18
#define STATE_DEC_DONE 19
#define STATE_RET 20 /* Return statement */
#define STATE_BEGIN STATE_STMT
/*
* Flags. Used in ej_t and as parameter to parse()
*/
#define FLAGS_EXE 0x1 /* Execute statements */
#define FLAGS_VARIABLES 0x2 /* Allocated variables store */
#define FLAGS_FUNCTIONS 0x4 /* Allocated function store */
/*
* Function call structure
*/
typedef struct {
char_t *fname; /* Function name */
char_t **args; /* Args for function (halloc) */
int nArgs; /* Number of args */
} ejfunc_t;
/*
* EJ evaluation block structure
*/
typedef struct ejEval {
ringq_t tokbuf; /* Current token */
ringq_t script; /* Input script for parsing */
char_t *putBackToken; /* Putback token string */
int putBackTokenId; /* Putback token ID */
char_t *line; /* Current line */
int lineLength; /* Current line length */
int lineNumber; /* Parse line number */
int lineColumn; /* Column in line */
} ejinput_t;
/*
* Per Ejscript session structure
*/
typedef struct ej {
ejinput_t *input; /* Input evaluation block */
sym_fd_t functions; /* Symbol table for functions */
sym_fd_t *variables; /* hAlloc list of variables */
int variableMax; /* Number of entries */
ejfunc_t *func; /* Current function */
char_t *result; /* Current expression result */
char_t *error; /* Error message */
char_t *token; /* Pointer to token string */
int tid; /* Current token id */
int eid; /* Halloc handle */
int flags; /* Flags */
int userHandle; /* User defined handle */
} ej_t;
/******************************** Prototypes **********************************/
extern int ejOpenBlock(int eid);
extern int ejCloseBlock(int eid, int vid);
extern char_t *ejEvalBlock(int eid, char_t *script, char_t **emsg);
#ifndef __NO_EJ_FILE
extern char_t *ejEvalFile(int eid, char_t *path, char_t **emsg);
#endif
extern int ejRemoveGlobalFunction(int eid, char_t *name);
extern void *ejGetGlobalFunction(int eid, char_t *name);
extern int ejSetGlobalFunctionDirect(sym_fd_t functions, char_t *name,
int (*fn)(int eid, void *handle, int argc, char_t **argv));
extern void ejError(ej_t* ep, char_t* fmt, ...);
extern void ejSetUserHandle(int eid, int handle);
extern int ejGetUserHandle(int eid);
extern int ejGetLineNumber(int eid);
extern char_t *ejGetResult(int eid);
extern void ejSetLocalVar(int eid, char_t *var, char_t *value);
extern void ejSetGlobalVar(int eid, char_t *var, char_t *value);
extern int ejLexOpen(ej_t* ep);
extern void ejLexClose(ej_t* ep);
extern int ejLexOpenScript(ej_t* ep, char_t *script);
extern void ejLexCloseScript(ej_t* ep);
extern void ejLexSaveInputState(ej_t* ep, ejinput_t* state);
extern void ejLexFreeInputState(ej_t* ep, ejinput_t* state);
extern void ejLexRestoreInputState(ej_t* ep, ejinput_t* state);
extern int ejLexGetToken(ej_t* ep, int state);
extern void ejLexPutbackToken(ej_t* ep, int tid, char_t *string);
extern sym_fd_t ejGetVariableTable(int eid);
extern sym_fd_t ejGetFunctionTable(int eid);
extern int ejEmfOpen(int eid);
extern void ejEmfClose(int eid);
extern int ejEmfDbRead(int eid, void *handle, int argc, char_t **argv);
extern int ejEmfDbReadKeyed(int eid, void *handle, int argc, char_t **argv);
extern int ejEmfDbTableGetNrow(int eid, void *handle, int argc, char_t **argv);
extern int ejEmfDbDeleteRow(int eid, void *handle, int argc, char_t **argv);
extern int ejEmfTrace(int eid, void *handle, int argc, char_t **argv);
extern int ejEmfDbWrite(int eid, void *handle, int argc, char_t **argv);
extern int ejEmfDbCollectTable(int eid, void *handle, int argc, char_t **argv);
#endif /* _h_EJINTERNAL */

View File

@@ -1,7 +1,7 @@
/*
* ejlex.c -- Ejscript(TM) Lexical Analyser
*
* Copyright (c) Go Ahead Software, Inc., 1995-1999
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
*
* See the file "license.txt" for usage and redistribution license requirements
*/
@@ -15,7 +15,7 @@
/********************************** Includes **********************************/
#include "ej.h"
#include "ejIntrn.h"
#if UEMF
#include "uemf.h"
@@ -23,12 +23,16 @@
#include "basic/basicInternal.h"
#endif
/********************************** Defines ***********************************/
#define OCTAL 8
#define HEX 16
/****************************** Forward Declarations **************************/
static int getLexicalToken(ej_t* ep, int state);
static int tokenAddChar(ej_t *ep, int c);
static int inputGetc(ej_t* ep);
static void inputPutback(ej_t* ep, int c);
static int charConvert(ej_t* ep, int base, int maxDig);
/************************************* Code ***********************************/
/*
@@ -77,13 +81,13 @@ int ejLexOpenScript(ej_t* ep, char_t *script)
if (ringqOpen(&ip->tokbuf, EJ_INC, -1) < 0) {
return -1;
}
if (ringqOpen(&ip->script, EJ_INC, -1) < 0) {
if (ringqOpen(&ip->script, EJ_SCRIPT_INC, -1) < 0) {
return -1;
}
/*
* Put the Ejscript into a ring queue for easy parsing
*/
ringqPutstr(&ip->script, script);
ringqPutStr(&ip->script, script);
ip->lineNumber = 1;
ip->lineLength = 0;
@@ -178,6 +182,7 @@ void ejLexFreeInputState(ej_t* ep, ejinput_t* state)
{
if (state->putBackToken) {
bfree(B_L, state->putBackToken);
state->putBackToken = NULL;
}
}
@@ -189,7 +194,7 @@ void ejLexFreeInputState(ej_t* ep, ejinput_t* state)
int ejLexGetToken(ej_t* ep, int state)
{
ep->tid = getLexicalToken(ep, state);
goahead_trace(7, T("ejGetToken: %d, \"%s\"\n"), ep->tid, ep->token);
trace(9, T("ejGetToken: %d, \"%s\"\n"), ep->tid, ep->token);
return ep->tid;
}
@@ -202,7 +207,7 @@ static int getLexicalToken(ej_t* ep, int state)
{
ringq_t *inq, *tokq;
ejinput_t* ip;
int done, tid, c, quote, style, back_quoted, lval, i;
int done, tid, c, quote, style;
a_assert(ep);
ip = ep->input;
@@ -218,7 +223,7 @@ static int getLexicalToken(ej_t* ep, int state)
ringqFlush(tokq);
if (ip->putBackTokenId > 0) {
ringqPutstr(tokq, ip->putBackToken);
ringqPutStr(tokq, ip->putBackToken);
tid = ip->putBackTokenId;
ip->putBackTokenId = 0;
ep->token = (char_t*) tokq->servp;
@@ -385,7 +390,7 @@ static int getLexicalToken(ej_t* ep, int state)
inputPutback(ep, c);
return TOK_ASSIGNMENT;
case '!': /* "!=" */
case '!': /* "!=" or "!"*/
if ((c = inputGetc(ep)) < 0) {
ejError(ep, T("Syntax Error"));
return TOK_ERR;
@@ -394,8 +399,9 @@ static int getLexicalToken(ej_t* ep, int state)
tokenAddChar(ep, EXPR_NOTEQ);
return TOK_EXPR;
}
tokenAddChar(ep, COND_NOT);
return TOK_LOGICAL;
inputPutback(ep, c);
tokenAddChar(ep, EXPR_BOOL_COMP);
return TOK_EXPR;
case ';':
tokenAddChar(ep, c);
@@ -428,25 +434,23 @@ static int getLexicalToken(ej_t* ep, int state)
ejError(ep, T("Syntax Error"));
return TOK_ERR;
}
back_quoted = 0;
while (c != quote) {
if (c == '\\' && !back_quoted) {
back_quoted++;
} else if (back_quoted) {
if (gisdigit((char_t) c)) {
lval = 0;
for (i = 0; i < 3; i++) {
if ('0' <= c && c <= '7') {
break;
}
lval = lval * 8 + c;
if ((c = inputGetc(ep)) < 0) {
break;
}
}
c = (int) lval;
} else if (back_quoted) {
while (c != quote) {
/*
* check for escape sequence characters
*/
if (c == '\\') {
c = inputGetc(ep);
if (gisdigit(c)) {
/*
* octal support, \101 maps to 65 = 'A'. put first char
* back so converter will work properly.
*/
inputPutback(ep, c);
c = charConvert(ep, OCTAL, 3);
} else {
switch (c) {
case 'n':
c = '\n'; break;
@@ -459,37 +463,28 @@ static int getLexicalToken(ej_t* ep, int state)
case 't':
c = '\t'; break;
case 'x':
lval = 0;
for (i = 0; i < 2; i++) {
if (! gisxdigit((char_t) c)) {
break;
}
lval = lval * 16 + c;
if ((c = inputGetc(ep)) < 0) {
break;
}
}
c = (int) lval;
/*
* hex support, \x41 maps to 65 = 'A'
*/
c = charConvert(ep, HEX, 2);
break;
case 'u':
lval = 0;
for (i = 0; i < 4; i++) {
if (! gisxdigit((char_t) c)) {
break;
}
lval = lval * 16 + c;
if ((c = inputGetc(ep)) < 0) {
break;
}
}
c = (int) lval;
/*
* unicode support, \x0401 maps to 65 = 'A'
*/
c = charConvert(ep, HEX, 2);
c = c*16 + charConvert(ep, HEX, 2);
break;
case '\'':
case '\"':
case '\\':
break;
default:
ejError(ep, T("Invalid Escape Sequence"));
return TOK_ERR;
}
}
back_quoted = 0;
if (tokenAddChar(ep, c) < 0) {
return TOK_ERR;
}
@@ -513,7 +508,7 @@ static int getLexicalToken(ej_t* ep, int state)
}
if ((c = inputGetc(ep)) < 0)
break;
} while (gisdigit((char_t) c));
} while (gisdigit(c));
inputPutback(ep, c);
return TOK_LITERAL;
@@ -521,21 +516,19 @@ static int getLexicalToken(ej_t* ep, int state)
/*
* Identifiers or a function names
*/
back_quoted = 0;
while (1) {
if (c == '\\' && !back_quoted) {
back_quoted++;
} else {
back_quoted = 0;
if (tokenAddChar(ep, c) < 0) {
if (c == '\\') {
/*
* just ignore any \ characters.
*/
} else if (tokenAddChar(ep, c) < 0) {
break;
}
}
if ((c = inputGetc(ep)) < 0) {
break;
}
if (!back_quoted && (!gisalnum((char_t) c) && c != '$' &&
c != '_')) {
if (!gisalnum(c) && c != '$' && c != '_' &&
c != '\\') {
break;
}
}
@@ -558,13 +551,16 @@ static int getLexicalToken(ej_t* ep, int state)
} else if (gstrcmp(ep->token, T("for")) == 0) {
return TOK_FOR;
} else if (gstrcmp(ep->token, T("return")) == 0) {
if ((c == ';') || (c == '(')) {
inputPutback(ep, c);
}
return TOK_RETURN;
}
}
/*
* skip white space after token to find out whether this is
* a function or not.
/*
* Skip white space after token to find out whether this is
* a function or not.
*/
while (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
if ((c = inputGetc(ep)) < 0)
@@ -677,3 +673,41 @@ static void inputPutback(ej_t* ep, int c)
}
/******************************************************************************/
/*
* Convert a hex or octal character back to binary, return original char if
* not a hex digit
*/
static int charConvert(ej_t* ep, int base, int maxDig)
{
int i, c, lval, convChar;
lval = 0;
for (i = 0; i < maxDig; i++) {
if ((c = inputGetc(ep)) < 0) {
break;
}
/*
* Initialize to out of range value
*/
convChar = base;
if (gisdigit(c)) {
convChar = c - '0';
} else if (c >= 'a' && c <= 'f') {
convChar = c - 'a' + 10;
} else if (c >= 'A' && c <= 'F') {
convChar = c - 'A' + 10;
}
/*
* if unexpected character then return it to buffer.
*/
if (convChar >= base) {
inputPutback(ep, c);
break;
}
lval = (lval * base) + convChar;
}
return lval;
}
/******************************************************************************/

View File

@@ -1,7 +1,7 @@
/*
* ejparse.c -- Ejscript(TM) Parser
*
* Copyright (c) Go Ahead Software, Inc., 1995-1999
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
*
* See the file "license.txt" for usage and redistribution license requirements
*/
@@ -15,7 +15,11 @@
/********************************** Includes **********************************/
#include "ej.h"
#include "ejIntrn.h"
#if CE
#include "CE/wincompat.h"
#endif
/********************************** Local Data ********************************/
@@ -24,11 +28,14 @@ int ejMax = -1; /* Maximum size of */
/****************************** Forward Declarations **************************/
#ifndef B_STATS
#define setString(a,b,c) setstring(b,c)
#endif
static ej_t *ejPtr(int eid);
static void clearString(char_t **ptr);
static void setString(char_t **ptr, char_t *s);
static void setString(B_ARGS_DEC, char_t **ptr, char_t *s);
static void appendString(char_t **ptr, char_t *s);
static void freeVar(sym_t* sp);
static int parse(ej_t *ep, int state, int flags);
static int parseStmt(ej_t *ep, int state, int flags);
static int parseDeclaration(ej_t *ep, int state, int flags);
@@ -39,6 +46,7 @@ static int evalExpr(ej_t *ep, char_t *lhs, int rel, char_t *rhs);
static int evalCond(ej_t *ep, char_t *lhs, int rel, char_t *rhs);
static int evalFunction(ej_t *ep);
static void freeFunc(ejfunc_t *func);
static void ejRemoveNewlines(ej_t *ep, int state);
/************************************* Code ***********************************/
/*
@@ -57,8 +65,8 @@ int ejOpenEngine(sym_fd_t variables, sym_fd_t functions)
ep->eid = eid;
/*
* Create a top level symbol table if one is not provided for variables and
* functions. Variables may create other symbol tables for block level
* Create a top level symbol table if one is not provided for variables and
* functions. Variables may create other symbol tables for block level
* declarations so we use hAlloc to manage a list of variable tables.
*/
if ((vid = hAlloc((void***) &ep->variables)) < 0) {
@@ -72,7 +80,6 @@ int ejOpenEngine(sym_fd_t variables, sym_fd_t functions)
if (variables == -1) {
ep->variables[vid] = symOpen(64) + EJ_OFFSET;
ep->flags |= FLAGS_VARIABLES;
} else {
ep->variables[vid] = variables + EJ_OFFSET;
}
@@ -122,36 +129,27 @@ void ejCloseEngine(int eid)
ejLexClose(ep);
if (ep->flags & FLAGS_VARIABLES) {
for (i = ep->variableMax - 1; i >= 0; i--) {
symClose(ep->variables[i] - EJ_OFFSET, freeVar);
ep->variableMax = hFree((void***) &ep->variables, i);
for (i = ep->variableMax - 1; i >= 0; i--) {
if (ep->flags & FLAGS_VARIABLES) {
symClose(ep->variables[i] - EJ_OFFSET);
}
ep->variableMax = hFree((void***) &ep->variables, i);
}
if (ep->flags & FLAGS_FUNCTIONS) {
symClose(ep->functions, freeVar);
symClose(ep->functions);
}
ejMax = hFree((void***) &ejHandles, ep->eid);
bfree(B_L, ep);
}
/******************************************************************************/
/*
* Callback from symClose. Free the variable.
*/
static void freeVar(sym_t* sp)
{
valueFree(&sp->content);
}
#ifndef __NO_EJ_FILE
/******************************************************************************/
/*
* Evaluate a Ejscript file
*/
#if DEV
char_t *ejEvalFile(int eid, char_t *path, char_t **emsg)
{
gstat_t sbuf;
@@ -165,6 +163,7 @@ char_t *ejEvalFile(int eid, char_t *path, char_t **emsg)
if (emsg) {
*emsg = NULL;
}
if ((ep = ejPtr(eid)) == NULL) {
return NULL;
}
@@ -173,26 +172,30 @@ char_t *ejEvalFile(int eid, char_t *path, char_t **emsg)
ejError(ep, T("Bad handle %d"), eid);
return NULL;
}
if (gstat(path, &sbuf) < 0) {
close(fd);
gclose(fd);
ejError(ep, T("Cant stat %s"), path);
return NULL;
}
if ((fileBuf = balloc(B_L, sbuf.st_size + 1)) == NULL) {
close(fd);
gclose(fd);
ejError(ep, T("Cant malloc %d"), sbuf.st_size);
return NULL;
}
if (read(fd, fileBuf, sbuf.st_size) != (int)sbuf.st_size) {
close(fd);
if (gread(fd, fileBuf, sbuf.st_size) != (int)sbuf.st_size) {
gclose(fd);
bfree(B_L, fileBuf);
ejError(ep, T("Error reading %s"), path);
return NULL;
}
fileBuf[sbuf.st_size] = '\0';
close(fd);
gclose(fd);
if ((script = ballocAscToUni(fileBuf)) == NULL) {
if ((script = ballocAscToUni(fileBuf, sbuf.st_size)) == NULL) {
bfree(B_L, fileBuf);
ejError(ep, T("Cant malloc %d"), sbuf.st_size + 1);
return NULL;
@@ -204,29 +207,31 @@ char_t *ejEvalFile(int eid, char_t *path, char_t **emsg)
bfree(B_L, script);
return rs;
}
#endif
#endif /* __NO_EJ_FILE */
/******************************************************************************/
/*
* Create a new variable scope block so that consecutive ejEval calls may
* be made with the same varible scope. This space MUST be closed with
* ejCloseBlock when the evaluations are complete.
* ejCloseBlock when the evaluations are complete.
*/
int ejOpenBlock(int eid)
{
ej_t *ep;
int vid;
int vid;
if((ep = ejPtr(eid)) == NULL) {
return -1;
}
}
if ((vid = hAlloc((void***) &ep->variables)) < 0) {
return -1;
}
if (vid >= ep->variableMax) {
ep->variableMax = vid + 1;
}
}
ep->variables[vid] = symOpen(64) + EJ_OFFSET;
return vid;
@@ -241,15 +246,16 @@ int ejOpenBlock(int eid)
int ejCloseBlock(int eid, int vid)
{
ej_t *ep;
if((ep = ejPtr(eid)) == NULL) {
return -1;
}
symClose(ep->variables[vid] - EJ_OFFSET, freeVar);
symClose(ep->variables[vid] - EJ_OFFSET);
ep->variableMax = hFree((void***) &ep->variables, vid);
return 0;
return 0;
}
/******************************************************************************/
/*
* Create a new variable scope block and evaluate a script. All variables
@@ -263,7 +269,7 @@ char_t *ejEvalBlock(int eid, char_t *script, char_t **emsg)
a_assert(script);
vid = ejOpenBlock(eid);
vid = ejOpenBlock(eid);
returnVal = ejEval(eid, script, emsg);
ejCloseBlock(eid, vid);
@@ -272,7 +278,7 @@ char_t *ejEvalBlock(int eid, char_t *script, char_t **emsg)
/******************************************************************************/
/*
* Parse and evaluate a Ejscript. The caller may provide a symbol table to
* Parse and evaluate a Ejscript. The caller may provide a symbol table to
* use for variables and function definitions. Return char_t pointer on
* success otherwise NULL pointer is returned.
*/
@@ -282,17 +288,21 @@ char_t *ejEval(int eid, char_t *script, char_t **emsg)
ej_t *ep;
ejinput_t *oldBlock;
int state;
void *endlessLoopTest;
int loopCounter;
a_assert(script);
if (emsg) {
*emsg = NULL;
}
}
if ((ep = ejPtr(eid)) == NULL) {
return NULL;
}
setString(&ep->result, T(""));
setString(B_L, &ep->result, T(""));
/*
* Allocate a new evaluation block, and save the old one
@@ -303,8 +313,29 @@ char_t *ejEval(int eid, char_t *script, char_t **emsg)
/*
* Do the actual parsing and evaluation
*/
loopCounter = 0;
endlessLoopTest = NULL;
do {
state = parse(ep, STATE_BEGIN, FLAGS_EXE);
if (state == STATE_RET) {
state = STATE_EOF;
}
/*
* prevent parser from going into infinite loop. If parsing the same
* line 10 times then fail and report Syntax error. Most normal error
* are caught in the parser itself.
*/
if (endlessLoopTest == ep->input->script.servp) {
if (loopCounter++ > 10) {
state = STATE_ERR;
ejError(ep, T("Syntax error"));
}
} else {
endlessLoopTest = ep->input->script.servp;
loopCounter = 0;
}
} while (state != STATE_EOF && state != STATE_ERR);
ejLexCloseScript(ep);
@@ -324,9 +355,11 @@ char_t *ejEval(int eid, char_t *script, char_t **emsg)
if (state == STATE_EOF) {
return ep->result;
}
if (state == STATE_ERR) {
return NULL;
}
return ep->result;
}
@@ -344,12 +377,25 @@ static int parse(ej_t *ep, int state, int flags)
* Any statement, function arguments or conditional expressions
*/
case STATE_STMT:
if ((state = parseStmt(ep, state, flags)) != STATE_STMT_DONE &&
state != STATE_EOF && state != STATE_STMT_BLOCK_DONE &&
state != STATE_RET) {
state = STATE_ERR;
}
break;
case STATE_DEC:
state = parseStmt(ep, state, flags);
if ((state = parseStmt(ep, state, flags)) != STATE_DEC_DONE &&
state != STATE_EOF) {
state = STATE_ERR;
}
break;
case STATE_EXPR:
state = parseStmt(ep, state, flags);
if ((state = parseStmt(ep, state, flags)) != STATE_EXPR_DONE &&
state != STATE_EOF) {
state = STATE_ERR;
}
break;
/*
@@ -397,9 +443,9 @@ static int parseStmt(ej_t *ep, int state, int flags)
ejfunc_t func;
ejfunc_t *saveFunc;
ejinput_t condScript, endScript, bodyScript, incrScript;
char_t *value;
char_t *identifier;
char_t *value, *identifier;
int done, expectSemi, thenFlags, elseFlags, tid, cond, forFlags;
int ejVarType;
a_assert(ep);
@@ -451,21 +497,22 @@ static int parseStmt(ej_t *ep, int state, int flags)
* This could either be a reference to a variable or an assignment
*/
identifier = NULL;
setString(&identifier, ep->token);
setString(B_L, &identifier, ep->token);
/*
* Peek ahead to see if this is an assignment
*/
tid = ejLexGetToken(ep, state);
if (tid == TOK_ASSIGNMENT) {
if (parse(ep, STATE_RELEXP, flags) != STATE_RELEXP_DONE) {
clearString(&identifier);
goto error;
}
if (flags & FLAGS_EXE) {
if ( state == STATE_DEC ) {
ejSetLocalVar(ep->eid, identifier, ep->result);
}
else {
if (ejGetVar(ep->eid, identifier, &value) > 0) {
} else {
ejVarType = ejGetVar(ep->eid, identifier, &value);
if (ejVarType > 0) {
ejSetLocalVar(ep->eid, identifier, ep->result);
} else {
ejSetGlobalVar(ep->eid, identifier, ep->result);
@@ -475,17 +522,23 @@ static int parseStmt(ej_t *ep, int state, int flags)
} else if (tid == TOK_INC_DEC ) {
value = NULL;
if ( flags & FLAGS_EXE ) {
if (ejGetVar(ep->eid, identifier, &value) < 0) {
if (flags & FLAGS_EXE) {
ejVarType = ejGetVar(ep->eid, identifier, &value);
if (ejVarType < 0) {
ejError(ep, T("Undefined variable %s\n"), identifier);
goto error;
}
setString(&ep->result, value);
setString(B_L, &ep->result, value);
if (evalExpr(ep, value, (int) *ep->token, T("1")) < 0) {
state = STATE_ERR;
break;
}
ejSetGlobalVar(ep->eid, identifier, ep->result);
if (ejVarType > 0) {
ejSetLocalVar(ep->eid, identifier, ep->result);
} else {
ejSetGlobalVar(ep->eid, identifier, ep->result);
}
}
} else {
@@ -495,7 +548,7 @@ static int parseStmt(ej_t *ep, int state, int flags)
value = NULL;
if (state == STATE_DEC) {
if (ejGetVar(ep->eid, identifier, &value) > 0) {
ejError(ep, T("Variable already declared"),
ejError(ep, T("Variable already declared"),
identifier);
clearString(&identifier);
goto error;
@@ -504,14 +557,14 @@ static int parseStmt(ej_t *ep, int state, int flags)
} else {
if ( flags & FLAGS_EXE ) {
if (ejGetVar(ep->eid, identifier, &value) < 0) {
ejError(ep, T("Undefined variable %s\n"),
ejError(ep, T("Undefined variable %s\n"),
identifier);
clearString(&identifier);
goto error;
}
}
}
setString(&ep->result, value);
setString(B_L, &ep->result, value);
ejLexPutbackToken(ep, tid, ep->token);
}
clearString(&identifier);
@@ -526,7 +579,7 @@ static int parseStmt(ej_t *ep, int state, int flags)
/*
* Set the result to the literal (number or string constant)
*/
setString(&ep->result, ep->token);
setString(B_L, &ep->result, ep->token);
if (state == STATE_STMT) {
expectSemi++;
}
@@ -541,10 +594,10 @@ static int parseStmt(ej_t *ep, int state, int flags)
saveFunc = ep->func;
}
memset(&func, 0, sizeof(ejfunc_t));
setString(&func.fname, ep->token);
setString(B_L, &func.fname, ep->token);
ep->func = &func;
setString(&ep->result, T(""));
setString(B_L, &ep->result, T(""));
if (ejLexGetToken(ep, state) != TOK_LPAREN) {
freeFunc(&func);
goto error;
@@ -604,11 +657,20 @@ static int parseStmt(ej_t *ep, int state, int flags)
elseFlags = flags;
}
/*
* Process the "then" case
* Process the "then" case. Allow for RETURN statement
*/
if (parse(ep, STATE_STMT, thenFlags) != STATE_STMT_DONE) {
switch (parse(ep, STATE_STMT, thenFlags)) {
case STATE_RET:
return STATE_RET;
case STATE_STMT_DONE:
break;
default:
goto error;
}
/*
* check to see if there is an "else" case
*/
ejRemoveNewlines(ep, state);
tid = ejLexGetToken(ep, state);
if (tid != TOK_ELSE) {
ejLexPutbackToken(ep, tid, ep->token);
@@ -616,9 +678,14 @@ static int parseStmt(ej_t *ep, int state, int flags)
break;
}
/*
* Process the "else" case
* Process the "else" case. Allow for return.
*/
if (parse(ep, STATE_STMT, elseFlags) != STATE_STMT_DONE) {
switch (parse(ep, STATE_STMT, elseFlags)) {
case STATE_RET:
return STATE_RET;
case STATE_STMT_DONE:
break;
default:
goto error;
}
done++;
@@ -650,7 +717,7 @@ static int parseStmt(ej_t *ep, int state, int flags)
}
/*
* The first time through, we save the current input context just
* The first time through, we save the current input context just
* to each step: prior to the conditional, the loop increment and the
* loop body.
*/
@@ -663,7 +730,7 @@ static int parseStmt(ej_t *ep, int state, int flags)
if (ejLexGetToken(ep, state) != TOK_SEMI) {
goto error;
}
/*
* Don't execute the loop increment statement or the body first time
*/
@@ -677,7 +744,7 @@ static int parseStmt(ej_t *ep, int state, int flags)
}
/*
* Parse the body and remember the end of the body script
* Parse the body and remember the end of the body script
*/
ejLexSaveInputState(ep, &bodyScript);
if (parse(ep, STATE_STMT, forFlags) != STATE_STMT_DONE) {
@@ -693,7 +760,13 @@ static int parseStmt(ej_t *ep, int state, int flags)
* Evaluate the body
*/
ejLexRestoreInputState(ep, &bodyScript);
if (parse(ep, STATE_STMT, flags) != STATE_STMT_DONE) {
switch (parse(ep, STATE_STMT, flags)) {
case STATE_RET:
return STATE_RET;
case STATE_STMT_DONE:
break;
default:
goto error;
}
/*
@@ -760,6 +833,13 @@ static int parseStmt(ej_t *ep, int state, int flags)
state = parse(ep, STATE_STMT, flags);
} while (state == STATE_STMT_DONE);
/*
* Allow return statement.
*/
if (state == STATE_RET) {
return state;
}
if (ejLexGetToken(ep, state) != TOK_RBRACE) {
goto error;
}
@@ -779,7 +859,7 @@ static int parseStmt(ej_t *ep, int state, int flags)
if (flags & FLAGS_EXE) {
while ( ejLexGetToken(ep, state) != TOK_EOF );
done++;
return STATE_EOF;
return STATE_RET;
}
break;
}
@@ -794,10 +874,7 @@ static int parseStmt(ej_t *ep, int state, int flags)
/*
* Skip newline after semi-colon
*/
tid = ejLexGetToken(ep, state);
if (tid != TOK_NEWLINE) {
ejLexPutbackToken(ep, tid, ep->token);
}
ejRemoveNewlines(ep, state);
}
/*
@@ -810,6 +887,7 @@ doneParse:
ejLexFreeInputState(ep, &endScript);
ejLexFreeInputState(ep, &bodyScript);
}
if (state == STATE_STMT) {
return STATE_STMT_DONE;
} else if (state == STATE_DEC) {
@@ -928,7 +1006,7 @@ static int parseCond(ej_t *ep, int state, int flags)
a_assert(ep);
setString(&ep->result, T(""));
setString(B_L, &ep->result, T(""));
rhs = lhs = NULL;
operator = 0;
@@ -942,14 +1020,15 @@ static int parseCond(ej_t *ep, int state, int flags)
state = STATE_ERR;
break;
}
if (operator > 0) {
setString(&rhs, ep->result);
setString(B_L, &rhs, ep->result);
if (evalCond(ep, lhs, operator, rhs) < 0) {
state = STATE_ERR;
break;
}
}
setString(&lhs, ep->result);
setString(B_L, &lhs, ep->result);
tid = ejLexGetToken(ep, state);
if (tid == TOK_LOGICAL) {
@@ -969,6 +1048,7 @@ static int parseCond(ej_t *ep, int state, int flags)
if (lhs) {
bfree(B_L, lhs);
}
if (rhs) {
bfree(B_L, rhs);
}
@@ -987,33 +1067,46 @@ static int parseExpr(ej_t *ep, int state, int flags)
a_assert(ep);
setString(&ep->result, T(""));
setString(B_L, &ep->result, T(""));
rhs = lhs = NULL;
rel = 0;
tid = 0;
do {
/*
* This loop will handle an entire expression list. We call parse
* to evalutate each term which returns the result in ep->result.
*/
state = parse(ep, STATE_EXPR, flags);
if (state != STATE_EXPR_DONE) {
state = STATE_ERR;
break;
}
if (rel > 0) {
setString(&rhs, ep->result);
if (evalExpr(ep, lhs, rel, rhs) < 0) {
if (tid == TOK_LOGICAL) {
if ((state = parse(ep, STATE_RELEXP, flags)) != STATE_RELEXP_DONE) {
state = STATE_ERR;
break;
}
} else {
if ((state = parse(ep, STATE_EXPR, flags)) != STATE_EXPR_DONE) {
state = STATE_ERR;
break;
}
}
setString(&lhs, ep->result);
if ((tid = ejLexGetToken(ep, state)) == TOK_EXPR) {
rel = (int) *ep->token;
if (rel > 0) {
setString(B_L, &rhs, ep->result);
if (tid == TOK_LOGICAL) {
if (evalCond(ep, lhs, rel, rhs) < 0) {
state = STATE_ERR;
break;
}
} else {
if (evalExpr(ep, lhs, rel, rhs) < 0) {
state = STATE_ERR;
break;
}
}
}
setString(B_L, &lhs, ep->result);
} else if (tid == TOK_INC_DEC) {
if ((tid = ejLexGetToken(ep, state)) == TOK_EXPR ||
tid == TOK_INC_DEC || tid == TOK_LOGICAL) {
rel = (int) *ep->token;
} else {
@@ -1023,10 +1116,14 @@ static int parseExpr(ej_t *ep, int state, int flags)
} while (state == STATE_EXPR_DONE);
if (rhs)
if (rhs) {
bfree(B_L, rhs);
if (lhs)
}
if (lhs) {
bfree(B_L, lhs);
}
return state;
}
@@ -1045,7 +1142,7 @@ static int evalCond(ej_t *ep, char_t *lhs, int rel, char_t *rhs)
a_assert(rel > 0);
lval = 0;
if (gisdigit(*lhs) && gisdigit(*rhs)) {
if (gisdigit((int)*lhs) && gisdigit((int)*rhs)) {
l = gatoi(lhs);
r = gatoi(rhs);
switch (rel) {
@@ -1060,15 +1157,15 @@ static int evalCond(ej_t *ep, char_t *lhs, int rel, char_t *rhs)
return -1;
}
} else {
if (!gisdigit(*lhs)) {
if (!gisdigit((int)*lhs)) {
ejError(ep, T("Conditional must be numeric"), lhs);
} else {
ejError(ep, T("Conditional must be numeric"), rhs);
}
}
stritoa(lval, buf, sizeof(buf));
setString(&ep->result, buf);
setString(B_L, &ep->result, buf);
return 0;
}
@@ -1091,19 +1188,21 @@ static int evalExpr(ej_t *ep, char_t *lhs, int rel, char_t *rhs)
*/
numeric = 1;
for (cp = lhs; *cp; cp++) {
if (!gisdigit(*cp)) {
if (!gisdigit((int)*cp)) {
numeric = 0;
break;
}
}
if (numeric) {
for (cp = rhs; *cp; cp++) {
if (!gisdigit(*cp)) {
if (!gisdigit((int)*cp)) {
numeric = 0;
break;
}
}
}
if (numeric) {
l = gatoi(lhs);
r = gatoi(rhs);
@@ -1161,6 +1260,9 @@ static int evalExpr(ej_t *ep, char_t *lhs, int rel, char_t *rhs)
case EXPR_GREATEREQ:
lval = (l >= r) ? 1 : 0;
break;
case EXPR_BOOL_COMP:
lval = (r == 0) ? 1 : 0;
break;
default:
ejError(ep, T("Bad operator %d"), rel);
return -1;
@@ -1205,7 +1307,7 @@ static int evalExpr(ej_t *ep, char_t *lhs, int rel, char_t *rhs)
}
stritoa(lval, buf, sizeof(buf));
setString(&ep->result, buf);
setString(B_L, &ep->result, buf);
return 0;
}
@@ -1223,13 +1325,14 @@ static int evalFunction(ej_t *ep)
ejError(ep, T("Undefined procedure %s"), ep->func->fname);
return -1;
}
fn = (int (*)(int, void*, int, char_t**)) sp->content.value.integer;
if (fn == NULL) {
ejError(ep, T("Undefined procedure %s"), ep->func->fname);
return -1;
}
return (*fn)(ep->eid, (void*) ep->userHandle, ep->func->nArgs,
return (*fn)(ep->eid, (void*) ep->userHandle, ep->func->nArgs,
ep->func->args);
}
@@ -1250,12 +1353,11 @@ void ejError(ej_t* ep, char_t* fmt, ...)
va_start(args, fmt);
msgbuf = NULL;
gvsnprintf(&msgbuf, E_MAX_ERROR, fmt, args);
fmtValloc(&msgbuf, E_MAX_ERROR, fmt, args);
va_end(args);
if (ep && ip) {
errbuf = NULL;
gsnprintf(&errbuf, E_MAX_ERROR, T("%s\n At line %d, line => \n\n%s\n"),
fmtAlloc(&errbuf, E_MAX_ERROR, T("%s\n At line %d, line => \n\n%s\n"),
msgbuf, ip->lineNumber, ip->line);
bfreeSafe(B_L, ep->error);
ep->error = errbuf;
@@ -1283,14 +1385,14 @@ static void clearString(char_t **ptr)
* Set a string value
*/
static void setString(char_t **ptr, char_t *s)
static void setString(B_ARGS_DEC, char_t **ptr, char_t *s)
{
a_assert(ptr);
if (*ptr) {
bfree(B_L, *ptr);
bfree(B_ARGS, *ptr);
}
*ptr = bstrdup(B_L, s);
*ptr = bstrdup(B_ARGS, s);
}
/******************************************************************************/
@@ -1319,7 +1421,7 @@ static void appendString(char_t **ptr, char_t *s)
* Define a function
*/
int ejSetGlobalFunction(int eid, char_t *name,
int ejSetGlobalFunction(int eid, char_t *name,
int (*fn)(int eid, void *handle, int argc, char_t **argv))
{
ej_t *ep;
@@ -1335,7 +1437,7 @@ int ejSetGlobalFunction(int eid, char_t *name,
* Define a function directly into the function symbol table.
*/
int ejSetGlobalFunctionDirect(sym_fd_t functions, char_t *name,
int ejSetGlobalFunctionDirect(sym_fd_t functions, char_t *name,
int (*fn)(int eid, void *handle, int argc, char_t **argv))
{
if (symEnter(functions, name, valueInteger((long) fn), 0) == NULL) {
@@ -1344,6 +1446,21 @@ int ejSetGlobalFunctionDirect(sym_fd_t functions, char_t *name,
return 0;
}
/******************************************************************************/
/*
* Remove ("undefine") a function
*/
int ejRemoveGlobalFunction(int eid, char_t *name)
{
ej_t *ep;
if ((ep = ejPtr(eid)) == NULL) {
return -1;
}
return symDelete(ep->functions, name);
}
/******************************************************************************/
/*
* Get a function definition
@@ -1358,6 +1475,7 @@ void *ejGetGlobalFunction(int eid, char_t *name)
if ((ep = ejPtr(eid)) == NULL) {
return NULL;
}
if ((sp = symLookup(ep->functions, name)) != NULL) {
fn = (int (*)(int, void*, int, char_t**)) sp->content.value.integer;
return (void*) fn;
@@ -1367,7 +1485,7 @@ void *ejGetGlobalFunction(int eid, char_t *name)
/******************************************************************************/
/*
* Utility routine to crack Ejscript arguments. Return the number of args
* Utility routine to crack Ejscript arguments. Return the number of args
* seen. This routine only supports %s and %d type args.
*
* Typical usage:
@@ -1477,7 +1595,7 @@ void ejSetResult(int eid, char_t *s)
if ((ep = ejPtr(eid)) == NULL) {
return;
}
setString(&ep->result, s);
setString(B_L, &ep->result, s);
}
/******************************************************************************/
@@ -1511,6 +1629,7 @@ void ejSetVar(int eid, char_t *var, char_t *value)
if ((ep = ejPtr(eid)) == NULL) {
return;
}
if (value == NULL) {
v = valueString(value, 0);
} else {
@@ -1535,6 +1654,7 @@ void ejSetLocalVar(int eid, char_t *var, char_t *value)
if ((ep = ejPtr(eid)) == NULL) {
return;
}
if (value == NULL) {
v = valueString(value, 0);
} else {
@@ -1545,7 +1665,7 @@ void ejSetLocalVar(int eid, char_t *var, char_t *value)
/******************************************************************************/
/*
* Set a global variable. Note: a variable with a value of NULL means
* Set a global variable. Note: a variable with a value of NULL means
* declared but undefined. The value is defined in the global variable frame.
*/
@@ -1559,6 +1679,7 @@ void ejSetGlobalVar(int eid, char_t *var, char_t *value)
if ((ep = ejPtr(eid)) == NULL) {
return;
}
if (value == NULL) {
v = valueString(value, 0);
} else {
@@ -1585,19 +1706,19 @@ int ejGetVar(int eid, char_t *var, char_t **value)
return -1;
}
for (i = ep->variableMax - 1; i >= 0; i--) {
if ((sp = symLookup(ep->variables[i] - EJ_OFFSET, var)) == NULL) {
continue;
i = ep->variableMax - 1;
if ((sp = symLookup(ep->variables[i] - EJ_OFFSET, var)) == NULL) {
i = 0;
if ((sp = symLookup(ep->variables[0] - EJ_OFFSET, var)) == NULL) {
return -1;
}
a_assert(sp->content.type == string);
*value = sp->content.value.string;
return i;
}
return -1;
a_assert(sp->content.type == string);
*value = sp->content.value.string;
return i;
}
/******************************************************************************/
#if UNUSED
/*
* Get the variable symbol table
*/
@@ -1609,9 +1730,9 @@ sym_fd_t ejGetVariableTable(int eid)
if ((ep = ejPtr(eid)) == NULL) {
return -1;
}
return ep->variables;
return *ep->variables;
}
#endif
/******************************************************************************/
/*
* Get the functions symbol table
@@ -1640,6 +1761,7 @@ static void freeFunc(ejfunc_t *func)
bfree(B_L, func->args[i]);
func->nArgs = hFree((void***) &func->args, i);
}
if (func->fname) {
bfree(B_L, func->fname);
func->fname = NULL;
@@ -1647,7 +1769,7 @@ static void freeFunc(ejfunc_t *func)
}
/******************************************************************************/
/*
/*
* Get Ejscript pointer
*/
@@ -1663,3 +1785,18 @@ static ej_t *ejPtr(int eid)
}
/******************************************************************************/
/*
* This function removes any new lines. Used for else cases, etc.
*/
static void ejRemoveNewlines(ej_t *ep, int state)
{
int tid;
do {
tid = ejLexGetToken(ep, state);
} while (tid == TOK_NEWLINE);
ejLexPutbackToken(ep, tid, ep->token);
}
/******************************************************************************/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,102 @@
/*
* emfdb.h -- EMF database compatability functions for GoAhead WebServer.
*
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
*
* See the file "license.txt" for usage and redistribution license requirements
*
* $Id$
*/
/******************************** Description *********************************/
/*
* Emf-like textfile database support for WebServer 2.1.
*/
/********************************* Includes ***********************************/
#ifndef _h_EMFDB
#define _h_EMFDB 1
#if ! UEMF
#include "basic/basic.h"
#include "emf/emf.h"
#else
#include "uemf.h"
#endif
/********************************* Defines ************************************/
#define T_INT 0
#define T_STRING 1
#define DB_OK 0
#define DB_ERR_GENERAL -1
#define DB_ERR_COL_NOT_FOUND -2
#define DB_ERR_COL_DELETED -3
#define DB_ERR_ROW_NOT_FOUND -4
#define DB_ERR_ROW_DELETED -5
#define DB_ERR_TABLE_NOT_FOUND -6
#define DB_ERR_TABLE_DELETED -7
#define DB_ERR_BAD_FORMAT -8
typedef struct dbTable_s {
char_t *name;
int nColumns;
char_t **columnNames;
int *columnTypes;
int nRows;
int **rows;
} dbTable_t;
/********************************** Prototypes ********************************/
/*
* Add a schema to the module-internal schema database
*/
extern int dbRegisterDBSchema(dbTable_t *sTable);
extern int dbOpen(char_t *databasename, char_t *filename,
int (*gettime)(int did), int flags);
extern void dbClose(int did);
extern int dbGetTableId(int did, char_t *tname);
extern char_t *dbGetTableName(int did, int tid);
extern int dbReadInt(int did, char_t *table, char_t *column, int row,
int *returnValue);
extern int dbReadStr(int did, char_t *table, char_t *column, int row,
char_t **returnValue);
extern int dbWriteInt(int did, char_t *table, char_t *column, int row,
int idata);
extern int dbWriteStr(int did, char_t *table, char_t *column, int row,
char_t *s);
extern int dbAddRow(int did, char_t *table);
extern int dbDeleteRow(int did, char_t *table, int rid);
extern int dbSetTableNrow(int did, char_t *table, int nNewRows);
extern int dbGetTableNrow(int did, char_t *table);
/*
* Dump the contents of a database to file
*/
extern int dbSave(int did, char_t *filename, int flags);
/*
* Load the contents of a database to file
*/
extern int dbLoad(int did, char_t *filename, int flags);
/*
* Search for a data in a given column
*/
extern int dbSearchStr(int did, char_t *table, char_t *column,
char_t *value, int flags);
extern void dbZero(int did);
extern char_t *basicGetProductDir();
extern void basicSetProductDir(char_t *proddir);
#endif /* _h_EMFDB */
/******************************************************************************/

View File

@@ -1,7 +1,7 @@
/*
* form.c -- Form processing (in-memory CGI) for the GoAhead Web server
*
* Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
*
* See the file "license.txt" for usage and redistribution license requirements
*/
@@ -29,12 +29,12 @@ static sym_fd_t formSymtab = -1; /* Symbol table for form handlers */
*/
int websFormHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg,
char_t *url, char_t *path, char_t* query)
char_t *url, char_t *path, char_t *query)
{
sym_t *sp;
char_t formBuf[FNAMESIZE];
char_t *cp, *formName;
int (*fn)(void *sock, char_t* path, char_t *args);
int (*fn)(void *sock, char_t *path, char_t *args);
a_assert(websValid(wp));
a_assert(url && *url);
@@ -63,16 +63,23 @@ int websFormHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg,
if (sp == NULL) {
websError(wp, 200, T("Form %s is not defined"), formName);
} else {
fn = (int (*)(void*, char_t*, char_t*)) sp->content.value.integer;
fn = (int (*)(void *, char_t *, char_t *)) sp->content.value.integer;
a_assert(fn);
if (fn) {
/*
* For good practice, forms must call websDone()
*/
(*fn)((void*) wp, formName, query);
/*
* Remove the test to force websDone, since this prevents
* the server "push" from a form>
*/
#if 0 /* push */
if (websValid(wp)) {
websError(wp, 200, T("Form didn't call websDone"));
}
#endif /* push */
}
}
return 1;
@@ -86,8 +93,6 @@ int websFormHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg,
int websFormDefine(char_t *name, void (*fn)(webs_t wp, char_t *path,
char_t *query))
{
static int once = 0;
a_assert(name && *name);
a_assert(fn);
@@ -95,9 +100,6 @@ int websFormDefine(char_t *name, void (*fn)(webs_t wp, char_t *path,
return -1;
}
if (once++ == 0) {
websFormOpen();
}
symEnter(formSymtab, name, valueInteger((int) fn), (int) NULL);
return 0;
}
@@ -109,7 +111,7 @@ int websFormDefine(char_t *name, void (*fn)(webs_t wp, char_t *path,
void websFormOpen()
{
formSymtab = symOpen(64);
formSymtab = symOpen(WEBS_SYM_INIT);
}
/******************************************************************************/
@@ -120,7 +122,8 @@ void websFormOpen()
void websFormClose()
{
if (formSymtab != -1) {
symClose(formSymtab, NULL);
symClose(formSymtab);
formSymtab = -1;
}
}
@@ -139,7 +142,7 @@ void websHeader(webs_t wp)
/*
* By license terms the following line of code must not be modified
*/
websWrite(wp, T("Server: GoAhead-Webs\r\n"));
websWrite(wp, T("Server: %s\r\n"), WEBS_NAME);
websWrite(wp, T("Pragma: no-cache\n"));
websWrite(wp, T("Cache-control: no-cache\n"));

View File

@@ -1,15 +1,15 @@
/*
* h.c -- Handle allocation module
*
* Copyright (c) GoAhead Software Inc., 1995-1999. All Rights Reserved.
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
* See the file "license.txt" for usage and redistribution license requirements
*/
/******************************** Description *********************************/
/*
* This module provides a simple API to allocate and free handles
* It maintains a dynamic array of pointers. These usually point to
* This module provides a simple API to allocate and free handles
* It maintains a dynamic array of pointers. These usually point to
* per-handle structures.
*/
@@ -36,12 +36,16 @@
/*********************************** Code *************************************/
/*
* Allocate a new file handle. On the first call, the caller must set the
* Allocate a new file handle. On the first call, the caller must set the
* handle map to be a pointer to a null pointer. *map points to the second
* element in the handle array.
*/
#if B_STATS
int HALLOC(B_ARGS_DEC, void ***map)
#else
int hAlloc(void ***map)
#endif
{
int *mp;
int handle, len, memsize, incr;
@@ -51,7 +55,11 @@ int hAlloc(void ***map)
if (*map == NULL) {
incr = H_INCR;
memsize = (incr + H_OFFSET) * sizeof(void**);
#if B_STATS
if ((mp = (int*) balloc(B_ARGS, memsize)) == NULL) {
#else
if ((mp = (int*) balloc(B_L, memsize)) == NULL) {
#endif
return -1;
}
memset(mp, 0, memsize);
@@ -68,11 +76,12 @@ int hAlloc(void ***map)
* Find the first null handle
*/
if (mp[H_USED] < mp[H_LEN]) {
for (handle = 0; handle < len; handle++)
for (handle = 0; handle < len; handle++) {
if (mp[handle+H_OFFSET] == 0) {
mp[H_USED]++;
return handle;
}
}
} else {
handle = len;
}
@@ -139,7 +148,11 @@ int hFree(void ***map, int handle)
* Allocate an entry in the halloc array.
*/
#if B_STATS
int HALLOCENTRY(B_ARGS_DEC, void ***list, int *max, int size)
#else
int hAllocEntry(void ***list, int *max, int size)
#endif
{
char_t *cp;
int id;
@@ -147,12 +160,20 @@ int hAllocEntry(void ***list, int *max, int size)
a_assert(list);
a_assert(max);
#if B_STATS
if ((id = HALLOC(B_ARGS, (void***) list)) < 0) {
#else
if ((id = hAlloc((void***) list)) < 0) {
#endif
return -1;
}
if (size > 0) {
#if B_STATS
if ((cp = balloc(B_ARGS, size)) == NULL) {
#else
if ((cp = balloc(B_L, size)) == NULL) {
#endif
hFree(list, id);
return -1;
}
@@ -169,3 +190,4 @@ int hAllocEntry(void ***list, int *max, int size)
}
/******************************************************************************/

View File

@@ -1,7 +1,7 @@
/*
* handler.c -- URL handler support
*
* Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
*
* See the file "license.txt" for usage and redistribution license requirements
*/
@@ -19,14 +19,16 @@
/*********************************** Locals ***********************************/
static websUrlHandlerType* websUrlHandler; /* URL handler list */
static websUrlHandlerType *websUrlHandler; /* URL handler list */
static int websUrlHandlerMax; /* Number of entries */
static int urlHandlerOpenCount = 0; /* count of apps */
/**************************** Forward Declarations ****************************/
static int websUrlHandlerSort(const void* p1, const void* p2);
static int websUrlHandlerSort(const void *p1, const void *p2);
static int websPublishHandler(webs_t wp, char_t *urlPrefix, char_t *webDir,
int sid, char_t *url, char_t *path, char_t *query);
static int websTidyUrl(webs_t wp);
/*********************************** Code *************************************/
/*
@@ -35,7 +37,11 @@ static int websPublishHandler(webs_t wp, char_t *urlPrefix, char_t *webDir,
int websUrlHandlerOpen()
{
websAspOpen();
if (++urlHandlerOpenCount == 1) {
websAspOpen();
websUrlHandler = NULL;
websUrlHandlerMax = 0;
}
return 0;
}
@@ -46,17 +52,20 @@ int websUrlHandlerOpen()
void websUrlHandlerClose()
{
websUrlHandlerType* sp;
websUrlHandlerType *sp;
websAspClose();
for (sp = websUrlHandler; sp < &websUrlHandler[websUrlHandlerMax]; sp++) {
bfree(B_L, sp->urlPrefix);
if (sp->webDir) {
bfree(B_L, sp->webDir);
if (--urlHandlerOpenCount <= 0) {
websAspClose();
for (sp = websUrlHandler; sp < &websUrlHandler[websUrlHandlerMax];
sp++) {
bfree(B_L, sp->urlPrefix);
if (sp->webDir) {
bfree(B_L, sp->webDir);
}
}
bfree(B_L, websUrlHandler);
websUrlHandlerMax = 0;
}
bfree(B_L, websUrlHandler);
websUrlHandlerMax = 0;
}
/******************************************************************************/
@@ -135,7 +144,7 @@ int websUrlHandlerDelete(int (*handler)(webs_t wp, char_t *urlPrefix,
* Sort in decreasing URL length order observing the flags for first and last
*/
static int websUrlHandlerSort(const void* p1, const void* p2)
static int websUrlHandlerSort(const void *p1, const void *p2)
{
websUrlHandlerType *s1, *s2;
int rc;
@@ -247,6 +256,8 @@ int websUrlHandlerRequest(webs_t wp)
websSetRequestPath(wp, websGetDefaultDir(), NULL);
websTidyUrl(wp);
/*
* We loop over each handler in order till one accepts the request.
* The security handler will handle the request if access is NOT allowed.
@@ -264,7 +275,7 @@ int websUrlHandlerRequest(webs_t wp)
return 1;
}
if (!websValid(wp)) {
goahead_trace(0,
trace(0,
T("webs: handler %s called websDone, but didn't return 1\n"),
sp->urlPrefix);
return 1;
@@ -272,7 +283,7 @@ int websUrlHandlerRequest(webs_t wp)
}
}
/*
* If no handler processed the request, then return an error. Note: It was
* If no handler processed the request, then return an error. Note: It is
* the handlers responsibility to call websDone
*/
if (i >= websUrlHandlerMax) {
@@ -281,4 +292,70 @@ int websUrlHandlerRequest(webs_t wp)
return 0;
}
/******************************************************************************/
/*
* Tidy up the URL path. Return -1 if the URL is bad.
* Used to eliminate repeated directory delimiters ('/').
*/
static int websTidyUrl(webs_t wp)
{
char_t *parts[64]; /* Array of ptr's to URL parts */
char_t *token, *url, *tidyurl;
int i, len, npart;
a_assert(websValid(wp));
/*
* Copy the string so we don't destroy the original (yet)
*/
url = bstrdup(B_L, wp->url);
websDecodeUrl(url, url, gstrlen(url));
len = npart = 0;
parts[0] = NULL;
token = gstrtok(url, T("/"));
/*
* Look at each directory segment and process "." and ".." segments
* Don't allow the browser to pop outside the root web.
*/
while (token != NULL) {
if (gstrcmp(token, T("..")) == 0) {
if (npart > 0) {
npart--;
}
} else if (gstrcmp(token, T(".")) != 0) {
parts[npart] = token;
len += gstrlen(token) + 1;
npart++;
}
token = gstrtok(NULL, T("/"));
}
/*
* Re-construct URL. Need extra space all "/" and null.
*/
if (npart || (gstrcmp(url, T("/")) == 0) || (url[0] == '\0')) {
tidyurl = balloc(B_L, (len + 2) * sizeof(char_t));
*tidyurl = '\0';
for (i = 0; i < npart; i++) {
gstrcat(tidyurl, T("/"));
gstrcat(tidyurl, parts[i]);
}
bfree(B_L, url);
bfree(B_L, wp->url);
wp->url = tidyurl;
return 0;
} else {
bfree(B_L, url);
return -1;
}
}
/******************************************************************************/

View File

@@ -0,0 +1,48 @@
/* MD5.H - header file for MD5C.C
*/
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
rights reserved.
License to copy and use this software is granted provided that it
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
Algorithm" in all material mentioning or referencing this software
or this function.
License is also granted to make and use derivative works provided
that such works are identified as "derived from the RSA Data
Security, Inc. MD5 Message-Digest Algorithm" in all material
mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this
documentation and/or software.
*/
#ifndef _h_MD5
#define _h_MD5 1
#ifndef UINT4
#define UINT4 unsigned long
#endif
#ifndef POINTER
#define POINTER unsigned char *
#endif
/* MD5 context. */
typedef struct {
UINT4 state[4]; /* state (ABCD) */
UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
unsigned char buffer[64]; /* input buffer */
} MD5_CONTEXT;
extern void MD5Init (MD5_CONTEXT *);
extern void MD5Update (MD5_CONTEXT *, unsigned char *, unsigned int);
extern void MD5Final (unsigned char [16], MD5_CONTEXT *);
#endif /* _h_MD5 */

View File

@@ -0,0 +1,335 @@
/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
*/
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
rights reserved.
License to copy and use this software is granted provided that it
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
Algorithm" in all material mentioning or referencing this software
or this function.
License is also granted to make and use derivative works provided
that such works are identified as "derived from the RSA Data
Security, Inc. MD5 Message-Digest Algorithm" in all material
mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this
documentation and/or software.
*/
#include "md5.h"
/* Constants for MD5Transform routine.
*/
#define S11 7
#define S12 12
#define S13 17
#define S14 22
#define S21 5
#define S22 9
#define S23 14
#define S24 20
#define S31 4
#define S32 11
#define S33 16
#define S34 23
#define S41 6
#define S42 10
#define S43 15
#define S44 21
static void MD5Transform (UINT4 [4], unsigned char [64]);
static void Encode (unsigned char *, UINT4 *, unsigned int);
static void Decode (UINT4 *, unsigned char *, unsigned int);
static void MD5_memcpy (POINTER, POINTER, unsigned int);
static void MD5_memset (POINTER, int, unsigned int);
static unsigned char PADDING[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
* Note: The following MD5 macros can be implemented as functions
* for code compactness, (at the expense of execution speed).
*/
/* F, G, H and I are basic MD5 functions.
*/
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))
/* ROTATE_LEFT rotates x left n bits.
*/
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
Rotation is separate from addition to prevent recomputation.
*/
#define FF(a, b, c, d, x, s, ac) { \
(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define GG(a, b, c, d, x, s, ac) { \
(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define HH(a, b, c, d, x, s, ac) { \
(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define II(a, b, c, d, x, s, ac) { \
(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
/* MD5 initialization. Begins an MD5 operation, writing a new context.
*/
void MD5Init (context)
MD5_CONTEXT *context; /* context */
{
context->count[0] = context->count[1] = 0;
/* Load magic initialization constants.
*/
context->state[0] = 0x67452301;
context->state[1] = 0xefcdab89;
context->state[2] = 0x98badcfe;
context->state[3] = 0x10325476;
}
/* MD5 block update operation. Continues an MD5 message-digest
operation, processing another message block, and updating the
context.
*/
void MD5Update (context, input, inputLen)
MD5_CONTEXT *context; /* context */
unsigned char *input; /* input block */
unsigned int inputLen; /* length of input block */
{
unsigned int i, index, partLen;
/* Compute number of bytes mod 64 */
index = (unsigned int)((context->count[0] >> 3) & 0x3F);
/* Update number of bits */
if ((context->count[0] += ((UINT4)inputLen << 3))
< ((UINT4)inputLen << 3))
context->count[1]++;
context->count[1] += ((UINT4)inputLen >> 29);
partLen = 64 - index;
/* Transform as many times as possible.
*/
if (inputLen >= partLen) {
MD5_memcpy
((POINTER)&context->buffer[index], (POINTER)input, partLen);
MD5Transform (context->state, context->buffer);
for (i = partLen; i + 63 < inputLen; i += 64)
MD5Transform (context->state, &input[i]);
index = 0;
}
else
i = 0;
/* Buffer remaining input */
MD5_memcpy
((POINTER)&context->buffer[index], (POINTER)&input[i],
inputLen-i);
}
/* MD5 finalization. Ends an MD5 message-digest operation, writing the
the message digest and zeroizing the context.
*/
void MD5Final (digest, context)
unsigned char digest[16]; /* message digest */
MD5_CONTEXT *context; /* context */
{
unsigned char bits[8];
unsigned int index, padLen;
/* Save number of bits */
Encode (bits, context->count, 8);
/* Pad out to 56 mod 64.
*/
index = (unsigned int)((context->count[0] >> 3) & 0x3f);
padLen = (index < 56) ? (56 - index) : (120 - index);
MD5Update (context, PADDING, padLen);
/* Append length (before padding) */
MD5Update (context, bits, 8);
/* Store state in digest */
Encode (digest, context->state, 16);
/* Zeroize sensitive information.
*/
MD5_memset ((POINTER)context, 0, sizeof (*context));
}
/* MD5 basic transformation. Transforms state based on block.
*/
static void MD5Transform (state, block)
UINT4 state[4];
unsigned char block[64];
{
UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
Decode (x, block, 64);
/* Round 1 */
FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
/* Round 2 */
GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
/* Round 3 */
HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
/* Round 4 */
II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
/* Zeroize sensitive information.
*/
MD5_memset ((POINTER)x, 0, sizeof (x));
}
/* Encodes input (UINT4) into output (unsigned char). Assumes len is
a multiple of 4.
*/
static void Encode (output, input, len)
unsigned char *output;
UINT4 *input;
unsigned int len;
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4) {
output[j] = (unsigned char)(input[i] & 0xff);
output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
}
}
/* Decodes input (unsigned char) into output (UINT4). Assumes len is
a multiple of 4.
*/
static void Decode (output, input, len)
UINT4 *output;
unsigned char *input;
unsigned int len;
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
(((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
}
/* Note: Replace "for loop" with standard memcpy if possible.
*/
static void MD5_memcpy (output, input, len)
POINTER output;
POINTER input;
unsigned int len;
{
unsigned int i;
for (i = 0; i < len; i++)
output[i] = input[i];
}
/* Note: Replace "for loop" with standard memset if possible.
*/
static void MD5_memset (output, value, len)
POINTER output;
int value;
unsigned int len;
{
unsigned int i;
for (i = 0; i < len; i++)
((char *)output)[i] = (char)value;
}

View File

@@ -1,7 +1,7 @@
/*
* mime.c -- Web server mime types
*
* Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
*
* See the file "license.txt" for usage and redistribution license requirements
*/

View File

@@ -1,7 +1,7 @@
/*
* misc.c -- Miscellaneous routines.
*
* Copyright (c) GoAhead Software Inc., 1995-1999. All Rights Reserved.
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
*
* See the file "license.txt" for usage and redistribution license requirements
*/
@@ -16,12 +16,12 @@
/********************************* Defines ************************************/
/*
* Sprintf buffer structure. Make the increment 8 less than 64 so that
* Sprintf buffer structure. Make the increment 64 so that
* a balloc can use a 64 byte block.
*/
#define STR_REALLOC 0x1 /* Reallocate the buffer as required */
#define STR_INC 58 /* Growth increment */
#define STR_INC 64 /* Growth increment */
typedef struct {
char_t *s; /* Pointer to buffer */
@@ -59,11 +59,11 @@ static void put_ulong(strbuf_t *buf, unsigned long int value, int base,
/************************************ Code ************************************/
/*
* "basename" returns a pointer to the last component of a pathname
* LINUX, RTEMS, and LynxOS have their own basename function
* LINUX and LynxOS have their own basename function
*/
#if ! LINUX & ! __rtems__ & ! LYNX
char_t *basename(char_t* name)
#if ! LINUX && ! LYNX && ! __rtems__
char_t *basename(char_t *name)
{
char_t *cp;
@@ -83,7 +83,7 @@ char_t *basename(char_t* name)
return ++cp;
}
}
#endif /* ! LINUX && ! __rtems__ && ! LYNX */
#endif /* ! LINUX & ! LYNX */
/******************************************************************************/
/*
@@ -91,9 +91,9 @@ char_t *basename(char_t* name)
* the size of the buffer in BYTES!
*/
char_t *dirname(char_t* buf, char_t* name, int bufsize)
char_t *dirname(char_t *buf, char_t *name, int bufsize)
{
char_t* cp;
char_t *cp;
int len;
a_assert(name);
@@ -130,14 +130,15 @@ char_t *dirname(char_t* buf, char_t* name, int bufsize)
return buf;
}
/******************************************************************************/
/*
* sprintf and vsprintf are bad, ok. You can easily clobber memory. Use
* gsnprintf and gvsnprintf instead! These functions do _not_ support floating
* fmtAlloc and fmtValloc instead! These functions do _not_ support floating
* point, like %e, %f, %g...
*/
int gsnprintf(char_t **s, int n, char_t *fmt, ...)
int fmtAlloc(char_t **s, int n, char_t *fmt, ...)
{
va_list ap;
int result;
@@ -147,7 +148,30 @@ int gsnprintf(char_t **s, int n, char_t *fmt, ...)
*s = NULL;
va_start(ap, fmt);
result = gvsnprintf(s, n, fmt, ap);
result = dsnprintf(s, n, fmt, ap, 0);
va_end(ap);
return result;
}
/******************************************************************************/
/*
* Support a static buffer version for small buffers only!
*/
int fmtStatic(char_t *s, int n, char_t *fmt, ...)
{
va_list ap;
int result;
a_assert(s);
a_assert(fmt);
a_assert(n <= 256);
if (n <= 0) {
return -1;
}
va_start(ap, fmt);
result = dsnprintf(&s, n, fmt, ap, 0);
va_end(ap);
return result;
}
@@ -158,7 +182,7 @@ int gsnprintf(char_t **s, int n, char_t *fmt, ...)
* reallocing if required.
*/
int gsprintfRealloc(char_t **s, int n, int msize, char_t *fmt, ...)
int fmtRealloc(char_t **s, int n, int msize, char_t *fmt, ...)
{
va_list ap;
int result;
@@ -180,17 +204,18 @@ int gsprintfRealloc(char_t **s, int n, int msize, char_t *fmt, ...)
* A vsprintf replacement.
*/
int gvsnprintf(char_t **s, int n, char_t *fmt, va_list arg)
int fmtValloc(char_t **s, int n, char_t *fmt, va_list arg)
{
a_assert(s);
a_assert(fmt);
*s = NULL;
return dsnprintf(s, n, fmt, arg, 0);
}
/******************************************************************************/
/*
* Dynamic sprintf implementation. Supports dynamic buffer allocation also.
* Dynamic sprintf implementation. Supports dynamic buffer allocation.
* This function can be called multiple times to grow an existing allocated
* buffer. In this case, msize is set to the size of the previously allocated
* buffer. The buffer will be realloced, as required. If msize is set, we
@@ -252,7 +277,7 @@ static int dsnprintf(char_t **s, int size, char_t *fmt, va_list arg, int msize)
}
c = *fmt++;
} else {
for ( ; gisdigit(c); c = *fmt++) {
for ( ; gisdigit((int)c); c = *fmt++) {
width = width * 10 + (c - '0');
}
}
@@ -263,7 +288,7 @@ static int dsnprintf(char_t **s, int size, char_t *fmt, va_list arg, int msize)
prec = va_arg(arg, int);
c = *fmt++;
} else {
for (prec = 0; gisdigit(c); c = *fmt++) {
for (prec = 0; gisdigit((int)c); c = *fmt++) {
prec = prec * 10 + (c - '0');
}
}
@@ -402,24 +427,28 @@ static int strnlen(char_t *s, unsigned int n)
static void put_char(strbuf_t *buf, char_t c)
{
if (buf->count >= buf->size) {
if (buf->count >= (buf->size - 1)) {
if (! (buf->flags & STR_REALLOC)) {
return;
}
buf->size += STR_INC;
if (buf->size > buf->max && buf->size > STR_INC) {
a_assert(buf->size <= buf->max);
/*
* Caller should increase the size of the calling buffer
*/
buf->size -= STR_INC;
return;
}
if (buf->s == NULL) {
buf->s = balloc(B_L, buf->size * sizeof(char_t*));
buf->s = balloc(B_L, buf->size * sizeof(char_t));
} else {
buf->s = brealloc(B_L, buf->s, buf->size * sizeof(char_t*));
buf->s = brealloc(B_L, buf->s, buf->size * sizeof(char_t));
}
}
buf->s[buf->count] = c;
++buf->count;
if (c != '\0') {
++buf->count;
}
}
/******************************************************************************/
@@ -428,7 +457,7 @@ static void put_char(strbuf_t *buf, char_t c)
*/
static void put_string(strbuf_t *buf, char_t *s, int len, int width,
int prec, enum flag f)
int prec, enum flag f)
{
int i;
@@ -458,7 +487,7 @@ static void put_string(strbuf_t *buf, char_t *s, int len, int width,
*/
static void put_ulong(strbuf_t *buf, unsigned long int value, int base,
int upper, char_t *prefix, int width, int prec, enum flag f)
int upper, char_t *prefix, int width, int prec, enum flag f)
{
unsigned long x, x2;
int len, zeros, i;
@@ -475,8 +504,14 @@ static void put_ulong(strbuf_t *buf, unsigned long int value, int base,
width -= strnlen(prefix, ULONG_MAX);
}
if (!(f & flag_minus)) {
for (i = 0; i < width; ++i) {
put_char(buf, ' ');
if (f & flag_zero) {
for (i = 0; i < width; ++i) {
put_char(buf, '0');
}
} else {
for (i = 0; i < width; ++i) {
put_char(buf, ' ');
}
}
}
if (prefix != NULL) {
@@ -524,7 +559,7 @@ char_t *ascToUni(char_t *ubuf, char *str, int nBytes)
* N.B. nBytes is the number of _bytes_ in the destination buffer, buf.
*/
char *uniToAsc(char *buf, char_t* ustr, int nBytes)
char *uniToAsc(char *buf, char_t *ustr, int nBytes)
{
#if UNICODE
if (WideCharToMultiByte(CP_ACP, 0, ustr, nBytes, buf, nBytes, NULL,
@@ -537,24 +572,26 @@ char *uniToAsc(char *buf, char_t* ustr, int nBytes)
return (char*) buf;
}
/******************************************************************************/
/*
* allocate (balloc) a buffer and do ascii to unicode conversion into it.
* cp points to the ascii string which must be NULL terminated.
* Return a pointer to the unicode buffer which must be bfree'd later.
* Return NULL on failure to get buffer.
* cp points to the ascii buffer. alen is the length of the buffer to be
* converted not including a terminating NULL. Return a pointer to the
* unicode buffer which must be bfree'd later. Return NULL on failure to
* get buffer. The buffer returned is NULL terminated.
*/
char_t *ballocAscToUni(char * cp)
char_t *ballocAscToUni(char *cp, int alen)
{
char_t * unip;
char_t *unip;
int ulen;
ulen = (strlen(cp) + 1) * sizeof(char_t);
ulen = (alen + 1) * sizeof(char_t);
if ((unip = balloc(B_L, ulen)) == NULL) {
return NULL;
}
ascToUni(unip, cp, ulen);
unip[alen] = 0;
return unip;
}
@@ -562,20 +599,68 @@ char_t *ballocAscToUni(char * cp)
/*
* allocate (balloc) a buffer and do unicode to ascii conversion into it.
* unip points to the unicoded string. ulen is the number of characters
* in the unicode string including teminating null, if there is one.
* Return a pointer to the ascii buffer which must be bfree'd later.
* Return NULL on failure to get buffer.
* in the unicode string not including a teminating null. Return a pointer
* to the ascii buffer which must be bfree'd later. Return NULL on failure
* to get buffer. The buffer returned is NULL terminated.
*/
char *ballocUniToAsc(char_t * unip, int ulen)
char *ballocUniToAsc(char_t *unip, int ulen)
{
char * cp;
if ((cp = balloc(B_L, ulen)) == NULL) {
if ((cp = balloc(B_L, ulen+1)) == NULL) {
return NULL;
}
uniToAsc(cp, unip, ulen);
cp[ulen] = '\0';
return cp;
}
/******************************************************************************/
/*
* convert a hex string to an integer. The end of the string or a non-hex
* character will indicate the end of the hex specification.
*/
unsigned int hextoi(char_t *hexstring)
{
register char_t *h;
register unsigned int c, v;
v = 0;
h = hexstring;
if (*h == '0' && (*(h+1) == 'x' || *(h+1) == 'X')) {
h += 2;
}
while ((c = (unsigned int)*h++) != 0) {
if (c >= '0' && c <= '9') {
c -= '0';
} else if (c >= 'a' && c <= 'f') {
c = (c - 'a') + 10;
} else if (c >= 'A' && c <= 'F') {
c = (c - 'A') + 10;
} else {
break;
}
v = (v * 0x10) + c;
}
return v;
}
/******************************************************************************/
/*
* convert a string to an integer. If the string starts with "0x" or "0X"
* a hexidecimal conversion is done.
*/
unsigned int gstrtoi(char_t *s)
{
if (*s == '0' && (*(s+1) == 'x' || *(s+1) == 'X')) {
s += 2;
return hextoi(s);
}
return gatoi(s);
}
/******************************************************************************/

View File

@@ -1,7 +1,7 @@
/*
* ringq.c -- Ring queue buffering module
*
* Copyright (c) GoAhead Software Inc., 1995-1999. All Rights Reserved.
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
*
* See the file "license.txt" for usage and redistribution license requirements
*/
@@ -10,7 +10,7 @@
/*
* A ring queue allows maximum utilization of memory for data storage and is
* ideal for input/output buffering. This module provides a highly effecient
* ideal for input/output buffering. This module provides a highly efficient
* implementation and a vehicle for dynamic strings.
*
* WARNING: This is a public implementation and callers have full access to
@@ -36,10 +36,10 @@
* rq->buf rq->servp rq->endp rq->enduf
*
* The queue is empty when servp == endp. This means that the queue will hold
* at most rq->buflen -1 bytes. It is the fillers responsibility to ensure
* at most rq->buflen -1 bytes. It is the filler's responsibility to ensure
* the ringq is never filled such that servp == endp.
*
* It is the fillers responsibility to "wrap" the endp back to point to
* It is the filler's responsibility to "wrap" the endp back to point to
* rq->buf when the pointer steps past the end. Correspondingly it is the
* consumers responsibility to "wrap" the servp when it steps to rq->endbuf.
* The ringqPutc and ringqGetc routines will do this automatically.
@@ -65,7 +65,10 @@
/***************************** Forward Declarations ***************************/
static int ringq_grow(ringq_t *rq);
static int ringqGrow(ringq_t *rq);
static int getBinBlockSize(int size);
int ringqGrowCalls = 0;
/*********************************** Code *************************************/
/*
@@ -76,12 +79,15 @@ static int ringq_grow(ringq_t *rq);
* dynamically allocated. Set maxsize
*/
int ringqOpen(ringq_t *rq, int increment, int maxsize)
int ringqOpen(ringq_t *rq, int initSize, int maxsize)
{
a_assert(rq);
a_assert(increment >= 0);
int increment;
if ((rq->buf = balloc(B_L, increment)) == NULL) {
a_assert(rq);
a_assert(initSize >= 0);
increment = getBinBlockSize(initSize);
if ((rq->buf = balloc(B_L, (increment))) == NULL) {
return -1;
}
rq->maxsize = maxsize;
@@ -115,8 +121,8 @@ void ringqClose(ringq_t *rq)
/******************************************************************************/
/*
* Return the length of the ringq. Users must fill the queue to a high
* water mark of at most one less than the queue size.
* Return the length of the data in the ringq. Users must fill the queue to
* a high water mark of at most one less than the queue size.
*/
int ringqLen(ringq_t *rq)
@@ -126,8 +132,7 @@ int ringqLen(ringq_t *rq)
if (rq->servp > rq->endp) {
return rq->buflen + rq->endp - rq->servp;
}
else {
} else {
return rq->endp - rq->servp;
}
}
@@ -166,12 +171,12 @@ int ringqGetc(ringq_t *rq)
int ringqPutc(ringq_t *rq, char_t c)
{
char_t* cp;
char_t *cp;
a_assert(rq);
a_assert(rq->buflen == (rq->endbuf - rq->buf));
if (ringqPutBlkMax(rq) < (int) sizeof(char_t) && !ringq_grow(rq)) {
if ((ringqPutBlkMax(rq) < (int) sizeof(char_t)) && !ringqGrow(rq)) {
return -1;
}
@@ -191,12 +196,12 @@ int ringqPutc(ringq_t *rq, char_t c)
int ringqInsertc(ringq_t *rq, char_t c)
{
char_t* cp;
char_t *cp;
a_assert(rq);
a_assert(rq->buflen == (rq->endbuf - rq->buf));
if (ringqPutBlkMax(rq) < (int) sizeof(char_t) && !ringq_grow(rq)) {
if (ringqPutBlkMax(rq) < (int) sizeof(char_t) && !ringqGrow(rq)) {
return -1;
}
if (rq->servp <= rq->buf) {
@@ -210,10 +215,10 @@ int ringqInsertc(ringq_t *rq, char_t c)
/******************************************************************************/
/*
* Add a string to the queue. Add a trailing wide null (two nulls)
* Add a string to the queue. Add a trailing null (maybe two nulls)
*/
int ringqPutstr(ringq_t *rq, char_t *str)
int ringqPutStr(ringq_t *rq, char_t *str)
{
int rc;
@@ -226,6 +231,19 @@ int ringqPutstr(ringq_t *rq, char_t *str)
return rc;
}
/******************************************************************************/
/*
* Add a null terminator. This does NOT increase the size of the queue
*/
void ringqAddNull(ringq_t *rq)
{
a_assert(rq);
a_assert(rq->buflen == (rq->endbuf - rq->buf));
*((char_t*) rq->endp) = (char_t) '\0';
}
/******************************************************************************/
#if UNICODE
/*
@@ -261,7 +279,7 @@ int ringqPutcA(ringq_t *rq, char c)
a_assert(rq);
a_assert(rq->buflen == (rq->endbuf - rq->buf));
if (ringqPutBlkMax(rq) == 0 && !ringq_grow(rq)) {
if (ringqPutBlkMax(rq) == 0 && !ringqGrow(rq)) {
return -1;
}
@@ -282,7 +300,7 @@ int ringqInsertcA(ringq_t *rq, char c)
a_assert(rq);
a_assert(rq->buflen == (rq->endbuf - rq->buf));
if (ringqPutBlkMax(rq) == 0 && !ringq_grow(rq)) {
if (ringqPutBlkMax(rq) == 0 && !ringqGrow(rq)) {
return -1;
}
if (rq->servp <= rq->buf) {
@@ -298,7 +316,7 @@ int ringqInsertcA(ringq_t *rq, char c)
* ie. beyond the last valid byte.
*/
int ringqPutstrA(ringq_t *rq, char *str)
int ringqPutStrA(ringq_t *rq, char *str)
{
int rc;
@@ -334,7 +352,7 @@ int ringqPutBlk(ringq_t *rq, unsigned char *buf, int size)
while (size > 0) {
this = min(ringqPutBlkMax(rq), size);
if (this <= 0) {
if (! ringq_grow(rq)) {
if (! ringqGrow(rq)) {
break;
}
this = min(ringqPutBlkMax(rq), size);
@@ -485,10 +503,13 @@ void ringqGetBlkAdj(ringq_t *rq, int size)
void ringqFlush(ringq_t *rq)
{
a_assert(rq);
a_assert(rq->servp);
rq->servp = rq->buf;
rq->endp = rq->buf;
*rq->servp = '\0';
if (rq->servp) {
*rq->servp = '\0';
}
}
/******************************************************************************/
@@ -498,7 +519,7 @@ void ringqFlush(ringq_t *rq)
* the maximum possible size.
*/
static int ringq_grow(ringq_t *rq)
static int ringqGrow(ringq_t *rq)
{
unsigned char *newbuf;
int len;
@@ -531,7 +552,31 @@ static int ringq_grow(ringq_t *rq)
rq->endbuf = &rq->buf[rq->buflen];
ringqPutBlk(rq, newbuf, len);
/*
* Double the increment so the next grow will line up with balloc'ed memory
*/
rq->increment = getBinBlockSize(2 * rq->increment);
return 1;
}
/******************************************************************************/
/*
* Find the smallest binary memory size that "size" will fit into. This
* makes the ringq and ringqGrow routines much more efficient. The balloc
* routine likes powers of 2 minus 1.
*/
static int getBinBlockSize(int size)
{
int q;
size = size >> B_SHIFT;
for (q = 0; size; size >>= 1) {
q++;
}
return (1 << (B_SHIFT + q));
}
/******************************************************************************/

View File

@@ -1,7 +1,7 @@
/*
* rom.c -- Support for ROMed page retrieval.
*
* Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
*
* See the file "license.txt" for usage and redistribution license requirements
*/
@@ -20,13 +20,6 @@
#include <stdlib.h>
#if CE
#define EINVAL 22
#define EBADF 9
#else
#include <errno.h>
#endif
#include "wsIntrn.h"
/******************************** Local Data **********************************/
@@ -46,7 +39,7 @@ int websRomOpen()
int nchars;
char_t name[SYM_MAX];
romTab = symOpen(64);
romTab = symOpen(WEBS_SYM_INIT);
for (wip = websRomPageIndex; wip->path; wip++) {
gstrncpy(name, wip->path, SYM_MAX);
@@ -67,7 +60,7 @@ int websRomOpen()
void websRomClose()
{
symClose(romTab, NULL);
symClose(romTab);
}
/******************************************************************************/
@@ -105,7 +98,7 @@ void websRomPageClose(int fd)
* Stat a web page
*/
int websRomPageStat(char_t *path, websStatType* sbuf)
int websRomPageStat(char_t *path, websStatType *sbuf)
{
websRomPageIndexType *wip;
sym_t *sp;
@@ -193,6 +186,6 @@ long websRomPageSeek(webs_t wp, long offset, int origin)
return (wip->pos = pos);
}
#endif
#endif /* WEBS_PAGE_ROM */
/******************************************************************************/

View File

@@ -1,7 +1,7 @@
/*
* security.c -- Security handler
*
* Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
*
* See the file "license.txt" for usage and redistribution license requirements
*/
@@ -9,18 +9,42 @@
/******************************** Description *********************************/
/*
* This module provides a basic security policy. It supports a single global
* password and ignores the username. Encoding/decoding of the password is
* -not- done.
* This module provides a basic security policy.
*/
/********************************* Includes ***********************************/
#include "wsIntrn.h"
#include "um.h"
#ifdef DIGEST_ACCESS_SUPPORT
#include "websda.h"
#endif
/********************************** Defines ***********************************/
/*
* The following #defines change the behaviour of security in the absence
* of User Management.
* Note that use of User management functions require prior calling of
* umInit() to behave correctly
*/
#ifndef USER_MANAGEMENT_SUPPORT
#define umGetAccessMethodForURL(url) AM_FULL
#define umUserExists(userid) 0
#define umUserCanAccessURL(userid, url) 1
#define umGetUserPassword(userid) websGetPassword()
#define umGetAccessLimitSecure(accessLimit) 0
#define umGetAccessLimit(url) NULL
#endif
/******************************** Local Data **********************************/
static char_t websPassword[WEBS_MAX_PASS]; /* Access password (decoded) */
#ifdef _DEBUG
static int debugSecurity = 1;
#else
static int debugSecurity = 0;
#endif
/*********************************** Code *************************************/
/*
@@ -30,46 +54,143 @@ static char_t websPassword[WEBS_MAX_PASS]; /* Access password (decoded) */
int websSecurityHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg,
char_t *url, char_t *path, char_t *query)
{
char_t *type, *password;
int flags;
char_t *type, *userid, *password, *accessLimit;
int flags, nRet;
accessMeth_t am;
a_assert(websValid(wp));
a_assert(url && *url);
a_assert(path && *path);
/*
* Get the critical request details
*/
type = websGetRequestType(wp);
password = websGetRequestPassword(wp);
userid = websGetRequestUserName(wp);
flags = websGetRequestFlags(wp);
/*
* Get the access limit for the URL. Exit if none found.
*/
accessLimit = umGetAccessLimit(path);
if (accessLimit == NULL) {
return 0;
}
/*
* Check to see if URL must be encrypted
*/
#ifdef WEBS_SSL_SUPPORT
nRet = umGetAccessLimitSecure(accessLimit);
if (nRet && ((flags | WEBS_SECURE) == 0)) {
websStats.access++;
websError(wp, 200, T("Access Denied\nSecure access is required."));
trace(3, T("SEC: Non-secure access attempted on <%s>\n"), path);
return 1;
}
#endif
/*
* Validate the users password if required (local access is always allowed)
* We compare the decoded form of the password.
* Get the access limit for the URL
*/
if (*websPassword && !(flags & WEBS_LOCAL_REQUEST)) {
am = umGetAccessMethodForURL(accessLimit);
if (password && *password) {
if (gstrcmp(password, websPassword) != 0) {
nRet = 0;
if ((flags & WEBS_LOCAL_REQUEST) && (debugSecurity == 0)) {
/*
* Local access is always allowed (defeat when debugging)
*/
} else if (am == AM_NONE) {
/*
* URL is supposed to be hidden! Make like it wasn't found.
*/
websStats.access++;
websError(wp, 400, T("Page Not Found"));
nRet = 1;
} else if (userid && *userid) {
if (!umUserExists(userid)) {
websStats.access++;
websError(wp, 200, T("Access Denied\nUnknown User"));
trace(3, T("SEC: Unknown user <%s> attempted to access <%s>\n"),
userid, path);
nRet = 1;
} else if (!umUserCanAccessURL(userid, accessLimit)) {
websStats.access++;
websError(wp, 403, T("Access Denied\nProhibited User"));
nRet = 1;
} else if (password && * password) {
char_t * userpass = umGetUserPassword(userid);
if (userpass) {
if (gstrcmp(password, userpass) != 0) {
websStats.access++;
websError(wp, 200, T("Access Denied\nWrong Password"));
trace(3, T("SEC: Password fail for user <%s>")
T("attempt to access <%s>\n"), userid, path);
nRet = 1;
} else {
/*
* User and password check out.
*/
}
bfree (B_L, userpass);
}
#ifdef DIGEST_ACCESS_SUPPORT
} else if (flags & WEBS_AUTH_DIGEST) {
char_t *digestCalc;
/*
* Check digest for equivalence
*/
wp->password = umGetUserPassword(userid);
a_assert(wp->digest);
a_assert(wp->nonce);
a_assert(wp->password);
digestCalc = websCalcDigest(wp);
a_assert(digestCalc);
if (gstrcmp(wp->digest, digestCalc) != 0) {
websStats.access++;
websError(wp, 200, T("Access Denied\nWrong Password"));
websSetPassword(T(""));
return 1;
nRet = 1;
}
bfree (B_L, digestCalc);
#endif
} else {
/*
* This will cause the browser to display a password / username
* dialog
* No password has been specified
*/
#ifdef DIGEST_ACCESS_SUPPORT
if (am == AM_DIGEST) {
wp->flags |= WEBS_AUTH_DIGEST;
}
#endif
websStats.errors++;
websError(wp, 401, T("<html><head>Access Denied</head><body>\r\n\
Access to this document requires a password.</body>\
</html>\r\n"));
return 1;
websError(wp, 401,
T("Access to this document requires a password"));
nRet = 1;
}
} else if (am != AM_FULL) {
/*
* This will cause the browser to display a password / username
* dialog
*/
#ifdef DIGEST_ACCESS_SUPPORT
if (am == AM_DIGEST) {
wp->flags |= WEBS_AUTH_DIGEST;
}
#endif
websStats.errors++;
websError(wp, 401, T("Access to this document requires a User ID"));
nRet = 1;
}
return 0;
bfree(B_L, accessLimit);
return nRet;
}
/******************************************************************************/
@@ -102,7 +223,7 @@ void websSetPassword(char_t *password)
char_t *websGetPassword()
{
return websPassword;
return bstrdup(B_L, websPassword);
}
/******************************************************************************/

File diff suppressed because it is too large Load Diff

View File

@@ -1,15 +1,15 @@
/*
* sym.c -- Symbol Table module
*
* Copyright (c) GoAhead Software Inc., 1995-1999. All Rights Reserved.
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
*
* See the file "license.txt" for usage and redistribution license requirements
*/
/******************************** Description *********************************/
/*
* This module implements a highly efficient generic symbol table with
* update and access routines. Symbols are simple character strings and
* This module implements a highly efficient generic symbol table with
* update and access routines. Symbols are simple character strings and
* the values they take can be flexible types as defined by value_t.
* This modules allows multiple symbol tables to be created.
*/
@@ -32,24 +32,51 @@ typedef struct { /* Symbol table descriptor */
/********************************* Globals ************************************/
static sym_tabent_t **sym; /* List of symbol tables */
static int sym_max; /* One past the max symbol table */
static sym_tabent_t **sym; /* List of symbol tables */
static int symMax; /* One past the max symbol table */
static int symOpenCount = 0; /* Count of apps using sym */
static int htIndex; /* Current location in table */
static sym_t* next; /* Next symbol in iteration */
static int htIndex; /* Current location in table */
static sym_t* next; /* Next symbol in iteration */
/**************************** Forward Declarations ****************************/
static int hashIndex(sym_tabent_t *tp, char_t *name);
static sym_t *hash(sym_tabent_t *tp, char_t *name);
static int calc_prime(int size);
static int hashIndex(sym_tabent_t *tp, char_t *name);
static sym_t *hash(sym_tabent_t *tp, char_t *name);
static int calcPrime(int size);
/*********************************** Code *************************************/
/*
* Open the symbol table subSystem.
*/
int symSubOpen()
{
if (++symOpenCount == 1) {
symMax = 0;
sym = NULL;
}
return 0;
}
/******************************************************************************/
/*
* Close the symbol table subSystem.
*/
void symSubClose()
{
if (--symOpenCount <= 0) {
symOpenCount = 0;
}
}
/******************************************************************************/
/*
* Create a symbol table.
*/
sym_fd_t symOpen(int hash_size)
sym_fd_t symOpen(int hash_size)
{
sym_fd_t sd;
sym_tabent_t *tp;
@@ -67,20 +94,20 @@ sym_fd_t symOpen(int hash_size)
* Create a new symbol table structure and zero
*/
if ((tp = (sym_tabent_t*) balloc(B_L, sizeof(sym_tabent_t))) == NULL) {
sym_max = hFree((void***) &sym, sd);
symMax = hFree((void***) &sym, sd);
return -1;
}
memset(tp, 0, sizeof(sym_tabent_t));
if (sd >= sym_max) {
sym_max = sd + 1;
if (sd >= symMax) {
symMax = sd + 1;
}
a_assert(0 <= sd && sd < sym_max);
a_assert(0 <= sd && sd < symMax);
sym[sd] = tp;
/*
* Now create the hash table for fast indexing.
*/
tp->hash_size = calc_prime(hash_size);
tp->hash_size = calcPrime(hash_size);
tp->hash_table = (sym_t**) balloc(B_L, tp->hash_size * sizeof(sym_t*));
a_assert(tp->hash_table);
memset(tp->hash_table, 0, tp->hash_size * sizeof(sym_t*));
@@ -94,13 +121,13 @@ sym_fd_t symOpen(int hash_size)
* to free resources associated with each symbol table entry.
*/
void symClose(sym_fd_t sd, void (*cleanup)(sym_t *symp))
void symClose(sym_fd_t sd)
{
sym_tabent_t *tp;
sym_t *sp, *forw;
int i;
int i;
a_assert(0 <= sd && sd < sym_max);
a_assert(0 <= sd && sd < symMax);
tp = sym[sd];
a_assert(tp);
@@ -110,30 +137,18 @@ void symClose(sym_fd_t sd, void (*cleanup)(sym_t *symp))
for (i = 0; i < tp->hash_size; i++) {
for (sp = tp->hash_table[i]; sp; sp = forw) {
forw = sp->forw;
if (cleanup) {
(*cleanup)(sp);
}
valueFree(&sp->name);
valueFree(&sp->content);
bfree(B_L, (void*) sp);
sp = forw;
}
}
bfree(B_L, (void*) tp->hash_table);
sym_max = hFree((void***) &sym, sd);
symMax = hFree((void***) &sym, sd);
bfree(B_L, (void*) tp);
}
/******************************************************************************/
/*
* Default callback for freeing the value.
*/
void symFreeVar(sym_t* sp)
{
valueFree(&sp->content);
}
/******************************************************************************/
/*
* Return the first symbol in the hashtable if there is one. This call is used
@@ -145,9 +160,9 @@ sym_t* symFirst(sym_fd_t sd)
{
sym_tabent_t *tp;
sym_t *sp, *forw;
int i;
int i;
a_assert(0 <= sd && sd < sym_max);
a_assert(0 <= sd && sd < symMax);
tp = sym[sd];
a_assert(tp);
@@ -180,9 +195,9 @@ sym_t* symNext(sym_fd_t sd)
{
sym_tabent_t *tp;
sym_t *sp, *forw;
int i;
int i;
a_assert(0 <= sd && sd < sym_max);
a_assert(0 <= sd && sd < symMax);
tp = sym[sd];
a_assert(tp);
@@ -219,9 +234,10 @@ sym_t *symLookup(sym_fd_t sd, char_t *name)
sym_t *sp;
char_t *cp;
a_assert(0 <= sd && sd < sym_max);
tp = sym[sd];
a_assert(tp);
a_assert(0 <= sd && sd < symMax);
if ((tp = sym[sd]) == NULL) {
return NULL;
}
if (name == NULL || *name == '\0') {
return NULL;
@@ -241,8 +257,10 @@ sym_t *symLookup(sym_fd_t sd, char_t *name)
/******************************************************************************/
/*
* Enter a symbol into the table. If already there, update its value.
* Always succeeds if memory available.
* Enter a symbol into the table. If already there, update its value.
* Always succeeds if memory available. We allocate a copy of "name" here
* so it can be a volatile variable. The value "v" is just a copy of the
* passed in value, so it MUST be persistent.
*/
sym_t *symEnter(sym_fd_t sd, char_t *name, value_t v, int arg)
@@ -252,13 +270,13 @@ sym_t *symEnter(sym_fd_t sd, char_t *name, value_t v, int arg)
char_t *cp;
int hindex;
a_assert(name && *name);
a_assert(0 <= sd && sd < sym_max);
a_assert(name);
a_assert(0 <= sd && sd < symMax);
tp = sym[sd];
a_assert(tp);
/*
* Calculate the first daisy-chain from the hash table. If non-zero, then
* Calculate the first daisy-chain from the hash table. If non-zero, then
* we have daisy-chain, so scan it and look for the symbol.
*/
last = NULL;
@@ -333,12 +351,12 @@ int symDelete(sym_fd_t sd, char_t *name)
int hindex;
a_assert(name && *name);
a_assert(0 <= sd && sd < sym_max);
a_assert(0 <= sd && sd < symMax);
tp = sym[sd];
a_assert(tp);
/*
* Calculate the first daisy-chain from the hash table. If non-zero, then
* Calculate the first daisy-chain from the hash table. If non-zero, then
* we have daisy-chain, so scan it and look for the symbol.
*/
last = NULL;
@@ -355,7 +373,7 @@ int symDelete(sym_fd_t sd, char_t *name)
if (sp == (sym_t*) NULL) { /* Not Found */
return -1;
}
/*
* Unlink and free the symbol. Last will be set if the element to be deleted
* is not first in the chain.
@@ -366,6 +384,7 @@ int symDelete(sym_fd_t sd, char_t *name)
tp->hash_table[hindex] = sp->forw;
}
valueFree(&sp->name);
valueFree(&sp->content);
bfree(B_L, (void*) sp);
return 0;
@@ -393,13 +412,13 @@ static sym_t *hash(sym_tabent_t *tp, char_t *name)
static int hashIndex(sym_tabent_t *tp, char_t *name)
{
unsigned int sum;
int i;
unsigned int sum;
int i;
a_assert(tp);
/*
* Add in each character shifted up progressively by 7 bits. The shift
* amount is rounded so as to not shift too far. It thus cycles with each
* amount is rounded so as to not shift too far. It thus cycles with each
* new cycle placing character shifted up by one bit.
*/
i = 0;
@@ -416,13 +435,14 @@ static int hashIndex(sym_tabent_t *tp, char_t *name)
* Check if this number is a prime
*/
static int is_prime(int n)
static int isPrime(int n)
{
int i;
int i, max;
a_assert(n > 0);
for (i = 2; i < n; i++) {
max = n / 2;
for (i = 2; i <= max; i++) {
if (n % i == 0) {
return 0;
}
@@ -435,14 +455,14 @@ static int is_prime(int n)
* Calculate the largest prime smaller than size.
*/
static int calc_prime(int size)
static int calcPrime(int size)
{
int count;
a_assert(size > 0);
for (count = size; count > 0; count--) {
if (is_prime(count)) {
if (isPrime(count)) {
return count;
}
}
@@ -450,3 +470,4 @@ static int calc_prime(int size)
}
/******************************************************************************/

View File

@@ -1,7 +1,7 @@
/*
* uemf.c -- GoAhead Micro Embedded Management Framework
*
* Copyright (c) Go Ahead Software, Inc., 1995-1999
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
*
* See the file "license.txt" for usage and redistribution license requirements
*/
@@ -22,31 +22,62 @@
int emfInst; /* Application instance handle */
/****************************** Forward Declarations **************************/
extern void defaultErrorHandler(int etype, char_t *buf);
static void (*errorHandler)(int etype, char_t *msg) = defaultErrorHandler;
extern void defaultTraceHandler(int level, char_t *buf);
static void (*traceHandler)(int level, char_t *buf) = defaultTraceHandler;
/************************************* Code ***********************************/
/*
* Error message that doesn't need user attention. Customize this code
* to direct error messages to whereever the developer wishes
* to direct error messages to wherever the developer wishes
*/
void error(E_ARGS_DEC, int flags, char_t *fmt, ...)
void error(E_ARGS_DEC, int etype, char_t *fmt, ...)
{
va_list arglist;
va_start(arglist, fmt);
if (flags & E_LOG) {
/* Log error message */
va_list args;
char_t *fmtBuf, *buf;
} else if (flags & E_ASSERT) {
/* Assert message */
va_start(args, fmt);
fmtValloc(&fmtBuf, E_MAX_ERROR, fmt, args);
} else if (flags & E_USER) {
/* Display message to the user */
if (etype == E_LOG) {
fmtAlloc(&buf, E_MAX_ERROR, T("%s\n"), fmtBuf);
#if DEV
} else if (etype == E_ASSERT) {
fmtAlloc(&buf, E_MAX_ERROR,
T("Assertion %s, failed at %s %d\n"), fmtBuf, E_ARGS);
#endif
} else if (etype == E_USER) {
fmtAlloc(&buf, E_MAX_ERROR, T("%s\n"), fmtBuf);
}
va_end(args);
bfree(B_L, fmtBuf);
if (errorHandler) {
errorHandler(etype, buf);
}
vprintf (fmt, arglist);
va_end(arglist);
bfreeSafe(B_L, buf);
}
/******************************************************************************/
/*
* Replace the default error handler. Return pointer to old error handler.
*/
void (*errorSetHandler(void (*function)(int etype, char_t *msg))) \
(int etype, char_t *msg)
{
void (*oldHandler)(int etype, char_t *buf);
oldHandler = errorHandler;
errorHandler = function;
return oldHandler;
}
/******************************************************************************/
@@ -54,21 +85,48 @@ void error(E_ARGS_DEC, int flags, char_t *fmt, ...)
* Trace log. Customize this function to log trace output
*/
void goahead_trace(int level, char_t *afmt, ...)
void trace(int level, char_t *fmt, ...)
{
#if DEBUG
va_list args;
char_t *buf;
va_start(args, afmt);
buf = NULL;
gvsnprintf(&buf, VALUE_MAX_STRING, afmt, args);
if (buf) {
gprintf(buf);
bfree(B_L, buf);
va_start(args, fmt);
fmtValloc(&buf, VALUE_MAX_STRING, fmt, args);
if (traceHandler) {
traceHandler(level, buf);
}
bfreeSafe(B_L, buf);
va_end(args);
#endif
}
/******************************************************************************/
/*
* Trace log. Customize this function to log trace output
*/
void traceRaw(char_t *buf)
{
if (traceHandler) {
traceHandler(0, buf);
}
}
/******************************************************************************/
/*
* Replace the default trace handler. Return a pointer to the old handler.
*/
void (*traceSetHandler(void (*function)(int level, char_t *buf)))
(int level, char *buf)
{
void (*oldHandler)(int level, char_t *buf);
oldHandler = traceHandler;
if (function) {
traceHandler = function;
}
return oldHandler;
}
/******************************************************************************/
@@ -197,4 +255,27 @@ char_t *stritoa(int n, char_t *string, int width)
}
/******************************************************************************/
/*
* Stubs
*/
char_t *basicGetProduct()
{
return T("uemf");
}
char_t *basicGetAddress()
{
return T("localhost");
}
int errorOpen(char_t *pname)
{
return 0;
}
void errorClose()
{
}
/******************************************************************************/

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,184 @@
/*
* um.h -- GoAhead User Management public header
*
* Copyright (c) GoAhead Software Inc., 1992-2000. All Rights Reserved.
*
* See the file "license.txt" for information on usage and redistribution
*
* $Id$
*/
#ifndef _h_UM
#define _h_UM 1
/******************************** Description *********************************/
/*
* GoAhead User Management header. This defines the User Management
* public APIs. Include this header for files that contain access to
* user inquiry or management.
*/
/********************************* Includes ***********************************/
#if ! UEMF
#include "basic/basic.h"
#include "emf/emf.h"
#else
#include "uemf.h"
#endif
/********************************** Defines ***********************************/
/*
* Error Return Flags
*/
#define UM_OK 0
#define UM_ERR_GENERAL -1
#define UM_ERR_NOT_FOUND -2
#define UM_ERR_PROTECTED -3
#define UM_ERR_DUPLICATE -4
#define UM_ERR_IN_USE -5
#define UM_ERR_BAD_NAME -6
#define UM_ERR_BAD_PASSWORD -7
/*
* Privilege Masks
*/
#define PRIV_NONE 0x00
#define PRIV_READ 0x01
#define PRIV_WRITE 0x02
#define PRIV_ADMIN 0x04
/*
* User classes
*/
typedef short bool_t;
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
typedef enum {
AM_NONE = 0,
AM_FULL,
AM_BASIC,
AM_DIGEST,
AM_INVALID
} accessMeth_t;
/********************************** Prototypes ********************************/
/*
* umOpen() must be called before accessing User Management functions
*/
extern int umOpen();
/*
* umClose() should be called before shutdown to free memory
*/
extern void umClose();
/*
* umCommit() persists the user management database
*/
extern int umCommit(char_t *filename);
/*
* umRestore() loads the user management database
*/
extern int umRestore(char_t *filename);
/*
* umUser functions use a user ID for a key
*/
extern int umAddUser(char_t *user, char_t *password,
char_t *group, bool_t protect, bool_t disabled);
extern int umDeleteUser(char_t *user);
extern char_t *umGetFirstUser();
extern char_t *umGetNextUser(char_t *lastUser);
extern bool_t umUserExists(char_t *user);
extern char_t *umGetUserPassword(char_t *user);
extern int umSetUserPassword(char_t *user, char_t *password);
extern char_t *umGetUserGroup(char_t *user);
extern int umSetUserGroup(char_t *user, char_t *password);
extern bool_t umGetUserEnabled(char_t *user);
extern int umSetUserEnabled(char_t *user, bool_t enabled);
extern bool_t umGetUserProtected(char_t *user);
extern int umSetUserProtected(char_t *user, bool_t protect);
/*
* umGroup functions use a group name for a key
*/
extern int umAddGroup(char_t *group, short privilege,
accessMeth_t am, bool_t protect, bool_t disabled);
extern int umDeleteGroup(char_t *group);
extern char_t *umGetFirstGroup();
extern char_t *umGetNextGroup(char_t *lastUser);
extern bool_t umGroupExists(char_t *group);
extern bool_t umGetGroupInUse(char_t *group);
extern accessMeth_t umGetGroupAccessMethod(char_t *group);
extern int umSetGroupAccessMethod(char_t *group, accessMeth_t am);
extern bool_t umGetGroupEnabled(char_t *group);
extern int umSetGroupEnabled(char_t *group, bool_t enabled);
extern short umGetGroupPrivilege(char_t *group);
extern int umSetGroupPrivilege(char_t *group, short privileges);
extern bool_t umGetGroupProtected(char_t *group);
extern int umSetGroupProtected(char_t *group, bool_t protect);
/*
* umAccessLimit functions use a URL as a key
*/
extern int umAddAccessLimit(char_t *url, accessMeth_t am,
short secure, char_t *group);
extern int umDeleteAccessLimit(char_t *url);
extern char_t *umGetFirstAccessLimit();
extern char_t *umGetNextAccessLimit(char_t *lastUser);
/*
* Returns the name of an ancestor access limit if
*/
extern char_t *umGetAccessLimit(char_t *url);
extern bool_t umAccessLimitExists(char_t *url);
extern accessMeth_t umGetAccessLimitMethod(char_t *url);
extern int umSetAccessLimitMethod(char_t *url, accessMeth_t am);
extern short umGetAccessLimitSecure(char_t *url);
extern int umSetAccessLimitSecure(char_t *url, short secure);
extern char_t *umGetAccessLimitGroup(char_t *url);
extern int umSetAccessLimitGroup(char_t *url, char_t *group);
/*
* Convenience Functions
*/
extern accessMeth_t umGetAccessMethodForURL(char_t *url);
extern bool_t umUserCanAccessURL(char_t *user, char_t *url);
#endif /* _h_UM */
/******************************************************************************/

View File

@@ -1,7 +1,7 @@
/*
* url.c -- Parse URLs
*
* Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
*
* See the file "license.txt" for usage and redistribution license requirements
*/
@@ -83,7 +83,7 @@ int websUrlParse(char_t *url, char_t **pbuf, char_t **phost, char_t **ppath,
ulen = gstrlen(url);
/*
* We allocate enough to store a separate hostname and port number fields.
* We allocate enough to store separate hostname and port number fields.
* As there are 3 strings in the one buffer, we need room for 3 null chars.
* We allocate MAX_PORT_LEN char_t's for the port number.
*/
@@ -146,16 +146,23 @@ int websUrlParse(char_t *url, char_t **pbuf, char_t **phost, char_t **ppath,
}
/*
* Parse the tag and the query
* Parse the query string
*/
if ((cp = gstrchr(tok, '#')) != NULL) {
*cp++ = '\0';
path = tok;
tok = cp;
}
if ((cp = gstrchr(tok, '?')) != NULL) {
*cp++ = '\0';
query = cp;
path = tok;
tok = query;
}
/*
* Parse the fragment identifier
*/
if ((cp = gstrchr(tok, '#')) != NULL) {
*cp++ = '\0';
if (*query == 0) {
path = tok;
}
}
/*

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
/*
* webcomp -- Compile web pages into C source
*
* Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
*
* See the file "license.txt" for usage and redistribution license requirements
*/
@@ -71,10 +71,10 @@ static int compile(char_t *fileList, char_t *prefix)
FILE *lp;
time_t now;
char_t file[FNAMESIZE];
char_t *cp;
char_t *cp, *sl;
char buf[512];
char *p;
int j, i, len, fd, nFile;
unsigned char *p;
int j, i, len, fd, nFile;
/*
* Open list of files
@@ -87,7 +87,7 @@ static int compile(char_t *fileList, char_t *prefix)
time(&now);
fprintf(stdout, "/*\n * webrom.c -- Compiled Web Pages\n *\n");
fprintf(stdout, " * Compiled by GoAhead WebCompile: %s */\n\n",
ctime(&now));
gctime(&now));
fprintf(stdout, "#include \"wsIntrn.h\"\n\n");
fprintf(stdout, "#ifndef WEBS_PAGE_ROM\n");
fprintf(stdout, "websRomPageIndexType websRomPageIndex[] = {\n");
@@ -102,6 +102,9 @@ static int compile(char_t *fileList, char_t *prefix)
if ((p = strchr(file, '\n')) || (p = strchr(file, '\r'))) {
*p = '\0';
}
if (*file == '\0') {
continue;
}
if (gstat(file, &sbuf) == 0 && sbuf.st_mode & S_IFDIR) {
continue;
}
@@ -109,7 +112,7 @@ static int compile(char_t *fileList, char_t *prefix)
fprintf(stderr, "Can't open file %s\n", file);
return -1;
}
fprintf(stdout, "static unsigned char page_%d[] = {\n", nFile);
fprintf(stdout, "static const unsigned char page_%d[] = {\n", nFile);
while ((len = read(fd, buf, sizeof(buf))) > 0) {
p = buf;
@@ -143,6 +146,9 @@ static int compile(char_t *fileList, char_t *prefix)
if ((p = strchr(file, '\n')) || (p = strchr(file, '\r'))) {
*p = '\0';
}
if (*file == '\0') {
continue;
}
/*
* Remove the prefix and add a leading "/" when we print the path
*/
@@ -151,6 +157,9 @@ static int compile(char_t *fileList, char_t *prefix)
} else {
cp = file;
}
while((sl = strchr(file, '\\')) != NULL) {
*sl = '/';
}
if (*cp == '/') {
cp++;
}
@@ -159,8 +168,8 @@ static int compile(char_t *fileList, char_t *prefix)
fprintf(stdout, " { T(\"/%s\"), 0, 0 },\n", cp);
continue;
}
fprintf(stdout, " { T(\"/%s\"), page_%d, %ld },\n", cp, nFile,
(long) sbuf.st_size);
fprintf(stdout, " { T(\"/%s\"), page_%d, %d },\n", cp, nFile,
sbuf.st_size);
nFile++;
}
fclose(lp);

View File

@@ -25,12 +25,22 @@
#include <rtems/error.h>
#ifdef WEBS_SSL_SUPPORT
#include "websSSL.h"
#endif
#ifdef USER_MANAGEMENT_SUPPORT
#include "um.h"
void formDefineUserMgmt(void);
#endif
/*********************************** Locals ***********************************/
/*
* Change configuration here
*/
static char_t *rootWeb = T("web"); /* Root web directory */
extern const char *tftpServer;
static char_t *rootWeb = T("goahead"); /* Root web directory */
static char_t *password = T(""); /* Security password */
static int port = 80; /* Server port */
static int retries = 5; /* Server port retries */
@@ -113,33 +123,47 @@ rtems_httpd_daemon()
/*
* Initialize the web server
*/
while (initWebs() < 0) {
printf("\nUnable to initialize Web server !!\n"
" Suspending the task. Resume to try again.\n");
rtems_task_suspend( RTEMS_SELF);
if (initWebs() < 0) {
rtems_panic("Unable to initialize Web server !!\n");
}
#ifdef WEBS_SSL_SUPPORT
websSSLOpen();
#endif
/*
* Basic event loop. SocketReady returns true when a socket is ready for
* service. SocketSelect will block until an event occurs. SocketProcess
* will actually do the servicing.
*/
while (!finished) {
if (socketReady() || socketSelect()) {
socketProcess();
if (socketReady(-1) || socketSelect(-1, 2000)) {
socketProcess(-1);
}
/*websCgiCleanup();*/
emfSchedProcess();
}
#ifdef WEBS_SSL_SUPPORT
websSSLClose();
#endif
#ifdef USER_MANAGEMENT_SUPPORT
umClose();
#endif
/*
* Close the socket module, report memory leaks and close the memory allocator
*/
websCloseServer();
websDefaultClose();
socketClose();
symSubClose();
#if B_STATS
memLeaks();
#endif
bclose();
rtems_task_delete( RTEMS_SELF );
rtems_task_delete( RTEMS_SELF );
}
/******************************************************************************/
@@ -177,15 +201,14 @@ static int initWebs()
memcpy((char *) &intaddr, (char *) hp->h_addr_list[0],
(size_t) hp->h_length);
#if 0
/*
* Set ../web as the root web. Modify this to suit your needs
* Set /TFTP/x.y.z.w/goahead as the root web. Modify to suit your needs
*/
getcwd(dir, sizeof(dir));
if ((cp = strrchr(dir, '/'))) {
*cp = '\0';
}
sprintf(webdir, "%s/%s", dir, rootWeb);
sprintf(webdir, "/TFTP/%s/%s", tftpServer, rootWeb);
#else
sprintf(webdir, "/");
#endif
/*
* Configure the web server options before opening the web server
*/
@@ -198,7 +221,11 @@ static int initWebs()
/*
* Configure the web server options before opening the web server
*/
#if 0
websSetDefaultPage(T("default.asp"));
#else
websSetDefaultPage(T("index.html"));
#endif
websSetPassword(password);
/*
@@ -380,7 +407,11 @@ static int websHomePageHandler(webs_t wp, char_t *urlPrefix, char_t *webDir,
* If the empty or "/" URL is invoked, redirect default URLs to the home page
*/
if (*url == '\0' || gstrcmp(url, T("/")) == 0) {
#if 0
websRedirect(wp, T("home.asp"));
#else
websRedirect(wp, T("index.html"));
#endif
return 1;
}
return 0;
@@ -391,12 +422,14 @@ static int websHomePageHandler(webs_t wp, char_t *urlPrefix, char_t *webDir,
#if B_STATS
static void memLeaks()
{
int fd;
int fd=1;
if ((fd = gopen(T("leak.txt"), O_CREAT | O_TRUNC | O_WRONLY)) >= 0) {
/* if ((fd = gopen(T("leak.txt"), O_CREAT | O_TRUNC | O_WRONLY)) >= 0) { */
bstats(fd, printMemStats);
/*
close(fd);
}
*/
}
/******************************************************************************/
@@ -416,4 +449,51 @@ static void printMemStats(int handle, char_t *fmt, ...)
}
#endif
/******************************************************************************/
/*****************************************************************************/
/*****************************************************************************/
/*
* Default error handler. The developer should insert code to handle
* error messages in the desired manner.
*/
void defaultErrorHandler(int etype, char_t *msg)
{
#if 1
write(1, msg, gstrlen(msg));
#endif
}
/*****************************************************************************/
/*
* Trace log. Customize this function to log trace output
*/
void defaultTraceHandler(int level, char_t *buf)
{
/*
* The following code would write all trace regardless of level
* to stdout.
*/
#if 1
if (buf) {
write(1, buf, gstrlen(buf));
}
#endif
}
/*****************************************************************************/
/*
* Returns a pointer to an allocated qualified unique temporary file name.
* This filename must eventually be deleted with bfree();
*/
char_t *websGetCgiCommName()
{
char_t *pname1, *pname2;
pname1 = tempnam(NULL, T("cgi"));
pname2 = bstrdup(B_L, pname1);
free(pname1);
return pname2;
}

View File

@@ -1,7 +1,7 @@
/*
* Page.c -- Support for page retrieval.
*
* Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
*
* See the file "license.txt" for usage and redistribution license requirements
*/
@@ -41,6 +41,8 @@ int websPageOpen(webs_t wp, char_t *lpath, char_t *path, int mode, int perm)
void websPageClose(webs_t wp)
{
a_assert(websValid(wp));
#if WEBS_PAGE_ROM
websRomPageClose(wp->docfd);
#else

View File

@@ -1,7 +1,8 @@
/*
* webrom.c -- Compiled Web Pages
*
* Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
*
* See the file "license.txt" for usage and redistribution license requirements
*/

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
/*
* webs.h -- Go Ahead Web public header
* webs.h -- GoAhead Web public header
*
* Copyright (c) Go Ahead Software Inc., 1992-1999. All Rights Reserved.
* Copyright (c) GoAhead Software Inc., 1992-2000. All Rights Reserved.
*
* See the file "license.txt" for information on usage and redistribution
*/
@@ -12,7 +12,7 @@
/******************************** Description *********************************/
/*
* Go Ahead Web Server header. This defines the Web public APIs.
* GoAhead Web Server header. This defines the Web public APIs.
* Include this header for files that contain ASP or Form procedures.
* Include wsIntrn.h when creating URL handlers.
*/
@@ -20,8 +20,17 @@
/********************************* Includes ***********************************/
#include "ej.h"
#ifdef WEBS_SSL_SUPPORT
#include "websSSL.h"
#endif
/********************************** Defines ***********************************/
/*
* By license terms the server software name defined in the following line of
* code must not be modified.
*/
#define WEBS_NAME T("GoAhead-Webs")
#define WEBS_VERSION T("2.1")
#define WEBS_HEADER_BUFINC 512 /* Header buffer size */
#define WEBS_ASP_BUFINC 512 /* Asp expansion increment */
@@ -31,6 +40,9 @@
#define WEBS_MAX_URL 4096 /* Maximum URL size for sanity */
#define WEBS_SOCKET_BUFSIZ 256 /* Bytes read from socket */
#define WEBS_HTTP_PORT T("httpPort")
#define CGI_BIN T("cgi-bin")
/*
* Request flags. Also returned by websGetRequestFlags().
*/
@@ -48,6 +60,10 @@
#define WEBS_FORM 0x800 /* Request is a form */
#define WEBS_REQUEST_DONE 0x1000 /* Request complete */
#define WEBS_POST_DATA 0x2000 /* Already appended post data */
#define WEBS_CGI_REQUEST 0x4000 /* cgi-bin request */
#define WEBS_SECURE 0x8000 /* connection uses SSL */
#define WEBS_AUTH_BASIC 0x10000 /* Basic authentication request */
#define WEBS_AUTH_DIGEST 0x20000 /* Digest authentication request */
#define WEBS_HEADER_DONE 0x40000 /* Already output the HTTP header */
/*
@@ -65,38 +81,56 @@ typedef struct websRec {
sym_fd_t cgiVars; /* CGI standard variables */
sym_fd_t cgiQuery; /* CGI decoded query string */
time_t timestamp; /* Last transaction with browser */
void* timeout; /* Timeout handle */
int timeout; /* Timeout handle */
char_t ipaddr[32]; /* Connecting ipaddress */
char_t type[64]; /* Mime type */
char_t* dir; /* Directory containing the page */
char_t* path; /* Path name without query */
char_t* url; /* Full request url */
char_t* host; /* Requested host */
char_t* lpath; /* Cache local path name */
char_t* query; /* Request query */
char_t* decodedQuery; /* Decoded request query */
char_t* password; /* Authorization password */
char_t* userName; /* Authorization username */
char_t* cookie; /* Cookie string */
char_t* userAgent; /* User agent (browser) */
char_t *dir; /* Directory containing the page */
char_t *path; /* Path name without query */
char_t *url; /* Full request url */
char_t *host; /* Requested host */
char_t *lpath; /* Cache local path name */
char_t *query; /* Request query */
char_t *decodedQuery; /* Decoded request query */
char_t *authType; /* Authorization type (Basic/DAA) */
char_t *password; /* Authorization password */
char_t *userName; /* Authorization username */
char_t *cookie; /* Cookie string */
char_t *userAgent; /* User agent (browser) */
char_t *protocol; /* Protocol (normally HTTP) */
char_t *protoVersion; /* Protocol version */
int sid; /* Socket id (handler) */
int listenSid; /* Listen Socket id */
int port; /* Request port number */
int state; /* Current state */
int flags; /* Current flags -- see above */
int code; /* Request result code */
int clen; /* Content length */
int wid; /* Index into webs */
char_t *cgiStdin; /* filename for CGI stdin */
int docfd; /* Document file descriptor */
int numbytes; /* Bytes to transfer to browser */
int numbytes; /* Bytes to transfer to browser */
int written; /* Bytes actually transferred */
void (*writeSocket)(struct websRec *wp);
#ifdef DIGEST_ACCESS_SUPPORT
char_t *realm; /* usually the same as "host" from websRec */
char_t *nonce; /* opaque-to-client string sent by server */
char_t *digest; /* digest form of user password */
char_t *uri; /* URI found in DAA header */
char_t *opaque; /* opaque value passed from server */
char_t *nc; /* nonce count */
char_t *cnonce; /* check nonce */
char_t *qop; /* quality operator */
#endif
#ifdef WEBS_SSL_SUPPORT
websSSL_t *wsp; /* SSL data structure */
#endif
} websRec;
typedef websRec *webs_t;
typedef websRec websType;
/******************************** Prototypes **********************************/
extern int websAccept(int sid, char *ipaddr, int port, int listenSid);
extern int websAspDefine(char_t *name,
int (*fn)(int ejid, webs_t wp, int argc, char_t **argv));
extern int websAspRequest(webs_t wp, char_t *lpath);
@@ -112,9 +146,11 @@ extern int websFormDefine(char_t *name, void (*fn)(webs_t wp,
extern char_t *websGetDefaultDir();
extern char_t *websGetDefaultPage();
extern char_t *websGetHostUrl();
extern char_t *websGetIpaddrUrl();
extern char_t *websGetPassword();
extern int websGetPort();
extern char_t *websGetPublishDir(char_t *path, char_t **urlPrefix);
extern char_t *websGetRealm();
extern int websGetRequestBytes(webs_t wp);
extern char_t *websGetRequestDir(webs_t wp);
extern int websGetRequestFlags(webs_t wp);
@@ -125,6 +161,7 @@ extern char_t *websGetRequestPassword(webs_t wp);
extern char_t *websGetRequestType(webs_t wp);
extern int websGetRequestWritten(webs_t wp);
extern char_t *websGetVar(webs_t wp, char_t *var, char_t *def);
extern int websCompareVar(webs_t wp, char_t *var, char_t *value);
extern void websHeader(webs_t wp);
extern int websOpenListen(int port, int retries);
extern int websPageOpen(webs_t wp, char_t *lpath, char_t *path,
@@ -142,6 +179,7 @@ extern void websSetEnv(webs_t wp);
extern void websSetHost(char_t *host);
extern void websSetIpaddr(char_t *ipaddr);
extern void websSetPassword(char_t *password);
extern void websSetRealm(char_t *realmName);
extern void websSetRequestBytes(webs_t wp, int bytes);
extern void websSetRequestFlags(webs_t wp, int flags);
extern void websSetRequestLpath(webs_t wp, char_t *lpath);
@@ -150,6 +188,7 @@ extern char_t *websGetRequestUserName(webs_t wp);
extern void websSetRequestWritten(webs_t wp, int written);
extern void websSetVar(webs_t wp, char_t *var, char_t *value);
extern int websTestVar(webs_t wp, char_t *var);
extern void websTimeoutCancel(webs_t wp);
extern int websUrlHandlerDefine(char_t *urlPrefix, char_t *webDir,
int arg, int (*fn)(webs_t wp, char_t *urlPrefix,
char_t *webDir, int arg, char_t *url, char_t *path,
@@ -164,10 +203,18 @@ extern int websUrlParse(char_t *url, char_t **buf, char_t **host,
extern char_t *websUrlType(char_t *webs, char_t *buf, int charCnt);
extern int websWrite(webs_t wp, char_t* fmt, ...);
extern int websWriteBlock(webs_t wp, char_t *buf, int nChars);
extern int websWriteBlockData(webs_t wp, char *buf, int nChars);
extern int websWriteDataNonBlock(webs_t wp, char *buf, int nChars);
extern int websValid(webs_t wp);
extern int websValidateUrl(webs_t wp, char_t *path);
extern int websCloseFileHandle(webs_t wp);
extern void websMarkTime(webs_t wp);
/*
* The following prototypes are used by the SSL patch found in websSSL.c
*/
extern int websAlloc(int sid);
extern void websFree(webs_t wp);
extern void websTimeout(void *arg, int id);
extern void websReadEvent(webs_t wp);
/*
* Prototypes for functions available when running as part of the

View File

@@ -1,7 +1,7 @@
/*
* websuemf.c -- GoAhead Micro Embedded Management Framework
*
* Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
*
* See the file "license.txt" for usage and redistribution license requirements
*/
@@ -14,14 +14,32 @@
/*********************************** Includes *********************************/
#include "ejIntrn.h"
#include "wsIntrn.h"
/*********************************** Defines **********************************/
/*
* This structure stores scheduled events.
*/
typedef struct {
void (*routine)(void *arg, int id);
void *arg;
time_t at;
int schedid;
} sched_t;
/*********************************** Locals ***********************************/
static sched_t **sched;
static int schedMax;
/************************************* Code ***********************************/
/*
* Evaluate a script
*/
int scriptEval(int engine, char_t* cmd, char_t** result, int chan)
int scriptEval(int engine, char_t *cmd, char_t **result, int chan)
{
int ejid;
@@ -37,3 +55,156 @@ int scriptEval(int engine, char_t* cmd, char_t** result, int chan)
}
/******************************************************************************/
/*
* Compare strings, ignoring case: normal strcmp return codes.
*
* WARNING: It is not good form to increment or decrement pointers inside a
* "call" to tolower et al. These can be MACROS, and have undesired side
* effects.
*/
int strcmpci(char_t *s1, char_t *s2)
{
int rc;
a_assert(s1 && s2);
if (s1 == NULL || s2 == NULL) {
return 0;
}
if (s1 == s2) {
return 0;
}
do {
rc = gtolower(*s1) - gtolower(*s2);
if (*s1 == '\0') {
break;
}
s1++;
s2++;
} while (rc == 0);
return rc;
}
/******************************************************************************/
/*
* This function is called when a scheduled process time has come.
*/
void TimerProc(int schedid)
{
sched_t *s;
a_assert(0 <= schedid && schedid < schedMax);
s = sched[schedid];
a_assert(s);
(s->routine)(s->arg, s->schedid);
}
/******************************************************************************/
/*
* Schedule an event in delay milliseconds time. We will use 1 second
* granularity for webServer.
*/
int emfSchedCallback(int delay, emfSchedProc *proc, void *arg)
{
sched_t *s;
int schedid;
if ((schedid = hAllocEntry((void***) &sched, &schedMax,
sizeof(sched_t))) < 0) {
return -1;
}
s = sched[schedid];
s->routine = proc;
s->arg = arg;
s->schedid = schedid;
/*
* Round the delay up to seconds.
*/
s->at = ((delay + 500) / 1000) + time(0);
return schedid;
}
/******************************************************************************/
/*
* Reschedule to a new delay.
*/
void emfReschedCallback(int schedid, int delay)
{
sched_t *s;
if (sched == NULL || schedid == -1 || schedid >= schedMax ||
(s = sched[schedid]) == NULL) {
return;
}
s->at = ((delay + 500) / 1000) + time(0);
}
/******************************************************************************/
void emfUnschedCallback(int schedid)
{
sched_t *s;
if (sched == NULL || schedid == -1 || schedid >= schedMax ||
(s = sched[schedid]) == NULL) {
return;
}
bfree(B_L, s);
schedMax = hFree((void***) &sched, schedid);
}
/******************************************************************************/
/*
* Take the tasks off the queue in a round robin fashion.
*/
void emfSchedProcess()
{
sched_t *s;
int schedid;
static int next = 0;
/*
* If schedMax is 0, there are no tasks scheduled, so just return.
*/
if (schedMax <= 0) {
return;
}
/*
* If next >= schedMax, the schedule queue was reduced in our absence
* so reset next to 0 to start from the begining of the queue again.
*/
if (next >= schedMax) {
next = 0;
}
schedid = next;
for (;;) {
if ((s = sched[schedid]) != NULL && (int)s->at <= (int)time(0)) {
TimerProc(schedid);
next = schedid + 1;
return;
}
if (++schedid >= schedMax) {
schedid = 0;
}
if (schedid == next) {
/*
* We've gone all the way through the queue without finding
* anything to do so just return.
*/
return;
}
}
}
/******************************************************************************/

View File

@@ -1,18 +1,18 @@
/*
* wsIntrn.h -- Internal Go Ahead Web server header
* wsIntrn.h -- Internal GoAhead Web server header
*
* Copyright (c) Go Ahead Software Inc., 1992-1999. All Rights Reserved.
* Copyright (c) GoAhead Software Inc., 1992-2000. All Rights Reserved.
*
* See the file "license.txt" for information on usage and redistribution
*/
#ifndef _h_WEBS_INTERNAL
#define _h_WEBS_INTERNAL 1
/******************************** Description *********************************/
/*
* Internal Go Ahead Web Server header. This defines the Web private APIs
* Internal GoAhead Web Server header. This defines the Web private APIs
* Include this header when you want to create URL handlers.
*/
@@ -33,7 +33,6 @@
* #define WEBS_PROXY_SUPPORT 1
*
* Define this to support reading pages from ROM
* Note: this is not yet fully implemented.
* #define WEBS_PAGE_ROM 1
*
* Define this to enable memory allocation and stack usage tracking
@@ -64,6 +63,13 @@
#include <sys/stat.h>
#endif
#if SCOV5
#include <fcntl.h>
#include <sys/stat.h>
#include <signal.h>
#include <unistd.h>
#endif
#if LYNX
#include <fcntl.h>
#include <sys/stat.h>
@@ -91,17 +97,24 @@
#include <sys/stat.h>
#endif
#if VXW486
#if VXWORKS
#include <vxWorks.h>
#include <fcntl.h>
#include <sys/stat.h>
#endif
#if SOLARIS
#include <macros.h>
#include <fcntl.h>
#include <sys/stat.h>
#endif
#if UEMF
#include "uemf.h"
#include "ej.h"
#include "ejIntrn.h"
#else
#include "emf/emfInternal.h"
#include "ej/ejIntrn.h"
#endif
#include "webs.h"
@@ -110,16 +123,18 @@
/*
* Read handler flags and state
*/
#define WEBS_BEGIN 0x1 /* Beginning state */
#define WEBS_HEADER 0x2 /* Ready to read first line */
#define WEBS_POST 0x4 /* POST without content */
#define WEBS_POST_CLEN 0x8 /* Ready to read content for POST */
#define WEBS_PROCESSING 0x10 /* Processing request */
#define WEBS_KEEP_TIMEOUT 15000 /* Keep-alive timeout (15 secs) */
#define WEBS_TIMEOUT 60000 /* General request timeout (60) */
#define WEBS_BEGIN 0x1 /* Beginning state */
#define WEBS_HEADER 0x2 /* Ready to read first line */
#define WEBS_POST 0x4 /* POST without content */
#define WEBS_POST_CLEN 0x8 /* Ready to read content for POST */
#define WEBS_PROCESSING 0x10 /* Processing request */
#define WEBS_KEEP_TIMEOUT 15000 /* Keep-alive timeout (15 secs) */
#define WEBS_TIMEOUT 60000 /* General request timeout (60) */
#define PAGE_READ_BUFSIZE 512 /* bytes read from page files */
#define MAX_PORT_LEN 10 /* max digits in port number */
#define PAGE_READ_BUFSIZE 512 /* bytes read from page files */
#define MAX_PORT_LEN 10 /* max digits in port number */
#define WEBS_SYM_INIT 64 /* initial # of sym table entries */
#define WEBS_VERSION_STR T("2.1.3") /* version of web server s/w */
/*
* URL handler structure. Stores the leading URL path and the handler
@@ -150,6 +165,7 @@ typedef struct {
long localHits;
long remoteHits;
long formHits;
long cgiHits;
long handlerHits;
} websStatsType;
@@ -185,7 +201,7 @@ typedef struct {
*/
typedef struct {
char_t *path; /* Web page URL path */
unsigned char *page; /* Web page data */
const unsigned char *page; /* Web page data */
int size; /* Size of web page in bytes */
int pos; /* Current read position */
} websRomPageIndexType;
@@ -209,6 +225,7 @@ extern int websMax; /* List size */
extern char_t websHost[64]; /* Name of this host */
extern char_t websIpaddr[64]; /* IP address of this host */
extern char_t *websHostUrl; /* URL for this host */
extern char_t *websIpaddrUrl; /* URL for this host */
extern int websPort; /* Port number */
/******************************** Prototypes **********************************/
@@ -224,12 +241,21 @@ extern int websDefaultHandler(webs_t wp, char_t *urlPrefix,
char_t *query);
extern int websFormHandler(webs_t wp, char_t *urlPrefix, char_t *webDir,
int arg, char_t *url, char_t *path, char_t *query);
extern int websCgiHandler(webs_t wp, char_t *urlPrefix, char_t *webDir,
int arg, char_t *url, char_t *path, char_t *query);
extern void websCgiCleanup();
extern int websCheckCgiProc(int handle);
extern char_t *websGetCgiCommName();
extern int websLaunchCgiProc(char_t *cgiPath, char_t **argp,
char_t **envp, char_t *stdIn, char_t *stdOut);
extern int websOpen(int sid);
extern void websResponse(webs_t wp, int code, char_t *msg,
char_t *redirect);
extern int websJavaScriptEval(webs_t wp, char_t *script);
extern int websPageReadData(webs_t wp, char *buf, int nBytes);
extern int websPageOpen(webs_t wp, char_t *lpath, char_t *path, int mode, int perm);
extern int websPageOpen(webs_t wp, char_t *lpath, char_t *path, int mode,
int perm);
extern void websPageClose(webs_t wp);
extern void websPageSeek(webs_t wp, long offset);
extern int websPageStat(webs_t wp, char_t *lpath, char_t *path,
@@ -253,6 +279,8 @@ extern int websOpenServer(int port, int retries);
extern void websCloseServer();
extern char_t* websGetDateString(websStatType* sbuf);
extern int strcmpci(char_t* s1, char_t* s2);
/*
* Prototypes for functions available when running as part of the
* GoAhead Embedded Management Framework (EMF)
@@ -263,6 +291,11 @@ extern void websEmfClose();
extern void websSetEmfEnvironment(webs_t wp);
#endif
#if CE
extern int writeUniToAsc(int fid, void *buf, unsigned int len);
extern int readAscToUni(int fid, void **buf, unsigned int len);
#endif
#endif /* _h_WEBS_INTERNAL */
/******************************************************************************/