/* file subsystem */ #include #include #include #include #include #include #include "eggdrop.h" #ifdef NO_DIRENT_H #include #else #include #ifdef SVR4 #include #endif #endif extern struct dcc_t dcc[]; extern int dcc_total; extern char dccdir[]; extern char dccin[]; extern char botname[]; extern struct userrec *userlist; /* if this is true, don't bother with '.files' stuff */ int raw_files=0; /* maximum number of simultaneous file downloads allowed */ int dcc_limit=3; /* add a file to the catalog in '.files' */ /* dir is relative to dcc */ /* flag is one of these: */ #define NEWFILE 0 /* add file entry */ #define INCGOT 1 /* just increment got counter (ignore who,when) */ #define DELFILE 2 /* delete entry */ #define DESC 3 /* change desc (who), ignore when */ #define CHGFILE 4 /* change entry except got counter */ #define UPLOAD 5 /* add file entry as upload */ #define SETGOT 6 /* set the got counter (ignore who, when) */ void n_add_file(dir,nfn,who,when,flag) char *dir,*nfn,*who; time_t when; int flag; { FILE *f,*g; char s[161],fn[41],oldfn[81],nick[21],tm[21]; sprintf(s,"%s%s/.files",dccdir,dir); oldfn[0]=0; if (flag==UPLOAD) sprintf(s,"%s.files",dir); f=fopen(s,"r"); sprintf(s,"%s%s/.files.new",dccdir,dir); if (flag==UPLOAD) sprintf(s,"%s.files.new",dir); g=fopen(s,"w"); if (g==NULL) { fclose(f); return; } if (f!=NULL) while (!feof(f)) { fgets(s,120,f); if (s[strlen(s)-1]=='\n') s[strlen(s)-1]=0; if (!feof(f)) { split(fn,s); if (!fn[0]) { strcpy(fn,s); s[0]=0; } rmspace(fn); if ((!fn[0]) || (fn[0]==';') || (fn[0]=='#')) { fprintf(g,"%s %s\n",fn,s); /* ignore */ } else if (fn[0]=='-') { if (((flag==DESC) || (flag==DELFILE) || (flag==NEWFILE)) && (strcmp(nfn,oldfn)==0)) ; /* erase it (new file? erase old entry if there is one) */ else fprintf(g,"- %s\n",s); } else { if (strcmp(fn,nfn)==0) { rmspace(s); split(nick,s); rmspace(nick); rmspace(s); split(tm,s); rmspace(tm); rmspace(s); if (flag==CHGFILE) fprintf(g,"%-30s %-10s%lu %s\n",fn,who,when,s); else if (flag==INCGOT) fprintf(g,"%-30s %-10s%s %d\n",fn,nick,tm,atoi(s)+1); else if (flag==SETGOT) fprintf(g,"%-30s %-10s%s %d\n",fn,nick,tm,(int)when); else if ((flag!=DELFILE) && (flag!=NEWFILE)) fprintf(g,"%-30s %-10s%s %s\n",fn,nick,tm,s); if ((flag==DESC) && (who[0])) { /* add description (may have embedded newlines - |) */ /* limit to 5 lines! anyone else needs to get a life!! */ char *rest,unit[512]; int lin=0; rest=(char *)nmalloc(strlen(who)+1); strcpy(rest,who); splitc(unit,rest,'|'); if (!unit[0]) { strcpy(unit,rest); rest[0]=0; } while (unit[0]) { if (strlen(unit)>60) { /* line too long, truncate at last space */ char *p=&unit[60]; while ((*p!=' ')&&(p!=unit)) p--; if (p==unit) unit[60]=0; /* no space, then truncate */ else { char *rest2; rest2=(char *)nmalloc(strlen(p+1)+strlen(rest)+2); strcpy(rest2,p+1); strcat(rest2,"|"); strcat(rest2,rest); nfree(rest); rest=rest2; /* i'm cornfuselfied */ *p=0; } } rmspace(unit); if ((lin<5) && (unit[0])) { fprintf(g,"- %s\n",unit); lin++; } splitc(unit,rest,'|'); if (!unit[0]) { strcpy(unit,rest); rest[0]=0; } } nfree(rest); } } else { rmspace(s); fprintf(g,"%-30s %s\n",fn,s); } strcpy(oldfn,fn); } } } if (f!=NULL) fclose(f); if ((flag==NEWFILE) || (flag==UPLOAD)) fprintf(g,"%-30s %-10s%lu 0\n",nfn,who,when); fclose(g); sprintf(s,"%s%s/.files",dccdir,dir); if (flag==UPLOAD) sprintf(s,"%s.files",dir); unlink(s); if (flag==UPLOAD) { char sx[121]; sprintf(s,"%s.files.new",dir); sprintf(sx,"%s.files",dir); #ifdef RENAME rename(s,sx); #else movefile(s,sx); #endif } else { char sx[121]; sprintf(s,"%s%s/.files.new",dccdir,dir); sprintf(sx,"%s%s/.files",dccdir,dir); #ifdef RENAME rename(s,sx); #else movefile(s,sx); #endif } } void add_file(dir,nfn,who,when,flag) char *dir,*nfn,*who; time_t when; int flag; { if (!(raw_files)) n_add_file(dir,nfn,who,when,flag); } int is_file(s) char *s; { struct stat ss; int i=stat(s,&ss); if (i<0) return 0; if ((ss.st_mode&S_IFREG) || (ss.st_mode&S_IFLNK)) return 1; return 0; } /* return true if this user has >= the maximum number of file xfers going */ int at_limit(nick) char *nick; { int i,x=0; for (i=0; i=dcc_limit); } /* is this file listed in the '.files' for this dir? */ int in_files(dir,check) char *dir,*check; { FILE *f; char s[161],fn[41]; if (raw_files) { sprintf(s,"%s%s/%s",dccdir,dir,check); return is_file(s); } sprintf(s,"%s%s/.files",dccdir,dir); f=fopen(s,"r"); if (f==NULL) return 0; while (!feof(f)) { fgets(s,120,f); if (s[strlen(s)-1]=='\n') s[strlen(s)-1]=0; if (!feof(f)) { split(fn,s); if (!fn[0]) { strcpy(fn,s); s[0]=0; } rmspace(fn); if ((!fn[0]) || (fn[0]==';') || (fn[0]=='#') || (fn[0]=='-')) { /* ignore */ } else if (strcmp(fn,check)==0) { fclose(f); return 1; } } } fclose(f); return 0; } /* get the name of the person who uploaded a certain file */ void get_file_owner(dir,file,owner) char *dir,*file,*owner; { FILE *f; char s[161],fn[41]; if (raw_files) { strcpy(owner,"HQ"); return; } sprintf(s,"%s%s/.files",dccdir,dir); f=fopen(s,"r"); if (f==NULL) { owner[0]=0; return; } while (!feof(f)) { fgets(s,120,f); if (s[strlen(s)-1]=='\n') s[strlen(s)-1]=0; if (!feof(f)) { nsplit(fn,s); rmspace(fn); if ((!fn[0]) || (fn[0]==';') || (fn[0]=='#') || (fn[0]=='-')) { /* ignore */ } else if (strcmp(fn,file)==0) { rmspace(s); nsplit(owner,s); rmspace(owner); fclose(f); return; } } } fclose(f); owner[0]=0; return; } void copy_desc(oldpath,oldfn,newpath,newfn) char *oldpath,*oldfn,*newpath,*newfn; { FILE *f; char s[161],fn[41],lastfn[41],desc[4096],owner[41],tm[41]; /* bug: description limited to 4096 chars max (a bit over 60 lines) */ int gots; if (raw_files) return; lastfn[0]=0; desc[0]=0; owner[0]=0; sprintf(s,"%s%s/.files",dccdir,oldpath); f=fopen(s,"r"); if (f==NULL) return; while (!feof(f)) { fgets(s,120,f); if (s[strlen(s)-1]=='\n') s[strlen(s)-1]=0; if (!feof(f)) { split(fn,s); if (!fn[0]) { strcpy(fn,s); s[0]=0; } rmspace(fn); if ((!fn[0]) || (fn[0]==';') || (fn[0]=='#')) { /* skip */ } else if (fn[0]=='-') { if (strcmp(lastfn,oldfn)==0) { if (desc[0]) strcat(desc,"|"); strcat(desc,s); } } else { strcpy(lastfn,fn); if (strcmp(fn,oldfn)==0) { rmspace(s); nsplit(owner,s); rmspace(owner); rmspace(s); nsplit(tm,s); rmspace(tm); gots=atoi(s); } } } } fclose(f); if (owner[0]) { add_file(newpath,newfn,owner,atol(tm),NEWFILE); add_file(newpath,newfn,"(broke)",(int)gots,SETGOT); if (desc[0]) add_file(newpath,newfn,desc,0,DESC); } } /* attempt to match a wildcard-string against all filenames in a directory (the raw directory, not the ".files" record) */ /* if start is not null, it will find the first match AFTER that file */ /* next match is returned in match, or match[0]=0 if no other matches */ void _get_file_match(dir,match,strt,found,allowdir) char *dir,*strt,*match,*found; int allowdir; { DIR *dr; int start=0; struct dirent *dd; struct stat ss; char s1[161]; dr=opendir(dir); if (dr==NULL) { found[0]=0; return; } if (strt==NULL) start=1; do { dd=readdir(dr); if (dd!=NULL) { if (dd->d_name[0]=='.') { /* ignore hidden files and '.' and '..' */ } else if (!start) { if (strcmp(dd->d_name,strt)==0) start=1; } else { if (wild_match_file(match,dd->d_name)) { sprintf(s1,"%s/%s",dir,dd->d_name); stat(s1,&ss); if ((allowdir) || (!(ss.st_mode&S_IFDIR))) { strcpy(found,dd->d_name); closedir(dr); return; } } } } } while (dd!=NULL); found[0]=0; closedir(dr); return; } void get_file_match(d,m,s,f) char *d,*m,*s,*f; { _get_file_match(d,m,s,f,0); } void get_filed_match(d,m,s,f) char *d,*m,*s,*f; { _get_file_match(d,m,s,f,1); } int is_dir(s) char *s; { struct stat ss; int i=stat(s,&ss); if (i<0) return 0; if (ss.st_mode&S_IFDIR) return 1; return 0; } int get_reqflags_dir(root,dir) char *root,*dir; { char rootx[161],s[121],fn[81],atrs[21]; FILE *f; strcpy(rootx,root); if (root[0]) if (root[strlen(root)-1]!='/') strcat(rootx,"/"); sprintf(fn,"%s%s.files",dccdir,rootx); f=fopen(fn,"r"); if (f==NULL) return 0; while (!feof(f)) { fgets(s,120,f); if (!feof(f)) { if (s[strlen(s)-1]=='\n') s[strlen(s)-1]=0; rmspace(s); if ((s[0]!=';') && (s[0]!='#')) { /* not comment */ nsplit(fn,s); rmspace(s); if (fn[strlen(fn)-1]=='/') { /* directory! */ fn[strlen(fn)-1]=0; if (strcmp(fn,dir)==0) { fclose(f); nsplit(atrs,s); if (atrs[0]=='+') return str2flags(atrs); return 0; } } } } } fclose(f); return 0; } int resolve_dir(old,nnew,real,atr) char *old,*nnew,*real; int atr; { char elem[512],s[1024],new[1024],*p; strcpy(real,old); strcpy(new,nnew); if (!new[0]) return 0; if (new[0]=='/') { /* EVERYONE has access here */ real[0]=0; strcpy(new,&new[1]); } /* cycle thru the elements */ strcat(new,"/"); p=strchr(new,'/'); while (p!=NULL) { *p=0; p++; strcpy(elem,new); strcpy(new,p); if (strcmp(elem,".")==0) { /* do nothing */ } else if (strcmp(elem,"..")==0) { /* go back */ /* always allowed */ p=strrchr(real,'/'); if (p==NULL) { if (!real[0]) { strcpy(real,old); return -1; } real[0]=0; } else *p=0; } else { /* allowed access here? */ if (!flags_ok(get_reqflags_dir(real,elem),atr)) { strcpy(real,old); return -1; } strcpy(s,real); if (s[0]) if (s[strlen(s)-1]!='/') strcat(s,"/"); sprintf(real,"%s%s",s,elem); sprintf(s,"%s%s",dccdir,real); if (!is_dir(s)) { strcpy(real,old); return -1; } } p=strchr(new,'/'); } return 0; } /* show file listing in this dir */ void n_tell_files(z,dr,match,atr) int z; char *dr,*match; int atr; { FILE *f; char nick[10],fn[40],tm[40],s[121],s1[121],dir[161]; struct stat ss; time_t t; int i,cnt=0,ismatch; strcpy(dir,dr); if (dir[strlen(dir)-1]!='/') strcat(dir,"/"); /* is target a directory? */ sprintf(s,"%s%s",dir,match); if (is_dir(s)) { strcat(dir,match); if (dir[strlen(dir)-1]!='/') strcat(dir,"/"); strcpy(match,"*"); } sprintf(s,"%s.files",dir); ismatch=1; f=fopen(s,"r"); if (f==NULL) { tprintf(z,"No files in this directory.\n"); return; } while (!feof(f)) { fgets(s,120,f); if (s[strlen(s)-1]=='\n') s[strlen(s)-1]=0; if (!feof(f)) { split(fn,s); if (!fn[0]) { strcpy(fn,s); s[0]=0; } rmspace(fn); rmspace(s); if ((!fn[0]) || (fn[0]=='#') || (fn[0]==';')) /* comment */ ; else if ((fn[0]=='-') && ismatch) { tprintf(z," %s\n",s); } else { if (wild_match_file(match,fn)) { ismatch=1; /* directory? allowed to see it? */ if (fn[strlen(fn)-1]=='/') { int req; nsplit(nick,s); if (nick[0]=='+') { req=str2flags(nick); if (!flags_ok(req,atr)) ismatch=0; } } if (ismatch) { if (cnt==0) { tprintf(z,"Filename Size Sent by/date # Gets\n"); tprintf(z,"------------------------------ ---- ------------------- ------\n"); } sprintf(s1,"%s%s",dir,fn); cnt++; if (s1[strlen(s1)-1]=='/') s1[strlen(s1)-1]=0; i=stat(s1,&ss); if (i<0) { /* missing! */ tprintf(z,"%-30s *** MISSING ***\n",fn); } else if (ss.st_mode&S_IFDIR) { /* directory */ if ((atr&USER_MASTER) && (nick[0]=='+')) tprintf(z,"%-30s (requires %s)\n",fn,nick); else tprintf(z,"%-30s \n",fn); } else { split(nick,s); rmspace(nick); rmspace(s); split(tm,s); rmspace(tm); rmspace(s); if (!tm[0]) { strcpy(tm,s); s[0]=0; } t=atol(tm); strcpy(tm,ctime(&t)); s1[0]=tm[8]; s1[1]=tm[9]; s1[2]=0; tm[7]=0; strcat(s1,&tm[4]); tm[24]=0; strcat(s1,&tm[22]); strcpy(tm,s1); i=ss.st_size; if (i<1024) sprintf(s1,"%5d",i); else sprintf(s1,"%4dk",(int)(i/1024)); tprintf(z,"%-30s %s %-9s (%s) %6d\n",fn,s1,nick,tm,atoi(s)); } } } else ismatch=0; } } } fclose(f); if (cnt==0) tprintf(z,"No files in this directory.\n"); else tprintf(z,"--- %d file%s.\n",cnt,cnt>1?"s":""); } void raw_tell_files(z,dr,match) int z; char *dr,*match; { char dir[161],s[161],s1[121],find[81],last[81]; int cnt=0,i; struct stat ss; strcpy(dir,dr); if (dir[strlen(dir)-1]!='/') strcat(dir,"/"); /* is target a directory? */ sprintf(s,"%s%s",dir,match); if (is_dir(s)) { strcat(dir,match); if (dir[strlen(dir)-1]!='/') strcat(dir,"/"); strcpy(match,"*"); } get_filed_match(dir,match,NULL,find); if (!find[0]) { tprintf(z,"No files in this directory.\n"); return; } while (find[0]) { if (cnt==0) { tprintf(z,"Filename Size\n"); tprintf(z,"--------------------------------------------- ----\n"); } sprintf(s1,"%s%s",dir,find); i=stat(s1,&ss); if (ss.st_mode&S_IFDIR) tprintf(z,"%-45s \n",find); else { i=ss.st_size; if (i<1024) sprintf(s1,"%5d",i); else sprintf(s1,"%4dk",(int)(i/1024)); tprintf(z,"%-45s %s\n",find,s1); } cnt++; strcpy(last,find); get_filed_match(dir,match,last,find); } if (cnt==0) tprintf(z,"No files in this directory.\n"); else tprintf(z,"--- %d file%s.\n",cnt,cnt>1?"s":""); } void cmd_chdir(idx,z,msg) int z,idx; char *msg; { char elem[81],olddir[121],s[121],*p; FILE *f; int atr; atr=get_attr_handle(dcc[idx].nick); if (resolve_dir(dcc[idx].u.file->dir,msg,s,atr)<0) { tprintf(z,"No such dir.\n"); return; } strcpy(dcc[idx].u.file->dir,s); set_handle_dccdir(userlist,dcc[idx].nick,dcc[idx].u.file->dir); log(LOG_FILES,"files: #%s# cd /%s",dcc[idx].nick,dcc[idx].u.file->dir); tprintf(z,"Now in: /%s\n",dcc[idx].u.file->dir); if (dcc[idx].u.file->chat->status&STAT_TALK) tprintf(z,"/// PROMPT /%s\n",dcc[idx].u.file->dir); } void relative_dir(s) char *s; { strcpy(s,&s[strlen(dccdir)]); } void uploaded(s,nick,dir) char *s,*nick,*dir; { add_file(dir,s,nick,time(NULL),UPLOAD); } void welcome_to_files(idx,z) { tprintf(z,"\n"); /* show motd if the user went straight here without going thru the party line */ if (!(dcc[idx].u.file->chat->status&STAT_CHAT)) show_motd(idx); telltext(idx,"files",dcc[idx].u.file->chat->status&STAT_CHAT, dcc[idx].u.file->chat->status&STAT_MASTER); get_handle_dccdir(dcc[idx].nick,dcc[idx].u.file->dir); if (dcc[idx].u.file->chat->status&STAT_TALK) { tprintf(z,"/// PROMPT /%s\n",dcc[idx].u.file->dir); tprintf(z,"/// ECHO ON\n"); } tprintf(z,"Current directory: /%s\n\n",dcc[idx].u.file->dir); } void cmd_import(idx,z,arg) int z,idx; char *arg; { char last[121],what[512],match[121],s[121]; int ok=0; if (raw_files) { tprintf(z,"This command has no meaning in raw-files mode.\n"); return; } nsplit(what,arg); sprintf(s,"%s%s",dccdir,dcc[idx].u.file->dir); if (what[strlen(what)-1]=='/') what[strlen(what)-1]=0; /* ^ importing a directory, by name */ get_filed_match(s,what,NULL,match); if (!match[0]) { tprintf(z,"No matching files found in this directory.\n"); return; } while (match[0]) { sprintf(s,"%s%s/%s",dccdir,dcc[idx].u.file->dir,match); if (is_dir(s)) strcat(match,"/"); if (!in_files(dcc[idx].u.file->dir,match)) { if (is_dir(s)) { char s[21]; int i; tprintf(z,"Imported: %s\n",match); if (arg[0]) { s[0]='+'; i=str2flags(arg); flags2str(i,&s[1]); tprintf(z," (requires %s to access)\n",s); } else s[0]=0; add_file(dcc[idx].u.file->dir,match,s,0,NEWFILE); } else { add_file(dcc[idx].u.file->dir,match,dcc[idx].nick,time(NULL),NEWFILE); tprintf(z,"Imported: %s\n",match); } ok++; } if (match[strlen(match)-1]=='/') match[strlen(match)-1]=0; strcpy(last,match); sprintf(s,"%s%s",dccdir,dcc[idx].u.file->dir); get_filed_match(s,what,last,match); } if (!ok) tprintf(z,"No matching files found in this directory.\n"); else { log(LOG_FILES,"files: #%s# import %s",dcc[idx].nick,what); if ((strchr(what,'?')!=NULL) || (strchr(what,'*')!=NULL)) tprintf(z,"Total of %d file%s imported.\n",ok,ok==1?"":"s"); } } void cmd_get(idx,z,par) int idx,z; char *par; { char *p,what[121],last[121],match[121],s[121]; int ok=0,atr; atr=get_attr_handle(dcc[idx].nick); nsplit(what,par); /* anything left in par is a new nickname */ sprintf(s,"%s%s",dccdir,dcc[idx].u.file->dir); p=strrchr(what,'/'); if (p!=NULL) { char s1[121]; *p=0; strcpy(s,what); strcpy(what,p+1); if (resolve_dir(dcc[idx].u.file->dir,s,s1,atr)<0) { tprintf(z,"Illegal directory.\n"); return; } sprintf(s,"%s%s",dccdir,s1); } get_file_match(s,what,NULL,match); if (!match[0]) { tprintf(z,"No matching files found in this directory.\n"); return; } while (match[0]) { if (in_files(dcc[idx].u.file->dir,match)) { char xx[121]; ok=1; if (par[0]) sprintf(xx,"%s %s",match,par); else strcpy(xx,match); if (do_dcc_send(idx,z,dcc[idx].u.file->dir,xx)) add_file(dcc[idx].u.file->dir,match,"",0,INCGOT); } strcpy(last,match); get_file_match(s,what,last,match); } if (!ok) tprintf(z,"No matching files found in this directory.\n"); else log(LOG_FILES,"files: #%s# get %s %s",dcc[idx].nick,what,par); } void cmd_ls(idx,z,par) int idx,z; char *par; { char s[161],s1[161],*p; int atr; atr=get_attr_handle(dcc[idx].nick); sprintf(s,"%s%s",dccdir,dcc[idx].u.file->dir); if (par[0]) { log(LOG_FILES,"files: #%s# ls %s",dcc[idx].nick,par); p=strrchr(par,'/'); if (p!=NULL) { *p=0; strcpy(s,par); strcpy(par,p+1); if (resolve_dir(dcc[idx].u.file->dir,s,s1,atr)<0) { tprintf(z,"Illegal directory.\n"); return; } sprintf(s,"%s%s",dccdir,s1); } if (raw_files) raw_tell_files(z,s,par); else n_tell_files(z,s,par,atr); } else { log(LOG_FILES,"files: #%s# ls",dcc[idx].nick); if (raw_files) raw_tell_files(z,s,"*"); else n_tell_files(z,s,"*",atr); } } void cmd_file_help(idx,z,par) int idx,z; char *par; { char s[121]; if (par[0]) { log(LOG_FILES,"files: #%s# help %s",dcc[idx].nick,par); sprintf(s,"files.%s",par); tellhelp(idx,s,dcc[idx].u.file->chat->status&STAT_CHAT, dcc[idx].u.file->chat->status&STAT_MASTER); } else { log(LOG_FILES,"files: #%s# help",dcc[idx].nick); tellhelp(idx,"files.help",dcc[idx].u.file->chat->status&STAT_CHAT, dcc[idx].u.file->chat->status&STAT_MASTER); } } void cmd_pwd(idx,z,par) int idx,z; char *par; { log(LOG_FILES,"files: #%s# pwd",dcc[idx].nick); tprintf(z,"Current directory: /%s\n",dcc[idx].u.file->dir); } void cmd_desc(idx,z,par) int idx,z; char *par; { char fn[512],owner[41],s[256],match[81],last[81]; int ok=0; if (raw_files) { tprintf(z,"This command has no meaning in raw-files mode.\n"); return; } nsplit(fn,par); if (!fn[0]) { tprintf(z,"Usage: desc \n"); return; } sprintf(s,"%s%s",dccdir,dcc[idx].u.file->dir); get_file_match(s,fn,NULL,match); if (!match[0]) { tprintf(z,"No matching files found in this directory.\n"); return; } while (match[0]) { if (in_files(dcc[idx].u.file->dir,match)) { ok=1; if (!(dcc[idx].u.file->chat->status&STAT_MASTER)) { get_file_owner(dcc[idx].u.file->dir,match,owner); if (strcasecmp(owner,dcc[idx].nick)!=0) tprintf(z,"Skipping: %s (you didn't upload it)\n",match); else { add_file(dcc[idx].u.file->dir,match,par,0,DESC); if (par[0]) tprintf(z,"Changed: %s\n",match); else tprintf(z,"Blanked: %s\n",match); } } else { add_file(dcc[idx].u.file->dir,match,par,0,DESC); if (par[0]) tprintf(z,"Changed: %s\n",match); else tprintf(z,"Blanked: %s\n",match); } } strcpy(last,match); get_file_match(s,fn,last,match); } if (!ok) tprintf(z,"No matching files found in this directory.\n"); else log(LOG_FILES,"files: #%s# desc %s %s",dcc[idx].nick,fn,par); } void cmd_hide(idx,z,par) int idx,z; char *par; { FILE *f; char s[161],fn[41]; int ok=0; if (raw_files) { tprintf(z,"This command has no meaning in raw-files mode.\n"); return; } sprintf(s,"%s%s/.files",dccdir,dcc[idx].u.file->dir); f=fopen(s,"r"); if (f==NULL) { tprintf(z,"No files to hide.\n"); return; } while (!feof(f)) { fgets(s,120,f); rmspace(s); if (!feof(f)) { nsplit(fn,s); rmspace(fn); if ((!fn[0]) || (fn[0]==';') || (fn[0]=='#') || (fn[0]=='-')) { /* ignore */ } else if (wild_match_file(par,fn)) { ok++; fclose(f); add_file(dcc[idx].u.file->dir,fn,"",0,DELFILE); tprintf(z,"Hidden: %s\n",fn); sprintf(s,"%s%s/.files",dccdir,dcc[idx].u.file->dir); f=fopen(s,"r"); } } } fclose(f); if (!ok) tprintf(z,"No matching files found.\n"); else { log(LOG_FILES,"files: #%s# hide %s",dcc[idx].nick,par); if (ok>1) tprintf(z,"Hid %d files.\n",ok); } } void cmd_rm(idx,z,par) int idx,z; char *par; { char s[161],s1[161],match[121]; int ok; sprintf(s,"%s%s",dccdir,dcc[idx].u.file->dir); get_file_match(s,par,NULL,match); ok=0; if (!match[0]) { tprintf(z,"No matching files found.\n"); return; } while (match[0]) { sprintf(s1,"%s%s/%s",dccdir,dcc[idx].u.file->dir,match); if (in_files(dcc[idx].u.file->dir,match)) { add_file(dcc[idx].u.file->dir,match,"",0,DELFILE); tprintf(z,"Erased: %s\n",match); } else tprintf(z,"Erased: %s (hidden)\n",match); unlink(s1); ok++; get_file_match(s,par,NULL,match); } if (!ok) tprintf(z,"No matching files found.\n"); else { log(LOG_FILES,"files: #%s# rm %s",dcc[idx].nick,par); if (ok>1) tprintf(z,"Erased %d files.\n",ok); } } void cmd_mv_cp(idx,z,par,copy) int idx,z; char *par; int copy; { char fn[512],*p,oldpath[161],s[161],newpath[161],newfn[161]; char match[121],last[121],s1[161]; int ok=0,atr; atr=get_attr_handle(dcc[idx].nick); split(fn,par); if (!fn[0]) { tprintf(z,"Usage: %s \n",copy?"cp":"mv"); return; } p=strrchr(fn,'/'); if (p!=NULL) { *p=0; strcpy(s,fn); strcpy(fn,p+1); if (resolve_dir(dcc[idx].u.file->dir,s,oldpath,atr)<0) { tprintf(z,"Illegal directory.\n"); return; } } else strcpy(oldpath,dcc[idx].u.file->dir); strcpy(s,par); if (resolve_dir(dcc[idx].u.file->dir,s,newpath,atr)<0) { /* destination is not just a directory */ p=strrchr(s,'/'); if (p==NULL) { strcpy(newfn,s); s[0]=0; } else { *p=0; strcpy(newfn,p+1); } if (resolve_dir(dcc[idx].u.file->dir,s,newpath,atr)<0) { tprintf(z,"Illegal destination directory.\n"); return; } } else newfn[0]=0; if ((strcmp(oldpath,newpath)==0) && ((!newfn[0]) || (strcmp(newfn,fn)==0))) { tprintf(z,"You can't %s files on top of themselves.\n",copy?"copy":"move"); return; } if (((strchr(fn,'?')!=NULL) || (strchr(fn,'*')!=NULL)) && (newfn[0])) { tprintf(z,"You can't %s multiple files to a single-file destination.\n", copy?"copy":"move"); return; } sprintf(s,"%s%s",dccdir,oldpath); get_file_match(s,fn,NULL,match); ok=0; if (!match[0]) { tprintf(z,"No matching files found.\n"); return; } while (match[0]) { if (in_files(oldpath,match)) { sprintf(s,"%s%s%s%s",dccdir,oldpath,oldpath[0]?"/":"",match); sprintf(s1,"%s%s%s%s",dccdir,newpath,newpath[0]?"/":"",newfn[0]? newfn:match); if (copyfile(s,s1)==0) { ok++; copy_desc(oldpath,match,newpath,newfn[0]?newfn:match); if (!copy) { unlink(s); add_file(oldpath,match,"",0,DELFILE); } tprintf(z,"%s /%s%s%s to /%s%s%s\n",copy?"Copied":"Moved",oldpath, oldpath[0]?"/":"",match,newpath,newpath[0]?"/":"", newfn[0]?newfn:match); } else tprintf(z,"Could not write /%s%s%s\n",newpath,newpath[0]?"/":"", newfn[0]?newfn:match); } strcpy(last,match); sprintf(s,"%s%s",dccdir,oldpath); if (copy) get_file_match(s,fn,last,match); else get_file_match(s,fn,NULL,match); /* ^ mv shouldn't stop till ALL matching files are GONE :) */ } if (!ok) tprintf(z,"No matching files found.\n"); else { log(LOG_FILES,"files: #%s# %s %s%s%s %s",dcc[idx].nick,copy?"cp":"mv", oldpath,oldpath[0]?"/":"",fn,par); if (ok>1) tprintf(z,"%s %d files.\n",copy?"Copied":"Moved",ok); } } void cmd_mv(idx,z,par) int idx,z; char *par; { cmd_mv_cp(idx,z,par,0); } void cmd_cp(idx,z,par) int idx,z; char *par; { cmd_mv_cp(idx,z,par,1); } void cmd_mkdir(idx,z,par) int idx,z; char *par; { char s[256],name[256]; int i; if (!par[0]) { tprintf(z,"Usage: mkdir [required-flags]\n"); return; } nsplit(name,par); if (name[strlen(name)-1]=='/') name[strlen(name)-1]=0; sprintf(s,"%s%s/%s",dccdir,dcc[idx].u.file->dir,name); if (mkdir(s,0755)==0) { strcat(name,"/"); tprintf(z,"Created directory /%s%s%s\n",dcc[idx].u.file->dir, dcc[idx].u.file->dir[0]?"/":"",name); if (par[0]) { s[0]='+'; i=str2flags(par); flags2str((i&USER_MASK),&s[1]); if (i&USER_FLAG1) strcat(s,"1"); if (i&USER_FLAG2) strcat(s,"2"); if (i&USER_FLAG3) strcat(s,"3"); if (i&USER_FLAG4) strcat(s,"4"); if (i&USER_FLAG5) strcat(s,"5"); tprintf(z,"Requires %s to access\n",s); } else s[0]=0; add_file(dcc[idx].u.file->dir,name,s,0,NEWFILE); log(LOG_FILES,"files: #%s# mkdir %s %s",dcc[idx].nick,name,par); return; } tprintf(z,"Failed.\n"); } void cmd_rmdir(idx,z,par) int idx,z; char *par; { char s[256]; if (!raw_files) sprintf(s,"%s%s/%s/.files",dccdir,dcc[idx].u.file->dir,par); unlink(s); /* remove the file table */ sprintf(s,"%s%s/%s",dccdir,dcc[idx].u.file->dir,par); if (rmdir(s)==0) { tprintf(z,"Removed directory /%s%s%s\n",dcc[idx].u.file->dir, dcc[idx].u.file->dir[0]?"/":"",par); add_file(dcc[idx].u.file->dir,par,"*",0,DELFILE); log(LOG_FILES,"files: #%s# rmdir %s",dcc[idx].nick,par); return; } tprintf(z,"Failed.\n"); } void cmd_pending(idx,z,par) int idx,z; char *par; { show_queued_files(idx,z); log(LOG_FILES,"#%s# pending",dcc[idx].nick); } void cmd_cancel(idx,z,par) int idx,z; char *par; { if (!par[0]) { tprintf(z,"Usage: cancel \n"); return; } fileq_cancel(idx,z,par); log(LOG_FILES,"files: #%s# cancel %s",dcc[idx].nick,par); }