/*
* FilelistDumpSearcher.java
*
* Copyright (C) 2008 AppleGrew
*
* 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 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; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.ag.sheriffbot;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.apache.tools.bzip2.CBZip2InputStream;
import org.elite.jdcbot.util.GlobalFunctions;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;
/**
* Use this to search dumps created by SheriffBot.<br>
* <p>
* Using this you can search for variety of information in the dumps. Just give it the directory name of the dump files
* and give it the search query. Run it to learn about the options it supports.<br>
* <p>
* Please note though, that this uses seems to use too much processing power and is quite slow. I still don't know
* where the bottleneck is. If you find out the bottleneck then do let me know.
*
* @author AppleGrew
* @since 0.7.1
* @version 0.1.1
*
*/
public class FilelistDumpSearcher {
public static void main(String args[]) {
if (args.length == 0 || args[0].equals("-h")) {
System.out.println("Argument Syntax: [-T|-t|-s|-p|-H] -d pathToDumpFileOrFolder SearchTerm");
System.out.println("-t stands for types. It can take one of - f and d; for file and directory.");
System.out.println("-s stands for size of file in MBs intended. It can only be specified for files.");
System.out.println("-T instructs to show the TTH of files. By default it is not shown.");
System.out.println("-p instructs to display the result row in PHP serialized form. By default it is not shown like that.");
System.out
.println("-H stands for hub name. It takes the name of the hub. The results retured are from hubs with such similar names only.");
}
FilelistDumpSearcher fds = new FilelistDumpSearcher();
boolean showTTH = false;
boolean phpSerialize = false;
String hubname = null;
int type = FilelistHandler.ANY;
long size = -1;
int i = 0;
String dumpLoc = null;
for (i = 0; i < args.length; i++) {
if (args[i].equals("-t")) {
if (args[i + 1].equals("f"))
type = FilelistHandler.FILE;
else if (args[i + 1].equals("d"))
type = FilelistHandler.DIR;
else {
System.err.println("Wrong type: " + args[i + 1]);
System.err.println("Arguments passed:\n" + arr2Str(args));
System.exit(1);
}
i++;
} else if (args[i].equals("-s")) {
size = Long.parseLong(args[++i]) * 1024 * 1024;
} else if (args[i].equals("-d")) {
dumpLoc = args[++i];
} else if (args[i].equals("-T")) {
showTTH = true;
} else if (args[i].equals("-p")) {
phpSerialize = true;
} else if (args[i].equals("-H")) {
hubname = args[++i];
} else
break;
}
if (dumpLoc == null) {
System.err.println("No dump file location given.");
System.err.println("Arguments passed:\n" + arr2Str(args));
System.exit(1);
}
if (i > args.length - 1) {
System.err.println("No serach term given.");
System.err.println("Arguments passed:\n" + arr2Str(args));
System.exit(1);
}
File f = new File(dumpLoc);
if (f.isFile()) {
Vector<String> r = fds.search(dumpLoc, args[i], type, size, showTTH, phpSerialize, hubname);
if (r != null)
System.out.print(FilelistDumpSearcher.Vector2String(FilelistDumpSearcher.removeDuplicates(r)));
} else if (f.isDirectory()) {
Vector<String> res = new Vector<String>();
File dfs[] = f.listFiles();
Arrays.sort(dfs, new Comparator<File>() {
public int compare(File o1, File o2) {
Pattern pattern = Pattern.compile("^.*-([0-9]{4}?)-([0-9]{2}?)-([0-9]{2}?)_([0-9]{2}?).([0-9]{2}?).([0-9]{2}?)$");
Matcher matcher1 = pattern.matcher(o1.getName());
Matcher matcher2 = pattern.matcher(o2.getName());
if (matcher1.matches() && matcher2.matches()) {
for (int i = 1; i < matcher1.groupCount() && i < matcher2.groupCount(); i++)
if (Integer.parseInt(matcher1.group(i)) < Integer.parseInt(matcher2.group(i)))
return 1;
else if (Integer.parseInt(matcher1.group(i)) > Integer.parseInt(matcher2.group(i)))
return -1;
}
return 0;
}
});
for (File df : dfs) {
Vector<String> r = fds.search(df.getAbsolutePath(), args[i], type, size, showTTH, phpSerialize, hubname);
if (r != null)
res.addAll(r);
}
System.out.print(FilelistDumpSearcher.Vector2String(FilelistDumpSearcher.removeDuplicates(res)));
} else {
System.err.println(dumpLoc + " is an invalid location.");
System.err.println("Arguments passed:\n" + arr2Str(args));
System.exit(1);
}
System.out.println();
}
public static String arr2Str(String arr[]) {
String r = "";
for (String a : arr)
r = r + a + "\n";
return r;
}
public Vector<String> search(String dumpfile, String srfor, int type, long size, boolean showTTH, boolean phpSerialize, String hubname) {
Vector<String> results = new Vector<String>();
BufferedInputStream ubin = null;
CBZip2InputStream bin = null;
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
//XMLReader parser = XMLReaderFactory.createXMLReader();
ubin = new BufferedInputStream(new FileInputStream(dumpfile));
ubin.read(new byte[2]); //To discard the starting BZ flag.
bin = new CBZip2InputStream(ubin);
String line = null;
int c = 0;
line = "";
while ((c = bin.read()) != '\n' && c != -1)
line = line + (char) c;
String dnt = line;
if (c == -1) {
dnt = "";
return null;
}
line = "";
while ((c = bin.read()) != '\n' && c != -1)
line = line + (char) c;
if (c == -1)
return null;
if (!phpSerialize)
results.add("Dump's Date and Time stamp: " + dnt + "\n==========================\n" + "hubname: " + line);
else
results.add("$" + dnt + "\n" + "|" + line);
if (hubname != null && !line.trim().toLowerCase().contains(hubname.toLowerCase().subSequence(0, hubname.length()))) {
results.add("No hits.");
return results;
}
while ((c = bin.read()) != '\n' && c != -1)
;
FilelistHandler handler = new FilelistHandler(srfor, type, size, showTTH, phpSerialize, results);
//parser.setContentHandler(handler);
try {
parser.parse(bin, handler);
//InputSource insrc = new InputSource(bin);
//insrc.setEncoding("UTF-8");
//parser.parse(insrc);
} catch (org.xml.sax.SAXParseException saxe) {
saxe.printStackTrace();
}
if (results.size() == 1) {
results.add("No hits.");
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
///e.printStackTrace();
} catch (SAXParseException e) {
e.printStackTrace();
System.err.println("Line: " + e.getLineNumber() + "; Col:" + e.getColumnNumber());
} catch (SAXException e) {
e.printStackTrace();
} finally {
if (bin != null) {
try {
bin.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return results;
}
public static Vector<String> removeDuplicates(Vector<String> res) {
Vector<String> vec = new Vector<String>();
for (int i = res.size() - 1; i >= 0; i--) {
boolean dup = false;
for (int j = i - 1; j >= 0; j--) {
if (res.get(i).equals(res.get(j))) {
dup = true;
break;
}
}
if (!dup)
vec.insertElementAt(res.get(i), 0);
//vec.add(res.get(i));
}
return vec;
}
public static String Vector2String(Vector<String> vec) {
String res = null;
for (String l : vec) {
if (res != null)
res = res + "\n";
else
res = "";
res = res + l;
}
return res;
}
public static String getMiscStats(String dumpfile) {
return null;
}
private class FilelistHandler extends DefaultHandler {
static final int USER = 0;
static final int FILE = 1;
static final int DIR = 2;
static final int ANY = 3;
static final int UNKNOWN = 4;
private Vector<String> results;
Vector<String> dirs = new Vector<String>();
private String srfor;
private String srforArr[];
private int type;
private long size;
private boolean showTTH;
private boolean phpSerialize;
private String currentUser;
private String currentIP;
private String pwd = "";
public FilelistHandler(String Srfor, int Type, long Size, boolean ShowTTH, boolean PhpSerialize, Vector<String> res) {
srfor = Srfor.trim().toLowerCase();
srforArr = srfor.split(" ");
type = Type;
size = Size;
showTTH = ShowTTH;
phpSerialize = PhpSerialize;
results = res;
}
public void startElement(String uri, String lname, String qname, Attributes attrs) throws SAXException {
String result = null;
long currsize = 0L;
String TTH = "";
String value = "";
int currType = UNKNOWN;
if (qname.equalsIgnoreCase("Directory")) {
value = attrs.getValue("Name");
dirs.add(value);
currType = DIR;
} else if (qname.equalsIgnoreCase("user")) {
currentUser = attrs.getValue("username");
currentIP = attrs.getValue("ip");
currType = USER;
} else if (qname.equalsIgnoreCase("File")) {
value = attrs.getValue("Name");
currsize = Long.parseLong(attrs.getValue("Size"));
TTH = attrs.getValue("TTH");
currType = FILE;
}
if (currType == DIR)
pwd = getPwd(dirs);
if (currType == FILE || currType == DIR) {
// Searching.
boolean found = false;
result = currentUser + ":" + currentIP + ":" + (currType == FILE && showTTH ? TTH + ":" : "") + pwd;
if (GlobalFunctions.matches(srforArr, result) || currType == FILE && TTH.equalsIgnoreCase(srfor)) {
found = true;
}
if (type != ANY && currType != type)
found = false;
if (size >= 0 && currType == FILE)
if ((size == 0 && currsize != size) || (size != 0 && (((double) (Math.abs(currsize - size))) / size) > 0.1))
found = false;
if (found) {
if (!phpSerialize) {
// result = currentUser + ":" + (content.type == Content.FILE && showTTH ? content.TTH + ":" : "") + getPwd(dirs);
if (currType == FILE)
result = result + "/" + value;
} else {
int index = 0;
result = serializeEntity(index++, currType == FILE ? "f" : "d");
result = result + serializeEntity(index++, currentUser);
result = result + serializeEntity(index++, currentIP);
if (currType == FILE && showTTH)
result = result + serializeEntity(index++, TTH);
result = result + serializeEntity(index++, getPwd(dirs));
if (currType == FILE)
result = result + serializeEntity(index++, value);
result = "a:" + index + ":{" + result + "}";
}
results.add(result); // ADDING THE RESULT.
}
}
//Thread.yield();
}
public void endElement(String uri, String lname, String qname) throws SAXException {
if (qname.equalsIgnoreCase("Directory")) {
dirs.remove(dirs.size() - 1);
}
}
private String getPwd(Vector<String> dirs) {
String pwd = "";
for (String dir : dirs) {
pwd = pwd + "/" + dir;
}
return pwd;
}
/**
* Helper function to convert to PHP serialized form, so that
* the output of this program can be automatically converted to
* PHP array. I infact prepared a website for it. ;-)
* @param index
* @param s
* @return
*/
private String serializeEntity(int index, String s) {
return "i:" + index + ";s:" + s.length() + ":\"" + s + "\";";
}
}
}