[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/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);
+				}
+			}
+		}
+	}
+}
+