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