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: 6314
Committed: Sat Aug 1 18:06:37 2015 UTC (8 years, 8 months ago) by michael
Content type: text/x-csrc
File size: 20208 byte(s)
Log Message:
- Make use of the *Flag() macros in some more places

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 5346 * 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 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 michael 5455 ENTITY_CLIENT = 2
55 michael 3774 };
56 michael 2796
57 michael 4084 static struct
58 adx 30 {
59     void *ptr;
60 michael 5455 unsigned int type;
61     unsigned int flags;
62 michael 2786 } targets[IRCD_BUFSIZE];
63 adx 30
64 michael 3283 static int unsigned ntargets = 0;
65 michael 2786
66    
67 adx 30 /*
68     ** m_privmsg
69     **
70     ** massive cleanup
71     ** rev argv 6/91
72     **
73     ** Another massive cleanup Nov, 2000
74     ** (I don't think there is a single line left from 6/91. Maybe.)
75     ** m_privmsg and m_notice do basically the same thing.
76     ** in the original 2.8.2 code base, they were the same function
77     ** "m_message.c." When we did the great cleanup in conjuncton with bleep
78     ** of ircu fame, we split m_privmsg.c and m_notice.c.
79 michael 4299 ** I don't see the point of that now. It's harder to maintain, it's
80 adx 30 ** easier to introduce bugs into one version and not the other etc.
81     ** Really, the penalty of an extra function call isn't that big a deal folks.
82     ** -db Nov 13, 2000
83     **
84     */
85    
86 michael 2796 /* duplicate_ptr()
87     *
88     * inputs - pointer to check
89     * - pointer to table of entities
90     * - number of valid entities so far
91     * output - YES if duplicate pointer in table, NO if not.
92     * note, this does the canonize using pointers
93     * side effects - NONE
94     */
95     static int
96 michael 4084 duplicate_ptr(const void *const ptr)
97 adx 30 {
98 michael 3283 for (unsigned int i = 0; i < ntargets; ++i)
99 michael 2796 if (targets[i].ptr == ptr)
100     return 1;
101 adx 30
102 michael 2796 return 0;
103 adx 30 }
104    
105 michael 2796 /* flood_attack_client()
106 adx 30 *
107 michael 2796 * inputs - flag 0 if PRIVMSG 1 if NOTICE. RFC
108     * say NOTICE must not auto reply
109 michael 2820 * - pointer to source Client
110 michael 2796 * - pointer to target Client
111     * output - 1 if target is under flood attack
112     * side effects - check for flood attack on target target_p
113 adx 30 */
114     static int
115 michael 4002 flood_attack_client(int p_or_n, struct Client *source_p, struct Client *target_p)
116 adx 30 {
117 michael 5452 assert(MyClient(target_p));
118     assert(IsClient(source_p));
119 adx 30
120 michael 5452 if (HasUMode(source_p, UMODE_OPER) || HasFlag(source_p, FLAGS_SERVICE))
121     return 0;
122    
123 michael 6314 if (GlobalSetOptions.floodcount && !HasFlag(source_p, FLAGS_CANFLOOD))
124 adx 30 {
125 michael 4589 if ((target_p->connection->first_received_message_time + 1)
126 michael 2796 < CurrentTime)
127     {
128 michael 5452 const int delta =
129 michael 4589 CurrentTime - target_p->connection->first_received_message_time;
130     target_p->connection->received_number_of_privmsgs -= delta;
131     target_p->connection->first_received_message_time = CurrentTime;
132 adx 30
133 michael 4589 if (target_p->connection->received_number_of_privmsgs <= 0)
134 adx 30 {
135 michael 4589 target_p->connection->received_number_of_privmsgs = 0;
136 michael 2796 DelFlag(target_p, FLAGS_FLOOD_NOTICED);
137 adx 30 }
138     }
139    
140 michael 4589 if ((target_p->connection->received_number_of_privmsgs >=
141 michael 2796 GlobalSetOptions.floodcount) || HasFlag(target_p, FLAGS_FLOOD_NOTICED))
142 adx 30 {
143 michael 2796 if (!HasFlag(target_p, FLAGS_FLOOD_NOTICED))
144 adx 30 {
145 michael 2796 sendto_realops_flags(UMODE_BOTS, L_ALL, SEND_NOTICE,
146     "Possible Flooder %s on %s target: %s",
147     get_client_name(source_p, HIDE_IP),
148     source_p->servptr->name, target_p->name);
149 michael 3774
150 michael 2796 AddFlag(target_p, FLAGS_FLOOD_NOTICED);
151 michael 4589 target_p->connection->received_number_of_privmsgs += 2; /* Add a bit of penalty */
152 adx 30 }
153    
154 michael 3774 if (MyClient(source_p) && p_or_n != NOTICE)
155 michael 3110 sendto_one_notice(source_p, &me, ":*** Message to %s throttled due to flooding",
156     target_p->name);
157 michael 2796 return 1;
158 adx 30 }
159 michael 2796 else
160 michael 4589 target_p->connection->received_number_of_privmsgs++;
161 michael 2796 }
162 adx 30
163 michael 2796 return 0;
164     }
165 adx 30
166 michael 2796 /* flood_attack_channel()
167     *
168     * inputs - flag 0 if PRIVMSG 1 if NOTICE. RFC
169     * says NOTICE must not auto reply
170 michael 2820 * - pointer to source Client
171 michael 2796 * - pointer to target channel
172     * output - 1 if target is under flood attack
173     * side effects - check for flood attack on target chptr
174     */
175     static int
176 michael 4002 flood_attack_channel(int p_or_n, struct Client *source_p, struct Channel *chptr)
177 michael 2796 {
178 michael 6314 if (GlobalSetOptions.floodcount && !HasFlag(source_p, FLAGS_CANFLOOD))
179 michael 2796 {
180     if ((chptr->first_received_message_time + 1) < CurrentTime)
181     {
182 michael 5455 const int delta = CurrentTime - chptr->first_received_message_time;
183 michael 2796 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 michael 4617 source_p->servptr->name, chptr->name);
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 michael 4617 chptr->name);
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_flags()
220     *
221 michael 2820 * inputs - flag 0 if PRIVMSG 1 if NOTICE. RFC
222 adx 30 * say NOTICE must not auto reply
223     * - pointer to command, "PRIVMSG" or "NOTICE"
224     * - pointer to source_p
225     * - pointer to channel
226     * - flags
227     * - pointer to text to send
228     * output - NONE
229     * side effects - message given channel either chanop or voice
230     */
231     static void
232 michael 5455 msg_channel(int p_or_n, const char *command, struct Client *source_p,
233     struct Channel *chptr, unsigned int flags, const char *text)
234 adx 30 {
235 michael 5455 int result = 0;
236 michael 4084 unsigned int type = 0;
237 michael 5455 const char *prefix = "";
238 adx 30
239     if (flags & CHFL_VOICE)
240     {
241 michael 5626 type = CHFL_CHANOP | CHFL_HALFOP | CHFL_VOICE;
242 michael 5455 prefix = "+";
243 adx 30 }
244     else if (flags & CHFL_HALFOP)
245     {
246 michael 5626 type = CHFL_CHANOP | CHFL_HALFOP;
247 michael 5455 prefix = "%";
248     }
249     else if (flags & CHFL_CHANOP)
250 adx 30 {
251     type = CHFL_CHANOP;
252 michael 5455 prefix = "@";
253 adx 30 }
254    
255 michael 4527 /* Chanops and voiced can flood their own channel with impunity */
256     if ((result = can_send(chptr, source_p, NULL, text)) < 0)
257     {
258     if (result == CAN_SEND_OPV ||
259     !flood_attack_channel(p_or_n, source_p, chptr))
260 michael 5455 sendto_channel_butone(source_p, source_p, chptr, type, "%s %s%s :%s",
261     command, prefix, chptr->name, text);
262 michael 4527 }
263     else
264     {
265     if (p_or_n != NOTICE)
266     {
267     if (result == ERR_NOCTRLSONCHAN)
268     sendto_one_numeric(source_p, &me, ERR_NOCTRLSONCHAN,
269 michael 4617 chptr->name, text);
270 michael 5463 else if (result == ERR_NOCTCP)
271     sendto_one_numeric(source_p, &me, ERR_NOCTCP,
272     chptr->name, text);
273 michael 4527 else if (result == ERR_NEEDREGGEDNICK)
274     sendto_one_numeric(source_p, &me, ERR_NEEDREGGEDNICK,
275 michael 4617 chptr->name);
276 michael 4527 else
277     sendto_one_numeric(source_p, &me, ERR_CANNOTSENDTOCHAN,
278 michael 4617 chptr->name);
279 michael 4527 }
280     }
281 adx 30 }
282    
283     /* msg_client()
284     *
285 michael 2820 * inputs - flag 0 if PRIVMSG 1 if NOTICE. RFC
286 adx 30 * say NOTICE must not auto reply
287     * - pointer to command, "PRIVMSG" or "NOTICE"
288     * - pointer to source_p source (struct Client *)
289     * - pointer to target_p target (struct Client *)
290     * - pointer to text
291     * output - NONE
292     * side effects - message given channel either chanop or voice
293     */
294     static void
295     msg_client(int p_or_n, const char *command, struct Client *source_p,
296 michael 4002 struct Client *target_p, const char *text)
297 adx 30 {
298 michael 3974 if (MyClient(source_p))
299 adx 30 {
300 michael 3978 if (target_p->away[0] && p_or_n != NOTICE)
301 michael 3109 sendto_one_numeric(source_p, &me, RPL_AWAY, target_p->name, target_p->away);
302 michael 1175
303     if (HasUMode(target_p, UMODE_REGONLY) && target_p != source_p)
304 michael 1173 {
305 michael 5626 if (!HasUMode(source_p, UMODE_REGISTERED | UMODE_OPER))
306 michael 1175 {
307     if (p_or_n != NOTICE)
308 michael 3109 sendto_one_numeric(source_p, &me, ERR_NONONREG, target_p->name);
309 michael 1175 return;
310     }
311 michael 1173 }
312 adx 30 }
313    
314 michael 5452 if (MyClient(target_p) && IsClient(source_p))
315 adx 30 {
316 michael 5626 if (HasUMode(target_p, UMODE_CALLERID | UMODE_SOFTCALLERID) &&
317 michael 5452 !accept_message(source_p, target_p))
318 adx 30 {
319 michael 5452 const int callerid = !!HasUMode(target_p, UMODE_CALLERID);
320    
321     /* check for accept, flag recipient incoming message */
322     if (p_or_n != NOTICE)
323     sendto_one_numeric(source_p, &me, RPL_TARGUMODEG,
324     target_p->name,
325     callerid ? "+g" : "+G",
326     callerid ? "server side ignore" :
327     "server side ignore with the exception of common channels");
328    
329     if ((target_p->connection->last_caller_id_time +
330     ConfigGeneral.caller_id_wait) < CurrentTime)
331 adx 30 {
332     if (p_or_n != NOTICE)
333 michael 5452 sendto_one_numeric(source_p, &me, RPL_TARGNOTIFY, target_p->name);
334 adx 30
335 michael 5452 sendto_one_numeric(target_p, &me, RPL_UMODEGMSG,
336 michael 6154 source_p->name, source_p->username, source_p->host,
337 michael 5452 callerid ? "+g" : "+G");
338     target_p->connection->last_caller_id_time = CurrentTime;
339     }
340 adx 30
341 michael 5452 /* Only so opers can watch for floods */
342 michael 5453 flood_attack_client(NOTICE, source_p, target_p);
343 michael 5452 return;
344     }
345 adx 30
346 michael 5452 if (flood_attack_client(p_or_n, source_p, target_p))
347     return;
348     }
349 adx 30
350 michael 5452 sendto_anywhere(target_p, source_p, command, ":%s", text);
351 adx 30 }
352    
353     /* handle_special()
354     *
355 michael 3159 * inputs - client pointer
356 adx 30 * - nick stuff to grok for opers
357     * - text to send if grok
358     * output - none
359     * side effects - old style username@server is handled here for non opers
360     * opers are allowed username%hostname@server
361     * all the traditional oper type messages are also parsed here.
362     * i.e. "/msg #some.host."
363     * However, syntax has been changed.
364     * previous syntax "/msg #some.host.mask"
365     * now becomes "/msg $#some.host.mask"
366     * previous syntax of: "/msg $some.server.mask" remains
367     * This disambiguates the syntax.
368     *
369     * XXX N.B. dalnet changed it to nick@server as have other servers.
370     * we will stick with tradition for now.
371     * - Dianora
372     */
373     static void
374 michael 3159 handle_special(int p_or_n, const char *command, struct Client *source_p,
375 michael 3950 const char *nick, const char *text)
376 adx 30 {
377 michael 3948 struct Client *target_p = NULL;
378     const char *server = NULL, *s = NULL;
379 adx 30
380     /*
381     * user[%host]@server addressed?
382     */
383 michael 2796 if ((server = strchr(nick, '@')))
384 adx 30 {
385 michael 3969 if ((target_p = hash_find_server(server + 1)) == NULL)
386 adx 30 {
387 michael 3948 sendto_one_numeric(source_p, &me, ERR_NOSUCHSERVER, server + 1);
388 adx 30 return;
389     }
390    
391 michael 3948 if (!HasUMode(source_p, UMODE_OPER) && strchr(nick, '%'))
392 adx 30 {
393 michael 3948 sendto_one_numeric(source_p, &me, ERR_NOSUCHNICK, nick);
394     return;
395     }
396 michael 3774
397 michael 3948 if (!IsMe(target_p))
398     {
399     sendto_one(target_p, ":%s %s %s :%s", source_p->id, command, nick, text);
400     return;
401     }
402 adx 30
403 michael 3948 sendto_one_numeric(source_p, &me, ERR_NOSUCHNICK, nick);
404 adx 30 return;
405     }
406    
407 michael 1219 if (!HasUMode(source_p, UMODE_OPER))
408 adx 30 {
409 michael 3109 sendto_one_numeric(source_p, &me, ERR_NOPRIVILEGES);
410 adx 30 return;
411     }
412    
413     /*
414 michael 2796 * The following two cases allow masks in NOTICEs
415 adx 30 * (for OPERs only)
416     *
417     * Armin, 8Jun90 (gruner@informatik.tu-muenchen.de)
418     */
419     if (*nick == '$')
420     {
421 michael 3482 if (*(nick + 1) == '$' || *(nick + 1) == '#')
422 michael 2796 ++nick;
423 michael 3964 else if (MyClient(source_p))
424 adx 30 {
425 michael 3110 sendto_one_notice(source_p, &me, ":The command %s %s is no longer supported, please use $%s",
426     command, nick, nick);
427 adx 30 return;
428     }
429    
430     if ((s = strrchr(nick, '.')) == NULL)
431     {
432 michael 3109 sendto_one_numeric(source_p, &me, ERR_NOTOPLEVEL, nick);
433 adx 30 return;
434     }
435    
436     while (*++s)
437     if (*s == '.' || *s == '*' || *s == '?')
438     break;
439    
440     if (*s == '*' || *s == '?')
441     {
442 michael 3109 sendto_one_numeric(source_p, &me, ERR_WILDTOPLEVEL, nick);
443 adx 30 return;
444     }
445 michael 2820
446 michael 3156 sendto_match_butone(IsServer(source_p->from) ? source_p->from : NULL, source_p,
447 adx 30 nick + 1, (*nick == '#') ? MATCH_HOST : MATCH_SERVER,
448     "%s $%s :%s", command, nick, text);
449     }
450     }
451    
452 michael 2796 /* build_target_list()
453 adx 30 *
454 michael 3159 * inputs - pointer to given source (oper/client etc.)
455 michael 2796 * - pointer to list of nicks/channels
456     * - pointer to table to place results
457     * - pointer to text (only used if source_p is an oper)
458     * output - number of valid entities
459     * side effects - target_table is modified to contain a list of
460     * pointers to channels or clients
461     * if source client is an oper
462     * all the classic old bizzare oper privmsg tricks
463     * are parsed and sent as is, if prefixed with $
464     * to disambiguate.
465     *
466 adx 30 */
467 michael 2796 static int
468 michael 3159 build_target_list(int p_or_n, const char *command, struct Client *source_p,
469 michael 5455 char *list, const char *text)
470 adx 30 {
471 michael 5455 unsigned int type = 0;
472     char *p = NULL;
473     void *target = NULL;
474 adx 30
475 michael 2796 ntargets = 0;
476    
477 michael 5455 for (const char *name = strtoken(&p, list, ","); name;
478     name = strtoken(&p, NULL, ","))
479 adx 30 {
480 michael 3982 const char *with_prefix = NULL;
481 michael 2796
482     /*
483     * Channels are privmsg'd a lot more than other clients, moved up
484     * here plain old channel msg?
485     */
486 michael 5455 if (IsChanPrefix(*name))
487 adx 30 {
488 michael 5455 if ((target = hash_find_channel(name)))
489 michael 2796 {
490 michael 5455 if (!duplicate_ptr(target))
491 michael 2796 {
492 michael 4341 if (ntargets >= ConfigGeneral.max_targets)
493 michael 2796 {
494 michael 3109 sendto_one_numeric(source_p, &me, ERR_TOOMANYTARGETS,
495 michael 5455 name, ConfigGeneral.max_targets);
496 michael 2796 return 1;
497     }
498 adx 30
499 michael 5455 targets[ntargets].ptr = target;
500     targets[ntargets].type = ENTITY_CHANNEL;
501     targets[ntargets++].flags = 0;
502 michael 2796 }
503     }
504 michael 5455 else if (p_or_n != NOTICE)
505     sendto_one_numeric(source_p, &me, ERR_NOSUCHNICK, name);
506 michael 2796
507     continue;
508     }
509    
510 michael 3774 /* Look for a PRIVMSG/NOTICE to another client */
511 michael 5455 if ((target = find_person(source_p, name)))
512 michael 2796 {
513 michael 5455 if (!duplicate_ptr(target))
514 michael 2796 {
515 michael 4341 if (ntargets >= ConfigGeneral.max_targets)
516 michael 2796 {
517 michael 3109 sendto_one_numeric(source_p, &me, ERR_TOOMANYTARGETS,
518 michael 5455 name, ConfigGeneral.max_targets);
519 michael 2796 return 1;
520     }
521    
522 michael 5455 targets[ntargets].ptr = target;
523 michael 2796 targets[ntargets].type = ENTITY_CLIENT;
524     targets[ntargets++].flags = 0;
525     }
526    
527     continue;
528     }
529 michael 2820
530 michael 2796 /* @#channel or +#channel message ? */
531     type = 0;
532 michael 5455 with_prefix = name;
533 michael 2796
534     /* Allow %+@ if someone wants to do that */
535 michael 3482 while (1)
536 michael 2796 {
537 michael 5455 if (*name == '@')
538 michael 2796 type |= CHFL_CHANOP;
539 michael 5455 else if (*name == '%')
540 michael 2796 type |= CHFL_CHANOP | CHFL_HALFOP;
541 michael 5455 else if (*name == '+')
542 michael 2796 type |= CHFL_CHANOP | CHFL_HALFOP | CHFL_VOICE;
543     else
544     break;
545 michael 5455 ++name;
546 michael 2796 }
547    
548 michael 3246 if (type)
549 michael 2796 {
550 michael 5455 if (EmptyString(name)) /* If it's a '\0' dump it, there is no recipient */
551 michael 2796 {
552 michael 3109 sendto_one_numeric(source_p, &me, ERR_NORECIPIENT, command);
553 adx 30 continue;
554 michael 2796 }
555 adx 30
556 michael 2796 /*
557 michael 5455 * At this point, name+1 should be a channel name i.e. #foo or &foo
558 michael 2796 * if the channel is found, fine, if not report an error
559     */
560 michael 5455 if ((target = hash_find_channel(name)))
561 adx 30 {
562 michael 2796 if (IsClient(source_p) && !HasFlag(source_p, FLAGS_SERVICE))
563     {
564 michael 5455 if (!has_member_flags(find_channel_link(source_p, target),
565 michael 2796 CHFL_CHANOP|CHFL_HALFOP|CHFL_VOICE))
566     {
567 michael 3109 sendto_one_numeric(source_p, &me, ERR_CHANOPRIVSNEEDED, with_prefix);
568 michael 5458 continue;
569 michael 2796 }
570     }
571    
572 michael 5455 if (!duplicate_ptr(target))
573 michael 2796 {
574 michael 4341 if (ntargets >= ConfigGeneral.max_targets)
575 michael 2796 {
576 michael 3109 sendto_one_numeric(source_p, &me, ERR_TOOMANYTARGETS,
577 michael 5455 name, ConfigGeneral.max_targets);
578 michael 2820 return 1;
579 michael 2796 }
580    
581 michael 5455 targets[ntargets].ptr = target;
582     targets[ntargets].type = ENTITY_CHANNEL;
583 michael 2796 targets[ntargets++].flags = type;
584     }
585 adx 30 }
586 michael 5455 else if (p_or_n != NOTICE)
587     sendto_one_numeric(source_p, &me, ERR_NOSUCHNICK, name);
588 michael 2796
589     continue;
590 adx 30 }
591 michael 2796
592 michael 5455 if (*name == '$' || strchr(name, '@'))
593     handle_special(p_or_n, command, source_p, name, text);
594 michael 2796 else
595     {
596     if (p_or_n != NOTICE)
597     {
598 michael 5455 if (!IsDigit(*name) || MyClient(source_p))
599     sendto_one_numeric(source_p, &me, ERR_NOSUCHNICK, name);
600 michael 2796 }
601     }
602 adx 30 }
603    
604 michael 2796 return 1;
605 adx 30 }
606 michael 1230
607 michael 2796 /*
608     * inputs - flag privmsg or notice
609     * - pointer to command "PRIVMSG" or "NOTICE"
610     * - pointer to source_p
611     * - pointer to channel
612     */
613     static void
614 michael 4002 m_message(int p_or_n, const char *command, struct Client *source_p, int parc, char *parv[])
615 michael 2796 {
616     if (parc < 2 || EmptyString(parv[1]))
617     {
618     if (p_or_n != NOTICE)
619 michael 3109 sendto_one_numeric(source_p, &me, ERR_NORECIPIENT, command);
620 michael 2796 return;
621     }
622    
623     if (parc < 3 || EmptyString(parv[2]))
624     {
625     if (p_or_n != NOTICE)
626 michael 3109 sendto_one_numeric(source_p, &me, ERR_NOTEXTTOSEND);
627 michael 2796 return;
628     }
629    
630     /* Finish the flood grace period... */
631     if (MyClient(source_p) && !IsFloodDone(source_p))
632     flood_endgrace(source_p);
633    
634 michael 3156 if (build_target_list(p_or_n, command, source_p, parv[1], parv[2]) < 0)
635 michael 2796 return;
636    
637 michael 3283 for (unsigned int i = 0; i < ntargets; ++i)
638 michael 2796 {
639     switch (targets[i].type)
640     {
641 michael 3774 case ENTITY_CLIENT:
642     msg_client(p_or_n, command, source_p, targets[i].ptr, parv[2]);
643     break;
644    
645 michael 2796 case ENTITY_CHANNEL:
646 michael 5455 msg_channel(p_or_n, command, source_p, targets[i].ptr,
647     targets[i].flags, parv[2]);
648 michael 2796 break;
649     }
650     }
651     }
652    
653 michael 2820 static int
654 michael 3156 m_privmsg(struct Client *source_p, int parc, char *parv[])
655 michael 2796 {
656     /*
657     * Servers have no reason to send privmsgs, yet sometimes there is cause
658     * for a notice.. (for example remote kline replies) --fl_
659     */
660     if (!IsClient(source_p))
661 michael 2820 return 0;
662 michael 2796
663 michael 3973 if (MyConnect(source_p))
664 michael 4589 source_p->connection->last_privmsg = CurrentTime;
665 michael 3973
666 michael 3156 m_message(PRIVMSG, "PRIVMSG", source_p, parc, parv);
667 michael 2820 return 0;
668 michael 2796 }
669    
670 michael 2820 static int
671 michael 3156 m_notice(struct Client *source_p, int parc, char *parv[])
672 michael 2796 {
673 michael 3156 m_message(NOTICE, "NOTICE", source_p, parc, parv);
674 michael 2820 return 0;
675 michael 2796 }
676    
677     static struct Message privmsg_msgtab =
678     {
679 michael 5880 .cmd = "PRIVMSG",
680     .args_max = MAXPARA,
681     .handlers[UNREGISTERED_HANDLER] = m_unregistered,
682     .handlers[CLIENT_HANDLER] = m_privmsg,
683     .handlers[SERVER_HANDLER] = m_privmsg,
684     .handlers[ENCAP_HANDLER] = m_ignore,
685     .handlers[OPER_HANDLER] = m_privmsg
686 michael 1230 };
687    
688 michael 2796 static struct Message notice_msgtab =
689     {
690 michael 5880 .cmd = "NOTICE",
691     .args_max = MAXPARA,
692     .handlers[UNREGISTERED_HANDLER] = m_unregistered,
693     .handlers[CLIENT_HANDLER] = m_notice,
694     .handlers[SERVER_HANDLER] = m_notice,
695     .handlers[ENCAP_HANDLER] = m_ignore,
696     .handlers[OPER_HANDLER] = m_notice
697 michael 1230 };
698    
699     static void
700     module_init(void)
701     {
702     mod_add_cmd(&privmsg_msgtab);
703     mod_add_cmd(&notice_msgtab);
704     }
705    
706     static void
707     module_exit(void)
708     {
709     mod_del_cmd(&privmsg_msgtab);
710     mod_del_cmd(&notice_msgtab);
711     }
712    
713 michael 2796 struct module module_entry =
714     {
715 michael 1230 .version = "$Revision$",
716     .modinit = module_init,
717     .modexit = module_exit,
718     .flags = MODULE_FLAG_CORE
719     };

Properties

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