blob: 7742a7b6d44e430e1e92c1d6b93b308522f3e0c4 [file] [log] [blame]
#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 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);
}
}
}
}
}