/* * ctcp.c: handles the client-to-client protocol(ctcp). * * Written By Michael Sandrof * * Copyright (c) 1990 Michael Sandrof. * Copyright (c) 1991, 1992 Troy Rollo. * Copyright (c) 1992-2003 Matthew R. Green. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: ctcp.c,v 1.51 2006/04/30 14:15:43 f Exp $ */ #include "irc.h" #ifndef _Windows #include <pwd.h> #endif /* _Windows */ #ifdef HAVE_UNAME # include <sys/utsname.h> #endif #include "ircaux.h" #include "hook.h" #include "crypt.h" #include "ctcp.h" #include "vars.h" #include "server.h" #include "status.h" #include "lastlog.h" #include "ignore.h" #include "output.h" #include "window.h" #include "dcc.h" #include "names.h" #include "parse.h" #include "whois.h" /**************************** PATCHED by Flier ******************************/ #include "myvars.h" #include "flood.h" #include "screen.h" #include "ircterm.h" #include <sys/time.h> #include <unistd.h> static char tmpaway[mybufsize/2]; /* Patched by Zakath */ #ifdef CELE extern char *CelerityVersion; #endif /* ***************** */ /* patched by acidflash */ #ifdef OPER extern char *AcidVersion; #endif extern NickList *CheckJoiners _((char *, char *, int , ChannelList *)); extern struct friends *CheckUsers _((char *, char *)); extern void UnbanIt _((char *, char *, int)); extern void AwaySave _((char *, int)); extern void CheckCdcc _((char *, char *, char *, int)); extern void ColorUserHost _((char *, char *, char *, int)); extern char *YNreply _((int)); extern void EncryptString _((char *, char *, char *, int, int)); extern void ChannelLogSave _((char *, ChannelList *)); extern int AutoReplyMatch _((char *)); extern void Check4WordKick _((char *, NickList *, int, ChannelList *)); /****************************************************************************/ static char FAR CTCP_Reply_Buffer[BIG_BUFFER_SIZE + 1] = ""; static void do_new_notice_ctcp _((char *, char *, char **, char *)); /* forward declarations for the built in CTCP functions */ #ifndef LITE static char *do_crypto _((CtcpEntry *, char *, char *, char *)); #endif static char *do_version _((CtcpEntry *, char *, char *, char *)); static char *do_clientinfo _((CtcpEntry *, char *, char *, char *)); static char *do_echo _((CtcpEntry *, char *, char *, char *)); static char *do_userinfo _((CtcpEntry *, char *, char *, char *)); static char *do_finger _((CtcpEntry *, char *, char *, char *)); static char *do_time _((CtcpEntry *, char *, char *, char *)); static char *do_atmosphere _((CtcpEntry *, char *, char *, char *)); static char *do_dcc _((CtcpEntry *, char *, char *, char *)); static char *do_utc _((CtcpEntry *, char *, char *, char *)); /**************************** Patched by Flier *****************************/ static char *do_invite _((CtcpEntry *, char *, char *, char *)); static char *do_op _((CtcpEntry *, char *, char *, char *)); static char *do_hop _((CtcpEntry *, char *, char *, char *)); static char *do_unban _((CtcpEntry *, char *, char *, char *)); static char *do_chops _((CtcpEntry *, char *, char *, char *)); static char *do_voice _((CtcpEntry *, char *, char *, char *)); static char *do_whoami _((CtcpEntry *, char *, char *, char *)); static char *do_help _((CtcpEntry *, char *, char *, char *)); char *do_cdcc _((CtcpEntry *, char *, char *, char *)); #ifndef CELE /* Patched by BiGhEaD */ static char *do_open _((CtcpEntry *, char *, char *, char *)); #endif #ifdef CTCPPAGE static char *do_page _((CtcpEntry *, char *, char*, char *)); #endif /**********************/ /****************************************************************************/ static CtcpEntry ctcp_cmd[] = { { "VERSION", "shows client type, version and environment", CTCP_VERBOSE, do_version }, { "CLIENTINFO", "gives information about available CTCP commands", CTCP_VERBOSE, do_clientinfo }, { "USERINFO", "returns user settable information", CTCP_VERBOSE, do_userinfo }, #define CTCP_ERRMSG 3 { "ERRMSG", "returns error messages", CTCP_VERBOSE, do_echo }, { "FINGER", "shows real name, login name and idle time of user", CTCP_VERBOSE, do_finger }, { "TIME", "tells you the time on the user's host", CTCP_VERBOSE, do_time }, { "ACTION", "contains action descriptions for atmosphere", CTCP_SHUTUP, do_atmosphere }, { "DCC", "requests a direct_client_connection", CTCP_SHUTUP | CTCP_NOREPLY, do_dcc }, { "UTC", "substitutes the local timezone", CTCP_SHUTUP | CTCP_NOREPLY, do_utc }, { "PING", "returns the arguments it receives", CTCP_VERBOSE, do_echo }, { "ECHO", "returns the arguments it receives", CTCP_VERBOSE, do_echo }, #ifndef LITE { CAST_STRING, UP("contains CAST-128 strongly encrypted data, CBC mode"), CTCP_SHUTUP | CTCP_NOREPLY, do_crypto }, #if 0 { RIJNDAEL_STRING, UP("contains rijndael (AES) strongly encrypted data, CBC mode"), CTCP_SHUTUP | CTCP_NOREPLY, do_crypto }, #endif { SED_STRING, UP("contains simple weekly encrypted data"), CTCP_SHUTUP | CTCP_NOREPLY, do_crypto }, #endif /**************************** PATCHED by Flier ******************************/ #define CTCP_INVITE { "INVITE", "invites user to a channel", CTCP_SHUTUP , do_invite }, { "OP", "ops user on a channel", CTCP_SHUTUP , do_op }, { "HOP", "halfops user on a channel", CTCP_SHUTUP , do_hop }, { "UNBAN", "unbans user on a channel", CTCP_SHUTUP , do_unban }, { "CHOPS", "lists channel operators", CTCP_SHUTUP , do_chops }, { "VOICE", "voices user on a channel", CTCP_SHUTUP , do_voice }, { "WHOAMI", "gives user info on his access", CTCP_SHUTUP , do_whoami }, { "HELP", "gives user CTCP usage", CTCP_SHUTUP , do_help }, { "VER", "shows client version", CTCP_VERBOSE, do_version }, { "CDCC", "xdcc clone", CTCP_SHUTUP , do_cdcc }, { "XDCC", "xdcc clone", CTCP_SHUTUP , do_cdcc }, #ifndef CELE /* Patched by BiGhEaD */ { "OPEN", "opens channel (-lk)", CTCP_SHUTUP , do_open }, #endif #ifdef CTCPPAGE { "PAGE", "pages user", CTCP_SHUTUP, do_page }, #endif /**********************/ /****************************************************************************/ }; #define NUMBER_OF_CTCPS (sizeof(ctcp_cmd) / sizeof(CtcpEntry)) /* XXX */ char *ctcp_type[] = { "PRIVMSG", "NOTICE" }; static char FAR ctcp_buffer[BIG_BUFFER_SIZE + 1]; /* This is set to one if we parsed an SED */ int sed = 0; /* * in_ctcp_flag is set to true when IRCII is handling a CTCP request. This * is used by the ctcp() sending function to force NOTICEs to be used in any * CTCP REPLY */ int in_ctcp_flag = 0; /* * quote_it: This quotes the given string making it sendable via irc. A * pointer to the length of the data is required and the data need not be * null terminated (it can contain nulls). Returned is a malloced, null * terminated string. */ char * ctcp_quote_it(str, len) char *str; size_t len; { char lbuf[BIG_BUFFER_SIZE + 1]; char *ptr; int i; ptr = lbuf; for (i = 0; i < len; i++) { switch (str[i]) { case CTCP_DELIM_CHAR: *(ptr++) = CTCP_QUOTE_CHAR; *(ptr++) = 'a'; break; case '\n': *(ptr++) = CTCP_QUOTE_CHAR; *(ptr++) = 'n'; break; case '\r': *(ptr++) = CTCP_QUOTE_CHAR; *(ptr++) = 'r'; break; case CTCP_QUOTE_CHAR: *(ptr++) = CTCP_QUOTE_CHAR; *(ptr++) = CTCP_QUOTE_CHAR; break; case '\0': *(ptr++) = CTCP_QUOTE_CHAR; *(ptr++) = '0'; break; case ':': *(ptr++) = CTCP_QUOTE_CHAR; default: *(ptr++) = str[i]; break; } } *ptr = '\0'; str = (char *) 0; malloc_strcpy(&str, lbuf); return (str); } /* * ctcp_unquote_it: This takes a null terminated string that had previously * been quoted using ctcp_quote_it and unquotes it. Returned is a malloced * space pointing to the unquoted string. The len is modified to contain * the size of the data returned. */ char * ctcp_unquote_it(str, len) char *str; size_t *len; { char *lbuf; char *ptr; char c; int i, new_size = 0; lbuf = (char *) new_malloc(sizeof(char) * *len); ptr = lbuf; i = 0; while (i < *len) { if ((c = str[i++]) == CTCP_QUOTE_CHAR) { switch (c = str[i++]) { case CTCP_QUOTE_CHAR: *(ptr++) = CTCP_QUOTE_CHAR; break; case 'a': *(ptr++) = CTCP_DELIM_CHAR; break; case 'n': *(ptr++) = '\n'; break; case 'r': *(ptr++) = '\r'; break; case '0': *(ptr++) = '\0'; break; default: *(ptr++) = c; break; } } else *(ptr++) = c; new_size++; } *len = new_size; return (lbuf); } /************************** PATCHED by Flier **************************/ static int dropit(int allowtwo) { static int ctcpcount=0; ctcpcount++; if (server_list[parsing_server_index].ctcp_last_reply_time+3>time((time_t *) 0)) { if (!allowtwo) return(1); if (!ctcpcount>2) return(1); } if (ctcpcount>2) ctcpcount=1; return(0); } static int request(ctcp,mynick,nick,userhost,channel,privs,required) char *ctcp; char *mynick; char *nick; char *userhost; char *channel; int privs; int required; { int access=privs&required; #ifdef WANTANSI char tmpbuf1[mybufsize/2]; ColorUserHost(userhost,CmdsColors[COLCTCP].color2,tmpbuf1,1); snprintf(tmpaway,sizeof(tmpaway),"%s%s%s request received from %s%s%s %s", CmdsColors[COLCTCP].color4,ctcp,Colors[COLOFF], CmdsColors[COLCTCP].color1,nick,Colors[COLOFF],tmpbuf1); if (channel && *channel) { snprintf(tmpbuf1,sizeof(tmpaway)," to %s%s%s", CmdsColors[COLCTCP].color3,channel,Colors[COLOFF]); strmcat(tmpaway,tmpbuf1,sizeof(tmpaway)); } #else snprintf(tmpaway,sizeof(tmpaway),"%s request received from %s (%s)",ctcp,nick,userhost); if (channel && *channel) { strmcat(tmpaway," to ",sizeof(tmpaway)); strmcat(tmpaway,channel,sizeof(tmpaway)); } #endif if (!(channel && *channel) && access && required && required!=FLALL) { if (!CTCPCloaking) send_to_server("NOTICE %s :Usage /CTCP %s %s [#]channel [password]", nick,mynick,ctcp); strmcat(tmpaway,", wrong usage",sizeof(tmpaway)); return(-1); } else if (required && ((required!=FLALL && access!=required) || (required==FLALL && !access))) { strmcat(tmpaway,", no access",sizeof(tmpaway)); if (!CTCPCloaking) send_to_server("NOTICE %s :You do not have access... -ScrollZ-",nick); return(0); } return(privs); } static void wrongpassword(nick) char *nick; { strmcat(tmpaway,", wrong password",sizeof(tmpaway)); send_to_server("NOTICE %s :Invalid password! -ScrollZ-",nick); if (away_set || LogOn) AwaySave(tmpaway,SAVECTCP); } static void notchanop(nick,channel) char *nick; char *channel; { send_to_server("NOTICE %s :I'm not opped on channel %s -ScrollZ-",nick,channel); } static void disabled(nick) char *nick; { send_to_server("NOTICE %s :This function has been disabled -ScrollZ-",nick); } static int checkpassword(tmpfriend,passwd) struct friends *tmpfriend; char *passwd; { char passbuf[mybufsize/8]; if (tmpfriend->passwd) { if (passwd && *passwd) { EncryptString(passbuf,passwd,passwd,mybufsize/16,0); return((!strcmp(passbuf,tmpfriend->passwd))?0:1); } return(1); } return(0); } /* Invites registered user under CTCP request to specified channel */ static char *do_invite(ctcp,from,to,args) CtcpEntry *ctcp; char *from; char *to; char *args; { int i; char *mynick; char *userhost=FromUserHost; char *channel=(char *) 0; char *passwd=(char *) 0; char tmpbuf1[mybufsize/2]; char tmpchan[mybufsize/2]; ChannelList *chan; struct friends *tmpfriend=NULL; if (to && is_channel(to)) return(NULL); if (dropit(1)) return(NULL); server_list[parsing_server_index].ctcp_last_reply_time=time(NULL); mynick=get_server_nickname(from_server); if (*args) { channel=next_arg(args,&args); passwd=next_arg(args,&args); if (channel && *channel) { if (!is_channel(channel)) snprintf(tmpchan,sizeof(tmpchan),"#%s",channel); else strmcpy(tmpchan,channel,sizeof(tmpchan)); channel=tmpchan; } } snprintf(tmpbuf1,sizeof(tmpbuf1),"%s!%s",from,userhost); if ((tmpfriend=CheckUsers(tmpbuf1,channel))) i=tmpfriend->privs; else i=0; i=request("INVITE",mynick,from,userhost,channel,i,FLINVITE); if (!i || !(i&FLINVITE)) { if (get_int_var(VERBOSE_CTCP_VAR)) say("%s",tmpaway); if (away_set || LogOn) AwaySave(tmpaway,SAVECTCP); return(NULL); } if (checkpassword(tmpfriend,passwd)) { wrongpassword(from); if (get_int_var(VERBOSE_CTCP_VAR)) say("%s",tmpaway); return(NULL); } if (get_int_var(VERBOSE_CTCP_VAR)) say("%s",tmpaway); if (away_set || LogOn) AwaySave(tmpaway,SAVECTCP); if (i==-1) return(NULL); if ((chan=lookup_channel(channel,from_server,0)) && HAS_OPS(chan->status)) { if (!(chan->FriendList)) { disabled(from); return(NULL); } if (!CheckJoiners(from,channel,from_server,chan)) { #ifndef VILAS if (chan->key) snprintf(tmpbuf1,sizeof(tmpbuf1)," (key is %s)",chan->key); else *tmpbuf1='\0'; send_to_server("NOTICE %s :You have been ctcp invited to %s%s -ScrollZ-", from,channel,tmpbuf1); #else if (chan->key) send_to_server("NOTICE %s :The channel %s key is %s", from,channel,chan->key); #endif send_to_server("INVITE %s %s",from,channel); } } else notchanop(from,channel); return(NULL); } /* Ops registered user under CTCP request on specified channel */ static char *do_op(ctcp,from,to,args) CtcpEntry *ctcp; char *from; char *to; char *args; { int i; char *mynick; char *userhost=FromUserHost; char *channel=(char *) 0; char *passwd=(char *) 0; char tmpbuf1[mybufsize/2]; char tmpchan[mybufsize/2]; ChannelList *chan; struct friends *tmpfriend=NULL; if (to && is_channel(to)) return(NULL); if (dropit(1)) return(NULL); server_list[parsing_server_index].ctcp_last_reply_time=time(NULL); mynick=get_server_nickname(from_server); if (*args) { channel=next_arg(args,&args); passwd=next_arg(args,&args); if (channel && *channel) { if (!is_channel(channel)) snprintf(tmpchan,sizeof(tmpchan),"#%s",channel); else strmcpy(tmpchan,channel,sizeof(tmpchan)); channel=tmpchan; } } snprintf(tmpbuf1,sizeof(tmpbuf1),"%s!%s",from,userhost); if ((tmpfriend=CheckUsers(tmpbuf1,channel))) i=tmpfriend->privs; else i=0; i=request("OP",mynick,from,userhost,channel,i,FLOP); if (!i || !(i&FLOP)) { if (get_int_var(VERBOSE_CTCP_VAR)) say("%s",tmpaway); if (away_set || LogOn) AwaySave(tmpaway,SAVECTCP); return(NULL); } if (checkpassword(tmpfriend,passwd)) { wrongpassword(from); if (get_int_var(VERBOSE_CTCP_VAR)) say("%s",tmpaway); return(NULL); } if (get_int_var(VERBOSE_CTCP_VAR)) say("%s",tmpaway); if (away_set || LogOn) AwaySave(tmpaway,SAVECTCP); if (i==-1) return(NULL); if ((chan=lookup_channel(channel,from_server,0)) && (chan->status&CHAN_CHOP)) { if (!(chan->FriendList)) { disabled(from); return(NULL); } send_to_server("MODE %s +o %s",channel,from); #ifndef VILAS send_to_server("NOTICE %s :You have been ctcp opped on %s -ScrollZ-",from, channel); #endif } else notchanop(from,channel); return(NULL); } /* Halfops registered user under CTCP request on specified channel */ static char *do_hop(ctcp,from,to,args) CtcpEntry *ctcp; char *from; char *to; char *args; { int i; char *mynick; char *userhost=FromUserHost; char *channel=(char *) 0; char *passwd=(char *) 0; char tmpbuf1[mybufsize/2]; char tmpchan[mybufsize/2]; ChannelList *chan; struct friends *tmpfriend=NULL; if (to && is_channel(to)) return(NULL); if (dropit(1)) return(NULL); server_list[parsing_server_index].ctcp_last_reply_time=time(NULL); mynick=get_server_nickname(from_server); if (*args) { channel=next_arg(args,&args); passwd=next_arg(args,&args); if (channel && *channel) { if (!is_channel(channel)) snprintf(tmpchan,sizeof(tmpchan),"#%s",channel); else strmcpy(tmpchan,channel,sizeof(tmpchan)); channel=tmpchan; } } snprintf(tmpbuf1,sizeof(tmpbuf1),"%s!%s",from,userhost); if ((tmpfriend=CheckUsers(tmpbuf1,channel))) i=tmpfriend->privs; else i=0; i=request("HOP",mynick,from,userhost,channel,i,FLHOP); if (!i || !(i&FLHOP)) { if (get_int_var(VERBOSE_CTCP_VAR)) say("%s",tmpaway); if (away_set || LogOn) AwaySave(tmpaway,SAVECTCP); return(NULL); } if (checkpassword(tmpfriend,passwd)) { wrongpassword(from); if (get_int_var(VERBOSE_CTCP_VAR)) say("%s",tmpaway); return(NULL); } if (get_int_var(VERBOSE_CTCP_VAR)) say("%s",tmpaway); if (away_set || LogOn) AwaySave(tmpaway,SAVECTCP); if (i==-1) return(NULL); if ((chan=lookup_channel(channel,from_server,0)) && (chan->status&CHAN_CHOP)) { if (!(chan->FriendList)) { disabled(from); return(NULL); } send_to_server("MODE %s +h %s",channel,from); #ifndef VILAS send_to_server("NOTICE %s :You have been ctcp halfopped on %s -ScrollZ-",from, channel); #endif } else notchanop(from,channel); return(NULL); } /* Unbans registered user under CTCP request on specified channel */ static char *do_unban(ctcp,from,to,args) CtcpEntry *ctcp; char *from; char *to; char *args; { int i; char *mynick; char *userhost=FromUserHost; char *channel=(char *) 0; char *passwd=(char *) 0; char tmpbuf1[mybufsize/2]; char tmpchan[mybufsize/2]; ChannelList *chan; struct friends *tmpfriend=NULL; if (to && is_channel(to)) return(NULL); if (dropit(1)) return(NULL); server_list[parsing_server_index].ctcp_last_reply_time=time(NULL); mynick=get_server_nickname(from_server); if (*args) { channel=next_arg(args,&args); passwd=next_arg(args,&args); if (channel && *channel) { if (!is_channel(channel)) snprintf(tmpchan,sizeof(tmpchan),"#%s",channel); else strmcpy(tmpchan,channel,sizeof(tmpchan)); channel=tmpchan; } } snprintf(tmpbuf1,sizeof(tmpbuf1),"%s!%s",from,userhost); if ((tmpfriend=CheckUsers(tmpbuf1,channel))) i=tmpfriend->privs; else i=0; i=request("UNBAN",mynick,from,userhost,channel,i,FLUNBAN); if (!i || !(i&FLUNBAN)) { if (get_int_var(VERBOSE_CTCP_VAR)) say("%s",tmpaway); if (away_set || LogOn) AwaySave(tmpaway,SAVECTCP); return(NULL); } if (checkpassword(tmpfriend,passwd)) { wrongpassword(from); if (get_int_var(VERBOSE_CTCP_VAR)) say("%s",tmpaway); return(NULL); } if (get_int_var(VERBOSE_CTCP_VAR)) say("%s",tmpaway); if (away_set || LogOn) AwaySave(tmpaway,SAVECTCP); if (i==-1) return(NULL); if ((chan=lookup_channel(channel,from_server,0)) && HAS_OPS(chan->status)) { if (!(chan->FriendList)) { disabled(from); return(NULL); } UnbanIt(tmpbuf1,channel,from_server); #ifndef VILAS send_to_server("NOTICE %s :You have been ctcp unbanned on %s -ScrollZ-", from,channel); #endif } else notchanop(from,channel); return(NULL); } /* Tells registered user who are the ops of specified channel */ static char *do_chops(ctcp,from,to,args) CtcpEntry *ctcp; char *from; char *to; char *args; { int i; char *mynick; char *chops=(char *) 0; char *userhost=FromUserHost; char *channel=(char *) 0; char *passwd=(char *) 0; char tmpbuf1[mybufsize/2]; char tmpchan[mybufsize/2]; NickList *tmp; ChannelList *chan; struct friends *tmpfriend=NULL; if (to && is_channel(to)) return(NULL); if (dropit(1)) return(NULL); server_list[parsing_server_index].ctcp_last_reply_time=time(NULL); mynick=get_server_nickname(from_server); if (*args) { channel=next_arg(args,&args); passwd=next_arg(args,&args); if (channel && *channel) { if (!is_channel(channel)) snprintf(tmpchan,sizeof(tmpchan),"#%s",channel); else strmcpy(tmpchan,channel,sizeof(tmpchan)); channel=tmpchan; } } snprintf(tmpbuf1,sizeof(tmpbuf1),"%s!%s",from,userhost); if ((tmpfriend=CheckUsers(tmpbuf1,channel))) i=tmpfriend->privs; else i=0; i=request("CHOPS",mynick,from,userhost,channel,i,FLCHOPS); if (!i || !(i&FLCHOPS)) { if (get_int_var(VERBOSE_CTCP_VAR)) say("%s",tmpaway); if (away_set || LogOn) AwaySave(tmpaway,SAVECTCP); return(NULL); } if (checkpassword(tmpfriend,passwd)) { wrongpassword(from); if (get_int_var(VERBOSE_CTCP_VAR)) say("%s",tmpaway); return(NULL); } if (get_int_var(VERBOSE_CTCP_VAR)) say("%s",tmpaway); if (away_set || LogOn) AwaySave(tmpaway,SAVECTCP); if (i==-1) return(NULL); if ((chan=lookup_channel(channel,from_server,0))) { if (!(chan->FriendList)) { disabled(from); return(NULL); } for (tmp=chan->nicks;tmp;tmp=tmp->next) { if (tmp->chanop) { if (chops) malloc_strcat(&chops," "); malloc_strcat(&chops,tmp->nick); } } if (chops) { send_to_server("NOTICE %s :Ops on %s are : %s -ScrollZ-", from, channel,chops); new_free(&chops); } else send_to_server("NOTICE %s :There are no ops on %s -ScrollZ-", from,channel); } else send_to_server("NOTICE %s :I'm not on channel %s -ScrollZ-",from,channel); return(NULL); } /* Voices registered user under CTCP request to specified channel */ static char *do_voice(ctcp,from,to,args) CtcpEntry *ctcp; char *from; char *to; char *args; { int i; char *mynick; char *userhost=FromUserHost; char *channel=(char *) 0; char *passwd=(char *) 0; char tmpbuf1[mybufsize/2]; char tmpchan[mybufsize/2]; ChannelList *chan; struct friends *tmpfriend=NULL; if (to && is_channel(to)) return(NULL); if (dropit(1)) return(NULL); server_list[parsing_server_index].ctcp_last_reply_time=time(NULL); mynick=get_server_nickname(from_server); if (*args) { channel=next_arg(args,&args); passwd=next_arg(args,&args); if (channel && *channel) { if (!is_channel(channel)) snprintf(tmpchan,sizeof(tmpchan),"#%s",channel); else strmcpy(tmpchan,channel,sizeof(tmpchan)); channel=tmpchan; } } snprintf(tmpbuf1,sizeof(tmpbuf1),"%s!%s",from,userhost); if ((tmpfriend=CheckUsers(tmpbuf1,channel))) i=tmpfriend->privs; else i=0; i=request("VOICE",mynick,from,userhost,channel,i,FLVOICE); if (!i || !(i&FLVOICE)) { if (get_int_var(VERBOSE_CTCP_VAR)) say("%s",tmpaway); if (away_set || LogOn) AwaySave(tmpaway,SAVECTCP); return(NULL); } if (checkpassword(tmpfriend,passwd)) { wrongpassword(from); if (get_int_var(VERBOSE_CTCP_VAR)) say("%s",tmpaway); return(NULL); } if (get_int_var(VERBOSE_CTCP_VAR)) say("%s",tmpaway); if (away_set || LogOn) AwaySave(tmpaway,SAVECTCP); if (i==-1) return(NULL); if ((chan=lookup_channel(channel,from_server,0)) && HAS_OPS(chan->status)) { if (!(chan->FriendList)) { disabled(from); return(NULL); } if (CheckJoiners(from,channel,from_server,chan)) { send_to_server("MODE %s +v %s",channel,from); #ifndef VILAS send_to_server("NOTICE %s :You have been ctcp voiced on %s -ScrollZ-", from,channel); #endif } } else notchanop(from,channel); return(NULL); } /* Tells registered users what privileges does he/she have */ static char *do_whoami(ctcp,from,to,args) CtcpEntry *ctcp; char *from; char *to; char *args; { int i; int found=0; char *mynick; char *userhost=FromUserHost; char tmpbuf1[mybufsize/2]; char tmpbuf2[mybufsize/2]; struct friends *tmpfriend=NULL; if (to && is_channel(to)) return(NULL); if (dropit(1)) return(NULL); server_list[parsing_server_index].ctcp_last_reply_time=time(NULL); mynick=get_server_nickname(from_server); snprintf(tmpbuf2,sizeof(tmpbuf2),"%s!%s",from,userhost); if ((tmpfriend=CheckUsers(tmpbuf2,NULL))) i=tmpfriend->privs; else i=0; i=request("WHOAMI",mynick,from,userhost,(char *) 0,i,FLALL); if (!i) { if (get_int_var(VERBOSE_CTCP_VAR)) say("%s",tmpaway); if (away_set || LogOn) AwaySave(tmpaway,SAVECTCP); return(NULL); } if (get_int_var(VERBOSE_CTCP_VAR)) say("%s",tmpaway); if (away_set || LogOn) AwaySave(tmpaway,SAVECTCP); if (!FriendList) { disabled(from); return(NULL); } for (tmpfriend=frlist;tmpfriend;tmpfriend=tmpfriend->next) { if (wild_match(tmpfriend->userhost,tmpbuf2)) { if (!found) { send_to_server("NOTICE %s :-ScrollZ- Found you in my friends list as:", from); found=1; } send_to_server("NOTICE %s :-ScrollZ- Mask: %s Channel(s): %s",from, tmpfriend->userhost,tmpfriend->channels); i=tmpfriend->privs; strmcpy(tmpbuf1,"CTCP access: ",sizeof(tmpbuf1)); if (i&FLINVITE) strmcat(tmpbuf1,"INVITE ",sizeof(tmpbuf1)); if (i&FLCHOPS) strmcat(tmpbuf1,"CHOPS ",sizeof(tmpbuf1)); if (i&FLOP) strmcat(tmpbuf1,"OP ",sizeof(tmpbuf1)); if (i&FLHOP) strmcat(tmpbuf1,"HOP ",sizeof(tmpbuf1)); if (i&FLUNBAN) strmcat(tmpbuf1,"UNBAN ",sizeof(tmpbuf1)); if (i&FLCDCC) strmcat(tmpbuf1,"CDCC ",sizeof(tmpbuf1)); if (i&FLVOICE) strmcat(tmpbuf1,"VOICE ",sizeof(tmpbuf1)); if ((i&(FLOP|FLINVITE|FLUNBAN))==(FLOP|FLINVITE|FLUNBAN)) strmcat(tmpbuf1,"OPEN",sizeof(tmpbuf1)); snprintf(tmpaway,sizeof(tmpaway),"Auto:%s Prot:%s No flood:%s God:%s", YNreply((i&FLAUTOOP)|(i&FLINSTANT)),YNreply(i&FLPROT), YNreply(i&FLNOFLOOD),YNreply(i&FLGOD)); send_to_server("NOTICE %s :-ScrollZ- %s",from,tmpbuf1); send_to_server("NOTICE %s :-ScrollZ- %s",from,tmpaway); if (i&FLJOIN) send_to_server("NOTICE %s :-ScrollZ- I will auto-join above channel(s) when invited by you.",from); } } return(NULL); } /* Tells registered user usage of the CTCPs */ static char *do_help(ctcp,from,to,args) CtcpEntry *ctcp; char *from; char *to; char *args; { int i; char *mynick; char *userhost=FromUserHost; char tmpbuf1[mybufsize/2]; struct friends *tmpfriend; if (to && is_channel(to)) return(NULL); if (dropit(1)) return(NULL); server_list[parsing_server_index].ctcp_last_reply_time=time(NULL); mynick=get_server_nickname(from_server); snprintf(tmpbuf1,sizeof(tmpbuf1),"%s!%s",from,userhost); if ((tmpfriend=CheckUsers(tmpbuf1,NULL))) i=tmpfriend->privs; else i=0; i=request("HELP",mynick,from,userhost,(char *) 0,i,FLALL); if (!i) { if (get_int_var(VERBOSE_CTCP_VAR)) say("%s",tmpaway); if (away_set || LogOn) AwaySave(tmpaway,SAVECTCP); return(NULL); } if (get_int_var(VERBOSE_CTCP_VAR)) say("%s",tmpaway); if (away_set || LogOn) AwaySave(tmpaway,SAVECTCP); if (!FriendList) { disabled(from); return(NULL); } send_to_server("NOTICE %s :Usage /CTCP %s <command> [channel] [password] where command is :",from,mynick); *tmpbuf1='\0'; if (i&FLINVITE) strmcat(tmpbuf1,"INVITE ",sizeof(tmpbuf1)); if (i&FLCHOPS) strmcat(tmpbuf1,"CHOPS ",sizeof(tmpbuf1)); if (i&FLOP) strmcat(tmpbuf1,"OP ",sizeof(tmpbuf1)); if (i&FLHOP) strmcat(tmpbuf1,"HOP ",sizeof(tmpbuf1)); if (i&FLUNBAN) strmcat(tmpbuf1,"UNBAN ",sizeof(tmpbuf1)); if ((i&FLOP) && (i&FLINVITE) && (i&FLUNBAN)) strmcat(tmpbuf1,"OPEN ",sizeof(tmpbuf1)); if (i&FLCDCC) strmcat(tmpbuf1,"CDCC ",sizeof(tmpbuf1)); if (i&FLVOICE) strmcat(tmpbuf1,"VOICE ",sizeof(tmpbuf1)); strmcat(tmpbuf1,"WHOAMI HELP",sizeof(tmpbuf1)); send_to_server("NOTICE %s : %s",from,tmpbuf1); return(NULL); } #ifndef CELE /* Patched by BiGhEaD */ /* Open channel (-lk) under CTCP request on specified channel (for OP users) */ static char *do_open(ctcp,from,to,args) CtcpEntry *ctcp; char *from; char *to; char *args; { int i; char *mynick; char *userhost=FromUserHost; char *channel=(char *) 0; char *passwd=(char *) 0; char tmpbuf1[mybufsize/2]; char tmpchan[mybufsize/2]; ChannelList *chan; struct friends *tmpfriend=NULL; if (to && is_channel(to)) return(NULL); if (dropit(1)) return(NULL); server_list[parsing_server_index].ctcp_last_reply_time=time(NULL); mynick=get_server_nickname(from_server); if (*args) { channel=next_arg(args,&args); passwd=next_arg(args,&args); if (channel && *channel) { if (!is_channel(channel)) snprintf(tmpchan,sizeof(tmpchan),"#%s",channel); else strmcpy(tmpchan,channel,sizeof(tmpchan)); channel=tmpchan; } } snprintf(tmpbuf1,sizeof(tmpbuf1),"%s!%s",from,userhost); if ((tmpfriend=CheckUsers(tmpbuf1,channel))) i=tmpfriend->privs; else i=0; i=request("OPEN",mynick,from,userhost,channel,i,FLOP|FLINVITE|FLUNBAN); if (!i || !(i&(FLOP|FLINVITE|FLUNBAN))) { if (get_int_var(VERBOSE_CTCP_VAR)) say("%s",tmpaway); if (away_set || LogOn) AwaySave(tmpaway,SAVECTCP); return(NULL); } if (checkpassword(tmpfriend,passwd)) { wrongpassword(from); if (get_int_var(VERBOSE_CTCP_VAR)) say("%s",tmpaway); return(NULL); } if (get_int_var(VERBOSE_CTCP_VAR)) say("%s",tmpaway); if (away_set || LogOn) AwaySave(tmpaway,SAVECTCP); if (i==-1) return(NULL); if ((chan=lookup_channel(channel,from_server,0)) && HAS_OPS(chan->status)) { if (!(chan->FriendList)) { disabled(from); return(NULL); } *tmpbuf1='\0'; if ((chan->mode)&MODE_LIMIT) strmcat(tmpbuf1,"l",sizeof(tmpbuf1)); if ((chan->mode)&MODE_KEY && chan->key) { strmcat(tmpbuf1,"k ",sizeof(tmpbuf1)); strmcat(tmpbuf1,chan->key,sizeof(tmpbuf1)); } if (*tmpbuf1) { send_to_server("MODE %s -%s",channel,tmpbuf1); #ifdef ACID send_to_server("INVITE %s %s",from,channel); #endif } #ifndef VILAS send_to_server("NOTICE %s :Channel %s has been ctcp opened -ScrollZ-",from,channel); #endif } else notchanop(from,channel); return(NULL); } #endif /* CELE */ #ifdef CTCPPAGE /* PAGE (BEEP) user from a friend */ static char *do_page(ctcp,from,to,args) CtcpEntry *ctcp; char *from; char *to; char *args; { int i; char *mynick; char *userhost=FromUserHost; char tmpbuf1[mybufsize/2]; struct friends *tmpfriend; if (to && is_channel(to)) return(NULL); if (dropit(1)) return(NULL); server_list[parsing_server_index].ctcp_last_reply_time=time(NULL); mynick=get_server_nickname(from_server); snprintf(tmpbuf1,sizeof(tmpbuf1),"%s!%s",from,userhost); if ((tmpfriend=CheckUsers(tmpbuf1,NULL))) i=tmpfriend->privs; else i=0; i=request("PAGE",mynick,from,userhost,(char *) 0,i,FLALL); if (!i) { if (get_int_var(VERBOSE_CTCP_VAR)) say("%s",tmpaway); if (away_set || LogOn) AwaySave(tmpaway,SAVECTCP); return(NULL); } if (get_int_var(VERBOSE_CTCP_VAR)) say("%s",tmpaway); if (away_set || LogOn) AwaySave(tmpaway,SAVECTCP); if (!FriendList) { disabled(from); return(NULL); } term_beep(); send_to_server("NOTICE %s :Ok, %s has been paged, wait for a reply. -ScrollZ-",from,mynick); return(NULL); } #endif /*******************************************/ /* Handles Cdcc requests */ char *do_cdcc(ctcp,from,to,args) CtcpEntry *ctcp; char *from; char *to; char *args; { int i; int flag; char *mynick; char *userhost=FromUserHost; char tmpbuf1[mybufsize/2]; char tmpbuf2[mybufsize/2]; struct friends *tmpfriend; if (dropit(0)) return(NULL); server_list[parsing_server_index].ctcp_last_reply_time=time(NULL); mynick=get_server_nickname(from_server); #ifdef WANTANSI if (args && *args) snprintf(tmpbuf1,sizeof(tmpbuf1)," %s%s%s",CmdsColors[COLCDCC].color3,args,Colors[COLOFF]); else *tmpbuf1='\0'; ColorUserHost(userhost,CmdsColors[COLCTCP].color2,tmpbuf2,1); snprintf(tmpaway,sizeof(tmpaway),"%sCdcc%s%s request received from %s%s%s %s", CmdsColors[COLCDCC].color4,Colors[COLOFF],tmpbuf1, CmdsColors[COLCDCC].color1,from,Colors[COLOFF],tmpbuf2); if (to && is_channel(to)) { snprintf(tmpbuf1,sizeof(tmpbuf1)," to %s%s%s",CmdsColors[COLCDCC].color6,to,Colors[COLOFF]); strmcat(tmpaway,tmpbuf1,sizeof(tmpaway)); } #else if (args && *args) snprintf(tmpbuf1,sizeof(tmpbuf1)," %s",args); else *tmpbuf1='\0'; snprintf(tmpaway,sizeof(tmpaway),"Cdcc%s request received from %s (%s)",tmpbuf1,from,userhost); if (to && is_channel(to)) { snprintf(tmpbuf1,sizeof(tmpbuf1)," to %s",to); strmcat(tmpaway,tmpbuf1,sizeof(tmpaway)); } #endif snprintf(tmpbuf2,sizeof(tmpbuf2),"%s!%s",from,userhost); if ((tmpfriend=CheckUsers(tmpbuf2,NULL))) i=tmpfriend->privs; else i=0; if (Security) if (!i || !(i&FLCDCC)) { strmcat(tmpaway,", no access",sizeof(tmpaway)); if (get_int_var(VERBOSE_CTCP_VAR)) say("%s",tmpaway); if (!i && !CTCPCloaking) send_to_server("NOTICE %s :You do not have access... -ScrollZ-",from); if (away_set || LogOn) AwaySave(tmpaway,SAVECTCP); return(NULL); } if (!(*args)) { strmcat(tmpaway,", wrong usage",sizeof(tmpaway)); if (get_int_var(VERBOSE_CTCP_VAR)) say("%s",tmpaway); if (!CTCPCloaking) send_to_server("NOTICE %s :Try /CTCP %s CDCC HELP",from,mynick); if (away_set || LogOn) AwaySave(tmpaway,SAVECTCP); return(NULL); } strmcpy(tmpbuf1,args,sizeof(tmpbuf1)); flag=in_ctcp_flag; in_ctcp_flag=0; CheckCdcc(from,tmpbuf1,to,0); in_ctcp_flag=flag; return(NULL); } /***********************************************************************/ /* * do_crypto: performs the ecrypted data trasfer for ctcp. Returns in a * malloc string the decryped message (if a key is set for that user) or the * text "[ENCRYPTED MESSAGE]" */ #ifndef LITE static char * do_crypto(ctcp, from, to, args) CtcpEntry *ctcp; char *from, *to, *args; { crypt_key *key; char *crypt_who, *msg; char *ret = NULL; if (is_channel(to)) crypt_who = to; else crypt_who = from; if ((key = is_crypted(crypt_who)) && (msg = crypt_msg(args, key, 0))) { /* this doesn't work ... ... when it does, set this to 0 ... */ static int the_youth_of_america_on_elle_esse_dee = 1; malloc_strcpy(&ret, msg); /* * since we are decrypting, run it through do_ctcp() again * to detect embeded CTCP messages, in an encrypted message. * we avoid recusing here more than once. */ if (the_youth_of_america_on_elle_esse_dee++ == 0) ret = do_ctcp(from, to, ret); the_youth_of_america_on_elle_esse_dee--; sed = 1; } else malloc_strcpy(&ret, "[ENCRYPTED MESSAGE]"); return (ret); } #endif /* * do_clientinfo: performs the CLIENTINFO CTCP. If cmd is empty, returns the * list of all CTCPs currently recognized by IRCII. If an arg is supplied, * it returns specific information on that CTCP. If a matching CTCP is not * found, an ERRMSG ctcp is returned */ static char * do_clientinfo(ctcp, from, to, cmd) CtcpEntry *ctcp; char *from, *to, *cmd; { int i; char *ucmd = (char *) 0; u_char buffer[BIG_BUFFER_SIZE+1]; /**************************** PATCHED by Flier ******************************/ if (CTCPCloaking==1) { /****************************************************************************/ if (cmd && *cmd) { malloc_strcpy(&ucmd, cmd); upper(ucmd); for (i = 0; i < NUMBER_OF_CTCPS; i++) { /**************************** PATCHED by Flier ******************************/ /* stop at invite */ if (!strcmp(ctcp_cmd[i].name,"INVITE")) break; /****************************************************************************/ if (strcmp(ucmd, ctcp_cmd[i].name) == 0) { send_ctcp_reply(from, ctcp->name, "%s %s", ctcp_cmd[i].name, ctcp_cmd[i].desc); return NULL; } } send_ctcp_reply(from, ctcp_cmd[CTCP_ERRMSG].name, "%s: %s is not a valid function", ctcp->name, cmd); } else { *buffer = '\0'; for (i = 0; i < NUMBER_OF_CTCPS; i++) { /**************************** PATCHED by Flier ******************************/ /* stop at invite */ if (!strcmp(ctcp_cmd[i].name,"INVITE")) break; /****************************************************************************/ strmcat(buffer, ctcp_cmd[i].name, BIG_BUFFER_SIZE); strmcat(buffer, " ", BIG_BUFFER_SIZE); } send_ctcp_reply(from, ctcp->name, "%s :Use CLIENTINFO <COMMAND> to get more specific information", buffer); } /**************************** PATCHED by Flier ******************************/ } else if (!CTCPCloaking) send_ctcp_reply(from, ctcp->name, "No client here! -ScrollZ-"); /****************************************************************************/ return NULL; } /* do_version: does the CTCP VERSION command */ static char * do_version(ctcp, from, to, cmd) CtcpEntry *ctcp; char *from, *to, *cmd; { /**************************** PATCHED by Flier ******************************/ char tmpbuf1[mybufsize/4]; char tmpbuf2[mybufsize/4]; if (CTCPCloaking==1) { /****************************************************************************/ #if defined(PARANOID) send_ctcp_reply(from, ctcp->name, "ircII user"); #else char *tmp; #if defined(HAVE_UNAME) struct utsname un; char *the_unix, *the_version; if (uname(&un) < 0) { the_version = empty_string; the_unix = "unknown"; } else { the_version = un.release; the_unix = un.sysname; } send_ctcp_reply(from, ctcp->name, "ircII %s %s %s :%s", irc_version, the_unix, the_version, #else #ifdef _Windows send_ctcp_reply(from, ctcp->name, "ircII %s MS-Windows :%s", irc_version, #else send_ctcp_reply(from, ctcp->name, "ircII %s *IX :%s", irc_version, #endif /* _Windows */ #endif /* HAVE_UNAME */ (tmp = get_string_var(CLIENTINFO_VAR)) ? tmp : IRCII_COMMENT); #endif /* PARANOID */ /**************************** PATCHED by Flier ******************************/ } else if (!CTCPCloaking) { strmcpy(tmpbuf1,ScrollZver,sizeof(tmpbuf1)); #ifdef CELE if (get_string_var(CLIENTINFO_VAR)) snprintf(tmpbuf2,sizeof(tmpbuf2),"%s+%s - %s",tmpbuf1,CelerityVersion, get_string_var(CLIENTINFO_VAR)); else snprintf(tmpbuf2,sizeof(tmpbuf2),"%s+%s",tmpbuf1,CelerityVersion); #else /* CELE */ #ifdef OPER if (get_string_var(CLIENTINFO_VAR)) snprintf(tmpbuf2,sizeof(tmpbuf2),"%s+%s - %s",tmpbuf1,AcidVersion, get_string_var(CLIENTINFO_VAR)); else snprintf(tmpbuf2,sizeof(tmpbuf2),"%s+%s",tmpbuf1,AcidVersion); #else /* OPER */ if (get_string_var(CLIENTINFO_VAR)) snprintf(tmpbuf2,sizeof(tmpbuf2),"%s - %s",tmpbuf1,get_string_var(CLIENTINFO_VAR)); else strmcpy(tmpbuf2,tmpbuf1,sizeof(tmpbuf2)); #endif /* OPER */ #endif /* CELE */ send_ctcp_reply(from, ctcp->name, "%s", tmpbuf2); } /****************************************************************************/ return NULL; } /* do_time: does the CTCP TIME command --- done by Veggen */ static char * do_time(ctcp, from, to, cmd) CtcpEntry *ctcp; char *from, *to, *cmd; { time_t tm = time((time_t *) 0); char *s, *t = ctime(&tm); if ((char *) 0 != (s = index(t, '\n'))) *s = '\0'; /************************ PATCHED by Flier ***************************/ /*send_ctcp_reply(from, ctcp->name, "%s", t);*/ if (CTCPCloaking!=2) send_ctcp_reply(from, ctcp->name, "%s", t); /*********************************************************************/ return NULL; } /* do_userinfo: does the CTCP USERINFO command */ static char * do_userinfo(ctcp, from, to, cmd) CtcpEntry *ctcp; char *from, *to, *cmd; { /**************************** PATCHED by Flier ******************************/ /*send_ctcp_reply(from, ctcp->name, "%s", get_string_var(USER_INFO_VAR));*/ if (CTCPCloaking==1) send_ctcp_reply(from, ctcp->name, "%s", get_string_var(USER_INFO_VAR)); else if (!CTCPCloaking) send_ctcp_reply(from,ctcp->name,"%s",DefaultUserinfo); /****************************************************************************/ return NULL; } /* * do_echo: does the CTCP ECHO, CTCP ERRMSG and CTCP PING commands. Does * not send an error for ERRMSG and if the CTCP was sent to a channel. */ static char * do_echo(ctcp, from, to, cmd) CtcpEntry *ctcp; char *from, *to, *cmd; { /**************************** PATCHED by Flier ******************************/ if (CTCPCloaking!=2) /****************************************************************************/ if (!is_channel(to) || strncmp(cmd, "ERRMSG", 6)) send_ctcp_reply(from, ctcp->name, "%s", cmd); return NULL; } static char * do_finger(ctcp, from, to, cmd) CtcpEntry *ctcp; char *from, *to, *cmd; { /**************************** PATCHED by Flier ******************************/ if (CTCPCloaking==1) { /****************************************************************************/ #if defined(PARANOID) send_ctcp_reply(from, ctcp->name, "ircII user"); #else struct passwd *pwd; time_t diff; unsigned uid; char c; /* * sojge complained that ircII says 'idle 1 seconds' * well, now he won't ever get the chance to see that message again * *grin* ;-) -lynx * * Made this better by saying 'idle 1 second' -phone */ diff = time(0) - idle_time; c = (diff == 1) ? ' ' : 's'; /* XXX - fix me */ # ifdef _Windows send_ctcp_reply(from, ctcp->name, "IRCII For MS-Windows User Idle %d second%c", (int)diff, c); # else uid = getuid(); # ifdef DAEMON_UID if (uid != DAEMON_UID) { # endif /* DAEMON_UID */ if ((pwd = getpwuid(uid)) != NULL) { char *tmp; # ifndef GECOS_DELIMITER # define GECOS_DELIMITER ',' # endif /* GECOS_DELIMITER */ if ((tmp = index(pwd->pw_gecos, GECOS_DELIMITER)) != NULL) *tmp = '\0'; send_ctcp_reply(from, ctcp->name, "%s (%s@%s) Idle %d second%c", pwd->pw_gecos, pwd->pw_name, hostname, (int)diff, c); } # ifdef DAEMON_UID } else send_ctcp_reply(from, ctcp->name, "IRCII Telnet User (%s) Idle %d second%c", realname, (int)diff, c); # endif /* DAEMON_UID */ # endif /* _Windows */ #endif /* PARANOID */ /**************************** PATCHED by Flier ******************************/ } else if (!CTCPCloaking) send_ctcp_reply(from, ctcp->name,"%s",DefaultFinger); /****************************************************************************/ return NULL; } /* * do_atmosphere: does the CTCP ACTION command --- done by lynX * Changed this to make the default look less offensive to people * who don't like it and added a /on ACTION. This is more in keeping * with the design philosophy behind IRCII */ static char * do_atmosphere(ctcp, from, to, cmd) CtcpEntry *ctcp; char *from, *to, *cmd; { /**************************** PATCHED by Flier ******************************/ int foundar = 0; int isshit; int isfriend; char *thing; #ifdef WANTANSI char *color = CmdsColors[COLME].color3; #else char *color = ""; #endif char tmpbuf1[mybufsize / 2]; void (*func)(); ChannelList *chan; NickList *joiner; Window *oldwin; #ifdef HAVE_ICONV_H if (get_int_var(HIGH_ASCII_VAR)) thing = "\342\210\236"; #else if (get_int_var(HIGH_ASCII_VAR)) thing = "ì"; #endif /* HAVE_ICONV_H */ else thing = "*"; if (Stamp == 2) func = (void(*)()) say; else func = (void(*)()) put_it; /****************************************************************************/ if (cmd && *cmd) { int old; /**************************** Patched by Flier ******************************/ if (AutoReplyBuffer) { char tmpbuf[2 * mybufsize]; strmcpy(tmpbuf, cmd, sizeof(tmpbuf)); foundar = AutoReplyMatch(tmpbuf); #ifdef WANTANSI if (foundar) color = CmdsColors[COLME].color6; #else if (foundar) color = ""; #endif } /****************************************************************************/ save_message_from(); old = set_lastlog_msg_level(LOG_ACTION); if (is_channel(to)) { message_from(to, LOG_ACTION); if (do_hook(ACTION_LIST, "%s %s %s", from, to, cmd)) { /**************************** PATCHED by Flier ******************************/ /*if (is_current_channel(to, parsing_server_index, 0)) put_it("* %s %s", from, cmd); else put_it("* %s:%s %s", from, to, cmd);*/ if (is_current_channel(to, parsing_server_index, 0)) #ifdef WANTANSI func("%s%s%s %s%s%s %s%s%s", CmdsColors[COLME].color1, thing, Colors[COLOFF], color, from, Colors[COLOFF], CmdsColors[COLME].color5, cmd, Colors[COLOFF]); #else func("%s %s%s%s %s", thing, color, from, color, cmd); #endif else { #ifdef WANTANSI snprintf(tmpbuf1,sizeof(tmpbuf1),"<%s%s%s> %s%s%s %s%s%s", CmdsColors[COLME].color4, to, Colors[COLOFF], CmdsColors[COLME].color1, thing, Colors[COLOFF], color, from, Colors[COLOFF]); func("%s %s%s%s",tmpbuf1, CmdsColors[COLME].color5,cmd, Colors[COLOFF]); #else func("<%s> %s %s%s%s %s", to, thing, color, from, color, cmd); #endif } /****************************************************************************/ } /**************************** Patched by Flier ******************************/ /* by braneded */ chan = lookup_channel(to, parsing_server_index, 0); if (chan) { joiner = CheckJoiners(from, to, parsing_server_index, chan); if (joiner) { isshit = joiner->shitlist ? joiner->shitlist->shit : 0; isfriend = (!isshit && joiner->frlist) ? joiner->frlist->privs : 0; Check4WordKick(cmd, joiner, isfriend, chan); if (ChanLog) { char tmpbuf2[mybufsize]; if (chan->ChanLog) { snprintf(tmpbuf2, sizeof(tmpbuf2), "* %s %s", from, cmd); ChannelLogSave(tmpbuf2, chan); } } } } if (foundar && (ARinWindow == 3 || (ARinWindow && chan->window != curr_scr_win))) { #ifdef WANTANSI snprintf(tmpbuf1, sizeof(tmpbuf1), "<%s%s%s> %s%s%s %s%s%s", CmdsColors[COLME].color4, to, Colors[COLOFF], CmdsColors[COLME].color1, thing, Colors[COLOFF], color, from, Colors[COLOFF]); #else sprintf(tmpbuf1, "<%s> %s %s%s%s %s", to, thing, color, from, color, cmd); #endif oldwin = to_window; if (ARinWindow == 1) /* ON */ to_window = curr_scr_win; else { /* USER/BOTH */ to_window = get_window_by_level(LOG_USER4); if (to_window == NULL) to_window = curr_scr_win; } #ifdef WANTANSI func("%s %s%s%s", tmpbuf1, CmdsColors[COLME].color5, cmd, Colors[COLOFF]); #else func("%s", tmpbuf1); #endif to_window = oldwin; } /****************************************************************************/ } else { if ('=' == *from) { set_lastlog_msg_level(LOG_DCC); message_from(from+1, LOG_DCC); } else message_from(from, LOG_ACTION); if (do_hook(ACTION_LIST, "%s %s %s", from, to, cmd)) /**************************** PATCHED by Flier ******************************/ /*put_it("*> %s %s", from, cmd);*/ #ifdef WANTANSI func("%s%s%s> %s%s%s %s%s%s", CmdsColors[COLME].color1, thing, Colors[COLOFF], color, from, Colors[COLOFF], CmdsColors[COLME].color5, cmd, Colors[COLOFF]); #else func("%s> %s%s%s %s", thing, color, from, color, cmd); #endif /****************************************************************************/ } set_lastlog_msg_level(old); restore_message_from(); } return NULL; } /* * do_dcc: Records data on an incoming DCC offer. Makes sure it's a * user->user CTCP, as channel DCCs don't make any sense whatsoever */ static char * do_dcc(ctcp, from, to, args) CtcpEntry *ctcp; char *from, *to, *args; { char *type; char *description; char *inetaddr; char *port; char *size; if (my_stricmp(to, get_server_nickname(parsing_server_index))) return NULL; if (!(type = next_arg(args, &args)) || /**************************** PATCHED by Flier ******************************/ /*!(description = next_arg(args, &args)) ||*/ /* support filenames enclosed in quotes */ !(description = new_next_arg(args, &args)) || /****************************************************************************/ !(inetaddr = next_arg(args, &args)) || !(port = next_arg(args, &args))) return NULL; size = next_arg(args, &args); register_dcc_offer(from, type, description, inetaddr, port, size); return NULL; } static char * do_utc(ctcp, from, to, args) CtcpEntry *ctcp; char *from, *to, *args; { time_t tm; char *date = NULL; if (!args || !*args) return NULL; tm = atol(args); malloc_strcpy(&date, ctime(&tm)); date[strlen(date)-1] = '\0'; return date; } /* * do_ctcp: handles the client to client protocol embedded in PRIVMSGs. Any * such messages are removed from the original str, so after do_ctcp() * returns, str will be changed */ char * do_ctcp(from, to, str) char *from, *to, *str; { int i = 0, ctcp_flag = 1; char *end, *cmd, *args, *ptr; char *arg_copy = NULL; int flag; int messages = 0; time_t curtime = time(NULL); /************************ PATCHED by Flier ***************************/ char *mynick=get_server_nickname(from_server); #if defined(WANTANSI) char tmpbuf1[mybufsize/2]; #endif /*********************************************************************/ flag = double_ignore(from, FromUserHost, IGNORE_CTCPS); if (!in_ctcp_flag) in_ctcp_flag = 1; *ctcp_buffer = '\0'; while ((cmd = index(str, CTCP_DELIM_CHAR)) != NULL) { if (messages > 3) break; *(cmd++) = '\0'; /**************************** Patched by Flier ******************************/ /*strcat(ctcp_buffer, str);*/ strmcat(ctcp_buffer, str, sizeof(ctcp_buffer)); /****************************************************************************/ if ((end = index(cmd, CTCP_DELIM_CHAR)) != NULL) { messages++; if (flag == IGNORED) continue; *(end++) = '\0'; if ((args = index(cmd, ' ')) != NULL) *(args++) = '\0'; else args = empty_string; /* Skip leading : for arguments */ if (*args == ':') ++args; malloc_strcpy(&arg_copy, args); /**************************** PATCHED by Flier ******************************/ /* if it came via DCC CHAT only allow ACTION to be processed */ if (*from!='=' || (*from=='=' && !strcmp(cmd,"ACTION"))) /****************************************************************************/ for (i = 0; i < NUMBER_OF_CTCPS; i++) { if (strcmp(cmd, ctcp_cmd[i].name) == 0) { /* protect against global (oper) messages */ if (*to != '$' && !(*to == '#' && !lookup_channel(to, parsing_server_index, CHAN_NOUNLINK))) { ptr = ctcp_cmd[i].func(&ctcp_cmd[i], from, to, arg_copy); if (ptr) { /**************************** Patched by Flier ******************************/ /*strcat(ctcp_buffer, ptr);*/ strmcat(ctcp_buffer, ptr, sizeof(ctcp_buffer)); /****************************************************************************/ new_free(&ptr); } } ctcp_flag = ctcp_cmd[i].flag; cmd = ctcp_cmd[i].name; break; } } new_free(&arg_copy); /**************************** PATCHED by Flier ******************************/ if (!check_flooding(from,CTCP_FLOOD,args)) continue; /* if it came via DCC CHAT only allow ACTION to be processed */ if (*from=='=' && strcmp(cmd,"ACTION")) continue; /****************************************************************************/ if (in_ctcp_flag == 1 && do_hook(CTCP_LIST, "%s %s %s %s", from, to, cmd, args) && get_int_var(VERBOSE_CTCP_VAR)) { int lastlog_level; save_message_from(); lastlog_level = set_lastlog_msg_level(LOG_CTCP); message_from((char *) 0, LOG_CTCP); /**************************** PATCHED by Flier ******************************/ /*if (i == NUMBER_OF_CTCPS) { if (beep_on_level & LOG_CTCP) beep_em(1); say("Unknown CTCP %s from %s to %s: %s%s", cmd, from, to, *args ? ": " : empty_string, args); } else if (ctcp_flag & CTCP_VERBOSE) { if (my_stricmp(to, get_server_nickname(parsing_server_index))) say("CTCP %s from %s to %s: %s", cmd, from, to, args); else say("CTCP %s from %s%s%s", cmd, from, *args ? ": " : empty_string, args); }*/ #ifdef WANTANSI ColorUserHost(FromUserHost,CmdsColors[COLCTCP].color2, tmpaway,1); #endif if (i == NUMBER_OF_CTCPS && get_int_var(VERBOSE_CTCP_VAR)) { if (beep_on_level & LOG_CTCP) beep_em(1); #ifdef WANTANSI snprintf(tmpbuf1,sizeof(tmpbuf1),"%sUnknown CTCP %s%s from %s%s%s", CmdsColors[COLCTCP].color4,cmd,Colors[COLOFF], CmdsColors[COLCTCP].color1,from,Colors[COLOFF]); if (to && my_stricmp(to,mynick)) say("%s %s to %s%s%s",tmpbuf1,tmpaway, CmdsColors[COLCTCP].color3,to,Colors[COLOFF]); else say("%s %s",tmpbuf1,tmpaway); #else say("Unknown CTCP %s from %s (%s)%s%s", cmd,from,FromUserHost, (to && my_stricmp(to,mynick))?" to ":"", (to && my_stricmp(to,mynick))?to:""); #endif } else if (ctcp_flag & CTCP_VERBOSE && get_int_var(VERBOSE_CTCP_VAR)) { if (beep_on_level & LOG_CTCP) beep_em(1); #ifdef WANTANSI snprintf(tmpbuf1,sizeof(tmpbuf1),"%sCTCP %s%s from %s%s%s", CmdsColors[COLCTCP].color4,cmd,Colors[COLOFF], CmdsColors[COLCTCP].color1,from,Colors[COLOFF]); if (to && my_stricmp(to,mynick)) say("%s %s to %s%s%s",tmpbuf1,tmpaway, CmdsColors[COLCTCP].color3,to,Colors[COLOFF]); else say("%s %s",tmpbuf1,tmpaway); #else say("CTCP %s from %s (%s)%s%s", cmd,from,FromUserHost, (to && my_stricmp(to,mynick))?" to ":"", (to && my_stricmp(to,mynick))?to:""); #endif } /****************************************************************************/ set_lastlog_msg_level(lastlog_level); restore_message_from(); } str = end; } else { /**************************** Patched by Flier ******************************/ /*strcat(ctcp_buffer, CTCP_DELIM_STR);*/ strmcat(ctcp_buffer, CTCP_DELIM_STR, sizeof(ctcp_buffer)); /****************************************************************************/ str = cmd; } } if (in_ctcp_flag == 1) in_ctcp_flag = 0; if (CTCP_Reply_Buffer && *CTCP_Reply_Buffer) { #ifdef PARANOID /* * paranoid users don't want to send ctcp replies to * requests send to channels, probably... */ if (is_channel(to)) goto clear_ctcp_reply_buffer; #endif /* * Newave ctcp flood protection : each time you are requested to send * more than CTCP_REPLY_FLOOD_SIZE bytes in CTCP_REPLY_BACKLOG_SECONDS * no ctcp replies will be done for CTCP_REPLY_IGNORE_SECONDS. * Current default is 256 bytes/ 5s/ 10s * This is a sliding window, i.e. you can't get caught sending too much * because of a 5s boundary, and the checking is still active even if * you don't reply anymore. */ if (*from == '=') send_ctcp(ctcp_type[CTCP_NOTICE], from, NULL, "%s", CTCP_Reply_Buffer); else { Server *cur_serv = &server_list[parsing_server_index]; int no_reply, no_flood = get_int_var(NO_CTCP_FLOOD_VAR), delta = cur_serv->ctcp_last_reply_time ? curtime-cur_serv->ctcp_last_reply_time : 0, size = 0, was_ignoring = cur_serv->ctcp_flood_time != 0, crbs = get_int_var(CTCP_REPLY_BACKLOG_SECONDS_VAR), crfs = get_int_var(CTCP_REPLY_FLOOD_SIZE_VAR), cris = get_int_var(CTCP_REPLY_IGNORE_SECONDS_VAR); cur_serv->ctcp_last_reply_time = curtime; if (delta) { for (i = crbs - 1; i >= delta; i--) cur_serv->ctcp_send_size[i] = cur_serv->ctcp_send_size[i - delta]; for (i = 0; i < delta && i < crbs; i++) cur_serv->ctcp_send_size[i] = 0; } cur_serv->ctcp_send_size[0] += strlen(CTCP_Reply_Buffer); for (i = 0; i < crbs; i++) size += cur_serv->ctcp_send_size[i]; if (size >= crfs) cur_serv->ctcp_flood_time = curtime; no_reply = cur_serv->ctcp_flood_time && (curtime <= cur_serv->ctcp_flood_time+cris); if (no_flood && get_int_var(VERBOSE_CTCP_VAR)) { save_message_from(); message_from((char *) 0, LOG_CTCP); if (no_reply && was_ignoring == 0) say("CTCP flood detected - suspending replies"); else if (no_reply == 0 && was_ignoring) say("CTCP reply suspending time elapsed - replying normally"); restore_message_from(); } if (no_flood == 0 || no_reply == 0) { cur_serv->ctcp_flood_time = 0; send_ctcp(ctcp_type[CTCP_NOTICE], from, NULL, "%s", CTCP_Reply_Buffer); } } #ifdef PARANOID clear_ctcp_reply_buffer: #endif *CTCP_Reply_Buffer = '\0'; } if (*str) /**************************** Patched by Flier ******************************/ /*strcat(ctcp_buffer, str);*/ strmcat(ctcp_buffer, str, sizeof(ctcp_buffer)); /****************************************************************************/ return (ctcp_buffer); } char * do_notice_ctcp(from, to, str) char *from, *to, *str; { char *cmd; in_ctcp_flag = -1; *ctcp_buffer = '\0'; /* * The following used to say "While". It now says "if" because people * Started using CTCP ERRMSG replies to CTCP bomb. The effect of this * is that IRCII users can only send one CTCP/message if they expect a * reply. This shouldn't be a problem as that is the way IRCII operates * * Changed this behavouir to follow NO_CTCP_FLOOD */ if (get_int_var(NO_CTCP_FLOOD_VAR)) { if ((cmd = index(str, CTCP_DELIM_CHAR)) != NULL) do_new_notice_ctcp(from, to, &str, cmd); } else while ((cmd = index(str, CTCP_DELIM_CHAR)) != NULL) do_new_notice_ctcp(from, to, &str, cmd); in_ctcp_flag = 0; /**************************** Patched by Flier ******************************/ /*strcat(ctcp_buffer, str);*/ strmcat(ctcp_buffer, str, sizeof(ctcp_buffer)); /****************************************************************************/ return (ctcp_buffer); } static void do_new_notice_ctcp(from, to, str, cmd) char *from, *to, **str, *cmd; { char *end, *args, *ptr, *arg_copy = NULL; int flags, i, lastlog_level; /**************************** PATCHED by Flier *****************************/ int isitme; char tmpbuf1[mybufsize/32]; #if defined(CELE) struct timeval timenow; #endif /***************************************************************************/ flags = 0; *(cmd++) = '\0'; /**************************** Patched by Flier ******************************/ /*strcat(ctcp_buffer, *str);*/ strmcat(ctcp_buffer, *str, sizeof(ctcp_buffer)); /****************************************************************************/ if ((end = index(cmd, CTCP_DELIM_CHAR)) != NULL) { *(end++) = '\0'; if ((args = index(cmd, ' ')) != NULL) *(args++) = '\0'; malloc_strcpy(&arg_copy, args); for (i = 0; i < NUMBER_OF_CTCPS; i++) { if ((strcmp(cmd, ctcp_cmd[i].name) == 0) && ctcp_cmd[i].flag & CTCP_NOREPLY) { if ((ptr = ctcp_cmd[i].func(&(ctcp_cmd[i]), from, to, arg_copy)) != NULL) { /**************************** Patched by Flier ******************************/ /*strcat(ctcp_buffer, ptr);*/ strmcat(ctcp_buffer, ptr, sizeof(ctcp_buffer)); /****************************************************************************/ new_free(&ptr); flags = ctcp_cmd[i].flag; } break; } } new_free(&arg_copy); if (!args) args = empty_string; if (do_hook(CTCP_REPLY_LIST, "%s %s %s", from, cmd, args) && !(flags & CTCP_NOREPLY)) { if (!strcmp(cmd, "PING")) { /**************************** PATCHED by Flier ******************************/ /*char buf[20]; time_t timediff, currenttime; currenttime = time(NULL); if (args && *args) timediff = currenttime - (time_t) atol(args); else timediff = (time_t) 0; snprintf(buf, sizeof buf, "%ld second%s", (long) timediff, (timediff == 1) ? "" : "s"); args = buf;*/ char *tmpstr=(char *) 0; char buf[mybufsize/16]; struct timeval timeofday; gettimeofday(&timeofday,NULL); if ((tmpstr=next_arg(args,&args))) { timeofday.tv_sec-=atol(tmpstr); if ((tmpstr=next_arg(args,&args))) { if (timeofday.tv_usec>=atol(tmpstr)) timeofday.tv_usec-=atol(tmpstr); else { timeofday.tv_usec=timeofday.tv_usec- atol(tmpstr)+1000000; timeofday.tv_sec--; } snprintf(tmpbuf1,sizeof(tmpbuf1),"%06ld",timeofday.tv_usec); tmpbuf1[3]='\0'; snprintf(buf,sizeof(buf),"%ld.%s",timeofday.tv_sec,tmpbuf1); strmcat(buf," seconds",sizeof(buf)); #ifdef CELE timenow=timeofday; #endif } else snprintf(buf,sizeof(buf),"%ld second%s",timeofday.tv_sec, (timeofday.tv_sec==1)?"":"s"); } else strcpy(buf, "0 seconds"); args=buf; /****************************************************************************/ } save_message_from(); lastlog_level = set_lastlog_msg_level(LOG_CTCP); message_from((char *) 0, LOG_CTCP); /**************************** PATCHED by Flier ******************************/ /*say("CTCP %s reply from %s: %s", cmd, from, args);*/ if (my_stricmp(cmd,"PING")) { #ifdef WANTANSI say("%sCTCP %s%s reply from %s%s%s: %s", CmdsColors[COLCTCP].color4,cmd,Colors[COLOFF], CmdsColors[COLCTCP].color1,from,Colors[COLOFF],args); #else say("CTCP %s reply from %s: %s",cmd,from,args); #endif } else { isitme=!my_stricmp(from,get_server_nickname(from_server)); #ifdef WANTANSI say("%sCTCP %s%s reply from %s%s%s: %s", CmdsColors[COLCTCP].color4,cmd,Colors[COLOFF], CmdsColors[COLCTCP].color1,from,Colors[COLOFF],args); #else say("CTCP %s reply from %s: %s",cmd,from,args); #endif if (isitme) { #if defined(CELE) /* CTCP Ping is client->server->client->client->server->client == double lag */ if (timenow.tv_sec>0) { if (timenow.tv_sec%2==0) { timenow.tv_sec=timenow.tv_sec/2; timenow.tv_usec=timenow.tv_usec/2; } else { timenow.tv_sec=(timenow.tv_sec-1)/2; timenow.tv_usec=(timenow.tv_usec/2)+500000; } } else timenow.tv_usec=timenow.tv_usec/2; LagTimer=timenow; #else LagTimer=atoi(args)>>1; #endif /*CELE*/ update_all_status(); } } /****************************************************************************/ set_lastlog_msg_level(lastlog_level); restore_message_from(); } *str = end; } else { /**************************** Patched by Flier ******************************/ /*strcat(ctcp_buffer, CTCP_DELIM_STR);*/ strmcat(ctcp_buffer, CTCP_DELIM_STR, sizeof(ctcp_buffer)); /****************************************************************************/ *str = cmd; } } /* in_ctcp: simply returns the value of the ctcp flag */ int in_ctcp() { return (in_ctcp_flag); } /* These moved here because they belong here - phone */ /* * send_ctcp: A simply way to send CTCP queries. if the datatag * is NULL, we must have already formatted the ctcp reply (it has the * ctcp delimiters), so don't add them again, etc. */ void #ifdef HAVE_STDARG_H send_ctcp(char *type, char *to, char *datatag, char *format, ...) { va_list vl; #else send_ctcp(type, to, datatag, format, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) char *type, *to, *datatag, *format; char *arg0, *arg1, *arg2, *arg3, *arg4, *arg5, *arg6, *arg7, *arg8, *arg9; { #endif char putbuf[BIG_BUFFER_SIZE + 1], sendbuf[BIG_BUFFER_SIZE + 1]; char *sendp; if (in_on_who) return; /* Silently drop it on the floor */ if (format) { #ifdef HAVE_STDARG_H va_start(vl, format); vsnprintf(putbuf, sizeof putbuf, format, vl); va_end(vl); #else snprintf(putbuf, sizeof putbuf, format, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); #endif /* HAVE_STDARG_H */ if (datatag) { snprintf(sendbuf, sizeof sendbuf, "%c%s %s%c", CTCP_DELIM_CHAR, datatag, putbuf, CTCP_DELIM_CHAR); sendp = sendbuf; } else sendp = putbuf; } else { snprintf(sendbuf, sizeof sendbuf, "%c%s%c", CTCP_DELIM_CHAR, datatag, CTCP_DELIM_CHAR); sendp = sendbuf; } /* * ugh, special case dcc because we don't want to go through * send_text in it's current state. XXX - fix send_text to * deal with ctcp's as well. */ if (*to == '=') dcc_message_transmit(to + 1, sendp, DCC_CHAT, 0); else /**************************** PATCHED by Flier ******************************/ { /****************************************************************************/ send_to_server("%s %s :%s", type, to, sendp); /**************************** PATCHED by Flier ******************************/ #ifndef CELEHOOK if (datatag && strcmp(datatag,"ACTION")) do_hook(SEND_CTCP_LIST, "%s %s %s %s",type,to,datatag,sendp); #endif } /****************************************************************************/ } /* * send_ctcp_notice: A simply way to send CTCP replies. I put this here * rather than in ctcp.c to keep my compiler quiet */ void #ifdef HAVE_STDARG_H send_ctcp_reply(char *to, char *datatag, char *format, ...) { va_list vl; #else send_ctcp_reply(to, datatag, format, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) char *to, *datatag, *format; char *arg0, *arg1, *arg2, *arg3, *arg4, *arg5, *arg6, *arg7, *arg8, *arg9; { #endif /* HAVE_STDARG_H */ char putbuf[BIG_BUFFER_SIZE + 1]; if (in_on_who) return; /* Silently drop it on the floor */ if (to && (*to == '=')) return; /* don't allow dcc replies */ strmcat(CTCP_Reply_Buffer, "\001", BIG_BUFFER_SIZE); strmcat(CTCP_Reply_Buffer, datatag, BIG_BUFFER_SIZE); strmcat(CTCP_Reply_Buffer, " ", BIG_BUFFER_SIZE); if (format) { #ifdef HAVE_STDARG_H va_start(vl, format); vsnprintf(putbuf, sizeof putbuf, format, vl); va_end(vl); #else snprintf(putbuf, sizeof putbuf, format, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); #endif /* HAVE_STDARG_H */ strmcat(CTCP_Reply_Buffer, putbuf, BIG_BUFFER_SIZE); } else strmcat(CTCP_Reply_Buffer, putbuf, BIG_BUFFER_SIZE); strmcat(CTCP_Reply_Buffer, "\001", BIG_BUFFER_SIZE); }