/* ** j###t ########## #### #### ** j###t ########## #### #### ** j###T "###L J###" ** ######P' ########## ######### ** ######k, ########## T######T ** ####~###L #### ** #### q###L ########## .##### ** #### \###L ########## #####" */ package key.util; import java.net.*; import java.io.*; import java.util.*; public class Ident extends Thread { public static final int DEFAULT_PORT = 113; Socket fromSocket; Socket identSocket; Callback back; Writer output; PushbackInputStream inputStream; public Ident( Socket s, Callback cb ) { fromSocket = s; back = cb; } public void run() { Socket is = null; try { identSocket = new Socket( fromSocket.getInetAddress(), DEFAULT_PORT ); // give up after 30 seconds identSocket.setSoTimeout( 30 * 1000 ); output = new BufferedWriter( new OutputStreamWriter( identSocket.getOutputStream() ) ); inputStream = new PushbackInputStream( identSocket.getInputStream() ); // query the socket send( fromSocket.getPort() + "," + fromSocket.getLocalPort() ); String result = input(); StringTokenizer st = new StringTokenizer( result, ":" ); // skip ports if( !st.hasMoreTokens() ) return; st.nextToken(); if( !st.hasMoreTokens() ) return; String responseType = st.nextToken().trim(); if( responseType.equalsIgnoreCase( "USERID" ) ) { String opsys = st.nextToken().trim(); if( st.hasMoreTokens() ) back.identResolvedUserId( opsys.toLowerCase(), st.nextToken("").trim() ); else back.identProtocolError( result ); } else if( responseType.equalsIgnoreCase( "ERROR" ) ) { if( st.hasMoreTokens() ) back.identResolvedError( st.nextToken().toLowerCase().trim() ); else back.identProtocolError( result ); } else { back.identProtocolError( result ); } } catch( IOException e ) { back.identProtocolError( e.getMessage() ); } finally { try { if( output != null ) output.close(); } catch( Exception e ) { } try { if( inputStream != null ) inputStream.close(); } catch( Exception e ) { } try { if( is != null ) is.close(); } catch( Exception e ) { } } } public static final String CRLF = "\r\n"; public static final int INPUT_BUFFER = 640; public static final int MAX_OVERRUN = 640; private char[] inBuffer = new char[INPUT_BUFFER+2]; private int lastCharWas = -1; public String input() throws IOException { int where=0; char b=' '; do { int i; // continuously skip until a CR or LF // when the buffer runs out if( where >= INPUT_BUFFER ) { int count = 0; do { i = inputStream.read(); count++; } while( !( i == '\r' || b == '\n' ) && (count < MAX_OVERRUN) ); if( count == MAX_OVERRUN ) throw new IOException( "max overrun reached" ); } else i = inputStream.read(); if( i != -1 ) b = (char) i; else throw new IOException( "connection closed" ); if( b >= 32 && b <= 126 ) // valid ascii characters only inBuffer[where++] = (char) b; else if( b == 8 || b == 127 ) { if( where > 0 ) where--; } } while( !((b == '\r') && !(lastCharWas == '\n')) && !((b == '\n') && !(lastCharWas == '\r' )) ); lastCharWas = b; return( new String( inBuffer, 0, where ) ); } public void send( String message ) throws IOException { output.write( message ); output.write( CRLF ); output.flush(); } public interface Callback { public void identResolvedError( String error ); public void identProtocolError( String error ); public void identResolvedUserId( String machine, String user ); } }