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