18 #include "clientbase.h"
19 #include "compressionbase.h"
20 #include "compressionzlib.h"
21 #include "connectionbase.h"
22 #include "connectionlistener.h"
23 #include "connectiontcpclient.h"
26 #include "eventhandler.h"
29 #include "iqhandler.h"
31 #include "loghandler.h"
34 #include "messagehandler.h"
35 #include "messagesessionhandler.h"
36 #include "mucinvitationhandler.h"
38 #include "mutexguard.h"
40 #include "presencehandler.h"
41 #include "rosterlistener.h"
42 #include "stanzaextensionfactory.h"
44 #include "subscription.h"
45 #include "subscriptionhandler.h"
47 #include "taghandler.h"
49 #include "tlsdefault.h"
64 #if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
67 # ifndef SecureZeroMemory
68 # define SecureZeroMemory(p,s) RtlFillMemory((p),(s),0)
77 ClientBase::Ping::Ping()
82 ClientBase::Ping::~Ping()
86 const std::string& ClientBase::Ping::filterString()
const
88 static const std::string filter =
"/iq/ping[@xmlns='" +
XMLNS_XMPP_PING +
"']";
95 : m_connection( 0 ), m_encryption( 0 ), m_compression( 0 ), m_disco( 0 ), m_namespace( ns ),
96 m_xmllang(
"en" ), m_server( server ), m_compressionActive( false ), m_encryptionActive( false ),
97 m_compress( true ), m_authed( false ), m_block( false ), m_sasl( true ), m_tls(
TLSOptional ), m_port( port ),
98 m_availableSaslMechs(
SaslMechAll ), m_smContext( CtxSMInvalid ), m_smHandled( 0 ),
99 m_statisticsHandler( 0 ), m_mucInvitationHandler( 0 ),
100 m_messageSessionHandlerChat( 0 ), m_messageSessionHandlerGroupchat( 0 ),
101 m_messageSessionHandlerHeadline( 0 ), m_messageSessionHandlerNormal( 0 ),
104 m_selectedSaslMech(
SaslMechNone ), m_customConnection( false ),
105 m_uniqueBaseId( (unsigned int)( ( (unsigned long long)time( 0 ) & 0xFFFF ) << 16 ) | ( ( (unsigned long long) & m_nextId ) & 0xFFFF ) ),
112 const std::string& server,
int port )
113 : m_connection( 0 ), m_encryption( 0 ), m_compression( 0 ), m_disco( 0 ), m_namespace( ns ),
114 m_password( password ),
115 m_xmllang(
"en" ), m_server( server ), m_compressionActive( false ), m_encryptionActive( false ),
116 m_compress( true ), m_authed( false ), m_block( false ), m_sasl( true ), m_tls(
TLSOptional ),
117 m_port( port ), m_availableSaslMechs(
SaslMechAll ), m_smContext( CtxSMInvalid ), m_smHandled( 0 ),
118 m_statisticsHandler( 0 ), m_mucInvitationHandler( 0 ),
119 m_messageSessionHandlerChat( 0 ), m_messageSessionHandlerGroupchat( 0 ),
120 m_messageSessionHandlerHeadline( 0 ), m_messageSessionHandlerNormal( 0 ),
123 m_selectedSaslMech(
SaslMechNone ), m_customConnection( false ),
124 m_uniqueBaseId( (unsigned int)( ( (unsigned long long)time( 0 ) & 0xFFFF ) << 16 ) | ( ( (unsigned long long) & m_nextId ) & 0xFFFF ) ),
130 void ClientBase::init()
147 memset( &m_stats, 0,
sizeof( m_stats ) );
153 m_iqHandlerMapMutex.
lock();
154 m_iqIDHandlers.clear();
155 m_iqHandlerMapMutex.
unlock();
157 m_iqExtHandlerMapMutex.
lock();
158 m_iqExtHandlers.clear();
159 m_iqExtHandlerMapMutex.
unlock();
174 PresenceJidHandlerList::const_iterator it1 = m_presenceJidHandlers.begin();
175 for( ; it1 != m_presenceJidHandlers.end(); ++it1 )
205 +
m_server + ( ( m_customConnection )?(
" using a custom connection" ):(
m_port > 0 ? (
":" + util::int2string(
m_port ) ) :
EmptyString ) ) +
"..." );
231 const std::string& version = tag->
findAttribute(
"version" );
235 " (it does not send a 'version' attribute). Please fix it or try another one.\n" );
241 handleStartNode( tag );
245 handleStreamError( tag );
250 if( !handleNormalNode( tag ) )
254 if( tag->
name() ==
"iq" )
260 notifyIqHandlers( iq );
265 else if( tag->
name() ==
"message" )
271 notifyMessageHandlers( msg );
276 else if( tag->
name() ==
"presence" )
279 if( type ==
"subscribe" || type ==
"unsubscribe"
280 || type ==
"subscribed" || type ==
"unsubscribed" )
286 notifySubscriptionHandlers( sub );
295 notifyPresenceHandlers( pres );
306 notifyTagHandlers( tag );
311 if( m_statisticsHandler )
397 notifyOnDisconnect( reason );
406 send(
"</stream:stream>" );
421 notifyOnDisconnect( reason );
423 #ifdef CLIENTBASE_TEST
428 void ClientBase::parse(
const std::string& data )
430 std::string copy = data;
432 if( ( i = m_parser.
feed( copy ) ) >= 0 )
434 std::string error =
"parse error (at pos ";
435 error += util::int2string( i );
438 Tag* e =
new Tag(
"stream:error" );
447 std::string head =
"<?xml version='1.0' ?>";
449 head +=
"xmlns:stream='http://etherx.jabber.org/streams' xml:lang='" +
m_xmllang +
"' ";
456 #if defined( HAVE_GNUTLS ) || defined( HAVE_OPENSSL ) || defined( HAVE_WINTLS )
483 m_selectedSaslMech = type;
502 m_gs2Header =
"p=tls-unique,";
508 m_gs2Header +=
"a=" + t;
512 m_clientFirstMessageBare =
"n=";
514 m_clientFirstMessageBare += t;
516 m_clientFirstMessageBare += t;
518 m_clientFirstMessageBare +=
",r=" +
getRandom();
553 #if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
568 "SASL GSSAPI is not supported on this platform. You should never see this." );
574 #if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
576 SEC_WINNT_AUTH_IDENTITY_W identity, *ident = 0;
577 memset( &identity, 0,
sizeof( identity ) );
579 WCHAR *usernameW = 0, *domainW = 0, *passwordW = 0;
580 int cchUsernameW = 0, cchDomainW = 0, cchPasswordW = 0;
587 cchUsernameW = ::MultiByteToWideChar( CP_UTF8, 0,
m_jid.
username().c_str(), -1, 0, 0 );
588 if( cchUsernameW > 0 )
590 usernameW =
new WCHAR[cchUsernameW];
591 ::MultiByteToWideChar( CP_UTF8, 0,
m_jid.
username().c_str(), -1, usernameW, cchUsernameW );
593 usernameW[cchUsernameW-1] = L
'\0';
595 cchDomainW = ::MultiByteToWideChar( CP_UTF8, 0, m_ntlmDomain.c_str(), -1, 0, 0 );
598 domainW =
new WCHAR[cchDomainW];
599 ::MultiByteToWideChar( CP_UTF8, 0, m_ntlmDomain.c_str(), -1, domainW, cchDomainW );
601 domainW[cchDomainW-1] = L
'\0';
603 cchPasswordW = ::MultiByteToWideChar( CP_UTF8, 0,
m_password.c_str(), -1, 0, 0 );
604 if( cchPasswordW > 0 )
606 passwordW =
new WCHAR[cchPasswordW];
607 ::MultiByteToWideChar( CP_UTF8, 0,
m_password.c_str(), -1, passwordW, cchPasswordW );
609 passwordW[cchPasswordW-1] = L
'\0';
611 identity.User = (
unsigned short*)usernameW;
612 identity.UserLength = (
unsigned long)cchUsernameW-1;
613 identity.Domain = (
unsigned short*)domainW;
614 identity.DomainLength = (
unsigned long)cchDomainW-1;
615 identity.Password = (
unsigned short*)passwordW;
616 identity.PasswordLength = (
unsigned long)cchPasswordW-1;
617 identity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
621 AcquireCredentialsHandleW( 0, L
"NTLM", SECPKG_CRED_OUTBOUND, 0, ident, 0, 0, &m_credHandle, 0 );
635 ::SecureZeroMemory( passwordW, cchPasswordW*
sizeof( WCHAR ) );
642 "SASL NTLM is not supported on this platform. You should never see this." );
653 std::string ClientBase::hmac(
const std::string& key,
const std::string& str )
656 std::string key_ = key;
657 if( key_.length() > 64 )
663 unsigned char ipad[65];
664 unsigned char opad[65];
665 memset( ipad,
'\0',
sizeof( ipad ) );
666 memset( opad,
'\0',
sizeof( opad ) );
667 memcpy( ipad, key_.c_str(), key_.length() );
668 memcpy( opad, key_.c_str(), key_.length() );
669 for(
int i = 0; i < 64; i++ )
674 sha.
feed( ipad, 64 );
678 sha.
feed( opad, 64 );
684 std::string ClientBase::hi(
const std::string& str,
const std::string& salt,
int iter )
686 unsigned char xored[20];
687 memset( xored,
'\0',
sizeof( xored ) );
688 std::string tmp = salt;
689 tmp.append(
"\0\0\0\1", 4 );
690 for(
int i = 0; i < iter; ++i )
692 tmp = hmac( str, tmp );
693 for(
int j = 0; j < 20; ++j )
694 xored[j] ^= tmp.c_str()[j];
696 return std::string( (
char*)xored, 20 );
705 switch( m_selectedSaslMech )
710 std::string snonce, salt, tmp;
712 std::string::size_type posn = decoded.find(
"r=" );
713 std::string::size_type poss = decoded.find(
"s=" );
714 std::string::size_type posi = decoded.find(
"i=" );
715 if( posn == std::string::npos || poss == std::string::npos || posi == std::string::npos )
718 snonce = decoded.substr( posn + 2, poss - posn - 3 );
720 tmp = decoded.substr( posi + 2, decoded.length() - posi - 2 );
721 iter = atoi( tmp.c_str() );
726 std::string saltedPwd = hi( tmp, salt, iter );
727 std::string ck = hmac( saltedPwd,
"Client Key" );
730 std::string storedKey = sha.
binary();
736 tmp +=
",r=" + snonce;
738 std::string authMessage = m_clientFirstMessageBare +
"," + decoded +
"," + tmp;
739 std::string clientSignature = hmac( storedKey, authMessage );
740 unsigned char clientProof[20];
741 memcpy( clientProof, ck.c_str(), 20 );
742 for(
int i = 0; i < 20; ++i )
743 clientProof[i] ^= clientSignature.c_str()[i];
744 std::string serverKey = hmac( saltedPwd,
"Server Key" );
745 m_serverSignature = hmac( serverKey, authMessage );
756 if( !decoded.compare( 0, 7,
"rspauth" ) )
760 std::string::size_type end = 0;
761 std::string::size_type pos = decoded.find(
"realm=" );
762 if( pos != std::string::npos )
764 end = decoded.find(
'"', pos + 7 );
765 realm = decoded.substr( pos + 7, end - ( pos + 7 ) );
770 pos = decoded.find(
"nonce=" );
771 if( pos == std::string::npos )
774 end = decoded.find(
'"', pos + 7 );
775 while( decoded[end-1] ==
'\\' )
776 end = decoded.find(
'"', end + 1 );
777 std::string nonce = decoded.substr( pos + 7, end - ( pos + 7 ) );
788 const std::string& a1_h = md5.
binary();
796 const std::string& a1 = md5.
hex();
798 md5.
feed(
"AUTHENTICATE:xmpp/" );
801 const std::string& a2 = md5.
hex();
806 md5.
feed(
":00000001:" );
808 md5.
feed(
":auth:" );
812 std::string response =
"username=\"";
814 response +=
"\",realm=\"";
816 response +=
"\",nonce=\"";
818 response +=
"\",cnonce=\"";
820 response +=
"\",nc=00000001,qop=auth,digest-uri=\"xmpp/";
822 response +=
"\",response=";
823 response += md5.
hex();
824 response +=
",charset=utf-8";
834 #if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
838 "Huh, received GSSAPI challenge?! This should have never happened!" );
843 #if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
844 bool type1 = ( decoded.length() < 7 ) ?
true :
false;
846 SecBuffer bufferIn = { type1 ? 0 : (
unsigned long)decoded.length(),
848 (
void*)decoded.c_str() };
849 SecBufferDesc secIn = { 0, 1, &bufferIn };
853 SecBuffer bufferOut = {
sizeof( buffer ), SECBUFFER_TOKEN, buffer };
854 SecBufferDesc secOut = { 0, 1, &bufferOut };
857 unsigned long contextAttr;
859 SECURITY_STATUS status = InitializeSecurityContext( &m_credHandle, type1 ? 0 : &m_ctxtHandle,
860 0, ISC_REQ_MUTUAL_AUTH, 0, 0, &secIn, 0,
861 &m_ctxtHandle, &secOut, &contextAttr,
863 std::string response;
864 if( SUCCEEDED( status ) )
866 response = std::string( (
const char *)bufferOut.pvBuffer, bufferOut.cbBuffer );
871 "InitializeSecurityContext() failed, return value "
872 + util::int2string( status ) );
878 "Huh, received NTLM challenge?! This should have never happened!" );
895 else if( tag->
hasChild(
"incorrect-encoding" ) )
897 else if( tag->
hasChild(
"invalid-authzid" ) )
899 else if( tag->
hasChild(
"invalid-mechanism" ) )
901 else if( tag->
hasChild(
"malformed-request" ) )
903 else if( tag->
hasChild(
"mechanism-too-weak" ) )
905 else if( tag->
hasChild(
"not-authorized" ) )
907 else if( tag->
hasChild(
"temporary-auth-failure" ) )
910 #if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
913 FreeCredentialsHandle( &m_credHandle );
914 DeleteSecurityContext( &m_ctxtHandle );
921 #if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
924 FreeCredentialsHandle( &m_credHandle );
925 DeleteSecurityContext( &m_ctxtHandle );
931 if( decoded.length() < 3 ||
Base64::decode64( decoded.substr( 2 ) ) != m_serverSignature )
942 if( iq.
id().empty() )
947 track.context = context;
949 m_iqHandlerMapMutex.
lock();
950 m_iqIDHandlers[iq.
id()] = track;
951 m_iqHandlerMapMutex.
unlock();
963 send( tag,
true,
false );
972 send( tag,
true,
false );
981 send( tag,
true,
false );
993 send( tag,
true,
false );
1001 send( tag,
false,
true );
1013 if( m_statisticsHandler )
1018 m_queueMutex.
lock();
1019 m_smQueue.insert( std::make_pair( ++m_smSent, tag ) );
1047 SMQueueMap::iterator it = m_smQueue.begin();
1048 while( it != m_smQueue.end() )
1050 if( (*it).first <= handled )
1052 delete (*it).second;
1053 m_smQueue.erase( it++ );
1055 else if( resend && (*it).first > handled )
1057 send( (*it).second,
false,
false );
1071 SMQueueMap::iterator it = m_smQueue.begin();
1072 for( ; it != m_smQueue.end(); ++it )
1073 l.push_back( (*it).second->clone() );
1078 void ClientBase::addFrom(
Tag* tag )
1086 void ClientBase::addNamespace( Tag* tag )
1088 if( !tag || !tag->xmlns().empty() )
1130 const std::string&
id =
getID();
1134 send( iq,
this, XMPPPing );
1137 bool ClientBase::handleIq(
const IQ& iq )
1150 void ClientBase::handleIqID(
const IQ& iq,
int context )
1152 if( context == XMPPPing )
1157 handleIqIDForward( iq, context );
1162 #ifdef CLIENTBASE_TEST // to create predictable UIDs in test mode
1163 return "uid" + util::int2string( m_nextId.
increment() );
1166 sprintf( r,
"uid-%08x-%08x", m_uniqueBaseId, m_nextId.
increment() );
1167 std::string ret( r, 21 );
1174 if( version.empty() )
1181 size_t dot = version.find(
'.' );
1182 if( !version.empty() && dot && dot != std::string::npos )
1184 major = atoi( version.substr( 0, dot ).c_str() );
1188 return myMajor >= major;
1195 m_customConnection =
true;
1216 void ClientBase::handleStreamError(
Tag* tag )
1220 TagList::const_iterator it = c.begin();
1221 for( ; it != c.end(); ++it )
1223 const std::string& name = (*it)->name();
1224 if( name ==
"bad-format" )
1226 else if( name ==
"bad-namespace-prefix" )
1228 else if( name ==
"conflict" )
1230 else if( name ==
"connection-timeout" )
1232 else if( name ==
"host-gone" )
1234 else if( name ==
"host-unknown" )
1236 else if( name ==
"improper-addressing" )
1238 else if( name ==
"internal-server-error" )
1240 else if( name ==
"invalid-from" )
1242 else if( name ==
"invalid-id" )
1244 else if( name ==
"invalid-namespace" )
1246 else if( name ==
"invalid-xml" )
1248 else if( name ==
"not-authorized" )
1250 else if( name ==
"policy-violation" )
1252 else if( name ==
"remote-connection-failed" )
1254 else if( name ==
"resource-constraint" )
1256 else if( name ==
"restricted-xml" )
1258 else if( name ==
"see-other-host" )
1261 m_streamErrorCData = tag->
findChild(
"see-other-host" )->
cdata();
1263 else if( name ==
"system-shutdown" )
1265 else if( name ==
"undefined-condition" )
1267 else if( name ==
"unsupported-encoding" )
1269 else if( name ==
"unsupported-stanza-type" )
1271 else if( name ==
"unsupported-version" )
1273 else if( name ==
"xml-not-well-formed" )
1275 else if( name ==
"text" )
1277 const std::string& lang = (*it)->findAttribute(
"xml:lang" );
1279 m_streamErrorText[lang] = (*it)->cdata();
1281 m_streamErrorText[
"default"] = (*it)->cdata();
1284 m_streamErrorAppCondition = (*it);
1287 m_streamError = err;
1293 StringMap::const_iterator it = m_streamErrorText.find( lang );
1294 return ( it != m_streamErrorText.end() ) ? (*it).second :
EmptyString;
1300 m_messageSessionHandlerChat = msh;
1303 m_messageSessionHandlerNormal = msh;
1306 m_messageSessionHandlerGroupchat = msh;
1309 m_messageSessionHandlerHeadline = msh;
1315 m_presenceHandlers.push_back( ph );
1321 m_presenceHandlers.remove( ph );
1328 JidPresHandlerStruct jph;
1329 jph.jid =
new JID( jid.
bare() );
1331 m_presenceJidHandlers.push_back( jph );
1337 PresenceJidHandlerList::iterator t;
1338 PresenceJidHandlerList::iterator it = m_presenceJidHandlers.begin();
1339 while( it != m_presenceJidHandlers.end() )
1343 if( ( !ph || (*t).ph == ph ) && (*t).jid->bare() == jid.
bare() )
1346 m_presenceJidHandlers.erase( t );
1353 IqTrackMap::iterator t;
1354 m_iqHandlerMapMutex.
lock();
1355 IqTrackMap::iterator it = m_iqIDHandlers.begin();
1356 while( it != m_iqIDHandlers.end() )
1360 if( ih == (*t).second.ih )
1361 m_iqIDHandlers.erase( t );
1363 m_iqHandlerMapMutex.
unlock();
1372 typedef IqHandlerMap::const_iterator IQci;
1373 std::pair<IQci, IQci> g = m_iqExtHandlers.equal_range( exttype );
1374 for( IQci it = g.first; it != g.second; ++it )
1376 if( (*it).second == ih )
1380 m_iqExtHandlers.insert( std::make_pair( exttype, ih ) );
1389 typedef IqHandlerMap::iterator IQi;
1390 std::pair<IQi, IQi> g = m_iqExtHandlers.equal_range( exttype );
1393 while( it != g.second )
1396 if( (*it2).second == ih )
1397 m_iqExtHandlers.erase( it2 );
1404 m_messageSessions.push_back( session );
1412 MessageSessionList::iterator it = std::find( m_messageSessions.begin(),
1413 m_messageSessions.end(),
1415 if( it != m_messageSessions.end() )
1418 m_messageSessions.erase( it );
1425 m_messageHandlers.push_back( mh );
1431 m_messageHandlers.remove( mh );
1437 m_subscriptionHandlers.push_back( sh );
1443 m_subscriptionHandlers.remove( sh );
1448 if( th && !tag.empty() )
1450 TagHandlerStruct ths;
1454 m_tagHandlers.push_back( ths );
1462 for( TagHandlerList::iterator it = m_tagHandlers.begin(); it != m_tagHandlers.end(); )
1464 if( (*it).th == th && (*it).tag == tag && (*it).xmlns == xmlns )
1471 m_tagHandlers.erase( it++ );
1484 m_statisticsHandler = sh;
1489 m_statisticsHandler = 0;
1496 m_mucInvitationHandler = mih;
1503 m_mucInvitationHandler = 0;
1510 m_connectionListeners.push_back( cl );
1516 m_connectionListeners.remove( cl );
1532 ConnectionListenerList::const_iterator it = m_connectionListeners.begin();
1533 for( ; it != m_connectionListeners.end() && (*it)->onTLSConnect( info ); ++it )
1535 return m_stats.
encryption = ( it == m_connectionListeners.end() );
1558 void ClientBase::notifyPresenceHandlers(
Presence& pres )
1561 PresenceJidHandlerList::const_iterator t;
1562 PresenceJidHandlerList::const_iterator itj = m_presenceJidHandlers.begin();
1563 while( itj != m_presenceJidHandlers.end() )
1566 if( (*t).jid->bare() == pres.
from().
bare() && (*t).ph )
1568 (*t).ph->handlePresence( pres );
1576 PresenceHandlerList::const_iterator it = m_presenceHandlers.begin();
1577 for( ; it != m_presenceHandlers.end(); ++it )
1579 (*it)->handlePresence( pres );
1585 void ClientBase::notifySubscriptionHandlers( Subscription& s10n )
1588 SubscriptionHandlerList::const_iterator it = m_subscriptionHandlers.begin();
1589 for( ; it != m_subscriptionHandlers.end(); ++it )
1591 (*it)->handleSubscription( s10n );
1597 void ClientBase::notifyIqHandlers( IQ& iq )
1599 m_iqHandlerMapMutex.
lock();
1600 IqTrackMap::iterator it_id = m_iqIDHandlers.find( iq.id() );
1601 bool haveIdHandler = ( it_id != m_iqIDHandlers.end() );
1602 m_iqHandlerMapMutex.
unlock();
1605 (*it_id).second.ih->handleIqID( iq, (*it_id).second.context );
1606 if( (*it_id).second.del )
1607 delete (*it_id).second.ih;
1608 m_iqHandlerMapMutex.
lock();
1609 m_iqIDHandlers.erase( it_id );
1610 m_iqHandlerMapMutex.
unlock();
1614 if( iq.extensions().empty() )
1625 bool handled =
false;
1638 m_iqExtHandlerMapMutex.
lock();
1639 typedef IqHandlerMap::const_iterator IQci;
1641 StanzaExtensionList::const_iterator itse = sel.begin();
1642 for( ; !handled && itse != sel.end(); ++itse )
1644 std::pair<IQci, IQci> g = m_iqExtHandlers.equal_range( (*itse)->extensionType() );
1645 for( IQci it = g.first; !handled && it != g.second; ++it )
1647 if( (*it).second->handleIq( iq ) )
1651 m_iqExtHandlerMapMutex.
unlock();
1653 if( !handled && ( iq.subtype() ==
IQ::Get || iq.subtype() ==
IQ::Set ) )
1661 void ClientBase::notifyMessageHandlers( Message& msg )
1663 if( m_mucInvitationHandler )
1665 const MUCRoom::MUCUser* mu = msg.findExtension<MUCRoom::MUCUser>(
ExtMUCUser );
1670 mu->jid() ? JID( *(mu->jid()) ) : JID(),
1680 MessageSessionList::const_iterator it1 = m_messageSessions.begin();
1681 for( ; it1 != m_messageSessions.end(); ++it1 )
1683 if( (*it1)->target().full() == msg.from().full() &&
1684 ( msg.thread().empty()
1685 || (*it1)->threadID() == msg.thread()
1686 || (*it1)->honorThreadID() ) &&
1688 ( (*it1)->types() & msg.subtype() || (*it1)->types() == 0 ) )
1690 (*it1)->handleMessage( msg );
1695 it1 = m_messageSessions.begin();
1696 for( ; it1 != m_messageSessions.end(); ++it1 )
1698 if( (*it1)->target().bare() == msg.from().bare() &&
1699 ( msg.thread().empty()
1700 || (*it1)->threadID() == msg.thread()
1701 || (*it1)->honorThreadID() ) &&
1703 ( (*it1)->types() & msg.subtype() || (*it1)->types() == 0 ) )
1705 (*it1)->handleMessage( msg );
1710 MessageSessionHandler* msHandler = 0;
1712 switch( msg.subtype() )
1715 msHandler = m_messageSessionHandlerChat;
1718 msHandler = m_messageSessionHandlerNormal;
1721 msHandler = m_messageSessionHandlerGroupchat;
1724 msHandler = m_messageSessionHandlerHeadline;
1732 MessageSession* session =
new MessageSession(
this, msg.from(),
true, msg.subtype() );
1734 session->handleMessage( msg );
1739 MessageHandlerList::const_iterator it = m_messageHandlers.begin();
1740 for( ; it != m_messageHandlers.end(); ++it )
1742 (*it)->handleMessage( msg );
1749 void ClientBase::notifyTagHandlers( Tag* tag )
1751 TagHandlerList::const_iterator it = m_tagHandlers.begin();
1752 for( ; it != m_tagHandlers.end(); ++it )
1754 if( (*it).tag == tag->name() && tag->hasAttribute(
XMLNS, (*it).xmlns ) )
1755 (*it).th->handleTag( tag );
1773 if( (*it)->extensionType() == type )
1787 for(
int i = 0; i < 4; ++i )
1788 sprintf( cn + i*8,
"%08x", rand() );
1789 return std::string( cn, 4*8 );;
1807 TLSBase* ClientBase::getDefaultEncryption()
1812 TLSDefault*
tls =
new TLSDefault(
this,
m_server );