#define Use_TagList #define Use_LinkedList #include #include #include #include #include #include "proboard.hpp" struct InputFile { int area; String name; InputFile(); InputFile(char *s); InputFile(char *s , int area); }; const int MAX_DOWNLOADS = 100; void create_dirlist(int area,char *firstdir,LinkedList& dirlist); bool is_freefile(char *fname); bool send_files( protocol& p , LinkedList& files ,LinkedList& downloads , LinkedList& uploads); void read_personal_files( LinkedList& files ); void delete_personal_file( char *name ); void copy_cdrom( LinkedList &files , LinkedList &copied); void delete_copied ( LinkedList &copied); void process_uploads(protocol& p , char *dir , LinkedList& uploads , bool pvt , bool ask_desc , bool no_log , bool quiet_dl , String extra_log ); bool check_dszlog(protocol& p , LinkedList& downloads , LinkedList& uploads); bool create_dszctl(protocol& p , LinkedList& files); static void read_from_file(LinkedList& input_files , char *fn) { TextFile f(fn); if(f.opened()) { while(!f.eof()) { String s = f.readLine(); s.delLast('\n'); s.trim(); if(!s.len()) continue; input_files.add(InputFile(s)); } } } void download(char *data) { bool no_input = FALSE; bool any_file = FALSE; bool private_download = FALSE; bool free_time = FALSE; char protocol_key = '\0'; bool quiet_download = FALSE; bool goodbye = FALSE; bool ignore_kbytes = FALSE; bool no_log = FALSE; bool ask_description = TRUE; int npara; int i; long total_bytes; long free_bytes; String param[20]; BitArray arealist(MAX_FILE_AREAS,1); LinkedList files; LinkedList input_files; LinkedList copied_to_cd; protocol prot; FileName extra_log; npara = parse_data(data,param); // Parse command line create_arealist(param,npara,arealist); // Create list of selected file areas adjust_limits(); for(i=0 ; i dirlist; create_dirlist(idx.area,fa.filepath,dirlist); for( dirlist.rewind() ; !dirlist.eol() && files_found < MAX_DOWNLOADS ; dirlist++) { String wildcard = dirlist.get(); wildcard << idx.name; DirScan scan(wildcard); while(int(scan) && files_found < MAX_DOWNLOADS) { DownloadFile tmpfile; tmpfile.area = idx.area; tmpfile.size = scan.size(); tmpfile.free = FALSE; tmpfile.copy = !!fa.cdrom; tmpfile.name = dirlist.get() + scan.name(); files.add(tmpfile); files_found++; scan++; } } } } } else { LOG("Error opening FILESIDX.PB"); } } total_bytes = 0; free_bytes = 0; if(!quiet_download) { io << '\n'; if(files.count()) { io << '\n' << S_DOWNLOAD_FILES_FOUND_HEADER << '\n'; } for(files.rewind() ; !files.eol() ; ) { FileArea fa; FileName fn; String area_name; fn = files.get().name; fn.stripPath(); if(files.get().area) { fa.read(files.get().area); area_name = fa.name; } else { if(private_download) area_name = "Personal Files"; else area_name = "Global"; } io << S_DOWNLOAD_FILE_FOUND_ENTRY((char *)fn,form("%ld",(files.get().size+512L) / 1024L),(char *)area_name); files.get().free = (fa.free || is_freefile((char *)fn)); if((total_bytes - free_bytes + files.get().size + user.kbToday*1024L) > (1024L*download_limit) && !files.get().free) { io << S_FILE_EXCEEDS_LIMIT(form("%u",download_limit)) << '\n'; files.remove(); } else { if(upload_needed > 0 && !files.get().free) { io << S_UPLOAD_REQUIRED(form("%u",upload_needed)) << '\n'; files.remove(); } else { io << S_FILE_FOUND_ACTION_PROMPT; char action = wait_language_hotkeys(K_FILE_FOUND_ACTION_PROMPT); int prompt_len = language_string_length(S_FILE_FOUND_ACTION_PROMPT); io << String('\b',prompt_len) << String(' ',prompt_len) << String('\b',prompt_len); switch(action) { case '\r': case 0: { io << S_ACTION_DOWNLOAD << ' '; if(files.get().free) { io << S_FREE_FILE; free_bytes += files.get().size; } total_bytes += files.get().size; io << '\n'; files++; } break; case 1 : { io << S_ACTION_FILE_SKIPPED << '\n'; files.remove(); } break; case 2 : { io << S_ACTION_FILE_QUIT << '\n'; while(!files.eol()) files.remove(); } break; } } } } if(!files.count()) { io << '\n' << S_NO_FILES_FOUND << "\n\n" << S_PRESS_ENTER_TO_CONTINUE; return; } word estimated = word(total_bytes / ((io.baud ? io.baud:115200L) * (prot.efficiency?prot.efficiency:100)/1000L)); if(prot.flags & PROT_LOCAL) estimated = 0; io << '\n' << S_X_FILES_SELECTED(form("%d",files.count()),form("%d",int(total_bytes/1024)),form("%02u:%02u",estimated/60,estimated%60)) << '\n'; if(!free_time && estimated/60>timer.left()) { io << '\n' << S_NOT_ENOUGH_TIME_LEFT_FOR_DOWNLOAD << "\n\n" << S_PRESS_ENTER_TO_CONTINUE; return; } io << '\n' << S_START_DOWNLOAD_PROMPT; char k = wait_language_hotkeys(K_START_DOWNLOAD_PROMPT); if(k==2) return; if(k==1) { io << S_DOWNLOAD_ACTION_GOODBYE; goodbye = TRUE; } io << "\n\n"; copy_cdrom( files , copied_to_cd); io << "\n\n" << S_ACTIVATING_PROTOCOL << '\xFF'; } LinkedList downloads,uploads; if(free_time) timer.suspend(); if(!send_files(prot , files , downloads , uploads)) { delete_copied(copied_to_cd); return; } delete_copied(copied_to_cd); if(free_time) timer.restart(); total_bytes = 0; free_bytes = 0; files_found = 0; for(downloads.rewind() ; !downloads.eol() ; downloads++) { for(files.rewind() ; !files.eol() ; ) { FileName fn(files.get().name); fn.stripPath(); if(downloads.get() == fn) { total_bytes += files.get().size; if(files.get().free) free_bytes += files.get().size; remove_tag(fn,files.get().area); if(private_download) delete_personal_file(files.get().name); files_found++; File f; if(extra_log.len()) { f.open(extra_log,fmode_copen | fmode_text | fmode_append | fmode_write); f.printf("D %d %s %ld %s\n",files.get().area,(char *)files.get().name,files.get().size,files.get().free ? "YES":"NO"); f.close(); } if(!no_log) { f.open(FileName(syspath,"DOWNLOAD.LOG"),fmode_write | fmode_append | fmode_copen | fmode_text); f.printf("%05d %s\n",files.get().area,(char *)files.get().name); f.close(); LOG(1,"Download-%c %s",prot.key,(char *)fn); } files.remove(); } else { files++; } } } if(!ignore_kbytes) { user.numDownloads += files_found; user.kbDownloaded += int((total_bytes-free_bytes) / 1024L); user.kbToday += int((total_bytes-free_bytes) / 1024L); } if(!quiet_download) { io << "\n\f\n" << S_X_FILES_DOWNLOADED_SUCCESSFULLY(form("%d",files_found),form("%ld",total_bytes/1024L)) << "\n\n"; if(files.count()) io << S_X_FILES_NOT_DOWNLOADED(form("%d",files.count())) << "\n\n"; if(goodbye && !files.count() && !uploads.count()) { unlink(prot.logfile); unlink(prot.ctlfile); io << "\n\n" << S_HANGUP_AFTER_DOWNLOAD_PROMPT << "10"; for(int i=10;i>0;i--) { io << form("\b\b%2d\xFF",i); char c = toupper(io.readkey()); if(c==K_HANGUP_AFTER_DOWNLOAD_PROMPT[0]) return; if(c==K_HANGUP_AFTER_DOWNLOAD_PROMPT[1]) break; sleep(1); } LOG("Hanging up after download."); showansascrip("DLHANGUP"); exit_proboard(); } if(uploads.count()) process_uploads(prot,cfg.uploadpath,uploads,private_download , ask_description , no_log , quiet_download , extra_log ); io << S_PRESS_ENTER_TO_CONTINUE; } } void read_personal_files( LinkedList& files ) { File f(FN_PVTFILES_PB); if(!f.opened()) return; f.rewind(); for(;;) { _PrivateFile pvt; if(f.read(&pvt,sizeof(pvt)) != sizeof(pvt)) break; if(strcmpl(pvt.to,user.name) || !pvt.fname[0]) continue; String fname; if(!strchr(pvt.fname,'\\')) fname = String(cfg.pvtuploadpath) + pvt.fname; else fname = pvt.fname; DirScan scan(fname); if(int(scan)) files.add( InputFile(fname) ); } } void delete_personal_file( char *name ) { File f(FN_PVTFILES_PB,fmode_rw | fmode_excl); if(!f.opened()) return; FileName fn; FileName fn_full( name ); _PrivateFile pvt; int num_found = 0; for(;;) { if(f.read(&pvt,sizeof(pvt))!=sizeof(pvt)) break; if(!pvt.fname[0]) continue; if(!strchr(pvt.fname,'\\')) fn = String(cfg.pvtuploadpath) + pvt.fname; else fn = pvt.fname; if(fn == fn_full) num_found++; } f.rewind(); for(;;) { if(f.read(&pvt,sizeof(pvt))!=sizeof(pvt)) break; if(!pvt.fname[0] || stricmp(pvt.to,user.name)) continue; if(!strchr(pvt.fname,'\\')) fn = String(cfg.pvtuploadpath) + pvt.fname; else fn = pvt.fname; if(fn_full == fn) { pvt.fname[0]=0; f.seek(-long(sizeof(pvt)),seek_cur); f.write(&pvt,sizeof(pvt)); if(pvt.attr & PVTFILE_KEEP) continue; if(num_found < 2) // Only kill file if not waiting for oher user unlink(fn_full); } } } InputFile::InputFile() { area = 0; } InputFile::InputFile(char *s) { area = 0; if(s[0] == '[') { area = atoi(&s[1]); for(int i=0; s[i] ; i++) { if(s[i] == ']') { name = &s[i+1]; return; } } } name = s; } InputFile::InputFile(char *s,int a) { name = s; area = a; }