Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * Nightmare 2.0 - General purpose file editor
- *
- * Copyright (C) 2009 Hextator,
- * hectorofchad (AIM) [email protected] (MSN)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3
- * as published by the Free Software Foundation
- *
- * 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; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * <Description> Wrapper class for the file to be edited by modules.
- */
- package IO;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.UnsupportedEncodingException;
- import java.util.zip.CRC32;
- /**
- * Wrapper class for the file to be edited by modules.
- * @author Hextator
- */
- public class Target_File
- {
- /**
- * For referencing the size of the file
- */
- public static int SIZE = -1;
- /**
- * For help keeping track of where something was written to
- */
- public static int LAST_WRITE_INDEX;
- /**
- * For checking if the file has been saved before
- */
- public static boolean named = false;
- /**
- * For checking if the file has been saved with the most recent changes
- */
- public static boolean saved = true;
- /**
- * For knowing where to save
- */
- public static String fileName;
- /**
- * Enumeration listing possible "genders" of data orientation
- */
- public static enum byteSex
- {
- /**
- * Reverse ordered bytes
- */
- little,
- /**
- * Generically linear bytes
- */
- big
- }
- /**
- * Static container of the enumeration detailing whether the file is
- * meant to be interpreted as being in a little or big endian format<br>
- * Little endianness is chosen by default
- */
- public static byteSex endianness = byteSex.little;
- /**
- * Wrapped field: the open file
- */
- private static byte file[];
- /**
- * For allowing much needed Module attachment leniency
- */
- private static boolean originalLittleChecksumValid;
- /**
- * For allowing much needed Module attachment leniency
- */
- private static boolean originalBigChecksumValid;
- /**
- * For allowing much needed Module attachment leniency
- */
- private static int originalChecksum;
- //The following six functions are for performing variable endian
- //data accesses on byte arrays; accesses supported are
- //8, 16 and 32 bit read and write
- //All are tested and working
- /**
- * Uses endianness static variable to variably perform a big
- * or little endian access of a file
- * @param source byte array to read from
- * @param address Address of byte array to read from
- * @return the byte at the address in the given byte array
- */
- public static Byte getByte(byte source[], int address)
- {
- try
- {
- return source[address];
- }
- catch (Exception e)
- {
- return null;
- }
- }
- /**
- * Uses endianness static variable to variably perform a big
- * or little endian access of a file
- * @param source byte array to read from
- * @param address Address of byte array to read from
- * @return the halfword at the address in the given byte array
- */
- public static Short getShort(byte source[], int address)
- {
- try
- {
- short tempShort;
- if (endianness == byteSex.little)
- {
- tempShort = (short) ((source[address + 1] & 0xFF) << 0x8);
- tempShort |= source[address] & 0xFF;
- }
- else
- {
- tempShort = (short) (source[address + 1] & 0xFF);
- tempShort |= (source[address] & 0xFF) << 0x8;
- }
- return tempShort;
- }
- catch (Exception e)
- {
- return null;
- }
- }
- /**
- * Uses endianness static variable to variably perform a big
- * or little endian access of a file
- * @param source byte array to read from
- * @param address Address of byte array to read from
- * @return the word at the address in the given byte array
- */
- public static Integer getInt(byte source[], int address)
- {
- try
- {
- int tempInt;
- if (endianness == byteSex.little)
- {
- tempInt = (source[address + 3] & 0xFF) << 0x18;
- tempInt |= (source[address + 2] & 0xFF) << 0x10;
- tempInt |= (source[address + 1] & 0xFF) << 0x8;
- tempInt |= source[address] & 0xFF;
- }
- else
- {
- tempInt = source[address + 3] & 0xFF;
- tempInt |= (source[address + 2] & 0xFF) << 0x8;
- tempInt |= (source[address + 1] & 0xFF) << 0x10;
- tempInt |= (source[address] & 0xFF) << 0x18;
- }
- return tempInt;
- }
- catch (Exception e)
- {
- return null;
- }
- }
- /**
- * Uses endianness static variable to variably perform a big
- * or little endian access of a file
- * @param dest byte array to write to
- * @param address Address of byte array to write to
- * @param input The byte to write at the address of a given byte array
- */
- public static void putByte(byte dest[], int address, byte input)
- {
- try
- {
- dest[address] = input;
- if (dest == file)
- saved = false;
- }
- catch (Exception e)
- {
- }
- }
- /**
- * Uses endianness static variable to variably perform a big
- * or little endian access of a file
- * @param dest byte array to write to
- * @param address Address of byte array to write to
- * @param input The halfword to write at the address of a given byte
- * array
- */
- public static void putShort(byte dest[], int address, short input)
- {
- try
- {
- if (endianness == byteSex.little)
- {
- dest[address + 1] = (byte) ((int) input >> 0x8);
- dest[address] = (byte) ((int) input & 0xFF);
- }
- else
- {
- dest[address] = (byte) ((int) input >> 0x8);
- dest[address + 1] = (byte) ((int) input & 0xFF);
- }
- if (dest == file)
- saved = false;
- }
- catch (Exception e)
- {
- }
- }
- /**
- * Uses endianness static variable to variably perform a big
- * or little endian access of a file
- * @param dest byte array to write to
- * @param address Address of byte array to write to
- * @param input The word to write at the address of a given byte array
- */
- public static void putInt(byte dest[], int address, int input)
- {
- try
- {
- if (endianness == byteSex.little)
- {
- dest[address + 3] = (byte) (input >> 0x18);
- dest[address + 2] =
- (byte) ((input >> 0x10) & 0xFF);
- dest[address + 1] =
- (byte) ((input >> 0x8) & 0xFF);
- dest[address] = (byte) (input & 0xFF);
- }
- else
- {
- dest[address] = (byte) (input >> 0x18);
- dest[address + 1] =
- (byte) ((input >> 0x10) & 0xFF);
- dest[address + 2] =
- (byte) ((input >> 0x8) & 0xFF);
- dest[address + 3] = (byte) (input & 0xFF);
- }
- if (dest == file)
- saved = false;
- }
- catch (Exception e)
- {
- }
- }
- //These two functions handle bit array reading and writing
- //Both are tested and working
- /**
- * Pulls a series of bits from the given byte array
- * @param source byte array to read from
- * @param address Address of byte containing first bit to be read
- * @param offset Bits closer to the LSB from the MSB of the byte that
- * the first bit of the bit set is located at
- * @param length The number of bits in the bit set being retrieved
- * @return null if an error occurs when loading the bits, or else the
- * value of the bits as a long such that the lowest addressed bit is
- * the MSB and the highest addressed bit is the LSB
- */
- public static Integer getBits
- (
- byte source[],
- int address,
- int offset,
- int length
- )
- {
- if (length > 32 || length <= 0)
- return null;
- int output = 0;
- while (length > 0)
- {
- if (offset == 8)
- address++;
- offset %= 8;
- output <<= 1;
- try
- {
- output |=
- (
- source[address]
- & (1 << (7 - offset))
- )
- >>
- (
- 7 - offset
- );
- }
- catch (Exception e)
- {
- return null;
- }
- offset++;
- length--;
- }
- return output;
- }
- /**
- * Puts a series of bits from the given input into the given byte array
- * @param dest byte array to write to
- * @param address Address of byte containing first bit to be
- * overwritten
- * @param offset The bit this many bits closer to the LSB from the MSB
- * of the first byte that the first bit of the bit set being written
- * will be placed at
- * @param length The number of bits in the bit set being written
- */
- public static void putBits
- (
- byte dest[],
- int address,
- int offset,
- int length,
- int input
- )
- {
- if (length > 32 || length <= 0)
- return;
- int mask = 1 << (length - 1);
- while (length > 0)
- {
- if (offset == 8)
- address++;
- offset %= 8;
- try
- {
- dest[address] =
- (byte)
- (
- (
- dest[address]
- & ~(1 << (7 - offset))
- )
- |
- (
- (
- (input & mask)
- >> (length - 1)
- )
- << (7 - offset)
- )
- );
- if (dest == file)
- saved = false;
- }
- catch (Exception e)
- {
- return;
- }
- offset++;
- mask >>= 1;
- length--;
- }
- }
- /**
- * file is private...hurf
- */
- public static byte[] getFile()
- {
- return file;
- } //getFile accessor
- /**
- * For testing whether this file was clean when it was opened
- * @param checksum Checksum expected
- * @return true if the original checksum of the file matches the given
- * checksum
- */
- public static boolean isValid(int checksum)
- {
- if
- (
- originalLittleChecksumValid
- && endianness == byteSex.little
- )
- return true;
- else if
- (
- originalBigChecksumValid
- && endianness == byteSex.big
- )
- return true;
- else
- return originalChecksum == checksum ? true : false;
- } //isClean method; doesn't need testing
- /**
- * Mutator for editing interfaces to update the file
- * @param input byte array to replace the current file
- */
- public static void setFile(byte input[])
- {
- file = input;
- } //setfile mutator
- /**
- * Method for acquiring ASCII strings from a byte array, usually the
- * file itself
- * @param source byte array to read from
- * @param start Start address to pull the string from
- * @param end Address of first byte following the ASCII string
- * @return the selected ASCII string as a String
- */
- public static String pullString(byte source[], int start, int end)
- {
- String tempString = "";
- try
- {
- tempString = new String
- (
- java.util.Arrays.copyOfRange
- (
- source,
- start,
- end
- ),
- "ASCII"
- );
- }
- catch (UnsupportedEncodingException e)
- {
- }
- return tempString;
- } //pullString method; tested and working!
- /**
- * Method for inserting Strings as ASCII strings into a byte array,
- * usually the file itself
- * @param dest byte array to write to
- * @param start Start address to put the ASCII version of the input
- * String at
- * @param input The String to insert
- */
- public static void putString(byte dest[], int start, String input)
- {
- byte inputArray[] = new byte[input.length()];
- for (int i = 0; i < inputArray.length; i++)
- inputArray[i] = (byte) input.charAt(i);
- System.arraycopy(inputArray, 0, file, start, inputArray.length);
- if (dest == file)
- saved = false;
- } //putString method; doesn't need testing
- /**
- * Gives user a file open dialog for selecting the file to edit
- * @param what Description of what to open
- * @param initPath Optional default path (use null if no default path
- * is desired)
- */
- public static void open(String what, String initPath)
- {
- saved = true;
- String inputFileName;
- if (initPath == null)
- {
- java.awt.FileDialog chooser = new java.awt.FileDialog
- (
- new java.awt.Frame(),
- "Select " + what + " for opening"
- );
- chooser.setVisible(true);
- chooser.setLocationRelativeTo(null);
- inputFileName = chooser.getDirectory() + chooser.getFile();
- if (inputFileName.equals("nullnull"))
- {
- /*
- javax.swing.JOptionPane.showMessageDialog
- (
- null,
- "No file was selected.\n",
- "Action canceled",
- javax.swing.JOptionPane.PLAIN_MESSAGE
- );
- */
- file = new byte[] {-1};
- SIZE = -1;
- return;
- }
- }
- else
- inputFileName = initPath;
- FileInputStream inputFile;
- File tempFile; //Just for getting the file size quickly
- try
- {
- inputFile = new FileInputStream(inputFileName);
- tempFile = new File(inputFileName);
- }
- catch (IOException e)
- {
- file = new byte[] {-1};
- SIZE = -1;
- return;
- }
- SIZE = (int) tempFile.length();
- tempFile = null; //Toss it; don't need it anymore
- file = new byte[SIZE];
- try
- {
- inputFile.read(file);
- inputFile.close();
- fileName = inputFileName;
- }
- catch (IOException e)
- {
- System.out.println("Error reading file");
- file = new byte[] {-1};
- SIZE = -1;
- return;
- }
- expand(0);
- CRC32 checksum = new CRC32();
- checksum.update(file);
- originalChecksum = (int) checksum.getValue();
- checksum.reset();
- checksum.update
- (
- java.util.Arrays.copyOf(file, SIZE - 4)
- );
- originalLittleChecksumValid = false;
- originalBigChecksumValid = false;
- int originalLittleChecksum = getInt(file, SIZE - 4);
- if (originalLittleChecksum == (int) checksum.getValue())
- originalLittleChecksumValid = true;
- endianness = byteSex.big;
- int originalBigChecksum = getInt(file, SIZE - 4);
- if (originalBigChecksum == (int) checksum.getValue())
- originalBigChecksumValid = true;
- endianness = byteSex.little;
- if (originalLittleChecksumValid || originalBigChecksumValid)
- {
- file = java.util.Arrays.copyOf(file, SIZE - 4);
- SIZE -= 4;
- }
- } //open method; tested and working!
- /**
- * Queries whether the user wants to save the modified file<br>
- * Tacks on a verification checksum onto the end of the file,
- * then saves it at the location specified by the user<br>
- * Rips the checksum back off so checksums won't accumulate
- * @param saveAs boolean of whether to force choosing of a file path
- * instead of using the last path
- */
- public static boolean save(boolean saveAs)
- {
- //Append checksum onto end of file for validation purposes
- CRC32 checksum = new CRC32();
- checksum.update(file);
- expand(4);
- putInt(file, SIZE - 4, (int) checksum.getValue());
- String outputFileName;
- if (!named || saveAs)
- {
- java.awt.FileDialog chooser = new java.awt.FileDialog
- (
- new java.awt.Frame(),
- "Save",
- java.awt.FileDialog.SAVE
- );
- chooser.setVisible(true);
- outputFileName = chooser.getDirectory() + chooser.getFile();
- if (outputFileName.equals("nullnull"))
- {
- //Rip off checksum so further editing without reopening
- //doesn't generate a checksum chain
- file = java.util.Arrays.copyOf(file, SIZE - 4);
- SIZE -= 4;
- return false;
- }
- }
- else
- outputFileName = fileName;
- FileOutputStream outputFile;
- try
- {
- outputFile = new FileOutputStream(outputFileName);
- outputFile.write(file);
- outputFile.close();
- saved = true;
- named = true;
- fileName = outputFileName;
- }
- catch (IOException e)
- {
- //Rip off checksum so further editing without reopening
- //doesn't generate a checksum chain
- file = java.util.Arrays.copyOf(file, SIZE - 4);
- SIZE -= 4;
- return false;
- }
- //Rip off checksum so further editing without reopening
- //doesn't generate a checksum chain
- file = java.util.Arrays.copyOf(file, SIZE - 4);
- SIZE -= 4;
- return true;
- } //save method; tested and working!
- /**
- * Adds a number of 0 filled bytes to the end of the file equal to
- * the given size with padding to the nearest word
- * @param size The number of bytes to expand the file by
- * @return the number of bytes the file was expanded by after
- * considering word alignment
- */
- public static int expand(int size)
- {
- int originalSize = size;
- size += 3;
- size >>= 2;
- size <<= 2;
- file = java.util.Arrays.copyOf(file, SIZE + size);
- SIZE += size;
- return size - originalSize;
- } //expand method; tested and working!
- /**
- * Uses a call to expand(int) to get space for the given appendix,
- * then fills the expanded area with the appendix
- * @param input A byte array of the data to append onto the end of the
- * open file
- */
- public static void append(byte input[])
- {
- int tempInt = expand(input.length);
- System.arraycopy(input, 0, file, SIZE - input.length - tempInt, input.length);
- } //append method; tested and working!
- /**
- * Performs file writing of given input array of bytes
- * at end of file
- * @param input A byte array of the data to write to the file
- */
- public static void writeToFile(byte input[])
- {
- LAST_WRITE_INDEX = SIZE;
- byte tempByte[] = new byte[input.length];
- System.arraycopy(input, 0, tempByte, 0, input.length);
- append(tempByte);
- saved = false;
- } //writeToFile method; tested and working!
- /**
- * This method is for overwriting invalid data and is very insecure<br>
- * The data in file from address to input.length + address is forcefully
- * filled with input's contents<br>
- * Because this method should only be used by methods that have knowledge
- * of what they're doing with this method, there are no index validations
- * or checks to make sure the data being overwritten is truly unnecessary
- * @param input A byte array of the data to overwrite part of the open
- * file with
- * @param address The address to write the input to within the
- * open file
- */
- public static void overwriteFile(byte input[], int address)
- {
- System.arraycopy(input, 0, file, address, input.length);
- saved = false;
- } //overwriteFile method; doesn't need testing
- /**
- * Performs a writeToFile call and places a pointer to the area
- * where the given data was written at the index of pointerAddress<br>
- * LAST_WRITE_INDEX is updated to equal pointerAddress
- * @param input A byte array of the data to overwrite part of the open
- * file with
- * @param pointerAddress The address of the pointer pointing to the
- * data being replaced so that it can be updated to point to the data
- * it is being replaced with
- */
- public static void writeAndRepoint
- (
- byte input[],
- int pointerAddress
- )
- {
- writeToFile(input);
- putInt(file, pointerAddress, LAST_WRITE_INDEX);
- LAST_WRITE_INDEX = pointerAddress;
- } //writeAndRepoint method; tested and working!
- /**
- * This method is for replacing aligned integer values
- * (emphasis on aligned)<br>
- * This is great for replacing old pointers with new pointers for
- * expansion purposes
- * @param oldVal Integer value to replace occurrences of
- * @param newVal Integer value to replace occurrences of oldVal with
- */
- public static void findAndReplace(int oldVal, int newVal)
- {
- for (int i = 0; i < SIZE; i += 4)
- if (getInt(file, i) == oldVal)
- putInt(file, i, newVal);
- saved = false;
- } //findAndReplace method; tested and working!
- /**
- * For resetting file variables to their "closed" status
- */
- public static void closeFile()
- {
- SIZE = -1;
- file = new byte[] {-1};
- LAST_WRITE_INDEX = 0;
- saved = true;
- fileName = "";
- } //closeFile method; doesn't need testing
- }
Advertisement
Add Comment
Please, Sign In to add comment