// Path: src/nb/barmie/exceptions/BaRMIeInvalidPortException.java
// public class BaRMIeInvalidPortException extends BaRMIeException {
// 	public BaRMIeInvalidPortException(int portNumber) {
// 		super("The given port number (" + portNumber + ") is not a valid TCP port number.");
// 	}
// }
// 
// Path: src/nb/barmie/exceptions/BaRMIeInvalidReplyDataPacketException.java
// public class BaRMIeInvalidReplyDataPacketException extends BaRMIeException {
// 	public BaRMIeInvalidReplyDataPacketException(String message) {
// 		super(message);
// 	}
// 	
// 	public BaRMIeInvalidReplyDataPacketException(String message, Throwable cause) {
// 		super(message, cause);
// 	}
// }
// 
// Path: src/nb/barmie/net/TCPEndpoint.java
// public class TCPEndpoint {
// 	/*******************
// 	 * Properties
// 	 ******************/
// 	private final String _host;
// 	private final int _port;
// 	
// 	/*******************
// 	 * Construct the TCP endpoint object with a given host and port.
// 	 * 
// 	 * @param host The host/IP to use.
// 	 * @param port The port to use.
// 	 * @throws nb.barmie.exceptions.BaRMIeInvalidPortException If the given port number is not a valid TCP port number.
// 	 ******************/
// 	public TCPEndpoint(String host, int port) throws BaRMIeInvalidPortException {
// 		//Store the properties
// 		this._host = host;
// 		this._port = port;
// 		
// 		//Validate the port number
// 		if(this._port < 1 || this._port > 65535) {
// 			throw new BaRMIeInvalidPortException(this._port);
// 		}
// 	}
// 	
// 	/*******************
// 	 * Return a string representation of this endpoint.
// 	 * 
// 	 * @return A host:port string.
// 	 ******************/
// 	public String toString() {
// 		return this._host + ":" + this._port;
// 	}
// 	
// 	/*******************
// 	 * Getters
// 	 ******************/
// 	public String getHost() { return this._host; }
// 	public int getPort() { return this._port; }
// }


import java.io.ObjectStreamConstants;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import nb.barmie.exceptions.BaRMIeInvalidPortException;
import nb.barmie.exceptions.BaRMIeInvalidReplyDataPacketException;
import nb.barmie.net.TCPEndpoint;
package nb.barmie.modes.enumeration;


/***********************************************************
 * Parser for RMI ReplyData packets (Java serialisation).
 * 
 * Extracts class names, string annotations, and the TCP
 * endpoint details of a remote object from the RMI
 * ReplyData packet.
 * 
 * Written by Nicky Bloor (@NickstaDB).
 **********************************************************/
public class RMIReplyDataParser {
	/*******************
	 * Properties
	 ******************/
	private boolean _recordClasses;											//Indicates whether class names should be recorded during object parsing
	private LinkedList<HashMap<Byte, ArrayList<Character>>> _classDataDesc;	//List of classDescFlags mapped to field type codes from an object's classDesc
	
	/*******************
	 * Construct the reply data parser.
	 ******************/
	public RMIReplyDataParser() {
		this._recordClasses = true;
		this._classDataDesc = new LinkedList<HashMap<Byte, ArrayList<Character>>>();
	}
	
	/*******************
	 * Extract object details from a ReplyData that was captured through the
	 * RMI registry proxy.
	 * 
	 * @param objName The object name bound to the RMI registry for which data is being extracted.
	 * @param packetBytes The ReplyData captured from the RMI registry which contains the remote object description.
	 * @return An RMIObject describing the remote object.
	 ******************/
	public RMIObject extractObjectDetails(String objName, ArrayList<Byte> packetBytes) {
		LinkedList<Byte> dataStack;
		RMIObject obj;
		byte b;
		int i;
		
		//Create the RMIObject with the given object name
		obj = new RMIObject(objName);
		
		//Copy the given buffer into a stack for parsing
		dataStack = new LinkedList<Byte>();
		dataStack.addAll(packetBytes);
		
		//Set the 'recordClasses' flag to true so that class descriptions are added to the object description
		this._recordClasses = true;
		
		//Start parsing the object data
		try {
			//Validate the RMI packet type byte
// Path: src/nb/barmie/exceptions/BaRMIeInvalidPortException.java
// public class BaRMIeInvalidPortException extends BaRMIeException {
// 	public BaRMIeInvalidPortException(int portNumber) {
// 		super("The given port number (" + portNumber + ") is not a valid TCP port number.");
// 	}
// }
// 
// Path: src/nb/barmie/exceptions/BaRMIeInvalidReplyDataPacketException.java
// public class BaRMIeInvalidReplyDataPacketException extends BaRMIeException {
// 	public BaRMIeInvalidReplyDataPacketException(String message) {
// 		super(message);
// 	}
// 	
// 	public BaRMIeInvalidReplyDataPacketException(String message, Throwable cause) {
// 		super(message, cause);
// 	}
// }
// 
// Path: src/nb/barmie/net/TCPEndpoint.java
// public class TCPEndpoint {
// 	/*******************
// 	 * Properties
// 	 ******************/
// 	private final String _host;
// 	private final int _port;
// 	
// 	/*******************
// 	 * Construct the TCP endpoint object with a given host and port.
// 	 * 
// 	 * @param host The host/IP to use.
// 	 * @param port The port to use.
// 	 * @throws nb.barmie.exceptions.BaRMIeInvalidPortException If the given port number is not a valid TCP port number.
// 	 ******************/
// 	public TCPEndpoint(String host, int port) throws BaRMIeInvalidPortException {
// 		//Store the properties
// 		this._host = host;
// 		this._port = port;
// 		
// 		//Validate the port number
// 		if(this._port < 1 || this._port > 65535) {
// 			throw new BaRMIeInvalidPortException(this._port);
// 		}
// 	}
// 	
// 	/*******************
// 	 * Return a string representation of this endpoint.
// 	 * 
// 	 * @return A host:port string.
// 	 ******************/
// 	public String toString() {
// 		return this._host + ":" + this._port;
// 	}
// 	
// 	/*******************
// 	 * Getters
// 	 ******************/
// 	public String getHost() { return this._host; }
// 	public int getPort() { return this._port; }
// }


// Path: src/nb/barmie/modes/enumeration/RMIReplyDataParser.java
import java.io.ObjectStreamConstants;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import nb.barmie.exceptions.BaRMIeInvalidPortException;
import nb.barmie.exceptions.BaRMIeInvalidReplyDataPacketException;
import nb.barmie.net.TCPEndpoint;

package nb.barmie.modes.enumeration;


/***********************************************************
 * Parser for RMI ReplyData packets (Java serialisation).
 * 
 * Extracts class names, string annotations, and the TCP
 * endpoint details of a remote object from the RMI
 * ReplyData packet.
 * 
 * Written by Nicky Bloor (@NickstaDB).
 **********************************************************/
public class RMIReplyDataParser {
	/*******************
	 * Properties
	 ******************/
	private boolean _recordClasses;											//Indicates whether class names should be recorded during object parsing
	private LinkedList<HashMap<Byte, ArrayList<Character>>> _classDataDesc;	//List of classDescFlags mapped to field type codes from an object's classDesc
	
	/*******************
	 * Construct the reply data parser.
	 ******************/
	public RMIReplyDataParser() {
		this._recordClasses = true;
		this._classDataDesc = new LinkedList<HashMap<Byte, ArrayList<Character>>>();
	}
	
	/*******************
	 * Extract object details from a ReplyData that was captured through the
	 * RMI registry proxy.
	 * 
	 * @param objName The object name bound to the RMI registry for which data is being extracted.
	 * @param packetBytes The ReplyData captured from the RMI registry which contains the remote object description.
	 * @return An RMIObject describing the remote object.
	 ******************/
	public RMIObject extractObjectDetails(String objName, ArrayList<Byte> packetBytes) {
		LinkedList<Byte> dataStack;
		RMIObject obj;
		byte b;
		int i;
		
		//Create the RMIObject with the given object name
		obj = new RMIObject(objName);
		
		//Copy the given buffer into a stack for parsing
		dataStack = new LinkedList<Byte>();
		dataStack.addAll(packetBytes);
		
		//Set the 'recordClasses' flag to true so that class descriptions are added to the object description
		this._recordClasses = true;
		
		//Start parsing the object data
		try {
			//Validate the RMI packet type byte
			if(dataStack.peek() != 0x51) { throw new BaRMIeInvalidReplyDataPacketException("The data buffer begins with 0x" + String.format("%02x", dataStack.peek()) + ", which is not a ReplyData packet (0x51 expected)."); }