From 72d4bb0200188a0281d9c58eff918c9fc7696524 Mon Sep 17 00:00:00 2001 From: TrianguloY Date: Sun, 12 Jul 2020 11:53:24 +0200 Subject: [PATCH] old first version --- .gitignore | 53 +++ app/.gitignore | 1 + app/build.gradle | 22 ++ app/proguard-rules.pro | 21 ++ app/src/main/AndroidManifest.xml | 37 +++ app/src/main/ic_launcher-web.png | Bin 0 -> 28997 bytes .../trianguloy/urlchecker/CustomAdapter.java | 68 ++++ .../com/trianguloy/urlchecker/OpenLink.java | 301 ++++++++++++++++++ .../com/trianguloy/urlchecker/Settings.java | 30 ++ .../urlchecker/VirusTotalUtility.java | 123 +++++++ .../main/res/layout/activity_open_link.xml | 72 +++++ app/src/main/res/layout/activity_settings.xml | 22 ++ app/src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 2933 bytes app/src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 1836 bytes app/src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 4179 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 6577 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 9513 bytes app/src/main/res/values/strings.xml | 3 + build.gradle | 27 ++ gradle.properties | 13 + gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 54708 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 172 ++++++++++ gradlew.bat | 84 +++++ settings.gradle | 1 + 25 files changed, 1056 insertions(+) create mode 100644 .gitignore create mode 100644 app/.gitignore create mode 100644 app/build.gradle create mode 100644 app/proguard-rules.pro create mode 100644 app/src/main/AndroidManifest.xml create mode 100644 app/src/main/ic_launcher-web.png create mode 100644 app/src/main/java/com/trianguloy/urlchecker/CustomAdapter.java create mode 100644 app/src/main/java/com/trianguloy/urlchecker/OpenLink.java create mode 100644 app/src/main/java/com/trianguloy/urlchecker/Settings.java create mode 100644 app/src/main/java/com/trianguloy/urlchecker/VirusTotalUtility.java create mode 100644 app/src/main/res/layout/activity_open_link.xml create mode 100644 app/src/main/res/layout/activity_settings.xml create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 app/src/main/res/values/strings.xml create mode 100644 build.gradle create mode 100644 gradle.properties create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7cae86d --- /dev/null +++ b/.gitignore @@ -0,0 +1,53 @@ +# Built application files +*.apk +*.ap_ +mapping.txt +output.json + +# Files for the ART/Dalvik VM +*.dex + +# Java class files +*.class + +# Generated files +bin/ +gen/ +out/ + +# Gradle files +.gradle/ +build/ + +# Local configuration file (sdk path, etc) +local.properties + +# Proguard folder generated by Eclipse +proguard/ + +# Log Files +*.log + +# Android Studio Navigation editor temp files +.navigation/ + +# Android Studio captures folder +captures/ + +# Intellij +*.iml +.idea/ + +# Keystore files +*.jks + +# External native build folder generated in Android Studio 2.2 and later +.externalNativeBuild + +# Google Services (e.g. APIs or Firebase) +google-services.json + +# Freeline +freeline.py +freeline/ +freeline_project_description.json diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..5f2a202 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,22 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 29 + defaultConfig { + applicationId "com.trianguloy.urlchecker" + minSdkVersion 10 + targetSdkVersion 29 + versionCode 1 + versionName "1.0" + } + buildTypes { + release { + minifyEnabled true + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..b1b9165 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/ic_launcher-web.png b/app/src/main/ic_launcher-web.png new file mode 100644 index 0000000000000000000000000000000000000000..d117d1ee4f42d5d309ddd1800bbbafd0c7e9a518 GIT binary patch literal 28997 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 C_2NGO literal 0 HcmV?d00001 diff --git a/app/src/main/java/com/trianguloy/urlchecker/CustomAdapter.java b/app/src/main/java/com/trianguloy/urlchecker/CustomAdapter.java new file mode 100644 index 0000000..6bc800f --- /dev/null +++ b/app/src/main/java/com/trianguloy/urlchecker/CustomAdapter.java @@ -0,0 +1,68 @@ +package com.trianguloy.urlchecker; + +import android.content.Context; +import android.content.pm.PackageManager; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.ImageView; + +import java.util.ArrayList; + +/** + * Class that [INSERT DESCRIPTION HERE] + */ +class CustomAdapter extends BaseAdapter { + + private Context cntx; + private ArrayList items = new ArrayList<>(); + + // Constructor + CustomAdapter(Context cntx) { + this.cntx = cntx; + } + + void addItem(String packageName) { + items.add(packageName); + } + + void clearAll() { + items.clear(); + } + + + @Override + public int getCount() { + return items.size(); + } + + @Override + public String getItem(int i) { + return items.get(i); + } + + @Override + public long getItemId(int i) { + return 0; + } + + @Override + public View getView(int i, View convertView, ViewGroup viewGroup) { + ImageView imageView; + if (convertView == null) { + // if it's not recycled, initialize some attributes + imageView = new ImageView(cntx); + imageView.setPadding(8, 8, 8, 8); + } else { + imageView = (ImageView) convertView; + } + + try { + imageView.setImageDrawable(cntx.getPackageManager().getApplicationIcon(items.get(i))); + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + imageView.setImageResource(R.mipmap.ic_launcher); + } + return imageView; + } +} diff --git a/app/src/main/java/com/trianguloy/urlchecker/OpenLink.java b/app/src/main/java/com/trianguloy/urlchecker/OpenLink.java new file mode 100644 index 0000000..6f276ac --- /dev/null +++ b/app/src/main/java/com/trianguloy/urlchecker/OpenLink.java @@ -0,0 +1,301 @@ +package com.trianguloy.urlchecker; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.graphics.Color; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.os.Parcelable; +import android.view.View; +import android.view.Window; +import android.widget.AdapterView; +import android.widget.GridView; +import android.widget.ImageButton; +import android.widget.TextView; +import android.widget.Toast; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLDecoder; +import java.util.ArrayList; +import java.util.List; + +public class OpenLink extends Activity { + + private TextView txt_url; + private TextView txt_result; + private ImageButton btn_redirect; + private ImageButton btn_scan; + + private CustomAdapter adapter; + + private String url = null; + private VirusTotalUtility.InternalReponse result = null; + + private boolean scanning = false; + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + requestWindowFeature(Window.FEATURE_NO_TITLE); + setContentView(R.layout.activity_open_link); + + Uri uri = this.getIntent().getData(); + if (uri == null) { + Toast.makeText(this, "No url!!!!", Toast.LENGTH_SHORT).show(); + finish(); + return; + } + url = uri.toString(); + + txt_url = findViewById(R.id.txt_url); + txt_result = findViewById(R.id.txt_result); + btn_redirect = findViewById(R.id.btn_goRedirect); + btn_scan = findViewById(R.id.btn_scan); + + GridView grdVw_browsers = findViewById(R.id.grdVw_browsers); + adapter = new CustomAdapter(this); + + grdVw_browsers.setAdapter(adapter); + grdVw_browsers.setOnItemClickListener(new AdapterView.OnItemClickListener() { + public void onItemClick(AdapterView parent, View v, int position, long id) { + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); + intent.setPackage(adapter.getItem(position)); + startActivity(intent); + } + }); + + + //setOnLongClick + View.OnLongClickListener onLongClickListener = new View.OnLongClickListener() { + @Override + public boolean onLongClick(View view) { + OpenLink.this.onLongClick(view); + return false; + } + }; + txt_url.setOnLongClickListener(onLongClickListener); + txt_result.setOnLongClickListener(onLongClickListener); + + btn_redirect.setOnLongClickListener(onLongClickListener); + btn_scan.setOnLongClickListener(onLongClickListener); + + + updateUI(); + createBrowsers(); + + } + + private void setResult(String message, int color) { + txt_result.setBackgroundColor(color); + txt_result.setText(message); + } + + private void scanUrl() { + if (scanning) { + scanning = false; + } else { + scanning = true; + new Thread(new Runnable() { + public void run() { + _scanUrl(); + } + }).start(); + } + updateUI(); + } + + private void _scanUrl() { + VirusTotalUtility.InternalReponse response; + while (scanning) { + response = VirusTotalUtility.scanUrl(url); + + if (response.detectionsTotal > 0) { + result = response; + scanning = false; + runOnUiThread(new Runnable() { + public void run() { + updateUI(); + } + }); + return; + } + + //retry + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + } + + private void updateUI() { + txt_url.setText(url); + + if (scanning) { + btn_scan.setImageResource(android.R.drawable.ic_menu_close_clear_cancel); + setResult("Scanning...", Color.GRAY); + } else { + btn_scan.setImageResource(android.R.drawable.ic_menu_search); + if (result == null) { + setResult("Press to scan", 0); + } else { + if (result.detectionsTotal <= 0) { + setResult("no detections? strange", Color.YELLOW); + } else if (result.detectionsPositive > 0) { + setResult("Uh oh, " + result.detectionsPositive + "/" + result.detectionsTotal + " engines detected the url (as of date " + result.date + ")", Color.RED); + } else { + setResult("None of the " + result.detectionsTotal + " engines detected the site (as of date " + result.date + ")", Color.GREEN); + } + } + } + + } + + public void onClick(View view) { + switch (view.getId()) { + case R.id.btn_scan: + scanUrl(); + break; + case R.id.btn_goRedirect: + followRedirect(); + break; + case R.id.txt_result: + if (result != null) { + openUrlInBrowser(result.scanUrl); + } + break; + + //DEBUG: just in case + case R.id.txt_url: + openUrlInBrowser(url); + break; + } + } + + public void onLongClick(View view) { + switch (view.getId()) { + case R.id.btn_goRedirect: + case R.id.btn_scan: + Toast.makeText(this, view.getContentDescription(), Toast.LENGTH_SHORT).show(); + break; + + case R.id.txt_result: + showDebug(); + break; + } + } + + private void showDebug() { + if (result != null) { + new AlertDialog.Builder(this) + .setMessage(result.info) + .show(); + } + } + + //https://stackoverflow.com/questions/1884230/urlconnection-doesnt-follow-redirect + private void followRedirect() { + + new Thread(new Runnable() { + public void run() { + String message = null; + HttpURLConnection conn = null; + try { + conn = (HttpURLConnection) new URL(url).openConnection(); + conn.setInstanceFollowRedirects(false); // Make the logic below easier to detect redirections + switch (conn.getResponseCode()) { + case HttpURLConnection.HTTP_MOVED_PERM: + case HttpURLConnection.HTTP_MOVED_TEMP: + String location = conn.getHeaderField("Location"); + location = URLDecoder.decode(location, "UTF-8"); + url = new URL(new URL(url), location).toExternalForm(); // Deal with relative URLs + result = null; + break; + default: + message = "No redirection, final URL, try to scan now"; + } + } catch (IOException e) { + e.printStackTrace(); + message = "Error when following redirect"; + } finally { + if (conn != null) { + conn.disconnect(); + } + } + _createBrowsers(); + + final String finalMessage = message; + runOnUiThread(new Runnable() { + public void run() { + updateUI(); + if (finalMessage != null) { + Toast.makeText(OpenLink.this, finalMessage, Toast.LENGTH_SHORT).show(); + btn_redirect.setEnabled(false); + } + } + }); + } + }).start(); + + + } + + private void createBrowsers() { + new Thread(new Runnable() { + @Override + public void run() { + _createBrowsers(); + runOnUiThread(new Runnable() { + @Override + public void run() { + adapter.notifyDataSetChanged(); + } + }); + } + }).start(); + } + + private void _createBrowsers() { + adapter.clearAll(); + Intent baseIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); + PackageManager packageManager = getPackageManager(); + List resolveInfos = packageManager.queryIntentActivities(baseIntent, Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? PackageManager.MATCH_ALL : 0); + for (ResolveInfo resolveInfo : resolveInfos) { + if (!resolveInfo.activityInfo.packageName.equals(getPackageName())) { + adapter.addItem(resolveInfo.activityInfo.packageName); + } + } + } + + + private void openUrlInBrowser(String url) { + Intent baseIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); + PackageManager packageManager = getPackageManager(); + List resolveInfos = packageManager.queryIntentActivities(baseIntent, Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? PackageManager.MATCH_ALL : 0); + List intents = new ArrayList<>(); + for (ResolveInfo resolveInfo : resolveInfos) { + if (!resolveInfo.activityInfo.packageName.equals(getPackageName())) { + Intent intent = new Intent(baseIntent); + intent.setPackage(resolveInfo.activityInfo.packageName); + intents.add(intent); + } + } + + Intent chooserIntent = Intent.createChooser(intents.remove(0), "Choose app"); + chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intents.toArray(new Parcelable[intents.size()])); + + startActivity(chooserIntent); + + //startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); + finish(); + } +} diff --git a/app/src/main/java/com/trianguloy/urlchecker/Settings.java b/app/src/main/java/com/trianguloy/urlchecker/Settings.java new file mode 100644 index 0000000..d535bae --- /dev/null +++ b/app/src/main/java/com/trianguloy/urlchecker/Settings.java @@ -0,0 +1,30 @@ +package com.trianguloy.urlchecker; + +import android.app.Activity; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.view.View; + +public class Settings extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_settings); + + + } + + public void onClick(View view) { + switch (view.getId()) { + case R.id.btn_debug: + openGoogle(); + break; + } + } + + private void openGoogle() { + startActivity(Intent.createChooser(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.google.com")), "Open")); + } +} diff --git a/app/src/main/java/com/trianguloy/urlchecker/VirusTotalUtility.java b/app/src/main/java/com/trianguloy/urlchecker/VirusTotalUtility.java new file mode 100644 index 0000000..c7106bf --- /dev/null +++ b/app/src/main/java/com/trianguloy/urlchecker/VirusTotalUtility.java @@ -0,0 +1,123 @@ +package com.trianguloy.urlchecker; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.UnsupportedEncodingException; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLEncoder; + +/** + * Class that [INSERT DESCRIPTION HERE] + */ +public class VirusTotalUtility { + static private final String key = "**REMOVED**"; + + static private final String urlGetReport = "http://www.virustotal.com/vtapi/v2/url/report"; + + static class InternalReponse { + String error = "Unknown error"; + int detectionsPositive; + int detectionsTotal; + String date; + String scanUrl; + String info; + } + + static InternalReponse scanUrl(String urlToScan) { + InternalReponse result = new InternalReponse(); + + String responseJSON = performPOST(urlGetReport, getPOSTparameters(urlToScan)); + + // parse response + try { + JSONObject response = new JSONObject(responseJSON); + + result.info = response.toString(1); + + if (response.getInt("response_code") == 1) { + result.detectionsPositive = response.optInt("positives", -1); + result.detectionsTotal = response.optInt("total", -1); + result.date = response.optString("scan_date", null); + result.scanUrl = response.optString("permalink", null); + + result.error = null; + return result; + } else { + result.error = response.getString("verbose_msg"); + } + } catch (JSONException e) { + e.printStackTrace(); + result.error = "JSON exception"; + } + + + return result; + + } + + static private String getPOSTparameters(String url) { + String data = null; + try { + data = URLEncoder.encode("resource", "UTF-8") + + "=" + URLEncoder.encode(url, "UTF-8"); + + data += "&" + URLEncoder.encode("scan", "UTF-8") + "=" + + URLEncoder.encode("1", "UTF-8"); + + data += "&" + URLEncoder.encode("apikey", "UTF-8") + + "=" + URLEncoder.encode(key, "UTF-8"); + + data += "&" + URLEncoder.encode("allinfo", "UTF-8") + + "=" + URLEncoder.encode("true", "UTF-8"); + + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return data; + } + + + private static String performPOST(String urlString, String parameters) { + BufferedReader reader = null; + try { + + // Defined URL where to send data + URL url = new URL(urlString); + + // Send POST data request + URLConnection conn = url.openConnection(); + conn.setDoOutput(true); + OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream()); + wr.write(parameters); + wr.flush(); + + // Get the server response + + reader = new BufferedReader(new InputStreamReader(conn.getInputStream())); + StringBuilder sb = new StringBuilder(); + String line = null; + // Read Server Response + while ((line = reader.readLine()) != null) { + // Append server response in string + sb.append(line).append("\n"); + } + return sb.toString(); + } catch (Exception ex) { + ex.printStackTrace(); + } finally { + if (reader != null) { + try { + reader.close(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + } + return null; + } +} diff --git a/app/src/main/res/layout/activity_open_link.xml b/app/src/main/res/layout/activity_open_link.xml new file mode 100644 index 0000000..327d7dc --- /dev/null +++ b/app/src/main/res/layout/activity_open_link.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml new file mode 100644 index 0000000..c0627f3 --- /dev/null +++ b/app/src/main/res/layout/activity_settings.xml @@ -0,0 +1,22 @@ + + + + + +