The InspIRCd Project
Home | Developers | Wiki | Forums | Bug Tracker | SVN | Download
Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

m_services.cpp

Go to the documentation of this file.
00001 /*       +------------------------------------+
00002  *       | Inspire Internet Relay Chat Daemon |
00003  *       +------------------------------------+
00004  *
00005  *  InspIRCd: (C) 2002-2008 InspIRCd Development Team
00006  * See: http://www.inspircd.org/wiki/index.php/Credits
00007  *
00008  * This program is free but copyrighted software; see
00009  *            the file COPYING for details.
00010  *
00011  * ---------------------------------------------------
00012  */
00013 
00014 #include "inspircd.h"
00015 
00016 static bool kludgeme = false;
00017 
00018 /* $ModDesc: Povides support for services +r user/chan modes and more */
00019 
00022 class Channel_r : public ModeHandler
00023 {
00024 
00025  public:
00026         Channel_r(InspIRCd* Instance) : ModeHandler(Instance, 'r', 0, 0, false, MODETYPE_CHANNEL, false) { }
00027 
00028         ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string &parameter, bool adding, bool)
00029         {
00030                 // only a u-lined server may add or remove the +r mode.
00031                 if ((ServerInstance->ULine(source->nick.c_str())) || (ServerInstance->ULine(source->server)) || (!*source->server || (source->nick.find('.') != std::string::npos)))
00032                 {
00033                         // Only change the mode if it's not redundant
00034                         if ((adding && !channel->IsModeSet('r')) || (!adding && channel->IsModeSet('r')))
00035                         {
00036                                 channel->SetMode('r',adding);
00037                                 return MODEACTION_ALLOW;
00038                         }
00039 
00040                         return MODEACTION_DENY;
00041                 }
00042                 else
00043                 {
00044                         source->WriteNumeric(500, "%s :Only a server may modify the +r channel mode", source->nick.c_str());
00045                         return MODEACTION_DENY;
00046                 }
00047         }
00048 };
00049 
00052 class User_r : public ModeHandler
00053 {
00054 
00055  public:
00056         User_r(InspIRCd* Instance) : ModeHandler(Instance, 'r', 0, 0, false, MODETYPE_USER, false) { }
00057 
00058         ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string &parameter, bool adding, bool)
00059         {
00060                 if ((kludgeme) || (ServerInstance->ULine(source->nick.c_str())) || (ServerInstance->ULine(source->server)) || (!*source->server || (source->nick.find('.') != std::string::npos)))
00061                 {
00062                         if ((adding && !dest->IsModeSet('r')) || (!adding && dest->IsModeSet('r')))
00063                         {
00064                                 dest->SetMode('r',adding);
00065                                 return MODEACTION_ALLOW;
00066                         }
00067                         return MODEACTION_DENY;
00068                 }
00069                 else
00070                 {
00071                         source->WriteNumeric(500, "%s :Only a server may modify the +r user mode", source->nick.c_str());
00072                         return MODEACTION_DENY;
00073                 }
00074         }
00075 };
00076 
00079 class Channel_R : public SimpleChannelModeHandler
00080 {
00081  public:
00082         Channel_R(InspIRCd* Instance) : SimpleChannelModeHandler(Instance, 'R') { }
00083 };
00084 
00087 class User_R : public SimpleUserModeHandler
00088 {
00089  public:
00090         User_R(InspIRCd* Instance) : SimpleUserModeHandler(Instance, 'R') { }
00091 };
00092 
00095 class Channel_M : public SimpleChannelModeHandler
00096 {
00097  public:
00098         Channel_M(InspIRCd* Instance) : SimpleChannelModeHandler(Instance, 'M') { }
00099 };
00100 
00103 class ModuleServices : public Module
00104 {
00105 
00106         Channel_r* m1;
00107         Channel_R* m2;
00108         Channel_M* m3;
00109         User_r* m4;
00110         User_R* m5;
00111  public:
00112         ModuleServices(InspIRCd* Me)
00113                 : Module(Me)
00114         {
00115 
00116                 m1 = new Channel_r(ServerInstance);
00117                 m2 = new Channel_R(ServerInstance);
00118                 m3 = new Channel_M(ServerInstance);
00119                 m4 = new User_r(ServerInstance);
00120                 m5 = new User_R(ServerInstance);
00121 
00122                 if (!ServerInstance->Modes->AddMode(m1) || !ServerInstance->Modes->AddMode(m2) || !ServerInstance->Modes->AddMode(m3)
00123                         || !ServerInstance->Modes->AddMode(m4) || !ServerInstance->Modes->AddMode(m5))
00124                 {
00125                         throw ModuleException("You cannot load m_services.so and m_services_account.so at the same time (or some other module has claimed our modes)!");
00126                 }
00127 
00128                 kludgeme = false;
00129                 Implementation eventlist[] = { I_OnWhois, I_OnUserPostNick, I_OnUserPreMessage, I_OnUserPreNotice, I_OnUserPreJoin };
00130                 ServerInstance->Modules->Attach(eventlist, this, 5);
00131         }
00132 
00133         /* <- :stitch.chatspike.net 307 w00t w00t :is a registered nick */
00134         virtual void OnWhois(User* source, User* dest)
00135         {
00136                 if (dest->IsModeSet('r'))
00137                 {
00138                         /* user is registered */
00139                         ServerInstance->SendWhoisLine(source, dest, 307, "%s %s :is a registered nick", source->nick.c_str(), dest->nick.c_str());
00140                 }
00141         }
00142 
00143 
00144         virtual void OnUserPostNick(User* user, const std::string &oldnick)
00145         {
00146                 /* On nickchange, if they have +r, remove it */
00147                 if (user->IsModeSet('r') && assign(user->nick) != oldnick)
00148                 {
00149                         std::vector<std::string> modechange;
00150                         modechange.push_back(user->nick);
00151                         modechange.push_back("-r");
00152                         kludgeme = true;
00153                         ServerInstance->SendMode(modechange,user);
00154                         kludgeme = false;
00155                 }
00156         }
00157 
00158         virtual int OnUserPreMessage(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list)
00159         {
00160                 if (!IS_LOCAL(user))
00161                         return 0;
00162 
00163                 if (target_type == TYPE_CHANNEL)
00164                 {
00165                         Channel* c = (Channel*)dest;
00166                         if ((c->IsModeSet('M')) && (!user->IsModeSet('r')))
00167                         {
00168                                 if ((ServerInstance->ULine(user->nick.c_str())) || (ServerInstance->ULine(user->server)))
00169                                 {
00170                                         // user is ulined, can speak regardless
00171                                         return 0;
00172                                 }
00173                                 // user messaging a +M channel and is not registered
00174                                 user->WriteNumeric(477, "%s %s :You need a registered nickname to speak on this channel", user->nick.c_str(), c->name.c_str());
00175                                 return 1;
00176                         }
00177                 }
00178                 if (target_type == TYPE_USER)
00179                 {
00180                         User* u = (User*)dest;
00181                         if ((u->IsModeSet('R')) && (!user->IsModeSet('r')))
00182                         {
00183                                 if ((ServerInstance->ULine(user->nick.c_str())) || (ServerInstance->ULine(user->server)))
00184                                 {
00185                                         // user is ulined, can speak regardless
00186                                         return 0;
00187                                 }
00188                                 // user messaging a +R user and is not registered
00189                                 user->WriteNumeric(477, "%s %s :You need a registered nickname to message this user", user->nick.c_str(), u->nick.c_str());
00190                                 return 1;
00191                         }
00192                 }
00193                 return 0;
00194         }
00195 
00196         virtual int OnUserPreNotice(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list)
00197         {
00198                 return OnUserPreMessage(user,dest,target_type,text,status, exempt_list);
00199         }
00200 
00201         virtual int OnUserPreJoin(User* user, Channel* chan, const char* cname, std::string &privs, const std::string &keygiven)
00202         {
00203                 if (chan)
00204                 {
00205                         if (chan->IsModeSet('R'))
00206                         {
00207                                 if (!user->IsModeSet('r'))
00208                                 {
00209                                         if ((ServerInstance->ULine(user->nick.c_str())) || (ServerInstance->ULine(user->server)))
00210                                         {
00211                                                 // user is ulined, won't be stopped from joining
00212                                                 return 0;
00213                                         }
00214                                         // joining a +R channel and not identified
00215                                         user->WriteNumeric(477, "%s %s :You need a registered nickname to join this channel", user->nick.c_str(), chan->name.c_str());
00216                                         return 1;
00217                                 }
00218                         }
00219                 }
00220                 return 0;
00221         }
00222 
00223         virtual ~ModuleServices()
00224         {
00225                 kludgeme = true;
00226                 ServerInstance->Modes->DelMode(m1);
00227                 ServerInstance->Modes->DelMode(m2);
00228                 ServerInstance->Modes->DelMode(m3);
00229                 ServerInstance->Modes->DelMode(m4);
00230                 ServerInstance->Modes->DelMode(m5);
00231                 delete m1;
00232                 delete m2;
00233                 delete m3;
00234                 delete m4;
00235                 delete m5;
00236         }
00237 
00238         virtual Version GetVersion()
00239         {
00240                 return Version("$Id: m_services.cpp 10379 2008-09-02 20:09:01Z brain $",VF_COMMON|VF_VENDOR,API_VERSION);
00241         }
00242 };
00243 
00244 
00245 MODULE_INIT(ModuleServices)