]> arthur.barton.de Git - ngircd-alex.git/blob - contrib/Anope/0001-Revert-Removed-ngircd.patch
Add preliminary ngIRCd protocol module for Anope 1.9
[ngircd-alex.git] / contrib / Anope / 0001-Revert-Removed-ngircd.patch
1 From bc5023fdba8091ab7eee29fe0deeca6843159743 Mon Sep 17 00:00:00 2001
2 From: Alexander Barton <alex@barton.de>
3 Date: Mon, 16 May 2011 18:23:01 +0200
4 Subject: [PATCH 1/2] Revert "Removed ngircd as we've decided not to support it at this time"
5
6 This reverts commit 605b5d57171d2f0fac56ee2ee3e1b1bbdadeb24f and re-enables
7 the ngIRCd protocol module for Anope.
8 ---
9  modules/protocol/ngircd.cpp |  475 +++++++++++++++++++++++++++++++++++++++++++
10  1 files changed, 475 insertions(+), 0 deletions(-)
11  create mode 100644 modules/protocol/ngircd.cpp
12
13 diff --git a/modules/protocol/ngircd.cpp b/modules/protocol/ngircd.cpp
14 new file mode 100644
15 index 0000000..6e1f21f
16 --- /dev/null
17 +++ b/modules/protocol/ngircd.cpp
18 @@ -0,0 +1,475 @@
19 +/* ngIRCd IRCD functions
20 + *
21 + * (C) 2003-2011 Anope Team
22 + * Contact us at team@anope.org
23 + *
24 + * Please read COPYING and README for further details.
25 + *
26 + * Based on the original code of Epona by Lara.
27 + * Based on the original code of Services by Andy Church.
28 + */
29 +
30 +#include "services.h"
31 +#include "modules.h"
32 +
33 +IRCDVar myIrcd[] = {
34 +       {"ngIRCd",      /* ircd name */
35 +        "+oi",         /* Modes used by pseudoclients */
36 +        0,             /* SVSNICK */
37 +        0,             /* Vhost */
38 +        0,             /* Supports SNlines */
39 +        0,             /* Supports SQlines */
40 +        0,             /* Supports SZlines */
41 +        0,             /* Join 2 Message */
42 +        0,             /* Chan SQlines */
43 +        1,             /* Quit on Kill */
44 +        0,             /* vidents */
45 +        0,             /* svshold */
46 +        0,             /* time stamp on mode */
47 +        0,             /* UMODE */
48 +        0,             /* O:LINE */
49 +        0,             /* No Knock requires +i */
50 +        0,             /* Can remove User Channel Modes with SVSMODE */
51 +        0,             /* Sglines are not enforced until user reconnects */
52 +        0,             /* ts6 */
53 +        "$",           /* TLD Prefix for Global */
54 +        20,            /* Max number of modes we can send per line */
55 +        0,             /* IRCd sends a SSL users certificate fingerprint */
56 +        }
57 +       ,
58 +       {NULL}
59 +};
60 +
61 +/* PASS */
62 +class ngIRCdProto : public IRCDProto
63 +{
64 +       void SendAkill(User *u, const XLine *x)
65 +       {
66 +               if (SGLine && u == NULL)
67 +                       for (Anope::insensitive_map<User *>::iterator it = UserListByNick.begin(); it != UserListByNick.end();)
68 +                       {
69 +                               u = it->second;
70 +                               ++it;
71 +                               if (SGLine->Check(u) != NULL)
72 +                                       break;
73 +                       }
74 +       }
75 +
76 +       void SendAkillDel(const XLine*) { }
77 +
78 +       void SendGlobopsInternal(const BotInfo *source, const Anope::string &buf)
79 +       {
80 +               send_cmd(source ? source->nick : Config->ServerName, "WALLOPS :%s", buf.c_str());
81 +       }
82 +
83 +       void SendJoin(BotInfo *user, Channel *c, const ChannelStatus *status)
84 +       {
85 +               send_cmd(user->nick, "JOIN %s", c->name.c_str());
86 +               if (status)
87 +                       for (unsigned i = 0; i < ModeManager::ChannelModes.size(); ++i)
88 +                               if (status->HasFlag(ModeManager::ChannelModes[i]->Name))
89 +                                       c->SetMode(user, ModeManager::ChannelModes[i], user->nick, false);
90 +       }
91 +
92 +       void SendSVSKillInternal(const BotInfo *source, const User *user, const Anope::string &buf)
93 +       {
94 +               send_cmd(source ? source->nick : Config->ServerName, "KILL %s :%s", user->nick.c_str(), buf.c_str());
95 +       }
96 +
97 +       /* SERVER name hop descript */
98 +       void SendServer(const Server *server)
99 +       {
100 +               send_cmd("", "SERVER %s %d :%s", server->GetName().c_str(), server->GetHops(), server->GetDescription().c_str());
101 +       }
102 +
103 +       void SendConnect()
104 +       {
105 +               send_cmd("", "PASS %s 0210-IRC+ Anope|%s:CLHSo P", uplink_server->password.c_str(), Anope::VersionShort().c_str());
106 +               /* Make myself known to myself in the serverlist */
107 +               SendServer(Me);
108 +               /* finish the enhanced server handshake and register the connection */
109 +               this->SendNumeric(Config->ServerName, 376, "*", ":End of MOTD command");
110 +       }
111 +
112 +       // Received: :dev.anope.de NICK DukeP 1 ~DukePyro p57ABF9C9.dip.t-dialin.net 1 +i :DukePyrolator
113 +       void SendClientIntroduction(const User *u, const Anope::string &modes)
114 +       {
115 +               EnforceQlinedNick(u->nick, "");
116 +               send_cmd(Config->ServerName, "NICK %s 1 %s %s 1 %s :%s", u->nick.c_str(), u->GetIdent().c_str(), u->host.c_str(), modes.c_str(), u->realname.c_str());
117 +       }
118 +
119 +       void SendPartInternal(const BotInfo *bi, const Channel *chan, const Anope::string &buf)
120 +       {
121 +               if (!buf.empty())
122 +                       send_cmd(bi->nick, "PART %s :%s", chan->name.c_str(), buf.c_str());
123 +               else
124 +                       send_cmd(bi->nick, "PART %s", chan->name.c_str());
125 +       }
126 +
127 +       void SendModeInternal(const BotInfo *bi, const Channel *dest, const Anope::string &buf)
128 +       {
129 +               send_cmd(bi ? bi->nick : Config->ServerName, "MODE %s %s", dest->name.c_str(), buf.c_str());
130 +       }
131 +
132 +       void SendModeInternal(const BotInfo *bi, const User *u, const Anope::string &buf)
133 +       {
134 +               send_cmd(bi ? bi->nick : Config->ServerName, "MODE %s %s", u->nick.c_str(), buf.c_str());
135 +       }
136 +
137 +       void SendKickInternal(const BotInfo *bi, const Channel *chan, const User *user, const Anope::string &buf)
138 +       {
139 +               if (!buf.empty())
140 +                       send_cmd(bi->nick, "KICK %s %s :%s", chan->name.c_str(), user->nick.c_str(), buf.c_str());
141 +               else
142 +                       send_cmd(bi->nick, "KICK %s %s", chan->name.c_str(), user->nick.c_str());
143 +       }
144 +
145 +       void SendNoticeChanopsInternal(const BotInfo *source, const Channel *dest, const Anope::string &buf)
146 +       {
147 +               send_cmd(source ? source->nick : Config->s_ChanServ, "NOTICE @%s :%s", dest->name.c_str(), buf.c_str());
148 +       }
149 +
150 +       /* INVITE */
151 +       void SendInvite(BotInfo *source, const Anope::string &chan, const Anope::string &nick)
152 +       {
153 +               send_cmd(source->nick, "INVITE %s %s", nick.c_str(), chan.c_str());
154 +       }
155 +
156 +       void SendChannel(Channel *c)
157 +       {
158 +               Anope::string mlock_modes = get_mlock_modes(c->ci, true);
159 +               if (mlock_modes.empty())
160 +                       mlock_modes = "+";
161 +               send_cmd(Config->ServerName, "CHANINFO %s %s", c->name.c_str(), mlock_modes.c_str());
162 +       }
163 +       void SendTopic(BotInfo *bi, Channel *c)
164 +       {
165 +               send_cmd(bi->nick, "TOPIC %s :%s", c->name.c_str(), c->topic.c_str());
166 +       }
167 +};
168 +
169 +class ngIRCdIRCdMessage : public IRCdMessage
170 +{
171 + public:
172 +       bool OnSJoin(const Anope::string&, const std::vector<Anope::string>&) { return false; }
173 +
174 +       /*
175 +        * Received: :dev.anope.de MODE #anope +b *!*@*aol*
176 +        */
177 +       bool OnMode(const Anope::string &source, const std::vector<Anope::string> &params)
178 +       {
179 +               if (params.size() < 2)
180 +                       return true;
181 +
182 +               Anope::string modes = params[1];
183 +               for (unsigned i = 2; i < params.size(); ++i)
184 +                       modes += " " + params[i];
185 +
186 +               if (params[0][0] == '#' || params[0][0] == '&')
187 +                       do_cmode(source, params[0], modes, "");
188 +               else
189 +                       do_umode(params[0], params[1]);
190 +
191 +               return true;
192 +       }
193 +
194 +       /*
195 +         Received: :DukeP_ NICK :test2
196 +         Received: :dev.anope.de NICK DukeP_ 1 ~DukePyro ip-2-201-236-154.web.vodafone.de 1 + :DukePyrolator
197 +         source = nickname on nickchange, servername on newuser
198 +         params[0] = nick
199 +         params[1] = <unknown>
200 +         params[2] = username
201 +         params[3] = host
202 +         params[4] = <unknown>
203 +         params[5] = modes
204 +         params[6] = info
205 +       */
206 +       bool OnNick(const Anope::string &source, const std::vector<Anope::string> &params)
207 +       {
208 +               if (params.size() == 1)
209 +               {
210 +                       // we have a nickchange
211 +                       do_nick(source, params[0], "", "", "", "", Anope::CurTime, "", "", "", "");
212 +               }
213 +               else if (params.size() == 7)
214 +               {
215 +                       // a new user is connecting to the network
216 +                       User *user = do_nick("", params[0], params[2], params[3], source, params[6], Anope::CurTime, "", "", "", params[5]);
217 +                       if (user)
218 +                               validate_user(user);
219 +               }
220 +               else
221 +               {
222 +                       Log() << "Received NICK with invalid number of parameters. source = " << source << "param[0] = " << params[0] << "params.size() = " << params.size();
223 +               }
224 +               return true;
225 +       }
226 +
227 +       bool OnServer(const Anope::string &source, const std::vector<Anope::string> &params)
228 +       {
229 +               if (params.size() == 3)
230 +                       do_server("", params[0], 0, params[2], params[1]);
231 +               else
232 +                       do_server(source, params[0], params[1].is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0, params[3], params[2]);
233 +               return true;
234 +       }
235 +
236 +       bool OnTopic(const Anope::string &source, const std::vector<Anope::string> &params)
237 +       {
238 +               Channel *c = findchan(params[0]);
239 +               if (!c)
240 +               {
241 +                       Log() << "TOPIC for nonexistant channel " << params[0];
242 +                       return true;
243 +               }
244 +
245 +               c->ChangeTopicInternal(source, params[1]);
246 +               return true;
247 +       }
248 +
249 +       /*
250 +        * <@po||ux> DukeP: RFC 2813, 4.2.1: the JOIN command on server-server links
251 +        * separates the modes ("o") with ASCII 7, not space. And you can't see ASCII 7.
252 +        *
253 +        * if a user joins a new channel, the ircd sends <channelname>\7<umode>
254 +        */
255 +       bool OnJoin (const Anope::string &source, const std::vector<Anope::string> &params)
256 +       {
257 +               if (!params.empty())
258 +               {
259 +                       size_t pos = params[0].find('\7');
260 +                       if (pos != Anope::string::npos)
261 +                       {
262 +                               Anope::string channel = params[0].substr(0, pos);
263 +                               Anope::string mode = '+' + params[0].substr(pos, params[0].length()) + " " + source;
264 +                               do_join(source, channel, "");
265 +                               do_cmode(source, channel, mode, "");
266 +                       }
267 +                       else
268 +                               do_join(source, params[0], "");
269 +               }
270 +               return true;
271 +       }
272 +};
273 +
274 +/*
275 + * CHANINFO <chan> +<modes>
276 + * CHANINFO <chan> +<modes> :<topic>
277 + * CHANINFO <chan> +<modes> <key> <limit> :<topic>
278 + */
279 +bool event_chaninfo(const Anope::string &source, const std::vector<Anope::string> &params)
280 +{
281 +
282 +       Channel *c = findchan(params[0]);
283 +       if (!c)
284 +               c = new Channel(params[0]);
285 +
286 +       Anope::string modes = params[1];
287 +       
288 +       if (params.size() == 3)
289 +       {
290 +               c->ChangeTopicInternal(source, params[2], Anope::CurTime);
291 +       } 
292 +       else if (params.size() == 5)
293 +       {
294 +               for (size_t i = 0, end = params[1].length(); i < end; ++i)
295 +               {
296 +                       switch(params[1][i])
297 +                       {
298 +                               case 'k':
299 +                                       modes += " " + params[2];
300 +                                       continue;
301 +                               case 'l':
302 +                                       modes += " " + params[3];
303 +                                       continue;
304 +                       }
305 +               }
306 +               c->ChangeTopicInternal(source, params[4], Anope::CurTime);
307 +       }
308 +
309 +       c->SetModesInternal(NULL, modes);
310 +
311 +       return true;
312 +}
313 +
314 +/*
315 + * Received: :dev.anope.de NJOIN #test :DukeP2,@DukeP
316 + */
317 +bool event_njoin(const Anope::string &source, const std::vector<Anope::string> &params)
318 +{
319 +       Channel *c = findchan(params[0]);
320 +       commasepstream sep(params[1]);
321 +       Anope::string buf;
322 +
323 +       if (!c)
324 +       {
325 +               c = new Channel(params[0], Anope::CurTime);
326 +               c->SetFlag(CH_SYNCING);
327 +       }
328 +       
329 +       while (sep.GetToken(buf))
330 +       {
331 +               std::list<ChannelMode *> Status;
332 +               char ch;
333 +
334 +               /* Get prefixes from the nick */
335 +               while ((ch = ModeManager::GetStatusChar(buf[0])))
336 +               {
337 +                       buf.erase(buf.begin());
338 +                       ChannelMode *cm = ModeManager::FindChannelModeByChar(ch);
339 +                       if (!cm)
340 +                       {
341 +                               Log() << "Received unknown mode prefix " << ch << " in NJOIN string.";
342 +                               continue;
343 +                       }
344 +                       Status.push_back(cm);
345 +               }
346 +               User *u = finduser(buf);
347 +               if (!u)
348 +               {
349 +                       Log(LOG_DEBUG) << "NJOIN for nonexistant user " << buf << " on " << c->name;
350 +                       continue;
351 +               }
352 +
353 +               EventReturn MOD_RESULT;
354 +               FOREACH_RESULT(I_OnPreJoinChannel, OnPreJoinChannel(u, c));
355 +
356 +               /* Add the user to the Channel */
357 +               c->JoinUser(u);
358 +
359 +               /* Update their status internally on the channel
360 +                * This will enforce secureops etc on the user
361 +                */
362 +               for (std::list<ChannelMode *>::iterator it = Status.begin(), it_end = Status.end(); it != it_end; ++it)
363 +                       c->SetModeInternal(*it, buf);
364 +               /* Now set whatever modes this user is allowed to have on the channel */
365 +               chan_set_correct_modes(u, c, 1);
366 +
367 +               /* Check to see if modules want the user to join, if they do
368 +                * check to see if they are allowed to join (CheckKick will kick/ban them)
369 +                * Don't trigger OnJoinChannel event then as the user will be destroyed
370 +                */
371 +               if (MOD_RESULT != EVENT_STOP && c->ci && c->ci->CheckKick(u))
372 +                       continue;
373 +
374 +               FOREACH_MOD(I_OnJoinChannel, OnJoinChannel(u, c));
375 +       } /* while */
376 +
377 +       if (c->HasFlag(CH_SYNCING))
378 +       {
379 +               c->UnsetFlag(CH_SYNCING);
380 +               c->Sync();
381 +       }
382 +
383 +       return true;
384 +}
385 +
386 +bool event_kick(const Anope::string &source, const std::vector<Anope::string> &params)
387 +{
388 +       if (params.size() > 2)
389 +               do_kick(source, params[0], params[1], params[2]);
390 +       return true;
391 +}
392 +
393 +bool event_pass(const Anope::string &source, const std::vector<Anope::string> &params)
394 +{
395 +       return true;
396 +}
397 +
398 +bool event_005(const Anope::string &source, const std::vector<Anope::string> &params)
399 +{
400 +       size_t pos;
401 +       Anope::string name, data;
402 +       for (unsigned i = 0, end = params.size(); i < end; ++i)
403 +       {
404 +               pos = params[i].find('=');
405 +               if (pos != Anope::string::npos)
406 +               {
407 +                       name = params[i].substr(0, pos);
408 +                       data = params[i].substr(pos+1, params[i].length());
409 +                       if (name == "NICKLEN")
410 +                       {
411 +                               unsigned newlen = convertTo<unsigned>(data);
412 +                               if (Config->NickLen != newlen)
413 +                               {
414 +                                       Log() << "Config->NickLen changed from " << Config->NickLen << " to " << newlen;
415 +                                       Config->NickLen = newlen;
416 +                               }
417 +                       }
418 +               }
419 +       }
420 +       return true;
421 +}
422 +
423 +bool event_442(const Anope::string &source, const std::vector<Anope::string> &params)
424 +{
425 +       return true;
426 +}
427 +
428 +bool event_376(const Anope::string &source, const std::vector<Anope::string> &params)
429 +{
430 +       return true;
431 +}
432 +
433 +
434 +class ProtongIRCd : public Module
435 +{
436 +       Message message_kick, message_pass, message_njoin, message_chaninfo, message_005, 
437 +               message_442, message_376;
438 +       
439 +       ngIRCdProto ircd_proto;
440 +       ngIRCdIRCdMessage ircd_message;
441 +
442 +       void AddModes()
443 +       {
444 +               /* Add user modes */
445 +               ModeManager::AddUserMode(new UserMode(UMODE_ADMIN, 'a'));
446 +               ModeManager::AddUserMode(new UserMode(UMODE_INVIS, 'i'));
447 +               ModeManager::AddUserMode(new UserMode(UMODE_OPER, 'o'));
448 +               ModeManager::AddUserMode(new UserMode(UMODE_RESTRICTED, 'r'));
449 +               ModeManager::AddUserMode(new UserMode(UMODE_SNOMASK, 's'));
450 +               ModeManager::AddUserMode(new UserMode(UMODE_WALLOPS, 'w'));
451 +               ModeManager::AddUserMode(new UserMode(UMODE_CLOAK, 'x'));
452 +
453 +               /* b/e/I */
454 +               ModeManager::AddChannelMode(new ChannelModeBan(CMODE_BAN, 'b'));
455 +               ModeManager::AddChannelMode(new ChannelModeList(CMODE_INVITEOVERRIDE, 'I'));
456 +
457 +               /* v/h/o/a/q */
458 +               ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_VOICE, 'v', '+'));
459 +               ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_OP, 'o', '@'));
460 +
461 +               /* Add channel modes */
462 +               // channel modes: biIklmnoPstvz
463 +               ModeManager::AddChannelMode(new ChannelMode(CMODE_INVITE, 'i'));
464 +               ModeManager::AddChannelMode(new ChannelModeKey('k'));
465 +               ModeManager::AddChannelMode(new ChannelModeParam(CMODE_LIMIT, 'l'));
466 +               ModeManager::AddChannelMode(new ChannelMode(CMODE_MODERATED, 'm'));
467 +               ModeManager::AddChannelMode(new ChannelMode(CMODE_NOEXTERNAL, 'n'));
468 +               ModeManager::AddChannelMode(new ChannelMode(CMODE_PERM, 'P'));
469 +               ModeManager::AddChannelMode(new ChannelMode(CMODE_SECRET, 's'));
470 +               ModeManager::AddChannelMode(new ChannelMode(CMODE_TOPIC, 't'));
471 +               ModeManager::AddChannelMode(new ChannelMode(CMODE_SSL, 'z'));
472 +       }
473 +
474 + public:
475 +       ProtongIRCd(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator),
476 +               message_kick("KICK", event_kick), message_pass("PASS", event_pass),
477 +               message_njoin("NJOIN", event_njoin), message_chaninfo("CHANINFO", event_chaninfo),
478 +               message_005("005", event_005), message_442("442", event_442), message_376("376", event_376)
479 +       {
480 +               this->SetAuthor("Anope");
481 +               this->SetType(PROTOCOL);
482 +               
483 +               Capab.SetFlag(CAPAB_QS);
484 +
485 +               pmodule_ircd_var(myIrcd);
486 +               pmodule_ircd_proto(&this->ircd_proto);
487 +               pmodule_ircd_message(&this->ircd_message);
488 +
489 +               this->AddModes();
490 +       }
491 +};
492 +
493 +MODULE_INIT(ProtongIRCd)
494 -- 
495 1.7.2.5
496