ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/branches/8.2.x/modules/core/m_message.c
Revision: 4564
Committed: Sun Aug 24 10:24:47 2014 UTC (9 years, 7 months ago) by michael
Content type: text/x-csrc
File size: 22222 byte(s)
Log Message:
- Update GPL 2 license headers

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 2820 * Copyright (c) 1997-2014 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 4564 * 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 3774 enum
45     {
46     PRIVMSG = 0,
47     NOTICE = 1
48     };
49 michael 2796
50 michael 3774 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 4084 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 4299 ** 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 4084 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 4002 flood_attack_client(int p_or_n, struct Client *source_p, struct Client *target_p)
117 adx 30 {
118 michael 4084 int delta = 0;
119 adx 30
120 michael 2796 if (GlobalSetOptions.floodcount && MyConnect(target_p) &&
121     IsClient(source_p) && !IsCanFlood(source_p))
122 adx 30 {
123 michael 2796 if ((target_p->localClient->first_received_message_time + 1)
124     < CurrentTime)
125     {
126     delta =
127     CurrentTime - target_p->localClient->first_received_message_time;
128     target_p->localClient->received_number_of_privmsgs -= delta;
129     target_p->localClient->first_received_message_time = CurrentTime;
130 adx 30
131 michael 2796 if (target_p->localClient->received_number_of_privmsgs <= 0)
132 adx 30 {
133 michael 2796 target_p->localClient->received_number_of_privmsgs = 0;
134     DelFlag(target_p, FLAGS_FLOOD_NOTICED);
135 adx 30 }
136     }
137    
138 michael 2796 if ((target_p->localClient->received_number_of_privmsgs >=
139     GlobalSetOptions.floodcount) || HasFlag(target_p, FLAGS_FLOOD_NOTICED))
140 adx 30 {
141 michael 2796 if (!HasFlag(target_p, FLAGS_FLOOD_NOTICED))
142 adx 30 {
143 michael 2796 sendto_realops_flags(UMODE_BOTS, L_ALL, SEND_NOTICE,
144     "Possible Flooder %s on %s target: %s",
145     get_client_name(source_p, HIDE_IP),
146     source_p->servptr->name, target_p->name);
147 michael 3774
148 michael 2796 AddFlag(target_p, FLAGS_FLOOD_NOTICED);
149 michael 3774 target_p->localClient->received_number_of_privmsgs += 2; /* Add a bit of penalty */
150 adx 30 }
151    
152 michael 3774 if (MyClient(source_p) && p_or_n != NOTICE)
153 michael 3110 sendto_one_notice(source_p, &me, ":*** Message to %s throttled due to flooding",
154     target_p->name);
155 michael 2796 return 1;
156 adx 30 }
157 michael 2796 else
158     target_p->localClient->received_number_of_privmsgs++;
159     }
160 adx 30
161 michael 2796 return 0;
162     }
163 adx 30
164 michael 2796 /* flood_attack_channel()
165     *
166     * inputs - flag 0 if PRIVMSG 1 if NOTICE. RFC
167     * says NOTICE must not auto reply
168 michael 2820 * - pointer to source Client
169 michael 2796 * - pointer to target channel
170     * output - 1 if target is under flood attack
171     * side effects - check for flood attack on target chptr
172     */
173     static int
174 michael 4002 flood_attack_channel(int p_or_n, struct Client *source_p, struct Channel *chptr)
175 michael 2796 {
176 michael 4084 int delta = 0;
177 adx 30
178 michael 2796 if (GlobalSetOptions.floodcount && !IsCanFlood(source_p))
179     {
180     if ((chptr->first_received_message_time + 1) < CurrentTime)
181     {
182     delta = CurrentTime - chptr->first_received_message_time;
183     chptr->received_number_of_privmsgs -= delta;
184     chptr->first_received_message_time = CurrentTime;
185 adx 30
186 michael 2796 if (chptr->received_number_of_privmsgs <= 0)
187 adx 30 {
188 michael 2796 chptr->received_number_of_privmsgs = 0;
189     ClearFloodNoticed(chptr);
190 adx 30 }
191     }
192    
193 michael 2796 if ((chptr->received_number_of_privmsgs >= GlobalSetOptions.floodcount) ||
194     IsSetFloodNoticed(chptr))
195 adx 30 {
196 michael 2796 if (!IsSetFloodNoticed(chptr))
197 adx 30 {
198 michael 2796 sendto_realops_flags(UMODE_BOTS, L_ALL, SEND_NOTICE,
199     "Possible Flooder %s on %s target: %s",
200     get_client_name(source_p, HIDE_IP),
201     source_p->servptr->name, chptr->chname);
202 michael 3774
203 michael 2796 SetFloodNoticed(chptr);
204 michael 3774 chptr->received_number_of_privmsgs += 2; /* Add a bit of penalty */
205 adx 30 }
206 michael 2796
207 michael 3774 if (MyClient(source_p) && p_or_n != NOTICE)
208 michael 3110 sendto_one_notice(source_p, &me, ":*** Message to %s throttled due to flooding",
209     chptr->chname);
210 michael 2796 return 1;
211 adx 30 }
212 michael 2796 else
213     chptr->received_number_of_privmsgs++;
214 adx 30 }
215    
216 michael 2786 return 0;
217 adx 30 }
218    
219     /* msg_channel()
220     *
221     * inputs - flag privmsg or notice
222     * - pointer to command "PRIVMSG" or "NOTICE"
223     * - pointer to source_p
224     * - pointer to channel
225     * output - NONE
226     * side effects - message given channel
227     */
228     static void
229 michael 4002 msg_channel(int p_or_n, const char *command, struct Client *source_p,
230     struct Channel *chptr, const char *text)
231 adx 30 {
232 michael 1937 int result = 0;
233 adx 30
234 michael 2796 /* Chanops and voiced can flood their own channel with impunity */
235 michael 1937 if ((result = can_send(chptr, source_p, NULL, text)) < 0)
236 adx 30 {
237     if (result == CAN_SEND_OPV ||
238 michael 1480 !flood_attack_channel(p_or_n, source_p, chptr))
239 michael 3164 sendto_channel_butone(source_p, source_p, chptr, 0, "%s %s :%s",
240 michael 1479 command, chptr->chname, text);
241 adx 30 }
242     else
243     {
244     if (p_or_n != NOTICE)
245 michael 1937 {
246     if (result == ERR_NOCTRLSONCHAN)
247 michael 3109 sendto_one_numeric(source_p, &me, ERR_NOCTRLSONCHAN,
248     chptr->chname, text);
249 michael 1954 else if (result == ERR_NEEDREGGEDNICK)
250 michael 3109 sendto_one_numeric(source_p, &me, ERR_NEEDREGGEDNICK,
251     chptr->chname);
252 michael 1937 else
253 michael 3109 sendto_one_numeric(source_p, &me, ERR_CANNOTSENDTOCHAN,
254     chptr->chname);
255 michael 1937 }
256 adx 30 }
257     }
258    
259     /* msg_channel_flags()
260     *
261 michael 2820 * inputs - flag 0 if PRIVMSG 1 if NOTICE. RFC
262 adx 30 * say NOTICE must not auto reply
263     * - pointer to command, "PRIVMSG" or "NOTICE"
264     * - pointer to source_p
265     * - pointer to channel
266     * - flags
267     * - pointer to text to send
268     * output - NONE
269     * side effects - message given channel either chanop or voice
270     */
271     static void
272 michael 4002 msg_channel_flags(int p_or_n, const char *command, struct Client *source_p,
273     struct Channel *chptr, int flags, const char *text)
274 adx 30 {
275 michael 4084 unsigned int type = 0;
276 michael 4527 int result = 0;
277 michael 4084 char c = '\0';
278 adx 30
279     if (flags & CHFL_VOICE)
280     {
281     type = CHFL_VOICE|CHFL_HALFOP|CHFL_CHANOP;
282     c = '+';
283     }
284     else if (flags & CHFL_HALFOP)
285     {
286     type = CHFL_HALFOP|CHFL_CHANOP;
287     c = '%';
288     }
289     else
290     {
291     type = CHFL_CHANOP;
292     c = '@';
293     }
294    
295 michael 4527 /* Chanops and voiced can flood their own channel with impunity */
296     if ((result = can_send(chptr, source_p, NULL, text)) < 0)
297     {
298     if (result == CAN_SEND_OPV ||
299     !flood_attack_channel(p_or_n, source_p, chptr))
300     sendto_channel_butone(source_p, source_p, chptr, type, "%s %c%s :%s",
301     command, c, chptr->chname, text);
302     }
303     else
304     {
305     if (p_or_n != NOTICE)
306     {
307     if (result == ERR_NOCTRLSONCHAN)
308     sendto_one_numeric(source_p, &me, ERR_NOCTRLSONCHAN,
309     chptr->chname, text);
310     else if (result == ERR_NEEDREGGEDNICK)
311     sendto_one_numeric(source_p, &me, ERR_NEEDREGGEDNICK,
312     chptr->chname);
313     else
314     sendto_one_numeric(source_p, &me, ERR_CANNOTSENDTOCHAN,
315     chptr->chname);
316     }
317     }
318 adx 30 }
319    
320     /* msg_client()
321     *
322 michael 2820 * inputs - flag 0 if PRIVMSG 1 if NOTICE. RFC
323 adx 30 * say NOTICE must not auto reply
324     * - pointer to command, "PRIVMSG" or "NOTICE"
325     * - pointer to source_p source (struct Client *)
326     * - pointer to target_p target (struct Client *)
327     * - pointer to text
328     * output - NONE
329     * side effects - message given channel either chanop or voice
330     */
331     static void
332     msg_client(int p_or_n, const char *command, struct Client *source_p,
333 michael 4002 struct Client *target_p, const char *text)
334 adx 30 {
335 michael 3974 if (MyClient(source_p))
336 adx 30 {
337 michael 3978 if (target_p->away[0] && p_or_n != NOTICE)
338 michael 3109 sendto_one_numeric(source_p, &me, RPL_AWAY, target_p->name, target_p->away);
339 michael 1175
340     if (HasUMode(target_p, UMODE_REGONLY) && target_p != source_p)
341 michael 1173 {
342 michael 1175 if (!HasUMode(source_p, UMODE_REGISTERED|UMODE_OPER))
343     {
344     if (p_or_n != NOTICE)
345 michael 3109 sendto_one_numeric(source_p, &me, ERR_NONONREG, target_p->name);
346 michael 1175 return;
347     }
348 michael 1173 }
349 adx 30 }
350    
351     if (MyClient(target_p))
352     {
353 michael 1219 if (!IsServer(source_p) && HasUMode(target_p, UMODE_CALLERID|UMODE_SOFTCALLERID))
354 adx 30 {
355     /* Here is the anti-flood bot/spambot code -db */
356 michael 4011 if (HasFlag(source_p, FLAGS_SERVICE) || accept_message(source_p, target_p) ||
357 michael 4341 (HasUMode(source_p, UMODE_OPER) && ConfigGeneral.opers_bypass_callerid))
358 adx 30 {
359     sendto_one(target_p, ":%s!%s@%s %s %s :%s",
360     source_p->name, source_p->username,
361     source_p->host, command, target_p->name, text);
362     }
363     else
364     {
365 michael 2580 int callerid = !!HasUMode(target_p, UMODE_CALLERID);
366    
367 adx 30 /* check for accept, flag recipient incoming message */
368     if (p_or_n != NOTICE)
369 michael 3109 sendto_one_numeric(source_p, &me, RPL_TARGUMODEG,
370     target_p->name,
371     callerid ? "+g" : "+G",
372     callerid ? "server side ignore" :
373     "server side ignore with the exception of common channels");
374 adx 30
375     if ((target_p->localClient->last_caller_id_time +
376 michael 4341 ConfigGeneral.caller_id_wait) < CurrentTime)
377 adx 30 {
378     if (p_or_n != NOTICE)
379 michael 3109 sendto_one_numeric(source_p, &me, RPL_TARGNOTIFY, target_p->name);
380 adx 30
381 michael 3109 sendto_one_numeric(target_p, &me, RPL_UMODEGMSG,
382     get_client_name(source_p, HIDE_IP),
383     callerid ? "+g" : "+G");
384 adx 30
385     target_p->localClient->last_caller_id_time = CurrentTime;
386    
387     }
388 michael 2796
389 adx 30 /* Only so opers can watch for floods */
390     flood_attack_client(p_or_n, source_p, target_p);
391     }
392     }
393     else
394     {
395 michael 2796 /*
396     * If the client is remote, we dont perform a special check for
397 michael 4299 * flooding.. as we wouldn't block their message anyway.. this means
398 michael 2820 * we dont give warnings.. we then check if theyre opered
399 adx 30 * (to avoid flood warnings), lastly if theyre our client
400 michael 2796 * and flooding -- fl
401     */
402 michael 1219 if (!MyClient(source_p) || HasUMode(source_p, UMODE_OPER) ||
403 michael 2799 !flood_attack_client(p_or_n, source_p, target_p))
404 michael 2793 sendto_anywhere(target_p, source_p, command, ":%s", text);
405 adx 30 }
406     }
407 michael 2796 else if (!MyClient(source_p) || HasUMode(source_p, UMODE_OPER) ||
408 michael 2799 !flood_attack_client(p_or_n, source_p, target_p))
409 michael 2793 sendto_anywhere(target_p, source_p, command, ":%s", text);
410 adx 30 }
411    
412     /* handle_special()
413     *
414 michael 3159 * inputs - client pointer
415 adx 30 * - nick stuff to grok for opers
416     * - text to send if grok
417     * output - none
418     * side effects - old style username@server is handled here for non opers
419     * opers are allowed username%hostname@server
420     * all the traditional oper type messages are also parsed here.
421     * i.e. "/msg #some.host."
422     * However, syntax has been changed.
423     * previous syntax "/msg #some.host.mask"
424     * now becomes "/msg $#some.host.mask"
425     * previous syntax of: "/msg $some.server.mask" remains
426     * This disambiguates the syntax.
427     *
428     * XXX N.B. dalnet changed it to nick@server as have other servers.
429     * we will stick with tradition for now.
430     * - Dianora
431     */
432     static void
433 michael 3159 handle_special(int p_or_n, const char *command, struct Client *source_p,
434 michael 3950 const char *nick, const char *text)
435 adx 30 {
436 michael 3948 struct Client *target_p = NULL;
437     const char *server = NULL, *s = NULL;
438 adx 30
439     /*
440     * user[%host]@server addressed?
441     */
442 michael 2796 if ((server = strchr(nick, '@')))
443 adx 30 {
444 michael 3969 if ((target_p = hash_find_server(server + 1)) == NULL)
445 adx 30 {
446 michael 3948 sendto_one_numeric(source_p, &me, ERR_NOSUCHSERVER, server + 1);
447 adx 30 return;
448     }
449    
450 michael 3948 if (!HasUMode(source_p, UMODE_OPER) && strchr(nick, '%'))
451 adx 30 {
452 michael 3948 sendto_one_numeric(source_p, &me, ERR_NOSUCHNICK, nick);
453     return;
454     }
455 michael 3774
456 michael 3948 if (!IsMe(target_p))
457     {
458     sendto_one(target_p, ":%s %s %s :%s", source_p->id, command, nick, text);
459     return;
460     }
461 adx 30
462 michael 3948 sendto_one_numeric(source_p, &me, ERR_NOSUCHNICK, nick);
463 adx 30 return;
464     }
465    
466 michael 1219 if (!HasUMode(source_p, UMODE_OPER))
467 adx 30 {
468 michael 3109 sendto_one_numeric(source_p, &me, ERR_NOPRIVILEGES);
469 adx 30 return;
470     }
471    
472     /*
473 michael 2796 * The following two cases allow masks in NOTICEs
474 adx 30 * (for OPERs only)
475     *
476     * Armin, 8Jun90 (gruner@informatik.tu-muenchen.de)
477     */
478     if (*nick == '$')
479     {
480 michael 3482 if (*(nick + 1) == '$' || *(nick + 1) == '#')
481 michael 2796 ++nick;
482 michael 3964 else if (MyClient(source_p))
483 adx 30 {
484 michael 3110 sendto_one_notice(source_p, &me, ":The command %s %s is no longer supported, please use $%s",
485     command, nick, nick);
486 adx 30 return;
487     }
488    
489     if ((s = strrchr(nick, '.')) == NULL)
490     {
491 michael 3109 sendto_one_numeric(source_p, &me, ERR_NOTOPLEVEL, nick);
492 adx 30 return;
493     }
494    
495     while (*++s)
496     if (*s == '.' || *s == '*' || *s == '?')
497     break;
498    
499     if (*s == '*' || *s == '?')
500     {
501 michael 3109 sendto_one_numeric(source_p, &me, ERR_WILDTOPLEVEL, nick);
502 adx 30 return;
503     }
504 michael 2820
505 michael 3156 sendto_match_butone(IsServer(source_p->from) ? source_p->from : NULL, source_p,
506 adx 30 nick + 1, (*nick == '#') ? MATCH_HOST : MATCH_SERVER,
507     "%s $%s :%s", command, nick, text);
508     }
509     }
510    
511 michael 2796 /* build_target_list()
512 adx 30 *
513 michael 3159 * inputs - pointer to given source (oper/client etc.)
514 michael 2796 * - pointer to list of nicks/channels
515     * - pointer to table to place results
516     * - pointer to text (only used if source_p is an oper)
517     * output - number of valid entities
518     * side effects - target_table is modified to contain a list of
519     * pointers to channels or clients
520     * if source client is an oper
521     * all the classic old bizzare oper privmsg tricks
522     * are parsed and sent as is, if prefixed with $
523     * to disambiguate.
524     *
525 adx 30 */
526 michael 2796 static int
527 michael 3159 build_target_list(int p_or_n, const char *command, struct Client *source_p,
528 michael 3981 char *nicks_channels, const char *text)
529 adx 30 {
530 michael 2796 int type = 0;
531     char *p = NULL, *nick = NULL;
532     char *target_list = NULL;
533     struct Channel *chptr = NULL;
534     struct Client *target_p = NULL;
535 adx 30
536 michael 2796 target_list = nicks_channels;
537 adx 30
538 michael 2796 ntargets = 0;
539    
540     for (nick = strtoken(&p, target_list, ","); nick;
541 michael 3246 nick = strtoken(&p, NULL, ","))
542 adx 30 {
543 michael 3982 const char *with_prefix = NULL;
544 michael 2796
545     /*
546     * Channels are privmsg'd a lot more than other clients, moved up
547     * here plain old channel msg?
548     */
549     if (IsChanPrefix(*nick))
550 adx 30 {
551 michael 2796 if ((chptr = hash_find_channel(nick)))
552     {
553     if (!duplicate_ptr(chptr))
554     {
555 michael 4341 if (ntargets >= ConfigGeneral.max_targets)
556 michael 2796 {
557 michael 3109 sendto_one_numeric(source_p, &me, ERR_TOOMANYTARGETS,
558 michael 4341 nick, ConfigGeneral.max_targets);
559 michael 2796 return 1;
560     }
561 adx 30
562 michael 2796 targets[ntargets].ptr = chptr;
563     targets[ntargets++].type = ENTITY_CHANNEL;
564     }
565     }
566     else
567     {
568     if (p_or_n != NOTICE)
569 michael 3109 sendto_one_numeric(source_p, &me, ERR_NOSUCHNICK, nick);
570 michael 2796 }
571    
572     continue;
573     }
574    
575 michael 3774 /* Look for a PRIVMSG/NOTICE to another client */
576 michael 3156 if ((target_p = find_person(source_p, nick)))
577 michael 2796 {
578     if (!duplicate_ptr(target_p))
579     {
580 michael 4341 if (ntargets >= ConfigGeneral.max_targets)
581 michael 2796 {
582 michael 3109 sendto_one_numeric(source_p, &me, ERR_TOOMANYTARGETS,
583 michael 4341 nick, ConfigGeneral.max_targets);
584 michael 2796 return 1;
585     }
586    
587     targets[ntargets].ptr = target_p;
588     targets[ntargets].type = ENTITY_CLIENT;
589     targets[ntargets++].flags = 0;
590     }
591    
592     continue;
593     }
594 michael 2820
595 michael 2796 /* @#channel or +#channel message ? */
596     type = 0;
597     with_prefix = nick;
598    
599     /* Allow %+@ if someone wants to do that */
600 michael 3482 while (1)
601 michael 2796 {
602     if (*nick == '@')
603     type |= CHFL_CHANOP;
604     else if (*nick == '%')
605     type |= CHFL_CHANOP | CHFL_HALFOP;
606     else if (*nick == '+')
607     type |= CHFL_CHANOP | CHFL_HALFOP | CHFL_VOICE;
608     else
609     break;
610     ++nick;
611     }
612    
613 michael 3246 if (type)
614 michael 2796 {
615 michael 4299 if (EmptyString(nick)) /* If it's a '\0' dump it, there is no recipient */
616 michael 2796 {
617 michael 3109 sendto_one_numeric(source_p, &me, ERR_NORECIPIENT, command);
618 adx 30 continue;
619 michael 2796 }
620 adx 30
621 michael 2796 /*
622     * At this point, nick+1 should be a channel name i.e. #foo or &foo
623     * if the channel is found, fine, if not report an error
624     */
625     if ((chptr = hash_find_channel(nick)))
626 adx 30 {
627 michael 2796 if (IsClient(source_p) && !HasFlag(source_p, FLAGS_SERVICE))
628     {
629     if (!has_member_flags(find_channel_link(source_p, chptr),
630     CHFL_CHANOP|CHFL_HALFOP|CHFL_VOICE))
631     {
632 michael 3109 sendto_one_numeric(source_p, &me, ERR_CHANOPRIVSNEEDED, with_prefix);
633 michael 2796 return -1;
634     }
635     }
636    
637     if (!duplicate_ptr(chptr))
638     {
639 michael 4341 if (ntargets >= ConfigGeneral.max_targets)
640 michael 2796 {
641 michael 3109 sendto_one_numeric(source_p, &me, ERR_TOOMANYTARGETS,
642 michael 4341 nick, ConfigGeneral.max_targets);
643 michael 2820 return 1;
644 michael 2796 }
645    
646     targets[ntargets].ptr = chptr;
647     targets[ntargets].type = ENTITY_CHANOPS_ON_CHANNEL;
648     targets[ntargets++].flags = type;
649     }
650 adx 30 }
651 michael 2796 else
652     {
653     if (p_or_n != NOTICE)
654 michael 3109 sendto_one_numeric(source_p, &me, ERR_NOSUCHNICK, nick);
655 michael 2796 }
656    
657     continue;
658 adx 30 }
659 michael 2796
660     if (*nick == '$' || strchr(nick, '@'))
661 michael 3156 handle_special(p_or_n, command, source_p, nick, text);
662 michael 2796 else
663     {
664     if (p_or_n != NOTICE)
665     {
666     if (!IsDigit(*nick) || MyClient(source_p))
667 michael 3109 sendto_one_numeric(source_p, &me, ERR_NOSUCHNICK, nick);
668 michael 2796 }
669     }
670 adx 30 }
671    
672 michael 2796 return 1;
673 adx 30 }
674 michael 1230
675 michael 2796 /*
676     * inputs - flag privmsg or notice
677     * - pointer to command "PRIVMSG" or "NOTICE"
678     * - pointer to source_p
679     * - pointer to channel
680     */
681     static void
682 michael 4002 m_message(int p_or_n, const char *command, struct Client *source_p, int parc, char *parv[])
683 michael 2796 {
684     if (parc < 2 || EmptyString(parv[1]))
685     {
686     if (p_or_n != NOTICE)
687 michael 3109 sendto_one_numeric(source_p, &me, ERR_NORECIPIENT, command);
688 michael 2796 return;
689     }
690    
691     if (parc < 3 || EmptyString(parv[2]))
692     {
693     if (p_or_n != NOTICE)
694 michael 3109 sendto_one_numeric(source_p, &me, ERR_NOTEXTTOSEND);
695 michael 2796 return;
696     }
697    
698     /* Finish the flood grace period... */
699     if (MyClient(source_p) && !IsFloodDone(source_p))
700     flood_endgrace(source_p);
701    
702 michael 3156 if (build_target_list(p_or_n, command, source_p, parv[1], parv[2]) < 0)
703 michael 2796 return;
704    
705 michael 3283 for (unsigned int i = 0; i < ntargets; ++i)
706 michael 2796 {
707     switch (targets[i].type)
708     {
709 michael 3774 case ENTITY_CLIENT:
710     msg_client(p_or_n, command, source_p, targets[i].ptr, parv[2]);
711     break;
712    
713 michael 2796 case ENTITY_CHANNEL:
714 michael 3156 msg_channel(p_or_n, command, source_p, targets[i].ptr, parv[2]);
715 michael 2796 break;
716    
717     case ENTITY_CHANOPS_ON_CHANNEL:
718 michael 4002 msg_channel_flags(p_or_n, command, source_p, targets[i].ptr,
719     targets[i].flags, parv[2]);
720 michael 2796 break;
721     }
722     }
723     }
724    
725 michael 2820 static int
726 michael 3156 m_privmsg(struct Client *source_p, int parc, char *parv[])
727 michael 2796 {
728     /*
729     * Servers have no reason to send privmsgs, yet sometimes there is cause
730     * for a notice.. (for example remote kline replies) --fl_
731     */
732     if (!IsClient(source_p))
733 michael 2820 return 0;
734 michael 2796
735 michael 3973 if (MyConnect(source_p))
736     source_p->localClient->last_privmsg = CurrentTime;
737    
738 michael 3156 m_message(PRIVMSG, "PRIVMSG", source_p, parc, parv);
739 michael 2820 return 0;
740 michael 2796 }
741    
742 michael 2820 static int
743 michael 3156 m_notice(struct Client *source_p, int parc, char *parv[])
744 michael 2796 {
745 michael 3156 m_message(NOTICE, "NOTICE", source_p, parc, parv);
746 michael 2820 return 0;
747 michael 2796 }
748    
749     static struct Message privmsg_msgtab =
750     {
751 michael 4546 "PRIVMSG", NULL, 0, 0, 0, MAXPARA, MFLG_SLOW, 0,
752 michael 2820 { m_unregistered, m_privmsg, m_privmsg, m_ignore, m_privmsg, m_ignore }
753 michael 1230 };
754    
755 michael 2796 static struct Message notice_msgtab =
756     {
757 michael 4546 "NOTICE", NULL, 0, 0, 0, MAXPARA, MFLG_SLOW, 0,
758 michael 2820 { m_unregistered, m_notice, m_notice, m_ignore, m_notice, m_ignore }
759 michael 1230 };
760    
761     static void
762     module_init(void)
763     {
764     mod_add_cmd(&privmsg_msgtab);
765     mod_add_cmd(&notice_msgtab);
766     }
767    
768     static void
769     module_exit(void)
770     {
771     mod_del_cmd(&privmsg_msgtab);
772     mod_del_cmd(&notice_msgtab);
773     }
774    
775 michael 2796 struct module module_entry =
776     {
777 michael 1230 .node = { NULL, NULL, NULL },
778     .name = NULL,
779     .version = "$Revision$",
780     .handle = NULL,
781     .modinit = module_init,
782     .modexit = module_exit,
783     .flags = MODULE_FLAG_CORE
784     };

Properties

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