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

📄 clientbase.cpp

📁 Jabber code library, developed with c
💻 CPP
📖 第 1 页 / 共 3 页
字号:
      case SaslMechPlain:      {        a->addAttribute( "mechanism", "PLAIN" );        std::string tmp;        if( m_authzid )          tmp += m_authzid.bare();        tmp += '\0';        tmp += m_jid.username();        tmp += '\0';        tmp += m_password;        a->setCData( Base64::encode64( tmp ) );        break;      }      case SaslMechAnonymous:        a->addAttribute( "mechanism", "ANONYMOUS" );        a->setCData( getID() );        break;      case SaslMechExternal:        a->addAttribute( "mechanism", "EXTERNAL" );        if( m_authzid )          a->setCData( Base64::encode64( m_authzid.bare() ) );        else          a->setCData( Base64::encode64( m_jid.bare() ) );        break;      case SaslMechGssapi:      {#ifdef _WIN32        a->addAttribute( "mechanism", "GSSAPI" );// The client calls GSS_Init_sec_context, passing in 0 for// input_context_handle (initially) and a targ_name equal to output_name// from GSS_Import_Name called with input_name_type of// GSS_C_NT_HOSTBASED_SERVICE and input_name_string of// "service@hostname" where "service" is the service name specified in// the protocol's profile, and "hostname" is the fully qualified host// name of the server.  The client then responds with the resulting// output_token.        std::string token;        a->setCData( Base64::encode64( token ) );//         etc... see gssapi-sasl-draft.txt#else        logInstance().log( LogLevelError, LogAreaClassClientbase,                    "GSSAPI is not supported on this platform. You should never see this." );#endif        break;      }      default:        break;    }    send( a );  }  void ClientBase::processSASLChallenge( const std::string& challenge )  {    Tag *t = new Tag( "response" );    t->addAttribute( "xmlns", XMLNS_STREAM_SASL );    const std::string& decoded = Base64::decode64( challenge );    switch( m_selectedSaslMech )    {      case SaslMechDigestMd5:      {        if( decoded.substr( 0, 7 ) == "rspauth" )        {          break;        }        std::string realm;        size_t r_pos = decoded.find( "realm=" );        if( r_pos != std::string::npos )        {          size_t r_end = decoded.find( "\"", r_pos + 7 );          realm = decoded.substr( r_pos + 7, r_end - (r_pos + 7 ) );        }        else          realm = m_jid.server();        size_t n_pos = decoded.find( "nonce=" );        if( n_pos == std::string::npos )        {          return;        }        size_t n_end = decoded.find( "\"", n_pos + 7 );        while( decoded.substr( n_end-1, 1 ) == "\\" )          n_end = decoded.find( "\"", n_end + 1 );        std::string nonce = decoded.substr( n_pos + 7, n_end - ( n_pos + 7 ) );        std::string cnonce;#ifdef _WIN32_WCE        char cn[4*8+1];        for( int i = 0; i < 4; ++i )          sprintf( cn + i*8, "%08x", rand() );        cnonce.assign( cn, 4*8 );#else        std::ostringstream cn;        for( int i = 0; i < 4; ++i )          cn << std::hex << std::setw( 8 ) << std::setfill( '0' ) << rand();        cnonce = cn.str();#endif        MD5 md5;        md5.feed( m_jid.username() );        md5.feed( ":" );        md5.feed( realm );        md5.feed( ":" );        md5.feed( m_password );        md5.finalize();        const std::string& a1_h = md5.binary();        md5.reset();        md5.feed( a1_h );        md5.feed( ":" );        md5.feed( nonce );        md5.feed( ":" );        md5.feed( cnonce );        md5.finalize();        const std::string& a1  = md5.hex();        md5.reset();        md5.feed( "AUTHENTICATE:xmpp/" );        md5.feed( m_jid.server() );        md5.finalize();        const std::string& a2 = md5.hex();        md5.reset();        md5.feed( a1 );        md5.feed( ":" );        md5.feed( nonce );        md5.feed( ":00000001:" );        md5.feed( cnonce );        md5.feed( ":auth:" );        md5.feed( a2 );        md5.finalize();        const std::string& response_value = md5.hex();        std::string response = "username=\"" + m_jid.username() + "\",realm=\"" + realm;        response += "\",nonce=\""+ nonce + "\",cnonce=\"" + cnonce;        response += "\",nc=00000001,qop=auth,digest-uri=\"xmpp/" + m_jid.server() + "\",response=";        response += response_value;        response += ",charset=utf-8";        if( m_authzid )          response += ",authzid=" + m_authzid.bare();        t->setCData( Base64::encode64( response ) );        break;      }      case SaslMechGssapi:#ifdef _WIN32        // see gssapi-sasl-draft.txt#else        m_logInstance.log( LogLevelError, LogAreaClassClientbase,                           "Huh, received GSSAPI challenge?! This should have never happened!" );#endif        break;      default:        // should never happen.        break;    }    send( t );  }  void ClientBase::processSASLError( Stanza *stanza )  {    if( stanza->hasChild( "aborted" ) )      m_authError = SaslAborted;    else if( stanza->hasChild( "incorrect-encoding" ) )      m_authError = SaslIncorrectEncoding;    else if( stanza->hasChild( "invalid-authzid" ) )      m_authError = SaslInvalidAuthzid;    else if( stanza->hasChild( "invalid-mechanism" ) )      m_authError = SaslInvalidMechanism;    else if( stanza->hasChild( "mechanism-too-weak" ) )      m_authError = SaslMechanismTooWeak;    else if( stanza->hasChild( "not-authorized" ) )      m_authError = SaslNotAuthorized;    else if( stanza->hasChild( "temporary-auth-failure" ) )      m_authError = SaslTemporaryAuthFailure;  }  void ClientBase::send( Tag *tag )  {    if( !tag )      return;    send( tag->xml() );    switch( tag->type() )    {      case StanzaIq:        ++m_stats.iqStanzasSent;        break;      case StanzaMessage:        ++m_stats.messageStanzasSent;        break;      case StanzaS10n:        ++m_stats.s10nStanzasSent;        break;      case StanzaPresence:        ++m_stats.presenceStanzasSent;        break;      default:        break;    }    ++m_stats.totalStanzasSent;    delete tag;    if( m_statisticsHandler )      m_statisticsHandler->handleStatistics( getStatistics() );  }  void ClientBase::send( const std::string& xml )  {    if( m_connection && m_connection->state() == StateConnected )    {      if( m_compression && m_compressionActive )        m_compression->compress( xml );      else if( m_encryption && m_encryptionActive )        m_encryption->encrypt( xml );      else        m_connection->send( xml );      logInstance().log( LogLevelDebug, LogAreaXmlOutgoing, xml );    }  }  StatisticsStruct ClientBase::getStatistics()  {//     if( m_connection )//       m_connection->getStatistics( m_stats.totalBytesReceived, m_stats.totalBytesSent,//                                    m_stats.compressedBytesReceived, m_stats.compressedBytesSent,//                                    m_stats.uncompressedBytesReceived, m_stats.uncompressedBytesSent,//                                    m_stats.compression );    return m_stats;  }  ConnectionState ClientBase::state() const  {    return m_connection ? m_connection->state() : StateDisconnected;  }  void ClientBase::whitespacePing()  {    send( " " );  }  void ClientBase::xmppPing( const JID& to )  {    const std::string& id = getID();    Tag *iq = new Tag( "iq" );    iq->addAttribute( "to", to.full() );    iq->addAttribute( "id", id );    iq->addAttribute( "type", "get" );    Tag *p = new Tag( iq, "ping" );    p->addAttribute( "xmlns", XMLNS_XMPP_PING );    send( iq );  }  const std::string ClientBase::getID()  {#ifdef _WIN32_WCE    char r[8+1];    sprintf( r, "%08x", rand() );    std::string ret( r, 8 );    return std::string( "uid" ) + ret;#else    std::ostringstream oss;    oss << ++m_idCount;    return std::string( "uid" ) + oss.str();#endif  }  bool ClientBase::checkStreamVersion( const std::string& version )  {    if( version.empty() )      return false;    int major = 0;    int minor = 0;    int myMajor = atoi( XMPP_STREAM_VERSION_MAJOR.c_str() );    size_t dot = version.find( "." );    if( !version.empty() && dot && dot != std::string::npos )    {      major = atoi( version.substr( 0, dot ).c_str() );      minor = atoi( version.substr( dot ).c_str() );    }    return myMajor >= major;  }  LogSink& ClientBase::logInstance()  {    return m_logInstance;  }  void ClientBase::setConnectionImpl( ConnectionBase *cb )  {    if( m_connection )    {      delete m_connection;    }    m_connection = cb;  }  void ClientBase::setEncryptionImpl( TLSBase *tb )  {    if( m_encryption )    {      delete m_encryption;    }    m_encryption = tb;  }  void ClientBase::setCompressionImpl( CompressionBase *cb )  {    if( m_compression )    {      delete m_compression;    }    m_compression = cb;  }  void ClientBase::handleStreamError( Stanza *stanza )  {    StreamError err = StreamErrorUndefined;    const Tag::TagList& c = stanza->children();    Tag::TagList::const_iterator it = c.begin();    for( ; it != c.end(); ++it )    {      if( (*it)->name() == "bad-format" )        err = StreamErrorBadFormat;      else if( (*it)->name() == "bad-namespace-prefix" )        err = StreamErrorBadNamespacePrefix;      else if( (*it)->name() == "conflict" )        err = StreamErrorConflict;      else if( (*it)->name() == "connection-timeout" )        err = StreamErrorConnectionTimeout;      else if( (*it)->name() == "host-gone" )        err = StreamErrorHostGone;      else if( (*it)->name() == "host-unknown" )        err = StreamErrorHostUnknown;      else if( (*it)->name() == "improper-addressing" )        err = StreamErrorImproperAddressing;      else if( (*it)->name() == "internal-server-error" )        err = StreamErrorInternalServerError;      else if( (*it)->name() == "invalid-from" )        err = StreamErrorInvalidFrom;      else if( (*it)->name() == "invalid-id" )        err = StreamErrorInvalidId;      else if( (*it)->name() == "invalid-namespace" )        err = StreamErrorInvalidNamespace;      else if( (*it)->name() == "invalid-xml" )        err = StreamErrorInvalidXml;      else if( (*it)->name() == "not-authorized" )        err = StreamErrorNotAuthorized;      else if( (*it)->name() == "policy-violation" )        err = StreamErrorPolicyViolation;      else if( (*it)->name() == "remote-connection-failed" )        err = StreamErrorRemoteConnectionFailed;      else if( (*it)->name() == "resource-constraint" )        err = StreamErrorResourceConstraint;      else if( (*it)->name() == "restricted-xml" )        err = StreamErrorRestrictedXml;      else if( (*it)->name() == "see-other-host" )      {        err = StreamErrorSeeOtherHost;        m_streamErrorCData = stanza->findChild( "see-other-host" )->cdata();      }      else if( (*it)->name() == "system-shutdown" )        err = StreamErrorSystemShutdown;      else if( (*it)->name() == "undefined-condition" )        err = StreamErrorUndefinedCondition;      else if( (*it)->name() == "unsupported-encoding" )        err = StreamErrorUnsupportedEncoding;      else if( (*it)->name() == "unsupported-stanza-type" )        err = StreamErrorUnsupportedStanzaType;      else if( (*it)->name() == "unsupported-version" )        err = StreamErrorUnsupportedVersion;      else if( (*it)->name() == "xml-not-well-formed" )        err = StreamErrorXmlNotWellFormed;      else if( (*it)->name() == "text" )      {        const std::string& lang = (*it)->findAttribute( "xml:lang" );        if( !lang.empty() )          m_streamErrorText[lang] = (*it)->cdata();        else          m_streamErrorText["default"] = (*it)->cdata();      }      else        m_streamErrorAppCondition = (*it);      if( err != StreamErrorUndefined && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )        m_streamError = err;    }  }  const std::string ClientBase::streamErrorText( const std::string& lang ) const  {    StringMap::const_iterator it = m_streamErrorText.find( lang );    return ( it != m_streamErrorText.end() ) ? (*it).second : std::string();  }  void ClientBase::registerMessageSessionHandler( MessageSessionHandler *msh, int types )  {    if( types & StanzaMessageChat || types == 0 )      m_messageSessionHandlerChat = msh;    if( types & StanzaMessageNormal || types == 0 )      m_messageSessionHandlerNormal = msh;    if( types & StanzaMessageGroupchat || types == 0 )      m_messageSessionHandlerGroupchat = msh;    if( types & StanzaMessageHeadline || types == 0 )

⌨️ 快捷键说明

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