From 0d50bca3d888ab75d872c65445f79c834491e0f2 Mon Sep 17 00:00:00 2001 From: Catfriend1 Date: Sun, 24 Feb 2019 13:47:56 +0100 Subject: [PATCH] Download Support Bundle (fixes #330) (#332) * http/GetRequest: Add URI_DEBUG_SUPPORT * Add ConfigXml#getGui * Update model/Gui * Add strings en-GB * Add pref: webUIDebugging * SettingsActivity: Add mWebUIDebugging, KEY_WEBUI_DEBUGGING * Add pref button: downloadSupportBundle * Add string: download_support_bundle_title * Update string: webui_debugging_summary * WIP * WIP * Use DownloadManager instead * Revert "Use DownloadManager instead" This reverts commit f2b24f5f295b27dd4d1aa2bed7bd2a08afce2159. * Try sending auth to browser - unsafe * Revert "Try sending auth to browser - unsafe" This reverts commit 53523aad2e65147c99ee590cd0722c0e221fad8f. * Add RestApi#downloadSupportBundle (fixes #330) * Add SettingsActivity#onDownloadSupportBundleClick (fixes #330) * FileUtils: Move getExternalStorageDownloadsDirectory code into separate function * RestApi#downloadSupportBundle: Add callback for result UI * SettingsActivity: Add UI to show if bundle download succeeded (fixes #330) * Add strings for success, failure, in progress * Add comment * Imported de translation --- .../activities/SettingsActivity.java | 81 +++++++++++++++---- .../syncthingandroid/http/GetRequest.java | 1 + .../syncthingandroid/service/RestApi.java | 34 ++++++++ app/src/main/res/values-de/strings.xml | 23 ++++++ app/src/main/res/values/strings.xml | 15 ++++ app/src/main/res/xml/app_settings.xml | 13 +++ 6 files changed, 151 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/com/nutomic/syncthingandroid/activities/SettingsActivity.java b/app/src/main/java/com/nutomic/syncthingandroid/activities/SettingsActivity.java index 20f20f06..5177119a 100644 --- a/app/src/main/java/com/nutomic/syncthingandroid/activities/SettingsActivity.java +++ b/app/src/main/java/com/nutomic/syncthingandroid/activities/SettingsActivity.java @@ -51,10 +51,12 @@ import com.nutomic.syncthingandroid.service.NotificationHandler; import com.nutomic.syncthingandroid.service.RestApi; import com.nutomic.syncthingandroid.service.SyncthingService; import com.nutomic.syncthingandroid.service.SyncthingServiceBinder; +import com.nutomic.syncthingandroid.util.FileUtils; import com.nutomic.syncthingandroid.util.Languages; import com.nutomic.syncthingandroid.util.Util; import com.nutomic.syncthingandroid.views.WifiSsidPreference; +import java.io.File; import java.lang.ref.WeakReference; import java.security.InvalidParameterException; import java.util.HashSet; @@ -132,9 +134,11 @@ public class SettingsActivity extends SyncthingActivity { Preference.OnPreferenceClickListener { private static final String TAG = "SettingsFragment"; - // Settings/Syncthing + // Settings/Syncthing Options private static final String KEY_WEBUI_TCP_PORT = "webUITcpPort"; private static final String KEY_WEBUI_REMOTE_ACCESS = "webUIRemoteAccess"; + private static final String KEY_WEBUI_DEBUGGING = "webUIDebugging"; + private static final String KEY_DOWNLOAD_SUPPORT_BUNDLE = "downloadSupportBundle"; private static final String KEY_UNDO_IGNORED_DEVICES_FOLDERS = "undo_ignored_devices_folders"; // Settings/Import and Export private static final String KEY_EXPORT_CONFIG = "export_config"; @@ -186,6 +190,8 @@ public class SettingsActivity extends SyncthingActivity { private CheckBoxPreference mWebUIRemoteAccess; private CheckBoxPreference mRestartOnWakeup; private CheckBoxPreference mUrAccepted; + private CheckBoxPreference mWebUIDebugging; + private Preference mDownloadSupportBundle; /* Experimental options */ private CheckBoxPreference mUseWakelock; @@ -307,7 +313,7 @@ public class SettingsActivity extends SyncthingActivity { } setPreferenceCategoryChangeListener(categoryBehaviour, this::onBehaviourPreferenceChange); - /* Syncthing options */ + /* Syncthing Options */ mDeviceName = (EditTextPreference) findPreference("deviceName"); mListenAddresses = (EditTextPreference) findPreference("listenAddresses"); mMaxRecvKbps = (EditTextPreference) findPreference("maxRecvKbps"); @@ -322,11 +328,14 @@ public class SettingsActivity extends SyncthingActivity { mSyncthingApiKey = findPreference(KEY_SYNCTHING_API_KEY); mRestartOnWakeup = (CheckBoxPreference) findPreference("restartOnWakeup"); mUrAccepted = (CheckBoxPreference) findPreference("urAccepted"); + mWebUIDebugging = (CheckBoxPreference) findPreference(KEY_WEBUI_DEBUGGING); + mDownloadSupportBundle = findPreference(KEY_DOWNLOAD_SUPPORT_BUNDLE); Preference undoIgnoredDevicesFolders = findPreference(KEY_UNDO_IGNORED_DEVICES_FOLDERS); mCategorySyncthingOptions = findPreference("category_syncthing_options"); setPreferenceCategoryChangeListener(mCategorySyncthingOptions, this::onSyncthingPreferenceChange); mSyncthingApiKey.setOnPreferenceClickListener(this); + mDownloadSupportBundle.setOnPreferenceClickListener(this); undoIgnoredDevicesFolders.setOnPreferenceClickListener(this); /* Import and Export */ @@ -503,17 +512,20 @@ public class SettingsActivity extends SyncthingActivity { mSyncthingVersion.setSummary(mRestApi.getVersion()); mSyncthingApiKey.setSummary(mRestApi.getApiKey()); mOptions = mRestApi.getOptions(); - - Joiner joiner = Joiner.on(", "); - mDeviceName.setText(mRestApi.getLocalDevice().name); - mListenAddresses.setText(joiner.join(mOptions.listenAddresses)); - mMaxRecvKbps.setText(Integer.toString(mOptions.maxRecvKbps)); - mMaxSendKbps.setText(Integer.toString(mOptions.maxSendKbps)); - mNatEnabled.setChecked(mOptions.natEnabled); - mLocalAnnounceEnabled.setChecked(mOptions.localAnnounceEnabled); - mGlobalAnnounceEnabled.setChecked(mOptions.globalAnnounceEnabled); - mRelaysEnabled.setChecked(mOptions.relaysEnabled); - mGlobalAnnounceServers.setText(joiner.join(mOptions.globalAnnounceServers)); + if (mOptions != null) { + Joiner joiner = Joiner.on(", "); + mDeviceName.setText(mRestApi.getLocalDevice().name); + mListenAddresses.setText(joiner.join(mOptions.listenAddresses)); + mMaxRecvKbps.setText(Integer.toString(mOptions.maxRecvKbps)); + mMaxSendKbps.setText(Integer.toString(mOptions.maxSendKbps)); + mNatEnabled.setChecked(mOptions.natEnabled); + mLocalAnnounceEnabled.setChecked(mOptions.localAnnounceEnabled); + mGlobalAnnounceEnabled.setChecked(mOptions.globalAnnounceEnabled); + mRelaysEnabled.setChecked(mOptions.relaysEnabled); + mGlobalAnnounceServers.setText(joiner.join(mOptions.globalAnnounceServers)); + mRestartOnWakeup.setChecked(mOptions.restartOnWakeup); + mUrAccepted.setChecked(mRestApi.isUsageReportingAccepted()); + } // Web GUI tcp port and bind ip address. mGui = mRestApi.getGui(); @@ -521,10 +533,9 @@ public class SettingsActivity extends SyncthingActivity { mWebUITcpPort.setText(mGui.getBindPort()); mWebUITcpPort.setSummary(mGui.getBindPort()); mWebUIRemoteAccess.setChecked(!BIND_LOCALHOST.equals(mGui.getBindAddress())); + mWebUIDebugging.setChecked(mGui.debugging); + mDownloadSupportBundle.setEnabled(mGui.debugging); } - - mRestartOnWakeup.setChecked(mOptions.restartOnWakeup); - mUrAccepted.setChecked(mRestApi.isUsageReportingAccepted()); } @Override @@ -663,6 +674,17 @@ public class SettingsActivity extends SyncthingActivity { mRestApi.setUsageReporting((boolean) o); mOptions = mRestApi.getOptions(); break; + case KEY_WEBUI_DEBUGGING: + mGui.debugging = (boolean) o; + + // Immediately apply changes. + mRestApi.editSettings(mGui, mOptions); + if (mRestApi != null && + mSyncthingService.getCurrentState() != SyncthingService.State.DISABLED) { + mRestApi.saveConfigAndRestart(); + mPendingConfig = false; + } + return true; default: throw new InvalidParameterException(); } @@ -793,6 +815,9 @@ public class SettingsActivity extends SyncthingActivity { return true; default: return false; + case KEY_DOWNLOAD_SUPPORT_BUNDLE: + onDownloadSupportBundleClick(); + return true; case KEY_UNDO_IGNORED_DEVICES_FOLDERS: new AlertDialog.Builder(getActivity()) .setMessage(R.string.undo_ignored_devices_folders_question) @@ -845,6 +870,30 @@ public class SettingsActivity extends SyncthingActivity { } } + private void onDownloadSupportBundleClick() { + if (mRestApi == null) { + Toast.makeText(mContext, + getString(R.string.generic_error) + getString(R.string.syncthing_disabled), + Toast.LENGTH_SHORT).show(); + return; + } + mDownloadSupportBundle.setEnabled(false); + mDownloadSupportBundle.setSummary(R.string.download_support_bundle_in_progress); + String localDeviceName = mRestApi.getLocalDevice().getDisplayName(); + String targetFileFullFN = FileUtils.getExternalStorageDownloadsDirectory() + "/" + + "syncthing-support-bundle_" + localDeviceName + ".zip"; + File targetFile = new File(targetFileFullFN); + + mRestApi.downloadSupportBundle(targetFile, failSuccess -> { + mDownloadSupportBundle.setEnabled(true); + if (!failSuccess) { + mDownloadSupportBundle.setSummary(R.string.download_support_bundle_failed); + return; + } + mDownloadSupportBundle.setSummary(getString(R.string.download_support_bundle_succeeded, targetFileFullFN)); + }); + } + /** * Enables or disables {@link #mUseRoot} preference depending whether root is available. */ diff --git a/app/src/main/java/com/nutomic/syncthingandroid/http/GetRequest.java b/app/src/main/java/com/nutomic/syncthingandroid/http/GetRequest.java index 242ac086..9c958e97 100644 --- a/app/src/main/java/com/nutomic/syncthingandroid/http/GetRequest.java +++ b/app/src/main/java/com/nutomic/syncthingandroid/http/GetRequest.java @@ -22,6 +22,7 @@ public class GetRequest extends ApiRequest { public static final String URI_VERSION = "/rest/system/version"; public static final String URI_SYSTEM_STATUS = "/rest/system/status"; public static final String URI_CONNECTIONS = "/rest/system/connections"; + public static final String URI_DEBUG_SUPPORT = "/rest/debug/support"; public static final String URI_DB_IGNORES = "/rest/db/ignores"; public static final String URI_DB_STATUS = "/rest/db/status"; public static final String URI_DEVICEID = "/rest/svc/deviceid"; diff --git a/app/src/main/java/com/nutomic/syncthingandroid/service/RestApi.java b/app/src/main/java/com/nutomic/syncthingandroid/service/RestApi.java index a1b7f2e4..a5bdc0a2 100644 --- a/app/src/main/java/com/nutomic/syncthingandroid/service/RestApi.java +++ b/app/src/main/java/com/nutomic/syncthingandroid/service/RestApi.java @@ -42,6 +42,9 @@ import com.nutomic.syncthingandroid.model.SystemStatus; import com.nutomic.syncthingandroid.model.SystemVersion; import com.nutomic.syncthingandroid.service.Constants; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; import java.lang.reflect.Type; import java.net.URL; import java.util.ArrayList; @@ -838,6 +841,37 @@ public class RestApi { } } + public void downloadSupportBundle(File targetFile, final OnResultListener1 listener) { + new GetRequest(mContext, mUrl, GetRequest.URI_DEBUG_SUPPORT, mApiKey, null, result -> { + Boolean failSuccess = true; + LogV("downloadSupportBundle: Writing '" + targetFile.getPath() + "' ..."); + FileOutputStream fileOutputStream = null; + try { + if (!targetFile.exists()) { + targetFile.createNewFile(); + } + fileOutputStream = new FileOutputStream(targetFile); + fileOutputStream.write(result.getBytes("ISO-8859-1")); // Do not use UTF-8 here because the ZIP would be corrupted. + fileOutputStream.flush(); + } catch (IOException e) { + Log.w(TAG, "downloadSupportBundle: Failed to write '" + targetFile.getPath() + "' #1", e); + failSuccess = false; + } finally { + try { + if (fileOutputStream != null) { + fileOutputStream.close(); + } + } catch (IOException e) { + Log.e(TAG, "downloadSupportBundle: Failed to write '" + targetFile.getPath() + "' #2", e); + failSuccess = false; + } + } + if (listener != null) { + listener.onResult(failSuccess); + } + }); + } + /** * Event triggered by {@link RunConditionMonitor} routed here through {@link SyncthingService}. */ diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index f7272a56..7f3f42c1 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -501,6 +501,21 @@ Bitte melden Sie auftretende Probleme via GitHub. Erlaubt es, von einem anderen Gerät aus auf die Weboberfläche zuzugreifen. Wenn aktiviert, kannst Du dich mit dem Benutzer \'syncthing\' und dem API Key als Passwort anmelden. Standard: Deaktiviert (am sichersten) + WebUI Fehlersuchmodus + + Ermögliche Profiling und das Herunterladen eines Supportpakets. Ändern dieser Option wird Syncthing sofort neu starten. + + Supportpaket herunterladen + + + Bereite Supportpaket-Download vor ... + + + Supportpaket erfolgreich heruntergeladen: %s + + + Herunterladen des Supportpakets fehlgeschlagen. Prüfe die Logs. + Mache Ignorieren von Geräten und Ordnern rückgängig Dies macht vorherige Entscheidungen, Geräte und Ordner zu ignorieren, rückgängig. Fortfahren? @@ -562,6 +577,10 @@ Bitte melden Sie auftretende Probleme via GitHub. Konfiguration importiert Import fehlgeschlagen, Dateien werden in %1$s erwartet + Neustart erforderlich + + Das Ändern dieser Option erfordert einen sofortigen Neustart der App. Alle anderen Änderungen werden verworfen. Fortsetzen? + STTRACE Optionen @@ -590,6 +609,10 @@ Bitte melden Sie auftretende Probleme via GitHub. Über + Ausführliches Log + + Aktivieren dieser Option wird sehr detaillierte Logs zur Fehlersuche liefern. + Log öffnen diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 297256ac..1e45950a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -504,6 +504,21 @@ Please report any problems you encounter via Github. Specify to permit accessing the Web UI from another device. If enabled, you are able to logon with user \'syncthing\' and API key as password. Default: disabled (most secure) + WebUI Debugging + + Enable to start profiling and to be able to download a support bundle. Changing this option will restart Syncthing immediately. + + Download Support Bundle + + + Preparing Support Bundle download ... + + + Support Bundle successfully downloaded to %s. + + + Failed downloading Support Bundle. Check the logs. + Undo ignoring devices and folders This will undo previous decisions to ignore devices and folders. Continue? diff --git a/app/src/main/res/xml/app_settings.xml b/app/src/main/res/xml/app_settings.xml index 77255470..8f53007a 100644 --- a/app/src/main/res/xml/app_settings.xml +++ b/app/src/main/res/xml/app_settings.xml @@ -193,9 +193,22 @@ android:title="@string/usage_reporting" android:persistent="false" /> + + + +