/*************** NNTP Java Class by Charles Bloom quite nice ***************/ import java.io.*; import java.net.*; import java.lang.*; class ArticleHeader { int number; String subject; String author; String date; int bytes,lines; int seqNum,seqTot; public void getSeq() /* from subject */ { int slashI,fdelimI,ldelimI,a,b; if ( (slashI = subject.lastIndexOf('/')) == -1 ) { seqNum=seqTot=0; return; } a = subject.lastIndexOf('(' /*)*/,slashI); b = subject.lastIndexOf('[',slashI); if ( a > b ) fdelimI = a; else fdelimI = b; if ( fdelimI == -1 ) { seqNum=seqTot=0; return; } a = subject.indexOf(/*(*/ ')',slashI); b = subject.indexOf(']',slashI); if ( a == -1 ) a = 999; if ( b == -1 ) b = 999; if ( a < b ) ldelimI = a; else ldelimI = b; if ( ldelimI == 999 ) { seqNum=seqTot=0; return; } try { seqNum = clib.atoi(subject.substring(fdelimI+1,slashI)); seqTot = clib.atoi(subject.substring(slashI+1,ldelimI)); } catch( NumberFormatException e ) { seqNum=seqTot=0; return; } } public String fileName() /* from subject */ { int dotidx,fspace,lspace; subject.replace('\t',' '); if ( (dotidx = subject.lastIndexOf('.')) == -1 ) { dotidx = 0; fspace = 0; } else { fspace = subject.lastIndexOf(' ',dotidx); fspace++; } if ( (lspace = subject.indexOf(' ',dotidx)) == -1 ) lspace = subject.length(); return ( subject.substring(fspace,lspace) ); }; }; class NNTP_Client { public SimpleClientConnection net; public long group_low=0,group_high=0; /* only valid right after goGroup */ boolean nntpConnected; DataInputStream nntp_in; PrintStream nntp_out; PrintStream log_out; String host,group_name; public boolean reset() throws IOException { ArticleHeader none = new ArticleHeader(); none.number = 0; return ( reset(none) ); }; public boolean reset(ArticleHeader last) throws IOException { disconnect(); NNTP_Connect(); if ( group_name != null ) { if ( ! goGroup(group_name) ) return(false); if ( ! goArticle(last.number) ) return(false); } return(true); }; /* these progress indicators should be in a seperate module so that they could be swapped out for GUI ones */ void progressUpdate(int cur,int tot) { System.err.print("nntp : " + cur + " / " + tot + "\r"); System.err.flush(); } void progressDone() { System.err.println(); } public byte[] getBody(ArticleHeader header) throws IOException { byte body[]; String instr; nntp_out.println("body"); instr = nntp_in.readLine(); log_out.println(instr); if ( instr.indexOf("body") == -1 ) throw new IOException("nntp.getBody:no article body"); { byte tbody[]; int curoff=0,lines=0,c; tbody = new byte[header.lines*80]; progressUpdate(lines,header.lines); while ( lines < header.lines ) { if ( (c = nntp_in.read()) == -1 ) break; tbody[curoff++] = (byte) c; if ( c == '\n' ) { lines++; if ( lines % 50 == 0 ) { progressUpdate(lines,header.lines); System.err.flush(); } } } progressUpdate(lines,header.lines); progressDone(); body = new byte[curoff]; System.arraycopy(tbody,0,body,0,curoff); } log_out.println( nntp_in.readLine() ); /* '.' line */ return( body ); }; public ArticleHeader getHeader() throws IOException { boolean goterror; String instr,curstr; ArticleHeader header = new ArticleHeader(); int next_pos; do { goterror = false; nntp_out.println("xover"); instr = nntp_in.readLine(); log_out.println(instr); if ( instr.indexOf("data follows") == -1 ) throw new IOException("nntp.getHeader:no xover data"); instr = nntp_in.readLine(); log_out.println(instr); /* now process instr and fill in header */ /* article number */ next_pos = instr.indexOf('\t'); curstr = instr.substring(0,next_pos); instr = instr.substring(next_pos + 1); try { header.number = clib.atoi(curstr); } catch ( NumberFormatException e ) { goterror = true; } /* subject */ next_pos = instr.indexOf( '\t'); curstr = instr.substring(0,next_pos); instr = instr.substring(next_pos + 1); header.subject = curstr; /* author */ next_pos = instr.indexOf( '\t'); curstr = instr.substring(0,next_pos); instr = instr.substring(next_pos + 1); header.author = curstr; /* date */ next_pos = instr.indexOf( '\t'); curstr = instr.substring(0,next_pos); instr = instr.substring(next_pos + 1); header.date = curstr; /* message-id */ next_pos = instr.indexOf('\t'); curstr = instr.substring(0,next_pos); instr = instr.substring(next_pos + 1); // ignore /* references */ next_pos = instr.indexOf( '\t'); curstr = instr.substring(0,next_pos); instr = instr.substring(next_pos + 1); // ignore /* bytes */ next_pos = instr.indexOf( '\t'); curstr = instr.substring(0,next_pos); instr = instr.substring(next_pos + 1); try { header.bytes = clib.atoi(curstr); } catch ( NumberFormatException e ) { goterror = true; } /* lines (last one) */ next_pos = instr.indexOf( '\t'); curstr = instr.substring(0,next_pos); instr = instr.substring(next_pos + 1); try { header.lines = clib.atoi(curstr); } catch ( NumberFormatException e ) { goterror = true; } log_out.println( nntp_in.readLine() ); /* a line of just "." */ } while( goterror ); return(header); }; public boolean goArticle(int number) { String retStr; nntp_out.println("stat " + number); try { log_out.println( retStr = nntp_in.readLine() ); } catch ( IOException e ) { return(false); } if ( retStr.indexOf("Bad") != -1 ) return(false); return(true); }; public boolean goGroup(String in_group_name) { String reply; String[] replyToks; group_low = group_high = 0; group_name = in_group_name; nntp_out.println("group " + group_name); try { log_out.println( reply = nntp_in.readLine() ); } catch ( IOException e ) { return(false); } if ( reply.indexOf("No such group") != -1 ) { log_out.println("NNTP_Client:Got:No such group"); return(false); } replyToks = clib.stringSpaceTok(reply); if ( replyToks.length < 5 ) { log_out.println("NNTP_Client:Got: less than 5 tokens in group header"); return(false); } group_low = clib.atol(replyToks[2]); group_high = clib.atol(replyToks[3]); return(true); }; /* next : returns false when no more messages */ public boolean next() throws IOException { String statstr; nntp_out.println("next"); statstr = nntp_in.readLine(); log_out.println(statstr); if ( statstr.indexOf("retrieved") == -1 ) return(false); return(true); }; public boolean isConnected() { return( nntpConnected ); }; public void disconnect() { if ( nntpConnected ) nntp_out.println("quit"); nntpConnected = false; net.disconnect(); }; public NNTP_Client(String in_host,PrintStream in_log_out) throws IOException { host = in_host; log_out = in_log_out; group_name = null; nntpConnected = false; NNTP_Connect(); } public void NNTP_Connect() throws IOException { net = new SimpleClientConnection(host, 119); /* 119 is NNTP */ nntpConnected = net.isConnected(); if ( nntpConnected ) { nntp_in = net.inputStream(); nntp_out = net.outputStream(); } else { nntp_in = null; nntp_out= null; } /* init */ { String incoming = null; log_out.println("Waiting for 'ready'"); do { incoming = nntp_in.readLine(); log_out.println(incoming); } while ( incoming.indexOf("ready") == -1 ); } }; };