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

📄 httputil.cpp

📁 mini http server,可以集成嵌入到程序中,实现简单的web功能
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		if ( !pFileMap || !pMap )
			{	
			HTTPCore_logError( 0, "HTTPUtil_sendFile: Could not memory \
map file with path '%s'.", pPath );
			PIFMap_delete( pFileMap );
			return PIAPI_ERROR;
			}
		else
			{
			if ( iLen )
				{
				pBuffer->Write( pMap, iLen, iBufferingFlags );
				};
			PIFMap_delete( pFileMap );
			};
		};

	return PIAPI_COMPLETED;
}


/*____________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:
\*____________________________________________________________________________*/
int HTTPUtil_sendFileRange( PIIOBuffer *pBuffer, PIFInfo *pFInfo,
	int iBufferingFlags, unsigned int uiFrom, unsigned int uiTo )
{
	assert( pBuffer );
	assert( pFInfo );

	if ( !pBuffer || !pFInfo )
		{
        return PIAPI_ERROR;
        };

	/* --- get path --- */
	const char *pPath = PIFInfo_getPath( pFInfo );

	/* --- get the file map --- */
	const char *pMap = 0;
	int iSize = 0;

	/* --- the range length --- */
	int iLen = 1 + uiTo - uiFrom;

	/* --- get filemap object --- */
	if ( PIFInfo_getSize( pFInfo ) )
		{
		PIFMap *pFileMap = PIFMap_new( pFInfo );
		if ( pFileMap )
			{
			pMap = (const char *)PIFMap_lock( pFileMap, &iSize );
			};

		if ( !pFileMap || !pMap )
			{	
			HTTPCore_logError( 0, "HTTPUtil_sendFileRange: Could not memory \
map file with path '%s'.", pPath );
			PIFMap_delete( pFileMap );
			return PIAPI_ERROR;
			}
		else
			{
			// check for wrong range (too big, negative...)
			if ( iLen < 1 || uiTo > iSize - 1 || iLen > iSize )
				{
				HTTPCore_logError( 0, "HTTPUtil_sendFileRange: Invalid Range \
(%d-%d) requested for file with path '%s'  of size %d.", uiFrom, uiTo, pPath, iSize );
				PIFMap_delete( pFileMap );
				return PIAPI_ERROR;
				}

			// Is something to send?
			if ( iLen )
				{
				pMap += uiFrom;
				pBuffer->Write( pMap, iLen, iBufferingFlags );
				}

			PIFMap_delete( pFileMap );
			};
		};

	return PIAPI_COMPLETED;
}


/*____________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:
\*____________________________________________________________________________*/
int HTTPUtil_recvFile( PIHTTP *pPIHTTP, PIIOBuffer *pBuffer, PIFInfo *pFInfo )
		{
		/* --- Open file from descriptor --- */
		PIPLATFORM_FD tFD = 0;
		tFD = PIFile_open( PIFInfo_getPath( pFInfo ), "w" );
		if ( tFD == PIPLATFORM_FD_INVALID ) return PIAPI_ERROR;

		/* --- get length to read --- */
		long iRead = 0;
		long iToRead = strtol((const char *)PIDB_lookup( pPIHTTP->pRequestDB,
			PIDBTYPE_RFC822, KEY_HTTP_CONTENTLENGTH, 0 ), NULL, 10);
		int iBufRead;

		/* --- loop until no more bytes left --- */
		do
			{
			/* --- no more data or client timeout --- */
			if ( PIIOBuffer_pollBeforeRead( pBuffer ) < 1 ) break;

			/* --- read the data --- */
			char *szData = (char *)PIIOBuffer_read( pBuffer, &iBufRead );
			iRead += iBufRead;

			/* --- this is an error --- */
			if ( ! iRead ) 
				{
				PIFile_close( tFD );
				return PIAPI_ERROR;
				};

			/* --- write the data to the file --- */
			if ( PIFile_write( tFD, iBufRead, szData ))
				{
				PIFile_close( tFD );
				return PIAPI_ERROR;
				};
			}
		while ( iRead < iToRead );

		/* --- close the file --- */
		if ( PIFile_close( tFD )) return PIAPI_ERROR;
		return PIAPI_COMPLETED;
	};


/*____________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:
 To split a HTTP Multipart Message (RFC1867) into it parts.
\*____________________________________________________________________________*/
PUBLIC_PIAPI int HTTPUtil_recvMultipartMsg( PIHTTP *pPIHTTP, PIIOBuffer *pBuffer,
										   PFN_MUTLIPARTCB cb, void *pUser )
	{
	assert( cb );

	// get length to read
	long iRead = 0;
	char *szContentLength = (char *)PIDB_lookup( pPIHTTP->pRequestDB,
		PIDBTYPE_RFC822, KEY_HTTP_CONTENTLENGTH, 0 );
	if ( !szContentLength ) return PIAPI_ERROR;
	long iToRead = atol( szContentLength );
	int iBufRead;
	unsigned int i = 0;

	enum { IDSIZE = 255 };
	char Id[IDSIZE+1] = "";
	char szName[IDSIZE+1] = "";
	char *szTemp1;
	char *szTemp2;
	enum { BUF_SIZE=8192 };
	char *szBuffer = (char *)PIUtil_malloc( BUF_SIZE );
	if ( !szBuffer ) return PIAPI_ERROR;

	char *szBufRead = szBuffer;
	char *szBufWrite = szBuffer;
	char *szBufEnd = szBuffer + BUF_SIZE;
	int iPhase = MP_PART_NONE;

	// get multipart Id from fist line of http message
	iRead += PIIOBuffer_getLine( pBuffer, Id, IDSIZE );
	iRead += strlen( HTTP_CRLF );

	// an error occured during reading request data
	if ( strlen( HTTP_CRLF ) == iRead || iRead >= iToRead ) goto error;

	// loop until no more bytes left
	do
		{
		// no more data or client timeout ?
		if ( PIIOBuffer_pollBeforeRead( pBuffer ) < 1 ) break;
		
		// read the data
		iBufRead = PIIOBuffer_readToBuffer( pBuffer, szBufRead, szBufEnd - szBufRead );

		if ( !strcmp( szName, "" ))
			{
			// Content Disposition
			szTemp1 = strstr( szBufRead, "Content-Disposition: " );
		
			// This is not a multipart message!
			if ( !szTemp1 ) goto error;

			// Name
			szTemp1 = strstr( szTemp1, "name=" );
			if ( !szTemp1 ) goto error;

			szTemp1 += strlen("name=") + 1;
			szTemp2 = strchr( szTemp1, '"' );
			if ( !szTemp2 ) goto error;

			strncpy( szName, szTemp1, szTemp2 - szTemp1 );
			};
			
		// this is a fatal error
		if ( !iBufRead ) goto error;

		// increase read count and pointer
		iRead += iBufRead;
		szBufRead += iBufRead;

		// ring buffer is full
		if ( szBufRead == szBufEnd )
			{ 
			for ( i = 0; i < BUF_SIZE - strlen( Id ); i++ )
				{
				// a new part was found
				if ( !memcmp( szBuffer + i, Id, strlen( Id ))) 
					{
					// this is the end Id, exit loop
					if ( i == BUF_SIZE - strlen( Id ) - 2 - strlen( HTTP_CRLF )) break;
					iPhase = iPhase ? MP_PART_LAST : MP_PART_FIRST;
					if ( cb( iPhase, szName, szBufWrite, i - (szBufWrite - szBuffer) - strlen( HTTP_CRLF ), pPIHTTP, pUser )) goto error;
					szBufWrite += szBufWrite - szBuffer + i + strlen( Id ) + strlen( HTTP_CRLF );

					// Content Disposition
					szTemp1 = strstr( szBufWrite, "Content-Disposition: " );
		
					// This is not a multipart message!
					if ( !szTemp1 ) goto error;

					// Name
					szTemp1 = strstr( szTemp1, "name=" );
					if ( !szTemp1 ) goto error;

					szTemp1 += strlen("name=") + 1;
					szTemp2 = strchr( szTemp1, '"' );
					if ( !szTemp2 ) goto error;

					strncpy( szName, szTemp1, szTemp2 - szTemp1 );
					szName[szTemp2 - szTemp1] = 0;

					iPhase = MP_PART_NONE;
					};
				};

			// the whole rest of the buffer
			iPhase = iPhase ? MP_PART_NEXT : MP_PART_FIRST;
			if ( cb( iPhase, szName, szBufWrite, szBufEnd - szBufWrite - strlen( Id ), pPIHTTP, pUser )) goto error;

			// move the untested margin to the start of the buffer
			memcpy( szBuffer, szBufRead - strlen( Id ), strlen( Id ));
			szBufRead = szBuffer + strlen( Id );
			szBufWrite = szBuffer;
			};
		}
	while ( iRead < iToRead );
		
	// an error occured during reading request data
	if ( iRead < iToRead ) goto error;

	// rest of ring buffer
	for ( i = 0; i < ( szBufRead - szBuffer ) - strlen( Id ); i++ )
		{
		// a new part was found
		if ( !memcmp( szBuffer + i, Id, strlen( Id ))) 
			{
			// this is the end Id, exit loop
			if ( i == ( szBufRead - szBuffer ) - strlen( Id ) - 2 - strlen( HTTP_CRLF )) break;
			iPhase = iPhase ? MP_PART_NEXT | MP_PART_LAST : MP_PART_FIRST | MP_PART_LAST;
			if ( cb( iPhase, szName, szBufWrite, i - ( szBufWrite - szBuffer ) - strlen( HTTP_CRLF ), pPIHTTP, pUser )) goto error;
			szBufWrite += szBufWrite - szBuffer + i + strlen( Id ) + strlen( HTTP_CRLF );

			// Content Disposition
			szTemp1 = strstr( szBufWrite, "Content-Disposition: " );
		
			// This is not a multipart message!
			if ( !szTemp1 ) goto error;

			// Name
			szTemp1 = strstr( szTemp1, "name=" );
			if ( !szTemp1 ) goto error;

			szTemp1 += strlen("name=") + 1;
			szTemp2 = strchr( szTemp1, '"' );
			if ( !szTemp2 ) goto error;

			strncpy( szName, szTemp1, szTemp2 - szTemp1 );
			szName[szTemp2 - szTemp1] = 0;

			iPhase = MP_PART_NONE;
			};
		};

	// the whole rest of the buffer
	iPhase = iPhase ? MP_PART_NEXT | MP_PART_LAST : MP_PART_FIRST | MP_PART_LAST;
	if ( cb( iPhase, szName, szBufWrite, szBufRead - szBufWrite - strlen( HTTP_CRLF )
		- strlen(Id) - 2 - strlen( HTTP_CRLF ),	pPIHTTP, pUser )) goto error;

	// Completion
	PIUtil_free( szBuffer );
	return PIAPI_COMPLETED;
error:
	PIUtil_free( szBuffer );
	return PIAPI_ERROR;
	};


/*____________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:
\*____________________________________________________________________________*/
static const char *pMethodMap[] = 
{
    0,
    MD_NAME_GET,
    MD_NAME_POST,
    MD_NAME_HEAD,
    MD_NAME_PUT,
    MD_NAME_DELETE,
    MD_NAME_OPTIONS,
    MD_NAME_TRACE,
    MD_NAME_CONNECT,
    0
};
static const char *pProtocolMap[] = 
{
    PR_NAME_UNKNOWN,
    PR_NAME_HTTP09,
    PR_NAME_HTTP10,
    PR_NAME_HTTP11,
    0
};
static const char *pConnectionMap[] = 
{
    "Close",
    "Keep-Alive",
    0
};
int HTTPUtil_doHTTPRequest( PIIOBuffer *pBuffer, PIDB *pQ )
{
    /*
    ** Gather items for the HTTP request and validate them
    */
    const char *pMethod = 0;
    const char *pURI = 0;
    const char *pQS = 0;
    const char *pProtocol = 0;
    const char *pConnection = 0;

    int iMethod = (int)PIDB_lookup( pQ, PIDBTYPE_OPAQUE, KEY_HTTP_METHOD, 0 );
    if ( iMethod<1 || iMethod>MD_LAST )
        { return PIAPI_EINVAL; };
    pMethod = pMethodMap[iMethod];

    int iProtocol = (int)PIDB_lookup( pQ, PIDBTYPE_OPAQUE, KEY_HTTP_PROTOCOL, 0 );
    if ( iProtocol<1 || iProtocol>PR_HTTP11 )
        { return PIAPI_EINVAL; };
    pProtocol = pProtocolMap[iProtocol];

    int iKeepAlive = (int)PIDB_lookup( pQ, PIDBTYPE_OPAQUE, KEY_HTTP_CONNECTION, 0 );
    if ( iKeepAlive<0 || iKeepAlive>1 )
        { return PIAPI_EINVAL; };
    pConnection = pConnectionMap[iKeepAlive];

    pURI = (const char *)PIDB_lookup( pQ, PIDBTYPE_STRING, KEY_HTTP_URI, 0 );
    if ( !pURI )
        { return PIAPI_EINVAL; };

    pQS = (const char *)PIDB_lookup( pQ, PIDBTYPE_STRING, KEY_HTTP_QUERYSTRING, 0 );
    
    /* ---
    Send the HTTP request line and standard headers 
    --- */
    PIIOBuffer_write( pBuffer, pMethod, -1, PIIOBUF_NONE );
    PIIOBuffer_write( pBuffer, " ", 1, PIIOBUF_NONE );
    PIIOBuffer_write( pBuffer, pURI, -1, PIIOBUF_NONE );
    if ( pQS && *pQS )
        {
        PIIOBuffer_write( pBuffer, "?", 1, PIIOBUF_NONE );
        PIIOBuffer_write( pBuffer, pQS, -1, PIIOBUF_NONE );
        };
    PIIOBuffer_write( pBuffer, " ", 1, PIIOBUF_NONE );
    PIIOBuffer_writeLn( pBuffer, pProtocol, -1, PIIOBUF_NONE );

    if (( iKeepAlive && iProtocol == PR_HTTP10 )
    || ( !iKeepAlive && iProtocol == PR_HTTP11 ))
        {
        PIIOBuffer_write( pBuffer, "Connection", -1, PIIOBUF_NONE );
        PIIOBuffer_write( pBuffer, ": ", 2, PIIOBUF_NONE );
        PIIOBuffer_writeLn( pBuffer, pConnection, -1, PIIOBUF_NONE );
        };

    /* ---
    Now send included headers
    --- */
    /* --- iterate over all headers, sending them to server --- */
    PIDBIterator *pRIter = PIDB_getIterator( pQ, PIDBTYPE_RFC822, 0, 0 );
    if ( pRIter )
        {
        for( ;  PIDBIterator_atValidElement( pRIter );
                PIDBIterator_next( pRIter ) )
            {
            const char *pKey;
            const char *pValue = (const char *)
                PIDBIterator_current( pRIter, &pKey );
            if ( pKey && *pKey )
                {
                PIIOBuffer_write( pBuffer, pKey, -1, PIIOBUF_NONE );
                PIIOBuffer_write( pBuffer, ": ", 2, PIIOBUF_NONE );
                PIIOBuffer_writeLn( pBuffer, pValue, -1, PIIOBUF_NONE );
                };
            };
        PIDBIterator_delete( pRIter );
        };
    PIIOBuffer_writeLn( pBuffer, "", 0, PIIOBUF_NONE );

    /* ---
    HTTP request has been started
    --- */
    return PIAPI_COMPLETED;
}

⌨️ 快捷键说明

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