⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 httpcore.cpp

📁 mini http server,可以集成嵌入到程序中,实现简单的web功能
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	--- */
	int i = 0;
	for( ; i<iLineLen && !(isspace(pLine[i])); i++);
	*ppProtocol = pLine;
	if ( i==iLineLen ) { return ST_BADREQUEST; };
	pLine[i]='\0'; i++;
	for(; i<iLineLen && (isspace(pLine[i])); i++);
	pLine = &( pLine[i] ); iLineLen -= i; i=0; 

	/* ---
	pLine now points at the statuscode following the protocol
	--- */

	/* --- Statuscode must exist --- */
	if ( i==iLineLen ) { return ST_BADREQUEST; };

	for(; i<iLineLen && !(isspace(pLine[i])); i++);
	const char *pStatusCode = pLine;
	pLine[i]='\0'; i++;

	*piStatusCode = atoi(pStatusCode);

	/* ---
	We ignore the status text and the whole rest
	--- */

	/* -- OK --- */
	return INT_CONTINUE;
}

/*____________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:
	Verify the HTTP request line and divide it into components. Returns
	INT_CONTINUE on success or an HTTP error status code on error.

	Assumes pLine is NULL terminated at pLine[iLineLen].

	On success instantiates all values to at least an empty string with the
	exception of the proxy values which will all be instantiated if
	ppProxyProtocol is instantiated.

\*____________________________________________________________________________*/
static int Internal_SplitRequestLine(
	char *pLine, 
	int iLineLen,
	const char **ppMethod,
	const char **ppProxyProtocol,
	const char **ppProxyHost,
	int *piProxyHostLen,
	const char **ppProxyPort,
	int *piProxyPortLen,
	const char **ppPath,
	const char **ppQueryString,
	const char **ppProtocol
	)
{
	assert( pLine );
	assert( iLineLen );
	assert( ppMethod );
	assert( ppProxyProtocol );
	assert( ppProxyHost );
	assert( piProxyHostLen );
	assert( ppProxyPort );
	assert( piProxyPortLen );
	assert( ppPath );
	assert( ppProtocol );

	*ppProtocol = "";	/* --- this is done because protcol is optional, i.e.
						HTTP/0.9 doesn't send one
						--- */
	/* 
	**  check URI for exluded characters acc. to RFC2396 2.4.3
	**  (silently checking the whole request line instead of URI only
	**  and intentional omitting \x00, \x20, '#' and '%' from this check)
	*/
#define deniedchars "\
\x7F\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\
\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\
<>\"{}|\\^[]`"
	if ( strcspn( pLine, deniedchars ) < strlen( pLine ))
		{ return ST_BADREQUEST; };

	/* ---
	method
	--- */
	int i = 0;
	for( ; i<iLineLen && !(isspace(pLine[i])); i++);
	*ppMethod = pLine;
	if ( i==iLineLen ) { return ST_BADREQUEST; };
	pLine[i]='\0'; i++;
	for(; i<iLineLen && (isspace(pLine[i])); i++);
	pLine = &( pLine[i] ); iLineLen -= i; i=0; 

	/* ---
	pLine now points at the component following the method
	--- */

	/* --- URL path must exist --- */
	if ( i==iLineLen )
		{ return ST_BADREQUEST; };

	/* ---
	proxy host and port
	--- */
	if ( (*pLine!='/') && (*pLine!='*'))
		{
		/* --- assume proxy host and port specification --- */
		for(;
			(i+2)<iLineLen &&
			strncmp(&(pLine[i]), "://", 3) && !(isspace(pLine[i])); i++)
			{ pLine[i] = tolower( pLine[i] ); };
		if ( !strncmp( &(pLine[i]), "://", 3 ) )
			{
			*ppProxyProtocol = pLine; pLine[i] = '\0';
			i += 3;
			pLine = &( pLine[i] ); iLineLen -= i; i=0;

			/* --- pLine now points at proxy host --- */
			*ppProxyHost = pLine;
			for(;	i<iLineLen &&
					pLine[i]!=':' &&
					pLine[i]!='/' &&
					!(isspace(pLine[i])); i++);
			*piProxyHostLen = i;
			if ( pLine[i]==':' ) 
				{
				i++;
				pLine = &( pLine[i] ); iLineLen -= i; i=0;

				/* --- pLine now points at proxy port --- */
				*ppProxyPort = pLine;
				for(; i<iLineLen && pLine[i]!='/' && !(isspace(pLine[i])); i++);
				*piProxyPortLen = i;
				}
			else
				{
				*ppProxyPort = "";
				*piProxyPortLen = 0;
				};
			pLine = &( pLine[i] ); iLineLen -= i; i=0;
			}
		else
			{
			/* ---
			The URL path didn't start with '/' but it wasn't a proxy request

			NOTE: Maybe this should raise a gateway error instead of the
			generic bad request error.

			--- */
			return ST_BADREQUEST;
			};
		};

	/* ---	
	pLine now points at first character of URL path
	--- */

	/* ---
	path and query string.
	--- */
	for(; i<iLineLen && pLine[i]!='?' && !(isspace(pLine[i])); i++);
	*ppPath = pLine;

	if ( pLine[i]=='?' )
		{ 
		pLine[i++] = '\0';
		*ppQueryString = &(pLine[i]);
		for(; i<iLineLen && !(isspace(pLine[i])); i++);
		}
	else
		{ *ppQueryString = ""; };

	// decode long file names with spaces
    char *pdest = strchr( *ppPath, '+' );
    while (pdest != NULL) {
		if (strlen(*ppQueryString) && (pdest > *ppQueryString)) break;
		pdest[0] = ' ';
		pdest = strchr( *ppPath, '+' );
	};

	if ( i==iLineLen ) { return INT_CONTINUE; };
	pLine[i++]='\0';
	for(; i<iLineLen && (isspace(pLine[i])); i++);
	pLine = &( pLine[i] ); iLineLen -= i; i=0; 

	/* ---
	pLine now points at the component following the URL path and
	query string.
	--- */

	/* ---
	protocol is last component on the line, skip components until the last
	--- */
	for(;;)
		{
		for(; i<iLineLen && !(isspace(pLine[i])); i++);
		*ppProtocol = pLine;
		for(; i<iLineLen && (isspace(pLine[i])); i++);
		if ( i==iLineLen ) { return INT_CONTINUE; }; /* this should be true */

		/* --- I guess not --- */
		pLine = &( pLine[i] ); iLineLen -= i; i=0;
		};

	/* -- OK --- */
	return INT_CONTINUE;
}

/*____________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:
	Returns INT_CONTINUE on success, otherwise HTTPCore_readHeaders() returns
	an HTTP error status code.
\*____________________________________________________________________________*/
int HTTPCore_readHeaders( 
	PIIOBuffer *pB,	/* Buffer */
	PIDB *pDB,		/* Request DB */
	int iFlags )
{
	assert( pB );
	PIIOBuffer &tB = *pB;

	char szLocalBuffer[ LOCAL_BUFFER_LEN+1 ];
	szLocalBuffer[ LOCAL_BUFFER_LEN ]='\0';

	int iLen = tB.GetLine( szLocalBuffer, LOCAL_BUFFER_LEN );
	if ( iLen<0 )
		{ return ST_INTERNALERROR; }
	else if ( iLen==0 )
		{ return ST_BADREQUEST; }
	if ( iLen==LOCAL_BUFFER_LEN )
		/* --- HTTP/1.1 status code --- */
		{ return ST_REQUESTURITOOLONG; }

	szLocalBuffer[iLen]='\0';

	/* ---
	Get status line
	--- */
	const char *pMethod = 0;
	const char *pProxyProtocol = 0;
	const char *pProxyHost = 0;
	int iProxyHostLen = 0;
	const char *pProxyPort = 0;
	int iProxyPortLen = 0;
	const char *pURI = 0;
	const char *pQueryString = 0;
	const char *pProtocol = 0;
		
	int iStatus;
	if ( iFlags==RH_CLIENTREQUEST )
		{
		/* ---
		Save the raw request line in the CLF header field
		--- */
		PIDB_add( pDB, PIDBTYPE_STRING, pFKCLF, szLocalBuffer,
			PIDBFLAG_FASTKEY );

		/* --- parse the line --- */
		iStatus = Internal_SplitRequestLine(
			szLocalBuffer,
			iLen,
			&pMethod,
			&pProxyProtocol,
			&pProxyHost,
			&iProxyHostLen,
			&pProxyPort,
			&iProxyPortLen,
			&pURI,
			&pQueryString,
			&pProtocol
			);
		
		if ( iStatus )
			{ return iStatus; };
		if ( !pMethod || !pURI || !pQueryString || !pProtocol )
			{ return ST_BADREQUEST; };

		/* --- store these headers --- */
		PIDB_add( pDB, PIDBTYPE_STRING, pFKMethod, (void *)pMethod,
			PIDBFLAG_FASTKEY );
		PIDB_add( pDB, PIDBTYPE_STRING, pFKURI, (void *)pURI, 
			PIDBFLAG_FASTKEY );
		PIDB_add( pDB, PIDBTYPE_STRING, pFKQueryString, (void *)pQueryString, 
			PIDBFLAG_FASTKEY );
		PIDB_add( pDB, PIDBTYPE_STRING, pFKProtocol, (void *)pProtocol,
			PIDBFLAG_FASTKEY );

		/* --- Is this a proxy request? --- */
		if ( pProxyProtocol )
			{
			PIDB_add( pDB, PIDBTYPE_STRING, pFKProxyProtocol,
				(void *)pProxyProtocol, PIDBFLAG_FASTKEY );
			PIString sProxyHost( pProxyHost, iProxyHostLen );
			PIDB_add( pDB, PIDBTYPE_STRING, pFKProxyHost,
				(void *)(const char *)sProxyHost, PIDBFLAG_FASTKEY );
			PIString sProxyPort( pProxyPort, iProxyPortLen );
			PIDB_add( pDB, PIDBTYPE_STRING, pFKProxyPort,
				(void *)(const char *)sProxyPort, PIDBFLAG_FASTKEY );
			};

		/* ---
		Convert method and protocol into internal numeric form	
		--- */
		int iMethod = MD_UNKNOWN;
		int iProtocol = PR_UNKNOWN;
		if ( !PIUtil_stricmp( pMethod, MD_NAME_GET ) )
			{ iMethod = MD_GET; }
		else if ( !PIUtil_stricmp( pMethod, MD_NAME_POST ) )
			{ iMethod = MD_POST; }
		else if ( !PIUtil_stricmp( pMethod, MD_NAME_HEAD ) )
			{ iMethod = MD_HEAD; }
		else if ( !PIUtil_stricmp( pMethod, MD_NAME_PUT ) )
			{ iMethod = MD_PUT; }
		else if ( !PIUtil_stricmp( pMethod, MD_NAME_DELETE ) )
			{ iMethod = MD_DELETE; }
		else if ( !PIUtil_stricmp( pMethod, MD_NAME_OPTIONS ) )
			{ iMethod = MD_OPTIONS; }
		else if ( !PIUtil_stricmp( pMethod, MD_NAME_TRACE ) )
			{ iMethod = MD_TRACE; };
		if ( *pProtocol )
			{
			/* --- any protocol is not HTTP/0.9 --- */
			if ( !PIUtil_stricmp( pProtocol, PR_NAME_HTTP10 ) )
				{ iProtocol = PR_HTTP10; }
			else if ( !PIUtil_stricmp( pProtocol, PR_NAME_HTTP11 ) )
				{ iProtocol = PR_HTTP11; };
			}
		else
			{ iProtocol = PR_HTTP09; };

		/* --- Do we support this method and protocol ? --- */
		if ( iMethod == MD_UNKNOWN )
			{ return ST_NOTIMPLEMENTED; };
		if ( iProtocol == PR_UNKNOWN )
			{ iProtocol = PR_HTTP10; };

		/* --- Do we support the method for version < HTTP/1.1 ? --- */
		// Removed because to strict, e.g. for uploads with Netscape
#if 0
		if ((iProtocol != PR_HTTP11) && (iMethod > MD_HEAD))
			{ return ST_BADREQUEST; }; // maybe better ST_NOTIMPLEMENTED?
#endif
		/* --- set the numeric method and protocol --- */
		PIDB_replace( pDB, PIDBTYPE_OPAQUE, pFKMethodNumber, (void *)iMethod,
				PIDBFLAG_FASTKEY );
		PIDB_replace( pDB, PIDBTYPE_OPAQUE, pFKProtocolNumber,
			(void *)iProtocol, PIDBFLAG_FASTKEY );
		/* --- 
		Don't get the rest of the RFC822 headers if the protocol
		is HTTP/0.9
		--- */
		if ( iProtocol==PR_HTTP09 )
			{ return INT_CONTINUE; };

		iLen = tB.GetLine( szLocalBuffer, LOCAL_BUFFER_LEN );	
		}
	else if ( iFlags==RH_RESPONSE )
		{
		/* ---
		determine if this is a full response:
			This is considered true if both the following are true	
			- The line starts with 'HTTP/' or 'http/'
			- The line does not contain the ':' character
		--- */
		if ( !PIUtil_strncmpi( szLocalBuffer, "HTTP/", 5 ) )
			{
			int i=0;
			for(; i<iLen && szLocalBuffer[i]!=':'; i++);
			if ( i==iLen )
				{
				/* ---
				this is a full response, add this line to the DB as CLF
				and get the next line
				--- */
				PIDB_add( pDB, PIDBTYPE_STRING, pFKCLF, szLocalBuffer,
					PIDBFLAG_FASTKEY );

				int iStatusCode = 0;
				
				iStatus = Internal_SplitResponseLine(
					szLocalBuffer,
					iLen,
					&pProtocol,
					&iStatusCode
				);

				if ( iStatus )
					{ return iStatus; };
				if ( !pProtocol || iStatusCode < 100 || iStatusCode > 599 )
					{ return ST_BADREQUEST; };

				/* ---
				Convert protocol into internal numeric form	
				--- */
				int iProtocol = PR_UNKNOWN;
				if ( *pProtocol )
					{
					/* --- any protocol is not HTTP/0.9 --- */
					if ( !PIUtil_stricmp( pProtocol, PR_NAME_HTTP10 ) )
						{ iProtocol = PR_HTTP10; }
					else if ( !PIUtil_stricmp( pProtocol, PR_NAME_HTTP11 ) )
						{ iProtocol = PR_HTTP11; };
					}
				else
					{ iProtocol = PR_HTTP09; };

				if ( iProtocol == PR_UNKNOWN )
					{ iProtocol = PR_HTTP10; };

				/* --- store the protocol name --- */
				PIDB_add( pDB, PIDBTYPE_STRING, pFKProtocol, (void *)pProtocol,
					PIDBFLAG_FASTKEY );

				/* --- set the numeric protocol and statuscode --- */
				PIDB_add( pDB, PIDBTYPE_OPAQUE, pFKProtocolNumber,
					(void *)iProtocol, PIDBFLAG_FASTKEY );

				PIDB_add( pDB, PIDBTYPE_OPAQUE, pFKStatusCode,
					(void *)iStatusCode, PIDBFLAG_FASTKEY );

				iLen = tB.GetLine( szLocalBuffer, LOCAL_BUFFER_LEN );
				};
			};
		};
	while( iLen>0 )
		{
		int i=0;
		for(; i<iLen && szLocalBuffer[i]!=':'; i++);
		szLocalBuffer[i++]='\0';
		for(; i<iLen && (isspace(szLocalBuffer[i])); i++);
		PIDB_add( pDB,
			PIDBTYPE_RFC822,
			szLocalBuffer,
			(void *)&(szLocalBuffer[i]),
			0
			);
		iLen = tB.GetLine( szLocalBuffer, LOCAL_BUFFER_LEN );	
		};

	/* --- The 'Host' Header is mandatory for HTTP/1.1 --- */
	if ((iFlags==RH_CLIENTREQUEST) && ((const int)PIDB_lookup(pDB,
		PIDBTYPE_OPAQUE, pFKProtocolNumber, PIDBFLAG_FASTKEY) == PR_HTTP11)
	&& !PIDB_lookup(pDB, PIDBTYPE_RFC822, KEY_HTTP_HOST, 0)) {
		return ST_BADREQUEST;
	};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -