/*
 * GNU.FREE 2002
 *
 * Copyright (c) 1999, 2000, 2001, 2002
 * The Free Software Foundation (www.fsf.org)
 *
 * GNU.FREE Co-ordinator: Jason Kitcat <jeep@free-project.org>
 *
 * GNU site: http://www.gnu.org/software/free/
 * 
 * FREE e-democracy site: http://www.free-project.org
 *
 * This program 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
 * of the License, or (at your option) any later version.
 *
 * This program 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.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program (COPYING); if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 */
  
package PollManager;
 
import java.util.*;
import Free.util.*;

/**
 * PMProtocol receives Strings of data from <code>TCPClient</code> and 
 * implements the logic to process these strings and formulate the appropriate
 * replies.
 *
 * The source code is extremely readable and best explains the full functionality.
 *
 * @version 0.11 8 September 2001
 * @author Jason Kitcat
 */
public class PMProtocol {

	/**
	 * process analyses packets and responds appropriately.
	 *
	 * @param inputData   Contains the contents of a received packet
	 * @returns		String with a packet to return to client
	 * @throws		<code>Exception</code>, all errors are handled by <code>TCPClient</code>
	 *				which has the ability to gracefully close the connection.  
	 */
	protected static String[] process(String inputData) throws Exception {

		String[] outputData = new String[] {" "," "}; // field one for control data, two for rest
		PollManager.comms.setSequence_number(PollManager.comms.getSequence_number()+1); // increment as we've just got a packet!
		
		if (inputData.charAt(0) == 'C') {
			/* confirm */
			Packet p = new Packet(inputData);

			if (AuthSys.checkHMAC(p,PollManager.comms.getServer_hmac_key(),PollManager.comms.getSequence_number())) {  // tamper check
			
				if (p.getMessage().equals("STAMP")) {
					if (PollManager.comms.getCheck() != null) {
						String data = PollManager.comms.getCheck().toString() + "-" + PollManager.name + "-" + AuthSys.makeDigest(PollManager.code) + "-" + AuthSys.makeDigest(PollManager.pword);
						PollManager.comms.setSequence_number(PollManager.comms.getSequence_number()+1); // incement as we send another packet
						outputData[1] = new Packet('C',data,PollManager.comms.getsession_key(),PollManager.comms.er_public_key,PollManager.comms.getClient_hmac_key(),PollManager.comms.getSequence_number()).toCryptString(true);
						//outputData[1] = RSAEncrypt.pubEncrypt(PollManager.comms.er_public_key,PollManager.comms.getsession_key()) + "-" + RSAEncrypt.blowEncrypt(PollManager.comms.getsession_key(),"C|" + data + "|" + AuthSys.makeDigest("C|" + data)) + "\r\n"; //reply with time stamp
						PollManager.frame2.showInfo(PollManager.messages.getString("stamp_sent"));		
					} else {
						PollManager.frame2.showError(PollManager.messages.getString("vote_sec_err"));
						outputData[1] = "ERROR";
					}
				} else {
					PollManager.frame2.showError(PollManager.messages.getString("unrec"));
					outputData[1] = "ERROR";
				}
			} else {
				PollManager.frame2.showError(PollManager.messages.getString("packet_alter"));
				outputData[1] = "ERROR";
			}			
							
		} else if (inputData.charAt(0) == 'D') {
			/* diagnostic */
			Packet p = new Packet(inputData);

			if (AuthSys.checkHMAC(p,PollManager.comms.getServer_hmac_key(),PollManager.comms.getSequence_number())) {  // tamper check

				PollManager.frame3.showInfo(PollManager.messages.getString("diag_rec"));
				outputData[0] = "X"; // ending connection
				PollManager.comms.setSequence_number(PollManager.comms.getSequence_number()+1); // incement as we send another packet
				outputData[1] = new Packet('X',"OK",PollManager.comms.getsession_key(),PollManager.comms.er_public_key,PollManager.comms.getClient_hmac_key(),PollManager.comms.getSequence_number()).toCryptString(true);
				//outputData[1] = RSAEncrypt.pubEncrypt(PollManager.comms.er_public_key,PollManager.comms.getsession_key()) + "-" + RSAEncrypt.blowEncrypt(PollManager.comms.getsession_key(),"X|OK|" + AuthSys.makeDigest("X|OK")) + "\r\n";
			
			} else {
				outputData[1] = "ERROR";
				throw new Exception(PollManager.messages.getString("packet_alter"));
			}

		} else if (inputData.charAt(0) == 'I') {
			/* initialisation */
			Packet p = new Packet(inputData);
			
			// parse to get seperate data fields
			String[] pp = p.splitMessage();
			String seed2 = pp[0];
			String clientmac = pp[1];

			PollManager.comms.setServer_hmac_seed(seed2);  // initialise protocol values
			PollManager.comms.setServer_hmac_key(AuthSys.seedToKey(PollManager.comms.getServer_hmac_seed()));

			if (AuthSys.checkHMAC(p,PollManager.comms.getServer_hmac_key(),PollManager.comms.getSequence_number())) {  // tamper check
			
				if (AuthSys.checkHMAC(new Packet("I|"+PollManager.comms.getClient_hmac_seed()+"|"+clientmac),PollManager.comms.getClient_hmac_key(),0)) {  // authentication check of server's key

					PollManager.comms.setSequence_number(PollManager.comms.getSequence_number()+1); // increment
					outputData[1] = PollManager.comms.getMessage_two();  // now send real data
				
				} else {
					outputData[1] = "ERROR";
					throw new Exception(PollManager.messages.getString("packet_alter"));
				}
			} else {
				outputData[1] = "ERROR";
				throw new Exception(PollManager.messages.getString("packet_alter"));
			}

		} else if (inputData.charAt(0) == 'P') {
			/* reply to PM ER Check */
			Packet p = new Packet(inputData);

			if (AuthSys.checkHMAC(p,PollManager.comms.getServer_hmac_key(),PollManager.comms.getSequence_number())) {  // tamper check
			
				// split message
				String[] pp = p.splitMessage();
				String voterOK = pp[0];
				String voterType = pp[1];
			
				if (voterType.equals("P") && voterOK.equals("F")) {
					// ok, not voted and register for polling station
					PollManager.frame3.showInfo(PollManager.messages.getString("auth_yes"));
					PollManager.frame3.jButton1.setEnabled(true);
					PollManager.voted = voterOK;
					PollManager.vote_where = voterType;
				} else if (voterType.equals("P") && voterOK.equals("C")) {
					// ok, not voted (but have logged in before) and for polling station
					PollManager.frame3.showInfo(PollManager.messages.getString("auth_yes"));
					PollManager.frame3.jButton1.setEnabled(true);
					PollManager.voted = voterOK;
					PollManager.vote_where = voterType;
				} else if (voterType.equals("I") && voterOK.equals("F")) {
					// ok, not voted and for Internet voting
					PollManager.frame3.showInfo(PollManager.messages.getString("auth_yes"));
					PollManager.frame3.jButton1.setEnabled(true);
					PollManager.voted = voterOK;
					PollManager.vote_where = voterType;
				} else if (voterType.equals("I") && voterOK.equals("C")) {
					// ok, not voted (but have logged in before) and for Internet voting
					PollManager.frame3.showInfo(PollManager.messages.getString("auth_yes"));
					PollManager.frame3.jButton1.setEnabled(true);
					PollManager.voted = voterOK;
					PollManager.vote_where = voterType;
				} else if (voterOK.equals("T")) {
					// user has voted
					PollManager.frame3.showError(PollManager.messages.getString("user_voted"));
					PollManager.frame3.showInfo(PollManager.messages.getString("try_again"));
					PollManager.frame3.jButton1.setEnabled(false);
					PollManager.frame3.jButton2.setEnabled(true);
				} else {
					// auth failed
					PollManager.frame3.showError(PollManager.messages.getString("auth_failed"));
					PollManager.frame3.showInfo(PollManager.messages.getString("try_again"));
					PollManager.frame3.jButton1.setEnabled(false);
					PollManager.frame3.jButton2.setEnabled(true);
				}
				
				outputData[0] = "X"; // ending connection
				PollManager.comms.setSequence_number(PollManager.comms.getSequence_number()+1); // incement as we send another packet
				outputData[1] = new Packet('X',"OK",PollManager.comms.getsession_key(),PollManager.comms.er_public_key,PollManager.comms.getClient_hmac_key(),PollManager.comms.getSequence_number()).toCryptString(true);
				//outputData[1] = RSAEncrypt.pubEncrypt(PollManager.comms.er_public_key,PollManager.comms.getsession_key()) + "-" + RSAEncrypt.blowEncrypt(PollManager.comms.getsession_key(),"X|OK|" + AuthSys.makeDigest("X|OK")) + "\r\n";

			} else {
				outputData[1] = "ERROR";
				PollManager.frame3.showError(PollManager.messages.getString("packet_alter"));
				PollManager.frame3.showInfo(PollManager.messages.getString("try_again"));
			}
			

		} else if (inputData.charAt(0) == 'S') {
			/* reply to PM Voted */
			Packet p = new Packet(inputData);

			if (AuthSys.checkHMAC(p,PollManager.comms.getServer_hmac_key(),PollManager.comms.getSequence_number())) {  // tamper check
			
				if (p.getMessage().equals("OK")) {
					PollManager.frame2.showInfo(PollManager.messages.getString("vote_reg"));
					PollManager.frame2.jButton4.setEnabled(true);
				} else {
					// auth failed
					PollManager.frame2.showError(PollManager.messages.getString("vote_sorry"));
					PollManager.frame2.showInfo(PollManager.messages.getString("try_again"));
					PollManager.frame2.jButton1.setEnabled(true);
				}
				
				outputData[0] = "X"; // ending connection
				PollManager.comms.setSequence_number(PollManager.comms.getSequence_number()+1); // incement as we send another packet
				outputData[1] = new Packet('X',"OK",PollManager.comms.getsession_key(),PollManager.comms.er_public_key,PollManager.comms.getClient_hmac_key(),PollManager.comms.getSequence_number()).toCryptString(true);
				//outputData[1] = RSAEncrypt.pubEncrypt(PollManager.comms.er_public_key,PollManager.comms.getsession_key()) + "-" + RSAEncrypt.blowEncrypt(PollManager.comms.getsession_key(),"X|OK|" + AuthSys.makeDigest("X|OK")) + "\r\n";

			} else {
				outputData[1] = "ERROR";
				PollManager.frame2.showError(PollManager.messages.getString("packet_alter"));
				PollManager.frame2.showInfo(PollManager.messages.getString("try_again"));
			}
			

		} else {
			outputData[1] = "ERROR";
			PollManager.frame3.showError(PollManager.messages.getString("unrec"));
		}
		
		return outputData;

	} //EOF process()

} //EOF Class