From b8088d52ef14b729a9fcefcc0c496c4eec6460fc Mon Sep 17 00:00:00 2001 From: Daniel Prange Date: Fri, 30 Apr 2021 16:42:18 +0200 Subject: [PATCH 1/2] Added a Service to listen to a configurable port and send the received link list to the server See issue #37 --- app/src/main/AndroidManifest.xml | 5 + .../org/pyload/android/client/pyLoad.java | 57 +++++--- .../org/pyload/android/client/pyLoadApp.java | 10 ++ .../clicknload/ClickNLoadService.java | 51 +++++++ .../services/clicknload/ClickNLoadTask.java | 124 ++++++++++++++++++ app/src/main/res/values-de/strings.xml | 5 + app/src/main/res/values/strings.xml | 5 + app/src/main/res/xml/preferences.xml | 21 ++- 8 files changed, 255 insertions(+), 23 deletions(-) create mode 100644 app/src/main/java/org/pyload/android/client/services/clicknload/ClickNLoadService.java create mode 100644 app/src/main/java/org/pyload/android/client/services/clicknload/ClickNLoadTask.java diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2f4be72..dca9088 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -105,5 +105,10 @@ + + diff --git a/app/src/main/java/org/pyload/android/client/pyLoad.java b/app/src/main/java/org/pyload/android/client/pyLoad.java index cd50b0e..ec83246 100644 --- a/app/src/main/java/org/pyload/android/client/pyLoad.java +++ b/app/src/main/java/org/pyload/android/client/pyLoad.java @@ -1,15 +1,21 @@ package org.pyload.android.client; -import java.io.File; -import java.io.FileInputStream; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Locale; - import android.app.NotificationManager; +import android.content.Context; +import android.content.Intent; import android.content.res.Configuration; -import android.view.*; +import android.content.res.Resources; +import android.net.ConnectivityManager; +import android.net.Uri; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.util.Log; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.widget.TabHost; + +import androidx.core.view.MenuItemCompat; import org.pyload.android.client.components.FragmentTabsPager; import org.pyload.android.client.dialogs.AccountDialog; @@ -18,31 +24,26 @@ import org.pyload.android.client.fragments.QueueFragment; import org.pyload.android.client.module.Eula; import org.pyload.android.client.module.GuiTask; +import org.pyload.android.client.services.clicknload.ClickNLoadService; import org.pyload.thrift.Destination; import org.pyload.thrift.PackageDoesNotExists; import org.pyload.thrift.Pyload.Client; -import android.content.Context; -import android.content.Intent; -import android.content.res.Resources; -import android.net.ConnectivityManager; -import android.net.Uri; -import android.os.Bundle; -import android.preference.PreferenceManager; -import android.util.Log; -import android.widget.TabHost; -import androidx.core.view.MenuItemCompat; +import java.io.File; +import java.io.FileInputStream; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Locale; public class pyLoad extends FragmentTabsPager { private pyLoadApp app; - // keep reference to set indeterminateProgress private MenuItem refreshItem; /** Called when the activity is first created. */ - public void onCreate(Bundle savedInstanceState) { @@ -90,6 +91,8 @@ public void onCreate(Bundle savedInstanceState) spec = mTabHost.newTabSpec(title).setIndicator(title, res.getDrawable(tab_collector)); mTabsAdapter.addTab(spec, CollectorFragment.class, null); + + startClickNLoadService(); } @Override @@ -359,4 +362,16 @@ public MenuItem getRefreshItem() { return refreshItem; } -} + + private void startClickNLoadService() { + if(app.prefs.getBoolean("check_box_clicknload", false)){ + Intent i= new Intent(getApplicationContext(), ClickNLoadService.class); + i.setAction("START"); + int port = Integer.parseInt(app.prefs.getString("edit_text_clicknload_port", "9666")); + i.putExtra("port", port); + + getApplicationContext().startService(i); + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/org/pyload/android/client/pyLoadApp.java b/app/src/main/java/org/pyload/android/client/pyLoadApp.java index a47d299..00bee60 100644 --- a/app/src/main/java/org/pyload/android/client/pyLoadApp.java +++ b/app/src/main/java/org/pyload/android/client/pyLoadApp.java @@ -14,6 +14,7 @@ import android.annotation.TargetApi; import android.content.Context; +import android.os.Looper; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; @@ -332,4 +333,13 @@ public boolean getCaptchaNotificationShown() return captchaNotificationShown; } + public void showToast(final String text, final int duration){ + new Handler(Looper.getMainLooper()).post(new Runnable(){ + @Override + public void run() { + Toast.makeText(getBaseContext(), text, duration).show(); + } + }); + } + } diff --git a/app/src/main/java/org/pyload/android/client/services/clicknload/ClickNLoadService.java b/app/src/main/java/org/pyload/android/client/services/clicknload/ClickNLoadService.java new file mode 100644 index 0000000..68d296d --- /dev/null +++ b/app/src/main/java/org/pyload/android/client/services/clicknload/ClickNLoadService.java @@ -0,0 +1,51 @@ +package org.pyload.android.client.services.clicknload; + +import android.app.Service; +import android.content.ComponentName; +import android.content.Intent; +import android.os.IBinder; +import android.util.Log; + +import org.pyload.android.client.pyLoadApp; + +import java.util.concurrent.Executors; + +public class ClickNLoadService extends Service { + + private final static String LOGTAG = "ClickNLoad Service"; + + private ClickNLoadTask clickNLoadTask; + private int port; + + @Override + public int onStartCommand(final Intent intent, int flags, int startId) { + + if (intent != null) { + String action = intent.getAction(); + port = intent.getExtras().getInt("port"); + switch(action) { + case "START": startService(); break; + case "STOP": stopService(); break; + default: Log.d(LOGTAG, "This should never happen. No action in the received intent"); + } + } else { + Log.d(LOGTAG, "with a null intent. It has been probably restarted by the system."); + } + + return Service.START_STICKY; + } + + private void stopService() { + clickNLoadTask.stop(); + } + + public void startService() { + clickNLoadTask = new ClickNLoadTask(port, (pyLoadApp) getApplicationContext()); + Executors.newSingleThreadExecutor().submit(clickNLoadTask); + } + + @Override + public IBinder onBind(Intent intent) { + return null; + } +} diff --git a/app/src/main/java/org/pyload/android/client/services/clicknload/ClickNLoadTask.java b/app/src/main/java/org/pyload/android/client/services/clicknload/ClickNLoadTask.java new file mode 100644 index 0000000..b3fca86 --- /dev/null +++ b/app/src/main/java/org/pyload/android/client/services/clicknload/ClickNLoadTask.java @@ -0,0 +1,124 @@ +package org.pyload.android.client.services.clicknload; + + +import android.content.Context; +import android.content.SharedPreferences; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.provider.Settings; +import android.util.Log; +import android.widget.Toast; + +import org.pyload.android.client.R; +import org.pyload.android.client.pyLoadApp; +import org.pyload.thrift.Destination; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.io.UnsupportedEncodingException; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.URLDecoder; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +public class ClickNLoadTask implements Runnable{ + + private final static String LOGTAG= "ClickNLoadTask"; + + private volatile boolean stopped = false; + private int port; + private pyLoadApp app; + + public ClickNLoadTask(int port, pyLoadApp app){ + this.port = port; + this.app = app; + + app.prefs.registerOnSharedPreferenceChangeListener(new SharedPreferences.OnSharedPreferenceChangeListener() { + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + //stop if clicknload gets disabled + if(key.equals("check_box_clicknload") && !sharedPreferences.getBoolean(key, true)){ + stop(); + } + } + }); + } + + @Override + public void run() { + Socket clientSocket = null; + BufferedReader in; + PrintStream out; + ServerSocket serverSocket = null; + + while (!stopped) { + + try { + if (serverSocket != null) { + serverSocket.close(); + clientSocket.close(); + } + serverSocket = new ServerSocket(port); + clientSocket = serverSocket.accept(); + + Log.d(LOGTAG, "Receiving ClickNLoad Event"); + in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); + out = new PrintStream(clientSocket.getOutputStream()); + } catch (IOException e) { + Log.e(LOGTAG, "Socket could not be opened", e); + stop(); + break; + } + + try { + String input; + while ((input = in.readLine()) != null) { + if (input.startsWith("source")) { + List urlList = getURLParamsAsMap(input).get("urls"); + app.getClient().addPackage("TestName", urlList, Destination.Collector); + app.showToast(String.format(getLocalizedResources(app).getString(R.string.clicknload_toast_msg), urlList.size()), Toast.LENGTH_LONG); + } + } + out.println("success"); + } catch (Exception e) { + Log.e(LOGTAG, "Data could not be parsed"); + break; + } + } + } + + public static Map> getURLParamsAsMap(String parameters) throws UnsupportedEncodingException { + final Map> parameterMap = new LinkedHashMap<>(); + final String[] pairs = parameters.split("&"); + for (String pair : pairs) { + final int idx = pair.indexOf("="); + final String key = idx > 0 ? URLDecoder.decode(pair.substring(0, idx), "UTF-8") : pair; + if (!parameterMap.containsKey(key)) { + parameterMap.put(key, new LinkedList()); + } + final String[] values = idx > 0 && pair.length() > idx + 1 ? URLDecoder.decode(pair.substring(idx + 1), "UTF-8").split("\\r?\\n") : new String[0]; + for (String value : values) { + parameterMap.get(key).add(value); + } + } + return parameterMap; + } + + public void stop() { + stopped = true; + } + + Resources getLocalizedResources(Context context) { + Configuration conf = context.getResources().getConfiguration(); + conf = new Configuration(conf); + conf.setLocale(Locale.getDefault()); + Context localizedContext = context.createConfigurationContext(conf); + return localizedContext.getResources(); + } +} diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 89cc4c9..d9bb24e 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -53,6 +53,11 @@ Bitte geben Sie den Text ein Tabfarbe invertieren Du kannst das Tab-Aussehen ändern, damit es besser zu deinem System Theme passt. + Aktiviere Click\'n\'Load + Lässt die App auf Click\'n\'Load Verbindungen reagieren. + Click\'n\'Load Port + Der Server Port für Click\'n\'Load. + Paket mit %d Links empfangen. Zum Collector gesendet SSL Verbindung Eine sichere Verbindung zum Server aufbauen, wenn SSL aktiviert wurde. Bestätige das SSL Zertifikat diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 21dc99b..37d033a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -58,6 +58,11 @@ Enter captcha to continue downloading. Invert tab icon color You may change the tab icon layout if it fits better to your theme. + Enable Click\'n\'Load + Have the app listen for Click\'n\'Load connections. + Click\'n\'Load Port + Server Port for Click\'n\'Load. + Received a package with %d links. Send to Collector SSL Connection Establish a secure connection to the core if you activated SSL Validate SSL Certificate diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 3fbd436..805a1b3 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -12,8 +12,25 @@ - - + + + + From a13d87e1f363f4810de93d05a88c6592ea47d7a7 Mon Sep 17 00:00:00 2001 From: Daniel Prange Date: Fri, 30 Apr 2021 16:48:18 +0200 Subject: [PATCH 2/2] fixed issue in Manifest.xml --- app/src/main/AndroidManifest.xml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index dca9088..a3f0fbd 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -107,8 +107,6 @@ - + android:exported="true"/>