Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ClickNLoad Support #38

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -105,5 +105,8 @@

<activity android:name=".RemoteSettings" android:label="@string/remotesettings_activity"/>

<service
android:name=".services.clicknload.ClickNLoadService"
android:exported="true"/>
</application>
</manifest>
57 changes: 36 additions & 21 deletions app/src/main/java/org/pyload/android/client/pyLoad.java
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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)
{

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
}
}

}
10 changes: 10 additions & 0 deletions app/src/main/java/org/pyload/android/client/pyLoadApp.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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();
}
});
}

}
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -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<String> 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<String, List<String>> getURLParamsAsMap(String parameters) throws UnsupportedEncodingException {
final Map<String, List<String>> 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<String>());
}
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();
}
}
5 changes: 5 additions & 0 deletions app/src/main/res/values-de/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@
<string name="captcha_dialog_titel">Bitte geben Sie den Text ein</string>
<string name="invert_tabs">Tabfarbe invertieren</string>
<string name="invert_tabs_desc">Du kannst das Tab-Aussehen ändern, damit es besser zu deinem System Theme passt.</string>
<string name="enable_clicknload">Aktiviere Click\'n\'Load</string>
<string name="enable_clicknload_desc">Lässt die App auf Click\'n\'Load Verbindungen reagieren.</string>
<string name="clicknload_port">Click\'n\'Load Port</string>
<string name="clicknload_port_desc">Der Server Port für Click\'n\'Load.</string>
<string name="clicknload_toast_msg">Paket mit %d Links empfangen. Zum Collector gesendet</string>
<string name="ssl">SSL Verbindung</string>
<string name="ssl_desc">Eine sichere Verbindung zum Server aufbauen, wenn SSL aktiviert wurde.</string>
<string name="ssl_validate">Bestätige das SSL Zertifikat</string>
Expand Down
5 changes: 5 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@
<string name="captcha_notification_desc">Enter captcha to continue downloading.</string>
<string name="invert_tabs">Invert tab icon color</string>
<string name="invert_tabs_desc">You may change the tab icon layout if it fits better to your theme.</string>
<string name="enable_clicknload">Enable Click\'n\'Load</string>
<string name="enable_clicknload_desc">Have the app listen for Click\'n\'Load connections.</string>
<string name="clicknload_port">Click\'n\'Load Port</string>
<string name="clicknload_port_desc">Server Port for Click\'n\'Load.</string>
<string name="clicknload_toast_msg">Received a package with %d links. Send to Collector</string>
<string name="ssl">SSL Connection</string>
<string name="ssl_desc">Establish a secure connection to the core if you activated SSL</string>
<string name="ssl_validate">Validate SSL Certificate</string>
Expand Down
21 changes: 19 additions & 2 deletions app/src/main/res/xml/preferences.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,25 @@
<EditTextPreference android:key="refresh_rate" android:defaultValue="5" android:summary="@string/refresh_rate_desc" android:title="@string/refresh_rate" android:numeric="integer"/>
<CheckBoxPreference android:key="pull_captcha" android:title="@string/retrieve_captcha" android:summary="@string/retrieve_captcha_desc" android:defaultValue="true"/>
<CheckBoxPreference android:key="invert_tabs" android:summary="@string/invert_tabs_desc" android:title="@string/invert_tabs" android:defaultValue="false"/>


<CheckBoxPreference
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:defaultValue="false"
android:key="check_box_clicknload"
android:summary="@string/enable_clicknload_desc"
android:title="@string/enable_clicknload" />
<EditTextPreference
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:defaultValue="9666"
android:digits="0123456789"
android:inputType="number"
android:key="edit_text_clicknload_port"
android:singleLine="true"
android:summary="@string/clicknload_port_desc"
android:title="@string/clicknload_port" />


</PreferenceCategory><PreferenceCategory android:key="login" android:title="@string/login">
<EditTextPreference android:key="username" android:summary="@string/username_desc" android:title="@string/username" android:singleLine="true"/>
<EditTextPreference android:key="password" android:title="@string/password" android:singleLine="true" android:password="true"/>
Expand Down