package net.krazyweb.helpers; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.ByteBuffer; import java.nio.channels.ByteChannel; import java.nio.file.DirectoryStream; import java.nio.file.FileVisitOption; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.util.Arrays; import java.util.EnumSet; import java.util.HashSet; import java.util.Set; import java.util.zip.Adler32; import java.util.zip.CheckedInputStream; import net.krazyweb.helpers.FileCopier.TreeCopier; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.message.ParameterizedMessage; public class FileHelper { private static final Logger log = LogManager.getLogger(FileHelper.class); /* * File signatures found at: http://www.garykessler.net/library/file_sigs.html */ private static final char[] SIG_SEVENZIP = new char[] { 0x37, 0x7A, 0xBC, 0xAF, 0x27, 0x1C }; private static final char[] SIG_RAR = new char[] { 0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x00 }; private static final char[] SIG_ZIP = new char[] { 0x50, 0x4B, 0x03, 0x04 }; private static final char[] SIG_PAK = new char[] { 0x53, 0x42, 0x42, 0x46, 0x30, 0x32 }; private static final char[][] SIGNATURES = new char[][] { SIG_SEVENZIP, SIG_RAR, SIG_ZIP, SIG_PAK }; private static final Set<String> SUPPORTED_TYPES = new HashSet<>(Arrays.asList("zip", "7z", "rar", "pak")); public static boolean copyFile(Path src, Path dest) { dest = Files.isDirectory(src) ? dest.resolve(src) : dest; EnumSet<FileVisitOption> opts = EnumSet.of(FileVisitOption.FOLLOW_LINKS); TreeCopier tc = new TreeCopier(src, dest, false, false); try { Files.walkFileTree(src, opts, Integer.MAX_VALUE, tc); return true; } catch (IOException e) { log.error(new ParameterizedMessage("Copying file/folder: {} to {}", src, dest), e); } return false; } public static final String identifyType(final byte[] data) { ByteBuffer buffer = ByteBuffer.wrap(data); String extension = ""; if (buffer.remaining() < 7) { return ""; } for (char[] array : SIGNATURES) { char[] signatureBytes = array; boolean typeFound = false; for (int i = 0; i < signatureBytes.length; i++) { if (buffer.get() != (char) signatureBytes[i]) { buffer.rewind(); break; } if (i == signatureBytes.length - 1) { typeFound = true; } } if (typeFound) { if (signatureBytes == SIG_SEVENZIP) { extension = "7z"; } else if (signatureBytes == SIG_RAR) { extension = "rar"; } else if (signatureBytes == SIG_ZIP) { extension = "zip"; } else if (signatureBytes == SIG_PAK) { extension = "pak"; } break; } } return extension; } public static final String identifyType(final Path path, final boolean suppressLogging) { if (path == null) { return null; } String extension = ""; //TODO Clean this up and close the resources properly. try { ByteChannel b = Files.newByteChannel(path, StandardOpenOption.READ); ByteBuffer buffer = ByteBuffer.allocate(10); b.read(buffer); buffer.position(0); for (char[] array : SIGNATURES) { char[] signatureBytes = array; boolean typeFound = false; for (int i = 0; i < signatureBytes.length; i++) { byte get = buffer.get(); if (get != (byte) signatureBytes[i]) { buffer.position(0); break; } if (i == signatureBytes.length - 1) { typeFound = true; break; } } if (typeFound) { if (signatureBytes == SIG_SEVENZIP) { extension = "7z"; } else if (signatureBytes == SIG_RAR) { extension = "rar"; } else if (signatureBytes == SIG_ZIP) { extension = "zip"; } else if (signatureBytes == SIG_PAK) { extension = "pak"; } break; } } if (!suppressLogging) { log.debug("File '{}' identified as '{}'", path, extension); } b.close(); } catch (IOException e) { // TODO Auto-generated catch block log.error("", e); } return extension; } public static final boolean isSupported(final Path path, final boolean suppressLogging) { if (path == null) { return false; } return SUPPORTED_TYPES.contains(identifyType(path, suppressLogging)); } public static final boolean isSupported(final Path path) { return isSupported(path, false); } public static long getChecksum(final Path path) throws IOException { FileInputStream inputFile = new FileInputStream(path.toFile()); CheckedInputStream checkedStream = new CheckedInputStream(inputFile, new Adler32()); BufferedInputStream input = new BufferedInputStream(checkedStream); while (input.read() != -1) { //Do nothing; simply reading file contents. } input.close(); checkedStream.close(); inputFile.close(); long checksum = checkedStream.getChecksum().getValue(); log.debug("Checksum ({}) created for file: {}", checksum, path); return checksum; } public static Set<Path> listFiles(final String directory, final Set<Path> paths) { return listFiles(Paths.get(directory), paths); } public static Set<Path> listFiles(final Path directory, final Set<Path> paths) { try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(Paths.get(directory.toUri()))) { for (Path path : directoryStream) { paths.add(path); } } catch (IOException e) { log.error(new ParameterizedMessage("Listing files in directory: {}", directory), e); } return paths; } public static void deleteFile(final Path path) throws IOException { //TODO Change to fully use nio if (Files.isDirectory(path)) { File[] children = path.toFile().listFiles(); if (children != null) { for (File child : path.toFile().listFiles()) { deleteFile(child.toPath()); } } } Files.deleteIfExists(path); } public static boolean isJSON(final Path file) { if (getExtension(file).equals("png") || getExtension(file).equals("wav") || getExtension(file).equals("ogg") || getExtension(file).equals("txt") || getExtension(file).equals("lua") || getExtension(file).equals("ttf")) { return false; } return true; } public static String fileToString(File file) { // TODO update to use nio String output = ""; try (BufferedReader in = new BufferedReader(new FileReader(file))) { String line; while ((line = in.readLine()) != null) { output += line + "\r\n"; } } catch (IOException e) { log.error(new ParameterizedMessage("Reading file '{}' to a string.", file), e); return null; } return output; } public static String fileToString(final InputStream file) { // TODO update to use nio String output = ""; try (BufferedReader in = new BufferedReader(new InputStreamReader(file))) { String line; while ((line = in.readLine()) != null) { output += line + "\r\n"; } } catch (IOException e) { log.error(new ParameterizedMessage("Reading file '{}' to a string.", file), e); return null; } return output; } public static String getExtension(final Path path) { int i = path.toString().lastIndexOf("."); if (i >= 0) { return path.toString().substring(i + 1); } return ""; } }