Naming Code
Quack Verification
When we first heard about the "quackifier" program over a week ago, our first impression was one of skepticism. All we knew was that this was a program that purported to change string values in an executable file. When run, it did create a new "quack3.exe" file, but what else did it do? It could have made more changes to the file than its claimed purpose, or even modify existing OpenGL drivers.
While we inquired into the quackifier source, we asked Andrew, our ace Gamers.com developer to create an application from scratch that does the same thing; namely, to search a single file for any string values containing "quake" or "Quake" and rename those to "quack". Within 5 minutes, we had a fully working version, shown below:
import java.io.*;
import java.util.*;
public class Test {
public static void main(String[] args) {
try {
//test string
String str = args[0];
String rep = args[1];
String inFile = args[2];
String outFile = args[3];
System.out.println( "Test String: " + str );
byte[] pattern = str.getBytes();
System.out.println( "Replace with: " + rep );
byte[] replace = rep.getBytes();
//read file into array
BufferedInputStream input = new BufferedInputStream
(new FileInputStream(inFile));
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int b = input.read();
while (b != -1) {
buffer.write(b);
b = input.read();
}
byte [] file = buffer.toByteArray();
buffer.reset();
System.out.println(inFile + " size: " + file.length + " bytes.");
// search thru file & replace
byte [] test = new byte[pattern.length];
for (int i=0; i < file.length; i++) {
if (file[i] == pattern[0] && (i + pattern.length) <= file.length ) {
System.arraycopy( file, i, test, 0, pattern.length);
if (Arrays.equals( pattern, test )) {
System.out.println("Match at: " + i);
buffer.write(replace, 0, replace.length);
i += (pattern.length - 1);
continue;
}
}
buffer.write(file[i]);
}
byte [] newFile = buffer.toByteArray();
buffer.close();
// write out new file if changed
if (! Arrays.equals(file, newFile) && ! outFile.equals("null")) {
BufferedOutputStream output = new BufferedOutputStream
(new FileOutputStream(outFile));
output.write(newFile, 0, newFile.length);
output.close();
System.out.println("Wrote new file: " + outFile);
} else {
System.out.println("File not written");
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void print(byte [] pattern) {
for (int i=0; i < pattern.length; i++) {
System.out.print( pattern[i] + " ");
}
System.out.println();
System.out.println();
}
}
The code above was spaced to fit in our page template, but you can download the source and compiled class files here to experiment at home:
Now that we have our quack, let's see what it does.