diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser index 2a47594..b29011f 100644 Binary files a/.idea/caches/build_file_checksums.ser and b/.idea/caches/build_file_checksums.ser differ diff --git a/app/build.gradle b/app/build.gradle index f7e850d..ccf6732 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -6,8 +6,8 @@ android { applicationId "us.spotco.malwarescanner" minSdkVersion 16 targetSdkVersion 29 - versionCode 47 - versionName "2.10" + versionCode 48 + versionName "2.11" resConfigs "en" } buildTypes { diff --git a/app/src/main/java/us/spotco/malwarescanner/Database.java b/app/src/main/java/us/spotco/malwarescanner/Database.java index c03c023..48b2454 100644 --- a/app/src/main/java/us/spotco/malwarescanner/Database.java +++ b/app/src/main/java/us/spotco/malwarescanner/Database.java @@ -32,8 +32,13 @@ import java.net.HttpURLConnection; import java.net.InetSocketAddress; import java.net.Proxy; import java.net.URL; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; import java.util.HashMap; import java.util.HashSet; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadPoolExecutor; import java.util.zip.GZIPInputStream; class Database { @@ -41,6 +46,7 @@ class Database { private static TextView log = null; private static SharedPreferences prefs = null; private static File databasePath = null; + private static ThreadPoolExecutor threadPoolExecutor = null; public final static HashSet signatureDatabases = new HashSet<>(); public final static String baseURL = "https://spotco.us/MalwareScannerSignatures/"; @@ -50,8 +56,11 @@ class Database { public final static HashMap signaturesSHA1 = new HashMap<>(); public final static HashMap signaturesSHA256 = new HashMap<>(); + private static final DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd"); + public Database(TextView log) { Database.log = log; + threadPoolExecutor = (ThreadPoolExecutor) Executors.newScheduledThreadPool(Utils.getMaxThreads()); } public static boolean areDatabasesAvailable() { @@ -68,9 +77,10 @@ class Database { public static void updateDatabase(Context context, HashSet signatureDatabases) { initDatabase(context); + log.append("Updating " + signatureDatabases.size() + " databases...\n"); for (SignatureDatabase signatureDatabase : signatureDatabases) { boolean onionRouting = prefs.getBoolean("ONION_ROUTING", false); - new Downloader().execute(onionRouting, signatureDatabase.getUrl(), databasePath + "/" + signatureDatabase.getName()); + new Downloader().executeOnExecutor(threadPoolExecutor, onionRouting, signatureDatabase.getUrl(), databasePath + "/" + signatureDatabase.getName()); } } @@ -153,13 +163,11 @@ class Database { } public static class Downloader extends AsyncTask { - @Override protected String doInBackground(Object... objects) { boolean onionRouting = (boolean) objects[0]; String url = (String) objects[1]; File out = new File((String) objects[2]); - publishProgress("Downloading " + url.replaceAll(baseURL, "")); try { HttpURLConnection connection; if (onionRouting) { @@ -173,10 +181,13 @@ class Database { connection.setConnectTimeout(90000); connection.setReadTimeout(30000); connection.addRequestProperty("User-Agent", "Hypatia"); + String lastModifiedLocal = ""; if (out.exists()) { connection.setIfModifiedSince(out.lastModified()); + lastModifiedLocal = " since " + dateFormat.format(new Date(out.lastModified())); } connection.connect(); + String lastModifiedServer = dateFormat.format(new Date(connection.getLastModified())); int res = connection.getResponseCode(); if (res != 304) { if (res == 200) { @@ -192,18 +203,23 @@ class Database { } fileOutputStream.close(); - publishProgress("Successfully downloaded\n"); + publishProgress(url.replaceAll(baseURL, "") + + "\n\tSuccessfully downloaded." + + "\n\tReleased on " + lastModifiedServer + "\n"); } else { - publishProgress("File not downloaded, response code " + res + "\n"); + publishProgress(url.replaceAll(baseURL, "") + + "\n\tFile not downloaded, response code " + res + "\n"); } } else { - publishProgress("File not changed\n"); + publishProgress(url.replaceAll(baseURL, "") + + "\n\tFile not changed" + lastModifiedLocal + "\n"); } connection.disconnect(); } catch (Exception e) { e.printStackTrace(); out.delete(); - publishProgress("Failed to download, check logcat\n"); + publishProgress(url.replaceAll(baseURL, "") + + "\nFailed to download, check logcat\n"); } return null; } diff --git a/app/src/main/java/us/spotco/malwarescanner/MalwareScanner.java b/app/src/main/java/us/spotco/malwarescanner/MalwareScanner.java index ee9f94f..48b9e26 100644 --- a/app/src/main/java/us/spotco/malwarescanner/MalwareScanner.java +++ b/app/src/main/java/us/spotco/malwarescanner/MalwareScanner.java @@ -102,18 +102,18 @@ class MalwareScanner extends AsyncTask, Object, String> { fileHashesSHA1.clear(); fileHashesSHA256.clear(); - publishProgress(filesToScan[0].size() + " files pending scan\n", true); + publishProgress("\t" + filesToScan[0].size() + " files pending scan\n", true); Database.loadDatabase(context, true, Database.signatureDatabases); if (Database.getSignatureCount() >= 0) { - publishProgress("Loaded database with " + Database.getSignatureCount() + " signatures\n", true); + publishProgress("\tLoaded database with " + Database.getSignatureCount() + " signatures\n", true); //Get file hashes - publishProgress("Hashing files...", true); + publishProgress("\tHashing files...", true); for (File file : filesToScan[0]) { getFileHashes(file); } - publishProgress("Calculated MD5/SHA-1/SHA-256 hashes for all files\n", true); + publishProgress("\tCalculated hashes for all files\n", true); //Check the hashes checkSignature("MD5", fileHashesMD5, Database.signaturesMD5); @@ -129,7 +129,7 @@ class MalwareScanner extends AsyncTask, Object, String> { Log.d("Hypatia", "Scan completed in " + (SystemClock.elapsedRealtime() - scanTime) + " ms!"); publishProgress("Scan completed in " + ((SystemClock.elapsedRealtime() - scanTime) / 1000) + " seconds!\n\n\n\n", true); } else { - publishProgress("No database available, not scanning...", true); + publishProgress("\tNo database available, not scanning...", true); } return null; } @@ -147,9 +147,9 @@ class MalwareScanner extends AsyncTask, Object, String> { publishProgress(result + " in " + file.getValue().toString().replaceAll(Environment.getExternalStorageDirectory().toString(), "~"), false); } } - publishProgress("Checked all " + hashType + " hashes against signature databases\n", true); + publishProgress("\tChecked all " + hashType + " hashes against signature databases\n", true); } else { - publishProgress("No " + hashType + " signatures available\n", true); + publishProgress("\tNo " + hashType + " signatures available\n", true); } }