3 * BNBT Beta 8.0 - A C++ BitTorrent Tracker
\r
4 * Copyright (C) 2003-2004 Trevor Hogan
\r
6 * CBTT variations (C) 2003-2005 Harold Feit
\r
8 * This library is free software; you can redistribute it and/or
\r
9 * modify it under the terms of the GNU Lesser General Public
\r
10 * License as published by the Free Software Foundation; either
\r
11 * version 2.1 of the License, or (at your option) any later version.
\r
13 * This library is distributed in the hope that it will be useful,
\r
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
\r
16 * Lesser General Public License for more details.
\r
18 * You should have received a copy of the GNU Lesser General Public
\r
19 * License along with this library; if not, write to the Free Software
\r
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
\r
25 #define unlink remove
\r
29 #include <sys/time.h>
\r
37 #include "bencode.h"
\r
38 #include "tracker.h"
\r
41 void UTIL_LogPrint( const char *format, ... )
\r
43 time_t tNow = time( NULL );
\r
44 char *szTime = asctime( localtime( &tNow ) );
\r
45 szTime[strlen( szTime ) - 1] = '\0';
\r
47 gmtxOutput.Claim( );
\r
49 printf( "[%s] ", szTime );
\r
52 va_start( args, format );
\r
53 vprintf( format, args );
\r
56 if( !gstrErrorLogDir.empty( ) && !gstrErrorLogFilePattern.empty( ) )
\r
59 memset( pTime, 0, sizeof( char ) * 256 );
\r
60 strftime( pTime, sizeof( char ) * 256, gstrErrorLogFilePattern.data( ), localtime( &tNow ) );
\r
62 string strFile = gstrErrorLogDir + pTime;
\r
64 if( gstrErrorLogFile != strFile )
\r
68 gstrErrorLogFile = strFile;
\r
72 fclose( gpErrorLog );
\r
77 gpErrorLog = fopen( strFile.c_str( ), "ab" );
\r
82 fprintf( gpErrorLog, "[%s] ", szTime );
\r
85 va_start( args, format );
\r
86 vfprintf( gpErrorLog, format, args );
\r
91 if( giErrorLogCount % giFlushInterval == 0 )
\r
92 fflush( gpErrorLog );
\r
96 gmtxOutput.Release( );
\r
99 //addition by labarks
\r
100 string UTIL_Date( )
\r
102 time_t tNow = time( NULL );
\r
106 memset( pTime, 0, sizeof( char ) * 256 );
\r
107 strftime( pTime, sizeof( char ) * 256, "%a, %d %b %Y %H:%M:%S", localtime( &tNow ) );
\r
108 #if defined( __APPLE__ ) || defined( __FREEBSD__ )
\r
109 long timezone = -( localtime( &tNow )->tm_gmtoff );
\r
112 // timezone has the wrong sign, change it
\r
115 strDate = (string) pTime + " -" + addzero( abs( timezone / 3600 ) % 60 ) + addzero( abs( timezone / 60 ) % 60 );
\r
117 strDate = (string) pTime + " +" + addzero( abs( timezone / 3600 ) % 60 ) + addzero( abs( timezone / 60 ) % 60 );
\r
122 string UTIL_AddedToDate( string strAdded )
\r
125 struct tm * tDate; //2004-05-09 01:30:21
\r
129 tDate = localtime ( &rawtime );
\r
130 tDate->tm_year = UTIL_StringToInt( strAdded.substr(0,4) ) - 1900;
\r
131 tDate->tm_mon = UTIL_StringToInt( strAdded.substr(5,2) ) - 1;
\r
132 tDate->tm_mday = UTIL_StringToInt( strAdded.substr(8,2) );
\r
133 tDate->tm_hour = UTIL_StringToInt( strAdded.substr(11,2) );
\r
134 tDate->tm_min = UTIL_StringToInt( strAdded.substr(14,2) );
\r
135 tDate->tm_sec = UTIL_StringToInt( strAdded.substr(17,2) );
\r
139 memset( pTime, 0, sizeof( char ) * 256 );
\r
140 strftime( pTime, sizeof( char ) * 256, "%a, %d %b %Y %H:%M:%S", tDate );
\r
141 #if defined( __APPLE__ ) || defined( __FREEBSD__ )
\r
142 time_t tNow = time( NULL );
\r
143 long timezone = -( localtime( &tNow )->tm_gmtoff );
\r
146 // timezone has the wrong sign, change it
\r
149 strDate = (string) pTime + " -" + addzero( abs( timezone / 3600 ) % 60 ) + addzero( abs( timezone / 60 ) % 60 );
\r
151 strDate = (string) pTime + " +" + addzero( abs( timezone / 3600 ) % 60 ) + addzero( abs( timezone / 60 ) % 60 );
\r
156 string addzero( unsigned long iLong ) //for timezones used in UTIL_Date and UTIL_AddedToDate
\r
159 return (string) "0" + string() + UTIL_LongToString( iLong );
\r
161 return UTIL_LongToString( iLong );
\r
165 void UTIL_AccessLogPrint( string strIP, string strUser, string strRequest, int iStatus, int iBytes )
\r
167 gmtxOutput.Claim( );
\r
169 if( !gstrAccessLogDir.empty( ) && !gstrAccessLogFilePattern.empty( ) )
\r
171 time_t tNow = time( NULL );
\r
174 memset( pTime, 0, sizeof( char ) * 256 );
\r
175 strftime( pTime, sizeof( char ) * 256, gstrAccessLogFilePattern.data( ), localtime( &tNow ) );
\r
177 string strFile = gstrAccessLogDir + pTime;
\r
179 if( gstrAccessLogFile != strFile )
\r
183 gstrAccessLogFile = strFile;
\r
187 fclose( gpAccessLog );
\r
189 gpAccessLog = NULL;
\r
192 gpAccessLog = fopen( strFile.c_str( ), "ab" );
\r
195 UTIL_LogPrint( "log warning - unable to open %s for writing\n", strFile.c_str( ) );
\r
200 fprintf( gpAccessLog, "%s - ", strIP.c_str( ) );
\r
202 if( strUser.empty( ) )
\r
203 fprintf( gpAccessLog, "- " );
\r
205 fprintf( gpAccessLog, "%s ", strUser.c_str( ) );
\r
207 strftime( pTime, sizeof( char ) * 256, "%d/%b/%Y:%H:%M:%S", localtime( &tNow ) );
\r
209 #if defined( __APPLE__ ) || defined( __FREEBSD__ )
\r
210 long timezone = -( localtime( &tNow )->tm_gmtoff );
\r
213 // timezone has the wrong sign, change it
\r
216 fprintf( gpAccessLog, "[%s -%02d%02d] ", pTime, abs( timezone / 3600 ) % 60, abs( timezone / 60 ) % 60 );
\r
218 fprintf( gpAccessLog, "[%s +%02d%02d] ", pTime, abs( timezone / 3600 ) % 60, abs( timezone / 60 ) % 60 );
\r
220 fprintf( gpAccessLog, "\"%s\" %d %d\n", strRequest.c_str( ), iStatus, iBytes );
\r
222 giAccessLogCount++;
\r
224 if( giAccessLogCount % giFlushInterval == 0 )
\r
225 fflush( gpAccessLog );
\r
229 gmtxOutput.Release( );
\r
233 // shamelessly stolen from wget source code
\r
236 struct bnbttv UTIL_CurrentTime( )
\r
243 GetSystemTime( &st );
\r
244 SystemTimeToFileTime( &st, &ft );
\r
245 btv.wintime.HighPart = ft.dwHighDateTime;
\r
246 btv.wintime.LowPart = ft.dwLowDateTime;
\r
249 gettimeofday( &tv, NULL );
\r
250 btv.sec = tv.tv_sec;
\r
251 btv.usec = tv.tv_usec;
\r
257 long UTIL_ElapsedTime( struct bnbttv btvStart, struct bnbttv btvEnd )
\r
260 return (long)( ( btvEnd.wintime.QuadPart - btvStart.wintime.QuadPart ) / 10000 );
\r
262 return ( btvEnd.sec - btvStart.sec ) * 1000 + ( btvEnd.usec - btvStart.usec ) / 1000;
\r
266 string UTIL_ElapsedTimeStr( struct bnbttv btvStart, struct bnbttv btvEnd )
\r
269 memset( szGen, 0, sizeof( char ) * 8 );
\r
270 sprintf( szGen, "%0.3f", UTIL_ElapsedTime( btvStart, btvEnd ) / 1000.0 );
\r
275 string UTIL_EscapedToString( const string &strEscape )
\r
277 // according to RFC 2396
\r
281 for( unsigned long i = 0; i < strEscape.size( ); )
\r
283 if( strEscape[i] == '%' )
\r
285 if( i < strEscape.size( ) - 2 )
\r
289 memset( pBuf, 0, sizeof( char ) * 4 );
\r
291 pBuf[0] = strEscape[i + 1];
\r
292 pBuf[1] = strEscape[i + 2];
\r
296 sscanf( pBuf, "%02X", &c );
\r
304 UTIL_LogPrint( "error decoding escaped string - possible truncation, halting decode\n" );
\r
309 else if( strEscape[i] == '+' )
\r
317 strString += strEscape[i];
\r
326 string UTIL_HashToString( const string &strHash )
\r
328 // convert a 20 character hash to a readable string
\r
332 if( strHash.size( ) != 20 )
\r
335 for( unsigned long i = 0; i < strHash.size( ); i++ )
\r
339 memset( pBuf, 0, sizeof( char ) * 4 );
\r
341 // this must be unsigned or some really strange errors appear (i.e. the value of i is reset to zero every loop)
\r
343 unsigned char c = strHash[i];
\r
345 sprintf( pBuf, "%02x", c );
\r
353 string UTIL_BytesToString( int64 iBytes )
\r
355 int64 iB = iBytes % 1024;
\r
357 int64 iKB = iBytes % 1024;
\r
359 int64 iMB = iBytes % 1024;
\r
361 int64 iGB = iBytes % 1024;
\r
363 int64 iTB = iBytes % 1024;
\r
365 int64 iPB = iBytes;
\r
367 // B -> KB -> MB -> GB -> TB -> PB -> EB -> ZB -> YB
\r
373 int iFrac = (int)( (float)iTB / (float)1024 * (float)100 );
\r
375 strBytes += CAtomLong( iPB ).toString( );
\r
378 if( CAtomInt( iFrac ).toString( ).size( ) == 1 )
\r
381 strBytes += CAtomInt( iFrac ).toString( );
\r
386 int iFrac = (int)( (float)iGB / (float)1024 * (float)100 );
\r
388 strBytes += CAtomLong( iTB ).toString( );
\r
391 if( CAtomInt( iFrac ).toString( ).size( ) == 1 )
\r
394 strBytes += CAtomInt( iFrac ).toString( );
\r
399 int iFrac = (int)( (float)iMB / (float)1024 * (float)100 );
\r
401 strBytes += CAtomLong( iGB ).toString( );
\r
404 if( CAtomInt( iFrac ).toString( ).size( ) == 1 )
\r
407 strBytes += CAtomInt( iFrac ).toString( );
\r
412 int iFrac = (int)( (float)iKB / (float)1024 * (float)100 );
\r
414 strBytes += CAtomLong( iMB ).toString( );
\r
417 if( CAtomInt( iFrac ).toString( ).size( ) == 1 )
\r
420 strBytes += CAtomInt( iFrac ).toString( );
\r
425 int iFrac = (int)( (float)iB / (float)1024 * (float)100 );
\r
427 strBytes += CAtomLong( iKB ).toString( );
\r
430 if( CAtomInt( iFrac ).toString( ).size( ) == 1 )
\r
433 strBytes += CAtomInt( iFrac ).toString( );
\r
438 strBytes += CAtomLong( iB ).toString( );
\r
445 string UTIL_SecondsToString( unsigned long iSeconds )
\r
447 // int iS = iSeconds % 60;
\r
450 int iM = iSeconds % 60;
\r
452 int iH = iSeconds % 24;
\r
458 strSeconds += CAtomInt( iD ).toString( );
\r
459 strSeconds += "d ";
\r
461 if( CAtomInt( iH ).toString( ).size( ) == 1 )
\r
464 strSeconds += CAtomInt( iH ).toString( );
\r
467 if( CAtomInt( iM ).toString( ).size( ) == 1 )
\r
470 strSeconds += CAtomInt( iM ).toString( );
\r
476 if( CAtomInt( iS ).toString( ).size( ) == 1 )
\r
479 strSeconds += CAtomInt( iS ).toString( );
\r
485 //addition by labarks
\r
486 string UTIL_IntToString( int intInt )
\r
490 strInt = CAtomInt( intInt ).toString( );
\r
495 string UTIL_LongToString( unsigned long iLong )
\r
499 iLong = (int64) iLong;
\r
501 strLong = CAtomLong( iLong ).toString( );
\r
506 int UTIL_StringToInt( string strInt )
\r
508 return atoi( strInt.c_str() );
\r
511 unsigned long UTIL_FileSize( const char *szFile )
\r
513 FILE *pFile = NULL;
\r
514 if( ( pFile = fopen( szFile, "rb" ) ) == NULL )
\r
516 //UTIL_LogPrint( "error opening file - unable to open %s for reading\n", szFile );
\r
519 fseek( pFile, 0, SEEK_END );
\r
520 unsigned long ulFileSize = ftell( pFile );
\r
526 string UTIL_FileSizeToString( const char *szFile )
\r
528 return UTIL_LongToString( UTIL_FileSize( szFile ) );
\r
532 string UTIL_StringToEscaped( const string &strString )
\r
534 // according to RFC 2396
\r
538 for( unsigned long i = 0; i < strString.size( ); i++ )
\r
540 unsigned char c = strString[i];
\r
542 if( isalpha( c ) || isdigit( c ) ||
\r
553 // found an unreserved character
\r
557 else if( c == ' ' )
\r
561 // found a reserved character
\r
565 memset( pBuf, 0, sizeof( char ) * 4 );
\r
567 sprintf( pBuf, "%02X", c );
\r
577 //addition by labarks
\r
578 string UTIL_URLEncode( const string &strString )
\r
580 // according to RFC 2396
\r
584 for( unsigned long i = 0; i < strString.size( ); i++ )
\r
586 unsigned char c = strString[i];
\r
588 if( isalpha( c ) || isdigit( c ) ||
\r
609 // found an unreserved character
\r
615 // found a reserved character
\r
619 memset( pBuf, 0, sizeof( char ) * 4 );
\r
621 sprintf( pBuf, "%02X", c );
\r
632 string UTIL_StringToEscapedStrict( const string &strString )
\r
636 for( unsigned long i = 0; i < strString.size( ); i++ )
\r
638 unsigned char c = strString[i];
\r
640 if( isalpha( c ) || isdigit( c ) ||
\r
651 // found an unreserved character
\r
657 // found a reserved character
\r
661 memset( pBuf, 0, sizeof( char ) * 4 );
\r
663 sprintf( pBuf, "%02X", c );
\r
673 string UTIL_StringToHash( const string &strString )
\r
675 // convert a readable string hash to a 20 character hash
\r
679 if( strString.size( ) != 40 )
\r
682 for( unsigned long i = 0; i < strString.size( ); i += 2 )
\r
686 memset( pBuf, 0, sizeof( char ) * 4 );
\r
688 pBuf[0] = strString[i];
\r
689 pBuf[1] = strString[i + 1];
\r
693 sscanf( pBuf, "%02x", &c );
\r
701 string UTIL_AccessToString( int iAccess )
\r
703 if( iAccess & ACCESS_ADMIN )
\r
705 else if( iAccess & ACCESS_EDIT )
\r
706 return "Moderator";
\r
707 else if( iAccess & ACCESS_UPLOAD )
\r
709 else if( iAccess & ACCESS_COMMENTS )
\r
711 else if( iAccess & ACCESS_DL )
\r
712 return "Downloader";
\r
713 else if( iAccess & ACCESS_VIEW )
\r
719 int64 UTIL_StringTo64( const char *sz64 )
\r
723 #if defined( WIN32 )
\r
724 sscanf( sz64, "%I64d", &i );
\r
725 #elif defined( __FREEBSD__ )
\r
726 sscanf( sz64, "%qd", &i );
\r
728 sscanf( sz64, "%lld", &i );
\r
734 string UTIL_InfoHash( CAtom *pTorrent )
\r
736 if( pTorrent && pTorrent->isDicti( ) )
\r
738 CAtom *pInfo = ( (CAtomDicti *)pTorrent )->getItem( "info" );
\r
740 if( pInfo && pInfo->isDicti( ) )
\r
742 CAtomDicti *pInfoDicti = (CAtomDicti *)pInfo;
\r
744 // encode the string
\r
746 string strData = Encode( pInfo );
\r
752 hasher.Update( (UINT_8 *)strData.c_str( ), strData.size( ) );
\r
755 char szInfoHash[64];
\r
756 memset( szInfoHash, 0, sizeof( char ) * 64 );
\r
758 hasher.ReportHash( szInfoHash );
\r
760 return UTIL_StringToHash( szInfoHash );
\r
767 bool UTIL_CheckFile( const char *szFile )
\r
769 // check if file exists
\r
771 FILE *pFile = NULL;
\r
773 if( ( pFile = fopen( szFile, "r" ) ) == NULL )
\r
781 void UTIL_MakeFile( const char *szFile, string strContents )
\r
783 FILE *pFile = NULL;
\r
785 if( ( pFile = fopen( szFile, "wb" ) ) == NULL )
\r
787 UTIL_LogPrint( "warning - unable to open %s for writing\n", szFile );
\r
792 fwrite( (void *)strContents.c_str( ), sizeof( char ), strContents.size( ), pFile );
\r
796 void UTIL_DeleteFile( const char *szFile )
\r
798 if( unlink( szFile ) == 0 )
\r
799 UTIL_LogPrint( "deleted \"%s\"\n", szFile );
\r
803 UTIL_LogPrint( "error deleting \"%s\"\n", szFile );
\r
805 UTIL_LogPrint( "error deleting \"%s\" - %s\n", szFile, strerror( errno ) );
\r
810 void UTIL_MoveFile( const char *szFile, const char *szDest )
\r
812 if( UTIL_CheckFile( szDest ) )
\r
813 UTIL_LogPrint( "error archiving \"%s\" - destination file already exists\n", szDest );
\r
815 UTIL_MakeFile( szDest, UTIL_ReadFile( szFile ) );
\r
819 UTIL_DeleteFile( szFile );
\r
822 string UTIL_ReadFile( const char *szFile )
\r
824 FILE *pFile = NULL;
\r
826 if( ( pFile = fopen( szFile, "rb" ) ) == NULL )
\r
828 UTIL_LogPrint( "warning - unable to open %s for reading\n", szFile );
\r
833 fseek( pFile, 0, SEEK_END );
\r
834 unsigned long ulFileSize = ftell( pFile );
\r
835 fseek( pFile, 0, SEEK_SET );
\r
836 char *pData = (char *)malloc( sizeof( char ) * ulFileSize );
\r
837 memset( pData, 0, sizeof( char ) * ulFileSize );
\r
838 fread( (void *)pData, sizeof( char ), ulFileSize, pFile );
\r
840 string strFile( pData, ulFileSize );
\r
846 string UTIL_ToLower( string strUpper )
\r
848 for( unsigned long i = 0; i < strUpper.size( ); i++ )
\r
849 strUpper[i] = tolower( strUpper[i] );
\r
854 string UTIL_StripPath( string strPath )
\r
856 string :: size_type iFileStart = strPath.rfind( '\\' );
\r
858 if( iFileStart == string :: npos )
\r
860 iFileStart = strPath.rfind( '/' );
\r
862 if( iFileStart == string :: npos )
\r
870 return strPath.substr( iFileStart );
\r
873 string UTIL_RemoveHTML( string strHTML )
\r
875 for( unsigned long i = 0; i < strHTML.size( ); i++ )
\r
877 if( strHTML[i] == '<' )
\r
878 strHTML.replace( i, 1, "<" );
\r
879 else if( strHTML[i] == '>' )
\r
880 strHTML.replace( i, 1, ">" );
\r
881 else if( strHTML[i] == '&' )
\r
882 strHTML.replace( i, 1, "&" );
\r
883 else if( strHTML[i] == '"' )
\r
884 strHTML.replace( i, 1, """ );
\r
885 else if( strHTML[i] == '\n' )
\r
889 if( strHTML[i - 1] == '\r' )
\r
891 strHTML.replace( i - 1, 2, "<br>" );
\r
897 strHTML.replace( i, 1, "<br>" );
\r
904 strHTML.replace( i, 1, "<br>" );
\r
914 string UTIL_FailureReason( string strFailureReason )
\r
918 dict.setItem( "failure reason", new CAtomString( strFailureReason ) );
\r
920 return Encode( &dict );
\r
925 ===================
\r
926 UTIL_DecodeHTTPPost
\r
927 ===================
\r
932 key1->string (quotes stripped)
\r
933 key2->string (quotes stripped)
\r
934 key3->string (quotes stripped)
\r
935 key4->string (quotes stripped)
\r
943 key1->string (quotes stripped)
\r
944 key2->string (quotes stripped)
\r
945 key3->string (quotes stripped)
\r
946 key4->string (quotes stripped)
\r
955 CAtomList *UTIL_DecodeHTTPPost( string strPost )
\r
957 // find the boundary
\r
959 string :: size_type iBoundary = strPost.find( "boundary=" );
\r
961 if( iBoundary == string :: npos )
\r
964 iBoundary += strlen( "boundary=" );
\r
966 string strBoundary = strPost.substr( iBoundary );
\r
968 string :: size_type iBoundEnd = strBoundary.find( "\r\n" );
\r
970 if( iBoundEnd == string :: npos )
\r
973 strBoundary = strBoundary.substr( 0, iBoundEnd );
\r
975 // strBoundary now contains the boundary
\r
977 string :: size_type iContent = strPost.find( "\r\n\r\n" );
\r
979 if( iContent == string :: npos )
\r
982 iContent += strlen( "\r\n\r\n" );
\r
984 string strContent = strPost.substr( iContent );
\r
988 CAtomList *pList = new CAtomList( );
\r
990 string :: size_type iSegStart = 0;
\r
991 string :: size_type iSegEnd = 0;
\r
997 iSegStart = strContent.find( strBoundary, iSegStart );
\r
999 if( iSegStart == string :: npos )
\r
1002 iSegStart += strBoundary.size( );
\r
1004 if( strContent.substr( iSegStart, 2 ) == "--" )
\r
1007 iSegStart += strlen( "\r\n" );
\r
1011 iSegEnd = strContent.find( strBoundary, iSegStart );
\r
1013 if( iSegEnd == string :: npos )
\r
1015 UTIL_LogPrint( "error decoding HTTP POST request - unexpected end of request\n" );
\r
1024 iSegEnd -= strlen( "\r\n--" );
\r
1028 CAtomDicti *pSegment = new CAtomDicti( );
\r
1030 pList->addItem( pSegment );
\r
1032 // this could do with some serious optimizing...
\r
1034 string strSeg = strContent.substr( iSegStart, iSegEnd - iSegStart );
\r
1036 string :: size_type iDispStart = strSeg.find( "Content-Disposition: " );
\r
1038 if( iDispStart == string :: npos )
\r
1040 UTIL_LogPrint( "error decoding HTTP POST request - couldn't find Content-Disposition\n" );
\r
1049 iDispStart += strlen( "Content-Disposition: " );
\r
1051 string :: size_type iDispEnd = strSeg.find( "\r\n", iDispStart );
\r
1053 if( iDispEnd == string :: npos )
\r
1055 UTIL_LogPrint( "error decoding HTTP POST request - malformed Content-Disposition\n" );
\r
1064 string strDisp = strSeg.substr( iDispStart, iDispEnd - iDispStart );
\r
1066 string :: size_type iDispPrev = 0;
\r
1067 string :: size_type iDispPos = 0;
\r
1069 CAtomDicti *pDisp = new CAtomDicti( );
\r
1071 pSegment->setItem( "disposition", pDisp );
\r
1075 // assume a semicolon indicates the end of the item and will never appear inside the item (probably a bad assumption)
\r
1077 iDispPrev = iDispPos;
\r
1078 iDispPos = strDisp.find( ";", iDispPos );
\r
1080 if( iDispPos == string :: npos )
\r
1082 // decode last item
\r
1084 iDispPos = strDisp.size( );
\r
1087 string strCurr = strDisp.substr( iDispPrev, iDispPos - iDispPrev );
\r
1089 string :: size_type iSplit = strCurr.find( "=" );
\r
1091 if( iSplit == string :: npos )
\r
1093 // found a key without value, i.e. "form-data", useless so ignore it
\r
1095 if( iDispPos == strDisp.size( ) )
\r
1098 // + strlen( ";" )
\r
1105 // strip whitespace
\r
1107 string :: size_type iKeyStart = strCurr.find_first_not_of( " " );
\r
1109 if( iKeyStart == string :: npos || iKeyStart > iSplit )
\r
1111 UTIL_LogPrint( "error decoding HTTP POST request - malformed Content-Disposition\n" );
\r
1120 string strKey = strCurr.substr( iKeyStart, iSplit - iKeyStart );
\r
1121 string strValue = strCurr.substr( iSplit + 1 );
\r
1125 if( strValue.size( ) > 1 && strValue[0] == '"' )
\r
1126 strValue = strValue.substr( 1, strValue.size( ) - 2 );
\r
1128 pDisp->setItem( strKey, new CAtomString( strValue ) );
\r
1130 if( iDispPos == strDisp.size( ) )
\r
1133 // + strlen( ";" )
\r
1140 string :: size_type iDataStart = strSeg.find( "\r\n\r\n" );
\r
1142 if( iDataStart == string :: npos )
\r
1144 UTIL_LogPrint( "error decoding HTTP POST request - malformed segment\n" );
\r
1153 iDataStart += strlen( "\r\n\r\n" );
\r
1155 pSegment->setItem( "data", new CAtomString( strSeg.substr( iDataStart ) ) );
\r
1158 // this should never happen, so who cares
\r