//: AuthNewsGateWay.java

/** Very simple server that takes care of the Authentication part of
  * logging into an authenticated news server so that older news
  * clients that don't know how to negotiate the authentication
  * protocol can still connect.  Once authentication is complete, acts
  * as a simple news gateway (A.K.A. tunnel or relay).
  *
  * How it works: Listens for connections to the well known news port,
  * 119.  Once a connection is established, it opens a new connection
  * to a real news server, which responds with a "200" message.  The
  * "200" message is saved to be sent to the client once
  * authentication is complete.  It then sends the username and
  * password on to the news server.  Once these are accepted, the
  * original "200" message is sent back to the client and a relay
  * connection is created so the client thinks it's connected
  * correctly to a normal news server and any further communications
  * gets re-directed via the relay to/from the real news server.
  *
  * @author Mark Crocker
  * @author http://www.markcrocker.com/~mcrocker/
  * @version 0.9.0.2 (Alpha) 2000-May-21
  * Derived from @see c15.MultiJabberServer from 'Thinking in Java,
  * 2nd ed.' by Bruce Eckel www.BruceEckel.com.  
  */

/* This is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.  
 */

import java.io.*;
import java.net.*;


/** ConnectAndAuthenticate

  * @param Socket to listen to and Socket to send to
  * @return No return value
  * @exception IOException, InterruptedException thrown 
  */

class ConnectAndAuthenticate {
    private Socket socket;
    private Socket replySocket;
    private BufferedReader in;
    private PrintWriter out;
    private PrintWriter replyPW;
    public ConnectAndAuthenticate(Socket s, Socket r) 
	throws IOException {
	socket = s;
	replySocket = r;
	in = new BufferedReader(
               new InputStreamReader(socket.getInputStream()));
	// Enable auto-flush:
	out = new PrintWriter(
                new BufferedWriter(
                  new OutputStreamWriter(socket.getOutputStream())), true);
	replyPW = new PrintWriter(
                    new BufferedWriter(
                      new OutputStreamWriter(replySocket.getOutputStream())), true);
	// If any of the above calls throw an 
	// exception, the caller is responsible for
	// closing the socket. Otherwise the thread
	// will close it.
	//start(); // Calls run()
    }

    /** run
     *  @param User name and pass word
     *  A somewhat braindead authentication responder.
     */
    public void run(String userName, String passWord) {
    try {
	String str = "";
	String twoHundredResponse = "";
	out.println("MODE READER");
	while ( !twoHundredResponse.startsWith("200") ) {  
	    //out.println("");
	    twoHundredResponse = in.readLine();
	    System.out.println("Server Response: " + twoHundredResponse);
	}
	out.println("AUTHINFO user " + userName);
	while ( !str.startsWith("381") ) {  
	    str = in.readLine();
	    System.out.println("Server Response: " + str);
	}
	out.println("AUTHINFO pass " + passWord);
	while ( !str.startsWith("281") ) {  
	    str = in.readLine();
	    System.out.println("Server Response: " + str);
	}
	System.out.println("Replying to client with 200 response");
	System.out.println(twoHundredResponse);
	replyPW.println(twoHundredResponse);
    } catch (IOException e) {}
  }
}


public class AuthNewsGateWay { 

    /** Standard News Server Port */
    public static final int PORT = 119;
    /** Host News server (or news firewall) lives on */
    public static final String NEWSSERVERHOST = "192.168.0.4"; 

    public static void main(String[] args) 
	throws IOException, InterruptedException {

	if(args.length != 2) {
	    System.err.println("Usage: AuthNewsGateWay userName passWord");
	    System.exit(1);
	}
	String userName = args[0];
	String passWord = args[1];

	// Server port
	ServerSocket s = new ServerSocket(PORT);
	System.out.println("Server started: " + s);

	try {
	    while(true) {
		// Blocks until a connection occurs:
		Socket socketS = s.accept();
		try {

		    // Relay port
		    InetAddress addr =  InetAddress.getByName(NEWSSERVERHOST);
		    System.out.println("relaying to addr = " + addr);
		    Socket socketR = new Socket(addr, PORT);
		    System.out.println("Relay socket started = " + socketR);
		    
		    ConnectAndAuthenticate caa = new ConnectAndAuthenticate(socketR, socketS);
		    caa.run(userName, passWord);

		    new RelayOneWay(socketS, socketR);
		    new RelayOneWay(socketR, socketS);
		    // If it fails, close the socket,
		    // otherwise the thread will close it:
		} catch(IOException e) {
		    System.out.println("Error establishing sockets...");
		    socketS.close();
		    //socketR.close();
		}
	    }
	} finally {
	    s.close();
	    //socketR.close();
	}
    } 
} ///:~

/* Todo:
 * 1. Command Line options -> almost have this working
 * 2. Popup window to fill in if no command line options supplied.
 * 3. Logging.
 * 4. Quiet mode.
 * 5. Debug mode.
 * 6. Add some error checking so it can recover from bad connections
 *    and dropped info, unexpected server responses etc..
 * 7. Clean-up documentation and generate Javadocs
 */