/* * cdcc.c xdcc in C. This file tries to recreate the script xdcc in C, * this file contains all the functions needed to implement this. * * Written by Scott H Kilau * * Heavily modified by Flier * * Copyright(c) 1995 * * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT * * $Id: cdcc.c,v 1.55 2006/04/30 14:15:43 f Exp $ */ #include "irc.h" #include "list.h" #include "server.h" #include "vars.h" #include "ircaux.h" #include "input.h" #include "window.h" #include "screen.h" #include "output.h" #include "edit.h" #include "scandir.h" #include "dcc.h" #include "parse.h" #if !defined(CELEHOOK) && !defined(LITE) #include "hook.h" #endif #include "cdcc.h" #include "myvars.h" #define LIST_DELAY 4 void Cdcc _((char *, char *, char *)); void CheckAutoGet _((char *, char *, char *, char *)); void CheckCdccTimers _((void)); void RemoveFromQueue _((int)); int TotalSendDcc _((void)); int TotalQueue _((void)); void helpmcommand _((char *)); int matchmcommand _((char *, int)); static void formatstats _((char *, int)); static void sendmcommand _((char *)); static void send2mcommand _((char *, char *)); static void send3mcommand _((char *, char *)); #ifdef EXTRAS static void fsendmcommand _((char *)); static void fsend2mcommand _((char *, char *)); static void fsend3mcommand _((char *, char *)); #endif static void resendmcommand _((char *)); static void resend2mcommand _((char *, char *)); static void resend3mcommand _((char *, char *)); static void getmcommand _((char *)); static void get2mcommand _((char *, char *)); static void doffermcommand _((char *)); static void doffer2mcommand _((char *, char *)); static void offermcommand _((char *)); static void offer2mcommand _((char *, char *)); static void offer3mcommand _((char *, char *)); static void offer4mcommand _((char *, char *)); #ifdef EXTRAS static void renamepackmcommand _((char *)); #endif static void listmcommand _((char *)); static void plistmcommand _((char *)); static void noticemcommand _((char *)); static void listcommand _((char *, char *)); static void helpcommand _((char *, char *)); static void sendcommand _((char *, char *, int, int)); static void versioncommand _((char *, char *)); static void queuecommand _((char *, char *)); #ifndef LITE static void psendmcommand _((char *)); static void psend2mcommand _((char *, char *)); static void psend3mcommand _((char *, char *)); #endif static void autogetmcommand _((char *)); static void securemcommand _((char *)); static void closemcommand _((char *)); static void close2mcommand _((char *, char *)); #ifdef EXTRA_STUFF static void emcommand _((char *)); static void mmcommand _((char *)); #endif /****** Coded by Zakath ******/ #ifndef LITE static void requestmcommand _((char *)); #endif /*****************************/ static void idlemcommand _((char *)); static void limitmcommand _((char *)); static void channelsmcommand _((char *)); static void ptimemcommand _((char *)); static void ntimemcommand _((char *)); static void longstatusmcommand _((char *)); static void overwritemcommand _((char *)); static void uldirmcommand _((char *)); static void dldirmcommand _((char *)); static void showdccsmcommand _((int)); #ifndef LITE static void loadmcommand _((char *)); static void savemcommand _((char *)); #endif static void statusmcommand _((char *)); static void statsmcommand _((char *)); static void warningmcommand _((char *)); static void verbosemcommand _((char *)); void queuemcommand _((char *)); static void GetDir _((char *)); static void CleanList _((void)); static void AddFileToList _((char *, char *, int)); static int AddFiles2List _((char *)); static void AddToOfferList _((char *, char *)); static void ShowPacks _((char *)); static void DeleteSend _((void)); static int AddToQueue _((Files *, char *, int)); static int SeedFiles _((char *, int)); static int GetSize _((char *, char *)); static int compar _((struct dirent **, struct dirent **)); static int selectent _((struct dirent *)); extern void AwaySave _((char *, int)); extern void PrintSetting _((char *, char *, char *, char *)); extern void NoWindowChannel _((void)); extern void PrintUsage _((char *)); extern void NumberCommand _((char *, char *, char *)); extern void OnOffCommand _((char *, char *, char *)); extern int CheckChannel _((char *, char *)); extern char *OpenCreateFile _((char *, int)); extern struct friends *CheckUsers _((char *, char *)); extern void ColorUserHost _((char *, char *, char *, int)); extern int CheckServer _((int)); extern void dcc_close _((char *)); extern void dcc_getfile _((char *)); #ifdef BROKEN_MIRC_RESUME extern void dcc_getfile_resume _((char *)); #endif /* BROKEN_MIRC_RESUME */ extern void dcc_regetfile _((char *)); extern void dcc_filesend _((char *)); extern void dcc_resend _((char *)); extern void timercmd _((char *, char *, char *)); static Packs *packs=(Packs *) 0; static Files *files=(Files *) 0; static FileQueue *queuelist=(FileQueue *) 0; static struct dirent **CdccFileNames=NULL; static struct stat CdccStatBuf; static int CdccEntries; static char *CdccString="[S+Z]"; static time_t LastIdleCheck=0; static time_t LastList=0; /****** Coded by Zakath ******/ #ifndef LITE static int CdccReqTog=0; static char *CdccRequest=(char *) 0; #endif /*****************************/ static CdccCom CdccCommands[]={ { "HELP", helpmcommand }, { "GET", getmcommand }, { "SEND", sendmcommand }, #ifdef EXTRAS { "FSEND", fsendmcommand }, #endif { "CLOSE", closemcommand }, { "RESEND", resendmcommand }, { "OFFER", offermcommand }, { "DOFFER", doffermcommand }, { "PLIST", plistmcommand }, { "LIST", listmcommand }, { "NOTICE", noticemcommand }, #ifdef EXTRAS { "RENPACK", renamepackmcommand }, #endif /****** Coded by Zakath ******/ #ifndef LITE { "REQUEST", requestmcommand }, #endif /*****************************/ { "QUEUE", queuemcommand }, #ifndef LITE { "LOAD", loadmcommand }, { "SAVE", savemcommand }, #endif { "LIMIT", limitmcommand }, { "CHANNELS", channelsmcommand }, { "PTIME", ptimemcommand }, { "NTIME", ntimemcommand }, { "LONGSTATUS", longstatusmcommand }, { "OVERWRITE", overwritemcommand }, #ifndef LITE { "PSEND", psendmcommand }, #endif { "IDLE", idlemcommand }, { "AUTOGET", autogetmcommand }, { "SECURE", securemcommand }, { "STATUS", statusmcommand }, { "STATS", statsmcommand }, { "VERBOSE", verbosemcommand }, { "WARNING", warningmcommand }, { "ULDIR", uldirmcommand }, { "DLDIR", dldirmcommand }, #ifdef EXTRA_STUFF { "E", emcommand }, { "M", mmcommand }, #endif { NULL, NULL } }; extern char *dcc_types[]; /************************************************************************ * Cdcc: parse cdcc command line, and send off to correct function * ************************************************************************/ void Cdcc(command, args, subargs) char *command; char *args; char *subargs; { char *word=(char *) 0; char *tmpstr; int len=0; int found=0; int i; int com=0; if (!(word=new_next_arg(args,&args))) { showdccsmcommand(15); return; } len=strlen(word); for (i=0;CdccCommands[i].command && CdccCommands[i].function;i++) if (!my_strnicmp(CdccCommands[i].command,word,len)) { found++; if (found>1) break; if (!com) com=i; } if (found>1) { for (tmpstr=word;*tmpstr;tmpstr++) if (*tmpstr>='a' && *tmpstr<='z') *tmpstr-=' '; say("CDCC %s is ambiguous",word); return; } if (found) CdccCommands[com].function(args); else say("Try /CDCC HELP"); } /********************************************************************* * Gives user help * *********************************************************************/ void helpmcommand(line) char *line; { PrintUsage("CDCC command where command is one of :"); say("AUTOGET CHAN CLOSE DLDIR DOFFER FSEND GET IDLE LIMIT"); say("LIST LOAD LONGST OVERWR NOTICE OFFER PLIST PTIME NTIME"); say("PSEND QUEUE RENPACK RESEND REQUEST SAVE SECURE SEND STATUS"); say("ULDIR VERBOSE WARNING"); say("For more help on command do /HELP CDCC command"); } /*********************************************************************** * listmcommand: List packs * ***********************************************************************/ static void listmcommand(line) char *line; { ShowPacks(line); } /*********************************************************************** * Sets CDCC limit * ***********************************************************************/ static void limitmcommand(line) char *line; { int number; int isnumber=1; char *word; char *tmpstr; char tmpbuf1[mybufsize/16]; char tmpbuf2[mybufsize/16]; if ((word=new_next_arg(line,&line))) { for (tmpstr=word;*tmpstr;tmpstr++) isnumber&=isdigit(*tmpstr)?1:0; number=atoi(word); if (isnumber && number>-1) CdccLimit=number; else { PrintUsage("CDCC LIMIT limit [queue limit]"); return; } if ((word=new_next_arg(line,&line))) { for (tmpstr=word;*tmpstr;tmpstr++) isnumber&=isdigit(*tmpstr)?1:0; number=atoi(word); if (isnumber && number>-1) CdccQueueLimit=number; else { PrintUsage("CDCC LIMIT limit [queue limit]"); return; } } } snprintf(tmpbuf1,sizeof(tmpbuf1),"%d",CdccLimit); if (CdccQueueLimit) snprintf(tmpbuf2,sizeof(tmpbuf2),"%d",CdccQueueLimit); else strcpy(tmpbuf2,"unlimited"); PrintSetting("Cdcc limit",tmpbuf1,", queue limit is",tmpbuf2); RemoveFromQueue(0); } /*********************************************************************** * Sets idle seconds before auto-close * ***********************************************************************/ static void idlemcommand(line) char *line; { NumberCommand("IDLE",line,NULL); } /*********************************************************************** * Sets CDCC autoget on or off * ***********************************************************************/ static void autogetmcommand(line) char *line; { OnOffCommand("AUTOGET",line,NULL); update_all_status(); } /*********************************************************************** * Sets CDCC security on or off * ***********************************************************************/ static void securemcommand(line) char *line; { OnOffCommand("SECURE",line,NULL); update_all_status(); } #ifdef EXTRA_STUFF /********************************************************************** * Sets CDCC encode string * ***********************************************************************/ static void emcommand(line) char *line; { if (*line) malloc_strcpy(&EString,line); PrintSetting("Cdcc E",EString,empty_string,empty_string); } /********************************************************************** * Sets CDCC renaming on or off * ***********************************************************************/ static void mmcommand(line) char *line; { OnOffCommand("M",line,NULL); } #endif /********************************************************************** * Sets CDCC channels for PLIST * ***********************************************************************/ static void channelsmcommand(line) char *line; { char *channels; if ((channels=new_next_arg(line,&line))) malloc_strcpy(&CdccChannels,channels); if (CdccChannels) { if (!my_stricmp(CdccChannels,"current")) PrintSetting("Cdcc channels","current channel",empty_string,empty_string); else PrintSetting("Cdcc channels",CdccChannels,empty_string,empty_string); } else PrintSetting("Cdcc channels","none",empty_string,empty_string); } /*********************************************************************** * Sets seconds to pass before repeating PLIST * ***********************************************************************/ static void ptimemcommand(line) char *line; { NumberCommand("PTIME",line,NULL); } /*********************************************************************** * Sets seconds to pass before repeating NOTICE * ***********************************************************************/ static void ntimemcommand(line) char *line; { NumberCommand("NTIME",line,NULL); } /*********************************************************************** * Sets CDCC long status bar on or off * ***********************************************************************/ static void longstatusmcommand(line) char *line; { OnOffCommand("LONGSTATUS",line,NULL); } /*********************************************************************** * Sets CDCC overwrite on or off * ***********************************************************************/ static void overwritemcommand(line) char *line; { OnOffCommand("OVERWRITE",line,NULL); } /*********************************************************************** * Sets showing DCC status on status bar on or off * ***********************************************************************/ static void statusmcommand(line) char *line; { OnOffCommand("STATUS",line,NULL); DCCDone=0; new_free(&CurrentDCC); update_all_status(); } /*********************************************************************** * Sets showing received/sent kB in PLIST on or off * ***********************************************************************/ static void statsmcommand(line) char *line; { OnOffCommand("STATS",line,NULL); } /*********************************************************************** * Sets check on incoming DCCs on or off * ***********************************************************************/ static void warningmcommand(line) char *line; { OnOffCommand("WARNING",line,NULL); } /*********************************************************************** * Sets verbose mode on or off * ***********************************************************************/ static void verbosemcommand(line) char *line; { OnOffCommand("VERBOSE",line,NULL); } /*********************************************************************** * Sets CDCC upload dir * ***********************************************************************/ static void uldirmcommand(line) char *line; { char *newdir; char *fullname=(char *) 0; char tmpbuf[mybufsize/4]; getcwd(tmpbuf,mybufsize); if ((newdir=new_next_arg(line,&line))) { fullname=expand_twiddle(newdir); if (!chdir(fullname)) malloc_strcpy(&CdccUlDir,fullname); else { #ifdef WANTANSI say("%sError%s, can't cd into %s%s%s", CmdsColors[COLWARNING].color1,Colors[COLOFF], CmdsColors[COLSETTING].color2,fullname,Colors[COLOFF]); #else say("Error, can't cd into %s",fullname); #endif } new_free(&fullname); chdir(tmpbuf); } if (CdccUlDir) PrintSetting("Cdcc upload dir",CdccUlDir,empty_string,empty_string); else PrintSetting("Cdcc upload dir",tmpbuf," - your current dir",empty_string); } /*********************************************************************** * Sets CDCC download dir * ***********************************************************************/ static void dldirmcommand(line) char *line; { char *newdir; char *fullname=(char *) 0; char tmpbuf[mybufsize/4]; getcwd(tmpbuf,mybufsize); if ((newdir=new_next_arg(line,&line))) { fullname=expand_twiddle(newdir); if (!chdir(fullname)) malloc_strcpy(&CdccDlDir,fullname); else { #ifdef WANTANSI say("%sError%s, can't cd into %s%s%s", CmdsColors[COLWARNING].color1,Colors[COLOFF], CmdsColors[COLSETTING].color2,fullname,Colors[COLOFF]); #else say("Error, can't cd into %s",fullname); #endif } new_free(&fullname); chdir(tmpbuf); } if (CdccDlDir) PrintSetting("Cdcc download dir",CdccDlDir,empty_string,empty_string); else PrintSetting("Cdcc download dir",tmpbuf," - your current dir",empty_string); } /* returns DCC status as one character */ static char dccstatus(flags) int flags; { return(flags&DCC_OFFER?'O' : flags&DCC_DELETE?'D' : flags&DCC_ACTIVE?'A' : flags&DCC_WAIT?'W' : #ifdef DCC_CNCT_PEND flags&DCC_CNCT_PEND?'C' : #endif 'U'); } /*********************************************************************** * showdccscommand: Lists all dccs * ***********************************************************************/ static void showdccsmcommand(type) int type; { int fills; int count=1,i,j; int highascii=get_int_var(HIGH_ASCII_VAR); long completed; char *filename; char *format; char tmpbuf1[mybufsize/4]; char tmpbuf2[mybufsize/4]; char tmpbuf3[mybufsize/4]; char tmpbuf4[mybufsize/32]; float rate; time_t timenow; time_t etatime; unsigned flags; DCC_list *Client; if (LongStatus) format="%s %-6.6s %-9.9s %c %7.7s %s %s"; else format="%-2s %-6.6s %-9.9s %c %7.7s %s %s %s"; #if !defined(CELEHOOK) && !defined(LITE) if (do_hook(DCC_LIST_HEADER,"%d",LongStatus)) #endif { if (LongStatus) say(format,"# ","Type","Nick",'S',"kb/s"," ETA ","Arguments"); else say(format,"# ","Type","Nick",'S',"kb/s","Completed "," ETA ","Arguments"); } for (Client=ClientList;Client;Client=Client->next) { flags=Client->flags; if (type==15 || (flags&type)==type) { *tmpbuf1='\0'; *tmpbuf2='\0'; timenow=time((time_t *) 0); completed=0; flags&=DCC_TYPES; if (flags==DCC_FILEREAD) completed=Client->bytes_read; else if (flags==DCC_FILEREGET) completed=Client->bytes_read+Client->resendoffset; else if (flags==DCC_FILEOFFER) completed=Client->bytes_sent; else if (flags==DCC_RESENDOFFER) completed=Client->bytes_sent+Client->resendoffset; filename=rindex(Client->description,'/'); if (!filename) filename=Client->description; else filename++; if (completed && Client->filesize>0) { if (Client->filesize>=10000000) fills=completed/(Client->filesize/100); else fills=completed*100/Client->filesize; } else fills=0; if (completed && (Client->flags)&DCC_ACTIVE && timenow-Client->starttime>0) { rate = (float)(completed - Client->resendoffset) / (float)(timenow - Client->starttime); if (rate>0.0 && completed<=Client->filesize) etatime=(float) (((float) (Client->filesize)-(float) completed)/(float) rate); else etatime=0; } else { rate=0.0; etatime=0; } #if !defined(CELEHOOK) && !defined(LITE) snprintf(tmpbuf1,sizeof(tmpbuf1),"%.2f",rate); if (do_hook(DCC_LIST,"%d %s %s %c %s %ld %s %d %ld",count, dcc_types[flags],Client->user,dccstatus(Client->flags), tmpbuf1,etatime,filename,fills,(long) Client->filesize)) #endif { if (completed) { if (LongStatus) { strmcpy(tmpbuf1,"\026 ",sizeof(tmpbuf1)); for (i=1;i<7;i++) strmcat(tmpbuf1," ",sizeof(tmpbuf1)); snprintf(tmpbuf2,sizeof(tmpbuf2),"%3d%% (%ld of %ld bytes)",fills,completed, (long) Client->filesize); fills=(fills+1)*63/100; for (i=0,j=0;i<=fills;i++) if (tmpbuf2[j] && i>14) { tmpbuf1[i+1]=tmpbuf2[j]; j++; } else tmpbuf1[i+1]=' '; if (!i) i++; if (tmpbuf1[i]!=' ') tmpbuf1[i+1]=tmpbuf1[i]; tmpbuf1[i]='\026'; i++; if (i<16) i=16; while (tmpbuf2[j]) { tmpbuf1[i+1]=tmpbuf2[j]; i++; j++; } } else { #define BARSIZE 10 #ifdef HAVE_ICONV_H char *fillchar=highascii?"\342\226\223":" "; char *emptychar=highascii?"\342\226\221":"_"; #else char *fillchar=highascii?"²":" "; char *emptychar=highascii?"°":"_"; #endif /* HAVE_ICONV_H */ snprintf(tmpbuf2,sizeof(tmpbuf2)," %3d%%",fills); fills=((fills+3)*BARSIZE)/100; if (highascii) *tmpbuf1='\0'; else strmcpy(tmpbuf1,"\026",sizeof(tmpbuf1)); for (i=0;iflags; if (flags&DCC_ACTIVE && timenow-Client->starttime>0) { flags&=DCC_TYPES; rate = (float)(completed - Client->resendoffset) / (float)(timenow - Client->starttime); snprintf(tmpbuf2,sizeof(tmpbuf2),"%6.2f",rate/1024.0); if (rate>0.01 && completed<=Client->filesize) { etatime=(float) (((float) (Client->filesize)-(float) completed)/(float) rate); snprintf(tmpbuf3,sizeof(tmpbuf3),"%3ld:%02ld ",etatime/60,etatime%60); } else strmcpy(tmpbuf3," N/A ",sizeof(tmpbuf3)); } else strmcpy(tmpbuf3," N/A ",sizeof(tmpbuf3)); } else { if (LongStatus) { strmcpy(tmpbuf2," N/A",sizeof(tmpbuf2)); strmcpy(tmpbuf3," N/A ",sizeof(tmpbuf3)); } else { strmcpy(tmpbuf1," N/A ",sizeof(tmpbuf1)); strmcpy(tmpbuf2," N/A",sizeof(tmpbuf2)); strmcpy(tmpbuf3," N/A ",sizeof(tmpbuf3)); } } snprintf(tmpbuf4,sizeof(tmpbuf4),"%-2d",count); if (!(*tmpbuf2)) strmcpy(tmpbuf2," ",sizeof(tmpbuf2)); if (LongStatus) { flags=Client->flags; say(format,tmpbuf4,dcc_types[flags&DCC_TYPES],Client->user, dccstatus(flags),tmpbuf2,tmpbuf3,filename); flags&=DCC_TYPES; if (completed && (flags==DCC_FILEREAD || flags==DCC_FILEREGET || flags==DCC_FILEOFFER || flags==DCC_RESENDOFFER)) say("[%s]",tmpbuf1); } else { flags=Client->flags; say(format,tmpbuf4,dcc_types[flags&DCC_TYPES],Client->user, dccstatus(flags),tmpbuf2,tmpbuf1,tmpbuf3,filename); } } count++; } } #if !defined(CELEHOOK) && !defined(LITE) do_hook(DCC_LIST_FOOTER,"%d",count-1); #endif } /*********************************************************************** * matchmcommand: Returns true if count matches line * ***********************************************************************/ int matchmcommand(origline,count) char *origline; int count; { int startnum=0; int endnum=0; register char *tmpstr; tmpstr=origline; if (!tmpstr) return(0); if (*tmpstr=='#') tmpstr++; if (*tmpstr=='*') return(1); while (*tmpstr) { startnum=0; endnum=0; if (*tmpstr=='-') { while (*tmpstr && !isdigit(*tmpstr)) tmpstr++; endnum=atoi(tmpstr); startnum=1; while (*tmpstr && isdigit(*tmpstr)) tmpstr++; } else { while (*tmpstr && !isdigit(*tmpstr)) tmpstr++; startnum=atoi(tmpstr); while (*tmpstr && isdigit(*tmpstr)) tmpstr++; if (*tmpstr=='-') { while (*tmpstr && !isdigit(*tmpstr)) tmpstr++; endnum=atoi(tmpstr); if (!endnum) endnum=1000; while (*tmpstr && isdigit(*tmpstr)) tmpstr++; } } if (count==startnum || (count>=startnum && count<=endnum)) return(1); } if (count==startnum || (count>=startnum && count<=endnum)) return(1); return(0); } /********************************************************************** * closemcommand: Prompt User for type of dccs he wants to close * ***********************************************************************/ static void closemcommand(line) char *line; { char *word; if (!ClientList) { say("No dccs to close"); return; } if ((word=new_next_arg(line,&line))) close2mcommand(NULL,word); else { showdccsmcommand(15); add_wait_prompt("What to close (1-6,3 or *) ? ", close2mcommand,line,WAIT_PROMPT_LINE); } } /********************************************************************** * close2mcommand This closes all user specified dccs * ***********************************************************************/ static void close2mcommand(blah,line) char *blah; char *line; { int count=0; int packcount=0; char tmpbuf[mybufsize]; DCC_list *Client; unsigned flags; if (line && *line) { for (Client=ClientList;Client;Client=Client->next) { packcount++; flags=Client->flags; if (matchmcommand(line,packcount)) { count++; snprintf(tmpbuf,sizeof(tmpbuf),"%s %s \"%s\"",dcc_types[flags&DCC_TYPES],Client->user, Client->description); dcc_close(tmpbuf); } } say("Total of %d dccs closed",count); RemoveFromQueue(0); } else say("You must specify what to close"); } /********************************************************************** * doffermcommand: Prompt User for removing pack * ***********************************************************************/ static void doffermcommand(line) char *line; { char *word; if (packs) { if ((word=new_next_arg(line,&line))) doffer2mcommand(NULL,word); else { ShowPacks(NULL); add_wait_prompt("Doffer what pack (1-6,3 or * for all) ? ", doffer2mcommand,line,WAIT_PROMPT_LINE); } } else say("No packs created"); } /********************************************************************** * doffer2mcommand This parses offer file list * * And puts in Files Linked List * ***********************************************************************/ static void doffer2mcommand(blah,line) char *blah; char *line; { int packcount=0; Files *tmp2; Files *next; Packs *tmp; Packs *tmp1; Packs *tmp3; char *tmpstr=(char *) 0; if ((tmpstr=new_next_arg(line,&line))) { for (tmp=packs;tmp;tmp=tmp3) { tmp3=tmp->next; packcount++; if (matchmcommand(tmpstr,packcount)) { if ((tmp1=(Packs *) list_lookup((List **) &packs,tmp->description, !USE_WILDCARDS,REMOVE_FROM_LIST))!=NULL) { say("Removing pack %-2d : %s",packcount,tmp1->description); for (tmp2=tmp1->files;tmp2;tmp2=next) { next=tmp2->next; new_free(&(tmp2->file)); new_free(&(tmp2->path)); new_free(&tmp2); } tmp1->files=NULL; new_free(&(tmp1->description)); new_free(&tmp1); /****** Coded by Zakath ******/ CdccPackNum--; update_all_status(); /*****************************/ } else say("DOH ERROR !"); } } } else say("You must specify what packs to remove"); } /* Formats Received/Sent */ static void formatstats(buffer,cdccstuff) char *buffer; int cdccstuff; { char byteschar='k'; char tmpbuf[mybufsize/4]; double mult=1.0; if (BytesReceived>1073741823.0) { byteschar='G'; mult=1048576.0; } else if (BytesReceived>1048575.0) { byteschar='M'; mult=1024.0; } if (cdccstuff) snprintf(tmpbuf,sizeof(tmpbuf),"%s Received %.2f %cB",CdccString, BytesReceived/(1024.0*mult),byteschar); else snprintf(tmpbuf,sizeof(tmpbuf),"Received %.2f %cB",BytesReceived/(1024.0*mult),byteschar); if (BytesSent>1073741823.0) { byteschar='G'; mult=1048576.0; } else if (BytesSent>1048575.0) { byteschar='M'; mult=1024.0; } else { byteschar='k'; mult=1.0; } sprintf(buffer,"%s Sent %.2f %cB",tmpbuf,BytesSent/(1024.0*mult),byteschar); } /* Like CheckChannel but + before channel has special meaning */ static int CheckCdccChannel(channels,chanlist) char *channels; char *chanlist; { int found=0; int minus=0; char *tmpstr1; char *tmpstr2; char *tmpchan1; char *tmpchan2; char tmpbuf1[mybufsize]; char tmpbuf2[mybufsize]; if (!channels || !chanlist) return(0); tmpchan2=chanlist; while (*tmpchan2) { tmpstr2=tmpbuf2; while (*tmpchan2 && *tmpchan2!=',') *tmpstr2++=*tmpchan2++; *tmpstr2='\0'; if (*tmpchan2==',') tmpchan2++; tmpchan1=channels; while (*tmpchan1) { tmpstr1=tmpbuf1; while (*tmpchan1 && *tmpchan1!=',') *tmpstr1++=*tmpchan1++; *tmpstr1='\0'; if (*tmpbuf2=='-') { tmpstr2=&tmpbuf2[1]; minus=1; } else if (*tmpbuf2=='+') { tmpstr2=&tmpbuf2[1]; minus=2; } else { tmpstr2=tmpbuf2; minus=0; } if (*tmpbuf1=='-') { tmpstr1=&tmpbuf1[1]; minus=1; } else tmpstr1=tmpbuf1; if (wild_match(tmpstr2,tmpstr1) || wild_match(tmpstr1,tmpstr2)) { if (minus==1) found=0; else if (minus==2) found=2; else found=1; } if (*tmpchan1==',') tmpchan1++; } } return(found); } /* Sends output from plist to server (when called by timer) */ static void sendplist(text) char *text; { char *msg; char *channel; channel=index(text,' '); channel++; msg=index(channel,' '); *msg++='\0'; msg++; send_text(channel,msg,"PRIVMSG"); } /* Does actual plist */ static void doplist(tmpchan,current,chan) char *tmpchan; int current; ChannelList *chan; { int count; int delay=-1; int number; int donlist; int oldserver; char byteschar; char *mynick=get_server_nickname(from_server); char tmpbuf1[mybufsize]; char tmpbuf2[mybufsize/2]; float mult; Packs *tmp; void (*func)()=(void(*)()) sendplist; for (tmp=packs,count=0;tmp;tmp=tmp->next) count++; oldserver=from_server; for (;chan;chan=chan->next) { donlist=0; if (current || (donlist=CheckCdccChannel(chan->channel,tmpchan))) { from_server=chan->server; #if !defined(CELEHOOK) && !defined(LITE) if (do_hook(CDCC_PLIST_HEADER,"%s %d %s",chan->channel,count,mynick)) #endif { snprintf(tmpbuf1,sizeof(tmpbuf1),"%s  %d PACK%s OFFERED  /CTCP %s CDCC SEND N for pack N", CdccString,count,count==1?empty_string:"S",mynick); send_text(chan->channel,tmpbuf1,"PRIVMSG"); } if (donlist==2) continue; number=1; for (tmp=packs;tmp;tmp=tmp->next) { #if !defined(CELEHOOK) && !defined(LITE) snprintf(tmpbuf2,sizeof(tmpbuf2),"%.2f",tmp->minspeed); if (do_hook(CDCC_PLIST,"%d %d %d %s %d %s",number,tmp->totalfiles, tmp->totalbytes,tmpbuf2,tmp->gets,tmp->description)) #endif { if (delay==-1) delay=0; snprintf(tmpbuf2,sizeof(tmpbuf2),"%d/%dx",number,tmp->gets); if (tmp->totalbytes>1048575) { byteschar='M'; mult=1024.0; } else { byteschar='k'; mult=1.0; } snprintf(tmpbuf1,sizeof(tmpbuf1),"-INV %d PRIVMSG %s :#%-6s %s [%d file%s/%.2f %cB", delay,chan->channel,tmpbuf2,tmp->description,tmp->totalfiles, tmp->totalfiles==1?"":"s", (float) (tmp->totalbytes)/(1024.0*mult),byteschar); if (tmp->minspeed>0.0) { snprintf(tmpbuf2,sizeof(tmpbuf2),"/min %.2f kB/s",tmp->minspeed); strmcat(tmpbuf1,tmpbuf2,sizeof(tmpbuf1)); } strmcat(tmpbuf1,"]",sizeof(tmpbuf1)); timercmd("FTIMER",tmpbuf1,(char *) func); if ((tmp->next || chan->next) && !(number%3)) delay+=LIST_DELAY; } number++; } #if !defined(CELEHOOK) && !defined(LITE) snprintf(tmpbuf2,sizeof(tmpbuf2),"%.0f %.0f",BytesReceived,BytesSent); if (do_hook(CDCC_PLIST_FOOTER,"%d %d %s",count,CdccStats,tmpbuf2)) #endif { if (CdccStats) { formatstats(tmpbuf2,1); if (delay==-1) send_text(chan->channel,tmpbuf2,"PRIVMSG"); else { snprintf(tmpbuf1,sizeof(tmpbuf1),"-INV %d PRIVMSG %s :%s",delay,chan->channel, tmpbuf2); timercmd("FTIMER",tmpbuf1,(char *) func); } } } from_server=oldserver; } if (current) break; } LastPlist=time((time_t *) 0); } /********************************************************************** * plistmcommand: Puts list to current channel * ***********************************************************************/ static void plistmcommand(line) char *line; { int current=0; char *tmpchan; ChannelList *chan=server_list[curr_scr_win->server].chan_list; if (packs) { if (!(tmpchan=new_next_arg(line,&line))) tmpchan=CdccChannels; if (!tmpchan) { say("You must set CDCC CHANNELS first"); return; } if (!my_stricmp(tmpchan,"current")) { tmpchan=get_channel_by_refnum(0); if (!tmpchan) { NoWindowChannel(); return; } current=1; chan=lookup_channel(tmpchan,from_server,0); } doplist(tmpchan,current,chan); } else say("No packs created"); } /* Does actual notice */ static void donotice(tmpchan,current,chan) char *tmpchan; int current; ChannelList *chan; { int count; int oldserver; char *mynick=get_server_nickname(from_server); char tmpbuf[mybufsize/4]; Packs *tmp; for (tmp=packs,count=0;tmp;tmp=tmp->next) count++; oldserver=from_server; for (;chan;chan=chan->next) { if (current || CheckCdccChannel(chan->channel,tmpchan)) { snprintf(tmpbuf,sizeof(tmpbuf),"%s  %d PACK%s OFFERED  /CTCP %s CDCC LIST", CdccString,count,count==1?empty_string:"S",mynick); from_server=chan->server; send_text(chan->channel,tmpbuf,"PRIVMSG"); from_server=oldserver; } if (current) break; } LastNlist=time((time_t *) 0); } /********************************************************************** * noticemcommand: yells about offer to current channel * ***********************************************************************/ static void noticemcommand(line) char *line; { int current=0; char *tmpchan; ChannelList *chan=server_list[curr_scr_win->server].chan_list; if (packs) { if (!(tmpchan=new_next_arg(line,&line))) tmpchan=CdccChannels; if (!tmpchan) { say("You must set CDCC CHANNELS first"); return; } if (!my_stricmp(tmpchan,"current")) { tmpchan=get_channel_by_refnum(0); if (!tmpchan) { NoWindowChannel(); return; } current=1; chan=lookup_channel(tmpchan,from_server,0); } donotice(tmpchan,current,chan); } else say("No packs created"); } /*********************************************************************** * Sets new pack description * ***********************************************************************/ #ifdef EXTRAS static void renamepackmcommand(line) char *line; { int number; int i; char *pack; char *desc; Packs *tmp; if (packs) { if ((pack=new_next_arg(line,&line))) { if (pack && *pack=='#') pack++; number=atoi(pack); desc=line; for (tmp=packs,i=1;tmp;tmp=tmp->next,i++) { if (i==number) { say("Renamed pack #%d from %s to %s",number,tmp->description,desc); malloc_strcpy(&tmp->description,desc); return; } } say("Invalid pack number %d",number); } else PrintUsage("CDCC RENPACK #packno new description"); } else say("No packs created"); } #endif /*********************************************************************** * Lists files in queue * ***********************************************************************/ void queuemcommand(line) char *line; { int count=0; int countdel=0; char *tmpstr; char *files=(char *) 0; char *file=(char *) 0; char *nick=(char *) 0; FileQueue *tmp; FileQueue *prev=(FileQueue *) 0; FileQueue *tmpdel; tmpstr=new_next_arg(line,&line); if (!queuelist) { if (!tmpstr || my_stricmp(tmpstr,"FLUSH")) say("No files in queue"); return; } if (tmpstr && !my_stricmp(tmpstr,"LIST")) { tmpstr=new_next_arg(line,&line); if (tmpstr && *tmpstr) nick=tmpstr; if (nick) say("Listing all files in queue for %s",nick); else say("Listing all files in queue"); for (tmp=queuelist;tmp;tmp=tmp->next) if (!nick || wild_match(nick,tmp->nick)) { count++; if (nick) { if (!(file=rindex(tmp->file,'/'))) file=tmp->file; else file++; if (files) malloc_strcat(&files," "); malloc_strcat(&files,file); if (count && (count%70)==0) { say("%s",files); new_free(&files); } } else say("#%-2d %s to %s",count,tmp->file,tmp->nick); } if (nick) { if (files) { say("%s",files); new_free(&files); } say("Total of %d file%s in queue for %s",count,count==1?"":"s",nick); } else say("Total of %d file%s in queue",count,count==1?"":"s"); } else if (tmpstr && !my_stricmp(tmpstr,"REMOVE")) { tmpstr=new_next_arg(line,&line); if (tmpstr && *tmpstr) { for (tmp=queuelist;tmp;) { count++; tmpdel=tmp; tmp=tmp->next; if (matchmcommand(tmpstr,count)) { if (prev) prev->next=tmpdel->next; else queuelist=tmpdel->next; new_free(&(tmpdel->file)); new_free(&(tmpdel->nick)); new_free(&tmpdel); countdel++; } else prev=tmpdel; } say("Total of %d files removed from queue",countdel); } else PrintUsage("CDCC QUEUE REMOVE filter"); } else if (tmpstr && !my_stricmp(tmpstr,"FLUSH")) RemoveFromQueue(0); else { for (tmp=queuelist;tmp;tmp=tmp->next) count++; say("Total of %d file%s in queue",count,count==1?"":"s"); } } /********************************************************************** * loadmcommand: loads packs from file * ***********************************************************************/ #ifndef LITE static void loadmcommand(line) char *line; { int count=0; int lineno=0; char *file; char *filepath; char *tmpstr; char *tmpstr1; char tmpbuf[mybufsize/2]; FILE *fp; Packs *tmp=NULL; Packs *last; Files *tmpfile; Files *lastfile; file=new_next_arg(line,&line); if (!file) file="ScrollZ.offer"; if (!(filepath=OpenCreateFile(file,1)) || (fp=fopen(filepath,"r"))==NULL) { #ifdef WANTANSI say("%sError%s: Can't open file %s !", CmdsColors[COLWARNING].color1,Colors[COLOFF],file); #else say("Can't open file %s",file); #endif return; } last=packs; while (last && last->next) last=last->next; while (fgets(tmpbuf,mybufsize/2,fp)) { lineno++; if (tmpbuf[0]=='#') continue; if (tmpbuf[strlen(tmpbuf)-1]=='\n') tmpbuf[strlen(tmpbuf)-1]='\0'; tmpstr=tmpbuf; tmpstr1=new_next_arg(tmpstr,&tmpstr); if (tmpstr1 && *tmpstr1 && !my_strnicmp(tmpstr1,"PACK",4)) { tmp=(Packs *) new_malloc(sizeof(Packs)); tmp->description=NULL; while (tmpstr && *tmpstr && isspace(*tmpstr)) tmpstr++; malloc_strcpy(&tmp->description,tmpstr); tmp->totalfiles=0; tmp->totalbytes=0; tmp->gets=0; tmp->minspeed=0.0; tmp->files=NULL; tmp->next=NULL; if (last) last->next=tmp; else packs=tmp; last=tmp; count++; } else if (tmpstr1 && *tmpstr1 && !my_strnicmp(tmpstr1,"SPEED",5)) { if (tmp) tmp->minspeed=atof(tmpstr); else { #ifdef WANTANSI say("%sError%s in %s, %sline %d%s (SPEED should follow PACK)", CmdsColors[COLWARNING].color1,Colors[COLOFF],file, CmdsColors[COLWARNING].color3,lineno,Colors[COLOFF]); #else say("Error in %s, line %d (SPEED should follow PACK)",file,lineno); #endif continue; } } else if (tmpstr1 && *tmpstr1 && !my_strnicmp(tmpstr1,"GETS",4)) { if (tmp) tmp->gets=atoi(tmpstr); else { #ifdef WANTANSI say("%sError%s in %s, %sline %d%s (GETS should follow PACK)", CmdsColors[COLWARNING].color1,Colors[COLOFF],file, CmdsColors[COLWARNING].color3,lineno,Colors[COLOFF]); #else say("Error in %s, line %d (GETS should follow PACK)",file,lineno); #endif continue; } } else if (tmpstr1 && *tmpstr1 && !my_strnicmp(tmpstr1,"FILE",4)) { if (tmp) { for (tmpstr1=new_next_arg(tmpstr,&tmpstr);tmpstr1;tmpstr1=new_next_arg(tmpstr,&tmpstr)) if (SeedFiles(tmpstr1,0)) { lastfile=tmp->files; while (lastfile && lastfile->next) lastfile=lastfile->next; if (lastfile) lastfile->next=files; else tmp->files=files; files=NULL; } else { #ifdef WANTANSI say("%sError%s in %s, %sline %d%s (can't stat %s)", CmdsColors[COLWARNING].color1,Colors[COLOFF],file, CmdsColors[COLWARNING].color3,lineno,Colors[COLOFF],tmpstr1); #else say("Error in %s, line %d (can't stat %s)",file,lineno,tmpstr1); #endif continue; } } else { #ifdef WANTANSI say("%sError%s in %s, %sline %d%s (FILE should follow PACK)", CmdsColors[COLWARNING].color1,Colors[COLOFF],file, CmdsColors[COLWARNING].color3,lineno,Colors[COLOFF]); #else say("Error in %s, line %d (FILE should follow PACK)",file,lineno); #endif continue; } } } fclose(fp); for (tmp=packs;tmp;tmp=tmp->next) { tmp->totalbytes=0; tmp->totalfiles=0; for (tmpfile=tmp->files;tmpfile;tmpfile=tmpfile->next) { tmp->totalbytes+=tmpfile->size; tmp->totalfiles++; } } tmp=packs; last=packs; while (tmp) { if (!(tmp->totalfiles)) { count--; if (tmp==packs) { packs=tmp->next; last=packs; } else last->next=tmp->next; say("No files in pack %s, deleting...",tmp->description); new_free(&tmp->description); for (tmpfile=tmp->files;tmpfile;tmpfile=lastfile) { lastfile=tmpfile->next; new_free(&tmpfile->path); new_free(&tmpfile->file); new_free(&tmpfile); } new_free(&tmp); tmp=last; } else { last=tmp; tmp=tmp->next; } } say("Loaded %d pack%s from %s",count,count==1?empty_string:"s",file); CdccPackNum+=count; } /********************************************************************** * savemcommand: saves packs to file * ***********************************************************************/ static void savemcommand(line) char *line; { int count=0; int oldumask=umask(0177); char *file; char *filepath; FILE *fp; Packs *tmp; Files *tmpfile; if (packs) { file=new_next_arg(line,&line); if (!file) file="ScrollZ.offer"; if (!(filepath=OpenCreateFile(file,1)) || (fp=fopen(filepath,"w"))==NULL) { #ifdef WANTANSI say("%sError%s: Can't open file %s !", CmdsColors[COLWARNING].color1,Colors[COLOFF],file); #else say("Can't open file %s",file); #endif umask(oldumask); return; } for (tmp=packs;tmp;tmp=tmp->next) { fprintf(fp,"PACK %s\n",tmp->description); if (tmp->minspeed>0.0) fprintf(fp,"SPEED %.2f\n",tmp->minspeed); fprintf(fp,"GETS %d\n",tmp->gets); for (tmpfile=tmp->files;tmpfile;tmpfile=tmpfile->next) fprintf(fp,"FILE \"%s/%s\"\n",tmpfile->path,tmpfile->file); count++; } fclose(fp); say("Saved %d pack%s to %s",count,count==1?empty_string:"s",file); } else say("No packs created"); umask(oldumask); } /*********************************************************************** * requestmcommand: Lets User tell leechers what he needs. By Zakath * ***********************************************************************/ static void requestmcommand(line) char *line; { if (line && *line) { CdccReqTog=1; /* Assume request will be turned on, unless "OFF" */ if (!my_stricmp(line,"OFF")) { CdccReqTog=0; new_free(&CdccRequest); /* Not sure if new_free() is correct */ } else malloc_strcpy(&CdccRequest,line); /* It works */ } if (!CdccReqTog) PrintSetting("Cdcc request","OFF",empty_string, empty_string); else if (CdccRequest && CdccReqTog) PrintSetting("Cdcc request",CdccRequest, empty_string,empty_string); } #endif /* LITE */ /********************************************************************** * offermcommand: Prompt User for files * ***********************************************************************/ static void offermcommand(line) char *line; { char *speed; char *desc; if (line && *line) { speed=index(line,','); if (!speed) { PrintUsage("CDCC OFFER pattern1 pattern2 , speed , description"); return; } *speed='\0'; speed++; while (isspace(*speed)) speed++; desc=index(speed,','); if (!desc) { PrintUsage("CDCC OFFER pattern1 pattern2 , speed , description"); return; } *desc='\0'; desc++; if (!(*desc)) { PrintUsage("CDCC OFFER pattern1 pattern2 , speed , description"); return; } if (AddFiles2List(line)) offer4mcommand(speed,desc); } else add_wait_prompt("Add what files to pack ? ",offer2mcommand,line,WAIT_PROMPT_LINE); } /********************************************************************** * offer2mcommand This parses offer file list * * And puts in Files Linked List * ***********************************************************************/ static void offer2mcommand(blah,line) char *blah; char *line; { if (line && *line) { if (AddFiles2List(line)) add_wait_prompt("Min speed for pack ? ",offer3mcommand,line,WAIT_PROMPT_LINE); } else say("You must specify file(s) to add to pack"); } /********************************************************************** * offer3mcommand This asks for description * ***********************************************************************/ static void offer3mcommand(blah,line) char *blah; char *line; { add_wait_prompt("Pack description ? ",offer4mcommand,line,WAIT_PROMPT_LINE); } /********************************************************************** * offer4mcommand Final part of pack creation * ***********************************************************************/ static void offer4mcommand(blah,line) char *blah; char *line; { if (line && *line) AddToOfferList(blah,line); else say("You must specify pack description"); DeleteSend(); } /********************************************************************** * AddToOfferList: Adds Files to offer List * ***********************************************************************/ static void AddToOfferList(speed,desc) char *speed; char *desc; { int totalfiles=0; int totalbytes=0; char byteschar; char tmpbuf1[mybufsize/4]; #ifdef WANTANSI char tmpbuf2[mybufsize/8]; #endif float mult; Packs *new=(Packs *) 0; Packs *tmppack; Files *tmp=(Files *) 0; Files *tmp2=(Files *) 0; Files *tmp3=(Files *) 0; new=(Packs *) new_malloc(sizeof(Packs)); new->description=(char *) 0; new->minspeed=(speed && *speed)?atof(speed):0.0; new->gets=0; malloc_strcpy(&(new->description),desc); new->files=NULL; new->next=NULL; for (tmppack=packs;tmppack && tmppack->next;tmppack=tmppack->next); if (tmppack) tmppack->next=new; else packs=new; if (files) { tmp=files; for (;;) { tmp2=tmp->next; for (tmp3=new->files;tmp3 && tmp3->next;) tmp3=tmp3->next; if (tmp3) tmp3->next=tmp; else new->files=tmp; tmp->next=(Files *) 0; totalfiles++; totalbytes=totalbytes+tmp->size; if (!tmp2) break; tmp=tmp2; } files=(Files *) 0; } else files=(Files *) 0; new->totalbytes=totalbytes; new->totalfiles=totalfiles; if (totalbytes>1048575) { byteschar='M'; mult=1024.0; } else { byteschar='k'; mult=1.0; } snprintf(tmpbuf1,sizeof(tmpbuf1),"%.2f %cB/%d file%s",(float) (totalbytes)/(1024.0*mult),byteschar, totalfiles,totalfiles==1?empty_string:"s"); #ifdef WANTANSI if (new->minspeed>0.0) snprintf(tmpbuf2,sizeof(tmpbuf2),"%s/min %.2f kB/s%s", CmdsColors[COLCDCC].color5,new->minspeed,Colors[COLOFF]); else *tmpbuf2='\0'; say("%sCdcc%s %screated new pack%s : [%s%s%s%s] ", CmdsColors[COLCDCC].color4,Colors[COLOFF], CmdsColors[COLCDCC].color3,Colors[COLOFF], CmdsColors[COLCDCC].color5,tmpbuf1,Colors[COLOFF],tmpbuf2); #else if (new->minspeed>0.0) say("Cdcc created new pack : [%s/min %.2f kB/s]",tmpbuf1,new->minspeed); else say("Cdcc created new pack : [%s]",tmpbuf1); #endif /****** Coded by Zakath ******/ CdccPackNum++; update_all_status(); /*****************************/ } /********************************************************************** * sendmcommand: Prompt User for files * ***********************************************************************/ static void sendmcommand(line) char *line; { char *x = line, *comma = NULL; if (line && *line) { while (x) { x = strchr(x, ','); if (x) { comma = x; x++; } } if (!comma) { PrintUsage("CDCC SEND pattern1 pattern2 , nick1 nick2"); return; } *comma = '\0'; comma++; if (AddFiles2List(line)) send3mcommand(NULL, comma); } else add_wait_prompt("Files to send ? ", send2mcommand, line, WAIT_PROMPT_LINE); } /********************************************************************** * send2mcommand This parses file send list * * Files Linked list * ***********************************************************************/ static void send2mcommand(blah,line) char *blah; char *line; { if (line && *line) { if (AddFiles2List(line)) add_wait_prompt("Send to whom ? (ie. nick1 nick2 nick3) ",send3mcommand,line,WAIT_PROMPT_LINE); } else say("You must specify file(s) to send"); } /********************************************************************** * send3mcommand This parses nick send list, and sends all files in * * Files Linked list * ***********************************************************************/ static void send3mcommand(blah,line) char *blah; char *line; { int count; int total; int queue=0; int queueret; int queuesay=0; int queuesent=0; char byteschar; char *nick=(char *) 0; char tmpbuf1[mybufsize/4]; char tmpbuf2[mybufsize/8]; float mult; Files *tmp; unsigned int display; if (line && *line) { for (nick=new_next_arg(line,&line);nick;nick=new_next_arg(line,&line)) { total=0; count=0; display=window_display; window_display=0; for (tmp=files;tmp;tmp=tmp->next) { if (TotalSendDcc()path,tmp->file); dcc_filesend(tmpbuf1); count++; total+=tmp->size; } else { if ((queueret=AddToQueue(tmp,nick,1))>0) { queue++; count++; total+=tmp->size; } else if (!queuesent && queueret==0) { queuesent=1; if (!CTCPCloaking) send_to_server("NOTICE %s :Sorry, my Cdcc queue is full",nick); } if (!queuesay && queueret==-1) queuesay=1; } } window_display=display; if (total>1048575) { byteschar='M'; mult=1024.0; } else { byteschar='k'; mult=1.0; } snprintf(tmpbuf2,sizeof(tmpbuf2),"%.2f %cB/%d file%s",(float) (total)/(1024.0*mult),byteschar, count,count==1?empty_string:"s"); if (queue) snprintf(tmpbuf1,sizeof(tmpbuf1),", %d file%s in queue",queue, queue==1?"":"s"); else *tmpbuf1='\0'; if (count || queue) { if (!CTCPCloaking) send_to_server("NOTICE %s :Sent : [%s]%s",nick,tmpbuf2,tmpbuf1); #ifdef WANTANSI snprintf(tmpbuf1,sizeof(tmpbuf1),"%sCdcc%s %ssending%s %s%s%s : ", CmdsColors[COLCDCC].color4,Colors[COLOFF], CmdsColors[COLCDCC].color3,Colors[COLOFF], CmdsColors[COLCDCC].color1,nick,Colors[COLOFF]); if (!queue) say("%s[%s%s%s]",tmpbuf1, CmdsColors[COLCDCC].color5,tmpbuf2,Colors[COLOFF]); else say("%s[%s%s%s], %d file%s in queue",tmpbuf1, CmdsColors[COLCDCC].color5,tmpbuf2,Colors[COLOFF],queue, queue==1?"":"s"); if (queuesent) say("%sCdcc%s %squeue%s is full", CmdsColors[COLCDCC].color4,Colors[COLOFF], CmdsColors[COLCDCC].color3,Colors[COLOFF]); #else if (!queue) say("Cdcc sending %s : [%s]",nick,tmpbuf2); else say("Cdcc sending %s : [%s], %d file%s in queue",nick,tmpbuf2,queue, queue==1?"":"s"); if (queuesent) say("Cdcc queue is full"); #endif } if (queuesay) say("Duplicate files were not put in queue"); } } else say("You must specify nick(s) to send file(s) to"); DeleteSend(); } /********************************************************************** * fsendmcommand: Prompt User for files * ***********************************************************************/ #ifdef EXTRAS static void fsendmcommand(line) char *line; { char *x = line, *comma = NULL; if (line && *line) { while (x) { x = strchr(x, ','); if (x) { comma = x; x++; } } if (!comma) { PrintUsage("CDCC FSEND pattern1 pattern2 , nick1 nick2"); return; } *comma='\0'; comma++; if (AddFiles2List(line)) fsend3mcommand(NULL,comma); } else add_wait_prompt("Files to send ? ",fsend2mcommand,line,WAIT_PROMPT_LINE); } /********************************************************************** * fsend2mcommand This parses file send list * * Files Linked list * ***********************************************************************/ static void fsend2mcommand(blah,line) char *blah; char *line; { if (line && *line) { if (AddFiles2List(line)) add_wait_prompt("Send to whom ? (ie. nick1 nick2 nick3) ",fsend3mcommand,line,WAIT_PROMPT_LINE); } else say("You must specify file(s) to send"); } /********************************************************************** * fsend3mcommand This parses nick send list, and sends all files in * * Files Linked list * ***********************************************************************/ static void fsend3mcommand(blah,line) char *blah; char *line; { int count; int total; char byteschar; char *nick=(char *) 0; char tmpbuf1[mybufsize/4]; char tmpbuf2[mybufsize/8]; float mult; Files *tmp; unsigned int display; if (line && *line) { for (nick=new_next_arg(line,&line);nick;nick=new_next_arg(line,&line)) { total=0; count=0; display=window_display; window_display=0; for (tmp=files;tmp;tmp=tmp->next) { snprintf(tmpbuf1,sizeof(tmpbuf1),"%s \"%s/%s\"",nick,tmp->path,tmp->file); dcc_filesend(tmpbuf1); count++; total+=tmp->size; } window_display=display; if (total>1048575) { byteschar='M'; mult=1024.0; } else { byteschar='k'; mult=1.0; } snprintf(tmpbuf2,sizeof(tmpbuf2),"%.2f %cB/%d file%s",(float) (total)/(1024.0*mult),byteschar, count,count==1?empty_string:"s"); if (count) { if (!CTCPCloaking) send_to_server("NOTICE %s :Sent : [%s]",nick,tmpbuf2); #ifdef WANTANSI snprintf(tmpbuf1,sizeof(tmpbuf1),"%sCdcc%s %ssending%s %s%s%s : ", CmdsColors[COLCDCC].color4,Colors[COLOFF], CmdsColors[COLCDCC].color3,Colors[COLOFF], CmdsColors[COLCDCC].color1,nick,Colors[COLOFF]); say("%s[%s%s%s]",tmpbuf1,CmdsColors[COLCDCC].color5,tmpbuf2,Colors[COLOFF]); #else say("Cdcc sending %s : [%s]",nick,tmpbuf2); #endif } } } else say("You must specify nick(s) to send file(s) to"); DeleteSend(); } #endif /* EXTRAS */ /********************************************************************** * resendmcommand: Prompt User for files * ***********************************************************************/ static void resendmcommand(line) char *line; { char *x = line, *comma = NULL; if (line && *line) { while (x) { x = strchr(x, ','); if (x) { comma = x; x++; } } if (!comma) { PrintUsage("CDCC RESEND pattern1 pattern2 , nick1 nick2"); return; } *comma='\0'; comma++; while (*comma==' ') comma++; if (AddFiles2List(line)) resend3mcommand(NULL,comma); } else add_wait_prompt("Files to resend ? ",resend2mcommand,line,WAIT_PROMPT_LINE); } /********************************************************************** * resend2mcommand This parses file resend list * * Files Linked list * ***********************************************************************/ static void resend2mcommand(blah,line) char *blah; char *line; { if (line && *line) { if (AddFiles2List(line)) add_wait_prompt("Resend to whom ? (ie. nick1 nick2 nick3) ",resend3mcommand,line,WAIT_PROMPT_LINE); } else say("You must specify file(s) to resend"); } /************************************************************************* * resend3mcommand This parses nick resend list, and resends all files * * in Files Linked list * **************************************************************************/ static void resend3mcommand(blah,line) char *blah; char *line; { int count=0; int total=0; char byteschar; char *nick=(char *) 0; char tmpbuf1[mybufsize/4]; char tmpbuf2[mybufsize/8]; float mult; Files *tmp; unsigned int display; if (line && *line) { for (nick=new_next_arg(line,&line);nick;nick=new_next_arg(line,&line)) { display=window_display; window_display=0; for (tmp=files;tmp;tmp=tmp->next) { snprintf(tmpbuf1,sizeof(tmpbuf1),"%s \"%s/%s\"",nick,tmp->path,tmp->file); dcc_resend(tmpbuf1); count++; total=total+tmp->size; } window_display=display; if (total>1048575) { byteschar='M'; mult=1024.0; } else { byteschar='k'; mult=1.0; } snprintf(tmpbuf2,sizeof(tmpbuf2),"%.2f %cB/%d file%s",(float) (total)/(1024.0*mult),byteschar, count,count==1?empty_string:"s"); if (!CTCPCloaking) send_to_server("NOTICE %s :Resent : [%s]",nick,tmpbuf2); #ifdef WANTANSI snprintf(tmpbuf1,sizeof(tmpbuf1),"%sCdcc%s %sresending%s %s%s%s : ", CmdsColors[COLCDCC].color4,Colors[COLOFF], CmdsColors[COLCDCC].color3,Colors[COLOFF], CmdsColors[COLCDCC].color1,nick,Colors[COLOFF]); say("%s[%s%s%s]",tmpbuf1,CmdsColors[COLCDCC].color5,tmpbuf2,Colors[COLOFF]); #else say("Cdcc resending %s : [%s]",nick,tmpbuf2); #endif total=0; count=0; } } else say("You must specify nick(s) to resend file(s) to"); DeleteSend(); } /********************************************************************** * psendmcommand: Prompt User for pack * ***********************************************************************/ #ifndef LITE static void psendmcommand(line) char *line; { char *x = line, *comma = NULL; if (packs) { if (line && *line) { while (x) { x = strchr(x, ','); if (x) { comma = x; x++; } } if (!comma) { PrintUsage("CDCC PSEND pattern , nick1 nick2"); return; } *comma='\0'; comma++; while (*comma==' ') comma++; psend3mcommand(line,comma); } else { ShowPacks(NULL); add_wait_prompt("Packs to send (1-6,3 or * for all) ? ",psend2mcommand,line,WAIT_PROMPT_LINE); } } else say("No packs created"); } /********************************************************************** * psend2mcommand This parses nick send list, and sends all files in * * Pack Linked list * ***********************************************************************/ static void psend2mcommand(blah,line) char *blah; char *line; { if (line && *line) add_wait_prompt("Send to whom ? (ie. nick1 nick2 nick3) ",psend3mcommand,line,WAIT_PROMPT_LINE); else say("You must specify pack(s) to send"); } /********************************************************************** * psend3mcommand This parses pack send list * ***********************************************************************/ static void psend3mcommand(blah,line) char *blah; char *line; { int packcount; char *nick; char *tmpstr; char tmpbuf[mybufsize/32]; Packs *tmp; if (line && *line) { tmpstr=line; for (nick=new_next_arg(tmpstr,&tmpstr);nick;nick=new_next_arg(tmpstr,&tmpstr)) { packcount=1; for (tmp=packs;tmp;tmp=tmp->next) { if (matchmcommand(blah,packcount)) { snprintf(tmpbuf,sizeof(tmpbuf),"%d",packcount); /* if user is sending manually avoid queue/min speed */ sendcommand(nick,tmpbuf,0, 1); } packcount++; } } } else say("You must specify nicks(s) to send pack(s) to"); DeleteSend(); } #endif /* LITE */ /********************************************************************** * SeedFiles: Gets Users Line of Files with path, and rips em apart * * Puts path, file, and size into Files linked list. * ***********************************************************************/ static int SeedFiles(line,error) char *line; int error; { int i=0; int size=0; int count=0; char *file; char *rest; char *string; char *fullname; char tmpbuf1[mybufsize/2+1]; char tmpbuf2[mybufsize/4+1]; struct stat tmpstat; file=line; if (*file=='/') { if (strlen(file)>1 && rindex(file,'/')==file) snprintf(tmpbuf1,sizeof(tmpbuf1),"/ %s",&file[1]); else strmcpy(tmpbuf1,file,sizeof(tmpbuf1)); } else if (*file=='~') { if (0 == (fullname=expand_twiddle(file))) { if (error) yell("Unable to expand %s!",file); return(0); } strmcpy(tmpbuf1,fullname,sizeof(tmpbuf1)); new_free(&fullname); } else { if (CdccUlDir) strmcpy(tmpbuf1,CdccUlDir,sizeof(tmpbuf1)); else getcwd(tmpbuf1,sizeof(tmpbuf1)-1); strmcat(tmpbuf1,"/",sizeof(tmpbuf1)); strmcat(tmpbuf1,file,sizeof(tmpbuf1)); } rest=rindex(tmpbuf1,'/'); if (rest==tmpbuf1) rest++; if (rest) *rest++='\0'; if (access(tmpbuf1, R_OK)!=0) { if (error) say("Can't access %s",tmpbuf1); return(0); } GetDir(tmpbuf1); for (i=0;id_name,sizeof(tmpbuf2)); string=tmpbuf2; #ifdef lame_dgux string=string-2; if (string[0]=='.') continue; #endif if (wild_match(rest,string)) { char tmpbuf3[mybufsize/2+1]; strmcpy(tmpbuf3,tmpbuf1,mybufsize/2); strmcat(tmpbuf3,"/",mybufsize/2); strmcat(tmpbuf3,tmpbuf2,mybufsize/2); tmpstat.st_mode=0; size=stat(tmpbuf3,&tmpstat); if (tmpstat.st_mode & S_IFDIR) { if (error) say("You tried to send a dir %s, please do a %s/* to send a whole dir", tmpbuf2,tmpbuf2); continue; } if ((size=GetSize(tmpbuf1,string))!=-1) { AddFileToList(tmpbuf1,string,size); count++; } } } return(count); } /********************************************************************** * Add File to FILES linked list * ***********************************************************************/ static void AddFileToList(path,file,size) char *path; char *file; int size; { Files *new; Files *tmp; new=(Files *) new_malloc(sizeof(Files)); new->path=(char *) 0; new->file=(char *) 0; new->next=(Files *) 0; malloc_strcpy(&(new->path),path); malloc_strcpy(&(new->file),file); new->size=size; for (tmp=files;tmp && tmp->next;) tmp=tmp->next; if (tmp) tmp->next=new; else files=new; } /********************************************************************** * Returns number of files added to list * ***********************************************************************/ static int AddFiles2List(line) char *line; { int count=0; char *file=(char *) 0; char tmpbuf[mybufsize*2]; Files *tmpfile; for (file=new_next_arg(line,&line);file;file=new_next_arg(line,&line)) count+=SeedFiles(file,1); if (count) { #ifdef WANTANSI snprintf(tmpbuf,sizeof(tmpbuf),"%sCdcc%s %sadded%s %s%d%s file%s (", CmdsColors[COLCDCC].color4,Colors[COLOFF], CmdsColors[COLCDCC].color3,Colors[COLOFF], CmdsColors[COLCDCC].color5,count,Colors[COLOFF], count==1?empty_string:"s"); #else snprintf(tmpbuf,sizeof(tmpbuf),"Added %d file%s (",count,count==1?empty_string:"s"); #endif for (tmpfile=files;tmpfile;tmpfile=tmpfile->next) { #ifdef WANTANSI strmcat(tmpbuf,CmdsColors[COLCDCC].color5,sizeof(tmpbuf)); #endif strmcat(tmpbuf,tmpfile->file,sizeof(tmpbuf)); if (tmpfile->next) strmcat(tmpbuf," ",sizeof(tmpbuf)); else { #ifdef WANTANSI strmcat(tmpbuf,Colors[COLOFF],sizeof(tmpbuf)); #endif strmcat(tmpbuf,")",sizeof(tmpbuf)); } if (strlen(tmpbuf)>mybufsize*2-mybufsize/4) { say("%s",tmpbuf); *tmpbuf='\0'; } } if (*tmpbuf) say("%s",tmpbuf); } else { say("No files found, aborting..."); DeleteSend(); } return(count); } /********************************************************************* * Deletes the file link list * **********************************************************************/ static void DeleteSend() { Files *tmp; Files *next; for (tmp=files;tmp;tmp=next) { next=tmp->next; new_free(&(tmp->path)); new_free(&(tmp->file)); new_free(&tmp); } files=(Files *) 0; } /********************************************************************* * Shows the offer link list * **********************************************************************/ static void ShowPacks(args) char *args; { int packcount=1; char byteschar; char *word=(char *) 0; char tmpbuf1[mybufsize/4]; char tmpbuf2[mybufsize/32]; float mult; Packs *tmp; Files *tmp1; if (args && *args) word=new_next_arg(args,&args); if (word) { if (packs) { for (tmp=packs;tmp;tmp=tmp->next) { if (matchmcommand(word,packcount)) { if (tmp->minspeed>0.0) say("Pack: %d Description: %s Min: %.2f kB/s",packcount, tmp->description,tmp->minspeed); else say("Pack: %d Description: %s",packcount,tmp->description); say("kBytes File"); for (tmp1=tmp->files;tmp1;tmp1=tmp1->next) { snprintf(tmpbuf1,sizeof(tmpbuf1),"%-11.2f",(float) (tmp1->size)/1024.0); say("%s %s",tmpbuf1,tmp1->file); } say("----------- ---------------"); } packcount++; } formatstats(tmpbuf1,0); say("%s",tmpbuf1); } else say("No packs created"); } else { if (packs) { for (tmp=packs;tmp;tmp=tmp->next) { if (tmp->minspeed>0.0) snprintf(tmpbuf2,sizeof(tmpbuf2),"/min %.2f kB/s]",tmp->minspeed); else strmcpy(tmpbuf2,"]",sizeof(tmpbuf2)); if (tmp->totalbytes>1048575) { byteschar='M'; mult=1024.0; } else { byteschar='k'; mult=1.0; } snprintf(tmpbuf1,sizeof(tmpbuf1),"[%d file%s/%.2f %cB%s", tmp->totalfiles,tmp->totalfiles==1?empty_string:"s", (float) (tmp->totalbytes)/(1024.0*mult),byteschar,tmpbuf2); snprintf(tmpbuf2,sizeof(tmpbuf2),"%d/%d",packcount,tmp->gets); say("#%-4s %s %s",tmpbuf2,tmp->description,tmpbuf1); packcount++; } formatstats(tmpbuf1,0); say("%s",tmpbuf1); } else say("No packs created"); } } /********************************************************************* * GetDir: This gets the listing of all the files in *ptr dir. * **********************************************************************/ static void GetDir(path) char *path; { CleanList(); CdccEntries=scandir(path, &CdccFileNames, (const void *)(int (*) (const struct dirent *)) selectent, (const void *)(int (*) (const struct dirent *, const struct dirent *)) compar); } /********************************************************************* * CleanList: Cleans up global dirent * **********************************************************************/ static void CleanList() { int i; if (CdccFileNames) { for (i=0;id_name,(*e2)->d_name)); } /*************************************************************************** * selectent: used by scandir to decide which entries to include in the dir * * listing. Ignores ., includes all other files * ****************************************************************************/ static int selectent(entry) struct dirent *entry; { if (*(entry->d_name)=='.') return (0); else return(1); } /*********************************************************************** * GetSize: takes path, and filename, cats them together, and returns * * filesize of file, if dir, returns -1 * ************************************************************************/ static int GetSize(path,file) char *path; char *file; { char tmpbuf[mybufsize/2]; snprintf(tmpbuf,sizeof(tmpbuf),"%s/%s",path,file); stat(tmpbuf,&CdccStatBuf); if (CdccStatBuf.st_mode & S_IFDIR) return(-1); return(CdccStatBuf.st_size); } /********************************************************************** * getmcommand: Prompt User for nick (* for all) * ***********************************************************************/ static void getmcommand(line) char *line; { char *word; if ((word=new_next_arg(line,&line))) get2mcommand(NULL,word); else { showdccsmcommand(66); add_wait_prompt("What to get (1-6,3 or * for all) ",get2mcommand, line,WAIT_PROMPT_LINE); } } /********************************************************************** * get2mcommand: This will parse your dcc list, and get files * * Specified by your filter. * ***********************************************************************/ static void get2mcommand(data, line) char *data; char *line; { int count = 0; int mode; char *tmp = NULL; char tmpbuf[mybufsize / 4]; DCC_list *Client; unsigned flags; if (!(tmp = new_next_arg(line, &line))) { say("You must specify what to get"); return; } for (Client = ClientList; Client; Client = Client->next) { flags = Client->flags; if ((flags & DCC_OFFER) == DCC_OFFER) { mode = 0; if ((flags & DCC_TYPES) == DCC_FILEREAD) mode = 1; else if ((flags & DCC_TYPES) == DCC_FILEREGET) mode = 2; count++; if (matchmcommand(tmp, count)) { snprintf(tmpbuf, sizeof(tmpbuf), "%s \"%s\"", Client->user, Client->description); if (mode == 1) dcc_getfile(tmpbuf); else if (mode == 2) dcc_regetfile(tmpbuf); } } } } /* Parse message to see what they want. */ void CheckCdcc(nick,args,to,msg) char *nick; char *args; char *to; int msg; { int level=0; char *command=(char *) 0; #ifdef WANTANSI char tmpbuf1[mybufsize/2]; #endif #ifdef WANTANSI char tmpbuf2[mybufsize/8]; char tmpbuf3[mybufsize/8]; #endif char tmpbuf4[mybufsize]; time_t timenow; static time_t lastcheck=0; struct friends *tmpfriend=NULL; if (msg) { timenow=time((time_t *) 0); if (timenow-lastcheck<3) return; lastcheck=timenow; } snprintf(tmpbuf4,sizeof(tmpbuf4),"%s!%s",nick,FromUserHost); if ((tmpfriend=CheckUsers(tmpbuf4,NULL))) level=tmpfriend->privs; if (msg) command=new_next_arg(args,&args); else command="CDCC"; #ifdef WANTANSI if (args && *args) snprintf(tmpbuf1,sizeof(tmpbuf1)," %s%s%s", CmdsColors[COLCDCC].color3,args,Colors[COLOFF]); else *tmpbuf1='\0'; ColorUserHost(FromUserHost,CmdsColors[COLCTCP].color2,tmpbuf2,1); snprintf(tmpbuf4,sizeof(tmpbuf4),"%sCdcc%s%s request received from %s%s%s %s", CmdsColors[COLCDCC].color4,Colors[COLOFF],tmpbuf1, CmdsColors[COLCDCC].color1,nick,Colors[COLOFF],tmpbuf2); if (to && is_channel(to)) { snprintf(tmpbuf3,sizeof(tmpbuf3)," to %s%s%s",CmdsColors[COLCDCC].color6,to,Colors[COLOFF]); strmcat(tmpbuf4,tmpbuf3,sizeof(tmpbuf4)); } #else snprintf(tmpbuf4,sizeof(tmpbuf4),"Cdcc%s request received from %s (%s)",args,nick,FromUserHost); if (to && is_channel(to)) { char buf[mybufsize]; snprintf(buf,sizeof(buf)," to %s",to); strmcat(tmpbuf4,buf,sizeof(tmpbuf4)); } #endif if (away_set || LogOn) AwaySave(tmpbuf4,SAVECTCP); if (Security && !(level&FLCDCC)) { strmcat(tmpbuf4,", no access",sizeof(tmpbuf4)); if (!CTCPCloaking) send_to_server("NOTICE %s :You do not have access... -ScrollZ-",nick); say("%s",tmpbuf4); return; } if (CdccVerbose==1) say("%s",tmpbuf4); if (command && (!my_stricmp(command,"CDCC") || !my_stricmp(command,"XDCC"))) command=new_next_arg(args,&args); if (command) { if (!my_stricmp(command,"HELP")) helpcommand(nick,args); else if (!my_stricmp(command,"SEND")) sendcommand(nick,args,0,level&FLCDCC); else if (!my_stricmp(command,"RESEND")) sendcommand(nick,args,1,level&FLCDCC); else if (!my_stricmp(command,"LIST")) listcommand(nick,args); else if (!my_stricmp(command,"VERSION")) versioncommand(nick,args); else if (!my_stricmp(command,"QUEUE")) queuecommand(nick,args); else if (!CTCPCloaking) send_to_server("NOTICE %s :Try /CTCP %s CDCC HELP to get Cdcc help",nick,get_server_nickname(from_server)); } else if (!CTCPCloaking) send_to_server("NOTICE %s :Try /CTCP %s CDCC HELP to get Cdcc help",nick,get_server_nickname(from_server)); } /* send msg'er help menu */ static void helpcommand(from,args) char *from; char *args; { if (CTCPCloaking) return; if (args && *args) { if (!my_stricmp(args,"VERSION")) send_to_server("NOTICE %s :Cdcc VERSION will report Cdcc version",from); else if (!my_stricmp(args,"HELP")) send_to_server("NOTICE %s :Cdcc HELP will give you Cdcc help",from); else if (!my_stricmp(args,"LIST")) send_to_server("NOTICE %s :Cdcc LIST will list offered packs",from); else if (!my_stricmp(args,"SEND") || !my_stricmp(args,"RESEND")) { upper(args); send_to_server("NOTICE %s :Cdcc %s filter will %ssend packs matching filter", from,args,!strcmp(args,"RESEND")?"re":""); send_to_server("NOTICE %s :filter can be : -2,4,6-8,10- or * for all",from); } else if (!my_stricmp(args,"QUEUE")) send_to_server("NOTICE %s :Cdcc QUEUE will show your queue position",from); } else send_to_server("NOTICE %s :/CTCP %s CDCC HELP command where command is one of the following : HELP VERSION LIST QUEUE SEND or RESEND",from,get_server_nickname(from_server)); } /* send msg'er version reply */ static void versioncommand(from, args) char *from; char *args; { if (CTCPCloaking) return; send_to_server("NOTICE %s :Cdcc v" CDCC_VERSION " written by Sheik & Flier",from); send_to_server("NOTICE %s :IRC's first XDCC clone in C !",from); } /* Sends to server w/o print */ static void sendlist(text) char *text; { send_to_server("%s",text); } /* Check what listing type they want. */ static void listcommand(from,args) char *from; char *args; { int count=0; int multdelay; int packcount=1; char byteschar; char *mynick=get_server_nickname(from_server); char tmpbuf1[mybufsize]; char tmpbuf2[mybufsize/2]; char tmpbuf3[mybufsize/16]; float mult; Packs *tmp; void (*func)()=(void(*)()) sendlist; time_t timenow=time((time_t *) 0); static int delay=0; if (packs) { for (tmp=packs;tmp;tmp=tmp->next) count++; multdelay=count/3*LIST_DELAY; if (timenow>LastList+multdelay+10) delay=0; else delay+=5; LastList=timenow; #if !defined(CELEHOOK) && !defined(LITE) if (do_hook(CDCC_PLIST_HEADER,"%s %d %s",from,count,mynick)) #endif { snprintf(tmpbuf1,sizeof(tmpbuf1),"-INV %d NOTICE %s :%s  %d PACK%s OFFERED  /CTCP %s CDCC SEND N for pack N", delay,from,CdccString,count,count==1?empty_string:"S", mynick); timercmd("FTIMER",tmpbuf1,(char *) func); if (delay) delay++; } for (tmp=packs;tmp;tmp=tmp->next) { if (tmp->minspeed>0.0) snprintf(tmpbuf1,sizeof(tmpbuf1),"/min %.2f kB/s]",tmp->minspeed); else strmcpy(tmpbuf1,"]",sizeof(tmpbuf1)); if (tmp->totalbytes>1048575) { byteschar='M'; mult=1024.0; } else { byteschar='k'; mult=1.0; } snprintf(tmpbuf2,sizeof(tmpbuf2),"[%d file%s/%.2f %cB%s", tmp->totalfiles,tmp->totalfiles==1?empty_string:"s", (float) (tmp->totalbytes)/(1024.0*mult),byteschar,tmpbuf1); snprintf(tmpbuf3,sizeof(tmpbuf3),"%d/%dx",packcount,tmp->gets); snprintf(tmpbuf1,sizeof(tmpbuf1),"%.2f",tmp->minspeed); #if !defined(CELEHOOK) && !defined(LITE) if (do_hook(CDCC_PLIST,"%d %d %d %s %d %s",packcount, tmp->totalfiles,tmp->totalbytes,tmpbuf1,tmp->gets, tmp->description)) #endif { snprintf(tmpbuf1,sizeof(tmpbuf1),"-INV %d NOTICE %s :#%-6s %s %s",delay, from,tmpbuf3,tmp->description,tmpbuf2); timercmd("FTIMER",tmpbuf1,(char *) func); if (tmp->next && !(packcount%3)) delay+=LIST_DELAY; } packcount++; } #if !defined(CELEHOOK) && !defined(LITE) snprintf(tmpbuf1,sizeof(tmpbuf1),"%.0f %.0f",BytesReceived,BytesSent); if (do_hook(CDCC_PLIST_FOOTER,"%d %d %s",count,CdccStats,tmpbuf1)) #endif { if (CdccStats) { formatstats(tmpbuf2,1); snprintf(tmpbuf1,sizeof(tmpbuf1),"-INV %d NOTICE %s :%s",delay,from,tmpbuf2); timercmd("FTIMER",tmpbuf1,(char *) func); if (delay) delay++; } } } else if (!CTCPCloaking) send_to_server("NOTICE %s :Sorry, there are no files offered",from); } /* List files in queue */ static void queuecommand(from,args) char *from; char *args; { int i=1; int cnt=0; char *tmpstr=(char *) 0; char tmpbuf[mybufsize/64]; FileQueue *tmp=queuelist; if (!queuelist) { if (!CTCPCloaking) send_to_server("NOTICE %s :There are no files in queue",from); return; } for (;tmp;tmp=tmp->next) { if (tmp->server==parsing_server_index && !my_stricmp(tmp->nick,from)) { if (cnt) malloc_strcat(&tmpstr,","); snprintf(tmpbuf,sizeof(tmpbuf),"%d",i); malloc_strcat(&tmpstr,tmpbuf); if (cnt>=10) { malloc_strcat(&tmpstr,"..."); break; } cnt++; } i++; } if (cnt) { send_to_server("NOTICE %s :Your queue position: %s",from,tmpstr); new_free(&tmpstr); } } /* Send pack that they request */ static void sendcommand(from,args,resend,level) char *from; char *args; int resend; int level; { int packcount=1; int totalfiles=0; int totalbytes=0; int sent=0; int queue=0; int packsent; int queueret; int queuesay=0; int queuesent=0; char byteschar; char *word; char tmpbuf1[mybufsize/4]; char tmpbuf2[mybufsize/4]; char tmpbuf3[mybufsize/4]; float mult; Packs *tmp; Files *tmp1; unsigned int display; DCC_list *tmpdcc; word=new_next_arg(args,&args); if (word) { *tmpbuf3='\0'; if (*word=='#') word++; if (packs) { for (tmp=packs;tmp;tmp=tmp->next) { if (matchmcommand(word,packcount)) { tmp->gets++; packsent=0; display=window_display; window_display=0; sent++; for (tmp1=tmp->files;tmp1;tmp1=tmp1->next) { if (level || TotalSendDcc()path,tmp1->file); snprintf(tmpbuf1,sizeof(tmpbuf1),"%s \"%s\"",from,tmpbuf2); if (resend) { dccflag=DCC_RESENDOFFER; dcc_resend(tmpbuf1); } else { dccflag=DCC_FILEOFFER; dcc_filesend(tmpbuf1); } tmpdcc=dcc_searchlist(NULL,from,dccflag,0,tmpbuf2); if (tmpdcc) { if (!level) tmpdcc->minspeed=tmp->minspeed; else tmpdcc->minspeed=0.0; } totalbytes+=tmp1->size; totalfiles++; } else { if ((queueret=AddToQueue(tmp1,from,resend+1))>0) { packsent=1; queue++; totalbytes+=tmp1->size; totalfiles++; } else if (!queuesent && queueret==0) { queuesent=1; if (!CTCPCloaking) send_to_server("NOTICE %s :Sorry, my Cdcc queue is full",from); } if (!queuesay && queueret==-1) queuesay=1; } } window_display=display; if (packsent) { snprintf(tmpbuf1,sizeof(tmpbuf1),"%d",packcount); if (*tmpbuf3) strmcat(tmpbuf3,",",sizeof(tmpbuf3)); strmcat(tmpbuf3,tmpbuf1,sizeof(tmpbuf3)); } } packcount++; } if (totalfiles) { if (totalbytes>1048575) { byteschar='M'; mult=1024.0; } else { byteschar='k'; mult=1.0; } snprintf(tmpbuf2,sizeof(tmpbuf2),"%.2f %cB/%d file%s", (float) (totalbytes)/(1024.0*mult),byteschar, totalfiles,totalfiles==1?empty_string:"s"); if (!queue) { if (!CTCPCloaking) send_to_server("NOTICE %s :%sent packs %s : %s",from, resend?"Res":"S",tmpbuf3,tmpbuf2); } else if (!CTCPCloaking) send_to_server("NOTICE %s :%sent packs %s : %s, %d file%s in queue", from,resend?"Res":"S",tmpbuf3,tmpbuf2,queue, queue==1?"":"s"); #ifdef WANTANSI snprintf(tmpbuf1,sizeof(tmpbuf1),"%sCdcc%s %s%ssent%s %s%s%s packs %s : ", CmdsColors[COLCDCC].color4,Colors[COLOFF], CmdsColors[COLCDCC].color3,resend?"re":"",Colors[COLOFF], CmdsColors[COLCDCC].color1,from,Colors[COLOFF],tmpbuf3); if (CdccVerbose==1) { if (!queue) say("%s[%s%s%s]",tmpbuf1, CmdsColors[COLCDCC].color5,tmpbuf2,Colors[COLOFF]); else say("%s[%s%s%s], %s%d%s file%s in queue",tmpbuf1, CmdsColors[COLCDCC].color5,tmpbuf2,Colors[COLOFF], CmdsColors[COLCDCC].color5,queue,Colors[COLOFF], queue==1?"":"s"); if (queuesent) say("%sCdcc%s %squeue%s is full", CmdsColors[COLCDCC].color4,Colors[COLOFF], CmdsColors[COLCDCC].color3,Colors[COLOFF]); } #else if (CdccVerbose==1) { if (!queue) say("Cdcc %ssent %s %s : [%s]",resend?"re":"", from,tmpbuf3,tmpbuf2); else say("Cdcc %ssent %s %s : [%s], %d file%s in queue", resend?"re":"",from,tmpbuf3,tmpbuf2,queue,queue==1?"":"s"); if (queuesent) say("Cdcc queue is full"); } #endif /****** Coded by Zakath ******/ #ifndef LITE if (CdccReqTog && CdccRequest) send_to_server("NOTICE %s :I need %s",from,CdccRequest); #endif /*****************************/ } if (queuesay && CdccVerbose==1) say("Duplicate files were not put in queue"); if (!sent && !CTCPCloaking) send_to_server("NOTICE %s :No packs found matching %s",from,word); } else if (!CTCPCloaking) send_to_server("NOTICE %s :Sorry, there are no files offered",from); } else if (!CTCPCloaking) send_to_server("NOTICE %s :Try /CTCP %s CDCC SEND N",from,get_server_nickname(from_server)); } /********************************************************************** * TotalSendDcc: Return Total Dcc Sends Currently on Dcc * * Linked List. * ***********************************************************************/ int TotalSendDcc() { DCC_list *Client; unsigned flags; int counter=0; for (Client=ClientList;Client;Client=Client->next) { flags=Client->flags; if (flags&DCC_DELETE) continue; if (((flags&DCC_TYPES)==DCC_FILEOFFER) || ((flags&DCC_TYPES)==DCC_RESENDOFFER)) counter++; } return(counter); } /* return number of files in queue */ int TotalQueue() { int count=0; FileQueue *tmp; for (tmp=queuelist;tmp;tmp=tmp->next) count++; return(count); } /* get offer files if auto-get is on */ void CheckAutoGet(nick,userhost,file,type) char *nick; char *userhost; char *file; char *type; { char tmpbuf[mybufsize/4]; struct friends *tmpfriend; if (Security) { snprintf(tmpbuf,sizeof(tmpbuf),"%s!%s",nick,userhost); tmpfriend=CheckUsers(tmpbuf,NULL); if (!tmpfriend) return; if (!((tmpfriend->privs)&FLCDCC)) return; } #ifdef WANTANSI snprintf(tmpbuf,sizeof(tmpbuf),"%sCdcc%s %sauto getting%s %s%s%s from ", CmdsColors[COLCDCC].color4,Colors[COLOFF], CmdsColors[COLCDCC].color3,Colors[COLOFF], CmdsColors[COLCDCC].color5,file,Colors[COLOFF]); say("%s%s%s%s",tmpbuf,CmdsColors[COLCDCC].color1,nick,Colors[COLOFF]); #else say("Cdcc auto getting %s from %s",file,nick); #endif if (away_set || LogOn) { snprintf(tmpbuf,sizeof(tmpbuf),"Cdcc auto getting %s from %s (%s)",file,nick,FromUserHost); AwaySave(tmpbuf,SAVECDCC); } snprintf(tmpbuf,sizeof(tmpbuf),"%s \"%s\"",nick,file); if (!my_stricmp(type,"SEND")) dcc_getfile(tmpbuf); else if (!my_stricmp(type,"RESEND")) dcc_regetfile(tmpbuf); #ifdef BROKEN_MIRC_RESUME else if (!my_stricmp(type,"RESUME")) dcc_getfile_resume(tmpbuf); #endif /* BROKEN_MIRC_RESUME */ } /********************************************************************** * CheckCdccTimer: Checks pending Cdcc timer stuff * ***********************************************************************/ void CheckCdccTimers() { int current=0; int oldserver; char *tmpstr; char *channel; #ifdef WANTANSI char tmpbuf1[mybufsize]; char tmpbuf2[mybufsize]; #endif time_t timenow; unsigned flags; DCC_list *Client; ChannelList *chan; timenow=time((time_t *) 0); if (timenow-LastIdleCheck>=60) { LastIdleCheck=timenow; for (Client=ClientList;CdccIdle && Client;Client=Client->next) { flags=Client->flags; if (!(flags&DCC_ACTIVE)) { tmpstr=rindex(Client->description,'/'); if (tmpstr) tmpstr++; else tmpstr=Client->description; if ((flags&DCC_TYPES)==DCC_FILEOFFER || (flags&DCC_TYPES)==DCC_RESENDOFFER) { if (timenow-Client->CdccTime>CdccIdle) { #ifdef WANTANSI snprintf(tmpbuf1,sizeof(tmpbuf1),"%sCdcc%s %sclosing%s idle dcc %s%s%s", CmdsColors[COLCDCC].color4,Colors[COLOFF], CmdsColors[COLCDCC].color3,Colors[COLOFF], CmdsColors[COLCDCC].color3,dcc_types[flags&DCC_TYPES], Colors[COLOFF]); snprintf(tmpbuf2,sizeof(tmpbuf2)," %s%s%s to %s%s%s", CmdsColors[COLCDCC].color5,tmpstr,Colors[COLOFF], CmdsColors[COLCDCC].color1,Client->user,Colors[COLOFF]); say("%s%s",tmpbuf1,tmpbuf2); #else say("Cdcc closing idle dcc %s %s to %s", dcc_types[flags&DCC_TYPES],tmpstr,Client->user); #endif if (!CTCPCloaking) { oldserver=from_server; from_server=Client->server; if (CheckServer(from_server)) send_to_server("NOTICE %s :Cdcc %s %s auto closed.", Client->user,dcc_types[flags&DCC_TYPES], tmpstr); from_server=oldserver; } dcc_erase(Client); } } else if (timenow-Client->CdccTime>3*CdccIdle) { #ifdef WANTANSI snprintf(tmpbuf1,sizeof(tmpbuf1),"%sCdcc%s %sclosing%s idle dcc %s%s%s", CmdsColors[COLCDCC].color4,Colors[COLOFF], CmdsColors[COLCDCC].color3,Colors[COLOFF], CmdsColors[COLCDCC].color3,dcc_types[flags&DCC_TYPES], Colors[COLOFF]); snprintf(tmpbuf2,sizeof(tmpbuf2)," %s%s%s from %s%s%s", CmdsColors[COLCDCC].color5,tmpstr,Colors[COLOFF], CmdsColors[COLCDCC].color1,Client->user,Colors[COLOFF]); say("%s%s",tmpbuf1,tmpbuf2); #else say("Cdcc closing idle dcc %s %s from %s",dcc_types[flags&DCC_TYPES], tmpstr,Client->user); #endif dcc_erase(Client); } } } } if (curr_scr_win->server!=-1) { chan=server_list[curr_scr_win->server].chan_list; if (packs && CdccChannels && PlistTime && timenow-LastPlist>PlistTime) { if (!my_stricmp(CdccChannels,"current")) { channel=get_channel_by_refnum(0); if (!channel) current=-1; else { current=1; chan=lookup_channel(channel,from_server,0); } } if (current!=-1) doplist(CdccChannels,current,chan); } if (packs && CdccChannels && NlistTime && timenow-LastNlist>NlistTime) { if (!my_stricmp(CdccChannels,"current")) { channel=get_channel_by_refnum(0); if (!channel) current=-1; else { current=1; chan=lookup_channel(channel,from_server,0); } } if (current!=-1) donotice(CdccChannels,current,chan); } } } /********************************************************************** * CheckDCCSpeed: Checks the pending DCC speed * ***********************************************************************/ void CheckDCCSpeed(Client,timenow) DCC_list *Client; time_t timenow; { int oldserver; float rate=-1.0; char *tmpstr; #ifdef WANTANSI char tmpbuf1[mybufsize/4]; char tmpbuf2[mybufsize/4]; #endif if (timenow-Client->starttime) rate=((float) (Client->bytes_sent)/(float)(timenow-Client->starttime))/1024.0; if (rate>=0.0 && rateminspeed) { tmpstr=rindex(Client->description,'/'); if (tmpstr) tmpstr++; #ifdef WANTANSI snprintf(tmpbuf1,sizeof(tmpbuf1),"%sCdcc%s %sclosing%s slow dcc %s%s%s ", CmdsColors[COLCDCC].color4,Colors[COLOFF], CmdsColors[COLCDCC].color3,Colors[COLOFF], CmdsColors[COLCDCC].color3,dcc_types[Client->flags&DCC_TYPES], Colors[COLOFF]); snprintf(tmpbuf2,sizeof(tmpbuf2),"%s%s%s%s to %s%s%s (%srate %.2f", tmpbuf1,CmdsColors[COLCDCC].color5,tmpstr,Colors[COLOFF], CmdsColors[COLCDCC].color1,Client->user,Colors[COLOFF], CmdsColors[COLCDCC].color5,rate); say("%skB/s%s/%smin %.2f kB/s%s)",tmpbuf2,Colors[COLOFF], CmdsColors[COLCDCC].color5,Client->minspeed,Colors[COLOFF]); #else say("Cdcc closing slow dcc %s %s to %s (rate %.2f kB/s/min %.2f kB/s)", dcc_types[Client->flags&DCC_TYPES],tmpstr,Client->user,rate, Client->minspeed); #endif if (!CTCPCloaking) { oldserver=from_server; from_server=Client->server; if (CheckServer(from_server)) send_to_server("NOTICE %s :Cdcc %s %s auto closed, dcc was too slow (rate %.2f kB/s/min %.2f kB/s)", Client->user,dcc_types[Client->flags&DCC_TYPES],tmpstr, rate,Client->minspeed); from_server=oldserver; } Client->flags|=DCC_DELETE; } else { if (rate>4*Client->minspeed) Client->CdccTime+=25L; else if (rate>2*Client->minspeed) Client->CdccTime+=20L; else Client->CdccTime+=15L; } } /********************************************************************** * AddToQueue: Adds file to queue * ***********************************************************************/ static int AddToQueue(tmpfile,nick,flag) Files *tmpfile; char *nick; int flag; { int count=0; char *spath; char tmpbuf[mybufsize/4]; DCC_list *Client; FileQueue *tmp; FileQueue *newfile; count=TotalQueue(); if (CdccQueueLimit>0 && count>=CdccQueueLimit) return(0); snprintf(tmpbuf,sizeof(tmpbuf),"%s/%s",tmpfile->path,tmpfile->file); /* check if nick/file combination is already in DCC list */ for (Client=ClientList;Client;Client=Client->next) { /* we're only interested in filename so we strip path */ if ((spath=rindex(Client->description,'/'))) spath++; else spath=Client->description; if (!strcmp(tmpfile->file,spath) && !my_stricmp(nick,Client->user)) return(-1); } /* check if nick/file combination is already in queue */ for (tmp=queuelist;tmp;tmp=tmp->next) if (!strcmp(tmpbuf,tmp->file) && !my_stricmp(nick,tmp->nick)) return(-1); newfile=(FileQueue *) new_malloc(sizeof(FileQueue)); newfile->server=from_server; newfile->file=(char *) 0; newfile->nick=(char *) 0; newfile->next=(FileQueue *) 0; malloc_strcpy(&(newfile->file),tmpbuf); malloc_strcpy(&(newfile->nick),nick); newfile->flag=flag; if (!queuelist) queuelist=newfile; else { for (tmp=queuelist;tmp && tmp->next;) tmp=tmp->next; tmp->next=newfile; } return(1); } /********************************************************************** * RemoveFromQueue: Removes file from queue * ***********************************************************************/ void RemoveFromQueue(removed) int removed; { int active=TotalSendDcc()-removed; int oldserver; char tmpbuf[mybufsize/4]; unsigned int display; FileQueue *tmp=queuelist; while (tmp && activenext; snprintf(tmpbuf,sizeof(tmpbuf),"%s \"%s\"",tmp->nick,tmp->file); display=window_display; window_display=0; oldserver=from_server; from_server=tmp->server; if (CheckServer(from_server)) { if (tmp->flag==1) dcc_filesend(tmpbuf); else dcc_resend(tmpbuf); active++; } from_server=oldserver; window_display=display; new_free(&(tmp->nick)); new_free(&(tmp->file)); new_free(&tmp); tmp=queuelist; } } /********************************************************************** * CdccQueueNickChange: Handle nick change * ***********************************************************************/ void CdccQueueNickChange(oldnick,newnick) char *oldnick; char *newnick; { FileQueue *tmp=queuelist; for (tmp=queuelist;tmp;tmp=tmp->next) { if (tmp->server!=from_server) continue; if (!my_stricmp(tmp->nick,oldnick)) malloc_strcpy(&(tmp->nick),newnick); } } /********************************************************************** * CleanUpCdcc: Free all allocated memory * ***********************************************************************/ void CleanUpCdcc() { Files *tmpfile; Files *tmpfilefree; Packs *tmppack; Packs *tmppackfree; FileQueue *tmpqueue; FileQueue *tmpqueuefree; for (tmppack=packs;tmppack;) { tmppackfree=tmppack; tmppack=tmppack->next; for (tmpfile=tmppackfree->files;tmpfile;) { tmpfilefree=tmpfile; tmpfile=tmpfile->next; new_free(&(tmpfilefree->path)); new_free(&(tmpfilefree->file)); new_free(&tmpfilefree); } new_free(&(tmppackfree->description)); new_free(&tmppackfree); } for (tmpqueue=queuelist;tmpqueue;) { tmpqueuefree=tmpqueue; tmpqueue=tmpqueue->next; new_free(&(tmpqueuefree->nick)); new_free(&(tmpqueuefree->file)); new_free(&tmpqueuefree); } } void CdccTimeWarning() { say("Warning: your CDCC PLIST or NLIST timer is set below two hours."); say("Due to a lot of complaints about this the above timers have been"); say("increased to two hours. If you feel your values are apropriate"); say("enter the following commands:"); if (PlistTime<7200) { say("/CDCC PTIME %d",PlistTime); PlistTime=7200; } if (NlistTime<7200) { say("/CDCC NTIME %d",NlistTime); NlistTime=7200; } }