[T106][ZXW-22]7520V3SCV2.01.01.02P42U09_VEC_V0.8_AP_VEC origin source commit

Change-Id: Ic6e05d89ecd62fc34f82b23dcf306c93764aec4b
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);
+            }
+
+         }
+    }  
+
+}
+