#include "p_apps.h"
#include "v_task.h"
#include "p_http.h"

//#ifdef GUI_HTTP
#if defined GUI_HTTP || defined GUI_WEB

#include "gdiconst.h"
#include "web\web_info.h"
#include "web\web_const.h"

/*	Page0: the login page
	Page1: the save successfully page
	Page2: the password error page
	Page3: the upgrade file page
	Page4a, 5b, 6c: the address book page

	Settings: the main settings page with or without super-password
*/
#define HTTP_TASK_NONE					0
#define HTTP_TASK_GET_PAGE0				1
#define	HTTP_TASK_GET_PAGE1				2
#define	HTTP_TASK_GET_PAGE2				3
#define	HTTP_TASK_GET_PAGE3				4
#define	HTTP_TASK_GET_PAGE4				5
#define	HTTP_TASK_GET_SETTINGS			6
#define	HTTP_TASK_GET_IMAGE				7
#define HTTP_TASK_POST_PAGE0			8
#define HTTP_TASK_POST_SETTINGS			9
#define HTTP_TASK_POST_ADDRESSBOOK		10
#define HTTP_TASK_POST_FIRMWARE			11
#define HTTP_TASK_POST_DIGITMAP			12
#define HTTP_TASK_POST_RING				13
#define HTTP_TASK_UNKNOWN				14

// for page5 speed dial, which is manually generated
#define SPEEDIAL_ENTRY_PER_LOOP			4
#define	SPEEDDIAL_LOOP_NUM				(SPEED_DIAL_NUM/SPEEDIAL_ENTRY_PER_LOOP)

#if defined OEM_VIRTTEL || defined OEM_HUAWEI3COM || defined RES_CZ
CCHAR _cSpeedDialPos[4][5] = {	{17, 35, 11, 71, 11},
								{66, 35, 11, 71, 11},
								{66, 35, 11, 71, 11},
								{66, 35, 11, 71, 11}
};
#elif defined OEM_NGTEL
#ifdef RES_DE
CCHAR _cSpeedDialPos[4][5] = {	{17, 35, 11, 71, 11},
								{66, 35, 11, 71, 11},
								{66, 35, 11, 71, 11},
								{66, 35, 11, 71, 11}
};
#elif defined RES_US
CCHAR _cSpeedDialPos[4][5] = {	{81, 35, 11, 71, 11},
								{57, 35, 11, 71, 11},
								{66, 35, 11, 71, 11},
								{57, 35, 11, 71, 11}
};
#endif
#else
CCHAR _cSpeedDialPos[4][5] = {	{81, 35, 11, 71, 11},
								{57, 35, 11, 71, 11},
								{66, 35, 11, 71, 11},
								{57, 35, 11, 71, 11}
};
#endif

CCHAR _cHttpLoopSdramLo[3] = {HTTP_PAGE4_SDRAM_LO, HTTP_PAGE5_SDRAM_LO, HTTP_PAGE6_SDRAM_LO};
CSHORT _cHttpLoopMsgLen[3] = {HTTP_PAGE4_MSG_LEN, HTTP_PAGE5_MSG_LEN, HTTP_PAGE6_MSG_LEN};

#define AUTH_LABEL_LENGTH	5
static CCHAR _cAuthLabel[] = "auth ";
#define UPDATE_LABEL_LEN	7	
static CCHAR _cUpdateLabel[] = "update ";
#define BACK_LABEL_LEN		5
static CCHAR _cBackLabel[] = "back ";
#define UPGRADE_LABEL_LEN	8
static CCHAR _cUpgradeLabel[] = "upgrade ";
#define ADDRESSBOOK_LABEL_LEN	12
static CCHAR _cAddressbookLabel[] = "addressbook ";

#define HTTP_UPDATE_NONE		0
#define HTTP_UPDATE_SETTINGS	1
#define HTTP_UPDATE_FIRMWARE	2
#define HTTP_UPDATE_DIGITMAP	3
#define HTTP_UPDATE_RING		4

#define HTTP_UPLOAD_STATE_INIT		0
#define HTTP_UPLOAD_STATE_BEGIN		1
#define HTTP_UPLOAD_STATE_HEAD_END	2
#define HTTP_UPLOAD_STATE_END		3

#define HTTP_TCP_NUM	2
static CCHAR _cHttpSdramLo[HTTP_TCP_NUM] = {HTTP_SERVER_SDRAM_LO, HTTP_SERVER2_SDRAM_LO};

#define HTTP_INFO_CONTENT_LEN	0
#define HTTP_INFO_STATE			4
#define HTTP_INFO_BROKEN_LINE	5
#define HTTP_INFO_EXTRA_DATA_TASK	6
#define HTTP_INFO_TOTAL_SEND_LEN	7
#define HTTP_INFO_EXTRA_DATA_FLAG	9
#define HTTP_INFO_TCP_OPEN			10
#define HTTP_INFO_LEN	10

// Tcp connection data
XCHAR Http_pRecvPacket[HTTP_MAX_RECV_LEN+1];

XCHAR Http_iRecvLen;
XCHAR Http_iState;
XSHORT Http_iCurMsgLen;
XLONG Http_lContentLen;
BOOLEAN Http_bBrokenLine;

static XCHAR _pConvertBuf[49];
static XCHAR _iConvertMaxLen;

static BOOLEAN _bPostComplete, _bLogin;
static XCHAR _iUpdateType, _iUploadState;
static XCHAR _iCurLoopNum;
static XSHORT _iIdleTimer; 
static XCHAR _iExtraDataFlag;
static XSHORT _iTotalSendLen;
static XCHAR _iCurHttpIndex;
static XCHAR _bTcpOpen;
static XCHAR _iExtraDataTask;

void _HttpSaveInfo(UCHAR iIndex)
{
	ULONG2PUCHAR(Http_lContentLen, (PUCHAR)(PXCHAR)(Sdram_pDataCache + HTTP_INFO_CONTENT_LEN)); 
	X_VAL(Sdram_pDataCache, HTTP_INFO_STATE) = Http_iState;
	X_VAL(Sdram_pDataCache, HTTP_INFO_BROKEN_LINE) = Http_bBrokenLine? 1:0;
	X_VAL(Sdram_pDataCache, HTTP_INFO_EXTRA_DATA_TASK) = _iExtraDataTask;
	USHORT2PXCHAR(_iTotalSendLen, (PXCHAR)(Sdram_pDataCache + HTTP_INFO_TOTAL_SEND_LEN));
	X_VAL(Sdram_pDataCache, HTTP_INFO_EXTRA_DATA_FLAG) = _iExtraDataFlag;
	X_VAL(Sdram_pDataCache, HTTP_INFO_TCP_OPEN) = _bTcpOpen;
	SdramWriteData((USHORT)(OPTIONS_SDRAM_POS+HTTP_INFO_SDRAM_LO + iIndex), HTTP_INFO_LEN);
}

void _HttpLoadInfo(UCHAR iIndex)
{
	SdramReadData((USHORT)(OPTIONS_SDRAM_POS+HTTP_INFO_SDRAM_LO + iIndex));
	Http_lContentLen = PXCHAR2ULONG((PXCHAR)(Sdram_pDataCache + HTTP_INFO_CONTENT_LEN)); 
	Http_iState = X_VAL(Sdram_pDataCache, HTTP_INFO_STATE);
	Http_bBrokenLine = X_VAL(Sdram_pDataCache, HTTP_INFO_BROKEN_LINE);
	_iExtraDataTask = X_VAL(Sdram_pDataCache, HTTP_INFO_EXTRA_DATA_TASK);
	_iTotalSendLen = PXCHAR2USHORT((PXCHAR)(Sdram_pDataCache + HTTP_INFO_TOTAL_SEND_LEN));
	_iExtraDataFlag = X_VAL(Sdram_pDataCache, HTTP_INFO_EXTRA_DATA_FLAG);
	 _bTcpOpen = X_VAL(Sdram_pDataCache, HTTP_INFO_TCP_OPEN);
}

void _HttpConvertPostStr()
{
	DCHAR i, iChar, iLen;
	XCHAR pTemp[3];

	iLen = 0;
	for (i = 0; i < Http_iRecvLen; i ++)
	{
		iChar = Http_pRecvPacket[i];
		if (iChar == '=' || iChar == '+')
		{
			iChar = ' ';
		}
		else if (iChar == '%')
		{
			p_memcpy_x2x_0(pTemp, (PXCHAR)(Http_pRecvPacket+i+1), 2);
			iChar = (UCHAR)p_atoi(pTemp, 16);
			i += 2;
		}
		Http_pRecvPacket[iLen] = iChar;
		iLen ++;
	}
	Http_pRecvPacket[iLen] = 0;
	Http_iRecvLen = iLen;
}

void _Http_itoa10_n(USHORT iData, PXCHAR pDst, UCHAR iWidth)
{
	DCHAR iLen;
	XCHAR pBuf[6];

	p_itoa(iData, pBuf, 10);
	iLen = p_strlen_x(pBuf);
	if (iWidth)
	{
		p_memset_x(pDst, '0', iWidth);
	}
	p_memcpy_x2x((PXCHAR)(pDst + iWidth - iLen), pBuf, iLen);
}

void _HttpCopyData(UCHAR iSdramLo, USHORT iLen)
{
	SdramRead(HTTP_SDRAM_HI, iSdramLo, SRAM_DMA_DWORD);
	p_wmemcpy_x2x((PXCHAR)Adapter_pSendTcpData, (PXCHAR)Sdram_pDataCache, 512);
	if (iLen > 512)
	{
		SdramRead(HTTP_SDRAM_HI, (UCHAR)(iSdramLo+2), SRAM_DMA_DWORD);
		p_wmemcpy_x2x((PXCHAR)(Adapter_pSendTcpData+512), (PXCHAR)Sdram_pDataCache, 512);
		if (iLen > 1024)
		{
			SdramRead(HTTP_SDRAM_HI, (UCHAR)(iSdramLo+4), SRAM_DMA_HALF_DWORD);
			p_memcpy_x2x((PXCHAR)(Adapter_pSendTcpData+1024), (PXCHAR)Sdram_pDataCache, (UCHAR)(iLen - 1024));
		}
	}
}

void _HttpSendData()
{
	TcpSend(Http_iCurMsgLen);
	Http_iCurMsgLen = 0;
}

///////////////////////////////////////////////////////////////////////////////
///  Update options in web page before sending it out
///////////////////////////////////////////////////////////////////////////////
void _HttpPadSpace()
{
	DCHAR iLen;
	iLen = p_strlen_x(_pConvertBuf);
	if (iLen < _iConvertMaxLen)
	{
		p_memset_x((PXCHAR)(_pConvertBuf + iLen), ' ', (UCHAR)(_iConvertMaxLen - iLen));
	}
}

void _HttpUpdateText(PXCHAR pDst, PXCHAR pSrc, UCHAR iMaxLen, BOOLEAN bQuoted)
{
	DCHAR iLen;

	if (iMaxLen)
	{
		p_memset_x(pDst, ' ', iMaxLen);
	}
	iLen = p_strlen_x(pSrc);
	if (iLen)
	{
		p_memcpy_x2x(pDst, pSrc, iLen);
	}
	if (bQuoted)
	{
		pDst[iLen] = '"';
	}
}

void _UpdateConfigQuotedText(PXCHAR pStr)
{
	_HttpUpdateText(_pConvertBuf, pStr, _iConvertMaxLen, TRUE);
}

void _UpdateConfigText(PXCHAR pStr)
{
	_HttpUpdateText(_pConvertBuf, pStr, _iConvertMaxLen, FALSE);
}

void _UpdateConfigIP(PXCHAR pIP)
{
	p_IP2String(pIP, _pConvertBuf);
	_HttpPadSpace();
}

void _UpdateConfigCheck(BOOLEAN bCheck)
{
	p_strcpy_c2x(_pConvertBuf, (bCheck ? (PCCHAR)"CHECKED" : (PCCHAR)"       "));
}

void _UpdateConfigNumber(USHORT iNumber)
{
	p_itoa(iNumber, _pConvertBuf, 10);
	_HttpPadSpace();
}

// if not select box, return 0xff; otherwise, return the variable
UCHAR _GetReplaceBuf(UCHAR iType)
{
	switch (iType)
	{
	case HTTP_RING_TYPE:
		return Task_iRingType;
	case HTTP_LOCAL_ALIAS:
		return Sys_iLocalType;
	case HTTP_CODEC_TYPE1:
		return Sys_pCodecType[0];
	case HTTP_CODEC_TYPE2:
		return Sys_pCodecType[1];
	case HTTP_CODEC_TYPE3:
		return Sys_pCodecType[2];
	case HTTP_CODEC_TYPE4:
		return Sys_pCodecType[3];
	case HTTP_CODEC_TYPE5:
		return Sys_pCodecType[4];
	case HTTP_CODEC_TYPE6:
		return Sys_pCodecType[5];
	case HTTP_NAT_TRAVERSAL:
		return Sys_iNatTraversal;
	case HTTP_DTMF_TYPE:
		return Sys_iDtmfType;
	case HTTP_SERVICE_TYPE:
		return Sys_iServiceType;
	case HTTP_OUTPUT_DEBUG:
		return Udp_iOutputDebug;
	case HTTP_IP_TYPE:
		return Sys_iIPType;
	case HTTP_INNER_LINE:
		return Sys_iInnerLine;
	case HTTP_DUAL_MODE:
		return Sys_iDualMode;
	case HTTP_TIME_ZONE:
		return (Sys_iTimeZone & TIMEZONE_DAYLIGHT_AND);
	case HTTP_UPGRADE_TYPE:
		return Sys_iUpgradeType;
	case HTTP_NTS_ADDR:
		_UpdateConfigIP(Sys_pNtsIP);
		break;
	case HTTP_JITTER_SIZE:
		_UpdateConfigNumber(Sys_iJitterSize);
		break;
	case HTTP_REGISTER_TTL:
		_UpdateConfigNumber(Sys_iRegisterTTL);
		break;
	case HTTP_NAT_TTL:
		_UpdateConfigNumber(Sys_iNatTTL);
		break;
	case HTTP_DAYLIGHT:
		_UpdateConfigCheck((BOOLEAN)((Sys_iTimeZone & TIMEZONE_DAYLIGHT_OR) ? TRUE : FALSE));
		break;
	case HTTP_VLAN_ENABLE:
		_UpdateConfigCheck(VLAN_bEnable);
		break;
	case HTTP_VLAN_ID:
		_UpdateConfigNumber(VLAN_iID);
		break;
#ifdef CALL_SIP
	case HTTP_FAST_START:
		_UpdateConfigCheck((BOOLEAN)((Sys_iCallType & FAST_START_OR) ? TRUE : FALSE));
		break;
	case HTTP_SIP_PRACK:
		_UpdateConfigCheck((BOOLEAN)((Sys_iCallType & SIP_PRACK_OR) ? TRUE : FALSE));
		break;
#endif
#ifdef CALL_IAX2
	case HTTP_REMOTE_DIALPLAN:
		_UpdateConfigCheck((BOOLEAN)((Sys_iCallType & REMOTE_DIALPLAN_OR) ? TRUE : FALSE));
		break;
#endif
	case HTTP_CALL_WAITING:
		_UpdateConfigCheck((BOOLEAN)((Sys_iForwardType & CALL_WAITING_OR) ? TRUE : FALSE));
		break;
	case HTTP_FWD_ALWAYS:
		_UpdateConfigCheck((BOOLEAN)((Sys_iForwardType & FORWARD_ALWAYS_OR) ? TRUE : FALSE));
		break;
	case HTTP_FWD_BUSY:
		_UpdateConfigCheck((BOOLEAN)((Sys_iForwardType & FORWARD_BUSY_OR) ? TRUE : FALSE));
		break;
	case HTTP_FWD_NOANSWER:
		_UpdateConfigCheck((BOOLEAN)((Sys_iForwardType & FORWARD_NOANSWER_OR) ? TRUE : FALSE));
		break;
	case HTTP_FWD_POWEROFF:
		_UpdateConfigCheck((BOOLEAN)((Sys_iForwardType & FORWARD_POWEROFF_OR) ? TRUE : FALSE));
		break;
	case HTTP_FORWARD_NUMBER:
		_UpdateConfigQuotedText(Sys_pForwardNumber);
		break;
	case HTTP_RING_NUMBER:
		_UpdateConfigNumber(Task_iRingNumber);
		break;
	case HTTP_USE_HIGH_RATE:
		_UpdateConfigCheck((BOOLEAN)((Dsp_iOptions & USE_HIGH_RATE_OR) ? TRUE : FALSE));
		break;
	case HTTP_USE_VAD:
		_UpdateConfigCheck((BOOLEAN)((Dsp_iOptions & USE_VAD_OR) ? TRUE : FALSE));
		break;
	case HTTP_USE_AGC:
		_UpdateConfigCheck((BOOLEAN)((Dsp_iOptions & USE_AGC_OR) ? TRUE : FALSE));
		break;
	case HTTP_USE_AEC:
		_UpdateConfigCheck((BOOLEAN)((Dsp_iOptions & USE_AEC_OR) ? TRUE : FALSE));
		break;
	case HTTP_IP_ADDR:
		_UpdateConfigIP(Local_pIPAddress);
		break;
	case HTTP_NAT_DNS:
		_UpdateConfigQuotedText(Sys_pNatAddr);
		break;
	case HTTP_USE_GK:
		_UpdateConfigCheck(Sys_bUseService);
		break;
	case HTTP_PHONE_NUMBER:
		_UpdateConfigQuotedText(Sys_pLocalNumber);
		break;
	case HTTP_SUBNET_MASK:
		_UpdateConfigIP(Local_pSubnetMask);
		break;
	case HTTP_ROUTER_ADDR:
		_UpdateConfigIP(Local_pRouteIP);
		break;
	case HTTP_HANDSET_INPUT:
		_UpdateConfigNumber(Ac97_iHandsetInputVol);
		break;
	case HTTP_HANDFREE_INPUT:
		_UpdateConfigNumber(Ac97_iHandfreeInputVol);
		break;
	case HTTP_HANDSET_OUTPUT:
		_UpdateConfigNumber(Ac97_iHandsetOutputVol);
		break;
	case HTTP_DNS_ADDR:
		_UpdateConfigIP(Dns_pServerIP);
		break;
	case HTTP_DNS_ADDR2:
		_UpdateConfigIP(Dns_pServerIP2);
		break;
	case HTTP_HANDFREE_OUTPUT:
		_UpdateConfigNumber(Ac97_iHandfreeOutputVol);
		break;
	case HTTP_AUDIO_FRAMES:
		_UpdateConfigNumber(Sys_iAudioFrames);
		break;
	case HTTP_Q931_PORT:
		_UpdateConfigNumber(Sys_iSignalPort);
		break;
	case HTTP_PASSWORD:
		_UpdateConfigQuotedText(Sys_pPassword);
		break;
	case HTTP_COUNTRY_CODE:
		_UpdateConfigQuotedText(Sys_pCountryCode);
		break;
	case HTTP_INTL_PREFIX:
		_UpdateConfigQuotedText(Sys_pIntlPrefix);
		break;
	case HTTP_USE_DIALPLAN:
		return Sys_iUseDialPlan;
	case HTTP_AREA_CODE:
		_UpdateConfigQuotedText(Sys_pAreaCode);
		break;
	case HTTP_LONG_PREFIX:
		_UpdateConfigQuotedText(Sys_pLongPrefix);
		break;
	case HTTP_DUALMODE_PREFIX:
		_UpdateConfigQuotedText(Sys_pDualModePrefix);
		break;
	case HTTP_INNERLINE_PREFIX:
		_UpdateConfigQuotedText(Sys_pInnerLinePrefix);
		break;
	case HTTP_ACCOUNT:
		_UpdateConfigQuotedText(Sys_pAccount);
		break;
	case HTTP_PIN:
		_UpdateConfigQuotedText(Sys_pPin);
		break;
	case HTTP_PPP_ID:
		_UpdateConfigQuotedText(PPP_pID);
		break;
	case HTTP_PPP_PASSWORD:
		_UpdateConfigQuotedText(PPP_pPassword);
		break;
	case HTTP_GKID:
		_UpdateConfigQuotedText(Sys_pServiceID);
		break;
	case HTTP_RAS_PORT:
		_UpdateConfigNumber(Sys_iRegisterPort);
		break;
	case HTTP_H245_PORT:
		_UpdateConfigNumber(Sys_iControlPort);
		break;
	case HTTP_RTP_PORT:
		_UpdateConfigNumber(Sys_iRtpPort);
		break;
	case HTTP_RTP_TOS:
		_UpdateConfigNumber(Rtp_iTos);
		break;
	case HTTP_DTMF_PTYPE:
		_UpdateConfigNumber(Sys_iDtmfPayloadType);
		break;
	case HTTP_ILBC_PTYPE:
		_UpdateConfigNumber(Sys_iIlbcPType);
		break;
	case HTTP_USE_DIGITMAP:
		_UpdateConfigCheck(Sys_bUseDigitMap);
		break;
	case HTTP_SUPER_PASSWORD:
		_UpdateConfigQuotedText(Sys_pSuperPassword);
		break;
	case HTTP_DIAL_NUMBER:
		_UpdateConfigQuotedText(Sys_pDialNumber);
		break;
	case HTTP_SERVICE_DNS:
		_UpdateConfigQuotedText(Sys_pServiceAddr);
		break;
	case HTTP_UPGRADE_ADDR:
		_UpdateConfigQuotedText(Sys_pUpgradeUrl);
		break;
	case HTTP_TITLE:
		_UpdateConfigText(GetVersionText());
		break;
	case HTTP_MAC_ADDR:
		p_Mac2String(Local_pMacAddress, _pConvertBuf);
		_HttpPadSpace();
		break;
	}
	return 0xff;
}

void _HttpUpdateSdram(UCHAR iSdramLo, UCHAR iPos, UCHAR iLen)
{
	SdramRead(HTTP_SDRAM_HI, iSdramLo, SRAM_DMA_HALF_DWORD);
	p_memcpy_x2x((PXCHAR)(Sdram_pDataCache + iPos), _pConvertBuf, iLen);
	SdramWrite(HTTP_SDRAM_HI, iSdramLo, SRAM_DMA_HALF_DWORD);
}

void _UpdatePageSdram(PCCHAR cInfo, UCHAR iSdramLo)
{
	DCHAR iLen;

	if (cInfo[HTTP_INFO_LEFTLEN])
	{
		iLen = cInfo[HTTP_INFO_MAXLEN] - cInfo[HTTP_INFO_LEFTLEN];
		_HttpUpdateSdram(iSdramLo, cInfo[HTTP_INFO_BEGINPOS], iLen);
		p_memcpy_x2x((PXCHAR)_pConvertBuf, (PXCHAR)(_pConvertBuf + iLen), cInfo[HTTP_INFO_LEFTLEN]);
		_HttpUpdateSdram((UCHAR)(iSdramLo+1), 0, cInfo[HTTP_INFO_LEFTLEN]);

	}
	else
	{
		_HttpUpdateSdram(iSdramLo, cInfo[HTTP_INFO_BEGINPOS], cInfo[HTTP_INFO_MAXLEN]);
	}
}

void _HttpReloadPage(PCCHAR cInfo, UCHAR iInfoNum, UCHAR iSdramLo)
{
	DCHAR i, j, iSelect, iType;
	PCCHAR_D pCur;

	for (i = 0; i < iInfoNum;)
	{
		pCur = (PCCHAR)(cInfo + i * HTTP_INFO_NUM);
		iType = pCur[HTTP_INFO_TYPE];
		_iConvertMaxLen = pCur[HTTP_INFO_MAXLEN];
		iSelect = _GetReplaceBuf(iType);
		if (iSelect == 0xff)
		{
			_UpdatePageSdram(pCur, (UCHAR)(iSdramLo + pCur[HTTP_INFO_BLOCK]));
			i ++;
		}
		else
		{
			for (j = i; j < iInfoNum; j ++)
			{
				pCur = (PCCHAR)(cInfo + j * HTTP_INFO_NUM);
				if (pCur[HTTP_INFO_TYPE] != iType)
				{
					break;
				}
				else
				{
					if (iSelect == (UCHAR)(j-i))
					{
						p_strcpy_c2x(_pConvertBuf, (PCCHAR)"SELECTED");
					}
					else
					{
						p_strcpy_c2x(_pConvertBuf, (PCCHAR)"        ");
					}
					_UpdatePageSdram(pCur, (UCHAR)(iSdramLo + pCur[HTTP_INFO_BLOCK]));
				}
			}
			i = j;
		}
	}
}


PXCHAR _SpeedDialUpdateEntry(PXCHAR pSendBuf, UCHAR iSpeedDialIndex, PCCHAR pPos)
{
	PXCHAR_D pCur; 
	DCHAR iIndex;
	XCHAR pTemp[3];

	iIndex = iSpeedDialIndex;

	_Http_itoa10_n((USHORT)(iIndex+1), pTemp, 3);
	iIndex <<= 1;

	pCur = (PXCHAR)(pSendBuf + pPos[0]);
	p_memcpy_x2x(pCur, pTemp, 3);
	pCur += pPos[1];
	p_memcpy_x2x(pCur, pTemp, 3);
	pCur += pPos[2];
	_HttpUpdateText(pCur, ReadSpeedDial((UCHAR)(iIndex+1)), (UCHAR)(PHONE_NUMBER_LEN + 1), TRUE);
	pCur += pPos[3];
	p_memcpy_x2x(pCur, pTemp, 3);
	pCur += pPos[4];
	_HttpUpdateText(pCur, ReadSpeedDial(iIndex), (UCHAR)(PHONE_NUMBER_LEN + 1), TRUE);
	return pCur;
}

// This function is specially written to reload speeddial loop
// if the loop content change, this function need to be modified
void _HttpReloadLoopPage(UCHAR iSdramLo)
{
	DCHAR iIndex;
	PXCHAR_D pCur;

	SdramRead(HTTP_SDRAM_HI, iSdramLo, SRAM_DMA_DWORD);
	p_wmemcpy_x2x((PXCHAR)Adapter_pSendTcpData, (PXCHAR)Sdram_pDataCache, 512);
	if (Http_iCurMsgLen > 512)
	{
		SdramRead(HTTP_SDRAM_HI, (UCHAR)(iSdramLo + 2), SRAM_DMA_DWORD);
		p_wmemcpy_x2x((PXCHAR)(Adapter_pSendTcpData + 512), (PXCHAR)Sdram_pDataCache, (USHORT)(Http_iCurMsgLen - 512));
	}

	pCur = (PXCHAR)Adapter_pSendTcpData;
	for (iIndex = 0; iIndex < 4; iIndex ++)
	{
		pCur = _SpeedDialUpdateEntry(pCur, (UCHAR)(iIndex+_iCurLoopNum * SPEEDIAL_ENTRY_PER_LOOP), _cSpeedDialPos[iIndex]);
	}
}

////////////////////////////////////////////////////////////////////////////
//  funtion to send out web page, 
//  may add more function to send more page
////////////////////////////////////////////////////////////////////////////

void _HttpPrepareSending()
{
	switch (_iExtraDataTask)
	{
#ifndef GUI_WEB
	case HTTP_TASK_GET_PAGE0:
		_HttpReloadPage((PCCHAR)_chttp_page0_info[0], HTTP_PAGE0_OPTION_NUM, HTTP_PAGE0_SDRAM_LO);
		break;

	case HTTP_TASK_GET_PAGE1:
		_HttpReloadPage((PCCHAR)_chttp_page1_info[0], HTTP_PAGE1_OPTION_NUM, HTTP_PAGE1_SDRAM_LO);
		break;
	
	case HTTP_TASK_GET_PAGE2:
		_HttpReloadPage((PCCHAR)_chttp_page2_info[0], HTTP_PAGE2_OPTION_NUM, HTTP_PAGE2_SDRAM_LO);
		break;

	case HTTP_TASK_GET_PAGE3:
		_HttpReloadPage((PCCHAR)_chttp_page3_info[0], HTTP_PAGE3_OPTION_NUM, HTTP_PAGE3_SDRAM_LO);
		break;

	case HTTP_TASK_GET_PAGE4:
		_HttpReloadPage((PCCHAR)_chttp_page4_info[0], HTTP_PAGE4_OPTION_NUM, HTTP_PAGE4_SDRAM_LO);
		break;
#endif
	case HTTP_TASK_GET_SETTINGS:
		_HttpReloadPage((PCCHAR)_csettings_head_info[0], SETTINGS_HEAD_OPTION_NUM, SETTINGS_HEAD_SDRAM_LO);
		_HttpReloadPage((PCCHAR)_csettings_dialplan_info[0], SETTINGS_DIALPLAN_OPTION_NUM, SETTINGS_DIALPLAN_SDRAM_LO);
		_HttpReloadPage((PCCHAR)_csettings_protocol_info[0], SETTINGS_PROTOCOL_OPTION_NUM, SETTINGS_PROTOCOL_SDRAM_LO);
		_HttpReloadPage((PCCHAR)_csettings_pa168v_info[0], SETTINGS_PA168V_OPTION_NUM, SETTINGS_PA168V_SDRAM_LO);
		_HttpReloadPage((PCCHAR)_csettings_phoneonly_info[0], SETTINGS_PHONEONLY_OPTION_NUM, SETTINGS_PHONEONLY_SDRAM_LO);
		_HttpReloadPage((PCCHAR)_csettings_tail_info[0], SETTINGS_TAIL_OPTION_NUM, SETTINGS_TAIL_SDRAM_LO);
		break;

	case HTTP_TASK_POST_PAGE0:
	case HTTP_TASK_POST_SETTINGS:
	case HTTP_TASK_POST_ADDRESSBOOK:
	case HTTP_TASK_POST_FIRMWARE:
	case HTTP_TASK_POST_DIGITMAP:
	case HTTP_TASK_POST_RING:
		return;

	case HTTP_TASK_UNKNOWN:
		Http_iCurMsgLen = HttpSendError();
		TcpClose(_cHttpSdramLo[_iCurHttpIndex]);
		_iExtraDataFlag= 0;
		_iExtraDataTask = HTTP_TASK_NONE;
		Http_iState = HTTP_STATE_INIT;
		return;
	}
	_iExtraDataFlag= 1;
	Http_iCurMsgLen = 0;
	Http_iState = HTTP_STATE_SEND_BEGIN;
}


BOOLEAN _SendOnePart(UCHAR iSdramLo, USHORT iMsgLen)
{
	DSHORT iLeftLen;
	DCHAR iBlockNum;

	iLeftLen = iMsgLen - _iTotalSendLen;
	iBlockNum = (UCHAR)(_iTotalSendLen >> 8);
	if (iLeftLen > HTTP_WINDOW_SIZE)
	{
		_HttpCopyData((UCHAR)(iSdramLo + iBlockNum), HTTP_WINDOW_SIZE);
		_iTotalSendLen += HTTP_WINDOW_SIZE;
		Http_iCurMsgLen = HTTP_WINDOW_SIZE;
		return TRUE;
	}
	else
	{
		_HttpCopyData((UCHAR)(iSdramLo + iBlockNum), iLeftLen);
		Http_iCurMsgLen = iLeftLen;
		return FALSE;
	}
}

// Send web page that has no loop. The whole web page has already been stored in sdram
void _SendCommonPage(UCHAR iSdramLo, USHORT iMsgLen, UCHAR iType)
{
	switch(_iExtraDataFlag)
	{
	case 1:
		Http_iCurMsgLen = HttpSendOK(iMsgLen, iType);
		_iExtraDataFlag++;
		_iTotalSendLen = 0;
		break;
	case 2:
		if (!_SendOnePart(iSdramLo, iMsgLen))
		{
			// we must close the connection by ourself after all data has been sent since "Connection: Keep-Alive"
			TcpClose(_cHttpSdramLo[_iCurHttpIndex]);
			_iExtraDataFlag= 0;
			Http_iState = HTTP_STATE_INIT;
		}
		break;
	}
}

#define STEP_SEND_OK	1
#define STEP_SEND_HEAD	2
#define STEP_SEND_PHONEONLY	3
#define STEP_SEND_PA168V	4
#ifndef CALL_MGCP
#define STEP_SEND_DIALPLAN	5
#define STEP_SEND_PROTOCOL	6
#define STEP_SEND_TAIL		7
#else
#define STEP_SEND_PROTOCOL	5
#define STEP_SEND_TAIL		6
#endif

void _SetNextPage()
{
	if (Task_bSupervisor)
	{
		_iExtraDataFlag = STEP_SEND_PROTOCOL;
	}
	else
	{
		_iExtraDataFlag = STEP_SEND_TAIL;
	}
}

void _SendSettingsPage()
{
	DSHORT iMsgLen;

	iMsgLen = SETTINGS_HEAD_MSG_LEN + SETTINGS_TAIL_MSG_LEN;
	if (Task_bSupervisor)
	{
		iMsgLen += SETTINGS_PROTOCOL_MSG_LEN;
	}
#ifndef CALL_MGCP
	iMsgLen += SETTINGS_DIALPLAN_MSG_LEN;
#endif
#ifdef _USE_FXS
#ifdef VER_PA168V
	iMsgLen += SETTINGS_PA168V_MSG_LEN;
#endif
#else
	iMsgLen += SETTINGS_PHONEONLY_MSG_LEN;
#endif

	switch(_iExtraDataFlag)
	{
	case STEP_SEND_OK:
		Http_iCurMsgLen = HttpSendOK(iMsgLen, HTTP_CT_TEXT_HTML);
		_iExtraDataFlag = STEP_SEND_HEAD;
		_iTotalSendLen = 0;
		break;
	case STEP_SEND_HEAD:
		if (!_SendOnePart(SETTINGS_HEAD_SDRAM_LO, SETTINGS_HEAD_MSG_LEN))
		{
#ifdef _USE_FXS
#ifdef _USE_FAKE_FXO
			_iExtraDataFlag = STEP_SEND_PA168V;
#else
#ifndef CALL_MGCP
			_iExtraDataFlag = STEP_SEND_DIALPLAN;
#else
			_SetNextPage();
#endif
#endif
#else
			_iExtraDataFlag = STEP_SEND_PHONEONLY;
#endif
			_iTotalSendLen = 0;
		}
		break;
	case STEP_SEND_PA168V:
		if (!_SendOnePart(SETTINGS_PA168V_SDRAM_LO, SETTINGS_PA168V_MSG_LEN))
		{
#ifndef CALL_MGCP
			_iExtraDataFlag = STEP_SEND_DIALPLAN;
#else
			_SetNextPage();
#endif
			_iTotalSendLen = 0;
		}
		break;
	case STEP_SEND_PHONEONLY:
		if (!_SendOnePart(SETTINGS_PHONEONLY_SDRAM_LO, SETTINGS_PHONEONLY_MSG_LEN))
		{
#ifndef CALL_MGCP
			_iExtraDataFlag = STEP_SEND_DIALPLAN;
#else
			_SetNextPage();
#endif
			_iTotalSendLen = 0;
		}
		break;
#ifndef CALL_MGCP
	case STEP_SEND_DIALPLAN:
		if (!_SendOnePart(SETTINGS_DIALPLAN_SDRAM_LO, SETTINGS_DIALPLAN_MSG_LEN))
		{
			_SetNextPage();
			_iTotalSendLen = 0;
		}
		break;
#endif
	case STEP_SEND_PROTOCOL:
		if (!_SendOnePart(SETTINGS_PROTOCOL_SDRAM_LO, SETTINGS_PROTOCOL_MSG_LEN))
		{
			_iExtraDataFlag = STEP_SEND_TAIL;
			_iTotalSendLen = 0;
		}
		break;
	case STEP_SEND_TAIL:
		if (!_SendOnePart(SETTINGS_TAIL_SDRAM_LO, SETTINGS_TAIL_MSG_LEN))
		{
			// we must close the connection by ourself after all data has been sent since "Connection: Keep-Alive"
			TcpClose(_cHttpSdramLo[_iCurHttpIndex]);
			_iExtraDataFlag= 0;
			Http_iState = HTTP_STATE_INIT;
		}
		break;
	}
}

// Send web page with loop; this need special treatment
void _SendLoopPage(UCHAR iLoopNum)
{
	DSHORT iLeftLen;

	switch (_iExtraDataFlag)
	{
	case 1:
		iLeftLen = (USHORT)_cHttpLoopMsgLen[1];
		iLeftLen *= iLoopNum;
		iLeftLen += _cHttpLoopMsgLen[0];
		iLeftLen += _cHttpLoopMsgLen[2]; 
		Http_iCurMsgLen = HttpSendOK(iLeftLen, HTTP_CT_TEXT_HTML);
		_iExtraDataFlag++;
		_iTotalSendLen = 0;
		break;
	case 2:
		if (!_SendOnePart(_cHttpLoopSdramLo[0], _cHttpLoopMsgLen[0]))
		{
			_iTotalSendLen = 0;
			_iCurLoopNum = 0;
			_iExtraDataFlag++;
		}
		break;
	case 3:
		if (_iCurLoopNum == (UCHAR)(iLoopNum - 1))
		{
			_iTotalSendLen = 0;
			_iExtraDataFlag++;
		}
		Http_iCurMsgLen = _cHttpLoopMsgLen[1];
		_HttpReloadLoopPage(_cHttpLoopSdramLo[1]);
		_iCurLoopNum ++;
		break;
	case 4:
		if (!_SendOnePart(_cHttpLoopSdramLo[2], _cHttpLoopMsgLen[2]))
		{
			TcpClose(_cHttpSdramLo[_iCurHttpIndex]);
			_iExtraDataFlag= 0;
			Http_iState = HTTP_STATE_INIT;
		}
		break;
	}
}

void _SendWebPage()
{
	switch (_iExtraDataTask)
	{
	case HTTP_TASK_GET_PAGE0:
		_SendCommonPage(HTTP_PAGE0_SDRAM_LO, HTTP_PAGE0_MSG_LEN, HTTP_CT_TEXT_HTML);
		break;

	case HTTP_TASK_GET_PAGE1:
		_SendCommonPage(HTTP_PAGE1_SDRAM_LO, HTTP_PAGE1_MSG_LEN, HTTP_CT_TEXT_HTML);
		break;

	case HTTP_TASK_GET_PAGE2:
		_SendCommonPage(HTTP_PAGE2_SDRAM_LO, HTTP_PAGE2_MSG_LEN, HTTP_CT_TEXT_HTML);
		break;

	case HTTP_TASK_GET_PAGE3:
		_SendCommonPage(HTTP_PAGE3_SDRAM_LO, HTTP_PAGE3_MSG_LEN, HTTP_CT_TEXT_HTML);
		break;

	case HTTP_TASK_GET_PAGE4:
		_SendLoopPage(SPEEDDIAL_LOOP_NUM);
		break;

	case HTTP_TASK_GET_SETTINGS:
		_SendSettingsPage();
		break;

	case HTTP_TASK_GET_IMAGE:
		_SendCommonPage(WEB_IMAGE_SDRAM_LO, WEB_IMAGE_MSG_LEN, HTTP_CT_IMAGE_GIF);
		break;
	}
}

////////////////////////////////////////////////////////////////////////////
//  funtion to handle incoming data, 
//  may add more function to handle more page
////////////////////////////////////////////////////////////////////////////
BOOLEAN _IsUploading()
{
	if (_iExtraDataTask == HTTP_TASK_POST_FIRMWARE || _iExtraDataTask == HTTP_TASK_POST_DIGITMAP || _iExtraDataTask == HTTP_TASK_POST_RING)
		return TRUE;
	else
		return FALSE;
}

void _CloseUpgrade()
{
	if (_IsUploading())
	{
		if (_iUpdateType && !_bPostComplete)
		{
			if (SoloFileClose() > FILE_ONE_PAGE_SIZE)
			{
				OnReboot();
			}
		}
	}
}

// Write Speeddial to temporary buffer
void _WriteTempSpeedDial(PXCHAR pBuf, UCHAR iIndex)
{
	DSHORT iPos;
	DCHAR iSdramLo, iOffset;

	iPos = iIndex;
	iPos <<= 4;		// iPos *= PHONE_NUMBER_LEN;
	iPos += (USHORT)(HTTP_SERVERBUF_SDRAM_LO << 8);
	iSdramLo = P_HIBYTE(iPos);
	iOffset = (UCHAR)iPos;
	SdramRead(HTTP_SDRAM_HI, iSdramLo, SRAM_DMA_HALF_DWORD);
	p_memcpy_x2x((PXCHAR)(Sdram_pDataCache+iOffset), pBuf, PHONE_NUMBER_LEN);
	SdramWrite(HTTP_SDRAM_HI, iSdramLo, SRAM_DMA_HALF_DWORD);
}


void _SaveSpeedDial(PXCHAR pSrc)
{
	DCHAR iIndex;
	PXCHAR_D pInput;

	pInput = pSrc;

	if (pInput[4] != ' ')	return;
	iIndex = (UCHAR)p_atoi((PXCHAR)(pInput+1), 10) - 1;
	if (iIndex >= SPEED_DIAL_NUM)	return;

	iIndex <<= 1;

	if (pInput[0] == 'p')
	{
		_WriteTempSpeedDial((PXCHAR)(pInput + 5), iIndex);
	}
	else if (pInput[0] == 'n')
	{
		_WriteTempSpeedDial((PXCHAR)(pInput + 5), (UCHAR)(iIndex+1));
	}
}

// in Http, when a checkbox is not checked, it will not be included in the post message
// eg. if use gk, "gk=on" is sent; if not use gk, then it is omitted
void _ResetSettingsBoolean()
{
#if defined OEM_VIRTTEL || defined OEM_HUAWEI3COM
	Sys_bUseService = FALSE; 
#else
	if (Task_bSupervisor)
	{
		Sys_bUseService = FALSE; 
	}
#endif
	Sys_bUseDigitMap = FALSE; 
	Dsp_iOptions = 0;
	Sys_iForwardType = 0;
	Sys_iTimeZone = 0;
	Sys_iCallType = 0;
	VLAN_bEnable = FALSE;
}

// Page0, currently use to do authentication
void _ProcessPage0Data()
{
	PXCHAR_D pCur;

	pCur = Http_pRecvPacket;
	if (!p_memcmp_c2x(pCur, _cAuthLabel, AUTH_LABEL_LENGTH))
	{
		pCur += AUTH_LABEL_LENGTH;
		_bLogin = IsPassword(pCur);
//		OutputString(IDS_HTTP_PASSWORD_ERROR);
		if (_bLogin)
		{
#if defined OEM_VIRTTEL || defined OEM_HUAWEI3COM
			Task_bSupervisor = TRUE;
#endif
			_iExtraDataTask = HTTP_TASK_GET_SETTINGS;
			_iIdleTimer = 0;
		}
		else
		{
			_iExtraDataTask = HTTP_TASK_GET_PAGE2;
		}
	}
}

// Settings, currently use to display and modify settings
void _ProcessSettingsData()
{
	PXCHAR_D pCur;

	pCur = Http_pRecvPacket;
	if (!SetHttpOptions(pCur) && !SetOptions(pCur))
	{
		if (!p_memcmp_c2x(pCur, _cUpdateLabel, UPDATE_LABEL_LEN))
		{
			_bPostComplete = TRUE;
			_iExtraDataTask = HTTP_TASK_GET_PAGE1;
		}
		else if (!p_memcmp_c2x(pCur, _cAddressbookLabel, ADDRESSBOOK_LABEL_LEN))
		{
			_iExtraDataTask = HTTP_TASK_GET_PAGE4;
			_iIdleTimer = 0;
		}
		else if (!p_memcmp_c2x(pCur, _cUpgradeLabel, UPGRADE_LABEL_LEN))
		{
			_iExtraDataTask = HTTP_TASK_GET_PAGE3;
			_iIdleTimer = 0;
		}
	}
}

void _ProcessPage4Data()
{
	PXCHAR_D pCur;
	DCHAR i, iSrcIndex, iDstIndex;

//	DebugCString((PCCHAR)"process speeddial data");
	pCur = Http_pRecvPacket;
	if (!p_memcmp_c2x(pCur, _cWriteLabel, p_strlen_c(_cWriteLabel)))
	{
//		DebugCString((PCCHAR)"jump back to page1");
		for (i = 0; i < (SPEED_DIAL_TOTAL_LEN >> 8); i ++)
		{
			iSrcIndex = HTTP_SERVERBUF_SDRAM_LO + i;
			iDstIndex = (SPEED_DIAL_BEGIN >> 8) + i;
			SdramRead(HTTP_SDRAM_HI, iSrcIndex, SRAM_DMA_HALF_DWORD);
			SdramWrite(OPTIONS_SDRAM_HI, iDstIndex, SRAM_DMA_HALF_DWORD);
		}
		_iExtraDataTask = HTTP_TASK_GET_SETTINGS;
		_iIdleTimer = 0;
	}
	else if (!p_memcmp_c2x(pCur, _cBackLabel, BACK_LABEL_LEN))
	{
		_iExtraDataTask = HTTP_TASK_GET_SETTINGS;
		_iIdleTimer = 0;
	}
	else
	{
		_SaveSpeedDial(pCur);
	}
}

void _ProcessHttpData()
{
	if (Http_iRecvLen)
	{
		Http_pRecvPacket[Http_iRecvLen] = 0;
		_HttpConvertPostStr();
//		DebugString(Http_pRecvPacket);
		switch (_iExtraDataTask)
		{
		case HTTP_TASK_POST_PAGE0:
			_ProcessPage0Data();
			break;

		case HTTP_TASK_POST_SETTINGS:
			if (_bLogin)
			{
				_ProcessSettingsData();
			}
			break;

		case HTTP_TASK_POST_ADDRESSBOOK:
			if (_bLogin)
			{
				_ProcessPage4Data();
			}
			break;
		}
		Http_iRecvLen = 0;
	}
}

UCHAR _MatchBoundary(PXCHAR pData, UCHAR iDataLen)
{
	DCHAR iLen;

	iLen = SdramReadData(OPTIONS_SDRAM_POS+HTTP_TEMP_SDRAM_LO);
	if (iDataLen < iLen)
	{
		if (!p_memcmp_x2x(pData, (PXCHAR)Sdram_pDataCache, iDataLen))
		{
			// Partially mactch
			return 1;
		}
		else
		{
			// Not match
			return 0;
		}
	}
	else if (iDataLen == iLen)
	{
		if (!p_memcmp_x2x(pData, (PXCHAR)Sdram_pDataCache, iDataLen))
		{
			// Exact mactch
			return 2;
		}
		else
		{
			// Not match
			return 0;
		}
	}
	else
	{
		if (!p_memcmp_x2x(pData, (PXCHAR)Sdram_pDataCache, iLen))
		{
			// Exact mactch
			return 2;
		}
		else
		{
			// Not match
			return 0;
		}
	}
}

void _ProcessUploadData(PXCHAR pData, USHORT iDataLen)
{
	DCHAR iMatch;
	DSHORT iIndex, iLength;

	iIndex = 0;
	if (Http_lContentLen >= iDataLen)
	{
		iLength = iDataLen;
		Http_lContentLen -= iLength;
	}
	else
	{
		iLength = (USHORT)Http_lContentLen;
		Http_lContentLen = 0;
	}

	if (_iUploadState == HTTP_UPLOAD_STATE_HEAD_END)
	{
		while (iIndex < iLength)
		{
			Http_pRecvPacket[Http_iRecvLen] = pData[iIndex];
			Http_iRecvLen ++;
			iMatch = _MatchBoundary(Http_pRecvPacket, Http_iRecvLen);
			if (iMatch == 0)
			{
				if (Http_iRecvLen > 1)
				{
					Http_iRecvLen --;
					SoloFileWrite(Http_pRecvPacket, Http_iRecvLen);
					Http_iRecvLen = 0;
					continue;
				}
				else
				{
					SoloFileWrite(Http_pRecvPacket, Http_iRecvLen);
					Http_iRecvLen = 0;
				}
			}
			else if (iMatch == 2)
			{
				SoloFileClose();
				_iUploadState = HTTP_UPLOAD_STATE_END;
				break;
			}
			iIndex ++;
		}
		DisplayFileStatus();
	}
	if (!Http_lContentLen)
	{
		Http_iState = HTTP_STATE_REQUEST_END;
		_bPostComplete = TRUE;
		_iExtraDataTask = HTTP_TASK_GET_PAGE1;
	}
}

void _SaveData(UCHAR iVal)
{
	if (Http_iRecvLen < HTTP_MAX_RECV_LEN)
	{
		Http_pRecvPacket[Http_iRecvLen] = iVal;
		Http_iRecvLen ++;
	}
}

void _HttpHandleContent(PXCHAR pData, USHORT iLength)
{
	PXCHAR_D pCur;
	DSHORT iLen;
	DCHAR iNewLine;

	if (_IsUploading())
	{
		iLen = 0;
		pCur = pData;
		while (iLen < iLength && Http_lContentLen)
		{
			if (_iUploadState < HTTP_UPLOAD_STATE_HEAD_END)
			{
				iNewLine = p_IsNewLine((PXCHAR)(pCur+iLen));
				if (iNewLine)
				{
					Http_pRecvPacket[Http_iRecvLen] = 0;
					iLen += iNewLine;
					Http_lContentLen -= iNewLine;

					if (_iUploadState == HTTP_UPLOAD_STATE_INIT)
					{
						p_memcpy_c2x((PXCHAR)Sdram_pDataCache, (PCCHAR)"\r\n", 2);
						p_memcpy_x2x((PXCHAR)(Sdram_pDataCache + 2), Http_pRecvPacket, Http_iRecvLen);
						SdramWriteData(OPTIONS_SDRAM_POS+HTTP_TEMP_SDRAM_LO, (UCHAR)(Http_iRecvLen+2));
						_iUploadState = HTTP_UPLOAD_STATE_BEGIN;
					}
					else if (_iUploadState == HTTP_UPLOAD_STATE_BEGIN)
					{
						if (!Http_iRecvLen)
						{
							_iUploadState = HTTP_UPLOAD_STATE_HEAD_END;
							//OutputString(IDS_CHECK_POINT_3);
						}
					}
					Http_iRecvLen = 0;
				}
				else
				{
					_SaveData(pCur[iLen]);
					// buffer not big enough, or corrupted data ? CAN'T add _HttpHandleException() here
					iLen ++;
					Http_lContentLen --;
				}
			}
			else
			{
				_ProcessUploadData((PXCHAR)(pCur+iLen), (USHORT)(iLength - iLen));
				break;
			}
		}
	}
	else
	{
		iLen = iLength;
		pCur = pData;
		while (Http_lContentLen && iLen && Http_iRecvLen < HTTP_MAX_RECV_LEN)
		{
			if (*pCur == '&')
			{
				_ProcessHttpData();
			}
			else
			{
				_SaveData(*pCur);
			}
			Http_lContentLen --;
			iLen --;
			pCur ++;		
		}

		if (!Http_lContentLen && Http_iRecvLen)
		{
			_ProcessHttpData();
			Http_iState = HTTP_STATE_REQUEST_END;
		}
	}
}


void _HttpHandleFirstLine(PXCHAR pBuf)
{
	PXCHAR_D pCur;
	PXCHAR_D pTemp;

	pCur = pBuf;
	Http_iState = HTTP_STATE_REQUEST_BEGIN;
	Http_lContentLen = 0;

	// Format of this message is "Method SP URL SP HTTP/version CRLF"
	if (!p_memcmp_c2x(pCur, Http_cMethodGet, HTTP_METHOD_GET_LEN))
	{
		pCur += HTTP_METHOD_GET_LEN;
		pTemp = p_strchr_x(pCur, ' ');
		if (pTemp)	pTemp[0] = 0;
		if (!p_strcmp_c2x(pCur, (PCCHAR)"/"))
		{
			_iExtraDataTask = HTTP_TASK_GET_PAGE0;
		}
		else if (!p_strcmp_c2x(pCur, (PCCHAR)"/image.gif"))
		{
			_iExtraDataTask = HTTP_TASK_GET_IMAGE;
		}
#if defined OEM_VIRTTEL || defined OEM_HUAWEI3COM
		else if (!p_strcmp_c2x(pCur, (PCCHAR)"/page3.htm"))
		{
			_iExtraDataTask = HTTP_TASK_GET_PAGE3;
		}
		else if (!p_strcmp_c2x(pCur, (PCCHAR)"/speeddial.htm"))
		{
			_iExtraDataTask = (_bLogin) ? HTTP_TASK_GET_PAGE4 : HTTP_TASK_GET_PAGE0;
		}
#endif
		else
		{
			_iExtraDataTask = HTTP_TASK_UNKNOWN;
		}
	}
	else if (!p_memcmp_c2x(pCur, Http_cMethodPost, HTTP_METHOD_POST_LEN))
	{
		pCur += HTTP_METHOD_POST_LEN;
		pTemp = p_strchr_x(pCur, ' ');
		if (pTemp)	pTemp[0] = 0;		
		if (!p_strcmp_c2x(pCur, (PCCHAR)"/a"))
		{
			// retrieve login password
			_iExtraDataTask = HTTP_TASK_POST_PAGE0;
		}
		else if (!p_strcmp_c2x(pCur, (PCCHAR)"/b"))
		{
			// retrieve settings
			if (_bLogin)
			{
				_iExtraDataTask = HTTP_TASK_POST_SETTINGS;
				_iUpdateType = HTTP_UPDATE_SETTINGS;
				_ResetSettingsBoolean();
			}
			else
			{
				_iExtraDataTask = HTTP_TASK_GET_PAGE0;
			}
			_iIdleTimer = 0;
		}
		else if (!p_strcmp_c2x(pCur, (PCCHAR)"/g"))
		{
			// retrieve speeddial
			_iExtraDataTask = (_bLogin) ? HTTP_TASK_POST_ADDRESSBOOK : HTTP_TASK_GET_PAGE0;
			_iIdleTimer = 0;
		}
		else if (!p_strcmp_c2x(pCur, (PCCHAR)"/d"))
		{
			// upload firmware
			if (_bLogin)
			{
				_iExtraDataTask = HTTP_TASK_POST_FIRMWARE;
				_iUpdateType = HTTP_UPDATE_FIRMWARE;
				_iUploadState = HTTP_UPLOAD_STATE_INIT;
				CreateUpgradeFile();
			}
			else
			{
				_iExtraDataTask = HTTP_TASK_GET_PAGE0;
			}
			_iIdleTimer = 0;
		}
		else if (!p_strcmp_c2x(pCur, (PCCHAR)"/e"))
		{
			// upload digitmap
			if (_bLogin)
			{
				_iExtraDataTask = HTTP_TASK_POST_DIGITMAP;
				_iUpdateType = HTTP_UPDATE_DIGITMAP;
				_iUploadState = HTTP_UPLOAD_STATE_INIT;
				CreateUpgradeFile();
			}
			else
			{
				_iExtraDataTask = HTTP_TASK_GET_PAGE0;
			}
			_iIdleTimer = 0;
		}
		else if (!p_strcmp_c2x(pCur, (PCCHAR)"/f"))
		{
			// upload music ring tone
			if (_bLogin)
			{
				_iExtraDataTask = HTTP_TASK_POST_RING;
				_iUpdateType = HTTP_UPDATE_RING;
				_iUploadState = HTTP_UPLOAD_STATE_INIT;
				CreateUpgradeFile();
			}
			else
			{
				_iExtraDataTask = HTTP_TASK_GET_PAGE0;
			}
			_iIdleTimer = 0;
		}
		else
		{
			_iExtraDataTask = HTTP_TASK_UNKNOWN;
		}
	}
	else
	{
		//something wrong, need to do something
		_iExtraDataTask = HTTP_TASK_UNKNOWN;
		Http_iState = HTTP_STATE_INIT;
	}
}

void _HttpHandleHeader(PXCHAR pBuf)
{
	DCHAR iLen;
	PXCHAR_D pHeader;

	pHeader = pBuf;

	iLen = p_strlen_x(pHeader);
	if (iLen <= CONTENT_LENGTH_LABEL_LEN)	return;

	if (p_memcmp_nocase_c2x(pHeader, Http_cContentLength, CONTENT_LENGTH_LABEL_LEN))
	{
		Http_lContentLen = p_atol((PXCHAR)(pHeader + CONTENT_LENGTH_LABEL_LEN), 10);
		OutputVal((USHORT)Http_lContentLen, IDS_CHECK_POINT_0);
		if (_IsUploading())
		{
			if (!Http_lContentLen)
			{
				Http_iState = HTTP_STATE_REQUEST_END;
				_iExtraDataTask = HTTP_TASK_NONE;
			}
		}
	}
}

void _ParseLine()
{
	Http_pRecvPacket[Http_iRecvLen] = 0;
	if (Http_iState == HTTP_STATE_INIT)
	{
		_HttpHandleFirstLine(Http_pRecvPacket);
	}
	else if (Http_iState == HTTP_STATE_REQUEST_BEGIN)
	{
		if (Http_iRecvLen)
		{
			_HttpHandleHeader(Http_pRecvPacket);
		}
		else 
		{
			if (Http_lContentLen)
			{
				Http_iState = HTTP_STATE_REQUEST_HEAD_END;
				//OutputString(IDS_CHECK_POINT_3);
			}
			else
			{
				Http_iState = HTTP_STATE_REQUEST_END;
			}
		}
	}
	Http_iRecvLen = 0;
}

void _RunHttpServer()
{
	DCHAR iVal, iNextVal;
	DSHORT iIndex;

	iIndex = 0;
	while (iIndex < Adapter_iReceiveLen)
	{
		if (Http_iState < HTTP_STATE_REQUEST_HEAD_END)
		{
			iVal = X_VAL(Adapter_pReceiveTcpData, iIndex);
			iIndex ++;
			if (iVal == 0x0d)
			{
				if (iIndex < Adapter_iReceiveLen)
				{
					iNextVal = X_VAL(Adapter_pReceiveTcpData, iIndex);
					iIndex ++;
					if (iNextVal == 0x0a)
					{
						_ParseLine();
					}
					else
					{
						_SaveData(iVal);
						_SaveData(iNextVal);
					}
				}
				else
				{
					Http_bBrokenLine = TRUE;
				}
			}
			else if (iVal == 0x0a)
			{
				if (Http_bBrokenLine)
				{
					_ParseLine();
					Http_bBrokenLine = FALSE;
				}
				else
				{
					_SaveData(iVal);
				}
			}
			else
			{
				_SaveData(iVal);
			}
		}
		else 
		{
			if (Http_iState == HTTP_STATE_REQUEST_HEAD_END && Http_lContentLen)
			{
				_HttpHandleContent((PXCHAR)(Adapter_pReceiveTcpData+iIndex), (USHORT)(Adapter_iReceiveLen - iIndex));
			}
			break;
		}
	}

	if (Http_iState == HTTP_STATE_REQUEST_END && _iExtraDataTask >= HTTP_TASK_GET_PAGE0)
	{
		_HttpPrepareSending();
	}
}

/////////////////////////////////////////////////////////////////////////////////////
//     Global Http function
////////////////////////////////////////////////////////////////////////////////////

void _Http_Initialize(UCHAR iIndex)
{
	// Tcp init
	TcbInit(HTTP_SERVER_PORT, HTTP_TIME_OUT, _cHttpSdramLo[iIndex]);
	_iExtraDataFlag = 0;
	_iTotalSendLen=0;
	_bTcpOpen = FALSE;
	_iExtraDataTask = HTTP_TASK_NONE;
	Http_bBrokenLine = FALSE;
	Http_iState = HTTP_STATE_INIT;
	Http_iRecvLen = 0;
	Http_iCurMsgLen = 0;
	Http_lContentLen = 0;

	_HttpSaveInfo(iIndex);
}

void _HttpInitOther()
{
	_iCurHttpIndex = 0;
	_iUpdateType = HTTP_UPDATE_NONE;
	_bPostComplete = FALSE;
	_bLogin = FALSE;
	Task_bSupervisor = FALSE;
}

void _HandleException(UCHAR iIndex)
{
//	DCHAR iAltIndex;

	_CloseUpgrade();
	_Http_Initialize(iIndex);

/*	iAltIndex = 1 - iIndex;
	SdramReadData((USHORT)(OPTIONS_SDRAM_POS+HTTP_INFO_SDRAM_LO + iAltIndex));
	 if (!X_VAL(Sdram_pDataCache, HTTP_INFO_TCP_OPEN))
	 {
		_HttpInitOther();
	 }
*/
}

void _HttpCheckSdramLimit(ULONG lLen)
{
	if (lLen > FILE_ONE_PAGE_SIZE)
	{
		OnReboot();
	}
}

void HttpInitialize()
{
	_HttpInitOther();
	_Http_Initialize(0);
	_Http_Initialize(1);
}

BOOLEAN HttpRun()
{
	DLONG lLen;

	if (TcbRun(HTTP_SERVER_SDRAM_LO))
	{
		_iCurHttpIndex = 0;
	}
	else if (TcbRun(HTTP_SERVER2_SDRAM_LO))
	{
		_iCurHttpIndex = 1;
	}
	else
	{
		return FALSE;
	}
	
	_HttpLoadInfo(_iCurHttpIndex);

	if (Tcp_bAcceptEvent)
	{
//		OutputString(IDS_HTTP_ACCEPT);
		Tcp_bAcceptEvent = FALSE;
		_bTcpOpen = TRUE;
	}
	if (Tcp_bConnectEvent)
	{
//		OutputString(IDS_HTTP_CONNECT);
		Tcp_bConnectEvent = FALSE;
	}

    if (Tcp_bDataEvent)
    {
//		DebugCString((PCCHAR)"http rcv data");
		_RunHttpServer();
		Tcp_bDataEvent = FALSE;
    }
	_HttpSendData();

	if (TcbAcked() && Http_iState == HTTP_STATE_SEND_BEGIN)
	{
//		DebugCString((PCCHAR)"http send page");
		_SendWebPage();
		_HttpSendData();
	}

	if (_bPostComplete && !_iExtraDataFlag)
	{
		lLen = SoloFileGetSize();
		switch(_iUpdateType)
		{
		case HTTP_UPDATE_SETTINGS:
			SysWriteOptions();
			OnUpdateOptions();
			break;
		case HTTP_UPDATE_FIRMWARE:
			if (IsFirmwareLenOK(lLen))
			{
				OnSwitchUpgrade(PROGRAM_UPGRADE_PAGE);
			}
			break;
		case HTTP_UPDATE_DIGITMAP:
			CopyFileToOption(8, DIAL_MAP_LO);
			OnUpdateOptions();
			break;
		case HTTP_UPDATE_RING:
#ifdef GUI_UPGRADE_RING
			OnUpdateRingFile(lLen);
#endif
			break;
		}
		_bPostComplete = FALSE;
		_HttpCheckSdramLimit(lLen);
	}

    if (Tcp_bCloseEvent || Tcp_bResetEvent)
    {
//		DebugCString((PCCHAR)"http close");
		Tcp_bCloseEvent = FALSE;
		Tcp_bResetEvent = FALSE;
		_CloseUpgrade();
		_HandleException(_iCurHttpIndex);
	}
	else
	{
		_HttpSaveInfo(_iCurHttpIndex);
	}
	return TRUE;
}

void HttpHandleTimer()
{
	if (_bLogin)
	{
		_iIdleTimer ++;
		if (_iIdleTimer > HTTP_IDLE_TTL)
		{
			_bLogin = FALSE;
			_iIdleTimer = 0;
		}
	}

	if (!TcbHandleTimer(HTTP_SERVER_SDRAM_LO))
	{
		OutputString(IDS_HTTP_TIMER_FAIL);
		TcpSendClose(_cHttpSdramLo[0]);
		_HandleException(0);
	}
	
	if (!TcbHandleTimer(HTTP_SERVER2_SDRAM_LO))
	{
		OutputString(IDS_HTTP_TIMER_FAIL);
		TcpSendClose(_cHttpSdramLo[1]);
		_HandleException(1);
	}
}

#endif // GUI_HTTP