zte's code,first commit

Change-Id: I9a04da59e459a9bc0d67f101f700d9d7dc8d681b
diff --git a/ap/app/goahead/server/Makefile b/ap/app/goahead/server/Makefile
new file mode 100755
index 0000000..1e209f7
--- /dev/null
+++ b/ap/app/goahead/server/Makefile
@@ -0,0 +1,246 @@
+# /*****************************************************************************
+#* °æÈ¨ËùÓÐ (C)2015, ÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾¡£
+#* 
+#* ÎļþÃû³Æ:     Makefile
+#* Îļþ±êʶ:     Makefile
+#* ÄÚÈÝÕªÒª:     Makefile of ZTE applications
+#* ʹÓ÷½·¨:     void
+#* 
+#* ÐÞ¸ÄÈÕÆÚ        °æ±¾ºÅ      Ð޸ıê¼Ç        ÐÞ¸ÄÈË          ÐÞ¸ÄÄÚÈÝ
+#* -----------------------------------------------------------------------------
+#* 2015/02/10      V1.0        Create          ÁõÑÇÄÏ          ´´½¨
+#* 
+# ******************************************************************************/
+
+#*******************************************************************************
+# include ZTE application makefile
+#*******************************************************************************
+include $(zte_app_mak)
+
+#*******************************************************************************
+# execute
+#*******************************************************************************
+EXEC    = goahead
+
+
+# User Management switch
+#UMSW	= -DUSER_MANAGEMENT_SUPPORT
+CPU_PUB_ROOT=$(TOPDIR_AP)/../pub
+INTERFACEDIR = ../interface5.0
+INTERFACELIB = $(INTERFACEDIR)/libwebinterface.a
+#*******************************************************************************
+# objects asp.o ejlex.o ejparse.o umui.o
+#*******************************************************************************
+OBJS    =		  balloc.o base64.o cgi.o default.o \
+				  form.o \
+				  h.o handler.o mime.o misc.o page.o  \
+				  ringq.o \
+				  sock.o sockGen.o \
+				  sym.o uemf.o value.o \
+				  webs.o websuemf.o goahead.o
+
+#*******************************************************************************
+# include path
+#*******************************************************************************
+CFLAGS	+= -DWEBS -DUEMF -DOS="LINUX" -DLINUX $(UMSW) $(DASW) $(SSLSW) $(IFMODSW)
+CFLAGS  += -Wall -fno-strict-aliasing -I../interface5.0/net -I.
+#CFLAGS	+= -I$(ROOTDIR)/lib/libnvram -I$(ROOTDIR)/$(LINUXDIR)/drivers/char -I$(ROOTDIR)/$(LINUXDIR)/include
+#CFLAGS  += -I$(ROOTDIR)/$(LINUXDIR)/drivers/flash -I$(INTERFACEDIR)
+
+#OTHERS	= -DB_STATS -DB_FILL -DDEBUG
+CFLAGS	+= -I../../include -g
+#CFLAGS	+= -I../../zte_sqlite
+#CFLAGS  += -I../../soft_timer
+CFLAGS	+= -I$(zte_lib_path)/libsqlite
+CFLAGS	+= -I$(zte_lib_path)/libsoft_timer
+CFLAGS  += -I../../at_server
+CFLAGS	+= -I$(zte_lib_path)/libnvram
+CFLAGS  += -I$(zte_lib_path)/libezxml
+CFLAGS  += -I$(zte_lib_path)/libmxml
+ifeq ($(CONFIG_USE_WEBUI_SSL),yes)
+OBJS += websSSL.o
+CFLAGS  += -I$(zte_lib_path)/libssl/install/include
+CFLAGS  += -I$(CPU_PUB_ROOT)/project/zx297520v3/include/nv
+CFLAGS	+= -DWEBS_SSL_SUPPORT -DOPENSSL
+LDLIBS += -L$(zte_lib_path)/libssl/install/lib -lssl -lcrypto
+LDLIBS += -ldl
+endif
+CFLAGS	+= -DWEBINSPECT_FIX
+LDLIBS += -lpthread
+LDLIBS += -lsoftap -L$(zte_lib_path)/libsoftap
+LDLIBS  += -lsoft_timer -L$(zte_lib_path)/libsoft_timer
+#LDLIBS  += -lkey -L$(zte_lib_path)/libkey
+LDLIBS  += -lamt -L$(zte_lib_path)/libamt
+LDLIBS  += -lcpnv -L$(zte_lib_path)/libcpnv
+
+ifeq ($(CONFIG_USE_WEBUI_SECURITY),yes)
+CFLAGS	+= -DWEBS_SECURITY
+endif
+#*******************************************************************************
+# macro definition
+#*******************************************************************************
+ifeq ($(CONFIG_USE_WEBUI_ZIP),yes)
+OBJS += ioapi.o unzip.o
+CFLAGS	+= -D_USE_WEBUI_ZIP
+CFLAGS  += -I$(zte_lib_path)/zlib/install/include
+LDFLAGS += -L$(zte_lib_path)/zlib/install/lib -lz
+endif
+
+ifeq ($(CUSTOM_MODEL), MF253S2)
+ifeq ($(CUSTOM_OPERATOR), CM_CN)
+CFLAGS	+= -DCUSTOM_VERSION_MF253S2_CM_CN
+endif
+endif
+
+##changed by huangmin10103007 for new partition, 20130116 begin
+ifeq ($(FEATURE_ZTE_CPE_CFG), YES)
+CFLAGS += -D_ZTE_CFG_
+endif
+##changed by huangmin10103007 for new partition, 20130116 end
+# Digest Access switch
+# DASW	= -DDIGEST_ACCESS_SUPPORT
+
+# SSL switches
+ifeq ("$(CONFIG_USER_GOAHEAD_SSL)", "y")
+SSLPATCHFILE = matrix_ssl.o sslSocket.o
+MATRIXDIR = $(ROOTDIR)/user/matrixssl-1.8.3
+SSLINC = $(MATRIXDIR)
+SSLLIB = $(MATRIXDIR)/src/libmatrixsslstatic.a
+SSLSW = -DWEBS_SSL_SUPPORT -DMATRIX_SSL -I$(SSLINC)
+endif
+
+#CONF_H	= $(ROOTDIR)/$(LINUXDIR)/include/linux/autoconf.h
+#CONF_H	= $(LINUX_DIR)/include/linux/autoconf.h
+#UCONF_H	= $(ROOTDIR)/config/autoconf.h
+
+#BUSYCONF_H = $(USR_DIR)/busybox-1.15.0/include/autoconf.h
+#UCONF_H	= $(CFG_DIR)/autoconf.h
+
+ifeq ($(FEATURE_DLNA), YES)
+# DLNA settings(libztedlna.so)
+LDLIBS += -L../../DMS -lztedlna -lpthread
+endif
+
+#*******************************************************************************
+# library
+#*******************************************************************************
+LDLIBS	+= -lnvram -lzte_pbm -lsqlite -lwlan_interface
+ifeq ($(LINUX_TYPE),uClinux)
+LDLIBS	+= -lpthread
+else
+LDLIBS	+= -lpthread
+endif
+
+
+ifeq ($(FEATURE_DLNA), YES)
+LDLIBS	+= -L../../DMS -lztedlna
+endif
+
+LDFLAGS	+= $(SSLLIB) $(IFMODLIB) $(INTERFACELIB) -lm -lgcc_s
+
+#LDFLAGS += -Wl,-elf2flt=-s131072
+
+CFLAGS += -I$(zte_lib_path)/libssl/install/include
+LDLIBS += -L$(zte_lib_path)/libssl/install/lib -lcrypto
+
+#*******************************************************************************
+# library path
+#*******************************************************************************
+LDLIBS  += -L$(zte_lib_path)/libnvram
+#LDLIBS  += -L$(zte_lib_path)/libsoft_timer
+LDLIBS  += -L$(zte_lib_path)/libsqlite
+LDLIBS  += -L$(zte_lib_path)/libzte_pbm
+LDLIBS  += -L$(zte_lib_path)/libmxml
+LDLIBS  += -L$(zte_lib_path)/libwlan_interface
+
+#*******************************************************************************
+# targets
+#*******************************************************************************
+all:$(EXEC)
+
+#
+#	Primary link
+#
+#$(CC) -o $@ $(OBJS) $(LDFLAGS) $(EXTRALIBS) $(LDLIBS)
+$(EXEC): $(OBJS) $(INTERFACELIB)
+	#$(LD)  -o $@ $(OBJS) $(LDFLAGS)  $(LDLIBS)
+	$(CC) -o $@ $(OBJS) $(LDFLAGS) $(EXTRALIBS) $(LDLIBS)
+
+root_fs:
+	cp $(EXEC) $(EXEC).elf
+	$(ROMFSINST) /bin/$(EXEC)
+
+romfs:
+	cp $(EXEC) $(EXEC).elf
+	$(ROMFSINST)  /bin/$(EXEC)
+
+clean:
+	-rm -f $(EXEC) *.o *.elf
+
+#
+#	Dependencies
+#
+asp.o:  webs.h wsIntrn.h ej.h ejIntrn.h uemf.h
+
+balloc.o: balloc.c uemf.h
+
+base64.o:  base64.c webs.h wsIntrn.h  ej.h ejIntrn.h uemf.h
+
+cgi.o:  webs.h wsIntrn.h uemf.h
+
+default.o:  default.c webs.h wsIntrn.h ej.h ejIntrn.h uemf.h $(CONF_H)
+
+ejlex.o:  ejlex.c ej.h ejIntrn.h uemf.h
+
+ejparse.o:  ejparse.c ej.h ejIntrn.h uemf.h
+
+emfdb.o:  emfdb.h wsIntrn.h uemf.h
+
+form.o:  form.c webs.h wsIntrn.h ej.h ejIntrn.h uemf.h
+
+h.o:  h.c uemf.h
+
+handler.o:  handler.c webs.h wsIntrn.h ej.h ejIntrn.h uemf.h
+
+md5c.o:  md5.h wsIntrn.h uemf.h
+
+mime.o:  mime.c webs.h wsIntrn.h ej.h ejIntrn.h uemf.h
+
+misc.o:  misc.c uemf.h
+
+page.o:  page.c webs.h wsIntrn.h ej.h ejIntrn.h uemf.h
+
+ringq.o:  ringq.c uemf.h
+
+rom.o:  rom.c webs.h wsIntrn.h ej.h ejIntrn.h uemf.h
+
+security.o:  security.c webs.h wsIntrn.h ej.h ejIntrn.h uemf.h
+
+sock.o:  sock.c uemf.h
+
+sockGen.o:  sockGen.c uemf.h $(CONF_H)
+
+sym.o:  sym.c uemf.h
+
+uemf.o:  uemf.c uemf.h
+
+um.o:  webs.h wsIntrn.h um.h uemf.h
+
+umui.o:  webs.h wsIntrn.h um.h uemf.h
+
+url.o:  url.c webs.h wsIntrn.h ej.h ejIntrn.h uemf.h
+
+value.o:  value.c uemf.h
+
+webrom.o:  webrom.c webs.h wsIntrn.h uemf.h
+
+webs.o:  webs.c webs.h wsIntrn.h ej.h ejIntrn.h uemf.h $(CONF_H)
+
+websda.o:  webs.h wsIntrn.h websda.h uemf.h
+
+websuemf.o:  websuemf.c webs.h wsIntrn.h ej.h ejIntrn.h uemf.h
+
+websSSL.o:  websSSL.c websSSL.h wsIntrn.h ej.h ejIntrn.h uemf.h
+
+#goahead.o:  goahead.c wsIntrn.h webs.h ej.h ejIntrn.h uemf.h $(CONF_H) $(UCONF_H) $(BUSYCONF_H)
+goahead.o:  goahead.c wsIntrn.h webs.h ej.h ejIntrn.h uemf.h $(CONF_H) $(BUSYCONF_H)
diff --git a/ap/app/goahead/server/balloc.c b/ap/app/goahead/server/balloc.c
new file mode 100755
index 0000000..da56e39
--- /dev/null
+++ b/ap/app/goahead/server/balloc.c
@@ -0,0 +1,206 @@
+#define IN_BALLOC
+
+#include	"uemf.h"
+#include	<stdarg.h>
+#include	<stdlib.h>
+
+static bType			*bQhead[B_MAX_CLASS];	
+static char				*bFreeBuf;				
+static char				*bFreeNext;				
+static int				bFreeSize;				
+static int				bFreeLeft;				
+static int				bFlags = B_USE_MALLOC;	
+static int				bopenCount = 0;			
+
+static int ballocGetSize(int size, int *q);
+
+int bopen(void *buf, int bufsize, int flags)
+{
+	bFlags = flags;
+
+	if (++bopenCount > 1) {
+		return 0;
+	}
+
+	if (buf == NULL) {
+		if (bufsize == 0) {
+			bufsize = B_DEFAULT_MEM;
+		}
+		if ((buf = malloc(bufsize)) == NULL) {
+         --bopenCount;
+			return -1;
+		}
+	} else {
+		bFlags |= B_USER_BUF;
+	}
+
+	bFreeSize = bFreeLeft = bufsize;
+	bFreeBuf = bFreeNext = buf;
+	memset(bQhead, 0, sizeof(bQhead));
+	return 0;
+}
+
+void bclose()
+{
+	if (--bopenCount <= 0 && !(bFlags & B_USER_BUF)) {
+		free(bFreeBuf);
+		bopenCount = 0;
+	}
+}
+
+bType	*balloc_tmp;
+void *balloc(B_ARGS_DEC, int size)
+{
+	bType	*bp;
+	int		q, memSize;
+
+	if (bFreeBuf == NULL) {
+		if (bopen(NULL, B_DEFAULT_MEM, 0) < 0) {
+			return NULL;
+		}
+	}
+	if (size < 0) {
+		return NULL;
+	}
+
+	memSize = ballocGetSize(size+1, &q);
+
+	if (q >= B_MAX_CLASS) {
+		if (bFlags & B_USE_MALLOC) {
+			bp = (bType*) malloc(memSize);
+			if (bp == NULL) {
+				traceRaw(T("B: malloc failed\n"));
+				return NULL;
+			}
+
+		} else {
+			traceRaw(T("B: malloc failed\n"));
+			return NULL;
+		}
+		bp->u.size = memSize - sizeof(bType);
+		bp->flags = B_MALLOCED;
+
+	} else if ((bp = bQhead[q]) != NULL) {
+#ifdef WEBS_SECURITY
+		bType	*tmp = bp->u.next;
+		if(tmp != NULL)
+ 			balloc_tmp = tmp->u.next;
+#endif		
+		bQhead[q] = bp->u.next;
+
+		bp->u.size = memSize - sizeof(bType);
+		bp->flags = 0;
+
+	} else {
+		if (bFreeLeft > memSize) {
+
+			bp = (bType*) bFreeNext;
+
+			bFreeNext += memSize;
+			bFreeLeft -= memSize;
+
+			bp->u.size = memSize - sizeof(bType);
+			bp->flags = 0;
+
+		} else if (bFlags & B_USE_MALLOC) {
+
+			if ((bp = (bType*) malloc(memSize)) == NULL) {
+				traceRaw(T("B: malloc failed\n"));
+				return NULL;
+			}
+			bp->u.size = memSize - sizeof(bType);
+			bp->flags = B_MALLOCED;
+
+		} else {
+			traceRaw(T("B: malloc failed\n"));
+			return NULL;
+		}
+	}
+
+	bp->flags |= B_INTEGRITY;
+
+	return (void*) ((char*) bp + sizeof(bType));
+}
+
+void bfree(B_ARGS_DEC, void *mp)
+{
+	bType	*bp;
+	int		q, memSize;
+
+	bp = (bType*) ((char*) mp - sizeof(bType));
+
+	a_assert((bp->flags & B_INTEGRITY_MASK) == B_INTEGRITY);
+
+	if ((bp->flags & B_INTEGRITY_MASK) != B_INTEGRITY) {
+		return;
+	}
+
+	memSize = ballocGetSize(bp->u.size, &q);
+
+	if (bp->flags & B_MALLOCED) {
+		free(bp);
+		return;
+	}
+
+	bp->u.next = bQhead[q];
+	bQhead[q] = bp;
+
+	bp->flags = B_FILL_WORD;
+}
+
+
+void bfreeSafe(B_ARGS_DEC, void *mp)
+{
+	if (mp) {
+		bfree(B_ARGS, mp);
+	}
+}
+
+char_t *bstrdup(B_ARGS_DEC, char_t *s)
+{
+	char_t	*cp;
+	int		len;
+
+	if (s == NULL) {
+		s = T("");
+	}
+	len = gstrlen(s) + 1;
+	if ((cp = balloc(B_ARGS, len * sizeof(char_t))) != NULL) {
+		gstrcpy(cp, s);
+	}
+	return cp;
+}
+
+void *brealloc(B_ARGS_DEC, void *mp, int newsize)
+{
+	bType	*bp;
+	void	*newbuf;
+
+	if (mp == NULL) {
+		return balloc(B_ARGS, newsize);
+	}
+	bp = (bType*) ((char*) mp - sizeof(bType));
+	a_assert((bp->flags & B_INTEGRITY_MASK) == B_INTEGRITY);
+
+	if (bp->u.size >= newsize) {
+		return mp;
+	}
+	if ((newbuf = balloc(B_ARGS, newsize)) != NULL) {
+		memcpy(newbuf, mp, bp->u.size);
+		bfree(B_ARGS, mp);
+	}
+	return newbuf;
+}
+
+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));
+}
+
+
diff --git a/ap/app/goahead/server/base64.c b/ap/app/goahead/server/base64.c
new file mode 100755
index 0000000..b05e21b
--- /dev/null
+++ b/ap/app/goahead/server/base64.c
@@ -0,0 +1,95 @@
+
+static char	map64[] = {
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
+	-1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
+    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, 
+	-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+};
+
+static char	alphabet64[] = {
+	'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
+	'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+	'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
+	'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
+	'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+	'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+	'w', 'x', 'y', 'z', '0', '1', '2', '3',
+	'4', '5', '6', '7', '8', '9', '+', '/',
+};
+
+int websDecode64(char *outbuf, char *string, int outlen)
+{
+	unsigned long	shiftbuf;
+	char			*cp, *op;
+	int				c, i, j, shift;
+
+	op = outbuf;
+	*op = '\0';
+	cp = string;
+	while (*cp && *cp != '=') {
+		shiftbuf = 0;
+		shift = 18;
+		for (i = 0; i < 4 && *cp && *cp != '='; i++, cp++) {
+			c = map64[*cp & 0xff];
+			if (c == -1) {
+				return -1;
+			} 
+			shiftbuf = shiftbuf | (c << shift);
+			shift -= 6;
+		}
+		--i;
+		if ((op + i) >= &outbuf[outlen]) {
+			strcpy(outbuf, "String too big");
+			return -1;
+		}
+		for (j = 0; j < i; j++) {
+			*op++ = (char) ((shiftbuf >> (8 * (2 - j))) & 0xff);
+		}
+		*op = '\0';
+	}
+	return 0;
+}
+
+void websEncode64(char *outbuf, char *string, int outlen)
+{
+	unsigned long	shiftbuf;
+	char			*cp, *op;
+	int				x, i, j, shift;
+
+	op = outbuf;
+	*op = '\0';
+	cp = string;
+	while (*cp) {
+		shiftbuf = 0;
+		for (j = 2; j >= 0 && *cp; j--, cp++) {
+			shiftbuf |= ((*cp & 0xff) << (j * 8));
+		}
+		shift = 18;
+		for (i = ++j; i < 4 && op < &outbuf[outlen] ; i++) {
+			x = (shiftbuf >> shift) & 0x3f;
+			*op++ = alphabet64[(shiftbuf >> shift) & 0x3f];
+			shift -= 6;
+		}
+		while (j-- > 0) {
+			*op++ = '=';
+		}
+		*op = '\0';
+	}
+}
+
diff --git a/ap/app/goahead/server/cgi.c b/ap/app/goahead/server/cgi.c
new file mode 100755
index 0000000..c9286c6
--- /dev/null
+++ b/ap/app/goahead/server/cgi.c
@@ -0,0 +1,311 @@
+#include	"wsIntrn.h"
+#include	<sys/types.h>
+#include	<sys/wait.h>
+#include	"uemf.h"
+
+static int		cgiMax;			
+typedef struct {				
+	webs_t	wp;					
+	long	fplacemark;			
+	int		handle;				
+	char_t	**envp;				
+	char_t	**argp;				
+	char_t	*cgiPath;			
+	char_t	*stdOut;			
+	char_t	*stdIn;				
+} cgiRec;
+static cgiRec	**cgiList;		
+
+int websCgiProcess(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg, 
+		char_t *url, char_t *path, char_t* query)
+{
+	
+		int 		n, envpsize, argpsize, pHandle, cid;
+		char_t		*cp, *cgiName, *cgiPath, **argp, **envp, **ep;
+		char_t		cgiBuf[FNAMESIZE], *stdIn, *stdOut, cwd[FNAMESIZE];
+		sym_t		*s;
+		cgiRec		*cgip;
+		a_assert(path && *path == '/');
+		a_assert(url && *url);
+		a_assert(websValid(wp));
+		websStats.cgiHits++;
+		char *cgipath_temp = NULL;
+		gstrncpy(cgiBuf, path, TSZ(cgiBuf)-1);
+		cgipath_temp = gstrchr(&cgiBuf[1], '/');
+		if(cgipath_temp!=NULL)
+		{
+			cgipath_temp++;
+		}else
+		{
+			websError(wp, 200, T("cgiBuf error,check path"));
+						
+			return 1;
+		}
+		printf("[goahead]cgipath_temp->%s.\n",cgipath_temp);
+		//if ((cgiName = gstrchr(&cgiBuf[1], '/')) == NULL) {
+		if ((cgiName = gstrchr(cgipath_temp, '/')) == NULL) {
+	
+			if((cgiName = gstrchr(&cgiBuf[1], '/')) == NULL)
+			{
+				websError(wp, 200, T("Missing CGI name"));
+				
+				return 1;
+			}
+		}
+		cgiName++;
+		printf("[goahead]cgiName->%s.\n",cgiName);
+		if ((cp = gstrchr(cgiName, '/')) != NULL) {
+			*cp = '\0';
+		}
+	//	fmtAlloc(&cgiPath, FNAMESIZE, T("%s/%s/%s"), websGetDefaultDir(),
+	//		CGI_BIN, cgiName);
+		fmtAlloc(&cgiPath, FNAMESIZE, T("%s/%s"),"/etc_ro/cgi-bin", cgiName);
+		{
+			gstat_t 	sbuf;
+			if (gstat(cgiPath, &sbuf) != 0 || (sbuf.st_mode & S_IFREG) == 0) {
+				websError(wp, 200, T("CGI process file does not exist"));
+				bfree(B_L, cgiPath);
+				return 1;
+			}
+			if (gaccess(cgiPath, X_OK) != 0) {
+				websError(wp, 200, T("CGI process file is not executable"));
+				bfree(B_L, cgiPath);
+				return 1;
+			}
+		}
+		ggetcwd(cwd, FNAMESIZE);
+		if ((cp = gstrrchr(cgiPath, '/')) != NULL) {
+			*cp = '\0';
+			gchdir(cgiPath);
+			*cp = '/';
+		}
+		argpsize = 10;
+		argp = balloc(B_L, argpsize * sizeof(char_t *));
+		if(argp == NULL){
+			bfreeSafe(B_L, cgiPath);
+			return 1;
+		}
+		*argp = cgiPath;
+		n = 1;
+		if (gstrchr(query, '=') == NULL) {
+			websDecodeUrl(query, query, gstrlen(query));
+			for (cp = gstrtok(query, T(" ")); cp != NULL; ) {
+				*(argp+n) = cp;
+				n++;
+				if (n >= argpsize) {
+					argpsize *= 2;
+					argp = brealloc(B_L, argp, argpsize * sizeof(char_t *));
+					if(argp == NULL){
+						bfreeSafe(B_L, cgiPath);
+						return 1;
+					}
+				}
+				cp = gstrtok(NULL, T(" "));
+			}
+		}
+		*(argp+n) = NULL;
+		envpsize = WEBS_SYM_INIT;
+		envp = balloc(B_L, envpsize * sizeof(char_t *));
+		if(envp == NULL){
+			bfreeSafe(B_L, cgiPath);
+			bfreeSafe(B_L, argp);
+			return 1;
+		}
+		n = 0;
+		fmtAlloc(envp+n, FNAMESIZE, T("%s=%s"),T("PATH_TRANSLATED"), cgiPath);
+		n++;
+		fmtAlloc(envp+n, FNAMESIZE, T("%s=%s/%s"),T("SCRIPT_NAME"),
+			CGI_BIN, cgiName);
+		n++;
+		fmtAlloc(envp+n, FNAMESIZE, T("%s=%s"),T("REMOTE_USER"), wp->userName);
+		n++;
+		fmtAlloc(envp+n, FNAMESIZE, T("%s=%s"),T("AUTH_TYPE"), wp->authType);
+		n++;
+		for (s = symFirst(wp->cgiVars); s != NULL; s = symNext(wp->cgiVars)) {
+			if (s->content.valid && s->content.type == string &&
+				gstrcmp(s->name.value.string, T("REMOTE_HOST")) != 0 &&
+				gstrcmp(s->name.value.string, T("HTTP_AUTHORIZATION")) != 0) {
+				fmtAlloc(envp+n, FNAMESIZE, T("%s=%s"), s->name.value.string,
+					s->content.value.string);
+				n++;
+				if (n >= envpsize) {
+					envpsize *= 2;
+					envp = brealloc(B_L, envp, envpsize * sizeof(char_t *));
+					if(envp == NULL){
+						bfreeSafe(B_L, cgiPath);
+						bfreeSafe(B_L, argp);
+						return 1;
+					}
+				}
+			}
+		}
+		if (wp->flags & WEBS_CGI_UPLOAD)
+		{
+	
+			if((wp->has_firmware_upload_clean)||(wp->flags & WEBS_CGI_FIRMWARE_UPLOAD))
+			{
+				fmtAlloc(envp+n, FNAMESIZE, T("%s=%s"), T("UPLOAD_FILENAME"), FIRMWARE_TMP_FILE); 
+			}
+			else
+			{					
+				fmtAlloc(envp+n, FNAMESIZE, T("%s=%s"), T("UPLOAD_FILENAME"), wp->cgiStdin);		
+			}
+			n++;
+		}
+		*(envp+n) = NULL;
+		if (wp->cgiStdin == NULL) {
+			wp->cgiStdin = websGetCgiCommName(wp);
+		} 
+		stdIn = wp->cgiStdin;
+		stdOut = websGetCgiCommName(wp);
+		printf("[goahead]cgiPath->%s.\n",cgiPath);
+	
+		if ((pHandle = websLaunchCgiProc(cgiPath, argp, envp, stdIn, stdOut)) 
+			== -1) {
+			websError(wp, 200, T("failed to spawn CGI task"));
+			for (ep = envp; *ep != NULL; ep++) {
+				bfreeSafe(B_L, *ep);
+			}
+			bfreeSafe(B_L, cgiPath);
+			bfreeSafe(B_L, argp);
+			bfreeSafe(B_L, envp);
+			bfreeSafe(B_L, stdOut);
+		} else {
+			cid = hAllocEntry((void***) &cgiList, &cgiMax, sizeof(cgiRec));
+			if(cgiList){
+			cgip = cgiList[cid];
+			cgip->handle = pHandle;
+			cgip->stdIn = stdIn;
+			cgip->stdOut = stdOut;
+			cgip->cgiPath = cgiPath;
+			cgip->argp = argp;
+			cgip->envp = envp;
+			cgip->wp = wp;
+			cgip->fplacemark = 0;
+			websTimeoutCancel(wp);
+			}
+			else
+			{
+				bfreeSafe(B_L, cgiPath);
+				bfreeSafe(B_L, argp);
+				bfreeSafe(B_L, envp);
+				bfreeSafe(B_L, stdOut);
+			}
+		}
+		gchdir(cwd);
+		return 1;
+
+}
+
+int websCgiHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg, 
+		char_t *url, char_t *path, char_t* query)
+{
+	if(!(wp->flags & WEBS_POST_REQUEST))
+	{
+		//websError(wp, 200, T("NOT POST REQUEST"));
+		printf("[goahead]NOT POST REQUEST.\n");
+		websDone(wp, 0);
+		return 1;
+	}
+
+	if (wp->flags & WEBS_CGI_HTTPSHARE_UPLOAD)
+	{
+		printf("[httpshare]call zte_process_cgi_end.\n");
+		return zte_process_cgi_end(wp);
+	}else if(wp->flags & WEBS_CGI_UPLOAD)
+	{
+		printf("[goahead]call upload cgi.\n");
+		return websCgiProcess(wp, urlPrefix, webDir, arg,url, path, query);
+	}else
+	{
+		//websError(wp, 200, T("NOT CGI OR HTTPSHARE,RETURN ERROR"));
+		printf("[goahead]wrong cgi request.\n");
+		websDone(wp, 0);
+		return 1;
+	}
+
+}
+
+void websCgiGatherOutput (cgiRec *cgip)
+{
+	gstat_t	sbuf;
+	char_t	cgiBuf[FNAMESIZE];
+	if ((gstat(cgip->stdOut, &sbuf) == 0) && 
+		(sbuf.st_size > cgip->fplacemark)) {
+		int fdout;
+		fdout = gopen(cgip->stdOut, O_RDONLY | O_BINARY, 0444 );
+		if (fdout >= 0) {
+			webs_t	wp = cgip->wp;
+			int		nRead;
+			int		rc;
+			if (cgip->fplacemark == 0) {
+				websWrite(wp, T("HTTP/1.0 200 OK\n"));
+			}	
+			if(glseek(fdout, cgip->fplacemark, SEEK_SET) < 0)
+			{
+			    printf("[goahead]glseek fail.\n");
+			}
+			while ((nRead = gread(fdout, cgiBuf, FNAMESIZE)) > 0) {
+				rc = websWriteBlock(wp, cgiBuf, nRead);
+				if (rc < 0) {
+					//todo: cov m
+				}
+				cgip->fplacemark += nRead;
+			}
+			gclose(fdout);
+		}
+	}
+}
+
+void websCgiCleanup()
+{
+	cgiRec	*cgip;
+	webs_t	wp;
+	char_t	**ep;
+	int		cid, nTries;
+	for (cid = 0; cid < cgiMax; cid++) {
+		if ((cgip = cgiList[cid]) != NULL) {
+			int exit_status;
+			wp = cgip->wp;
+			websCgiGatherOutput (cgip);
+			if ( websCheckCgiProc(cgip->handle, &exit_status) == 0) {
+				nTries = 0;
+				while ((cgip->fplacemark == 0) && (nTries < 100)) {
+					websCgiGatherOutput(cgip);
+					if (cgip->fplacemark == 0) {
+					}
+					nTries++;
+				}
+				gunlink(cgip->stdIn);
+				gunlink(cgip->stdOut);
+				cgiMax = hFree((void***) &cgiList, cid);
+				for (ep = cgip->envp; ep != NULL && *ep != NULL; ep++) {
+					bfreeSafe(B_L, *ep);
+				}
+				bfreeSafe(B_L, cgip->cgiPath);
+				bfreeSafe(B_L, cgip->argp);
+				bfreeSafe(B_L, cgip->envp);
+				bfreeSafe(B_L, cgip->stdOut);
+				bfreeSafe(B_L, cgip);
+				if(wp->has_firmware_upload_clean){
+					if (WIFEXITED(exit_status) && WEXITSTATUS(exit_status) != 0) {
+						if (cgip->fplacemark == 0) { //cov h
+							websError(wp, 200, T("CGI generated no output"));
+						} else {
+							websDone(wp, 200);
+						}
+						return;
+					}
+					sync();
+					//doSystem("sleep 3 && reboot &");
+				}
+				if (cgip->fplacemark == 0) { //cov h
+					websError(wp, 200, T("CGI generated no output"));
+				} else {
+					websDone(wp, 200);
+				}
+			}
+		}
+	}
+}
+
diff --git a/ap/app/goahead/server/default.c b/ap/app/goahead/server/default.c
new file mode 100755
index 0000000..cd8aec1
--- /dev/null
+++ b/ap/app/goahead/server/default.c
@@ -0,0 +1,826 @@
+#include	"wsIntrn.h"
+
+static char_t	*websDefaultPage;			/* Default page name */
+static char_t	*websDefaultDir;			/* Default Web page directory */
+
+static void websCgiDownLoadWriteEvent(webs_t wp);
+static void websDefaultWriteEvent(webs_t wp);
+
+static int web_check_url(char *buf, char *nv_name, int is_ipv6)
+{
+	if(buf && nv_name) {
+		char url[40] = {0};
+		char full_url[50] = {0};
+		cfg_get_item(nv_name, url, sizeof(url));
+		if (websSSLIsOpen()){
+			if(is_ipv6)
+				snprintf(full_url, sizeof(full_url),"https://[%s]",url);
+			else
+				snprintf(full_url, sizeof(full_url),"https://%s",url);
+		} else {
+			if(is_ipv6)
+				snprintf(full_url, sizeof(full_url),"http://[%s]",url);
+			else
+				snprintf(full_url, sizeof(full_url),"http://%s",url);
+		}
+		if(strlen(buf) > strlen(full_url) && strstr(buf,full_url)) {
+			return 1;
+		}
+	}
+	return 0;
+}
+
+int websDefaultHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg,
+						char_t *url, char_t *path, char_t *query)
+{
+	websStatType	sbuf;
+	char_t			*lpath, *tmp, *date;
+	int				bytes, flags, nchars;
+	char 			wifi_png__path[256] = {0};
+	char 			*wifi_ptr = NULL;
+	char 			wifi_root_dir[20] = {0};
+	a_assert(websValid(wp));
+	a_assert(url && *url);
+	a_assert(path);
+	a_assert(query);
+#ifdef WEBINSPECT_FIX	
+	if (strstr(query,"txtPwd")) {
+		websDone(wp, 0);
+		return 1;
+	}
+#ifdef WEBS_SECURITY
+	if (strstr(query,"_method")) {
+		printf("websDH: qry=%s\n",query);
+		websError(wp, 405, T(""));
+		return 1;
+	}
+#endif
+#endif	
+
+	flags = websGetRequestFlags(wp);
+
+	if (websValidateUrl(wp, path) < 0) 
+   {
+      websError(wp, 500, T("Invalid URL"));
+		return 1;
+	}
+	lpath = websGetRequestLpath(wp);
+		
+//qrcode_ssid_wifikey.png   qrcode_multi_ssid_wifikey.png
+	if((strstr(lpath,"pic/qrcode_ssid_wifikey.png")!=NULL)||(strstr(lpath,"pic/qrcode_multi_ssid_wifikey.png")!=NULL))
+	{
+		cfg_get_item("wifi_root_dir",wifi_root_dir,sizeof(wifi_root_dir));
+		wifi_ptr=strstr(lpath,"pic/qrcode_");
+		wifi_ptr+=4;
+		//printf("[wifi_png]wifi_ptr:%s\n",wifi_ptr);
+		snprintf(wifi_png__path,sizeof(wifi_png__path),"%s/wifi/%s",wifi_root_dir,wifi_ptr);
+		//printf("[wifi_png]wifi_png_path:%s\n",wifi_png__path);
+		lpath=wifi_png__path;
+	}
+	
+    if(strstr(lpath,"web/messages"))
+	{
+		//lpath="/var/log/webshow_messages";
+		snprintf(wifi_png__path,sizeof(wifi_png__path),"%s","/var/log/webshow_messages");
+		lpath=wifi_png__path;// kw OVERWRITE_CONST_CHAR
+    }
+	if(strstr(lpath,"/webshow_messages"))
+	{
+		//lpath="/etc_ro/web/webshow_messages";
+		snprintf(wifi_png__path,sizeof(wifi_png__path),"%s","/etc_ro/web/webshow_messages");
+		lpath=wifi_png__path;// kw OVERWRITE_CONST_CHAR
+    }
+	nchars = gstrlen(lpath) - 1;
+	if (lpath[nchars] == '/' || lpath[nchars] == '\\') {
+		lpath[nchars] = '\0';
+	}
+	if(lpath != websGetRequestLpath(wp))
+	{
+		websSetRequestLpath(wp,lpath);
+		lpath = websGetRequestLpath(wp);
+	}
+
+	if (websPageIsDirectory(lpath)) {
+		nchars = gstrlen(path);
+		if (path[nchars-1] == '/' || path[nchars-1] == '\\') {
+			path[--nchars] = '\0';
+		}
+		nchars += gstrlen(websDefaultPage) + 2;
+		fmtAlloc(&tmp, nchars, T("%s/%s"), path, websDefaultPage);
+		websRedirect(wp, tmp);
+		bfreeSafe(B_L, tmp);
+		return 1;
+	}
+#ifdef WEBS_SECURITY	
+	if (strstr(path,websDefaultPage)){
+		if (!(wp->flags & WEBS_SECURE) && websSSLIsOpen()){
+			printf("[goahead]no https Redirect\n");
+			websRedirect(wp, zte_web_get_login_page(wp));
+			return 1;
+		}
+	} else {
+#if 0
+		if(wp->cookie == NULL) {
+			printf("[goahead]no cookie Redirect\n");
+			websRedirect(wp, zte_web_get_login_page(wp));
+			return 1;
+		}
+#endif		
+		if(wp->referer)
+		{
+			if(web_check_url(wp->referer, "LocalDomain", 0) == 0
+				&& web_check_url(wp->referer, "lan_ipaddr", 0) == 0
+				&& web_check_url(wp->referer, "lan_ipv6addr", 1) == 0) {
+				printf("[goahead]referer=%s Redirect\n",wp->referer);
+				websRedirect(wp, zte_web_get_login_page(wp));
+				return 1;
+			}
+		}
+	}
+#endif
+/*
+ *	Open the document. Stat for later use.
+ */
+
+	if (websPageOpen(wp, lpath, path, SOCKET_RDONLY | SOCKET_BINARY, 
+		0666) < 0) 
+   {
+      /* 
+       * <http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html>
+       */
+      
+		websError(wp, 404, T("Cannot open URL"));
+		return 1;
+	} 
+
+	if (websPageStat(wp, lpath, path, &sbuf) < 0) {
+		websError(wp, 400, T("Cannot stat page for URL"));
+		return 1;
+	}
+
+	websStats.localHits++;
+#ifdef WEBS_IF_MODIFIED_SUPPORT
+	if (flags & WEBS_IF_MODIFIED && !(flags & WEBS_ASP)) {
+		if (sbuf.mtime <= wp->since) {
+			websWrite(wp, T("HTTP/1.0 304 Use local copy\r\n"));
+
+			websWrite(wp, T("Server: %s\r\n"), WEBS_NAME);
+
+			if (flags & WEBS_KEEP_ALIVE) {
+				websWrite(wp, T("Connection: keep-alive\r\n"));
+			}
+			websWrite(wp, T("\r\n"));
+			websSetRequestFlags(wp, flags |= WEBS_HEADER_DONE);
+			websDone(wp, 304);
+			return 1;
+		}
+	}
+#endif
+
+	if ((date = websGetDateString(NULL)) != NULL) {
+		websWrite(wp, T("HTTP/1.0 200 OK\r\nDate: %s\r\n"), date);
+
+		websWrite(wp, T("Server: %s\r\n"), WEBS_NAME);
+		bfree(B_L, date);
+	}
+	flags |= WEBS_HEADER_DONE;
+
+	if (flags & WEBS_ASP) {
+		bytes = 0;
+#ifndef WEBINSPECT_FIX	
+		websWrite(wp, T("Pragma: no-cache\r\nCache-Control: no-cache\r\n"));
+#endif
+	} else {
+		if ((date = websGetDateString(&sbuf)) != NULL) {
+			websWrite(wp, T("Last-modified: %s\r\n"), date);
+			bfree(B_L, date);
+		}
+		bytes = sbuf.size;
+	}
+#ifdef WEBINSPECT_FIX		
+	websWrite(wp, T("X-Frame-Options: SAMEORIGIN\r\nPragma: no-cache\r\nCache-Control: no-cache\r\n"));
+#endif
+#ifdef WEBS_SECURITY
+	websWrite(wp, T("Expires: 0\n"));
+	if (strstr(path,websDefaultPage)){
+		char id[33] = {0};
+		int ret = web_make_salt_base64(id, sizeof(id));
+		if(ret > 0)
+		{
+			if (websSSLIsOpen())
+				websWrite(wp, T("Set-Cookie: id=%s; secure; HttpOnly; SameSite=Lax;\r\n"),id);
+			else
+				websWrite(wp, T("Set-Cookie: id=%s; HttpOnly; SameSite=Lax;\r\n"),id);
+		}
+	}
+#endif	
+
+	if (bytes) {
+#ifdef WEBINSPECT_FIX	
+		if (strstr(path,"/tmpl/"))
+			websWrite(wp, T("Content-length: %d\r\n"), bytes+86);
+		else
+#endif		
+			websWrite(wp, T("Content-length: %d\r\n"), bytes);
+		websSetRequestBytes(wp, bytes);
+	}
+	websWrite(wp, T("Content-type: %s\r\n"), websGetRequestType(wp));
+
+	if ((flags & WEBS_KEEP_ALIVE) && !(flags & WEBS_ASP)) {
+		websWrite(wp, T("Connection: keep-alive\r\n"));
+	}
+	websWrite(wp, T("\r\n"));
+
+	if (flags & WEBS_HEAD_REQUEST) {
+		websDone(wp, 200);
+		return 1;
+	}
+
+#ifdef WEB_ASP		
+	if (flags & WEBS_ASP) {
+		if (websAspRequest(wp, lpath) < 0) {
+			return 1;
+		}
+		websDone(wp, 200);
+		return 1;
+	}
+#endif		
+#ifdef WEBINSPECT_FIX
+	if (strstr(path,"/tmpl/") && bytes) {
+		websWrite(wp, T("<script type=\"text/javascript\">if(self!=top){top.location = self.location;}</script>\r\n"));
+	}
+#endif	
+#ifdef WEBS_SSL_SUPPORT
+	if (wp->flags & WEBS_SECURE) {
+		websDefaultWriteEvent(wp);
+	} else {
+		websSetRequestSocketHandler(wp, SOCKET_WRITABLE, websDefaultWriteEvent);
+	}
+#else
+
+	websSetRequestSocketHandler(wp, SOCKET_WRITABLE, websDefaultWriteEvent);
+#endif
+	return 1;
+}
+
+//#ifdef FEATURE_ZTE_WEB_TCARD
+//added by guo shoupeng 10124224 for http share 20120110 start
+int websCgiDownLoadHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg,
+						char_t *url, char_t *path, char_t *query)
+{
+	//urlPrefix /mmc2
+	//url /mmc2/test.file?.........    url = ALL
+	//path /mmc2/test.file
+	//query ......
+	if (zte_check_downloading_file())
+	{
+		printf("[httpshare]call websCgiDownLoadHandler:system is downloading!.\n");
+		websError(wp, 404, T("System is downloading file,please try later!"));
+		return 1;
+	}
+	websStatType	sbuf;
+	char_t			*lpath, *tmp, *date;
+	int				bytes, flags, nchars;
+
+	a_assert(websValid(wp));
+	a_assert(url && *url);
+	a_assert(path);
+	a_assert(query);
+	char_t mmc2_path[4096+1] = {0};
+
+	flags = websGetRequestFlags(wp);
+
+	if (websValidateUrl(wp, path) < 0) 
+   {
+      websError(wp, 500, T("Invalid URL"));
+		return 1;
+	}
+
+	lpath = websGetRequestLpath(wp);
+
+	nchars = gstrlen(lpath) - 1;
+	if (lpath[nchars] == '/' || lpath[nchars] == '\\') {
+		lpath[nchars] = '\0';
+	}
+
+	if (websPageIsDirectory(lpath)) {
+		nchars = gstrlen(path);
+		if (path[nchars-1] == '/' || path[nchars-1] == '\\') {
+			path[--nchars] = '\0';
+		}
+		nchars += gstrlen(websDefaultPage) + 2;
+		fmtAlloc(&tmp, nchars, T("%s/%s"), path, websDefaultPage);
+		websRedirect(wp, tmp);
+		bfreeSafe(B_L, tmp);
+		return 1;
+	}
+//added for download file  start
+	
+	if(strstr(lpath,"/mmc2"))
+	{		
+		snprintf(mmc2_path,4096+1,"/etc_rw/config%s",path);
+		lpath = mmc2_path;
+		path = mmc2_path;
+		
+		printf("[httpshare]insert download file->%s\n",mmc2_path);
+		zte_insert_download_file(mmc2_path);
+		websSetRequestLpath(wp,lpath);
+	}
+
+//added for download file end
+
+	if (websPageOpen(wp, lpath, path, SOCKET_RDONLY | SOCKET_BINARY, 
+		0666) < 0) 
+   {
+      	printf("[httpshare]file is too big , can't open!\n");
+	  	if(strstr(mmc2_path,"/mmc2") != NULL)
+		{
+			zte_del_download_file();
+			printf("[httpshare]websPageClose:del file->%s form sql download.\n",mmc2_path);			
+		}
+		websError(wp, 404, T("Cannot open URL,File Error!"));
+		return 1;
+	} 
+
+	if (websPageStat(wp, lpath, path, &sbuf) < 0) {
+
+		if(strstr(mmc2_path,"/mmc2") != NULL)
+		{
+			zte_del_download_file();
+			printf("[httpshare]websPageClose:del file->%s form sql download.\n",mmc2_path);			
+		}
+	  	websError(wp, 400, T("Cannot stat page for URL"));
+		return 1;
+	}
+
+	websStats.localHits++;
+#ifdef WEBS_IF_MODIFIED_SUPPORT
+	if (flags & WEBS_IF_MODIFIED && !(flags & WEBS_ASP)) {
+		if (sbuf.mtime <= wp->since) {
+			websWrite(wp, T("HTTP/1.0 304 Use local copy\r\n"));
+
+			websWrite(wp, T("Server: %s\r\n"), WEBS_NAME);
+
+			if (flags & WEBS_KEEP_ALIVE) {
+				websWrite(wp, T("Connection: keep-alive\r\n"));
+			}
+			websWrite(wp, T("\r\n"));
+			websSetRequestFlags(wp, flags |= WEBS_HEADER_DONE);
+			websDone(wp, 304);
+			return 1;
+		}
+	}
+#endif
+
+	if ((date = websGetDateString(NULL)) != NULL) {
+		websWrite(wp, T("HTTP/1.0 200 OK\r\nDate: %s\r\n"), date);
+
+		websWrite(wp, T("Server: %s\r\n"), WEBS_NAME);
+		bfree(B_L, date);
+	}
+	flags |= WEBS_HEADER_DONE;
+
+ #if 0
+	if (flags & WEBS_ASP) {
+		bytes = 0;
+		websWrite(wp, T("Pragma: no-cache\r\nCache-Control: no-cache\r\n"));
+
+	} else {
+#endif	
+		if ((date = websGetDateString(&sbuf)) != NULL) {
+			websWrite(wp, T("Last-modified: %s\r\n"), date);
+			bfree(B_L, date);
+		}
+		bytes = sbuf.size;
+#if 0		
+	}
+#endif	
+#if 0
+	if (bytes) {
+#endif	
+		websWrite(wp, T("Content-length: %d\r\n"), bytes);	       
+		websSetRequestBytes(wp, bytes);		
+#if 0		
+	}	
+#endif	
+#if 0
+	websWrite(wp, T("Content-type: %s\r\n"), websGetRequestType(wp));
+#else
+	char name[256] = {0};
+	int k = 0;
+	int i = 0;
+	for(i = 0; i < gstrlen(lpath); i++){
+		if((lpath[i] == '/') ||  (lpath[i] == '\\')){
+			memset(name, 0, sizeof(name));
+			k = 0;
+			continue;
+		}else{
+			name[k] = lpath[i];
+			k++;
+		}		
+	}
+	name[k] = '\0';
+
+	
+	websWrite(wp, T("Content-type: application/octet-stream\r\n"));
+	websWrite(wp, T("Content-Disposition: attachment; filename\r\n"));		
+#endif
+
+#if 0
+	if ((flags & WEBS_KEEP_ALIVE) 
+#if 0		
+		&& !(flags & WEBS_ASP)
+#endif		
+		) {
+		websWrite(wp, T("Connection: keep-alive\r\n"));
+	}
+#endif
+	websWrite(wp, T("\r\n"));
+
+/*
+ *	All done if the browser did a HEAD request
+ */
+	/*if (flags & WEBS_HEAD_REQUEST) {
+
+		printf("Head request:websDone\n");
+		websDone(wp, 200);
+		return 1;
+	}*/
+
+/*
+ *	Evaluate ASP requests
+ */
+ #if 0
+	if (flags & WEBS_ASP) {
+		if (websAspRequest(wp, lpath) < 0) {
+			return 1;
+		}
+		websDone(wp, 200);
+		return 1;
+	}
+#endif	
+
+#ifdef WEBS_SSL_SUPPORT
+	if (wp->flags & WEBS_SECURE) {
+		websDefaultWriteEvent(wp);
+	} else {
+		websSetRequestSocketHandler(wp, SOCKET_WRITABLE, websCgiDownLoadWriteEvent);
+	}
+#else
+/*
+ *	For normal web documents, return the data via background write
+ */
+	websSetRequestSocketHandler(wp, SOCKET_WRITABLE, websCgiDownLoadWriteEvent);
+#endif
+	return 1;
+}
+//added by guo shoupeng 10124224 for http share 20120110 end
+//#endif
+
+#ifdef WIN32
+
+static int badPath(char_t* path, char_t* badPath, int badLen)
+{
+   int retval = 0;
+   int len = gstrlen(path);
+   int i = 0;
+
+   if (len <= badLen +1)
+   {
+      for (i = 0; i < badLen; ++i)
+      {
+         if (badPath[i] != gtolower(path[i]))
+         {
+            return 0;
+         }
+      }
+
+      retval = 1;
+      if (badLen + 1 == len)
+      {
+         if (gisalnum(path[len-1]))
+         {
+            retval = 0;
+         }
+      }
+   }
+
+   return retval;
+}
+
+
+static int isBadWindowsPath(char_t** parts, int partCount)
+{
+   OSVERSIONINFO version;
+   int i;
+   version.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+   if (GetVersionEx(&version))
+   {
+      if (VER_PLATFORM_WIN32_NT != version.dwPlatformId)
+      {
+         for (i = 0; i < partCount; ++i)
+         {
+            if ( 
+             (badPath(parts[i], T("con"), 3)) ||
+             (badPath(parts[i], T("nul"), 3)) ||
+             (badPath(parts[i], T("aux"), 3)) ||
+             (badPath(parts[i], T("clock$"), 6)) ||
+             (badPath(parts[i], T("config$"), 7)) )
+            {
+               return 1;
+            }
+         }
+      }
+   }
+
+   return 0;
+}
+#endif
+
+int websValidateUrl(webs_t wp, char_t *path)
+{
+#define kMaxUrlParts 64
+	char_t	*parts[kMaxUrlParts];	/* Array of ptr's to URL parts */
+	char_t	*token, *dir, *lpath; 
+   int	      i, len, npart;
+
+	a_assert(websValid(wp));
+	a_assert(path);
+
+	dir = websGetRequestDir(wp);
+	if (/*dir == NULL ||*/ *dir == '\0') {  // kw 3
+		return -1;
+	}
+
+	path = bstrdup(B_L, path);
+	websDecodeUrl(path, path, gstrlen(path));
+
+	len = npart = 0;
+	parts[0] = NULL;
+
+   token = gstrchr(path, '\\');
+   while (token != NULL)
+   {
+      *token = '/';
+      token = gstrchr(token, '\\');
+   }
+   
+	token = gstrtok(path, T("/"));
+
+	while (token != NULL) 
+   {
+      if (npart >= kMaxUrlParts)
+      {
+         bfree(B_L, path);
+         return -1;
+      }
+		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("/"));
+	}
+
+#ifdef WIN32
+   if (isBadWindowsPath(parts, npart))
+   {
+      bfree(B_L, path);
+      return -1;
+   }
+
+#endif
+
+
+	if (npart || (gstrcmp(path, T("/")) == 0) || (path[0] == '\0')) 
+   {
+		lpath = balloc(B_L, (gstrlen(dir) + 1 + len + 1) * sizeof(char_t));
+		if(lpath == NULL){
+			bfree(B_L, path);
+			return -1;
+		}
+		gstrcpy(lpath, dir);
+
+		for (i = 0; i < npart; i++) 
+      {
+			gstrcat(lpath, T("/"));
+			gstrcat(lpath, parts[i]);
+		}
+		websSetRequestLpath(wp, lpath);
+		bfree(B_L, path);
+		bfree(B_L, lpath);
+	} 
+   else 
+   {
+		bfree(B_L, path);
+		return -1;
+	}
+	return 0;
+}
+
+//#ifdef FEATURE_ZTE_WEB_TCARD
+//added by guo shoupeng 10124224 for http share 20120110 start
+int write_bytes = 0;
+static void websCgiDownLoadWriteEvent(webs_t wp)
+{
+ //printf("websCgiDownLoadWriteEvent start\n");
+	int		len = -1;
+	int wrote, flags, bytes, written;
+	char	*buf;
+	
+	extern int errno;
+
+	a_assert(websValid(wp));
+
+	flags = websGetRequestFlags(wp);
+
+	websSetTimeMark(wp);
+
+	wrote = bytes = 0;
+	written = websGetRequestWritten(wp);
+	static unsigned int timer = 0;
+
+#if 0
+	if ( !(flags & WEBS_ASP)) {
+#endif		
+		bytes = websGetRequestBytes(wp);
+
+		if ((buf = balloc(B_L, 16*PAGE_READ_BUFSIZE)) == NULL) {
+			websError(wp, 200, T("Can't get memory"));
+			return; //cov
+		} else {
+			while ((len = websPageReadData(wp, buf, 16*PAGE_READ_BUFSIZE)) > 0) {
+				if ((wrote = websWriteDataNonBlock(wp, buf, len)) < 0) {
+					break;
+				}
+				write_bytes += wrote;
+				written += wrote;
+				if (wrote != len) {
+					websPageSeek(wp, - (len - wrote));
+					break;
+				}
+				if(write_bytes > DOWNLOAD_INTERVAL)
+				{
+					write_bytes = 0;
+					break;
+				}
+
+				if( timer ==0)
+                {
+                    websSetLoginTimemark(wp);
+					printf("[httpshare]download reset login state~\n");
+                }
+				
+				timer++;
+				timer=timer-(timer>>11<<11);  //timer%2^11
+			}
+
+ 		    //EOF, done
+			if (len == 0) {
+				a_assert(written >= bytes);
+				written = bytes;
+			}
+			memset(buf, 0, 16*PAGE_READ_BUFSIZE);//kw
+			bfree(B_L, buf);
+		}
+#if 0		
+	}
+#endif	
+
+ 	if(len < 0)
+	{
+		printf("[zyl-download-len-error]len->%d, errno->%d\n",len,errno);
+	}
+	websSetRequestWritten(wp, written);
+	if (wrote < 0 || written >= bytes|| len < 0) {
+	//if (wrote < 0 || written >= bytes) {
+		websDone(wp, 200);
+	}
+}
+//added by guo shoupeng 10124224 for http share 20120110 end
+//#endif
+
+static void websDefaultWriteEvent(webs_t wp)
+{
+	int		len, wrote, flags, bytes, written;
+	char	*buf;
+
+	a_assert(websValid(wp));
+
+	flags = websGetRequestFlags(wp);
+
+	websSetTimeMark(wp);
+
+	wrote = bytes = 0;
+	written = websGetRequestWritten(wp);
+
+	if ( !(flags & WEBS_ASP)) {
+		bytes = websGetRequestBytes(wp);
+
+		if ((buf = balloc(B_L, PAGE_READ_BUFSIZE)) == NULL) {
+			websError(wp, 200, T("Can't get memory"));
+			return; //cov
+		} else {
+			while ((len = websPageReadData(wp, buf, PAGE_READ_BUFSIZE)) > 0) {
+				if ((wrote = websWriteDataNonBlock(wp, buf, len)) < 0) {
+					break;
+				}
+#ifdef _USE_WEBUI_ZIP
+				if (wrote != len)
+				{
+					int tmplen;
+					int leftlen = (len - wrote);
+					while(leftlen > 0)
+					{
+						if((get_sys_uptime() - wp->timestamp) > (WEBS_TIMEOUT/1000))
+							break;
+						tmplen = websWriteDataNonBlock(wp, buf+wrote, leftlen);
+						if(tmplen >= 0)
+						{
+							//printf("%s write=%d left=%d\n",wp->path,tmplen, leftlen);
+							wrote +=tmplen;
+							leftlen -=tmplen;
+							usleep(1000);
+						}
+						else
+						{
+							break;
+						}
+					}
+
+				}
+#endif				
+				written += wrote;
+				if (wrote != len) {
+					websPageSeek(wp, - (len - wrote));
+					break;
+				}
+			}
+
+			if (len == 0) {
+				a_assert(written >= bytes);
+				written = bytes;
+			
+			}
+			memset(buf, 0, PAGE_READ_BUFSIZE);//kw
+			bfree(B_L, buf);
+		}
+	}
+
+	websSetRequestWritten(wp, written);
+	if (wrote < 0 || written >= bytes) {
+		websDone(wp, 200);
+	}
+}
+
+void websDefaultClose()
+{
+	if (websDefaultPage) {
+		bfree(B_L, websDefaultPage);
+		websDefaultPage = NULL;
+	}
+	if (websDefaultDir) {
+		bfree(B_L, websDefaultDir);
+		websDefaultDir = NULL;
+	}
+}
+
+char_t *websGetDefaultPage()
+{
+	return websDefaultPage;
+}
+
+char_t *websGetDefaultDir()
+{
+	return websDefaultDir;
+}
+
+void websSetDefaultPage(char_t *page)
+{
+	a_assert(page && *page);
+
+	if (websDefaultPage) {
+		bfree(B_L, websDefaultPage);
+	}
+	websDefaultPage = bstrdup(B_L, page);
+}
+
+void websSetDefaultDir(char_t *dir)
+{
+	a_assert(dir && *dir);
+	if (websDefaultDir) {
+		bfree(B_L, websDefaultDir);
+	}
+	websDefaultDir = bstrdup(B_L, dir);
+}
+
+
diff --git a/ap/app/goahead/server/ej.h b/ap/app/goahead/server/ej.h
new file mode 100755
index 0000000..ada8488
--- /dev/null
+++ b/ap/app/goahead/server/ej.h
@@ -0,0 +1,23 @@
+#ifndef _h_EJ
+#define _h_EJ 1
+
+#ifndef UEMF
+	#include	"basic/basic.h"
+	#include	"emf/emf.h"
+#else
+	#include	"uemf.h"
+#endif
+
+extern void		ejSetVar(int eid, char_t *var, char_t *value);
+extern int		ejGetVar(int eid, char_t *var, char_t **value);
+extern char_t	*ejEval(int eid, char_t *script, char_t **emsg);
+
+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 		ejSetGlobalFunction(int eid, char_t *name, int (*fn)(int eid, void *handle, int argc, char_t **argv));
+
+
+#endif /* _h_EJ */
+
diff --git a/ap/app/goahead/server/ejIntrn.h b/ap/app/goahead/server/ejIntrn.h
new file mode 100755
index 0000000..1f1bf93
--- /dev/null
+++ b/ap/app/goahead/server/ejIntrn.h
@@ -0,0 +1,185 @@
+#ifndef _h_EJINTERNAL
+#define _h_EJINTERNAL 1
+
+#include	<ctype.h>
+#include	<stdarg.h>
+#include	<stdlib.h>
+
+#ifdef CE
+#ifndef UEMF
+	#include	<io.h>
+#endif
+#endif
+
+#ifdef LYNX
+	#include	<unistd.h>
+#endif
+
+#ifdef QNX4
+	#include	<dirent.h>
+#endif
+
+#ifdef UEMF
+	#include	"uemf.h"
+#else
+	#include	<param.h>
+	#include	<stat.h>
+	#include	"basic/basicInternal.h"
+	#include	"emf/emfInternal.h"
+#endif
+
+#include		"ej.h"
+
+#define EJ_OFFSET			1		
+#define EJ_MAX_RECURSE		100		
+
+#define EJ_INC				110		
+#define EJ_SCRIPT_INC		1023	
+
+
+
+#define TOK_ERR				-1		
+#define TOK_LPAREN			1		
+#define TOK_RPAREN			2		
+#define TOK_IF				3		
+#define TOK_ELSE			4		
+#define TOK_LBRACE			5		
+#define TOK_RBRACE			6		
+#define TOK_LOGICAL			7		
+#define TOK_EXPR			8		
+#define TOK_SEMI			9		
+#define TOK_LITERAL			10		
+#define TOK_FUNCTION		11		
+#define TOK_NEWLINE			12		
+#define TOK_ID				13		
+#define TOK_EOF				14		
+#define TOK_COMMA			15		
+#define TOK_VAR				16		
+#define TOK_ASSIGNMENT		17		
+#define TOK_FOR				18		
+#define TOK_INC_DEC			19		
+#define TOK_RETURN			20		
+
+#define COND_AND			1		
+#define COND_OR				2		
+#define COND_NOT			3	
+
+#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		
+
+
+#define STATE_ERR				-1			
+#define STATE_EOF				1			
+#define STATE_COND				2			
+#define STATE_COND_DONE			3
+#define STATE_RELEXP			4			
+#define STATE_RELEXP_DONE		5
+#define STATE_EXPR				6			
+#define STATE_EXPR_DONE			7
+#define STATE_STMT				8			
+#define STATE_STMT_DONE			9
+#define STATE_STMT_BLOCK_DONE	10			
+#define STATE_ARG_LIST			11			
+#define STATE_ARG_LIST_DONE		12
+#define STATE_DEC_LIST			16			
+#define STATE_DEC_LIST_DONE		17
+#define STATE_DEC				18
+#define STATE_DEC_DONE			19
+#define STATE_RET				20			
+#define STATE_BEGIN				STATE_STMT
+
+#define FLAGS_EXE				0x1				
+#define FLAGS_VARIABLES			0x2				
+#define FLAGS_FUNCTIONS			0x4				
+
+
+typedef struct {
+	char_t		*fname;							
+	char_t		**args;							
+	int			nArgs;							/* Number of args */
+} ejfunc_t;
+
+typedef struct ejEval {
+	ringq_t		tokbuf;							
+	ringq_t		script;							/* Input script for parsing */
+	char_t		*putBackToken;					
+	int			putBackTokenId;					
+	char_t		*line;							
+	int			lineLength;						
+	int			lineNumber;						
+	int			lineColumn;						
+} ejinput_t;
+
+typedef struct ej {
+	ejinput_t	*input;							
+	sym_fd_t	functions;						
+	sym_fd_t	*variables;						
+	int			variableMax;					
+	ejfunc_t	*func;							
+	char_t		*result;						
+	char_t		*error;							
+	char_t		*token;							
+	int			tid;							/* Current token id */
+	int			eid;							/* Halloc handle */
+	int			flags;							
+	int			userHandle;						/* User defined handle */
+} ej_t;
+
+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 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);
+
+extern sym_fd_t	ejGetVariableTable(int eid);
+extern sym_fd_t	ejGetFunctionTable(int eid);
+
+extern int		ejEmfOpen(int eid);
+extern void		ejEmfClose(int eid);
+#endif /* _h_EJINTERNAL */
+
diff --git a/ap/app/goahead/server/form.c b/ap/app/goahead/server/form.c
new file mode 100755
index 0000000..1713f58
--- /dev/null
+++ b/ap/app/goahead/server/form.c
@@ -0,0 +1,107 @@
+#include	"wsIntrn.h"
+
+static sym_fd_t	formSymtab = -1;
+
+void websHeader(webs_t wp)
+{
+	a_assert(websValid(wp));
+
+	websWrite(wp, T("HTTP/1.0 200 OK\n"));
+
+	websWrite(wp, T("Server: %s\r\n"), WEBS_NAME);
+#ifdef WEBINSPECT_FIX
+	websWrite(wp, T("X-Frame-Options: SAMEORIGIN\n"));
+#endif	
+	websWrite(wp, T("Pragma: no-cache\n"));
+	websWrite(wp, T("Cache-control: no-cache\n"));
+	websWrite(wp, T("Content-Type: text/html\n"));
+	websWrite(wp, T("\n"));
+	websWrite(wp, T("<html>\n"));
+}
+
+
+int websFormDefine(char_t *name, void (*fn)(webs_t wp, char_t *path, 
+	char_t *query))
+{
+	a_assert(name && *name);
+	a_assert(fn);
+
+	if (fn == NULL) {
+		return -1;
+	}
+
+	symEnter(formSymtab, name, valueInteger((int) fn), (int) NULL);
+	return 0;
+}
+
+void websFooter(webs_t wp)
+{
+	a_assert(websValid(wp));
+
+	websWrite(wp, T("</html>\n"));
+}
+
+int websFormHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg, 
+	char_t *url, char_t *path, char_t *query)
+{	
+	char_t		form_buf[FNAMESIZE];
+	char_t		*cp, *form_name;
+	sym_t		*sp;
+	int			(*fn)(void *sock, char_t *path, char_t *args);
+
+	a_assert(websValid(wp));
+	a_assert(url && *url);
+	a_assert(path && *path == '/');
+
+	websStats.formHits++;
+#ifdef WEBS_SECURITY
+	if (strstr(query,"_method")) {
+		printf("websFH: qry=%s\n",query);
+		websError(wp, 405, T(""));
+		return 1;
+	}
+#endif
+
+	gstrncpy(form_buf, path, TSZ(form_buf)-1);
+	if ((form_name = gstrchr(&form_buf[1], '/')) == NULL) {
+		websError(wp, 200, T("Missing form name"));
+		return 1;
+	}
+	form_name++;
+	if ((cp = gstrchr(form_name, '/')) != NULL) {
+		*cp = '\0';
+	}
+
+	sp = symLookup(formSymtab, form_name);
+	if (sp == NULL) {
+#ifdef WEBINSPECT_FIX
+		websDone(wp, 0);
+#else
+		websError(wp, 200, T("Form %s is not defined"), form_name);
+#endif		
+	} else {
+		fn = (int (*)(void *, char_t *, char_t *)) sp->content.value.integer;
+		a_assert(fn);
+		if (fn) {
+			(*fn)((void*) wp, form_name, query);
+		}
+	}
+	return 1;
+}
+
+
+void websFormClose()
+{
+	if (formSymtab != -1) {
+		symClose(formSymtab);
+		formSymtab = -1;
+	}
+}
+
+
+void websFormOpen()
+{
+	formSymtab = symOpen(WEBS_SYM_INIT);
+}
+
+
diff --git a/ap/app/goahead/server/goahead.c b/ap/app/goahead/server/goahead.c
new file mode 100755
index 0000000..680db6a
--- /dev/null
+++ b/ap/app/goahead/server/goahead.c
@@ -0,0 +1,339 @@
+#include	"uemf.h"
+#include	"wsIntrn.h"
+#include	<signal.h>
+#include	<unistd.h> 
+#include	<sys/types.h>
+#include	<sys/wait.h>
+#include    <sched.h>
+#ifdef WEBS_SSL_SUPPORT
+#include	"websSSL.h"
+#endif
+#include "../interface5.0/zte_web_interface.h"
+
+static char_t		*rootWeb = T("etc_ro/web");			/* Root web directory */
+static int			port = 80;						/* Server port */
+static int			retries = 5;					/* Server port retries */
+static int			finished;						/* Finished flag */
+
+/****************************** Forward Declarations **************************/
+
+static int 	initWebs();
+static int  websHomePageHandler(webs_t wp, char_t *urlPrefix, char_t *webDir,
+				int arg, char_t *url, char_t *path, char_t *query);
+extern void defaultErrorHandler(int etype, char_t *msg);
+extern void defaultTraceHandler(int level, char_t *buf);
+
+//added by liuyingnan for PC Client begin, 20120829
+extern int websXMLPostHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg, char_t *url, char_t *path, char_t *query);
+//added by liuyingnan for PC Client end, 20120829
+
+int main(int argc, char** argv)
+{
+    int rs;
+    struct sched_param param;
+
+    loglevel_init();
+	slog(MISC_PRINT, SLOG_DEBUG, "goahead main\n");
+	bopen(NULL, (60 * 1024), B_USE_MALLOC);
+	signal(SIGPIPE, SIG_IGN);
+	if (initWebs() < 0) {
+		slog(MISC_PRINT, SLOG_ERR, "goahead initWebs failed.");
+		return -1;
+	}
+
+#ifdef WEBS_SSL_SUPPORT
+	websSSLOpen();
+#endif
+	web_init_pwd();
+	web_aes_init();
+
+	slog(MISC_PRINT, SLOG_NORMAL,"[goahead] enter working\n");
+	while (!finished) {
+		if (socketReady(-1) || socketSelect(-1, 1000)) {         
+			socketProcess(-1);
+		}
+		websCgiCleanup();
+		emfSchedProcess();
+	}
+
+#ifdef WEBS_SSL_SUPPORT
+	websSSLClose();
+#endif
+
+	websCloseServer();
+	socketClose();
+	bclose();
+	return 0;
+}
+
+static int initWebs()
+{
+	struct in_addr	intaddr;
+	const char			lan_ip[128] = {0};
+	char			host[128], dir[128], webdir[128];
+	char			*cp;
+	char_t			wbuf[128];
+	socketOpen();
+
+	cfg_get_item("lan_ipaddr", lan_ip, sizeof(lan_ip));
+	if (0 == strcmp(lan_ip, "")) {
+		slog(MISC_PRINT, SLOG_ERR, "goahead initWebs failed: lan_ip is NULL!");
+		return -1;
+	}
+	intaddr.s_addr = inet_addr(lan_ip);
+	if (intaddr.s_addr == INADDR_NONE) {
+		slog(MISC_PRINT, SLOG_ERR, "goahead initWebs failed: lan_ip is %s, INADDR_NONE!", lan_ip);
+		return -1;
+	}
+	getcwd(dir, sizeof(dir)); 
+	if ((cp = strrchr(dir, '/'))) {
+		*cp = '\0';
+	}
+    snprintf(webdir, sizeof(webdir), "%s/%s", dir, rootWeb);
+    slog(MISC_PRINT,SLOG_DEBUG, "goahead initWebs info: webdir is %s!",webdir);
+	websSetDefaultDir(webdir);
+	cp = inet_ntoa(intaddr);
+	ascToUni(wbuf, cp, min(strlen(cp) + 1, sizeof(wbuf)));
+	websSetIpaddr(wbuf);
+	websSetHost(wbuf);
+	websSetDefaultPage(T(ZTE_WEB_PAGE_LOGIN_NAME));
+	websOpenServer(port, retries);
+	//websUrlHandlerDefine(T(""), NULL, 0, websSecurityHandler, WEBS_HANDLER_FIRST);
+	websUrlHandlerDefine(T("/reqproc"), NULL, 0, websFormHandler, 0);
+#ifndef WEBS_SECURITY
+	websUrlHandlerDefine(T("/cgi-bin"), NULL, 0, websCgiHandler, 0);
+    //websUrlHandlerDefine(T("/api/xmlclient/post"), NULL, 0, websXMLPostHandler, 0);
+	websUrlHandlerDefine(T("/mmc2"), NULL, 0, websCgiDownLoadHandler, 0);//http share
+#endif	
+	websUrlHandlerDefine(T(""), NULL, 0, websDefaultHandler, WEBS_HANDLER_LAST); 
+	zte_web_init();
+	zte_httpshare_init();//httpshare
+	websUrlHandlerDefine(T("/"), NULL, 0, websHomePageHandler, 0); 
+
+	system("rm -rf /firmware_tmp_file");
+	return 0;
+}
+
+static int websHomePageHandler(webs_t wp, char_t *urlPrefix, char_t *webDir,
+                               int arg, char_t *url, char_t *path, char_t *query)
+{
+    if (*url == '\0' || gstrcmp(url, T("/")) == 0) 
+    {
+        websRedirect(wp, zte_web_get_login_page(wp)); /*×ÔÊÊÓ¦ÖÕ¶Ëä¯ÀÀÆ÷*/
+        return 1;
+    }
+    return 0;
+}
+
+void defaultErrorHandler(int etype, char_t *msg)
+{
+	printf("[goahead]e %s\n",msg);
+}
+
+void defaultTraceHandler(int level, char_t *buf)
+{
+	if (buf) {
+		printf("[goahead]t %s\n",buf);
+	}
+}
+
+char_t *websGetCgiCommName(webs_t wp)
+{
+	char_t	*pname1, *pname2;
+
+	pname1 = (char_t *)tempnam(T("/var"), T("cgi"));
+	pname2 = bstrdup(B_L, pname1);
+	free(pname1);
+	return pname2;
+}
+
+int websLaunchCgiProc(char_t *cgiPath, char_t **argp, char_t **envp,
+					  char_t *stdIn, char_t *stdOut)
+{
+	int	pid, fdin, fdout, hstdin, hstdout, rc;
+
+	fdin = fdout = hstdin = hstdout = rc = -1; 
+	if ((fdin = open(stdIn, O_RDWR | O_CREAT, 0666)) < 0 ||
+		(fdout = open(stdOut, O_RDWR | O_CREAT, 0666)) < 0 ||
+		(hstdin = dup(0)) == -1 ||
+		(hstdout = dup(1)) == -1 ||
+		dup2(fdin, 0) == -1 ||
+		dup2(fdout, 1) == -1) {
+		goto DONE;
+	}
+		
+ 	rc = pid = fork();
+ 	if (pid == 0) {
+        int result = execve(cgiPath, argp, envp);
+        slog(MISC_PRINT,SLOG_DEBUG, "content-type: text/html Execution of cgi process :%d", result);
+		exit (0);
+	} 
+
+DONE:
+	if (hstdout >= 0) {
+		dup2(hstdout, 1);
+      close(hstdout);
+	}
+	if (hstdin >= 0) {
+		dup2(hstdin, 0);
+      close(hstdin);
+	}
+	if (fdout >= 0) {
+		close(fdout);
+	}
+	if (fdin >= 0) {
+		close(fdin);
+	}
+	return rc;
+}
+
+int websCheckCgiProc(int handle, int *status)
+{
+	if (waitpid(handle, status, WNOHANG) == handle) {
+		return 0;
+	} else {
+		return 1;
+	}
+}
+
+static int i64c(int i)
+{
+	i &= 0x3f;
+	if (i == 0)
+		return '.';
+	if (i == 1)
+		return '/';
+	if (i < 12)
+		return ('0' - 2 + i);
+	if (i < 38)
+		return ('A' - 12 + i);
+	return ('a' - 38 + i);
+}
+
+static int web_make_salt(char *p, int cnt /*, int x */)
+{
+	/* was: x += ... */
+	int x = getpid() + (int)time(0);
+	do {
+		/* x = (x*1664525 + 1013904223) % 2^32 generator is lame
+		 * (low-order bit is not "random", etc...),
+		 * but for our purposes it is good enough */
+		x = x*1664525 + 1013904223;
+		/* BTW, Park and Miller's "minimal standard generator" is
+		 * x = x*16807 % ((2^31)-1)
+		 * It has no problem with visibly alternating lowest bit
+		 * but is also weak in cryptographic sense + needs div,
+		 * which needs more code (and slower) on many CPUs */
+		*p++ = i64c(x >> 16);
+		*p++ = i64c(x >> 22);
+	} while (--cnt);
+	*p = '\0';
+	return x;
+}
+
+int web_set_pwd(char *buf)
+{
+	if(buf == NULL)
+		return -1;
+	int bufLen = strlen(buf);
+	if(bufLen <= 0 || bufLen > LOGIN_PSW_MAX_LEN)
+		return -1;
+#ifdef WEBS_SSL_SUPPORT
+	char salt[LOGIN_PSW_MAX_LEN+1]={0};
+	web_make_salt(salt,(sizeof(salt)-1)/2);
+	slog(MISC_PRINT,SLOG_DEBUG, "[goahead]salt %s\n",salt);
+	unsigned char md[LOGIN_PSW_MAX_LEN] = {0};
+	{
+		unsigned char src[LOGIN_PSW_MAX_LEN*2+1] = {0};
+		memcpy(src,salt,LOGIN_PSW_MAX_LEN);
+		memcpy(src+LOGIN_PSW_MAX_LEN,buf,bufLen);
+		SHA256((const unsigned char *)src, bufLen+LOGIN_PSW_MAX_LEN, md);
+	}
+	{
+		char i = 0; 
+		char str_md[LOGIN_PSW_MAX_LEN*2+1] = {0};
+		for(i = 0; i < LOGIN_PSW_MAX_LEN; i++)
+		{
+			sprintf(str_md+i+i,"%02x", md[i]);
+		}
+		char psw_buf[100] = {0};
+		snprintf(psw_buf,sizeof(psw_buf),"%s%s",salt,str_md);
+		slog(MISC_PRINT,SLOG_DEBUG, "goahead]set_pw %s\n",psw_buf);
+		return cfg_set("admin_Password", psw_buf);
+	}
+#else
+	return cfg_set("admin_Password", buf);
+#endif
+}
+
+void web_init_pwd(void)
+{
+#ifdef WEBS_SSL_SUPPORT
+	char psw_buf[LOGIN_PSW_MAX_LEN*3+1] = {0};
+	cfg_get_item("admin_Password", psw_buf, sizeof(psw_buf));
+	slog(MISC_PRINT,SLOG_DEBUG, "[goahead]init_pw %s\n",psw_buf);
+	if(strlen(psw_buf) <= LOGIN_PSW_MAX_LEN)
+	{
+		web_set_pwd(psw_buf);
+	}
+#endif	
+}
+
+int web_check_pwd(char* buf)
+{
+	char psw_buf[LOGIN_PSW_MAX_LEN*3+1] = {0};
+	if(buf == NULL)
+		return -1;
+	int bufLen = strlen(buf);
+	if(bufLen <= 0 || bufLen > LOGIN_PSW_MAX_LEN)
+		return -1;
+	cfg_get_item("admin_Password", psw_buf, sizeof(psw_buf));
+	slog(MISC_PRINT,SLOG_DEBUG, "[goahead]check_pw in %s\n",buf);
+	slog(MISC_PRINT,SLOG_DEBUG, "[goahead]check_pw src %s\n",psw_buf);
+#ifdef WEBS_SSL_SUPPORT
+	unsigned char md[LOGIN_PSW_MAX_LEN] = {0};
+	{
+		unsigned char src[LOGIN_PSW_MAX_LEN*2+1] = {0};
+		memcpy(src,psw_buf,LOGIN_PSW_MAX_LEN);
+		memcpy(src+LOGIN_PSW_MAX_LEN,buf,bufLen);
+		SHA256((const unsigned char *)src, bufLen+LOGIN_PSW_MAX_LEN, md);
+	}
+	{
+		char i = 0;	
+		char str_md[65] = {0};
+		for(i = 0; i < LOGIN_PSW_MAX_LEN; i++)
+		{
+			sprintf(str_md+i+i,"%02x", md[i]);
+		}
+		return strncmp(str_md,psw_buf+LOGIN_PSW_MAX_LEN,sizeof(str_md)-1);
+	}
+#else
+	if(bufLen != strlen(psw_buf))
+		return -1;
+
+	return strncmp(buf,psw_buf,bufLen);;
+#endif
+}
+
+int web_make_salt_base64(char *buf, int len)
+{
+	int salt_len;
+	char *salt;
+	if(buf == NULL || len < 5)
+	{
+		return 0;
+	}
+	salt_len = (len - 1)/4*3;
+	salt = balloc(B_L, salt_len+1);
+	if(salt == NULL)
+	{
+		return 0;
+	}
+	web_make_salt(salt,salt_len/2);
+	websEncode64(buf, salt, len);
+	bfree(B_L, salt);
+	*(buf + len -1) = '\0';
+	slog(MISC_PRINT,SLOG_DEBUG, "[goahead]salt_base64=%s\n",buf);
+	return strlen(buf);
+}
+
diff --git a/ap/app/goahead/server/h.c b/ap/app/goahead/server/h.c
new file mode 100755
index 0000000..228b162
--- /dev/null
+++ b/ap/app/goahead/server/h.c
@@ -0,0 +1,146 @@
+#ifdef UEMF
+	#include	"uemf.h"
+#else
+	#include	"basic/basicInternal.h"
+#endif
+
+
+#define H_LEN		0		
+#define H_USED		1		
+#define H_OFFSET	2		
+#define H_INCR		16		
+
+
+int hFree(void ***map, int handle)
+{
+	int 	len;
+	int		*mp;	
+
+	a_assert(map);
+	mp = &((*(int**)map)[-H_OFFSET]);
+	a_assert(mp[H_LEN] >= H_INCR);
+
+	a_assert(mp[handle + H_OFFSET]);
+	a_assert(mp[H_USED]);
+	mp[handle + H_OFFSET] = 0;
+	if (--(mp[H_USED]) == 0) {
+		bfree(B_L, (void*) mp);
+		*map = NULL;
+	}
+
+
+	if (*map == NULL) {
+		handle = -1;
+	} else {
+		len = mp[H_LEN];
+		if (mp[H_USED] < mp[H_LEN]) {
+			for (handle = len - 1; handle >= 0; handle--) {
+				if (mp[handle + H_OFFSET])
+					break;
+			}
+		} else {
+			handle = len;
+		}
+	}
+	return handle + 1;
+}
+
+
+#ifdef B_STATS
+int HALLOC(B_ARGS_DEC, void ***map)
+#else
+int hAlloc(void ***map)
+#endif
+{
+	int		handle, len, memsize, incr;
+	int		*mp;
+
+	a_assert(map);
+
+	if (*map == NULL) {
+		incr = H_INCR;
+		memsize = (incr + H_OFFSET) * sizeof(void**);
+#ifdef 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);
+		mp[H_LEN] = incr;
+		mp[H_USED] = 0;
+		*map = (void**) &mp[H_OFFSET];
+	} else {
+		mp = &((*(int**)map)[-H_OFFSET]);
+	}
+
+	len = mp[H_LEN];
+
+
+	if (mp[H_USED] < mp[H_LEN]) {
+		for (handle = 0; handle < len; handle++) {
+			if (mp[handle+H_OFFSET] == 0) {
+				mp[H_USED]++;
+				return handle;
+			}
+		}
+	} else {
+		handle = len;
+	}
+
+	len += H_INCR;
+	memsize = (len + H_OFFSET) * sizeof(void**);
+	if ((mp = (int*) brealloc(B_L, (void*) mp, memsize)) == NULL) {
+		return -1;
+	}
+	*map = (void**) &mp[H_OFFSET];
+	mp[H_LEN] = len;
+    memset(&mp[H_OFFSET + len - H_INCR], 0, sizeof(int) * H_INCR);
+
+	mp[H_USED]++;
+	return handle;
+}
+
+
+#ifdef B_STATS
+int HALLOCENTRY(B_ARGS_DEC, void ***list, int *max, int size)
+#else
+int hAllocEntry(void ***list, int *max, int size)
+#endif
+{
+	int		id;
+	char_t	*cp;
+
+	a_assert(list);
+	a_assert(max);
+
+#ifdef B_STATS
+	if ((id = HALLOC(B_ARGS, (void***) list)) < 0) {
+#else
+	if ((id = hAlloc((void***) list)) < 0) {
+#endif
+		return -1;
+	}
+
+	if (size > 0) {
+#ifdef B_STATS
+		if ((cp = balloc(B_ARGS, size)) == NULL) {
+#else
+		if ((cp = balloc(B_L, size)) == NULL) {
+#endif
+			hFree(list, id);
+			return -1;
+		}
+		a_assert(cp);
+		memset(cp, 0, size);
+
+		(*list)[id] = (void*) cp;
+	}
+
+	if (id >= *max) {
+		*max = id + 1;
+	}
+	return id;
+}
+
diff --git a/ap/app/goahead/server/handler.c b/ap/app/goahead/server/handler.c
new file mode 100755
index 0000000..0015686
--- /dev/null
+++ b/ap/app/goahead/server/handler.c
@@ -0,0 +1,377 @@
+#include	"wsIntrn.h"
+#include "../interface5.0/zte_web_interface.h"
+//#include "../interface5.0/zte_rest_comm_interface.h"
+
+
+
+static websUrlHandlerType	*websUrlHandler;			
+static int					websUrlHandlerMax;			
+static int					urlHandlerOpenCount = 0;	
+
+static int 		websUrlHandlerSort(const void *p1, const void *p2);
+static char_t	*websCondenseMultipleChars(char_t *strToCondense, char_t cCondense);
+
+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 websUrlHandlerSort(const void *p1, const void *p2)
+{
+	websUrlHandlerType	*s1, *s2;
+	int 				rc;
+
+	a_assert(p1);
+	a_assert(p2);
+
+	s1 = (websUrlHandlerType*) p1;
+	s2 = (websUrlHandlerType*) p2;
+
+	if ((s1->flags & WEBS_HANDLER_FIRST) || (s2->flags & WEBS_HANDLER_LAST)) {
+		return -1;
+	}
+
+	if ((s2->flags & WEBS_HANDLER_FIRST) || (s1->flags & WEBS_HANDLER_LAST)) {
+		return 1;
+	}
+
+	if ((rc = gstrcmp(s1->urlPrefix, s2->urlPrefix)) == 0) {
+		if (s1->len < s2->len) {
+			return 1;
+		} else if (s1->len > s2->len) {
+			return -1;
+		}
+	}
+	return -rc; 
+}
+
+int websUrlHandlerOpen()
+{
+	if (++urlHandlerOpenCount == 1) {
+#ifdef WEB_ASP	
+		websAspOpen();
+#endif
+		websUrlHandler = NULL;
+		websUrlHandlerMax = 0;
+	}
+	return 0;
+}
+
+int websUrlHandlerDefine(char_t *urlPrefix, char_t *webDir, int arg,
+		int (*handler)(webs_t wp, char_t *urlPrefix, char_t *webdir, int arg, 
+		char_t *url, char_t *path, char_t *query), int flags)
+{
+	websUrlHandlerType	*sp;
+	int					len;
+
+	a_assert(urlPrefix);
+	a_assert(handler);
+
+	len = (websUrlHandlerMax + 1) * sizeof(websUrlHandlerType);
+	if ((websUrlHandler = brealloc(B_L, websUrlHandler, len)) == NULL) {
+		return -1;
+	}
+	sp = &websUrlHandler[websUrlHandlerMax++];
+	memset(sp, 0, sizeof(websUrlHandlerType));
+
+	sp->urlPrefix = bstrdup(B_L, urlPrefix);
+	if(sp->urlPrefix)
+	sp->len = gstrlen(sp->urlPrefix);
+	if (webDir) {
+		sp->webDir = bstrdup(B_L, webDir);
+	} else {
+		sp->webDir = bstrdup(B_L, T(""));
+	}
+	sp->handler = handler;
+	sp->arg = arg;
+	sp->flags = flags;
+
+	qsort(websUrlHandler, websUrlHandlerMax, sizeof(websUrlHandlerType), 
+		websUrlHandlerSort);
+	return 0;
+}
+
+void websUrlHandlerClose()
+{
+	websUrlHandlerType *sp;
+
+	if (--urlHandlerOpenCount <= 0) {
+#ifdef WEB_ASP	
+		websAspClose();
+#endif
+		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;
+	}
+}
+
+int websPublish(char_t *urlPrefix, char_t *path)
+{
+	return websUrlHandlerDefine(urlPrefix, path, 0, websPublishHandler, 0);
+}
+
+
+int websUrlHandlerDelete(int (*handler)(webs_t wp, char_t *urlPrefix, 
+	char_t *webDir, int arg, char_t *url, char_t *path, char_t *query))
+{
+	websUrlHandlerType	*sp;
+	int					index;
+
+	for (index = 0; index < websUrlHandlerMax; index++) {
+		sp = &websUrlHandler[index];
+		if (sp->handler == handler) {
+			sp->handler = NULL;
+			return 0;
+		}
+	}
+	return -1;
+}
+
+char_t *websGetPublishDir(char_t *path, char_t **urlPrefix)
+{
+	websUrlHandlerType	*sp;
+	int					index;
+
+	for (index = 0; index < websUrlHandlerMax; index++) {
+		sp = &websUrlHandler[index];
+		if (sp->urlPrefix[0] == '\0') {
+			continue;
+		}
+		if (sp->handler && gstrncmp(sp->urlPrefix, path, sp->len) == 0) {
+			if (urlPrefix) {
+				*urlPrefix = sp->urlPrefix;
+			}
+			return sp->webDir;
+		}
+	}
+	return NULL;
+}
+
+
+static int websPublishHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, 
+	int sid, char_t *url, char_t *path, char_t *query)
+{
+	int		len;
+
+	a_assert(websValid(wp));
+	a_assert(path);
+
+	len = gstrlen(urlPrefix) + 1;
+	websSetRequestPath(wp, webDir, &path[len]);
+	return 0;
+}
+
+#ifdef OBSOLETE_CODE
+static int websTidyUrl(webs_t wp)
+{
+	char_t	*parts[64]; 				
+	char_t	*token, *url, *tidyurl;
+	int 	i, len, npart;
+
+	a_assert(websValid(wp));
+
+
+	url = bstrdup(B_L, wp->url);
+	websDecodeUrl(url, url, gstrlen(url));
+
+	len = npart = 0;
+	parts[0] = NULL;
+	token = gstrtok(url, T("/"));
+
+	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("/"));
+	}
+
+	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;
+	}
+}
+#endif
+
+int websUrlHandlerRequest(webs_t wp)
+{
+    websUrlHandlerType	*sp;
+    int i, first;
+    int m=0;
+    int n=0;
+    int m_count=0;
+    int n_count=0;
+    
+    char  zte_user_login_flag[10] = {0};
+    char  zte_web_global_flag[10] = {0};  // 1 means needn't LOGIN, 0 means need LOGIN
+    char_t *ip_address = NULL; 
+    char  dataCard[32] = {0};
+    char  userIpaddr[40] = {0};
+    a_assert(websValid(wp));
+	if(websValid(wp)== 0){
+		softap_assert("websUrlHandlerRequest 1");
+	}
+    
+    socketDeleteHandler(wp->sid);
+    wp->state = WEBS_PROCESSING;
+    websStats.handlerHits++;
+    
+    websSetRequestPath(wp, websGetDefaultDir(), NULL);
+    
+    
+    ip_address = websGetRequestIpaddr(wp);
+#if 0 // kw 3	
+    if (NULL == ip_address)
+    {
+        slog(MISC_PRINT,SLOG_ERR,"ip_address is null.");
+        websDone(wp, 200);
+        return 0;
+    }
+#endif
+	
+    cfg_get_item(NV_DATA_CARD,dataCard,sizeof(dataCard));
+    cfg_get_item(NV_USER_IP_ADDR,userIpaddr,sizeof(userIpaddr));
+    if (0 == strcmp(dataCard,"1"))
+    {
+        strcpy(zte_user_login_flag,"ok");
+    }
+    else if(0 == strcmp(userIpaddr,ip_address))
+    {
+        cfg_get_item("loginfo",zte_user_login_flag,sizeof(zte_user_login_flag));
+    }
+    else
+    {
+        strcpy(zte_user_login_flag,""); 
+    }
+    if(strstr(wp->url, "messages"))
+    {
+        if(strcmp("ok", zte_user_login_flag) != 0) 
+        {
+            slog(MISC_PRINT,SLOG_DEBUG,"websUrlHandlerRequest -> GET is not allowed: %s", wp->url);
+            
+            //zte_webs_feedback_top(wp, zte_web_get_login_page(wp)); /*×ÔÊÊÓ¦ÖÕ¶Ëä¯ÀÀÆ÷*/
+            //websDone(wp, 200);
+			websRedirect(wp, zte_web_get_login_page(wp));
+            return 0;
+        }
+        //   allow pass        
+    }
+    
+    if (strstr(wp->url, "default_parameter") ||strstr(wp->url, "version_parameter") ||strstr(wp->url, "custom_parameter") ||strstr(wp->url, "zteconfig/config"))
+    {
+        slog(MISC_PRINT,SLOG_DEBUG,"websUrlHandlerRequest -> GET is not allowed: %s", wp->url);
+        websError(wp, 404, T("Bad state"));
+        return 0;
+    }
+    
+    //zte_nv_read("loginfo", zte_user_login_flag, sizeof(zte_user_login_flag));
+    
+    if (strcmp("ok", zte_user_login_flag) != 0)   // not login
+    {
+        //   allow pass 
+        
+    }
+    
+#ifdef FEATURE_ZTE_WEB_TCARD
+    //added by guo shoupeng 10124224 for http share 20111001 start
+    zte_httpShare_urlHandler(wp,wp->url);
+    //added by guo shoupeng 10124224 for http share 20111001 start
+#endif //def FEATURE_ZTE_WEB_TCARD
+    
+    /*
+    *	Eliminate security hole
+    */
+    websCondenseMultipleChars(wp->path, '/');
+    websCondenseMultipleChars(wp->url, '/');
+    
+    first = 1;
+    for (i = 0; i < websUrlHandlerMax; i++) 
+    {
+        sp = &websUrlHandler[i];
+        if (sp->handler && gstrncmp(sp->urlPrefix, wp->path, sp->len) == 0) 
+        {
+            if (first) 
+            {
+                websSetEnv(wp);
+                first = 0;
+            }
+			
+			if(websValid(wp)== 0){
+				softap_assert("websUrlHandlerRequest 2");
+			}
+
+            if ((*sp->handler)(wp, sp->urlPrefix, sp->webDir, sp->arg, 
+                               wp->url, wp->path, wp->query)) 
+            {
+                return 1;
+            }
+            if (!websValid(wp)) 
+            {
+                trace(0, T("webs: handler %s called websDone, but didn't return 1\n"), sp->urlPrefix);
+                return 1;
+            }
+        }
+    }
+
+    if (i >= websUrlHandlerMax) 
+    {
+        websError(wp, 200, T("No handler for this URL"));
+    }
+    return 0;
+}
+
+static char_t *websCondenseMultipleChars(char_t *strToCondense, char_t cCondense)
+{
+	if (strToCondense != NULL) {
+		char_t *pStr, *pScan;
+
+		pStr = pScan = strToCondense;
+
+		while (*pScan && *pStr) {
+
+			while ((*pScan == cCondense) && (*(pScan + 1) == cCondense)) {
+				pScan++;
+			}
+
+			if (pStr != pScan) {
+				*pStr = *pScan;
+			}
+			
+			pScan++;
+			pStr++;
+		}
+
+		if (pStr != pScan) {
+			*pStr = 0;
+		}
+	}
+
+	return strToCondense;
+}
+
diff --git a/ap/app/goahead/server/ioapi.c b/ap/app/goahead/server/ioapi.c
new file mode 100644
index 0000000..7f5c191
--- /dev/null
+++ b/ap/app/goahead/server/ioapi.c
@@ -0,0 +1,247 @@
+/* ioapi.h -- IO base function header for compress/uncompress .zip
+   part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
+
+         Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
+
+         Modifications for Zip64 support
+         Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
+
+         For more info read MiniZip_info.txt
+
+*/
+
+#if defined(_WIN32) && (!(defined(_CRT_SECURE_NO_WARNINGS)))
+        #define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#if defined(__APPLE__) || defined(IOAPI_NO_64)
+// In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions
+#define FOPEN_FUNC(filename, mode) fopen(filename, mode)
+#define FTELLO_FUNC(stream) ftello(stream)
+#define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin)
+#else
+#define FOPEN_FUNC(filename, mode) fopen64(filename, mode)
+#define FTELLO_FUNC(stream) ftello64(stream)
+#define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin)
+#endif
+
+
+#include "ioapi.h"
+
+voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode)
+{
+    if (pfilefunc->zfile_func64.zopen64_file != NULL)
+        return (*(pfilefunc->zfile_func64.zopen64_file)) (pfilefunc->zfile_func64.opaque,filename,mode);
+    else
+    {
+        return (*(pfilefunc->zopen32_file))(pfilefunc->zfile_func64.opaque,(const char*)filename,mode);
+    }
+}
+
+long call_zseek64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin)
+{
+    if (pfilefunc->zfile_func64.zseek64_file != NULL)
+        return (*(pfilefunc->zfile_func64.zseek64_file)) (pfilefunc->zfile_func64.opaque,filestream,offset,origin);
+    else
+    {
+        uLong offsetTruncated = (uLong)offset;
+        if (offsetTruncated != offset)
+            return -1;
+        else
+            return (*(pfilefunc->zseek32_file))(pfilefunc->zfile_func64.opaque,filestream,offsetTruncated,origin);
+    }
+}
+
+ZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream)
+{
+    if (pfilefunc->zfile_func64.zseek64_file != NULL)
+        return (*(pfilefunc->zfile_func64.ztell64_file)) (pfilefunc->zfile_func64.opaque,filestream);
+    else
+    {
+        uLong tell_uLong = (*(pfilefunc->ztell32_file))(pfilefunc->zfile_func64.opaque,filestream);
+        if ((tell_uLong) == MAXU32)
+            return (ZPOS64_T)-1;
+        else
+            return tell_uLong;
+    }
+}
+
+void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32)
+{
+    p_filefunc64_32->zfile_func64.zopen64_file = NULL;
+    p_filefunc64_32->zopen32_file = p_filefunc32->zopen_file;
+    p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file;
+    p_filefunc64_32->zfile_func64.zread_file = p_filefunc32->zread_file;
+    p_filefunc64_32->zfile_func64.zwrite_file = p_filefunc32->zwrite_file;
+    p_filefunc64_32->zfile_func64.ztell64_file = NULL;
+    p_filefunc64_32->zfile_func64.zseek64_file = NULL;
+    p_filefunc64_32->zfile_func64.zclose_file = p_filefunc32->zclose_file;
+    p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file;
+    p_filefunc64_32->zfile_func64.opaque = p_filefunc32->opaque;
+    p_filefunc64_32->zseek32_file = p_filefunc32->zseek_file;
+    p_filefunc64_32->ztell32_file = p_filefunc32->ztell_file;
+}
+
+
+
+static voidpf  ZCALLBACK fopen_file_func OF((voidpf opaque, const char* filename, int mode));
+static uLong   ZCALLBACK fread_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size));
+static uLong   ZCALLBACK fwrite_file_func OF((voidpf opaque, voidpf stream, const void* buf,uLong size));
+static ZPOS64_T ZCALLBACK ftell64_file_func OF((voidpf opaque, voidpf stream));
+static long    ZCALLBACK fseek64_file_func OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin));
+static int     ZCALLBACK fclose_file_func OF((voidpf opaque, voidpf stream));
+static int     ZCALLBACK ferror_file_func OF((voidpf opaque, voidpf stream));
+
+static voidpf ZCALLBACK fopen_file_func (voidpf opaque, const char* filename, int mode)
+{
+    FILE* file = NULL;
+    const char* mode_fopen = NULL;
+    if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
+        mode_fopen = "rb";
+    else
+    if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
+        mode_fopen = "r+b";
+    else
+    if (mode & ZLIB_FILEFUNC_MODE_CREATE)
+        mode_fopen = "wb";
+
+    if ((filename!=NULL) && (mode_fopen != NULL))
+        file = fopen(filename, mode_fopen);
+    return file;
+}
+
+static voidpf ZCALLBACK fopen64_file_func (voidpf opaque, const void* filename, int mode)
+{
+    FILE* file = NULL;
+    const char* mode_fopen = NULL;
+    if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
+        mode_fopen = "rb";
+    else
+    if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
+        mode_fopen = "r+b";
+    else
+    if (mode & ZLIB_FILEFUNC_MODE_CREATE)
+        mode_fopen = "wb";
+
+    if ((filename!=NULL) && (mode_fopen != NULL))
+        file = FOPEN_FUNC((const char*)filename, mode_fopen);
+    return file;
+}
+
+
+static uLong ZCALLBACK fread_file_func (voidpf opaque, voidpf stream, void* buf, uLong size)
+{
+    uLong ret;
+    ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream);
+    return ret;
+}
+
+static uLong ZCALLBACK fwrite_file_func (voidpf opaque, voidpf stream, const void* buf, uLong size)
+{
+    uLong ret;
+    ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream);
+    return ret;
+}
+
+static long ZCALLBACK ftell_file_func (voidpf opaque, voidpf stream)
+{
+    long ret;
+    ret = ftell((FILE *)stream);
+    return ret;
+}
+
+
+static ZPOS64_T ZCALLBACK ftell64_file_func (voidpf opaque, voidpf stream)
+{
+    ZPOS64_T ret;
+    ret = FTELLO_FUNC((FILE *)stream);
+    return ret;
+}
+
+static long ZCALLBACK fseek_file_func (voidpf  opaque, voidpf stream, uLong offset, int origin)
+{
+    int fseek_origin=0;
+    long ret;
+    switch (origin)
+    {
+    case ZLIB_FILEFUNC_SEEK_CUR :
+        fseek_origin = SEEK_CUR;
+        break;
+    case ZLIB_FILEFUNC_SEEK_END :
+        fseek_origin = SEEK_END;
+        break;
+    case ZLIB_FILEFUNC_SEEK_SET :
+        fseek_origin = SEEK_SET;
+        break;
+    default: return -1;
+    }
+    ret = 0;
+    if (fseek((FILE *)stream, offset, fseek_origin) != 0)
+        ret = -1;
+    return ret;
+}
+
+static long ZCALLBACK fseek64_file_func (voidpf  opaque, voidpf stream, ZPOS64_T offset, int origin)
+{
+    int fseek_origin=0;
+    long ret;
+    switch (origin)
+    {
+    case ZLIB_FILEFUNC_SEEK_CUR :
+        fseek_origin = SEEK_CUR;
+        break;
+    case ZLIB_FILEFUNC_SEEK_END :
+        fseek_origin = SEEK_END;
+        break;
+    case ZLIB_FILEFUNC_SEEK_SET :
+        fseek_origin = SEEK_SET;
+        break;
+    default: return -1;
+    }
+    ret = 0;
+
+    if(FSEEKO_FUNC((FILE *)stream, offset, fseek_origin) != 0)
+                        ret = -1;
+
+    return ret;
+}
+
+
+static int ZCALLBACK fclose_file_func (voidpf opaque, voidpf stream)
+{
+    int ret;
+    ret = fclose((FILE *)stream);
+    return ret;
+}
+
+static int ZCALLBACK ferror_file_func (voidpf opaque, voidpf stream)
+{
+    int ret;
+    ret = ferror((FILE *)stream);
+    return ret;
+}
+
+void fill_fopen_filefunc (pzlib_filefunc_def)
+  zlib_filefunc_def* pzlib_filefunc_def;
+{
+    pzlib_filefunc_def->zopen_file = fopen_file_func;
+    pzlib_filefunc_def->zread_file = fread_file_func;
+    pzlib_filefunc_def->zwrite_file = fwrite_file_func;
+    pzlib_filefunc_def->ztell_file = ftell_file_func;
+    pzlib_filefunc_def->zseek_file = fseek_file_func;
+    pzlib_filefunc_def->zclose_file = fclose_file_func;
+    pzlib_filefunc_def->zerror_file = ferror_file_func;
+    pzlib_filefunc_def->opaque = NULL;
+}
+
+void fill_fopen64_filefunc (zlib_filefunc64_def*  pzlib_filefunc_def)
+{
+    pzlib_filefunc_def->zopen64_file = fopen64_file_func;
+    pzlib_filefunc_def->zread_file = fread_file_func;
+    pzlib_filefunc_def->zwrite_file = fwrite_file_func;
+    pzlib_filefunc_def->ztell64_file = ftell64_file_func;
+    pzlib_filefunc_def->zseek64_file = fseek64_file_func;
+    pzlib_filefunc_def->zclose_file = fclose_file_func;
+    pzlib_filefunc_def->zerror_file = ferror_file_func;
+    pzlib_filefunc_def->opaque = NULL;
+}
diff --git a/ap/app/goahead/server/ioapi.h b/ap/app/goahead/server/ioapi.h
new file mode 100644
index 0000000..8dcbdb0
--- /dev/null
+++ b/ap/app/goahead/server/ioapi.h
@@ -0,0 +1,208 @@
+/* ioapi.h -- IO base function header for compress/uncompress .zip
+   part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
+
+         Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
+
+         Modifications for Zip64 support
+         Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
+
+         For more info read MiniZip_info.txt
+
+         Changes
+
+    Oct-2009 - Defined ZPOS64_T to fpos_t on windows and u_int64_t on linux. (might need to find a better why for this)
+    Oct-2009 - Change to fseeko64, ftello64 and fopen64 so large files would work on linux.
+               More if/def section may be needed to support other platforms
+    Oct-2009 - Defined fxxxx64 calls to normal fopen/ftell/fseek so they would compile on windows.
+                          (but you should use iowin32.c for windows instead)
+
+*/
+
+#ifndef _ZLIBIOAPI64_H
+#define _ZLIBIOAPI64_H
+
+#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__))
+
+  // Linux needs this to support file operation on files larger then 4+GB
+  // But might need better if/def to select just the platforms that needs them.
+
+        #ifndef __USE_FILE_OFFSET64
+                #define __USE_FILE_OFFSET64
+        #endif
+        #ifndef __USE_LARGEFILE64
+                #define __USE_LARGEFILE64
+        #endif
+        #ifndef _LARGEFILE64_SOURCE
+                #define _LARGEFILE64_SOURCE
+        #endif
+        #ifndef _FILE_OFFSET_BIT
+                #define _FILE_OFFSET_BIT 64
+        #endif
+
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "zlib.h"
+
+#if defined(USE_FILE32API)
+#define fopen64 fopen
+#define ftello64 ftell
+#define fseeko64 fseek
+#else
+#ifdef __FreeBSD__
+#define fopen64 fopen
+#define ftello64 ftello
+#define fseeko64 fseeko
+#endif
+#ifdef _MSC_VER
+ #define fopen64 fopen
+ #if (_MSC_VER >= 1400) && (!(defined(NO_MSCVER_FILE64_FUNC)))
+  #define ftello64 _ftelli64
+  #define fseeko64 _fseeki64
+ #else // old MSC
+  #define ftello64 ftell
+  #define fseeko64 fseek
+ #endif
+#endif
+#endif
+
+/*
+#ifndef ZPOS64_T
+  #ifdef _WIN32
+                #define ZPOS64_T fpos_t
+  #else
+    #include <stdint.h>
+    #define ZPOS64_T uint64_t
+  #endif
+#endif
+*/
+
+#ifdef HAVE_MINIZIP64_CONF_H
+#include "mz64conf.h"
+#endif
+
+/* a type choosen by DEFINE */
+#ifdef HAVE_64BIT_INT_CUSTOM
+typedef  64BIT_INT_CUSTOM_TYPE ZPOS64_T;
+#else
+#ifdef HAS_STDINT_H
+#include "stdint.h"
+typedef uint64_t ZPOS64_T;
+#else
+
+/* Maximum unsigned 32-bit value used as placeholder for zip64 */
+#define MAXU32 0xffffffff
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+typedef unsigned __int64 ZPOS64_T;
+#else
+typedef unsigned long long int ZPOS64_T;
+#endif
+#endif
+#endif
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define ZLIB_FILEFUNC_SEEK_CUR (1)
+#define ZLIB_FILEFUNC_SEEK_END (2)
+#define ZLIB_FILEFUNC_SEEK_SET (0)
+
+#define ZLIB_FILEFUNC_MODE_READ      (1)
+#define ZLIB_FILEFUNC_MODE_WRITE     (2)
+#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3)
+
+#define ZLIB_FILEFUNC_MODE_EXISTING (4)
+#define ZLIB_FILEFUNC_MODE_CREATE   (8)
+
+
+#ifndef ZCALLBACK
+ #if (defined(WIN32) || defined(_WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK)
+   #define ZCALLBACK CALLBACK
+ #else
+   #define ZCALLBACK
+ #endif
+#endif
+
+
+
+
+typedef voidpf   (ZCALLBACK *open_file_func)      OF((voidpf opaque, const char* filename, int mode));
+typedef uLong    (ZCALLBACK *read_file_func)      OF((voidpf opaque, voidpf stream, void* buf, uLong size));
+typedef uLong    (ZCALLBACK *write_file_func)     OF((voidpf opaque, voidpf stream, const void* buf, uLong size));
+typedef int      (ZCALLBACK *close_file_func)     OF((voidpf opaque, voidpf stream));
+typedef int      (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream));
+
+typedef long     (ZCALLBACK *tell_file_func)      OF((voidpf opaque, voidpf stream));
+typedef long     (ZCALLBACK *seek_file_func)      OF((voidpf opaque, voidpf stream, uLong offset, int origin));
+
+
+/* here is the "old" 32 bits structure structure */
+typedef struct zlib_filefunc_def_s
+{
+    open_file_func      zopen_file;
+    read_file_func      zread_file;
+    write_file_func     zwrite_file;
+    tell_file_func      ztell_file;
+    seek_file_func      zseek_file;
+    close_file_func     zclose_file;
+    testerror_file_func zerror_file;
+    voidpf              opaque;
+} zlib_filefunc_def;
+
+typedef ZPOS64_T (ZCALLBACK *tell64_file_func)    OF((voidpf opaque, voidpf stream));
+typedef long     (ZCALLBACK *seek64_file_func)    OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin));
+typedef voidpf   (ZCALLBACK *open64_file_func)    OF((voidpf opaque, const void* filename, int mode));
+
+typedef struct zlib_filefunc64_def_s
+{
+    open64_file_func    zopen64_file;
+    read_file_func      zread_file;
+    write_file_func     zwrite_file;
+    tell64_file_func    ztell64_file;
+    seek64_file_func    zseek64_file;
+    close_file_func     zclose_file;
+    testerror_file_func zerror_file;
+    voidpf              opaque;
+} zlib_filefunc64_def;
+
+void fill_fopen64_filefunc OF((zlib_filefunc64_def* pzlib_filefunc_def));
+void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def));
+
+/* now internal definition, only for zip.c and unzip.h */
+typedef struct zlib_filefunc64_32_def_s
+{
+    zlib_filefunc64_def zfile_func64;
+    open_file_func      zopen32_file;
+    tell_file_func      ztell32_file;
+    seek_file_func      zseek32_file;
+} zlib_filefunc64_32_def;
+
+
+#define ZREAD64(filefunc,filestream,buf,size)     ((*((filefunc).zfile_func64.zread_file))   ((filefunc).zfile_func64.opaque,filestream,buf,size))
+#define ZWRITE64(filefunc,filestream,buf,size)    ((*((filefunc).zfile_func64.zwrite_file))  ((filefunc).zfile_func64.opaque,filestream,buf,size))
+//#define ZTELL64(filefunc,filestream)            ((*((filefunc).ztell64_file)) ((filefunc).opaque,filestream))
+//#define ZSEEK64(filefunc,filestream,pos,mode)   ((*((filefunc).zseek64_file)) ((filefunc).opaque,filestream,pos,mode))
+#define ZCLOSE64(filefunc,filestream)             ((*((filefunc).zfile_func64.zclose_file))  ((filefunc).zfile_func64.opaque,filestream))
+#define ZERROR64(filefunc,filestream)             ((*((filefunc).zfile_func64.zerror_file))  ((filefunc).zfile_func64.opaque,filestream))
+
+voidpf call_zopen64 OF((const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode));
+long    call_zseek64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin));
+ZPOS64_T call_ztell64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream));
+
+void    fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32);
+
+#define ZOPEN64(filefunc,filename,mode)         (call_zopen64((&(filefunc)),(filename),(mode)))
+#define ZTELL64(filefunc,filestream)            (call_ztell64((&(filefunc)),(filestream)))
+#define ZSEEK64(filefunc,filestream,pos,mode)   (call_zseek64((&(filefunc)),(filestream),(pos),(mode)))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/ap/app/goahead/server/mime.c b/ap/app/goahead/server/mime.c
new file mode 100755
index 0000000..20a407f
--- /dev/null
+++ b/ap/app/goahead/server/mime.c
@@ -0,0 +1,125 @@
+#include	"wsIntrn.h"
+
+
+websMimeType websMimeList[] = {
+	{ T("text/html"), T(".asp") },
+
+	{ T("text/css"), T(".css") },
+	{ T("application/java"), T(".class") },
+
+	{ T("text/html"), T(".htm") },
+	{ T("text/html"), T(".html") },
+
+	{ T("image/gif"), T(".gif") },
+	
+	{ T("application/java"), T(".jar") },
+	{ T("application/x-javascript"), T(".js") },
+	{ T("image/jpeg"), T(".jpg") },
+   
+   	{ T("application/x-shockwave-flash"), T(".swf") },
+
+	{ T("text/plain"), T(".txt") },
+
+	{ T("text/xml"), T(".xml") },
+
+#ifdef MORE_MIME_TYPES
+	{ T("application/postscript"), T(".ai") },
+	{ T("video/x-msvideo"), T(".avi") },
+	{ T("audio/basic"), T(".au snd") },
+	{ T("audio/x-aiff"), T(".aif") },
+	{ T("audio/x-aiff"), T(".aiff") },
+	{ T("audio/x-aiff"), T(".aifc") },
+
+	{ T("application/octet-stream"), T(".bin") },
+	{ T("application/x-bcpio"), T(".bcpio") },
+	
+	{ T("application/x-cpio"), T(".cpio") },
+	{ T("application/x-csh"), T(".csh") },
+	{ T("application/x-netcdf"), T(".cdf") },
+	{ T("text/html"), T(".cfm") },
+
+	{ T("application/x-dvi"), T(".dvi") },
+
+	{ T("application/binary"), T(".exe") },
+	{ T("application/postscript"), T(".eps") },
+	{ T("text/x-setext"), T(".etx") },
+	
+	{ T("application/x-gtar"), T(".gtar") },
+	
+	{ T("application/x-hdf"), T(".hdf") },
+	
+	{ T("image/ief"), T(".ief") },
+	
+	{ T("image/jpeg"), T(".jpeg") },
+	{ T("image/jpeg"), T(".jpe") },
+	
+	{ T("application/x-latex"), T(".latex") },
+	
+	{ T("application/x-mif"), T(".mif") },
+	{ T("application/x-troff-man"), T(".man") },
+	{ T("application/x-troff-me"), T(".me") },
+	{ T("application/x-troff-ms"), T(".ms") },
+	{ T("video/quicktime"), T(".mov") },
+	{ T("video/x-sgi-movie"), T(".movie") },
+	{ T("video/mpeg"), T(".mpeg mpg mpe") },
+	
+	{ T("application/x-netcdf"), T(".nc") },
+	
+	
+	{ T("application/gzip"), T(".gz") },
+	
+	{ T("application/oda"), T(".oda") },
+	
+	{ T("application/pdf"), T(".pdf") },
+	{ T("application/postscript"), T(".ps") },
+	{ T("application/x-ns-proxy-autoconfig"), T(".pac") },
+	{ T("application/x-patch"), T(".patch") },
+	{ T("image/x-portable-anymap"), T(".pnm") },
+	{ T("image/x-portable-bitmap"), T(".pbm") },
+	{ T("image/x-portable-graymap"), T(".pgm") },
+	{ T("image/x-portable-pixmap"), T(".ppm") },
+
+	{ T("video/quicktime"), T(".qt") },
+	
+	{ T("application/rtf"), T(".rtf") },
+	{ T("image/x-rgb"), T(".rgb") },
+	{ T("application/x-troff"), T(".roff") },
+	{ T("image/x-cmu-raster"), T(".ras") },
+	{ T("audio/x-wav"), T(".ram") },
+	
+	{ T("application/x-sh"), T(".sh") },
+	{ T("text/html"), T(".shtm") },
+	{ T("text/html"), T(".shtml") },
+	{ T("application/x-shar"), T(".shar") },
+	{ T("application/x-wais-source"), T(".src") },
+	{ T("application/x-sv4cpio"), T(".sv4cpio") },
+	{ T("application/x-sv4crc"), T(".sv4crc") },
+	
+	{ T("application/x-tar"), T(".tar") },
+	{ T("application/x-tcl"), T(".tcl") },
+	{ T("application/x-tex"), T(".tex") },
+	{ T("text/richtext"), T(".rtx") },
+	{ T("application/x-troff"), T(".t") },
+	{ T("application/x-troff"), T(".tr") },
+	{ T("application/x-texinfo"), T(".texinfo") },
+	{ T("application/x-texinfo"), T(".texi") },
+	{ T("text/tab-separated-values"), T(".tsv") },
+	{ T("image/tiff"), T(".tiff") },
+	{ T("image/tiff"), T(".tif") },
+	
+	{ T("application/x-ustar"), T(".ustar") },
+	
+	{ T("audio/x-wav"), T(".wav") },
+	
+	{ T("image/x-xbitmap"), T(".xbm") },
+	{ T("image/x-xpixmap"), T(".xpm") },
+	{ T("image/x-xwindowdump"), T(".xwd") },
+	
+	{ T("application/compress"), T(".z") },
+	{ T("application/zip"), T(".zip") },
+#endif
+	{ NULL, NULL},
+};
+
+/*****************************************************************************/
+
diff --git a/ap/app/goahead/server/misc.c b/ap/app/goahead/server/misc.c
new file mode 100755
index 0000000..9e03368
--- /dev/null
+++ b/ap/app/goahead/server/misc.c
@@ -0,0 +1,450 @@
+#ifdef UEMF
+	#include	"uemf.h"
+#else
+	#include	"basic/basicInternal.h"
+#endif
+
+#define kUseMemcopy
+
+#define STR_REALLOC		0x1				
+#define STR_INC			64				
+
+typedef struct {
+	char_t	*s;							
+	int		size;						
+	int		max;						
+	int		count;						
+	int		flags;						
+} strbuf_t;
+
+enum flag {
+	flag_none = 0,
+	flag_minus = 1,
+	flag_plus = 2,
+	flag_space = 4,
+	flag_hash = 8,
+	flag_zero = 16,
+	flag_short = 32,
+	flag_long = 64
+};
+
+static int 	dsnprintf(char_t **s, int size, char_t *fmt, va_list arg, int msize);
+static int	strnlen(char_t *s, unsigned int n);
+
+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);
+
+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);
+
+static void put_char(strbuf_t *buf, char_t c)
+{
+	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) {
+
+			buf->size -= STR_INC;
+			return;
+		}
+		if (buf->s == NULL) {
+			buf->s = balloc(B_L, buf->size * sizeof(char_t));
+		} else {
+			buf->s = brealloc(B_L, buf->s, buf->size * sizeof(char_t));
+		}
+	}
+	if(buf->s){
+	buf->s[buf->count] = c;
+	if (c != '\0') {
+		++buf->count;
+	}
+	}
+}
+
+static void put_string(strbuf_t *buf, char_t *s, int len, int width,
+		int prec, enum flag f)
+{
+	int		index;
+
+	if (len < 0) { 
+		len = strnlen(s, prec >= 0 ? prec : ULONG_MAX); 
+	} else if (prec >= 0 && prec < len) { 
+		len = prec; 
+	}
+	if (width > len && !(f & flag_minus)) {
+		for (index = len; index < width; ++index) { 
+			put_char(buf, ' '); 
+		}
+	}
+	for (index = 0; index < len; ++index) { 
+		put_char(buf, s[index]); 
+	}
+	if (width > len && f & flag_minus) {
+		for (index = len; index < width; ++index) { 
+			put_char(buf, ' '); 
+		}
+	}
+}
+
+int fmtAlloc(char_t **s, int n, char_t *fmt, ...)
+{
+	va_list	ap = {0};
+	int		result;
+
+	a_assert(s);
+	a_assert(fmt);
+
+	*s = NULL;
+	va_start(ap, fmt);
+	result = dsnprintf(s, n, fmt, ap, 0);
+	va_end(ap);
+	return result;
+}
+
+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);
+}
+
+int fmtRealloc(char_t **s, int n, int msize, char_t *fmt, ...)
+{
+	va_list	ap = {0};
+	int		result;
+
+	a_assert(s);
+	a_assert(fmt);
+
+	if (msize == -1) {
+		*s = NULL;
+	}
+	va_start(ap, fmt);
+	result = dsnprintf(s, n, fmt, ap, msize);
+	va_end(ap);
+	return result;
+}
+
+static int dsnprintf(char_t **s, int size, char_t *fmt, va_list arg, int msize)
+{
+	char_t		tmp_c;
+	strbuf_t	tmp_buf;
+	
+	a_assert(s);
+	a_assert(fmt);
+
+	memset(&tmp_buf, 0, sizeof(tmp_buf));
+	tmp_buf.s = *s;
+
+	if (*s == NULL || msize != 0) {
+		tmp_buf.max = size;
+		tmp_buf.flags |= STR_REALLOC;
+		if (msize != 0) {
+			tmp_buf.size = max(msize, 0);
+		}
+		if (*s != NULL && msize != 0) {
+			tmp_buf.count = gstrlen(*s);
+		}
+	} else {
+		tmp_buf.size = size;
+	}
+
+	while ((tmp_c = *fmt++) != '\0') {
+		if (tmp_c != '%' || (tmp_c = *fmt++) == '%') {
+			put_char(&tmp_buf, tmp_c);
+		} else {
+			enum flag f = flag_none;
+			int width = 0;
+			int prec = -1;
+			for ( ; tmp_c != '\0'; tmp_c = *fmt++) {
+				if (tmp_c == '-') { 
+					f |= flag_minus; 
+				} else if (tmp_c == '+') { 
+					f |= flag_plus; 
+				} else if (tmp_c == ' ') { 
+					f |= flag_space; 
+				} else if (tmp_c == '#') { 
+					f |= flag_hash; 
+				} else if (tmp_c == '0') { 
+					f |= flag_zero; 
+				} else {
+					break;
+				}
+			}
+			if (tmp_c == '*') {
+				width = va_arg(arg, int);
+				if (width < 0) {
+					f |= flag_minus;
+					width = -width;
+				}
+				tmp_c = *fmt++;
+			} else {
+				for ( ; gisdigit((int)tmp_c); tmp_c = *fmt++) {
+					width = width * 10 + (tmp_c - '0');
+				}
+			}
+			if (tmp_c == '.') {
+				f &= ~flag_zero;
+				tmp_c = *fmt++;
+				if (tmp_c == '*') {
+					prec = va_arg(arg, int);
+					tmp_c = *fmt++;
+				} else {
+					for (prec = 0; gisdigit((int)tmp_c); tmp_c = *fmt++) {
+						prec = prec * 10 + (tmp_c - '0');
+					}
+				}
+			}
+			if (tmp_c == 'h' || tmp_c == 'l') {
+				f |= (tmp_c == 'h' ? flag_short : flag_long);
+				tmp_c = *fmt++;
+			}
+			if (tmp_c == 'd' || tmp_c == 'i') {
+				long int value;
+				if (f & flag_short) {
+					value = (short int) va_arg(arg, int);
+				} else if (f & flag_long) {
+					value = va_arg(arg, long int);
+				} else {
+					value = va_arg(arg, int);
+				}
+				if (value >= 0) {
+					if (f & flag_plus) {
+						put_ulong(&tmp_buf, value, 10, 0, T("+"), width, prec, f);
+					} else if (f & flag_space) {
+						put_ulong(&tmp_buf, value, 10, 0, T(" "), width, prec, f);
+					} else {
+						put_ulong(&tmp_buf, value, 10, 0, NULL, width, prec, f);
+					}
+				} else {
+					put_ulong(&tmp_buf, -value, 10, 0, T("-"), width, prec, f);
+				}
+			} else if (tmp_c == 'o' || tmp_c == 'u' || tmp_c == 'x' || tmp_c == 'X') {
+				unsigned long int value;
+				if (f & flag_short) {
+					value = (unsigned short int) va_arg(arg, unsigned int);
+				} else if (f & flag_long) {
+					value = va_arg(arg, unsigned long int);
+				} else {
+					value = va_arg(arg, unsigned int);
+				}
+				if (tmp_c == 'o') {
+					if (f & flag_hash && value != 0) {
+						put_ulong(&tmp_buf, value, 8, 0, T("0"), width, prec, f);
+					} else {
+						put_ulong(&tmp_buf, value, 8, 0, NULL, width, prec, f);
+					}
+				} else if (tmp_c == 'u') {
+					put_ulong(&tmp_buf, value, 10, 0, NULL, width, prec, f);
+				} else {
+					if (f & flag_hash && value != 0) {
+						if (tmp_c == 'x') {
+							put_ulong(&tmp_buf, value, 16, 0, T("0x"), width, prec, f);
+						} else {
+							put_ulong(&tmp_buf, value, 16, 1, T("0X"), width, prec, f);
+						}
+					} else {
+						put_ulong(&tmp_buf, value, 16, ('X' == tmp_c) , NULL, width, prec, f);
+					}
+				}
+
+			} else if (tmp_c == 'c') {
+				char_t value = va_arg(arg, int);
+				put_char(&tmp_buf, value);
+
+			} else if (tmp_c == 's' || tmp_c == 'S') {
+				char_t *value = va_arg(arg, char_t *);
+				if (value == NULL) {
+					put_string(&tmp_buf, T("(null)"), -1, width, prec, f);
+				} else if (f & flag_hash) {
+					put_string(&tmp_buf,
+						value + 1, (char_t) *value, width, prec, f);
+				} else {
+					put_string(&tmp_buf, value, -1, width, prec, f);
+				}
+			} else if (tmp_c == 'p') {
+				void *value = va_arg(arg, void *);
+				put_ulong(&tmp_buf,
+					(unsigned long int) value, 16, 0, T("0x"), width, prec, f);
+			} else if (tmp_c == 'n') {
+				if (f & flag_short) {
+					short int *value = va_arg(arg, short int *);
+					*value = tmp_buf.count;
+				} else if (f & flag_long) {
+					long int *value = va_arg(arg, long int *);
+					*value = tmp_buf.count;
+				} else {
+					int *value = va_arg(arg, int *);
+					*value = tmp_buf.count;
+				}
+			} else {
+				put_char(&tmp_buf, tmp_c);
+			}
+		}
+	}
+	if (tmp_buf.s == NULL) {
+		put_char(&tmp_buf, '\0');
+	}
+
+	if (*s == NULL || msize != 0) {
+		*s = tmp_buf.s;
+	}
+
+	if (*s != NULL && size > 0) {
+		if (tmp_buf.count < size) {
+			(*s)[tmp_buf.count] = '\0';
+		} else {
+			(*s)[tmp_buf.size - 1] = '\0';
+		}
+	}
+
+	if (msize != 0) {
+		return tmp_buf.size;
+	}
+	return tmp_buf.count;
+}
+
+static int strnlen(char_t *s, unsigned int n)
+{
+	unsigned int 	len;
+
+	len = gstrlen(s);
+	return min(len, n);
+}
+
+
+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)
+{
+	unsigned long	x, x2;
+	int				len, zeros, index;
+
+	for (len = 1, x = 1; x < ULONG_MAX / base; ++len, x = x2) {
+		x2 = x * base;
+		if (x2 > value) { 
+			break; 
+		}
+	}
+	zeros = (prec > len) ? prec - len : 0;
+	width -= zeros + len;
+	if (prefix != NULL) { 
+		width -= strnlen(prefix, ULONG_MAX); 
+	}
+	if (!(f & flag_minus)) {
+		if (f & flag_zero) {
+			for (index = 0; index < width; ++index) { 
+				put_char(buf, '0'); 
+			}
+		} else {
+			for (index = 0; index < width; ++index) { 
+				put_char(buf, ' '); 
+			}
+		}
+	}
+	if (prefix != NULL) { 
+		put_string(buf, prefix, -1, 0, -1, flag_none); 
+	}
+	for (index = 0; index < zeros; ++index) { 
+		put_char(buf, '0'); 
+	}
+	for ( ; x > 0; x /= base) {
+		int digit = (value / x) % base;
+		put_char(buf, (char)((digit < 10 ? '0' : (upper ? 'A' : 'a') - 10) + digit));
+	}
+	if (f & flag_minus) {
+		for (index = 0; index < width; ++index) { 
+			put_char(buf, ' '); 
+		}
+	}
+}
+
+char_t *ascToUni(char_t *ubuf, char *str, int nBytes)
+{
+    memcpy(ubuf, str, nBytes);
+	return ubuf;
+}
+
+
+char_t *ballocAscToUni(char *cp, int alen)
+{
+	char_t *unip;
+	int ulen;
+
+	ulen = (alen + 1) * sizeof(char_t);
+	if ((unip = balloc(B_L, ulen)) == NULL) {
+		return NULL;
+	}
+	ascToUni(unip, cp, ulen);
+	unip[alen] = 0;
+	return unip;
+}
+
+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;
+}
+
+char *uniToAsc(char *buf, char_t *ustr, int nBytes)
+{
+#ifdef UNICODE
+   if (WideCharToMultiByte(CP_ACP, 0, ustr, nBytes, buf, nBytes, 
+    NULL, NULL) < 0) 
+   {
+      return (char*) ustr;
+   }
+#else
+#ifdef kUseMemcopy
+   memcpy(buf, ustr, nBytes);
+#else
+   strncpy(buf, ustr, nBytes);
+#endif /* kUseMemcopy */
+#endif
+   return (char*) buf;
+}
+
+char *ballocUniToAsc(char_t *unip, int ulen)
+{
+	char * cp;
+
+	if ((cp = balloc(B_L, ulen+1)) == NULL) {
+		return NULL;
+	}
+	uniToAsc(cp, unip, ulen);
+	cp[ulen] = '\0';
+	return cp;
+}
+
+unsigned int gstrtoi(char_t *s)
+{
+	if (*s == '0' && (*(s+1) == 'x' || *(s+1) == 'X')) {
+		s += 2;
+		return hextoi(s);
+	}
+	return gatoi(s);
+}
+
diff --git a/ap/app/goahead/server/page.c b/ap/app/goahead/server/page.c
new file mode 100755
index 0000000..b5d7bf8
--- /dev/null
+++ b/ap/app/goahead/server/page.c
@@ -0,0 +1,219 @@
+#include "wsIntrn.h"
+#include <sys/stat.h> 
+#include <unistd.h>
+#ifdef _USE_WEBUI_ZIP
+#include "unzip.h"
+#define WEB_ZIP_PATH "etc_ro/web.zip"
+#define WEB_ZIP_PATH_HEAD "web/"
+#endif
+
+int websPageOpen(webs_t wp, char_t *lpath, char_t *path, int mode, int perm)
+{
+	a_assert(websValid(wp));
+
+#ifdef WEBS_PAGE_ROM
+	return websRomPageOpen(wp, path, mode, perm);
+#else
+#ifdef _USE_WEBUI_ZIP
+	char *filename = strstr(lpath,WEB_ZIP_PATH_HEAD);
+	if(filename != NULL)
+	{
+		unzFile uzFile = unzOpen(WEB_ZIP_PATH);
+		if(unzLocateFile(uzFile,filename,0) == UNZ_OK
+			&& unzOpenCurrentFile(uzFile) == UNZ_OK)
+		{
+			wp->docfd = uzFile;
+		}
+		else
+		{
+			unzClose(uzFile);
+			wp->docfd = -1;
+		}
+		return wp->docfd;
+	}
+	else
+	{
+		printf("[zpr]erropen %s\n", lpath);
+	}
+#endif
+	//printf("[httpshare]lpath->%s\n",lpath);
+
+	if(strstr(lpath,"/mmc2") != NULL)
+	{
+#if 0  // cov M
+		unsigned long filesize = -1; 
+#else
+        long filesize = -1; 
+#endif
+		struct stat statbuff;	
+		
+		if(stat(lpath, &statbuff) < 0)
+		{	 
+		   return filesize;    
+	    }
+		else
+		{	 
+	 	   filesize = statbuff.st_size;    
+	    }
+		
+		printf("[httpshare]websPageOpen:size->%d\n", filesize);
+
+#if 0	 // cov M	
+		if(filesize<2*1024*1024*1024)
+		{
+			return (wp->docfd = gopen(lpath, mode, perm));
+		}
+		else
+			return -1;
+#else
+		if(filesize > 0 && filesize <= LONG_MAX-1)
+		{
+			return (wp->docfd = gopen(lpath, mode, perm));
+		}
+		else
+			return -1;
+
+#endif
+	}
+
+	return (wp->docfd = gopen(lpath, mode, perm));
+#endif /* WEBS_PAGE_ROM */
+}
+
+void websPageClose(webs_t wp)
+{
+	a_assert(websValid(wp));
+
+#ifdef WEBS_PAGE_ROM
+	websRomPageClose(wp->docfd);
+#else
+#ifdef _USE_WEBUI_ZIP
+	if(wp->docfd > 0 && wp->lpath != NULL && strstr(wp->lpath,WEB_ZIP_PATH_HEAD) != NULL)
+	{
+		unzCloseCurrentFile(wp->docfd);
+		unzClose(wp->docfd);
+		wp->docfd = -1;
+		return;
+	}
+#endif	
+	if (wp->docfd >= 0) {
+		close(wp->docfd);
+		wp->docfd = -1;
+		//printf("[httpsahre]lpath->%s,path->%s\n",wp->lpath,wp->path);
+		if(strstr(wp->path,"/mmc2") != NULL)
+		{
+			zte_del_download_file();		
+		}
+	}
+#endif
+}
+
+int websPageStat(webs_t wp, char_t *lpath, char_t *path, websStatType* sbuf)
+{
+	if(lpath == NULL)
+		return -1;
+#ifdef WEBS_PAGE_ROM
+	return websRomPageStat(path, sbuf);
+#else
+#ifdef _USE_WEBUI_ZIP
+	if(strstr(lpath,WEB_ZIP_PATH_HEAD) != NULL)
+	{
+		unz_file_info file_info = {0};
+		if(unzGetCurrentFileInfo(wp->docfd, &file_info, NULL, 0, NULL, 0, NULL, 0)< 0)
+		{
+			printf("[webzip]errStat %s\n", lpath);
+			return -1;
+		}
+		sbuf->size = file_info.uncompressed_size;
+		sbuf->mtime = file_info.dosDate;
+		sbuf->isDir = websPageIsDirectory(lpath);
+		return 0;
+	}
+#endif
+	gstat_t	s;
+
+	if (gstat(lpath, &s) < 0) {
+		return -1;
+	}
+	sbuf->size = s.st_size;
+	sbuf->mtime = s.st_mtime;
+	sbuf->isDir = s.st_mode & S_IFDIR;
+	return 0;
+#endif
+}
+
+int websPageIsDirectory(char_t *lpath)
+{
+	if(lpath == NULL)
+		return 0;
+#ifdef WEBS_PAGE_ROM
+	websStatType	sbuf;
+
+	if (websRomPageStat(lpath, &sbuf) >= 0) {
+		return(sbuf.isDir);
+	} else {
+		return 0;
+	}
+#else
+#ifdef _USE_WEBUI_ZIP
+	if(strstr(lpath,WEB_ZIP_PATH_HEAD) != NULL)
+	{
+		char *p = lpath;
+		int is_dir = 0;
+		while ((*p) != '\0') {
+			p++;
+		}
+		p--;
+
+		if (((*p) == '/') || ((*p) == '\\')) {
+			is_dir = 1;
+		}
+		return is_dir;
+	}
+#endif
+	gstat_t sbuf;
+
+	if (gstat(lpath, &sbuf) >= 0) {
+		return(sbuf.st_mode & S_IFDIR);
+	} else {
+		return 0;
+	}
+#endif
+}
+
+int websPageReadData(webs_t wp, char *buf, int nBytes)
+{
+	a_assert(websValid(wp));
+#ifdef WEBS_PAGE_ROM
+	return websRomPageReadData(wp, buf, nBytes);
+#else
+#ifdef _USE_WEBUI_ZIP
+	if(wp->lpath != NULL && strstr(wp->lpath,WEB_ZIP_PATH_HEAD) != NULL)
+	{
+		return unzReadCurrentFile(wp->docfd, buf, nBytes);
+	}
+#endif
+	return read(wp->docfd, buf, nBytes);
+#endif
+}
+
+void websPageSeek(webs_t wp, long offset)
+{
+	a_assert(websValid(wp));
+#ifdef WEBS_PAGE_ROM
+	websRomPageSeek(wp, offset, SEEK_CUR);
+#else
+#ifdef _USE_WEBUI_ZIP
+	if(wp->lpath != NULL && strstr(wp->lpath,WEB_ZIP_PATH_HEAD) != NULL)
+	{
+		printf("[webzip]seek %s\n",wp->lpath);
+		return;
+	}
+#endif
+	if(lseek(wp->docfd, offset, SEEK_CUR) < 0)
+	{
+		return;	    
+	}
+#endif
+}
+
diff --git a/ap/app/goahead/server/ringq.c b/ap/app/goahead/server/ringq.c
new file mode 100755
index 0000000..e6ba5f3
--- /dev/null
+++ b/ap/app/goahead/server/ringq.c
@@ -0,0 +1,403 @@
+#ifdef UEMF
+	#include	"uemf.h"
+#else
+	#include	"basic/basicInternal.h"
+#endif
+
+static int	getBinBlockSize(int size);
+static int	ringqGrow(ringq_t *rq);
+
+#define RINGQ_LEN(rq) \
+	((rq->servp > rq->endp) ? \
+		(rq->buflen + (rq->endp - rq->servp)) : \
+		(rq->endp - rq->servp))
+
+
+
+int			ringqGrowCalls = 0;
+
+int ringqOpen(ringq_t *rq, int initSize, int maxsize)
+{
+	int	increment;
+
+	a_assert(rq);
+	a_assert(initSize >= 0);
+
+	increment = getBinBlockSize(initSize);
+	if ((rq->buf = balloc(B_L, (increment))) == NULL) {
+		return -1;
+	}
+	rq->maxsize = maxsize;
+	rq->buflen = increment;
+	rq->increment = increment;
+	rq->endbuf = &rq->buf[rq->buflen];
+	rq->servp = rq->buf;
+	rq->endp = rq->buf;
+	*rq->servp = '\0';
+	return 0;
+}
+
+int ringqInsertc(ringq_t *rq, char_t c)
+{
+	char_t *cp;
+
+	a_assert(rq);
+	a_assert(rq->buflen == (rq->endbuf - rq->buf));
+
+	if (ringqPutBlkMax(rq) < (int) sizeof(char_t) && !ringqGrow(rq)) {
+		return -1;
+	}
+	if (rq->servp <= rq->buf) {
+		rq->servp = rq->endbuf;
+	}
+	cp = (char_t*) rq->servp;
+	*--cp = (char_t) c;
+	rq->servp = (unsigned char *) cp;
+	return 0;
+}
+
+int ringqPutc(ringq_t *rq, char_t c)
+{
+	char_t *cp;
+
+	a_assert(rq);
+	a_assert(rq->buflen == (rq->endbuf - rq->buf));
+
+	if ((ringqPutBlkMax(rq) < (int) sizeof(char_t)) && !ringqGrow(rq)) {
+		return -1;
+	}
+
+	cp = (char_t*) rq->endp;
+	*cp++ = (char_t) c;
+	rq->endp = (unsigned char *) cp;
+	if (rq->endp >= rq->endbuf) {
+		rq->endp = rq->buf;
+	}
+	return 0;
+}
+
+int ringqGetc(ringq_t *rq)
+{
+	char_t	c;
+	char_t*	cp;
+
+	a_assert(rq);
+	a_assert(rq->buflen == (rq->endbuf - rq->buf));
+
+	if (rq->servp == rq->endp) {
+		return -1;
+	}
+
+	cp = (char_t*) rq->servp;
+	c = *cp++;
+	rq->servp = (unsigned char *) cp;
+	if (rq->servp >= rq->endbuf) {
+		rq->servp = rq->buf;
+	}
+	return (int) ((unsigned char) c);
+}
+
+int ringqLen(ringq_t *rq)
+{
+	a_assert(rq);
+	a_assert(rq->buflen == (rq->endbuf - rq->buf));
+
+	if (rq->servp > rq->endp) {
+		return rq->buflen + rq->endp - rq->servp;
+	} else {
+		return rq->endp - rq->servp;
+	}
+}
+
+void ringqAddNull(ringq_t *rq)
+{
+	a_assert(rq);
+	a_assert(rq->buflen == (rq->endbuf - rq->buf));
+
+	*((char_t*) rq->endp) = (char_t) '\0';
+}
+
+int ringqPutStr(ringq_t *rq, char_t *str)
+{
+	int		rc;
+
+	a_assert(rq);
+	a_assert(str);
+	a_assert(rq->buflen == (rq->endbuf - rq->buf));
+
+	rc = ringqPutBlk(rq, (unsigned char*) str, gstrlen(str) * sizeof(char_t));
+	*((char_t*) rq->endp) = (char_t) '\0';
+	return rc;
+}
+
+
+void ringqClose(ringq_t *rq)
+{
+	a_assert(rq);
+	a_assert(rq->buflen == (rq->endbuf - rq->buf));
+
+	if (rq == NULL) {
+		return;
+	}
+
+	ringqFlush(rq);
+	bfree(B_L, (char*) rq->buf);
+	rq->buf = NULL;
+}
+
+
+void ringqFlush(ringq_t *rq)
+{
+	a_assert(rq);
+	a_assert(rq->servp);
+
+	rq->servp = rq->buf;
+	rq->endp = rq->buf;
+	if (rq->servp) {
+		*rq->servp = '\0';
+	}
+}
+
+
+#ifdef UNICODE
+int ringqPutStrA(ringq_t *rq, char *str)
+{
+	int		rc;
+
+	a_assert(rq);
+	a_assert(str);
+	a_assert(rq->buflen == (rq->endbuf - rq->buf));
+
+	rc = ringqPutBlk(rq, (unsigned char*) str, strlen(str));
+	rq->endp[0] = '\0';
+	return rc;
+}
+
+int ringqGetcA(ringq_t *rq)
+{
+	unsigned char	c;
+
+	a_assert(rq);
+	a_assert(rq->buflen == (rq->endbuf - rq->buf));
+
+	if (rq->servp == rq->endp) {
+		return -1;
+	}
+
+	c = *rq->servp++;
+	if (rq->servp >= rq->endbuf) {
+		rq->servp = rq->buf;
+	}
+	return c;
+}
+
+int ringqInsertcA(ringq_t *rq, char c)
+{
+	a_assert(rq);
+	a_assert(rq->buflen == (rq->endbuf - rq->buf));
+
+	if (ringqPutBlkMax(rq) == 0 && !ringqGrow(rq)) {
+		return -1;
+	}
+	if (rq->servp <= rq->buf) {
+		rq->servp = rq->endbuf;
+	}
+	*--rq->servp = (unsigned char) c;
+	return 0;
+}
+
+int ringqPutcA(ringq_t *rq, char c)
+{
+	a_assert(rq);
+	a_assert(rq->buflen == (rq->endbuf - rq->buf));
+
+	if (ringqPutBlkMax(rq) == 0 && !ringqGrow(rq)) {
+		return -1;
+	}
+
+	*rq->endp++ = (unsigned char) c;
+	if (rq->endp >= rq->endbuf) {
+		rq->endp = rq->buf;
+	}
+	return 0;
+}
+
+#endif /* UNICODE */
+
+void ringqGetBlkAdj(ringq_t *rq, int size)
+{
+	a_assert(rq);
+	a_assert(rq->buflen == (rq->endbuf - rq->buf));
+	a_assert(0 < size && size < rq->buflen);
+
+	rq->servp += size;
+	if (rq->servp >= rq->endbuf) {
+		rq->servp -= rq->buflen;
+	}
+
+	if (rq->servp >= rq->endbuf) {
+		error(E_L, E_LOG, T("Bad serv pointer"));
+		ringqFlush(rq);
+	}
+}
+
+int ringqGetBlkMax(ringq_t *rq)
+{
+	int		len, in_a_line;
+
+	a_assert(rq);
+	a_assert(rq->buflen == (rq->endbuf - rq->buf));
+
+	len = RINGQ_LEN(rq);
+	in_a_line = rq->endbuf - rq->servp;
+
+	return min(in_a_line, len);
+}
+
+int ringqGetBlk(ringq_t *rq, unsigned char *buf, int size)
+{
+	int		this, bytes_read;
+
+	a_assert(rq);
+	a_assert(rq->buflen == (rq->endbuf - rq->buf));
+	a_assert(buf);
+	a_assert(0 <= size && size < rq->buflen);
+
+	bytes_read = 0;
+	while (size > 0) {
+		this = ringqGetBlkMax(rq);
+		this = min(this, size);
+		if (this <= 0) {
+			break;
+		}
+
+		memcpy(buf, rq->servp, this);
+		buf += this;
+		rq->servp += this;
+		size -= this;
+		bytes_read += this;
+
+		if (rq->servp >= rq->endbuf) {
+			rq->servp = rq->buf;
+		}
+	}
+	return bytes_read;
+}
+
+int ringqPutBlk(ringq_t *rq, unsigned char *buf, int size)
+{
+	int		this, bytes_put;
+
+	a_assert(rq);
+	a_assert(rq->buflen == (rq->endbuf - rq->buf));
+	a_assert(buf);
+	a_assert(0 <= size);
+
+	bytes_put = 0;
+	while (size > 0) {
+		this = min(ringqPutBlkMax(rq), size);
+		if (this <= 0) {
+			if (! ringqGrow(rq)) {
+				break;
+			}
+			this = min(ringqPutBlkMax(rq), size);
+		}
+
+		memcpy(rq->endp, buf, this);
+		buf += this;
+		rq->endp += this;
+		size -= this;
+		bytes_put += this;
+
+		if (rq->endp >= rq->endbuf) {
+			rq->endp = rq->buf;
+		}
+	}
+	return bytes_put;
+}
+
+
+int ringqPutBlkMax(ringq_t *rq)
+{
+	int		space, in_a_line;
+
+	a_assert(rq);
+	a_assert(rq->buflen == (rq->endbuf - rq->buf));
+	
+	space = rq->buflen - RINGQ_LEN(rq) - 1;
+	in_a_line = rq->endbuf - rq->endp;
+
+	return min(in_a_line, space);
+}
+
+
+void ringqPutBlkAdj(ringq_t *rq, int size)
+{
+	a_assert(rq);
+	a_assert(rq->buflen == (rq->endbuf - rq->buf));
+	a_assert(0 <= size && size < rq->buflen);
+
+	rq->endp += size;
+	if (rq->endp >= rq->endbuf) {
+		rq->endp -= rq->buflen;
+	}
+
+	if (rq->endp >= rq->endbuf) {
+		error(E_L, E_LOG, T("Bad end pointer"));
+		ringqFlush(rq);
+	}
+}
+
+
+
+static int ringqGrow(ringq_t *rq)
+{
+	int 			rq_len;
+	unsigned char	*reall_buf;
+
+
+	a_assert(rq);
+
+	if (rq->maxsize >= 0 && rq->buflen >= rq->maxsize) {
+		return 0;
+	}
+
+	rq_len = ringqLen(rq);
+
+	if ((reall_buf = balloc(B_L, rq->buflen + rq->increment)) == NULL) {
+		return 0;
+	}
+	ringqGetBlk(rq, reall_buf, ringqLen(rq));
+	bfree(B_L, (char*) rq->buf);
+
+#ifdef OLD
+	rq->endp = &reall_buf[endp];
+	rq->servp = &reall_buf[servp];
+	rq->endbuf = &reall_buf[rq->buflen];
+	rq->buf = reall_buf;
+#endif
+
+	rq->buflen += rq->increment;
+	rq->endp = reall_buf;
+	rq->servp = reall_buf;
+	rq->buf = reall_buf;
+	rq->endbuf = &rq->buf[rq->buflen];
+
+	ringqPutBlk(rq, reall_buf, rq_len);
+
+	rq->increment = getBinBlockSize(2 * rq->increment);
+
+	return 1;
+}
+
+static int	getBinBlockSize(int size)
+{
+	int	q;
+
+	size = size >> B_SHIFT;
+	for (q = 0; size; size >>= 1) {
+		q++;
+	}
+	return (1 << (B_SHIFT + q));
+}
+
diff --git a/ap/app/goahead/server/sock.c b/ap/app/goahead/server/sock.c
new file mode 100755
index 0000000..1990f71
--- /dev/null
+++ b/ap/app/goahead/server/sock.c
@@ -0,0 +1,499 @@
+#include	<string.h>
+#include	<stdlib.h>
+
+#ifdef UEMF
+	#include	"uemf.h"
+#else
+	#include	<socket.h>
+	#include	<types.h>
+	#include	<unistd.h>
+	#include	"emfInternal.h"
+#endif
+
+static int	socketDoOutput(socket_t *sp, char *buf, int toWrite, int *errCode);
+static int	tryAlternateSendTo(int sock, char *buf, int toWrite, int i,
+			struct sockaddr *server);
+
+int 		socketHighestFd = -1;	
+
+socket_t	**socketList;			
+int			socketMax;				
+
+
+int	socketWriteString(int sid, char_t *buf)
+{
+ #ifdef UNICODE
+ 	char	*byteBuf;
+ 	int		r, buf_len;
+ 
+ 	buf_len = gstrlen(buf);
+ 	byteBuf = ballocUniToAsc(buf, buf_len);
+ 	r = socketWrite(sid, byteBuf, buf_len);
+ 	bfreeSafe(B_L, byteBuf);
+ 	return r;
+ #else
+ 	return socketWrite(sid, buf, strlen(buf));
+ #endif /* UNICODE */
+}
+
+
+int	socketWrite(int sid, char *buf, int bufsize)
+{
+	socket_t	*sp;
+	ringq_t		*rq;
+	int			buf_len, bytesWritten, room;
+
+	a_assert(buf);
+	a_assert(bufsize >= 0);
+
+	if ((sp = socketPtr(sid)) == NULL) {
+		return -1;
+	}
+
+	rq = &sp->outBuf;
+	for (bytesWritten = 0; bufsize > 0; ) {
+		if ((room = ringqPutBlkMax(rq)) == 0) {
+			if (socketFlush(sid) < 0) {
+				return -1;
+			}
+			if ((room = ringqPutBlkMax(rq)) == 0) {
+				if (sp->flags & SOCKET_BLOCK) {
+#if (defined (WIN) || defined (CE))
+					int		errCode;
+					if (! socketWaitForEvent(sp,  FD_WRITE | SOCKET_WRITABLE, &errCode)) {
+						return -1;
+					}
+#endif
+					continue;
+				}
+				break;
+			}
+			continue;
+		}
+		buf_len = min(room, bufsize);
+		ringqPutBlk(rq, (unsigned char *) buf, buf_len);
+		bytesWritten += buf_len;
+		bufsize -= buf_len;
+		buf += buf_len;
+	}
+	return bytesWritten;
+}
+
+
+int	socketRead(int sid, char *buf, int bufsize)
+{
+	socket_t	*sp;
+	ringq_t		*rq;
+	int			buf_len, room, errCode, bytesRead;
+
+	a_assert(buf);
+	a_assert(bufsize > 0);
+
+	if ((sp = socketPtr(sid)) == NULL) {
+		return -1;
+	}
+
+	if (sp->flags & SOCKET_EOF) {
+		return 0;
+	}
+
+	rq = &sp->inBuf;
+	for (bytesRead = 0; bufsize > 0; ) {
+		buf_len = min(ringqLen(rq), bufsize);
+		if (buf_len <= 0) {
+
+			if ((sp->flags & SOCKET_BLOCK) &&
+				(bytesRead > 0)) {
+				break;
+			}
+
+			ringqFlush(rq);
+			room = ringqPutBlkMax(rq);
+			buf_len = socketGetInput(sid, (char *) rq->endp, room, &errCode);
+			if (buf_len < 0) {
+				if (errCode == EWOULDBLOCK) {
+					if ((sp->flags & SOCKET_BLOCK) &&
+						(bytesRead ==  0)) {
+						continue;
+					}
+//					if (bytesRead >= 0) {  // kw 3 ;  bytesRead>=0 always be true
+						return bytesRead;
+//					}
+				}
+				return -1;
+
+			} else if (buf_len == 0) {
+
+				if (bytesRead == 0) {
+					sp->flags |= SOCKET_EOF;
+				}
+				return bytesRead;
+			}
+			ringqPutBlkAdj(rq, buf_len);
+			buf_len = min(buf_len, bufsize);
+		}
+		memcpy(&buf[bytesRead], rq->servp, buf_len);
+		ringqGetBlkAdj(rq, buf_len);
+		bufsize -= buf_len;
+		bytesRead += buf_len;
+	}
+	return bytesRead;
+}
+
+int socketFlush(int sid)
+{
+	socket_t	*sp;
+	ringq_t		*rq;
+	int			rq_len, bytesWritten, errCode;
+	int         errEINTRNum = 0; /* myp: ÓÃÓÚ¹æ±Üsocket´íÎó */
+
+	if ((sp = socketPtr(sid)) == NULL) {
+		return -1;
+	}
+	rq = &sp->outBuf;
+
+	if (! (sp->flags & SOCKET_BLOCK)) {
+		sp->flags |= SOCKET_FLUSHING;
+	}
+
+	while (ringqLen(rq) > 0) {
+		rq_len = ringqGetBlkMax(&sp->outBuf);
+		bytesWritten = socketDoOutput(sp, (char*) rq->servp, rq_len, &errCode);
+		if (bytesWritten < 0) {
+			if (errCode == EINTR && errEINTRNum++ < 1000) {
+				continue;
+//			} else if (errCode == EWOULDBLOCK || errCode == EAGAIN) { kw 3   // #define	EWOULDBLOCK	EAGAIN
+            } else if (errCode == EAGAIN) {
+				if (sp->saveMask < 0 ) {
+					sp->saveMask = sp->handlerMask;
+					socketRegisterInterest(sp, 
+					sp->handlerMask | SOCKET_WRITABLE);
+				}
+				return 0;
+			}
+			return -1;
+		}
+		ringqGetBlkAdj(rq, bytesWritten);
+	}
+
+	if (ringqLen(rq) == 0) {
+		ringqFlush(rq);
+	}
+
+	if (sp->saveMask >= 0) {
+		socketRegisterInterest(sp, sp->saveMask);
+		sp->saveMask = -1;
+	}
+	sp->flags &= ~SOCKET_FLUSHING;
+	return 0;
+}
+
+int	socketGets(int sid, char_t **buf)
+{
+	socket_t	*sp;
+	ringq_t		*lq;
+	char		c = '\0'; //cov
+	int			rc, rq_len;
+
+	a_assert(buf);
+	*buf = NULL;
+
+	if ((sp = socketPtr(sid)) == NULL) {
+		return -1;
+	}
+	lq = &sp->lineBuf;
+
+	while (ringqLen(lq) < 1536) {
+
+		if ((rc = socketRead(sid, &c, 1)) < 0) {
+			return rc;
+		}
+		
+		if (rc == 0) {
+			if (ringqLen(lq) > 0 && (sp->flags & SOCKET_EOF)) {
+				c = '\n';
+			} else {
+				return -1;
+			}
+		}
+
+		if (c == '\n') {
+			rq_len = ringqLen(lq);
+			if (rq_len > 0) {
+				*buf = ballocAscToUni((char *)lq->servp, rq_len);
+			} else {
+				*buf = NULL;
+			}
+			ringqFlush(lq);
+			return rq_len;
+
+		} else if (c == '\r') {
+			continue;
+		}
+		ringqPutcA(lq, c);
+	}
+	ringqFlush(lq);
+	return -1;
+}
+
+
+int socketInputBuffered(int sid)
+{
+	socket_t	*sp;
+
+	if ((sp = socketPtr(sid)) == NULL) {
+		return -1;
+	}
+	if (socketEof(sid)) {
+		return -1;
+	}
+	return ringqLen(&sp->lineBuf) + ringqLen(&sp->inBuf);
+}
+
+int socketEof(int sid)
+{
+	socket_t	*sp;
+
+	if ((sp = socketPtr(sid)) == NULL) {
+		return -1;
+	}
+	return sp->flags & SOCKET_EOF;
+}
+
+void socketCreateHandler(int sid, int handlerMask, socketHandler_t handler, 
+		int data)
+{
+	socket_t	*sp;
+
+	if ((sp = socketPtr(sid)) == NULL) {
+		return;
+	}
+	sp->handler = handler;
+	sp->handler_data = data;
+	socketRegisterInterest(sp, handlerMask);
+}
+
+static int socketDoOutput(socket_t *sp, char *buf, int toWrite, int *errCode)
+{
+	struct sockaddr_in	server;
+	int					bytes;
+
+	a_assert(sp);
+	a_assert(buf);
+	a_assert(toWrite > 0);
+	a_assert(errCode);
+
+	*errCode = 0;
+
+	if (sp->flags & SOCKET_BROADCAST) {
+		server.sin_family = AF_INET;
+		server.sin_addr.s_addr = INADDR_BROADCAST;
+		server.sin_port = htons((short)(sp->port & 0xFFFF));
+		bytes = sendto(sp->sock, buf, toWrite, 0,(struct sockaddr *) &server, sizeof(server));
+	} else if (sp->flags & SOCKET_DATAGRAM) {
+		server.sin_family = AF_INET;
+		server.sin_addr.s_addr = inet_addr(sp->host);
+		server.sin_port = htons((short)(sp->port & 0xFFFF));
+		bytes = sendto(sp->sock, buf, toWrite, 0,(struct sockaddr *) &server, sizeof(server));
+
+	} else {
+		bytes = send(sp->sock, buf, toWrite, 0);
+	}
+
+	if (bytes < 0) {
+		*errCode = socketGetError();
+        //printf("\n socketDoOutput ERROR: bytes = %d, *errCode = %d! ", bytes, *errCode);
+		return -1;
+
+	} else if (bytes == 0 && bytes != toWrite) {
+		*errCode = EWOULDBLOCK;
+        //printf("\n socketDoOutput ERROR: bytes = %d, *errCode = %d! ", bytes, *errCode);
+		return -1;
+	}
+
+	return bytes;
+}
+
+void socketDeleteHandler(int sid)
+{
+	socket_t	*sp;
+
+	if ((sp = socketPtr(sid)) == NULL) {
+		return;
+	}
+	sp->handler = NULL;
+	socketRegisterInterest(sp, 0);
+}
+
+int socketAlloc(char *host, int port, socketAccept_t accept, int flags)
+{
+	socket_t	*sp;
+	int			sid;
+
+	if ((sid = hAllocEntry((void***) &socketList, &socketMax,
+			sizeof(socket_t))) < 0) {
+		return -1;
+	}
+	sp = socketList[sid];
+
+	sp->sid = sid;
+	sp->accept = accept;
+	sp->port = port;
+	sp->fileHandle = -1;
+	sp->saveMask = -1;
+
+	if (host) {
+		strncpy(sp->host, host, sizeof(sp->host)-1);
+	}
+
+	a_assert((flags & ~(SOCKET_BROADCAST|SOCKET_DATAGRAM|SOCKET_BLOCK|
+						SOCKET_LISTENING)) == 0);
+	sp->flags = flags & (SOCKET_BROADCAST | SOCKET_DATAGRAM | SOCKET_BLOCK|
+						SOCKET_LISTENING);
+
+
+	ringqOpen(&sp->inBuf, SOCKET_BUFSIZ, SOCKET_BUFSIZ);
+	ringqOpen(&sp->outBuf, SOCKET_BUFSIZ + 1, SOCKET_BUFSIZ + 1);
+	ringqOpen(&sp->lineBuf, SOCKET_BUFSIZ, -1);
+
+	return sid;
+}
+
+void socketFree(int sid)
+{
+	socket_t	*sp;
+	char_t		buf[256];
+	int			i;
+	int recv_len = -1;
+
+	if ((sp = socketPtr(sid)) == NULL) {
+		return;
+	}
+
+	socketRegisterInterest(sp, 0);
+	if (sp->sock >= 0) {
+		socketSetBlock(sid, 0);
+		if (shutdown(sp->sock, 1) >= 0) {
+			recv_len = recv(sp->sock, buf, sizeof(buf), 0);
+			if(recv_len < 0){
+				;
+			}else if(recv_len == 0){
+				// ÕâÀï±íʾ¶Ô¶ËµÄsocketÒÑÕý³£¹Ø±Õ?
+				;
+			}else if(recv_len == sizeof(buf)){
+				;
+			}else{
+				;// ÐèÒªÔٴζÁÈ¡
+			}
+		}
+#if (defined (WIN) || defined (CE))
+		closesocket(sp->sock);
+#else
+		close(sp->sock);
+#endif
+	}
+
+	ringqClose(&sp->inBuf);
+	ringqClose(&sp->outBuf);
+	ringqClose(&sp->lineBuf);
+
+	bfree(B_L, sp);
+	socketMax = hFree((void***) &socketList, sid);
+
+	socketHighestFd = -1;
+	for (i = 0; i < socketMax; i++) {
+		if ((sp = socketList[i]) == NULL) {
+			continue;
+		} 
+		socketHighestFd = max(socketHighestFd, sp->sock);
+	}
+}
+
+
+int socketGetError()
+{
+#if (defined (WIN) || defined (CE))
+	switch (WSAGetLastError()) {
+	case WSAEWOULDBLOCK:
+		return EWOULDBLOCK;
+	case WSAECONNRESET:
+		return ECONNRESET;
+	case WSAENETDOWN:
+		return ENETDOWN;
+	case WSAEPROCLIM:
+		return EAGAIN;
+	case WSAEINTR:
+		return EINTR;
+	default:
+		return EINVAL;
+	}
+#else
+	return errno;
+#endif
+}
+
+socket_t *socketPtr(int sid)
+{
+	if (sid < 0 || sid >= socketMax || socketList[sid] == NULL) {
+		a_assert(NULL);
+		errno = EBADF;
+		return NULL;
+	}
+
+	a_assert(socketList[sid]);
+	return socketList[sid];
+}
+
+int socketGetHandle(int sid)
+{
+	socket_t	*sp;
+
+	if ((sp = socketPtr(sid)) == NULL) {
+		return -1;
+	}
+	return sp->sock;
+}
+
+int socketGetBlock(int sid)
+{
+	socket_t	*sp;
+
+	if ((sp = socketPtr(sid)) == NULL) {
+		a_assert(0);
+		return 0;
+	}
+	return (sp->flags & SOCKET_BLOCK);
+}
+
+int socketGetMode(int sid)
+{
+	socket_t	*sp;
+
+	if ((sp = socketPtr(sid)) == NULL) {
+		a_assert(0);
+		return 0;
+	}
+	return sp->flags;
+}
+
+void socketSetMode(int sid, int mode)
+{
+	socket_t	*sp;
+
+	if ((sp = socketPtr(sid)) == NULL) {
+		a_assert(0);
+		return;
+	}
+	sp->flags = mode;
+}
+
+int socketGetPort(int sid)
+{
+	socket_t	*sp;
+
+	if ((sp = socketPtr(sid)) == NULL) {
+		return -1;
+	}
+	return sp->port;
+}
+
diff --git a/ap/app/goahead/server/sockGen.c b/ap/app/goahead/server/sockGen.c
new file mode 100755
index 0000000..8e3292c
--- /dev/null
+++ b/ap/app/goahead/server/sockGen.c
@@ -0,0 +1,522 @@
+#include	<errno.h>
+#include	<fcntl.h>
+#include	<string.h>
+#include	<stdlib.h>
+#include	"uemf.h"
+#include "softap_log.h"
+
+extern socket_t		**socketList;			
+extern int			socketMax;				
+extern int			socketHighestFd;		
+static int			socketOpenCount = 0;	
+
+static void socketAccept(socket_t *sp);
+static int 	socketDoEvent(socket_t *sp);
+static int	tryAlternateConnect(int sock, struct sockaddr *sockaddr);
+
+int socketOpen()
+{
+	if (++socketOpenCount > 1) {
+		return 0;
+	}
+	socketList = NULL;
+	socketMax = 0;
+	socketHighestFd = -1;
+
+	return 0;
+}
+
+int socketWaitForEvent(socket_t *sp, int handlerMask, int *errCode)
+{
+	int	mask;
+
+	a_assert(sp);
+
+	mask = sp->handlerMask;
+	sp->handlerMask |= handlerMask;
+	while (socketSelect(sp->sid, 1000)) {
+		if (sp->currentEvents & (handlerMask | SOCKET_EXCEPTION)) {
+			break;
+		}
+	}
+	sp->handlerMask = mask;
+	if (sp->currentEvents & SOCKET_EXCEPTION) {
+		return -1;
+	} else if (sp->currentEvents & handlerMask) {
+		return 1;
+	}
+	if (errCode) {
+		*errCode = errno = EWOULDBLOCK;
+	}
+	return 0;
+}
+
+void socketClose()
+{
+	int		i;
+
+	if (--socketOpenCount <= 0) {
+		for (i = socketMax; i >= 0; i--) {
+			if (socketList && socketList[i]) {
+				socketCloseConnection(i);
+			}
+		}
+		socketOpenCount = 0;
+	}
+}
+
+int socketOpenConnection6(char *host, int port, socketAccept_t accept, int flags)
+{
+	socket_t			*sp;
+	struct sockaddr_in6	sockaddr;
+	int					sid, dgram, rc;
+	if (port > SOCKET_PORT_MAX) {
+		return -1;
+	}
+	if ((sid = socketAlloc(NULL, port, accept, flags)) < 0) {
+		return -1;
+	}
+	sp = socketList[sid];
+	a_assert(sp);
+	memset((char *) &sockaddr, '\0', sizeof(struct sockaddr_in6));
+	sockaddr.sin6_family = AF_INET6;
+	sockaddr.sin6_port = htons((short) (port & 0xFFFF));
+	dgram = sp->flags & SOCKET_DATAGRAM;
+	sp->sock = socket(AF_INET6, dgram ? SOCK_DGRAM: SOCK_STREAM, 0);
+	if (sp->sock < 0) {
+		socketFree(sid);
+		return -1;
+	}
+	if(fcntl(sp->sock, F_SETFD, FD_CLOEXEC) < 0)
+	{
+		slog(MISC_PRINT,SLOG_ERR, "fcntl return -1.\n");
+	}
+
+	socketHighestFd = max(socketHighestFd, sp->sock);
+	rc = 1;
+	// cov 3 CHECKED_RETURN
+	if(setsockopt(sp->sock, SOL_SOCKET, SO_REUSEADDR, (char *)&rc, sizeof(rc)) < 0){
+        ;
+	}
+	if (bind(sp->sock, (struct sockaddr *) &sockaddr, 
+			sizeof(sockaddr)) < 0) {
+		socketFree(sid);
+		return -1;
+	}
+
+	if (! dgram) {
+		if (listen(sp->sock, SOMAXCONN) < 0) {
+			socketFree(sid);
+			return -1;
+		}
+
+		sp->flags |= SOCKET_LISTENING;
+	}
+	sp->handlerMask |= SOCKET_READABLE;
+
+	if (flags & SOCKET_BLOCK) {
+		socketSetBlock(sid, 1);
+	} else {
+		socketSetBlock(sid, 0);
+	}
+	return sid;
+}
+
+void socketCloseConnection(int sid)
+{
+	socket_t	*sp;
+
+	if ((sp = socketPtr(sid)) == NULL) {
+		return;
+	}
+	socketFree(sid);
+}
+
+static void socketAccept(socket_t *sp)
+{
+	struct sockaddr_in6	addr;
+	//socket_t 			*nsp;
+	size_t				len;
+	char				pString[40]={0};
+	int 				newSock, nid;
+
+	a_assert(sp);
+	len = sizeof(struct sockaddr_in6);
+	if ((newSock = accept(sp->sock, (struct sockaddr *) &addr, (int *) &len)) < 0) {
+		return;
+	}
+	if(fcntl(newSock, F_SETFD, FD_CLOEXEC) < 0)
+	{
+		slog(MISC_PRINT,SLOG_ERR, "fcntl return -1.\n");
+	}
+	socketHighestFd = max(socketHighestFd, newSock);
+
+	nid = socketAlloc(sp->host, sp->port, sp->accept, sp->flags);
+	//nsp = socketList[nid];
+	a_assert(socketList[nid]);
+	if (socketList[nid] == NULL) {
+		close(newSock);
+		return;
+	}
+	socketList[nid]->sock = newSock;
+	socketList[nid]->flags &= ~SOCKET_LISTENING;
+
+	socketSetBlock(nid, (socketList[nid]->flags & SOCKET_BLOCK) ? 1: 0);
+
+	if (sp->accept != NULL) {
+		//pString = inet_ntoa(addr);
+		if(addr.sin6_addr.s6_addr32[0] == 0
+			&& addr.sin6_addr.s6_addr32[1] == 0
+			&& addr.sin6_addr.s6_addr32[2] == 0xffff0000)
+			inet_ntop(AF_INET,(void*)&addr.sin6_addr.s6_addr32[3],pString,sizeof(pString));
+		else
+			inet_ntop(AF_INET6,(void*)&addr.sin6_addr,pString,sizeof(pString));
+		if ((sp->accept)(nid, pString, ntohs(addr.sin6_port), sp->sid) < 0) {
+			socketFree(nid);
+		}
+	}
+	else
+		socketFree(nid);
+}
+
+int socketGetInput(int sid, char *buf, int toRead, int *errCode)
+{
+	struct sockaddr_in 	server;
+	socket_t			*sp;
+	int 				len, bytesRead;
+    static int          s_ErrorCnt = 0;
+	a_assert(buf);
+	a_assert(errCode);
+
+	*errCode = 0;
+
+	if ((sp = socketPtr(sid)) == NULL) {
+		return -1;
+	}
+
+	if (sp->flags & SOCKET_EOF) {
+		return 0;
+	}
+	if (sp->flags & SOCKET_DATAGRAM) {
+		len = sizeof(server);
+		bytesRead = recvfrom(sp->sock, buf, toRead, 0,
+			(struct sockaddr *) &server, &len);
+	} else {
+		bytesRead = recv(sp->sock, buf, toRead, 0);
+	}
+   
+    if (bytesRead < 0) 
+    {
+        *errCode = socketGetError();
+        //printf("\n socketGetInput ERROR: bytesRead = %d, *errCode = %d! ", bytesRead, *errCode);
+        if (*errCode == ECONNRESET || s_ErrorCnt++ > 500) 
+        {
+            sp->flags |= SOCKET_CONNRESET;
+            return 0;
+        }
+        return -1;
+    }
+    else
+    {
+        s_ErrorCnt = 0;
+    }
+	return bytesRead;
+}
+
+void socketRegisterInterest(socket_t *sp, int handlerMask)
+{
+	a_assert(sp);
+
+	sp->handlerMask = handlerMask;
+}
+
+int socketReady(int sid)
+{
+	socket_t 	*sp;
+	int			all;
+
+	all = 0;
+	if (sid < 0) {
+		sid = 0;
+		all = 1;
+	}
+
+	for (; sid < socketMax; sid++) {
+		if ((sp = socketList[sid]) == NULL) {
+			if (! all) {
+				break;
+			} else {
+				continue;
+			}
+		} 
+		if (sp->flags & SOCKET_CONNRESET) {
+			socketCloseConnection(sid);
+			return 0;
+		}
+		if (sp->currentEvents & sp->handlerMask) {
+			return 1;
+		}
+
+		if (sp->handlerMask & SOCKET_READABLE && socketInputBuffered(sid) > 0) {
+			socketSelect(sid, 0);
+			return 1;
+		}
+		if (! all) {
+			break;
+		}
+	}
+	return 0;
+}
+
+int socketSelect(int sid, int timeout)
+{
+	socket_t		*sp;
+	struct timeval	tv;
+	fd_mask 		*readFds, *writeFds, *exceptFds;
+	int 			all, len, nwords, index, bit, nEvents;
+
+	nwords = (socketHighestFd + NFDBITS) / NFDBITS;
+	len = nwords * sizeof(int);
+
+	readFds = balloc(B_L, len);
+	if(readFds == NULL)
+		return 0;
+	memset(readFds, 0, len);
+	writeFds = balloc(B_L, len);
+	if(writeFds == NULL){
+		bfree(B_L, readFds);
+		return 0;
+	}
+	memset(writeFds, 0, len);
+	exceptFds = balloc(B_L, len);
+	if(exceptFds == NULL){
+		bfree(B_L, readFds);
+		bfree(B_L, writeFds);
+		return 0;
+	}
+	memset(exceptFds, 0, len);
+
+	tv.tv_sec = timeout / 1000;
+	tv.tv_usec = (timeout % 1000) * 1000;
+
+	all = nEvents = 0;
+
+	if (sid < 0) {
+		all++;
+		sid = 0;
+	}
+
+	for (; sid < socketMax; sid++) {
+		if ((sp = socketList[sid]) == NULL) {
+			if (all == 0) {
+				break;
+			} else {
+				continue;
+			}
+		}
+		a_assert(sp);
+
+		index = sp->sock / (NBBY * sizeof(fd_mask));
+		bit = 1 << (sp->sock % (NBBY * sizeof(fd_mask)));
+		
+		if (sp->handlerMask & SOCKET_READABLE) {
+			readFds[index] |= bit;
+			nEvents++;
+			if (socketInputBuffered(sid) > 0) {
+				tv.tv_sec = 0;
+				tv.tv_usec = 0;
+			}
+		}
+		if (sp->handlerMask & SOCKET_WRITABLE) {
+			writeFds[index] |= bit;
+			nEvents++;
+		}
+		if (sp->handlerMask & SOCKET_EXCEPTION) {
+			exceptFds[index] |= bit;
+			nEvents++;
+		}
+		if (! all) {
+			break;
+		}
+	}
+
+	nEvents = select(socketHighestFd + 1, (fd_set *) readFds,
+		(fd_set *) writeFds, (fd_set *) exceptFds, &tv);
+
+	if (nEvents > 0) {
+		if (all) {
+			sid = 0;
+		}
+		for (; sid < socketMax; sid++) {
+			if ((sp = socketList[sid]) == NULL) {
+				if (all == 0) {
+					break;
+				} else {
+					continue;
+				}
+			}
+
+			index = sp->sock / (NBBY * sizeof(fd_mask));
+			bit = 1 << (sp->sock % (NBBY * sizeof(fd_mask)));
+
+			if (readFds[index] & bit || socketInputBuffered(sid) > 0) {
+				sp->currentEvents |= SOCKET_READABLE;
+			}
+			if (writeFds[index] & bit) {
+				sp->currentEvents |= SOCKET_WRITABLE;
+			}
+			if (exceptFds[index] & bit) {
+				sp->currentEvents |= SOCKET_EXCEPTION;
+			}
+			if (! all) {
+				break;
+			}
+		}
+	}
+
+	bfree(B_L, readFds);
+	bfree(B_L, writeFds);
+	bfree(B_L, exceptFds);
+
+	return nEvents;
+}
+
+void socketProcess(int sid)
+{
+	socket_t	*sp;
+	int			all;
+
+	all = 0;
+	if (sid < 0) {
+		all = 1;
+		sid = 0;
+	}
+	for (; sid < socketMax; sid++) {
+		if ((sp = socketList[sid]) == NULL) {
+			if (! all) {
+				break;
+			} else {
+				continue;
+			}
+		}
+		if (socketReady(sid)) {
+			socketDoEvent(sp);
+		}
+		if (! all) {
+			break;
+		}
+	}
+}
+
+static int socketDoEvent(socket_t *sp)
+{
+	ringq_t		*rq;
+	int 		sid;
+
+	a_assert(sp);
+
+	sid = sp->sid;
+	if (sp->currentEvents & SOCKET_READABLE) {
+		if (sp->flags & SOCKET_LISTENING) { 
+			socketAccept(sp);
+			sp->currentEvents = 0;
+			return 1;
+		} 
+
+	} else {
+
+		if (sp->handlerMask & SOCKET_READABLE && socketInputBuffered(sid) > 0) {
+			sp->currentEvents |= SOCKET_READABLE;
+		}
+	}
+
+	if (sp->currentEvents & SOCKET_WRITABLE) {
+		if (sp->flags & SOCKET_FLUSHING) {
+			rq = &sp->outBuf;
+			if (ringqLen(rq) > 0) {
+				socketFlush(sp->sid);
+			} else {
+				sp->flags &= ~SOCKET_FLUSHING;
+			}
+		}
+	}
+
+	if (sp->handler && (sp->handlerMask & sp->currentEvents)) {
+		(sp->handler)(sid, sp->handlerMask & sp->currentEvents, 
+			sp->handler_data);
+
+		if (socketList && sid < socketMax && socketList[sid] == sp) {
+			sp->currentEvents = 0;
+		}
+	}
+	return 1;
+}
+
+int socketSetBlock(int sid, int on)
+{
+	socket_t		*sp;
+	unsigned long	flag;
+	int				iflag;
+	int				oldBlock;
+	struct timeval rcv_timeo;
+
+	flag = iflag = !on;
+
+	if ((sp = socketPtr(sid)) == NULL) {
+		a_assert(0);
+		return 0;
+	}
+	oldBlock = (sp->flags & SOCKET_BLOCK);
+	sp->flags &= ~(SOCKET_BLOCK);
+	if (on) {
+		sp->flags |= SOCKET_BLOCK;
+	}
+
+
+	if (sp->flags & SOCKET_BLOCK) {
+
+		if(fcntl(sp->sock, F_SETFL, fcntl(sp->sock, F_GETFL) & ~O_NONBLOCK) < 0)
+    	{
+    		slog(MISC_PRINT,SLOG_ERR, "fcntl return -1.\n");
+    	}			
+
+	rcv_timeo.tv_sec = 60;
+	rcv_timeo.tv_usec = 0;
+	//printf("[zyl]set 60s send timeout\n");
+	//ÉèÖÃ60Ãë·¢Ëͳ¬Ê±
+	// cov 3 CHECKED_RETURN
+	if(setsockopt(sp->sock, SOL_SOCKET,SO_SNDTIMEO, (void*)&rcv_timeo, sizeof(rcv_timeo)) < 0){
+        ;
+	}
+	rcv_timeo.tv_sec = 1;
+	rcv_timeo.tv_usec = 0;
+	
+	//ÉèÖÃ1Ãë½ÓÊÕ³¬Ê±
+	// cov 3 CHECKED_RETURN
+	if(setsockopt(sp->sock, SOL_SOCKET,SO_RCVTIMEO, (void*)&rcv_timeo, sizeof(rcv_timeo)) < 0){
+        ;
+	}
+
+	} else {
+		if(fcntl(sp->sock, F_SETFL, fcntl(sp->sock, F_GETFL) | O_NONBLOCK) < 0)
+    	{
+    		slog(MISC_PRINT,SLOG_ERR, "fcntl return -1.\n");
+    	}			
+	}
+	return oldBlock;
+}
+
+int socketSockBuffered(int sock)
+{
+	socket_t	*sp;
+	int			i;
+
+	for (i = 0; i < socketMax; i++) {
+		if ((sp = socketList[i]) == NULL || sp->sock != sock) {
+			continue;
+		}
+		return socketInputBuffered(i);
+	}
+	return 0;
+}
+
diff --git a/ap/app/goahead/server/sym.c b/ap/app/goahead/server/sym.c
new file mode 100755
index 0000000..036431a
--- /dev/null
+++ b/ap/app/goahead/server/sym.c
@@ -0,0 +1,345 @@
+#ifdef UEMF
+	#include	"uemf.h"
+#else
+	#include	"basic/basicInternal.h"
+#endif
+
+static int		calcPrime(int size);
+
+typedef struct {						
+	int		inuse;						
+	int		hash_size;					
+	sym_t	**hash_table;				
+} sym_tabent_t;
+
+static int symMax;				
+static int hashIndex(sym_tabent_t *tp, char_t *name);
+static int htIndex;			
+static sym_t *hash(sym_tabent_t *tp, char_t *name);
+static sym_t *next;				
+static sym_tabent_t **sym;				
+
+sym_fd_t symOpen(int hash_size)
+{
+	sym_fd_t		sd;
+	sym_tabent_t	*tp;
+
+	a_assert(hash_size > 2);
+
+	if ((sd = hAlloc((void***) &sym)) < 0) {
+		return -1;
+	}
+
+	if ((tp = (sym_tabent_t*) balloc(B_L, sizeof(sym_tabent_t))) == NULL) {
+		symMax = hFree((void***) &sym, sd);
+		return -1;
+	}
+	memset(tp, 0, sizeof(sym_tabent_t));
+	if (sd >= symMax) {
+		symMax = sd + 1;
+	}
+	a_assert(0 <= sd && sd < symMax);
+	sym[sd] = tp;
+
+	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);
+	if(tp->hash_table)
+	memset(tp->hash_table, 0, tp->hash_size * sizeof(sym_t*));
+
+	return sd;
+}
+
+void symClose(sym_fd_t sd)
+{
+	sym_tabent_t	*tp;
+	sym_t			*sp, *forw;
+	int				i;
+
+	a_assert(0 <= sd && sd < symMax);
+	tp = sym[sd];
+	a_assert(tp);
+
+	for (i = 0; i < tp->hash_size; i++) {
+		for (sp = tp->hash_table[i]; sp; sp = forw) {
+			forw = sp->forw;
+			valueFree(&sp->name);
+			valueFree(&sp->content);
+			bfree(B_L, (void*) sp);
+			sp = forw;
+		}
+	}
+	bfree(B_L, (void*) tp->hash_table);
+
+	symMax = hFree((void***) &sym, sd);
+	bfree(B_L, (void*) tp);
+}
+
+sym_t* symFirst(sym_fd_t sd)
+{
+	sym_tabent_t	*tp;
+	sym_t			*sp, *forw;
+	int				i;
+
+	a_assert(0 <= sd && sd < symMax);
+	tp = sym[sd];
+	a_assert(tp);
+
+	for (i = 0; i < tp->hash_size; i++) {
+
+#if 0	// KW 3 cov M
+		for (sp = tp->hash_table[i]; sp; sp = forw) {
+			forw = sp->forw;
+
+			if (forw == NULL) {
+				htIndex = i + 1;
+				next = tp->hash_table[htIndex];
+			} else {
+				htIndex = i;
+				next = forw;
+			}
+			return sp;
+		}
+#else
+        sp = tp->hash_table[i];
+        if(NULL != sp){
+			forw = sp->forw;
+
+			if (forw == NULL) {
+				htIndex = i + 1;
+				next = tp->hash_table[htIndex];
+			} else {
+				htIndex = i;
+				next = forw;
+			}
+			return sp;
+		}
+			
+#endif
+	}
+	return NULL;
+}
+
+sym_t* symNext(sym_fd_t sd)
+{
+	sym_tabent_t	*tp;
+	sym_t			*sp, *forw;
+	int				i;
+
+	a_assert(0 <= sd && sd < symMax);
+	tp = sym[sd];
+	a_assert(tp);
+
+	for (i = htIndex; i < tp->hash_size; i++) {
+
+#if 0 // kw 3 cov M	
+		for (sp = next; sp; sp = forw) {
+			forw = sp->forw;
+
+			if (forw == NULL) {
+				htIndex = i + 1;
+				next = tp->hash_table[htIndex];
+			} else {
+				htIndex = i;
+				next = forw;
+			}
+			return sp;
+		}
+#else
+        sp = next;
+        if(NULL != sp) {
+        	forw = sp->forw;
+        
+        	if (forw == NULL) {
+        		htIndex = i + 1;
+        		next = tp->hash_table[htIndex];
+        	} else {
+        		htIndex = i;
+        		next = forw;
+        	}
+        	return sp;
+        }
+
+#endif
+		next = tp->hash_table[i + 1];
+	}
+	return NULL;
+}
+
+
+sym_t *symEnter(sym_fd_t sd, char_t *name, value_t v, int arg)
+{
+	sym_tabent_t	*tp;
+	sym_t			*sp, *last;
+	char_t			*cp;
+	int				hindex;
+
+	a_assert(name);
+	a_assert(0 <= sd && sd < symMax);
+	tp = sym[sd];
+	a_assert(tp);
+
+	last = NULL;
+	hindex = hashIndex(tp, name);
+	if ((sp = tp->hash_table[hindex]) != NULL) {
+		for (; sp; sp = sp->forw) {
+			cp = sp->name.value.string;
+			if (cp[0] == name[0] && gstrcmp(cp, name) == 0) {
+				break;
+			}
+			last = sp;
+		}
+		if (sp) {
+
+			if (sp->content.valid) {
+				valueFree(&sp->content);
+			}
+			sp->content = v;
+			sp->arg = arg;
+			return sp;
+		}
+
+		sp = (sym_t*) balloc(B_L, sizeof(sym_t));
+		if (sp == NULL) {
+			return NULL;
+		}
+		sp->content = v;
+		sp->forw = (sym_t*) NULL;
+		sp->name = valueString(name, VALUE_ALLOCATE);
+		sp->arg = arg;
+		last->forw = sp;
+
+	} else {
+		sp = (sym_t*) balloc(B_L, sizeof(sym_t));
+		if (sp == NULL) {
+			return NULL;
+		}
+		tp->hash_table[hindex] = sp;
+		tp->hash_table[hashIndex(tp, name)] = sp;
+
+		sp->arg = arg;
+		sp->content = v;
+		sp->name = valueString(name, VALUE_ALLOCATE);
+		sp->forw = (sym_t*) NULL;
+	}
+	return sp;
+}
+
+sym_t *symLookup(sym_fd_t sd, char_t *name)
+{
+	sym_tabent_t	*tp;
+	sym_t			*sp;
+	char_t			*cp;
+
+	a_assert(0 <= sd && sd < symMax);
+	if ((tp = sym[sd]) == NULL) {
+		return NULL;
+	}
+
+	if (name == NULL || *name == '\0') {
+		return NULL;
+	}
+
+
+	for (sp = hash(tp, name); sp; sp = sp->forw) {
+		cp = sp->name.value.string;
+		if (cp[0] == name[0] && gstrcmp(cp, name) == 0) {
+			break;
+		}
+	}
+	return sp;
+}
+
+int symDelete(sym_fd_t sd, char_t *name)
+{
+	sym_t			*last = NULL;
+	int				hindex;
+	char_t			*cp;
+	sym_t			*sp;
+	sym_tabent_t	*tp;
+
+	a_assert(name && *name);
+	a_assert(0 <= sd && sd < symMax);
+	tp = sym[sd];
+	a_assert(tp);
+
+	hindex = hashIndex(tp, name);
+	if ((sp = tp->hash_table[hindex]) != NULL) {
+		for ( ; sp; sp = sp->forw) {
+			cp = sp->name.value.string;
+			if (cp[0] == name[0] && gstrcmp(cp, name) == 0) {
+				break;
+			}
+			last = sp;
+		}
+	}
+	if (sp == (sym_t*) NULL) {				
+		return -1;
+	}
+
+	if (last) {
+		last->forw = sp->forw;
+	} else {
+		tp->hash_table[hindex] = sp->forw;
+	}
+	valueFree(&sp->name);
+	valueFree(&sp->content);
+	bfree(B_L, (void*) sp);
+
+	return 0;
+}
+
+
+
+static int hashIndex(sym_tabent_t *tp, char_t *name)
+{
+	unsigned int	sum;
+	int				i;
+
+	a_assert(tp);
+
+	i = 0;
+	sum = 0;
+	while (*name) {
+		sum += (((int) *name++) << i);
+		i = (i + 7) % (BITS(int) - BITSPERBYTE);
+	}
+	return sum % tp->hash_size;
+}
+
+static int isPrime(int n)
+{
+	int		i, max;
+
+	a_assert(n > 0);
+
+	max = n / 2;
+	for (i = 2; i <= max; i++) {
+		if (n % i == 0) {
+			return 0;
+		}
+	}
+	return 1;
+}
+
+static sym_t *hash(sym_tabent_t *tp, char_t *name)
+{
+	a_assert(tp);
+
+	return tp->hash_table[hashIndex(tp, name)];
+}
+
+static int calcPrime(int size)
+{
+	int count;
+
+	a_assert(size > 0);
+
+	for (count = size; count > 0; count--) {
+		if (isPrime(count)) {
+			return count;
+		}
+	}
+	return 1;
+}
+
diff --git a/ap/app/goahead/server/uemf.c b/ap/app/goahead/server/uemf.c
new file mode 100755
index 0000000..8155d8a
--- /dev/null
+++ b/ap/app/goahead/server/uemf.c
@@ -0,0 +1,159 @@
+#include	"uemf.h"
+
+
+int emfInst;
+extern void defaultErrorHandler(int etype, char_t *buf);
+extern void	defaultTraceHandler(int level, char_t *buf);
+
+static void (*traceHandler)(int level, char_t *buf) = defaultTraceHandler;
+static void (*errorHandler)(int etype, char_t *msg) = defaultErrorHandler;
+
+void error(E_ARGS_DEC, int etype, char_t *fmt, ...)
+{
+	va_list 	args = {0};
+	char_t		*fmtBuf, *buf;
+
+	va_start(args, fmt);
+	fmtValloc(&fmtBuf, E_MAX_ERROR, fmt, args);
+
+	if (etype == E_LOG) {
+		fmtAlloc(&buf, E_MAX_ERROR, T("%s\n"), fmtBuf);
+/*#ifdef 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);
+	}
+
+   else {
+      fmtAlloc(&buf, E_MAX_ERROR, T("Unknown error"));
+   }
+	va_end(args);
+
+	bfree(B_L, fmtBuf);
+
+	printf("%s",buf);
+
+	bfreeSafe(B_L, buf);
+}
+
+void traceRaw(char_t *buf)
+{
+	if(buf)
+	printf("%s",buf);
+}
+
+void trace(int level, char_t *fmt, ...)
+{
+	va_list 	args = {0};
+	char_t		*buf;
+
+	va_start(args, fmt);
+	fmtValloc(&buf, VALUE_MAX_STRING, fmt, args);
+	printf("%s",buf);
+	bfreeSafe(B_L, buf);
+	va_end(args);
+}
+
+char_t *strlower(char_t *string)
+{
+	char_t	*s;
+
+	a_assert(string);
+
+	if (string == NULL) {
+		return NULL;
+	}
+
+	s = string;
+	while (*s) {
+		if (gisupper(*s)) {
+			*s = (char_t) gtolower(*s);
+		}
+		s++;
+	}
+	*s = '\0';
+	return string;
+}
+
+char_t *strupper(char_t *string)
+{
+	char_t	*s;
+
+	a_assert(string);
+	if (string == NULL) {
+		return NULL;
+	}
+
+	s = string;
+	while (*s) {
+		if (gislower(*s)) {
+			*s = (char_t) gtoupper(*s);
+		}
+		s++;
+	}
+	*s = '\0';
+	return string;
+}
+
+char_t *basicGetProduct()
+{
+	return T("uemf");
+}
+
+char_t *basicGetAddress()
+{
+	return T("localhost");
+}
+
+char_t *stritoa(int n, char_t *string, int width)
+{
+	char_t	*cp, *lim, *s;
+	int		next, minus;
+	char_t	tmp_buf[16];
+
+	a_assert(string && width > 0);
+
+	if (string == NULL) {
+		if (width == 0) {
+			width = 10;
+		}
+		if ((string = balloc(B_L, width + 1)) == NULL) {
+			return NULL;
+		}
+	}
+	if (n < 0) {
+		minus = 1;
+		n = -n;
+		width--;
+	} else {
+		minus = 0;
+	}
+
+	cp = tmp_buf;
+	lim = &tmp_buf[width - 1];
+	while (n > 9 && cp < lim) {
+		next = n;
+		n /= 10;
+		*cp++ = (char_t) (next - n * 10 + '0');
+	}
+	if (cp < lim) {
+		*cp++ = (char_t) (n + '0');
+	}
+
+	s = string;
+	if (minus) {
+		*s++ = '-';
+	}
+
+	while (cp > tmp_buf) {
+		*s++ = *--cp;
+	}
+
+	*s++ = '\0';
+	return string;
+}
+
+
diff --git a/ap/app/goahead/server/uemf.h b/ap/app/goahead/server/uemf.h
new file mode 100755
index 0000000..3010ac0
--- /dev/null
+++ b/ap/app/goahead/server/uemf.h
@@ -0,0 +1,929 @@
+#ifndef _h_UEMF
+#define _h_UEMF 1
+
+#ifdef WIN
+	#include	<direct.h>
+	#include	<io.h>
+	#include	<sys/stat.h>
+	#include	<limits.h>
+	#include	<tchar.h>
+	#include	<windows.h>
+	#include	<winnls.h>
+	#include	<time.h>
+	#include	<sys/types.h>
+	#include	<stdio.h>
+	#include	<stdlib.h>
+	#include	<fcntl.h>
+	#include	<errno.h>
+#endif /* WIN */
+
+#ifdef CE
+	/*#include	<errno.h>*/
+	#include	<limits.h>
+	#include	<tchar.h>
+	#include	<windows.h>
+	#include	<winsock.h>
+	#include	<winnls.h>
+	#include	"CE/wincompat.h"
+	#include	<winsock.h>
+#endif /* CE */
+
+#ifdef NW
+	#include	<direct.h>
+	#include	<io.h>
+	#include	<sys/stat.h>
+	#include	<time.h>
+	#include	<sys/types.h>
+	#include	<stdio.h>
+	#include	<stdlib.h>
+	#include	<fcntl.h>
+	#include	<errno.h>
+	#include	<niterror.h>
+	#define		EINTR EINUSE
+	#define		 WEBS	1
+	#include	<limits.h>
+	#include	<netdb.h>
+	#include	<process.h>
+	#include	<tiuser.h>
+	#include	<sys/time.h>
+	#include	<arpa/inet.h>
+	#include	<sys/types.h>
+	#include	<sys/socket.h>
+	#include	<sys/filio.h>
+	#include	<netinet/in.h>
+#endif /* NW */
+
+#ifdef SCOV5 
+	#include	<sys/types.h>
+	#include	<stdio.h>
+	#include	"sys/socket.h"
+	#include	"sys/select.h"
+	#include	"netinet/in.h"
+	#include 	"arpa/inet.h"
+	#include 	"netdb.h"
+#endif /* SCOV5 */
+
+#ifdef UNIX
+	#include	<stdio.h>
+#endif /* UNIX */
+
+#ifdef LINUX
+	#include	<sys/types.h>
+	#include	<sys/stat.h>
+	#include	<sys/param.h>
+	#include	<limits.h>
+	#include	<stdio.h>
+	#include	<stdlib.h>
+	#include	<unistd.h>
+	#include	<sys/socket.h>
+	#include	<sys/select.h>
+	#include	<netinet/in.h>
+	#include 	<arpa/inet.h>
+	#include 	<netdb.h>
+	#include	<time.h>
+	#include	<fcntl.h>
+	#include	<errno.h>
+#endif /* LINUX */
+
+#ifdef LYNX
+	#include	<limits.h>
+	#include	<stdarg.h>
+	#include	<stdio.h>
+	#include	<stdlib.h>
+	#include	<unistd.h>
+	#include	<socket.h>
+	#include	<netinet/in.h>
+	#include 	<arpa/inet.h>
+	#include 	<netdb.h>
+	#include	<time.h>
+	#include	<fcntl.h>
+	#include	<errno.h>
+#endif /* LYNX */
+
+#ifdef MACOSX
+	#include	<sys/stat.h>
+	#include	<stdio.h>
+	#include	<stdlib.h>
+	#include	<unistd.h>
+	#include	<sys/socket.h>
+	#include	<netinet/in.h>
+	#include 	<arpa/inet.h>
+	#include 	<netdb.h>
+	#include	<fcntl.h>
+	#include	<errno.h>
+#endif /* MACOSX */
+
+#ifdef UW
+	#include	<stdio.h>
+#endif /* UW */
+
+#ifdef VXWORKS
+	#include	<vxWorks.h>
+	#include	<sockLib.h>
+	#include	<selectLib.h>
+	#include	<inetLib.h>
+	#include	<ioLib.h>
+	#include	<stdio.h>
+	#include	<stat.h>
+	#include	<time.h>
+	#include	<usrLib.h>
+	#include	<fcntl.h>
+	#include	<errno.h>
+#endif /* VXWORKS */
+
+#ifdef sparc
+# define __NO_PACK
+#endif /* sparc */
+
+#ifdef SOLARIS
+	#include	<sys/types.h>
+	#include	<limits.h>
+	#include	<stdio.h>
+	#include	<stdlib.h>
+	#include	<unistd.h>
+	#include	<socket.h>
+	#include	<sys/select.h>
+	#include	<netinet/in.h>
+	#include 	<arpa/inet.h>
+	#include 	<netdb.h>
+	#include	<time.h>
+	#include	<fcntl.h>
+	#include	<errno.h>
+#endif /* SOLARIS */
+
+#ifdef QNX4
+	#include	<sys/types.h>
+	#include	<stdio.h>
+	#include	<sys/socket.h>
+	#include	<sys/select.h>
+	#include	<netinet/in.h>
+	#include 	<arpa/inet.h>
+	#include 	<netdb.h>
+    #include    <stdlib.h>
+    #include    <unistd.h>
+    #include    <sys/uio.h>
+    #include    <sys/wait.h>
+#endif /* QNX4 */
+
+#ifdef ECOS
+	#include	<limits.h>
+	#include	<cyg/infra/cyg_type.h>
+	#include	<cyg/kernel/kapi.h>
+	#include	<time.h>
+	#include	<network.h>
+	#include	<errno.h>
+#endif /* ECOS */
+
+#include	<ctype.h>
+#include	<stdarg.h>
+#include	<string.h>
+
+#ifndef WEBS
+#include	"messages.h"
+#endif /* ! WEBS */
+
+#ifdef UW
+	#define		__NO_PACK		1
+#endif /* UW */
+
+#if (defined (SCOV5) || defined (VXWORKS) || defined (LINUX) || defined (LYNX) || defined (MACOSX))
+#ifndef O_BINARY
+#define O_BINARY 		0
+#endif /* O_BINARY */
+#define	SOCKET_ERROR	-1
+#endif /* SCOV5 || VXWORKS || LINUX || LYNX || MACOSX */
+
+#if (defined (WIN) || defined (CE))
+
+#define		__NO_FCNTL		1
+
+#undef R_OK
+#define R_OK	4
+#undef W_OK
+#define W_OK	2
+#undef X_OK
+#define X_OK	1
+#undef F_OK
+#define F_OK	0
+#endif /* WIN || CE */
+
+#if (defined (LINUX) && !defined (_STRUCT_TIMEVAL))
+struct timeval
+{
+	time_t	tv_sec;		
+	time_t	tv_usec;	
+};
+#define _STRUCT_TIMEVAL 1
+#endif /* LINUX && ! _STRUCT_TIMEVAL */
+
+#ifdef ECOS
+	#define		O_RDONLY		1
+	#define		O_BINARY		2
+
+	#define		__NO_PACK		1
+	#define		__NO_EJ_FILE	1
+	#define		__NO_CGI_BIN	1
+	#define		__NO_FCNTL		1
+
+	#define		LIBKERN_INLINE
+
+#endif /* ECOS */
+
+#ifdef QNX4
+    typedef long        fd_mask;
+    #define NFDBITS (sizeof (fd_mask) * NBBY)   /* bits per mask */
+#endif /* QNX4 */
+
+#ifdef NW
+	#define fd_mask			fd_set
+	#define INADDR_NONE		-1l
+	#define Sleep			delay
+
+	#define __NO_FCNTL		1
+
+	#undef R_OK
+	#define R_OK    4
+	#undef W_OK
+	#define W_OK    2
+	#undef X_OK
+	#define X_OK    1
+	#undef F_OK
+	#define F_OK    0
+#endif /* NW */
+
+#define TRACE_MAX			(4096 - 48)
+#define VALUE_MAX_STRING	(4096 - 48)
+#define SYM_MAX				(512)
+#define XML_MAX				4096			
+#define BUF_MAX				4096			
+#define FMT_STATIC_MAX		256				
+
+#if (defined (LITTLEFOOT) || defined (WEBS))
+#define LF_BUF_MAX		(510)
+#define LF_PATHSIZE		LF_BUF_MAX
+#else
+#define	LF_BUF_MAX		BUF_MAX
+#define LF_PATHSIZE		PATHSIZE
+#define UPPATHSIZE		PATHSIZE
+#endif /* LITTLEFOOT || WEBS */
+
+#ifndef CHAR_T_DEFINED
+#define CHAR_T_DEFINED 1
+#ifdef UNICODE
+
+#define	T(x)				__TXT(x)
+#define	__TXT(s)			L ## s
+typedef unsigned short 		char_t;
+typedef unsigned short		uchar_t;
+
+#define	TSZ(x)				(sizeof(x) / sizeof(char_t))
+
+#define	TASTRL(x)			((wcslen(x) + 1) * sizeof(char_t))
+
+#else
+#define	T(s) 				s
+typedef char				char_t;
+#define	TSZ(x)				(sizeof(x))
+#define	TASTRL(x)			(strlen(x) + 1)
+#ifdef WIN
+typedef unsigned char		uchar_t;
+#endif /* WIN */
+
+#endif /* UNICODE */
+
+#endif /* ! CHAR_T_DEFINED */
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#define GOAHEAD_COPYRIGHT \
+	T("Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.")
+
+#if (defined (LITTLEFOOT) && defined (INMEM))
+	#include	"lf/inmem.h"
+#endif /* LITTLEFOOT && INMEM */
+
+#ifdef UNICODE
+
+#define gmain		wmain
+
+#define gasctime	_wasctime
+#define gsprintf	swprintf
+#define gprintf		wprintf
+#define gfprintf	fwprintf
+#define gsscanf		swscanf
+#define gvsprintf	vswprintf
+
+#define gstrcpy		wcscpy
+#define gstrncpy	wcsncpy
+#define gstrncat	wcsncat
+#define gstrlen		wcslen
+#define gstrcat		wcscat
+#define gstrcmp		wcscmp
+#define gstrncmp	wcsncmp
+#define gstricmp	wcsicmp
+#define gstrchr		wcschr
+#define gstrrchr	wcsrchr
+#define gstrtok		wcstok
+#define gstrnset	wcsnset
+#define gstrrchr	wcsrchr
+#define gstrspn	wcsspn
+#define gstrcspn	wcscspn
+#define gstrstr		wcsstr
+#define gstrtol		wcstol
+
+#define gfopen		_wfopen
+#define gopen		_wopen
+#define gclose		close
+#define gcreat		_wcreat
+#define gfgets		fgetws
+#define gfputs		fputws
+#define gfscanf		fwscanf
+#define ggets		_getws
+#define glseek		lseek
+#define gunlink		_wunlink
+#define gread		read
+#define grename		_wrename
+#define gwrite		write
+#define gtmpnam		_wtmpnam
+#define gtempnam	_wtempnam
+#define gfindfirst	_wfindfirst
+#define gfinddata_t	_wfinddata_t
+#define gfindnext	_wfindnext
+#define gfindclose	_findclose
+#define gstat		_wstat
+#define gaccess		_waccess
+#define gchmod		_wchmod
+
+typedef struct _stat gstat_t;
+
+#define gmkdir		_wmkdir
+#define gchdir		_wchdir
+#define grmdir		_wrmdir
+#define ggetcwd		_wgetcwd
+
+#define gtolower	towlower
+#define gtoupper	towupper
+#ifdef CE
+#define gisspace	isspace
+#define gisdigit	isdigit
+#define gisxdigit	isxdigit
+#define gisupper	isupper
+#define gislower	islower
+#define gisprint	isprint
+#else
+#define gremove		_wremove
+#define gisspace	iswspace
+#define gisdigit	iswdigit
+#define gisxdigit	iswxdigit
+#define gisupper	iswupper
+#define gislower	iswlower
+#endif	/* if CE */
+#define gisalnum	iswalnum
+#define gisalpha	iswalpha
+#define gatoi(s)	wcstol(s, NULL, 10)
+
+#define gctime		_wctime
+#define ggetenv		_wgetenv
+#define gexecvp		_wexecvp
+
+#else /* ! UNICODE */
+
+#ifdef VXWORKS
+#define gchdir		vxchdir
+#define gmkdir		vxmkdir
+#define grmdir		vxrmdir
+#elif (defined (LYNX) || defined (LINUX) || defined (MACOSX) || defined (SOLARIS))
+#define gchdir		chdir
+#define gmkdir(s)	mkdir(s,0755)
+#define grmdir		rmdir
+#else
+#define gchdir		chdir
+#define gmkdir		mkdir
+#define grmdir		rmdir
+#endif /* VXWORKS #elif LYNX || LINUX || MACOSX || SOLARIS*/
+
+#define gclose		close
+#define gclosedir	closedir
+#define gchmod		chmod
+#define ggetcwd		getcwd
+#define glseek		lseek
+#define gloadModule	loadModule
+#define gopen		open
+#define gopendir	opendir
+#define gread		read
+#define greaddir	readdir
+#define grename		rename
+#define gstat		stat
+#define gunlink		unlink
+#define gwrite		write
+
+#define gasctime	asctime
+#define gsprintf	sprintf
+#define gprintf		printf
+#define gfprintf	fprintf
+#define gsscanf		sscanf
+#define gvsprintf	vsprintf
+
+#define gstrcpy		strcpy
+#define gstrncpy	strncpy
+#define gstrncat	strncat
+#define gstrlen		strlen
+#define gstrcat		strcat
+#define gstrcmp		strcmp
+#define gstrncmp	strncmp
+#define gstricmp	strcmpci
+#define gstrchr		strchr
+#define gstrrchr	strrchr
+#define gstrtok		strtok
+#define gstrnset	strnset
+#define gstrrchr	strrchr
+#define gstrspn	strspn
+#define gstrcspn	strcspn
+#define gstrstr		strstr
+#define gstrtol		strtol
+
+#define gfopen		fopen
+#define gcreat		creat
+#define gfgets		fgets
+#define gfputs		fputs
+#define gfscanf		fscanf
+#define ggets		gets
+#define gtmpnam		tmpnam
+#define gtempnam	tempnam
+#define gfindfirst	_findfirst
+#define gfinddata_t	_finddata_t
+#define gfindnext	_findnext
+#define gfindclose	_findclose
+#define gaccess		access
+
+typedef struct stat gstat_t;
+
+#define gremove		remove
+
+#define gtolower	tolower
+#define gtoupper	toupper
+#define gisspace	isspace
+#define gisdigit	isdigit
+#define gisxdigit	isxdigit
+#define gisalnum	isalnum
+#define gisalpha	isalpha
+#define gisupper	isupper
+#define gislower	islower
+#define gatoi		atoi
+
+#define gctime		ctime
+#define ggetenv		getenv
+#define gexecvp		execvp
+#ifndef VXWORKS
+#define gmain		main
+#endif /* ! VXWORKS */
+#ifdef VXWORKS
+#define	fcntl(a, b, c)
+#endif /* VXWORKS */
+#endif /* ! UNICODE */
+
+#ifdef INMEM
+	#include	"lf/inmem.h"
+#endif
+
+#ifndef FNAMESIZE
+#define FNAMESIZE			254			
+#endif /* FNAMESIZE */
+
+#define E_MAX_ERROR			4096
+#define URL_MAX				4096
+
+#define	E_ASSERT			0x1			
+#define	E_LOG				0x2			
+#define	E_USER				0x3			
+
+#define E_L					T(__FILE__), __LINE__
+#define E_ARGS_DEC			char_t *file, int line
+#define E_ARGS				file, line
+
+#if (defined (ASSERT) || defined (ASSERT_CE))
+	#define a_assert(C)		if (C) ; else error(E_L, E_ASSERT, T("%s"), T(#C))
+#else
+	#define a_assert(C)		if (1) ; else
+#endif /* ASSERT || ASSERT_CE */
+
+typedef enum {
+	undefined	= 0,
+	byteint		= 1,
+	shortint	= 2,
+	integer		= 3,
+	hex			= 4,
+	percent 	= 5,
+	octal		= 6,
+	big			= 7,
+	flag		= 8,
+	floating	= 9,
+	string 		= 10,
+	bytes 		= 11,
+	symbol 		= 12,
+	errmsg 		= 13
+} vtype_t;
+
+#ifndef __NO_PACK
+#pragma pack(2)
+#endif /* _NO_PACK */
+
+typedef struct {
+
+	union {
+		char	flag;
+		char	byteint;
+		short	shortint;
+		char	percent;
+		long	integer;
+		long	hex;
+		long	octal;
+		long	big[2];
+#ifdef FLOATING_POINT_SUPPORT
+		double	floating;
+#endif /* FLOATING_POINT_SUPPORT */
+		char_t	*string;
+		char	*bytes;
+		char_t	*errmsg;
+		void	*symbol;
+	} value;
+
+	vtype_t			type;
+	unsigned int	valid		: 8;
+	unsigned int	allocated	: 8;		
+} value_t;
+
+#ifndef __NO_PACK
+#pragma pack()
+#endif /* __NO_PACK */
+
+#define VALUE_ALLOCATE		0x1
+
+#define value_numeric(t)	(t >= byteint && t <= big)
+#define value_str(t) 		(t >= string && t <= bytes)
+#define value_ok(t) 		(t > undefined && t <= symbol)
+
+#define VALUE_VALID			{ {0}, integer, 1 }
+#define VALUE_INVALID		{ {0}, undefined, 0 }
+
+typedef struct {
+	unsigned char	*buf;				
+	unsigned char	*servp;				
+	unsigned char	*endp;				
+	unsigned char	*endbuf;			
+	int				buflen;				
+	int				maxsize;			
+	int				increment;			
+} ringq_t;
+
+#ifdef	B_STATS
+#ifndef B_L
+#define B_L				T(__FILE__), __LINE__
+#define B_ARGS_DEC		char_t *file, int line
+#define B_ARGS			file, line
+#endif /* B_L */
+#endif /* B_STATS */
+
+typedef struct {
+	union {
+		void	*next;							
+		int		size;							
+	} u;
+	int			flags;							
+} bType;
+
+#define B_SHIFT			4					
+#define B_ROUND			((1 << (B_SHIFT)) - 1)
+#define B_MAX_CLASS		13					
+#define B_MALLOCED		0x80000000			
+#define B_DEFAULT_MEM	(64 * 1024)			
+#define B_MAX_FILES		(512)				
+#define B_FILL_CHAR		(0x77)				
+#define B_FILL_WORD		(0x77777777)		
+#define B_MAX_BLOCKS	(64 * 1024)			
+
+
+#define B_INTEGRITY			0x8124000		
+#define B_INTEGRITY_MASK	0xFFFF000		
+#define B_USE_MALLOC		0x1				
+#define B_USER_BUF			0x2				
+
+
+typedef struct sym_t {
+	struct sym_t	*forw;					
+	value_t			name;					
+	value_t			content;				
+	int				arg;					
+} sym_t;
+
+typedef int sym_fd_t;						
+
+#define EMF_SCRIPT_JSCRIPT			0		
+#define EMF_SCRIPT_TCL	 			1		
+#define EMF_SCRIPT_EJSCRIPT 		2		
+#define EMF_SCRIPT_MAX	 			3
+
+#define	MAXINT		INT_MAX
+#define BITSPERBYTE 8
+#define BITS(type)	(BITSPERBYTE * (int) sizeof(type))
+#define	STRSPACE	T("\t \n\r\t")
+
+#ifndef max
+#define max(a,b)  (((a) > (b)) ? (a) : (b))
+#endif /* max */
+
+#ifndef min
+#define min(a,b)  (((a) < (b)) ? (a) : (b))
+#endif /* min */
+
+typedef struct {
+	char_t	*minute;
+	char_t	*hour;
+	char_t	*day;
+	char_t	*month;
+	char_t	*dayofweek;
+} cron_t;
+
+extern long		cronUntil(cron_t *cp, int period, time_t testTime);
+extern int		cronAlloc(cron_t *cp, char_t *str);
+extern int		cronFree(cron_t *cp);
+
+
+#if ((defined (WIN) || defined (CE)) && defined (WEBS))
+#define EWOULDBLOCK             WSAEWOULDBLOCK
+#define ENETDOWN                WSAENETDOWN
+#define ECONNRESET              WSAECONNRESET
+#endif /* (WIN || CE) && WEBS) */
+
+#define SOCKET_EOF				0x1		
+#define SOCKET_CONNECTING		0x2		
+#define SOCKET_BROADCAST		0x4		
+#define SOCKET_PENDING			0x8		
+#define SOCKET_FLUSHING			0x10	
+#define SOCKET_DATAGRAM			0x20	
+#define SOCKET_ASYNC			0x40	
+#define SOCKET_BLOCK			0x80	
+#define SOCKET_LISTENING		0x100	
+#define SOCKET_CLOSING			0x200	
+#define SOCKET_CONNRESET		0x400	
+
+#define SOCKET_PORT_MAX			0xffff	
+
+
+#define SOCKET_WOULDBLOCK		1		
+#define SOCKET_RESET			2		
+#define SOCKET_NETDOWN			3		
+#define SOCKET_AGAIN			4		
+#define SOCKET_INTR				5		
+#define SOCKET_INVAL			6		
+
+#define SOCKET_READABLE			0x2		
+#define SOCKET_WRITABLE			0x4		
+#define SOCKET_EXCEPTION		0x8		
+#define EMF_SOCKET_MESSAGE		(WM_USER+13)
+
+#ifdef LITTLEFOOT
+#define SOCKET_BUFSIZ			510		
+#else
+#define SOCKET_BUFSIZ			1024	
+#endif /* LITTLEFOOT */
+
+typedef void 	(*socketHandler_t)(int sid, int mask, int data);
+typedef int		(*socketAccept_t)(int sid, char *ipaddr, int port, 
+					int listenSid);
+typedef struct {
+	char			host[64];				
+	ringq_t			inBuf;					
+	ringq_t			outBuf;					
+	ringq_t			lineBuf;				
+	socketAccept_t	accept;					
+	socketHandler_t	handler;				
+	int				handler_data;			
+	int				handlerMask;			
+	int				sid;					
+	int				port;					
+	int				flags;					
+	int				sock;					
+	int				fileHandle;				
+	int				interestEvents;			
+	int				currentEvents;			
+	int				selectEvents;			
+	int				saveMask;				
+	int				error;					
+} socket_t;
+
+
+extern void 	 bclose();
+extern int 		 bopen(void *buf, int bufsize, int flags);
+
+
+#ifdef NO_BALLOC
+#define balloc(B_ARGS, num) malloc(num)
+#define bfree(B_ARGS, p) free(p)
+#define bfreeSafe(B_ARGS, p) \
+	if (p) { free(p); } else
+#define brealloc(B_ARGS, p, num) realloc(p, num)
+extern char_t *bstrdupNoBalloc(char_t *s);
+extern char *bstrdupANoBalloc(char *s);
+#define bstrdup(B_ARGS, s) bstrdupNoBalloc(s)
+#define bstrdupA(B_ARGS, s) bstrdupANoBalloc(s)
+#define gstrdup(B_ARGS, s) bstrdupNoBalloc(s)
+
+#else /* BALLOC */
+
+#ifndef B_STATS
+#define balloc(B_ARGS, num) balloc(num)
+#define bfree(B_ARGS, p) bfree(p)
+#define bfreeSafe(B_ARGS, p) bfreeSafe(p)
+#define brealloc(B_ARGS, p, size) brealloc(p, size)
+#define bstrdup(B_ARGS, p) bstrdup(p)
+
+#ifdef UNICODE
+#define bstrdupA(B_ARGS, p) bstrdupA(p)
+#else /* UNICODE */
+#define bstrdupA bstrdup
+#endif /* UNICODE */
+
+#endif /* B_STATS */
+
+#define gstrdup	bstrdup
+extern void		*balloc(B_ARGS_DEC, int size);
+extern void		bfree(B_ARGS_DEC, void *mp);
+extern void		bfreeSafe(B_ARGS_DEC, void *mp);
+extern void		*brealloc(B_ARGS_DEC, void *buf, int newsize);
+extern char_t	*bstrdup(B_ARGS_DEC, char_t *s);
+
+#ifdef UNICODE
+extern char *bstrdupA(B_ARGS_DEC, char *s);
+#else /* UNICODE */
+#define bstrdupA bstrdup
+#endif /* UNICODE */
+#endif /* BALLOC */
+
+extern void bstats(int handle, void (*writefn)(int handle, char_t *fmt, ...));
+
+#define B_USE_MALLOC		0x1				/* Okay to use malloc if required */
+#define B_USER_BUF			0x2				/* User supplied buffer for mem */
+
+
+#ifndef LINUX
+extern char_t	*basename(char_t *name);
+#endif /* !LINUX */
+
+#if (defined (UEMF) && defined (WEBS))
+
+#define emfSchedCallback	websSchedCallBack
+#define emfUnschedCallback	websUnschedCallBack
+#define emfReschedCallback	websReschedCallBack
+#endif /* UEMF && WEBS */
+
+typedef void	(emfSchedProc)(void *data, int id);
+extern int		emfSchedCallback(int delay, emfSchedProc *proc, void *arg);
+extern void 	emfUnschedCallback(int id);
+extern void 	emfReschedCallback(int id, int delay);
+extern void		emfSchedProcess();
+extern int		emfInstGet();
+extern void		emfInstSet(int inst);
+extern void		error(E_ARGS_DEC, int flags, char_t *fmt, ...);
+extern void		(*errorSetHandler(void (*function)(int etype, char_t *msg))) \
+					(int etype, char_t *msg);
+
+#ifdef B_STATS
+#define 		hAlloc(x) 				HALLOC(B_L, x)
+#define			hAllocEntry(x, y, z)	HALLOCENTRY(B_L, x, y, z)
+extern int		HALLOC(B_ARGS_DEC, void ***map);
+extern int 		HALLOCENTRY(B_ARGS_DEC, void ***list, int *max, int size);
+#else
+extern int		hAlloc(void ***map);
+extern int 		hAllocEntry(void ***list, int *max, int size);
+#endif /* B_STATS */
+
+extern int		hFree(void ***map, int handle);
+
+extern int	 	ringqOpen(ringq_t *rq, int increment, int maxsize);
+extern void 	ringqClose(ringq_t *rq);
+extern int 		ringqLen(ringq_t *rq);
+
+extern int 		ringqPutc(ringq_t *rq, char_t c);
+extern int	 	ringqInsertc(ringq_t *rq, char_t c);
+extern int	 	ringqPutStr(ringq_t *rq, char_t *str);
+extern int 		ringqGetc(ringq_t *rq);
+
+extern int		fmtValloc(char_t **s, int n, char_t *fmt, va_list arg);
+extern int		fmtAlloc(char_t **s, int n, char_t *fmt, ...);
+extern int		fmtStatic(char_t *s, int n, char_t *fmt, ...);
+
+#ifdef UNICODE
+extern int 		ringqPutcA(ringq_t *rq, char c);
+extern int	 	ringqInsertcA(ringq_t *rq, char c);
+extern int	 	ringqPutStrA(ringq_t *rq, char *str);
+extern int 		ringqGetcA(ringq_t *rq);
+#else
+#define ringqPutcA ringqPutc
+#define ringqInsertcA ringqInsertc
+#define ringqPutStrA ringqPutStr
+#define ringqGetcA ringqGetc
+#endif /* UNICODE */
+
+extern int 		ringqPutBlk(ringq_t *rq, unsigned char *buf, int len);
+extern int 		ringqPutBlkMax(ringq_t *rq);
+extern void 	ringqPutBlkAdj(ringq_t *rq, int size);
+extern int 		ringqGetBlk(ringq_t *rq, unsigned char *buf, int len);
+extern int 		ringqGetBlkMax(ringq_t *rq);
+extern void 	ringqGetBlkAdj(ringq_t *rq, int size);
+extern void 	ringqFlush(ringq_t *rq);
+extern void 	ringqAddNull(ringq_t *rq);
+
+extern int		scriptSetVar(int engine, char_t *var, char_t *value);
+extern int		scriptEval(int engine, char_t *cmd, char_t **rslt, int chan);
+
+extern void		socketClose();
+extern void		socketCloseConnection(int sid);
+extern void		socketCreateHandler(int sid, int mask, socketHandler_t 
+					handler, int arg);
+extern void		socketDeleteHandler(int sid);
+extern int		socketEof(int sid);
+extern int 		socketCanWrite(int sid);
+extern void 	socketSetBufferSize(int sid, int in, int line, int out);
+extern int		socketFlush(int sid);
+extern int		socketGets(int sid, char_t **buf);
+extern int		socketGetPort(int sid);
+extern int		socketInputBuffered(int sid);
+extern int		socketOpen();
+extern int 		socketOpenConnection(char *host, int port, 
+					socketAccept_t accept, int flags);
+extern void 	socketProcess(int hid);
+extern int		socketRead(int sid, char *buf, int len);
+extern int 		socketReady(int hid);
+extern int		socketWrite(int sid, char *buf, int len);
+extern int		socketWriteString(int sid, char_t *buf);
+extern int 		socketSelect(int hid, int timeout);
+extern int 		socketGetHandle(int sid);
+extern int 		socketSetBlock(int sid, int flags);
+extern int 		socketGetBlock(int sid);
+extern int 		socketAlloc(char *host, int port, socketAccept_t accept, 
+					int flags);
+extern void 	socketFree(int sid);
+extern int		socketGetError();
+extern socket_t *socketPtr(int sid);
+extern int 		socketWaitForEvent(socket_t *sp, int events, int *errCode);
+extern void 	socketRegisterInterest(socket_t *sp, int handlerMask);
+extern int 		socketGetInput(int sid, char *buf, int toRead, int *errCode);
+
+extern char_t	*strlower(char_t *string);
+extern char_t	*strupper(char_t *string);
+
+extern char_t	*stritoa(int n, char_t *string, int width);
+
+extern sym_fd_t	symOpen(int hash_size);
+extern void		symClose(sym_fd_t sd);
+extern sym_t	*symLookup(sym_fd_t sd, char_t *name);
+extern sym_t	*symEnter(sym_fd_t sd, char_t *name, value_t v, int arg);
+extern int		symDelete(sym_fd_t sd, char_t *name);
+extern void 	symWalk(sym_fd_t sd, void (*fn)(sym_t *symp));
+extern sym_t	*symFirst(sym_fd_t sd);
+extern sym_t	*symNext(sym_fd_t sd);
+extern int		symSubOpen();
+extern void 	symSubClose();
+
+extern void		trace(int lev, char_t *fmt, ...);
+extern void		traceRaw(char_t *buf);
+extern void		(*traceSetHandler(void (*function)(int level, char_t *buf))) 
+					(int level, char_t *buf);
+ 
+extern value_t 	valueInteger(long value);
+extern value_t	valueString(char_t *value, int flags);
+extern value_t	valueErrmsg(char_t *value);
+extern void 	valueFree(value_t *v);
+extern int		vxchdir(char *dirname);
+
+extern unsigned int hextoi(char_t *hexstring);
+extern unsigned int gstrtoi(char_t *s);
+extern				time_t	timeMsec();
+
+extern char_t 	*ascToUni(char_t *ubuf, char *str, int nBytes);
+extern char 	*uniToAsc(char *buf, char_t *ustr, int nBytes);
+extern char_t	*ballocAscToUni(char  *cp, int alen);
+extern char		*ballocUniToAsc(char_t *unip, int ulen);
+
+extern char_t	*basicGetHost();
+extern char_t	*basicGetAddress();
+extern char_t	*basicGetProduct();
+extern void		basicSetHost(char_t *host);
+extern void		basicSetAddress(char_t *addr);
+
+extern int		harnessOpen(char_t **argv);
+extern void		harnessClose(int status);
+extern void		harnessTesting(char_t *msg, ...);
+extern void		harnessPassed();
+extern void		harnessFailed(int line);
+extern int		harnessLevel();
+
+#endif /* _h_UEMF */
+
diff --git a/ap/app/goahead/server/unzip.c b/ap/app/goahead/server/unzip.c
new file mode 100644
index 0000000..c51d7ec
--- /dev/null
+++ b/ap/app/goahead/server/unzip.c
@@ -0,0 +1,2208 @@
+/* unzip.c -- IO for uncompress .zip files using zlib
+   Version 1.1, February 14h, 2010
+   part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
+
+         Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
+
+         Modifications of Unzip for Zip64
+         Copyright (C) 2007-2008 Even Rouault
+
+         Modifications for Zip64 support on both zip and unzip
+         Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
+
+         For more info read MiniZip_info.txt
+
+
+  ------------------------------------------------------------------------------------
+  Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of
+  compatibility with older software. The following is from the original crypt.c.
+  Code woven in by Terry Thorsen 1/2003.
+
+  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2000-Apr-09 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, all these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+
+        crypt.c (full version) by Info-ZIP.      Last revised:  [see crypt.h]
+
+  The encryption/decryption parts of this source code (as opposed to the
+  non-echoing password parts) were originally written in Europe.  The
+  whole source package can be freely distributed, including from the USA.
+  (Prior to January 2000, re-export from the US was a violation of US law.)
+
+        This encryption code is a direct transcription of the algorithm from
+  Roger Schlafly, described by Phil Katz in the file appnote.txt.  This
+  file (appnote.txt) is distributed with the PKZIP program (even in the
+  version without encryption capabilities).
+
+        ------------------------------------------------------------------------------------
+
+        Changes in unzip.c
+
+        2007-2008 - Even Rouault - Addition of cpl_unzGetCurrentFileZStreamPos
+  2007-2008 - Even Rouault - Decoration of symbol names unz* -> cpl_unz*
+  2007-2008 - Even Rouault - Remove old C style function prototypes
+  2007-2008 - Even Rouault - Add unzip support for ZIP64
+
+        Copyright (C) 2007-2008 Even Rouault
+
+
+        Oct-2009 - Mathias Svensson - Removed cpl_* from symbol names (Even Rouault added them but since this is now moved to a new project (minizip64) I renamed them again).
+  Oct-2009 - Mathias Svensson - Fixed problem if uncompressed size was > 4G and compressed size was <4G
+                                should only read the compressed/uncompressed size from the Zip64 format if
+                                the size from normal header was 0xFFFFFFFF
+  Oct-2009 - Mathias Svensson - Applied some bug fixes from paches recived from Gilles Vollant
+        Oct-2009 - Mathias Svensson - Applied support to unzip files with compression mathod BZIP2 (bzip2 lib is required)
+                                Patch created by Daniel Borca
+
+  Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer
+
+  Copyright (C) 1998 - 2010 Gilles Vollant, Even Rouault, Mathias Svensson
+
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef NOUNCRYPT
+        #define NOUNCRYPT
+#endif
+
+#include "zlib.h"
+#include "unzip.h"
+
+#ifdef STDC
+#  include <stddef.h>
+#  include <string.h>
+#  include <stdlib.h>
+#endif
+#ifdef NO_ERRNO_H
+    extern int errno;
+#else
+#   include <errno.h>
+#endif
+
+
+#ifndef local
+#  define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+
+#ifndef CASESENSITIVITYDEFAULT_NO
+#  if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES)
+#    define CASESENSITIVITYDEFAULT_NO
+#  endif
+#endif
+
+
+#ifndef UNZ_BUFSIZE
+#define UNZ_BUFSIZE (16384)
+#endif
+
+#ifndef UNZ_MAXFILENAMEINZIP
+#define UNZ_MAXFILENAMEINZIP (256)
+#endif
+
+//#define WEB_ZIP_MEM_DEBUG
+#ifdef WEB_ZIP_MEM_DEBUG
+static void* web_malloc(unsigned int bytes);
+static void web_free(void* mem);
+
+#define ALLOC(size) (web_malloc(size))
+#define TRYFREE(p) {if (p) web_free(p);}
+#endif
+
+#ifndef ALLOC
+# define ALLOC(size) (malloc(size))
+#endif
+#ifndef TRYFREE
+# define TRYFREE(p) {if (p) free(p);}
+#endif
+
+#define SIZECENTRALDIRITEM (0x2e)
+#define SIZEZIPLOCALHEADER (0x1e)
+
+
+const char unz_copyright[] =
+   " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
+
+/* unz_file_info_interntal contain internal info about a file in zipfile*/
+typedef struct unz_file_info64_internal_s
+{
+    ZPOS64_T offset_curfile;/* relative offset of local header 8 bytes */
+} unz_file_info64_internal;
+
+
+/* file_in_zip_read_info_s contain internal information about a file in zipfile,
+    when reading and decompress it */
+typedef struct
+{
+    char  *read_buffer;         /* internal buffer for compressed data */
+    z_stream stream;            /* zLib stream structure for inflate */
+
+#ifdef HAVE_BZIP2
+    bz_stream bstream;          /* bzLib stream structure for bziped */
+#endif
+
+    ZPOS64_T pos_in_zipfile;       /* position in byte on the zipfile, for fseek*/
+    uLong stream_initialised;   /* flag set if stream structure is initialised*/
+
+    ZPOS64_T offset_local_extrafield;/* offset of the local extra field */
+    uInt  size_local_extrafield;/* size of the local extra field */
+    ZPOS64_T pos_local_extrafield;   /* position in the local extra field in read*/
+    ZPOS64_T total_out_64;
+
+    uLong crc32;                /* crc32 of all data uncompressed */
+    uLong crc32_wait;           /* crc32 we must obtain after decompress all */
+    ZPOS64_T rest_read_compressed; /* number of byte to be decompressed */
+    ZPOS64_T rest_read_uncompressed;/*number of byte to be obtained after decomp*/
+    zlib_filefunc64_32_def z_filefunc;
+    voidpf filestream;        /* io structore of the zipfile */
+    uLong compression_method;   /* compression method (0==store) */
+    ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
+    int   raw;
+} file_in_zip64_read_info_s;
+
+
+/* unz64_s contain internal information about the zipfile
+*/
+typedef struct
+{
+    zlib_filefunc64_32_def z_filefunc;
+    int is64bitOpenFunction;
+    voidpf filestream;        /* io structore of the zipfile */
+    unz_global_info64 gi;       /* public global information */
+    ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
+    ZPOS64_T num_file;             /* number of the current file in the zipfile*/
+    ZPOS64_T pos_in_central_dir;   /* pos of the current file in the central dir*/
+    ZPOS64_T current_file_ok;      /* flag about the usability of the current file*/
+    ZPOS64_T central_pos;          /* position of the beginning of the central dir*/
+
+    ZPOS64_T size_central_dir;     /* size of the central directory  */
+    ZPOS64_T offset_central_dir;   /* offset of start of central directory with
+                                   respect to the starting disk number */
+
+    unz_file_info64 cur_file_info; /* public info about the current file in zip*/
+    unz_file_info64_internal cur_file_info_internal; /* private info about it*/
+    file_in_zip64_read_info_s* pfile_in_zip_read; /* structure about the current
+                                        file if we are decompressing it */
+    int encrypted;
+
+    int isZip64;
+
+#    ifndef NOUNCRYPT
+    unsigned long keys[3];     /* keys defining the pseudo-random sequence */
+    const z_crc_t* pcrc_32_tab;
+#    endif
+} unz64_s;
+
+
+#ifndef NOUNCRYPT
+#include "crypt.h"
+#endif
+
+/* ===========================================================================
+     Read a byte from a gz_stream; update next_in and avail_in. Return EOF
+   for end of file.
+   IN assertion: the stream s has been successfully opened for reading.
+*/
+
+
+local int unz64local_getByte OF((
+    const zlib_filefunc64_32_def* pzlib_filefunc_def,
+    voidpf filestream,
+    int *pi));
+
+local int unz64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi)
+{
+    unsigned char c;
+    int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1);
+    if (err==1)
+    {
+        *pi = (int)c;
+        return UNZ_OK;
+    }
+    else
+    {
+        if (ZERROR64(*pzlib_filefunc_def,filestream))
+            return UNZ_ERRNO;
+        else
+            return UNZ_EOF;
+    }
+}
+
+
+/* ===========================================================================
+   Reads a long in LSB order from the given gz_stream. Sets
+*/
+local int unz64local_getShort OF((
+    const zlib_filefunc64_32_def* pzlib_filefunc_def,
+    voidpf filestream,
+    uLong *pX));
+
+local int unz64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def,
+                             voidpf filestream,
+                             uLong *pX)
+{
+    uLong x ;
+    int i = 0;
+    int err;
+
+    err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+    x = (uLong)i;
+
+    if (err==UNZ_OK)
+        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+    x |= ((uLong)i)<<8;
+
+    if (err==UNZ_OK)
+        *pX = x;
+    else
+        *pX = 0;
+    return err;
+}
+
+local int unz64local_getLong OF((
+    const zlib_filefunc64_32_def* pzlib_filefunc_def,
+    voidpf filestream,
+    uLong *pX));
+
+local int unz64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def,
+                            voidpf filestream,
+                            uLong *pX)
+{
+    uLong x ;
+    int i = 0;
+    int err;
+
+    err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+    x = (uLong)i;
+
+    if (err==UNZ_OK)
+        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+    x |= ((uLong)i)<<8;
+
+    if (err==UNZ_OK)
+        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+    x |= ((uLong)i)<<16;
+
+    if (err==UNZ_OK)
+        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+    x += ((uLong)i)<<24;
+
+    if (err==UNZ_OK)
+        *pX = x;
+    else
+        *pX = 0;
+    return err;
+}
+
+local int unz64local_getLong64 OF((
+    const zlib_filefunc64_32_def* pzlib_filefunc_def,
+    voidpf filestream,
+    ZPOS64_T *pX));
+
+
+local int unz64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def,
+                            voidpf filestream,
+                            ZPOS64_T *pX)
+{
+    ZPOS64_T x ;
+    int i = 0;
+    int err;
+
+    err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+    x = (ZPOS64_T)i;
+
+    if (err==UNZ_OK)
+        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+    x |= ((ZPOS64_T)i)<<8;
+
+    if (err==UNZ_OK)
+        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+    x |= ((ZPOS64_T)i)<<16;
+
+    if (err==UNZ_OK)
+        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+    x |= ((ZPOS64_T)i)<<24;
+
+    if (err==UNZ_OK)
+        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+    x |= ((ZPOS64_T)i)<<32;
+
+    if (err==UNZ_OK)
+        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+    x |= ((ZPOS64_T)i)<<40;
+
+    if (err==UNZ_OK)
+        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+    x |= ((ZPOS64_T)i)<<48;
+
+    if (err==UNZ_OK)
+        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+    x |= ((ZPOS64_T)i)<<56;
+
+    if (err==UNZ_OK)
+        *pX = x;
+    else
+        *pX = 0;
+    return err;
+}
+
+/* My own strcmpi / strcasecmp */
+local int strcmpcasenosensitive_internal (const char* fileName1, const char* fileName2)
+{
+    for (;;)
+    {
+        char c1=*(fileName1++);
+        char c2=*(fileName2++);
+        if ((c1>='a') && (c1<='z'))
+            c1 -= 0x20;
+        if ((c2>='a') && (c2<='z'))
+            c2 -= 0x20;
+        if (c1=='\0')
+            return ((c2=='\0') ? 0 : -1);
+        if (c2=='\0')
+            return 1;
+        if (c1<c2)
+            return -1;
+        if (c1>c2)
+            return 1;
+    }
+}
+
+
+#ifdef  CASESENSITIVITYDEFAULT_NO
+#define CASESENSITIVITYDEFAULTVALUE 2
+#else
+#define CASESENSITIVITYDEFAULTVALUE 1
+#endif
+
+#ifndef STRCMPCASENOSENTIVEFUNCTION
+#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
+#endif
+
+/*
+   Compare two filename (fileName1,fileName2).
+   If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
+   If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
+                                                                or strcasecmp)
+   If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
+        (like 1 on Unix, 2 on Windows)
+
+*/
+extern int ZEXPORT unzStringFileNameCompare (const char*  fileName1,
+                                                 const char*  fileName2,
+                                                 int iCaseSensitivity)
+
+{
+    if (iCaseSensitivity==0)
+        iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
+
+    if (iCaseSensitivity==1)
+        return strcmp(fileName1,fileName2);
+
+    return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);
+}
+
+#ifndef BUFREADCOMMENT
+#define BUFREADCOMMENT (0x400)
+#endif
+
+/*
+  Locate the Central directory of a zipfile (at the end, just before
+    the global comment)
+*/
+local ZPOS64_T unz64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream));
+local ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)
+{
+    unsigned char* buf;
+    ZPOS64_T uSizeFile;
+    ZPOS64_T uBackRead;
+    ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */
+    ZPOS64_T uPosFound=0;
+
+    if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
+        return 0;
+
+
+    uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);
+
+    if (uMaxBack>uSizeFile)
+        uMaxBack = uSizeFile;
+
+    buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
+    if (buf==NULL)
+        return 0;
+
+    uBackRead = 4;
+    while (uBackRead<uMaxBack)
+    {
+        uLong uReadSize;
+        ZPOS64_T uReadPos ;
+        int i;
+        if (uBackRead+BUFREADCOMMENT>uMaxBack)
+            uBackRead = uMaxBack;
+        else
+            uBackRead+=BUFREADCOMMENT;
+        uReadPos = uSizeFile-uBackRead ;
+
+        uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
+                     (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos);
+        if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+            break;
+
+        if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
+            break;
+
+        for (i=(int)uReadSize-3; (i--)>0;)
+            if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
+                ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
+            {
+                uPosFound = uReadPos+i;
+                break;
+            }
+
+        if (uPosFound!=0)
+            break;
+    }
+    TRYFREE(buf);
+    return uPosFound;
+}
+
+
+/*
+  Locate the Central directory 64 of a zipfile (at the end, just before
+    the global comment)
+*/
+local ZPOS64_T unz64local_SearchCentralDir64 OF((
+    const zlib_filefunc64_32_def* pzlib_filefunc_def,
+    voidpf filestream));
+
+local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def,
+                                      voidpf filestream)
+{
+    unsigned char* buf;
+    ZPOS64_T uSizeFile;
+    ZPOS64_T uBackRead;
+    ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */
+    ZPOS64_T uPosFound=0;
+    uLong uL;
+                ZPOS64_T relativeOffset;
+
+    if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
+        return 0;
+
+
+    uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);
+
+    if (uMaxBack>uSizeFile)
+        uMaxBack = uSizeFile;
+
+    buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
+    if (buf==NULL)
+        return 0;
+
+    uBackRead = 4;
+    while (uBackRead<uMaxBack)
+    {
+        uLong uReadSize;
+        ZPOS64_T uReadPos;
+        int i;
+        if (uBackRead+BUFREADCOMMENT>uMaxBack)
+            uBackRead = uMaxBack;
+        else
+            uBackRead+=BUFREADCOMMENT;
+        uReadPos = uSizeFile-uBackRead ;
+
+        uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
+                     (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos);
+        if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+            break;
+
+        if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
+            break;
+
+        for (i=(int)uReadSize-3; (i--)>0;)
+            if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
+                ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07))
+            {
+                uPosFound = uReadPos+i;
+                break;
+            }
+
+        if (uPosFound!=0)
+            break;
+    }
+    TRYFREE(buf);
+    if (uPosFound == 0)
+        return 0;
+
+    /* Zip64 end of central directory locator */
+    if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0)
+        return 0;
+
+    /* the signature, already checked */
+    if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
+        return 0;
+
+    /* number of the disk with the start of the zip64 end of  central directory */
+    if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
+        return 0;
+    if (uL != 0)
+        return 0;
+
+    /* relative offset of the zip64 end of central directory record */
+    if (unz64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=UNZ_OK)
+        return 0;
+
+    /* total number of disks */
+    if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
+        return 0;
+    if (uL != 1)
+        return 0;
+
+    /* Goto end of central directory record */
+    if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0)
+        return 0;
+
+     /* the signature */
+    if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
+        return 0;
+
+    if (uL != 0x06064b50)
+        return 0;
+
+    return relativeOffset;
+}
+
+/*
+  Open a Zip file. path contain the full pathname (by example,
+     on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer
+     "zlib/zlib114.zip".
+     If the zipfile cannot be opened (file doesn't exist or in not valid), the
+       return value is NULL.
+     Else, the return value is a unzFile Handle, usable with other function
+       of this unzip package.
+*/
+local unzFile unzOpenInternal (const void *path,
+                               zlib_filefunc64_32_def* pzlib_filefunc64_32_def,
+                               int is64bitOpenFunction)
+{
+    unz64_s us = {0};
+    unz64_s *s;
+    ZPOS64_T central_pos;
+    uLong   uL;
+
+    uLong number_disk;          /* number of the current dist, used for
+                                   spaning ZIP, unsupported, always 0*/
+    uLong number_disk_with_CD;  /* number the the disk with central dir, used
+                                   for spaning ZIP, unsupported, always 0*/
+    ZPOS64_T number_entry_CD;      /* total number of entries in
+                                   the central dir
+                                   (same than number_entry on nospan) */
+
+    int err=UNZ_OK;
+
+    if (unz_copyright[0]!=' ')
+        return NULL;
+
+    us.z_filefunc.zseek32_file = NULL;
+    us.z_filefunc.ztell32_file = NULL;
+    if (pzlib_filefunc64_32_def==NULL)
+        fill_fopen64_filefunc(&us.z_filefunc.zfile_func64);
+    else
+        us.z_filefunc = *pzlib_filefunc64_32_def;
+    us.is64bitOpenFunction = is64bitOpenFunction;
+
+
+
+    us.filestream = ZOPEN64(us.z_filefunc,
+                                                 path,
+                                                 ZLIB_FILEFUNC_MODE_READ |
+                                                 ZLIB_FILEFUNC_MODE_EXISTING);
+    if (us.filestream==NULL)
+        return NULL;
+
+    central_pos = unz64local_SearchCentralDir64(&us.z_filefunc,us.filestream);
+    if (central_pos)
+    {
+        uLong uS;
+        ZPOS64_T uL64;
+
+        us.isZip64 = 1;
+
+        if (ZSEEK64(us.z_filefunc, us.filestream,
+                                      central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+        err=UNZ_ERRNO;
+
+        /* the signature, already checked */
+        if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
+            err=UNZ_ERRNO;
+
+        /* size of zip64 end of central directory record */
+        if (unz64local_getLong64(&us.z_filefunc, us.filestream,&uL64)!=UNZ_OK)
+            err=UNZ_ERRNO;
+
+        /* version made by */
+        if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK)
+            err=UNZ_ERRNO;
+
+        /* version needed to extract */
+        if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK)
+            err=UNZ_ERRNO;
+
+        /* number of this disk */
+        if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
+            err=UNZ_ERRNO;
+
+        /* number of the disk with the start of the central directory */
+        if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
+            err=UNZ_ERRNO;
+
+        /* total number of entries in the central directory on this disk */
+        if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK)
+            err=UNZ_ERRNO;
+
+        /* total number of entries in the central directory */
+        if (unz64local_getLong64(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK)
+            err=UNZ_ERRNO;
+
+        if ((number_entry_CD!=us.gi.number_entry) ||
+            (number_disk_with_CD!=0) ||
+            (number_disk!=0))
+            err=UNZ_BADZIPFILE;
+
+        /* size of the central directory */
+        if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK)
+            err=UNZ_ERRNO;
+
+        /* offset of start of central directory with respect to the
+          starting disk number */
+        if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK)
+            err=UNZ_ERRNO;
+
+        us.gi.size_comment = 0;
+    }
+    else
+    {
+        central_pos = unz64local_SearchCentralDir(&us.z_filefunc,us.filestream);
+        if (central_pos==0)
+            err=UNZ_ERRNO;
+
+        us.isZip64 = 0;
+
+        if (ZSEEK64(us.z_filefunc, us.filestream,
+                                        central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+            err=UNZ_ERRNO;
+
+        /* the signature, already checked */
+        if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
+            err=UNZ_ERRNO;
+
+        /* number of this disk */
+        if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
+            err=UNZ_ERRNO;
+
+        /* number of the disk with the start of the central directory */
+        if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
+            err=UNZ_ERRNO;
+
+        /* total number of entries in the central dir on this disk */
+        if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
+            err=UNZ_ERRNO;
+        us.gi.number_entry = uL;
+
+        /* total number of entries in the central dir */
+        if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
+            err=UNZ_ERRNO;
+        number_entry_CD = uL;
+
+        if ((number_entry_CD!=us.gi.number_entry) ||
+            (number_disk_with_CD!=0) ||
+            (number_disk!=0))
+            err=UNZ_BADZIPFILE;
+
+        /* size of the central directory */
+        if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
+            err=UNZ_ERRNO;
+        us.size_central_dir = uL;
+
+        /* offset of start of central directory with respect to the
+            starting disk number */
+        if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
+            err=UNZ_ERRNO;
+        us.offset_central_dir = uL;
+
+        /* zipfile comment length */
+        if (unz64local_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK)
+            err=UNZ_ERRNO;
+    }
+
+    if ((central_pos<us.offset_central_dir+us.size_central_dir) &&
+        (err==UNZ_OK))
+        err=UNZ_BADZIPFILE;
+
+    if (err!=UNZ_OK)
+    {
+        ZCLOSE64(us.z_filefunc, us.filestream);
+        return NULL;
+    }
+
+    us.byte_before_the_zipfile = central_pos -
+                            (us.offset_central_dir+us.size_central_dir);
+    us.central_pos = central_pos;
+    us.pfile_in_zip_read = NULL;
+    us.encrypted = 0;
+
+
+    s=(unz64_s*)ALLOC(sizeof(unz64_s));
+    if( s != NULL)
+    {
+        *s=us;
+        unzGoToFirstFile((unzFile)s);
+    }
+    return (unzFile)s;
+}
+
+
+extern unzFile ZEXPORT unzOpen2 (const char *path,
+                                        zlib_filefunc_def* pzlib_filefunc32_def)
+{
+    if (pzlib_filefunc32_def != NULL)
+    {
+        zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
+        fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill,pzlib_filefunc32_def);
+        return unzOpenInternal(path, &zlib_filefunc64_32_def_fill, 0);
+    }
+    else
+        return unzOpenInternal(path, NULL, 0);
+}
+
+extern unzFile ZEXPORT unzOpen2_64 (const void *path,
+                                     zlib_filefunc64_def* pzlib_filefunc_def)
+{
+    if (pzlib_filefunc_def != NULL)
+    {
+        zlib_filefunc64_32_def zlib_filefunc64_32_def_fill = {0};
+        zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def;
+        zlib_filefunc64_32_def_fill.ztell32_file = NULL;
+        zlib_filefunc64_32_def_fill.zseek32_file = NULL;
+        return unzOpenInternal(path, &zlib_filefunc64_32_def_fill, 1);
+    }
+    else
+        return unzOpenInternal(path, NULL, 1);
+}
+
+extern unzFile ZEXPORT unzOpen (const char *path)
+{
+    return unzOpenInternal(path, NULL, 0);
+}
+
+extern unzFile ZEXPORT unzOpen64 (const void *path)
+{
+    return unzOpenInternal(path, NULL, 1);
+}
+
+/*
+  Close a ZipFile opened with unzOpen.
+  If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
+    these files MUST be closed with unzCloseCurrentFile before call unzClose.
+  return UNZ_OK if there is no problem. */
+extern int ZEXPORT unzClose (unzFile file)
+{
+    unz64_s* s;
+    if (file==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz64_s*)file;
+
+    if (s->pfile_in_zip_read!=NULL)
+        unzCloseCurrentFile(file);
+
+    ZCLOSE64(s->z_filefunc, s->filestream);
+    TRYFREE(s);
+    return UNZ_OK;
+}
+
+
+/*
+  Write info about the ZipFile in the *pglobal_info structure.
+  No preparation of the structure is needed
+  return UNZ_OK if there is no problem. */
+extern int ZEXPORT unzGetGlobalInfo64 (unzFile file, unz_global_info64* pglobal_info)
+{
+    unz64_s* s;
+    if (file==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz64_s*)file;
+    *pglobal_info=s->gi;
+    return UNZ_OK;
+}
+
+extern int ZEXPORT unzGetGlobalInfo (unzFile file, unz_global_info* pglobal_info32)
+{
+    unz64_s* s;
+    if (file==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz64_s*)file;
+    /* to do : check if number_entry is not truncated */
+    pglobal_info32->number_entry = (uLong)s->gi.number_entry;
+    pglobal_info32->size_comment = s->gi.size_comment;
+    return UNZ_OK;
+}
+/*
+   Translate date/time from Dos format to tm_unz (readable more easilty)
+*/
+local void unz64local_DosDateToTmuDate (ZPOS64_T ulDosDate, tm_unz* ptm)
+{
+    ZPOS64_T uDate;
+    uDate = (ZPOS64_T)(ulDosDate>>16);
+    ptm->tm_mday = (uInt)(uDate&0x1f) ;
+    ptm->tm_mon =  (uInt)((((uDate)&0x1E0)/0x20)-1) ;
+    ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
+
+    ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
+    ptm->tm_min =  (uInt) ((ulDosDate&0x7E0)/0x20) ;
+    ptm->tm_sec =  (uInt) (2*(ulDosDate&0x1f)) ;
+}
+
+/*
+  Get Info about the current file in the zipfile, with internal only info
+*/
+local int unz64local_GetCurrentFileInfoInternal OF((unzFile file,
+                                                  unz_file_info64 *pfile_info,
+                                                  unz_file_info64_internal
+                                                  *pfile_info_internal,
+                                                  char *szFileName,
+                                                  uLong fileNameBufferSize,
+                                                  void *extraField,
+                                                  uLong extraFieldBufferSize,
+                                                  char *szComment,
+                                                  uLong commentBufferSize));
+
+local int unz64local_GetCurrentFileInfoInternal (unzFile file,
+                                                  unz_file_info64 *pfile_info,
+                                                  unz_file_info64_internal
+                                                  *pfile_info_internal,
+                                                  char *szFileName,
+                                                  uLong fileNameBufferSize,
+                                                  void *extraField,
+                                                  uLong extraFieldBufferSize,
+                                                  char *szComment,
+                                                  uLong commentBufferSize)
+{
+    unz64_s* s;
+    unz_file_info64 file_info;
+    unz_file_info64_internal file_info_internal;
+    int err=UNZ_OK;
+    uLong uMagic;
+    long lSeek=0;
+    uLong uL;
+
+    if (file==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz64_s*)file;
+    if (ZSEEK64(s->z_filefunc, s->filestream,
+              s->pos_in_central_dir+s->byte_before_the_zipfile,
+              ZLIB_FILEFUNC_SEEK_SET)!=0)
+        err=UNZ_ERRNO;
+
+
+    /* we check the magic */
+    if (err==UNZ_OK)
+    {
+        if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
+            err=UNZ_ERRNO;
+        else if (uMagic!=0x02014b50)
+            err=UNZ_BADZIPFILE;
+    }
+
+    if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK)
+        err=UNZ_ERRNO;
+
+    if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK)
+        err=UNZ_ERRNO;
+
+    if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK)
+        err=UNZ_ERRNO;
+
+    if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK)
+        err=UNZ_ERRNO;
+
+    if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK)
+        err=UNZ_ERRNO;
+
+    unz64local_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
+
+    if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK)
+        err=UNZ_ERRNO;
+
+    if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
+        err=UNZ_ERRNO;
+    file_info.compressed_size = uL;
+
+    if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
+        err=UNZ_ERRNO;
+    file_info.uncompressed_size = uL;
+
+    if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK)
+        err=UNZ_ERRNO;
+
+    if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK)
+        err=UNZ_ERRNO;
+
+    if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK)
+        err=UNZ_ERRNO;
+
+    if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)
+        err=UNZ_ERRNO;
+
+    if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK)
+        err=UNZ_ERRNO;
+
+    if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK)
+        err=UNZ_ERRNO;
+
+                // relative offset of local header
+    if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
+        err=UNZ_ERRNO;
+    file_info_internal.offset_curfile = uL;
+
+    lSeek+=file_info.size_filename;
+    if ((err==UNZ_OK) && (szFileName!=NULL))
+    {
+        uLong uSizeRead ;
+        if (file_info.size_filename<fileNameBufferSize)
+        {
+            *(szFileName+file_info.size_filename)='\0';
+            uSizeRead = file_info.size_filename;
+        }
+        else
+            uSizeRead = fileNameBufferSize;
+
+        if ((file_info.size_filename>0) && (fileNameBufferSize>0))
+            if (ZREAD64(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead)
+                err=UNZ_ERRNO;
+        lSeek -= uSizeRead;
+    }
+
+    // Read extrafield
+    if ((err==UNZ_OK) && (extraField!=NULL))
+    {
+        ZPOS64_T uSizeRead ;
+        if (file_info.size_file_extra<extraFieldBufferSize)
+            uSizeRead = file_info.size_file_extra;
+        else
+            uSizeRead = extraFieldBufferSize;
+
+        if (lSeek!=0)
+        {
+            if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
+                lSeek=0;
+            else
+                err=UNZ_ERRNO;
+        }
+
+        if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
+            if (ZREAD64(s->z_filefunc, s->filestream,extraField,(uLong)uSizeRead)!=uSizeRead)
+                err=UNZ_ERRNO;
+
+        lSeek += file_info.size_file_extra - (uLong)uSizeRead;
+    }
+    else
+        lSeek += file_info.size_file_extra;
+
+
+    if ((err==UNZ_OK) && (file_info.size_file_extra != 0))
+    {
+                                uLong acc = 0;
+
+        // since lSeek now points to after the extra field we need to move back
+        lSeek -= file_info.size_file_extra;
+
+        if (lSeek!=0)
+        {
+            if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
+                lSeek=0;
+            else
+                err=UNZ_ERRNO;
+        }
+
+        while(acc < file_info.size_file_extra)
+        {
+            uLong headerId;
+                                                uLong dataSize;
+
+            if (unz64local_getShort(&s->z_filefunc, s->filestream,&headerId) != UNZ_OK)
+                err=UNZ_ERRNO;
+
+            if (unz64local_getShort(&s->z_filefunc, s->filestream,&dataSize) != UNZ_OK)
+                err=UNZ_ERRNO;
+
+            /* ZIP64 extra fields */
+            if (headerId == 0x0001)
+            {
+                                                        uLong uL;
+
+                                                                if(file_info.uncompressed_size == MAXU32)
+                                                                {
+                                                                        if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)
+                                                                                        err=UNZ_ERRNO;
+                                                                }
+
+                                                                if(file_info.compressed_size == MAXU32)
+                                                                {
+                                                                        if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)
+                                                                                  err=UNZ_ERRNO;
+                                                                }
+
+                                                                if(file_info_internal.offset_curfile == MAXU32)
+                                                                {
+                                                                        /* Relative Header offset */
+                                                                        if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)
+                                                                                err=UNZ_ERRNO;
+                                                                }
+
+                                                                if(file_info.disk_num_start == MAXU32)
+                                                                {
+                                                                        /* Disk Start Number */
+                                                                        if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
+                                                                                err=UNZ_ERRNO;
+                                                                }
+
+            }
+            else
+            {
+                if (ZSEEK64(s->z_filefunc, s->filestream,dataSize,ZLIB_FILEFUNC_SEEK_CUR)!=0)
+                    err=UNZ_ERRNO;
+            }
+
+            acc += 2 + 2 + dataSize;
+        }
+    }
+
+    if ((err==UNZ_OK) && (szComment!=NULL))
+    {
+        uLong uSizeRead ;
+        if (file_info.size_file_comment<commentBufferSize)
+        {
+            *(szComment+file_info.size_file_comment)='\0';
+            uSizeRead = file_info.size_file_comment;
+        }
+        else
+            uSizeRead = commentBufferSize;
+
+        if (lSeek!=0)
+        {
+            if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
+                lSeek=0;
+            else
+                err=UNZ_ERRNO;
+        }
+
+        if ((file_info.size_file_comment>0) && (commentBufferSize>0))
+            if (ZREAD64(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead)
+                err=UNZ_ERRNO;
+        lSeek+=file_info.size_file_comment - uSizeRead;
+    }
+    else
+        lSeek+=file_info.size_file_comment;
+
+
+    if ((err==UNZ_OK) && (pfile_info!=NULL))
+        *pfile_info=file_info;
+
+    if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
+        *pfile_info_internal=file_info_internal;
+
+    return err;
+}
+
+
+
+/*
+  Write info about the ZipFile in the *pglobal_info structure.
+  No preparation of the structure is needed
+  return UNZ_OK if there is no problem.
+*/
+extern int ZEXPORT unzGetCurrentFileInfo64 (unzFile file,
+                                          unz_file_info64 * pfile_info,
+                                          char * szFileName, uLong fileNameBufferSize,
+                                          void *extraField, uLong extraFieldBufferSize,
+                                          char* szComment,  uLong commentBufferSize)
+{
+    return unz64local_GetCurrentFileInfoInternal(file,pfile_info,NULL,
+                                                szFileName,fileNameBufferSize,
+                                                extraField,extraFieldBufferSize,
+                                                szComment,commentBufferSize);
+}
+
+extern int ZEXPORT unzGetCurrentFileInfo (unzFile file,
+                                          unz_file_info * pfile_info,
+                                          char * szFileName, uLong fileNameBufferSize,
+                                          void *extraField, uLong extraFieldBufferSize,
+                                          char* szComment,  uLong commentBufferSize)
+{
+    int err;
+    unz_file_info64 file_info64;
+    err = unz64local_GetCurrentFileInfoInternal(file,&file_info64,NULL,
+                                                szFileName,fileNameBufferSize,
+                                                extraField,extraFieldBufferSize,
+                                                szComment,commentBufferSize);
+    if ((err==UNZ_OK) && (pfile_info != NULL))
+    {
+        pfile_info->version = file_info64.version;
+        pfile_info->version_needed = file_info64.version_needed;
+        pfile_info->flag = file_info64.flag;
+        pfile_info->compression_method = file_info64.compression_method;
+        pfile_info->dosDate = file_info64.dosDate;
+        pfile_info->crc = file_info64.crc;
+
+        pfile_info->size_filename = file_info64.size_filename;
+        pfile_info->size_file_extra = file_info64.size_file_extra;
+        pfile_info->size_file_comment = file_info64.size_file_comment;
+
+        pfile_info->disk_num_start = file_info64.disk_num_start;
+        pfile_info->internal_fa = file_info64.internal_fa;
+        pfile_info->external_fa = file_info64.external_fa;
+
+        pfile_info->tmu_date = file_info64.tmu_date,
+
+
+        pfile_info->compressed_size = (uLong)file_info64.compressed_size;
+        pfile_info->uncompressed_size = (uLong)file_info64.uncompressed_size;
+
+    }
+    return err;
+}
+/*
+  Set the current file of the zipfile to the first file.
+  return UNZ_OK if there is no problem
+*/
+extern int ZEXPORT unzGoToFirstFile (unzFile file)
+{
+    int err=UNZ_OK;
+    unz64_s* s;
+    if (file==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz64_s*)file;
+    s->pos_in_central_dir=s->offset_central_dir;
+    s->num_file=0;
+    err=unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+                                             &s->cur_file_info_internal,
+                                             NULL,0,NULL,0,NULL,0);
+    s->current_file_ok = (err == UNZ_OK);
+    return err;
+}
+
+/*
+  Set the current file of the zipfile to the next file.
+  return UNZ_OK if there is no problem
+  return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
+*/
+extern int ZEXPORT unzGoToNextFile (unzFile  file)
+{
+    unz64_s* s;
+    int err;
+
+    if (file==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz64_s*)file;
+    if (!s->current_file_ok)
+        return UNZ_END_OF_LIST_OF_FILE;
+    if (s->gi.number_entry != 0xffff)    /* 2^16 files overflow hack */
+      if (s->num_file+1==s->gi.number_entry)
+        return UNZ_END_OF_LIST_OF_FILE;
+
+    s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
+            s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
+    s->num_file++;
+    err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+                                               &s->cur_file_info_internal,
+                                               NULL,0,NULL,0,NULL,0);
+    s->current_file_ok = (err == UNZ_OK);
+    return err;
+}
+
+
+/*
+  Try locate the file szFileName in the zipfile.
+  For the iCaseSensitivity signification, see unzStringFileNameCompare
+
+  return value :
+  UNZ_OK if the file is found. It becomes the current file.
+  UNZ_END_OF_LIST_OF_FILE if the file is not found
+*/
+extern int ZEXPORT unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity)
+{
+    unz64_s* s;
+    int err;
+
+    /* We remember the 'current' position in the file so that we can jump
+     * back there if we fail.
+     */
+    unz_file_info64 cur_file_infoSaved;
+    unz_file_info64_internal cur_file_info_internalSaved;
+    ZPOS64_T num_fileSaved;
+    ZPOS64_T pos_in_central_dirSaved;
+
+
+    if (file==NULL)
+        return UNZ_PARAMERROR;
+
+    if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
+        return UNZ_PARAMERROR;
+
+    s=(unz64_s*)file;
+    if (!s->current_file_ok)
+        return UNZ_END_OF_LIST_OF_FILE;
+
+    /* Save the current state */
+    num_fileSaved = s->num_file;
+    pos_in_central_dirSaved = s->pos_in_central_dir;
+    cur_file_infoSaved = s->cur_file_info;
+    cur_file_info_internalSaved = s->cur_file_info_internal;
+
+    err = unzGoToFirstFile(file);
+
+    while (err == UNZ_OK)
+    {
+        char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
+        err = unzGetCurrentFileInfo64(file,NULL,
+                                    szCurrentFileName,sizeof(szCurrentFileName)-1,
+                                    NULL,0,NULL,0);
+        if (err == UNZ_OK)
+        {
+            if (unzStringFileNameCompare(szCurrentFileName,
+                                            szFileName,iCaseSensitivity)==0)
+                return UNZ_OK;
+            err = unzGoToNextFile(file);
+        }
+    }
+
+    /* We failed, so restore the state of the 'current file' to where we
+     * were.
+     */
+    s->num_file = num_fileSaved ;
+    s->pos_in_central_dir = pos_in_central_dirSaved ;
+    s->cur_file_info = cur_file_infoSaved;
+    s->cur_file_info_internal = cur_file_info_internalSaved;
+    return err;
+}
+
+
+/*
+///////////////////////////////////////////
+// Contributed by Ryan Haksi (mailto://cryogen@infoserve.net)
+// I need random access
+//
+// Further optimization could be realized by adding an ability
+// to cache the directory in memory. The goal being a single
+// comprehensive file read to put the file I need in a memory.
+*/
+
+/*
+typedef struct unz_file_pos_s
+{
+    ZPOS64_T pos_in_zip_directory;   // offset in file
+    ZPOS64_T num_of_file;            // # of file
+} unz_file_pos;
+*/
+
+extern int ZEXPORT unzGetFilePos64(unzFile file, unz64_file_pos*  file_pos)
+{
+    unz64_s* s;
+
+    if (file==NULL || file_pos==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz64_s*)file;
+    if (!s->current_file_ok)
+        return UNZ_END_OF_LIST_OF_FILE;
+
+    file_pos->pos_in_zip_directory  = s->pos_in_central_dir;
+    file_pos->num_of_file           = s->num_file;
+
+    return UNZ_OK;
+}
+
+extern int ZEXPORT unzGetFilePos(
+    unzFile file,
+    unz_file_pos* file_pos)
+{
+    unz64_file_pos file_pos64;
+    int err = unzGetFilePos64(file,&file_pos64);
+    if (err==UNZ_OK)
+    {
+        file_pos->pos_in_zip_directory = (uLong)file_pos64.pos_in_zip_directory;
+        file_pos->num_of_file = (uLong)file_pos64.num_of_file;
+    }
+    return err;
+}
+
+extern int ZEXPORT unzGoToFilePos64(unzFile file, const unz64_file_pos* file_pos)
+{
+    unz64_s* s;
+    int err;
+
+    if (file==NULL || file_pos==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz64_s*)file;
+
+    /* jump to the right spot */
+    s->pos_in_central_dir = file_pos->pos_in_zip_directory;
+    s->num_file           = file_pos->num_of_file;
+
+    /* set the current file */
+    err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+                                               &s->cur_file_info_internal,
+                                               NULL,0,NULL,0,NULL,0);
+    /* return results */
+    s->current_file_ok = (err == UNZ_OK);
+    return err;
+}
+
+extern int ZEXPORT unzGoToFilePos(
+    unzFile file,
+    unz_file_pos* file_pos)
+{
+    unz64_file_pos file_pos64;
+    if (file_pos == NULL)
+        return UNZ_PARAMERROR;
+
+    file_pos64.pos_in_zip_directory = file_pos->pos_in_zip_directory;
+    file_pos64.num_of_file = file_pos->num_of_file;
+    return unzGoToFilePos64(file,&file_pos64);
+}
+
+/*
+// Unzip Helper Functions - should be here?
+///////////////////////////////////////////
+*/
+
+/*
+  Read the local header of the current zipfile
+  Check the coherency of the local header and info in the end of central
+        directory about this file
+  store in *piSizeVar the size of extra info in local header
+        (filename and size of extra field data)
+*/
+local int unz64local_CheckCurrentFileCoherencyHeader (unz64_s* s, uInt* piSizeVar,
+                                                    ZPOS64_T * poffset_local_extrafield,
+                                                    uInt  * psize_local_extrafield)
+{
+    uLong uMagic,uData,uFlags;
+    uLong size_filename;
+    uLong size_extra_field;
+    int err=UNZ_OK;
+
+    *piSizeVar = 0;
+    *poffset_local_extrafield = 0;
+    *psize_local_extrafield = 0;
+
+    if (ZSEEK64(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile +
+                                s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
+        return UNZ_ERRNO;
+
+
+    if (err==UNZ_OK)
+    {
+        if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
+            err=UNZ_ERRNO;
+        else if (uMagic!=0x04034b50)
+            err=UNZ_BADZIPFILE;
+    }
+
+    if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
+        err=UNZ_ERRNO;
+/*
+    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
+        err=UNZ_BADZIPFILE;
+*/
+    if (unz64local_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK)
+        err=UNZ_ERRNO;
+
+    if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
+        err=UNZ_ERRNO;
+    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
+        err=UNZ_BADZIPFILE;
+
+    if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
+/* #ifdef HAVE_BZIP2 */
+                         (s->cur_file_info.compression_method!=Z_BZIP2ED) &&
+/* #endif */
+                         (s->cur_file_info.compression_method!=Z_DEFLATED))
+        err=UNZ_BADZIPFILE;
+
+    if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */
+        err=UNZ_ERRNO;
+
+    if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */
+        err=UNZ_ERRNO;
+    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && ((uFlags & 8)==0))
+        err=UNZ_BADZIPFILE;
+
+    if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */
+        err=UNZ_ERRNO;
+    else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && ((uFlags & 8)==0))
+        err=UNZ_BADZIPFILE;
+
+    if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */
+        err=UNZ_ERRNO;
+    else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && ((uFlags & 8)==0))
+        err=UNZ_BADZIPFILE;
+
+    if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK)
+        err=UNZ_ERRNO;
+    else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
+        err=UNZ_BADZIPFILE;
+
+    *piSizeVar += (uInt)size_filename;
+
+    if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK)
+        err=UNZ_ERRNO;
+    *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
+                                    SIZEZIPLOCALHEADER + size_filename;
+    *psize_local_extrafield = (uInt)size_extra_field;
+
+    *piSizeVar += (uInt)size_extra_field;
+
+    return err;
+}
+
+/*
+  Open for reading data the current file in the zipfile.
+  If there is no error and the file is opened, the return value is UNZ_OK.
+*/
+extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method,
+                                            int* level, int raw, const char* password)
+{
+    int err=UNZ_OK;
+    uInt iSizeVar;
+    unz64_s* s;
+    file_in_zip64_read_info_s* pfile_in_zip_read_info;
+    ZPOS64_T offset_local_extrafield;  /* offset of the local extra field */
+    uInt  size_local_extrafield;    /* size of the local extra field */
+#    ifndef NOUNCRYPT
+    char source[12];
+#    else
+    if (password != NULL)
+        return UNZ_PARAMERROR;
+#    endif
+
+    if (file==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz64_s*)file;
+    if (!s->current_file_ok)
+        return UNZ_PARAMERROR;
+
+    if (s->pfile_in_zip_read != NULL)
+        unzCloseCurrentFile(file);
+
+    if (unz64local_CheckCurrentFileCoherencyHeader(s,&iSizeVar, &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
+        return UNZ_BADZIPFILE;
+
+    pfile_in_zip_read_info = (file_in_zip64_read_info_s*)ALLOC(sizeof(file_in_zip64_read_info_s));
+    if (pfile_in_zip_read_info==NULL)
+        return UNZ_INTERNALERROR;
+
+    pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
+    pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
+    pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
+    pfile_in_zip_read_info->pos_local_extrafield=0;
+    pfile_in_zip_read_info->raw=raw;
+
+    if (pfile_in_zip_read_info->read_buffer==NULL)
+    {
+        TRYFREE(pfile_in_zip_read_info);
+        return UNZ_INTERNALERROR;
+    }
+
+    pfile_in_zip_read_info->stream_initialised=0;
+
+    if (method!=NULL)
+        *method = (int)s->cur_file_info.compression_method;
+
+    if (level!=NULL)
+    {
+        *level = 6;
+        switch (s->cur_file_info.flag & 0x06)
+        {
+          case 6 : *level = 1; break;
+          case 4 : *level = 2; break;
+          case 2 : *level = 9; break;
+        }
+    }
+
+    if ((s->cur_file_info.compression_method!=0) &&
+/* #ifdef HAVE_BZIP2 */
+        (s->cur_file_info.compression_method!=Z_BZIP2ED) &&
+/* #endif */
+        (s->cur_file_info.compression_method!=Z_DEFLATED))
+
+        err=UNZ_BADZIPFILE;
+
+    pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
+    pfile_in_zip_read_info->crc32=0;
+    pfile_in_zip_read_info->total_out_64=0;
+    pfile_in_zip_read_info->compression_method = s->cur_file_info.compression_method;
+    pfile_in_zip_read_info->filestream=s->filestream;
+    pfile_in_zip_read_info->z_filefunc=s->z_filefunc;
+    pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
+
+    pfile_in_zip_read_info->stream.total_out = 0;
+
+    if ((s->cur_file_info.compression_method==Z_BZIP2ED) && (!raw))
+    {
+#ifdef HAVE_BZIP2
+      pfile_in_zip_read_info->bstream.bzalloc = (void *(*) (void *, int, int))0;
+      pfile_in_zip_read_info->bstream.bzfree = (free_func)0;
+      pfile_in_zip_read_info->bstream.opaque = (voidpf)0;
+      pfile_in_zip_read_info->bstream.state = (voidpf)0;
+
+      pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
+      pfile_in_zip_read_info->stream.zfree = (free_func)0;
+      pfile_in_zip_read_info->stream.opaque = (voidpf)0;
+      pfile_in_zip_read_info->stream.next_in = (voidpf)0;
+      pfile_in_zip_read_info->stream.avail_in = 0;
+
+      err=BZ2_bzDecompressInit(&pfile_in_zip_read_info->bstream, 0, 0);
+      if (err == Z_OK)
+        pfile_in_zip_read_info->stream_initialised=Z_BZIP2ED;
+      else
+      {
+        TRYFREE(pfile_in_zip_read_info);
+        return err;
+      }
+#else
+      pfile_in_zip_read_info->raw=1;
+#endif
+    }
+    else if ((s->cur_file_info.compression_method==Z_DEFLATED) && (!raw))
+    {
+      pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
+      pfile_in_zip_read_info->stream.zfree = (free_func)0;
+      pfile_in_zip_read_info->stream.opaque = (voidpf)0;
+      pfile_in_zip_read_info->stream.next_in = 0;
+      pfile_in_zip_read_info->stream.avail_in = 0;
+
+      err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
+      if (err == Z_OK)
+        pfile_in_zip_read_info->stream_initialised=Z_DEFLATED;
+      else
+      {
+	  	TRYFREE(pfile_in_zip_read_info->read_buffer);
+        TRYFREE(pfile_in_zip_read_info);
+        return err;
+      }
+        /* windowBits is passed < 0 to tell that there is no zlib header.
+         * Note that in this case inflate *requires* an extra "dummy" byte
+         * after the compressed stream in order to complete decompression and
+         * return Z_STREAM_END.
+         * In unzip, i don't wait absolutely Z_STREAM_END because I known the
+         * size of both compressed and uncompressed data
+         */
+    }
+    pfile_in_zip_read_info->rest_read_compressed =
+            s->cur_file_info.compressed_size ;
+    pfile_in_zip_read_info->rest_read_uncompressed =
+            s->cur_file_info.uncompressed_size ;
+
+
+    pfile_in_zip_read_info->pos_in_zipfile =
+            s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
+              iSizeVar;
+
+    pfile_in_zip_read_info->stream.avail_in = (uInt)0;
+
+    s->pfile_in_zip_read = pfile_in_zip_read_info;
+                s->encrypted = 0;
+
+#    ifndef NOUNCRYPT
+    if (password != NULL)
+    {
+        int i;
+        s->pcrc_32_tab = get_crc_table();
+        init_keys(password,s->keys,s->pcrc_32_tab);
+        if (ZSEEK64(s->z_filefunc, s->filestream,
+                  s->pfile_in_zip_read->pos_in_zipfile +
+                     s->pfile_in_zip_read->byte_before_the_zipfile,
+                  SEEK_SET)!=0)
+            return UNZ_INTERNALERROR;
+        if(ZREAD64(s->z_filefunc, s->filestream,source, 12)<12)
+            return UNZ_INTERNALERROR;
+
+        for (i = 0; i<12; i++)
+            zdecode(s->keys,s->pcrc_32_tab,source[i]);
+
+        s->pfile_in_zip_read->pos_in_zipfile+=12;
+        s->encrypted=1;
+    }
+#    endif
+
+
+    return UNZ_OK;
+}
+
+extern int ZEXPORT unzOpenCurrentFile (unzFile file)
+{
+    return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
+}
+
+extern int ZEXPORT unzOpenCurrentFilePassword (unzFile file, const char*  password)
+{
+    return unzOpenCurrentFile3(file, NULL, NULL, 0, password);
+}
+
+extern int ZEXPORT unzOpenCurrentFile2 (unzFile file, int* method, int* level, int raw)
+{
+    return unzOpenCurrentFile3(file, method, level, raw, NULL);
+}
+
+/** Addition for GDAL : START */
+
+extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64( unzFile file)
+{
+    unz64_s* s;
+    file_in_zip64_read_info_s* pfile_in_zip_read_info;
+    s=(unz64_s*)file;
+    if (file==NULL)
+        return 0; //UNZ_PARAMERROR;
+    pfile_in_zip_read_info=s->pfile_in_zip_read;
+    if (pfile_in_zip_read_info==NULL)
+        return 0; //UNZ_PARAMERROR;
+    return pfile_in_zip_read_info->pos_in_zipfile +
+                         pfile_in_zip_read_info->byte_before_the_zipfile;
+}
+
+/** Addition for GDAL : END */
+
+/*
+  Read bytes from the current file.
+  buf contain buffer where data must be copied
+  len the size of buf.
+
+  return the number of byte copied if somes bytes are copied
+  return 0 if the end of file was reached
+  return <0 with error code if there is an error
+    (UNZ_ERRNO for IO error, or zLib error for uncompress error)
+*/
+extern int ZEXPORT unzReadCurrentFile  (unzFile file, voidp buf, unsigned len)
+{
+    int err=UNZ_OK;
+    uInt iRead = 0;
+    unz64_s* s;
+    file_in_zip64_read_info_s* pfile_in_zip_read_info;
+    if (file==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz64_s*)file;
+    pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+    if (pfile_in_zip_read_info==NULL)
+        return UNZ_PARAMERROR;
+
+
+    if (pfile_in_zip_read_info->read_buffer == NULL)
+        return UNZ_END_OF_LIST_OF_FILE;
+    if (len==0)
+        return 0;
+
+    pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
+
+    pfile_in_zip_read_info->stream.avail_out = (uInt)len;
+
+    if ((len>pfile_in_zip_read_info->rest_read_uncompressed) &&
+        (!(pfile_in_zip_read_info->raw)))
+        pfile_in_zip_read_info->stream.avail_out =
+            (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
+
+    if ((len>pfile_in_zip_read_info->rest_read_compressed+
+           pfile_in_zip_read_info->stream.avail_in) &&
+         (pfile_in_zip_read_info->raw))
+        pfile_in_zip_read_info->stream.avail_out =
+            (uInt)pfile_in_zip_read_info->rest_read_compressed+
+            pfile_in_zip_read_info->stream.avail_in;
+
+    while (pfile_in_zip_read_info->stream.avail_out>0)
+    {
+        if ((pfile_in_zip_read_info->stream.avail_in==0) &&
+            (pfile_in_zip_read_info->rest_read_compressed>0))
+        {
+            uInt uReadThis = UNZ_BUFSIZE;
+            if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
+                uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
+            if (uReadThis == 0)
+                return UNZ_EOF;
+            if (ZSEEK64(pfile_in_zip_read_info->z_filefunc,
+                      pfile_in_zip_read_info->filestream,
+                      pfile_in_zip_read_info->pos_in_zipfile +
+                         pfile_in_zip_read_info->byte_before_the_zipfile,
+                         ZLIB_FILEFUNC_SEEK_SET)!=0)
+                return UNZ_ERRNO;
+            if (ZREAD64(pfile_in_zip_read_info->z_filefunc,
+                      pfile_in_zip_read_info->filestream,
+                      pfile_in_zip_read_info->read_buffer,
+                      uReadThis)!=uReadThis)
+                return UNZ_ERRNO;
+
+
+#            ifndef NOUNCRYPT
+            if(s->encrypted)
+            {
+                uInt i;
+                for(i=0;i<uReadThis;i++)
+                  pfile_in_zip_read_info->read_buffer[i] =
+                      zdecode(s->keys,s->pcrc_32_tab,
+                              pfile_in_zip_read_info->read_buffer[i]);
+            }
+#            endif
+
+
+            pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
+
+            pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
+
+            pfile_in_zip_read_info->stream.next_in =
+                (Bytef*)pfile_in_zip_read_info->read_buffer;
+            pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
+        }
+
+        if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw))
+        {
+            uInt uDoCopy,i ;
+
+            if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
+                (pfile_in_zip_read_info->rest_read_compressed == 0))
+                return (iRead==0) ? UNZ_EOF : iRead;
+
+            if (pfile_in_zip_read_info->stream.avail_out <
+                            pfile_in_zip_read_info->stream.avail_in)
+                uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
+            else
+                uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
+
+            for (i=0;i<uDoCopy;i++)
+                *(pfile_in_zip_read_info->stream.next_out+i) =
+                        *(pfile_in_zip_read_info->stream.next_in+i);
+
+            pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uDoCopy;
+
+            pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
+                                pfile_in_zip_read_info->stream.next_out,
+                                uDoCopy);
+            pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
+            pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
+            pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
+            pfile_in_zip_read_info->stream.next_out += uDoCopy;
+            pfile_in_zip_read_info->stream.next_in += uDoCopy;
+            pfile_in_zip_read_info->stream.total_out += uDoCopy;
+            iRead += uDoCopy;
+        }
+        else if (pfile_in_zip_read_info->compression_method==Z_BZIP2ED)
+        {
+#ifdef HAVE_BZIP2
+            uLong uTotalOutBefore,uTotalOutAfter;
+            const Bytef *bufBefore;
+            uLong uOutThis;
+
+            pfile_in_zip_read_info->bstream.next_in        = (char*)pfile_in_zip_read_info->stream.next_in;
+            pfile_in_zip_read_info->bstream.avail_in       = pfile_in_zip_read_info->stream.avail_in;
+            pfile_in_zip_read_info->bstream.total_in_lo32  = pfile_in_zip_read_info->stream.total_in;
+            pfile_in_zip_read_info->bstream.total_in_hi32  = 0;
+            pfile_in_zip_read_info->bstream.next_out       = (char*)pfile_in_zip_read_info->stream.next_out;
+            pfile_in_zip_read_info->bstream.avail_out      = pfile_in_zip_read_info->stream.avail_out;
+            pfile_in_zip_read_info->bstream.total_out_lo32 = pfile_in_zip_read_info->stream.total_out;
+            pfile_in_zip_read_info->bstream.total_out_hi32 = 0;
+
+            uTotalOutBefore = pfile_in_zip_read_info->bstream.total_out_lo32;
+            bufBefore = (const Bytef *)pfile_in_zip_read_info->bstream.next_out;
+
+            err=BZ2_bzDecompress(&pfile_in_zip_read_info->bstream);
+
+            uTotalOutAfter = pfile_in_zip_read_info->bstream.total_out_lo32;
+            uOutThis = uTotalOutAfter-uTotalOutBefore;
+
+            pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis;
+
+            pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,bufBefore, (uInt)(uOutThis));
+            pfile_in_zip_read_info->rest_read_uncompressed -= uOutThis;
+            iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
+
+            pfile_in_zip_read_info->stream.next_in   = (Bytef*)pfile_in_zip_read_info->bstream.next_in;
+            pfile_in_zip_read_info->stream.avail_in  = pfile_in_zip_read_info->bstream.avail_in;
+            pfile_in_zip_read_info->stream.total_in  = pfile_in_zip_read_info->bstream.total_in_lo32;
+            pfile_in_zip_read_info->stream.next_out  = (Bytef*)pfile_in_zip_read_info->bstream.next_out;
+            pfile_in_zip_read_info->stream.avail_out = pfile_in_zip_read_info->bstream.avail_out;
+            pfile_in_zip_read_info->stream.total_out = pfile_in_zip_read_info->bstream.total_out_lo32;
+
+            if (err==BZ_STREAM_END)
+              return (iRead==0) ? UNZ_EOF : iRead;
+            if (err!=BZ_OK)
+              break;
+#endif
+        } // end Z_BZIP2ED
+        else
+        {
+            ZPOS64_T uTotalOutBefore,uTotalOutAfter;
+            const Bytef *bufBefore;
+            ZPOS64_T uOutThis;
+            int flush=Z_SYNC_FLUSH;
+
+            uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
+            bufBefore = pfile_in_zip_read_info->stream.next_out;
+
+            /*
+            if ((pfile_in_zip_read_info->rest_read_uncompressed ==
+                     pfile_in_zip_read_info->stream.avail_out) &&
+                (pfile_in_zip_read_info->rest_read_compressed == 0))
+                flush = Z_FINISH;
+            */
+            err=inflate(&pfile_in_zip_read_info->stream,flush);
+
+            if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL))
+              err = Z_DATA_ERROR;
+
+            uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
+            uOutThis = uTotalOutAfter-uTotalOutBefore;
+
+            pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis;
+
+            pfile_in_zip_read_info->crc32 =
+                crc32(pfile_in_zip_read_info->crc32,bufBefore,
+                        (uInt)(uOutThis));
+
+            pfile_in_zip_read_info->rest_read_uncompressed -=
+                uOutThis;
+
+            iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
+
+            if (err==Z_STREAM_END)
+                return (iRead==0) ? UNZ_EOF : iRead;
+            if (err!=Z_OK)
+                break;
+        }
+    }
+
+    if (err==Z_OK)
+        return iRead;
+    return err;
+}
+
+
+/*
+  Give the current position in uncompressed data
+*/
+extern z_off_t ZEXPORT unztell (unzFile file)
+{
+    unz64_s* s;
+    file_in_zip64_read_info_s* pfile_in_zip_read_info;
+    if (file==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz64_s*)file;
+    pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+    if (pfile_in_zip_read_info==NULL)
+        return UNZ_PARAMERROR;
+
+    return (z_off_t)pfile_in_zip_read_info->stream.total_out;
+}
+
+extern ZPOS64_T ZEXPORT unztell64 (unzFile file)
+{
+
+    unz64_s* s;
+    file_in_zip64_read_info_s* pfile_in_zip_read_info;
+    if (file==NULL)
+        return (ZPOS64_T)-1;
+    s=(unz64_s*)file;
+    pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+    if (pfile_in_zip_read_info==NULL)
+        return (ZPOS64_T)-1;
+
+    return pfile_in_zip_read_info->total_out_64;
+}
+
+
+/*
+  return 1 if the end of file was reached, 0 elsewhere
+*/
+extern int ZEXPORT unzeof (unzFile file)
+{
+    unz64_s* s;
+    file_in_zip64_read_info_s* pfile_in_zip_read_info;
+    if (file==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz64_s*)file;
+    pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+    if (pfile_in_zip_read_info==NULL)
+        return UNZ_PARAMERROR;
+
+    if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
+        return 1;
+    else
+        return 0;
+}
+
+
+
+/*
+Read extra field from the current file (opened by unzOpenCurrentFile)
+This is the local-header version of the extra field (sometimes, there is
+more info in the local-header version than in the central-header)
+
+  if buf==NULL, it return the size of the local extra field that can be read
+
+  if buf!=NULL, len is the size of the buffer, the extra header is copied in
+    buf.
+  the return value is the number of bytes copied in buf, or (if <0)
+    the error code
+*/
+extern int ZEXPORT unzGetLocalExtrafield (unzFile file, voidp buf, unsigned len)
+{
+    unz64_s* s;
+    file_in_zip64_read_info_s* pfile_in_zip_read_info;
+    uInt read_now;
+    ZPOS64_T size_to_read;
+
+    if (file==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz64_s*)file;
+    pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+    if (pfile_in_zip_read_info==NULL)
+        return UNZ_PARAMERROR;
+
+    size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
+                pfile_in_zip_read_info->pos_local_extrafield);
+
+    if (buf==NULL)
+        return (int)size_to_read;
+
+    if (len>size_to_read)
+        read_now = (uInt)size_to_read;
+    else
+        read_now = (uInt)len ;
+
+    if (read_now==0)
+        return 0;
+
+    if (ZSEEK64(pfile_in_zip_read_info->z_filefunc,
+              pfile_in_zip_read_info->filestream,
+              pfile_in_zip_read_info->offset_local_extrafield +
+              pfile_in_zip_read_info->pos_local_extrafield,
+              ZLIB_FILEFUNC_SEEK_SET)!=0)
+        return UNZ_ERRNO;
+
+    if (ZREAD64(pfile_in_zip_read_info->z_filefunc,
+              pfile_in_zip_read_info->filestream,
+              buf,read_now)!=read_now)
+        return UNZ_ERRNO;
+
+    return (int)read_now;
+}
+
+/*
+  Close the file in zip opened with unzOpenCurrentFile
+  Return UNZ_CRCERROR if all the file was read but the CRC is not good
+*/
+extern int ZEXPORT unzCloseCurrentFile (unzFile file)
+{
+    int err=UNZ_OK;
+
+    unz64_s* s;
+    file_in_zip64_read_info_s* pfile_in_zip_read_info;
+    if (file==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz64_s*)file;
+    pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+    if (pfile_in_zip_read_info==NULL)
+        return UNZ_PARAMERROR;
+
+
+    if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&
+        (!pfile_in_zip_read_info->raw))
+    {
+        if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
+            err=UNZ_CRCERROR;
+    }
+
+
+    TRYFREE(pfile_in_zip_read_info->read_buffer);
+    pfile_in_zip_read_info->read_buffer = NULL;
+    if (pfile_in_zip_read_info->stream_initialised == Z_DEFLATED)
+        inflateEnd(&pfile_in_zip_read_info->stream);
+#ifdef HAVE_BZIP2
+    else if (pfile_in_zip_read_info->stream_initialised == Z_BZIP2ED)
+        BZ2_bzDecompressEnd(&pfile_in_zip_read_info->bstream);
+#endif
+
+
+    pfile_in_zip_read_info->stream_initialised = 0;
+    TRYFREE(pfile_in_zip_read_info);
+
+    s->pfile_in_zip_read=NULL;
+
+    return err;
+}
+
+
+/*
+  Get the global comment string of the ZipFile, in the szComment buffer.
+  uSizeBuf is the size of the szComment buffer.
+  return the number of byte copied or an error code <0
+*/
+extern int ZEXPORT unzGetGlobalComment (unzFile file, char * szComment, uLong uSizeBuf)
+{
+    unz64_s* s;
+    uLong uReadThis ;
+    if (file==NULL)
+        return (int)UNZ_PARAMERROR;
+    s=(unz64_s*)file;
+
+    uReadThis = uSizeBuf;
+    if (uReadThis>s->gi.size_comment)
+        uReadThis = s->gi.size_comment;
+
+    if (ZSEEK64(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0)
+        return UNZ_ERRNO;
+
+    if (uReadThis>0)
+    {
+      *szComment='\0';
+      if (ZREAD64(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis)
+        return UNZ_ERRNO;
+    }
+
+    if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
+        *(szComment+s->gi.size_comment)='\0';
+    return (int)uReadThis;
+}
+
+/* Additions by RX '2004 */
+extern ZPOS64_T ZEXPORT unzGetOffset64(unzFile file)
+{
+    unz64_s* s;
+
+    if (file==NULL)
+          return 0; //UNZ_PARAMERROR;
+    s=(unz64_s*)file;
+    if (!s->current_file_ok)
+      return 0;
+    if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff)
+      if (s->num_file==s->gi.number_entry)
+         return 0;
+    return s->pos_in_central_dir;
+}
+
+extern uLong ZEXPORT unzGetOffset (unzFile file)
+{
+    ZPOS64_T offset64;
+
+    if (file==NULL)
+          return 0; //UNZ_PARAMERROR;
+    offset64 = unzGetOffset64(file);
+    return (uLong)offset64;
+}
+
+extern int ZEXPORT unzSetOffset64(unzFile file, ZPOS64_T pos)
+{
+    unz64_s* s;
+    int err;
+
+    if (file==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz64_s*)file;
+
+    s->pos_in_central_dir = pos;
+    s->num_file = s->gi.number_entry;      /* hack */
+    err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+                                              &s->cur_file_info_internal,
+                                              NULL,0,NULL,0,NULL,0);
+    s->current_file_ok = (err == UNZ_OK);
+    return err;
+}
+
+extern int ZEXPORT unzSetOffset (unzFile file, uLong pos)
+{
+    return unzSetOffset64(file,pos);
+}
+
+#ifdef WEB_ZIP_MEM_DEBUG
+
+typedef struct zip_node
+{
+  struct zip_node *next;
+  unsigned int len;
+  void* ptr;
+}t_zip_node;
+
+t_zip_node zip_list ={0};
+
+static void* web_malloc(unsigned int bytes)
+{
+	t_zip_node *node = (t_zip_node *)malloc(sizeof(t_zip_node));
+	if(node == NULL)
+		return NULL;
+	node->ptr = malloc(bytes);
+	if(node->ptr == NULL)
+	{
+		free(node);
+		return NULL;
+	}
+	node->next = NULL;
+	node->len = bytes;
+	t_zip_node *list = &zip_list;
+	while(list->next != NULL)
+	{
+		list = list->next;
+	}
+	list->next = node;
+	return node->ptr;
+}
+
+#ifndef assert
+extern unsigned int sleep (unsigned int __seconds);
+#define assert(cond) {if(!(cond)){while(1){printf("zip assert\n");sleep(1);}}}
+#endif
+
+static void web_free(void* mem)
+{
+	t_zip_node *list = &zip_list;
+	t_zip_node *temp;
+	assert(list->next);
+	while(list->next->ptr != mem)
+	{
+		list = list->next;
+		assert(list->next);
+	}
+	temp = list->next;
+	list->next = list->next->next;
+	free(temp);
+	free(mem);
+}
+
+void print_zip_mem(void)
+{
+	t_zip_node *list = &zip_list;
+	int num = -1;
+	unsigned int len = 0;
+	do
+	{
+		len += list->len;
+		num++;
+		list = list->next;
+	}
+	while(list != NULL);
+	printf("num=%d,total=%d\n",num,len);
+	return;
+}
+
+#endif
+
diff --git a/ap/app/goahead/server/unzip.h b/ap/app/goahead/server/unzip.h
new file mode 100644
index 0000000..2104e39
--- /dev/null
+++ b/ap/app/goahead/server/unzip.h
@@ -0,0 +1,437 @@
+/* unzip.h -- IO for uncompress .zip files using zlib
+   Version 1.1, February 14h, 2010
+   part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
+
+         Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
+
+         Modifications of Unzip for Zip64
+         Copyright (C) 2007-2008 Even Rouault
+
+         Modifications for Zip64 support on both zip and unzip
+         Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
+
+         For more info read MiniZip_info.txt
+
+         ---------------------------------------------------------------------------------
+
+        Condition of use and distribution are the same than zlib :
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  ---------------------------------------------------------------------------------
+
+        Changes
+
+        See header of unzip64.c
+
+*/
+
+#ifndef _unz64_H
+#define _unz64_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _ZLIB_H
+#include "zlib.h"
+#endif
+
+#ifndef  _ZLIBIOAPI_H
+#include "ioapi.h"
+#endif
+
+#ifdef HAVE_BZIP2
+#include "bzlib.h"
+#endif
+
+#define Z_BZIP2ED 12
+
+#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP)
+/* like the STRICT of WIN32, we define a pointer that cannot be converted
+    from (void*) without cast */
+typedef struct TagunzFile__ { int unused; } unzFile__;
+typedef unzFile__ *unzFile;
+#else
+typedef voidp unzFile;
+#endif
+
+
+#define UNZ_OK                          (0)
+#define UNZ_END_OF_LIST_OF_FILE         (-100)
+#define UNZ_ERRNO                       (Z_ERRNO)
+#define UNZ_EOF                         (0)
+#define UNZ_PARAMERROR                  (-102)
+#define UNZ_BADZIPFILE                  (-103)
+#define UNZ_INTERNALERROR               (-104)
+#define UNZ_CRCERROR                    (-105)
+
+/* tm_unz contain date/time info */
+typedef struct tm_unz_s
+{
+    uInt tm_sec;            /* seconds after the minute - [0,59] */
+    uInt tm_min;            /* minutes after the hour - [0,59] */
+    uInt tm_hour;           /* hours since midnight - [0,23] */
+    uInt tm_mday;           /* day of the month - [1,31] */
+    uInt tm_mon;            /* months since January - [0,11] */
+    uInt tm_year;           /* years - [1980..2044] */
+} tm_unz;
+
+/* unz_global_info structure contain global data about the ZIPfile
+   These data comes from the end of central dir */
+typedef struct unz_global_info64_s
+{
+    ZPOS64_T number_entry;         /* total number of entries in
+                                     the central dir on this disk */
+    uLong size_comment;         /* size of the global comment of the zipfile */
+} unz_global_info64;
+
+typedef struct unz_global_info_s
+{
+    uLong number_entry;         /* total number of entries in
+                                     the central dir on this disk */
+    uLong size_comment;         /* size of the global comment of the zipfile */
+} unz_global_info;
+
+/* unz_file_info contain information about a file in the zipfile */
+typedef struct unz_file_info64_s
+{
+    uLong version;              /* version made by                 2 bytes */
+    uLong version_needed;       /* version needed to extract       2 bytes */
+    uLong flag;                 /* general purpose bit flag        2 bytes */
+    uLong compression_method;   /* compression method              2 bytes */
+    uLong dosDate;              /* last mod file date in Dos fmt   4 bytes */
+    uLong crc;                  /* crc-32                          4 bytes */
+    ZPOS64_T compressed_size;   /* compressed size                 8 bytes */
+    ZPOS64_T uncompressed_size; /* uncompressed size               8 bytes */
+    uLong size_filename;        /* filename length                 2 bytes */
+    uLong size_file_extra;      /* extra field length              2 bytes */
+    uLong size_file_comment;    /* file comment length             2 bytes */
+
+    uLong disk_num_start;       /* disk number start               2 bytes */
+    uLong internal_fa;          /* internal file attributes        2 bytes */
+    uLong external_fa;          /* external file attributes        4 bytes */
+
+    tm_unz tmu_date;
+} unz_file_info64;
+
+typedef struct unz_file_info_s
+{
+    uLong version;              /* version made by                 2 bytes */
+    uLong version_needed;       /* version needed to extract       2 bytes */
+    uLong flag;                 /* general purpose bit flag        2 bytes */
+    uLong compression_method;   /* compression method              2 bytes */
+    uLong dosDate;              /* last mod file date in Dos fmt   4 bytes */
+    uLong crc;                  /* crc-32                          4 bytes */
+    uLong compressed_size;      /* compressed size                 4 bytes */
+    uLong uncompressed_size;    /* uncompressed size               4 bytes */
+    uLong size_filename;        /* filename length                 2 bytes */
+    uLong size_file_extra;      /* extra field length              2 bytes */
+    uLong size_file_comment;    /* file comment length             2 bytes */
+
+    uLong disk_num_start;       /* disk number start               2 bytes */
+    uLong internal_fa;          /* internal file attributes        2 bytes */
+    uLong external_fa;          /* external file attributes        4 bytes */
+
+    tm_unz tmu_date;
+} unz_file_info;
+
+extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1,
+                                                 const char* fileName2,
+                                                 int iCaseSensitivity));
+/*
+   Compare two filename (fileName1,fileName2).
+   If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
+   If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
+                                or strcasecmp)
+   If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
+    (like 1 on Unix, 2 on Windows)
+*/
+
+
+extern unzFile ZEXPORT unzOpen OF((const char *path));
+extern unzFile ZEXPORT unzOpen64 OF((const void *path));
+/*
+  Open a Zip file. path contain the full pathname (by example,
+     on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer
+     "zlib/zlib113.zip".
+     If the zipfile cannot be opened (file don't exist or in not valid), the
+       return value is NULL.
+     Else, the return value is a unzFile Handle, usable with other function
+       of this unzip package.
+     the "64" function take a const void* pointer, because the path is just the
+       value passed to the open64_file_func callback.
+     Under Windows, if UNICODE is defined, using fill_fopen64_filefunc, the path
+       is a pointer to a wide unicode string (LPCTSTR is LPCWSTR), so const char*
+       does not describe the reality
+*/
+
+
+extern unzFile ZEXPORT unzOpen2 OF((const char *path,
+                                    zlib_filefunc_def* pzlib_filefunc_def));
+/*
+   Open a Zip file, like unzOpen, but provide a set of file low level API
+      for read/write the zip file (see ioapi.h)
+*/
+
+extern unzFile ZEXPORT unzOpen2_64 OF((const void *path,
+                                    zlib_filefunc64_def* pzlib_filefunc_def));
+/*
+   Open a Zip file, like unz64Open, but provide a set of file low level API
+      for read/write the zip file (see ioapi.h)
+*/
+
+extern int ZEXPORT unzClose OF((unzFile file));
+/*
+  Close a ZipFile opened with unzOpen.
+  If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
+    these files MUST be closed with unzCloseCurrentFile before call unzClose.
+  return UNZ_OK if there is no problem. */
+
+extern int ZEXPORT unzGetGlobalInfo OF((unzFile file,
+                                        unz_global_info *pglobal_info));
+
+extern int ZEXPORT unzGetGlobalInfo64 OF((unzFile file,
+                                        unz_global_info64 *pglobal_info));
+/*
+  Write info about the ZipFile in the *pglobal_info structure.
+  No preparation of the structure is needed
+  return UNZ_OK if there is no problem. */
+
+
+extern int ZEXPORT unzGetGlobalComment OF((unzFile file,
+                                           char *szComment,
+                                           uLong uSizeBuf));
+/*
+  Get the global comment string of the ZipFile, in the szComment buffer.
+  uSizeBuf is the size of the szComment buffer.
+  return the number of byte copied or an error code <0
+*/
+
+
+/***************************************************************************/
+/* Unzip package allow you browse the directory of the zipfile */
+
+extern int ZEXPORT unzGoToFirstFile OF((unzFile file));
+/*
+  Set the current file of the zipfile to the first file.
+  return UNZ_OK if there is no problem
+*/
+
+extern int ZEXPORT unzGoToNextFile OF((unzFile file));
+/*
+  Set the current file of the zipfile to the next file.
+  return UNZ_OK if there is no problem
+  return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
+*/
+
+extern int ZEXPORT unzLocateFile OF((unzFile file,
+                     const char *szFileName,
+                     int iCaseSensitivity));
+/*
+  Try locate the file szFileName in the zipfile.
+  For the iCaseSensitivity signification, see unzStringFileNameCompare
+
+  return value :
+  UNZ_OK if the file is found. It becomes the current file.
+  UNZ_END_OF_LIST_OF_FILE if the file is not found
+*/
+
+
+/* ****************************************** */
+/* Ryan supplied functions */
+/* unz_file_info contain information about a file in the zipfile */
+typedef struct unz_file_pos_s
+{
+    uLong pos_in_zip_directory;   /* offset in zip file directory */
+    uLong num_of_file;            /* # of file */
+} unz_file_pos;
+
+extern int ZEXPORT unzGetFilePos(
+    unzFile file,
+    unz_file_pos* file_pos);
+
+extern int ZEXPORT unzGoToFilePos(
+    unzFile file,
+    unz_file_pos* file_pos);
+
+typedef struct unz64_file_pos_s
+{
+    ZPOS64_T pos_in_zip_directory;   /* offset in zip file directory */
+    ZPOS64_T num_of_file;            /* # of file */
+} unz64_file_pos;
+
+extern int ZEXPORT unzGetFilePos64(
+    unzFile file,
+    unz64_file_pos* file_pos);
+
+extern int ZEXPORT unzGoToFilePos64(
+    unzFile file,
+    const unz64_file_pos* file_pos);
+
+/* ****************************************** */
+
+extern int ZEXPORT unzGetCurrentFileInfo64 OF((unzFile file,
+                         unz_file_info64 *pfile_info,
+                         char *szFileName,
+                         uLong fileNameBufferSize,
+                         void *extraField,
+                         uLong extraFieldBufferSize,
+                         char *szComment,
+                         uLong commentBufferSize));
+
+extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file,
+                         unz_file_info *pfile_info,
+                         char *szFileName,
+                         uLong fileNameBufferSize,
+                         void *extraField,
+                         uLong extraFieldBufferSize,
+                         char *szComment,
+                         uLong commentBufferSize));
+/*
+  Get Info about the current file
+  if pfile_info!=NULL, the *pfile_info structure will contain somes info about
+        the current file
+  if szFileName!=NULL, the filemane string will be copied in szFileName
+            (fileNameBufferSize is the size of the buffer)
+  if extraField!=NULL, the extra field information will be copied in extraField
+            (extraFieldBufferSize is the size of the buffer).
+            This is the Central-header version of the extra field
+  if szComment!=NULL, the comment string of the file will be copied in szComment
+            (commentBufferSize is the size of the buffer)
+*/
+
+
+/** Addition for GDAL : START */
+
+extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64 OF((unzFile file));
+
+/** Addition for GDAL : END */
+
+
+/***************************************************************************/
+/* for reading the content of the current zipfile, you can open it, read data
+   from it, and close it (you can close it before reading all the file)
+   */
+
+extern int ZEXPORT unzOpenCurrentFile OF((unzFile file));
+/*
+  Open for reading data the current file in the zipfile.
+  If there is no error, the return value is UNZ_OK.
+*/
+
+extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file,
+                                                  const char* password));
+/*
+  Open for reading data the current file in the zipfile.
+  password is a crypting password
+  If there is no error, the return value is UNZ_OK.
+*/
+
+extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file,
+                                           int* method,
+                                           int* level,
+                                           int raw));
+/*
+  Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
+    if raw==1
+  *method will receive method of compression, *level will receive level of
+     compression
+  note : you can set level parameter as NULL (if you did not want known level,
+         but you CANNOT set method parameter as NULL
+*/
+
+extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file,
+                                           int* method,
+                                           int* level,
+                                           int raw,
+                                           const char* password));
+/*
+  Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
+    if raw==1
+  *method will receive method of compression, *level will receive level of
+     compression
+  note : you can set level parameter as NULL (if you did not want known level,
+         but you CANNOT set method parameter as NULL
+*/
+
+
+extern int ZEXPORT unzCloseCurrentFile OF((unzFile file));
+/*
+  Close the file in zip opened with unzOpenCurrentFile
+  Return UNZ_CRCERROR if all the file was read but the CRC is not good
+*/
+
+extern int ZEXPORT unzReadCurrentFile OF((unzFile file,
+                      voidp buf,
+                      unsigned len));
+/*
+  Read bytes from the current file (opened by unzOpenCurrentFile)
+  buf contain buffer where data must be copied
+  len the size of buf.
+
+  return the number of byte copied if somes bytes are copied
+  return 0 if the end of file was reached
+  return <0 with error code if there is an error
+    (UNZ_ERRNO for IO error, or zLib error for uncompress error)
+*/
+
+extern z_off_t ZEXPORT unztell OF((unzFile file));
+
+extern ZPOS64_T ZEXPORT unztell64 OF((unzFile file));
+/*
+  Give the current position in uncompressed data
+*/
+
+extern int ZEXPORT unzeof OF((unzFile file));
+/*
+  return 1 if the end of file was reached, 0 elsewhere
+*/
+
+extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file,
+                                             voidp buf,
+                                             unsigned len));
+/*
+  Read extra field from the current file (opened by unzOpenCurrentFile)
+  This is the local-header version of the extra field (sometimes, there is
+    more info in the local-header version than in the central-header)
+
+  if buf==NULL, it return the size of the local extra field
+
+  if buf!=NULL, len is the size of the buffer, the extra header is copied in
+    buf.
+  the return value is the number of bytes copied in buf, or (if <0)
+    the error code
+*/
+
+/***************************************************************************/
+
+/* Get the current file offset */
+extern ZPOS64_T ZEXPORT unzGetOffset64 (unzFile file);
+extern uLong ZEXPORT unzGetOffset (unzFile file);
+
+/* Set the current file offset */
+extern int ZEXPORT unzSetOffset64 (unzFile file, ZPOS64_T pos);
+extern int ZEXPORT unzSetOffset (unzFile file, uLong pos);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _unz64_H */
diff --git a/ap/app/goahead/server/value.c b/ap/app/goahead/server/value.c
new file mode 100755
index 0000000..66a2fcf
--- /dev/null
+++ b/ap/app/goahead/server/value.c
@@ -0,0 +1,41 @@
+#include	"uemf.h"
+
+value_t valueString(char_t* value, int flags)
+{
+	value_t	v;
+
+	memset(&v, 0x0, sizeof(v));
+	v.valid = 1;
+	v.type = string;
+	if (flags & VALUE_ALLOCATE) {
+		v.allocated = 1;
+		v.value.string = gstrdup(B_L, value);
+	} else {
+		v.allocated = 0;
+		v.value.string = value;
+	}
+	return v;
+}
+
+value_t valueInteger(long value)
+{
+	value_t	v;
+
+	memset(&v, 0x0, sizeof(v));
+	v.valid = 1;
+	v.type = integer;
+	v.value.integer = value;
+	return v;
+}
+
+void valueFree(value_t* v)
+{
+	if (v->valid && v->allocated && v->type == string &&
+			v->value.string != NULL) {
+		bfree(B_L, v->value.string);
+	}
+	v->type = undefined;
+	v->valid = 0;
+	v->allocated = 0;
+}
+
diff --git a/ap/app/goahead/server/webs.c b/ap/app/goahead/server/webs.c
new file mode 100755
index 0000000..b0238e1
--- /dev/null
+++ b/ap/app/goahead/server/webs.c
@@ -0,0 +1,2303 @@
+#include	"wsIntrn.h"
+#ifdef DIGEST_ACCESS_SUPPORT
+	#include	"websda.h"
+#endif
+#include "../interface5.0/zte_web_interface.h"
+//#include "../interface5.0/zte_rest_comm_interface.h"
+
+websStatsType	websStats;				
+webs_t			*webs;					
+sym_fd_t		websMime;				
+int				websMax;				
+int				websPort;				
+char_t			websHost[64];			
+char_t			websIpaddr[64];			
+char_t			*websHostUrl = NULL;	
+char_t			*websIpaddrUrl = NULL;	
+//added by liuyingnan for PC Client begin, 20120829
+char websRecvHttpBuffer[HTTP_BUFFER_SIZE] = {0};
+char websRecvHttpBuffer_XML[HTTP_BUFFER_SIZE] = {0};
+
+extern void zte_change_wp_query(webs_t wp,char_t *xml_str);
+//added by liuyingnan for PC Client begin, 20120829
+
+websErrorType websErrors[] = {
+	{ 200, T("Data follows") },
+	{ 204, T("No Content") },
+	{ 301, T("Redirect") },
+	{ 302, T("Redirect") },
+	{ 304, T("Use local copy") },
+	{ 400, T("Page not found") },
+	{ 401, T("Unauthorized") },
+	{ 403, T("Forbidden") },
+	{ 404, T("Site or Page Not Found") },
+	{ 405, T("Access Denied") },
+	{ 500, T("Web Error") },
+	{ 501, T("Not Implemented") },
+	{ 503, T("Site Temporarily Unavailable. Try again.") },
+	{ 0, NULL }
+};
+
+typedef enum { 
+	RET_DATA_ERROR = -1,
+	RET_FAILED = 0, 
+	RET_OK = 1, 
+} ERROR_CODE;
+
+
+#ifdef FEATURE_ZTE_WEB_TCARD
+//added by guo shoupeng 10124224 for http share 20111001 start
+
+typedef enum { 
+	RET_FAILED = 0, 
+	RET_OK = 1, 
+	RET_UNKNOWN = 3,	
+	MALLOC_FIALED = 4,
+	SD_NONE = 5,
+	USB_OUT = 6,
+	USER_MALLOC_FAILED = 7,
+	UPLOAD_FILE_LIMITED = 8,
+	USER_UNKNOWN = 9,	
+} ERROR_CODE;
+
+//added by guo shoupeng 10124224 for http share 20111001 end
+#endif
+
+
+
+static int 		websGetInput(webs_t wp, char_t **ptext, int *nbytes);
+static int 		websParseFirst(webs_t wp, char_t *text);
+static int 	websParseRequest(webs_t wp);
+static void		websSocketEvent(int sid, int mask, int data);
+static int		websGetTimeSinceMark(webs_t wp);
+
+static int		websListenSock;					
+static char_t	websRealm[64] = T("GoAhead");	
+
+static int		websOpenCount = 0;		
+
+
+int websOpenServer(int port, int retries)
+{
+	websMimeType	*mt;
+
+	if (++websOpenCount != 1) {
+		return websPort;
+	}
+
+	a_assert(port > 0);
+	a_assert(retries >= 0);
+
+	webs = NULL;
+	websMax = 0;
+
+	websMime = symOpen(WEBS_SYM_INIT * 4);
+	a_assert(websMime >= 0);
+	if(websMime < 0)  // cov M NEGATIVE_RETURNS
+	{
+	    return -1;
+	}
+	for (mt = websMimeList; mt->type; mt++) {
+		symEnter(websMime, mt->ext, valueString(mt->type, 0), 0);
+	}
+
+#if 1
+    // kw 3 INVARIANT_CONDITION.UNREACH websUrlHandlerOpen only return 0
+    websUrlHandlerOpen();
+#else
+	if (websUrlHandlerOpen() < 0) {
+		return -1;
+	}
+#endif	
+	websFormOpen();
+
+	return websOpenListen(port, retries);
+}
+
+
+
+void websCloseServer()
+{
+	webs_t	wp;
+	int		wid;
+
+	if (--websOpenCount > 0) {
+		return;
+	}
+
+	websCloseListen();
+
+	for (wid = websMax; webs && wid >= 0; wid--) {
+		if ((wp = webs[wid]) == NULL) {
+			continue;
+		}
+		socketCloseConnection(wp->sid);
+		websFree(wp);
+	}
+
+	symClose(websMime);
+	websFormClose();
+	websUrlHandlerClose();
+}
+
+
+void websCloseListen()
+{
+	if (websListenSock >= 0) {
+		socketCloseConnection(websListenSock);
+		websListenSock = -1;
+	}
+	bfreeSafe(B_L, websHostUrl);
+	bfreeSafe(B_L, websIpaddrUrl);
+	websIpaddrUrl = websHostUrl = NULL;
+}
+
+
+int websOpenListen(int port, int retries)
+{
+	int		i, orig;
+
+	a_assert(port > 0);
+	a_assert(retries >= 0);
+	
+	orig = port;
+
+	for (i = 0; i <= retries; i++) {
+		websListenSock = socketOpenConnection6(NULL, port, websAccept, 0);
+		if (websListenSock >= 0) {
+			break;
+		}
+		port++;
+	}
+	if (i > retries) {
+		error(E_L, E_USER, T("Couldn't open a socket on ports %d - %d"),
+			orig, port - 1);
+		return -1;
+	} 
+
+	websPort = port;
+	bfreeSafe(B_L, websHostUrl);
+	bfreeSafe(B_L, websIpaddrUrl);
+	websIpaddrUrl = websHostUrl = NULL;
+
+	if (port == 80) {
+		websHostUrl = bstrdup(B_L, websHost);
+		websIpaddrUrl = bstrdup(B_L, websIpaddr);
+	} else {
+		fmtAlloc(&websHostUrl, WEBS_MAX_URL + 80, T("%s:%d"), websHost, port);
+		fmtAlloc(&websIpaddrUrl, WEBS_MAX_URL + 80, T("%s:%d"), 
+			websIpaddr, port);
+	}
+	trace(0, T("webs: Listening for HTTP requests at address %s\n"),
+		websIpaddrUrl);
+
+	return port;
+}
+
+
+static void websSocketEvent(int sid, int mask, int iwp)
+{
+	webs_t	wp;
+
+	wp = (webs_t) iwp;
+	a_assert(wp);
+
+	if (! websValid(wp)) {
+		return;
+	}
+
+	if (mask & SOCKET_READABLE) {
+		websReadEvent(wp);
+	} 
+	if (mask & SOCKET_WRITABLE) {
+		if (websValid(wp) && wp->writeSocket) {
+			(*wp->writeSocket)(wp);
+		}
+	} 
+}
+
+int websAccept(int sid, char *ipaddr, int port, int listenSid)
+{
+	webs_t	wp;
+	int		wid;
+
+	a_assert(ipaddr && *ipaddr);
+	a_assert(sid >= 0);
+	a_assert(port >= 0);
+
+	if ((wid = websAlloc(sid)) < 0) {
+		return -1;
+	}
+	wp = webs[wid];
+	a_assert(wp);
+	wp->listenSid = listenSid;
+
+	ascToUni(wp->ipaddr, ipaddr, min(sizeof(wp->ipaddr), strlen(ipaddr) + 1));
+
+	if (gstrcmp(wp->ipaddr, T("127.0.0.1")) == 0 || 
+			gstrcmp(wp->ipaddr, websIpaddr) == 0 || 
+			gstrcmp(wp->ipaddr, websHost) == 0) {
+		wp->flags |= WEBS_LOCAL_REQUEST;
+	}
+
+	socketCreateHandler(sid, SOCKET_READABLE, websSocketEvent, (int) wp);
+
+	wp->timeout = emfSchedCallback(WEBS_TIMEOUT, websTimeout, (void *) wp);
+	//trace(8, T("webs: accept request\n"));
+	return 0;
+}
+
+
+
+#ifdef FEATURE_ZTE_WEB_TCARD
+//added by guo shoupeng 10124224 for http share 20120110 start
+static int read_bytes = 0;
+//added by guo shoupeng 10124224 for http share 20120110 end
+#endif
+
+void websReadEvent(webs_t wp)
+{
+	char_t 	*text;
+	int		rc, nbytes, len, done, fd;
+
+	a_assert(wp);
+	a_assert(websValid(wp));
+
+	websSetTimeMark(wp);
+	
+	static unsigned int timer = 0;
+
+	text = NULL;
+	fd = -1;
+	for (done = 0; !done; ) {
+		if (text) {
+			bfree(B_L, text);
+			text = NULL;
+		}
+
+
+#ifdef FEATURE_ZTE_WEB_TCARD
+//added by guo shoupeng 10124224 for http share 20120110 start
+		if( read_bytes > UPLOAD_INTERVAL)
+		{
+			read_bytes = 0;
+			break;
+		}
+//added by guo shoupeng 10124224 for http share 20120110 end
+#endif
+		assert(wp);
+		assert(websValid(wp));		
+		while ((rc = websGetInput(wp, &text, &nbytes)) == 0) {
+			;
+		}
+
+
+		if (rc < 0) {
+            if(websValid(wp) && (wp->flags & WEBS_CGI_REQUEST ))
+            {
+                //printf("\n +++sockettt upload websSetTimeMark+++ \n");
+                websSetTimeMark(wp);
+            }
+			break;
+		}
+		if(text == NULL)
+			break;//for kw
+
+		switch(wp->state) {
+		case WEBS_BEGIN:
+
+			if (websParseFirst(wp, text) < 0) {
+				done++;
+				break;
+			}
+			wp->state = WEBS_HEADER;
+			break;
+		
+		case WEBS_HEADER:
+
+			if (ringqLen(&wp->header) > 0) {
+				ringqPutStr(&wp->header, T("\n"));
+			}
+			ringqPutStr(&wp->header, text);
+			break;
+
+		case WEBS_POST_CLEN:
+
+#ifndef __NO_CGI_BIN
+			if (wp->flags & WEBS_CGI_REQUEST) {
+
+				//if(!(wp->flags & WEBS_CGI_FIRMWARE_UPLOAD))
+				if(wp->flags & WEBS_CGI_HTTPSHARE_UPLOAD)
+				{
+					if( timer ==0)
+                    {
+                        websSetLoginTimemark(wp);
+						printf("[httpshare]upload reset login state~\n");
+                    }
+					ERROR_CODE ret = zte_process_cgi_recv(wp, wp->clen,text, nbytes);	
+
+					if(RET_DATA_ERROR == ret || RET_FAILED == ret)
+					{												  
+						websError(wp, 404, T("Bad state"));
+						printf("[httpshare]ret->%d\n",ret);
+						done++; 						  
+						break;		  
+					} 
+					
+					timer++;
+					timer=timer-(timer>>11<<11);  //timer%2^11
+				}else if(wp->flags & WEBS_CGI_UPLOAD)
+				{
+					if (fd == -1) 
+					{
+						if(wp->flags & WEBS_CGI_FIRMWARE_UPLOAD )
+						{
+							fd = gopen(FIRMWARE_TMP_FILE, O_CREAT | O_WRONLY | O_BINARY | O_APPEND, 0666);
+							printf("[goahead]open cgi temp file\n");
+						}
+						else
+					  	{
+							fd = gopen(wp->cgiStdin, O_CREAT | O_WRONLY | O_BINARY | O_APPEND, 0666);
+	                    }
+					}
+                    if(fd < 0){
+                        break;
+					}
+						
+					
+					gwrite(fd, text, nbytes);
+				}else
+				{
+					websError(wp, 404, T("Bad state"));
+					printf("[goahead]bad cgi request\n");
+					done++; 						  
+					break;
+				}
+
+
+			} else 
+#endif
+			//added by liuyingnan for PC Client begin, 20120829
+            if(wp->flags & WEBS_REST_CLIENT_REQUEST){
+                printf("%s", "websReadEvent: pc client post");
+                if (nbytes > (HTTP_BUFFER_SIZE-gstrlen(websRecvHttpBuffer)-1))
+                {
+                    gstrncpy(websRecvHttpBuffer+gstrlen(websRecvHttpBuffer), text, HTTP_BUFFER_SIZE-gstrlen(websRecvHttpBuffer)-1);
+                }
+                else
+                {
+                    gstrncpy(websRecvHttpBuffer+gstrlen(websRecvHttpBuffer), text, nbytes);
+                }
+            } else  if(wp->flags & WEBS_XML_CLIENT_REQUEST){
+            if (nbytes > (HTTP_BUFFER_SIZE-gstrlen(websRecvHttpBuffer_XML)-1))
+            {
+                gstrncpy(websRecvHttpBuffer_XML+gstrlen(websRecvHttpBuffer_XML), text, HTTP_BUFFER_SIZE-gstrlen(websRecvHttpBuffer_XML)-1);
+            }
+            else
+            {
+                gstrncpy(websRecvHttpBuffer_XML+gstrlen(websRecvHttpBuffer_XML), text, nbytes);
+            }
+            } else    
+			//added by liuyingnan for PC Client end, 20120829
+
+
+
+			if (wp->query) {
+				if (wp->query[0] && !(wp->flags & WEBS_POST_DATA)) {
+
+					len = gstrlen(wp->query);
+					wp->query = brealloc(B_L, wp->query, (len + gstrlen(text) +
+						2) * sizeof(char_t));
+					if(wp->query == NULL)
+						break;//for kw
+					wp->query[len++] = '&';
+					gstrcpy(&wp->query[len], text);
+
+				} else {
+
+               //if (text != NULL)//for kw
+               {
+                  len = gstrlen(wp->query);
+                  wp->query = brealloc(B_L, wp->query, (len +	gstrlen(text) +
+                     1) * sizeof(char_t));
+                  if (wp->query) {
+                     gstrcpy(&wp->query[len], text);
+                  }
+               }
+				}
+
+			} else {
+				wp->query = bstrdup(B_L, text);
+			}
+#if 0 //for kw			
+            //Add By liuyingnan for XML COMM API START
+            if(wp->flags & WEBS_XML_CLIENT_REQUEST)
+            {
+                slog(MISC_PRINT,SLOG_DEBUG,"[websReadEvent]:zte_change_wp_query function:%s\n",websRecvHttpBuffer_XML);
+                //zte_change_wp_query(wp,websRecvHttpBuffer_Json);
+                zte_change_wp_query(wp,websRecvHttpBuffer_XML);
+                memset(websRecvHttpBuffer_XML,0,HTTP_BUFFER_SIZE);
+                slog(MISC_PRINT,SLOG_DEBUG,"[out the function]:wp->query:%s\n",wp->query);
+            } 
+            //Add By liuyingnan for XML COMM API END
+#endif
+            
+			wp->flags |= WEBS_POST_DATA;
+			wp->clen -= nbytes;
+			if (wp->clen > 0) {
+				if (nbytes > 0) {
+					break;
+				}
+				done++;
+				break;
+			}
+#ifdef FEATURE_ZTE_WEB_TCARD
+//added by guo shoupeng 10124224 for http share 20120110 start
+			else
+			{
+			    zte_efs_write(wp);
+			}
+//added by guo shoupeng 10124224 for http share 20120110 end
+#endif	
+
+			if (fd != -1) {
+				gclose (fd);
+				fd = -1;
+			}
+			websUrlHandlerRequest(wp);
+			done++;
+			break;
+
+		case WEBS_POST:
+
+
+#ifndef __NO_CGI_BIN
+			if (wp->flags & WEBS_CGI_REQUEST) {
+				if (fd == -1) {
+					fd = gopen(wp->cgiStdin, O_CREAT | O_WRONLY | O_BINARY,
+						0666);
+				}
+
+				if(fd < 0){
+                    break;
+				}
+				gwrite(fd, text, gstrlen(text));
+				gwrite(fd, T("\n"), sizeof(char_t));
+			} else
+#endif
+			if (wp->query && *wp->query && !(wp->flags & WEBS_POST_DATA)) {
+				len = gstrlen(wp->query);
+				wp->query = brealloc(B_L, wp->query, (len + gstrlen(text) +
+					2) * sizeof(char_t));
+				if (wp->query) {
+					wp->query[len++] = '&';
+					gstrcpy(&wp->query[len], text);
+				}
+
+			} else {
+				wp->query = bstrdup(B_L, text);
+			}
+			wp->flags |= WEBS_POST_DATA;
+			done++;
+			break;
+
+		default:
+			websError(wp, 404, T("Bad state"));
+			done++;
+			break;
+		}
+	}
+
+	if (fd != -1) {
+		fd = gclose (fd);
+	}
+
+	if (text) {
+		bfree(B_L, text);
+	}
+}
+char_t	htmExt[] = T(".htm");
+int websUrlParse(char_t *url, char_t **pbuf, char_t **phost, char_t **ppath, 
+	char_t **pport, char_t **pquery, char_t **pproto, char_t **ptag, 
+	char_t **pext)
+{
+	char_t		*hostbuf, *portbuf, *buf;
+	int			c, len, ulen;
+	char_t		*tok, *cp, *host, *path, *port, *proto, *tag, *query, *ext;
+
+	a_assert(url);
+	a_assert(pbuf);
+
+	ulen = gstrlen(url);
+
+	len = ulen * 2 + MAX_PORT_LEN + 3;
+	if ((buf = balloc(B_L, len * sizeof(char_t))) == NULL) {
+		return -1;
+	}
+	portbuf = &buf[len - MAX_PORT_LEN - 1];
+	hostbuf = &buf[ulen+1];
+
+ 	websDecodeUrl(buf, url, ulen);
+
+	url = buf;
+
+	if(portbuf == NULL) //for kw 20210312
+		return -1;
+	
+	stritoa(websGetPort(), portbuf, MAX_PORT_LEN);
+	port = portbuf;
+	path = T("/");
+	proto = T("http");
+	host = T("localhost");
+	query = T("");
+	ext = htmExt;
+	tag = T("");
+
+	if (gstrncmp(url, T("http://"), 7) == 0) {
+		tok = &url[7];
+		tok[-3] = '\0';
+		proto = url;
+		host = tok;
+		for (cp = tok; *cp; cp++) {
+			if (*cp == '/') {
+				break;
+			}
+			if (*cp == ':') {
+				*cp++ = '\0';
+				port = cp;
+				tok = cp;
+			}
+		}
+		if ((cp = gstrchr(tok, '/')) != NULL) {
+
+			c = *cp;
+			*cp = '\0';
+			gstrncpy(hostbuf, host, ulen);
+			gstrncpy(portbuf, port, MAX_PORT_LEN);
+			*cp = c;
+			host = hostbuf;
+			port = portbuf;
+			path = cp;
+			tok = cp;
+		}
+
+	} else {
+		path = url;
+		tok = url;
+	}
+
+	if ((cp = gstrchr(tok, '?')) != NULL) {
+		*cp++ = '\0';
+		query = cp;
+		path = tok;
+		tok = query;
+	} 
+
+	if ((cp = gstrchr(tok, '#')) != NULL) {
+		*cp++ = '\0';
+		if (*query == 0) {
+			path = tok;
+		}
+	}
+
+	if (pext) {
+
+		if ((cp = gstrrchr(path, '.')) != NULL) {
+			const char_t* garbage = T("/\\");
+			int length = gstrcspn(cp, garbage);
+			int garbageLength = gstrspn(cp + length, garbage);
+			int ok = (length + garbageLength == (int) gstrlen(cp));
+
+			if (ok) {
+				cp[length] = '\0';
+				ext = cp;
+			}
+		}
+	}
+
+	if (phost)
+		*phost = host;
+	if (ppath)
+		*ppath = path;
+	if (pport)
+		*pport = port;
+	if (pproto)
+		*pproto = proto;
+	if (pquery)
+		*pquery = query;
+	if (ptag)
+		*ptag = tag;
+	if (pext)
+		*pext = ext;
+	*pbuf = buf;
+	return 0;
+}
+
+char_t *websUrlType(char_t *url, char_t *buf, int charCnt)
+{
+	char_t	*ext = NULL; //cov
+	char_t	*tmp_buf;
+	sym_t	*psym;
+
+	a_assert(url && *url);
+	a_assert(buf && charCnt > 0);
+
+	if (url == NULL || *url == '\0') {
+		gstrcpy(buf, T("text/plain"));
+		return buf;
+	}
+	if (websUrlParse(url, &tmp_buf, NULL, NULL, NULL, NULL, NULL, 
+			NULL, &ext) < 0) {
+		gstrcpy(buf, T("text/plain"));
+		return buf;
+	}
+	strlower(ext);
+
+	if ((psym = symLookup(websMime, ext)) != NULL) {
+		gstrncpy(buf, psym->content.value.string, charCnt);
+	} else {
+		gstrcpy(buf, T("text/plain"));
+	}
+	bfree(B_L, tmp_buf);
+	return buf;
+}
+
+static int websParseFirst(webs_t wp, char_t *text)
+{
+	char_t 	*op, *proto, *protoVer, *url, *host, *query, *path, *port, *ext;
+	char_t	*buf;
+	int		testPort;
+
+#ifdef FEATURE_ZTE_WEB_TCARD
+//added by guo shoupeng 10124224 for http share 20111001 start
+	char *page_att=NULL;
+//added by guo shoupeng 10124224 for http share 20111001 end
+#endif
+	a_assert(websValid(wp));
+	a_assert(text && *text);
+#ifdef WEBINSPECT_FIX	
+	if(text && (!is_print_str(text,strlen(text)) || strstr(text, "HTTP") == NULL))
+	{
+		websDone(wp, 0);
+		slog(MISC_PRINT, SLOG_ERR,"[goahead]es\n");
+		return -1;
+	}
+#endif
+	op = gstrtok(text, T(" \t"));
+	if (op == NULL || *op == '\0') {
+		websError(wp, 400, T("Bad HTTP request"));
+		return -1;
+	}
+	if (gstrcmp(op, T("GET")) != 0) {
+		if (gstrcmp(op, T("POST")) == 0) {
+			wp->flags |= WEBS_POST_REQUEST;
+		} else if (gstrcmp(op, T("HEAD")) == 0) {
+			wp->flags |= WEBS_HEAD_REQUEST;
+		} else {
+			websError(wp, 400, T("Bad request type"));
+			return -1;
+		}
+	}
+
+	websSetVar(wp, T("REQUEST_METHOD"), op);
+
+	url = gstrtok(NULL, T(" \t\n"));
+	if (url == NULL || *url == '\0') {
+		websError(wp, 400, T("Bad HTTP request"));
+		return -1;
+	}
+	protoVer = gstrtok(NULL, T(" \t\n"));
+
+	host = path = port = proto = query = ext = NULL;
+	if (websUrlParse(url, &buf, &host, &path, &port, &query, &proto, 
+			NULL, &ext) < 0) {
+		websError(wp, 400, T("Bad URL format"));
+		return -1;
+	}
+
+	wp->url = bstrdup(B_L, url);
+
+#ifndef __NO_CGI_BIN
+
+
+	if ((gstrstr(url, CGI_BIN) != NULL)&&((wp->flags & WEBS_POST_REQUEST))) {
+		wp->flags |= WEBS_CGI_REQUEST;
+		
+		printf("[goahead]set WEBS_CGI_REQUEST \n");
+
+		// special case: upload.cgi
+		
+		if(gstrstr(url, CGI_BIN_UPLOAD) != NULL)
+		{
+			if(gstrstr(url, CGI_FIRMWARE_UPLOAD) != NULL){
+				wp->flags |= WEBS_CGI_FIRMWARE_UPLOAD;
+				system("rm -rf  /firmware_tmp_file");
+				zte_mgmt_login_timemark_set();
+				printf("[goahead]set WEBS_CGI_FIRMWARE_UPLOAD \n");
+			}
+			wp->cgiStdin = websGetCgiCommName(wp);
+			printf("[goahead]get cgi name.\n");
+			// ex: upload_setting....
+			wp->flags |= WEBS_CGI_UPLOAD;
+		}
+
+		if(gstrstr(url, CGI_BIN_HTTPSHARE) != NULL)
+		{
+			printf("[httpshare]upload file.\n"); 
+
+			if(!zte_reset_cgi_state(wp))	
+			{
+				printf("[httpshare]upload file.reset cgi state error.\n");
+				bfree(B_L, buf);
+				return -1;
+			}
+			wp->flags |= WEBS_CGI_HTTPSHARE_UPLOAD;
+		}
+	            
+
+	}
+#endif
+
+	wp->query = bstrdup(B_L, query);
+	wp->host = bstrdup(B_L, host);
+	wp->path = bstrdup(B_L, path);
+	wp->protocol = bstrdup(B_L, proto);
+	wp->protoVersion = bstrdup(B_L, protoVer);
+	
+	//added by liuyingnan for PC Client begin, 20120829
+    if (gstrstr(url, "api/client/post") != NULL) {
+        printf("%s", "websParseFirst: pc client post");
+        wp->flags |= WEBS_REST_CLIENT_REQUEST;
+    }
+    //added by huangmin for PC Client end, 20120829
+    if (gstrstr(url, "api/xmlclient/post") != NULL) {
+        wp->flags |= WEBS_XML_CLIENT_REQUEST;
+    }
+	
+	if ((testPort = socketGetPort(wp->listenSid)) >= 0) {
+		wp->port = testPort;
+	} else {
+		wp->port = gatoi(port);
+	}
+
+	if (gstrcmp(ext, T(".asp")) == 0) {
+		wp->flags |= WEBS_ASP;
+	}
+	bfree(B_L, buf);
+
+	websUrlType(url, wp->type, TSZ(wp->type));
+
+	ringqFlush(&wp->header);
+	return 0;
+}
+
+static int websGetInput(webs_t wp, char_t **ptext, int *pnbytes) 
+{
+	char_t	*text;
+	char	buf[WEBS_SOCKET_BUFSIZ+1];
+	int		nbytes, len, clen;
+
+	a_assert(websValid(wp));
+	a_assert(ptext);
+	a_assert(pnbytes);
+
+	if(websValid(wp) == 0 || ptext == NULL || pnbytes == NULL){
+		softap_assert("websGetInput 1");
+		return -1;//for kw
+	}
+
+	*ptext = text = NULL;
+	*pnbytes = 0;
+
+	if (wp->state == WEBS_POST_CLEN) {
+		len = (wp->clen > WEBS_SOCKET_BUFSIZ) ? WEBS_SOCKET_BUFSIZ : wp->clen;
+	} else {
+		len = 0;
+	}
+
+	if (len > 0) {
+
+#ifdef WEBS_SSL_SUPPORT
+		if (wp->flags & WEBS_SECURE) {
+			nbytes = websSSLRead(wp->wsp, buf, len);
+		} else {
+			nbytes = socketRead(wp->sid, buf, len);
+		}
+#else
+		nbytes = socketRead(wp->sid, buf, len);
+#endif
+		if (nbytes < 0) {						/* Error */
+			websDone(wp, 0);
+			return -1;
+
+		}  else if (nbytes == 0) {				/* EOF or No data available */
+			//trace(8, T("@@@@webs 0x%x 0x%x: websGetInput read 0\n"),wp,wp->sid);
+			if (socketEof(wp->sid)) {
+				websDone(wp, 0);
+			}
+			return -1;
+
+		} else {								/* Valid data */
+
+			buf[nbytes] = '\0';
+			if ((text = ballocAscToUni(buf, nbytes)) == NULL) {
+				websError(wp, 503, T("Insufficient memory"));
+				return -1;
+			}
+		}
+
+	} else {
+#ifdef WEBS_SSL_SUPPORT
+		if (wp->flags & WEBS_SECURE) {
+			nbytes = websSSLGets(wp->wsp, &text);
+		} else {
+			nbytes = socketGets(wp->sid, &text);
+		}
+#else
+		nbytes = socketGets(wp->sid, &text);
+#endif
+
+		if (nbytes < 0) {
+			int eof;
+
+#ifdef WEBS_SSL_SUPPORT
+			if (wp->flags & WEBS_SECURE) {
+
+				if (wp->state == WEBS_BEGIN) {
+					eof = 1;
+				} else {
+					eof = websSSLEof(wp->wsp);
+				}
+			} else {
+				eof = socketEof(wp->sid);
+			}
+#else
+			eof = socketEof(wp->sid);
+#endif
+
+			if (eof) {
+
+				if (wp->state == WEBS_POST) {
+					websUrlHandlerRequest(wp);
+				} else {
+					websDone(wp, 0);
+				}
+			} else {
+					trace(8, T("@@@@webs 0x%x 0x%x: websGetInput no eof\n"),wp,wp->sid);
+
+#if 1//def HP_FIX
+				websDone(wp, 0);
+#endif /*HP_FIX*/
+
+			}
+
+#if 0 //def UNUSED
+			if (wp->state == WEBS_HEADER && ringqLen(&wp->header) <= 0) {
+				websParseRequest(wp);
+				websUrlHandlerRequest(wp);
+			}
+#endif
+			bfreeSafe(B_L,text);//for kw
+			return -1;
+
+		} else if (nbytes == 0) {
+			if (wp->state == WEBS_HEADER) {
+
+				if(websParseRequest(wp) != 0){
+					return -1;
+				}
+				if (wp->flags & WEBS_POST_REQUEST) {
+					if (wp->flags & WEBS_CLEN) {
+						wp->state = WEBS_POST_CLEN;
+						clen = wp->clen;
+					} else {
+						wp->state = WEBS_POST;
+						clen = 1;
+					}
+					if (clen > 0) {
+
+						return 0;
+					}
+					return 1;
+				}
+
+				websUrlHandlerRequest(wp);
+			}
+			return -1;
+		}
+	}
+
+//	if(text == NULL || nbytes <= 0){ // kw 3 nbytes <= 0 already return
+    if(text == NULL){
+		softap_assert("websGetInput 2");
+	}
+	a_assert(text);
+	a_assert(nbytes > 0);
+	*ptext = text;
+	*pnbytes = nbytes;
+	return 1;
+}
+
+
+#define isgoodchar(s) (gisalnum((s)) || ((s) == '/') || ((s) == '_') || \
+						((s) == '.')  || ((s) == '-') )
+
+static int websParseRequest(webs_t wp)
+{
+	char_t	*authType, *upperKey, *cp, *browser, *lp, *key, *value;
+	int smugglingFlag = 0;
+	a_assert(websValid(wp));
+
+	websSetVar(wp, T("HTTP_AUTHORIZATION"), T(""));
+
+	browser = NULL;
+	char tmp[4] = T("");
+	for (lp = (char_t*) wp->header.servp; lp && *lp; ) {
+		cp = lp;
+		if ((lp = gstrchr(lp, '\n')) != NULL) {
+			lp++;
+		}
+
+		if ((key = gstrtok(cp, T(": \t\n"))) == NULL) {
+			continue;
+		}
+
+		if ((value = gstrtok(NULL, T("\n"))) == NULL) {
+			//value = T("");
+			value = tmp;// kw OVERWRITE_CONST_CHAR
+		}
+
+		while (gisspace(*value)) {
+			value++;
+		}
+		strlower(key);
+
+		fmtAlloc(&upperKey, (gstrlen(key) + 6), T("HTTP_%s"), key);
+		for (cp = upperKey; *cp; cp++) {
+			if (*cp == '-')
+				*cp = '_';
+		}
+		strupper(upperKey);
+		websSetVar(wp, upperKey, value);
+		bfree(B_L, upperKey);
+
+		if (gstrcmp(key, T("user-agent")) == 0) {
+			if (wp->userAgent)
+				bfree(B_L, wp->userAgent);
+			wp->userAgent = bstrdup(B_L, value);
+
+		} else if (gstricmp(key, T("authorization")) == 0) {
+
+			authType = bstrdup (B_L, value);
+			a_assert (authType);
+
+			cp = authType;
+			while (gisalpha(*cp)) {
+				cp++;
+			}
+			*cp = '\0';
+			if (wp->authType)
+				bfree(B_L, wp->authType);
+			wp->authType = bstrdup(B_L, authType);
+			bfree(B_L, authType);
+
+			if (gstricmp(wp->authType, T("basic")) == 0) {
+				char_t	userAuth[FNAMESIZE];
+
+				if ((cp = gstrchr(value, ' ')) != NULL) {
+					*cp = '\0';
+
+               bfree(B_L, wp->authType);
+					wp->authType = bstrdup(B_L, value);
+					websDecode64(userAuth, ++cp, sizeof(userAuth));
+				} else {
+					websDecode64(userAuth, value, sizeof(userAuth));
+				}
+
+				if ((cp = gstrchr(userAuth, ':')) != NULL) {
+					*cp++ = '\0';
+				}
+				if (wp->password)
+					bfree(B_L, wp->password);
+				if (wp->userName)
+					bfree(B_L, wp->userName);
+				if (cp) {
+					wp->userName = bstrdup(B_L, userAuth);
+					wp->password = bstrdup(B_L, cp);
+				} else {
+					wp->userName = bstrdup(B_L, T(""));
+					wp->password = bstrdup(B_L, T(""));
+				}
+
+				wp->flags |= WEBS_AUTH_BASIC;
+			} else {
+#ifdef DIGEST_ACCESS_SUPPORT
+
+				char_t *np;		
+				char_t tp;		
+				char_t *vp;		
+				char_t *npv;	
+				char_t tpv;		
+
+				wp->flags |= WEBS_AUTH_DIGEST;
+
+ 				cp = value;
+				while (isgoodchar(*cp)) {
+					cp++;
+				}
+				while (!isgoodchar(*cp)) {
+					cp++;
+				}
+
+
+				vp = gstrchr(cp, '=');
+				while (vp) {
+
+					np = cp;
+					while (isgoodchar(*np)) {
+						np++;
+					}
+					tp = *np;
+					*np = 0;
+
+					vp++;
+					while (!isgoodchar(*vp)) {
+						vp++;
+					}
+
+					npv = vp;
+					while (isgoodchar(*npv)) {
+						npv++;
+					}
+					tpv = *npv;
+					*npv = 0;
+
+					if (gstricmp(cp, T("username")) == 0) {
+						wp->userName = bstrdup(B_L, vp);
+					} else if (gstricmp(cp, T("response")) == 0) {
+						wp->digest = bstrdup(B_L, vp);
+					} else if (gstricmp(cp, T("opaque")) == 0) {
+						wp->opaque = bstrdup(B_L, vp);
+					} else if (gstricmp(cp, T("uri")) == 0) {
+						wp->uri = bstrdup(B_L, vp);
+					} else if (gstricmp(cp, T("realm")) == 0) {
+						wp->realm = bstrdup(B_L, vp);
+					} else if (gstricmp(cp, T("nonce")) == 0) {
+						wp->nonce = bstrdup(B_L, vp);
+					} else if (gstricmp(cp, T("nc")) == 0) {
+						wp->nc = bstrdup(B_L, vp);
+					} else if (gstricmp(cp, T("cnonce")) == 0) {
+						wp->cnonce = bstrdup(B_L, vp);
+					} else if (gstricmp(cp, T("qop")) == 0) {
+						wp->qop = bstrdup(B_L, vp);
+					}
+
+					*np = tp;
+					*npv = tpv;
+
+ 					cp = npv;
+					while (*cp && isgoodchar(*cp)) {
+						cp++;
+					}
+					while (*cp && !isgoodchar(*cp)) {
+						cp++;
+					}
+
+					if (*cp) {
+						vp = gstrchr(cp, '=');
+					} else {
+						vp = NULL;
+					}
+				}
+#endif /* DIGEST_ACCESS_SUPPORT */
+			} /* if (gstrcmp(wp->authType)) */
+#ifdef WEBS_SECURITY
+		} else if (gstrcmp(key, T("x-http-method")) == 0) {
+			printf("websParseRequest: key=%s\n",key);
+			websError(wp, 405, T(""));
+			return -1;
+		} else if (gstrcmp(key, T("x-http-method-override")) == 0) {
+			printf("websParseRequest: key=%s\n",key);
+			websError(wp, 405, T(""));
+			return -1;
+		} else if (gstrcmp(key, T("x-method-override")) == 0) {
+			printf("websParseRequest: key=%s\n",key);
+			websError(wp, 405, T(""));
+			return -1;
+		} else if (gstrcmp(key, T("transfer-encoding")) == 0) {
+			printf("websParseRequest: key=%s\n",key);
+			if(smugglingFlag) {
+				websError(wp, 403, T(""));
+				return -1;
+			}
+			smugglingFlag = 1;
+#endif
+
+		} else if (gstrcmp(key, T("content-length")) == 0) {
+
+#ifdef WEBS_SECURITY
+		 if(smugglingFlag) {
+			 websError(wp, 403, T(""));
+			 return -1;
+		 }
+		 smugglingFlag = 1;
+#endif		 
+         wp->clen = gatoi(value);
+         if (wp->clen > 0)
+         {
+			   wp->flags |= WEBS_CLEN;			
+			   websSetVar(wp, T("CONTENT_LENGTH"), value);
+         }
+         else
+         {
+            wp->clen = 0;
+         }
+
+		} else if (gstrcmp(key, T("content-type")) == 0) {
+			websSetVar(wp, T("CONTENT_TYPE"), value);
+
+#ifdef WEBS_KEEP_ALIVE_SUPPORT
+		} else if (gstrcmp(key, T("connection")) == 0) {
+			strlower(value);
+			if (gstrcmp(value, T("keep-alive")) == 0) {
+				wp->flags |= WEBS_KEEP_ALIVE;
+			}
+#endif
+
+#ifdef WEBS_PROXY_SUPPORT
+
+		} else if (gstrcmp(key, T("pragma")) == 0) {
+			char_t	tmp[256];
+			gstrncpy(tmp, value, TSZ(tmp));
+			strlower(tmp);
+			if (gstrstr(tmp, T("no-cache"))) {
+				wp->flags |= WEBS_DONT_USE_CACHE;
+			}
+#endif /* WEBS_PROXY_SUPPORT */
+
+
+		} else if (gstrcmp(key, T("cookie")) == 0) {
+			wp->flags |= WEBS_COOKIE;
+			if (wp->cookie)
+				bfree(B_L, wp->cookie);
+			wp->cookie = bstrdup(B_L, value);
+		} else if (gstrcmp(key, T("referer")) == 0) {
+			if (wp->referer)
+				bfree(B_L, wp->referer);
+			wp->referer = bstrdup(B_L, value);
+
+		}
+	}
+	return 0;
+}
+
+
+int websTestVar(webs_t wp, char_t *var)
+{
+	sym_t		*sp;
+
+	a_assert(websValid(wp));
+
+	if (var == NULL || *var == '\0') {
+		return 0;
+	}
+
+	if ((sp = symLookup(wp->cgiVars, var)) == NULL) {
+		return 0;
+	}
+	return 1;
+}
+
+void websSetVar(webs_t wp, char_t *var, char_t *value)
+{
+	value_t		 v;
+
+	a_assert(websValid(wp));
+
+	if (value) {
+		v = valueString(value, VALUE_ALLOCATE);
+	} else {
+		v = valueString(T(""), VALUE_ALLOCATE);
+	}
+	symEnter(wp->cgiVars, var, v, 0);
+}
+
+
+void websSetEnv(webs_t wp)
+{
+	char_t	portBuf[8];
+	char_t	*keyword, *value, *valCheck, *valNew;
+
+	a_assert(websValid(wp));
+
+	websSetVar(wp, T("QUERY_STRING"), wp->query);
+	websSetVar(wp, T("GATEWAY_INTERFACE"), T("CGI/1.1"));
+	websSetVar(wp, T("SERVER_HOST"), websHost);
+	websSetVar(wp, T("SERVER_NAME"), websHost);
+	websSetVar(wp, T("SERVER_URL"), websHostUrl);
+	websSetVar(wp, T("REMOTE_HOST"), wp->ipaddr);
+	websSetVar(wp, T("REMOTE_ADDR"), wp->ipaddr);
+	websSetVar(wp, T("PATH_INFO"), wp->path);
+	stritoa(websPort, portBuf, sizeof(portBuf));
+	websSetVar(wp, T("SERVER_PORT"), portBuf);
+	websSetVar(wp, T("SERVER_ADDR"), websIpaddr);
+	fmtAlloc(&value, FNAMESIZE, T("%s/%s"), WEBS_NAME, WEBS_VERSION);
+	websSetVar(wp, T("SERVER_SOFTWARE"), value);
+	bfreeSafe(B_L, value);
+	websSetVar(wp, T("SERVER_PROTOCOL"), wp->protoVersion);
+
+	wp->decodedQuery = bstrdup(B_L, wp->query);
+	keyword = gstrtok(wp->decodedQuery, T("&"));
+	char tmp[4] = T("");
+	while (keyword != NULL) {
+		if ((value = gstrchr(keyword, '=')) != NULL) {
+			*value++ = '\0';
+			websDecodeUrl(keyword, keyword, gstrlen(keyword));
+			websDecodeUrl(value, value, gstrlen(value));
+		} else {
+			//value = T("");
+			value = tmp;// kw OVERWRITE_CONST_CHAR
+		}
+
+		if (*keyword) {
+
+			if ((valCheck = websGetVar(wp, keyword, NULL)) != 0) {
+				fmtAlloc(&valNew, 256, T("%s %s"), valCheck, value);
+				websSetVar(wp, keyword, valNew);
+				bfreeSafe(B_L, valNew);
+			} else {
+				websSetVar(wp, keyword, value);
+			}
+		}
+		keyword = gstrtok(NULL, T("&"));
+	}
+
+#ifdef EMF
+
+	websSetEmfEnvironment(wp);
+#endif
+}
+
+
+int websCompareVar(webs_t wp, char_t *var, char_t *value)
+{
+	a_assert(websValid(wp));
+	a_assert(var && *var);
+ 
+	if (gstrcmp(value, websGetVar(wp, var, T(" __UNDEF__ "))) == 0) {
+		return 1;
+	}
+	return 0;
+}
+
+char_t *websGetVar(webs_t wp, char_t *var, char_t *defaultGetValue)
+{
+	sym_t	*sp;
+
+	a_assert(websValid(wp));
+	a_assert(var && *var);
+ 
+	if ((sp = symLookup(wp->cgiVars, var)) != NULL) {
+		a_assert(sp->content.type == string);
+		if (sp->content.value.string) {
+			return sp->content.value.string;
+		} else {
+			return T("");
+		}
+	}
+	return defaultGetValue;
+}
+
+
+void websResponse(webs_t wp, int code, char_t *message, char_t *redirect)
+{
+	char_t		*date;
+
+	a_assert(websValid(wp));
+
+	wp->flags &= ~WEBS_KEEP_ALIVE;
+
+	if ( !(wp->flags & WEBS_HEADER_DONE)) {
+		wp->flags |= WEBS_HEADER_DONE;
+
+		if (redirect != NULL) {
+			websWrite(wp, T("HTTP/1.0 %d %s\r\n"), code, websErrorMsg(code));
+		} else {
+			websWrite(wp, T("HTTP/1.1 %d %s\r\n"), code, websErrorMsg(code));
+		}
+
+
+		websWrite(wp, T("Server: %s\r\n"), WEBS_NAME);
+
+		if ((date = websGetDateString(NULL)) != NULL) {
+			websWrite(wp, T("Date: %s\r\n"), date);
+			bfree(B_L, date);
+		}
+
+		if (code == 401) {
+			if (!(wp->flags & WEBS_AUTH_DIGEST)) {
+				websWrite(wp, T("WWW-Authenticate: Basic realm=\"%s\"\r\n"), 
+					websGetRealm());
+#ifdef DIGEST_ACCESS_SUPPORT
+			} else {
+				char_t *nonce, *opaque;
+
+            /* $$$ before... (note commas instead of semicolons...)
+				nonce = websCalcNonce(wp), 
+				opaque = websCalcOpaque(wp), 
+            $$$ after */
+				nonce = websCalcNonce(wp);
+				opaque = websCalcOpaque(wp); 
+            /* ...$$$ end */
+				websWrite(wp, 
+					T("WWW-Authenticate: Digest realm=\"%s\", domain=\"%s\",")
+					T("qop=\"%s\", nonce=\"%s\", opaque=\"%s\",")
+					T("algorithm=\"%s\", stale=\"%s\"\r\n"), 
+					websGetRealm(),
+					websGetHostUrl(),
+					T("auth"),
+					nonce,
+					opaque, T("MD5"), T("FALSE"));
+				bfree(B_L, nonce);
+				bfree(B_L, opaque);
+#endif
+			}
+		}
+
+		if (wp->flags & WEBS_KEEP_ALIVE) {
+			websWrite(wp, T("Connection: keep-alive\r\n"));
+		}
+#ifdef WEBINSPECT_FIX
+		websWrite(wp, T("X-Frame-Options: SAMEORIGIN\r\n"));
+#endif
+		websWrite(wp, T("Pragma: no-cache\r\nCache-Control: no-cache\r\n"));
+		websWrite(wp, T("Content-Type: text/html\r\n"));
+
+		if (redirect) {
+			websWrite(wp, T("Location: %s\r\n"), redirect);
+		}
+		websWrite(wp, T("\r\n"));
+	}
+
+
+	if ((wp->flags & WEBS_HEAD_REQUEST) == 0 && message && *message) {
+		websWrite(wp, T("%s\r\n"), message);
+	}
+	websDone(wp, code);
+}
+
+void websTimeoutCancel(webs_t wp)
+{
+	a_assert(websValid(wp));
+
+	if (wp->timeout >= 0) {
+		emfUnschedCallback(wp->timeout);
+		wp->timeout = -1;
+	}
+}
+
+void websRedirect(webs_t wp, char_t *url)
+{
+	char_t	*msgbuf, *urlbuf, *redirectFmt;
+
+	a_assert(websValid(wp));
+	a_assert(url);
+
+	websStats.redirects++;
+	msgbuf = urlbuf = NULL;
+	
+	if (gstrstr(url, T("%0D")) || gstrstr(url, T("%0A")) 
+		|| gstrstr(url, T("%0d")) || gstrstr(url, T("%0a"))
+		|| gstrstr(url, T("\r")) || gstrstr(url, T("\n"))) {
+		printf("[goahead]Redirect injo %s\n",url);
+		url = T(ZTE_WEB_PAGE_LOGIN_NAME);
+		/*ÓÃÓÚÖØ¶¨ÏòµÄÊäÈë²ÎÊý²»Äܰüº¬»Ø³µºÍ»»ÐÐ×Ö·û£¬ÒÔ·ÀÖ¹HTTPÏìÓ¦²ð·Ö¹¥»÷*/
+	}
+
+
+	if (gstrstr(url, T("http://")) == NULL && gstrstr(url, T("https://")) == NULL) {
+		if (*url == '/') {
+			url++;
+		}
+
+		//redirectFmt = T("http://%s/%s");
+
+#ifdef WEBS_SSL_SUPPORT
+		//if (wp->flags & WEBS_SECURE) {			
+		if (websSSLIsOpen()) {
+			//redirectFmt = T("https://%s/%s");// kw OVERWRITE_CONST_CHAR
+			fmtAlloc(&urlbuf, WEBS_MAX_URL + 80, "https://%s/%s",
+				websGetVar(wp, T("HTTP_HOST"),	websHostUrl), url);
+		}
+		else
+#endif
+		{
+			fmtAlloc(&urlbuf, WEBS_MAX_URL + 80, "http://%s/%s",
+				websGetVar(wp, T("HTTP_HOST"), 	websHostUrl), url);
+		}
+		url = urlbuf;
+		printf("[goahead]Redirect %s\n",url);
+	}
+
+
+	fmtAlloc(&msgbuf, WEBS_MAX_URL + 80, 
+		T("<html><head></head><body>\r\n\
+		This document has moved to a new <a href=\"%s\">location</a>.\r\n\
+		Please update your documents to reflect the new location.\r\n\
+		</body></html>\r\n"), url);
+
+	websResponse(wp, 302, msgbuf, url);
+
+	bfreeSafe(B_L, msgbuf);
+	bfreeSafe(B_L, urlbuf);
+}
+
+static int charCount(const char_t* str, char_t ch);
+
+#define kLt '<'
+#define kLessThan T("&lt;")
+#define kGt '>'
+#define kGreaterThan T("&gt;")
+
+static char_t* websSafeUrl(const char_t* url)
+{
+
+   int ltCount = charCount(url, kLt);
+   int gtCount = charCount(url, kGt);
+   int safeLen = 0;
+   char_t* safeUrl = NULL;
+   char_t* src = NULL;
+   char_t* dest = NULL;
+
+   if (NULL != url)
+   {
+      safeLen = gstrlen(url);
+      if (ltCount == 0 && gtCount == 0)
+      {
+         safeUrl = bstrdup(B_L, (char_t*) url);
+      }
+      else
+      {
+         safeLen += (ltCount * 4);
+         safeLen += (gtCount * 4);
+
+         safeUrl = balloc(B_L, safeLen);
+         if (safeUrl != NULL)
+         {
+            src = (char_t*) url;
+            dest = safeUrl;
+            while (*src)
+            {
+               if (*src == kLt)
+               {
+                  gstrcpy(dest, kLessThan);
+                  dest += gstrlen(kLessThan);
+               }
+               else if (*src == kGt)
+               {
+                  gstrcpy(dest, kGreaterThan);
+                  dest += gstrlen(kGreaterThan);
+               }
+               else
+               {
+                  *dest++ = *src;
+               }
+               ++src;
+            }
+            /* don't forget to terminate the string...*/
+            *dest = '\0';
+         }
+      }
+   }
+   return safeUrl;
+}
+
+static int charCount(const char_t* str, char_t ch)
+{
+   int count = 0;
+   char_t* p = (char_t*) str;
+   
+   if (NULL == str)
+   {
+      return 0;
+   }
+
+   while (1)
+   {
+      p = gstrchr(p, ch);
+      if (NULL == p)
+      {
+         break;
+      }
+
+      ++count;
+      ++p;
+   }
+   return count;
+}
+
+
+char_t *websErrorMsg(int code)
+{
+	websErrorType	*ep;
+
+	for (ep = websErrors; ep->code; ep++) {
+		if (code == ep->code) {
+			return ep->msg;
+		}
+	}
+	a_assert(0);
+	return T("");
+}
+
+
+#ifdef qRichErrorPage
+extern int dmfRichError(webs_t wp, int code, char_t* userMsg);
+#endif
+void websError(webs_t wp, int code, char_t *fmt, ...)
+{
+	va_list		args = {0};
+	char_t		*msg, *userMsg, *buf;
+   char_t*     safeUrl = NULL;
+   char_t*     safeMsg = NULL;
+#ifdef qRichErrorPage
+   static int reEntry = 0;
+   int errorOk;
+#endif
+
+	a_assert(websValid(wp));
+	a_assert(fmt);
+
+	websStats.errors++;
+
+   safeUrl = websSafeUrl(wp->url);
+   bfreeSafe(B_L, wp->url);
+   wp->url = safeUrl;
+
+	va_start(args, fmt);
+	userMsg = NULL;
+	fmtValloc(&userMsg, WEBS_BUFSIZE, fmt, args);
+	va_end(args);
+   safeMsg = websSafeUrl(userMsg);
+   bfreeSafe(B_L, userMsg);
+   userMsg = safeMsg;
+   safeMsg  = NULL;
+
+
+
+#ifdef qRichErrorPage
+   if (!reEntry)
+   {
+
+      reEntry = 1;
+      errorOk = dmfRichError(wp, code, userMsg);
+      reEntry = 0;
+      if (errorOk)
+      {
+         bfreeSafe(B_L, userMsg);
+         return;
+      }
+      
+   }
+   
+#endif
+
+/*	msg = T("<html><head><title>Document Error: %s</title></head>\r\n\
+		<body><h2>Access Error: %s</h2>\r\n\
+		<p>%s</p></body></html>\r\n");*/
+// kw OVERWRITE_CONST_CHAR
+
+	buf = NULL;
+	fmtAlloc(&buf, WEBS_BUFSIZE, "<html><head><title>Document Error: %s</title></head>\r\n\
+		<body><h2>Access Error: %s</h2>\r\n\
+		<p>%s</p></body></html>\r\n", websErrorMsg(code), 
+		websErrorMsg(code), userMsg);
+
+	websResponse(wp, code, buf, NULL);
+	bfreeSafe(B_L, buf);
+	bfreeSafe(B_L, userMsg);
+}
+
+
+int websWriteBlock(webs_t wp, char_t *buf, int nChars)
+{
+	int		len, done;
+	char	*asciiBuf, *pBuf;
+
+	a_assert(wp);
+	a_assert(websValid(wp));
+	a_assert(buf);
+	a_assert(nChars >= 0);
+	if(wp == NULL)
+		return -1;//for kw
+
+	done = len = 0;
+
+	pBuf = asciiBuf = ballocUniToAsc(buf, nChars);
+	if(asciiBuf == NULL)
+		return -1;//for kw
+
+	while (nChars > 0) {  
+#ifdef WEBS_SSL_SUPPORT
+		if (wp->flags & WEBS_SECURE) {
+			if ((len = websSSLWrite(wp->wsp, pBuf, nChars)) < 0) {
+				bfree(B_L, asciiBuf);
+				return -1;
+			}
+			websSSLFlush(wp->wsp);
+		} else {
+			if ((len = socketWrite(wp->sid, pBuf, nChars)) < 0) {
+				bfree(B_L, asciiBuf);
+				return -1;
+			}
+			socketFlush(wp->sid);
+		}
+#else /* ! WEBS_SSL_SUPPORT */
+		if ((len = socketWrite(wp->sid, pBuf, nChars)) < 0) {
+			bfree(B_L, asciiBuf);
+			return -1;
+		}
+		socketFlush(wp->sid);
+#endif /* WEBS_SSL_SUPPORT */
+		nChars -= len;
+		pBuf += len;
+		done += len;
+	}
+
+	bfree(B_L, asciiBuf);
+	return done;
+}
+
+int websWrite(webs_t wp, char_t *fmt, ...)
+{
+	va_list		 vargs = {0};
+	char_t		*buf;
+	int			 rc;
+	
+	a_assert(websValid(wp));
+
+	va_start(vargs, fmt);
+
+	buf = NULL;
+	rc = 0;
+
+	if (fmtValloc(&buf, WEBS_BUFSIZE, fmt, vargs) >= WEBS_BUFSIZE) {
+		trace(0, T("webs: websWrite lost data, buffer overflow\n"));
+	}
+   
+	va_end(vargs);
+	a_assert(buf);
+	if (buf) {
+		rc = websWriteBlock(wp, buf, gstrlen(buf));
+		bfree(B_L, buf);
+	}
+	return rc;
+}
+
+
+void websDecodeUrl(char_t *decoded, char_t *token, int len)
+{
+	char_t	*ip,  *op;
+	int		num, i, c;
+	
+	a_assert(decoded);
+	a_assert(token);
+
+	op = decoded;
+	for (ip = token; *ip && len > 0; ip++, op++) {
+		if (*ip == '+') {
+			*op = ' ';
+		} else if (*ip == '%' && gisxdigit(ip[1]) && gisxdigit(ip[2])) {
+
+			ip++;
+			for (i = 0, num = 0; i < 2; i++, ip++) {
+				c = tolower(*ip);
+				if (c >= 'a' && c <= 'f') {
+					num = (num * 16) + 10 + c - 'a';
+				} else {
+					num = (num * 16) + c - '0';
+				}
+			}
+			*op = (char_t) num;
+			ip--;
+
+		} else {
+			*op = *ip;
+		}
+		len--;
+	}
+	*op = '\0';
+}
+
+int websWriteDataNonBlock(webs_t wp, char *buf, int nChars)
+{
+	int r;
+
+	a_assert(wp);
+	a_assert(websValid(wp));
+	a_assert(buf);
+	a_assert(nChars >= 0);
+
+#ifdef WEBS_SSL_SUPPORT
+	if (wp->flags & WEBS_SECURE) {
+		r = websSSLWrite(wp->wsp, buf, nChars);
+		websSSLFlush(wp->wsp);
+	} else {
+		r = socketWrite(wp->sid, buf, nChars);
+		socketFlush(wp->sid);
+	}
+#else
+	r = socketWrite(wp->sid, buf, nChars);
+	socketFlush(wp->sid);
+#endif
+
+	return r;
+}
+
+
+void websTimeout(void *arg, int id)
+{
+	webs_t		wp;
+	int			delay, tm;
+
+	wp = (webs_t) arg;
+	a_assert(websValid(wp));
+
+	tm = websGetTimeSinceMark(wp) * 1000;
+	trace(8, T("@@websTimeout %d ip:%s url:%s\n"),tm,wp->ipaddr,wp->url);
+	if (tm >= WEBS_TIMEOUT) {
+		websStats.timeouts++;
+		emfUnschedCallback(id);
+
+		wp->timeout = -1;
+		websDone(wp, 404);
+	} else {
+		delay = WEBS_TIMEOUT - tm;
+		a_assert(delay > 0);
+		emfReschedCallback(id, delay);
+	}
+}
+
+void websDone(webs_t wp, int code)
+{
+	a_assert(websValid(wp));
+
+	socketDeleteHandler(wp->sid);
+
+	if (code != 200) {
+		wp->flags &= ~WEBS_KEEP_ALIVE;
+	}
+
+	websPageClose(wp);
+
+#ifdef WEBS_SSL_SUPPORT
+	if (wp->flags & WEBS_SECURE) {
+		websTimeoutCancel(wp);
+		websSSLFlush(wp->wsp);
+		socketCloseConnection(wp->sid);
+		websFree(wp);
+		return;
+	}
+#endif
+
+	if (wp->flags & WEBS_KEEP_ALIVE) {
+		if (socketFlush(wp->sid) == 0) {
+			wp->state = WEBS_BEGIN;
+			wp->flags |= WEBS_REQUEST_DONE;
+			if (wp->header.buf) {
+				ringqFlush(&wp->header);
+			}
+			socketCreateHandler(wp->sid, SOCKET_READABLE, websSocketEvent, 
+				(int) wp);
+			websTimeoutCancel(wp);
+			wp->timeout = emfSchedCallback(WEBS_TIMEOUT, websTimeout,
+				(void *) wp);
+			return;
+		}
+	} else {
+		websTimeoutCancel(wp);
+		socketSetBlock(wp->sid, 1);
+		socketFlush(wp->sid);
+		socketCloseConnection(wp->sid);
+	}
+	websFree(wp);
+}
+
+void websFree(webs_t wp)
+{
+	a_assert(websValid(wp));
+
+	if (wp->path)
+		bfree(B_L, wp->path);
+	if (wp->url)
+		bfree(B_L, wp->url);
+	if (wp->host)
+		bfree(B_L, wp->host);
+	if (wp->lpath)
+		bfree(B_L, wp->lpath);
+	if (wp->query)
+		bfree(B_L, wp->query);
+	if (wp->decodedQuery)
+		bfree(B_L, wp->decodedQuery);
+	if (wp->authType)
+		bfree(B_L, wp->authType);
+	if (wp->password)
+		bfree(B_L, wp->password);
+	if (wp->userName)
+		bfree(B_L, wp->userName);
+	if (wp->cookie)
+		bfree(B_L, wp->cookie);
+	if (wp->referer)
+		bfree(B_L, wp->referer);
+	if (wp->userAgent)
+		bfree(B_L, wp->userAgent);
+	if (wp->dir)
+		bfree(B_L, wp->dir);
+	if (wp->protocol)
+		bfree(B_L, wp->protocol);
+	if (wp->protoVersion)
+		bfree(B_L, wp->protoVersion);
+	if (wp->cgiStdin)
+		bfree(B_L, wp->cgiStdin);
+
+
+#ifdef DIGEST_ACCESS_SUPPORT
+	if (wp->realm)
+		bfree(B_L, wp->realm);
+	if (wp->uri)
+		bfree(B_L, wp->uri);
+	if (wp->digest)
+		bfree(B_L, wp->digest);
+	if (wp->opaque)
+		bfree(B_L, wp->opaque);
+	if (wp->nonce)
+		bfree(B_L, wp->nonce);
+	if (wp->nc)
+		bfree(B_L, wp->nc);
+	if (wp->cnonce)
+		bfree(B_L, wp->cnonce);
+	if (wp->qop)
+		bfree(B_L, wp->qop);
+#endif
+#ifdef WEBS_SSL_SUPPORT
+	websSSLFree(wp->wsp);
+#endif
+	symClose(wp->cgiVars);
+
+	if (wp->header.buf) {
+		ringqClose(&wp->header);
+	}
+
+	websMax = hFree((void***) &webs, wp->wid);
+	bfree(B_L, wp);
+	a_assert(websMax >= 0);
+}
+
+
+int websAlloc(int sid)
+{
+	webs_t		wp;
+	int			wid;
+
+	if ((wid = hAllocEntry((void***) &webs, &websMax,
+			sizeof(struct websRec))) < 0) {
+		return -1;
+	}
+	wp = webs[wid];
+
+	wp->wid = wid;
+	wp->sid = sid;
+	wp->state = WEBS_BEGIN;
+	wp->docfd = -1;
+	wp->timeout = -1;
+	wp->dir = NULL;
+	wp->authType = NULL;
+	wp->protocol = NULL;
+	wp->protoVersion = NULL;
+	wp->password = NULL;
+	wp->userName = NULL;
+	wp->cookie = NULL;
+	wp->referer = NULL;
+	wp->has_firmware_upload_clean = 0;
+    wp->has_firmware_upload_shell = 0;
+#ifdef DIGEST_ACCESS_SUPPORT
+	wp->realm = NULL;
+	wp->nonce = NULL;
+	wp->digest = NULL;
+	wp->uri = NULL;
+	wp->opaque = NULL;
+	wp->nc = NULL;
+	wp->cnonce = NULL;
+	wp->qop = NULL;
+#endif
+#ifdef WEBS_SSL_SUPPORT
+	wp->wsp = NULL;
+#endif
+
+	ringqOpen(&wp->header, WEBS_HEADER_BUFINC, WEBS_MAX_HEADER);
+
+	wp->cgiVars = symOpen(WEBS_SYM_INIT);
+
+	return wid;
+}
+
+
+char_t *websGetIpaddrUrl()
+{
+	return websIpaddrUrl;
+}
+
+
+char_t *websGetHostUrl()
+{
+	return websHostUrl;
+}
+
+
+int websGetPort()
+{
+	return websPort;
+}
+
+char_t *websGetHost()
+{
+	return websHost;
+}
+
+
+int websGetRequestBytes(webs_t wp)
+{
+	a_assert(websValid(wp));
+
+	return wp->numbytes;
+}
+
+
+int websGetRequestFlags(webs_t wp)
+{
+	a_assert(websValid(wp));
+
+	return wp->flags;
+}
+
+char_t *websGetRequestDir(webs_t wp)
+{
+	a_assert(websValid(wp));
+
+	if (wp->dir == NULL) {
+		return T("");
+	}
+
+	return wp->dir;
+}
+
+
+int websGetSid(webs_t wp)
+{
+	a_assert(websValid(wp));
+
+	return wp->sid;
+}
+
+
+char_t *websGetRequestIpaddr(webs_t wp)
+{
+	a_assert(websValid(wp));
+	return wp->ipaddr;
+}
+
+
+#ifdef FEATURE_ZTE_WEB_TCARD
+//added by guo shoupeng 10124224 for http share 20111001 start
+char_t * websGetURL(webs_t wp)
+{
+	a_assert(websValid(wp));
+
+	return wp->url;
+}
+
+char_t *websGetFileName(webs_t wp)
+{
+	a_assert(websValid(wp));
+
+	return wp->cgiStdin;
+}
+
+
+int websGetState(webs_t wp)
+{
+	a_assert(websValid(wp));
+
+	return wp->state;
+}
+
+int websGetlen(webs_t wp)
+{
+	a_assert(websValid(wp));
+
+	return wp->clen;
+}
+
+//added by guo shoupeng 10124224 for http share 20111001 end
+#endif
+
+
+char_t *websGetRequestLpath(webs_t wp)
+{
+	a_assert(websValid(wp));
+
+	return wp->lpath;
+}
+
+
+char_t *websGetRequestPassword(webs_t wp)
+{
+	a_assert(websValid(wp));
+
+	return wp->password;
+}
+
+char_t *websGetRequestPath(webs_t wp)
+{
+	a_assert(websValid(wp));
+
+	if (wp->path == NULL) {
+		return T("");
+	}
+
+	return wp->path;
+}
+
+
+char_t *websGetRequestType(webs_t wp)
+{
+	a_assert(websValid(wp));
+
+	return wp->type;
+}
+
+
+int websGetRequestWritten(webs_t wp)
+{
+	a_assert(websValid(wp));
+
+	return wp->written;
+}
+
+
+char_t *websGetRequestUserName(webs_t wp)
+{
+	a_assert(websValid(wp));
+
+	return wp->userName;
+}
+
+void websSetHost(char_t *host)
+{
+	gstrncpy(websHost, host, TSZ(websHost)-1);
+}
+
+
+void websSetIpaddr(char_t *ipaddr)
+{
+	a_assert(ipaddr && *ipaddr);
+
+	gstrncpy(websIpaddr, ipaddr, TSZ(websIpaddr)-1);
+}
+
+void websSetHostUrl(char_t *url)
+{
+	a_assert(url && *url);
+
+	bfreeSafe(B_L, websHostUrl);
+	websHostUrl = gstrdup(B_L, url);
+}
+
+
+void websSetRequestBytes(webs_t wp, int bytes)
+{
+	a_assert(websValid(wp));
+	a_assert(bytes >= 0);
+
+	wp->numbytes = bytes;
+}
+
+
+void websSetRequestLpath(webs_t wp, char_t *lpath)
+{
+	a_assert(websValid(wp));
+	a_assert(lpath && *lpath);
+
+	if (wp->lpath) {
+		bfree(B_L, wp->lpath);
+	}
+	wp->lpath = bstrdup(B_L, lpath);
+	websSetVar(wp, T("PATH_TRANSLATED"), wp->lpath);
+}
+
+void websSetRequestFlags(webs_t wp, int flags)
+{
+	a_assert(websValid(wp));
+
+	wp->flags = flags;
+}
+
+
+void websSetRequestPath(webs_t wp, char_t *dir, char_t *path)
+{
+	char_t	*tmp;
+
+	a_assert(websValid(wp));
+
+	if (dir) { 
+		tmp = wp->dir;
+		wp->dir = bstrdup(B_L, dir);
+		if (tmp) {
+			bfree(B_L, tmp);
+		}
+	}
+	if (path) {
+		tmp = wp->path;
+		wp->path = bstrdup(B_L, path);
+		websSetVar(wp, T("PATH_INFO"), wp->path);
+		if (tmp) {
+			bfree(B_L, tmp);
+		}
+	}
+}
+
+
+void websSetRequestWritten(webs_t wp, int written)
+{
+	a_assert(websValid(wp));
+
+	wp->written = written;
+}
+
+
+void websSetRequestSocketHandler(webs_t wp, int mask, void (*fn)(webs_t wp))
+{
+	a_assert(websValid(wp));
+
+	wp->writeSocket = fn;
+	socketCreateHandler(wp->sid, SOCKET_WRITABLE, websSocketEvent, (int) wp);
+}
+
+
+char_t *websGetDateString(websStatType *sbuf)
+{
+	char_t*	cp, *r;
+	time_t	now;
+
+	if (sbuf == NULL) {
+		time(&now);
+	} else {
+		now = sbuf->mtime;
+	}
+	if ((cp = gctime(&now)) != NULL) {
+		cp[gstrlen(cp) - 1] = '\0';
+		r = bstrdup(B_L, cp);
+		return r;
+	}
+	return NULL;
+}
+
+
+int websValid(webs_t wp)
+{
+	int		wid;
+
+	for (wid = 0; wid < websMax; wid++) {
+		if (wp == webs[wid]) {
+			return 1;
+		}
+	}
+	return 0;
+}
+
+
+void websSetTimeMark(webs_t wp)
+{
+	wp->timestamp = get_sys_uptime();
+}
+
+
+void websSetRealm(char_t *realmName)
+{
+	a_assert(realmName);
+
+	gstrncpy(websRealm, realmName, TSZ(websRealm)-1);
+}
+
+
+char_t *websGetRealm()
+{
+	return websRealm;
+}
+
+
+static int websGetTimeSinceMark(webs_t wp)
+{
+	return get_sys_uptime() - wp->timestamp;
+}
+
+void websSetLoginTimemark(webs_t wp)
+{
+
+    char_t login_timemark[64] = {0};
+    char_t login_info[20] = {0};
+    char_t nv_ipaddr[40] = {0};
+    char_t *ip_address = NULL;
+    zte_topsw_state_e_type status = ZTE_NVIO_MAX;
+    long timemark = 0;    
+    char_t user_login_timemark[64] = {0};
+    long timemark_check = 0;
+	long luser_login_timemark = 0;
+
+  
+    status = zte_web_read(NV_LOGINFO, login_info);
+
+    if(0 == strcmp(login_info,"ok"))
+    {
+
+        zte_web_read("user_login_timemark", user_login_timemark);
+
+        luser_login_timemark = atol(user_login_timemark);
+		if(luser_login_timemark < 0 || luser_login_timemark > LONG_MAX-1){
+            luser_login_timemark = LONG_MAX;
+		}
+		
+        timemark_check = time(0) - luser_login_timemark;  
+        if(timemark_check > LOGIN_TIMEOUT)
+        {
+            (void)zte_web_write(NV_USER_IP_ADDR,"");
+            (void)zte_web_write(NV_LOGINFO,"timeout");
+			(void)zte_web_write(NV_COOKIE_ID, "");
+            (void)zte_web_write(NV_USER_LOGIN_TIMEMARK,"0");
+            slog(MISC_PRINT,SLOG_ERR,"zte_mgmt_login_timemark_check: the login is timeout .\n");
+        }
+        else
+        {
+            ip_address = websGetRequestIpaddr(wp);
+#if 0		 // kw 3 INVARIANT_CONDITION.UNREACH	  wp->ipaddr is array, address can not be null
+            if (NULL == ip_address)
+            {
+                slog(MISC_PRINT,SLOG_ERR,"websSetLoginTimemark: ip_address is null.\n");
+                return ;
+            }
+#endif
+            zte_web_read(NV_USER_IP_ADDR, nv_ipaddr);
+           
+
+            if (0 == strcmp(ip_address,nv_ipaddr))
+            {
+                timemark = time(0);
+                sprintf(login_timemark,"%ld",timemark);  
+                (void)zte_web_write(NV_USER_LOGIN_TIMEMARK, login_timemark);
+            }
+
+         }
+    }  
+
+}
+
diff --git a/ap/app/goahead/server/webs.h b/ap/app/goahead/server/webs.h
new file mode 100755
index 0000000..9dcb6af
--- /dev/null
+++ b/ap/app/goahead/server/webs.h
@@ -0,0 +1,267 @@
+#ifndef _h_WEBS
+#define _h_WEBS 1
+
+#include	"ej.h"
+#ifdef WEBS_SSL_SUPPORT
+	#include	"websSSL.h"
+#else	
+static inline int websSSLIsOpen()
+{
+	return 0;
+}
+#endif
+
+
+#ifdef WEBINSPECT_FIX 
+#define WEBS_NAME				T("Demo-Webs")
+#else
+#define WEBS_NAME				T("GoAhead-Webs")
+#endif
+#define WEBS_VERSION			T("2.1.8")
+
+#define WEBS_HEADER_BUFINC 		512			
+#define WEBS_ASP_BUFINC			512			
+#define WEBS_MAX_PASS			32			
+
+#define WEBS_BUFSIZE			(8*1024)
+
+#define WEBS_MAX_HEADER			(5 * 1024)	
+#define WEBS_MAX_URL			4096		
+#ifdef FEATURE_ZTE_WEB_TCARD
+//added for http share 20111001 start
+#define WEBS_SOCKET_BUFSIZ		4*1024		
+#else
+#define WEBS_SOCKET_BUFSIZ		4*1024		
+//added for http share 20111001 end
+#endif
+//added for PC Client begin, 20120829
+#define HTTP_BUFFER_SIZE    (5*1024)
+//added for PC Client end, 20120829
+#define WEBS_HTTP_PORT			T("httpPort")
+#define CGI_BIN					T("cgi-bin")
+#define CGI_BIN_UPLOAD			T("cgi-bin/upload/")
+#define CGI_BIN_HTTPSHARE		T("cgi-bin/httpshare/")
+
+
+#define WEBS_LOCAL_PAGE			0x1			
+#define WEBS_KEEP_ALIVE			0x2			
+#define WEBS_DONT_USE_CACHE		0x4			
+#define WEBS_COOKIE				0x8			
+#define WEBS_IF_MODIFIED		0x10		
+#define WEBS_POST_REQUEST		0x20		
+#define WEBS_LOCAL_REQUEST		0x40		
+#define WEBS_HOME_PAGE			0x80		
+#define WEBS_ASP				0x100		 
+#define WEBS_HEAD_REQUEST		0x200		
+#define WEBS_CLEN				0x400		
+#define WEBS_FORM				0x800		
+#define WEBS_REQUEST_DONE		0x1000		
+#define WEBS_POST_DATA			0x2000		
+#define WEBS_CGI_REQUEST		0x4000		
+#define WEBS_SECURE				0x8000		
+#define WEBS_AUTH_BASIC			0x10000		
+#define WEBS_AUTH_DIGEST		0x20000		
+#define WEBS_HEADER_DONE		0x40000		
+#define WEBS_CGI_UPLOAD			0x80000		
+#define WEBS_CGI_FIRMWARE_UPLOAD 0x100000	
+#define WEBS_CGI_HTTPSHARE_UPLOAD 0x200000	
+
+
+#define CGI_UPLOAD				T("upload")
+#define CGI_FIRMWARE_UPLOAD		T("upload.cgi")
+#define CGI_FIRMWARE_WRITE      T("upload.write")
+#define CGI_HTTPSHARE_UPLOAD      T("httpshare.up")
+
+//#define FIRMWARE_TMP_FILE                  T("/var/firmware_tmp_file")
+#define FIRMWARE_TMP_FILE                  T("/firmware_tmp_file")
+
+//added by liuyingnan for PC Client begin, 20120829
+#define WEBS_REST_CLIENT_REQUEST       0x200000
+#define WEBS_XML_CLIENT_REQUEST       0x400000
+//added by liuyingnan for PC Client end, 20120829
+
+
+#define WEBS_HANDLER_FIRST	0x1			
+#define WEBS_HANDLER_LAST	0x2			
+
+typedef struct websRec {
+	ringq_t			header;				
+	time_t			since;				
+	sym_fd_t		cgiVars;			
+	sym_fd_t		cgiQuery;			
+	time_t			timestamp;			
+	int				timeout;			
+	char_t			ipaddr[40];			
+	char_t			ifaddr[32];			
+	char_t			type[64];			
+	char_t			*dir;				
+	char_t			*path;				
+	char_t			*url;				
+	char_t			*host;				
+	char_t			*lpath;				
+	char_t			*query;				
+	char_t			*decodedQuery;		
+	char_t			*authType;			
+	char_t			*password;			
+	char_t			*userName;			
+	char_t			*cookie;			
+	char_t			*referer;			
+	char_t			*userAgent;			
+	char_t			*protocol;			
+	char_t			*protoVersion;		
+	int				sid;				
+	int				listenSid;			
+	int				port;				
+	int				state;				
+	int				flags;				
+	int				code;				
+	int				clen;				
+	int				wid;				
+	char_t			*cgiStdin;			
+	int				docfd;				
+	int				numbytes;			
+	int				written;			
+	int				has_firmware_upload_clean; 
+    int				has_firmware_upload_shell; 
+	void			(*writeSocket)(struct websRec *wp);
+#ifdef DIGEST_ACCESS_SUPPORT
+    char_t			*realm;		
+    char_t			*nonce;		
+    char_t			*digest;	
+    char_t			*uri;		
+    char_t			*opaque;	
+    char_t			*nc;		
+    char_t			*cnonce;	
+    char_t			*qop;		
+#endif
+#ifdef WEBS_SSL_SUPPORT
+	websSSL_t		*wsp;		
+#endif
+} websRec;
+
+typedef websRec	*webs_t;
+typedef websRec websType;
+
+extern void 	 websSetDefaultDir(char_t *dir);
+extern void 	 websSetDefaultPage(char_t *page);
+
+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);
+
+extern void  	 websFooter(webs_t wp);
+extern int 		 websFormDefine(char_t *name, void (*fn)(webs_t wp, 
+					char_t *path, char_t *query));
+
+extern int 		 websDecode64(char_t *outbuf, char_t *string, int buflen);
+extern void		 websDecodeUrl(char_t *token, char_t *decoded, int len);
+
+extern void 	 websEncode64(char_t *outbuf, char_t *string, int buflen);
+
+
+extern void		 websCloseListen();
+extern void  	 websDone(webs_t wp, int code);
+
+extern void  	 websError(webs_t wp, int code, char_t *msg, ...);
+extern char_t 	*websErrorMsg(int code);
+
+extern char_t 	*websGetDefaultDir();
+extern char_t 	*websGetDefaultPage();
+
+extern char_t 	*websGetRealm();
+extern int 		 websGetRequestBytes(webs_t wp);
+extern char_t	*websGetRequestDir(webs_t wp);
+extern int		 websGetRequestFlags(webs_t wp);
+
+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	*websGetRequestType(webs_t wp);
+extern int 		 websGetRequestWritten(webs_t wp);
+
+extern char_t	*websGetRequestIpaddr(webs_t wp);
+extern int 		websGetSid(webs_t wp);
+extern char_t 	*websGetRequestLpath(webs_t wp);
+extern char_t	*websGetRequestPath(webs_t wp);
+extern char_t	*websGetRequestPassword(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 int 		 websPublish(char_t *urlPrefix, char_t *path);
+extern void		 websRedirect(webs_t wp, char_t *url);
+extern void 	 websSecurityDelete();
+extern int 		 websSecurityHandler(webs_t wp, char_t *urlPrefix, 
+					char_t *webDir, int arg, char_t *url, char_t *path, 
+					char_t *query);
+
+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,
+					int mode, int perm);
+extern void 	 websPageClose(webs_t wp);
+
+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 	 websSetVar(webs_t wp, char_t *var, char_t *value);
+extern int 		 websTestVar(webs_t wp, char_t *var);
+
+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, 
+					char_t *query), int flags);
+extern int 		 websUrlHandlerDelete(int (*fn)(webs_t wp, char_t *urlPrefix,
+					char_t *webDir, int arg, char_t *url, char_t *path, 
+					char_t *query));
+extern int		 websUrlHandlerRequest(webs_t wp);
+extern int 		 websUrlParse(char_t *url, char_t **buf, char_t **host, 
+					char_t **path, char_t **port, char_t **query, 
+					char_t **proto, char_t **tag, char_t **ext);
+extern char_t 	*websUrlType(char_t *webs, char_t *buf, int charCnt);
+
+extern int 		 websValid(webs_t wp);
+extern int 		 websValidateUrl(webs_t wp, char_t *path);
+
+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);
+extern void 	 websSetRequestPath(webs_t wp, char_t *dir, char_t *path);
+extern char_t	*websGetRequestUserName(webs_t wp);
+extern void 	 websSetRequestWritten(webs_t wp, int written);
+
+extern int 		 websWrite(webs_t wp, char_t* fmt, ...);
+extern int 		 websWriteBlock(webs_t wp, char_t *buf, int nChars);
+extern int 		 websWriteDataNonBlock(webs_t wp, char *buf, int nChars);
+
+
+extern void 	websTimeout(void *arg, int id);
+extern void		websSetTimeMark(webs_t wp);
+extern void		 websTimeoutCancel(webs_t wp);
+
+
+extern int 		websAlloc(int sid);
+extern void 	websFree(webs_t wp);
+
+extern void 	websReadEvent(webs_t wp);
+
+
+extern char websRecvHttpBuffer[HTTP_BUFFER_SIZE];
+extern int is_print_str(char *str, int len);
+
+#ifdef EMF
+extern void 	 websFormExplain(webs_t wp, char_t *path, char_t *query);
+#endif
+
+extern int web_make_salt_base64(char *id, int len);
+
+#endif /* _h_WEBS */
+
diff --git a/ap/app/goahead/server/websSSL.c b/ap/app/goahead/server/websSSL.c
new file mode 100755
index 0000000..30949b2
--- /dev/null
+++ b/ap/app/goahead/server/websSSL.c
@@ -0,0 +1,759 @@
+#ifndef __ENABLE_MOCANA_SSL_SERVER__ 
+
+#include	"wsIntrn.h"
+#include	"webs.h"
+#include	"websSSL.h"
+#include	"ref_nv_def.h"
+
+
+#define DEFAULT_KEY_FILE	"/etc_ro/certs/cakey.pem"
+#define DEFAULT_CA_FILE		"/etc_ro/certs/cacert.pem"
+#define DEFAULT_PWD_FILE	"/etc_ro/certs/password"
+#define SSL_PORT			443
+
+#define DEFAULT_KEY_MASK	0x60
+typedef struct websSSLKey {
+	char pwd[17];
+	unsigned char procType;
+	unsigned short dekType;
+	unsigned char dekInfo[16];
+	unsigned char privateKey[624];
+	unsigned short certLen;
+} websSSLKey;
+
+
+
+#ifdef SIGPIPE
+#define do_pipe_sig()	signal(SIGPIPE,SIG_IGN)
+#else
+#define do_pipe_sig()
+#endif
+
+
+#  if defined(MSDOS) || defined(WIN16) || defined(WIN32)
+#    ifdef _O_BINARY
+#      define apps_startup() \
+		_fmode=_O_BINARY; do_pipe_sig(); CRYPTO_malloc_init(); \
+		SSLC_add_all_algorithms()
+#    else
+#      define apps_startup() \
+		_fmode=O_BINARY; do_pipe_sig(); CRYPTO_malloc_init(); \
+		SSLC_add_all_algorithms()
+#    endif
+#  else
+#    define apps_startup()	do_pipe_sig(); SSLC_add_all_algorithms();
+#  endif
+
+
+#ifdef OPENSSL
+#ifndef SSLeay_add_all_algorithms
+#define SSLeay_add_all_algorithms() OpenSSL_add_all_algorithms()
+#endif
+
+#define SSLC_add_all_algorithms()	SSLeay_add_all_algorithms()
+#else
+extern void SSLC_add_all_algorithms(void);
+#endif
+
+
+static int		websSSLVerifyCallback(int ok, X509_STORE_CTX *ctx);
+static RSA		*websSSLTempRSACallback(SSL *s, int is_export, int keylength);
+
+static int		websSSLReadEvent (webs_t wp);
+static int		websSSLAccept(int sid, char *ipaddr, int port, int listenSid);
+static void		websSSLSocketEvent(int sid, int mask, int data);
+static int		websSSLSetCertStuff(SSL_CTX *ctx, char *cert_file, char *key_file);
+
+
+static int		sslListenSock = -1;			
+static SSL_CTX	*sslctx = NULL;
+static char		*sslpwd = NULL;
+static websSSLKey sslkey = {0};
+static unsigned char *sslcert = NULL;
+
+
+static int getFileSize(char *lpath)
+{
+	gstat_t s;
+	
+	if (lpath && stat(lpath, &s) == 0) {
+		return s.st_size;
+	}
+	return 0;
+}
+
+
+int websSSLOpen()
+{
+	SSL_METHOD	*meth;
+
+	apps_startup();
+	trace(7, T("SSL: Initializing SSL\n")); 
+
+#ifdef SSLC
+	SSL_library_init();
+#endif
+
+	SSL_load_error_strings();
+
+#ifdef OPENSSL
+	SSLeay_add_ssl_algorithms();
+#endif
+
+
+#ifdef WEBINSPECT_FIX 
+	meth = TLSv1_2_server_method();
+#else 
+	meth = SSLv23_server_method();
+#endif	
+	sslctx = SSL_CTX_new(meth);
+
+	a_assert(sslctx);
+
+	if (sslctx == NULL) {
+		trace(2, T("SSL: Unable to create SSL context!\n")); 
+		return -1;
+	}
+
+
+	SSL_CTX_set_quiet_shutdown(sslctx, 1);
+	SSL_CTX_set_options(sslctx, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
+	SSL_CTX_sess_set_cache_size(sslctx, 128);
+	
+	EC_KEY *ecdh = EC_KEY_new_by_curve_name (NID_X9_62_prime256v1);
+	if (ecdh){
+		long eret = SSL_CTX_set_tmp_ecdh (sslctx, ecdh);
+		trace(2, T("SSL: ecdh:%x ret=%d\n"), ecdh, eret); 
+		EC_KEY_free(ecdh);
+		ecdh = NULL;
+	}
+
+
+#ifdef WEBINSPECT_FIX	
+	if(!SSL_CTX_set_cipher_list(sslctx,"ALL:!aNULL:!ADH:!eNULL:!LOW:!EXP:!NULL:!RC4:!RC2:!DES:!3DES:!SHA:!SHA256:!SHA384:!MD5+HIGH:+MEDIUM"))
+		trace(2, T("SSL: Unable to set !DES:!RC4:!SHA1\n")); 
+#endif		
+
+	unsigned char webkey_flag = 0;
+	int retCode = cpnv_NvItemRead(ZPS_REF_MSINFO_WEBKEY_FLAG_BASE_ADDR, &webkey_flag, sizeof(webkey_flag));
+	if (retCode == CPNV_ERROR)
+	{
+		trace(2, T("SSL: read cpnv keyflag error\n"));
+		websSSLClose();
+		return -1;
+	}
+	trace(2, T("SSL: webkey_flag=%d\n"),webkey_flag);
+	if (webkey_flag != 1)
+	{
+		ssize_t read_len = 0;
+		char *pwdFile = DEFAULT_PWD_FILE;
+		int pwdSize = getFileSize(pwdFile);
+		if(pwdSize > 0)
+		{
+			int fd = open(pwdFile, SOCKET_RDONLY | SOCKET_BINARY, 0666);
+			if(fd >= 0) 
+			{
+				sslpwd = balloc(B_L,pwdSize + 1);
+				if(sslpwd != NULL)
+				{
+					memset(sslpwd, 0, pwdSize + 1);
+					read_len = read(fd, sslpwd, pwdSize);
+					if(read_len < 0)
+					{
+						trace(2, T("read len:%d ; errno: %s\n"), read_len, strerror(errno)); 
+					}
+					trace(2, T("SSL: pwd:%s\n"), sslpwd); 
+					SSL_CTX_set_default_passwd_cb_userdata(sslctx, (void *)sslpwd);
+				}
+				close(fd);
+			}
+		}
+			
+		//char *certFile = DEFAULT_CA_FILE;
+		//char *keyFile = DEFAULT_KEY_FILE;// kw OVERWRITE_CONST_CHAR
+		if (websSSLSetCertStuff(sslctx, DEFAULT_CA_FILE, DEFAULT_KEY_FILE) != 0) {
+			websSSLClose();
+			return -1;
+		}
+	}
+	else
+	{
+		retCode = cpnv_NvItemRead(ZPS_REF_MSINFO_WEBKEY_DATA_BASE_ADDR, (unsigned char *)&sslkey, sizeof(sslkey));
+		char i = 0;
+		if (retCode == CPNV_ERROR)
+		{
+			trace(2, T("SSL: read cpnv key error\n"));
+			websSSLClose();
+			return -1;
+		}
+		trace(2, T("SSL: key procType=%d dekType=%d certLen=%d\n"),sslkey.procType,sslkey.dekType,sslkey.certLen);
+		sslcert = balloc(B_L, sslkey.certLen);
+		if(sslcert == NULL)
+		{
+			trace(2, T("SSL: alloc cpnv cert fail\n"));
+			websSSLClose();
+			return -1;
+		}
+		retCode = cpnv_NvItemRead(ZPS_REF_MSINFO_WEBKEY_DATA_BASE_ADDR+sizeof(sslkey), sslcert, sslkey.certLen);
+		if (retCode == CPNV_ERROR)
+		{
+			trace(2, T("SSL: read cpnv cert error\n"));
+			websSSLClose();
+			return -1;
+		}
+		for(i=0; i < sizeof(sslkey.pwd); i++)
+		{
+			if(sslkey.pwd[i] != 0)
+			{
+				sslkey.pwd[i] = sslkey.pwd[i] - DEFAULT_KEY_MASK;
+			}
+			else
+			{
+				break;
+			}
+		}
+		SSL_CTX_set_default_passwd_cb_userdata(sslctx, (void *)sslkey.pwd);
+		retCode = websSSLSetCertificate(sslctx, sslcert, sslkey.certLen);
+		if (retCode <= 0)
+		{
+			trace(2, T("SSL: websSSLSetCertificate fail ret=%d\n"),retCode);
+			websSSLClose();
+			return -1;
+		}
+		retCode = websSSLSetPrivateKey(sslctx, &sslkey);
+		if (retCode <= 0)
+		{
+			trace(2, T("SSL: websSSLSetPrivateKey fail ret=%d\n"),retCode);
+			websSSLClose();
+			return -1;
+		}
+	}
+
+	SSL_CTX_set_tmp_rsa_callback(sslctx, websSSLTempRSACallback);
+
+
+	SSL_CTX_set_verify(sslctx, SSL_VERIFY_NONE, websSSLVerifyCallback);
+
+
+	sslListenSock = socketOpenConnection6(NULL, SSL_PORT, 
+		websSSLAccept, SOCKET_BLOCK);
+
+	if (sslListenSock < 0) {
+		trace(2, T("SSL: Unable to open SSL socket on port <%d>!\n"), 
+			SSL_PORT);
+		return -1;
+	}
+
+	return 0;
+}
+
+
+
+int websSSLIsOpen()
+{
+	return (sslListenSock != -1);
+}
+
+
+
+int websSSLAccept(int sid, char *ipaddr, int port, int listenSid)
+{
+	webs_t	wp;
+	int		wid;
+
+	a_assert(ipaddr && *ipaddr);
+	a_assert(sid >= 0);
+	a_assert(port >= 0);
+
+
+	if ((wid = websAlloc(sid)) < 0) {
+		return -1;
+	}
+	wp = webs[wid];
+	a_assert(wp);
+	wp->listenSid = listenSid;
+
+	ascToUni(wp->ipaddr, ipaddr, min(sizeof(wp->ipaddr), strlen(ipaddr)+1));
+
+
+	if (gstrcmp(wp->ipaddr, T("127.0.0.1")) == 0 || 
+			gstrcmp(wp->ipaddr, websIpaddr) == 0 || 
+			gstrcmp(wp->ipaddr, websHost) == 0) {
+		wp->flags |= WEBS_LOCAL_REQUEST;
+	}
+
+	wp->flags |= WEBS_SECURE;
+
+
+	socketCreateHandler(sid, SOCKET_READABLE, websSSLSocketEvent, (int) wp);
+
+	wp->timeout = emfSchedCallback(WEBS_TIMEOUT, websTimeout, (void *) wp);
+	//trace(8, T("webs: accept request\n"));
+	return 0;
+}
+
+void websSSLClose()
+{
+	trace(7, T("SSL: Closing SSL\n")); 
+
+	if (sslctx != NULL) {
+		SSL_CTX_free(sslctx);
+		sslctx = NULL;
+	}
+
+	if (sslListenSock != -1) {
+		socketCloseConnection(sslListenSock);
+		sslListenSock = -1;
+	}
+
+	if(sslpwd != NULL) {
+		bfree(B_L, sslpwd);
+		sslpwd = NULL;
+	}
+
+#ifdef SSLC
+	SSL_library_cleanup();
+#endif
+}
+
+
+static int websSSLReadEvent (webs_t wp)
+{
+	int			ret, sock;
+	socket_t	*sptr;
+	SSL			*ssl;
+	BIO			*bio, *bioSSL, *bioSock;
+#ifdef DEV
+	const char	*ciphers;
+#endif
+
+	a_assert (wp);
+	a_assert(websValid(wp));
+
+	sptr = socketPtr(wp->sid);
+	a_assert(sptr);
+	if(sptr == NULL)
+		return -1;
+	sock = sptr->sock;
+
+	bio = BIO_new(BIO_f_buffer());
+	a_assert(bio);
+
+	if (!BIO_set_write_buffer_size(bio, 128)) {
+		return -1;
+	}
+
+	ssl = (SSL *) SSL_new(sslctx);
+	a_assert(ssl);
+
+	if (ssl == NULL) {
+		return -1;
+	}
+
+	SSL_set_session(ssl, NULL);
+
+	bioSSL =  BIO_new(BIO_f_ssl());
+	a_assert(bioSSL);
+
+	bioSock = BIO_new_socket(sock, BIO_NOCLOSE);
+	a_assert(bioSock);
+
+	SSL_set_bio(ssl, bioSock, bioSock);
+	SSL_set_accept_state(ssl);
+
+	ret = BIO_set_ssl(bioSSL, ssl, BIO_CLOSE);
+	BIO_push(bio, bioSSL);
+
+#ifdef DEV
+	ciphers = SSL_get_cipher_list(ssl, 10);
+#endif
+
+#ifdef WEBS_SSL_SUPPORT
+	websSSLFree(wp->wsp);
+	wp->wsp = balloc(B_L, sizeof(websSSL_t));
+	a_assert (wp->wsp);
+	if(wp->wsp == NULL)
+		return -1;
+	(wp->wsp)->bio = bio;
+	(wp->wsp)->ssl = ssl;
+#endif
+
+	websReadEvent(wp);
+
+	return ret;
+}
+
+static void websSSLSocketEvent(int sid, int mask, int iwp)
+{
+	webs_t	wp;
+
+	wp = (webs_t) iwp;
+	a_assert(wp);
+
+	if (! websValid(wp)) {
+		return;
+	}
+
+	if (mask & SOCKET_READABLE) {
+		websSSLReadEvent(wp);
+	} 
+	if (mask & SOCKET_WRITABLE) {
+		if (websValid(wp) && wp->writeSocket) {//cov
+			(*wp->writeSocket)(wp);
+		}
+	} 
+}
+
+static int sslVerifyDepth = 0;
+static int sslVerifyError = X509_V_OK;
+
+int websSSLVerifyCallback(int ok, X509_STORE_CTX *ctx)
+{
+	char	buf[256];
+	X509	*errCert;
+	int		err;
+	int		depth;
+
+	errCert =	X509_STORE_CTX_get_current_cert(ctx);
+	err =		X509_STORE_CTX_get_error(ctx);
+	depth =		X509_STORE_CTX_get_error_depth(ctx);
+
+	X509_NAME_oneline(X509_get_subject_name(errCert), buf, 256);
+
+	if (!ok) {
+		if (sslVerifyDepth >= depth)	{
+			ok = 1;
+			sslVerifyError = X509_V_OK;
+		} else {
+			ok=0;
+			sslVerifyError = X509_V_ERR_CERT_CHAIN_TOO_LONG;
+		}
+	}
+
+	switch (err)	{
+	case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
+#ifdef OPENSSL
+		//X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, 256);
+		X509_NAME_oneline(X509_get_issuer_name(X509_STORE_CTX_get_current_cert(ctx)), buf, 256);
+#endif
+		break;
+
+	case X509_V_ERR_CERT_NOT_YET_VALID:
+	case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
+	case X509_V_ERR_CERT_HAS_EXPIRED:
+	case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
+		break;
+	}
+
+	return ok;
+}
+
+int websSSLSetCertificate(SSL_CTX *ctx, const unsigned char *data, int len)
+{
+	BIO *in;
+	int ret = 0;
+	X509 *x = NULL;
+	
+	in = BIO_new(BIO_s_mem());
+	if (in == NULL) {
+		trace(2, T("SSL: cert BIO_new NULL\n"));
+		goto end;
+	}
+
+	ret = PEM_write_bio(in, PEM_STRING_X509, "", data, len);
+	if (ret <= 0){
+		trace(2, T("SSL: cert PEM_write_bio fail ret=%d\n"),ret);
+		goto end;
+	}
+	x = PEM_read_bio_X509(in, NULL,
+			SSL_CTX_get_default_passwd_cb(ctx),//ctx->default_passwd_callback,
+			SSL_CTX_get_default_passwd_cb_userdata(ctx));//ctx->default_passwd_callback_userdata);
+
+	if (x == NULL) {
+		trace(2, T("SSL: cert PEM_read_bio_X509 NULL\n"));
+		goto end;
+	}
+
+	ret = SSL_CTX_use_certificate(ctx, x);
+	X509_free(x);
+
+ end:
+	if (in != NULL)
+		BIO_free(in);
+	return (ret);
+}
+
+int websSSLSetPrivateKey(SSL_CTX *ctx, websSSLKey *key)
+{
+	int ret = 0;
+	BIO *in;
+	EVP_PKEY *pkey = NULL;
+	const char *objstr = NULL;
+	char buf[PEM_BUFSIZE] = {0};
+	
+	in = BIO_new(BIO_s_mem());
+	if (in == NULL) {
+		trace(2, T("SSL: key BIO_new NULL\n"));
+		goto end;
+	}
+
+	objstr = OBJ_nid2sn(key->dekType);
+	if (objstr == NULL) {
+		trace(2, T("SSL: key OBJ_nid2sn NULL type = %d\n"),key->dekType);
+		goto end;
+	}
+	PEM_proc_type(buf, key->procType);
+	PEM_dek_info(buf, objstr, sizeof(key->dekInfo), (char *)key->dekInfo);
+
+	ret = PEM_write_bio(in, PEM_STRING_RSA, buf, key->privateKey, sizeof(key->privateKey));
+	if (ret <= 0){
+		trace(2, T("SSL: key PEM_write_bio fail ret=%d\n"),ret);
+		goto end;
+	}
+	pkey = PEM_read_bio_PrivateKey(in, NULL,
+			SSL_CTX_get_default_passwd_cb(ctx),//ctx->default_passwd_callback,
+			SSL_CTX_get_default_passwd_cb_userdata(ctx));//ctx->default_passwd_callback_userdata);
+	if (pkey == NULL) {
+		trace(2, T("SSL: key PEM_read_bio_PrivateKey NULL\n"));
+		goto end;
+	}
+	ret = SSL_CTX_use_PrivateKey(ctx, pkey);
+	EVP_PKEY_free(pkey);
+	
+ end:
+	if (in != NULL)
+		BIO_free(in);
+	return (ret);
+}
+
+
+int websSSLSetCertStuff(SSL_CTX *ctx, char *certFile, char *keyFile)
+{
+	a_assert (ctx);
+	a_assert (certFile);
+
+	if (certFile != NULL) {
+		if (SSL_CTX_use_certificate_file(ctx, certFile, 
+			SSL_FILETYPE_PEM) <= 0) {
+			trace(2, T("SSL: Unable to set certificate file <%s>\n"),
+				certFile); 
+			return -1;
+		}
+
+		if (keyFile == NULL) {
+			keyFile = certFile;
+		}
+
+		if (SSL_CTX_use_PrivateKey_file(ctx, keyFile, SSL_FILETYPE_PEM) <= 0) {
+			trace(2, T("SSL: Unable to set private key file <%s>\n"),
+				keyFile); 
+			return -1;
+		}
+
+
+		if (!SSL_CTX_check_private_key(ctx)) {
+			trace(2, T("SSL: Check of private key file <%s> FAILED!\n"),
+				keyFile); 
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+
+int websSSLSetKeyFile(char_t *keyFile)
+{
+	a_assert (sslctx);
+	a_assert (keyFile);
+
+	if (sslctx == NULL) {
+		return -1;
+	}
+
+	if (SSL_CTX_use_PrivateKey_file(sslctx, keyFile, SSL_FILETYPE_PEM) <= 0) {
+		return -1;
+	}
+
+	if (!SSL_CTX_check_private_key(sslctx)) {
+		return -1;
+	}
+
+	return 0;
+}
+
+
+int websSSLSetCertFile(char_t *certFile)
+{
+	a_assert (sslctx);
+	a_assert (certFile);
+
+	if (sslctx == NULL) {
+		return -1;
+	}
+
+	if (SSL_CTX_use_certificate_file(sslctx, certFile, 
+		SSL_FILETYPE_PEM) <= 0) {
+		return -1;
+	}
+
+	if (!SSL_CTX_check_private_key(sslctx)) {
+		return -1;
+	}
+
+	return 0;
+}
+
+#ifdef SSLC
+extern RSA *RSA_new(void);
+#endif
+
+int websSSLEof(websSSL_t *wsp)
+{
+	a_assert(wsp);
+
+	if ((wsp == NULL) || (wsp->bio == NULL)) {
+		return -1;
+	} 
+
+	return BIO_eof(wsp->bio);
+}
+
+
+int websSSLRead(websSSL_t *wsp, char_t *buf, int len)
+{
+	a_assert(wsp);
+	a_assert(buf);
+
+	if ((wsp == NULL) || (wsp->bio == NULL)) {
+		return -1;
+	} 
+
+	return BIO_read(wsp->bio, buf, len);
+}
+
+static RSA *websSSLTempRSACallback(SSL *ssl, int isExport, int keyLength)
+{
+	static RSA *rsaTemp = NULL;
+
+	if (rsaTemp == NULL) {
+
+#ifdef OPENSSL
+		rsaTemp = RSA_generate_key(keyLength, RSA_F4, NULL, NULL);
+#endif
+
+#ifdef SSLC
+		rsaTemp = RSA_new();
+#endif
+
+	}
+
+	return rsaTemp;
+}
+
+
+int websSSLFree(websSSL_t *wsp)
+{
+	if (wsp == NULL) {
+		return -1;
+	}
+
+	if (wsp->ssl != NULL) {
+		SSL_set_shutdown(wsp->ssl, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
+	}
+
+	if (wsp->bio != NULL) {
+		BIO_free_all(wsp->bio);
+	}
+
+	bfree(B_L, wsp);
+
+	return 0;
+}
+
+
+
+
+#define BUF_BLOCK 256
+
+int websSSLGets(websSSL_t *wsp, char_t **buf)
+{
+	int		rc,	len, lenBuf;
+	char	c;
+
+	a_assert(wsp);
+	a_assert(buf);
+
+	lenBuf = 0;
+	len = 0;
+
+	if ((wsp == NULL) || (wsp->bio == NULL)) {
+		return -1;
+	} 
+
+	while (len < 1536) {
+
+		if ((rc = BIO_read(wsp->bio, &c, 1)) < 0) {
+			return rc;
+		}
+		
+		if (rc == 0) {
+
+			if (len > 0 && BIO_eof(wsp->bio)) {
+				c = '\n';
+			} else {
+				return -1;
+			}
+		}
+
+		if (c == '\n') {
+			if ((len > 0) && (len < lenBuf)) {
+				(*buf)[len] = 0;
+			}
+			return len;
+		} else if (c == '\r') {
+			continue;
+		} 
+
+		if (lenBuf == 0 || len >= lenBuf - 1) {
+			lenBuf += BUF_BLOCK;
+			*buf = brealloc(B_L, *buf, lenBuf);
+		}
+
+		a_assert(*buf);
+		if(*buf == NULL)
+			return -1;
+		(*buf)[len] = c;
+		len++;
+	}
+	bfreeSafe(B_L,*buf);
+	*buf = NULL;
+	return -1;
+}
+
+
+int websSSLWrite(websSSL_t *wsp, char_t *buf, int len)
+{
+	a_assert(wsp);
+	a_assert(buf);
+
+	if ((wsp == NULL) || (wsp->bio == NULL)) {
+		return -1;
+	} 
+
+	return BIO_write(wsp->bio, buf, len);
+}
+
+
+int websSSLFlush(websSSL_t *wsp)
+{
+	a_assert(wsp);
+
+	if ((wsp == NULL) || (wsp->bio == NULL)) {
+		return -1;
+	} 
+
+	return BIO_flush(wsp->bio);
+}
+
+#endif
diff --git a/ap/app/goahead/server/websSSL.h b/ap/app/goahead/server/websSSL.h
new file mode 100755
index 0000000..8f1abfe
--- /dev/null
+++ b/ap/app/goahead/server/websSSL.h
@@ -0,0 +1,45 @@
+#ifndef _h_websSSL
+#define _h_websSSL 1
+
+
+#ifdef OPENSSL
+#define SSLEAY		
+#define USE_SOCKETS 
+#include <openssl/ssl.h>
+#else
+#include <sslc.h>
+#endif
+
+#ifndef UEMF
+	#include	"basic/basic.h"
+	#include	"emf/emf.h"
+#else
+	#include	"uemf.h"
+#endif
+
+typedef struct {
+	SSL	*ssl;
+	BIO	*bio;
+} websSSL_t;
+
+
+extern int	websSSLIsOpen();
+
+extern int	websSSLGets(websSSL_t *wsp, char_t **buf);
+extern int	websSSLRead(websSSL_t *wsp, char_t *buf, int nChars);
+extern int	websSSLWrite(websSSL_t *wsp, char_t *buf, int nChars);
+
+extern int	websSSLOpen();
+extern void websSSLClose();
+
+extern int	websSSLEof(websSSL_t *wsp);
+
+extern int	websSSLFlush(websSSL_t *wsp);
+extern int	websSSLFree(websSSL_t *wsp);
+
+extern int	websSSLSetKeyFile(char_t *keyFile);
+extern int	websSSLSetCertFile(char_t *certFile);
+
+
+#endif /* _h_websSSL */
+
diff --git a/ap/app/goahead/server/websuemf.c b/ap/app/goahead/server/websuemf.c
new file mode 100755
index 0000000..0ebed71
--- /dev/null
+++ b/ap/app/goahead/server/websuemf.c
@@ -0,0 +1,141 @@
+#include	"ejIntrn.h"
+#include	"wsIntrn.h"
+
+
+typedef struct {
+	void	(*routine)(void *arg, int id);
+	void	*arg;
+	time_t	at;
+	int		schedid;
+} sched_t;
+
+
+static sched_t		**sched;
+static int			schedMax;
+
+
+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);
+}
+
+
+#if 0
+int scriptEval(int engine, char_t *cmd, char_t **result, int chan)
+{
+	int		ejid;
+
+	if (engine == EMF_SCRIPT_EJSCRIPT) {
+		ejid = (int) chan;
+      
+		if (ejEval(ejid, cmd, result) ) {
+			return 0;
+		} else {
+			return -1;
+		}
+	}
+	return -1;
+}
+#endif
+
+
+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->arg = arg;
+	s->routine = proc;
+	s->at = ((delay + 500) / 1000) + time(0);
+	s->schedid = schedid;
+
+	return schedid;
+}
+
+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;
+}
+
+void emfSchedProcess()
+{
+	sched_t		*s;
+	int			schedid;
+	static int	next = 0;	
+
+
+	if (schedMax <= 0) {
+		return;
+	}
+
+	if (next >= schedMax) {
+		next = 0;
+	}
+
+	schedid = next;
+	while(1) {
+		if ((s = sched[schedid]) != NULL &&	(int)s->at <= (int)time(0)) {
+			{
+				sched_t *s;
+			
+				a_assert(0 <= schedid && schedid < schedMax);
+				s = sched[schedid];
+				a_assert(s);
+			
+				(s->routine)(s->arg, s->schedid);
+			}
+			next = schedid + 1;
+			return;
+		}
+		if (++schedid >= schedMax) {
+			schedid = 0;
+		}
+		if (schedid == next) {
+
+			return;
+		}
+	};
+}
+
+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);
+}
+
diff --git a/ap/app/goahead/server/wsIntrn.h b/ap/app/goahead/server/wsIntrn.h
new file mode 100755
index 0000000..d55148e
--- /dev/null
+++ b/ap/app/goahead/server/wsIntrn.h
@@ -0,0 +1,292 @@
+
+#ifndef _h_WEBS_INTERNAL
+#define _h_WEBS_INTERNAL 1
+
+
+#include	<ctype.h>
+#include	<stdlib.h>
+#include	<string.h>
+#include	<stdarg.h>
+
+#ifdef NETWARE
+	#include	<fcntl.h>
+	#include	<sys/stat.h>
+	#include	<signal.h>
+	#include	<io.h>
+#endif
+
+#ifdef WIN
+	#include	<fcntl.h>
+	#include	<sys/stat.h>
+	#include	<io.h>
+#endif
+
+#ifdef CE
+#ifndef UEMF
+	#include	<io.h>
+#endif
+#endif
+
+#ifdef NW
+	#include	<fcntl.h>
+	#include	<sys/stat.h>
+#endif
+
+#ifdef SCOV5
+	#include	<fcntl.h>
+	#include	<sys/stat.h>
+	#include	<signal.h>
+	#include	<unistd.h>
+#endif
+
+#ifdef LYNX
+	#include	<fcntl.h>
+	#include	<sys/stat.h>
+	#include	<signal.h>
+	#include	<unistd.h>
+#endif
+
+#ifdef UNIX
+	#include	<fcntl.h>
+	#include	<sys/stat.h>
+	#include	<signal.h>
+	#include	<unistd.h>
+#endif
+
+#ifdef QNX4
+	#include	<fcntl.h>
+	#include	<sys/stat.h>
+	#include	<signal.h>
+	#include	<unistd.h>
+	#include	<unix.h>
+#endif
+
+#ifdef SOLARIS
+	#include	<macros.h>
+	#include	<fcntl.h>
+	#include	<sys/stat.h>
+#endif
+
+#ifdef VXWORKS
+	#include	<vxWorks.h>
+	#include	<fcntl.h>
+	#include	<sys/stat.h>
+#endif
+
+#ifdef UW
+	#include	<fcntl.h>
+	#include	<sys/stat.h>
+#endif
+
+#ifdef UEMF
+	#include	"uemf.h"
+	#include	"ejIntrn.h"
+#else
+	#include	"emf/emfInternal.h"
+	#include	"ej/ejIntrn.h"
+#endif
+
+#include	"webs.h"
+
+
+#define WEBS_BEGIN			0x1			
+#define WEBS_HEADER			0x2			
+#define WEBS_POST			0x4			
+#define WEBS_POST_CLEN		0x8			
+#define WEBS_PROCESSING		0x10		
+#define WEBS_KEEP_TIMEOUT	15000		
+#define WEBS_TIMEOUT		60000		
+
+#define PAGE_READ_BUFSIZE	512			
+#define MAX_PORT_LEN		10			
+#define WEBS_SYM_INIT		64			
+
+ 
+typedef struct {
+	int		(*handler)(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg, 
+			char_t *url, char_t *path, 
+			char_t *query);					
+	char_t	*webDir;						
+	char_t	*urlPrefix;						
+	int		len;							
+	int		arg;							
+	int		flags;							
+} websUrlHandlerType;
+
+
+typedef struct {
+	long			errors;					
+	long			redirects;
+	long			net_requests;
+	long			activeNetRequests;
+	long			activeBrowserRequests;
+	long 			timeouts;
+	long			access;					
+	long 			localHits;
+	long 			remoteHits;
+	long 			formHits;
+	long 			cgiHits;
+	long 			handlerHits;
+} websStatsType;
+
+extern websStatsType websStats;				
+
+typedef struct {
+	int		code;							
+	char_t	*msg;							
+} websErrorType;
+
+
+typedef struct {
+	char_t	*type;							
+	char_t	*ext;							
+} websMimeType;
+
+
+typedef struct {
+	unsigned long	size;					
+	int				isDir;					
+	time_t			mtime;					
+} websStatType;
+
+
+typedef struct {
+	char_t			*path;					
+	unsigned char	*page;					
+	int				size;					
+	int				pos;					
+} websRomPageIndexType;
+
+
+#ifndef CE
+#define	SOCKET_RDONLY	O_RDONLY
+#define	SOCKET_BINARY	O_BINARY
+#else /* CE */
+#define	SOCKET_RDONLY	0x1
+#define	SOCKET_BINARY	0x2
+#endif /* CE */
+
+//#define DOWNLOAD_INTERVAL  1048576  //4194304
+extern int zte_process_cgi_end(webs_t wp);
+extern int zte_check_downloading_file();
+extern int 		 websCgiDownLoadHandler(webs_t wp, char_t *urlPrefix, 
+					char_t *webDir, int arg,	char_t *url, char_t *path, 
+					char_t *query);
+
+#define DOWNLOAD_INTERVAL  1048576  //4194304
+#define UPLOAD_INTERVAL 65536
+
+#ifdef FEATURE_ZTE_WEB_TCARD
+//added by guo shoupeng 10124224 for http share 20111001 start
+#define UPLOAD_INTERVAL 65536
+#define DOWNLOAD_INTERVAL  1048576  //4194304
+#define PATH_SD_CARD "/mmc2"
+#define PATH_SD_MNT "/mnt"
+
+extern int sd_card_isExist();
+extern int sd_card_isClose (webs_t wp);
+extern int zte_process_cgi(webs_t wp);
+extern int zte_process_cgi_end(webs_t wp);
+extern int		 websGetState(webs_t wp);
+extern int		 websGetlen(webs_t wp);
+extern char_t * websGetURL(webs_t wp);
+extern int zte_efs_write(webs_t wp);
+
+extern int zte_http_share_process_flagfile_exist(const char *i_filename );
+extern int 		 websCgiDownLoadHandler(webs_t wp, char_t *urlPrefix, 
+					char_t *webDir, int arg,	char_t *url, char_t *path, 
+					char_t *query);
+
+//added by guo shoupeng 10124224 for http share 20111001 end
+#endif
+extern websRomPageIndexType	websRomPageIndex[];
+extern websMimeType		websMimeList[];		
+extern sym_fd_t			websMime;			
+extern webs_t*			webs;				
+extern int				websMax;			
+extern char_t			websHost[64];		
+extern char_t			websIpaddr[64];		
+extern char_t			*websHostUrl;		
+extern char_t			*websIpaddrUrl;		
+extern int				websPort;			
+
+extern char_t*	 websGetDateString(websStatType* sbuf);
+
+extern int		strcmpci(char_t* s1, char_t* s2);
+
+extern int		 websAspOpen();
+extern void		 websAspClose();
+
+extern int		 websAspWrite(int ejid, webs_t wp, int argc, char_t **argv);
+
+extern void		 websFormOpen();
+extern void		 websFormClose();
+
+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, int *status);
+extern char_t	 *websGetCgiCommName();
+
+extern int		 websLaunchCgiProc(char_t *cgiPath, char_t **argp,
+					char_t **envp, char_t *stdIn, char_t *stdOut);
+
+extern void  	 websDefaultClose();
+
+extern void 	 websUrlHandlerClose();
+extern int 		 websUrlHandlerOpen();
+
+extern int 		 websDefaultHandler(webs_t wp, char_t *urlPrefix, 
+					char_t *webDir, int arg, char_t *url, char_t *path, 
+					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 		 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 void		 websPageSeek(webs_t wp, long offset);
+extern int 	 	 websPageStat(webs_t wp, char_t *lpath, char_t *path,
+					websStatType *sbuf);
+extern int		 websPageIsDirectory(char_t *lpath);
+
+extern int		 websPageOpen(webs_t wp, char_t *lpath, char_t *path, int mode,
+					int perm);
+extern void		 websPageClose(webs_t wp);
+
+
+extern int 		 websRomPageOpen(webs_t wp, char_t *path, int mode, int perm);
+extern void 	 websRomPageClose(int fd);
+extern int 		 websRomPageReadData(webs_t wp, char *buf, int len);
+extern int 	 	 websRomPageStat(char_t *path, websStatType *sbuf);
+extern long		 websRomPageSeek(webs_t wp, long offset, int origin);
+
+extern int 		 websRomOpen();
+extern void		 websRomClose();
+
+extern void 	 websSetRequestSocketHandler(webs_t wp, int mask, 
+					void (*fn)(webs_t wp));
+extern int 		 websSolutionHandler(webs_t wp, char_t *urlPrefix,
+					char_t *webDir, int arg, char_t *url, char_t *path, 
+					char_t *query);
+
+extern int 		 websOpenServer(int port, int retries);
+extern void 	 websCloseServer();
+
+#ifdef CE
+extern int writeUniToAsc(int fid, void *buf, unsigned int len);
+extern int readAscToUni(int fid, void **buf, unsigned int len);
+#endif
+
+#ifdef EMF
+extern int 		 websEmfOpen();
+extern void 	 websSetEmfEnvironment(webs_t wp);
+extern void 	 websEmfClose();
+#endif
+
+
+#endif /* _h_WEBS_INTERNAL */
+