/******** todo: resume in the middle binhex 8-bit raw content gui *********/ import java.io.*; import java.net.*; import java.lang.*; import java.util.*; class articleSetList { Hashtable hash; public articleSetList() { hash = new Hashtable(1024,(float)0.5); }; public articleSet getSet(ArticleHeader a) { String key; key = a.fileName(); if ( hash.containsKey( (Object) key ) ) { return (articleSet)hash.get( (Object) key ); } else { articleSet s; s = new articleSet(a); hash.put( (Object)key , (Object) s ); return s; } }; }; class articleSet { String fileName; int numParts; int numHave; ArticleHeader headers[]; public articleSet(ArticleHeader a) { int i; fileName = a.fileName(); a.getSeq(); numHave = 0; numParts = a.seqTot; if ( numParts == 0 ) numParts = 1; headers = new ArticleHeader[numParts]; for(i=0;i perhaps handle this better */ numHave++; headers[a.seqNum - 1] = a; } public void gotAll(NNTP_Client nntp,String outdir) throws IOException { int part; File outFile; byte body[]; long diffclock; long byps; byte[] rawdata; CodecInfo info; ArticleHeader header; long start_time,stop_time; Date date; /* seen 'em all; */ /* change to desired one; get it to file; repeat */ /* go back to "current article number" */ start_time = System.currentTimeMillis(); date = new Date(start_time); System.out.println(" starting download at: " + date.toLocaleString() ); outFile = new File(outdir,fileName); FileOutputStream outFileStream = new FileOutputStream(outFile); for(part=0;part 1 ) { if ( curArg.charAt(0) == '@' ) { String[] fileLines; curArg = args[argi].substring(1); if ( (fileLines = clib.readFileLines(curArg)) != null ) { int fileI; for(fileI=0;fileI set newshost"); console_out.println(" o output dir [curdir]"); console_out.println(" i include-list file"); console_out.println(" e exclude-list file"); console_out.println(" v verbose"); console_out.println(" d delay get : demand full sets"); console_out.println(" w await new"); console_out.println(" x exclude file extensions from seen-tracking"); console_out.println(" q quiet"); console_out.println(" r reconnect/retry forever"); console_out.println(" u accept unnumbered, treat as part 1 of 1"); console_out.println(" lmin set min number of lines [1]"); console_out.println(" lmax set max number of lines [20000]"); console_out.println(" pmin set min number of parts [1]"); console_out.println(" pmax set max number of parts [50]"); console_out.println(" bmin set min size of output [1]"); console_out.println(" bmax set max size of output [999999]"); console_out.println(" n starting article number [0]"); console_out.println(" s don't get files in (also updates list)"); console_out.println(" g group status file: tracks last number seen"); console_out.println(" a name:password"); console_out.println(" m max number of downloads; then quit"); console_out.println(); console_out.println("Any strings matched in the exclude-list are excluded"); console_out.println("A string must match something in the include-list"); console_out.println("These only apply when the include or exclude lists are given"); console_out.println(); console_out.println("Matches are made against 'subject:author'"); console_out.println(); console_out.println("Command files are processed linearly, just like command lines"); console_out.println("Each text line in a command file is treated as a new command line"); console_out.println("Configuration information is remembered between lines"); return; } }; public static void flushState() { console_out.println("------------------"); logfile.println("status : Doing Garbage Collection..."); System.gc(); logfile.println("status : Garbage Collection done."); if ( seenList != null ) { if ( seenList.changed ) { console_out.println("status : Flushing Seen-List..."); seenList.save( seenListFile ); console_out.println("status : Seen-List written."); } else logfile.println("status : Seen-List is up to date."); } if ( groupStatusFile != null && groupStatus != null ) { console_out.println("status : Flushing group-status file..."); groupStatus.save( groupStatusFile ); console_out.println("status : group-status written."); } if ( incFileName != null ) { String[] incpatterns; console_out.println("status : Reloading Include-List..."); if ( (incpatterns = clib.readFileLines(incFileName)) != null ) { int i; inc_subj_patterns = new WildCard[incpatterns.length]; for(i=0;i 1 ) { if ( args[argi].charAt(0) == '-' ) { int parami = 2; String param; if ( args[argi].length() > 2 ) if ( args[argi].charAt(2) == ':' || args[argi].charAt(2) == '=' ) parami++; if ( args[argi].length() > parami ) param = new String(args[argi].substring(parami)); else param = null; switch( args[argi].charAt(1) ) { case 'M': case 'm': max_downloads = clib.atoi(param); console_out.println("max downloads:"+ max_downloads); break; case 'U': case 'u': accept_unnumbered = true; console_out.println("accept unnumbered articles"); break; case 'R': case 'r': keep_retrying = true; console_out.println("reconnect/retry forever"); break; case 'H': case 'h': host = new String(param); console_out.println("host:" + host); break; case 'o': case 'O': outdir = new String(param); outdirFile = new File(outdir); if ( outdirFile.exists() && !outdirFile.isDirectory() ) { console_out.println("Outdir " + outdir + " exists and isn't a dir. exiting"); return; } if ( ! outdirFile.exists() ) if ( ! outdirFile.mkdirs() ) { console_out.println("Couldn't mkdirs " + outdir + ". exiting"); return; } console_out.println("outdir:" + outdir); break; case 'x': case 'X': noSeenExtensions = true; console_out.println("Exclude extensions from seen-file tracking"); break; case 's': case 'S': seenListFile = new String(param); seenList = new StringIndex( seenListFile , true ); console_out.println("seenlist:" + seenListFile); break; case 'g': case 'G': groupStatusFile = new String(param); groupStatus = new StrValIndex( groupStatusFile , true ); console_out.println("groupstatus:" + groupStatusFile); break; case 'i': case 'I': { String[] incpatterns; incFileName = new String(param); if ( (incpatterns = clib.readFileLines(incFileName)) != null ) { int i; inc_subj_patterns = new WildCard[incpatterns.length]; for(i=0;i nntp.group_high ) { console_out.println("No new articles in group."); return; } if ( article_num > nntp.group_low ) { int num_tries,step,max_num_tries = 100; console_out.println("Changing to article: " + article_num); num_tries = 0; step = 1; while ( ! nntp.goArticle(article_num) && num_tries < max_num_tries ) { num_tries ++; article_num += step; step ++; if ( article_num > nntp.group_high ) { System.err.println("failed"); return; } } if ( num_tries < max_num_tries) { console_out.println("okay, at article: " + article_num); } else { console_out.println("gave up after : " + num_tries + " tries"); } } console_out.println("Getting article headers."); lastheader = null; do { try { header = nntp.getHeader(); lastheader = header; console_out.println("------------------"); console_out.print("header : subject: "); if ( header.subject.length() > 60 ) console_out.println(header.subject.substring(header.subject.length() - 60) ); else console_out.println(header.subject); console_out.println("header : author : " + header.author); if ( verbose ) { console_out.println("header : date : " + header.date); console_out.println("header : number : " + header.number); console_out.println("header : lines : " + header.lines); console_out.println("header : bytes : " + header.bytes); console_out.println("------------------"); } articles_seen++; header.getSeq(); if ( header.seqNum == 0 && header.seqTot == 0 && accept_unnumbered ) header.seqNum = header.seqTot = 1; if ( header.seqNum == 0 || header.seqTot == 0 ) { console_out.println("skipped: sequence number invalid"); logfile.println("skipped: sequence number invalid"); } else if ( header.seqTot < minparts || header.seqTot > maxparts ) { console_out.println("skipped: sequence number out of range:" + header.seqTot); logfile.println("skipped: sequence number out of range:" + header.seqTot); } else if ( header.lines < minlines || header.lines > maxlines ) { console_out.println("skipped: numlines out of range : " + minlines + ":" + header.lines + ":" + maxlines); logfile.println("skipped: numlines out of range : " + minlines + ":" + header.lines + ":" + maxlines); } else { matchMe = header.subject + ":" + header.author + " "; matched = true; if ( (exc_subj_patterns != null) ) { int i; for(i=0;i= minoutsize && rawdata.length <= maxoutsize ) { FileOutputStream outFileStream = new FileOutputStream(outFile); outFileStream.write(rawdata); console_err.println("wrote : " + rawdata.length + " to " + outName); outFileStream.close(); logoutfile.println(outName + " : " + header.author + " : " + header.subject); } else { console_err.println("skipped: decode failed !!!"); logfile.println("skipped: decode failed !!!"); logfailfile.println(header.fileName() + " : " + header.author + " : " + header.subject); } if ( header.seqTot != 1 ) { String outNamePrefix = info.fileName + "_"; String outNamePostfix = "_" + header.seqTot; boolean allExist=true; int n; for(n=1;allExist && n<=header.seqTot;n++) { outFile = new File(outdir,outNamePrefix + n + outNamePostfix); if ( outFile == null || ! outFile.exists() ) allExist = false; } if ( allExist ) { MyFileInputStream inFileStream; FileOutputStream outFileStream; byte[] buf; outFileStream = new FileOutputStream( new File(outdir,info.fileName) ); for(n=1;n<=header.seqTot;n++) { inFileStream = new MyFileInputStream( new File(outdir,outNamePrefix + n + outNamePostfix) ); buf = inFileStream.readFully(); if ( buf != null ) outFileStream.write( buf ); inFileStream.close(); inFileStream = null; } outFileStream.close(); outFileStream = null; System.gc(); if ( seenList != null ) { if ( noSeenExtensions ) seenList.addNoCase(clib.cutExtension(info.fileName)); else seenList.addNoCase(info.fileName); } console_err.println("got end: " + info.fileName + " : " + header.seqTot + " parts"); for(n=1;n<=header.seqTot;n++) { outFile = new File(outdir,outNamePrefix + n + outNamePostfix); outFile.delete(); } outFile = null; System.gc(); max_downloads--; } } else { max_downloads--; } } articles_got++; } } } } keepgoing = nntp.next(); if ( awaitNew && !keepgoing ) { flushState(); console_out.println("status : waiting for new articles in group"); while( !keepgoing ) { keepgoing = nntp.next(); try { /* surrender CPU for 1 second */ Thread.currentThread().sleep(1000); } catch( InterruptedException e ) { } } } } catch ( IOException e ) { boolean newkeepgoing = false; do { keepgoing = true; System.err.println("error : " + e + ", trying NNTP.reset"); try { if ( lastheader == null ) keepgoing = nntp.reset(); else keepgoing = nntp.reset(lastheader); } catch ( IOException err ) { System.err.println("fatal : couldn't reset : " + err ); keepgoing = false; } if ( keep_retrying ) newkeepgoing = true; else if ( ! keepgoing ) newkeepgoing = clib.askContinue(); } while(!keepgoing && newkeepgoing ); } console_err.println("status : got " + articles_got + " of " + articles_inc + " included of " + articles_seen + " articles seen"); if ( (articles_seen % flush_quantum) == 0 ) { if ( groupStatus != null && lastheader != null ) groupStatus.changeNoCase(group_name,lastheader.number+1); flushState(); } if ( max_downloads <= 0 ) { console_err.println("Quitting : got max # of downloads"); keepgoing = false; } } while( keepgoing ); if ( groupStatus != null && lastheader != null ) groupStatus.changeNoCase(group_name,lastheader.number+1); console_out.println("------------------"); console_out.println("No more articles."); console_out.println("Disconnecting..."); nntp.disconnect(); console_out.println("done."); flushState(); } public static void addGotList(ArticleHeader header) throws IOException { } };