?? channel.c
字號:
/* * Copyright (C) 1998 Mark Baysinger (mbaysing@ucsd.edu) * Copyright (C) 1998,1999,2000 Ross Combs (rocombs@cs.nmsu.edu) * Copyright (C) 2000,2001 Marco Ziech (mmz@gmx.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#define CHANNEL_INTERNAL_ACCESS#include "common/setup_before.h"#include <stdio.h>#ifdef HAVE_STDDEF_H# include <stddef.h>#else# ifndef NULL# define NULL ((void *)0)# endif#endif#ifdef STDC_HEADERS# include <stdlib.h>#else# ifdef HAVE_MALLOC_H# include <malloc.h># endif#endif#ifdef HAVE_STRING_H# include <string.h>#else# ifdef HAVE_STRINGS_H# include <strings.h># endif#endif#include "compat/strrchr.h"#include "compat/strdup.h"#include "compat/strcasecmp.h"#include <errno.h>#include "compat/strerror.h"#ifdef TIME_WITH_SYS_TIME# include <sys/time.h># include <time.h>#else# ifdef HAVE_SYS_TIME_H# include <sys/time.h># else# include <time.h># endif#endif#ifdef HAVE_SYS_TYPES_H# include <sys/types.h>#endif#include "connection.h"#include "common/eventlog.h"#include "common/list.h"#include "message.h"#include "account.h"#include "account_wrap.h"#include "common/util.h"#include "prefs.h"#include "common/token.h"#include "channel.h"#include "irc.h"#include "common/tag.h"#include "common/xalloc.h"#include "common/setup_after.h"static t_list * channellist_head=NULL;static t_channelmember * memberlist_curr=NULL;static int totalcount=0;static int channellist_load_permanent(char const * filename);static t_channel * channellist_find_channel_by_fullname(char const * name);static char * channel_format_name(char const * sname, char const * country, char const * realmname, unsigned int id);extern int channel_set_userflags(t_connection * c);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){ t_channel * channel; if (!fullname) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL fullname"); return NULL; } if (fullname[0]=='\0') { eventlog(eventlog_level_error,__FUNCTION__,"got empty fullname"); return NULL; } if (shortname && shortname[0]=='\0') { eventlog(eventlog_level_error,__FUNCTION__,"got empty shortname"); return NULL; } if (clienttag && strlen(clienttag)!=4) { eventlog(eventlog_level_error,__FUNCTION__,"client tag has bad length (%u chars)",strlen(clienttag)); return NULL; } /* non-permanent already checks for this in conn_set_channel */ if (permflag) { if ((channel = channellist_find_channel_by_fullname(fullname))) { if ((channel_get_clienttag(channel)) && (clienttag) && (strcmp(channel_get_clienttag(channel),clienttag)==0)) { eventlog(eventlog_level_error,__FUNCTION__,"could not create duplicate permanent channel (fullname \"%s\")",fullname); return NULL; } else if (((channel->flags & channel_flags_allowbots)!=(botflag?channel_flags_allowbots:0)) || ((channel->flags & channel_flags_allowopers)!=(operflag?channel_flags_allowopers:0)) || (channel->maxmembers!=maxmembers) || ((channel->flags & channel_flags_moderated)!=(moderated?channel_flags_moderated:0)) || (channel->logname && logflag==0) || (!(channel->logname) && logflag ==1)) { eventlog(eventlog_level_error,__FUNCTION__,"channel parameters do not match for \"%s\" and \"%s\"",fullname,channel->name); return NULL; } } } channel = xmalloc(sizeof(t_channel)); if (permflag) { channel->flags = channel_flags_public; if (clienttag && maxmembers!=-1) /* approximation.. we want things like "Starcraft USA-1" */ channel->flags |= channel_flags_system; } else channel->flags = channel_flags_none; if (moderated) channel->flags |= channel_flags_moderated; if(shortname && (!strcasecmp(shortname, CHANNEL_NAME_KICKED) || !strcasecmp(shortname, CHANNEL_NAME_BANNED))) channel->flags |= channel_flags_thevoid; 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, shortname?"\"":"(", /* all this is doing is printing the name in quotes else "none" in parens */ shortname?shortname:"none", shortname?"\"":")", clienttag?"\"":"(", clienttag?clienttag:"none", clienttag?"\"":")", country?"\"":"(", country?country:"none", country?"\"":")", realmname?"\"":"(", realmname?realmname:"none", realmname?"\"":")"); channel->name = xstrdup(fullname); if (!shortname) channel->shortname = NULL; else channel->shortname = xstrdup(shortname); if (clienttag) channel->clienttag = xstrdup(clienttag); else channel->clienttag = NULL; if (country) channel->country = xstrdup(country); else channel->country = NULL; if (realmname) channel->realmname = xstrdup(realmname); else channel->realmname=NULL; channel->banlist = list_create(); totalcount++; if (totalcount==0) /* if we wrap (yeah right), don't use id 0 */ totalcount = 1; channel->id = totalcount; channel->maxmembers = maxmembers; channel->currmembers = 0; channel->memberlist = NULL; if (permflag) channel->flags |= channel_flags_permanent; if (botflag) channel->flags |= channel_flags_allowbots; if (operflag) channel->flags |= channel_flags_allowopers; if (clanflag) channel->flags |= channel_flags_clan; if (autoname) channel->flags |= channel_flags_autoname; if (logflag) { time_t now; struct tm * tmnow; char dstr[64]; char timetemp[CHANLOG_TIME_MAXLEN]; now = time(NULL); if (!(tmnow = localtime(&now))) dstr[0] = '\0'; else sprintf(dstr,"%04d%02d%02d%02d%02d%02d", 1900+tmnow->tm_year, tmnow->tm_mon+1, tmnow->tm_mday, tmnow->tm_hour, tmnow->tm_min, tmnow->tm_sec); channel->logname = xmalloc(strlen(prefs_get_chanlogdir())+9+strlen(dstr)+1+6+1); /* dir + "/chanlog-" + dstr + "-" + id + NUL */ sprintf(channel->logname,"%s/chanlog-%s-%06u",prefs_get_chanlogdir(),dstr,channel->id); if (!(channel->log = fopen(channel->logname,"w"))) eventlog(eventlog_level_error,__FUNCTION__,"could not open channel log \"%s\" for writing (fopen: %s)",channel->logname,pstrerror(errno)); else { fprintf(channel->log,"name=\"%s\"\n",channel->name); if (channel->shortname) fprintf(channel->log,"shortname=\"%s\"\n",channel->shortname); else fprintf(channel->log,"shortname=none\n"); fprintf(channel->log,"permanent=\"%s\"\n",(channel->flags & channel_flags_permanent)?"true":"false"); fprintf(channel->log,"allowbotse=\"%s\"\n",(channel->flags & channel_flags_allowbots)?"true":"false"); fprintf(channel->log,"allowopers=\"%s\"\n",(channel->flags & channel_flags_allowopers)?"true":"false"); if (channel->clienttag) fprintf(channel->log,"clienttag=\"%s\"\n",channel->clienttag); else fprintf(channel->log,"clienttag=none\n"); if (tmnow) strftime(timetemp,sizeof(timetemp),CHANLOG_TIME_FORMAT,tmnow); else strcpy(timetemp,"?"); fprintf(channel->log,"created=\"%s\"\n\n",timetemp); fflush(channel->log); } } else { channel->logname = NULL; channel->log = NULL; } channel->gameOwner = NULL; channel->gameOwnerIP = 0; channel->gameType = 0; channel->gameTournament = 0; channel->gameOptions = NULL; list_append_data(channellist_head,channel); eventlog(eventlog_level_debug,__FUNCTION__,"channel created successfully"); return channel;}extern int channel_destroy(t_channel * channel, t_elem ** curr){ t_elem * ban; if (!channel) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel"); return -1; } if (channel->memberlist) { eventlog(eventlog_level_debug,__FUNCTION__,"channel is not empty, deferring"); channel->flags &= ~channel_flags_permanent; /* make it go away when the last person leaves */ return -1; } if (list_remove_data(channellist_head,channel,curr)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not remove item from list"); return -1; } eventlog(eventlog_level_info,__FUNCTION__,"destroying channel \"%s\"",channel->name); LIST_TRAVERSE(channel->banlist,ban) { char const * banned; if (!(banned = elem_get_data(ban))) eventlog(eventlog_level_error,__FUNCTION__,"found NULL name in banlist"); else xfree((void *)banned); /* avoid warning */ if (list_remove_elem(channel->banlist,&ban)<0) eventlog(eventlog_level_error,__FUNCTION__,"unable to remove item from list"); } list_destroy(channel->banlist); if (channel->log) { time_t now; struct tm * tmnow; char timetemp[CHANLOG_TIME_MAXLEN]; now = time(NULL); if ((!(tmnow = localtime(&now)))) strcpy(timetemp,"?"); else strftime(timetemp,sizeof(timetemp),CHANLOG_TIME_FORMAT,tmnow); fprintf(channel->log,"\ndestroyed=\"%s\"\n",timetemp); if (fclose(channel->log)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not close channel log \"%s\" after writing (fclose: %s)",channel->logname,pstrerror(errno)); } if (channel->logname) xfree((void *)channel->logname); /* avoid warning */ if (channel->country) xfree((void *)channel->country); /* avoid warning */ if (channel->realmname) xfree((void *)channel->realmname); /* avoid warning */ if (channel->clienttag) xfree((void *)channel->clienttag); /* avoid warning */ if (channel->shortname) xfree((void *)channel->shortname); /* avoid warning */ xfree((void *)channel->name); /* avoid warning */ xfree(channel); return 0;}extern char const * channel_get_name(t_channel const * channel){ if (!channel) { eventlog(eventlog_level_warn,__FUNCTION__,"got NULL channel"); return ""; } return channel->name;}extern char const * channel_get_clienttag(t_channel const * channel){ if (!channel) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel"); return ""; } return channel->clienttag;}extern t_channel_flags channel_get_flags(t_channel const * channel){ if (!channel) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel"); return channel_flags_none; } return channel->flags;}extern int channel_set_flags(t_channel * channel, t_channel_flags flags){ if (!channel) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel"); return -1; } channel->flags = flags; return 0;}extern int channel_get_permanent(t_channel const * channel){ if (!channel) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel"); return 0; } return (channel->flags & channel_flags_permanent);}extern unsigned int channel_get_channelid(t_channel const * channel){ if (!channel) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel"); return 0; } return channel->id;}extern int channel_set_channelid(t_channel * channel, unsigned int channelid){ if (!channel) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel"); return -1; } channel->id = channelid; return 0;}extern int channel_rejoin(t_connection * conn){ t_channel const * channel; char const * temp; char const * chname; if (!(channel = conn_get_channel(conn))) return -1; if (!(temp = channel_get_name(channel))) return -1; chname=xstrdup(temp); conn_set_channel(conn, NULL); if (conn_set_channel(conn,chname)<0) conn_set_channel(conn,CHANNEL_NAME_BANNED); xfree((void *)chname); return 0; }extern int channel_add_connection(t_channel * channel, t_connection * connection){ t_channelmember * member; t_connection * user; if (!channel) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel"); return -1; } if (!connection) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (channel_check_banning(channel,connection)) { channel_message_log(channel,connection,0,"JOIN FAILED (banned)"); return -1; } member = xmalloc(sizeof(t_channelmember)); member->connection = connection; member->next = channel->memberlist; channel->memberlist = member; channel->currmembers++; channel_message_log(channel,connection,0,"JOINED"); message_send_text(connection,message_type_channel,connection,channel_get_name(channel)); if ((!(channel->flags & channel_flags_permanent)) && (!(channel->flags & channel_flags_thevoid)) && (!(channel->flags & channel_flags_clan)) && (channel->currmembers==1) && (account_is_operator_or_admin(conn_get_account(connection),channel_get_name(channel))==0)) { message_send_text(connection,message_type_info,connection,"you are now tempOP for this channel"); conn_set_tmpOP_channel(connection,(char *)channel_get_name(channel)); channel_update_userflags(connection); } if(!(channel_get_flags(channel) & channel_flags_thevoid)) for (user=channel_get_first(channel); user; user=channel_get_next()) { message_send_text(connection,message_type_adduser,user,NULL); if (user!=connection) message_send_text(user,message_type_join,connection,NULL); } /* please don't remove this notice */ if (channel->log) message_send_text(connection,message_type_info,connection,prefs_get_log_notice()); return 0;}extern int channel_del_connection(t_channel * channel, t_connection * connection){ t_channelmember * curr; t_channelmember * temp; t_elem * curr2; if (!channel) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel"); return -1; } if (!connection) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } channel_message_log(channel,connection,0,"PARTED"); channel_message_send(channel,message_type_part,connection,NULL); curr = channel->memberlist; if (curr->connection==connection) { channel->memberlist = channel->memberlist->next; xfree(curr); } else { while (curr->next && curr->next->connection!=connection) curr = curr->next; if (curr->next) { temp = curr->next; curr->next = curr->next->next; xfree(temp); } else { eventlog(eventlog_level_error,__FUNCTION__,"[%d] connection not in channel member list",conn_get_socket(connection)); return -1; } } channel->currmembers--; if (conn_get_tmpOP_channel(connection) && strcmp(conn_get_tmpOP_channel(connection),channel_get_name(channel))==0) { conn_set_tmpOP_channel(connection,NULL); } if (!channel->memberlist && !(channel->flags & channel_flags_permanent)) /* if channel is empty, delete it unless it's a permanent channel */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -