diff --git a/app/src/main/java/ca/pkay/rcloneexplorer/Dialogs/ServeDialog.java b/app/src/main/java/ca/pkay/rcloneexplorer/Dialogs/ServeDialog.java
new file mode 100644
index 0000000..84cad14
--- /dev/null
+++ b/app/src/main/java/ca/pkay/rcloneexplorer/Dialogs/ServeDialog.java
@@ -0,0 +1,148 @@
+package ca.pkay.rcloneexplorer.Dialogs;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.design.widget.TextInputLayout;
+import android.support.v4.app.DialogFragment;
+import android.support.v4.app.FragmentActivity;
+import android.support.v7.app.AlertDialog;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.EditText;
+import android.widget.RadioGroup;
+
+import ca.pkay.rcloneexplorer.R;
+import ca.pkay.rcloneexplorer.Rclone;
+
+public class ServeDialog extends DialogFragment {
+
+ private Context context;
+ private boolean isDarkTheme;
+ private Callback callback;
+ private RadioGroup protocol;
+ private CheckBox allowRemoteAccess;
+ private EditText user;
+ private EditText password;
+
+ public interface Callback {
+ void onServeOptionsSelected(int protocol, boolean allowRemoteAccess, String user, String password);
+ }
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ if (getParentFragment() != null) {
+ callback = (Callback) getParentFragment();
+ }
+
+ if (savedInstanceState != null) {
+ isDarkTheme = savedInstanceState.getBoolean("isDarkTheme");
+ }
+
+ AlertDialog.Builder builder;
+ if (isDarkTheme) {
+ builder = new AlertDialog.Builder(context, R.style.DarkDialogTheme);
+ } else {
+ builder = new AlertDialog.Builder(context);
+ }
+
+ LayoutInflater layoutInflater = ((FragmentActivity)context).getLayoutInflater();
+ View view = layoutInflater.inflate(R.layout.dialog_serve, null);
+
+ protocol = view.findViewById(R.id.radio_group_protocol);
+ allowRemoteAccess = view.findViewById(R.id.checkbox_allow_remote_access);
+ user = view.findViewById(R.id.edit_text_user);
+ password = view.findViewById(R.id.edit_text_password);
+
+ ((TextInputLayout) view.findViewById(R.id.text_input_layout_user)).setHint("Username");
+ ((TextInputLayout) view.findViewById(R.id.text_input_layout_password)).setHint("Password");
+
+ builder.setTitle(R.string.serve_dialog_title);
+ builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ sendCallback();
+ }
+ });
+
+ builder.setNegativeButton(R.string.cancel, null);
+
+ builder.setView(view);
+
+ return builder.show();
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putBoolean("isDarkTheme", isDarkTheme);
+ outState.putInt("protocol", protocol.getCheckedRadioButtonId());
+ outState.putBoolean("allowRemoteAccess", allowRemoteAccess.isChecked());
+ if (!user.getText().toString().trim().isEmpty()) {
+ outState.putString("user", user.getText().toString());
+ }
+ if (!password.getText().toString().trim().isEmpty()) {
+ outState.putString("password", password.getText().toString());
+ }
+ }
+
+ @Override
+ public void onViewStateRestored(@Nullable Bundle savedInstanceState) {
+ super.onViewStateRestored(savedInstanceState);
+ if (savedInstanceState == null) {
+ return;
+ }
+
+ allowRemoteAccess.setChecked(savedInstanceState.getBoolean("allowRemoteAccess", false));
+ String savedUser = savedInstanceState.getString("user");
+ if (savedUser != null) {
+ user.setText(savedUser);
+ }
+
+ String savedPassword = savedInstanceState.getString("password");
+ if (savedPassword != null) {
+ password.setText(savedPassword);
+ }
+
+ int savedProtocol = savedInstanceState.getInt("protocol", -1);
+ if (savedProtocol == R.id.radio_http || savedProtocol == R.id.radio_webdav) {
+ protocol.check(savedProtocol);
+ }
+ }
+
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ this.context = context;
+
+ if (context instanceof Callback) {
+ callback = (Callback) context;
+ }
+ }
+
+ public ServeDialog setDarkTheme(boolean isDarkTheme) {
+ this.isDarkTheme = isDarkTheme;
+ return this;
+ }
+
+ private void sendCallback() {
+ int selectedProtocolId = protocol.getCheckedRadioButtonId();
+ int selectedProtocol;
+ switch (selectedProtocolId) {
+ case R.id.radio_webdav:
+ selectedProtocol = Rclone.SERVE_PROTOCOL_WEBDAV;
+ break;
+ case R.id.radio_http:
+ default:
+ selectedProtocol = Rclone.SERVE_PROTOCOL_HTTP;
+ break;
+ }
+
+ callback.onServeOptionsSelected(selectedProtocol, allowRemoteAccess.isChecked(), user.getText().toString(), password.getText().toString());
+ }
+}
diff --git a/app/src/main/java/ca/pkay/rcloneexplorer/Fragments/FileExplorerFragment.java b/app/src/main/java/ca/pkay/rcloneexplorer/Fragments/FileExplorerFragment.java
index b7c8544..343e040 100644
--- a/app/src/main/java/ca/pkay/rcloneexplorer/Fragments/FileExplorerFragment.java
+++ b/app/src/main/java/ca/pkay/rcloneexplorer/Fragments/FileExplorerFragment.java
@@ -62,6 +62,7 @@
import ca.pkay.rcloneexplorer.Dialogs.InputDialog;
import ca.pkay.rcloneexplorer.Dialogs.LinkDialog;
import ca.pkay.rcloneexplorer.Dialogs.LoadingDialog;
+import ca.pkay.rcloneexplorer.Dialogs.ServeDialog;
import ca.pkay.rcloneexplorer.Dialogs.SortDialog;
import ca.pkay.rcloneexplorer.FileComparators;
import ca.pkay.rcloneexplorer.Dialogs.FilePropertiesDialog;
@@ -90,7 +91,8 @@ public class FileExplorerFragment extends Fragment implements FileExplorerRecy
OpenAsDialog.OnClickListener,
InputDialog.OnPositive,
GoToDialog.Callbacks,
- SortDialog.OnClickListener {
+ SortDialog.OnClickListener,
+ ServeDialog.Callback {
private static final String ARG_REMOTE = "remote_param";
private static final String SHARED_PREFS_SORT_ORDER = "ca.pkay.rcexplorer.sort_order";
@@ -593,34 +595,7 @@ public boolean onOptionsItemSelected(MenuItem item) {
recyclerViewAdapter.toggleSelectAll();
return true;
case R.id.action_serve:
- String[] serveOptions = new String[] {"HTTP", "Webdav"};
- AlertDialog.Builder builder = new AlertDialog.Builder(context);
- builder.setItems(serveOptions, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- Intent intent = new Intent(getContext(), StreamingService.class);
- switch (which) {
- case 0: // HTTP
- intent.putExtra(StreamingService.SERVE_PATH_ARG, directoryObject.getCurrentPath());
- intent.putExtra(StreamingService.REMOTE_ARG, remote);
- intent.putExtra(StreamingService.SERVE_PROTOCOL, StreamingService.SERVE_HTTP);
- intent.putExtra(StreamingService.SHOW_NOTIFICATION_TEXT, true);
- break;
- case 1: // Webdav
- intent.putExtra(StreamingService.SERVE_PATH_ARG, directoryObject.getCurrentPath());
- intent.putExtra(StreamingService.REMOTE_ARG, remote);
- intent.putExtra(StreamingService.SERVE_PROTOCOL, StreamingService.SERVE_WEBDAV);
- intent.putExtra(StreamingService.SHOW_NOTIFICATION_TEXT, true);
- break;
- default:
- return;
- }
- context.startService(intent);
- }
- });
- builder.setTitle(R.string.pick_a_protocol);
- builder.show();
-
+ serve();
return true;
case R.id.action_empty_trash:
emptyTrash();
@@ -650,6 +625,36 @@ public void onClick(DialogInterface dialog, int which) {
}
}
+ private void serve() {
+ ServeDialog serveDialog = new ServeDialog();
+ serveDialog.setDarkTheme(isDarkTheme);
+ serveDialog.show(getChildFragmentManager(), "serve dialog");
+ }
+
+ // serve callback
+ @Override
+ public void onServeOptionsSelected(int protocol, boolean allowRemoteAccess, String user, String password) {
+ Intent intent = new Intent(getContext(), StreamingService.class);
+ intent.putExtra(StreamingService.SERVE_PATH_ARG, directoryObject.getCurrentPath());
+ intent.putExtra(StreamingService.REMOTE_ARG, remote);
+ intent.putExtra(StreamingService.SHOW_NOTIFICATION_TEXT, true);
+ intent.putExtra(StreamingService.ALLOW_REMOTE_ACCESS, allowRemoteAccess);
+ intent.putExtra(StreamingService.AUTHENTICATION_USERNAME, user);
+ intent.putExtra(StreamingService.AUTHENTICATION_PASSWORD, password);
+
+ switch (protocol) {
+ case Rclone.SERVE_PROTOCOL_HTTP: // HTTP
+ intent.putExtra(StreamingService.SERVE_PROTOCOL, StreamingService.SERVE_HTTP);
+ break;
+ case Rclone.SERVE_PROTOCOL_WEBDAV: // Webdav
+ intent.putExtra(StreamingService.SERVE_PROTOCOL, StreamingService.SERVE_WEBDAV);
+ break;
+ default:
+ return;
+ }
+ context.startService(intent);
+ }
+
private void emptyTrash() {
AlertDialog.Builder builder;
diff --git a/app/src/main/java/ca/pkay/rcloneexplorer/Rclone.java b/app/src/main/java/ca/pkay/rcloneexplorer/Rclone.java
index af6c92d..0ba69c9 100644
--- a/app/src/main/java/ca/pkay/rcloneexplorer/Rclone.java
+++ b/app/src/main/java/ca/pkay/rcloneexplorer/Rclone.java
@@ -33,8 +33,10 @@
public class Rclone {
- public static int SYNC_DIRECTION_LOCAL_TO_REMOTE = 1;
- public static int SYNC_DIRECTION_REMOTE_TO_LOCAL = 2;
+ public static final int SYNC_DIRECTION_LOCAL_TO_REMOTE = 1;
+ public static final int SYNC_DIRECTION_REMOTE_TO_LOCAL = 2;
+ public static final int SERVE_PROTOCOL_HTTP = 1;
+ public static final int SERVE_PROTOCOL_WEBDAV = 2;
private Context context;
private String rclone;
private String rcloneConf;
@@ -353,37 +355,49 @@ public String obscure(String pass) {
}
}
- public Process serveHttp(RemoteItem remote, String servePath, int port) {
+ public Process serve(int protocol, int port, boolean allowRemoteAccess, String user, String password, RemoteItem remote, String servePath) {
String remoteName = remote.getName();
String localRemotePath = (remote.isRemoteType(RemoteItem.LOCAL)) ? Environment.getExternalStorageDirectory().getAbsolutePath() + "/" : "";
String path = (servePath.compareTo("//" + remoteName) == 0) ? remoteName + ":" + localRemotePath : remoteName + ":" + localRemotePath + servePath;
- String[] command = createCommandWithOptions("serve", "http", "--addr", ":" + String.valueOf(port), path);
- try {
- return Runtime.getRuntime().exec(command);
- } catch (IOException e) {
- e.printStackTrace();
- return null;
+ String commandProtocol = protocol == SERVE_PROTOCOL_HTTP ? "http" : "webdav";
+ String address;
+ if (allowRemoteAccess) {
+ address = ":" + String.valueOf(port);
+ } else {
+ address = "127.0.0.1:" + String.valueOf(port);
}
- }
-
- public Process serveWebdav(RemoteItem remote, String servePath, int port) {
- String remoteName = remote.getName();
- String localRemotePath = (remote.isRemoteType(RemoteItem.LOCAL)) ? Environment.getExternalStorageDirectory().getAbsolutePath() + "/" : "";
- String path = (servePath.compareTo("//" + remoteName) == 0) ? remoteName + ":" + localRemotePath : remoteName + ":" + localRemotePath + servePath;
- String[] command = createCommandWithOptions("serve", "webdav", "--addr", ":" + String.valueOf(port), path);
-
String cachePath = context.getCacheDir().getAbsolutePath();
String[] environmentalVariables = {"TMPDIR=" + cachePath}; // this is a fix for #199
+ String[] command;
+
+ if (user == null && password != null) {
+ command = createCommandWithOptions("serve", commandProtocol, "--addr", address, path, "--pass", password);
+ } else if (user != null && password == null) {
+ command = createCommandWithOptions("serve", commandProtocol, "--addr", address, path, "--user", user);
+ } else if (user != null) {
+ command = createCommandWithOptions("serve", commandProtocol, "--addr", address, path, "--user", user, "--pass", password);
+ } else {
+ command = createCommandWithOptions("serve", commandProtocol, "--addr", address, path);
+ }
+
try {
- return Runtime.getRuntime().exec(command, environmentalVariables);
+ if (protocol == SERVE_PROTOCOL_WEBDAV) {
+ return Runtime.getRuntime().exec(command, environmentalVariables);
+ } else {
+ return Runtime.getRuntime().exec(command);
+ }
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
+ public Process serve(int protocol, int port, boolean localhostOnly, RemoteItem remote, String servePath) {
+ return serve(protocol, port, localhostOnly, null, null, remote, servePath);
+ }
+
public Process sync(RemoteItem remoteItem, String remote, String localPath, int syncDirection) {
String[] command;
String remoteName = remoteItem.getName();
diff --git a/app/src/main/java/ca/pkay/rcloneexplorer/Services/StreamingService.java b/app/src/main/java/ca/pkay/rcloneexplorer/Services/StreamingService.java
index 2a794d5..ce5733b 100644
--- a/app/src/main/java/ca/pkay/rcloneexplorer/Services/StreamingService.java
+++ b/app/src/main/java/ca/pkay/rcloneexplorer/Services/StreamingService.java
@@ -23,6 +23,9 @@ public class StreamingService extends IntentService {
public static final String REMOTE_ARG = "ca.pkay.rcexplorer.streaming_service.arg2";
public static final String SHOW_NOTIFICATION_TEXT = "ca.pkay.rcexplorer.streaming_service.arg3";
public static final String SERVE_PROTOCOL = "ca.pkay.rcexplorer.serve_protocol";
+ public static final String ALLOW_REMOTE_ACCESS = "ca.pkay.rcexplorer.allow_remote_access";
+ public static final String AUTHENTICATION_USERNAME = "ca.pkay.rcexplorer.username";
+ public static final String AUTHENTICATION_PASSWORD = "ca.pkay.rcexplorer.password";
public static final int SERVE_HTTP = 11;
public static final int SERVE_WEBDAV = 12;
private final String CHANNEL_ID = "ca.pkay.rcexplorer.streaming_channel";
@@ -54,6 +57,9 @@ protected void onHandleIntent(@Nullable Intent intent) {
final RemoteItem remote = intent.getParcelableExtra(REMOTE_ARG);
final Boolean showNotificationText = intent.getBooleanExtra(SHOW_NOTIFICATION_TEXT, false);
final int protocol = intent.getIntExtra(SERVE_PROTOCOL, SERVE_HTTP);
+ final Boolean allowRemoteAccess = intent.getBooleanExtra(ALLOW_REMOTE_ACCESS, false);
+ final String authenticationUsername = intent.getStringExtra(AUTHENTICATION_USERNAME);
+ final String authenticationPassword = intent.getStringExtra(AUTHENTICATION_PASSWORD);
Intent foregroundIntent = new Intent(this, StreamingService.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, foregroundIntent, 0);
@@ -81,11 +87,11 @@ protected void onHandleIntent(@Nullable Intent intent) {
switch (protocol) {
case SERVE_WEBDAV:
- runningProcess = rclone.serveWebdav(remote, servePath, 8080);
+ runningProcess = rclone.serve(Rclone.SERVE_PROTOCOL_WEBDAV, 8080, allowRemoteAccess, authenticationUsername, authenticationPassword, remote, servePath);
break;
case SERVE_HTTP:
default:
- runningProcess = rclone.serveHttp(remote, servePath, 8080);
+ runningProcess = rclone.serve(Rclone.SERVE_PROTOCOL_HTTP, 8080, allowRemoteAccess, authenticationUsername, authenticationPassword, remote, servePath);
break;
}
diff --git a/app/src/main/java/ca/pkay/rcloneexplorer/Services/ThumbnailsLoadingService.java b/app/src/main/java/ca/pkay/rcloneexplorer/Services/ThumbnailsLoadingService.java
index 3a2632c..030e793 100644
--- a/app/src/main/java/ca/pkay/rcloneexplorer/Services/ThumbnailsLoadingService.java
+++ b/app/src/main/java/ca/pkay/rcloneexplorer/Services/ThumbnailsLoadingService.java
@@ -30,7 +30,7 @@ protected void onHandleIntent(@Nullable Intent intent) {
}
RemoteItem remote = intent.getParcelableExtra(REMOTE_ARG);
- process = rclone.serveHttp(remote, "", 29170);
+ process = rclone.serve(Rclone.SERVE_PROTOCOL_HTTP, 29170, true, remote, "");
if (process != null) {
try {
process.waitFor();
diff --git a/app/src/main/res/layout/dialog_serve.xml b/app/src/main/res/layout/dialog_serve.xml
new file mode 100644
index 0000000..c8d5d29
--- /dev/null
+++ b/app/src/main/res/layout/dialog_serve.xml
@@ -0,0 +1,100 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 0b6f330..b2661bb 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -361,4 +361,8 @@
Hidden remotes
shared_preferences_hidden_remotes
Select remotes to hide
+ Allow remote access
+ Authentication
+ Optional
+ Serve a remote