ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/core/m_message.c
Revision: 5451
Committed: Mon Feb 2 18:30:01 2015 UTC (11 years, 8 months ago) by michael
Content type: text/x-csrc
File size: 21270 byte(s)
Log Message:
- m_message.c: sanitize msg_client(); fixed some logic errors in the flooding code

File Contents

# User Rev Content
1 adx 30 /*
2 michael 2820 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 adx 30 *
4 michael 5347 * Copyright (c) 1997-2015 ircd-hybrid development team
5 adx 30 *
6     * This program is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18 michael 4565 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19 adx 30 * USA
20     */
21    
22 michael 2820 /*! \file m_message.c
23     * \brief Includes required functions for processing the PRIVMSG/NOTICE command.
24     * \version $Id$
25     */
26    
27 adx 30 #include "stdinc.h"
28 michael 1011 #include "list.h"
29 adx 30 #include "client.h"
30     #include "ircd.h"
31     #include "numeric.h"
32 michael 1309 #include "conf.h"
33 michael 3347 #include "server.h"
34 adx 30 #include "send.h"
35     #include "parse.h"
36     #include "modules.h"
37     #include "channel.h"
38     #include "channel_mode.h"
39     #include "irc_string.h"
40     #include "hash.h"
41     #include "packet.h"
42    
43 michael 1243
44 michael 3773 enum
45     {
46     PRIVMSG = 0,
47     NOTICE = 1
48     };
49 michael 2796
50 michael 3773 enum
51     {
52     ENTITY_NONE = 0,
53     ENTITY_CHANNEL = 1,
54     ENTITY_CHANOPS_ON_CHANNEL = 2,
55     ENTITY_CLIENT = 3
56     };
57 michael 2796
58 michael 4085 static struct
59 adx 30 {
60     void *ptr;
61     int type;
62     int flags;
63 michael 2786 } targets[IRCD_BUFSIZE];
64 adx 30
65 michael 3283 static int unsigned ntargets = 0;
66 michael 2786
67    
68 adx 30 /*
69     ** m_privmsg
70     **
71     ** massive cleanup
72     ** rev argv 6/91
73     **
74     ** Another massive cleanup Nov, 2000
75     ** (I don't think there is a single line left from 6/91. Maybe.)
76     ** m_privmsg and m_notice do basically the same thing.
77     ** in the original 2.8.2 code base, they were the same function
78     ** "m_message.c." When we did the great cleanup in conjuncton with bleep
79     ** of ircu fame, we split m_privmsg.c and m_notice.c.
80 michael 4298 ** I don't see the point of that now. It's harder to maintain, it's
81 adx 30 ** easier to introduce bugs into one version and not the other etc.
82     ** Really, the penalty of an extra function call isn't that big a deal folks.
83     ** -db Nov 13, 2000
84     **
85     */
86    
87 michael 2796 /* duplicate_ptr()
88     *
89     * inputs - pointer to check
90     * - pointer to table of entities
91     * - number of valid entities so far
92     * output - YES if duplicate pointer in table, NO if not.
93     * note, this does the canonize using pointers
94     * side effects - NONE
95     */
96     static int
97 michael 4085 duplicate_ptr(const void *const ptr)
98 adx 30 {
99 michael 3283 for (unsigned int i = 0; i < ntargets; ++i)
100 michael 2796 if (targets[i].ptr == ptr)
101     return 1;
102 adx 30
103 michael 2796 return 0;
104 adx 30 }
105    
106 michael 2796 /* flood_attack_client()
107 adx 30 *
108 michael 2796 * inputs - flag 0 if PRIVMSG 1 if NOTICE. RFC
109     * say NOTICE must not auto reply
110 michael 2820 * - pointer to source Client
111 michael 2796 * - pointer to target Client
112     * output - 1 if target is under flood attack
113     * side effects - check for flood attack on target target_p
114 adx 30 */
115     static int
116 michael 4001 flood_attack_client(int p_or_n, struct Client *source_p, struct Client *target_p)
117 adx 30 {
118 michael 5451 assert(MyClient(target_p));
119     assert(IsClient(source_p));
120 adx 30
121 michael 5451 if (HasUMode(source_p, UMODE_OPER) || HasFlag(source_p, FLAGS_SERVICE))
122     return 0;
123    
124     if (GlobalSetOptions.floodcount && !IsCanFlood(source_p))
125 adx 30 {
126 michael 4588 if ((target_p->connection->first_received_message_time + 1)
127 michael 2796 < CurrentTime)
128     {
129 michael 5451 const int delta =
130 michael 4588 CurrentTime - target_p->connection->first_received_message_time;
131     target_p->connection->received_number_of_privmsgs -= delta;
132     target_p->connection->first_received_message_time = CurrentTime;
133 adx 30
134 michael 4588 if (target_p->connection->received_number_of_privmsgs <= 0)
135 adx 30 {
136 michael 4588 target_p->connection->received_number_of_privmsgs = 0;
137 michael 2796 DelFlag(target_p, FLAGS_FLOOD_NOTICED);
138 adx 30 }
139     }
140    
141 michael 4588 if ((target_p->connection->received_number_of_privmsgs >=
142 michael 2796 GlobalSetOptions.floodcount) || HasFlag(target_p, FLAGS_FLOOD_NOTICED))
143 adx 30 {
144 michael 2796 if (!HasFlag(target_p, FLAGS_FLOOD_NOTICED))
145 adx 30 {
146 michael 2796 sendto_realops_flags(UMODE_BOTS, L_ALL, SEND_NOTICE,
147     "Possible Flooder %s on %s target: %s",
148     get_client_name(source_p, HIDE_IP),
149     source_p->servptr->name, target_p->name);
150 michael 3773
151 michael 2796 AddFlag(target_p, FLAGS_FLOOD_NOTICED);
152 michael 4588 target_p->connection->received_number_of_privmsgs += 2; /* Add a bit of penalty */
153 adx 30 }
154    
155 michael 3773 if (MyClient(source_p) && p_or_n != NOTICE)
156 michael 3110 sendto_one_notice(source_p, &me, ":*** Message to %s throttled due to flooding",
157     target_p->name);
158 michael 2796 return 1;
159 adx 30 }
160 michael 2796 else
161 michael 4588 target_p->connection->received_number_of_privmsgs++;
162 michael 2796 }
163 adx 30
164 michael 2796 return 0;
165     }
166 adx 30
167 michael 2796 /* flood_attack_channel()
168     *
169     * inputs - flag 0 if PRIVMSG 1 if NOTICE. RFC
170     * says NOTICE must not auto reply
171 michael 2820 * - pointer to source Client
172 michael 2796 * - pointer to target channel
173     * output - 1 if target is under flood attack
174     * side effects - check for flood attack on target chptr
175     */
176     static int
177 michael 4001 flood_attack_channel(int p_or_n, struct Client *source_p, struct Channel *chptr)
178 michael 2796 {
179 michael 4085 int delta = 0;
180 adx 30
181 michael 2796 if (GlobalSetOptions.floodcount && !IsCanFlood(source_p))
182     {
183     if ((chptr->first_received_message_time + 1) < CurrentTime)
184     {
185     delta = CurrentTime - chptr->first_received_message_time;
186     chptr->received_number_of_privmsgs -= delta;
187     chptr->first_received_message_time = CurrentTime;
188 adx 30
189 michael 2796 if (chptr->received_number_of_privmsgs <= 0)
190 adx 30 {
191 michael 2796 chptr->received_number_of_privmsgs = 0;
192     ClearFloodNoticed(chptr);
193 adx 30 }
194     }
195    
196 michael 2796 if ((chptr->received_number_of_privmsgs >= GlobalSetOptions.floodcount) ||
197     IsSetFloodNoticed(chptr))
198 adx 30 {
199 michael 2796 if (!IsSetFloodNoticed(chptr))
200 adx 30 {
201 michael 2796 sendto_realops_flags(UMODE_BOTS, L_ALL, SEND_NOTICE,
202     "Possible Flooder %s on %s target: %s",
203     get_client_name(source_p, HIDE_IP),
204 michael 4618 source_p->servptr->name, chptr->name);
205 michael 3773
206 michael 2796 SetFloodNoticed(chptr);
207 michael 3773 chptr->received_number_of_privmsgs += 2; /* Add a bit of penalty */
208 adx 30 }
209 michael 2796
210 michael 3773 if (MyClient(source_p) && p_or_n != NOTICE)
211 michael 3110 sendto_one_notice(source_p, &me, ":*** Message to %s throttled due to flooding",
212 michael 4618 chptr->name);
213 michael 2796 return 1;
214 adx 30 }
215 michael 2796 else
216     chptr->received_number_of_privmsgs++;
217 adx 30 }
218    
219 michael 2786 return 0;
220 adx 30 }
221    
222     /* msg_channel()
223     *
224     * inputs - flag privmsg or notice
225     * - pointer to command "PRIVMSG" or "NOTICE"
226     * - pointer to source_p
227     * - pointer to channel
228     * output - NONE
229     * side effects - message given channel
230     */
231     static void
232 michael 4001 msg_channel(int p_or_n, const char *command, struct Client *source_p,
233     struct Channel *chptr, const char *text)
234 adx 30 {
235 michael 1937 int result = 0;
236 adx 30
237 michael 2796 /* Chanops and voiced can flood their own channel with impunity */
238 michael 1937 if ((result = can_send(chptr, source_p, NULL, text)) < 0)
239 adx 30 {
240     if (result == CAN_SEND_OPV ||
241 michael 1480 !flood_attack_channel(p_or_n, source_p, chptr))
242 michael 3164 sendto_channel_butone(source_p, source_p, chptr, 0, "%s %s :%s",
243 michael 4618 command, chptr->name, text);
244 adx 30 }
245     else
246     {
247     if (p_or_n != NOTICE)
248 michael 1937 {
249     if (result == ERR_NOCTRLSONCHAN)
250 michael 3109 sendto_one_numeric(source_p, &me, ERR_NOCTRLSONCHAN,
251 michael 4618 chptr->name, text);
252 michael 1954 else if (result == ERR_NEEDREGGEDNICK)
253 michael 3109 sendto_one_numeric(source_p, &me, ERR_NEEDREGGEDNICK,
254 michael 4618 chptr->name);
255 michael 1937 else
256 michael 3109 sendto_one_numeric(source_p, &me, ERR_CANNOTSENDTOCHAN,
257 michael 4618 chptr->name);
258 michael 1937 }
259 adx 30 }
260     }
261    
262     /* msg_channel_flags()
263     *
264 michael 2820 * inputs - flag 0 if PRIVMSG 1 if NOTICE. RFC
265 adx 30 * say NOTICE must not auto reply
266     * - pointer to command, "PRIVMSG" or "NOTICE"
267     * - pointer to source_p
268     * - pointer to channel
269     * - flags
270     * - pointer to text to send
271     * output - NONE
272     * side effects - message given channel either chanop or voice
273     */
274     static void
275 michael 4001 msg_channel_flags(int p_or_n, const char *command, struct Client *source_p,
276     struct Channel *chptr, int flags, const char *text)
277 adx 30 {
278 michael 4085 unsigned int type = 0;
279 michael 4528 int result = 0;
280 michael 4085 char c = '\0';
281 adx 30
282     if (flags & CHFL_VOICE)
283     {
284     type = CHFL_VOICE|CHFL_HALFOP|CHFL_CHANOP;
285     c = '+';
286     }
287     else if (flags & CHFL_HALFOP)
288     {
289     type = CHFL_HALFOP|CHFL_CHANOP;
290     c = '%';
291     }
292     else
293     {
294     type = CHFL_CHANOP;
295     c = '@';
296     }
297    
298 michael 4528 /* Chanops and voiced can flood their own channel with impunity */
299     if ((result = can_send(chptr, source_p, NULL, text)) < 0)
300     {
301     if (result == CAN_SEND_OPV ||
302     !flood_attack_channel(p_or_n, source_p, chptr))
303     sendto_channel_butone(source_p, source_p, chptr, type, "%s %c%s :%s",
304 michael 4618 command, c, chptr->name, text);
305 michael 4528 }
306     else
307     {
308     if (p_or_n != NOTICE)
309     {
310     if (result == ERR_NOCTRLSONCHAN)
311     sendto_one_numeric(source_p, &me, ERR_NOCTRLSONCHAN,
312 michael 4618 chptr->name, text);
313 michael 4528 else if (result == ERR_NEEDREGGEDNICK)
314     sendto_one_numeric(source_p, &me, ERR_NEEDREGGEDNICK,
315 michael 4618 chptr->name);
316 michael 4528 else
317     sendto_one_numeric(source_p, &me, ERR_CANNOTSENDTOCHAN,
318 michael 4618 chptr->name);
319 michael 4528 }
320     }
321 adx 30 }
322    
323     /* msg_client()
324     *
325 michael 2820 * inputs - flag 0 if PRIVMSG 1 if NOTICE. RFC
326 adx 30 * say NOTICE must not auto reply
327     * - pointer to command, "PRIVMSG" or "NOTICE"
328     * - pointer to source_p source (struct Client *)
329     * - pointer to target_p target (struct Client *)
330     * - pointer to text
331     * output - NONE
332     * side effects - message given channel either chanop or voice
333     */
334     static void
335     msg_client(int p_or_n, const char *command, struct Client *source_p,
336 michael 4001 struct Client *target_p, const char *text)
337 adx 30 {
338 michael 3975 if (MyClient(source_p))
339 adx 30 {
340 michael 3979 if (target_p->away[0] && p_or_n != NOTICE)
341 michael 3109 sendto_one_numeric(source_p, &me, RPL_AWAY, target_p->name, target_p->away);
342 michael 1175
343     if (HasUMode(target_p, UMODE_REGONLY) && target_p != source_p)
344 michael 1173 {
345 michael 1175 if (!HasUMode(source_p, UMODE_REGISTERED|UMODE_OPER))
346     {
347     if (p_or_n != NOTICE)
348 michael 3109 sendto_one_numeric(source_p, &me, ERR_NONONREG, target_p->name);
349 michael 1175 return;
350     }
351 michael 1173 }
352 adx 30 }
353    
354 michael 5451 if (MyClient(target_p) && IsClient(source_p))
355 adx 30 {
356 michael 5451 if (HasUMode(target_p, UMODE_CALLERID|UMODE_SOFTCALLERID) &&
357     !accept_message(source_p, target_p))
358 adx 30 {
359 michael 5451 const int callerid = !!HasUMode(target_p, UMODE_CALLERID);
360    
361     /* check for accept, flag recipient incoming message */
362     if (p_or_n != NOTICE)
363     sendto_one_numeric(source_p, &me, RPL_TARGUMODEG,
364     target_p->name,
365     callerid ? "+g" : "+G",
366     callerid ? "server side ignore" :
367     "server side ignore with the exception of common channels");
368    
369     if ((target_p->connection->last_caller_id_time +
370     ConfigGeneral.caller_id_wait) < CurrentTime)
371 adx 30 {
372     if (p_or_n != NOTICE)
373 michael 5451 sendto_one_numeric(source_p, &me, RPL_TARGNOTIFY, target_p->name);
374 adx 30
375 michael 5451 sendto_one_numeric(target_p, &me, RPL_UMODEGMSG,
376     get_client_name(source_p, HIDE_IP),
377     callerid ? "+g" : "+G");
378     target_p->connection->last_caller_id_time = CurrentTime;
379     }
380 adx 30
381 michael 5451 /* Only so opers can watch for floods */
382     flood_attack_client(p_or_n, source_p, target_p);
383     return;
384     }
385 adx 30
386 michael 5451 if (flood_attack_client(p_or_n, source_p, target_p))
387     return;
388     }
389 adx 30
390 michael 5451 sendto_anywhere(target_p, source_p, command, ":%s", text);
391 adx 30 }
392    
393     /* handle_special()
394     *
395 michael 3159 * inputs - client pointer
396 adx 30 * - nick stuff to grok for opers
397     * - text to send if grok
398     * output - none
399     * side effects - old style username@server is handled here for non opers
400     * opers are allowed username%hostname@server
401     * all the traditional oper type messages are also parsed here.
402     * i.e. "/msg #some.host."
403     * However, syntax has been changed.
404     * previous syntax "/msg #some.host.mask"
405     * now becomes "/msg $#some.host.mask"
406     * previous syntax of: "/msg $some.server.mask" remains
407     * This disambiguates the syntax.
408     *
409     * XXX N.B. dalnet changed it to nick@server as have other servers.
410     * we will stick with tradition for now.
411     * - Dianora
412     */
413     static void
414 michael 3159 handle_special(int p_or_n, const char *command, struct Client *source_p,
415 michael 3951 const char *nick, const char *text)
416 adx 30 {
417 michael 3949 struct Client *target_p = NULL;
418     const char *server = NULL, *s = NULL;
419 adx 30
420     /*
421     * user[%host]@server addressed?
422     */
423 michael 2796 if ((server = strchr(nick, '@')))
424 adx 30 {
425 michael 3968 if ((target_p = hash_find_server(server + 1)) == NULL)
426 adx 30 {
427 michael 3949 sendto_one_numeric(source_p, &me, ERR_NOSUCHSERVER, server + 1);
428 adx 30 return;
429     }
430    
431 michael 3949 if (!HasUMode(source_p, UMODE_OPER) && strchr(nick, '%'))
432 adx 30 {
433 michael 3949 sendto_one_numeric(source_p, &me, ERR_NOSUCHNICK, nick);
434     return;
435     }
436 michael 3773
437 michael 3949 if (!IsMe(target_p))
438     {
439     sendto_one(target_p, ":%s %s %s :%s", source_p->id, command, nick, text);
440     return;
441     }
442 adx 30
443 michael 3949 sendto_one_numeric(source_p, &me, ERR_NOSUCHNICK, nick);
444 adx 30 return;
445     }
446    
447 michael 1219 if (!HasUMode(source_p, UMODE_OPER))
448 adx 30 {
449 michael 3109 sendto_one_numeric(source_p, &me, ERR_NOPRIVILEGES);
450 adx 30 return;
451     }
452    
453     /*
454 michael 2796 * The following two cases allow masks in NOTICEs
455 adx 30 * (for OPERs only)
456     *
457     * Armin, 8Jun90 (gruner@informatik.tu-muenchen.de)
458     */
459     if (*nick == '$')
460     {
461 michael 3481 if (*(nick + 1) == '$' || *(nick + 1) == '#')
462 michael 2796 ++nick;
463 michael 3965 else if (MyClient(source_p))
464 adx 30 {
465 michael 3110 sendto_one_notice(source_p, &me, ":The command %s %s is no longer supported, please use $%s",
466     command, nick, nick);
467 adx 30 return;
468     }
469    
470     if ((s = strrchr(nick, '.')) == NULL)
471     {
472 michael 3109 sendto_one_numeric(source_p, &me, ERR_NOTOPLEVEL, nick);
473 adx 30 return;
474     }
475    
476     while (*++s)
477     if (*s == '.' || *s == '*' || *s == '?')
478     break;
479    
480     if (*s == '*' || *s == '?')
481     {
482 michael 3109 sendto_one_numeric(source_p, &me, ERR_WILDTOPLEVEL, nick);
483 adx 30 return;
484     }
485 michael 2820
486 michael 3156 sendto_match_butone(IsServer(source_p->from) ? source_p->from : NULL, source_p,
487 adx 30 nick + 1, (*nick == '#') ? MATCH_HOST : MATCH_SERVER,
488     "%s $%s :%s", command, nick, text);
489     }
490     }
491    
492 michael 2796 /* build_target_list()
493 adx 30 *
494 michael 3159 * inputs - pointer to given source (oper/client etc.)
495 michael 2796 * - pointer to list of nicks/channels
496     * - pointer to table to place results
497     * - pointer to text (only used if source_p is an oper)
498     * output - number of valid entities
499     * side effects - target_table is modified to contain a list of
500     * pointers to channels or clients
501     * if source client is an oper
502     * all the classic old bizzare oper privmsg tricks
503     * are parsed and sent as is, if prefixed with $
504     * to disambiguate.
505     *
506 adx 30 */
507 michael 2796 static int
508 michael 3159 build_target_list(int p_or_n, const char *command, struct Client *source_p,
509 michael 3980 char *nicks_channels, const char *text)
510 adx 30 {
511 michael 2796 int type = 0;
512     char *p = NULL, *nick = NULL;
513     char *target_list = NULL;
514     struct Channel *chptr = NULL;
515     struct Client *target_p = NULL;
516 adx 30
517 michael 2796 target_list = nicks_channels;
518 adx 30
519 michael 2796 ntargets = 0;
520    
521     for (nick = strtoken(&p, target_list, ","); nick;
522 michael 3246 nick = strtoken(&p, NULL, ","))
523 adx 30 {
524 michael 3983 const char *with_prefix = NULL;
525 michael 2796
526     /*
527     * Channels are privmsg'd a lot more than other clients, moved up
528     * here plain old channel msg?
529     */
530     if (IsChanPrefix(*nick))
531 adx 30 {
532 michael 2796 if ((chptr = hash_find_channel(nick)))
533     {
534     if (!duplicate_ptr(chptr))
535     {
536 michael 4340 if (ntargets >= ConfigGeneral.max_targets)
537 michael 2796 {
538 michael 3109 sendto_one_numeric(source_p, &me, ERR_TOOMANYTARGETS,
539 michael 4340 nick, ConfigGeneral.max_targets);
540 michael 2796 return 1;
541     }
542 adx 30
543 michael 2796 targets[ntargets].ptr = chptr;
544     targets[ntargets++].type = ENTITY_CHANNEL;
545     }
546     }
547     else
548     {
549     if (p_or_n != NOTICE)
550 michael 3109 sendto_one_numeric(source_p, &me, ERR_NOSUCHNICK, nick);
551 michael 2796 }
552    
553     continue;
554     }
555    
556 michael 3773 /* Look for a PRIVMSG/NOTICE to another client */
557 michael 3156 if ((target_p = find_person(source_p, nick)))
558 michael 2796 {
559     if (!duplicate_ptr(target_p))
560     {
561 michael 4340 if (ntargets >= ConfigGeneral.max_targets)
562 michael 2796 {
563 michael 3109 sendto_one_numeric(source_p, &me, ERR_TOOMANYTARGETS,
564 michael 4340 nick, ConfigGeneral.max_targets);
565 michael 2796 return 1;
566     }
567    
568     targets[ntargets].ptr = target_p;
569     targets[ntargets].type = ENTITY_CLIENT;
570     targets[ntargets++].flags = 0;
571     }
572    
573     continue;
574     }
575 michael 2820
576 michael 2796 /* @#channel or +#channel message ? */
577     type = 0;
578     with_prefix = nick;
579    
580     /* Allow %+@ if someone wants to do that */
581 michael 3481 while (1)
582 michael 2796 {
583     if (*nick == '@')
584     type |= CHFL_CHANOP;
585     else if (*nick == '%')
586     type |= CHFL_CHANOP | CHFL_HALFOP;
587     else if (*nick == '+')
588     type |= CHFL_CHANOP | CHFL_HALFOP | CHFL_VOICE;
589     else
590     break;
591     ++nick;
592     }
593    
594 michael 3246 if (type)
595 michael 2796 {
596 michael 4298 if (EmptyString(nick)) /* If it's a '\0' dump it, there is no recipient */
597 michael 2796 {
598 michael 3109 sendto_one_numeric(source_p, &me, ERR_NORECIPIENT, command);
599 adx 30 continue;
600 michael 2796 }
601 adx 30
602 michael 2796 /*
603     * At this point, nick+1 should be a channel name i.e. #foo or &foo
604     * if the channel is found, fine, if not report an error
605     */
606     if ((chptr = hash_find_channel(nick)))
607 adx 30 {
608 michael 2796 if (IsClient(source_p) && !HasFlag(source_p, FLAGS_SERVICE))
609     {
610     if (!has_member_flags(find_channel_link(source_p, chptr),
611     CHFL_CHANOP|CHFL_HALFOP|CHFL_VOICE))
612     {
613 michael 3109 sendto_one_numeric(source_p, &me, ERR_CHANOPRIVSNEEDED, with_prefix);
614 michael 2796 return -1;
615     }
616     }
617    
618     if (!duplicate_ptr(chptr))
619     {
620 michael 4340 if (ntargets >= ConfigGeneral.max_targets)
621 michael 2796 {
622 michael 3109 sendto_one_numeric(source_p, &me, ERR_TOOMANYTARGETS,
623 michael 4340 nick, ConfigGeneral.max_targets);
624 michael 2820 return 1;
625 michael 2796 }
626    
627     targets[ntargets].ptr = chptr;
628     targets[ntargets].type = ENTITY_CHANOPS_ON_CHANNEL;
629     targets[ntargets++].flags = type;
630     }
631 adx 30 }
632 michael 2796 else
633     {
634     if (p_or_n != NOTICE)
635 michael 3109 sendto_one_numeric(source_p, &me, ERR_NOSUCHNICK, nick);
636 michael 2796 }
637    
638     continue;
639 adx 30 }
640 michael 2796
641     if (*nick == '$' || strchr(nick, '@'))
642 michael 3156 handle_special(p_or_n, command, source_p, nick, text);
643 michael 2796 else
644     {
645     if (p_or_n != NOTICE)
646     {
647     if (!IsDigit(*nick) || MyClient(source_p))
648 michael 3109 sendto_one_numeric(source_p, &me, ERR_NOSUCHNICK, nick);
649 michael 2796 }
650     }
651 adx 30 }
652    
653 michael 2796 return 1;
654 adx 30 }
655 michael 1230
656 michael 2796 /*
657     * inputs - flag privmsg or notice
658     * - pointer to command "PRIVMSG" or "NOTICE"
659     * - pointer to source_p
660     * - pointer to channel
661     */
662     static void
663 michael 4001 m_message(int p_or_n, const char *command, struct Client *source_p, int parc, char *parv[])
664 michael 2796 {
665     if (parc < 2 || EmptyString(parv[1]))
666     {
667     if (p_or_n != NOTICE)
668 michael 3109 sendto_one_numeric(source_p, &me, ERR_NORECIPIENT, command);
669 michael 2796 return;
670     }
671    
672     if (parc < 3 || EmptyString(parv[2]))
673     {
674     if (p_or_n != NOTICE)
675 michael 3109 sendto_one_numeric(source_p, &me, ERR_NOTEXTTOSEND);
676 michael 2796 return;
677     }
678    
679     /* Finish the flood grace period... */
680     if (MyClient(source_p) && !IsFloodDone(source_p))
681     flood_endgrace(source_p);
682    
683 michael 3156 if (build_target_list(p_or_n, command, source_p, parv[1], parv[2]) < 0)
684 michael 2796 return;
685    
686 michael 3283 for (unsigned int i = 0; i < ntargets; ++i)
687 michael 2796 {
688     switch (targets[i].type)
689     {
690 michael 3773 case ENTITY_CLIENT:
691     msg_client(p_or_n, command, source_p, targets[i].ptr, parv[2]);
692     break;
693    
694 michael 2796 case ENTITY_CHANNEL:
695 michael 3156 msg_channel(p_or_n, command, source_p, targets[i].ptr, parv[2]);
696 michael 2796 break;
697    
698     case ENTITY_CHANOPS_ON_CHANNEL:
699 michael 4001 msg_channel_flags(p_or_n, command, source_p, targets[i].ptr,
700     targets[i].flags, parv[2]);
701 michael 2796 break;
702     }
703     }
704     }
705    
706 michael 2820 static int
707 michael 3156 m_privmsg(struct Client *source_p, int parc, char *parv[])
708 michael 2796 {
709     /*
710     * Servers have no reason to send privmsgs, yet sometimes there is cause
711     * for a notice.. (for example remote kline replies) --fl_
712     */
713     if (!IsClient(source_p))
714 michael 2820 return 0;
715 michael 2796
716 michael 3972 if (MyConnect(source_p))
717 michael 4588 source_p->connection->last_privmsg = CurrentTime;
718 michael 3972
719 michael 3156 m_message(PRIVMSG, "PRIVMSG", source_p, parc, parv);
720 michael 2820 return 0;
721 michael 2796 }
722    
723 michael 2820 static int
724 michael 3156 m_notice(struct Client *source_p, int parc, char *parv[])
725 michael 2796 {
726 michael 3156 m_message(NOTICE, "NOTICE", source_p, parc, parv);
727 michael 2820 return 0;
728 michael 2796 }
729    
730     static struct Message privmsg_msgtab =
731     {
732 michael 4545 "PRIVMSG", NULL, 0, 0, 0, MAXPARA, MFLG_SLOW, 0,
733 michael 2820 { m_unregistered, m_privmsg, m_privmsg, m_ignore, m_privmsg, m_ignore }
734 michael 1230 };
735    
736 michael 2796 static struct Message notice_msgtab =
737     {
738 michael 4545 "NOTICE", NULL, 0, 0, 0, MAXPARA, MFLG_SLOW, 0,
739 michael 2820 { m_unregistered, m_notice, m_notice, m_ignore, m_notice, m_ignore }
740 michael 1230 };
741    
742     static void
743     module_init(void)
744     {
745     mod_add_cmd(&privmsg_msgtab);
746     mod_add_cmd(&notice_msgtab);
747     }
748    
749     static void
750     module_exit(void)
751     {
752     mod_del_cmd(&privmsg_msgtab);
753     mod_del_cmd(&notice_msgtab);
754     }
755    
756 michael 2796 struct module module_entry =
757     {
758 michael 1230 .node = { NULL, NULL, NULL },
759     .name = NULL,
760     .version = "$Revision$",
761     .handle = NULL,
762     .modinit = module_init,
763     .modexit = module_exit,
764     .flags = MODULE_FLAG_CORE
765     };

Properties

Name Value
svn:eol-style native
svn:keywords Id Revision