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

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

ParseLineArgV

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

Parameters:
argc number of tokens in the line
argv tokenized line

Definition at line 1589 of file ClientConnection.cpp.

References CChannel::AreModesValid(), CChannel::GetBanlist(), CIRCConnection::GetChannel(), CChannel::GetChannelModes(), CUser::GetClientConnections(), CChannel::GetCreationTime(), CIRCConnection::GetCurrentNick(), CIRCConnection::GetHighestUserFlag(), CUser::GetIdent(), CUser::GetIRCConnection(), CIRCConnection::GetISupportAll(), CUser::GetKeyring(), CVector< Type >::GetLength(), CCore::GetModules(), CChannel::GetNames(), CNick::GetNick(), GetNick(), CObject< CClientConnection, CUser >::GetOwner(), CConnection::GetPeerCertificate(), CNick::GetPrefixes(), CIRCConnection::GetServer(), CIRCConnection::GetServerFeat(), CIRCConnection::GetServerVersion(), CIRCConnection::GetSite(), CChannel::GetTopic(), CChannel::GetTopicNick(), CChannel::GetTopicStamp(), CUser::GetUseQuitReason(), CUser::GetUsername(), CChannel::HasBans(), CChannel::HasNames(), CChannel::HasTopic(), CBanlist::Iterate(), Kill(), m_LastResponse, m_NamesXSupport, m_Nick, m_Password, m_PeerName, m_Username, ban_s::Mask, ban_s::Nick, ParseLine(), ProcessBncCommand(), CChannel::SendWhoReply(), CUser::SetAwayText(), CKeyring::SetKey(), CUser::SetNick(), ban_s::Timestamp, ValidateUser(), CConnection::WriteLine(), and WriteUnformattedLine().

Referenced by ParseLine().

                                                                 {
      char *Out;

      if (argc == 0) {
            return false;
      }

      m_LastResponse = g_CurrentTime;

      const CVector<CModule *> *Modules = g_Bouncer->GetModules();

      for (unsigned int i = 0; i < Modules->GetLength(); i++) {
            if (!(*Modules)[i]->InterceptClientMessage(this, argc, argv)) {
                  return false;
            }
      }

      const char *Command = argv[0];

      if (GetOwner() == NULL) {
            if (strcasecmp(Command, "nick") == 0 && argc > 1) {
                  const char *Nick = argv[1];

                  if (m_Nick != NULL) {
                        if (strcmp(m_Nick, Nick) != 0) {
                              WriteLine(":%s!ident@sbnc NICK :%s", m_Nick, Nick);
                        }
                  }

                  ufree(m_Nick);
                  m_Nick = ustrdup(Nick);

                  if (GetBox() != NULL) {
                        safe_put_string(GetBox(), "Nick", Nick);
                  }

                  if (m_Username != NULL && m_Password != NULL) {
                        ValidateUser();
                  } else if (m_Username != NULL) {
                        WriteUnformattedLine(":shroudbnc.info NOTICE AUTH :*** This server requires a password. Use /QUOTE PASS thepassword to supply a password now.");
                  }
            } else if (strcasecmp(Command, "pass") == 0) {
                  if (argc < 2) {
                        WriteLine(":shroudbnc.info 461 %s :Not enough parameters", m_Nick);
                  } else {
                        const char *ColonPtr = strchr(argv[1], ':');

                        if (ColonPtr != NULL) {
                              ufree(m_Username);

                              m_Username = ustrdup(argv[1]);
                              m_Username[ColonPtr - argv[1]] = '\0';

                              ufree(m_Password);
                              m_Password = ustrdup(ColonPtr + 1);
                        } else{
                              ufree(m_Password);
                              m_Password = ustrdup(argv[1]);
                        }
                  }

                  if (m_Nick != NULL && m_Username != NULL && m_Password != NULL) {
                        ValidateUser();
                  }

                  return false;
            } else if (strcasecmp(Command, "user") == 0 && argc > 1) {
                  if (m_Username) {
                        WriteLine(":shroudbnc.info 462 %s :You may not reregister", m_Nick);
                  } else {
                        if (!argv[1]) {
                              WriteLine(":shroudbnc.info 461 %s :Not enough parameters", m_Nick);
                        } else {
                              const char *Username = argv[1];

                              ufree(m_Username);
                              m_Username = ustrdup(Username);
                        }
                  }

                  bool ValidSSLCert = false;

                  if (m_Nick != NULL && m_Username != NULL) {
                        if (m_Password != NULL || GetPeerCertificate() != NULL) {
                              ValidSSLCert = ValidateUser();
                        }

                        if (m_Password == NULL && !ValidSSLCert) {
                              WriteUnformattedLine(":shroudbnc.info NOTICE AUTH :*** This server requires a password. Use /QUOTE PASS thepassword to supply a password now.");
                        }
                  }

                  return false;
            } else if (strcasecmp(Command, "quit") == 0) {
                  Kill("*** Thanks for flying with shroudBNC :P");

                  return false;
            }
      }

      if (GetOwner() != NULL) {
            if (strcasecmp(Command, "quit") == 0) {
                  char *QuitReason;
                  bool QuitAsAway = GetOwner()->GetUseQuitReason();

                  if (argc > 1 && argv[1][0] != '\0') {
                        if (QuitAsAway) {
                              GetOwner()->SetAwayText(argv[1]);
                        }

                        asprintf(&QuitReason, "Quit: %s", argv[1]);
                  } else {
                        asprintf(&QuitReason, "Quit");
                  }

                  CHECK_ALLOC_RESULT(QuitReason, asprintf) { } else {
                        SetQuitReason(QuitReason);

                        free(QuitReason);
                  } CHECK_ALLOC_RESULT_END;

                  Kill("*** Thanks for flying with shroudBNC :P");
                  return false;
            } else if (strcasecmp(Command, "nick") == 0) {
                  if (argc >= 2) {
                        ufree(m_Nick);
                        m_Nick = ustrdup(argv[1]);

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

                        GetOwner()->SetNick(argv[1]);
                  }
            } else if (argc > 1 && strcasecmp(Command, "join") == 0) {
                  CIRCConnection *IRC;
                  const char *Key;

                  if (argc > 2 && strstr(argv[0], ",") == NULL && strstr(argv[1], ",") == NULL) {
                        GetOwner()->GetKeyring()->SetKey(argv[1], argv[2]);
                  } else if (GetOwner()->GetKeyring() != NULL && (Key = GetOwner()->GetKeyring()->GetKey(argv[1])) != NULL && (IRC = GetOwner()->GetIRCConnection()) != NULL) {
                        IRC->WriteLine("JOIN %s %s", argv[1], Key);

                        return false;
                  }
            } else if (strcasecmp(Command, "whois") == 0) {
                  if (argc >= 2) {
                        const char *Nick = argv[1];

                        if (strcasecmp("-sbnc", Nick) == 0) {
                              WriteLine(":shroudbnc.info 311 %s -sBNC core shroudbnc.info * :shroudBNC", m_Nick);
                              WriteLine(":shroudbnc.info 312 %s -sBNC shroudbnc.info :shroudBNC IRC Proxy", m_Nick);
                              WriteLine(":shroudbnc.info 318 %s -sBNC :End of /WHOIS list.", m_Nick);

                              return false;
                        }
                  }
            } else if (argc > 2 && strcasecmp(Command, "privmsg") == 0 && strcasecmp(argv[1], "-sbnc") == 0) {
                  tokendata_t Tokens;
                  
                  Tokens = ArgTokenize2(argv[2]);

                  const char **Arr = ArgToArray2(Tokens);

                  ProcessBncCommand(Arr[0], ArgCount2(Tokens), Arr, false);

                  ArgFreeArray(Arr);

                  return false;
            } else if (argc > 2 && strcasecmp(Command, "privmsg") == 0) {
                  CVector<client_t> *Clients = GetOwner()->GetClientConnections();
                  const char *Site;

                  if (GetOwner()->GetIRCConnection() == NULL) {
                        return false;
                  }

                  Site = GetOwner()->GetIRCConnection()->GetSite();

                  if (strcasecmp(GetOwner()->GetNick(), argv[1]) == 0) {
                        WriteLine(":%s!%s PRIVMSG %s :%s", GetOwner()->GetNick(), Site, GetOwner()->GetNick(), argv[2]);

                        return false;
                  }

                  CChannel *Channel = GetOwner()->GetIRCConnection()->GetChannel(argv[1]);

                  for (unsigned int i = 0; i < Clients->GetLength(); i++) {
                        if ((*Clients)[i].Client != this) {
                              sockaddr *Remote = (*Clients)[i].Client->GetRemoteAddress();

                              if (Channel == NULL) {
                                    (*Clients)[i].Client->WriteLine(":%s!%s PRIVMSG %s :-> %s", argv[1], Site, GetOwner()->GetNick(), argv[2]);
                              } else {
                                    (*Clients)[i].Client->WriteLine(":%s!unknown@host PRIVMSG %s :%s", GetOwner()->GetNick(), argv[1], argv[2]);
                              }
                        }
                  }
            } else if (argc > 2 && strcasecmp(Command, "notice") == 0) {
                  if (GetOwner()->GetIRCConnection() == NULL) {
                        return false;
                  }

                  if (strcasecmp(GetOwner()->GetNick(), argv[1]) == 0) {
                        WriteLine(":%s!%s NOTICE %s :%s", GetOwner()->GetNick(), GetOwner()->GetIRCConnection()->GetSite(), GetOwner()->GetNick(), argv[2]);

                        return false;
                  }
            } else if (strcasecmp(Command, "userhost") == 0) {
                  if (argc == 2 && strcasecmp(argv[1], m_Nick) == 0) {
                        const char *Server, *Ident;
                        CIRCConnection *IRC;

                        IRC = GetOwner()->GetIRCConnection();

                        if (IRC != NULL) {
                              Server = IRC->GetServer();
                        } else {
                              Server = "bouncer";
                        }

                        Ident = GetOwner()->GetIdent();

                        if (Ident == NULL) {
                              Ident = GetOwner()->GetUsername();
                        }

                        WriteLine(":%s 302 %s :%s=+%s@%s", Server, m_Nick, m_Nick, Ident, m_PeerName);

                        return false;
                  }
            } else if (argc > 1 && strcasecmp(Command, "ping") == 0) {
                  if (GetOwner()->GetIRCConnection() == NULL) {
                        WriteLine(":shroudbnc.info PONG :%s", argv[1]);

                        return false;
                  }
            } else if (strcasecmp(Command, "protoctl") == 0) {
                  if (argc > 1 && strcasecmp(argv[1], "namesx") == 0) {
                        m_NamesXSupport = true;

                        return false;
                  }
            } else if (strcasecmp(Command, "sbnc") == 0) {
                  return ProcessBncCommand(argv[1], argc - 1, &argv[1], true);
            } else if (strcasecmp(Command, "synth") == 0) {
                  if (argc < 2) {
                        Privmsg("Syntax: SYNTH command parameter");
                        Privmsg("supported commands are: mode, topic, names, version, version-forcereply, who");

                        return false;
                  }

                  if (strcasecmp(argv[1], "mode") == 0 && argc > 2) {
                        CIRCConnection *IRC = GetOwner()->GetIRCConnection();

                        if (IRC) {
                              CChannel *Chan = IRC->GetChannel(argv[2]);

                              if (argc == 3) {
                                    if (Chan && Chan->AreModesValid()) {
                                          WriteLine(":%s 324 %s %s %s", IRC->GetServer(), IRC->GetCurrentNick(), argv[2], (const char *)Chan->GetChannelModes());
                                          WriteLine(":%s 329 %s %s %d", IRC->GetServer(), IRC->GetCurrentNick(), argv[2], Chan->GetCreationTime());
                                    } else
                                          IRC->WriteLine("MODE %s", argv[2]);
                              } else if (argc == 4 && strcmp(argv[3],"+b") == 0) {
                                    if (Chan && Chan->HasBans()) {
                                          CBanlist *Bans = Chan->GetBanlist();

                                          int i = 0; 

                                          while (const hash_t<ban_t *> *BanHash = Bans->Iterate(i++)) {
                                                ban_t *Ban = BanHash->Value;

                                                WriteLine(":%s 367 %s %s %s %s %d", IRC->GetServer(), IRC->GetCurrentNick(), argv[2], Ban->Mask, Ban->Nick, Ban->Timestamp);
                                          }

                                          WriteLine(":%s 368 %s %s :End of Channel Ban List", IRC->GetServer(), IRC->GetCurrentNick(), argv[2]);
                                    } else
                                          IRC->WriteLine("MODE %s +b", argv[2]);
                              }
                        }
                  } else if (strcasecmp(argv[1], "topic") == 0 && argc > 2) {
                        CIRCConnection *IRC = GetOwner()->GetIRCConnection();

                        if (IRC) {
                              CChannel *Chan = IRC->GetChannel(argv[2]);

                              if (Chan && Chan->HasTopic() != 0) {
                                    if (Chan->GetTopic() && *(Chan->GetTopic())) {
                                          WriteLine(":%s 332 %s %s :%s", IRC->GetServer(), IRC->GetCurrentNick(), argv[2], Chan->GetTopic());
                                          WriteLine(":%s 333 %s %s %s %d", IRC->GetServer(), IRC->GetCurrentNick(), argv[2], Chan->GetTopicNick(), Chan->GetTopicStamp());
                                    }
                              } else {
                                    IRC->WriteLine("TOPIC %s", argv[2]);
                              }
                        }
                  } else if (strcasecmp(argv[1], "names") == 0 && argc > 2) {
                        CIRCConnection *IRC = GetOwner()->GetIRCConnection();

                        if (IRC) {
                              CChannel *Chan = IRC->GetChannel(argv[2]);

                              if (Chan && Chan->HasNames() != 0) {
                                    char *Nicks = (char *)malloc(1);
                                    Nicks[0] = '\0';

                                    const CHashtable<CNick *, false, 64> *H = Chan->GetNames();

                                    int a = 0;

                                    while (hash_t<CNick *> *NickHash = H->Iterate(a++)) {
                                          size_t Size;
                                          CNick *NickObj = NickHash->Value;

                                          const char *Prefix = NickObj->GetPrefixes();
                                          const char *Nick = NickObj->GetNick();

                                          const char *outPref;
                                          char outPrefTemp[2] = { IRC->GetHighestUserFlag(Prefix), '\0' };

                                          if (m_NamesXSupport) {
                                                if (Prefix != NULL) {
                                                      outPref = Prefix;
                                                } else {
                                                      outPref = "";
                                                }
                                          } else {
                                                outPref = outPrefTemp;
                                          }

                                          if (Nick == NULL) {
                                                continue;
                                          }

                                          Size = (Nicks ? strlen(Nicks) : 0) + strlen(outPref) + strlen(Nick) + 2;
                                          Nicks = (char *)realloc(Nicks, Size);

                                          if (Nicks == NULL) {
                                                Kill("CClientConnection::ParseLineArgV: realloc() failed. Please reconnect.");

                                                return false;
                                          }

                                          if (Nicks[0] != '\0') {
                                                strmcat(Nicks, " ", Size);
                                          }

                                          strmcat(Nicks, outPref, Size);
                                          strmcat(Nicks, Nick, Size);

                                          if (strlen(Nicks) > 400) {
                                                WriteLine(":%s 353 %s = %s :%s", IRC->GetServer(), IRC->GetCurrentNick(), argv[2], Nicks);

                                                Nicks = (char *)realloc(Nicks, 1);

                                                if (Nicks == NULL) {
                                                      Kill("CClientConnection::ParseLineArgV: realloc() failed. Please reconnect.");

                                                      return false;
                                                }

                                                *Nicks = '\0';
                                          }
                                    }

                                    if (a) {
                                          WriteLine(":%s 353 %s = %s :%s", IRC->GetServer(), IRC->GetCurrentNick(), argv[2], Nicks);
                                    }

                                    free(Nicks);

                                    WriteLine(":%s 366 %s %s :End of /NAMES list.", IRC->GetServer(), IRC->GetCurrentNick(), argv[2]);
                              } else {
                                    IRC->WriteLine("NAMES %s", argv[2]);
                              }
                        }
                  } else if (strcasecmp(argv[1], "who") == 0 && argc > 2) {
                        CIRCConnection *IRC = GetOwner()->GetIRCConnection();

                        if (IRC) {
                              CChannel *Channel = IRC->GetChannel(argv[2]);

                              if (Channel && g_CurrentTime - GetOwner()->GetLastSeen() < 300 && Channel->SendWhoReply(this, true)) {
                                    Channel->SendWhoReply(this, false);
                              } else {
                                    IRC->WriteLine("WHO %s", argv[2]);
                              }
                        }
                  } else if ((strcasecmp(argv[1], "version") == 0 || strcasecmp(argv[1], "version-forcereply") == 0) && argc >= 2) {
                        CIRCConnection *IRC = GetOwner()->GetIRCConnection();

                        if (IRC != NULL) {
                              const char *ServerVersion = IRC->GetServerVersion();
                              const char *ServerFeat = IRC->GetServerFeat();

                              if (ServerVersion != NULL && ServerFeat != NULL) {
                                    WriteLine(":%s 351 %s %s %s :%s", IRC->GetServer(), IRC->GetCurrentNick(), ServerVersion, IRC->GetServer(), ServerFeat);
                              } else if (strcasecmp(argv[1], "version-forcereply") != 0) {
                                    IRC->WriteLine("VERSION");

                                    return false;
                              }

                              char *Feats = (char *)malloc(1);
                              Feats[0] = '\0';

                              int a = 0, i = 0;

                              while (hash_t<char *> *Feat = IRC->GetISupportAll()->Iterate(i++)) {
                                    size_t Size;
                                    char *Name = Feat->Name;
                                    char *Value = Feat->Value;

                                    Size = (Feats ? strlen(Feats) : 0) + strlen(Name) + 1 + strlen(Value) + 2;
                                    Feats = (char *)realloc(Feats, Size);

                                    if (Feats == NULL) {
                                          Kill("CClientConnection::ParseLineArgV: realloc() failed. Please reconnect.");

                                          return false;
                                    }


                                    if (Feats[0] != '\0') {
                                          strmcat(Feats, " ", Size);
                                    }

                                    strmcat(Feats, Name, Size);

                                    if (Value != NULL && Value[0] != '\0') {
                                          strmcat(Feats, "=", Size);
                                          strmcat(Feats, Value, Size);
                                    }

                                    if (++a == 11) {
                                          WriteLine(":%s 005 %s %s :are supported by this server", IRC->GetServer(), IRC->GetCurrentNick(), Feats);

                                          Feats = (char *)realloc(Feats, 1);

                                          if (Feats == NULL) {
                                                Kill("CClientConnection::ParseLineArgV: realloc() failed. Please reconnect.");

                                                return false;
                              
                                          }

                                          *Feats = '\0';
                                          a = 0;
                                    }
                              }

                              if (a > 0) {
                                    WriteLine(":%s 005 %s %s :are supported by this server", IRC->GetServer(), IRC->GetCurrentNick(), Feats);
                              }

                              free(Feats);
                        }
                  }

                  return false;
            } else if (strcasecmp(Command, "mode") == 0 || strcasecmp(Command, "topic") == 0 ||
                        strcasecmp(Command, "names") == 0 || strcasecmp(Command, "who") == 0) {
                  if (argc == 2 || (strcasecmp(Command, "mode") == 0 && argc == 3) && strcmp(argv[2],"+b") == 0) {
                        if (argc == 2) {
                              asprintf(&Out, "SYNTH %s :%s", argv[0], argv[1]);
                        } else {
                              asprintf(&Out, "SYNTH %s %s :%s", argv[0], argv[1], argv[2]);
                        }

                  CHECK_ALLOC_RESULT(Out, asprintf) {} else {
                        ParseLine(Out);
                        free(Out);
                  } CHECK_ALLOC_RESULT_END;

                        return false;
                  }
            } else if (strcasecmp(Command, "version") == 0) {
                  ParseLine("SYNTH VERSION");

                  return false;
            } else if (strcasecmp(Command, "pong") == 0 && argc > 1 && strcasecmp(argv[1], "sbnc") == 0) {
                  return false;
            }
      }

      return true;
}


Generated by  Doxygen 1.6.0   Back to index