/[LeafOK_CVS]/pvpgn-1.7.4/src/bnetd/channel.c
ViewVC logotype

Annotation of /pvpgn-1.7.4/src/bnetd/channel.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (hide annotations)
Tue Jun 6 03:41:37 2006 UTC (19 years, 9 months ago) by sysadm
Branch point for: GNU, MAIN
Content type: text/x-csrc
Initial revision

1 sysadm 1.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    
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     list_append_data(channellist_head,channel);
262    
263     eventlog(eventlog_level_debug,__FUNCTION__,"channel created successfully");
264     return channel;
265     }
266    
267    
268     extern int channel_destroy(t_channel * channel, t_elem ** curr)
269     {
270     t_elem * ban;
271    
272     if (!channel)
273     {
274     eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
275     return -1;
276     }
277    
278     if (channel->memberlist)
279     {
280     eventlog(eventlog_level_debug,__FUNCTION__,"channel is not empty, deferring");
281     channel->flags &= ~channel_flags_permanent; /* make it go away when the last person leaves */
282     return -1;
283     }
284    
285     if (list_remove_data(channellist_head,channel,curr)<0)
286     {
287     eventlog(eventlog_level_error,__FUNCTION__,"could not remove item from list");
288     return -1;
289     }
290    
291     eventlog(eventlog_level_info,__FUNCTION__,"destroying channel \"%s\"",channel->name);
292    
293     LIST_TRAVERSE(channel->banlist,ban)
294     {
295     char const * banned;
296    
297     if (!(banned = elem_get_data(ban)))
298     eventlog(eventlog_level_error,__FUNCTION__,"found NULL name in banlist");
299     else
300     xfree((void *)banned); /* avoid warning */
301     if (list_remove_elem(channel->banlist,&ban)<0)
302     eventlog(eventlog_level_error,__FUNCTION__,"unable to remove item from list");
303     }
304     list_destroy(channel->banlist);
305    
306     if (channel->log)
307     {
308     time_t now;
309     struct tm * tmnow;
310     char timetemp[CHANLOG_TIME_MAXLEN];
311    
312     now = time(NULL);
313     if ((!(tmnow = localtime(&now))))
314     strcpy(timetemp,"?");
315     else
316     strftime(timetemp,sizeof(timetemp),CHANLOG_TIME_FORMAT,tmnow);
317     fprintf(channel->log,"\ndestroyed=\"%s\"\n",timetemp);
318    
319     if (fclose(channel->log)<0)
320     eventlog(eventlog_level_error,__FUNCTION__,"could not close channel log \"%s\" after writing (fclose: %s)",channel->logname,pstrerror(errno));
321     }
322    
323     if (channel->logname)
324     xfree((void *)channel->logname); /* avoid warning */
325    
326     if (channel->country)
327     xfree((void *)channel->country); /* avoid warning */
328    
329     if (channel->realmname)
330     xfree((void *)channel->realmname); /* avoid warning */
331    
332     if (channel->clienttag)
333     xfree((void *)channel->clienttag); /* avoid warning */
334    
335     if (channel->shortname)
336     xfree((void *)channel->shortname); /* avoid warning */
337    
338     xfree((void *)channel->name); /* avoid warning */
339    
340     xfree(channel);
341    
342     return 0;
343     }
344    
345    
346     extern char const * channel_get_name(t_channel const * channel)
347     {
348     if (!channel)
349     {
350     eventlog(eventlog_level_warn,__FUNCTION__,"got NULL channel");
351     return "";
352     }
353    
354     return channel->name;
355     }
356    
357    
358     extern char const * channel_get_clienttag(t_channel const * channel)
359     {
360     if (!channel)
361     {
362     eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
363     return "";
364     }
365    
366     return channel->clienttag;
367     }
368    
369    
370     extern t_channel_flags channel_get_flags(t_channel const * channel)
371     {
372     if (!channel)
373     {
374     eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
375     return channel_flags_none;
376     }
377    
378     return channel->flags;
379     }
380    
381     extern int channel_set_flags(t_channel * channel, t_channel_flags flags)
382     {
383     if (!channel)
384     {
385     eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
386     return -1;
387     }
388     channel->flags = flags;
389    
390     return 0;
391     }
392    
393     extern int channel_get_permanent(t_channel const * channel)
394     {
395     if (!channel)
396     {
397     eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
398     return 0;
399     }
400    
401     return (channel->flags & channel_flags_permanent);
402     }
403    
404    
405     extern unsigned int channel_get_channelid(t_channel const * channel)
406     {
407     if (!channel)
408     {
409     eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
410     return 0;
411     }
412     return channel->id;
413     }
414    
415    
416     extern int channel_set_channelid(t_channel * channel, unsigned int channelid)
417     {
418     if (!channel)
419     {
420     eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
421     return -1;
422     }
423     channel->id = channelid;
424     return 0;
425     }
426    
427     extern int channel_rejoin(t_connection * conn)
428     {
429     t_channel const * channel;
430     char const * temp;
431     char const * chname;
432    
433     if (!(channel = conn_get_channel(conn)))
434     return -1;
435    
436     if (!(temp = channel_get_name(channel)))
437     return -1;
438    
439     chname=xstrdup(temp);
440     conn_set_channel(conn, NULL);
441     if (conn_set_channel(conn,chname)<0)
442     conn_set_channel(conn,CHANNEL_NAME_BANNED);
443     xfree((void *)chname);
444     return 0;
445     }
446    
447    
448     extern int channel_add_connection(t_channel * channel, t_connection * connection)
449     {
450     t_channelmember * member;
451     t_connection * user;
452    
453     if (!channel)
454     {
455     eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
456     return -1;
457     }
458     if (!connection)
459     {
460     eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection");
461     return -1;
462     }
463    
464     if (channel_check_banning(channel,connection))
465     {
466     channel_message_log(channel,connection,0,"JOIN FAILED (banned)");
467     return -1;
468     }
469    
470     member = xmalloc(sizeof(t_channelmember));
471     member->connection = connection;
472     member->next = channel->memberlist;
473     channel->memberlist = member;
474     channel->currmembers++;
475    
476     channel_message_log(channel,connection,0,"JOINED");
477    
478     message_send_text(connection,message_type_channel,connection,channel_get_name(channel));
479    
480     if ((!(channel->flags & channel_flags_permanent))
481     && (!(channel->flags & channel_flags_thevoid))
482     && (!(channel->flags & channel_flags_clan))
483     && (channel->currmembers==1)
484     && (account_is_operator_or_admin(conn_get_account(connection),channel_get_name(channel))==0))
485     {
486     message_send_text(connection,message_type_info,connection,"you are now tempOP for this channel");
487     conn_set_tmpOP_channel(connection,(char *)channel_get_name(channel));
488     channel_update_userflags(connection);
489     }
490    
491     if(!(channel_get_flags(channel) & channel_flags_thevoid))
492     for (user=channel_get_first(channel); user; user=channel_get_next())
493     {
494     message_send_text(connection,message_type_adduser,user,NULL);
495     if (user!=connection)
496     message_send_text(user,message_type_join,connection,NULL);
497     }
498    
499     /* please don't remove this notice */
500     if (channel->log)
501     message_send_text(connection,message_type_info,connection,prefs_get_log_notice());
502    
503     return 0;
504     }
505    
506    
507     extern int channel_del_connection(t_channel * channel, t_connection * connection)
508     {
509     t_channelmember * curr;
510     t_channelmember * temp;
511     t_elem * curr2;
512    
513     if (!channel)
514     {
515     eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
516     return -1;
517     }
518     if (!connection)
519     {
520     eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection");
521     return -1;
522     }
523    
524     channel_message_log(channel,connection,0,"PARTED");
525    
526     channel_message_send(channel,message_type_part,connection,NULL);
527    
528     curr = channel->memberlist;
529     if (curr->connection==connection)
530     {
531     channel->memberlist = channel->memberlist->next;
532     xfree(curr);
533     }
534     else
535     {
536     while (curr->next && curr->next->connection!=connection)
537     curr = curr->next;
538    
539     if (curr->next)
540     {
541     temp = curr->next;
542     curr->next = curr->next->next;
543     xfree(temp);
544     }
545     else
546     {
547     eventlog(eventlog_level_error,__FUNCTION__,"[%d] connection not in channel member list",conn_get_socket(connection));
548     return -1;
549     }
550     }
551     channel->currmembers--;
552    
553     if (conn_get_tmpOP_channel(connection) &&
554     strcmp(conn_get_tmpOP_channel(connection),channel_get_name(channel))==0)
555     {
556     conn_set_tmpOP_channel(connection,NULL);
557     }
558    
559     if (!channel->memberlist && !(channel->flags & channel_flags_permanent)) /* if channel is empty, delete it unless it's a permanent channel */
560     {
561     channel_destroy(channel,&curr2);
562     }
563    
564     return 0;
565     }
566    
567    
568     extern void channel_update_latency(t_connection * me)
569     {
570     t_channel * channel;
571     t_message * message;
572     t_connection * c;
573    
574     if (!me)
575     {
576     eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection");
577     return;
578     }
579     if (!(channel = conn_get_channel(me)))
580     {
581     eventlog(eventlog_level_error,__FUNCTION__,"connection has no channel");
582     return;
583     }
584    
585     if (!(message = message_create(message_type_userflags,me,NULL,NULL))) /* handles NULL text */
586     return;
587    
588     for (c=channel_get_first(channel); c; c=channel_get_next())
589     if (conn_get_class(c)==conn_class_bnet)
590     message_send(message,c);
591     message_destroy(message);
592     }
593    
594    
595     extern void channel_update_userflags(t_connection * me)
596     {
597     t_channel * channel;
598     t_message * message;
599     t_connection * c;
600    
601     if (!me)
602     {
603     eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection");
604     return;
605     }
606     if (!(channel = conn_get_channel(me)))
607     {
608     eventlog(eventlog_level_error,__FUNCTION__,"connection has no channel");
609     return;
610     }
611    
612     if (!(message = message_create(message_type_userflags,me,NULL,NULL))) /* handles NULL text */
613     return;
614    
615     for (c=channel_get_first(channel); c; c=channel_get_next())
616     message_send(message,c);
617    
618     message_destroy(message);
619     }
620    
621    
622     extern void channel_message_log(t_channel const * channel, t_connection * me, int fromuser, char const * text)
623     {
624     if (!channel)
625     {
626     eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
627     return;
628     }
629     if (!me)
630     {
631     eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection");
632     return;
633     }
634    
635     if (channel->log)
636     {
637     time_t now;
638     struct tm * tmnow;
639     char timetemp[CHANLOG_TIME_MAXLEN];
640    
641     now = time(NULL);
642     if ((!(tmnow = localtime(&now))))
643     strcpy(timetemp,"?");
644     else
645     strftime(timetemp,sizeof(timetemp),CHANLOGLINE_TIME_FORMAT,tmnow);
646    
647     if (fromuser)
648     fprintf(channel->log,"%s: \"%s\" \"%s\"\n",timetemp,conn_get_username(me),text);
649     else
650     fprintf(channel->log,"%s: \"%s\" %s\n",timetemp,conn_get_username(me),text);
651     fflush(channel->log);
652     }
653     }
654    
655    
656     extern void channel_message_send(t_channel const * channel, t_message_type type, t_connection * me, char const * text)
657     {
658     t_connection * c;
659     unsigned int heard;
660     t_message * message;
661     char const * tname;
662    
663     if (!channel)
664     {
665     eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
666     return;
667     }
668     if (!me)
669     {
670     eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection");
671     return;
672     }
673    
674     if(channel_get_flags(channel) & channel_flags_thevoid) // no talking in the void
675     return;
676    
677     if(channel_get_flags(channel) & channel_flags_moderated) // moderated channel - only admins,OPs and voices may talk
678     {
679     if (type==message_type_talk || type==message_type_emote)
680     {
681     if (!((account_is_operator_or_admin(conn_get_account(me),channel_get_name(channel))) ||
682     (channel_conn_has_tmpVOICE(channel,me))))
683     {
684     message_send_text(me,message_type_error,me,"This channel is moderated");
685     return;
686     }
687     }
688     }
689    
690     if (!(message = message_create(type,me,NULL,text)))
691     {
692     eventlog(eventlog_level_error,__FUNCTION__,"could not create message");
693     return;
694     }
695    
696     heard = 0;
697     tname = conn_get_chatname(me);
698     for (c=channel_get_first(channel); c; c=channel_get_next())
699     {
700     if (c==me && (type==message_type_talk || type==message_type_join || type==message_type_part))
701     continue; /* ignore ourself */
702     if ((type==message_type_talk || type==message_type_whisper || type==message_type_emote || type==message_type_broadcast) &&
703     conn_check_ignoring(c,tname)==1)
704     continue; /* ignore squelched players */
705    
706     if (message_send(message,c)==0 && c!=me)
707     heard = 1;
708    
709     }
710     conn_unget_chatname(me,tname);
711    
712     message_destroy(message);
713    
714     if (!heard && (type==message_type_talk || type==message_type_emote))
715     message_send_text(me,message_type_info,me,"No one hears you.");
716     }
717    
718     extern int channel_ban_user(t_channel * channel, char const * user)
719     {
720     t_elem const * curr;
721     char * temp;
722    
723     if (!channel)
724     {
725     eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
726     return -1;
727     }
728     if (!user)
729     {
730     eventlog(eventlog_level_error,__FUNCTION__,"got NULL user");
731     return -1;
732     }
733     if (!channel->name)
734     {
735     eventlog(eventlog_level_error,__FUNCTION__,"got channel with NULL name");
736     return -1;
737     }
738    
739     if (strcasecmp(channel->name,CHANNEL_NAME_BANNED)==0 ||
740     strcasecmp(channel->name,CHANNEL_NAME_KICKED)==0)
741     return -1;
742    
743     LIST_TRAVERSE_CONST(channel->banlist,curr)
744     if (strcasecmp(elem_get_data(curr),user)==0)
745     return 0;
746    
747     temp = xstrdup(user);
748     list_append_data(channel->banlist,temp);
749    
750     return 0;
751     }
752    
753    
754     extern int channel_unban_user(t_channel * channel, char const * user)
755     {
756     t_elem * curr;
757    
758     if (!channel)
759     {
760     eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
761     return -1;
762     }
763     if (!user)
764     {
765     eventlog(eventlog_level_error,__FUNCTION__,"got NULL user");
766     return -1;
767     }
768    
769     LIST_TRAVERSE(channel->banlist,curr)
770     {
771     char const * banned;
772    
773     if (!(banned = elem_get_data(curr)))
774     {
775     eventlog(eventlog_level_error,__FUNCTION__,"found NULL name in banlist");
776     continue;
777     }
778     if (strcasecmp(banned,user)==0)
779     {
780     if (list_remove_elem(channel->banlist,&curr)<0)
781     {
782     eventlog(eventlog_level_error,__FUNCTION__,"unable to remove item from list");
783     return -1;
784     }
785     xfree((void *)banned); /* avoid warning */
786     return 0;
787     }
788     }
789    
790     return -1;
791     }
792    
793    
794     extern int channel_check_banning(t_channel const * channel, t_connection const * user)
795     {
796     t_elem const * curr;
797    
798     if (!channel)
799     {
800     eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
801     return -1;
802     }
803     if (!user)
804     {
805     eventlog(eventlog_level_error,__FUNCTION__,"got NULL user");
806     return -1;
807     }
808    
809     if (!(channel->flags & channel_flags_allowbots) && conn_get_class(user)==conn_class_bot)
810     return 1;
811    
812     LIST_TRAVERSE_CONST(channel->banlist,curr)
813     if (conn_match(user,elem_get_data(curr))==1)
814     return 1;
815    
816     return 0;
817     }
818    
819    
820     extern int channel_get_length(t_channel const * channel)
821     {
822     t_channelmember const * curr;
823     int count;
824    
825     for (curr=channel->memberlist,count=0; curr; curr=curr->next,count++);
826    
827     return count;
828     }
829    
830    
831     extern t_connection * channel_get_first(t_channel const * channel)
832     {
833     if (!channel)
834     {
835     eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
836     return NULL;
837     }
838    
839     memberlist_curr = channel->memberlist;
840    
841     return channel_get_next();
842     }
843    
844     extern t_connection * channel_get_next(void)
845     {
846    
847     t_channelmember * member;
848    
849     if (memberlist_curr)
850     {
851     member = memberlist_curr;
852     memberlist_curr = memberlist_curr->next;
853    
854     return member->connection;
855     }
856     return NULL;
857     }
858    
859    
860     extern t_list * channel_get_banlist(t_channel const * channel)
861     {
862     if (!channel)
863     {
864     eventlog(eventlog_level_warn,__FUNCTION__,"got NULL channel");
865     return NULL;
866     }
867    
868     return channel->banlist;
869     }
870    
871    
872     extern char const * channel_get_shortname(t_channel const * channel)
873     {
874     if (!channel)
875     {
876     eventlog(eventlog_level_warn,__FUNCTION__,"got NULL channel");
877     return NULL;
878     }
879    
880     return channel->shortname;
881     }
882    
883    
884     static int channellist_load_permanent(char const * filename)
885     {
886     FILE * fp;
887     unsigned int line;
888     unsigned int pos;
889     int botflag;
890     int operflag;
891     int logflag;
892     unsigned int modflag;
893     char * buff;
894     char * name;
895     char * sname;
896     char * tag;
897     char * bot;
898     char * oper;
899     char * log;
900     char * country;
901     char * max;
902     char * moderated;
903     char * newname;
904     char * realmname;
905    
906     if (!filename)
907     {
908     eventlog(eventlog_level_error,__FUNCTION__,"got NULL filename");
909     return -1;
910     }
911    
912     if (!(fp = fopen(filename,"r")))
913     {
914     eventlog(eventlog_level_error,__FUNCTION__,"could not open channel file \"%s\" for reading (fopen: %s)",filename,pstrerror(errno));
915     return -1;
916     }
917    
918     for (line=1; (buff = file_get_line(fp)); line++)
919     {
920     if (buff[0]=='#' || buff[0]=='\0')
921     {
922     continue;
923     }
924     pos = 0;
925     if (!(name = next_token(buff,&pos)))
926     {
927     eventlog(eventlog_level_error,__FUNCTION__,"missing name in line %u in file \"%s\"",line,filename);
928     continue;
929     }
930     if (!(sname = next_token(buff,&pos)))
931     {
932     eventlog(eventlog_level_error,__FUNCTION__,"missing sname in line %u in file \"%s\"",line,filename);
933     continue;
934     }
935     if (!(tag = next_token(buff,&pos)))
936     {
937     eventlog(eventlog_level_error,__FUNCTION__,"missing tag in line %u in file \"%s\"",line,filename);
938     continue;
939     }
940     if (!(bot = next_token(buff,&pos)))
941     {
942     eventlog(eventlog_level_error,__FUNCTION__,"missing bot in line %u in file \"%s\"",line,filename);
943     continue;
944     }
945     if (!(oper = next_token(buff,&pos)))
946     {
947     eventlog(eventlog_level_error,__FUNCTION__,"missing oper in line %u in file \"%s\"",line,filename);
948     continue;
949     }
950     if (!(log = next_token(buff,&pos)))
951     {
952     eventlog(eventlog_level_error,__FUNCTION__,"missing log in line %u in file \"%s\"",line,filename);
953     continue;
954     }
955     if (!(country = next_token(buff,&pos)))
956     {
957     eventlog(eventlog_level_error,__FUNCTION__,"missing country in line %u in file \"%s\"",line,filename);
958     continue;
959     }
960     if (!(realmname = next_token(buff,&pos)))
961     {
962     eventlog(eventlog_level_error,__FUNCTION__,"missing realmname in line %u in file \"%s\"",line,filename);
963     continue;
964     }
965     if (!(max = next_token(buff,&pos)))
966     {
967     eventlog(eventlog_level_error,__FUNCTION__,"missing max in line %u in file \"%s\"",line,filename);
968     continue;
969     }
970     if (!(moderated = next_token(buff,&pos)))
971     {
972     eventlog(eventlog_level_error,__FUNCTION__,"missing mod in line %u in file \"%s\"",line,filename);
973     continue;
974     }
975    
976     switch (str_get_bool(bot))
977     {
978     case 1:
979     botflag = 1;
980     break;
981     case 0:
982     botflag = 0;
983     break;
984     default:
985     eventlog(eventlog_level_error,__FUNCTION__,"invalid boolean value \"%s\" for field 4 on line %u in file \"%s\"",bot,line,filename);
986     continue;
987     }
988    
989     switch (str_get_bool(oper))
990     {
991     case 1:
992     operflag = 1;
993     break;
994     case 0:
995     operflag = 0;
996     break;
997     default:
998     eventlog(eventlog_level_error,__FUNCTION__,"invalid boolean value \"%s\" for field 5 on line %u in file \"%s\"",oper,line,filename);
999     continue;
1000     }
1001    
1002     switch (str_get_bool(log))
1003     {
1004     case 1:
1005     logflag = 1;
1006     break;
1007     case 0:
1008     logflag = 0;
1009     break;
1010     default:
1011     eventlog(eventlog_level_error,__FUNCTION__,"invalid boolean value \"%s\" for field 5 on line %u in file \"%s\"",log,line,filename);
1012     continue;
1013     }
1014    
1015     switch (str_get_bool(moderated))
1016     {
1017     case 1:
1018     modflag = 1;
1019     break;
1020     case 0:
1021     modflag = 0;
1022     break;
1023     default:
1024     eventlog(eventlog_level_error,__FUNCTION__,"invalid boolean value \"%s\" for field 10 on line %u in file \"%s\"",moderated,line,filename);
1025     continue;
1026     }
1027    
1028     if (strcmp(sname,"NULL") == 0)
1029     sname = NULL;
1030     if (strcmp(tag,"NULL") == 0)
1031     tag = NULL;
1032     if (strcmp(name,"NONE") == 0)
1033     name = NULL;
1034     if (strcmp(country, "NULL") == 0)
1035     country = NULL;
1036     if (strcmp(realmname,"NULL") == 0)
1037     realmname = NULL;
1038    
1039     if (name)
1040     {
1041     channel_create(name,sname,tag,1,botflag,operflag,logflag,country,realmname,atoi(max),modflag,0,0);
1042     }
1043     else
1044     {
1045     newname = channel_format_name(sname,country,realmname,1);
1046     if (newname)
1047     {
1048     channel_create(newname,sname,tag,1,botflag,operflag,logflag,country,realmname,atoi(max),modflag,0,1);
1049     xfree(newname);
1050     }
1051     else
1052     {
1053     eventlog(eventlog_level_error,__FUNCTION__,"cannot format channel name");
1054     }
1055     }
1056    
1057     /* FIXME: call channel_delete() on current perm channels and do a
1058     channellist_find_channel() and set the long name, perm flag, etc,
1059     otherwise call channel_create(). This will make HUPing the server
1060     handle re-reading this file correctly. */
1061     }
1062    
1063     file_get_line(NULL); // clear file_get_line buffer
1064     if (fclose(fp)<0)
1065     eventlog(eventlog_level_error,__FUNCTION__,"could not close channel file \"%s\" after reading (fclose: %s)",filename,pstrerror(errno));
1066     return 0;
1067     }
1068    
1069     static char * channel_format_name(char const * sname, char const * country, char const * realmname, unsigned int id)
1070     {
1071     char * fullname;
1072     unsigned int len;
1073    
1074     if (!sname)
1075     {
1076     eventlog(eventlog_level_error,__FUNCTION__,"got NULL sname");
1077     return NULL;
1078     }
1079     len = strlen(sname)+1; /* FIXME: check lengths and format */
1080     if (country)
1081     len = len + strlen(country) + 1;
1082     if (realmname)
1083     len = len + strlen(realmname) + 1;
1084     len = len + 32 + 1;
1085    
1086     fullname=xmalloc(len);
1087     sprintf(fullname,"%s%s%s%s%s-%d",
1088     realmname?realmname:"",
1089     realmname?" ":"",
1090     sname,
1091     country?" ":"",
1092     country?country:"",
1093     id);
1094     return fullname;
1095     }
1096    
1097     extern int channellist_reload(void)
1098     {
1099     t_elem * curr;
1100     t_channel * channel, * old_channel;
1101     t_channelmember * memberlist, * member, * old_member;
1102     t_list * channellist_old;
1103    
1104     if (channellist_head)
1105     {
1106    
1107     channellist_old = list_create();
1108    
1109     /* First pass - get members */
1110     LIST_TRAVERSE(channellist_head,curr)
1111     {
1112     if (!(channel = elem_get_data(curr)))
1113     {
1114     eventlog(eventlog_level_error,__FUNCTION__,"channel list contains NULL item");
1115     continue;
1116     }
1117     /* Trick to avoid automatic channel destruction */
1118     channel->flags |= channel_flags_permanent;
1119     if (channel->memberlist)
1120     {
1121     /* we need only channel name and memberlist */
1122    
1123     old_channel = (t_channel *) xmalloc(sizeof(t_channel));
1124     old_channel->shortname = xstrdup(channel->shortname);
1125     old_channel->memberlist = NULL;
1126     member = channel->memberlist;
1127    
1128     /* First pass */
1129     while (member)
1130     {
1131     old_member = xmalloc(sizeof(t_channelmember));
1132     old_member->connection = member->connection;
1133    
1134     if (old_channel->memberlist)
1135     old_member->next = old_channel->memberlist;
1136     else
1137     old_member->next = NULL;
1138    
1139     old_channel->memberlist = old_member;
1140     member = member->next;
1141     }
1142    
1143     /* Second pass - remove connections from channel */
1144     member = old_channel->memberlist;
1145     while (member)
1146     {
1147     channel_del_connection(channel,member->connection);
1148     conn_set_channel_var(member->connection,NULL);
1149     member = member->next;
1150     }
1151    
1152     list_prepend_data(channellist_old,old_channel);
1153     }
1154    
1155     /* Channel is empty - Destroying it */
1156     channel->flags &= ~channel_flags_permanent;
1157     if (channel_destroy(channel,&curr)<0)
1158     eventlog(eventlog_level_error,__FUNCTION__,"could not destroy channel");
1159    
1160     }
1161    
1162     /* Cleanup and reload */
1163    
1164     if (list_destroy(channellist_head)<0)
1165     return -1;
1166    
1167     channellist_head = NULL;
1168     channellist_create();
1169    
1170     /* Now put all users on their previous channel */
1171    
1172     LIST_TRAVERSE(channellist_old,curr)
1173     {
1174     if (!(channel = elem_get_data(curr)))
1175     {
1176     eventlog(eventlog_level_error,__FUNCTION__,"old channel list contains NULL item");
1177     continue;
1178     }
1179    
1180     memberlist = channel->memberlist;
1181     while (memberlist)
1182     {
1183     member = memberlist;
1184     memberlist = memberlist->next;
1185     conn_set_channel(member->connection, channel->shortname);
1186     }
1187     }
1188    
1189    
1190     /* Ross don't blame me for this but this way the code is cleaner */
1191    
1192     LIST_TRAVERSE(channellist_old,curr)
1193     {
1194     if (!(channel = elem_get_data(curr)))
1195     {
1196     eventlog(eventlog_level_error,__FUNCTION__,"old channel list contains NULL item");
1197     continue;
1198     }
1199    
1200     memberlist = channel->memberlist;
1201     while (memberlist)
1202     {
1203     member = memberlist;
1204     memberlist = memberlist->next;
1205     xfree((void*)member);
1206     }
1207    
1208     if (channel->shortname)
1209     xfree((void*)channel->shortname);
1210    
1211     if (list_remove_data(channellist_old,channel,&curr)<0)
1212     eventlog(eventlog_level_error,__FUNCTION__,"could not remove item from list");
1213     xfree((void*)channel);
1214    
1215     }
1216    
1217     if (list_destroy(channellist_old)<0)
1218     return -1;
1219     }
1220     return 0;
1221    
1222     }
1223    
1224     extern int channellist_create(void)
1225     {
1226     channellist_head = list_create();
1227    
1228     return channellist_load_permanent(prefs_get_channelfile());
1229     }
1230    
1231    
1232     extern int channellist_destroy(void)
1233     {
1234     t_channel * channel;
1235     t_elem * curr;
1236    
1237     if (channellist_head)
1238     {
1239     LIST_TRAVERSE(channellist_head,curr)
1240     {
1241     if (!(channel = elem_get_data(curr))) /* should not happen */
1242     {
1243     eventlog(eventlog_level_error,__FUNCTION__,"channel list contains NULL item");
1244     continue;
1245     }
1246    
1247     channel_destroy(channel,&curr);
1248     }
1249    
1250     if (list_destroy(channellist_head)<0)
1251     return -1;
1252     channellist_head = NULL;
1253     }
1254    
1255     return 0;
1256     }
1257    
1258    
1259     extern t_list * channellist(void)
1260     {
1261     return channellist_head;
1262     }
1263    
1264    
1265     extern int channellist_get_length(void)
1266     {
1267     return list_get_length(channellist_head);
1268     }
1269    
1270     extern int channel_get_max(t_channel const * channel)
1271     {
1272     if (!channel)
1273     {
1274     eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
1275     return 0;
1276     }
1277    
1278     return channel->maxmembers;
1279     }
1280    
1281     extern int channel_get_curr(t_channel const * channel)
1282     {
1283     if (!channel)
1284     {
1285     eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
1286     return 0;
1287     }
1288    
1289     return channel->currmembers;
1290    
1291     }
1292    
1293     extern int channel_conn_is_tmpOP(t_channel const * channel, t_connection * c)
1294     {
1295     if (!channel)
1296     {
1297     eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
1298     return 0;
1299     }
1300    
1301     if (!c)
1302     {
1303     eventlog(eventlog_level_error,__FUNCTION__,"got NULL account");
1304     return 0;
1305     }
1306    
1307     if (!conn_get_tmpOP_channel(c)) return 0;
1308    
1309     if (strcmp(conn_get_tmpOP_channel(c),channel_get_name(channel))==0) return 1;
1310    
1311     return 0;
1312     }
1313    
1314     extern int channel_conn_has_tmpVOICE(t_channel const * channel, t_connection * c)
1315     {
1316     if (!channel)
1317     {
1318     eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel");
1319     return 0;
1320     }
1321    
1322     if (!c)
1323     {
1324     eventlog(eventlog_level_error,__FUNCTION__,"got NULL account");
1325     return 0;
1326     }
1327    
1328     if (!conn_get_tmpVOICE_channel(c)) return 0;
1329    
1330     if (strcmp(conn_get_tmpVOICE_channel(c),channel_get_name(channel))==0) return 1;
1331    
1332     return 0;
1333     }
1334    
1335     static t_channel * channellist_find_channel_by_fullname(char const * name)
1336     {
1337     t_channel * channel;
1338     t_elem const * curr;
1339    
1340     if (channellist_head)
1341     {
1342     LIST_TRAVERSE(channellist_head,curr)
1343     {
1344     channel = elem_get_data(curr);
1345     if (!channel->name)
1346     {
1347     eventlog(eventlog_level_error,__FUNCTION__,"found channel with NULL name");
1348     continue;
1349     }
1350    
1351     if (strcasecmp(channel->name,name)==0)
1352     return channel;
1353     }
1354     }
1355    
1356     return NULL;
1357     }
1358    
1359    
1360     /* Find a channel based on the name.
1361     * Create a new channel if it is a permanent-type channel and all others
1362     * are full.
1363     */
1364     extern t_channel * channellist_find_channel_by_name(char const * name, char const * country, char const * realmname)
1365     {
1366     t_channel * channel;
1367     t_elem const * curr;
1368     int foundperm;
1369     int foundlang;
1370     int maxchannel; /* the number of "rollover" channels that exist */
1371     char const * saveshortname;
1372     char const * savespecialname;
1373     char const * savetag;
1374     int savebotflag;
1375     int saveoperflag;
1376     int savelogflag;
1377     unsigned int savemoderated;
1378     char const * savecountry;
1379     char const * saverealmname;
1380     int savemaxmembers;
1381     t_channel * special_channel;
1382    
1383     // try to make gcc happy and initialize all variables
1384     saveshortname = savespecialname = savetag = savecountry = saverealmname = NULL;
1385     savebotflag = saveoperflag = savelogflag = savemaxmembers = savemoderated = 0;
1386    
1387     maxchannel = 0;
1388     foundperm = 0;
1389     foundlang = 0;
1390     if (channellist_head)
1391     {
1392     LIST_TRAVERSE(channellist_head,curr)
1393     {
1394     channel = elem_get_data(curr);
1395     if (!channel->name)
1396     {
1397     eventlog(eventlog_level_error,__FUNCTION__,"found channel with NULL name");
1398     continue;
1399     }
1400    
1401     if (strcasecmp(channel->name,name)==0)
1402     {
1403     // eventlog(eventlog_level_debug,__FUNCTION__,"found exact match for \"%s\"",name);
1404     return channel;
1405     }
1406    
1407     if (channel->shortname && strcasecmp(channel->shortname,name)==0)
1408     {
1409     special_channel = channellist_find_channel_by_name(channel->name,country,realmname);
1410     if (special_channel) channel= special_channel;
1411    
1412     /* FIXME: what should we do if the client doesn't have a country? For now, just take the first
1413     * channel that would otherwise match. */
1414     if ( ((!channel->country && !foundlang) || !country ||
1415     (channel->country && country && (strcmp(channel->country, country)==0))) &&
1416     ((!channel->realmname && !realmname) ||
1417     (channel->realmname && realmname && (strcmp(channel->realmname, realmname)==0))) )
1418    
1419     {
1420     if (channel->maxmembers==-1 || channel->currmembers<channel->maxmembers)
1421     {
1422     eventlog(eventlog_level_debug,__FUNCTION__,"found permanent channel \"%s\" for \"%s\"",channel->name,name);
1423     return channel;
1424     }
1425    
1426     if (!foundlang && (channel->country)) //remember we had found a language specific channel but it was full
1427     {
1428     foundlang = 1;
1429     if (!(channel->flags & channel_flags_autoname))
1430     savespecialname = channel->name;
1431     maxchannel = 0;
1432     }
1433    
1434     maxchannel++;
1435     }
1436    
1437     // eventlog(eventlog_level_debug,__FUNCTION__,"countries didn't match");
1438    
1439     foundperm = 1;
1440    
1441     /* save off some info in case we need to create a new copy */
1442     saveshortname = channel->shortname;
1443     savetag = channel->clienttag;
1444     savebotflag = channel->flags & channel_flags_allowbots;
1445     saveoperflag = channel->flags & channel_flags_allowopers;
1446     if (channel->logname)
1447     savelogflag = 1;
1448     else
1449     savelogflag = 0;
1450     if (country)
1451     savecountry = country;
1452     else
1453     savecountry = channel->country;
1454     if (realmname)
1455     saverealmname = realmname;
1456     else
1457     saverealmname = channel->realmname;
1458     savemaxmembers = channel->maxmembers;
1459     savemoderated = channel->flags & channel_flags_moderated;
1460     }
1461     }
1462     }
1463    
1464     /* we've gone thru the whole list and either there was no match or the
1465     * channels are all full.
1466     */
1467    
1468     if (foundperm) /* All the channels were full, create a new one */
1469     {
1470     char * channelname;
1471    
1472     if (!foundlang || !savespecialname)
1473     {
1474     if (!(channelname=channel_format_name(saveshortname,savecountry,saverealmname,maxchannel+1)))
1475     return NULL;
1476     }
1477     else
1478     {
1479     if (!(channelname=channel_format_name(savespecialname,NULL,saverealmname,maxchannel+1)))
1480     return NULL;
1481     }
1482    
1483     channel = channel_create(channelname,saveshortname,savetag,1,savebotflag,saveoperflag,savelogflag,savecountry,saverealmname,savemaxmembers,savemoderated,0,1);
1484     xfree(channelname);
1485    
1486     eventlog(eventlog_level_debug,__FUNCTION__,"created copy \"%s\" of channel \"%s\"",(channel)?(channel->name):("<failed>"),name);
1487     return channel;
1488     }
1489    
1490     /* no match */
1491     eventlog(eventlog_level_debug,__FUNCTION__,"could not find channel \"%s\"",name);
1492     return NULL;
1493     }
1494    
1495    
1496     extern t_channel * channellist_find_channel_bychannelid(unsigned int channelid)
1497     {
1498     t_channel * channel;
1499     t_elem const * curr;
1500    
1501     if (channellist_head)
1502     {
1503     LIST_TRAVERSE(channellist_head,curr)
1504     {
1505     channel = elem_get_data(curr);
1506     if (!channel->name)
1507     {
1508     eventlog(eventlog_level_error,__FUNCTION__,"found channel with NULL name");
1509     continue;
1510     }
1511     if (channel->id==channelid)
1512     return channel;
1513     }
1514     }
1515    
1516     return NULL;
1517     }
1518    
1519     extern int channel_set_userflags(t_connection * c)
1520     {
1521     unsigned int newflags;
1522     char const * channel;
1523     t_account * acc;
1524    
1525     if (!c) return -1; // user not connected, no need to update his flags
1526    
1527     acc = conn_get_account(c);
1528    
1529     /* well... unfortunatly channel_get_name never returns NULL but "" instead
1530     so we first have to check if user is in a channel at all */
1531     if ((!conn_get_channel(c)) || (!(channel = channel_get_name(conn_get_channel(c)))))
1532     return -1;
1533    
1534     if (account_get_auth_admin(acc,channel) == 1 || account_get_auth_admin(acc,NULL) == 1)
1535     newflags = MF_BLIZZARD;
1536     else if (account_get_auth_operator(acc,channel) == 1 ||
1537     account_get_auth_operator(acc,NULL) == 1)
1538     newflags = MF_BNET;
1539     else if (channel_conn_is_tmpOP(conn_get_channel(c),c))
1540     newflags = MF_GAVEL;
1541     else if ((account_get_auth_voice(acc,channel) == 1) ||
1542     (channel_conn_has_tmpVOICE(conn_get_channel(c),c)))
1543     newflags = MF_VOICE;
1544     else
1545     if ((conn_get_clienttag(c) == CLIENTTAG_WARCRAFT3_UINT) ||
1546     (conn_get_clienttag(c) == CLIENTTAG_WAR3XP_UINT))
1547     newflags = W3_ICON_SET;
1548     else
1549     newflags = 0;
1550    
1551     if (conn_get_flags(c) != newflags) {
1552     conn_set_flags(c, newflags);
1553     channel_update_userflags(c);
1554     }
1555    
1556     return 0;
1557     }

webmaster@leafok.com
ViewVC Help
Powered by ViewVC 1.3.0-beta1