CClient :: ~CClient( ) { if( closesocket( m_sckClient ) == SOCKET_ERROR ) UTIL_LogPrint( "client error: Closing Socket (error %s)\n", GetLastErrorString( ) ); else if( gbDebug ) UTIL_LogPrint( "client: Socket Closed\n" ); }
CAtomDicti *DecodeDicti( const string &x, unsigned long iStart ) { unsigned long i = iStart + 1; CAtomDicti *pDicti = new CAtomDicti( ); while( i < x.size( ) && x[i] != 'e' ) { CAtom *pKey = Decode( x, i ); if( pKey && dynamic_cast<CAtomString *>( pKey ) ) { i += pKey->EncodedLength( ); string strKey = pKey->toString( ); delete pKey; if( i < x.size( ) ) { CAtom *pValue = Decode( x, i ); if( pValue ) { i += pValue->EncodedLength( ); pDicti->setItem( strKey, pValue ); } else { UTIL_LogPrint( "error decoding dictionary - error decoding value, discarding dictionary\n" ); delete pDicti; return NULL; } } } else { UTIL_LogPrint( "error decoding dictionary - error decoding key, discarding dictionary\n" ); delete pDicti; return NULL; } } return pDicti; }
CAtomList *DecodeList( const string &x, unsigned long iStart ) { unsigned long i = iStart + 1; CAtomList *pList = new CAtomList( ); while( i < x.size( ) && x[i] != 'e' ) { CAtom *pAtom = Decode( x, i ); if( pAtom ) { i += pAtom->EncodedLength( ); pList->addItem( pAtom ); } else { UTIL_LogPrint( "error decoding list - error decoding list item, discarding list\n" ); delete pList; return NULL; } } return pList; }
void CClient :: Reset( ) { if( gbDebug && ( gucDebugLevel & DEBUG_CLIENT ) ) UTIL_LogPrint( "client: reset\n" ); m_ucState = CS_RECVHEADERS; m_strReceiveBuf.erase( ); m_strReceiveBuf.reserve( 1024 ); m_strSendBuf.erase( ); m_strSendBuf.reserve( 1024 ); rqst.strMethod.erase( ); rqst.strURL.erase( ); rqst.mapParams.clear( ); rqst.mapHeaders.clear( ); rqst.mapCookies.clear( ); rqst.user.strLogin.erase( ); rqst.user.strLowerLogin.erase( ); rqst.user.strMD5.erase( ); rqst.user.strMail.erase( ); rqst.user.strLowerMail.erase( ); rqst.user.strCreated.erase( ); rqst.user.ucAccess = 0; rsp.strCode.erase( ); rsp.mapHeaders.clear( ); rsp.strContent.erase( ); rsp.strContent.reserve( 1024 ); rsp.bCompressOK = true; m_ulLast = GetTime( ); m_bReset = true; }
CServer :: ~CServer( ) { closesocket( m_sckServer ); unsigned long iStart = GetTime( ); while( 1 ) { for( vector<CClient *> :: iterator i = m_vecClients.begin( ); i != m_vecClients.end( ); ) { if( (*i)->m_iState == CS_WAITING1 || (*i)->m_iState == CS_WAITING2 || (*i)->m_iState == CS_DEAD ) { delete *i; i = m_vecClients.erase( i ); } else i++; } if( m_vecClients.size( ) > 0 ) { UTIL_LogPrint( "server - waiting for %d clients to disconnect\n", m_vecClients.size( ) ); MILLISLEEP( 1000 ); } else break; if( GetTime( ) - iStart > 60 ) { UTIL_LogPrint( "server - waited 60 seconds, exiting anyway\n" ); break; } } if( m_pTracker ) delete m_pTracker; m_pTracker = NULL; UTIL_LogPrint( "server - exit\n" ); }
CAtomString *DecodeString( const string &x, unsigned long iStart ) { string :: size_type iSplit = x.find_first_not_of( "1234567890", iStart ); if( iSplit == string :: npos ) { UTIL_LogPrint( "error decoding string - couldn't find \":\", halting decode\n" ); return NULL; } return new CAtomString( x.substr( iSplit + 1, atoi( x.substr( iStart, iSplit - iStart ).c_str( ) ) ) ); }
CAtom *Decode( const string &x, unsigned long iStart ) { if( iStart < x.size( ) ) { if( x[iStart] == 'i' ) return DecodeLong( x, iStart ); else if( isdigit( x[iStart] ) ) return DecodeString( x, iStart ); else if( x[iStart] == 'l' ) return DecodeList( x, iStart ); else if( x[iStart] == 'd' ) return DecodeDicti( x, iStart ); string temp = x.substr( iStart ); UTIL_LogPrint( "error decoding - found unexpected character %u, halting decode\n", (unsigned char)x[iStart] ); } else UTIL_LogPrint( "error decoding - out of range\n" ); return NULL; }
CMySQLQuery :: CMySQLQuery( string strQuery ) { mysql_real_query( gpMySQL, strQuery.c_str( ), strQuery.size( ) ); m_pRes = mysql_store_result( gpMySQL ); if( mysql_errno( gpMySQL ) ) { m_pRes = NULL; if( gbDebug ) UTIL_LogPrint( "mysql error - %s\n", mysql_error( gpMySQL ) ); } }
CClient :: CClient( SOCKET &sckClient, struct sockaddr_in &sinAddress, const unsigned int &cuiTimeOut, const char &ccCompression ) { if( gbDebug ) UTIL_LogPrint( "client: Socket Opening\n" ); m_sckClient = sckClient; // make socket non blocking #ifdef WIN32 u_long ulMode = 1; if( ioctlsocket( m_sckClient, FIONBIO, &ulMode ) == SOCKET_ERROR ) #else if( fcntl( m_sckClient, F_SETFL, fcntl( m_sckClient, F_GETFL ) | O_NONBLOCK ) == SOCKET_ERROR ) #endif UTIL_LogPrint( "client warning: socket blocking (error %s)\n", GetLastErrorString( ) ); m_uiTimeOut = cuiTimeOut; m_cCompression = ccCompression; rqst.sin = sinAddress; Reset( ); }
CServer :: ~CServer( ) { for( vector<SOCKET> :: iterator itListener = m_vecListeners.begin( ); itListener != m_vecListeners.end( ); itListener++ ) closesocket( *itListener ); for( vector<CClient *> :: iterator itClient = m_vecClients.begin( ); itClient != m_vecClients.end( ); itClient++ ) delete *itClient; m_vecListeners.clear( ); m_vecClients.clear( ); if( m_pTracker ) delete m_pTracker; m_pTracker = 0; UTIL_LogPrint( ( gmapLANG_CFG["server_exit"] + "\n" ).c_str( ) ); }
CAtom *DecodeFile( const char *szFile ) { FILE *pFile = FILE_ERROR; pFile = fopen( szFile, "rb" ); if( pFile == FILE_ERROR ) { UTIL_LogPrint( "warning - unable to open %s for reading\n", szFile ); return 0; } // Find the end of the file fseek( pFile, 0, SEEK_END ); // Remember the file size for later const unsigned long culFileSize( ftell( pFile ) ); // Reset to the start of the file fseek( pFile, 0, SEEK_SET ); // Allocate memory for the data buffer char *pData = (char *)malloc( sizeof( char ) * culFileSize ); // Read the data fread( pData, sizeof( char ), culFileSize, pFile ); // Close the file fclose( pFile ); // Place the data in a string const string cstrFile( pData, culFileSize ); // Free the data buffer memory free( pData ); // Return the decoded data return Decode( cstrFile ); }
CAtomDicti :: CAtomDicti( const CAtomDicti &c ) { // copy constructor map<string, CAtom *> *pmapDicti = c.getValuePtr( ); for( map<string, CAtom *> :: iterator i = pmapDicti->begin( ); i != pmapDicti->end( ); i++ ) { if( dynamic_cast<CAtomInt *>( (*i).second ) && dynamic_cast<CAtomInt *>( (*i).second ) != NULL ) setItem( (*i).first, new CAtomInt( *dynamic_cast<CAtomInt *>( (*i).second ) ) ); else if( dynamic_cast<CAtomLong *>( (*i).second ) && dynamic_cast<CAtomLong *>( (*i).second ) != NULL ) setItem( (*i).first, new CAtomLong( *dynamic_cast<CAtomLong *>( (*i).second ) ) ); else if( dynamic_cast<CAtomString *>( (*i).second ) && dynamic_cast<CAtomString *>( (*i).second ) != NULL ) setItem( (*i).first, new CAtomString( *dynamic_cast<CAtomString *>( (*i).second ) ) ); else if( dynamic_cast<CAtomList *>( (*i).second ) && dynamic_cast<CAtomList *>( (*i).second ) != NULL ) setItem( (*i).first, new CAtomList( *dynamic_cast<CAtomList *>( (*i).second ) ) ); else if( dynamic_cast<CAtomDicti *>( (*i).second ) && dynamic_cast<CAtomDicti *>( (*i).second ) != NULL ) setItem( (*i).first, new CAtomDicti( *dynamic_cast<CAtomDicti *>( (*i).second ) ) ); else UTIL_LogPrint( "error copying dictionary - found invalid atom, ignoring\n" ); } }
CAtomDicti :: CAtomDicti( const CAtomDicti &c ) { // copy constructor map<string, CAtom *> *pmapDicti = c.getValuePtr( ); for( map<string, CAtom *> :: iterator itAtom = pmapDicti->begin( ); itAtom != pmapDicti->end( ); itAtom++ ) { if( dynamic_cast<CAtomInt *>( (*itAtom).second ) ) setItem( (*itAtom).first, new CAtomInt( *dynamic_cast<CAtomInt *>( (*itAtom).second ) ) ); else if( dynamic_cast<CAtomLong *>( (*itAtom).second ) ) setItem( (*itAtom).first, new CAtomLong( *dynamic_cast<CAtomLong *>( (*itAtom).second ) ) ); else if( dynamic_cast<CAtomString *>( (*itAtom).second ) ) setItem( (*itAtom).first, new CAtomString( *dynamic_cast<CAtomString *>( (*itAtom).second ) ) ); else if( dynamic_cast<CAtomList *>( (*itAtom).second ) ) setItem( (*itAtom).first, new CAtomList( *dynamic_cast<CAtomList *>( (*itAtom).second ) ) ); else if( dynamic_cast<CAtomDicti *>( (*itAtom).second ) ) setItem( (*itAtom).first, new CAtomDicti( *dynamic_cast<CAtomDicti *>( (*itAtom).second ) ) ); else UTIL_LogPrint( ( gmapLANG_CFG["atomdicti_copy_warning"] + "\n" ).c_str( ) ); } }
CAtomList :: CAtomList( const CAtomList &c ) { // copy constructor vector<CAtom *> *pvecList = c.getValuePtr( ); for( vector<CAtom *> :: iterator i = pvecList->begin( ); i != pvecList->end( ); i++ ) { if( dynamic_cast<CAtomInt *>( *i ) ) addItem( new CAtomInt( *dynamic_cast<CAtomInt *>( *i ) ) ); else if( dynamic_cast<CAtomLong *>( *i ) ) addItem( new CAtomLong( *dynamic_cast<CAtomLong *>( *i ) ) ); else if( dynamic_cast<CAtomString *>( *i ) ) addItem( new CAtomString( *dynamic_cast<CAtomString *>( *i ) ) ); else if( dynamic_cast<CAtomList *>( *i ) ) addItem( new CAtomList( *dynamic_cast<CAtomList *>( *i ) ) ); else if( dynamic_cast<CAtomDicti *>( *i ) ) addItem( new CAtomDicti( *dynamic_cast<CAtomDicti *>( *i ) ) ); else UTIL_LogPrint( "error copying list - found invalid atom, ignoring\n" ); } }
CAtomList :: CAtomList( const CAtomList &c ) { // copy constructor vector<CAtom *> *pvecList = c.getValuePtr( ); for( vector<CAtom *> :: iterator itAtom = pvecList->begin( ); itAtom != pvecList->end( ); itAtom++ ) { if( dynamic_cast<CAtomInt *>( *itAtom ) ) addItem( new CAtomInt( *dynamic_cast<CAtomInt *>( *itAtom ) ) ); else if( dynamic_cast<CAtomLong *>( *itAtom ) ) addItem( new CAtomLong( *dynamic_cast<CAtomLong *>( *itAtom ) ) ); else if( dynamic_cast<CAtomString *>( *itAtom ) ) addItem( new CAtomString( *dynamic_cast<CAtomString *>( *itAtom ) ) ); else if( dynamic_cast<CAtomList *>( *itAtom ) ) addItem( new CAtomList( *dynamic_cast<CAtomList *>( *itAtom ) ) ); else if( dynamic_cast<CAtomDicti *>( *itAtom ) ) addItem( new CAtomDicti( *dynamic_cast<CAtomDicti *>( *itAtom ) ) ); else UTIL_LogPrint( ( gmapLANG_CFG["atomlist_copy_warning"] + "\n" ).c_str( ) ); } }
CAtomLong *DecodeLong( const string &x, unsigned long iStart ) { string :: size_type iEnd = x.find( "e", iStart ); if( iEnd == string :: npos ) { UTIL_LogPrint( "error decoding long - couldn't find \"e\", halting decode\n" ); return NULL; } int64 i; #if defined( WIN32 ) sscanf( x.substr( iStart + 1, iEnd - iStart - 1 ).c_str( ), "%I64d", &i ); #elif defined( FreeBSD ) sscanf( x.substr( iStart + 1, iEnd - iStart - 1 ).c_str( ), "%qd", &i ); #else sscanf( x.substr( iStart + 1, iEnd - iStart - 1 ).c_str( ), "%lld", &i ); #endif return new CAtomLong( i ); }
CAtom *DecodeFile( const char *szFile ) { FILE *pFile = NULL; if( ( pFile = fopen( szFile, "rb" ) ) == NULL ) { UTIL_LogPrint( "warning - unable to open %s for reading\n", szFile ); return NULL; } fseek( pFile, 0, SEEK_END ); unsigned long ulFileSize = ftell( pFile ); fseek( pFile, 0, SEEK_SET ); char *pData = (char *)malloc( sizeof( char ) * ulFileSize ); memset( pData, 0, sizeof( char ) * ulFileSize ); fread( (void *)pData, sizeof( char ), ulFileSize, pFile ); fclose( pFile ); string strFile( pData, ulFileSize ); free( pData ); return Decode( strFile ); }
CServer :: CServer( ) { m_bKill = false; m_iSocketTimeOut = CFG_GetInt( "socket_timeout", 15 ); m_strBind = CFG_GetString( "bind", string( ) ); m_iCompression = CFG_GetInt( "bnbt_compression_level", 6 ); // clamp if( m_iCompression > 9 ) m_iCompression = 9; struct sockaddr_in sin; memset( &sin, 0, sizeof( sin ) ); sin.sin_family = AF_INET; if( !m_strBind.empty( ) ) { // bind to m_strBind if( gbDebug ) UTIL_LogPrint( "server - binding to %s\n", m_strBind.c_str( ) ); if( ( sin.sin_addr.s_addr = inet_addr( m_strBind.c_str( ) ) ) == INADDR_NONE ) { UTIL_LogPrint( "server error - unable to bind to %s\n", m_strBind.c_str( ) ); Kill( ); } } else { // bind to all available addresses if( gbDebug ) UTIL_LogPrint( "server - binding to all available addresses\n" ); sin.sin_addr.s_addr = INADDR_ANY; } if( ( sin.sin_port = htons( (u_short)CFG_GetInt( "port", 6969 ) ) ) == 0 ) { UTIL_LogPrint( "server error - invalid port %d\n", CFG_GetInt( "port", 6969 ) ); Kill( ); } // map protocol name to protocol number struct protoent *pPE; if( ( pPE = getprotobyname( "tcp" ) ) == 0 ) { UTIL_LogPrint( "server error - unable to get tcp protocol entry (error %d)\n", GetLastError( ) ); Kill( ); } // allocate socket if( ( m_sckServer = socket( PF_INET, SOCK_STREAM, pPE->p_proto ) ) == INVALID_SOCKET ) { UTIL_LogPrint( "server error - unable to allocate socket (error %d)\n", GetLastError( ) ); Kill( ); } // bind socket int optval = 1; #ifdef WIN32 setsockopt( m_sckServer, SOL_SOCKET, SO_REUSEADDR, (const char *)&optval, sizeof( int ) ); #else setsockopt( m_sckServer, SOL_SOCKET, SO_REUSEADDR, (const void *)&optval, sizeof( int ) ); #endif if( bind( m_sckServer, (struct sockaddr *)&sin, sizeof( sin ) ) == SOCKET_ERROR ) { UTIL_LogPrint( "server error - unable to bind socket (error %d)\n", GetLastError( ) ); Kill( ); } // listen, queue length 8 if( listen( m_sckServer, 8 ) == SOCKET_ERROR ) { UTIL_LogPrint( "server error - unable to listen (error %d)\n", GetLastError( ) ); Kill( ); } m_pTracker = new CTracker( ); UTIL_LogPrint( "server - start\n" ); }
bool CServer :: Update( bool bBlock ) { if( m_vecClients.size( ) < (unsigned int)giMaxConns ) { fd_set fdServer; FD_ZERO( &fdServer ); FD_SET( m_sckServer, &fdServer ); struct timeval tv; if( bBlock ) { // block for 100 ms to keep from eating up all cpu time tv.tv_sec = 0; tv.tv_usec = 100000; } else { tv.tv_sec = 0; tv.tv_usec = 0; } #ifdef WIN32 if( select( 1, &fdServer, NULL, NULL, &tv ) == SOCKET_ERROR ) #else if( select( m_sckServer + 1, &fdServer, NULL, NULL, &tv ) == SOCKET_ERROR ) #endif { UTIL_LogPrint( "server warning - select error (error %d)\n", GetLastError( ) ); FD_ZERO( &fdServer ); MILLISLEEP( 100 ); } if( FD_ISSET( m_sckServer, &fdServer ) ) { struct sockaddr_in adrFrom; int iAddrLen = sizeof( adrFrom ); SOCKET sckClient; #ifdef WIN32 if( ( sckClient = accept( m_sckServer, (struct sockaddr *)&adrFrom, &iAddrLen ) ) == INVALID_SOCKET ) #else if( ( sckClient = accept( m_sckServer, (struct sockaddr *)&adrFrom, (socklen_t *)&iAddrLen ) ) == INVALID_SOCKET ) #endif UTIL_LogPrint( "server warning - accept error (error %d)\n", GetLastError( ) ); else { // reuse the old timeval structure just because tv.tv_sec = m_iSocketTimeOut; tv.tv_usec = 0; CClient *pClient = new CClient( sckClient, adrFrom, tv, m_iCompression ); #ifdef WIN32 if( _beginthread( ( void (*)(void *) )StartReceiving, 0, (void *)pClient ) == -1 ) { UTIL_LogPrint( "server warning - unable to spawn receiver thread\n" ); pClient->m_iState = CS_DEAD; } #else pthread_t thread; // set detached state since we don't need to join with any threads pthread_attr_t attr; pthread_attr_init( &attr ); pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED ); int c = pthread_create( &thread, &attr, ( void * (*)(void *) )StartReceiving, (void *)pClient ); if( c != 0 ) { UTIL_LogPrint( "server warning - unable to spawn receiver thread (error %s)\n", strerror( c ) ); pClient->m_iState = CS_DEAD; } #endif m_vecClients.push_back( pClient ); } } } else { // maximum connections reached MILLISLEEP( 100 ); } // process for( vector<CClient *> :: iterator i = m_vecClients.begin( ); i != m_vecClients.end( ); ) { if( (*i)->m_iState == CS_WAITING1 ) { (*i)->Process( ); i++; } else if( (*i)->m_iState == CS_WAITING2 ) { (*i)->m_iState = CS_SENDING; #ifdef WIN32 if( _beginthread( ( void (*)(void *) )StartSending, 0, (void *)(*i) ) == -1 ) { UTIL_LogPrint( "server warning - unable to spawn sender thread\n" ); (*i)->m_iState = CS_DEAD; } #else pthread_t thread; // set detached state since we don't need to join with any threads pthread_attr_t attr; pthread_attr_init( &attr ); pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED ); int c = pthread_create( &thread, &attr, ( void * (*)(void *) )StartSending, (void *)(*i) ); if( c != 0 ) { UTIL_LogPrint( "server warning - unable to spawn sender thread (error %s)\n", strerror( c ) ); (*i)->m_iState = CS_DEAD; } #endif i++; } else if( (*i)->m_iState == CS_DEAD ) { delete *i; i = m_vecClients.erase( i ); } else i++; } if( m_pTracker ) m_pTracker->Update( ); return m_bKill; }
int bnbtmain( ) { gmtxOutput.Initialize( ); gmtxMySQL.Initialize( ); UTIL_LogPrint( "Tracker Start\n" ); srand( (unsigned int)time( 0 ) ); gtStartTime = time( 0 ); CFG_Open( CFG_FILE ); CFG_SetDefaults( ); CFG_Close( CFG_FILE ); // XBNBT Language Configuration LANG_CFG_Init( LANG_CFG_FILE ); UTIL_LogPrint( "Setting debug level, access and error log files\n" ); guiFlushInterval = CFG_GetInt( "bnbt_flush_interval", 100 ); // Log gstrLogDir = CFG_GetString( "bnbt_log_dir", string( ) ); gstrLogFilePattern = CFG_GetString( "bnbt_log_file_pattern", "%Y-%m-%d.log" ); if( !gstrLogDir.empty( ) && gstrLogDir[gstrLogDir.size( ) - 1] != PATH_SEP ) gstrLogDir += PATH_SEP; gpLog = 0; gulLogCount = 0; // Error log gstrErrorLogDir = CFG_GetString( "bnbt_error_log_dir", string( ) ); gstrErrorLogFilePattern = CFG_GetString( "bnbt_error_log_file_pattern", "%Y-%m-%de.log" ); if( !gstrErrorLogDir.empty( ) && gstrErrorLogDir[gstrErrorLogDir.size( ) - 1] != PATH_SEP ) gstrErrorLogDir += PATH_SEP; gpErrorLog = 0; gulErrorLogCount = 0; // Access log gstrAccessLogDir = CFG_GetString( "bnbt_access_log_dir", string( ) ); gstrAccessLogFilePattern = CFG_GetString( "bnbt_access_log_file_pattern", "%Y-%m-%da.log" ); if( !gstrAccessLogDir.empty( ) && gstrAccessLogDir[gstrAccessLogDir.size( ) - 1] != PATH_SEP ) gstrAccessLogDir += PATH_SEP; gpAccessLog = 0; gulAccessLogCount = 0; // Set the debug level gbDebug = CFG_GetInt( "bnbt_debug", 1 ) == 0 ? false : true; gucDebugLevel = (unsigned char)CFG_GetInt( "bnbt_debug_level", 0 ); UTIL_LogPrint( "***********************************************\n" ); if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) ) { UTIL_LogPrint( "Debug is on at level (%u)\n", gucDebugLevel ); if( gstrLogDir.empty( ) ) UTIL_LogPrint( "Log directory is not set\n" ); else UTIL_LogPrint( "Log dir (%s)\n", gstrLogDir.c_str( ) ); if( gstrErrorLogDir.empty( ) ) UTIL_LogPrint( "Error log directory is not set\n" ); else UTIL_LogPrint( "Error log dir (%s)\n", gstrErrorLogDir.c_str( ) ); if( gstrErrorLogDir.empty( ) ) UTIL_LogPrint( "Access log directory is not set\n" ); else UTIL_LogPrint( "Access log dir (%s)\n", gstrAccessLogDir.c_str( ) ); } // Other globals if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) ) UTIL_LogPrint( "Setting global variables\n" ); // PID gstrPID = CFG_GetString( "bnbt_pid_file", string( ) ); if( gstrPID.empty( ) ) { if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) ) UTIL_LogPrint( "PID file is not set\n" ); } else { // Write the process ID to file const long clPID( (long)getpid( ) ); UTIL_LogPrint( "Recording PID (%ld) to file (%s)\n", clPID, gstrPID.c_str( ) ); FILE *pFile = FILE_ERROR; pFile = fopen( gstrPID.c_str( ), "wt" ); if( pFile == FILE_ERROR ) UTIL_LogPrint( "Unable to write PID file (%s)\n", gstrPID.c_str( ) ); else { fprintf( pFile, "%ld", clPID ); fclose( pFile ); } if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) ) UTIL_LogPrint( "Recording PID completed\n" ); } guiRestartServerInterval = CFG_GetInt( "bnbt_restart_interval", 24 ); gulRestartServerNext = GetTime( ) + guiRestartServerInterval * 3600; guiMaxConns = CFG_GetInt( "bnbt_max_conns", 64 ); guiMaxRecvSize = CFG_GetInt( "bnbt_max_recv_size", 524288 ); gstrStyle = CFG_GetString( "bnbt_style_sheet", string( ) ); gstrCharSet = CFG_GetString( "bnbt_charset", "utf-8" ); gstrRealm = CFG_GetString( "bnbt_realm", "BNBT" ); gstrPasswordKey = CFG_GetString( "bnbt_password_key", "ZiJingBT" ); // The Trinity Edition - Addition Begins // Sets the value for the Custom NT Service Name variable gstrNTServiceName = CFG_GetString( "cbtt_service_name", "BNBT Service" ); // TCP window size guiSO_RECBUF = CFG_GetInt( "xbnbt_so_recbuf", 128 ) * 1024; guiSO_SNDBUF = CFG_GetInt( "xbnbt_so_sndbuf", 128 ) * 1024; // Naggles algorithm gbTCP_NODELAY = CFG_GetInt( "xbnbt_tcp_nodelay", 0 ) == 0 ? false : true; #ifdef WIN32 // start winsock if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) ) UTIL_LogPrint( "Starting the windows sockets\n" ); WSADATA wsaData; const int ciResult( WSAStartup( MAKEWORD(2,2), &wsaData ) ); if ( ciResult != NO_ERROR ) { UTIL_LogPrint( ( gmapLANG_CFG["unable_to_start_winsock"] + "\n" ).c_str( ), GetLastErrorString( ) ); // Delete the PID file if( !gstrPID.empty( ) ) { if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) ) UTIL_LogPrint( "Deleting the PID file\n" ); UTIL_DeleteFile( gstrPID.c_str( ) ); } // Close the log if( gpLog ) { if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) ) UTIL_LogPrint( "Closing the log\n" ); fclose( gpLog ); } // Close the access log if( gpAccessLog ) { if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) ) UTIL_LogPrint( "Closing the access log\n" ); fclose( gpAccessLog ); } // Close the error log if( gpErrorLog ) { if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) ) UTIL_LogPrint( "Closing the error log\n" ); fclose( gpErrorLog ); } UTIL_LogPrint( "Tracker Stop\n" ); gmtxMySQL.Destroy( ); gmtxOutput.Destroy( ); return 1; } #endif // start mysql if( gbDebug ) if( gucDebugLevel & DEBUG_BNBT ) UTIL_LogPrint( "Setting MySQL dstate global variables\n" ); if( !( gpMySQL = mysql_init( 0 ) ) ) { UTIL_LogPrint( ( gmapLANG_CFG["bnbt_mysql_error"] + "\n" ).c_str( ), mysql_error( gpMySQL ) ); // Delete the PID file if( !gstrPID.empty( ) ) { if( gbDebug ) if( gucDebugLevel & DEBUG_BNBT ) UTIL_LogPrint( "Deleting the PID file\n" ); UTIL_DeleteFile( gstrPID.c_str( ) ); } // Close the log if( gpLog ) { if( gbDebug ) if( gucDebugLevel & DEBUG_BNBT ) UTIL_LogPrint( "Closing the log\n" ); fclose( gpLog ); } // Close the access log if( gpAccessLog ) { if( gbDebug ) if( gucDebugLevel & DEBUG_BNBT ) UTIL_LogPrint( "Closing the access log\n" ); fclose( gpAccessLog ); } // Close the error log if( gpErrorLog ) { if( gbDebug ) if( gucDebugLevel & DEBUG_BNBT ) UTIL_LogPrint( "Closing the error log\n" ); fclose( gpErrorLog ); } UTIL_LogPrint( "Tracker Stop\n" ); gmtxMySQL.Destroy( ); gmtxOutput.Destroy( ); return 1; } gmapMySQL.clear( ); gmapMySQL[pthread_self( )] = gpMySQL; gstrMySQLHost = CFG_GetString( "mysql_host", string( ) ); gstrMySQLDatabase = CFG_GetString( "mysql_database", "bnbt" ); gstrMySQLUser = CFG_GetString( "mysql_user", string( ) ); gstrMySQLPassword = CFG_GetString( "mysql_password", string( ) ); guiMySQLPort = CFG_GetInt( "mysql_port", 0 ); if( !( mysql_real_connect( gpMySQL, gstrMySQLHost.c_str( ), gstrMySQLUser.c_str( ), gstrMySQLPassword.c_str( ), 0, guiMySQLPort, 0, 0 ) ) ) { UTIL_LogPrint( ( gmapLANG_CFG["bnbt_mysql_error"] + "\n" ).c_str( ), mysql_error( gpMySQL ) ); // Delete the PID file if( !gstrPID.empty( ) ) { if( gbDebug ) if( gucDebugLevel & DEBUG_BNBT ) UTIL_LogPrint( "Deleting the PID file\n" ); UTIL_DeleteFile( gstrPID.c_str( ) ); } // Close the log if( gpLog ) { if( gbDebug ) if( gucDebugLevel & DEBUG_BNBT ) UTIL_LogPrint( "Closing the log\n" ); fclose( gpLog ); } // Close the access log if( gpAccessLog ) { if( gbDebug ) if( gucDebugLevel & DEBUG_BNBT ) UTIL_LogPrint( "Closing the access log\n" ); fclose( gpAccessLog ); } // Close the error log if( gpErrorLog ) { if( gbDebug ) if( gucDebugLevel & DEBUG_BNBT ) UTIL_LogPrint( "Closing the error log\n" ); fclose( gpErrorLog ); } UTIL_LogPrint( "Tracker Stop\n" ); gmtxMySQL.Destroy( ); gmtxOutput.Destroy( ); return 1; } UTIL_LogPrint( ( gmapLANG_CFG["bnbt_mysql_connected"] + "\n" ).c_str( ) ); UTIL_MySQLCreateDatabase( ); if( mysql_select_db( gpMySQL, gstrMySQLDatabase.c_str( ) ) ) { UTIL_LogPrint( ( gmapLANG_CFG["bnbt_mysql_error"] + "\n" ).c_str( ), mysql_error( gpMySQL ) ); // Delete the PID file if( !gstrPID.empty( ) ) { if( gbDebug ) if( gucDebugLevel & DEBUG_BNBT ) UTIL_LogPrint( "Deleting the PID file\n" ); UTIL_DeleteFile( gstrPID.c_str( ) ); } // Close the log if( gpLog ) { if( gbDebug ) if( gucDebugLevel & DEBUG_BNBT ) UTIL_LogPrint( "Closing the log\n" ); fclose( gpLog ); } // Close the access log if( gpAccessLog ) { if( gbDebug ) if( gucDebugLevel & DEBUG_BNBT ) UTIL_LogPrint( "Closing the access log\n" ); fclose( gpAccessLog ); } // Close the error log if( gpErrorLog ) { if( gbDebug ) if( gucDebugLevel & DEBUG_BNBT ) UTIL_LogPrint( "Closing the error log\n" ); fclose( gpErrorLog ); } UTIL_LogPrint( "Tracker Stop\n" ); gmtxMySQL.Destroy( ); gmtxOutput.Destroy( ); return 1; } UTIL_MySQLCreateTables( ); // Create the server if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) ) UTIL_LogPrint( "Creating server\n" ); gpServer = new CServer( ); // // Link // // if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) ) // UTIL_LogPrint( "Creating link client/server\n" ); // gpLink = 0; // gpLinkServer = 0; // if( CFG_GetInt( "bnbt_tlink_server", 0 ) != 0 ) // gpLinkServer = new CLinkServer( ); // else // { // if( !CFG_GetString( "bnbt_tlink_connect", string( ) ).empty( ) ) // { //#ifdef WIN32 // int iLinkThreadResult = (int)_beginthread( ( void (*)(void *) )StartLink, 0, 0 ); // // if( iLinkThreadResult == -1 ) // UTIL_LogPrint( ( gmapLANG_CFG["unable_to_spawn_link_thread_win32"] + "\n" ).c_str( ) ); //#else // pthread_t thread; // // set detached state since we don't need to join with any threads // pthread_attr_t attr; // pthread_attr_init( &attr ); // pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED ); // int iLinkThreadResult = pthread_create( &thread, &attr, ( void * (*)(void *) )StartLink, 0 ); // if( iLinkThreadResult != 0 ) // UTIL_LogPrint( ( gmapLANG_CFG["unable_to_spawn_link_thread"] + "\n" ).c_str( ), strerror( iLinkThreadResult ) ); //#endif // } // } // // HUBLink // // if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) ) // UTIL_LogPrint( "Creating hublink client/server\n" ); // gpHUBLink = 0; // gpHUBLinkServer = 0; // if( CFG_GetInt( "xbnbt_thlink_server", 0 ) != 0 ) // gpHUBLinkServer = new CHUBLinkServer( ); // else // { // if( !CFG_GetString( "xbnbt_thlink_connect", string( ) ).empty( ) ) // { //#ifdef WIN32 // int iHubLinkThreadResult = (int)_beginthread( ( void (*)(void *) )StartHUBLink, 0, 0 ); // // if( iHubLinkThreadResult == -1 ) // UTIL_LogPrint( ( gmapLANG_CFG["unable_to_spawn_hublink_thread_win32"] + "\n" ).c_str( ) ); //#else // pthread_t thread; // // set detached state since we don't need to join with any threads // pthread_attr_t attr; // pthread_attr_init( &attr ); // pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED ); // int iHubLinkThreadResult = pthread_create( &thread, &attr, ( void * (*)(void *) )StartHUBLink, 0 ); // if( iHubLinkThreadResult != 0 ) // UTIL_LogPrint( ( gmapLANG_CFG["unable_to_spawn_hublink_thread"] + "\n" ).c_str( ), strerror( iHubLinkThreadResult ) ); //#endif // } // } // // update loop // if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) ) UTIL_LogPrint( "Entering update loop\n" ); bool bDoUpdate = true; while( bDoUpdate ) { if( gbDebug && ( gucDebugLevel & DEBUG_LOOPS ) && gpServer ) UTIL_LogPrint( "Updating server\n" ); if( gpServer && gpServer->Update( true ) ) { if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) ) UTIL_LogPrint( "Deleting server\n" ); delete gpServer; gpServer = 0; // if( gpLinkServer ) // { // if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) ) // UTIL_LogPrint( "Deleting link server\n" ); // delete gpLinkServer; // gpLinkServer = 0; // } // if( gpHUBLinkServer ) // { // if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) ) // UTIL_LogPrint( "Deleting hublink server\n" ); // delete gpHUBLinkServer; // gpHUBLinkServer = 0; // } if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) ) UTIL_LogPrint( "Exit the update loop\n" ); bDoUpdate = false; } else if( gpServer && guiRestartServerInterval > 0 && GetTime( ) > gulRestartServerNext ) { if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) ) UTIL_LogPrint( "Restarting server\n" ); delete gpServer; gpServer = new CServer( ); gulRestartServerNext = GetTime( ) + guiRestartServerInterval * 3600; } // if( gpLinkServer && gucDebugLevel != 0 ) // { // if( gbDebug && ( gucDebugLevel & DEBUG_LOOPS ) ) // UTIL_LogPrint( "Updating link server\n" ); // gpLinkServer->Update( ); // } // if( gpHUBLinkServer && gucDebugLevel != 0 ) // { // if( gbDebug && ( gucDebugLevel & DEBUG_LOOPS ) ) // UTIL_LogPrint( "Updating hublink server\n" ); // gpHUBLinkServer->Update( ); // } } // // wait for the link or it might make a big mess // // if( gpLink ) // { // if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) ) // UTIL_LogPrint( "Killing link client\n" ); // // gpLink->Kill( ); // } // const unsigned long culStart( GetTime( ) ); // while( gpLink ) // { // UTIL_LogPrint( ( gmapLANG_CFG["wait_link_disconnect"] + "\n" ).c_str( ) ); // MILLISLEEP( 1000 ); // if( GetTime( ) - culStart > 60 ) // { // UTIL_LogPrint( ( gmapLANG_CFG["waited_link_disconnect"] + "\n" ).c_str( ) ); // break; // } // } // // wait for the hub link or it might make a big mess // // if( gpHUBLink ) // { // if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) ) // UTIL_LogPrint( "Killing hublink client\n" ); // gpHUBLink->Kill( ); // } // const unsigned long culStartHUB( GetTime( ) ); // while( gpHUBLink ) // { // UTIL_LogPrint( ( gmapLANG_CFG["wait_hublink_disconnect"] + "\n" ).c_str( ) ); // MILLISLEEP( 1000 ); // if( GetTime( ) - culStartHUB > 60 ) // { // UTIL_LogPrint( ( gmapLANG_CFG["waited_hublink_disconnect"] + "\n" ).c_str( ) ); // break; // } // } // Close the BNBT MySQL database if( gpMySQL ) { if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) ) UTIL_LogPrint( "Closing MySQL dstate integration build\n" ); mysql_close( gpMySQL ); } #ifdef WIN32 // Exit windows sockets if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) ) UTIL_LogPrint( "Closing the windows sockets\n" ); WSACleanup( ); #endif // Delete the PID file if( !gstrPID.empty( ) ) { if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) ) UTIL_LogPrint( "Deleting the PID file\n" ); UTIL_DeleteFile( gstrPID.c_str( ) ); } // Close the log if( gpLog ) { if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) ) UTIL_LogPrint( "Closing the log\n" ); fclose( gpLog ); } // Close the access log if( gpAccessLog ) { if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) ) UTIL_LogPrint( "Closing the access log\n" ); fclose( gpAccessLog ); } // Close the error log if( gpErrorLog ) { if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) ) UTIL_LogPrint( "Closing the error log\n" ); fclose( gpErrorLog ); } UTIL_LogPrint( "Tracker Stop\n" ); gmtxMySQL.Destroy( ); gmtxOutput.Destroy( ); return 0; }
int bnbtmain( ) { gmtxOutput.Initialize( ); srand( time( NULL ) ); giStartTime = time( NULL ); CFG_Open( CFG_FILE ); CFG_SetDefaults( ); CFG_Close( CFG_FILE ); gstrErrorLogFilePattern = CFG_GetString( "bnbt_error_log_file_pattern", "%Y-%m-%de.log" ); gstrErrorLogDir = CFG_GetString( "bnbt_error_log_dir", string( ) ); if( !gstrErrorLogDir.empty( ) && gstrErrorLogDir[gstrErrorLogDir.size( ) - 1] != PATH_SEP ) gstrErrorLogDir += PATH_SEP; gpErrorLog = NULL; gstrAccessLogFilePattern = CFG_GetString( "bnbt_access_log_file_pattern", "%Y-%m-%d.log" ); gstrAccessLogDir = CFG_GetString( "bnbt_access_log_dir", string( ) ); if( !gstrAccessLogDir.empty( ) && gstrAccessLogDir[gstrAccessLogDir.size( ) - 1] != PATH_SEP ) gstrAccessLogDir += PATH_SEP; gpAccessLog = NULL; giErrorLogCount = 0; giAccessLogCount = 0; giFlushInterval = CFG_GetInt( "bnbt_flush_interval", 100 ); gbDebug = CFG_GetInt( "bnbt_debug", 1 ) == 0 ? false : true; giMaxConns = CFG_GetInt( "bnbt_max_conns", 64 ); giMaxRecvSize = CFG_GetInt( "bnbt_max_recv_size", 524288 ); gstrStyle = CFG_GetString( "bnbt_style_sheet", string( ) ); gstrCharSet = CFG_GetString( "bnbt_charset", "iso-8859-1" ); gstrRealm = CFG_GetString( "bnbt_realm", "BNBT" ); // start winsock // TCP window size giSO_RECBUF = CFG_GetInt( "xbnbt_so_recbuf", 128 ) * 1024; giSO_SNDBUF = CFG_GetInt( "xbnbt_so_sndbuf", 128 ) * 1024; #ifdef WIN32 WSADATA wsaData; int iResult = WSAStartup( MAKEWORD(2,2), &wsaData ); if ( iResult != NO_ERROR ) { UTIL_LogPrint( "error - unable to start winsock (error %d)\n", GetLastError( ) ); if( gpAccessLog ) fclose( gpAccessLog ); if( gpErrorLog ) fclose( gpErrorLog ); gmtxOutput.Destroy( ); return 1; } #endif // start mysql #ifdef BNBT_MYSQL if( !( gpMySQL = mysql_init( NULL ) ) ) { UTIL_LogPrint( "mysql error - %s\n", mysql_error( gpMySQL ) ); if( gpAccessLog ) fclose( gpAccessLog ); if( gpErrorLog ) fclose( gpErrorLog ); gmtxOutput.Destroy( ); return 1; } gstrMySQLHost = CFG_GetString( "mysql_host", string( ) ); gstrMySQLDatabase = CFG_GetString( "mysql_database", "bnbt" ); gstrMySQLUser = CFG_GetString( "mysql_user", string( ) ); gstrMySQLPassword = CFG_GetString( "mysql_password", string( ) ); giMySQLPort = CFG_GetInt( "mysql_port", 0 ); if( !( mysql_real_connect( gpMySQL, gstrMySQLHost.c_str( ), gstrMySQLUser.c_str( ), gstrMySQLPassword.c_str( ), gstrMySQLDatabase.c_str( ), giMySQLPort, NULL, 0 ) ) ) { UTIL_LogPrint( "mysql error - %s\n", mysql_error( gpMySQL ) ); if( gpAccessLog ) fclose( gpAccessLog ); if( gpErrorLog ) fclose( gpErrorLog ); gmtxOutput.Destroy( ); return 1; } UTIL_LogPrint( "mysql - connected\n" ); #endif gpServer = new CServer( ); gpLink = NULL; gpLinkServer = NULL; if( CFG_GetInt( "bnbt_tlink_server", 0 ) != 0 ) gpLinkServer = new CLinkServer( ); else { if( !CFG_GetString( "bnbt_tlink_connect", string( ) ).empty( ) ) { #ifdef WIN32 if( _beginthread( ( void (*)(void *) )StartLink, 0, NULL ) == -1 ) UTIL_LogPrint( "error - unable to spawn link thread\n" ); #else pthread_t thread; // set detached state since we don't need to join with any threads pthread_attr_t attr; pthread_attr_init( &attr ); pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED ); int c = pthread_create( &thread, &attr, ( void * (*)(void *) )StartLink, NULL ); if( c != 0 ) UTIL_LogPrint( "error - unable to spawn link thread (error %s)\n", strerror( c ) ); #endif } } while( 1 ) { if( gpServer->Update( true ) ) { delete gpServer; gpServer = NULL; if( gpLinkServer ) { delete gpLinkServer; gpLinkServer = NULL; } break; } if( gpLinkServer ) gpLinkServer->Update( ); } // wait for the link or it might make a big mess if( gpLink ) gpLink->Kill( ); unsigned long iStart = GetTime( ); while( gpLink ) { UTIL_LogPrint( "server - waiting for link to disconnect\n" ); MILLISLEEP( 1000 ); if( GetTime( ) - iStart > 60 ) { UTIL_LogPrint( "server - waited 60 seconds, exiting anyway\n" ); break; } } #ifdef BNBT_MYSQL mysql_close( gpMySQL ); #endif if( gpAccessLog ) fclose( gpAccessLog ); if( gpErrorLog ) fclose( gpErrorLog ); gmtxOutput.Destroy( ); #ifdef WIN32 WSACleanup( ); #endif return 0; }
void CTracker :: serverResponseSignupLilyPOST( struct request_t *pRequest, struct response_t *pResponse, CAtomList *pPost ) { // Set the start time const struct bnbttv btv( UTIL_CurrentTime( ) ); // Verify that the IP is permitted to access the tracker if( m_ucIPBanMode != 0 ) if( IsIPBanned( pRequest, pResponse, btv, gmapLANG_CFG["signup_page"], string( CSS_SIGNUP ), NOT_INDEX ) ) return; string cstrLogin = string( ); string cstrLilyID = string( ); if( pPost ) { // Initialise segment dictionary CAtomDicti *pSegment = 0; CAtom *pDisposition = 0; CAtom *pData = 0; CAtom *pName = 0; CAtom *pFile = 0; // Get the segments from the post vector<CAtom *> vecSegments = pPost->getValue( ); // Loop through the segments for( unsigned long ulCount = 0; ulCount < vecSegments.size( ); ulCount++ ) { // Is the segment a dictionary? if( vecSegments[ulCount]->isDicti( ) ) { // Get the segment dictionary pSegment = (CAtomDicti *)vecSegments[ulCount]; // Get the disposition and the data from the segment dictionary pDisposition = pSegment->getItem( "disposition" ); pData = pSegment->getItem( "data" ); // Did we get a disposition that is a dictionary and has data? if( pDisposition && pDisposition->isDicti( ) && pData ) { // Get the content name from the disposition pName = ( (CAtomDicti *)pDisposition )->getItem( "name" ); // Did we get a content name? if( pName ) { // What is the content name to be tested? string strName = pName->toString( ); if( strName == "us_login") cstrLogin = pData->toString( ); else if( strName == "us_lilyid") cstrLilyID = UTIL_ToLower( pData->toString( ) ); } else { // Output common HTML head HTML_Common_Begin( pRequest, pResponse, gmapLANG_CFG["signup_page"], string( CSS_SIGNUP ), string( ), NOT_INDEX, CODE_400 ); // failed pResponse->strContent += "<p class=\"failed\">" + gmapLANG_CFG["failed"] + "</p>\n"; // Signal a bad request pResponse->strContent += "<p class=\"body_upload\">400 " + gmapLANG_CFG["server_response_400"] + "</p>\n"; // Output common HTML tail HTML_Common_End( pRequest, pResponse, btv, NOT_INDEX, string( CSS_SIGNUP ) ); if( gbDebug ) UTIL_LogPrint( "Login Warning - Bad request (no users name)\n" ); return; } } } } } else { // Output common HTML head HTML_Common_Begin( pRequest, pResponse, gmapLANG_CFG["signup_page"], string( CSS_SIGNUP ), string( ), NOT_INDEX, CODE_400 ); // failed pResponse->strContent += "<p class=\"failed\">" + gmapLANG_CFG["failed"] + "</p>\n"; // Signal a bad request pResponse->strContent += "<p class=\"body_upload\">400 " + gmapLANG_CFG["server_response_400"] + "</p>\n"; // Output common HTML tail HTML_Common_End( pRequest, pResponse, btv, NOT_INDEX, string( CSS_SIGNUP ) ); if( gbDebug ) UTIL_LogPrint( "Upload Warning - Bad request (no post received)\n" ); return; } if( pRequest->user.ucAccess & ACCESS_SIGNUP ) { HTML_Common_Begin( pRequest, pResponse, gmapLANG_CFG["signup_page"], string( CSS_SIGNUP ), string( ), NOT_INDEX, CODE_200 ); if( !cstrLogin.empty( ) && !cstrLilyID.empty( ) ) { // if( cstrLogin[0] == ' ' || cstrLogin[cstrLogin.size( ) - 1] == ' ' || cstrLogin.size( ) > m_uiNameLength ) if( cstrLogin.find( ' ' ) != string :: npos || cstrLogin.find( '.' ) != string :: npos || cstrLogin.find( '%' ) != string :: npos || cstrLogin.find( '&' ) != string :: npos || cstrLilyID.find( ' ' ) != string :: npos || cstrLilyID.find( '.' ) != string :: npos || cstrLilyID.find( '%' ) != string :: npos || cstrLilyID.find( '&' ) != string :: npos || cstrLogin.size( ) > m_uiNameLength ) { // Unable to signup. Your name must be less than " + CAtomInt( m_uiNameLength ).toString( ) + " characters long and it must not start or end with spaces. pResponse->strContent += "<p class=\"signup_failed\">" + UTIL_Xsprintf( gmapLANG_CFG["signup_name_error"].c_str( ), CAtomInt( m_uiNameLength ).toString( ).c_str( ), string( "<a title=\"" + gmapLANG_CFG["navbar_signup"] + "\" href=\"" + RESPONSE_STR_SIGNUP_LILY_HTML + "\">" ).c_str( ), "</a>" ) + "</p>\n\n"; // Output common HTML tail HTML_Common_End( pRequest, pResponse, btv, NOT_INDEX, string( CSS_SIGNUP ) ); return; } time_t tNow = time( 0 ); char pTime[256]; memset( pTime, 0, sizeof( pTime ) / sizeof( char ) ); strftime( pTime, sizeof( pTime ) / sizeof( char ), "%Y %m/%d %H:%M:%S", localtime( &tNow ) ); const string cstrA1( cstrLogin + ":" + gstrRealm + ":" + pTime ); unsigned char szMD5[16]; memset( szMD5, 0, sizeof( szMD5 ) / sizeof( unsigned char ) ); MD5_CTX md5; MD5Init( &md5 ); MD5Update( &md5, (const unsigned char *)cstrA1.c_str( ), (unsigned int)cstrA1.size( ) ); MD5Final( szMD5, &md5 ); const string cstrPass = UTIL_HashToString( string( (char *)szMD5, sizeof( szMD5 ) / sizeof( unsigned char ) ) ).substr( 0, 8 ); const string cstrMail = cstrLilyID + "@bbs.nju.edu.cn"; if( !getUser( cstrLogin, m_ucGuestAccess ).strLogin.empty( ) ) { // Unable to signup. The user \"" + UTIL_RemoveHTML( cstrLogin ) + "\" already exists. pResponse->strContent += "<p class=\"signup_failed\">" + UTIL_Xsprintf( gmapLANG_CFG["signup_exists_error"].c_str( ), UTIL_RemoveHTML( cstrLogin ).c_str( ), string( "<a title=\"" + gmapLANG_CFG["navbar_signup"] + "\" href=\"" + RESPONSE_STR_SIGNUP_LILY_HTML + "\">" ).c_str( ), "</a>" ) + "</p>\n\n"; } else { CMySQLQuery *pQuery = new CMySQLQuery( "SELECT blilyid FROM lily WHERE blilyid=\'" + UTIL_StringToMySQL( cstrLilyID ) + "\'" ); if( pQuery->nextRow( ).size( ) == 1 ) { pResponse->strContent += "<p class=\"signup_failed\">" + UTIL_Xsprintf( gmapLANG_CFG["signup_exists_error_lily"].c_str( ), UTIL_RemoveHTML( cstrLogin ).c_str( ), UTIL_RemoveHTML( cstrLilyID ).c_str( ), string( "<a title=\"" + gmapLANG_CFG["navbar_signup"] + "\" href=\"" + RESPONSE_STR_SIGNUP_LILY_HTML + "\">" ).c_str( ), "</a>" ) + "</p>\n\n"; } else { if( addUser( cstrLogin, cstrPass, m_ucMemberAccess, cstrMail ) ) { CMySQLQuery mq01( "INSERT INTO lily (blilyid,busername,bpassword) VALUES(\'" + UTIL_StringToMySQL( cstrLilyID ) + "\',\'" + UTIL_StringToMySQL( cstrLogin ) + "\',\'" + UTIL_StringToMySQL( cstrPass ) + "\')" ); system( string( "echo \"ID: " + cstrLogin + " Password: "******"\" | mutt -s \"ZiJingBT\" " + cstrMail ).c_str( ) ); // Thanks! You've successfully signed up! pResponse->strContent += "<p class=\"signup_ok\">" + UTIL_Xsprintf( gmapLANG_CFG["signup_success_lily"].c_str( ), UTIL_RemoveHTML( cstrLilyID ).c_str( ), string( "<a title=\"" + gmapLANG_CFG["navbar_signup"] + "\" href=\"" + RESPONSE_STR_LOGIN_HTML + "\">" ).c_str( ), "</a>" ) + "</p>\n\n"; } else pResponse->strContent += "<p class=\"signup_failed\">" + UTIL_Xsprintf( gmapLANG_CFG["users_max_create_fail"].c_str( ), string( "<a title=\"" + gmapLANG_CFG["navbar_users"] + "\" href=\"" + RESPONSE_STR_USERS_HTML + "\">" ).c_str( ), "</a>" ) + "</p>\n"; } delete pQuery; } HTML_Common_End( pRequest, pResponse, btv, NOT_INDEX, string( CSS_SIGNUP ) ); } } else { //Unable to signup. You must fill in all the fields. pResponse->strContent += "<p class=\"signup_failed\">" + UTIL_Xsprintf( gmapLANG_CFG["signup_fields_error"].c_str( ), string( "<a title=\"" + gmapLANG_CFG["navbar_signup"] + "\" href=\"" + RESPONSE_STR_SIGNUP_LILY_HTML + "\">" ).c_str( ), "</a>" ) + "</p>\n\n"; // Output common HTML tail HTML_Common_End( pRequest, pResponse, btv, NOT_INDEX, string( CSS_SIGNUP ) ); return; } }
// The signal catching routine void sigCatcher( int sig ) { if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) ) UTIL_LogPrint( "sigCatcher: reset the signals \n" ); // reset the signal catcher signal( SIGABRT, sigCatcher ); signal( SIGINT, sigCatcher ); signal( SIGTERM, sigCatcher ); #if defined SIGHUP signal( SIGHUP, sigCatcher ); #endif if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) ) UTIL_LogPrint( "sigCatcher: reset the signals completed \n" ); if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) ) { switch( sig ) { case SIGABRT: UTIL_LogPrint( "sigCatcher: caught SIGABRT\n" ); break; case SIGINT: UTIL_LogPrint( "sigCatcher: caught SIGINT\n" ); break; case SIGTERM: UTIL_LogPrint( "sigCatcher: caught SIGTERM\n" ); break; #if defined SIGHUP case SIGHUP: UTIL_LogPrint( "sigCatcher: caught SIGHUP\n" ); break; #endif default: UTIL_LogPrint( "sigCatcher: caught unknown signal (signal %d)\n", sig ); } } if( gpServer ) { if( gpServer->isDying( ) ) { if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) ) UTIL_LogPrint( "sigCatcher: server is dying -> exit\n" ); exit( 1 ); } else { if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) ) UTIL_LogPrint( "sigCatcher: server sending kill\n" ); gpServer->Kill( ); } } else { if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) ) UTIL_LogPrint( "sigCatcher: server closed -> exit\n" ); exit( 1 ); } if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) ) UTIL_LogPrint( "sigCatcher: killing server\n" ); }
CServer :: CServer( ) { m_vecClients.reserve( guiMaxConns ); m_bKill = false; m_uiSocketTimeOut = CFG_GetInt( "socket_timeout", 15 ); m_strBind = CFG_GetString( "bind", string( ) ); m_cCompression = (char)CFG_GetInt( "bnbt_compression_level", 6 ); // clamp compression if( m_cCompression > 9 ) m_cCompression = 9; struct sockaddr_in6 sin; memset( &sin, 0, sizeof( sin ) ); sin.sin6_family = AF_INET6; if( !m_strBind.empty( ) ) { // bind to m_strBind if( gbDebug && ( gucDebugLevel & DEBUG_SERVER ) ) UTIL_LogPrint( "server - binding to %s\n", m_strBind.c_str( ) ); if( inet_pton( AF_INET6, m_strBind.c_str( ), &sin.sin6_addr ) == NULL ) { UTIL_LogPrint( ( gmapLANG_CFG["unable_to_bind"] + "\n" ).c_str( ), m_strBind.c_str( ) ); exit( 1 ); } } else { // bind to all available addresses if( gbDebug && ( gucDebugLevel & DEBUG_SERVER ) ) UTIL_LogPrint( ( gmapLANG_CFG["binding_to_all"] + "\n" ).c_str( ) ); sin.sin6_addr = in6addr_any; } // tphogan - legacy support, check for "port" config entry // by doing this here "port" will always be required // so in fact this isn't entirely legacy support since it'll continue to be used // sin.sin6_len = sizeof(sin); sin.sin6_port = htons( (u_short)CFG_GetInt( "port", 6969 ) ) ; if( sin.sin6_port == 0 ) UTIL_LogPrint( ( gmapLANG_CFG["binding_to_all"] + "\n" ).c_str( ), CAtomInt( CFG_GetInt( "port", 6969 ) ).toString( ).c_str( ) ); else if( !AddListener( sin ) ) UTIL_LogPrint( ( gmapLANG_CFG["unable_to_listen"] + "\n" ).c_str( ), CAtomInt( CFG_GetInt( "port", 6969 ) ).toString( ).c_str( ) ); else UTIL_LogPrint( ( gmapLANG_CFG["listen_on_port"] + "\n" ).c_str( ), CAtomInt( CFG_GetInt( "port", 6969 ) ).toString( ).c_str( ) ); // tphogan - retrieve list of ports from config file for multiport listeners // do we want to support multiple bindings as well? // this code will bind every socket to the same address unsigned char ucPort = 1; string strName = "port" + CAtomInt( ucPort ).toString( ); string strPort = CFG_GetString( strName, string( ) ); while( !strPort.empty( ) ) { sin.sin6_port = htons( (u_short)atoi( strPort.c_str( ) ) ) ; if( sin.sin6_port == 0 ) UTIL_LogPrint( ( gmapLANG_CFG["invalid_ports"] + "\n" ).c_str( ), strPort.c_str( ), strName.c_str( ) ); else if( !AddListener( sin ) ) UTIL_LogPrint( ( gmapLANG_CFG["unable_to_listens"] + "\n" ).c_str( ), strPort.c_str( ), strName.c_str( ) ); else UTIL_LogPrint( ( gmapLANG_CFG["listen_on_ports"] + "\n" ).c_str( ), strPort.c_str( ), strName.c_str( ) ); strName = "port" + CAtomInt( ++ucPort ).toString( ); strPort = CFG_GetString( strName, string( ) ); } // tphogan - we didn't exit on invalid ports above // so make sure we're listening on at least one valid port // however, since "port" is always forced greater than zero in CFG_SetDefaults // this should only happen if a valid port is denied for "port" // for example, address in use or not enough privs for ports < 1024 if( m_vecListeners.empty( ) ) { UTIL_LogPrint( ( gmapLANG_CFG["not_listening"] + "\n" ).c_str( ) ); exit( 1 ); } m_pTracker = new CTracker( ); UTIL_LogPrint( ( gmapLANG_CFG["server_start"] + "\n" ).c_str( ) ); }
bool CServer :: Update( const bool &bBlock ) { if( m_vecClients.size( ) < guiMaxConns ) { // tphogan - check every listener for new connections fd_set fdServer; FD_ZERO( &fdServer ); struct timeval tv; struct sockaddr_in6 adrFrom; int iAddrLen = 0; SOCKET sckClient = 0; for( vector<SOCKET> :: iterator itListener = m_vecListeners.begin( ); itListener != m_vecListeners.end( ); itListener++ ) { FD_CLR( *itListener, &fdServer ); FD_SET( *itListener, &fdServer ); // tphogan - only block on the first listener // this is actually a bit of a hack but it don't feel like doing it "right" :) if( bBlock && itListener == m_vecListeners.begin( ) ) { // block for 100 ms to keep from eating up all cpu time tv.tv_sec = 0; tv.tv_usec = 100000; } else { tv.tv_sec = 0; tv.tv_usec = 0; } #ifdef WIN32 if( select( 1, &fdServer, 0, 0, &tv ) == SOCKET_ERROR ) #else if( select( *itListener + 1, &fdServer, 0, 0, &tv ) == SOCKET_ERROR ) #endif { UTIL_LogPrint( ( gmapLANG_CFG["select_error"] + "\n" ).c_str( ), GetLastErrorString( ) ); FD_CLR( *itListener, &fdServer ); } if( FD_ISSET( *itListener, &fdServer ) !=0 ) { iAddrLen = sizeof( adrFrom ); #ifdef WIN32 sckClient = accept( *itListener, (struct sockaddr *)&adrFrom, &iAddrLen ); if( sckClient == INVALID_SOCKET ) #else sckClient = accept( *itListener, (struct sockaddr *)&adrFrom, (socklen_t *)&iAddrLen ); if( sckClient == INVALID_SOCKET ) #endif UTIL_LogPrint( ( gmapLANG_CFG["accept_error"] + "\n" ).c_str( ), GetLastErrorString( ) ); else m_vecClients.push_back( new CClient( sckClient, adrFrom, m_uiSocketTimeOut, m_cCompression ) ); } } } else { // maximum connections reached // tphogan - reduced from 100 ms to 10 ms // it's very difficult to tell if the backlog is due to legitimate load or hung clients // hung clients don't eat CPU time so the server's CPU usage will skyrocket // but if it's due to load then sleeping for 100 ms is a terrible idea! // someone should take a look at this and rewrite it eventually UTIL_LogPrint( "Server Info - Max. connections reached\n" ); MILLISLEEP( 10 ); } // process the clients for( vector<CClient *> :: iterator itClient = m_vecClients.begin( ); itClient != m_vecClients.end( ); ) { if( (*itClient)->Update( ) ) { delete *itClient; itClient = m_vecClients.erase( itClient ); } else itClient++; } if( m_pTracker ) m_pTracker->Update( ); return m_bKill; }
bool CServer :: AddListener( struct sockaddr_in6 sin ) { SOCKET sckListener; // map protocol name to protocol number struct protoent *pPE; pPE = getprotobyname( "tcp" ); if( pPE == 0 ) { UTIL_LogPrint( ( gmapLANG_CFG["no_tcp_protocol"] + "\n" ).c_str( ), GetLastErrorString( ) ); return false; } // allocate socket sckListener = socket( PF_INET6, SOCK_STREAM, pPE->p_proto ); if( sckListener == INVALID_SOCKET ) { UTIL_LogPrint( ( gmapLANG_CFG["not_allocated_socket"] + "\n" ).c_str( ), GetLastErrorString( ) ); return false; } #ifdef WIN32 const unsigned int cuiOptVal( 1 ); // TCP window size // Send if( setsockopt( sckListener, SOL_SOCKET, SO_SNDBUF, (const char *)&guiSO_SNDBUF, sizeof(guiSO_SNDBUF) ) == SOCKET_ERROR ) UTIL_LogPrint( ( gmapLANG_CFG["no_sndbuf"] + "\n" ).c_str( ), GetLastErrorString( ) ); // Receive if( setsockopt( sckListener, SOL_SOCKET, SO_RCVBUF, (const char *)&guiSO_RECBUF, sizeof(guiSO_RECBUF) ) == SOCKET_ERROR ) UTIL_LogPrint( ( gmapLANG_CFG["no_rcvbuf"] + "\n" ).c_str( ), GetLastErrorString( ) ); // Allows the socket to be bound to an address that is already in use. if( setsockopt( sckListener, SOL_SOCKET, SO_REUSEADDR, (const char *)&cuiOptVal, sizeof( cuiOptVal ) ) == SOCKET_ERROR ) UTIL_LogPrint( ( gmapLANG_CFG["no_reuseaddr"] + "\n" ).c_str( ), GetLastErrorString( ) ); // Naggle's Algorithm if( setsockopt( sckListener, SOL_SOCKET, TCP_NODELAY, (const char *)&gbTCP_NODELAY, sizeof( int ) ) == SOCKET_ERROR ) UTIL_LogPrint( ( gmapLANG_CFG["no_nodelay"] + "\n" ).c_str( ), GetLastErrorString( ) ); // bind socket if( bind( sckListener, (SOCKADDR*)&sin, sizeof( sin ) ) == SOCKET_ERROR ) { UTIL_LogPrint( ( gmapLANG_CFG["unable_to_bind_socket"] + "\n" ).c_str( ), GetLastErrorString( ) ); return false; } #else const unsigned int cuiOptVal( 1 ); #ifdef SO_NOSIGPIPE // Ignore SIGPIPE - FreeBSD if( setsockopt( sckListener, SOL_SOCKET, SO_NOSIGPIPE, (const void *)&cuiOptVal, (socklen_t)sizeof( cuiOptVal ) ) == SOCKET_ERROR ) UTIL_LogPrint( ( gmapLANG_CFG["no_nosigpipe"] + "\n" ).c_str( ), GetLastErrorString( ) ); #endif #ifdef SO_SNDBUF // TCP window size Send if( setsockopt( sckListener, SOL_SOCKET, SO_SNDBUF, (const char *)&guiSO_SNDBUF, (socklen_t)sizeof( guiSO_SNDBUF ) ) == SOCKET_ERROR ) UTIL_LogPrint( ( gmapLANG_CFG["no_sndbuf"] + "\n" ).c_str( ), GetLastErrorString( ) ); #endif #ifdef SO_RCVBUF // TCP window size Receive if( setsockopt( sckListener, SOL_SOCKET, SO_RCVBUF, (const char *)&guiSO_RECBUF, (socklen_t)sizeof( guiSO_RECBUF ) ) == SOCKET_ERROR ) UTIL_LogPrint( ( gmapLANG_CFG["no_rcvbuf"] + "\n" ).c_str( ), GetLastErrorString( ) ); #endif #ifdef SO_REUSEADDR // Allows the socket to be bound to an address that is already in use. if( setsockopt( sckListener, SOL_SOCKET, SO_REUSEADDR, (const void *)&cuiOptVal, (socklen_t)sizeof( cuiOptVal ) ) == SOCKET_ERROR ); UTIL_LogPrint( ( gmapLANG_CFG["no_reuseaddr"] + "\n" ).c_str( ), GetLastErrorString( ) ); #endif #ifdef TCP_NODELAY // Nagle's Algorithm if( setsockopt( sckListener, SOL_SOCKET, TCP_NODELAY, (const char *)&gbTCP_NODELAY, (socklen_t)sizeof( int ) ) == SOCKET_ERROR ) UTIL_LogPrint( ( gmapLANG_CFG["no_nodelay"] + "\n" ).c_str( ), GetLastErrorString( ) ); #endif // bind if( bind( sckListener, (struct sockaddr *)&sin, sizeof( sin ) ) == SOCKET_ERROR ) { UTIL_LogPrint( ( gmapLANG_CFG["unable_to_bind_socket"] + "\n" ).c_str( ), GetLastErrorString( ) ); return false; } #endif // listen on the socket if( listen( sckListener, 1 ) == SOCKET_ERROR ) { UTIL_LogPrint( ( gmapLANG_CFG["unable_to_listen"] + "\n" ).c_str( ), GetLastErrorString( ) ); return false; } // Add the socket to the vector of sockets m_vecListeners.push_back( sckListener ); return true; }
bool CClient :: Update( ) { if( gbDebug && ( gucDebugLevel & DEBUG_CLIENT ) ) UTIL_LogPrint( "client: update start\n" ); if( GetTime( ) > m_ulLast + m_uiTimeOut ) { if( gbDebug && ( gucDebugLevel & DEBUG_CLIENT ) ) UTIL_LogPrint( "client warning: socket timed out (%d s, state(%d), reset(%d))\n", m_uiTimeOut, m_ucState, m_bReset ); return true; } bool bGrabParams = true; bool bGrabHeaders = true; bool bGrabCookies = true; fd_set fdClient; //FD_ZERO( &fdClient ); struct timeval tv; char cCompress = COMPRESS_NONE; char *szAuth = 0; unsigned char *pBuf = 0; unsigned char *pNextIn = 0; unsigned char szMD5[16]; string :: size_type iNewLine = 0; string :: size_type iDoubleNewLine = 0; string :: size_type iMethodEnd = 0; string :: size_type iParamsStart = 0; string :: size_type iURLEnd = 0; string :: size_type iWhite = 0; string :: size_type iSplit = 0; string :: size_type iEnd = 0; string strAuthorization = string( ); string strContentLength = string( ); string strCookies = string( ); string strLogin = string( ); string strMD5 = string( ); string strRequest = string( ); string strTemp = string( ); string strType = string( ); string strBase64 = string( ); string strAuth = string( ); string strPass = string( ); string strA1 = string( ); string strAcceptEncoding = string( ); string strKey = string( ); string strValue = string( ); int iRecv = 0; int iSend = 0; int windowBits = 0; int iResult = 0; unsigned int uiSize = 0; switch( m_ucState ) { case CS_RECVHEADERS : if( gbDebug && ( gucDebugLevel & DEBUG_CLIENT ) ) UTIL_LogPrint( "client: receive headers\n" ); FD_ZERO( &fdClient ); //FD_CLR( m_sckClient, &fdClient ); FD_SET( m_sckClient, &fdClient ); tv.tv_sec = 0; tv.tv_usec = 0; #ifdef WIN32 if( select( 1, &fdClient, 0, 0, &tv ) == SOCKET_ERROR ) #else if( select( m_sckClient + 1, &fdClient, 0, 0, &tv ) == SOCKET_ERROR ) #endif { UTIL_LogPrint( "client error: select error headers (error %s)\n", GetLastErrorString( ) ); return true; } if( FD_ISSET( m_sckClient, &fdClient ) ) { m_ulLast = GetTime( ); memset( gpBuf, 0, sizeof(gpBuf) / sizeof(char) ); iRecv = recv( m_sckClient, gpBuf, sizeof(gpBuf), 0 ); if( iRecv == SOCKET_ERROR && GetLastError( ) != EWOULDBLOCK ) { if( gbDebug && ( gucDebugLevel & DEBUG_CLIENT ) ) UTIL_LogPrint( "client error: receive headers error (error %s)\n", GetLastErrorString( ) ); else if( GetLastError( ) != EPIPE && GetLastError( ) != ECONNRESET ) UTIL_LogPrint( "client error: receive headers error (error %s)\n", GetLastErrorString( ) ); return true; } else if( iRecv == 0 ) { if( gbDebug && ( gucDebugLevel & DEBUG_CLIENT ) ) UTIL_LogPrint( "client error: receive headers returned 0\n" ); return true; } else if( iRecv > 0 ) { m_strReceiveBuf += string( gpBuf, iRecv ); if( m_strReceiveBuf.size( ) > guiMaxRecvSize ) { UTIL_LogPrint( "client error: exceeded max receive header size\n" ); return true; } gtXStats.tcp.iRecv += iRecv; } else { UTIL_LogPrint( "client error: receive header returned garbage\n" ); return true; } } if( m_strReceiveBuf.find( C_STR_DOUBLE_NEWLINE ) != string :: npos ) m_ucState = CS_PROCESSHEADERS; else break; case CS_PROCESSHEADERS: if( gbDebug && ( gucDebugLevel & DEBUG_CLIENT ) ) UTIL_LogPrint( "client: process headers\n" ); // grab method iMethodEnd = m_strReceiveBuf.find( C_STR_WSPACE ); if( iMethodEnd == string :: npos ) { UTIL_LogPrint( "client error: malformed HTTP request (can't find method)\n" ); return true; } rqst.strMethod = m_strReceiveBuf.substr( 0, iMethodEnd ); // grab url strTemp = m_strReceiveBuf.substr( iMethodEnd + 1 ); iURLEnd = strTemp.find( C_STR_WSPACE ); if( iURLEnd == string :: npos ) { UTIL_LogPrint( "client error: malformed HTTP request (can't find URL)\n" ); return true; } strTemp = strTemp.substr( 0, iURLEnd ); iParamsStart = strTemp.find( C_STR_ITEMQU ); if( iParamsStart == string :: npos ) { rqst.strURL = strTemp; rqst.hasQuery = false; } else { rqst.strURL = strTemp.substr( 0, iParamsStart ); rqst.hasQuery = true; } // grab params if( iParamsStart != string :: npos ) { strTemp = strTemp.substr( iParamsStart + 1 ); rqst.hasQuery = true; iSplit = 0; iEnd = 0; strKey = string( ); strValue = string( ); bGrabParams = true; while( bGrabParams ) { iSplit = strTemp.find( C_STR_ITEMEQ ); iEnd = strTemp.find( C_STR_ITEMAND ); if( iSplit == string :: npos ) { UTIL_LogPrint( "client warning: malformed HTTP request (found param key without value)\n" ); bGrabParams = false; } strKey = UTIL_EscapedToString( strTemp.substr( 0, iSplit ) ); strValue = UTIL_EscapedToString( strTemp.substr( iSplit + 1, iEnd - iSplit - 1 ) ); // multimap for scrape, regular map for everything else if ( rqst.strURL == RESPONSE_STR_SCRAPE ) rqst.multiParams.insert( pair<string,string>( strKey, strValue ) ); else rqst.mapParams.insert( pair<string, string>( strKey, strValue ) ); strTemp = strTemp.substr( iEnd + 1, strTemp.size( ) - iEnd - 1 ); if( iEnd == string :: npos ) bGrabParams = false; } } // grab headers iNewLine = m_strReceiveBuf.find( C_STR_NEWLINE ); iDoubleNewLine = m_strReceiveBuf.find( C_STR_DOUBLE_NEWLINE ); if( iNewLine != iDoubleNewLine ) { strTemp = m_strReceiveBuf.substr( iNewLine + ( sizeof(C_STR_NEWLINE) - 1 ), iDoubleNewLine - iNewLine - ( sizeof(C_STR_NEWLINE) - 1 ) ); iSplit = 0; iEnd = 0; strKey = string( ); strValue = string( ); bGrabHeaders = true; while( bGrabHeaders ) { iSplit = strTemp.find( C_STR_COLON ); iEnd = strTemp.find( C_STR_NEWLINE ); // http://www.addict3d.org/index.php?page=viewarticle&type=security&ID=4861 if( iSplit == string :: npos || iSplit == 0 ) { UTIL_LogPrint( "client warning: malformed HTTP request (bad header)\n" ); bGrabHeaders = false; } strKey = strTemp.substr( 0, iSplit ); strValue = strTemp.substr( iSplit + ( sizeof(": ") - 1 ), iEnd - iSplit - ( sizeof(C_STR_NEWLINE) - 1 ) ); rqst.mapHeaders.insert( pair<string, string>( strKey, strValue ) ); strTemp = strTemp.substr( iEnd + ( sizeof(C_STR_NEWLINE) - 1 ) ); if( iEnd == string :: npos ) bGrabHeaders = false; } } // grab cookies strCookies = rqst.mapHeaders["Cookie"]; if( !strCookies.empty( ) ) { iWhite = 0; iSplit = 0; iEnd = 0; strKey = string( ); strValue = string( ); bGrabCookies = true; while( bGrabCookies ) { iWhite = strCookies.find_first_not_of( C_STR_WSPACE ); if( iWhite != string :: npos ) strCookies = strCookies.substr( iWhite ); iSplit = strCookies.find( C_STR_ITEMEQ ); iEnd = strCookies.find( C_STR_SEMICOLON ); if( iSplit == string :: npos ) { UTIL_LogPrint( "client warning: malformed HTTP request (found cookie key without value)\n" ); bGrabCookies = false; } strKey = UTIL_EscapedToString( strCookies.substr( 0, iSplit ) ); strValue = UTIL_EscapedToString( strCookies.substr( iSplit + 1, iEnd - iSplit - 1 ) ); // strip quotes if( strValue.size( ) > 1 && strValue[0] == CHAR_QUOTE ) strValue = strValue.substr( 1, strValue.size( ) - 2 ); rqst.mapCookies.insert( pair<string, string>( strKey, strValue ) ); strCookies = strCookies.substr( iEnd + 1, strCookies.size( ) - iEnd - 1 ); if( iEnd == string :: npos ) bGrabCookies = false; } } // grab authentication strLogin = rqst.mapCookies["login"]; strMD5 = rqst.mapCookies["md5"]; strAuthorization = rqst.mapHeaders["Authorization"]; // if( ( !strAuthorization.empty( ) && strLogout != "1" ) || ( !strLogin.empty( ) ) ) if( !strAuthorization.empty( ) ) { iWhite = strAuthorization.find( C_STR_WSPACE ); if( iWhite != string :: npos ) { strType = strAuthorization.substr( 0, iWhite ); strBase64 = strAuthorization.substr( iWhite + 1 ); if( strType == "Basic" ) { szAuth = b64decode( strBase64.c_str( ) ); if( szAuth ) { strAuth = szAuth; free( szAuth ); iSplit = strAuth.find( C_STR_COLON ); if( iSplit != string :: npos ) { strLogin = strAuth.substr( 0, iSplit ); strPass = strAuth.substr( iSplit + 1 ); #if defined ( XBNBT_MYSQL ) // XBNBT MySQL Users Integration if( gbMySQLUsersOverrideUsers ) { CMD5 md5( ( const char* )strPass.c_str( ) ); strMD5 = md5.getMD5Digest( ); } else { #endif // Original code // calculate md5 hash of A1 strA1 = strLogin + C_STR_COLON + gstrRealm + C_STR_COLON + strPass; memset( szMD5, 0, sizeof(szMD5) / sizeof(unsigned char) ); MD5_CTX md5; MD5Init( &md5 ); MD5Update( &md5, (const unsigned char *)strA1.c_str( ), (unsigned int)strA1.size( ) ); MD5Final( szMD5, &md5 ); strMD5 = string( (char *)szMD5, sizeof(szMD5) / sizeof(unsigned char) ); #if defined ( XBNBT_MYSQL ) } #endif } } } } } // if ( strOldLogin.empty( ) ) // { // if ( !strLogin.empty( ) ) // UTIL_LogPrint( "NewLogin: (%s)\n", strLogin.c_str( ) ); // rqst.user = gpServer->getTracker( )->checkUser( strOldLogin, strOldMD5 ); // if ( strLogout != "1" ) // if ( !strLogin.empty( ) ) rqst.user = gpServer->getTracker( )->checkUser( strLogin, strMD5 ); // else // rqst.user = gpServer->getTracker( )->checkUser( strOldLogin, strOldMD5 ); // } // } // else // { // rqst.user.strLogin.erase( ); // rqst.user.strLowerLogin.erase( ); // rqst.user.strMD5.erase( ); // rqst.user.strMail.erase( ); // rqst.user.strLowerMail.erase( ); // rqst.user.strCreated.erase( ); // rqst.user.ucAccess = 0; // } if( rqst.strMethod == "POST" ) m_ucState = CS_RECVBODY; else { m_ucState = CS_MAKERESPONSE; break; } case CS_RECVBODY: if( gbDebug && ( gucDebugLevel & DEBUG_CLIENT ) ) UTIL_LogPrint( "client: receive body\n" ); strContentLength = rqst.mapHeaders["Content-Length"]; if( strContentLength.empty( ) ) { UTIL_LogPrint( "client error: malformed HTTP request (no Content-Length with POST)\n" ); return true; } FD_ZERO( &fdClient ); //FD_CLR( m_sckClient, &fdClient ); FD_SET( m_sckClient, &fdClient ); tv.tv_sec = 0; tv.tv_usec = 0; #ifdef WIN32 if( select( 1, &fdClient, 0, 0, &tv ) == SOCKET_ERROR ) #else if( select( m_sckClient + 1, &fdClient, 0, 0, &tv ) == SOCKET_ERROR ) #endif { UTIL_LogPrint( "client error: select error body (error %s)\n", GetLastErrorString( ) ); return true; } if( FD_ISSET( m_sckClient, &fdClient ) ) { m_ulLast = GetTime( ); memset( gpBuf, 0, sizeof(gpBuf) / sizeof(char) ); iRecv = recv( m_sckClient, gpBuf, sizeof(gpBuf), 0 ); if( iRecv == SOCKET_ERROR && GetLastError( ) != EWOULDBLOCK ) { if( gbDebug && ( gucDebugLevel & DEBUG_CLIENT ) ) UTIL_LogPrint( "client error: receive body error (error %s)\n", GetLastErrorString( ) ); else if( GetLastError( ) != EPIPE && GetLastError( ) != ECONNRESET ) UTIL_LogPrint( "client error: receive body error (error %s)\n", GetLastErrorString( ) ); return true; } else if( iRecv == 0 ) { UTIL_LogPrint( "client error: receive body returned 0\n" ); return true; } else if( iRecv > 0 ) { m_strReceiveBuf += string( gpBuf, iRecv ); if( m_strReceiveBuf.size( ) > guiMaxRecvSize ) { UTIL_LogPrint( "client error: exceeded max receive body size\n" ); return true; } gtXStats.tcp.iRecv += iRecv; } else { UTIL_LogPrint( "client error: receive body returned garbage\n" ); return true; } } if( m_strReceiveBuf.size( ) >= m_strReceiveBuf.find( C_STR_DOUBLE_NEWLINE ) + ( sizeof(C_STR_DOUBLE_NEWLINE) - 1 ) + atol( strContentLength.c_str( ) ) ) m_ucState = CS_MAKERESPONSE; else break; case CS_MAKERESPONSE: if( gbDebug ) UTIL_LogPrint( "client - make response\n" ); if( rqst.strMethod == "GET" ) gpServer->getTracker( )->serverResponseGET( &rqst, &rsp ); else if( rqst.strMethod == "POST" ) { CAtomList *pPost = UTIL_DecodeHTTPPost( m_strReceiveBuf ); gpServer->getTracker( )->serverResponsePOST( &rqst, &rsp, pPost ); if( pPost ) delete pPost; } else rsp.strCode = "400 Bad Request"; // compress cCompress = COMPRESS_NONE; if( rsp.bCompressOK && m_cCompression > 0 ) { strAcceptEncoding = UTIL_ToLower( rqst.mapHeaders["Accept-Encoding"] ); if( strAcceptEncoding.find( "gzip" ) != string :: npos ) cCompress = COMPRESS_GZIP; else if( strAcceptEncoding.find( "deflate" ) != string :: npos ) cCompress = COMPRESS_DEFLATE; } if( !rsp.strContent.empty( ) && cCompress != COMPRESS_NONE ) { // allocate avail_in * 1.001 + 18 bytes (12 + 6 for gzip) uiSize = (unsigned int)( rsp.strContent.size( ) * 1.001 + 18 ); pBuf = new unsigned char[uiSize]; memset( pBuf, 0, sizeof(pBuf) / sizeof(unsigned char) ); z_stream_s zCompress; //unsigned char pNextIn = new unsigned char[uiSize]; memset( pNextIn, 0, sizeof(pNextIn) / sizeof(unsigned char) ); snprintf( (char *)pNextIn, uiSize / sizeof(unsigned char), "%s", rsp.strContent.c_str( ) ); zCompress.next_in = pNextIn; zCompress.avail_in = (unsigned int)rsp.strContent.size( ); zCompress.next_out = pBuf; zCompress.avail_out = uiSize; zCompress.zalloc = (alloc_func)0; zCompress.zfree = (free_func)0; zCompress.opaque = (voidpf)0; zCompress.total_in = 0; zCompress.total_out = 0; windowBits = 15; if( cCompress == COMPRESS_GZIP ) windowBits = 31; iResult = deflateInit2( &zCompress, m_cCompression, Z_DEFLATED, windowBits, 8, Z_DEFAULT_STRATEGY ); if( iResult == Z_OK ) { iResult = deflate( &zCompress, Z_FINISH ); if( iResult == Z_STREAM_END ) { if( zCompress.total_in > zCompress.total_out ) { if( gbDebug ) UTIL_LogPrint( "client: (zlib) compressed %lu bytes to %lu bytes\n", zCompress.total_in, zCompress.total_out ); if( cCompress == COMPRESS_GZIP ) rsp.mapHeaders.insert( pair<string, string>( "Content-Encoding", "gzip" ) ); else rsp.mapHeaders.insert( pair<string, string>( "Content-Encoding", "deflate" ) ); rsp.strContent = string( (char *)pBuf, zCompress.total_out ); } deflateEnd( &zCompress ); delete [] pBuf; } else { if( iResult != Z_OK ) UTIL_LogPrint( "client warning: (zlib) deflate error (%d) on \"%s\", in = %u, sending raw\n", iResult, rqst.strURL.c_str( ), rsp.strContent.size( ) ); deflateEnd( &zCompress ); delete [] pBuf; } } else { UTIL_LogPrint( "client warning: (zlib) deflateInit2 error (%d), sending raw\n", iResult ); delete [] pBuf; } delete [] pNextIn; } // keep alive if( UTIL_ToLower( rqst.mapHeaders["Connection"] ) == "keep-alive" ) { m_bKeepAlive = true; rsp.mapHeaders.insert( pair<string, string>( "Connection", "Keep-Alive" ) ); rsp.mapHeaders.insert( pair<string, string>( "Keep-Alive", CAtomInt( m_uiTimeOut - 1 ).toString( ) ) ); } else { m_bKeepAlive = false; rsp.mapHeaders.insert( pair<string, string>( "Connection", "Close" ) ); } rsp.mapHeaders.insert( pair<string, string>( "Content-Length", CAtomLong( rsp.strContent.size( ) ).toString( ) ) ); // access log strRequest = string( ); iNewLine = m_strReceiveBuf.find( C_STR_NEWLINE ); if( iNewLine != string :: npos ) strRequest = m_strReceiveBuf.substr( 0, iNewLine ); UTIL_AccessLogPrint( inet_ntoa( rqst.sin.sin_addr ), rqst.user.strLogin, strRequest, atoi( rsp.strCode.substr( 0, 3 ).c_str( ) ), (int)rsp.strContent.size( ) ); // compose send buffer // fix for \r\n issues with non-tolerant HTTP client implementations - DWK m_strSendBuf += "HTTP/1.1 " + rsp.strCode + "\r\n"; for( multimap<string, string> :: iterator it = rsp.mapHeaders.begin( ); it != rsp.mapHeaders.end( ); it++ ) m_strSendBuf += (*it).first + ": " + (*it).second + "\r\n"; m_strSendBuf += "\r\n"; m_strSendBuf += rsp.strContent; m_ucState = CS_SEND; case CS_SEND: if( gbDebug ) UTIL_LogPrint( "client - send\n" ); FD_ZERO( &fdClient ); //FD_CLR( m_sckClient, &fdClient ); FD_SET( m_sckClient, &fdClient ); tv.tv_sec = 0; tv.tv_usec = 0; #ifdef WIN32 if( select( 1, 0, &fdClient, 0, &tv ) == SOCKET_ERROR ) #else if( select( m_sckClient + 1, 0, &fdClient, 0, &tv ) == SOCKET_ERROR ) #endif { UTIL_LogPrint( "client error: select error send (error %s)\n", GetLastErrorString( ) ); return true; } if( FD_ISSET( m_sckClient, &fdClient ) ) { m_ulLast = GetTime( ); iSend = send( m_sckClient, m_strSendBuf.c_str( ), (int)m_strSendBuf.size( ), MSG_NOSIGNAL ); if( iSend == SOCKET_ERROR && GetLastError( ) != EWOULDBLOCK ) { if( gbDebug && ( gucDebugLevel & DEBUG_CLIENT ) ) UTIL_LogPrint( "client error: send error (error %s)\n", GetLastErrorString( ) ); else if( GetLastError( ) != EPIPE && GetLastError( ) != ECONNRESET ) UTIL_LogPrint( "client error: send error (error %s)\n", GetLastErrorString( ) ); return true; } else if( iSend == 0 ) { UTIL_LogPrint( "client error: send returned 0\n" ); return true; } else if( iSend > 0 ) { m_strSendBuf = m_strSendBuf.substr( iSend ); gtXStats.tcp.iSend += iSend; if( m_strSendBuf.empty( ) ) { if( m_bKeepAlive ) { if( gbDebug && ( gucDebugLevel & DEBUG_CLIENT ) ) UTIL_LogPrint( "client: keep alive\n" ); Reset( ); return false; } else return true; } } else { UTIL_LogPrint( "client error: send returned garbage\n" ); return true; } } break; default: UTIL_LogPrint( "client error: unknown state\n" ); } if( gbDebug && ( gucDebugLevel & DEBUG_CLIENT ) ) UTIL_LogPrint( "client: update end\n" ); m_bReset = false; return false; }
int bnbtmain( ) { gmtxOutput.Initialize( ); srand( time( NULL ) ); giStartTime = time( NULL ); CFG_Open( CFG_FILE ); CFG_SetDefaults( ); CFG_Close( CFG_FILE ); gstrErrorLogDir = CFG_GetString( "bnbt_error_log_dir", string( ) ); if( !gstrErrorLogDir.empty( ) && gstrErrorLogDir[gstrErrorLogDir.size( ) - 1] != PATH_SEP ) gstrErrorLogDir += PATH_SEP; gpErrorLog = NULL; gstrAccessLogDir = CFG_GetString( "bnbt_access_log_dir", string( ) ); if( !gstrAccessLogDir.empty( ) && gstrAccessLogDir[gstrAccessLogDir.size( ) - 1] != PATH_SEP ) gstrAccessLogDir += PATH_SEP; gpAccessLog = NULL; giErrorLogCount = 0; giAccessLogCount = 0; giFlushInterval = CFG_GetInt( "bnbt_flush_interval", 100 ); gbDebug = CFG_GetInt( "bnbt_debug", 1 ) == 0 ? false : true; giMaxConns = CFG_GetInt( "bnbt_max_conns", 64 ); gstrStyle = CFG_GetString( "bnbt_style_sheet", string( ) ); gstrCharSet = CFG_GetString( "bnbt_charset", "iso-8859-1" ); gstrRealm = CFG_GetString( "bnbt_realm", "BNBT" ); // The Trinity Edition - Addition Begins // Sets the value for the Custom NT Service Name variable gstrNTServiceName = CFG_GetString( "trinity_nt_service_name", "BNBT Service" ); // Sets the "bnbt_alt_signup_url" value gstrAltSignupURL = CFG_GetString( "bnbt_alt_signup_url", string( ) ); // Sets the "bnbt_tracker_title" value gstrTrackerTitle = CFG_GetString( "bnbt_tracker_title", string( ) ); // Sets the "bnbt_external_js" value gstrExternalJavascript = CFG_GetString( "bnbt_external_js", string( ) ); // --------------------------------------- End of Addition // start winsock #ifdef WIN32 WSADATA wsadata; if( WSAStartup( MAKEWORD( 2, 0 ), &wsadata ) != 0 ) { UTIL_LogPrint( "error - unable to start winsock (error %d)\n", GetLastError( ) ); if( gpAccessLog ) fclose( gpAccessLog ); if( gpErrorLog ) fclose( gpErrorLog ); gmtxOutput.Destroy( ); return 1; } #endif gpServer = new CServer( ); gpLink = NULL; gpLinkServer = NULL; if( CFG_GetInt( "bnbt_tlink_server", 0 ) != 0 ) gpLinkServer = new CLinkServer( ); else { if( !CFG_GetString( "bnbt_tlink_connect", string( ) ).empty( ) ) { #ifdef WIN32 if( _beginthread( ( void (*)(void *) )StartLink, 0, NULL ) == -1 ) UTIL_LogPrint( "error - unable to spawn link thread\n" ); #else pthread_t thread; // set detached state since we don't need to join with any threads pthread_attr_t attr; pthread_attr_init( &attr ); pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED ); int c = pthread_create( &thread, &attr, ( void * (*)(void *) )StartLink, NULL ); if( c != 0 ) UTIL_LogPrint( "error - unable to spawn link thread (error %s)\n", strerror( c ) ); #endif } } while( 1 ) { if( gpServer->Update( true ) ) { delete gpServer; gpServer = NULL; if( gpLinkServer ) { delete gpLinkServer; gpLinkServer = NULL; } break; } if( gpLinkServer ) gpLinkServer->Update( ); } // wait for the link or it might make a big mess if( gpLink ) gpLink->Kill( ); unsigned long iStart = GetTime( ); while( gpLink ) { UTIL_LogPrint( "server - waiting for link to disconnect\n" ); MILLISLEEP( 1000 ); if( GetTime( ) - iStart > 60 ) { UTIL_LogPrint( "server - waited 60 seconds, exiting anyway\n" ); break; } } if( gpAccessLog ) fclose( gpAccessLog ); if( gpErrorLog ) fclose( gpErrorLog ); gmtxOutput.Destroy( ); #ifdef WIN32 WSACleanup( ); #endif return 0; }
inline CAtomList *UTIL_DecodeHTTPPost( const string &cstrPost ) { // find the boundary string :: size_type iBoundary = cstrPost.find( C_STR_BOUNDARY ); if( iBoundary == string :: npos ) return 0; iBoundary += ( sizeof(C_STR_BOUNDARY) - 1 ); string strBoundary = cstrPost.substr( iBoundary ); const string :: size_type ciBoundEnd( strBoundary.find( C_STR_NEWLINE ) ); if( ciBoundEnd == string :: npos ) return 0; strBoundary = strBoundary.substr( 0, ciBoundEnd ); // strBoundary now contains the boundary string :: size_type iContent = cstrPost.find( C_STR_DOUBLE_NEWLINE ); if( iContent == string :: npos ) return 0; iContent += ( sizeof(C_STR_DOUBLE_NEWLINE) - 1 ); const string cstrContent( cstrPost.substr( iContent ) ); // decode CAtomList *pList = new CAtomList( ); CAtomDicti *pSegment = 0; string :: size_type iSegStart = 0; string :: size_type iSegEnd = 0; string :: size_type iDispPrev = 0; string :: size_type iDispPos = 0; CAtomDicti *pDisp = 0; string strSeg = string( ); string strDisp = string( ); string :: size_type iDispStart = 0; string :: size_type iDispEnd = 0; string strCurr = string( ); string :: size_type iSplit = 0; string :: size_type iKeyStart = 0; string strKey = string( ); string strValue = string( ); string :: size_type iDataStart = 0; bool bDoSegmentLoop = true; while( bDoSegmentLoop ) { // segment start iSegStart = cstrContent.find( strBoundary, iSegStart ); if( iSegStart == string :: npos ) return pList; iSegStart += strBoundary.size( ); if( cstrContent.substr( iSegStart, 2 ) == C_STR_SEGSTART ) return pList; iSegStart += ( sizeof(C_STR_SEGSTART) - 1 ); // segment end iSegEnd = cstrContent.find( strBoundary, iSegStart ); if( iSegEnd == string :: npos ) { UTIL_LogPrint( string( gmapLANG_CFG["decode_http_post_end"] + "\n" ).c_str( ) ); delete pList; pList = 0; return 0; } iSegEnd -= ( sizeof(C_STR_SEGEND) - 1 ); // found segment pSegment = new CAtomDicti( ); pList->addItem( pSegment ); // this could do with some serious optimizing... strSeg = cstrContent.substr( iSegStart, iSegEnd - iSegStart ); iDispStart = strSeg.find( C_STR_DISPSTART ); if( iDispStart == string :: npos ) { UTIL_LogPrint( string( gmapLANG_CFG["decode_http_post_notfound"] + "\n" ).c_str( ) ); delete pList; pList = 0; return 0; } iDispStart += ( sizeof(C_STR_DISPSTART) - 1 ); iDispEnd = strSeg.find( C_STR_NEWLINE, iDispStart ); if( iDispEnd == string :: npos ) { UTIL_LogPrint( string( gmapLANG_CFG["decode_http_post_disposition"] + "\n" ).c_str( ) ); delete pList; pList = 0; return 0; } strDisp = strSeg.substr( iDispStart, iDispEnd - iDispStart ); iDispPrev = 0; iDispPos = 0; pDisp = new CAtomDicti( ); pSegment->setItem( "disposition", pDisp ); bool bDoItemLoop = true; while( bDoItemLoop ) { // assume a semicolon indicates the end of the item and will never appear inside the item (probably a bad assumption) iDispPrev = iDispPos; iDispPos = strDisp.find( C_STR_ITEMEND, iDispPos ); if( iDispPos == string :: npos ) { // decode last item iDispPos = strDisp.size( ); } strCurr = strDisp.substr( iDispPrev, iDispPos - iDispPrev ); iSplit = strCurr.find( C_STR_ITEMEQ ); if( iSplit == string :: npos ) { // found a key without value, i.e. "form-data", useless so ignore it if( iDispPos == strDisp.size( ) ) break; // + strlen( ";" ) iDispPos++; continue; } // strip whitespace iKeyStart = strCurr.find_first_not_of( C_STR_WSPACE ); if( iKeyStart == string :: npos || iKeyStart > iSplit ) { UTIL_LogPrint( string( gmapLANG_CFG["decode_http_post_disposition"] + "\n" ).c_str( ) ); delete pList; pList = 0; return 0; } strKey = strCurr.substr( iKeyStart, iSplit - iKeyStart ); strValue = strCurr.substr( iSplit + 1 ); // strip quotes if( strValue.size( ) > 1 && strValue[0] == CHAR_QUOTE ) strValue = strValue.substr( 1, strValue.size( ) - 2 ); pDisp->setItem( strKey, new CAtomString( strValue ) ); if( iDispPos == strDisp.size( ) ) bDoItemLoop = false; // + strlen( ";" ) iDispPos++; } // data iDataStart = strSeg.find( C_STR_DOUBLE_NEWLINE ); if( iDataStart == string :: npos ) { UTIL_LogPrint( string( gmapLANG_CFG["decode_http_post_segment"] + "\n" ).c_str( ) ); delete pList; pList = 0; return 0; } iDataStart += ( sizeof(C_STR_DOUBLE_NEWLINE) - 1 ); pSegment->setItem( "data", new CAtomString( strSeg.substr( iDataStart ) ) ); } // this should never happen, so who cares delete pList; pList = 0; return 0; }