www.pudn.com > NETINFO.rar > http.cpp


#include "http.h" 
 
//some tool function 
BOOL SplitHttpHeader(const char line[], char name[MAX_HTTP_HEADER_LINE], char value[MAX_HTTP_HEADER_LINE]) 
{ 
	const char *pColon = strchr(line, ':'); 
	if( !pColon ) //because I have found some cases that is using '=' as seperator 
		pColon = strchr(line, '='); 
	if( !pColon ) return FALSE; 
	const char *pStart, *pEnd; 
 
	//extract name 
	for(pStart = line; pStart=pStart && isspace(*pEnd); pEnd--)NULL; //skip end space 
	if(pEnd>=pStart && pEnd - pStart + 2 < MAX_HTTP_HEADER_LINE ) 
	{ 
		memcpy(name, pStart, pEnd-pStart+1); 
		name[pEnd-pStart+1] = 0; 
	} 
	else 
		strcpy(name, ""); 
 
	//extract value 
	const char* pZero = pColon + strlen(pColon); 
	for(pStart = pColon+1; pStart=pStart && isspace(*pEnd); pEnd--)NULL; //skip end space 
	if(pEnd>=pStart && pEnd - pStart + 2 < MAX_HTTP_HEADER_LINE ) 
	{ 
		memcpy(value, pStart, pEnd-pStart+1); 
		value[pEnd-pStart+1] = 0; 
	} 
	else 
		strcpy(value, ""); 
	return TRUE; 
} 
 
//if successfully analyse a header field, return TRUE, else return FALSE 
BOOL HttpAnalyseHeader(const char*fullLine, HTTP_HEADER_INFO* pHeader, enum HTTP_ANALYSE_HEADER_TYPE type) 
{ 
	if( strcmp(fullLine, "") == 0 ) 
		return FALSE; 
	if( type == HEADER_TYPE_REQUEST_LINE ) 
	{ 
		sscanf(fullLine, "%s %s %s", pHeader->method, pHeader->url, pHeader->http_Version); 
 
		//check validation 
		strlwr(pHeader->http_Version); 
		if( memicmp(pHeader->http_Version, "http/1.", 7) ) 
		{ 
			printf("invalidate http_version: %s\n", pHeader->http_Version); 
			return FALSE; 
		} 
	} 
	else if( type == HEADER_TYPE_STATUS_LINE ) 
	{		 
		sscanf(fullLine, "%s %s", pHeader->http_Version, pHeader->status_Code); 
		//check validation 
		if( memicmp(pHeader->http_Version, "http/1.", 7) ) 
		{ 
			printf("invalidate http_version: %s\n", pHeader->http_Version); 
			return FALSE; 
		} 
	} 
	else if( type == HEADER_TYPE_NORMAL_HEADER ) 
	{ 
		char name[MAX_HTTP_HEADER_LINE], value[MAX_HTTP_HEADER_LINE]; 
		if( !SplitHttpHeader(fullLine, name, value) )  
			return FALSE; 
		if( stricmp(name, "Content-Location") == 0 ) 
		{ 
			if( strlen(value)content_Location) ) 
				strcpy(pHeader->content_Location, value); 
		} 
		else if( stricmp(name, "Location") == 0 ) 
		{ 
			if( strlen(value)location) ) 
				strcpy(pHeader->location, value); 
		} 
		else if( stricmp(name, "Host") == 0 ) 
		{ 
			if( strlen(value)host) ) 
				strcpy(pHeader->host, value); 
		} 
		else if( stricmp(name, "Connection") == 0 ) 
		{ 
			if( strlen(value)connection) ) 
				strcpy(pHeader->connection, value); 
		} 
		else if( stricmp(name, "Content-Encoding") == 0 ) 
		{ 
			if( strlen(value)content_Encoding) ) 
				strcpy(pHeader->content_Encoding, value); 
		} 
		else if( stricmp(name, "Content-Length") == 0 ) 
		{ 
			if( strlen(value)content_Length) ) 
				strcpy(pHeader->content_Length, value); 
		} 
		else if( stricmp(name, "Content-Type") == 0 ) 
		{ 
			char *pSlash = strchr(value, '/'); 
			if( pSlash ) 
			{ 
				memcpy(pHeader->content_MainType, value, pSlash - value); 
				pHeader->content_MainType[pSlash-value] = 0; 
				char *pEnd; 
				if( (pEnd = strchr(pSlash, ';'))==NULL ) 
					pEnd = pSlash+strlen(pSlash); 
				memcpy(pHeader->content_SubType, pSlash+1, pEnd - pSlash - 1); 
				pHeader->content_SubType[pEnd-pSlash-1] = 0; 
			} 
		} 
		else if( stricmp(name, "Content-Range") == 0 ) 
		{ 
			if( strlen(value)content_Range) ) 
				strcpy(pHeader->content_Range, value); 
		} 
		else if( stricmp(name, "Referer") == 0 ) 
		{ 
			if( strlen(value)referer) ) 
				strcpy(pHeader->referer, value); 
		} 
		else if( stricmp(name, "Transfer-Encoding") == 0 ) 
		{ 
			if( strlen(value)transfer_Encoding) ) 
				strcpy(pHeader->transfer_Encoding, value); 
		}		 
	} 
	return TRUE; 
} 
 
BOOL GetHostFromUrl(const char url[], char host[MAX_HOST_LENGTH]) 
{ 
	BOOL retVal = FALSE; 
	const char *p1, *p2; 
	p1 = strstr(url, "://"); 
	p2 = strstr(url, "/"); 
	if( p1!=NULL && p1 < p2 ) 
	{ 
		const char *pStart, *pEnd, *pChar; 
		pStart = p1 + 3; 
		pEnd = strchr(pStart, '/'); 
		if( pEnd ) 
		{ 
			//look for '@' to check if it's a url such as 
			// http://123:123@www.test.com:88/index.htm 
			for(pChar = pStart; pCharOnHttpClientBegin ) 
		m_pFuncs->OnHttpClientBegin(m_pNi, this); 
} 
 
 
CHttpConnection::~CHttpConnection() 
{ 
	if( m_status == HTTP_REQUEST_BODY ) 
	{ 
		if( m_pFuncs && m_pFuncs->OnHttpClientEnd ) 
			m_pFuncs->OnHttpClientEnd(m_pNi, this); 
	} 
	else if( m_status == HTTP_RESPONSE_BODY ) 
	{ 
		if( m_pFuncs && m_pFuncs->OnHttpServerEnd ) 
			m_pFuncs->OnHttpServerEnd(m_pNi, this); 
	} 
} 
 
BOOL CHttpConnection::OnData(int sender, int receiver, const BYTE* pData, DWORD length) 
{ 
	if( m_status == HTTP_REQUEST_LINE || m_status == HTTP_REQUEST_HEADER  
		|| m_status == HTTP_STATUS_LINE || m_status == HTTP_RESPONSE_HEADER ) 
	{ 
		if( ( (m_status == HTTP_REQUEST_LINE || m_status == HTTP_REQUEST_HEADER) && sender==m_listener ) 
			|| ( (m_status == HTTP_STATUS_LINE || m_status == HTTP_RESPONSE_HEADER) && sender==m_connecter ) ) 
		{ 
			printf("invalid direction data when decoding headers\n"); 
			return FALSE; 
		} 
		if( !m_lineBuf.PutData((const char*)pData, length) ) return FALSE; 
 
		char line[MAX_HTTP_HEADER_LINE]; 
		int writeLen; 
		while( m_lineBuf.GetLine(line, sizeof(line), &writeLen, FALSE) ) 
		{ 
			//add this LWSP line to current line 
			if( line[0] == ' ' || line[0] == '\t' ) 
			{ 
				if( strlen(line) + strlen(m_szLastLine) + 1 > sizeof(m_szLastLine) ) 
				{ 
					printf("CHttpConnection::OnData(): m_szLastLine is too small\n"); 
					return FALSE; 
				} 
				strcat(m_szLastLine, line); 
			} 
			else 
			{ 
				//analyse m_szLastLine 
				if( strcmp(m_szLastLine,"")!=0 ) 
				{ 
					enum HTTP_ANALYSE_HEADER_TYPE headerType; 
					HTTP_HEADER_INFO *pHeader = (sender==m_connecter) ? &m_request : &m_response; 
					if( m_status == HTTP_REQUEST_LINE ) 
					{ 
						headerType = HEADER_TYPE_REQUEST_LINE; 
						m_status = HTTP_REQUEST_HEADER; 
					} 
					else if( m_status == HTTP_STATUS_LINE ) 
					{ 
						headerType = HEADER_TYPE_STATUS_LINE; 
						m_status = HTTP_RESPONSE_HEADER;  
					} 
					else 
						headerType = HEADER_TYPE_NORMAL_HEADER; 
					if( !HttpAnalyseHeader(m_szLastLine, pHeader, headerType) ) 
					{ 
						printf("CHttpConnection::OnData(): error occured when decoding header\n"); 
						return FALSE; 
					} 
				} 
 
				//store current line to m_szLastLine 
				strcpy(m_szLastLine, line); 
 
				//check whether encounter ending CRLF line of headers 
				if( strcmp(line, "") == 0 ) 
				{ 
					if( m_status == HTTP_REQUEST_HEADER ) 
					{ 
						if( m_pFuncs && m_pFuncs->OnHttpClientHeader ) 
							m_pFuncs->OnHttpClientHeader(m_pNi, this, &m_request); 
						m_status = HTTP_REQUEST_BODY; 
						if( m_lineBuf.GetCount() != 0 ) 
						{ 
							if( m_pFuncs && m_pFuncs->OnHttpClientBody ) 
								m_pFuncs->OnHttpClientBody(m_pNi, this, (const BYTE*)m_lineBuf.GetRemainStart(), m_lineBuf.GetCount() ); 
						}						 
					} 
					else if( m_status == HTTP_RESPONSE_HEADER ) 
					{ 
						if( m_pFuncs && m_pFuncs->OnHttpServerHeader ) 
							m_pFuncs->OnHttpServerHeader(m_pNi, this, &m_request, &m_response); 
						m_status = HTTP_RESPONSE_BODY; 
						if( m_lineBuf.GetCount() != 0 ) 
						{ 
							if( m_pFuncs && m_pFuncs->OnHttpServerBody ) 
								m_pFuncs->OnHttpServerBody(m_pNi, this, (const BYTE*)m_lineBuf.GetRemainStart(), m_lineBuf.GetCount() ); 
						}						 
					} 
					m_lineBuf.ResetContent(); 
					strcpy(m_szLastLine, ""); 
				} 
			} 
		} 
	} 
	else if( m_status == HTTP_REQUEST_BODY ) 
	{ 
		if( sender == m_connecter ) 
		{ 
			if( m_pFuncs && m_pFuncs->OnHttpClientBody ) 
				m_pFuncs->OnHttpClientBody(m_pNi, this, pData, length); 
		} 
		else 
		{ 
			if( m_pFuncs && m_pFuncs->OnHttpClientEnd ) 
				m_pFuncs->OnHttpClientEnd(m_pNi, this); 
			m_status = HTTP_STATUS_LINE; 
			if( m_pFuncs && m_pFuncs->OnHttpServerBegin ) 
				m_pFuncs->OnHttpServerBegin(m_pNi, this); 
			m_lineBuf.ResetContent(); 
			strcpy(m_szLastLine, ""); 
			return OnData(sender, receiver, pData, length); 
		} 
	} 
	else if( m_status == HTTP_RESPONSE_BODY ) 
	{ 
		if( sender == m_listener ) 
		{ 
			if( m_pFuncs && m_pFuncs->OnHttpServerBody ) 
				m_pFuncs->OnHttpServerBody(m_pNi, this, pData, length); 
		} 
		else 
		{ 
			if( m_pFuncs && m_pFuncs->OnHttpServerEnd ) 
				m_pFuncs->OnHttpServerEnd(m_pNi, this); 
			m_lineBuf.ResetContent(); 
			strcpy(m_szLastLine, ""); 
			memset(&m_request, 0, sizeof(m_request)); 
			memset(&m_response, 0, sizeof(m_response)); 
			m_status = HTTP_REQUEST_LINE; 
			if( m_pFuncs && m_pFuncs->OnHttpClientBegin ) 
				m_pFuncs->OnHttpClientBegin(m_pNi, this); 
			return OnData(sender, receiver, pData, length); 
		} 
	} 
	return TRUE; 
} 
 
void GetHttpHeader(HHTTPCONNECT hHttpConnect, const HTTP_HEADER_INFO **ppRequest, const HTTP_HEADER_INFO **ppResponse) 
{ 
	*ppRequest = &hHttpConnect->m_request; 
	*ppResponse = &hHttpConnect->m_response; 
}