LCOV - code coverage report
Current view: top level - src - IRC.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 7 646 1.1 %
Date: 2010-12-13 Functions: 3 8 37.5 %
Branches: 39 584 6.7 %

           Branch data     Line data    Source code
       1                 :            : // $Id: IRC.cc 4582 2007-07-04 01:14:09Z vern $
       2                 :            : 
       3                 :            : // An IRC analyzer contributed by Roland Gruber.
       4                 :            : 
       5                 :            : #include <iostream>
       6                 :            : #include "IRC.h"
       7                 :            : #include "DPM.h"
       8                 :            : #include "ContentLine.h"
       9                 :            : #include "NetVar.h"
      10                 :            : #include "Event.h"
      11                 :            : #include "ZIP.h"
      12                 :            : 
      13                 :            : 
      14                 :          0 : IRC_Analyzer::IRC_Analyzer(Connection* conn)
      15                 :          0 : : TCP_ApplicationAnalyzer(AnalyzerTag::IRC, conn)
      16                 :            :         {
      17                 :          0 :         invalid_msg_count = 0;
      18                 :          0 :         invalid_msg_max_count = 20;
      19                 :          0 :         orig_status = WAIT_FOR_REGISTRATION;
      20                 :          0 :         resp_status = WAIT_FOR_REGISTRATION;
      21                 :          0 :         orig_zip_status = NO_ZIP;
      22                 :          0 :         resp_zip_status = NO_ZIP;
      23                 :          0 :         AddSupportAnalyzer(new ContentLine_Analyzer(conn, true));
      24                 :          0 :         AddSupportAnalyzer(new ContentLine_Analyzer(conn, false));
      25                 :          0 :         }
      26                 :            : 
      27                 :          1 : bool IRC_Analyzer::Available()
      28                 :            :         {
      29                 :            :         static bool did_avail = false;
      30                 :            :         static bool avail = false;
      31                 :            : 
      32         [ +  - ]:          1 :         if ( ! did_avail )
      33                 :            :                 {
      34                 :            :                 // It's a lot of events, but for consistency with other
      35                 :            :                 // analyzers we need to check for all of them.
      36                 :            :                 avail = irc_client || irc_server || irc_request || irc_reply ||
      37                 :            :                         irc_message || irc_enter_message || irc_quit_message ||
      38                 :            :                         irc_privmsg_message || irc_notice_message ||
      39                 :            :                         irc_squery_message || irc_join_message ||
      40                 :            :                         irc_part_message || irc_nick_message ||
      41                 :            :                         irc_invalid_nick || irc_network_info ||
      42                 :            :                         irc_server_info || irc_channel_info || irc_who_line ||
      43                 :            :                         irc_who_message || irc_whois_message ||
      44                 :            :                         irc_whois_user_line || irc_whois_operator_line ||
      45                 :            :                         irc_whois_channel_line || irc_oper_message ||
      46                 :            :                         irc_oper_response || irc_kick_message ||
      47                 :            :                         irc_error_message || irc_invite_message ||
      48                 :            :                         irc_mode_message || irc_squit_message ||
      49                 :            :                         irc_names_info || irc_dcc_message ||
      50                 :            :                         irc_global_users || irc_user_message ||
      51 [ +  - ][ +  - ]:          1 :                         irc_channel_topic || irc_password_message;
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ -  + ]
      52                 :            : 
      53                 :          1 :                 did_avail = true;
      54                 :            :                 }
      55                 :            : 
      56                 :          1 :         return avail;
      57                 :            :         }
      58                 :            : 
      59                 :          0 : void IRC_Analyzer::Done()
      60                 :            :         {
      61                 :          0 :         TCP_ApplicationAnalyzer::Done();
      62                 :          0 :         }
      63                 :            : 
      64                 :          0 : void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig)
      65                 :            :         {
      66                 :          0 :         TCP_ApplicationAnalyzer::DeliverStream(length, line, orig);
      67                 :            : 
      68                 :            :         // check line size
      69         [ #  # ]:          0 :         if ( length > 512 )
      70                 :            :                 {
      71                 :          0 :                 Weird("irc_line_size_exceeded");
      72                 :          0 :                 return;
      73                 :            :                 }
      74                 :            : 
      75         [ #  # ]:          0 :         if ( length < 2 )
      76                 :            :                 {
      77                 :          0 :                 Weird("irc_line_too_short");
      78                 :          0 :                 return;
      79                 :            :                 }
      80                 :            : 
      81                 :          0 :         string myline = string((const char*) line);
      82                 :            : 
      83                 :            :         // Check for prefix.
      84                 :          0 :         string prefix = "";
      85         [ #  # ]:          0 :         if ( line[0] == ':' )
      86                 :            :                 { // find end of prefix and extract it
      87                 :          0 :                 unsigned int pos = myline.find(' ');
      88         [ #  # ]:          0 :                 if ( pos > (unsigned int) length )
      89                 :            :                         {
      90                 :          0 :                         Weird("irc_invalid_line");
      91                 :          0 :                         return;
      92                 :            :                         }
      93                 :            : 
      94                 :          0 :                 prefix = myline.substr(1, pos - 1);
      95                 :          0 :                 myline = myline.substr(pos + 1);  // remove prefix from line
      96                 :            :                 }
      97                 :            : 
      98                 :            : 
      99         [ #  # ]:          0 :         if ( orig )
     100                 :            :                 {
     101                 :          0 :                 ProtocolConfirmation();
     102         [ #  # ]:          0 :                 if ( irc_client )
     103                 :            :                         {
     104                 :          0 :                         val_list* vl = new val_list;
     105                 :          0 :                         vl->append(BuildConnVal());
     106                 :          0 :                         vl->append(new StringVal(prefix.c_str()));
     107                 :          0 :                         vl->append(new StringVal(myline.c_str()));
     108                 :          0 :                         ConnectionEvent(irc_client, vl);
     109                 :            :                         }
     110                 :            :                 }
     111                 :            :         else
     112                 :            :                 {
     113         [ #  # ]:          0 :                 if ( irc_server )
     114                 :            :                         {
     115                 :          0 :                         val_list* vl = new val_list;
     116                 :          0 :                         vl->append(BuildConnVal());
     117                 :          0 :                         vl->append(new StringVal(prefix.c_str()));
     118                 :          0 :                         vl->append(new StringVal(myline.c_str()));
     119                 :          0 :                         ConnectionEvent(irc_server, vl);
     120                 :            :                         }
     121                 :            :                 }
     122                 :            : 
     123                 :          0 :         int code = 0;
     124                 :          0 :         string command = "";
     125                 :            : 
     126                 :            :         // Check if line is long enough to include status code or command.
     127         [ #  # ]:          0 :         if ( myline.size() < 4 )
     128                 :            :                 {
     129                 :          0 :                 Weird("irc_invalid_line");
     130                 :          0 :                 ProtocolViolation("line too short");
     131                 :            :                 return;
     132                 :            :                 }
     133                 :            : 
     134                 :            :         // Check if this is a server reply.
     135         [ #  # ]:          0 :         if ( isdigit(myline[0]) )
     136                 :            :                 {
     137 [ #  # ][ #  # ]:          0 :                 if ( isdigit(myline[1]) && isdigit(myline[2]) &&
         [ #  # ][ #  # ]
     138                 :            :                      myline[3] == ' ')
     139                 :            :                         {
     140                 :            :                         code = (myline[0] - '0') * 100 +
     141                 :          0 :                                 (myline[1] - '0') * 10 + (myline[2] - '0');
     142                 :          0 :                         myline = myline.substr(4);
     143                 :            :                         }
     144                 :            :                 else
     145                 :            :                         {
     146                 :          0 :                         Weird("irc_invalid_reply_number");
     147                 :          0 :                         ProtocolViolation("invalid reply number");
     148                 :            :                         return;
     149                 :            :                         }
     150                 :            :                 }
     151                 :            :         else
     152                 :            :                 { // get command
     153                 :          0 :                 unsigned int pos = myline.find(' ');
     154         [ #  # ]:          0 :                 if ( pos > (unsigned int) length )
     155                 :            :                         {
     156                 :          0 :                         Weird("irc_invalid_line");
     157                 :            :                         return;
     158                 :            :                         }
     159                 :            : 
     160                 :          0 :                 command = myline.substr(0, pos);
     161         [ #  # ]:          0 :                 for ( unsigned int i = 0; i < command.size(); ++i )
     162                 :          0 :                         command[i] = toupper(command[i]);
     163                 :            : 
     164                 :          0 :                 myline = myline.substr(pos + 1);
     165                 :            :                 }
     166                 :            : 
     167                 :            :         // Extract parameters.
     168                 :          0 :         string params = myline;
     169                 :            : 
     170                 :            :         // Check for Server2Server - connections with ZIP enabled.
     171   [ #  #  #  # ]:          0 :         if ( orig && orig_status == WAIT_FOR_REGISTRATION )
     172                 :            :                 {
     173         [ #  # ]:          0 :                 if ( command == "PASS" )
     174                 :            :                         {
     175                 :          0 :                         vector<string> p = SplitWords(params,' ');
     176   [ #  #  #  # ]:          0 :                         if ( p.size() > 3 &&
         [ #  # ][ #  # ]
     177                 :            :                              (p[3].find('Z')<=p[3].size() ||
     178                 :            :                               p[3].find('z')<=p[3].size()) )
     179                 :          0 :                                 orig_zip_status = ACCEPT_ZIP;
     180                 :            :                         else
     181                 :          0 :                                 orig_zip_status = NO_ZIP;
     182                 :            :                         }
     183                 :            : 
     184                 :            :                 // We do not check if SERVER command is successful, since
     185                 :            :                 // the connection will be terminated by the server if
     186                 :            :                 // authentication fails.
     187                 :            :                 //
     188                 :            :                 // (### This seems not quite prudent to me - VP)
     189 [ #  # ][ #  # ]:          0 :                 if ( command == "SERVER" && prefix == "")
                 [ #  # ]
     190                 :            :                         {
     191                 :          0 :                         orig_status = REGISTERED;
     192                 :            :                         }
     193                 :            :                 }
     194                 :            : 
     195 [ #  # ][ #  # ]:          0 :         if ( ! orig && resp_status == WAIT_FOR_REGISTRATION )
     196                 :            :                 {
     197         [ #  # ]:          0 :                 if ( command == "PASS" )
     198                 :            :                         {
     199                 :          0 :                         vector<string> p = SplitWords(params,' ');
     200   [ #  #  #  # ]:          0 :                         if ( p.size() > 3 &&
         [ #  # ][ #  # ]
     201                 :            :                              (p[3].find('Z')<=p[3].size() ||
     202                 :            :                               p[3].find('z')<=p[3].size()) )
     203                 :          0 :                                 resp_zip_status = ACCEPT_ZIP;
     204                 :            :                         else
     205                 :          0 :                                 resp_zip_status = NO_ZIP;
     206                 :            : 
     207                 :            :                         }
     208                 :            : 
     209                 :            :                 // Again, don't bother checking whether SERVER command
     210                 :            :                 // is successful.
     211 [ #  # ][ #  # ]:          0 :                 if ( command == "SERVER" && prefix == "")
                 [ #  # ]
     212                 :          0 :                         resp_status = REGISTERED;
     213                 :            :                 }
     214                 :            : 
     215                 :            :         // Analyze server reply messages.
     216         [ #  # ]:          0 :         if ( code > 0 )
     217                 :            :                 {
     218 [ #  #  #  #  # :          0 :                 switch ( code ) {
          #  #  #  #  #  
             #  #  #  # ]
     219                 :            :                 // Ignore unimportant messages.
     220                 :            :                 case 1: // RPL_WELCOME
     221                 :            :                 case 2: // RPL_YOURHOST
     222                 :            :                 case 3: // RPL_CREATED
     223                 :            :                 case 4: // RPL_MYINFO
     224                 :            :                 case 5: // RPL_BOUNCE
     225                 :            :                 case 252: // number of ops online
     226                 :            :                 case 253: // number of unknown connections
     227                 :            :                 case 265: // RPL_LOCALUSERS
     228                 :            :                 case 312: // whois server reply
     229                 :            :                 case 315: // end of who list
     230                 :            :                 case 317: // whois idle reply
     231                 :            :                 case 318: // end of whois list
     232                 :            :                 case 366: // end of names list
     233                 :            :                 case 372: // RPL_MOTD
     234                 :            :                 case 375: // RPL_MOTDSTART
     235                 :            :                 case 376: // RPL_ENDOFMOTD
     236                 :            :                 case 331: // RPL_NOTOPIC
     237                 :          0 :                         break;
     238                 :            : 
     239                 :            :                 // Count of users, services and servers in whole network.
     240                 :            :                 case 251:
     241         [ #  # ]:          0 :                         if ( ! irc_network_info )
     242                 :          0 :                                 break;
     243                 :            : 
     244                 :            :                         {
     245                 :          0 :                         vector<string> parts = SplitWords(params, ' ');
     246                 :          0 :                         int users = 0;
     247                 :          0 :                         int services = 0;
     248                 :          0 :                         int servers = 0;
     249                 :            : 
     250         [ #  # ]:          0 :                         for ( unsigned int i = 1; i < parts.size(); ++i )
     251                 :            :                                 {
     252         [ #  # ]:          0 :                                 if ( parts[i] == "users" )
     253                 :          0 :                                         users = atoi(parts[i-1].c_str());
     254         [ #  # ]:          0 :                                 else if ( parts[i] == "services" )
     255                 :          0 :                                         services = atoi(parts[i-1].c_str());
     256         [ #  # ]:          0 :                                 else if ( parts[i] == "servers" )
     257                 :          0 :                                         servers = atoi(parts[i-1].c_str());
     258                 :            :                                 // else ###
     259                 :            :                                 }
     260                 :            : 
     261                 :          0 :                         val_list* vl = new val_list;
     262                 :          0 :                         vl->append(BuildConnVal());
     263                 :          0 :                         vl->append(new Val(users, TYPE_INT));
     264                 :          0 :                         vl->append(new Val(services, TYPE_INT));
     265                 :          0 :                         vl->append(new Val(servers, TYPE_INT));
     266                 :            : 
     267                 :          0 :                         ConnectionEvent(irc_network_info, vl);
     268                 :            :                         }
     269                 :          0 :                         break;
     270                 :            : 
     271                 :            :                 // List of users in a channel (names command).
     272                 :            :                 case 353:
     273         [ #  # ]:          0 :                         if ( ! irc_names_info )
     274                 :          0 :                                 break;
     275                 :            : 
     276                 :            :                         {
     277                 :          0 :                         vector<string> parts = SplitWords(params, ' ');
     278                 :            : 
     279                 :            :                         // Remove nick name.
     280                 :          0 :                         parts.erase(parts.begin());
     281         [ #  # ]:          0 :                         if ( parts.size() < 2 )
     282                 :            :                                 {
     283                 :          0 :                                 Weird("irc_invalid_names_line");
     284                 :            :                                 return;
     285                 :            :                                 }
     286                 :            : 
     287                 :          0 :                         string type = parts[0];
     288                 :          0 :                         string channel = parts[1];
     289                 :            : 
     290                 :            :                         // Remove type and channel.
     291                 :          0 :                         parts.erase(parts.begin());
     292                 :          0 :                         parts.erase(parts.begin());
     293                 :            : 
     294   [ #  #  #  # ]:          0 :                         if ( parts.size() > 0 && parts[0][0] == ':' )
                 [ #  # ]
     295                 :          0 :                                 parts[0] = parts[0].substr(1);
     296                 :            : 
     297                 :          0 :                         val_list* vl = new val_list;
     298                 :          0 :                         vl->append(BuildConnVal());
     299                 :          0 :                         vl->append(new StringVal(type.c_str()));
     300                 :          0 :                         vl->append(new StringVal(channel.c_str()));
     301                 :            : 
     302                 :          0 :                         TableVal* set = new TableVal(string_set);
     303         [ #  # ]:          0 :                         for ( unsigned int i = 0; i < parts.size(); ++i )
     304                 :            :                                 {
     305         [ #  # ]:          0 :                                 if ( parts[i][0] == '@' )
     306                 :          0 :                                         parts[i] = parts[i].substr(1);
     307                 :          0 :                                 set->Assign(new StringVal(parts[i].c_str()), 0);
     308                 :            :                                 }
     309                 :          0 :                         vl->append(set);
     310                 :            : 
     311         [ #  # ]:          0 :                         ConnectionEvent(irc_names_info, vl);
     312                 :            :                         }
     313                 :          0 :                         break;
     314                 :            : 
     315                 :            :                 // Count of users and services on this server.
     316                 :            :                 case 255:
     317         [ #  # ]:          0 :                         if ( ! irc_server_info )
     318                 :          0 :                                 break;
     319                 :            : 
     320                 :            :                         {
     321                 :          0 :                         vector<string> parts = SplitWords(params, ' ');
     322                 :          0 :                         int users = 0;
     323                 :          0 :                         int services = 0;
     324                 :          0 :                         int servers = 0;
     325                 :            : 
     326         [ #  # ]:          0 :                         for ( unsigned int i = 1; i < parts.size(); ++i )
     327                 :            :                                 {
     328         [ #  # ]:          0 :                                 if ( parts[i] == "users," )
     329                 :          0 :                                         users = atoi(parts[i-1].c_str());
     330         [ #  # ]:          0 :                                 else if ( parts[i] == "clients" )
     331                 :          0 :                                         users = atoi(parts[i-1].c_str());
     332         [ #  # ]:          0 :                                 else if ( parts[i] == "services" )
     333                 :          0 :                                         services = atoi(parts[i-1].c_str());
     334         [ #  # ]:          0 :                                 else if ( parts[i] == "servers" )
     335                 :          0 :                                         servers = atoi(parts[i-1].c_str());
     336                 :            :                                 // else ###
     337                 :            :                                 }
     338                 :            : 
     339                 :          0 :                         val_list* vl = new val_list;
     340                 :          0 :                         vl->append(BuildConnVal());
     341                 :          0 :                         vl->append(new Val(users, TYPE_INT));
     342                 :          0 :                         vl->append(new Val(services, TYPE_INT));
     343                 :          0 :                         vl->append(new Val(servers, TYPE_INT));
     344                 :            : 
     345                 :          0 :                         ConnectionEvent(irc_server_info, vl);
     346                 :            :                         }
     347                 :          0 :                         break;
     348                 :            : 
     349                 :            :                 // Count of channels.
     350                 :            :                 case 254:
     351         [ #  # ]:          0 :                         if ( ! irc_channel_info )
     352                 :          0 :                                 break;
     353                 :            : 
     354                 :            :                         {
     355                 :          0 :                         vector<string> parts = SplitWords(params, ' ');
     356                 :          0 :                         int channels = 0;
     357         [ #  # ]:          0 :                         for ( unsigned int i = 1; i < parts.size(); ++i )
     358         [ #  # ]:          0 :                                 if ( parts[i] == ":channels" )
     359                 :          0 :                                         channels = atoi(parts[i - 1].c_str());
     360                 :            : 
     361                 :          0 :                         val_list* vl = new val_list;
     362                 :          0 :                         vl->append(BuildConnVal());
     363                 :          0 :                         vl->append(new Val(channels, TYPE_INT));
     364                 :            : 
     365                 :          0 :                         ConnectionEvent(irc_channel_info, vl);
     366                 :            :                         }
     367                 :          0 :                         break;
     368                 :            : 
     369                 :            :                 // RPL_GLOBALUSERS
     370                 :            :                 case 266:
     371                 :            :                         {
     372                 :            :                         // FIXME: We should really streamline all this
     373                 :            :                         // parsing code ...
     374         [ #  # ]:          0 :                         if ( ! irc_global_users )
     375                 :          0 :                                 break;
     376                 :            : 
     377                 :          0 :                         const char* prefix = params.c_str();
     378                 :            : 
     379                 :          0 :                         const char* eop = strchr(prefix, ' ');
     380         [ #  # ]:          0 :                         if ( ! eop )
     381                 :            :                                 {
     382                 :          0 :                                 Weird("invalid_irc_global_users_reply");
     383                 :          0 :                                 break;
     384                 :            :                                 }
     385                 :            : 
     386                 :          0 :                         const char *msg = strchr(++eop, ':');
     387         [ #  # ]:          0 :                         if ( ! msg )
     388                 :            :                                 {
     389                 :          0 :                                 Weird("invalid_irc_global_users_reply");
     390                 :          0 :                                 break;
     391                 :            :                                 }
     392                 :            : 
     393                 :          0 :                         val_list* vl = new val_list;
     394                 :          0 :                         vl->append(BuildConnVal());
     395                 :          0 :                         vl->append(new StringVal(eop - prefix, prefix));
     396                 :          0 :                         vl->append(new StringVal(++msg));
     397                 :          0 :                         ConnectionEvent(irc_global_users, vl);
     398                 :          0 :                         break;
     399                 :            :                         }
     400                 :            : 
     401                 :            :                 // WHOIS user reply line.
     402                 :            :                 case 311:
     403         [ #  # ]:          0 :                         if ( ! irc_whois_user_line )
     404                 :          0 :                                 break;
     405                 :            : 
     406                 :            :                         {
     407                 :          0 :                         vector<string> parts = SplitWords(params, ' ');
     408                 :            : 
     409         [ #  # ]:          0 :                         if ( parts.size() > 1 )
     410                 :          0 :                                 parts.erase(parts.begin());
     411         [ #  # ]:          0 :                         if ( parts.size() < 5 )
     412                 :            :                                 {
     413                 :          0 :                                 Weird("irc_invalid_whois_user_line");
     414                 :            :                                 return;
     415                 :            :                                 }
     416                 :            : 
     417                 :          0 :                         val_list* vl = new val_list;
     418                 :          0 :                         vl->append(BuildConnVal());
     419                 :          0 :                         vl->append(new StringVal(parts[0].c_str()));
     420                 :          0 :                         vl->append(new StringVal(parts[1].c_str()));
     421                 :          0 :                         vl->append(new StringVal(parts[2].c_str()));
     422                 :            : 
     423                 :          0 :                         parts.erase(parts.begin(), parts.begin() + 4);
     424                 :            : 
     425                 :          0 :                         string real_name = parts[0];
     426         [ #  # ]:          0 :                         for ( unsigned int i = 1; i < parts.size(); ++i )
     427                 :          0 :                                 real_name = real_name + " " + parts[i];
     428                 :            : 
     429         [ #  # ]:          0 :                         if ( real_name[0] == ':' )
     430                 :          0 :                                 real_name = real_name.substr(1);
     431                 :            : 
     432                 :          0 :                         vl->append(new StringVal(real_name.c_str()));
     433                 :            : 
     434         [ #  # ]:          0 :                         ConnectionEvent(irc_whois_user_line, vl);
     435                 :            :                         }
     436                 :          0 :                         break;
     437                 :            : 
     438                 :            :                 // WHOIS operator reply line.
     439                 :            :                 case 313:
     440         [ #  # ]:          0 :                         if ( ! irc_whois_operator_line )
     441                 :          0 :                                 break;
     442                 :            : 
     443                 :            :                         {
     444                 :          0 :                         vector<string> parts = SplitWords(params, ' ');
     445                 :            : 
     446         [ #  # ]:          0 :                         if ( parts.size() > 1 )
     447                 :          0 :                                 parts.erase(parts.begin());
     448                 :            : 
     449         [ #  # ]:          0 :                         if ( parts.size() < 2 )
     450                 :            :                                 {
     451                 :          0 :                                 Weird("irc_invalid_whois_operator_line");
     452                 :            :                                 return;
     453                 :            :                                 }
     454                 :            : 
     455                 :          0 :                         val_list* vl = new val_list;
     456                 :          0 :                         vl->append(BuildConnVal());
     457                 :          0 :                         vl->append(new StringVal(parts[0].c_str()));
     458                 :            : 
     459         [ #  # ]:          0 :                         ConnectionEvent(irc_whois_operator_line, vl);
     460                 :            :                         }
     461                 :          0 :                         break;
     462                 :            : 
     463                 :            :                 // WHOIS channel reply.
     464                 :            :                 case 319:
     465         [ #  # ]:          0 :                         if ( ! irc_whois_channel_line )
     466                 :          0 :                                 break;
     467                 :            : 
     468                 :            :                         {
     469                 :          0 :                         vector<string> parts = SplitWords(params, ' ');
     470                 :            : 
     471                 :            :                         // Remove nick name.
     472                 :          0 :                         parts.erase(parts.begin());
     473         [ #  # ]:          0 :                         if ( parts.size() < 2 )
     474                 :            :                                 {
     475                 :          0 :                                 Weird("irc_invalid_whois_channel_line");
     476                 :            :                                 return;
     477                 :            :                                 }
     478                 :            : 
     479                 :          0 :                         string nick = parts[0];
     480                 :          0 :                         parts.erase(parts.begin());
     481                 :            : 
     482   [ #  #  #  # ]:          0 :                         if ( parts.size() > 0 && parts[0][0] == ':' )
                 [ #  # ]
     483                 :          0 :                                 parts[0] = parts[0].substr(1);
     484                 :            : 
     485                 :          0 :                         val_list* vl = new val_list;
     486                 :          0 :                         vl->append(BuildConnVal());
     487                 :          0 :                         vl->append(new StringVal(nick.c_str()));
     488                 :          0 :                         TableVal* set = new TableVal(string_set);
     489         [ #  # ]:          0 :                         for ( unsigned int i = 0; i < parts.size(); ++i )
     490                 :            :                                 {
     491                 :          0 :                                 Val* idx = new StringVal(parts[i].c_str());
     492                 :          0 :                                 set->Assign(idx, 0);
     493                 :          0 :                                 Unref(idx);
     494                 :            :                                 }
     495                 :            : 
     496                 :          0 :                         vl->append(set);
     497                 :            : 
     498         [ #  # ]:          0 :                         ConnectionEvent(irc_whois_channel_line, vl);
     499                 :            :                         }
     500                 :          0 :                         break;
     501                 :            : 
     502                 :            :                 // RPL_TOPIC reply.
     503                 :            :                 case 332:
     504                 :            :                         {
     505         [ #  # ]:          0 :                         if ( ! irc_channel_topic )
     506                 :          0 :                                 break;
     507                 :            : 
     508                 :          0 :                         vector<string> parts = SplitWords(params, ' ');
     509         [ #  # ]:          0 :                         if ( parts.size() < 4 )
     510                 :            :                                 {
     511                 :          0 :                                 Weird("irc_invalid_topic_reply");
     512                 :            :                                 return;
     513                 :            :                                 }
     514                 :            : 
     515                 :          0 :                         unsigned int pos = params.find(':');
     516         [ #  # ]:          0 :                         if ( pos < params.size() )
     517                 :            :                                 {
     518                 :          0 :                                 string topic = params.substr(pos + 1);
     519                 :          0 :                                 val_list* vl = new val_list;
     520                 :            : 
     521                 :          0 :                                 vl->append(BuildConnVal());
     522                 :          0 :                                 vl->append(new StringVal(parts[1].c_str()));
     523                 :            : 
     524                 :          0 :                                 const char* t = topic.c_str();
     525         [ #  # ]:          0 :                                 if ( *t == ':' )
     526                 :          0 :                                         ++t;
     527                 :            : 
     528                 :          0 :                                 vl->append(new StringVal(t));
     529                 :            : 
     530                 :          0 :                                 ConnectionEvent(irc_channel_topic, vl);
     531                 :            :                                 }
     532                 :            :                         else
     533                 :            :                                 {
     534                 :          0 :                                 Weird("irc_invalid_topic_reply");
     535                 :            :                                 return;
     536                 :            :                                 }
     537         [ #  # ]:          0 :                         break;
     538                 :            :                         }
     539                 :            : 
     540                 :            :                 // WHO reply line.
     541                 :            :                 case 352:
     542         [ #  # ]:          0 :                         if ( ! irc_who_line )
     543                 :          0 :                                 break;
     544                 :            : 
     545                 :            :                         {
     546                 :          0 :                         vector<string> parts = SplitWords(params, ' ');
     547         [ #  # ]:          0 :                         if ( parts.size() < 9 )
     548                 :            :                                 {
     549                 :          0 :                                 Weird("irc_invalid_who_line");
     550                 :            :                                 return;
     551                 :            :                                 }
     552                 :            : 
     553                 :          0 :                         val_list* vl = new val_list;
     554                 :          0 :                         vl->append(BuildConnVal());
     555                 :          0 :                         vl->append(new StringVal(parts[0].c_str()));
     556                 :          0 :                         vl->append(new StringVal(parts[1].c_str()));
     557         [ #  # ]:          0 :                         if ( parts[2][0] == '~' )
     558                 :          0 :                                 parts[2] = parts[2].substr(1);
     559                 :          0 :                         vl->append(new StringVal(parts[2].c_str()));
     560                 :          0 :                         vl->append(new StringVal(parts[3].c_str()));
     561                 :          0 :                         vl->append(new StringVal(parts[4].c_str()));
     562                 :          0 :                         vl->append(new StringVal(parts[5].c_str()));
     563                 :          0 :                         vl->append(new StringVal(parts[6].c_str()));
     564         [ #  # ]:          0 :                         if ( parts[7][0] == ':' )
     565                 :          0 :                                 parts[7] = parts[7].substr(1);
     566                 :          0 :                         vl->append(new Val(atoi(parts[7].c_str()), TYPE_INT));
     567                 :          0 :                         vl->append(new StringVal(parts[8].c_str()));
     568                 :            : 
     569         [ #  # ]:          0 :                         ConnectionEvent(irc_who_line, vl);
     570                 :            :                         }
     571                 :          0 :                         break;
     572                 :            : 
     573                 :            :                 // Invalid nick name.
     574                 :            :                 case 431:
     575                 :            :                 case 432:
     576                 :            :                 case 433:
     577                 :            :                 case 436:
     578         [ #  # ]:          0 :                         if ( irc_invalid_nick )
     579                 :            :                                 {
     580                 :          0 :                                 val_list* vl = new val_list;
     581                 :          0 :                                 vl->append(BuildConnVal());
     582                 :          0 :                                 ConnectionEvent(irc_invalid_nick, vl);
     583                 :            :                                 }
     584                 :          0 :                         break;
     585                 :            : 
     586                 :            :                 // Operator responses.
     587                 :            :                 case 381:  // User is operator
     588                 :            :                 case 491:  // user is not operator
     589         [ #  # ]:          0 :                         if ( irc_oper_response )
     590                 :            :                                 {
     591                 :          0 :                                 val_list* vl = new val_list;
     592                 :          0 :                                 vl->append(BuildConnVal());
     593                 :          0 :                                 vl->append(new Val(code == 381, TYPE_BOOL));
     594                 :          0 :                                 ConnectionEvent(irc_oper_response, vl);
     595                 :            :                                 }
     596                 :          0 :                         break;
     597                 :            : 
     598                 :            :                 // All other server replies.
     599                 :            :                 default:
     600                 :          0 :                         val_list* vl = new val_list;
     601                 :          0 :                         vl->append(BuildConnVal());
     602                 :          0 :                         vl->append(new StringVal(prefix.c_str()));
     603                 :          0 :                         vl->append(new Val(code, TYPE_COUNT));
     604                 :          0 :                         vl->append(new StringVal(params.c_str()));
     605                 :            : 
     606                 :          0 :                         ConnectionEvent(irc_reply, vl);
     607                 :            :                         break;
     608                 :            :                 }
     609                 :            :                 return;
     610                 :            :                 }
     611                 :            : 
     612                 :            :         // Check if command is valid.
     613         [ #  # ]:          0 :         if ( command.size() > 20 )
     614                 :            :                 {
     615                 :          0 :                 Weird("irc_invalid_command");
     616         [ #  # ]:          0 :                 if ( ++invalid_msg_count > invalid_msg_max_count )
     617                 :            :                         {
     618                 :          0 :                         Weird("irc_too_many_invalid");
     619                 :          0 :                         ProtocolViolation("too many long lines");
     620                 :            :                         return;
     621                 :            :                         }
     622                 :            :                 return;
     623                 :            :                 }
     624                 :            : 
     625 [ #  # ][ #  # ]:          0 :         else if ( irc_privmsg_message && command == "PRIVMSG")
                 [ #  # ]
     626                 :            :                 {
     627                 :          0 :                 unsigned int pos = params.find(' ');
     628         [ #  # ]:          0 :                 if ( pos >= params.size() )
     629                 :            :                         {
     630                 :          0 :                         Weird("irc_invalid_privmsg_message_format");
     631                 :            :                         return;
     632                 :            :                         }
     633                 :            : 
     634                 :          0 :                 string target = params.substr(0, pos);
     635                 :          0 :                 string message = params.substr(pos + 1);
     636                 :            : 
     637   [ #  #  #  # ]:          0 :                 if ( message.size() > 0 && message[0] == ':' )
                 [ #  # ]
     638                 :          0 :                         message = message.substr(1);
     639 [ #  # ][ #  # ]:          0 :                 if ( message.size() > 0 && message[0] == 1 )
                 [ #  # ]
     640                 :          0 :                         message = message.substr(1); // DCC
     641                 :            : 
     642                 :            :                 // Check for DCC messages.
     643 [ #  # ][ #  # ]:          0 :                 if ( message.size() > 3 && message.substr(0, 3) == "DCC" )
         [ #  # ][ #  # ]
                 [ #  # ]
     644                 :            :                         {
     645 [ #  # ][ #  # ]:          0 :                         if ( message.size() > 0 &&
                 [ #  # ]
     646                 :            :                              message[message.size() - 1] == 1 )
     647                 :          0 :                                 message = message.substr(0, message.size() - 1);
     648                 :            : 
     649                 :          0 :                         vector<string> parts = SplitWords(message, ' ');
     650   [ #  #  #  # ]:          0 :                         if ( parts.size() < 5 || parts.size() > 6 )
                 [ #  # ]
     651                 :            :                                 {
     652                 :          0 :                                 Weird("irc_invalid_dcc_message_format");
     653                 :            :                                 return;
     654                 :            :                                 }
     655                 :            : 
     656                 :            :                         // Calculate IP address.
     657                 :          0 :                         uint32 raw_ip = 0;
     658         [ #  # ]:          0 :                         for ( unsigned int i = 0; i < parts[3].size(); ++i )
     659                 :            :                                 {
     660                 :          0 :                                 string s = parts[3].substr(i, 1);
     661                 :          0 :                                 raw_ip = (10 * raw_ip) + atoi(s.c_str());
     662                 :            :                                 }
     663                 :            : 
     664                 :          0 :                         val_list* vl = new val_list;
     665                 :          0 :                         vl->append(BuildConnVal());
     666                 :          0 :                         vl->append(new StringVal(prefix.c_str()));
     667                 :          0 :                         vl->append(new StringVal(target.c_str()));
     668                 :          0 :                         vl->append(new StringVal(parts[1].c_str()));
     669                 :          0 :                         vl->append(new StringVal(parts[2].c_str()));
     670                 :          0 :                         vl->append(new AddrVal(htonl(raw_ip)));
     671                 :          0 :                         vl->append(new Val(atoi(parts[4].c_str()), TYPE_INT));
     672         [ #  # ]:          0 :                         if ( parts.size() == 6 )
     673                 :            :                                 vl->append(new Val(atoi(parts[5].c_str()),
     674                 :          0 :                                                         TYPE_INT));
     675                 :            :                         else
     676                 :          0 :                                 vl->append(new Val(0, TYPE_INT));
     677                 :            : 
     678         [ #  # ]:          0 :                         ConnectionEvent(irc_dcc_message, vl);
     679                 :            :                         }
     680                 :            : 
     681                 :            :                 else
     682                 :            :                         {
     683                 :          0 :                         val_list* vl = new val_list;
     684                 :          0 :                         vl->append(BuildConnVal());
     685                 :          0 :                         vl->append(new StringVal(prefix.c_str()));
     686                 :          0 :                         vl->append(new StringVal(target.c_str()));
     687                 :          0 :                         vl->append(new StringVal(message.c_str()));
     688                 :            : 
     689                 :          0 :                         ConnectionEvent(irc_privmsg_message, vl);
     690 [ #  # ][ #  # ]:          0 :                         }
     691                 :            :                 }
     692                 :            : 
     693 [ #  # ][ #  # ]:          0 :         else if ( irc_notice_message && command == "NOTICE" )
                 [ #  # ]
     694                 :            :                 {
     695                 :          0 :                 unsigned int pos = params.find(' ');
     696         [ #  # ]:          0 :                 if ( pos >= params.size() )
     697                 :            :                         {
     698                 :          0 :                         Weird("irc_invalid_notice_message_format");
     699                 :            :                         return;
     700                 :            :                         }
     701                 :            : 
     702                 :          0 :                 string target = params.substr(0, pos);
     703                 :          0 :                 string message = params.substr(pos + 1);
     704         [ #  # ]:          0 :                 if ( message[0] == ':' )
     705                 :          0 :                         message = message.substr(1);
     706                 :            : 
     707                 :          0 :                 val_list* vl = new val_list;
     708                 :          0 :                 vl->append(BuildConnVal());
     709                 :          0 :                 vl->append(new StringVal(prefix.c_str()));
     710                 :          0 :                 vl->append(new StringVal(target.c_str()));
     711                 :          0 :                 vl->append(new StringVal(message.c_str()));
     712                 :            : 
     713                 :          0 :                 ConnectionEvent(irc_notice_message, vl);
     714                 :            :                 }
     715                 :            : 
     716 [ #  # ][ #  # ]:          0 :         else if ( irc_squery_message && command == "SQUERY" )
                 [ #  # ]
     717                 :            :                 {
     718                 :          0 :                 unsigned int pos = params.find(' ');
     719         [ #  # ]:          0 :                 if ( pos >= params.size() )
     720                 :            :                         {
     721                 :          0 :                         Weird("irc_invalid_squery_message_format");
     722                 :            :                         return;
     723                 :            :                         }
     724                 :            : 
     725                 :          0 :                 string target = params.substr(0, pos);
     726                 :          0 :                 string message = params.substr(pos + 1);
     727         [ #  # ]:          0 :                 if ( message[0] == ':' )
     728                 :          0 :                         message = message.substr(1);
     729                 :            : 
     730                 :          0 :                 val_list* vl = new val_list;
     731                 :          0 :                 vl->append(BuildConnVal());
     732                 :          0 :                 vl->append(new StringVal(prefix.c_str()));
     733                 :          0 :                 vl->append(new StringVal(target.c_str()));
     734                 :          0 :                 vl->append(new StringVal(message.c_str()));
     735                 :            : 
     736                 :          0 :                 ConnectionEvent(irc_squery_message, vl);
     737                 :            :                 }
     738                 :            : 
     739 [ #  # ][ #  # ]:          0 :         else if ( irc_user_message && command == "USER" )
                 [ #  # ]
     740                 :            :                 {
     741                 :            :                 // extract username and real name
     742                 :          0 :                 vector<string> parts = SplitWords(params, ' ');
     743                 :          0 :                 val_list* vl = new val_list;
     744                 :          0 :                 vl->append(BuildConnVal());
     745                 :            : 
     746         [ #  # ]:          0 :                 if ( parts.size() > 0 )
     747                 :          0 :                         vl->append(new StringVal(parts[0].c_str()));
     748                 :          0 :                 else vl->append(new StringVal(""));
     749                 :            : 
     750         [ #  # ]:          0 :                 if ( parts.size() > 1 )
     751                 :          0 :                         vl->append(new StringVal(parts[1].c_str()));
     752                 :          0 :                 else vl->append(new StringVal(""));
     753                 :            : 
     754         [ #  # ]:          0 :                 if ( parts.size() > 2 )
     755                 :          0 :                         vl->append(new StringVal(parts[2].c_str()));
     756                 :          0 :                 else vl->append(new StringVal(""));
     757                 :            : 
     758                 :          0 :                 string realname;
     759         [ #  # ]:          0 :                 for ( unsigned int i = 3; i < parts.size(); i++ )
     760                 :            :                         {
     761                 :          0 :                         realname += parts[i];
     762         [ #  # ]:          0 :                         if ( i > 3 )
     763                 :          0 :                                 realname += " ";
     764                 :            :                         }
     765                 :            : 
     766                 :          0 :                 const char* name = realname.c_str();
     767         [ #  # ]:          0 :                 vl->append(new StringVal(*name == ':' ? name + 1 : name));
     768                 :            : 
     769                 :          0 :                 ConnectionEvent(irc_user_message, vl);
     770                 :            :                 }
     771                 :            : 
     772 [ #  # ][ #  # ]:          0 :         else if ( irc_oper_message && command == "OPER" )
                 [ #  # ]
     773                 :            :                 {
     774                 :            :                 // extract username and password
     775                 :          0 :                 vector<string> parts = SplitWords(params, ' ');
     776         [ #  # ]:          0 :                 if ( parts.size() == 2 )
     777                 :            :                         {
     778                 :          0 :                         val_list* vl = new val_list;
     779                 :          0 :                         vl->append(BuildConnVal());
     780                 :          0 :                         vl->append(new StringVal(parts[0].c_str()));
     781                 :          0 :                         vl->append(new StringVal(parts[1].c_str()));
     782                 :            : 
     783                 :          0 :                         ConnectionEvent(irc_oper_message, vl);
     784                 :            :                         }
     785                 :            : 
     786                 :            :                 else
     787                 :          0 :                         Weird("irc_invalid_oper_message_format");
     788                 :            :                 }
     789                 :            : 
     790 [ #  # ][ #  # ]:          0 :         else if ( irc_kick_message && command == "KICK" )
                 [ #  # ]
     791                 :            :                 {
     792                 :            :                 // Extract channels, users and comment.
     793                 :          0 :                 vector<string> parts = SplitWords(params, ' ');
     794         [ #  # ]:          0 :                 if ( parts.size() <= 1 )
     795                 :            :                         {
     796                 :          0 :                         Weird("irc_invalid_kick_message_format");
     797                 :            :                         return;
     798                 :            :                         }
     799                 :            : 
     800                 :          0 :                 val_list* vl = new val_list;
     801                 :          0 :                 vl->append(BuildConnVal());
     802                 :          0 :                 vl->append(new StringVal(prefix.c_str()));
     803                 :          0 :                 vl->append(new StringVal(parts[0].c_str()));
     804                 :          0 :                 vl->append(new StringVal(parts[1].c_str()));
     805         [ #  # ]:          0 :                 if ( parts.size() > 2 )
     806                 :            :                         {
     807                 :          0 :                         string comment = parts[2];
     808         [ #  # ]:          0 :                         for ( unsigned int i = 3; i < parts.size(); ++i )
     809                 :          0 :                                 comment += " " + parts[i];
     810                 :            : 
     811         [ #  # ]:          0 :                         if ( comment[0] == ':' )
     812                 :          0 :                                 comment = comment.substr(1);
     813                 :            : 
     814                 :          0 :                         vl->append(new StringVal(comment.c_str()));
     815                 :            :                         }
     816                 :            :                 else
     817                 :          0 :                         vl->append(new StringVal(""));
     818                 :            : 
     819         [ #  # ]:          0 :                 ConnectionEvent(irc_kick_message, vl);
     820                 :            :                 }
     821                 :            : 
     822 [ #  # ][ #  # ]:          0 :         else if ( irc_join_message && command == "JOIN" )
                 [ #  # ]
     823                 :            :                 {
     824         [ #  # ]:          0 :                 if ( params[0] == ':' )
     825                 :          0 :                         params = params.substr(1);
     826                 :            : 
     827                 :          0 :                 vector<string> parts = SplitWords(params, ' ');
     828                 :            : 
     829         [ #  # ]:          0 :                 if ( parts.size() < 1 )
     830                 :            :                         {
     831                 :          0 :                         Weird("irc_invalid_join_line");
     832                 :            :                         return;
     833                 :            :                         }
     834                 :            : 
     835                 :          0 :                 string nickname = "";
     836         [ #  # ]:          0 :                 if ( prefix.size() > 0 )
     837                 :            :                         {
     838                 :          0 :                         unsigned int pos = prefix.find('!');
     839         [ #  # ]:          0 :                         if ( pos < prefix.size() )
     840                 :          0 :                                 nickname = prefix.substr(0, pos);
     841                 :            :                         }
     842                 :            : 
     843                 :          0 :                 val_list* vl = new val_list;
     844                 :          0 :                 vl->append(BuildConnVal());
     845                 :            : 
     846                 :          0 :                 TableVal* list = new TableVal(irc_join_list);
     847                 :          0 :                 vector<string> channels = SplitWords(parts[0], ',');
     848                 :          0 :                 vector<string> passwords;
     849                 :            : 
     850         [ #  # ]:          0 :                 if ( parts.size() > 1 )
     851                 :          0 :                         passwords = SplitWords(parts[1], ',');
     852                 :            : 
     853                 :          0 :                 string empty_string = "";
     854         [ #  # ]:          0 :                 for ( unsigned int i = 0; i < channels.size(); ++i )
     855                 :            :                         {
     856                 :          0 :                         RecordVal* info = new RecordVal(irc_join_info);
     857                 :          0 :                         info->Assign(0, new StringVal(nickname.c_str()));
     858                 :          0 :                         info->Assign(1, new StringVal(channels[i].c_str()));
     859         [ #  # ]:          0 :                         if ( i < passwords.size() )
     860                 :          0 :                                 info->Assign(2, new StringVal(passwords[i].c_str()));
     861                 :            :                         else
     862                 :          0 :                                 info->Assign(2, new StringVal(empty_string.c_str()));
     863                 :            :                         // User mode.
     864                 :          0 :                         info->Assign(3, new StringVal(empty_string.c_str()));
     865                 :          0 :                         list->Assign(info, 0);
     866                 :          0 :                         Unref(info);
     867                 :            :                         }
     868                 :            : 
     869                 :          0 :                 vl->append(list);
     870                 :            : 
     871         [ #  # ]:          0 :                 ConnectionEvent(irc_join_message, vl);
     872                 :            :                 }
     873                 :            : 
     874 [ #  # ][ #  # ]:          0 :         else if ( irc_join_message && command == "NJOIN" )
                 [ #  # ]
     875                 :            :                 {
     876                 :          0 :                 vector<string> parts = SplitWords(params, ' ');
     877         [ #  # ]:          0 :                 if ( parts.size() != 2 )
     878                 :            :                         {
     879                 :          0 :                         Weird("irc_invalid_njoin_line");
     880                 :            :                         return;
     881                 :            :                         }
     882                 :            : 
     883                 :          0 :                 string channel = parts[0];
     884         [ #  # ]:          0 :                 if ( parts[1][0] == ':' )
     885                 :          0 :                         parts[1] = parts[1].substr(1);
     886                 :            : 
     887                 :          0 :                 vector<string> users = SplitWords(parts[1], ',');
     888                 :            : 
     889                 :          0 :                 val_list* vl = new val_list;
     890                 :          0 :                 vl->append(BuildConnVal());
     891                 :            : 
     892                 :          0 :                 TableVal* list = new TableVal(irc_join_list);
     893                 :          0 :                 string empty_string = "";
     894                 :            : 
     895         [ #  # ]:          0 :                 for ( unsigned int i = 0; i < users.size(); ++i )
     896                 :            :                         {
     897                 :          0 :                         RecordVal* info = new RecordVal(irc_join_info);
     898                 :          0 :                         string nick = users[i];
     899                 :          0 :                         string mode = "none";
     900                 :            : 
     901         [ #  # ]:          0 :                         if ( nick[0] == '@' )
     902                 :            :                                 {
     903         [ #  # ]:          0 :                                 if ( nick[1] == '@' )
     904                 :            :                                         {
     905                 :          0 :                                         nick = nick.substr(2);
     906                 :          0 :                                         mode = "creator";
     907                 :            :                                         }
     908                 :            :                                 else
     909                 :            :                                         {
     910                 :          0 :                                         nick = nick.substr(1);
     911                 :          0 :                                         mode = "operator";
     912                 :            :                                         }
     913                 :            :                                 }
     914                 :            : 
     915         [ #  # ]:          0 :                         else if ( nick[0] == '+' )
     916                 :            :                                 {
     917                 :          0 :                                 nick = nick.substr(1);
     918                 :          0 :                                 mode = "voice";
     919                 :            :                                 }
     920                 :            : 
     921                 :          0 :                         info->Assign(0, new StringVal(nick.c_str()));
     922                 :          0 :                         info->Assign(1, new StringVal(channel.c_str()));
     923                 :            :                         // Password:
     924                 :          0 :                         info->Assign(2, new StringVal(empty_string.c_str()));
     925                 :            :                         // User mode:
     926                 :          0 :                         info->Assign(3, new StringVal(mode.c_str()));
     927                 :          0 :                         list->Assign(info, 0);
     928                 :          0 :                         Unref(info);
     929                 :            :                         }
     930                 :            : 
     931                 :          0 :                 vl->append(list);
     932                 :            : 
     933         [ #  # ]:          0 :                 ConnectionEvent(irc_join_message, vl);
     934                 :            :                 }
     935                 :            : 
     936 [ #  # ][ #  # ]:          0 :         else if ( irc_part_message && command == "PART" )
                 [ #  # ]
     937                 :            :                 {
     938                 :          0 :                 string channels = params;
     939                 :          0 :                 string message = "";
     940                 :          0 :                 unsigned int pos = params.find(' ');
     941                 :            : 
     942         [ #  # ]:          0 :                 if ( pos < params.size() )
     943                 :            :                         {
     944                 :          0 :                         channels = params.substr(0, pos);
     945         [ #  # ]:          0 :                         if ( params.size() > pos + 1 )
     946                 :          0 :                                 message = params.substr(pos + 1);
     947         [ #  # ]:          0 :                         if ( message[0] == ':' )
     948                 :          0 :                                 message = message.substr(1);
     949                 :            :                         }
     950                 :            : 
     951                 :          0 :                 string nick = prefix;
     952                 :          0 :                 pos = nick.find('!');
     953         [ #  # ]:          0 :                 if ( pos < nick.size() )
     954                 :          0 :                         nick = nick.substr(0, pos);
     955                 :            : 
     956                 :          0 :                 vector<string> channelList = SplitWords(channels, ',');
     957                 :          0 :                 TableVal* set = new TableVal(string_set);
     958                 :            : 
     959         [ #  # ]:          0 :                 for ( unsigned int i = 0; i < channelList.size(); ++i )
     960                 :            :                         {
     961                 :          0 :                         Val* idx = new StringVal(channelList[i].c_str());
     962                 :          0 :                         set->Assign(idx, 0);
     963                 :          0 :                         Unref(idx);
     964                 :            :                         }
     965                 :            : 
     966                 :          0 :                 val_list* vl = new val_list;
     967                 :          0 :                 vl->append(BuildConnVal());
     968                 :          0 :                 vl->append(new StringVal(nick.c_str()));
     969                 :          0 :                 vl->append(set);
     970                 :          0 :                 vl->append(new StringVal(message.c_str()));
     971                 :            : 
     972                 :          0 :                 ConnectionEvent(irc_part_message, vl);
     973                 :            :                 }
     974                 :            : 
     975 [ #  # ][ #  # ]:          0 :         else if ( irc_quit_message && command == "QUIT" )
                 [ #  # ]
     976                 :            :                 {
     977                 :          0 :                 string message = params;
     978         [ #  # ]:          0 :                 if ( message[0] == ':' )
     979                 :          0 :                         message = message.substr(1);
     980                 :            : 
     981                 :          0 :                 string nickname = "";
     982         [ #  # ]:          0 :                 if ( prefix.size() > 0 )
     983                 :            :                         {
     984                 :          0 :                         unsigned int pos = prefix.find('!');
     985         [ #  # ]:          0 :                         if ( pos < prefix.size() )
     986                 :          0 :                                 nickname = prefix.substr(0, pos);
     987                 :            :                         }
     988                 :            : 
     989                 :          0 :                 val_list* vl = new val_list;
     990                 :          0 :                 vl->append(BuildConnVal());
     991                 :          0 :                 vl->append(new StringVal(nickname.c_str()));
     992                 :          0 :                 vl->append(new StringVal(message.c_str()));
     993                 :            : 
     994                 :          0 :                 ConnectionEvent(irc_quit_message, vl);
     995                 :            :                 }
     996                 :            : 
     997 [ #  # ][ #  # ]:          0 :         else if ( irc_nick_message && command == "NICK" )
                 [ #  # ]
     998                 :            :                 {
     999                 :          0 :                 string nick = params;
    1000         [ #  # ]:          0 :                 if ( nick[0] == ':' )
    1001                 :          0 :                         nick = nick.substr(1);
    1002                 :            : 
    1003                 :          0 :                 val_list* vl = new val_list;
    1004                 :          0 :                 vl->append(BuildConnVal());
    1005                 :          0 :                 vl->append(new StringVal(prefix.c_str()));
    1006                 :          0 :                 vl->append(new StringVal(nick.c_str()));
    1007                 :            : 
    1008                 :          0 :                 ConnectionEvent(irc_nick_message, vl);
    1009                 :            :                 }
    1010                 :            : 
    1011 [ #  # ][ #  # ]:          0 :         else if ( irc_who_message && command == "WHO" )
                 [ #  # ]
    1012                 :            :                 {
    1013                 :          0 :                 vector<string> parts = SplitWords(params, ' ');
    1014   [ #  #  #  # ]:          0 :                 if ( parts.size() < 1 || parts.size() > 2 )
                 [ #  # ]
    1015                 :            :                         {
    1016                 :          0 :                         Weird("irc_invalid_who_message_format");
    1017                 :            :                         return;
    1018                 :            :                         }
    1019                 :            : 
    1020                 :          0 :                 bool oper = false;
    1021 [ #  # ][ #  # ]:          0 :                 if ( parts.size() == 2 && parts[1] == "o" )
                 [ #  # ]
    1022                 :          0 :                         oper = true;
    1023                 :            : 
    1024                 :            :                 // Remove ":" from mask.
    1025 [ #  # ][ #  # ]:          0 :                 if ( parts[0].size() > 0 && parts[0][0] == ':' )
                 [ #  # ]
    1026                 :          0 :                         parts[0] = parts[0].substr(1);
    1027                 :            : 
    1028                 :          0 :                 val_list* vl = new val_list;
    1029                 :          0 :                 vl->append(BuildConnVal());
    1030                 :          0 :                 vl->append(new StringVal(parts[0].c_str()));
    1031                 :          0 :                 vl->append(new Val(oper, TYPE_BOOL));
    1032                 :            : 
    1033         [ #  # ]:          0 :                 ConnectionEvent(irc_who_message, vl);
    1034                 :            :                 }
    1035                 :            : 
    1036 [ #  # ][ #  # ]:          0 :         else if ( irc_whois_message && command == "WHOIS" )
                 [ #  # ]
    1037                 :            :                 {
    1038                 :          0 :                 vector<string> parts = SplitWords(params, ' ');
    1039   [ #  #  #  # ]:          0 :                 if ( parts.size() < 1 || parts.size() > 2 )
                 [ #  # ]
    1040                 :            :                         {
    1041                 :          0 :                         Weird("irc_invalid_whois_message_format");
    1042                 :            :                         return;
    1043                 :            :                         }
    1044                 :            : 
    1045                 :          0 :                 string server = "";
    1046                 :          0 :                 string users = "";
    1047                 :            : 
    1048         [ #  # ]:          0 :                 if ( parts.size() == 2 )
    1049                 :            :                         {
    1050                 :          0 :                         server = parts[0];
    1051                 :          0 :                         users = parts[1];
    1052                 :            :                         }
    1053                 :            :                 else
    1054                 :          0 :                         users = parts[0];
    1055                 :            : 
    1056                 :          0 :                 val_list* vl = new val_list;
    1057                 :          0 :                 vl->append(BuildConnVal());
    1058                 :          0 :                 vl->append(new StringVal(server.c_str()));
    1059                 :          0 :                 vl->append(new StringVal(users.c_str()));
    1060                 :            : 
    1061         [ #  # ]:          0 :                 ConnectionEvent(irc_whois_message, vl);
    1062                 :            :                 }
    1063                 :            : 
    1064 [ #  # ][ #  # ]:          0 :         else if ( irc_error_message && command == "ERROR" )
                 [ #  # ]
    1065                 :            :                 {
    1066                 :          0 :                 val_list* vl = new val_list;
    1067                 :          0 :                 vl->append(BuildConnVal());
    1068                 :          0 :                 vl->append(new StringVal(prefix.c_str()));
    1069         [ #  # ]:          0 :                 if ( params[0] == ':' )
    1070                 :          0 :                         params = params.substr(1);
    1071                 :          0 :                 vl->append(new StringVal(params.c_str()));
    1072                 :            : 
    1073                 :          0 :                 ConnectionEvent(irc_error_message, vl);
    1074                 :            :                 }
    1075                 :            : 
    1076 [ #  # ][ #  # ]:          0 :         else if ( irc_invite_message && command == "INVITE" )
                 [ #  # ]
    1077                 :            :                 {
    1078                 :          0 :                 vector<string> parts = SplitWords(params, ' ');
    1079         [ #  # ]:          0 :                 if ( parts.size() == 2 )
    1080                 :            :                         { // remove ":" from channel
    1081 [ #  # ][ #  # ]:          0 :                         if ( parts[1].size() > 0 && parts[1][0] == ':' )
                 [ #  # ]
    1082                 :          0 :                                 parts[1] = parts[1].substr(1);
    1083                 :            : 
    1084                 :          0 :                         val_list* vl = new val_list;
    1085                 :          0 :                         vl->append(BuildConnVal());
    1086                 :          0 :                         vl->append(new StringVal(prefix.c_str()));
    1087                 :          0 :                         vl->append(new StringVal(parts[0].c_str()));
    1088                 :          0 :                         vl->append(new StringVal(parts[1].c_str()));
    1089                 :            : 
    1090                 :          0 :                         ConnectionEvent(irc_invite_message, vl);
    1091                 :            :                         }
    1092                 :            :                 else
    1093                 :          0 :                         Weird("irc_invalid_invite_message_format");
    1094                 :            :                 }
    1095                 :            : 
    1096 [ #  # ][ #  # ]:          0 :         else if ( irc_mode_message && command == "MODE" )
                 [ #  # ]
    1097                 :            :                 {
    1098         [ #  # ]:          0 :                 if ( params.size() > 0 )
    1099                 :            :                         {
    1100                 :          0 :                         val_list* vl = new val_list;
    1101                 :          0 :                         vl->append(BuildConnVal());
    1102                 :          0 :                         vl->append(new StringVal(prefix.c_str()));
    1103                 :          0 :                         vl->append(new StringVal(params.c_str()));
    1104                 :            : 
    1105                 :          0 :                         ConnectionEvent(irc_mode_message, vl);
    1106                 :            :                         }
    1107                 :            : 
    1108                 :            :                 else
    1109                 :          0 :                         Weird("irc_invalid_mode_message_format");
    1110                 :            :                 }
    1111                 :            : 
    1112 [ #  # ][ #  # ]:          0 :         else if ( irc_password_message && command == "PASS" )
                 [ #  # ]
    1113                 :            :                 {
    1114                 :          0 :                 val_list* vl = new val_list;
    1115                 :          0 :                 vl->append(BuildConnVal());
    1116                 :          0 :                 vl->append(new StringVal(params.c_str()));
    1117                 :          0 :                 ConnectionEvent(irc_password_message, vl);
    1118                 :            :                 }
    1119                 :            : 
    1120 [ #  # ][ #  # ]:          0 :         else if ( irc_squit_message && command == "SQUIT" )
                 [ #  # ]
    1121                 :            :                 {
    1122                 :          0 :                 string server = params;
    1123                 :          0 :                 string message = "";
    1124                 :            : 
    1125                 :          0 :                 unsigned int pos = params.find(' ');
    1126         [ #  # ]:          0 :                 if ( pos < params.size() )
    1127                 :            :                         {
    1128                 :          0 :                         server = params.substr(0, pos);
    1129                 :          0 :                         message = params.substr(pos + 1);
    1130         [ #  # ]:          0 :                         if ( message[0] == ':' )
    1131                 :          0 :                                 message = message.substr(1);
    1132                 :            :                         }
    1133                 :            : 
    1134                 :          0 :                 val_list* vl = new val_list;
    1135                 :          0 :                 vl->append(BuildConnVal());
    1136                 :          0 :                 vl->append(new StringVal(prefix.c_str()));
    1137                 :          0 :                 vl->append(new StringVal(server.c_str()));
    1138                 :          0 :                 vl->append(new StringVal(message.c_str()));
    1139                 :            : 
    1140                 :          0 :                 ConnectionEvent(irc_squit_message, vl);
    1141                 :            :                 }
    1142                 :            : 
    1143                 :            : 
    1144         [ #  # ]:          0 :         else if ( orig )
    1145                 :            :                 {
    1146         [ #  # ]:          0 :                 if ( irc_request )
    1147                 :            :                         {
    1148                 :          0 :                         val_list* vl = new val_list;
    1149                 :          0 :                         vl->append(BuildConnVal());
    1150                 :          0 :                         vl->append(new StringVal(prefix.c_str()));
    1151                 :          0 :                         vl->append(new StringVal(command.c_str()));
    1152                 :          0 :                         vl->append(new StringVal(params.c_str()));
    1153                 :            : 
    1154                 :          0 :                         ConnectionEvent(irc_request, vl);
    1155                 :            :                         }
    1156                 :            :                 }
    1157                 :            : 
    1158                 :            :         else
    1159                 :            :                 {
    1160         [ #  # ]:          0 :                 if ( irc_message )
    1161                 :            :                         {
    1162                 :          0 :                         val_list* vl = new val_list;
    1163                 :          0 :                         vl->append(BuildConnVal());
    1164                 :          0 :                         vl->append(new StringVal(prefix.c_str()));
    1165                 :          0 :                         vl->append(new StringVal(command.c_str()));
    1166                 :          0 :                         vl->append(new StringVal(params.c_str()));
    1167                 :            : 
    1168                 :          0 :                         ConnectionEvent(irc_message, vl);
    1169                 :            :                         }
    1170                 :            :                 }
    1171                 :            : 
    1172 [ #  # ][ #  # ]:          0 :         if ( orig_status == REGISTERED && resp_status == REGISTERED &&
         [ #  # ][ #  # ]
    1173                 :            :              orig_zip_status == ACCEPT_ZIP && resp_zip_status == ACCEPT_ZIP )
    1174                 :            :                 {
    1175                 :            : #ifdef HAVE_LIBZ
    1176                 :          0 :                 orig_zip_status = ZIP_LOADED;
    1177                 :          0 :                 resp_zip_status = ZIP_LOADED;
    1178                 :          0 :                 AddSupportAnalyzer(new ZIP_Analyzer(Conn(), true));
    1179                 :          0 :                 AddSupportAnalyzer(new ZIP_Analyzer(Conn(), false));
    1180                 :            : #else
    1181                 :            :                 run_time("IRC analyzer lacking libz support");
    1182                 :            :                 Remove();
    1183                 :            : #endif
    1184                 :            :                 }
    1185                 :            : 
    1186                 :          0 :         return;
    1187                 :            :         }
    1188                 :            : 
    1189                 :          0 : vector<string> IRC_Analyzer::SplitWords(const string input, const char split)
    1190                 :            :         {
    1191                 :          0 :         vector<string> words;
    1192                 :            : 
    1193         [ #  # ]:          0 :         if ( input.size() < 1 )
    1194                 :          0 :                 return words;
    1195                 :            : 
    1196                 :          0 :         unsigned int start = 0;
    1197                 :          0 :         unsigned int split_pos = 0;
    1198                 :            : 
    1199                 :            :         // Ignore split-characters at the line beginning.
    1200         [ #  # ]:          0 :         while ( input[start] == split )
    1201                 :            :                 {
    1202                 :          0 :                 ++start;
    1203                 :          0 :                 ++split_pos;
    1204                 :            :                 }
    1205                 :            : 
    1206                 :          0 :         string word = "";
    1207         [ #  # ]:          0 :         while ( (split_pos = input.find(split, start)) < input.size() )
    1208                 :            :                 {
    1209                 :          0 :                 word = input.substr(start, split_pos - start);
    1210   [ #  #  #  # ]:          0 :                 if ( word.size() > 0 && word[0] != split )
                 [ #  # ]
    1211                 :          0 :                         words.push_back(word);
    1212                 :            : 
    1213                 :          0 :                 start = split_pos + 1;
    1214                 :            :                 }
    1215                 :            : 
    1216                 :            :         // Add line end if needed.
    1217         [ #  # ]:          0 :         if ( start < input.size() )
    1218                 :            :                 {
    1219                 :          0 :                 word = input.substr(start, input.size() - start);
    1220                 :          0 :                 words.push_back(word);
    1221                 :            :                 }
    1222                 :            : 
    1223                 :          0 :         return words;
    1224 [ +  - ][ +  - ]:          6 :         }

Generated by: LCOV version 1.8