Logo Search packages:      
Sourcecode: sbnc version File versions  Download package

bool CIRCConnection::ParseLineArgV ( int  argc,
const char **  argv 
) [private]

ParseLineArgV

Parses and processes a line which was sent by the server.

Parameters:
argc number of tokens
argv the tokens

Definition at line 265 of file IRCConnection.cpp.

References AddChannel(), CChannel::AddUser(), CClientConnection::ChangeNick(), CChannel::ClearModes(), CCore::CreateTimer(), DelayJoinTimer, CUser::GetAutoModes(), CUser::GetAwayNick(), CUser::GetAwayText(), CChannel::GetBanlist(), GetChannel(), CUser::GetClientConnectionMultiplexer(), CUser::GetConfig(), GetCurrentNick(), CUser::GetDelayJoin(), CUser::GetDropModes(), CVector< Type >::GetLength(), CCore::GetModules(), CClientConnection::GetNick(), CObject< CIRCConnection, CUser >::GetOwner(), CConnection::GetSocket(), CObject< CIRCConnection, CUser >::GetUser(), IsNickPrefix(), JoinChannels(), CCore::Log(), CUser::Log(), CCore::LogUser(), m_Channels, m_CurrentNick, m_DelayJoinTimer, m_EatPong, m_ISupport, m_LastResponse, m_NickCatchTimer, m_Server, m_ServerFeat, m_ServerVersion, m_Site, m_State, m_Usermodes, ModuleEvent(), NickCatchTimer, CChannel::ParseModeChange(), CConfig::ReadInteger(), RemoveChannel(), CChannel::RemoveUser(), CUser::ScheduleReconnect(), CBanlist::SetBan(), CChannel::SetCreationTime(), CChannel::SetHasBans(), CChannel::SetHasNames(), CNick::SetIdleSince(), CChannel::SetModesValid(), CChannel::SetNoTopic(), CChannel::SetTopic(), CChannel::SetTopicNick(), CChannel::SetTopicStamp(), UpdateHostHelper(), UpdateWhoHelper(), and CConnection::WriteLine().

Referenced by ParseLine().

                                                              {
      CChannel *Channel;
      CClientConnection *Client;

      m_LastResponse = g_CurrentTime;

      if (argc < 2) {
            return true;
      }

      const char *Reply = argv[0];
      const char *Raw = argv[1];
      char *Nick = ::NickFromHostmask(Reply);
      int iRaw = atoi(Raw);

      bool b_Me = false;
      if (m_CurrentNick != NULL && Nick != NULL && strcasecmp(Nick, m_CurrentNick) == 0) {
            b_Me = true;
      }

      free(Nick);

      Client = GetOwner()->GetClientConnectionMultiplexer();

      // HASH values
      CHashCompare hashRaw(argv[1]);
      static CHashCompare hashPrivmsg("PRIVMSG");
      static CHashCompare hashNotice("NOTICE");
      static CHashCompare hashJoin("JOIN");
      static CHashCompare hashPart("PART");
      static CHashCompare hashKick("KICK");
      static CHashCompare hashNick("NICK");
      static CHashCompare hashQuit("QUIT");
      static CHashCompare hashMode("MODE");
      static CHashCompare hashTopic("TOPIC");
      static CHashCompare hashPong("PONG");
      // END of HASH values

      if (argc > 3 && iRaw == 433) {
            bool ReturnValue = ModuleEvent(argc, argv);

            if (ReturnValue) {
                  if (GetCurrentNick() == NULL) {
                        WriteLine("NICK :%s_", argv[3]);
                  }

                  if (m_NickCatchTimer == NULL) {
                        m_NickCatchTimer = new CTimer(30, false, NickCatchTimer, this);
                  }
            }

            return ReturnValue;
      } else if (argc > 3 && hashRaw == hashPrivmsg && Client == NULL) {
            const char *Host;
            const char *Dest = argv[2];
            char *Nick = ::NickFromHostmask(Reply);

            Channel = GetChannel(Dest);

            if (Channel != NULL) {
                  CNick *User = Channel->GetNames()->Get(Nick);

                  if (User != NULL) {
                        User->SetIdleSince(g_CurrentTime);
                  }
            }

            if (!ModuleEvent(argc, argv)) {
                  free(Nick);
                  return false;
            }

            /* don't log ctcp requests */
            if (argv[3][0] != '\1' && argv[3][strlen(argv[3]) - 1] != '\1' && Dest != NULL && Nick != NULL && m_CurrentNick != NULL && strcasecmp(Dest, m_CurrentNick) == 0 && strcasecmp(Nick, m_CurrentNick) != 0) {
                  char *Dup;
                  char *Delim;

                  Dup = strdup(Reply);

                  if (Dup == NULL) {
                        LOGERROR("strdup() failed.");

                        free(Nick);

                        return true;
                  }

                  Delim = strstr(Dup, "!");

                  if (Delim != NULL) {
                        *Delim = '\0';

                        Host = Delim + 1;
                  }

                  GetOwner()->Log("%s (%s): %s", Dup, Delim ? Host : "<unknown host>", argv[3]);

                  free(Dup);
            }

            free(Nick);

            UpdateHostHelper(Reply);

            return true;
      } else if (argc > 3 && hashRaw == hashNotice && Client == NULL) {
            const char *Dest = argv[2];
            char *Nick;
            
            if (!ModuleEvent(argc, argv)) {
                  return false;
            }

            Nick = ::NickFromHostmask(Reply);

            /* don't log ctcp replies */
            if (argv[3][0] != '\1' && argv[3][strlen(argv[3]) - 1] != '\1' && Dest != NULL && Nick != NULL && m_CurrentNick != NULL && strcasecmp(Dest, m_CurrentNick) == 0 && strcasecmp(Nick, m_CurrentNick) != 0) {
                  GetOwner()->Log("%s (notice): %s", Reply, argv[3]);
            }

            free(Nick);

            return true;
      } else if (argc > 2 && hashRaw == hashJoin) {
            if (b_Me) {
                  AddChannel(argv[2]);

                  /* GetOwner() can be NULL if AddChannel failed */
                  if (GetOwner() != NULL && Client == NULL) {
                        WriteLine("MODE %s", argv[2]);
                  }
            }

            Channel = GetChannel(argv[2]);

            if (Channel != NULL) {
                  Nick = NickFromHostmask(Reply);

                  if (Nick == NULL) {
                        LOGERROR("NickFromHostmask() failed.");

                        return false;
                  }

                  Channel->AddUser(Nick, '\0');
                  free(Nick);
            }

            UpdateHostHelper(Reply);
      } else if (argc > 2 && hashRaw == hashPart) {
            bool bRet = ModuleEvent(argc, argv);

            if (b_Me) {
                  RemoveChannel(argv[2]);
            } else {
                  Channel = GetChannel(argv[2]);

                  if (Channel != NULL) {
                        Nick = ::NickFromHostmask(Reply);

                        if (Nick == NULL) {
                              LOGERROR("NickFromHostmask() failed.");

                              return false;
                        }

                        Channel->RemoveUser(Nick);

                        free(Nick);
                  }
            }

            UpdateHostHelper(Reply);

            return bRet;
      } else if (argc > 3 && hashRaw == hashKick) {
            bool bRet = ModuleEvent(argc, argv);

            if (m_CurrentNick != NULL && strcasecmp(argv[3], m_CurrentNick) == 0) {
                  RemoveChannel(argv[2]);

                  if (Client == NULL) {
                        char *Dup = strdup(Reply);

                        if (Dup == NULL) {
                              LOGERROR("strdup() failed. Could not log event.");

                              return bRet;
                        }

                        char *Delim = strstr(Dup, "!");
                        const char *Host;

                        if (Delim) {
                              *Delim = '\0';

                              Host = Delim + 1;
                        }

                        GetOwner()->Log("%s (%s) kicked you from %s (%s)", Dup, Delim ? Host : "<unknown host>", argv[2], argc > 4 ? argv[4] : "");

                        free(Dup);
                  }
            } else {
                  Channel = GetChannel(argv[2]);

                  if (Channel != NULL) {
                        Channel->RemoveUser(argv[3]);
                  }
            }

            UpdateHostHelper(Reply);

            return bRet;
      } else if (argc > 2 && iRaw == 1) {
            if (Client != NULL) {
                  if (strcmp(Client->GetNick(), argv[2]) != 0) {
                        Client->WriteLine(":%s!ident@sbnc NICK :%s", Client->GetNick(), argv[2]);
                  }
            }

            ufree(m_CurrentNick);
            m_CurrentNick = ustrdup(argv[2]);

            ufree(m_Server);
            m_Server = ustrdup(Reply);

            if (GetBox() != NULL) {
                  safe_put_string(GetBox(), "Nick", argv[2]);
                  safe_put_string(GetBox(), "Server", Reply);
            }
      } else if (argc > 2 && hashRaw == hashNick) {
            if (b_Me) {
                  ufree(m_CurrentNick);
                  m_CurrentNick = ustrdup(argv[2]);

                  if (GetBox() != NULL) {
                        safe_put_string(GetBox(), "Nick", argv[2]);
                  }
            }

            Nick = NickFromHostmask(argv[0]);

            int i = 0;

            if (!b_Me && GetOwner()->GetClientConnectionMultiplexer() == NULL) {
                  const char *AwayNick = GetOwner()->GetAwayNick();

                  if (AwayNick != NULL && strcasecmp(AwayNick, Nick) == 0) {
                        WriteLine("NICK %s", AwayNick);
                  }
            }

            while (hash_t<CChannel *> *ChannelHash = m_Channels->Iterate(i++)) {
                  ChannelHash->Value->RenameUser(Nick, argv[2]);
            }

            free(Nick);
      } else if (argc > 1 && hashRaw == hashQuit) {
            bool bRet = ModuleEvent(argc, argv);

            Nick = NickFromHostmask(argv[0]);

            unsigned int i = 0;

            while (hash_t<CChannel *> *ChannelHash = m_Channels->Iterate(i++)) {
                  ChannelHash->Value->RemoveUser(Nick);
            }

            free(Nick);

            return bRet;
      } else if (argc > 1 && (iRaw == 422 || iRaw == 376)) {
            int DelayJoin = GetOwner()->GetDelayJoin();
            if (m_State != State_Connected) {
                  const CVector<CModule *> *Modules = g_Bouncer->GetModules();

                  for (unsigned int i = 0; i < Modules->GetLength(); i++) {
                        (*Modules)[i]->ServerLogon(GetOwner()->GetUsername());
                  }

                  const char *ClientNick;

                  if (Client != NULL) {
                        ClientNick = Client->GetNick();

                        if (strcmp(m_CurrentNick, ClientNick) != 0) {
                              Client->ChangeNick(m_CurrentNick);
                        }
                  }

                  GetOwner()->Log("You were successfully connected to an IRC server.");
                  g_Bouncer->Log("User %s connected to an IRC server.", GetOwner()->GetUsername());

                  if (GetBox() != NULL) {
                        safe_put_integer(GetBox(), "Socket", GetSocket());
                  }
            }

/*          if (Client != NULL && Client->GetPreviousNick() != NULL && strcmp(Client->GetPreviousNick(), m_CurrentNick) != 0) {
                  const char *Site = GetSite();

                  if (Site == NULL) {
                        Site = "unknown@host";
                  }

                  Client->WriteLine(":%s!%s NICK %s", Client->GetPreviousNick(), Site, m_CurrentNick);
            }*/

            if (DelayJoin == 1) {
                  m_DelayJoinTimer = g_Bouncer->CreateTimer(5, false, DelayJoinTimer, this);
            } else if (DelayJoin == 0) {
                  JoinChannels();
            }

            if (Client == NULL) {
                  bool AppendTS = (GetOwner()->GetConfig()->ReadInteger("user.ts") != 0);
                  const char *AwayReason = GetOwner()->GetAwayText();

                  if (AwayReason != NULL) {
                        WriteLine(AppendTS ? "AWAY :%s (Away since the dawn of time)" : "AWAY :%s", AwayReason);
                  }
            }

            const char *AutoModes = GetOwner()->GetAutoModes();
            const char *DropModes = GetOwner()->GetDropModes();

            if (AutoModes != NULL) {
                  WriteLine("MODE %s +%s", GetCurrentNick(), AutoModes);
            }

            if (DropModes != NULL && Client == NULL) {
                  WriteLine("MODE %s -%s", GetCurrentNick(), DropModes);
            }

            m_State = State_Connected;
      } else if (argc > 1 && strcasecmp(Reply, "ERROR") == 0) {
            if (strstr(Raw, "throttle") != NULL) {
                  GetOwner()->ScheduleReconnect(120);
            } else {
                  GetOwner()->ScheduleReconnect(5);
            }

            g_Bouncer->LogUser(GetUser(), "Error received for user %s: %s", GetOwner()->GetUsername(), argv[1]);
      } else if (argc > 3 && iRaw == 465) {
            g_Bouncer->LogUser(GetUser(), "G/K-line reason for user %s: %s", GetOwner()->GetUsername(), argv[3]);
      } else if (argc > 5 && iRaw == 351) {
            ufree(m_ServerVersion);
            m_ServerVersion = ustrdup(argv[3]);

            ufree(m_ServerFeat);
            m_ServerFeat = ustrdup(argv[5]);

            if (GetBox() != NULL) {
                  safe_put_string(GetBox(), "ServerVersion", argv[3]);
                  safe_put_string(GetBox(), "ServerFeatures", argv[5]);
            }
      } else if (argc > 3 && iRaw   == 5) {
            for (int i = 3; i < argc - 1; i++) {
                  char *Dup = strdup(argv[i]);

                  CHECK_ALLOC_RESULT(Dup, strdup) {
                        return false;
                  } CHECK_ALLOC_RESULT_END;

                  char *Eq = strstr(Dup, "=");

                  if (strcasecmp(Dup, "NAMESX") == 0) {
                        WriteLine("PROTOCTL NAMESX");
                  }

                  char *Value;

                  if (Eq) {
                        *Eq = '\0';

                        Value = ustrdup(++Eq);
                  } else {
                        Value = ustrdup("");
                  }

                  m_ISupport->Add(Dup, Value);

                  safe_box_t ISupportBox;

                  if (GetBox() != NULL) {
                        ISupportBox = safe_put_box(GetBox(), "ISupport");

                        if (ISupportBox != NULL) {
                              safe_put_string(ISupportBox, Dup, Value);
                        }
                  }

                  free(Dup);
            }
      } else if (argc > 4 && iRaw == 324) {
            Channel = GetChannel(argv[3]);

            if (Channel != NULL) {
                  Channel->ClearModes();
                  Channel->ParseModeChange(argv[0], argv[4], argc - 5, &argv[5]);
                  Channel->SetModesValid(true);
            }
      } else if (argc > 3 && hashRaw == hashMode) {
            Channel = GetChannel(argv[2]);

            if (Channel != NULL) {
                  Channel->ParseModeChange(argv[0], argv[3], argc - 4, &argv[4]);
            } else if (strcmp(m_CurrentNick, argv[2]) == 0) {
                  bool Flip = true, WasNull;
                  const char *Modes = argv[3];
                  size_t Length = strlen(Modes) + 1;

                  if (m_Usermodes != NULL) {
                        Length += strlen(m_Usermodes);
                  }

                  WasNull = (m_Usermodes != NULL) ? false : true;
                  m_Usermodes = (char *)urealloc(m_Usermodes, Length);

                  CHECK_ALLOC_RESULT(m_Usermodes, realloc) {
                        return false;
                  } CHECK_ALLOC_RESULT_END;

                  if (WasNull) {
                        m_Usermodes[0] = '\0';
                  }

                  while (*Modes != '\0') {
                        if (*Modes == '+') {
                              Flip = true;
                        } else if (*Modes == '-') {
                              Flip = false;
                        } else {
                              if (Flip) {
                                    size_t Position = strlen(m_Usermodes);
                                    m_Usermodes[Position] = *Modes;
                                    m_Usermodes[Position + 1] = '\0';
                              } else {
                                    char *CurrentModes = m_Usermodes;
                                    size_t a = 0;

                                    while (*CurrentModes != '\0') {
                                          *CurrentModes = m_Usermodes[a];

                                          if (*CurrentModes != *Modes) {
                                                CurrentModes++;
                                          }

                                          a++;
                                    }
                              }
                        }

                        Modes++;
                  }
            }

            UpdateHostHelper(Reply);
      } else if (argc > 4 && iRaw == 329) {
            Channel = GetChannel(argv[3]);

            if (Channel != NULL) {
                  Channel->SetCreationTime(atoi(argv[4]));
            }
      } else if (argc > 4 && iRaw == 332) {
            Channel = GetChannel(argv[3]);

            if (Channel != NULL) {
                  Channel->SetTopic(argv[4]);
            }
      } else if (argc > 5 && iRaw == 333) {
            Channel = GetChannel(argv[3]);

            if (Channel != NULL) {
                  Channel->SetTopicNick(argv[4]);
                  Channel->SetTopicStamp(atoi(argv[5]));
            }
      } else if (argc > 3 && iRaw == 331) {
            Channel = GetChannel(argv[3]);

            if (Channel != NULL) {
                  Channel->SetNoTopic();
            }
      } else if (argc > 3 && hashRaw == hashTopic) {
            Channel = GetChannel(argv[2]);

            if (Channel != NULL) {
                  Channel->SetTopic(argv[3]);
                  Channel->SetTopicStamp(g_CurrentTime);
                  Channel->SetTopicNick(argv[0]);
            }

            UpdateHostHelper(Reply);
      } else if (argc > 5 && iRaw == 353) {
            Channel = GetChannel(argv[4]);

            if (Channel != NULL) {
                  const char *nicks;
                  const char **nickv;

                  nicks = ArgTokenize(argv[5]);

                  CHECK_ALLOC_RESULT(nicks, ArgTokenize) {
                        return false;
                  } CHECK_ALLOC_RESULT_END;

                  nickv = ArgToArray(nicks);

                  CHECK_ALLOC_RESULT(nickv, ArgToArray) {
                        ArgFree(nicks);

                        return false;
                  } CHECK_ALLOC_RESULT_END;

                  int nickc = ArgCount(nicks);

                  for (int i = 0; i < nickc; i++) {
                        char *Nick = strdup(nickv[i]);
                        char *BaseNick = Nick;

                        CHECK_ALLOC_RESULT(Nick, strdup) {
                              ArgFree(nicks);

                              return false;
                        } CHECK_ALLOC_RESULT_END;

                        StrTrim(Nick);

                        while (IsNickPrefix(*Nick)) {
                              Nick++;
                        }

                        char *Modes = NULL;

                        if (BaseNick != Nick) {
                              Modes = (char *)malloc(Nick - BaseNick + 1);

                              CHECK_ALLOC_RESULT(Modes, malloc) {} else {
                                    strmcpy(Modes, BaseNick, Nick - BaseNick + 1);
                              } CHECK_ALLOC_RESULT_END;
                        }

                        Channel->AddUser(Nick, Modes);

                        free(BaseNick);
                        free(Modes);
                  }

                  ArgFreeArray(nickv);
                  ArgFree(nicks);
            }
      } else if (argc > 3 && iRaw == 366) {
            Channel = GetChannel(argv[3]);

            if (Channel != NULL) {
                  Channel->SetHasNames();
            }
      } else if (argc > 9 && iRaw == 352) {
            const char *Ident = argv[4];
            const char *Host = argv[5];
            const char *Server = argv[6];
            const char *Nick = argv[7];
            const char *Realname = argv[9];
            char *Mask;

            asprintf(&Mask, "%s!%s@%s", Nick, Ident, Host);

            UpdateHostHelper(Mask);
            UpdateWhoHelper(Nick, Realname, Server);

            free(Mask);
      } else if (argc > 6 && iRaw == 367) {
            Channel = GetChannel(argv[3]);

            if (Channel != NULL) {
                  Channel->GetBanlist()->SetBan(argv[4], argv[5], atoi(argv[6]));
            }
      } else if (argc > 3 && iRaw == 368) {
            Channel = GetChannel(argv[3]);

            if (Channel != NULL) {
                  Channel->SetHasBans();
            }
      } else if (argc > 3 && iRaw == 396) {
            ufree(m_Site);
            m_Site = ustrdup(argv[3]);

            if (m_Site == NULL) {
                  LOGERROR("ustrdup() failed.");
            }
      } else if (argc > 3 && hashRaw == hashPong && m_Server != NULL && strcasecmp(argv[3], m_Server) == 0 && m_EatPong) {
            m_EatPong = false;

            return false;
      }

      if (GetOwner() != NULL) {
            return ModuleEvent(argc, argv);
      } else {
            return true;
      }
}


Generated by  Doxygen 1.6.0   Back to index