ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/vendor/ircservices-5.1.24/modules/protocol/dreamforge.c
Revision: 3389
Committed: Fri Apr 25 14:12:15 2014 UTC (11 years, 4 months ago) by michael
Content type: text/x-csrc
File size: 14649 byte(s)
Log Message:
- Imported ircservices-5.1.24

File Contents

# User Rev Content
1 michael 3389 /* Dreamforge protocol module for IRC Services.
2     *
3     * IRC Services is copyright (c) 1996-2009 Andrew Church.
4     * E-mail: <achurch@achurch.org>
5     * Parts written by Andrew Kempe and others.
6     * This program is free but copyrighted software; see the file GPL.txt for
7     * details.
8     */
9    
10     #include "services.h"
11     #include "modules.h"
12     #include "conffile.h"
13     #include "language.h"
14     #include "messages.h"
15     #include "modules/operserv/operserv.h"
16     #include "modules/nickserv/nickserv.h"
17    
18     #include "svsnick.c"
19    
20     /*************************************************************************/
21    
22     static Module *module_operserv;
23    
24     static char *NetworkDomain = NULL;
25    
26     /*************************************************************************/
27     /***************** Local interface to external routines ******************/
28     /*************************************************************************/
29    
30     static typeof(is_services_admin) *p_is_services_admin = NULL;
31    
32     static int local_is_services_admin(User *u)
33     {
34     return p_is_services_admin && (*p_is_services_admin)(u);
35     }
36     #define is_services_admin local_is_services_admin
37    
38     /*************************************************************************/
39     /************************** User/channel modes ***************************/
40     /*************************************************************************/
41    
42     struct modedata_init {
43     uint8 mode;
44     ModeData data;
45     };
46    
47     static const struct modedata_init new_usermodes[] = {
48     {'g', {0x00000008}}, /* Receive globops */
49     {'h', {0x00000010}}, /* Helpop */
50     {'r', {0x00000020,0,0,0,MI_REGISTERED}},
51     /* Registered nick */
52     {'a', {0x00000040}}, /* Services admin */
53     {'A', {0x00000080}}, /* Server admin */
54     };
55    
56     static const struct modedata_init new_chanmodes[] = {
57     {'R', {0x00000100,0,0,0,MI_REGNICKS_ONLY}},
58     /* Only identified users can join */
59     {'r', {0x00000200,0,0,0,MI_REGISTERED}},
60     /* Set for all registered channels */
61     };
62    
63     static const struct modedata_init new_chanusermodes[] = {
64     };
65    
66     static void init_modes(void)
67     {
68     int i;
69    
70     for (i = 0; i < lenof(new_usermodes); i++)
71     usermodes[new_usermodes[i].mode] = new_usermodes[i].data;
72     for (i = 0; i < lenof(new_chanmodes); i++)
73     chanmodes[new_chanmodes[i].mode] = new_chanmodes[i].data;
74     for (i = 0; i < lenof(new_chanusermodes); i++)
75     chanusermodes[new_chanusermodes[i].mode] = new_chanusermodes[i].data;
76    
77     mode_setup();
78     };
79    
80     /*************************************************************************/
81     /************************* IRC message receiving *************************/
82     /*************************************************************************/
83    
84     static void m_nick(char *source, int ac, char **av)
85     {
86     char *tmp;
87    
88     if (*source) {
89     /* Old user changing nicks. */
90     if (ac != 2) {
91     module_log_debug(1, "NICK message: wrong number of parameters"
92     " (%d) for source `%s'", ac, source);
93     } else {
94     do_nick(source, ac, av);
95     }
96     return;
97     }
98    
99     /* New user. */
100    
101     if (ac != 8) {
102     module_log_debug(1, "NICK message: wrong number of parameters (%d)"
103     " for new user", ac);
104     return;
105     }
106    
107     /* Swap parameters so the Services timestamp is last. */
108     tmp = av[6];
109     av[6] = av[7];
110     av[7] = tmp;
111    
112     do_nick(source, ac, av);
113     }
114    
115     /*************************************************************************/
116    
117     static void m_svsmode(char *source, int ac, char **av)
118     {
119     if (*av[0] == '#' || *av[0] == '&') {
120     module_log("SVSMODE from %s for invalid target (channel %s): %s",
121     source, av[0], merge_args(ac-1,av+1));
122     } else {
123     if (ac < 2)
124     return;
125     do_umode(source, ac, av);
126     }
127     }
128    
129     /*************************************************************************/
130    
131     static Message dreamforge_messages[] = {
132     { "AKILL", NULL },
133     { "GLOBOPS", NULL },
134     { "GNOTICE", NULL },
135     { "GOPER", NULL },
136     { "NICK", m_nick },
137     { "PROTOCTL", NULL },
138     { "RAKILL", NULL },
139     { "SILENCE", NULL },
140     { "SQLINE", NULL },
141     { "SVSMODE", m_svsmode },
142     { NULL }
143     };
144    
145     /*************************************************************************/
146     /************************** IRC message sending **************************/
147     /*************************************************************************/
148    
149     /* Send a NICK command for a new user. */
150    
151     static void do_send_nick(const char *nick, const char *user, const char *host,
152     const char *server, const char *name,
153     const char *modes)
154     {
155     send_cmd(NULL, "NICK %s 1 %ld %s %s %s 0 :%s", nick, (long)time(NULL),
156     user, host, server, name);
157     if (modes)
158     send_cmd(nick, "MODE %s +%s", nick, modes);
159     }
160    
161     /*************************************************************************/
162    
163     /* Send a NICK command to change an existing user's nick. */
164    
165     static void do_send_nickchange(const char *nick, const char *newnick)
166     {
167     send_cmd(nick, "NICK %s %ld", newnick, (long)time(NULL));
168     }
169    
170     /*************************************************************************/
171    
172     /* Send a command to change a user's "real name". */
173    
174     static void do_send_namechange(const char *nick, const char *newname)
175     {
176     /* Not supported by this protocol. */
177     }
178    
179     /*************************************************************************/
180    
181     /* Send a SERVER command, and anything else needed at the beginning of the
182     * connection.
183     */
184    
185     static void do_send_server(void)
186     {
187     send_cmd(NULL, "PASS :%s", RemotePassword);
188     send_cmd(NULL, "SERVER %s 1 :%s", ServerName, ServerDesc);
189     }
190    
191     /*************************************************************************/
192    
193     /* Send a SERVER command for a remote (juped) server. */
194    
195     static void do_send_server_remote(const char *server, const char *reason)
196     {
197     send_cmd(NULL, "SERVER %s 2 :%s", server, reason);
198     }
199    
200     /*************************************************************************/
201    
202     /* Send a WALLOPS (really a GLOBOPS). */
203    
204     static void do_wallops(const char *source, const char *fmt, ...)
205     {
206     va_list args;
207     char buf[BUFSIZE];
208    
209     va_start(args, fmt);
210     vsnprintf(buf, sizeof(buf), fmt, args);
211     va_end(args);
212     send_cmd(source ? source : ServerName, "GLOBOPS :%s", buf);
213     }
214    
215     /*************************************************************************/
216    
217     /* Send a NOTICE to all users on the network. */
218    
219     static void do_notice_all(const char *source, const char *fmt, ...)
220     {
221     va_list args;
222     char msgbuf[BUFSIZE];
223    
224     va_start(args, fmt);
225     vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
226     va_end(args);
227     if (NetworkDomain) {
228     send_cmd(source, "NOTICE $*.%s :%s", NetworkDomain, msgbuf);
229     } else {
230     /* Go through all common top-level domains. If you have others,
231     * add them here. */
232     send_cmd(source, "NOTICE $*.com :%s", msgbuf);
233     send_cmd(source, "NOTICE $*.net :%s", msgbuf);
234     send_cmd(source, "NOTICE $*.org :%s", msgbuf);
235     send_cmd(source, "NOTICE $*.edu :%s", msgbuf);
236     }
237     }
238    
239     /*************************************************************************/
240    
241     /* Send a command which modifies channel status. */
242    
243     static void do_send_channel_cmd(const char *source, const char *fmt, ...)
244     {
245     va_list args;
246    
247     va_start(args, fmt);
248     vsend_cmd(source, fmt, args);
249     va_end(args);
250     }
251    
252     /*************************************************************************/
253     /******************************* Callbacks *******************************/
254     /*************************************************************************/
255    
256     static int do_user_servicestamp_change(User *user)
257     {
258     send_cmd(ServerName, "SVSMODE %s +d %u", user->nick, user->servicestamp);
259     return 0;
260     }
261    
262     /*************************************************************************/
263    
264     static int do_user_mode(User *user, int modechar, int add, char **av)
265     {
266     switch (modechar) {
267     case 'd':
268     module_log("MODE tried to change services stamp for %s", user->nick);
269     send_cmd(ServerName, "SVSMODE %s +d %u", user->nick,
270     user->servicestamp);
271     return 0;
272    
273     case 'o':
274     if (add) {
275     user->mode |= UMODE_o;
276     if (add && user_identified(user) && is_services_admin(user))
277     send_cmd(ServerName, "SVSMODE %s +a", user->nick);
278     user->mode &= ~UMODE_o;
279     }
280     return 0;
281    
282     case 'r':
283     if (user_identified(user)) {
284     if (!add)
285     send_cmd(ServerName, "SVSMODE %s +r", user->nick);
286     } else {
287     if (add)
288     send_cmd(ServerName, "SVSMODE %s -r", user->nick);
289     }
290     return 1;
291    
292     case 'a':
293     if (is_oper(user)) {
294     if (is_services_admin(user)) {
295     if (!add)
296     send_cmd(ServerName, "SVSMODE %s +a", user->nick);
297     } else {
298     if (add)
299     send_cmd(ServerName, "SVSMODE %s -a", user->nick);
300     }
301     return 1;
302     }
303     }
304     return 0;
305     }
306    
307     /*************************************************************************/
308    
309     static int do_nick_identified(User *u, int old_status)
310     {
311     if (is_oper(u) && is_services_admin(u))
312     send_cmd(ServerName, "SVSMODE %s +a", u->nick);
313     return 0;
314     }
315    
316     /*************************************************************************/
317    
318     static int do_set_topic(const char *source, Channel *c, const char *topic,
319     const char *setter, time_t t)
320     {
321     if (setter)
322     return 0;
323     if (c->topic_time && t >= c->topic_time)
324     t = c->topic_time - 1; /* Force topic change */
325     c->topic_time = t;
326     send_cmd(source, "TOPIC %s %s %ld :%s", c->name, c->topic_setter,
327     (long)c->topic_time, c->topic ? c->topic : "");
328     return 1;
329     }
330    
331     /*************************************************************************/
332    
333     static int do_send_akill(const char *username, const char *host,
334     time_t expires, const char *who, const char *reason)
335     {
336     send_cmd(ServerName, "AKILL %s %s :%s", host, username, reason);
337     return 1;
338     }
339    
340     /*************************************************************************/
341    
342     static int do_cancel_akill(const char *username, const char *host)
343     {
344     send_cmd(ServerName, "RAKILL %s %s", host, username);
345     return 1;
346     }
347    
348     /*************************************************************************/
349     /***************************** Module stuff ******************************/
350     /*************************************************************************/
351    
352     ConfigDirective module_config[] = {
353     { "NetworkDomain", { { CD_STRING, 0, &NetworkDomain } } },
354     { NULL }
355     };
356    
357     /*************************************************************************/
358    
359     static int do_load_module(Module *mod, const char *modname)
360     {
361     if (strcmp(modname, "operserv/main") == 0) {
362     module_operserv = mod;
363     p_is_services_admin = get_module_symbol(mod, "is_services_admin");
364     if (!p_is_services_admin) {
365     module_log("warning: unable to look up symbol `is_services_admin'"
366     " in module `operserv/main'");
367     }
368     } else if (strcmp(modname, "operserv/akill") == 0) {
369     if (!add_callback(mod, "send_akill", do_send_akill))
370     module_log("Unable to add send_akill callback");
371     if (!add_callback(mod, "cancel_akill", do_cancel_akill))
372     module_log("Unable to add cancel_akill callback");
373     } else if (strcmp(modname, "nickserv/main") == 0) {
374     if (!add_callback(mod, "identified", do_nick_identified))
375     module_log("Unable to add NickServ identified callback");
376     }
377     return 0;
378     }
379    
380     /*************************************************************************/
381    
382     static int do_unload_module(Module *mod)
383     {
384     if (mod == module_operserv) {
385     module_operserv = NULL;
386     p_is_services_admin = NULL;
387     }
388     return 0;
389     }
390    
391     /*************************************************************************/
392    
393     int init_module(void)
394     {
395     unsigned char c;
396    
397    
398     protocol_name = "Dreamforge/DALnet";
399     protocol_version = "4.4.15+";
400     protocol_features = 0;
401     protocol_nickmax = 30;
402    
403     if (!register_messages(dreamforge_messages)) {
404     module_log("Unable to register messages");
405     exit_module(1);
406     return 0;
407     }
408    
409     if (!add_callback(NULL, "load module", do_load_module)
410     || !add_callback(NULL, "unload module", do_unload_module)
411     || !add_callback(NULL, "user servicestamp change",
412     do_user_servicestamp_change)
413     || !add_callback(NULL, "user MODE", do_user_mode)
414     || !add_callback(NULL, "set topic", do_set_topic)
415     ) {
416     module_log("Unable to add callbacks");
417     exit_module(1);
418     return 0;
419     }
420    
421     if (!init_svsnick("SVSNICK")) {
422     exit_module(1);
423     return 0;
424     }
425    
426     init_modes();
427    
428     irc_lowertable['['] = '[';
429     irc_lowertable['\\'] = '\\';
430     irc_lowertable[']'] = ']';
431     for (c = 0; c < 32; c++)
432     valid_chan_table[c] = 0;
433     valid_chan_table['+'] = 3;
434     valid_chan_table[':'] = 0;
435     valid_chan_table[160] = 0;
436    
437     send_nick = do_send_nick;
438     send_nickchange = do_send_nickchange;
439     send_namechange = do_send_namechange;
440     send_server = do_send_server;
441     send_server_remote = do_send_server_remote;
442     wallops = do_wallops;
443     notice_all = do_notice_all;
444     send_channel_cmd = do_send_channel_cmd;
445     pseudoclient_modes = "";
446     enforcer_modes = "";
447     pseudoclient_oper = 0;
448    
449     mapstring(OPER_BOUNCY_MODES, OPER_BOUNCY_MODES_U_LINE);
450    
451     return 1;
452     }
453    
454     /*************************************************************************/
455    
456     int exit_module(int shutdown)
457     {
458     if (!shutdown) {
459     /* Do not allow removal */
460     return 0;
461     }
462    
463     exit_svsnick();
464     remove_callback(NULL, "load module", do_load_module);
465     remove_callback(NULL, "unload module", do_unload_module);
466     remove_callback(NULL, "user MODE", do_user_mode);
467     remove_callback(NULL, "user servicestamp change",
468     do_user_servicestamp_change);
469     remove_callback(NULL, "set topic", do_set_topic);
470     unregister_messages(dreamforge_messages);
471     return 1;
472     }
473    
474     /*************************************************************************/
475    
476     /*
477     * Local variables:
478     * c-file-style: "stroustrup"
479     * c-file-offsets: ((case-label . *) (statement-case-intro . *))
480     * indent-tabs-mode: nil
481     * End:
482     *
483     * vim: expandtab shiftwidth=4:
484     */