[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/default.c b/ap/app/goahead/server/default.c
new file mode 100755
index 0000000..1aa79d4
--- /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};
+		sc_cfg_get(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))
+	{
+		sc_cfg_get("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);
+}
+
+