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

📄 sendfile.cpp

📁 mini http server,可以集成嵌入到程序中,实现简单的web功能
💻 CPP
📖 第 1 页 / 共 4 页
字号:
		int i = 0;																
		/*
		** loop over all RFC822 headers in request block to calculate Content Length
		*/				
		PIDBIterator *pIter = PIDB_getIterator( pQ, PIDBTYPE_RFC822, 0, 0 );	
		if ( !pIter )															
			{
				return PIAPI_ERROR;
			};	
	
		for(; PIDBIterator_atValidElement( pIter ); PIDBIterator_next( pIter ) )
			{																
			const char *pKey;													
			const char *pValue = (const char *)PIDBIterator_current( pIter,	&pKey );
			assert( pKey && pValue );
			ulLen += strlen(pKey) + strlen(pValue) + 4;
			};
		PIDBIterator_delete( pIter );

		/* --- content-length --- */
		char szBuf[2];
		sprintf( szBuf, "%lu", ulLen );
		PIDB_replace( pR, PIDBTYPE_RFC822, KEY_HTTP_CONTENTLENGTH, szBuf, 0 );
		PIDB_replace( pR, PIDBTYPE_RFC822, KEY_HTTP_CONTENTTYPE, (void *)TYPE_MSG_HTTP, 0 );

		/* --- start response --- */
		if (	HTTPCore_sendGeneralHeaders( &tPIHTTP ) ||
				HTTPCore_sendEntityHeaders( &tPIHTTP, pR ) )
			{
			return PIAPI_ERROR;
			};

		if ( PIIOBuffer_write( tPIHTTP.pBuffer, pReq, strlen(pReq), PIIOBUF_NONE) == 0 )
			{
			return PIAPI_ERROR;
			};
		if ( PIIOBuffer_write( tPIHTTP.pBuffer, "\r\n", 2, PIIOBUF_NONE) == 0 )
			{
			return PIAPI_ERROR;
			};

		pIter = PIDB_getIterator( pQ, PIDBTYPE_RFC822, 0, 0 );
		for(; PIDBIterator_atValidElement( pIter ); PIDBIterator_next( pIter ) )
			{																
			const char *pKey;													
			const char *pValue = (const char *)PIDBIterator_current( pIter,	&pKey );
			assert( pKey && pValue );
			if ( PIIOBuffer_write( tPIHTTP.pBuffer, pKey, strlen(pKey), PIIOBUF_NONE) == 0 )
				{
				PIDBIterator_delete( pIter );
				return PIAPI_ERROR;
				};
			if ( PIIOBuffer_write( tPIHTTP.pBuffer, ": ", 2, PIIOBUF_NONE) == 0 )
				{
				PIDBIterator_delete( pIter );
				return PIAPI_ERROR;
				};
			if ( PIIOBuffer_write( tPIHTTP.pBuffer, pValue, strlen(pValue), PIIOBUF_NONE) == 0 )
				{
				PIDBIterator_delete( pIter );
				return PIAPI_ERROR;
				};
			if ( PIIOBuffer_write( tPIHTTP.pBuffer, "\r\n", 2, PIIOBUF_NONE) == 0 )
				{
				PIDBIterator_delete( pIter );
				return PIAPI_ERROR;
				};
			};
		PIDBIterator_delete( pIter );

		return PIAPI_COMPLETED;
		};

public:
	SendFile( PIObject *pObject, int iArgc, const char *ppArgv[] )
	:	HandlerBaseHTTP( pObject ),
		pHeaderPattern( 0 ),
		pFooterPattern( 0 ),
		iMethods( FLG_GET | FLG_HEAD ),
		sFileKey( "upfile" ),
		sNoteKey( "notes" ),
		pAnnotation( 0 ),
		sDescFile( 0 ),
		sPathInfo( 0 ),
		sUploadPath( 0 ),
		sUploadFile( 0 ),
		iUploadLimit( 0 ),
		iChunkLimit( 0 ),
		iAllowRanges( 0 ),
		tFD( PIPLATFORM_FD_INVALID ),
		pFKMethod( PIDB_getFastKey( KEY_HTTP_METHOD, PIDBTYPE_OPAQUE )),
		pFKRange( PIDB_getFastKey( KEY_HTTP_RANGE, PIDBTYPE_RFC822 )),
		pFKIfRange( PIDB_getFastKey( KEY_HTTP_IFRANGE, PIDBTYPE_RFC822 )),
		pFKPath( PIDB_getFastKey( KEY_INT_PATH, PIDBTYPE_STRING )),
		pFKProtocol( PIDB_getFastKey( KEY_HTTP_PROTOCOL, PIDBTYPE_OPAQUE ))
		{
		ReadParameters( iArgc, ppArgv );
		};

	~SendFile()
		{
		Pi3Expression_delete( pHeaderPattern );
		Pi3Expression_delete( pFooterPattern );
		};

	int Handle( int iPhase, PIHTTP &tPIHTTP, PIIOBuffer &tB )
		{
		if ( iPhase!=PH_HANDLE ) { return PIAPI_ERROR; };

		/* ---
		Lookup method 
		--- */
		int iMethod = (int)PIDB_lookup( tPIHTTP.pRequestDB, PIDBTYPE_OPAQUE,
			pFKMethod, PIDBFLAG_FASTKEY );

		/* ---
		Check for supported methods
		--- */
		if ( iMethods )
			{
			int iMethFlag = 1;
			iMethFlag <<= iMethod;
			/* ---
			The method is not handled by this object
			--- */
			if ( !(iMethFlag & iMethods) )
				{
				/* ---
				The object has been created with default methods
				--- */
				if ( (iMethods==(FLG_GET | FLG_HEAD)) &&
					(!( iMethFlag==FLG_GET || iMethFlag==FLG_HEAD )))
					{ return PIAPI_CONTINUE; };

				/* ---
				The object has been created with method mask
				--- */
				return HTTPUtil_doHTTPError( &tPIHTTP, ST_NOTIMPLEMENTED );
				};
			}

		// check, that range headers are provided only in GET and HEAD requests
		// AND ignore range header in sub-requests (internal redirects)
		const char *szRangeHeader = 0;
		if (!PIHTTP_isChild( &tPIHTTP))
			{
			szRangeHeader = (const char *)PIDB_lookup( tPIHTTP.pRequestDB, PIDBTYPE_RFC822,
			pFKRange, PIDBFLAG_FASTKEY );
			};

		if ( szRangeHeader && !(iMethod==MD_GET || iMethod==MD_HEAD))
			{
			HTTPCore_logError( &tPIHTTP, "SendFile: Range headers can only be processed in GET and HEAD requests.");
			return HTTPUtil_doHTTPError( &tPIHTTP, ST_NOTIMPLEMENTED );
			};

		switch( iMethod )
			{
			case MD_GET:
			case MD_HEAD:
				return Get_Head( tPIHTTP, iMethod, szRangeHeader );

			case MD_PUT:
				return Put( tPIHTTP, tB );

			case MD_POST:
				return Post( tPIHTTP, tB );

			case MD_DELETE:
				return Delete( tPIHTTP );

			case MD_OPTIONS:
				return Options( tPIHTTP, tB );

			case MD_TRACE:
				return Trace( tPIHTTP, tB );

			default:
				assert( 0 );
				/* ---
				Something is real going wrong
				--- */
				return PIAPI_ERROR;
			};

		return PIAPI_ERROR;
		};
};

#define pfkUpfileHandle "UPFILE_HANDLE"

int fnMultipartCb( int iKind, char *szName, char *szData, long lData, PIHTTP *pPIHTTP, void *pUser )
{
	// The file part of the message
	if ( !PIUtil_stricmp( szName, ((SendFile *)pUser)->sFileKey ))
		{
		PIString sPath;

		if ( iKind & MP_PART_FIRST )
			{
			// Extract filename
			char *pFileName = strstr( szData, "filename=" );
			if ( !pFileName ) return PIAPI_ERROR;
			pFileName += strlen("filename=") + 1;
			char *pStrEnd = strchr( pFileName, '"' );
			if ( pStrEnd )
			    {
			    *pStrEnd = 0;
			    }
			else
			    {
			    return PIAPI_ERROR;
			    };
			// memset( strchr( pFileName, '"' ), 0, 1);

			PIFInfo *pFInfo = HTTPCore_getCachedFile( pFileName );
			if ( !pFInfo ) return PIAPI_ERROR;
			strcpy( pFileName, PIFInfo_getName( pFInfo ));
			((SendFile *)pUser)->sUploadFile = pFileName;
			HTTPCore_releaseCachedFile( pFInfo );

			/* ---
			Get file path 
			--- */
			sPath = ((SendFile *)pUser)->sUploadPath;
			sPath.Concatenate( ((SendFile *)pUser)->sUploadFile );
		
			/* ---
			Get the file object
			--- */
			pFInfo = HTTPCore_getCachedFile( sPath ); 
			if ( !pFInfo ) return PIAPI_ERROR;

			/* ---	
			If this file exist it must be a regular file 
			--- */
			if ( PIFInfo_exists( pFInfo ) && !PIFInfo_isRegular( pFInfo ))
				{
				HTTPCore_logError( pPIHTTP, "SendFile: File with \
path '%s' is not a regular file.", (const char *)sPath );
				HTTPCore_releaseCachedFile( pFInfo );	
				return HTTPUtil_doHTTPError( pPIHTTP, ST_INTERNALERROR );
			};

			/* ---	
			If this file exist it must be a writeable file 
			--- */
			if ( PIFInfo_exists( pFInfo ) && !PIFInfo_isWritable( pFInfo ))
				{
				HTTPCore_releaseCachedFile( pFInfo );	
				return HTTPUtil_doHTTPError( pPIHTTP, ST_FORBIDDEN );
				};

			HTTPCore_releaseCachedFile( pFInfo );

			// jump over Content-Disposition
			char *szStart = (char *)memchr( szData, 10, lData );
			if ( !szStart ) return PIAPI_ERROR;

			// jump over Content-Type
			szStart = (char *)memchr( szStart + 1, 10, lData );
			if ( !szStart ) return PIAPI_ERROR;

			// jump over CR/LF
			szStart = (char *)memchr( szStart + 1, 10, lData ) + 1;
			if ( !szStart ) return PIAPI_ERROR;

			// Open file from origin name
			((SendFile *)pUser)->tFD = PIFile_open( sPath, "w" );
			if ( ((SendFile *)pUser)->tFD == PIPLATFORM_FD_INVALID ) return PIAPI_ERROR;

			if ( PIFile_write( ((SendFile *)pUser)->tFD, lData - (szStart - szData), szStart ))
				{
				PIFile_close( ((SendFile *)pUser)->tFD );
				((SendFile *)pUser)->tFD = PIPLATFORM_FD_INVALID;
				return PIAPI_ERROR;
				};
			};

		if ( iKind & MP_PART_NEXT )
			{
			// write the data to the file
			if ( PIFile_write( ((SendFile *)pUser)->tFD, lData, szData ))
				{
				PIFile_close( ((SendFile *)pUser)->tFD );
				((SendFile *)pUser)->tFD = PIPLATFORM_FD_INVALID;
				return PIAPI_ERROR;
				};
			};

		if ( iKind & MP_PART_LAST )
			{
			if ( iKind == MP_PART_LAST )
				{
				// write the data to the file
				if ( PIFile_write( ((SendFile *)pUser)->tFD, lData, szData ))
					{
					PIFile_close( ((SendFile *)pUser)->tFD );
					((SendFile *)pUser)->tFD = PIPLATFORM_FD_INVALID;
					return PIAPI_ERROR;
					};
				};

			// close the file
			if ( PIFile_close( ((SendFile *)pUser)->tFD )) return PIAPI_ERROR;
			((SendFile *)pUser)->tFD = PIPLATFORM_FD_INVALID;

			/* ---
			Write the annotation
			--- */
			if ( !((SendFile *)pUser)->pAnnotation ) return PIAPI_COMPLETED;

			enum { BUF_SIZE=1024 };
			char szBuf[BUF_SIZE];
			strcpy( szBuf, ((SendFile *)pUser)->sUploadPath );
			strcat( szBuf, ((SendFile *)pUser)->sUploadFile );
			char *pStrEnd = strchr( szBuf, '.' );
			if ( pStrEnd )
			    {
			    *pStrEnd = '_';
			    }
			else
			    {
			    return PIAPI_ERROR;
			    };
			
			// if ( strchr( szBuf, '.' )) memset( strchr( szBuf, '.' ), '_', 1 );
			sPath = szBuf;
			sPath.Concatenate( NOTE_EXT );

			char *pBuf = szBuf;
			int iLen = Pi3Expression_write( ((SendFile *)pUser)->pAnnotation, pPIHTTP, 0, pBuf, BUF_SIZE );
			if ( iLen > BUF_SIZE )
				{
				pBuf = PI_NEW( char[iLen] );
				Pi3Expression_write( ((SendFile *)pUser)->pAnnotation, pPIHTTP, 0, pBuf, iLen );
				};
		
			// Open file from origin name
			((SendFile *)pUser)->tFD = PIFile_open( sPath, "w" );
			if ( ((SendFile *)pUser)->tFD == PIPLATFORM_FD_INVALID ) return PIAPI_ERROR;

			/* --- write the message --- */
			int iRet = PIFile_writeAtomic( ((SendFile *)pUser)->tFD, iLen, pBuf );
			if ( pBuf != szBuf )
				{
				PI_DELETE( [] pBuf );
				};
			if ( iRet )
				{
				/* --- an error occurred --- */
				HTTPCore_logError( pPIHTTP, "SendFile: \
PIFile_writeAtomic() failed for file '%s', error code '%d'.", (const char *)sPath,
				PIPlatform_getLastError() );
				PIFile_close( ((SendFile *)pUser)->tFD );
				((SendFile *)pUser)->tFD = PIPLATFORM_FD_INVALID;
				return HTTPUtil_doHTTPError( pPIHTTP, ST_INTERNALERROR );
				};

			// close the file
			if ( PIFile_close( ((SendFile *)pUser)->tFD )) return PIAPI_ERROR;
			((SendFile *)pUser)->tFD = PIPLATFORM_FD_INVALID;
			};

		return PIAPI_COMPLETED;
		};

	// The note part of the message
	if ( !PIUtil_stricmp( szName, ((SendFile *)pUser)->sNoteKey ))
		{
		if ( !((SendFile *)pUser)->sDescFile ) return PIAPI_COMPLETED;
		
		// The file name must exist!
		if ( !((SendFile *)pUser)->sUploadFile ) return PIAPI_ERROR;

		/* ---
		Get path information of upload file
		--- */
		PIFInfo *pFInfo = HTTPCore_getCachedFile( ((SendFile *)pUser)->sUploadPath );
		if ( !pFInfo ) return PIAPI_ERROR;

		PIString sPath = ((SendFile *)pUser)->sUploadPath;
		sPath.Concatenate( ((SendFile *)pUser)->sDescFile );
		HTTPCore_releaseCachedFile( pFInfo );

		// jump over Content-Disposition
		char *szStart = (char *)memchr( szData, 10, lData );
		if ( !szStart ) return PIAPI_ERROR;

		// jump over CR/LF
		szStart = (char *)memchr( szStart + 1, 10, lData ) + 1;
		if ( !szStart ) return PIAPI_ERROR;

		PIDB *pDescriptionDB = PIDB_new( 0, "File Descriptions" );
		if ( !((SendFile *)pUser)->LoadDescriptionFile( pDescriptionDB, sPath )) 
			{
			PIDB_delete( pDescriptionDB );
			return PIAPI_ERROR;
			};

		DescriptionMap *pDesc = (DescriptionMap *)PIDB_lookup( pDescriptionDB,
			PIDBTYPE_OPAQUE, ((SendFile *)pUser)->sUploadFile, 0 );

		if ( !pDesc )
			{
			pDesc = PI_NEW( DescriptionMap( ((SendFile *)pUser)->sUploadFile,
				szStart, lData - (szStart - szData)));
			PIDB_add( pDescriptionDB, PIDBTYPE_OPAQUE, pDesc->sFileName,
				(void *)pDesc, 0 );
			}
		else
			{
			PIString sTmp( szStart, lData - (szStart - szData));
			pDesc->sDescription = sTmp;
			};

		if ( !((SendFile *)pUser)->SaveDescriptionFile( pDescriptionDB, sPath )) 
			{
			PIDB_delete( pDescriptionDB );
			return PIAPI_ERROR;
			};

		PIDB_delete( pDescriptionDB );

		return PIAPI_COMPLETED;
		};

	return PIAPI_ERROR;
};

/*____________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:
\*____________________________________________________________________________*/
PUBLIC_PIAPI int SendFile_constructor( PIObject *pObj,
	int iArgc, const char *ppArgv[] )
{
	return HandlerBaseHTTP_constructor( pObj, PI_NEW( SendFile( pObj,
		iArgc, ppArgv ) ) );
}

#if 0
/*___+++CNF_BEGIN+++___*/
	<Class>
		Name SendFileClass
		Type LogicExtension
		Library HTTP
		OnClassLoad HandlerBaseHTTP_onClassLoad
		Constructor SendFile_constructor
		CopyConstructor HandlerBaseHTTP_copyConstructor
		Destructor HandlerBaseHTTP_destructor
		Execute HandlerBaseHTTP_execute
	</Class>

	<Object>
		Name SendFile
		Class SendFileClass
	</Object>

/*___+++CNF_END+++___*/
#endif

⌨️ 快捷键说明

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