Simple Java *nix shell (Proof of Concept)

This is a very simple shell interface with a built-in history feature for use in your favorite *nix environment. This small project comes from a project in my Operating Systems class at Marshall University in which we were studying message passing models in modern OSs.

It should work fine with any program that is defined in your system $PATH variable (usually /usr/bin, etc). If you type !!, it will re-run the previous command. Or n!, where n is the number of the previous command. To get a list of these previous commands and their corresponding numbers, use the ‘history’ command which will show you all of your previous entries.

/*
 * Simple java shell with history feature
 * @author bradley carey
 * @date September 26, 2011
 */

 
import java.io.*;
import java.util.*;
import java.lang.ProcessBuilder;
 
public class SimpleShell {
    public static void main(String[] args) throws java.io.IOException
    {
        String commandLine, delims = "[ ]+", pwd;
        ArrayList<String> history = new ArrayList<String>();
 
        BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
 
        pwd = System.getProperty("user.home");
 
        while (true)
        {
            System.out.print("jsh@" + pwd + ">");
            commandLine = console.readLine();
 
            if(commandLine.equals(""))
                continue;
 
            if(commandLine.equals("exit"))
                System.exit(0);
 
            String[] tokens = commandLine.split(delims);
            for (String s: tokens)
            {
                //currentCommand.add(s);
                System.out.println("tokens:" + s);
            }
            history.add(commandLine);
            if(commandLine.equals("history"))
            {
                for(int i=0; i < history.size()-1; i++)
                    System.out.println("[" + i + "] " + history.get(i));
                continue;
            }
 
            if(commandLine.charAt(0) == '!')
            {
                char which = commandLine.charAt(1);
                if(which=='!') // !! entered, print previous command
                {
                    if(history.size() > 2)
                    {
                        String toRun = history.get(history.size()-2);
                        tokens = toRun.split(delims);
                        for (String s: tokens)
                            System.out.println(s);
 
                    } else {
                        System.out.println("Error: unable to run previous command!");
                        continue;
                    }
                } else { // !n, run nth command
                    int whichNum = Integer.parseInt(Character.toString(which));
                    if(history.size() > whichNum)
                    {
                        String toRun = history.get(whichNum);
                        tokens = toRun.split(delims);
                        System.out.println(toRun);
                    } else {
                        System.out.println("Error: unable to run history command. Out of bounds error?");
                        continue;
                    }
                }
            }
 
            if(commandLine.equals("cd"))
            {
                pwd = System.getProperty("user.home");
                continue;
            }
 
            if(tokens[0].equals("cd"))
            {
                String changeTo = tokens[1];
                if(changeTo.contains("/")) // absolute path
                {
                    File tempFile = new File(tokens[1]);
                    if(!tempFile.exists()) // file doesnt exist, abort
                    {
                        System.out.println("Error: invalid directory specified");
                        continue;
                    } else { // file exists, change dir
                        pwd = tokens[1];
                    }
                } else { // relative path
                    System.out.println(pwd + "/" + tokens[1]);
                    File tempFile = new File(pwd + "/" + tokens[1]);
                    if(!tempFile.exists())
                    {
                        System.out.println("Error: invalid directory specified");
                        continue;
                    } else {
                        pwd = pwd + "/" + tokens[1];
                    }
                }
                continue;
            }
 
            try
            {
                ProcessBuilder newProcess = new ProcessBuilder(tokens);
                newProcess.directory(new File(pwd));
                Process current = newProcess.start();
                current.waitFor(); // create new process and wait for execution to finish
 
                // print output
                BufferedReader is = new BufferedReader(new InputStreamReader(current.getInputStream()));
                String line;
                while ((line = is.readLine()) != null)
                    System.out.println(line);
 
                // print errors
                is = new BufferedReader(new InputStreamReader(current.getErrorStream()));
                while ((line = is.readLine()) != null)
                    System.out.println(line);
            } catch(IOException e) {
                System.out.println("Error: IOException has occurred. Command invalid?");
            } catch(InterruptedException e2) {
                System.out.println("Error: InterruptedException has occurred");
            }
        } // end while loop
    }
}

Apache Commons JSP Web Implementation

acwi

If you are a Java developer then you are very familiar with The Apache Commons. This web app is just basically a web implementation of the commons’ Math library. Here is an excerpt from the Commons’ website about Commons Math:

Commons Math is a library of lightweight, self-contained mathematics and statistics components addressing the most common problems not available in the Java programming language or Commons Lang.

Guiding principles:

  1. Real-world application use cases determine development priority.
  2. This package emphasizes small, easily integrated components rather than large libraries with complex dependencies and configurations.
  3. All algorithms are fully documented and follow generally accepted best practices.
  4. In situations where multiple standard algorithms exist, a Strategy pattern is used to support multiple implementations.
  5. Limited dependencies. No external dependencies beyond Commons components and the core Java platform (at least Java 1.3 up to version 1.2 of the library, at least Java 5 starting with version 2.0 of the library).

This JSP implements this library using a web interface. It was coded in Java using the Netbeans IDE and ran on Apache Tomcat. It does have Commons Lang and Commons Math as dependencies, which are not included. The *.jar files for these are availiable ont he Apache Commons website. For more details, visit the Google Code website.

Links:

Simple Multithread Java Webserver (proof of concept)

This project was nothing more than a proof-of-concept and should not be put into usage (get apache instead). It is a simple webserver written in Java that can take simultaneous requests via multithreading, parse the request, and properly respond. This program served as my forray into multithreading as well as the gritty details to what happens behind the scenes in a webserver.

/**
 * web server and client
 * @author Bradley Carey
 */

 
import java.io.*;
import java.net.*;
import java.util.*;
 
public final class WebServer
{
    public static void main(String argv[]) throws Exception
    {
        //set port number
        int port = 8080;
        ServerSocket myServerSocket = null;
 
        //establish listen socket
        try {
            myServerSocket = new ServerSocket(port);
        } catch (IOException e) {
            System.out.println("Could not listen on port # " + port);
            System.exit(-1);
        }
 
        //process http service requests in infinite loop
        while(true)
        {
            //listen for tcp connection requests
            Socket clientSocket = null;
            try {
                clientSocket = myServerSocket.accept();
            } catch (IOException e) {
                System.out.println("Accept failed on port # " + port);
                System.exit(-1);
            }
 
            HttpRequest request = new HttpRequest(clientSocket);
            Thread thread = new Thread(request);
            thread.start();
        }
    }
}
 
final class HttpRequest implements Runnable
{
    final static String CRLF = "\r\n";
    Socket socket;
 
    public HttpRequest(Socket socket) throws Exception
    {
        this.socket = socket;
    }
 
    public void run()
    {
        try
        {
            processRequest();
        } catch (Exception e) {
            System.out.println(e);
        }
        //throw new UnsupportedOperationException("Not supported yet.");
    }
 
    private void processRequest() throws Exception
    {
        //get reference to socket's input & output streams and setup filters
        InputStream is = socket.getInputStream();
        InputStreamReader isr = new InputStreamReader(is);
        OutputStream os = socket.getOutputStream();
        DataOutputStream dos = new DataOutputStream(os);
        BufferedReader br = new BufferedReader(isr);
 
        String requestLine = br.readLine();
        System.out.println(requestLine);
 
        String headerLine = null;
        while ((headerLine = br.readLine()).length() != 0) {
            System.out.println(headerLine);
        }
 
        StringTokenizer tokens = new StringTokenizer(requestLine);
        tokens.nextToken();
        String fileName = tokens.nextToken();
 
        if (fileName.equals("/"))
                fileName = "/default.htm";
 
        fileName = "." + fileName;
 
        System.out.println("\nfileName:" + fileName);
 
        FileInputStream fis = null;
        boolean fileExists = true;
        try {
            fis = new FileInputStream(fileName);
        } catch (FileNotFoundException e) {
            fileExists = false;
        }
 
        String statusLine = null;
        String contentTypeLine = null;
        String entityBody = null;
        if (fileExists) {
            statusLine = "HTTP/1.1 202 Accepted" + CRLF;
            contentTypeLine = "Content-type: " + contentType(fileName) + CRLF;
        } else {
            statusLine = "HTTP/1.1 404 Not Found" + CRLF;
            contentTypeLine = "text/html" + CRLF;
            entityBody = "<HTML>"
              + "<HEAD><TITLE>Not Found</TITLE></HEAD>"
              + "<BODY>404 Not Found</BODY></HTML>";
        }
 
        //Send the status line
        dos.writeBytes(statusLine);
        System.out.println("statusLine: " + statusLine);
 
        //Send the content type line
        dos.writeBytes(contentTypeLine);
        System.out.println("contentTypeLine: " + contentTypeLine);
        System.out.println("entityBody: " + entityBody);
 
        //Send a blank line to indicate the end of the header line
        dos.writeBytes(CRLF);
 
        //Send the entity body
        if (fileExists) {
          sendBytes(fis, os);
          fis.close();
        } else {
          os.write(entityBody.getBytes());
        }
 
        dos.close();
        os.close();
        br.close();
        socket.close();
    }
 
    private static void sendBytes(FileInputStream fis, OutputStream os) throws Exception
    {
        byte[] buffer = new byte[1024];
        int bytes = 0;
 
        while((bytes = fis.read(buffer)) != -1) {
            os.write(buffer, 0, bytes);
        }
    }
 
    private static String contentType(String fileName)
    {
        if (fileName.endsWith(".htm") || fileName.endsWith(".html"))
            return "text/html";
        if(fileName.endsWith(".gif"))
            return "image/gif";
        if(fileName.endsWith(".jpg"))
            return "image/jpg";
 
        return "application/octet-stream";
    }
}

XOR Encryption with Brute Force methods for decryption (proof of concept)

This project evolved from my time in the Cyber Security class at Marshall University. The goal was to create an implementation of a simple encryption scheme as well as brute force methods for decrypting the ciphertext without the original key. To use it:

  1. Select a text file as the active file for encryption/decryption.
  2. Enter your choice of operation.
  3. If the file has been previously encrypted, you can decrypt it as long as you know the key.
  4. If you don’t know the key to an encrypted file, select the brute force method to have the program try all possible combinations to detemine which key was originally used to decrypt the file.

This program uses a wordlist of more than 58,000 words from the English language when brute forcing, which is parsed into a java TreeSet for maximum speed. As such, a text file containing words to match it to is required. I’ve used the one found at this link: Corncob Wordlist

/**
 * CS340 Cryptography
 * February 23, 2011
 * @author Bradley carey
 */

 
import java.io.*;
import java.util.*;
import javax.swing.*;
 
public class Encryption
{
    public static void main(String[] args)
            throws NullPointerException, FileNotFoundException, IOException,
            NumberFormatException, Exception
    {
        Scanner input = new Scanner(System.in);
        File file = null;
        String strLine = "";
        JFileChooser fc = new JFileChooser(".");
 
        file = openFile(fc);
        strLine = readFile(file);
        System.out.println(strLine);
 
        int select = -1;
        while(select != 0)
        {
            String fName = file.getName();
            System.out.print(""
                    + "\nCurrently selected file: \"" + fName + "\"..."
                    + "\n1 - Open a different file."
                    + "\n2 - Encrypt " + fName
                    + "\n3 - Decrypt " + fName
                    + "\n4 - Attempt to brute force the key used to encrypt  " + fName
                    + "\n0 - Quit."
                    + "\nWhat would you like to do? ");
            select = Integer.parseInt(input.nextLine());
            switch(select)
            {
                case 1: //open file
                    file = openFile(fc);
                    strLine = readFile(file);
                    System.out.println(strLine);
                    break;
                case 2: // encrypt
                    encrypt(file, true);
                    break;
                case 3: //decrypt
                    encrypt(file, false);
                    break;
                case 4: // brute force
                    bruteForce(file);
                    break;
                case 0: //exit
                    System.exit(0);
                    break;
                default:
                    System.out.println("User fail detected. Please stop doing it wrong and try again.");
                    break;
            }
        }
    }
 
    /**
     *
     * @param fc : .
     * @return   : Returns the file to be opened.
     */

    public static File openFile(JFileChooser fc)
    {
        File file = null;
        System.out.println("Open a file...");
        int returnVal = fc.showOpenDialog(null);
        if(returnVal == JFileChooser.APPROVE_OPTION)
        {
            file = fc.getSelectedFile();
            System.out.println("Opened \"" + file.getName() + "\"...");
        } else
        {
            System.out.println("User cancelled the process. "
                    + "File selection unchanged.");
        }
        return file;
    }
 
    /**
     *
     * @param file : Reads in a file.
     * @return     : Returns the text in the file.
     * @throws FileNotFoundException
     * @throws IOException
     */

    public static String readFile(File file)
            throws FileNotFoundException, IOException
    {
        FileReader fr = new FileReader(file);
        BufferedReader br = new BufferedReader(fr);
        String strLine = "";
 
        int temp = br.read();
        while(temp != -1)
        {
            strLine += (char)temp;
            temp = br.read();
        }
        br.close();
        fr.close();
        return strLine;
    }
 
    /**
     *
     * @param file    : File to be encrypted or decrypted.
     * @param encrypt : Encrypt if TRUE, decrypt if FALSE.
     * @param brute   : Overrides encrypt if TRUE, will brutally force the
     *                  selected file open. Does nothing if FALSE.
     * @throws UnsupportedEncodingException
     * @throws FileNotFoundException
     * @throws IOException
     * @throws StringIndexOutOfBoundsException
     */

    public static void encrypt(File file, boolean encrypt)
            throws UnsupportedEncodingException, FileNotFoundException,
            IOException, StringIndexOutOfBoundsException
    {
        byte[] tempbyte = new byte[2];
        byte[] tempkey = new byte[2];
        String outfile = "";
 
        Scanner input = new Scanner(System.in);
        FileReader fr = new FileReader(file);
        BufferedReader br = new BufferedReader(fr);
 
        System.out.print("Enter key: ");
        String key = input.nextLine();
        key = key.substring(0, 2);
        tempkey = key.getBytes("US-ASCII");
 
        String outstr = "";
        String txt = "";
 
        int temp0 = br.read();
        while(temp0 != -1)
        {
            txt += (char)temp0;
            temp0 = br.read();
        }
 
        if(txt.length() % 2 != 0)
            txt += " ";
        for(int i = 0; i < txt.length()/2; i++)
        {
            tempbyte[0] = (byte)txt.charAt(i*2);
            tempbyte[1] = (byte)txt.charAt(i*2+1);
            tempbyte[0] = (byte)(tempbyte[0] ^ tempkey[0]);
            tempbyte[1] = (byte)(tempbyte[1] ^ tempkey[1]);
            outstr += (char)tempbyte[0] + "" + (char)tempbyte[1];
        }
 
        if(encrypt)
        {
            outfile += "encryptedMessage.txt";
        }
        else if(!encrypt)
        {
            outfile += "decryptedMessage.txt";
        }
        FileWriter fw = new FileWriter(new File(".\\" + outfile));
        BufferedWriter bw = new BufferedWriter(fw);
        bw.write(outstr);
        bw.close();
        fw.close();
        System.out.println(""
                    + "\nWritten to file: \"" + outfile + "\"..."
                    + "\n" + outstr);
    }
 
    /*
     *  Decrypts file and returns the file as a string for use in the
     *  brute force function
     * @param file  : File to decrypt
     * @param key1  : First byte of encryption key
     * @param key2  : Second byte of encryption key
     */

    public static String decrypt(File file, byte key1, byte key2) throws Exception
    {
        String outstr = "";
        String txt = "";
        byte[] tempbyte = new byte[2];
 
        FileReader fr = new FileReader(file);
        BufferedReader br = new BufferedReader(fr);
 
        int temp0 = br.read();
        while(temp0 != -1)
        {
            txt += (char)temp0;
            temp0 = br.read();
        }
 
        if(txt.length() % 2 != 0)
            txt += " ";
        for(int i = 0; i < txt.length()/2; i++)
        {
            tempbyte[0] = (byte)txt.charAt(i*2);
            tempbyte[1] = (byte)txt.charAt(i*2+1);
            tempbyte[0] = (byte)(tempbyte[0] ^ key1);
            tempbyte[1] = (byte)(tempbyte[1] ^ key2);
            outstr += (char)tempbyte[0] + "" + (char)tempbyte[1];
        }
 
        return outstr;
    }
 
    /* Attempts to discover the 16 bit key used to encrypt the given file
     * @param file  : File to brute force
     */

    public static void bruteForce(File file) throws Exception
    {
        ArrayList<String> possibleKeys = new ArrayList<String>(); // holds possible keys
 
        TreeSet<String> wordList = new TreeSet<String>(); // populate tree with wordlist
        File words = new File(".\\corncob_lowercase.txt");
        Scanner in = new Scanner(words);
        while(in.hasNextLine())
            wordList.add(in.nextLine());
        in.close();
 
        byte[] tempkey = new byte[2];
        FileReader fr = new FileReader(file);
        BufferedReader br = new BufferedReader(fr);
        for(int i = 32; i <= 126; i++)
        {
            for(int j = 32; j <= 126; j++)
            {
                tempkey[0] = (byte)i;
                tempkey[1] = (byte)j;
                String decryptedStuff = decrypt(file, tempkey[0], tempkey[1]);
 
                ArrayList<String> tokens = new ArrayList<String>();
                Scanner tokenize = new Scanner(decryptedStuff);
                while (tokenize.hasNext())  //tokenize decrypted ciphertext
                {
                    tokens.add(tokenize.next());
                }
                //System.out.println("Key: [" + (char)tempkey[0] + "" + (char)tempkey[1] + "] Message: " + decryptedStuff);
                //System.out.println("Tokens: [" + tokens + "] and total # of tokens: " + tokens.size());
 
                int confidence = 0;
 
                for(int w = 0; w < tokens.size(); w++)
                {
                    String s = tokens.get(w).toLowerCase();
                    //s = s.replaceAll("[^a-zA-Z]", ""); // remove all non-alpha characters from current token?
 
                    if(s.length() > 3 && wordList.contains(s)) //ignore words less than 3 characters to improve speed
                    {
                        System.out.println("Match found using token [" + s + "] and key " + (char)tempkey[0] + (char)tempkey[1]);
                        confidence++;
                    }
                }
                if(confidence > 1) // add key to list of possible solutions as well as a confidence level
                    possibleKeys.add(confidence + " " + (char)tempkey[0] + "" + (char)tempkey[1]);
            }
        }
 
        Collections.sort(possibleKeys, Collections.reverseOrder()); // sort possible keys in order from highest confidence to least
 
        System.out.println("Now printing 5 best matches. The number at the start is the confidence level and it is followed by the two-digit key.");
        for (int r=0; r < possibleKeys.size() && r < 5; r++) // print possible keys that were found
        {
            System.out.println(possibleKeys.get(r));
        }
 
        String temp = possibleKeys.get(0);
        temp = temp.substring(temp.length()-2);
        System.out.println("The key used to encrypt was probably " + temp
                + "\nIf you feel this is incorrect, please refer to the list above.");
    }
}