1 /*
2 * Copyright (C) 1998 Mark Baysinger (mbaysing@ucsd.edu)
3 * Copyright (C) 1998,1999,2000 Ross Combs (rocombs@cs.nmsu.edu)
4 * Copyright (C) 2000,2001 Marco Ziech (mmz@gmx.net)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (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 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20 #define CHANNEL_INTERNAL_ACCESS
21 #include "common/setup_before.h"
22 #include <stdio.h>
23 #ifdef HAVE_STDDEF_H
24 # include <stddef.h>
25 #else
26 # ifndef NULL
27 # define NULL ((void *)0)
28 # endif
29 #endif
30 #ifdef STDC_HEADERS
31 # include <stdlib.h>
32 #else
33 # ifdef HAVE_MALLOC_H
34 # include <malloc.h>
35 # endif
36 #endif
37 #ifdef HAVE_STRING_H
38 # include <string.h>
39 #else
40 # ifdef HAVE_STRINGS_H
41 # include <strings.h>
42 # endif
43 #endif
44 #include "compat/strrchr.h"
45 #include "compat/strdup.h"
46 #include "compat/strcasecmp.h"
47 #include <errno.h>
48 #include "compat/strerror.h"
49 #ifdef TIME_WITH_SYS_TIME
50 # include <sys/time.h>
51 # include <time.h>
52 #else
53 # ifdef HAVE_SYS_TIME_H
54 # include <sys/time.h>
55 # else
56 # include <time.h>
57 # endif
58 #endif
59 #ifdef HAVE_SYS_TYPES_H
60 # include <sys/types.h>
61 #endif
62 #include "connection.h"
63 #include "common/eventlog.h"
64 #include "common/list.h"
65 #include "message.h"
66 #include "account.h"
67 #include "account_wrap.h"
68 #include "common/util.h"
69 #include "prefs.h"
70 #include "common/token.h"
71 #include "channel.h"
72 #include "irc.h"
73 #include "common/tag.h"
74 #include "common/xalloc.h"
75 #include "common/setup_after.h"
76
77
78 static t_list * channellist_head=NULL;
79
80 static t_channelmember * memberlist_curr=NULL;
81 static int totalcount=0;
82
83
84 static int channellist_load_permanent(char const * filename);
85 static t_channel * channellist_find_channel_by_fullname(char const * name);
86 static char * channel_format_name(char const * sname, char const * country, char const * realmname, unsigned int id);
87
88 extern int channel_set_userflags(t_connection * c);
89
channel_create(char const * fullname,char const * shortname,char const * clienttag,int permflag,int botflag,int operflag,int logflag,char const * country,char const * realmname,int maxmembers,int moderated,int clanflag,int autoname)90 extern t_channel * channel_create(char const * fullname, char const * shortname, char const * clienttag, int permflag, int botflag, int operflag, int logflag, char const * country, char const * realmname, int maxmembers, int moderated, int clanflag, int autoname)
91 {
92 t_channel * channel;
93
94 if (!fullname)
95 {
96 eventlog(eventlog_level_error,__FUNCTION__,"got NULL fullname");
97 return NULL;
98 }
99 if (fullname[0]=='\0')
100 {
101 eventlog(eventlog_level_error,__FUNCTION__,"got empty fullname");
102 return NULL;
103 }
104 if (shortname && shortname[0]=='\0')
105 {
106 eventlog(eventlog_level_error,__FUNCTION__,"got empty shortname");
107 return NULL;
108 }
109 if (clienttag && strlen(clienttag)!=4)
110 {
111 eventlog(eventlog_level_error,__FUNCTION__,"client tag has bad length (%u chars)",strlen(clienttag));
112 return NULL;
113 }
114
115 /* non-permanent already checks for this in conn_set_channel */
116 if (permflag)
117 {
118 if ((channel = channellist_find_channel_by_fullname(fullname)))
119 {
120 if ((channel_get_clienttag(channel)) && (clienttag) && (strcmp(channel_get_clienttag(channel),clienttag)==0))
121 {
122 eventlog(eventlog_level_error,__FUNCTION__,"could not create duplicate permanent channel (fullname \"%s\")",fullname);
123 return NULL;
124 }
125 else if (((channel->flags & channel_flags_allowbots)!=(botflag?channel_flags_allowbots:0)) ||
126 ((channel->flags & channel_flags_allowopers)!=(operflag?channel_flags_allowopers:0)) ||
127 (channel->maxmembers!=maxmembers) ||
128 ((channel->flags & channel_flags_moderated)!=(moderated?channel_flags_moderated:0)) ||
129 (channel->logname && logflag==0) || (!(channel->logname) && logflag ==1))
130 {
131 eventlog(eventlog_level_error,__FUNCTION__,"channel parameters do not match for \"%s\" and \"%s\"",fullname,channel->name);
132 return NULL;
133 }
134 }
135 }
136
137 channel = xmalloc(sizeof(t_channel));
138
139 if (permflag)
140 {
141 channel->flags = channel_flags_public;
142 if (clienttag && maxmembers!=-1) /* approximation.. we want things like "Starcraft USA-1" */
143 channel->flags |= channel_flags_system;
144 } else
145 channel->flags = channel_flags_none;
146
147 if (moderated)
148 channel->flags |= channel_flags_moderated;
149
150 if(shortname && (!strcasecmp(shortname, CHANNEL_NAME_KICKED)
151 || !strcasecmp(shortname, CHANNEL_NAME_BANNED)))
152 channel->flags |= channel_flags_thevoid;
153
154 eventlog(eventlog_level_debug,__FUNCTION__,"creating new channel \"%s\" shortname=%s%s%s clienttag=%s%s%s country=%s%s%s realm=%s%s%s",fullname,
155 shortname?"\"":"(", /* all this is doing is printing the name in quotes else "none" in parens */
156 shortname?shortname:"none",
157 shortname?"\"":")",
158 clienttag?"\"":"(",
159 clienttag?clienttag:"none",
160 clienttag?"\"":")",
161 country?"\"":"(",
162 country?country:"none",
163 country?"\"":")",
164 realmname?"\"":"(",
165 realmname?realmname:"none",
166 realmname?"\"":")");
167
168
169 channel->name = xstrdup(fullname);
170
171 if (!shortname)
172 channel->shortname = NULL;
173 else
174 channel->shortname = xstrdup(shortname);
175
176 if (clienttag)
177 channel->clienttag = xstrdup(clienttag);
178 else
179 channel->clienttag = NULL;
180
181 if (country)
182 channel->country = xstrdup(country);
183 else
184 channel->country = NULL;
185
186 if (realmname)
187 channel->realmname = xstrdup(realmname);
188 else
189 channel->realmname=NULL;
190
191 channel->banlist = list_create();
192
193 totalcount++;
194 if (totalcount==0) /* if we wrap (yeah right), don't use id 0 */
195 totalcount = 1;
196 channel->id = totalcount;
197 channel->maxmembers = maxmembers;
198 channel->currmembers = 0;
199 channel->memberlist = NULL;
200
201 if (permflag) channel->flags |= channel_flags_permanent;
202 if (botflag) channel->flags |= channel_flags_allowbots;
203 if (operflag) channel->flags |= channel_flags_allowopers;
204 if (clanflag) channel->flags |= channel_flags_clan;
205 if (autoname) channel->flags |= channel_flags_autoname;
206
207 if (logflag)
208 {
209 time_t now;
210 struct tm * tmnow;
211 char dstr[64];
212 char timetemp[CHANLOG_TIME_MAXLEN];
213
214 now = time(NULL);
215
216 if (!(tmnow = localtime(&now)))
217 dstr[0] = '\0';
218 else
219 sprintf(dstr,"%04d%02d%02d%02d%02d%02d",
220 1900+tmnow->tm_year,
221 tmnow->tm_mon+1,
222 tmnow->tm_mday,
223 tmnow->tm_hour,
224 tmnow->tm_min,
225 tmnow->tm_sec);
226
227 channel->logname = xmalloc(strlen(prefs_get_chanlogdir())+9+strlen(dstr)+1+6+1); /* dir + "/chanlog-" + dstr + "-" + id + NUL */
228 sprintf(channel->logname,"%s/chanlog-%s-%06u",prefs_get_chanlogdir(),dstr,channel->id);
229
230 if (!(channel->log = fopen(channel->logname,"w")))
231 eventlog(eventlog_level_error,__FUNCTION__,"could not open channel log \"%s\" for writing (fopen: %s)",channel->logname,pstrerror(errno));
232 else
233 {
234 fprintf(channel->log,"name=\"%s\"\n",channel->name);
235 if (channel->shortname)
236 fprintf(channel->log,"shortname=\"%s\"\n",channel->shortname);
237 else
238 fprintf(channel->log,"shortname=none\n");
239 fprintf(channel->log,"permanent=\"%s\"\n",(channel->flags & channel_flags_permanent)?"true":"false");
240 fprintf(channel->log,"allowbotse=\"%s\"\n",(channel->flags & channel_flags_allowbots)?"true":"false");
241 fprintf(channel->log,"allowopers=\"%s\"\n",(channel->flags & channel_flags_allowopers)?"true":"false");
242 if (channel->clienttag)
243 fprintf(channel->log,"clienttag=\"%s\"\n",channel->clienttag);
244 else
245 fprintf(channel->log,"clienttag=none\n");
246
247 if (tmnow)
248 strftime(timetemp,sizeof(timetemp),CHANLOG_TIME_FORMAT,tmnow);
249 else
250 strcpy(timetemp,"?");
251 fprintf(channel->log,"created=\"%s\"\n\n",timetemp);
252 fflush(channel->log);
253 }
254 }
255 else
256 {
257 channel->logname = NULL;
258 channel->log = NULL;
259 }
260
261 channel->gameOwner = NULL;
262 channel->gameOwnerIP = 0;
263
264 channel->gameType = 0;
265 channel->gameTournament = 0;
266
267 channel->gameOptions = NULL;
268
269 list_append_data(channellist_head,channel);
270
271 eventlog(eventlog_level_debug,__FUNCTION__,"channel created successfully");
272 return channel;
273 }
274
275
channel_destroy(t_channel * channel,t_elem ** curr)276 extern int channel_destroy(t_channel * channel, t_elem ** curr)
277 {
278 t_elem * ban;
279
280 if (!channel)
281 {
282 eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
283 return -1;
284 }
285
286 if (channel->memberlist)
287 {
288 eventlog(eventlog_level_debug,__FUNCTION__,"channel is not empty, deferring");
289 channel->flags &= ~channel_flags_permanent; /* make it go away when the last person leaves */
290 return -1;
291 }
292
293 if (list_remove_data(channellist_head,channel,curr)<0)
294 {
295 eventlog(eventlog_level_error,__FUNCTION__,"could not remove item from list");
296 return -1;
297 }
298
299 eventlog(eventlog_level_info,__FUNCTION__,"destroying channel \"%s\"",channel->name);
300
301 LIST_TRAVERSE(channel->banlist,ban)
302 {
303 char const * banned;
304
305 if (!(banned = elem_get_data(ban)))
306 eventlog(eventlog_level_error,__FUNCTION__,"found NULL name in banlist");
307 else
308 xfree((void *)banned); /* avoid warning */
309 if (list_remove_elem(channel->banlist,&ban)<0)
310 eventlog(eventlog_level_error,__FUNCTION__,"unable to remove item from list");
311 }
312 list_destroy(channel->banlist);
313
314 if (channel->log)
315 {
316 time_t now;
317 struct tm * tmnow;
318 char timetemp[CHANLOG_TIME_MAXLEN];
319
320 now = time(NULL);
321 if ((!(tmnow = localtime(&now))))
322 strcpy(timetemp,"?");
323 else
324 strftime(timetemp,sizeof(timetemp),CHANLOG_TIME_FORMAT,tmnow);
325 fprintf(channel->log,"\ndestroyed=\"%s\"\n",timetemp);
326
327 if (fclose(channel->log)<0)
328 eventlog(eventlog_level_error,__FUNCTION__,"could not close channel log \"%s\" after writing (fclose: %s)",channel->logname,pstrerror(errno));
329 }
330
331 if (channel->logname)
332 xfree((void *)channel->logname); /* avoid warning */
333
334 if (channel->country)
335 xfree((void *)channel->country); /* avoid warning */
336
337 if (channel->realmname)
338 xfree((void *)channel->realmname); /* avoid warning */
339
340 if (channel->clienttag)
341 xfree((void *)channel->clienttag); /* avoid warning */
342
343 if (channel->shortname)
344 xfree((void *)channel->shortname); /* avoid warning */
345
346 xfree((void *)channel->name); /* avoid warning */
347
348 xfree(channel);
349
350 return 0;
351 }
352
353
channel_get_name(t_channel const * channel)354 extern char const * channel_get_name(t_channel const * channel)
355 {
356 if (!channel)
357 {
358 eventlog(eventlog_level_warn,__FUNCTION__,"got NULL channel");
359 return "";
360 }
361
362 return channel->name;
363 }
364
365
channel_get_clienttag(t_channel const * channel)366 extern char const * channel_get_clienttag(t_channel const * channel)
367 {
368 if (!channel)
369 {
370 eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
371 return "";
372 }
373
374 return channel->clienttag;
375 }
376
377
channel_get_flags(t_channel const * channel)378 extern t_channel_flags channel_get_flags(t_channel const * channel)
379 {
380 if (!channel)
381 {
382 eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
383 return channel_flags_none;
384 }
385
386 return channel->flags;
387 }
388
channel_set_flags(t_channel * channel,t_channel_flags flags)389 extern int channel_set_flags(t_channel * channel, t_channel_flags flags)
390 {
391 if (!channel)
392 {
393 eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
394 return -1;
395 }
396 channel->flags = flags;
397
398 return 0;
399 }
400
channel_get_permanent(t_channel const * channel)401 extern int channel_get_permanent(t_channel const * channel)
402 {
403 if (!channel)
404 {
405 eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
406 return 0;
407 }
408
409 return (channel->flags & channel_flags_permanent);
410 }
411
412
channel_get_channelid(t_channel const * channel)413 extern unsigned int channel_get_channelid(t_channel const * channel)
414 {
415 if (!channel)
416 {
417 eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
418 return 0;
419 }
420 return channel->id;
421 }
422
423
channel_set_channelid(t_channel * channel,unsigned int channelid)424 extern int channel_set_channelid(t_channel * channel, unsigned int channelid)
425 {
426 if (!channel)
427 {
428 eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
429 return -1;
430 }
431 channel->id = channelid;
432 return 0;
433 }
434
channel_rejoin(t_connection * conn)435 extern int channel_rejoin(t_connection * conn)
436 {
437 t_channel const * channel;
438 char const * temp;
439 char const * chname;
440
441 if (!(channel = conn_get_channel(conn)))
442 return -1;
443
444 if (!(temp = channel_get_name(channel)))
445 return -1;
446
447 chname=xstrdup(temp);
448 conn_set_channel(conn, NULL);
449 if (conn_set_channel(conn,chname)<0)
450 conn_set_channel(conn,CHANNEL_NAME_BANNED);
451 xfree((void *)chname);
452 return 0;
453 }
454
455
channel_add_connection(t_channel * channel,t_connection * connection)456 extern int channel_add_connection(t_channel * channel, t_connection * connection)
457 {
458 t_channelmember * member;
459 t_connection * user;
460
461 if (!channel)
462 {
463 eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
464 return -1;
465 }
466 if (!connection)
467 {
468 eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection");
469 return -1;
470 }
471
472 if (channel_check_banning(channel,connection))
473 {
474 channel_message_log(channel,connection,0,"JOIN FAILED (banned)");
475 return -1;
476 }
477
478 member = xmalloc(sizeof(t_channelmember));
479 member->connection = connection;
480 member->next = channel->memberlist;
481 channel->memberlist = member;
482 channel->currmembers++;
483
484 channel_message_log(channel,connection,0,"JOINED");
485
486 message_send_text(connection,message_type_channel,connection,channel_get_name(channel));
487
488 if ((!(channel->flags & channel_flags_permanent))
489 && (!(channel->flags & channel_flags_thevoid))
490 && (!(channel->flags & channel_flags_clan))
491 && (channel->currmembers==1)
492 && (account_is_operator_or_admin(conn_get_account(connection),channel_get_name(channel))==0))
493 {
494 message_send_text(connection,message_type_info,connection,"you are now tempOP for this channel");
495 conn_set_tmpOP_channel(connection,(char *)channel_get_name(channel));
496 channel_update_userflags(connection);
497 }
498
499 if(!(channel_get_flags(channel) & channel_flags_thevoid))
500 for (user=channel_get_first(channel); user; user=channel_get_next())
501 {
502 message_send_text(connection,message_type_adduser,user,NULL);
503 if (user!=connection)
504 message_send_text(user,message_type_join,connection,NULL);
505 }
506
507 /* please don't remove this notice */
508 if (channel->log)
509 message_send_text(connection,message_type_info,connection,prefs_get_log_notice());
510
511 return 0;
512 }
513
514
channel_del_connection(t_channel * channel,t_connection * connection)515 extern int channel_del_connection(t_channel * channel, t_connection * connection)
516 {
517 t_channelmember * curr;
518 t_channelmember * temp;
519 t_elem * curr2;
520
521 if (!channel)
522 {
523 eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
524 return -1;
525 }
526 if (!connection)
527 {
528 eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection");
529 return -1;
530 }
531
532 channel_message_log(channel,connection,0,"PARTED");
533
534 channel_message_send(channel,message_type_part,connection,NULL);
535
536 curr = channel->memberlist;
537 if (curr->connection==connection)
538 {
539 channel->memberlist = channel->memberlist->next;
540 xfree(curr);
541 }
542 else
543 {
544 while (curr->next && curr->next->connection!=connection)
545 curr = curr->next;
546
547 if (curr->next)
548 {
549 temp = curr->next;
550 curr->next = curr->next->next;
551 xfree(temp);
552 }
553 else
554 {
555 eventlog(eventlog_level_error,__FUNCTION__,"[%d] connection not in channel member list",conn_get_socket(connection));
556 return -1;
557 }
558 }
559 channel->currmembers--;
560
561 if (conn_get_tmpOP_channel(connection) &&
562 strcmp(conn_get_tmpOP_channel(connection),channel_get_name(channel))==0)
563 {
564 conn_set_tmpOP_channel(connection,NULL);
565 }
566
567 if (!channel->memberlist && !(channel->flags & channel_flags_permanent)) /* if channel is empty, delete it unless it's a permanent channel */
568 {
569 channel_destroy(channel,&curr2);
570 }
571
572 return 0;
573 }
574
575
channel_update_latency(t_connection * me)576 extern void channel_update_latency(t_connection * me)
577 {
578 t_channel * channel;
579 t_message * message;
580 t_connection * c;
581
582 if (!me)
583 {
584 eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection");
585 return;
586 }
587 if (!(channel = conn_get_channel(me)))
588 {
589 eventlog(eventlog_level_error,__FUNCTION__,"connection has no channel");
590 return;
591 }
592
593 if (!(message = message_create(message_type_userflags,me,NULL,NULL))) /* handles NULL text */
594 return;
595
596 for (c=channel_get_first(channel); c; c=channel_get_next())
597 if (conn_get_class(c)==conn_class_bnet)
598 message_send(message,c);
599 message_destroy(message);
600 }
601
602
channel_update_userflags(t_connection * me)603 extern void channel_update_userflags(t_connection * me)
604 {
605 t_channel * channel;
606 t_message * message;
607 t_connection * c;
608
609 if (!me)
610 {
611 eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection");
612 return;
613 }
614 if (!(channel = conn_get_channel(me)))
615 {
616 eventlog(eventlog_level_error,__FUNCTION__,"connection has no channel");
617 return;
618 }
619
620 if (!(message = message_create(message_type_userflags,me,NULL,NULL))) /* handles NULL text */
621 return;
622
623 for (c=channel_get_first(channel); c; c=channel_get_next())
624 message_send(message,c);
625
626 message_destroy(message);
627 }
628
629
channel_message_log(t_channel const * channel,t_connection * me,int fromuser,char const * text)630 extern void channel_message_log(t_channel const * channel, t_connection * me, int fromuser, char const * text)
631 {
632 if (!channel)
633 {
634 eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
635 return;
636 }
637 if (!me)
638 {
639 eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection");
640 return;
641 }
642
643 if (channel->log)
644 {
645 time_t now;
646 struct tm * tmnow;
647 char timetemp[CHANLOG_TIME_MAXLEN];
648
649 now = time(NULL);
650 if ((!(tmnow = localtime(&now))))
651 strcpy(timetemp,"?");
652 else
653 strftime(timetemp,sizeof(timetemp),CHANLOGLINE_TIME_FORMAT,tmnow);
654
655 if (fromuser)
656 fprintf(channel->log,"%s: \"%s\" \"%s\"\n",timetemp,conn_get_username(me),text);
657 else
658 fprintf(channel->log,"%s: \"%s\" %s\n",timetemp,conn_get_username(me),text);
659 fflush(channel->log);
660 }
661 }
662
663
channel_message_send(t_channel const * channel,t_message_type type,t_connection * me,char const * text)664 extern void channel_message_send(t_channel const * channel, t_message_type type, t_connection * me, char const * text)
665 {
666 t_connection * c;
667 unsigned int heard;
668 t_message * message;
669 char const * tname;
670 t_account * acc;
671
672 if (!channel)
673 {
674 eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
675 return;
676 }
677 if (!me)
678 {
679 eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection");
680 return;
681 }
682
683 acc = conn_get_account(me);
684
685 if(channel_get_flags(channel) & channel_flags_thevoid) // no talking in the void
686 return;
687
688 if(channel_get_flags(channel) & channel_flags_moderated) // moderated channel - only admins,OPs and voices may talk
689 {
690 if (type==message_type_talk || type==message_type_emote)
691 {
692 if (!((account_is_operator_or_admin(conn_get_account(me),channel_get_name(channel))) ||
693 (channel_conn_has_tmpVOICE(channel,me)) || (account_get_auth_voice(acc,channel_get_name(channel)) == 1)))
694 {
695 message_send_text(me,message_type_error,me,"This channel is moderated");
696 return;
697 }
698 }
699 }
700
701 if (!(message = message_create(type,me,NULL,text)))
702 {
703 eventlog(eventlog_level_error,__FUNCTION__,"could not create message");
704 return;
705 }
706
707 heard = 0;
708 tname = conn_get_chatname(me);
709 for (c=channel_get_first(channel); c; c=channel_get_next())
710 {
711 if (c==me && (type==message_type_talk || type==message_type_join || type==message_type_part || type==message_wol_gameopt_owner))
712 continue; /* ignore ourself */
713 if ((type==message_type_talk || type==message_type_whisper || type==message_type_emote || type==message_type_broadcast) &&
714 conn_check_ignoring(c,tname)==1)
715 continue; /* ignore squelched players */
716
717 if (message_send(message,c)==0 && c!=me)
718 heard = 1;
719
720 }
721 conn_unget_chatname(me,tname);
722
723 message_destroy(message);
724
725 if ((conn_get_wol(me) == 0))
726 {
727 if (!heard && (type==message_type_talk || type==message_type_emote))
728 message_send_text(me,message_type_info,me,"No one hears you.");
729 }
730 }
731
channel_ban_user(t_channel * channel,char const * user)732 extern int channel_ban_user(t_channel * channel, char const * user)
733 {
734 t_elem const * curr;
735 char * temp;
736
737 if (!channel)
738 {
739 eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
740 return -1;
741 }
742 if (!user)
743 {
744 eventlog(eventlog_level_error,__FUNCTION__,"got NULL user");
745 return -1;
746 }
747 if (!channel->name)
748 {
749 eventlog(eventlog_level_error,__FUNCTION__,"got channel with NULL name");
750 return -1;
751 }
752
753 if (strcasecmp(channel->name,CHANNEL_NAME_BANNED)==0 ||
754 strcasecmp(channel->name,CHANNEL_NAME_KICKED)==0)
755 return -1;
756
757 LIST_TRAVERSE_CONST(channel->banlist,curr)
758 if (strcasecmp(elem_get_data(curr),user)==0)
759 return 0;
760
761 temp = xstrdup(user);
762 list_append_data(channel->banlist,temp);
763
764 return 0;
765 }
766
767
channel_unban_user(t_channel * channel,char const * user)768 extern int channel_unban_user(t_channel * channel, char const * user)
769 {
770 t_elem * curr;
771
772 if (!channel)
773 {
774 eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
775 return -1;
776 }
777 if (!user)
778 {
779 eventlog(eventlog_level_error,__FUNCTION__,"got NULL user");
780 return -1;
781 }
782
783 LIST_TRAVERSE(channel->banlist,curr)
784 {
785 char const * banned;
786
787 if (!(banned = elem_get_data(curr)))
788 {
789 eventlog(eventlog_level_error,__FUNCTION__,"found NULL name in banlist");
790 continue;
791 }
792 if (strcasecmp(banned,user)==0)
793 {
794 if (list_remove_elem(channel->banlist,&curr)<0)
795 {
796 eventlog(eventlog_level_error,__FUNCTION__,"unable to remove item from list");
797 return -1;
798 }
799 xfree((void *)banned); /* avoid warning */
800 return 0;
801 }
802 }
803
804 return -1;
805 }
806
807
channel_check_banning(t_channel const * channel,t_connection const * user)808 extern int channel_check_banning(t_channel const * channel, t_connection const * user)
809 {
810 t_elem const * curr;
811
812 if (!channel)
813 {
814 eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
815 return -1;
816 }
817 if (!user)
818 {
819 eventlog(eventlog_level_error,__FUNCTION__,"got NULL user");
820 return -1;
821 }
822
823 if (!(channel->flags & channel_flags_allowbots) && conn_get_class(user)==conn_class_bot)
824 return 1;
825
826 LIST_TRAVERSE_CONST(channel->banlist,curr)
827 if (conn_match(user,elem_get_data(curr))==1)
828 return 1;
829
830 return 0;
831 }
832
833
channel_get_length(t_channel const * channel)834 extern int channel_get_length(t_channel const * channel)
835 {
836 t_channelmember const * curr;
837 int count;
838
839 for (curr=channel->memberlist,count=0; curr; curr=curr->next,count++);
840
841 return count;
842 }
843
844
channel_get_first(t_channel const * channel)845 extern t_connection * channel_get_first(t_channel const * channel)
846 {
847 if (!channel)
848 {
849 eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
850 return NULL;
851 }
852
853 memberlist_curr = channel->memberlist;
854
855 return channel_get_next();
856 }
857
channel_get_next(void)858 extern t_connection * channel_get_next(void)
859 {
860
861 t_channelmember * member;
862
863 if (memberlist_curr)
864 {
865 member = memberlist_curr;
866 memberlist_curr = memberlist_curr->next;
867
868 return member->connection;
869 }
870 return NULL;
871 }
872
873
channel_get_banlist(t_channel const * channel)874 extern t_list * channel_get_banlist(t_channel const * channel)
875 {
876 if (!channel)
877 {
878 eventlog(eventlog_level_warn,__FUNCTION__,"got NULL channel");
879 return NULL;
880 }
881
882 return channel->banlist;
883 }
884
885
channel_get_shortname(t_channel const * channel)886 extern char const * channel_get_shortname(t_channel const * channel)
887 {
888 if (!channel)
889 {
890 eventlog(eventlog_level_warn,__FUNCTION__,"got NULL channel");
891 return NULL;
892 }
893
894 return channel->shortname;
895 }
896
897
channellist_load_permanent(char const * filename)898 static int channellist_load_permanent(char const * filename)
899 {
900 FILE * fp;
901 unsigned int line;
902 unsigned int pos;
903 int botflag;
904 int operflag;
905 int logflag;
906 unsigned int modflag;
907 char * buff;
908 char * name;
909 char * sname;
910 char * tag;
911 char * bot;
912 char * oper;
913 char * log;
914 char * country;
915 char * max;
916 char * moderated;
917 char * newname;
918 char * realmname;
919
920 if (!filename)
921 {
922 eventlog(eventlog_level_error,__FUNCTION__,"got NULL filename");
923 return -1;
924 }
925
926 if (!(fp = fopen(filename,"r")))
927 {
928 eventlog(eventlog_level_error,__FUNCTION__,"could not open channel file \"%s\" for reading (fopen: %s)",filename,pstrerror(errno));
929 return -1;
930 }
931
932 for (line=1; (buff = file_get_line(fp)); line++)
933 {
934 if (buff[0]=='#' || buff[0]=='\0')
935 {
936 continue;
937 }
938 pos = 0;
939 if (!(name = next_token(buff,&pos)))
940 {
941 eventlog(eventlog_level_error,__FUNCTION__,"missing name in line %u in file \"%s\"",line,filename);
942 continue;
943 }
944 if (!(sname = next_token(buff,&pos)))
945 {
946 eventlog(eventlog_level_error,__FUNCTION__,"missing sname in line %u in file \"%s\"",line,filename);
947 continue;
948 }
949 if (!(tag = next_token(buff,&pos)))
950 {
951 eventlog(eventlog_level_error,__FUNCTION__,"missing tag in line %u in file \"%s\"",line,filename);
952 continue;
953 }
954 if (!(bot = next_token(buff,&pos)))
955 {
956 eventlog(eventlog_level_error,__FUNCTION__,"missing bot in line %u in file \"%s\"",line,filename);
957 continue;
958 }
959 if (!(oper = next_token(buff,&pos)))
960 {
961 eventlog(eventlog_level_error,__FUNCTION__,"missing oper in line %u in file \"%s\"",line,filename);
962 continue;
963 }
964 if (!(log = next_token(buff,&pos)))
965 {
966 eventlog(eventlog_level_error,__FUNCTION__,"missing log in line %u in file \"%s\"",line,filename);
967 continue;
968 }
969 if (!(country = next_token(buff,&pos)))
970 {
971 eventlog(eventlog_level_error,__FUNCTION__,"missing country in line %u in file \"%s\"",line,filename);
972 continue;
973 }
974 if (!(realmname = next_token(buff,&pos)))
975 {
976 eventlog(eventlog_level_error,__FUNCTION__,"missing realmname in line %u in file \"%s\"",line,filename);
977 continue;
978 }
979 if (!(max = next_token(buff,&pos)))
980 {
981 eventlog(eventlog_level_error,__FUNCTION__,"missing max in line %u in file \"%s\"",line,filename);
982 continue;
983 }
984 if (!(moderated = next_token(buff,&pos)))
985 {
986 eventlog(eventlog_level_error,__FUNCTION__,"missing mod in line %u in file \"%s\"",line,filename);
987 continue;
988 }
989
990 switch (str_get_bool(bot))
991 {
992 case 1:
993 botflag = 1;
994 break;
995 case 0:
996 botflag = 0;
997 break;
998 default:
999 eventlog(eventlog_level_error,__FUNCTION__,"invalid boolean value \"%s\" for field 4 on line %u in file \"%s\"",bot,line,filename);
1000 continue;
1001 }
1002
1003 switch (str_get_bool(oper))
1004 {
1005 case 1:
1006 operflag = 1;
1007 break;
1008 case 0:
1009 operflag = 0;
1010 break;
1011 default:
1012 eventlog(eventlog_level_error,__FUNCTION__,"invalid boolean value \"%s\" for field 5 on line %u in file \"%s\"",oper,line,filename);
1013 continue;
1014 }
1015
1016 switch (str_get_bool(log))
1017 {
1018 case 1:
1019 logflag = 1;
1020 break;
1021 case 0:
1022 logflag = 0;
1023 break;
1024 default:
1025 eventlog(eventlog_level_error,__FUNCTION__,"invalid boolean value \"%s\" for field 5 on line %u in file \"%s\"",log,line,filename);
1026 continue;
1027 }
1028
1029 switch (str_get_bool(moderated))
1030 {
1031 case 1:
1032 modflag = 1;
1033 break;
1034 case 0:
1035 modflag = 0;
1036 break;
1037 default:
1038 eventlog(eventlog_level_error,__FUNCTION__,"invalid boolean value \"%s\" for field 10 on line %u in file \"%s\"",moderated,line,filename);
1039 continue;
1040 }
1041
1042 if (strcmp(sname,"NULL") == 0)
1043 sname = NULL;
1044 if (strcmp(tag,"NULL") == 0)
1045 tag = NULL;
1046 if (strcmp(name,"NONE") == 0)
1047 name = NULL;
1048 if (strcmp(country, "NULL") == 0)
1049 country = NULL;
1050 if (strcmp(realmname,"NULL") == 0)
1051 realmname = NULL;
1052
1053 if (name)
1054 {
1055 channel_create(name,sname,tag,1,botflag,operflag,logflag,country,realmname,atoi(max),modflag,0,0);
1056 }
1057 else
1058 {
1059 newname = channel_format_name(sname,country,realmname,1);
1060 if (newname)
1061 {
1062 channel_create(newname,sname,tag,1,botflag,operflag,logflag,country,realmname,atoi(max),modflag,0,1);
1063 xfree(newname);
1064 }
1065 else
1066 {
1067 eventlog(eventlog_level_error,__FUNCTION__,"cannot format channel name");
1068 }
1069 }
1070
1071 /* FIXME: call channel_delete() on current perm channels and do a
1072 channellist_find_channel() and set the long name, perm flag, etc,
1073 otherwise call channel_create(). This will make HUPing the server
1074 handle re-reading this file correctly. */
1075 }
1076
1077 file_get_line(NULL); // clear file_get_line buffer
1078 if (fclose(fp)<0)
1079 eventlog(eventlog_level_error,__FUNCTION__,"could not close channel file \"%s\" after reading (fclose: %s)",filename,pstrerror(errno));
1080 return 0;
1081 }
1082
channel_format_name(char const * sname,char const * country,char const * realmname,unsigned int id)1083 static char * channel_format_name(char const * sname, char const * country, char const * realmname, unsigned int id)
1084 {
1085 char * fullname;
1086 unsigned int len;
1087
1088 if (!sname)
1089 {
1090 eventlog(eventlog_level_error,__FUNCTION__,"got NULL sname");
1091 return NULL;
1092 }
1093 len = strlen(sname)+1; /* FIXME: check lengths and format */
1094 if (country)
1095 len = len + strlen(country) + 1;
1096 if (realmname)
1097 len = len + strlen(realmname) + 1;
1098 len = len + 32 + 1;
1099
1100 fullname=xmalloc(len);
1101 sprintf(fullname,"%s%s%s%s%s-%d",
1102 realmname?realmname:"",
1103 realmname?" ":"",
1104 sname,
1105 country?" ":"",
1106 country?country:"",
1107 id);
1108 return fullname;
1109 }
1110
channellist_reload(void)1111 extern int channellist_reload(void)
1112 {
1113 t_elem * curr;
1114 t_channel * channel, * old_channel;
1115 t_channelmember * memberlist, * member, * old_member;
1116 t_list * channellist_old;
1117
1118 if (channellist_head)
1119 {
1120
1121 channellist_old = list_create();
1122
1123 /* First pass - get members */
1124 LIST_TRAVERSE(channellist_head,curr)
1125 {
1126 if (!(channel = elem_get_data(curr)))
1127 {
1128 eventlog(eventlog_level_error,__FUNCTION__,"channel list contains NULL item");
1129 continue;
1130 }
1131 /* Trick to avoid automatic channel destruction */
1132 channel->flags |= channel_flags_permanent;
1133 if (channel->memberlist)
1134 {
1135 /* we need only channel name and memberlist */
1136
1137 old_channel = (t_channel *) xmalloc(sizeof(t_channel));
1138 old_channel->shortname = xstrdup(channel->shortname);
1139 old_channel->memberlist = NULL;
1140 member = channel->memberlist;
1141
1142 /* First pass */
1143 while (member)
1144 {
1145 old_member = xmalloc(sizeof(t_channelmember));
1146 old_member->connection = member->connection;
1147
1148 if (old_channel->memberlist)
1149 old_member->next = old_channel->memberlist;
1150 else
1151 old_member->next = NULL;
1152
1153 old_channel->memberlist = old_member;
1154 member = member->next;
1155 }
1156
1157 /* Second pass - remove connections from channel */
1158 member = old_channel->memberlist;
1159 while (member)
1160 {
1161 channel_del_connection(channel,member->connection);
1162 conn_set_channel_var(member->connection,NULL);
1163 member = member->next;
1164 }
1165
1166 list_prepend_data(channellist_old,old_channel);
1167 }
1168
1169 /* Channel is empty - Destroying it */
1170 channel->flags &= ~channel_flags_permanent;
1171 if (channel_destroy(channel,&curr)<0)
1172 eventlog(eventlog_level_error,__FUNCTION__,"could not destroy channel");
1173
1174 }
1175
1176 /* Cleanup and reload */
1177
1178 if (list_destroy(channellist_head)<0)
1179 return -1;
1180
1181 channellist_head = NULL;
1182 channellist_create();
1183
1184 /* Now put all users on their previous channel */
1185
1186 LIST_TRAVERSE(channellist_old,curr)
1187 {
1188 if (!(channel = elem_get_data(curr)))
1189 {
1190 eventlog(eventlog_level_error,__FUNCTION__,"old channel list contains NULL item");
1191 continue;
1192 }
1193
1194 memberlist = channel->memberlist;
1195 while (memberlist)
1196 {
1197 member = memberlist;
1198 memberlist = memberlist->next;
1199 conn_set_channel(member->connection, channel->shortname);
1200 }
1201 }
1202
1203
1204 /* Ross don't blame me for this but this way the code is cleaner */
1205
1206 LIST_TRAVERSE(channellist_old,curr)
1207 {
1208 if (!(channel = elem_get_data(curr)))
1209 {
1210 eventlog(eventlog_level_error,__FUNCTION__,"old channel list contains NULL item");
1211 continue;
1212 }
1213
1214 memberlist = channel->memberlist;
1215 while (memberlist)
1216 {
1217 member = memberlist;
1218 memberlist = memberlist->next;
1219 xfree((void*)member);
1220 }
1221
1222 if (channel->shortname)
1223 xfree((void*)channel->shortname);
1224
1225 if (list_remove_data(channellist_old,channel,&curr)<0)
1226 eventlog(eventlog_level_error,__FUNCTION__,"could not remove item from list");
1227 xfree((void*)channel);
1228
1229 }
1230
1231 if (list_destroy(channellist_old)<0)
1232 return -1;
1233 }
1234 return 0;
1235
1236 }
1237
channellist_create(void)1238 extern int channellist_create(void)
1239 {
1240 channellist_head = list_create();
1241
1242 return channellist_load_permanent(prefs_get_channelfile());
1243 }
1244
1245
channellist_destroy(void)1246 extern int channellist_destroy(void)
1247 {
1248 t_channel * channel;
1249 t_elem * curr;
1250
1251 if (channellist_head)
1252 {
1253 LIST_TRAVERSE(channellist_head,curr)
1254 {
1255 if (!(channel = elem_get_data(curr))) /* should not happen */
1256 {
1257 eventlog(eventlog_level_error,__FUNCTION__,"channel list contains NULL item");
1258 continue;
1259 }
1260
1261 channel_destroy(channel,&curr);
1262 }
1263
1264 if (list_destroy(channellist_head)<0)
1265 return -1;
1266 channellist_head = NULL;
1267 }
1268
1269 return 0;
1270 }
1271
1272
channellist(void)1273 extern t_list * channellist(void)
1274 {
1275 return channellist_head;
1276 }
1277
1278
channellist_get_length(void)1279 extern int channellist_get_length(void)
1280 {
1281 return list_get_length(channellist_head);
1282 }
1283
channel_get_max(t_channel const * channel)1284 extern int channel_get_max(t_channel const * channel)
1285 {
1286 if (!channel)
1287 {
1288 eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
1289 return 0;
1290 }
1291
1292 return channel->maxmembers;
1293 }
1294
channel_set_max(t_channel * channel,int maxmembers)1295 extern int channel_set_max(t_channel * channel, int maxmembers)
1296 {
1297 if (!channel)
1298 {
1299 eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
1300 return 0;
1301 }
1302
1303 if (maxmembers)
1304 channel->maxmembers = maxmembers;
1305 return 1;
1306 }
1307
channel_get_curr(t_channel const * channel)1308 extern int channel_get_curr(t_channel const * channel)
1309 {
1310 if (!channel)
1311 {
1312 eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
1313 return 0;
1314 }
1315
1316 return channel->currmembers;
1317
1318 }
1319
channel_conn_is_tmpOP(t_channel const * channel,t_connection * c)1320 extern int channel_conn_is_tmpOP(t_channel const * channel, t_connection * c)
1321 {
1322 if (!channel)
1323 {
1324 eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
1325 return 0;
1326 }
1327
1328 if (!c)
1329 {
1330 eventlog(eventlog_level_error,__FUNCTION__,"got NULL account");
1331 return 0;
1332 }
1333
1334 if (!conn_get_tmpOP_channel(c)) return 0;
1335
1336 if (strcmp(conn_get_tmpOP_channel(c),channel_get_name(channel))==0) return 1;
1337
1338 return 0;
1339 }
1340
channel_conn_has_tmpVOICE(t_channel const * channel,t_connection * c)1341 extern int channel_conn_has_tmpVOICE(t_channel const * channel, t_connection * c)
1342 {
1343 if (!channel)
1344 {
1345 eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
1346 return 0;
1347 }
1348
1349 if (!c)
1350 {
1351 eventlog(eventlog_level_error,__FUNCTION__,"got NULL account");
1352 return 0;
1353 }
1354
1355 if (!conn_get_tmpVOICE_channel(c)) return 0;
1356
1357 if (strcmp(conn_get_tmpVOICE_channel(c),channel_get_name(channel))==0) return 1;
1358
1359 return 0;
1360 }
1361
channellist_find_channel_by_fullname(char const * name)1362 static t_channel * channellist_find_channel_by_fullname(char const * name)
1363 {
1364 t_channel * channel;
1365 t_elem const * curr;
1366
1367 if (channellist_head)
1368 {
1369 LIST_TRAVERSE(channellist_head,curr)
1370 {
1371 channel = elem_get_data(curr);
1372 if (!channel->name)
1373 {
1374 eventlog(eventlog_level_error,__FUNCTION__,"found channel with NULL name");
1375 continue;
1376 }
1377
1378 if (strcasecmp(channel->name,name)==0)
1379 return channel;
1380 }
1381 }
1382
1383 return NULL;
1384 }
1385
1386
1387 /* Find a channel based on the name.
1388 * Create a new channel if it is a permanent-type channel and all others
1389 * are full.
1390 */
channellist_find_channel_by_name(char const * name,char const * country,char const * realmname)1391 extern t_channel * channellist_find_channel_by_name(char const * name, char const * country, char const * realmname)
1392 {
1393 t_channel * channel;
1394 t_elem const * curr;
1395 int foundperm;
1396 int foundlang;
1397 int maxchannel; /* the number of "rollover" channels that exist */
1398 char const * saveshortname;
1399 char const * savespecialname;
1400 char const * savetag;
1401 int savebotflag;
1402 int saveoperflag;
1403 int savelogflag;
1404 unsigned int savemoderated;
1405 char const * savecountry;
1406 char const * saverealmname;
1407 int savemaxmembers;
1408 t_channel * special_channel;
1409
1410 // try to make gcc happy and initialize all variables
1411 saveshortname = savespecialname = savetag = savecountry = saverealmname = NULL;
1412 savebotflag = saveoperflag = savelogflag = savemaxmembers = savemoderated = 0;
1413
1414 maxchannel = 0;
1415 foundperm = 0;
1416 foundlang = 0;
1417 if (channellist_head)
1418 {
1419 LIST_TRAVERSE(channellist_head,curr)
1420 {
1421 channel = elem_get_data(curr);
1422 if (!channel->name)
1423 {
1424 eventlog(eventlog_level_error,__FUNCTION__,"found channel with NULL name");
1425 continue;
1426 }
1427
1428 if (strcasecmp(channel->name,name)==0)
1429 {
1430 // eventlog(eventlog_level_debug,__FUNCTION__,"found exact match for \"%s\"",name);
1431 return channel;
1432 }
1433
1434 if (channel->shortname && strcasecmp(channel->shortname,name)==0)
1435 {
1436 special_channel = channellist_find_channel_by_name(channel->name,country,realmname);
1437 if (special_channel) channel= special_channel;
1438
1439 /* FIXME: what should we do if the client doesn't have a country? For now, just take the first
1440 * channel that would otherwise match. */
1441 if ( ((!channel->country && !foundlang) || !country ||
1442 (channel->country && country && (strcmp(channel->country, country)==0))) &&
1443 (!channel->realmname || !realmname || !strcmp(channel->realmname, realmname)) )
1444 {
1445 if (channel->maxmembers==-1 || channel->currmembers<channel->maxmembers)
1446 {
1447 eventlog(eventlog_level_debug,__FUNCTION__,"found permanent channel \"%s\" for \"%s\"",channel->name,name);
1448 return channel;
1449 }
1450
1451 if (!foundlang && (channel->country)) //remember we had found a language specific channel but it was full
1452 {
1453 foundlang = 1;
1454 if (!(channel->flags & channel_flags_autoname))
1455 savespecialname = channel->name;
1456 maxchannel = 0;
1457 }
1458
1459 maxchannel++;
1460 }
1461
1462 // eventlog(eventlog_level_debug,__FUNCTION__,"countries didn't match");
1463
1464 foundperm = 1;
1465
1466 /* save off some info in case we need to create a new copy */
1467 saveshortname = channel->shortname;
1468 savetag = channel->clienttag;
1469 savebotflag = channel->flags & channel_flags_allowbots;
1470 saveoperflag = channel->flags & channel_flags_allowopers;
1471 if (channel->logname)
1472 savelogflag = 1;
1473 else
1474 savelogflag = 0;
1475 if (country)
1476 savecountry = country;
1477 else
1478 savecountry = channel->country;
1479 if (realmname)
1480 saverealmname = realmname;
1481 else
1482 saverealmname = channel->realmname;
1483 savemaxmembers = channel->maxmembers;
1484 savemoderated = channel->flags & channel_flags_moderated;
1485 }
1486 }
1487 }
1488
1489 /* we've gone thru the whole list and either there was no match or the
1490 * channels are all full.
1491 */
1492
1493 if (foundperm) /* All the channels were full, create a new one */
1494 {
1495 char * channelname;
1496
1497 if (!foundlang || !savespecialname)
1498 {
1499 if (!(channelname=channel_format_name(saveshortname,savecountry,saverealmname,maxchannel+1)))
1500 return NULL;
1501 }
1502 else
1503 {
1504 if (!(channelname=channel_format_name(savespecialname,NULL,saverealmname,maxchannel+1)))
1505 return NULL;
1506 }
1507
1508 channel = channel_create(channelname,saveshortname,savetag,1,savebotflag,saveoperflag,savelogflag,savecountry,saverealmname,savemaxmembers,savemoderated,0,1);
1509 xfree(channelname);
1510
1511 eventlog(eventlog_level_debug,__FUNCTION__,"created copy \"%s\" of channel \"%s\"",(channel)?(channel->name):("<failed>"),name);
1512 return channel;
1513 }
1514
1515 /* no match */
1516 eventlog(eventlog_level_debug,__FUNCTION__,"could not find channel \"%s\"",name);
1517 return NULL;
1518 }
1519
1520
channellist_find_channel_bychannelid(unsigned int channelid)1521 extern t_channel * channellist_find_channel_bychannelid(unsigned int channelid)
1522 {
1523 t_channel * channel;
1524 t_elem const * curr;
1525
1526 if (channellist_head)
1527 {
1528 LIST_TRAVERSE(channellist_head,curr)
1529 {
1530 channel = elem_get_data(curr);
1531 if (!channel->name)
1532 {
1533 eventlog(eventlog_level_error,__FUNCTION__,"found channel with NULL name");
1534 continue;
1535 }
1536 if (channel->id==channelid)
1537 return channel;
1538 }
1539 }
1540
1541 return NULL;
1542 }
1543
channel_set_userflags(t_connection * c)1544 extern int channel_set_userflags(t_connection * c)
1545 {
1546 unsigned int newflags;
1547 char const * channel;
1548 t_account * acc;
1549
1550 if (!c) return -1; // user not connected, no need to update his flags
1551
1552 acc = conn_get_account(c);
1553
1554 /* well... unfortunatly channel_get_name never returns NULL but "" instead
1555 so we first have to check if user is in a channel at all */
1556 if ((!conn_get_channel(c)) || (!(channel = channel_get_name(conn_get_channel(c)))))
1557 return -1;
1558
1559 if (account_get_auth_admin(acc,channel) == 1 || account_get_auth_admin(acc,NULL) == 1)
1560 newflags = MF_BLIZZARD;
1561 else if (account_get_auth_operator(acc,channel) == 1 ||
1562 account_get_auth_operator(acc,NULL) == 1)
1563 newflags = MF_BNET;
1564 else if (channel_conn_is_tmpOP(conn_get_channel(c),c))
1565 newflags = MF_GAVEL;
1566 else if ((account_get_auth_voice(acc,channel) == 1) ||
1567 (channel_conn_has_tmpVOICE(conn_get_channel(c),c)))
1568 newflags = MF_VOICE;
1569 else
1570 if ((conn_get_clienttag(c) == CLIENTTAG_WARCRAFT3_UINT) ||
1571 (conn_get_clienttag(c) == CLIENTTAG_WAR3XP_UINT))
1572 newflags = W3_ICON_SET;
1573 else
1574 newflags = 0;
1575
1576 if (conn_get_flags(c) != newflags) {
1577 conn_set_flags(c, newflags);
1578 channel_update_userflags(c);
1579 }
1580
1581 return 0;
1582 }
1583
1584 /**
1585 * Westwood Online Extensions
1586 */
channel_wol_get_game_owner(t_channel const * channel)1587 extern char const * channel_wol_get_game_owner(t_channel const * channel)
1588 {
1589 if (!channel)
1590 {
1591 eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
1592 return NULL;
1593 }
1594
1595 return channel->gameOwner;
1596 }
1597
channel_wol_set_game_owner(t_channel * channel,char const * gameOwner)1598 extern int channel_wol_set_game_owner(t_channel * channel, char const * gameOwner)
1599 {
1600 if (!channel)
1601 {
1602 eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
1603 return 0;
1604 }
1605
1606 if (channel->gameOwner)
1607 xfree((void *)channel->gameOwner); /* avoid warning */
1608 channel->gameOwner = xstrdup(gameOwner);
1609
1610 return 1;
1611 }
1612
channel_wol_get_game_ownerip(t_channel const * channel)1613 extern int channel_wol_get_game_ownerip(t_channel const * channel)
1614 {
1615 if (!channel)
1616 {
1617 eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
1618 return -1;
1619 }
1620
1621 return channel->gameOwnerIP;
1622 }
1623
channel_wol_set_game_ownerip(t_channel * channel,int gameOwnerIP)1624 extern int channel_wol_set_game_ownerip(t_channel * channel, int gameOwnerIP)
1625 {
1626 if (!channel)
1627 {
1628 eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
1629 return 0;
1630 }
1631
1632 if (gameOwnerIP)
1633 channel->gameOwnerIP = gameOwnerIP;
1634
1635 return 1;
1636 }
1637
channel_wol_get_game_type(t_channel const * channel)1638 extern int channel_wol_get_game_type(t_channel const * channel)
1639 {
1640 if (!channel)
1641 {
1642 eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
1643 return -1;
1644 }
1645
1646 return channel->gameType;
1647 }
1648
channel_wol_set_game_type(t_channel * channel,int gameType)1649 extern int channel_wol_set_game_type(t_channel * channel, int gameType)
1650 {
1651 if (!channel)
1652 {
1653 eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
1654 return 0;
1655 }
1656
1657 if (gameType)
1658 channel->gameType = gameType;
1659
1660 return 1;
1661 }
1662
channel_wol_get_game_tournament(t_channel const * channel)1663 extern int channel_wol_get_game_tournament(t_channel const * channel)
1664 {
1665 if (!channel)
1666 {
1667 eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
1668 return -1;
1669 }
1670
1671 return channel->gameTournament;
1672 }
1673
channel_wol_set_game_tournament(t_channel * channel,int gameTournament)1674 extern int channel_wol_set_game_tournament(t_channel * channel, int gameTournament)
1675 {
1676 if (!channel)
1677 {
1678 eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
1679 return 0;
1680 }
1681
1682 if (gameTournament)
1683 channel->gameTournament = gameTournament;
1684
1685 return 1;
1686 }
1687
channel_wol_get_game_options(t_channel const * channel)1688 extern char const * channel_wol_get_game_options(t_channel const * channel)
1689 {
1690 if (!channel)
1691 {
1692 eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
1693 return NULL;
1694 }
1695
1696 return channel->gameOptions;
1697 }
1698
channel_wol_set_game_options(t_channel * channel,char const * gameOptions)1699 extern int channel_wol_set_game_options(t_channel * channel, char const * gameOptions)
1700 {
1701 if (!channel)
1702 {
1703 eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
1704 return 0;
1705 }
1706
1707 if (channel->gameOptions)
1708 xfree((void *)channel->gameOptions); /* avoid warning */
1709 channel->gameOptions = xstrdup(gameOptions);
1710
1711 return 1;
1712 }
1713