1 /*
2 * Copyright (C) 1998 Mark Baysinger (mbaysing@ucsd.edu)
3 * Copyright (C) 1998,1999,2001,2002 Ross Combs (rocombs@cs.nmsu.edu)
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19 #define MESSAGE_INTERNAL_ACCESS
20 #include "common/setup_before.h"
21 #include <stdio.h>
22 #ifdef HAVE_STDDEF_H
23 # include <stddef.h>
24 #else
25 # ifndef NULL
26 # define NULL ((void *)0)
27 # endif
28 #endif
29 #ifdef STDC_HEADERS
30 # include <stdlib.h>
31 #else
32 # ifdef HAVE_MALLOC_H
33 # include <malloc.h>
34 # endif
35 #endif
36 #ifdef HAVE_STRING_H
37 # include <string.h>
38 #else
39 # ifdef HAVE_STRINGS_H
40 # include <strings.h>
41 # endif
42 #endif
43 #include "compat/strdup.h"
44 #ifdef HAVE_UNISTD_H
45 # include <unistd.h>
46 #endif
47 #include "compat/gethostname.h"
48 #include <errno.h>
49 #include "compat/strerror.h"
50 #include "connection.h"
51 #include "common/bn_type.h"
52 #include "common/queue.h"
53 #include "common/packet.h"
54 #include "common/bot_protocol.h"
55 #include "common/bnet_protocol.h"
56 #include "common/field_sizes.h"
57 #include "common/eventlog.h"
58 #include "common/list.h"
59 #include "common/util.h"
60 #include "common/version.h"
61 #include "common/addr.h"
62 #include "account.h"
63 #include "account_wrap.h"
64 #include "game.h"
65 #include "channel.h"
66 #include "channel_conv.h"
67 #include "command.h"
68 #include "irc.h"
69 #include "message.h"
70 #include "mail.h"
71 #include "prefs.h"
72 #include "common/tag.h"
73 #include "common/xalloc.h"
74 #include "common/setup_after.h"
75
76 static int message_telnet_format(t_packet * packet, t_message_type type, t_connection * me, t_connection * dst, char const * text, unsigned int dstflags);
77 static int message_bot_format(t_packet * packet, t_message_type type, t_connection * me, t_connection * dst, char const * text, unsigned int dstflags);
78 static int message_bnet_format(t_packet * packet, t_message_type type, t_connection * me, t_connection * dst, char const * text, unsigned int dstflags);
79 static t_packet * message_cache_lookup(t_message * message, t_connection *dst, unsigned int flags);
80
message_type_get_str(t_message_type type)81 static char const * message_type_get_str(t_message_type type)
82 {
83 switch (type)
84 {
85 case message_type_adduser:
86 return "adduser";
87 case message_type_join:
88 return "join";
89 case message_type_part:
90 return "part";
91 case message_type_whisper:
92 return "whisper";
93 case message_type_talk:
94 return "talk";
95 case message_type_broadcast:
96 return "broadcast";
97 case message_type_channel:
98 return "channel";
99 case message_type_userflags:
100 return "userflags";
101 case message_type_whisperack:
102 return "whisperack";
103 case message_type_friendwhisperack: //[zap-zero] 20020518
104 return "friendwhisperack";
105 case message_type_channelfull:
106 return "channelfull";
107 case message_type_channeldoesnotexist:
108 return "channeldoesnotexist";
109 case message_type_channelrestricted:
110 return "channelrestricted";
111 case message_type_info:
112 return "info";
113 case message_type_error:
114 return "error";
115 case message_type_emote:
116 return "emote";
117 case message_type_uniqueid:
118 return "uniqueid";
119 case message_type_mode:
120 return "mode";
121 case message_type_notice:
122 return "notice";
123 case message_type_null:
124 return "null";
125 default:
126 return "UNKNOWN";
127 }
128 }
129
130
131 /* make sure none of the expanded format symbols is longer than this (with null) */
132 #define MAX_INC 64
133
message_format_line(t_connection const * c,char const * in)134 extern char * message_format_line(t_connection const * c, char const * in)
135 {
136 char * out;
137 unsigned int inpos;
138 unsigned int outpos;
139 unsigned int outlen=MAX_INC;
140 unsigned int inlen;
141 char clienttag_str[5];
142
143 out = xmalloc(outlen+1);
144
145 inlen = strlen(in);
146 out[0] = 'I';
147 for (inpos=0,outpos=1; inpos<inlen; inpos++)
148 {
149 if (in[inpos]!='%')
150 {
151 out[outpos] = in[inpos];
152 outpos += 1;
153 }
154 else
155 switch (in[++inpos])
156 {
157 case '%':
158 out[outpos++] = '%';
159 break;
160
161 case 'a':
162 sprintf(&out[outpos],"%u",accountlist_get_length());
163 outpos += strlen(&out[outpos]);
164 break;
165
166 case 'c':
167 sprintf(&out[outpos],"%d",channellist_get_length());
168 outpos += strlen(&out[outpos]);
169 break;
170
171 case 'g':
172 sprintf(&out[outpos],"%d",gamelist_get_length());
173 outpos += strlen(&out[outpos]);
174 break;
175
176 case 'h':
177 if (gethostname(&out[outpos],MAX_INC)<0)
178 {
179 eventlog(eventlog_level_error,__FUNCTION__,"could not get hostname (gethostname: %s)",pstrerror(errno));
180 strcpy(&out[outpos],"localhost"); /* not much else you can do */
181 }
182 outpos += strlen(&out[outpos]);
183 break;
184
185 case 'i':
186 sprintf(&out[outpos],UID_FORMAT,conn_get_userid(c));
187 outpos += strlen(&out[outpos]);
188 break;
189
190 case 'l':
191 {
192 char const * tname;
193
194 strncpy(&out[outpos],(tname = (conn_get_chatname(c)?conn_get_chatname(c):conn_get_loggeduser(c))),USER_NAME_MAX-1);
195 conn_unget_chatname(c,tname);
196 }
197 out[outpos+USER_NAME_MAX-1] = '\0';
198 outpos += strlen(&out[outpos]);
199 break;
200
201 case 'm':
202 sprintf(&out[outpos],"%s",check_mail(c));
203 outpos += strlen(&out[outpos]);
204 break;
205
206 case 'r':
207 strncpy(&out[outpos],addr_num_to_ip_str(conn_get_addr(c)),MAX_INC-1);
208 out[outpos+MAX_INC-1] = '\0';
209 outpos += strlen(&out[outpos]);
210 break;
211
212 case 's':
213 sprintf(&out[outpos],"%s",prefs_get_servername());
214 outpos += strlen(&out[outpos]);
215 break;
216
217 case 't':
218 sprintf(&out[outpos],"%s",tag_uint_to_str(clienttag_str,conn_get_clienttag(c)));
219 outpos += strlen(&out[outpos]);
220 break;
221
222 case 'u':
223 sprintf(&out[outpos],"%d",connlist_login_get_length());
224 outpos += strlen(&out[outpos]);
225 break;
226
227 case 'v':
228 strcpy(&out[outpos],PVPGN_SOFTWARE" "PVPGN_VERSION);
229 outpos += strlen(&out[outpos]);
230 break;
231
232 case 'C': /* simulated command */
233 out[0] = 'C';
234 break;
235
236 case 'B': /* BROADCAST */
237 out[0] = 'B';
238 break;
239
240 case 'E': /* ERROR */
241 out[0] = 'E';
242 break;
243
244 case 'G':
245 sprintf(&out[outpos],"%d",game_get_count_by_clienttag(conn_get_clienttag(c)));
246 outpos += strlen(&out[outpos]);
247 break;
248
249 case 'H':
250 strcpy(&out[outpos],prefs_get_contact_name());
251 outpos += strlen(&out[outpos]);
252 break;
253
254 case 'I': /* INFO */
255 out[0] = 'I';
256 break;
257
258 case 'M': /* MESSAGE */
259 out[0] = 'M';
260 break;
261
262 case 'N':
263 strcpy(&out[outpos],clienttag_get_title(conn_get_clienttag(c)));
264 outpos += strlen(&out[outpos]);
265 break;
266
267 case 'T': /* EMOTE */
268 out[0] = 'T';
269 break;
270
271 case 'U':
272 sprintf(&out[outpos],"%d",conn_get_user_count_by_clienttag(conn_get_clienttag(c)));
273 outpos += strlen(&out[outpos]);
274 break;
275
276 case 'W': /* INFO */
277 out[0] = 'W';
278 break;
279
280 default:
281 eventlog(eventlog_level_warn,__FUNCTION__,"bad formatter \"%%%c\"",in[inpos-1]);
282 }
283
284 if ((outpos+MAX_INC)>=outlen)
285 {
286 char * newout;
287
288 outlen += MAX_INC;
289 newout = xrealloc(out,outlen);
290 out = newout;
291 }
292 }
293 out[outpos] = '\0';
294
295 return out;
296 }
297
298
message_telnet_format(t_packet * packet,t_message_type type,t_connection * me,t_connection * dst,char const * text,unsigned int dstflags)299 static int message_telnet_format(t_packet * packet, t_message_type type, t_connection * me, t_connection * dst, char const * text, unsigned int dstflags)
300 {
301 char * msgtemp;
302
303 if (!packet)
304 {
305 eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet");
306 return -1;
307 }
308
309 switch (type)
310 {
311 case message_type_uniqueid:
312 if (!text)
313 {
314 eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type));
315 return -1;
316 }
317 msgtemp = xmalloc(strlen(text)+32);
318 sprintf(msgtemp,"Your unique name: %s\r\n",text);
319 break;
320 case message_type_adduser:
321 if (!me)
322 {
323 eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type));
324 return -1;
325 }
326 {
327 char const * tname;
328
329 tname = conn_get_chatcharname(me, dst);
330 msgtemp = xmalloc(strlen(tname)+32);
331 sprintf(msgtemp,"[%s is here]\r\n",tname);
332 conn_unget_chatcharname(me,tname);
333 }
334 break;
335 case message_type_join:
336 if (!me)
337 {
338 eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type));
339 return -1;
340 }
341 {
342 char const * tname;
343
344 tname = conn_get_chatcharname(me, dst);
345 msgtemp = xmalloc(strlen(tname)+32);
346 sprintf(msgtemp,"[%s enters]\r\n",tname);
347 conn_unget_chatcharname(me,tname);
348 }
349 break;
350 case message_type_part:
351 if (!me)
352 {
353 eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type));
354 return -1;
355 }
356 {
357 char const * tname;
358
359 tname = conn_get_chatcharname(me, dst);
360 msgtemp = xmalloc(strlen(tname)+32);
361 sprintf(msgtemp,"[%s leaves]\r\n",tname);
362 conn_unget_chatcharname(me,tname);
363 }
364 break;
365 case message_type_whisper:
366 case message_type_notice:
367 if (!text)
368 {
369 eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type));
370 return -1;
371 }
372 if (dstflags&MF_X)
373 return -1; /* player is ignored */
374 {
375 char const * tname;
376 char const * newtext;
377
378 if (me)
379 tname = conn_get_chatcharname(me, dst);
380 else
381 tname = prefs_get_servername();
382
383 if ((newtext = escape_chars(text,strlen(text))))
384 {
385 msgtemp = xmalloc(strlen(tname)+8+strlen(newtext)+4);
386 sprintf(msgtemp,"<from %s> %s\r\n",tname,newtext);
387 xfree((void *)newtext); /* avoid warning */
388 }
389 else
390 {
391 msgtemp = xmalloc(16+strlen(tname));
392 sprintf(msgtemp,"<from %s> \r\n",tname);
393 }
394 if (me)
395 conn_unget_chatcharname(me,tname);
396 }
397 break;
398 case message_type_talk:
399 if (!text)
400 {
401 eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type));
402 return -1;
403 }
404 if (dstflags&MF_X)
405 return -1; /* player is ignored */
406 {
407 char const * tname;
408 char const * newtext;
409
410 if (me)
411 tname = conn_get_chatcharname(me, dst);
412 else
413 tname = prefs_get_servername();
414
415 if ((newtext = escape_chars(text,strlen(text))))
416 {
417 msgtemp = xmalloc(strlen(tname)+4+strlen(newtext)+4);
418 sprintf(msgtemp,"<%s> %s\r\n",tname,newtext);
419 xfree((void *)newtext); /* avoid warning */
420 }
421 else
422 {
423 msgtemp = xmalloc(strlen(tname)+8);
424 sprintf(msgtemp,"<%s> \r\n",tname);
425 }
426 if (me)
427 conn_unget_chatcharname(me,tname);
428 }
429 break;
430 case message_type_broadcast:
431 if (!text)
432 {
433 eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type));
434 return -1;
435 }
436 if (dstflags&MF_X)
437 return -1; /* player is ignored */
438 {
439 char const * newtext;
440
441 if ((newtext = escape_chars(text,strlen(text))))
442 {
443 msgtemp = xmalloc(16+strlen(newtext)+4);
444 sprintf(msgtemp,"Broadcast: %s\r\n",newtext); /* FIXME: show source? */
445 xfree((void *)newtext); /* avoid warning */
446 }
447 else
448 {
449 msgtemp = xmalloc(16);
450 sprintf(msgtemp,"Broadcast: \r\n"); /* FIXME: show source? */
451 }
452 }
453 break;
454 case message_type_channel:
455 if (!text)
456 {
457 eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type));
458 return -1;
459 }
460 msgtemp = xmalloc(strlen(text)+32);
461 sprintf(msgtemp,"Joining channel: \"%s\"\r\n",text);
462 break;
463 case message_type_userflags:
464 if (!me)
465 {
466 eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type));
467 return -1;
468 }
469 msgtemp = xstrdup("");
470 break;
471 case message_type_whisperack:
472 if (!me)
473 {
474 eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type));
475 return -1;
476 }
477 if (!text)
478 {
479 eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type));
480 return -1;
481 }
482 {
483 char const * tname;
484 char const * newtext;
485
486 tname = conn_get_chatcharname(me, dst);
487 if ((newtext = escape_chars(text,strlen(text))))
488 {
489 msgtemp = xmalloc(strlen(tname)+8+strlen(newtext)+4);
490 sprintf(msgtemp,"<to %s> %s\r\n",tname,newtext);
491 xfree((void *)newtext); /* avoid warning */
492 }
493 else
494 {
495 msgtemp = xmalloc(strlen(tname)+8+strlen(text)+4);
496 sprintf(msgtemp,"<to %s> %s\r\n",tname,text);
497 }
498 conn_unget_chatcharname(me,tname);
499 }
500 break;
501 case message_type_friendwhisperack: // [zap-zero] 20020518
502 if (!me)
503 {
504 eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type));
505 return -1;
506 }
507 if (!text)
508 {
509 eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type));
510 return -1;
511 }
512 {
513 char const * newtext;
514
515 if ((newtext = escape_chars(text,strlen(text))))
516 {
517 msgtemp = xmalloc(14+8+strlen(newtext)+4);
518 sprintf(msgtemp,"<to your friends> %s\r\n",newtext);
519 xfree((void *)newtext); /* avoid warning */
520 }
521 else
522 {
523 msgtemp = xmalloc(14+8+strlen(text)+4);
524 sprintf(msgtemp,"<to your friends> %s\r\n",text);
525 }
526 }
527 break;
528
529 case message_type_channelfull:
530 /* FIXME */
531 msgtemp = xstrdup("");
532 break;
533 case message_type_channeldoesnotexist:
534 /* FIXME */
535 msgtemp = xstrdup("");
536 break;
537 case message_type_channelrestricted:
538 /* FIXME */
539 msgtemp = xstrdup("");
540 break;
541 case message_type_info:
542 if (!text)
543 {
544 eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type));
545 return -1;
546 }
547 {
548 char const * newtext;
549
550 if ((newtext = escape_chars(text,strlen(text))))
551 {
552 msgtemp = xmalloc(strlen(newtext)+4);
553 sprintf(msgtemp,"%s\r\n",newtext);
554 xfree((void *)newtext); /* avoid warning */
555 }
556 else
557 {
558 msgtemp = xmalloc(strlen(text)+4);
559 sprintf(msgtemp,"%s\r\n",text);
560 }
561 }
562 break;
563 case message_type_error:
564 if (!text)
565 {
566 eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type));
567 return -1;
568 }
569 {
570 char const * newtext;
571
572 if ((newtext = escape_chars(text,strlen(text))))
573 {
574 msgtemp = xmalloc(8+strlen(newtext)+4);
575 sprintf(msgtemp,"ERROR: %s\r\n",newtext);
576 xfree((void *)newtext); /* avoid warning */
577 }
578 else
579 {
580 msgtemp = xmalloc(8+strlen(text)+4);
581 sprintf(msgtemp,"ERROR: %s\r\n",text);
582 }
583 }
584 break;
585 case message_type_emote:
586 if (!me)
587 {
588 eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type));
589 return -1;
590 }
591 if (!text)
592 {
593 eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type));
594 return -1;
595 }
596 if (dstflags&MF_X)
597 return -1; /* player is ignored */
598 {
599 char const * tname;
600 char const * newtext;
601
602 tname = conn_get_chatcharname(me, dst);
603 if ((newtext = escape_chars(text,strlen(text))))
604 {
605 msgtemp = xmalloc(strlen(tname)+4+strlen(newtext)+4);
606 sprintf(msgtemp,"<%s %s>\r\n",tname,newtext);
607 xfree((void *)newtext); /* avoid warning */
608 }
609 else
610 {
611 msgtemp = xmalloc(strlen(tname)+4+strlen(text)+4);
612 sprintf(msgtemp,"<%s %s>\r\n",tname,text);
613 }
614 conn_unget_chatcharname(me,tname);
615 }
616 break;
617 case message_type_mode:
618 if (!me)
619 {
620 eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type));
621 return -1;
622 }
623 {
624 char const * tname;
625
626 tname = conn_get_chatcharname(me,dst);
627 msgtemp = xmalloc(strlen(tname)+32);
628 sprintf(msgtemp,"%s change mode: %s\r\n",tname,text);
629 conn_unget_chatcharname(me,tname);
630 }
631 default:
632 eventlog(eventlog_level_error,__FUNCTION__,"got bad message type %d",(int)type);
633 return -1;
634 }
635
636 {
637 int retval;
638
639 retval = packet_append_ntstring(packet,msgtemp);
640 xfree(msgtemp);
641 return retval;
642 }
643 }
644
645
message_bot_format(t_packet * packet,t_message_type type,t_connection * me,t_connection * dst,char const * text,unsigned int dstflags)646 static int message_bot_format(t_packet * packet, t_message_type type, t_connection * me, t_connection * dst, char const * text, unsigned int dstflags)
647 {
648 char * msgtemp;
649 char clienttag_str[5];
650
651 if (!packet)
652 {
653 eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet");
654 return -1;
655 }
656
657 /* special-case the login banner so it doesn't have numbers
658 * at the start of each line
659 */
660 if (me &&
661 conn_get_state(me)!=conn_state_loggedin &&
662 conn_get_state(me)!=conn_state_destroy &&
663 type!=message_type_null) /* this does not apply for NULL messages */
664 {
665 if (!text)
666 {
667 #if 0
668 /* battle.net actually sends them during login */
669 if (type==message_type_null)
670 return 0; /* don't display null messages during the login */
671 #endif
672 eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for non-loggedin state");
673 return -1;
674 }
675 msgtemp = xmalloc(strlen(text)+4);
676 sprintf(msgtemp,"%s\r\n",text);
677 }
678 else
679 switch (type)
680 {
681 case message_type_null:
682 msgtemp = xmalloc(32);
683 sprintf(msgtemp,"%u %s\r\n",EID_NULL,"NULL");
684 break;
685 case message_type_uniqueid: /* FIXME: need to send this for some bots, also needed to support guest accounts */
686 if (!text)
687 {
688 eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type));
689 return -1;
690 }
691 msgtemp = xmalloc(strlen(text)+32);
692 sprintf(msgtemp,"%u %s %s\r\n",EID_UNIQUENAME,"NAME",text);
693 break;
694 case message_type_adduser:
695 if (!me)
696 {
697 eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type));
698 return -1;
699 }
700 {
701 char const * tname;
702
703 tname = conn_get_chatcharname(me, dst);
704 msgtemp = xmalloc(32+strlen(tname)+32);
705 sprintf(msgtemp,"%u %s %s %04x [%s]\r\n",EID_SHOWUSER,"USER",tname,conn_get_flags(me)|dstflags,tag_uint_to_str(clienttag_str,conn_get_fake_clienttag(me)));
706 conn_unget_chatcharname(me,tname);
707 }
708 break;
709 case message_type_join:
710 if (!me)
711 {
712 eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type));
713 return -1;
714 }
715 {
716 char const * tname;
717
718 tname = conn_get_chatcharname(me, dst);
719 msgtemp = xmalloc(32+strlen(tname)+32);
720 sprintf(msgtemp,"%u %s %s %04x [%s]\r\n",EID_JOIN,"JOIN",tname,conn_get_flags(me)|dstflags,tag_uint_to_str(clienttag_str,conn_get_fake_clienttag(me)));
721 conn_unget_chatcharname(me,tname);
722 }
723 break;
724 case message_type_part:
725 if (!me)
726 {
727 eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type));
728 return -1;
729 }
730 {
731 char const * tname;
732
733 tname = conn_get_chatcharname(me, dst);
734 msgtemp = xmalloc(32+strlen(tname)+32);
735 sprintf(msgtemp,"%u %s %s %04x\r\n",EID_LEAVE,"LEAVE",tname,conn_get_flags(me)|dstflags);
736 conn_unget_chatcharname(me,tname);
737 }
738 break;
739 case message_type_whisper:
740 case message_type_notice:
741 if (!text)
742 {
743 eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type));
744 return -1;
745 }
746 if (dstflags&MF_X)
747 return -1; /* player is ignored */
748 {
749 char const * tname;
750
751 if (me)
752 tname = conn_get_chatcharname(me, dst);
753 else
754 tname = prefs_get_servername();
755
756 msgtemp = xmalloc(32+strlen(tname)+32+strlen(text));
757 sprintf(msgtemp,"%u %s %s %04x \"%s\"\r\n",EID_WHISPER,"WHISPER",tname,me?conn_get_flags(me)|dstflags:dstflags,text);
758 if (me)
759 conn_unget_chatcharname(me,tname);
760 }
761 break;
762 case message_type_talk:
763 if (!me)
764 {
765 eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type));
766 return -1;
767 }
768 if (!text)
769 {
770 eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type));
771 return -1;
772 }
773 if (dstflags&MF_X)
774 return -1; /* player is ignored */
775 {
776 char const * tname;
777
778 tname = conn_get_chatcharname(me, dst);
779 msgtemp = xmalloc(32+strlen(tname)+32+strlen(text));
780 sprintf(msgtemp,"%u %s %s %04x \"%s\"\r\n",EID_TALK,"TALK",tname,conn_get_flags(me)|dstflags,text);
781 conn_unget_chatcharname(me,tname);
782 }
783 break;
784 case message_type_broadcast:
785 if (!text)
786 {
787 eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type));
788 return -1;
789 }
790 if (dstflags&MF_X)
791 return -1; /* player is ignored */
792 msgtemp = xmalloc(32+32+strlen(text));
793 sprintf(msgtemp,"%u %s \"%s\"\r\n",EID_BROADCAST,"_",text); /* FIXME: what does this look like on Battle.net? */
794 break;
795 case message_type_channel:
796 if (!text)
797 {
798 eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type));
799 return -1;
800 }
801 msgtemp = xmalloc(32+strlen(text));
802 sprintf(msgtemp,"%u %s \"%s\"\r\n",EID_CHANNEL,"CHANNEL",text);
803 break;
804 case message_type_userflags:
805 if (!me)
806 {
807 eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type));
808 return -1;
809 }
810 {
811 char const * tname;
812
813 tname = conn_get_chatcharname(me, dst);
814 msgtemp = xmalloc(32+strlen(tname)+16);
815 sprintf(msgtemp,"%u %s %s %04x\r\n",EID_USERFLAGS,"USER",tname,conn_get_flags(me)|dstflags);
816 conn_unget_chatcharname(me,tname);
817 }
818 break;
819 case message_type_whisperack:
820 if (!me)
821 {
822 eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type));
823 return -1;
824 }
825 if (!text)
826 {
827 eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type));
828 return -1;
829 }
830 {
831 char const * tname;
832
833 tname = conn_get_chatcharname(me, dst);
834 msgtemp = xmalloc(32+strlen(tname)+32+strlen(text));
835 sprintf(msgtemp,"%u %s %s %04x \"%s\"\r\n",EID_WHISPERSENT,"WHISPER",tname,conn_get_flags(me)|dstflags,text);
836 conn_unget_chatcharname(me,tname);
837 }
838 break;
839 case message_type_friendwhisperack: // [zap-zero] 20020518
840 if (!me)
841 {
842 eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type));
843 return -1;
844 }
845 if (!text)
846 {
847 eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type));
848 return -1;
849 }
850 {
851 msgtemp = xmalloc(32+16+32+strlen(text));
852 sprintf(msgtemp,"%u %s \"your friends\" %04x \"%s\"\r\n",EID_WHISPERSENT,"WHISPER",conn_get_flags(me)|dstflags,text);
853 }
854 break;
855
856 case message_type_channelfull:
857 msgtemp = xmalloc(32);
858 sprintf(msgtemp,"%u \r\n",EID_CHANNELFULL); /* FIXME */
859 break;
860 case message_type_channeldoesnotexist:
861 msgtemp = xmalloc(32);
862 sprintf(msgtemp,"%u \r\n",EID_CHANNELDOESNOTEXIST); /* FIXME */
863 break;
864 case message_type_channelrestricted:
865 msgtemp = xmalloc(32);
866 sprintf(msgtemp,"%u \r\n",EID_CHANNELRESTRICTED); /* FIXME */
867 break;
868 case message_type_info:
869 if (!text)
870 {
871 eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type));
872 return -1;
873 }
874 msgtemp = xmalloc(32+16+strlen(text));
875 sprintf(msgtemp,"%u %s \"%s\"\r\n",EID_INFO,"INFO",text);
876 break;
877 case message_type_error:
878 if (!text)
879 {
880 eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type));
881 return -1;
882 }
883 msgtemp = xmalloc(32+16+strlen(text));
884 sprintf(msgtemp,"%u %s \"%s\"\r\n",EID_ERROR,"ERROR",text);
885 break;
886 case message_type_emote:
887 if (!me)
888 {
889 eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type));
890 return -1;
891 }
892 if (!text)
893 {
894 eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type));
895 return -1;
896 }
897 if (dstflags&MF_X)
898 return -1; /* player is ignored */
899 {
900 char const * tname;
901
902 tname = conn_get_chatcharname(me, dst);
903 msgtemp = xmalloc(32+strlen(tname)+32+strlen(text));
904 sprintf(msgtemp,"%u %s %s %04x \"%s\"\r\n",EID_EMOTE,"EMOTE",tname,conn_get_flags(me)|dstflags,text);
905 conn_unget_chatcharname(me,tname);
906 }
907 break;
908 default:
909 eventlog(eventlog_level_error,__FUNCTION__,"got bad message type %d",(int)type);
910 return -1;
911 }
912
913 if (strlen(msgtemp)>MAX_MESSAGE_LEN)
914 msgtemp[MAX_MESSAGE_LEN] = '\0'; /* now truncate to max size */
915
916 {
917 int retval;
918
919 retval = packet_append_ntstring(packet,msgtemp);
920 xfree(msgtemp);
921 return retval;
922 }
923 }
924
925
message_bnet_format(t_packet * packet,t_message_type type,t_connection * me,t_connection * dst,char const * text,unsigned int dstflags)926 static int message_bnet_format(t_packet * packet, t_message_type type, t_connection * me, t_connection * dst, char const * text, unsigned int dstflags)
927 {
928 if (!packet)
929 {
930 eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet");
931 return -1;
932 }
933
934 if (text && text[0]=='\0')
935 text = " "; /* empty messages crash some clients, just send whitespace */
936
937 packet_set_size(packet,sizeof(t_server_message));
938 packet_set_type(packet,SERVER_MESSAGE);
939 bn_int_set(&packet->u.server_message.player_ip,SERVER_MESSAGE_PLAYER_IP_DUMMY);
940 bn_int_nset(&packet->u.server_message.account_num,SERVER_MESSAGE_ACCOUNT_NUM);
941 bn_int_set(&packet->u.server_message.reg_auth,SERVER_MESSAGE_REG_AUTH);
942
943 switch (type)
944 {
945 case message_type_adduser:
946 if (!me)
947 {
948 eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type));
949 return -1;
950 }
951 bn_int_set(&packet->u.server_message.type,SERVER_MESSAGE_TYPE_ADDUSER);
952 bn_int_set(&packet->u.server_message.flags,conn_get_flags(me)|dstflags);
953 bn_int_set(&packet->u.server_message.latency,conn_get_latency(me));
954 {
955 char const * tname;
956 char const * playerinfo;
957
958 tname = conn_get_chatcharname(me, dst);
959 packet_append_string(packet,tname);
960 conn_unget_chatcharname(me,tname);
961 if ((conn_get_clienttag(me) == CLIENTTAG_WARCRAFT3_UINT) || (conn_get_clienttag(me) == CLIENTTAG_WAR3XP_UINT))
962 playerinfo = conn_get_w3_playerinfo(me);
963 else playerinfo = conn_get_playerinfo(me);
964
965 if (playerinfo == NULL) { playerinfo = ""; }
966 packet_append_string(packet,playerinfo);
967 }
968 break;
969 case message_type_join:
970 if (!me)
971 {
972 eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type));
973 return -1;
974 }
975 bn_int_set(&packet->u.server_message.type,SERVER_MESSAGE_TYPE_JOIN);
976 bn_int_set(&packet->u.server_message.flags,conn_get_flags(me)|dstflags);
977 bn_int_set(&packet->u.server_message.latency,conn_get_latency(me));
978 {
979 char const * tname;
980 char const * playerinfo;
981
982 tname = conn_get_chatcharname(me, dst);
983 packet_append_string(packet,tname);
984 conn_unget_chatcharname(me,tname);
985
986 if ((conn_get_clienttag(me) == CLIENTTAG_WARCRAFT3_UINT) || (conn_get_clienttag(me) == CLIENTTAG_WAR3XP_UINT))
987 playerinfo = conn_get_w3_playerinfo(me);
988 else playerinfo = conn_get_playerinfo(me);
989
990 if (playerinfo == NULL) { playerinfo = ""; }
991 packet_append_string(packet, playerinfo);
992 }
993 break;
994 case message_type_part:
995 if (!me)
996 {
997 eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type));
998 return -1;
999 }
1000 bn_int_set(&packet->u.server_message.type,SERVER_MESSAGE_TYPE_PART);
1001 bn_int_set(&packet->u.server_message.flags,conn_get_flags(me)|dstflags);
1002 bn_int_set(&packet->u.server_message.latency,conn_get_latency(me));
1003 {
1004 char const * tname;
1005
1006 tname = conn_get_chatcharname(me, dst);
1007 packet_append_string(packet,tname);
1008 conn_unget_chatcharname(me,tname);
1009 packet_append_string(packet,"");
1010 }
1011 break;
1012 case message_type_whisper:
1013 case message_type_notice:
1014 if (!text)
1015 {
1016 eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type));
1017 return -1;
1018 }
1019 if (dstflags&MF_X)
1020 return -1; /* player is ignored */
1021 bn_int_set(&packet->u.server_message.type,SERVER_MESSAGE_TYPE_WHISPER);
1022 bn_int_set(&packet->u.server_message.flags,me?conn_get_flags(me)|dstflags:dstflags);
1023 bn_int_set(&packet->u.server_message.latency,me?conn_get_latency(me):0);
1024
1025 if (me)
1026 {
1027 char const * tname;
1028
1029 tname = conn_get_chatcharname(me, dst);
1030 packet_append_string(packet,tname);
1031 conn_unget_chatcharname(me,tname);
1032 }
1033 else
1034 packet_append_string(packet,prefs_get_servername());
1035
1036 packet_append_string(packet,text);
1037
1038 break;
1039 case message_type_talk:
1040 if (!me)
1041 {
1042 eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type));
1043 return -1;
1044 }
1045 if (!text)
1046 {
1047 eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type));
1048 return -1;
1049 }
1050 if (dstflags&MF_X)
1051 return -1; /* player is ignored */
1052 bn_int_set(&packet->u.server_message.type,SERVER_MESSAGE_TYPE_TALK);
1053 bn_int_set(&packet->u.server_message.flags,conn_get_flags(me)|dstflags);
1054 bn_int_set(&packet->u.server_message.latency,conn_get_latency(me));
1055 {
1056 char const * tname;
1057
1058 tname = conn_get_chatcharname(me, dst);
1059 packet_append_string(packet,tname);
1060 conn_unget_chatcharname(me,tname);
1061 packet_append_string(packet,text);
1062 }
1063 break;
1064 case message_type_broadcast:
1065 if (!text)
1066 {
1067 eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type));
1068 return -1;
1069 }
1070 if (dstflags&MF_X)
1071 return -1; /* player is ignored */
1072 bn_int_set(&packet->u.server_message.type,SERVER_MESSAGE_TYPE_BROADCAST);
1073 bn_int_set(&packet->u.server_message.flags,conn_get_flags(me)|dstflags);
1074 bn_int_set(&packet->u.server_message.latency,conn_get_latency(me));
1075 {
1076 char const * tname;
1077
1078 tname = conn_get_chatcharname(me, dst);
1079 packet_append_string(packet,tname);
1080 conn_unget_chatcharname(me,tname);
1081 packet_append_string(packet,text);
1082 }
1083 break;
1084 case message_type_channel:
1085 if (!me)
1086 {
1087 eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type));
1088 return -1;
1089 }
1090 if (!text)
1091 {
1092 eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type));
1093 return -1;
1094 }
1095 bn_int_set(&packet->u.server_message.type,SERVER_MESSAGE_TYPE_CHANNEL);
1096 {
1097 t_channel const * channel;
1098
1099 if (!(channel = conn_get_channel(me)))
1100 bn_int_set(&packet->u.server_message.flags,0);
1101 else
1102 bn_int_set(&packet->u.server_message.flags,cflags_to_bncflags(channel_get_flags(channel)));
1103 }
1104 bn_int_set(&packet->u.server_message.latency,conn_get_latency(me));
1105 {
1106 char const * tname;
1107
1108 tname = conn_get_chatname(me);
1109 packet_append_string(packet,tname);
1110 conn_unget_chatname(me,tname);
1111 packet_append_string(packet,text);
1112 }
1113 break;
1114 case message_type_userflags:
1115 if (!me)
1116 {
1117 eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type));
1118 return -1;
1119 }
1120 bn_int_set(&packet->u.server_message.type,SERVER_MESSAGE_TYPE_USERFLAGS);
1121 bn_int_set(&packet->u.server_message.flags,conn_get_flags(me)|dstflags);
1122 bn_int_set(&packet->u.server_message.latency,conn_get_latency(me));
1123 {
1124 char const * tname;
1125 char const * playerinfo;
1126
1127 tname = conn_get_chatcharname(me, dst);
1128 packet_append_string(packet,tname);
1129 conn_unget_chatcharname(me,tname);
1130 if ((conn_get_clienttag(me) == CLIENTTAG_WARCRAFT3_UINT) || (conn_get_clienttag(me) == CLIENTTAG_WAR3XP_UINT))
1131 playerinfo = conn_get_w3_playerinfo(me);
1132 else playerinfo = conn_get_playerinfo(me);
1133
1134 if (playerinfo == NULL) { playerinfo = ""; }
1135
1136 packet_append_string(packet, playerinfo);
1137 }
1138 break;
1139 case message_type_whisperack:
1140 if (!me)
1141 {
1142 eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type));
1143 return -1;
1144 }
1145 if (!text)
1146 {
1147 eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type));
1148 return -1;
1149 }
1150 bn_int_set(&packet->u.server_message.type,SERVER_MESSAGE_TYPE_WHISPERACK);
1151 bn_int_set(&packet->u.server_message.flags,conn_get_flags(me)|dstflags);
1152 bn_int_set(&packet->u.server_message.latency,conn_get_latency(me));
1153 {
1154 char const * tname;
1155
1156 tname = conn_get_chatcharname(me, dst);
1157 packet_append_string(packet,tname);
1158 conn_unget_chatcharname(me,tname);
1159 packet_append_string(packet,text);
1160 }
1161 break;
1162 case message_type_friendwhisperack: // [zap-zero] 20020518
1163 if (!me)
1164 {
1165 eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type));
1166 return -1;
1167 }
1168 if (!text)
1169 {
1170 eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type));
1171 return -1;
1172 }
1173 bn_int_set(&packet->u.server_message.type,SERVER_MESSAGE_TYPE_WHISPERACK);
1174 bn_int_set(&packet->u.server_message.flags,conn_get_flags(me)|dstflags);
1175 bn_int_set(&packet->u.server_message.latency,conn_get_latency(me));
1176 {
1177
1178 packet_append_string(packet,"your friends");
1179 packet_append_string(packet,text);
1180 }
1181 break;
1182
1183 case message_type_channelfull: /* FIXME */
1184 bn_int_set(&packet->u.server_message.type,SERVER_MESSAGE_TYPE_CHANNELFULL);
1185 bn_int_set(&packet->u.server_message.flags,0);
1186 bn_int_set(&packet->u.server_message.latency,0);
1187 packet_append_string(packet,"");
1188 packet_append_string(packet,"");
1189 break;
1190 case message_type_channeldoesnotexist:
1191 if (!me)
1192 {
1193 eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type));
1194 return -1;
1195 }
1196 if (!text)
1197 {
1198 eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type));
1199 return -1;
1200 }
1201 bn_int_set(&packet->u.server_message.type,SERVER_MESSAGE_TYPE_CHANNELDOESNOTEXIST);
1202 bn_int_set(&packet->u.server_message.flags,conn_get_flags(me)|dstflags);
1203 bn_int_set(&packet->u.server_message.latency,conn_get_latency(me));
1204 {
1205 char const * tname;
1206
1207 tname = conn_get_chatname(me);
1208 packet_append_string(packet,tname);
1209 conn_unget_chatname(me,tname);
1210 packet_append_string(packet,text);
1211 }
1212 break;
1213 case message_type_channelrestricted: /* FIXME */
1214 bn_int_set(&packet->u.server_message.type,SERVER_MESSAGE_TYPE_CHANNELRESTRICTED);
1215 bn_int_set(&packet->u.server_message.flags,0);
1216 bn_int_set(&packet->u.server_message.latency,0);
1217 packet_append_string(packet,"");
1218 packet_append_string(packet,"");
1219 break;
1220 case message_type_info:
1221 if (!text)
1222 {
1223 eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type));
1224 return -1;
1225 }
1226 bn_int_set(&packet->u.server_message.type,SERVER_MESSAGE_TYPE_INFO);
1227 bn_int_set(&packet->u.server_message.flags,0);
1228 bn_int_set(&packet->u.server_message.latency,0);
1229 packet_append_string(packet,"");
1230 packet_append_string(packet,text);
1231 break;
1232 case message_type_error:
1233 if (!text)
1234 {
1235 eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type));
1236 return -1;
1237 }
1238 bn_int_set(&packet->u.server_message.type,SERVER_MESSAGE_TYPE_ERROR);
1239 bn_int_set(&packet->u.server_message.flags,0);
1240 bn_int_set(&packet->u.server_message.latency,0);
1241 packet_append_string(packet,"");
1242 packet_append_string(packet,text);
1243 break;
1244 case message_type_emote:
1245 if (!me)
1246 {
1247 eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection for %s",message_type_get_str(type));
1248 return -1;
1249 }
1250 if (!text)
1251 {
1252 eventlog(eventlog_level_error,__FUNCTION__,"got NULL text for %s",message_type_get_str(type));
1253 return -1;
1254 }
1255 if (dstflags&MF_X)
1256 return -1; /* player is ignored */
1257 bn_int_set(&packet->u.server_message.type,SERVER_MESSAGE_TYPE_EMOTE);
1258 bn_int_set(&packet->u.server_message.flags,conn_get_flags(me)|dstflags);
1259 bn_int_set(&packet->u.server_message.latency,conn_get_latency(me));
1260 {
1261 char const * tname;
1262
1263 tname = conn_get_chatcharname(me, dst);
1264 packet_append_string(packet,tname);
1265 conn_unget_chatcharname(me,tname);
1266 packet_append_string(packet,text);
1267 }
1268 break;
1269 default:
1270 eventlog(eventlog_level_error,__FUNCTION__,"got bad message type %d",(int)type);
1271 return -1;
1272 }
1273
1274 return 0;
1275 }
1276
1277
message_create(t_message_type type,t_connection * src,t_connection * dst,char const * text)1278 extern t_message * message_create(t_message_type type, t_connection * src, t_connection * dst, char const * text)
1279 {
1280 t_message * message;
1281
1282 message = xmalloc(sizeof(t_message));
1283 message->num_cached = 0;
1284 message->packets = NULL;
1285 message->classes = NULL;
1286 message->dstflags = NULL;
1287 message->mclasses = NULL;
1288 message->type = type;
1289 message->src = src;
1290 message->dst = dst;
1291 message->text = text;
1292
1293 return message;
1294 }
1295
1296
message_destroy(t_message * message)1297 extern int message_destroy(t_message * message)
1298 {
1299 unsigned int i;
1300
1301 if (!message)
1302 {
1303 eventlog(eventlog_level_error,__FUNCTION__,"got NULL message");
1304 return -1;
1305 }
1306
1307 for (i=0; i<message->num_cached; i++)
1308 if (message->packets[i])
1309 packet_del_ref(message->packets[i]);
1310 if (message->packets)
1311 xfree(message->packets);
1312 if (message->classes)
1313 xfree(message->classes);
1314 if (message->dstflags)
1315 xfree(message->dstflags);
1316 if (message->mclasses)
1317 xfree(message->mclasses);
1318 xfree(message);
1319
1320 return 0;
1321 }
1322
1323
message_cache_lookup(t_message * message,t_connection * dst,unsigned int dstflags)1324 static t_packet * message_cache_lookup(t_message * message, t_connection *dst, unsigned int dstflags)
1325 {
1326 unsigned int i;
1327 t_packet * packet;
1328 t_message_class mclass;
1329 t_conn_class class;
1330
1331 if (!message)
1332 {
1333 eventlog(eventlog_level_error,__FUNCTION__,"got NULL message");
1334 return NULL;
1335 }
1336
1337 class = conn_get_class(dst);
1338 mclass = conn_get_message_class(message->src, dst);
1339 for (i=0; i<message->num_cached; i++)
1340 if (message->classes[i]==class && message->dstflags[i]==dstflags
1341 && message->mclasses[i]==mclass)
1342 return message->packets[i];
1343
1344 {
1345 t_packet * * temp_packets;
1346 t_conn_class * temp_classes;
1347 unsigned int * temp_dstflags;
1348 t_message_class *temp_mclasses;
1349
1350 if (!message->packets)
1351 temp_packets = xmalloc(sizeof(t_packet *)*(message->num_cached+1));
1352 else
1353 temp_packets = xrealloc(message->packets,sizeof(t_packet *)*(message->num_cached+1));
1354
1355 if (!message->classes)
1356 temp_classes = xmalloc(sizeof(t_conn_class)*(message->num_cached+1));
1357 else
1358 temp_classes = xrealloc(message->classes,sizeof(t_conn_class)*(message->num_cached+1));
1359
1360 if (!message->dstflags)
1361 temp_dstflags = xmalloc(sizeof(unsigned int)*(message->num_cached+1));
1362 else
1363 temp_dstflags = xrealloc(message->dstflags,sizeof(unsigned int)*(message->num_cached+1));
1364
1365 if (!message->mclasses)
1366 temp_mclasses = xmalloc(sizeof(t_message_class)*(message->num_cached+1));
1367 else
1368 temp_mclasses = xrealloc(message->mclasses,sizeof(t_message_class)*(message->num_cached+1));
1369
1370 message->packets = temp_packets;
1371 message->classes = temp_classes;
1372 message->dstflags = temp_dstflags;
1373 message->mclasses = temp_mclasses;
1374 }
1375
1376 switch (class)
1377 {
1378 case conn_class_telnet:
1379 if (!(packet = packet_create(packet_class_raw)))
1380 {
1381 eventlog(eventlog_level_error,__FUNCTION__,"could not create packet");
1382 return NULL;
1383 }
1384 if (message_telnet_format(packet,message->type,message->src,message->dst,message->text,dstflags)<0)
1385 {
1386 packet_del_ref(packet);
1387 packet = NULL; /* we can cache the NULL too */
1388 }
1389 break;
1390 case conn_class_bot:
1391 if (!(packet = packet_create(packet_class_raw)))
1392 {
1393 eventlog(eventlog_level_error,__FUNCTION__,"could not create packet");
1394 return NULL;
1395 }
1396 if (message_bot_format(packet,message->type,message->src,message->dst,message->text,dstflags)<0)
1397 {
1398 packet_del_ref(packet);
1399 packet = NULL; /* we can cache the NULL too */
1400 }
1401 break;
1402 case conn_class_bnet:
1403 if (!(packet = packet_create(packet_class_bnet)))
1404 {
1405 eventlog(eventlog_level_error,__FUNCTION__,"could not create packet");
1406 return NULL;
1407 }
1408 if (message_bnet_format(packet,message->type,message->src,dst,message->text,dstflags)<0)
1409 {
1410 packet_del_ref(packet);
1411 packet = NULL; /* we can cache the NULL too */
1412 }
1413 break;
1414 case conn_class_irc:
1415 case conn_class_wol:
1416 if (!(packet = packet_create(packet_class_raw)))
1417 {
1418 eventlog(eventlog_level_error,__FUNCTION__,"could not create packet");
1419 return NULL;
1420 }
1421 /* irc_message_format() is in irc.c */
1422 if (irc_message_format(packet,message->type,message->src,message->dst,message->text,dstflags)<0)
1423 {
1424 packet_del_ref(packet);
1425 packet = NULL; /* we can cache the NULL too */
1426 }
1427 break;
1428 case conn_class_init:
1429 case conn_class_file:
1430 case conn_class_d2cs_bnetd:
1431 case conn_class_w3route:
1432 packet = NULL;
1433 break; /* cache the NULL but dont send any error,
1434 * this are normal connections */
1435 default:
1436 eventlog(eventlog_level_error,__FUNCTION__,"unsupported connection class %d",(int)class);
1437 packet = NULL; /* we can cache the NULL too */
1438 }
1439
1440 message->num_cached++;
1441 message->packets[i] = packet;
1442 message->classes[i] = class;
1443 message->dstflags[i] = dstflags;
1444 message->mclasses[i] = mclass;
1445
1446 return packet;
1447 }
1448
1449
message_send(t_message * message,t_connection * dst)1450 extern int message_send(t_message * message, t_connection * dst)
1451 {
1452 t_packet * packet;
1453 unsigned int dstflags;
1454
1455 if (!message)
1456 {
1457 eventlog(eventlog_level_error,__FUNCTION__,"got NULL message");
1458 return -1;
1459 }
1460 if (!dst)
1461 {
1462 eventlog(eventlog_level_error,__FUNCTION__,"got NULL dst connection");
1463 return -1;
1464 }
1465
1466 dstflags = 0;
1467 if (message->src)
1468 {
1469 char const * tname;
1470
1471 if ((tname = conn_get_chatname(message->src)) && conn_check_ignoring(dst,tname)==1)
1472 {
1473 conn_unget_chatname(message->src,tname);
1474 dstflags |= MF_X;
1475 }
1476 if (tname)
1477 conn_unget_chatname(message->src,tname);
1478 }
1479
1480 if (!(packet = message_cache_lookup(message,dst,dstflags)))
1481 return -1;
1482
1483 /* FIXME: this is not needed now, message has dst */
1484 if ((conn_get_class(dst)==conn_class_irc)||(conn_get_class(dst)==conn_class_wol)) {
1485 /* HACK: IRC message always need the recipient and are therefore bad to cache. */
1486 /* So we only cache a pseudo packet and convert it to a real packet later ... */
1487 packet = packet_duplicate(packet); /* we want to modify packet so we have to create a copy ... */
1488 if (irc_message_postformat(packet,dst)<0) {
1489 packet_del_ref(packet); /* we don't need the previously created copy anymore ... */
1490 return -1;
1491 }
1492 }
1493
1494 conn_push_outqueue(dst,packet);
1495
1496 if ((conn_get_class(dst)==conn_class_irc)||(conn_get_class(dst)==conn_class_wol))
1497 packet_del_ref(packet); /* we don't need the previously created copy anymore ... */
1498
1499 return 0;
1500 }
1501
1502
message_send_all(t_message * message)1503 extern int message_send_all(t_message * message)
1504 {
1505 t_connection * c;
1506 t_elem const * curr;
1507 int rez;
1508
1509 if (!message)
1510 {
1511 eventlog(eventlog_level_error,__FUNCTION__,"got NULL message");
1512 return -1;
1513 }
1514
1515 rez = -1;
1516 LIST_TRAVERSE_CONST(connlist(),curr)
1517 {
1518 c = elem_get_data(curr);
1519 if (message_send(message,c)==0)
1520 rez = 0;
1521 }
1522
1523 return rez;
1524 }
1525
1526
message_send_text(t_connection * dst,t_message_type type,t_connection * src,char const * text)1527 extern int message_send_text(t_connection * dst, t_message_type type, t_connection * src, char const * text)
1528 {
1529 t_message * message;
1530 int rez;
1531
1532 if (!dst)
1533 {
1534 eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection");
1535 return -1;
1536 }
1537
1538 if (!(message = message_create(type,src,dst,text)))
1539 return -1;
1540 rez = message_send(message,dst);
1541 message_destroy(message);
1542
1543 return rez;
1544 }
1545
1546
message_send_admins(t_connection * src,t_message_type type,char const * text)1547 extern int message_send_admins(t_connection * src, t_message_type type, char const * text)
1548 {
1549 t_elem const * curr;
1550 t_connection * tc;
1551 int counter = 0;
1552
1553 LIST_TRAVERSE_CONST(connlist(),curr)
1554 {
1555 tc = elem_get_data(curr);
1556 if (!tc)
1557 continue;
1558 if (account_get_auth_admin(conn_get_account(tc),NULL)==1 && tc != src)
1559 {
1560 message_send_text(tc,type,src,text);
1561 counter++;
1562 }
1563 }
1564
1565 return counter;
1566 }
1567
1568
message_send_formatted(t_connection * dst,char const * text)1569 extern int message_send_formatted(t_connection * dst, char const * text)
1570 {
1571 char * line;
1572
1573 if (!dst)
1574 {
1575 eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection");
1576 return -1;
1577 }
1578
1579 if (!(line = message_format_line(dst,text)))
1580 {
1581 eventlog(eventlog_level_error,__FUNCTION__,"could not format input text \"%s\"",text);
1582 return -1;
1583 }
1584
1585 /* caller beware: empty messages can crash Blizzard clients */
1586 switch (line[0])
1587 {
1588 case 'C':
1589 if (line[1]=='/')
1590 handle_command(dst,&line[1]);
1591 else
1592 if (conn_get_channel(dst) && !conn_quota_exceeded(dst,&line[1]))
1593 channel_message_send(conn_get_channel(dst),message_type_talk,dst,&line[1]);
1594 break;
1595 case 'B':
1596 message_send_text(dst,message_type_broadcast,dst,&line[1]);
1597 break;
1598 case 'E':
1599 message_send_text(dst,message_type_error,dst,&line[1]);
1600 break;
1601 case 'M':
1602 message_send_text(dst,message_type_talk,dst,&line[1]);
1603 break;
1604 case 'T':
1605 message_send_text(dst,message_type_emote,dst,&line[1]);
1606 break;
1607 case 'I':
1608 case 'W':
1609 message_send_text(dst,message_type_info,dst,&line[1]);
1610 break;
1611 default:
1612 eventlog(eventlog_level_error,__FUNCTION__,"unknown message type '%c'",line[0]);
1613 xfree(line);
1614 return -1;
1615 }
1616
1617 xfree(line);
1618 return 0;
1619 }
1620
1621
message_send_file(t_connection * dst,FILE * fd)1622 extern int message_send_file(t_connection * dst, FILE * fd)
1623 {
1624 char * buff;
1625
1626 if (!dst)
1627 {
1628 eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection");
1629 return -1;
1630 }
1631 if (!fd)
1632 {
1633 eventlog(eventlog_level_error,__FUNCTION__,"got NULL fd");
1634 return -1;
1635 }
1636
1637 while ((buff = file_get_line(fd)))
1638 {
1639 message_send_formatted(dst,buff);
1640 }
1641 file_get_line(NULL); // clear file_get_line buffer
1642
1643 return 0;
1644 }
1645