1 /*
2  * msgcmds.c -- part of irc.mod
3  *   all commands entered via /MSG
4  *
5  * $Id: msgcmds.c,v 1.49 (0.9) 2004/01/12 01:10:20 [Xp-AvR] Exp $
6  */
7 
msg_addhost(char * nick,char * host,struct userrec * u,char * par)8 static int msg_addhost(char *nick, char *host, struct userrec *u, char *par)
9 {
10   char *pass;
11 
12   if (match_my_nick(nick) || !u || (u->flags & USER_BOT))
13     return 1;
14 
15   if (u->flags & USER_COMMON) {
16     if (!quiet_reject)
17       dprintf(DP_HELP, "NOTICE %s :%s\n", nick, IRC_FAILCOMMON);
18     return 1;
19   }
20   pass = newsplit(&par);
21   if (!par[0]) {
22     if (!quiet_reject)
23       dprintf(DP_HELP, "NOTICE %s :You must supply a hostmask\n", nick);
24   } else if (rfc_casecmp(u->handle, origbotname)) {
25     if (u_pass_match(u, "-")) {
26       if (!quiet_reject)
27         dprintf(DP_HELP, "NOTICE %s :%s\n", nick, IRC_NOPASS);
28     } else if (!u_pass_match(u, pass)) {
29       if (!quiet_reject)
30         dprintf(DP_HELP, "NOTICE %s :%s\n", nick, IRC_DENYACCESS);
31     } else if (get_user_by_host(par)) {
32       if (!quiet_reject)
33         dprintf(DP_HELP, "NOTICE %s :That hostmask clashes with another "
34                 "already in use.\n", nick);
35     } else {
36       putlog(LOG_CMDS, "*", "(%s!%s) !*! ADDHOST %s", nick, host, par);
37       dprintf(DP_HELP, "NOTICE %s :%s: %s\n", nick, IRC_ADDHOSTMASK, par);
38       addhost_by_handle(u->handle, par);
39       check_this_user(u->handle, 0, NULL);
40       return 1;
41     }
42   }
43   putlog(LOG_CMDS, "*", "(%s!%s) !*! failed ADDHOST %s", nick, host, par);
44   return 1;
45 }
46 
msg_op(char * nick,char * host,struct userrec * u,char * par)47 static int msg_op(char *nick, char *host, struct userrec *u, char *par)
48 {
49   struct chanset_t *chan;
50   char *pass;
51   struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };
52 
53   if (match_my_nick(nick))
54     return 1;
55 
56   pass = newsplit(&par);
57   if (u_pass_match(u, pass)) {
58     if (!u_pass_match(u, "-")) {
59       if (par[0]) {
60         chan = findchan_by_dname(par);
61         if (chan && channel_active(chan)) {
62           get_user_flagrec(u, &fr, par);
63           if (chan_op(fr) || (glob_op(fr) && !chan_deop(fr)))
64             add_mode(chan, '+', 'o', nick);
65           putlog(LOG_CMDS, "*", "(%s!%s) !%s! OP %s", nick, host, u->handle,
66                  par);
67           return 1;
68         }
69       } else {
70         for (chan = chanset; chan; chan = chan->next) {
71           get_user_flagrec(u, &fr, chan->dname);
72           if (chan_op(fr) || (glob_op(fr) && !chan_deop(fr)))
73             add_mode(chan, '+', 'o', nick);
74         }
75         putlog(LOG_CMDS, "*", "(%s!%s) !%s! OP", nick, host, u->handle);
76         return 1;
77       }
78     }
79   }
80   putlog(LOG_CMDS, "*", "(%s!%s) !*! failed OP", nick, host);
81   return 1;
82 }
83 
msg_key(char * nick,char * host,struct userrec * u,char * par)84 static int msg_key(char *nick, char *host, struct userrec *u, char *par)
85 {
86   struct chanset_t *chan;
87   char *pass;
88   struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };
89 
90   if (match_my_nick(nick))
91     return 1;
92 
93   pass = newsplit(&par);
94   if (u_pass_match(u, pass)) {
95     /* Prevent people from getting key with no pass set */
96     if (!u_pass_match(u, "-")) {
97       if (!(chan = findchan_by_dname(par))) {
98         dprintf(DP_HELP, "NOTICE %s :%s: /MSG %s key <pass> <channel>\n",
99                 nick, MISC_USAGE, botname);
100         return 1;
101       }
102       if (!channel_active(chan)) {
103         dprintf(DP_HELP, "NOTICE %s :%s: %s\n", nick, par, IRC_NOTONCHAN);
104         return 1;
105       }
106       chan = findchan_by_dname(par);
107       if (chan && channel_active(chan)) {
108         get_user_flagrec(u, &fr, par);
109         if (chan_op(fr) || (glob_op(fr) && !chan_deop(fr))) {
110           if (chan->channel.key[0]) {
111             dprintf(DP_SERVER, "NOTICE %s :%s: key is %s\n", nick, par,
112                     chan->channel.key);
113             if (invite_key && (chan->channel.mode & CHANINV)) {
114               dprintf(DP_SERVER, "INVITE %s %s\n", nick, chan->name);
115               putlog(LOG_CMDS, "*", "(%s!%s) !%s! KEY %s",
116                      nick, host, u->handle, par);
117             }
118           } else {
119             dprintf(DP_HELP, "NOTICE %s :%s: no key set for this channel\n",
120                     nick, par);
121             putlog(LOG_CMDS, "*", "(%s!%s) !%s! KEY %s", nick, host, u->handle,
122                    par);
123           }
124         }
125         return 1;
126       }
127     }
128   }
129   putlog(LOG_CMDS, "*", "(%s!%s) !%s! failed KEY %s", nick, host,
130          (u ? u->handle : "*"), par);
131   return 1;
132 }
133 
msg_voice(char * nick,char * host,struct userrec * u,char * par)134 static int msg_voice(char *nick, char *host, struct userrec *u, char *par)
135 {
136   struct chanset_t *chan;
137   char *pass;
138   struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };
139 
140   if (match_my_nick(nick))
141     return 1;
142 
143   pass = newsplit(&par);
144   if (u_pass_match(u, pass)) {
145     if (!u_pass_match(u, "-")) {
146       if (par[0]) {
147         chan = findchan_by_dname(par);
148         if (chan && channel_active(chan)) {
149           get_user_flagrec(u, &fr, par);
150           if (chan_voice(fr) || glob_voice(fr) || chan_op(fr) || glob_op(fr)) {
151             add_mode(chan, '+', 'v', nick);
152             putlog(LOG_CMDS, "*", "(%s!%s) !%s! VOICE %s", nick, host,
153                    u->handle, par);
154           } else
155             putlog(LOG_CMDS, "*", "(%s!%s) !*! failed VOICE %s",
156                    nick, host, par);
157           return 1;
158         }
159       } else {
160         for (chan = chanset; chan; chan = chan->next) {
161           get_user_flagrec(u, &fr, chan->dname);
162           if (chan_voice(fr) || glob_voice(fr) || chan_op(fr) || glob_op(fr))
163             add_mode(chan, '+', 'v', nick);
164         }
165         putlog(LOG_CMDS, "*", "(%s!%s) !%s! VOICE", nick, host, u->handle);
166         return 1;
167       }
168     }
169   }
170   putlog(LOG_CMDS, "*", "(%s!%s) !*! failed VOICE", nick, host);
171   return 1;
172 }
173 
msg_invite(char * nick,char * host,struct userrec * u,char * par)174 static int msg_invite(char *nick, char *host, struct userrec *u, char *par)
175 {
176   char *pass;
177   struct chanset_t *chan;
178   struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };
179 
180   if (match_my_nick(nick))
181     return 1;
182 
183   pass = newsplit(&par);
184   if (u_pass_match(u, pass) && !u_pass_match(u, "-")) {
185     if (par[0] == '*') {
186       for (chan = chanset; chan; chan = chan->next) {
187         get_user_flagrec(u, &fr, chan->dname);
188         if ((chan_op(fr) || (glob_op(fr) && !chan_deop(fr))) &&
189             (chan->channel.mode & CHANINV))
190           dprintf(DP_SERVER, "INVITE %s %s\n", nick, chan->name);
191       }
192       putlog(LOG_CMDS, "*", "(%s!%s) !%s! INVITE ALL", nick, host, u->handle);
193       return 1;
194     }
195     if (!(chan = findchan_by_dname(par))) {
196       dprintf(DP_HELP, "NOTICE %s :%s: /MSG %s invite <pass> <channel>\n",
197               nick, MISC_USAGE, botname);
198       return 1;
199     }
200     if (!channel_active(chan)) {
201       dprintf(DP_HELP, "NOTICE %s :%s: %s\n", nick, par, IRC_NOTONCHAN);
202       return 1;
203     }
204     /* We need to check access here also (dw 991002) */
205     get_user_flagrec(u, &fr, par);
206     if (chan_op(fr) || (glob_op(fr) && !chan_deop(fr))) {
207       dprintf(DP_SERVER, "INVITE %s %s\n", nick, chan->name);
208       putlog(LOG_CMDS, "*", "(%s!%s) !%s! INVITE %s", nick, host,
209              u->handle, par);
210       return 1;
211     }
212   }
213   putlog(LOG_CMDS, "*", "(%s!%s) !%s! failed INVITE %s", nick, host,
214          (u ? u->handle : "*"), par);
215   return 1;
216 }
217 
msg_go(char * nick,char * host,struct userrec * u,char * par)218 static int msg_go(char *nick, char *host, struct userrec *u, char *par)
219 {
220   struct chanset_t *chan;
221   int ok = 0, ok2 = 0;
222   struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };
223 
224   if (match_my_nick(nick))
225     return 1;
226 
227   if (!u)
228     return 0;
229 
230   if (par[0]) {
231     chan = findchan_by_dname(par);
232     if (!chan)
233       return 0;
234     if (!(chan->status & CHAN_ACTIVE)) {
235       putlog(LOG_CMDS, "*", "(%s!%s) !%s! failed GO (i'm blind)", nick, host,
236              u->handle);
237       return 1;
238     }
239     get_user_flagrec(u, &fr, par);
240     if (!chan_op(fr) && !(glob_op(fr) && !chan_deop(fr))) {
241       putlog(LOG_CMDS, "*", "(%s!%s) !%s! failed GO (not op)", nick, host,
242              u->handle);
243       return 1;
244     }
245     if (!me_op(chan)) {
246       dprintf(DP_SERVER, "PART %s\n", chan->name);
247       putlog(LOG_CMDS, chan->dname, "(%s!%s) !%s! GO %s", nick, host,
248              u->handle, par);
249       return 1;
250     }
251     putlog(LOG_CMDS, chan->dname, "(%s!%s) !%s! failed GO %s (i'm chop)",
252            nick, host, u->handle, par);
253     return 1;
254   }
255   for (chan = chanset; chan; chan = chan->next) {
256     if (ismember(chan, nick)) {
257       get_user_flagrec(u, &fr, par);
258       if (chan_op(fr) || (glob_op(fr) && !chan_deop(fr))) {
259         ok2 = 1;
260         if (!me_op(chan)) {
261           dprintf(DP_SERVER, "PART %s\n", chan->name);
262           ok = 1;
263         }
264       }
265     }
266   }
267   if (ok) {
268     putlog(LOG_CMDS, "*", "(%s!%s) !%s! GO", nick, host, u->handle);
269   } else if (ok2) {
270     putlog(LOG_CMDS, "*", "(%s!%s) !%s! failed GO (i'm chop)", nick, host,
271            u->handle);
272   } else {
273     putlog(LOG_CMDS, "*", "(%s!%s) !%s! failed GO (not op)", nick, host,
274            u->handle);
275   }
276   return 1;
277 }
278 
279 /* MSG COMMANDS
280  *
281  * Function call should be:
282  *    int msg_cmd("handle","nick","user@host","params");
283  *
284  * The function is responsible for any logging. Return 1 if successful,
285  * 0 if not.
286  */
287 static cmd_t C_msg[] = {
288   {"addhost", "",    (Function) msg_addhost, NULL},
289   {"go",      "",    (Function) msg_go,      NULL},
290   {"invite",  "o|o", (Function) msg_invite,  NULL},
291   {"key",     "o|o", (Function) msg_key,     NULL},
292   {"op",      "",    (Function) msg_op,      NULL},
293   {"voice",   "",    (Function) msg_voice,   NULL},
294   {NULL,      NULL,  NULL,                   NULL}
295 };
296