/*
* Copyright (C) 2011 Alvaro Duran Tovar
*
* This file is part of AFA.
*
* AFA 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 3 of the License, or
* (at your option) 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, see <http://www.gnu.org/licenses/>.
*/
package afa.control.filesystem;
import afa.control.Constants;
import afa.control.Tools;
import afa.control.analisis.Scheduler;
import afa.model.*;
import java.io.File;
import java.io.IOException;
import java.util.Vector;
/**
* Clase encargada de buscar en el disco duro.
* Buscara una direccion concreta o bien una busqueda recursiva.
* Dado un vector de objetos file patterns comprueba si cada fichero pasa
* o no los patrones.
*
* @author Alvaro Duran Tovar
*/
public class Explorer {
private static boolean stoped = false;
private static boolean console_mode = false;
/**
* Check if one file exists. Used by techniques that are not recursive.
* @param path
* @return
*/
public static boolean checkLocation(String path, Technique t) throws Exception {
boolean match = checkMatch(new File(path), new FilePattern(t));
return match;
}
/**
* Alias for the other checkLocationsRecursively
* @param dev
* @param path
* @param patterns
* @throws Exception
*/
public static void checkLocationsRecursively(Device dev, String path, Vector<FilePattern> patterns) throws Exception {
checkLocationsRecursively(dev, new File(path), patterns);
}
/**
*
* @param dev
* @param path
* @param patterns
* @throws Exception
*/
public static void checkLocationsRecursively(Device dev, File path,
Vector<FilePattern> patterns) throws Exception {
String relativePath = path.getAbsolutePath();
if (!dev.getMountPoint().getAbsolutePath().equals("/")) {
relativePath = relativePath.replace(dev.getMountPoint().getAbsolutePath(), "");
}
if (!console_mode) {
Scheduler.notifyMessage("[" + dev.getDeviceName().getAbsolutePath() + "] " + relativePath,
Constants.VERBOSE_FEEDBACK_COLOR);
} else {
System.out.println("[" + dev.getDeviceName().getAbsolutePath() + "]" + " " + relativePath);
}
if (stoped) {
return;
}
//explore files of the path
File files[] = path.listFiles();
if (files != null) //check permisions
{
for (File file : files) {
if (stoped) return;
//if symbolic link return
if (isLink(file)) continue;
//check if its a directory or not.
//if its then make a recursive call
if (file.isDirectory())
checkLocationsRecursively(dev, file, patterns);
else
checkMatchs(dev, file, patterns);
}
}
}
/**
* Check if each pattern matchs against the selected file.
*
* @param patterns
* @param f
*/
private static void checkMatchs(Device dev, File file, Vector<FilePattern> patterns) throws Exception {
for (FilePattern fp : patterns) {
//file pattern match with current file
if (checkMatch(file, fp)) {
fp.addMatch(dev, file.getAbsolutePath());
//notify
Result aux = fp.getLastMatch(dev);
if (!console_mode) {
Scheduler.notifyResult(aux);
} else {
System.out.println("result: " + aux);
}
}
}
}
/**
* Check if the filepattern match with the selected file.
* The method will apply diferent filters and if one of them return negative
* then method stop.
*
* @param fp
* @param matcher
* @return if the file matchs with the file pattern
*/
private static boolean checkMatch(File matcher, FilePattern fp) throws IOException, Exception {
if (fp.getInitialPath() != null && fp.getName() != null) {
/* start fix paths */
String auxPath = fp.getInitialPath();
if (!auxPath.startsWith(File.separator)) {
auxPath = File.separator + auxPath;
}
if (!auxPath.endsWith(File.separator)) {
auxPath += File.separator;
}
/* end fix paths*/
if (matcher.getAbsolutePath().contains(auxPath)
&& matcher.getAbsolutePath().contains(matcher.getName())) {
//begining of the matchs section
//the variable flag will tell if the filters are passed or not.
boolean flag = true;
/* check file name */
//check if the file being analized ends with the name of the file pattern
//maybe it should check only its the exact name.
flag = flag & matcher.getName().endsWith(fp.getName());
//in case of negative match return.
if (!flag) return flag;
/* check md5 */
//if the file pattern have a MD5 pattern
if (fp.getHashType().equals("MD5")) {
//check if the md5 values match
flag = flag & (Tools.getMD5(matcher.getAbsolutePath()).equals(fp.getHashValue()));
//in case of negative match return.
if (!flag) return flag;
}
/* check file content */
//if the file pattern have a pattern to check content
if (fp.haveContent()) {
//check if the file contains the value of the filepattern
flag = flag & FindContent.find(matcher, fp.getContent());
//in case of negative match return.
if (!flag) return flag;
}
/* check mimetype */
//if file pattern have mime type
if(fp.haveMimeType()){
flag = flag & MimeType.getMimeType(matcher.getAbsolutePath()).contains(fp.getMimeType());
if(!flag) return flag;
}
return flag;
}
}
//shouldn't be here.
return false;
}
/**
* Check if a File is a symbolic link.
* Im not sure if it works...
*/
private static boolean isLink(File file) {
try {
if (!file.exists()) {
return true;
} else {
String cnnpath = file.getCanonicalPath();
String abspath = file.getAbsolutePath();
return !abspath.equals(cnnpath);
}
} catch (Exception e) {
e.printStackTrace();
return true;
}
}
/**
* Finaliza la ejecucion del explorador. Utilizado para terminar la ejecucion de busquedas
* recursivas manualmente.
*/
public static void stop() {
stoped = true;
}
/**
* Inicializa el explorador de forma que asigna al atributo "stoped" el valor false.
*/
public static void init() {
stoped = false;
}
}