From 519d6ce9d699e895bf6adb00f3ec9d0238cc570b Mon Sep 17 00:00:00 2001 From: MStrecke Date: Thu, 25 Feb 2021 23:08:00 +0100 Subject: [PATCH] use full URL for custom gpodder server (#4932) --- .../discovery/GpodnetPodcastSearcher.java | 2 +- .../fragment/gpodnet/PodcastListFragment.java | 2 +- .../fragment/gpodnet/TagListFragment.java | 2 +- .../GpodderAuthenticationFragment.java | 17 ++-- .../res/layout/gpodnetauth_credentials.xml | 11 ++- .../core/preferences/GpodnetPreferences.java | 24 ++---- .../antennapod/core/sync/SyncService.java | 2 +- .../core/sync/gpoddernet/GpodnetService.java | 78 +++++++++++++------ core/src/main/res/values/strings.xml | 1 + 9 files changed, 89 insertions(+), 50 deletions(-) diff --git a/app/src/main/java/de/danoeh/antennapod/discovery/GpodnetPodcastSearcher.java b/app/src/main/java/de/danoeh/antennapod/discovery/GpodnetPodcastSearcher.java index 53237579f..6de2186e0 100644 --- a/app/src/main/java/de/danoeh/antennapod/discovery/GpodnetPodcastSearcher.java +++ b/app/src/main/java/de/danoeh/antennapod/discovery/GpodnetPodcastSearcher.java @@ -18,7 +18,7 @@ public class GpodnetPodcastSearcher implements PodcastSearcher { return Single.create((SingleOnSubscribe>) subscriber -> { try { GpodnetService service = new GpodnetService(AntennapodHttpClient.getHttpClient(), - GpodnetPreferences.getHostname()); + GpodnetPreferences.getHosturl()); List gpodnetPodcasts = service.searchPodcasts(query, 0); List results = new ArrayList<>(); for (GpodnetPodcast podcast : gpodnetPodcasts) { diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java index 1f5434688..be9699348 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java @@ -71,7 +71,7 @@ public abstract class PodcastListFragment extends Fragment { protected List doInBackground(Void... params) { try { GpodnetService service = new GpodnetService(AntennapodHttpClient.getHttpClient(), - GpodnetPreferences.getHostname()); + GpodnetPreferences.getHosturl()); return loadPodcastData(service); } catch (GpodnetServiceException e) { exception = e; diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/TagListFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/TagListFragment.java index 2c41ee070..a26ec9e84 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/TagListFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/TagListFragment.java @@ -54,7 +54,7 @@ public class TagListFragment extends ListFragment { @Override protected List doInBackground(Void... params) { GpodnetService service = new GpodnetService(AntennapodHttpClient.getHttpClient(), - GpodnetPreferences.getHostname()); + GpodnetPreferences.getHosturl()); try { return service.getTopTags(COUNT); } catch (GpodnetServiceException e) { diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/GpodderAuthenticationFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/GpodderAuthenticationFragment.java index 187e8480b..6eb19aff2 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/GpodderAuthenticationFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/GpodderAuthenticationFragment.java @@ -82,8 +82,9 @@ public class GpodderAuthenticationFragment extends DialogFragment { final Button selectHost = view.findViewById(R.id.chooseHostButton); final RadioGroup serverRadioGroup = view.findViewById(R.id.serverRadioGroup); final EditText serverUrlText = view.findViewById(R.id.serverUrlText); - if (!GpodnetService.DEFAULT_BASE_HOST.equals(GpodnetPreferences.getHostname())) { - serverUrlText.setText(GpodnetPreferences.getHostname()); + + if (!GpodnetService.DEFAULT_BASE_HOST.equals(GpodnetPreferences.getHosturl())) { + serverUrlText.setText(GpodnetPreferences.getHosturl()); } final TextInputLayout serverUrlTextInput = view.findViewById(R.id.serverUrlTextInput); serverRadioGroup.setOnCheckedChangeListener((group, checkedId) -> { @@ -91,12 +92,12 @@ public class GpodderAuthenticationFragment extends DialogFragment { }); selectHost.setOnClickListener(v -> { if (serverRadioGroup.getCheckedRadioButtonId() == R.id.customServerRadio) { - GpodnetPreferences.setHostname(serverUrlText.getText().toString()); + GpodnetPreferences.setHosturl(serverUrlText.getText().toString()); } else { - GpodnetPreferences.setHostname(GpodnetService.DEFAULT_BASE_HOST); + GpodnetPreferences.setHosturl(GpodnetService.DEFAULT_BASE_HOST); } - service = new GpodnetService(AntennapodHttpClient.getHttpClient(), GpodnetPreferences.getHostname()); - getDialog().setTitle(GpodnetPreferences.getHostname()); + service = new GpodnetService(AntennapodHttpClient.getHttpClient(), GpodnetPreferences.getHosturl()); + getDialog().setTitle(GpodnetPreferences.getHosturl()); advance(); }); } @@ -108,10 +109,14 @@ public class GpodderAuthenticationFragment extends DialogFragment { final TextView txtvError = view.findViewById(R.id.credentialsError); final ProgressBar progressBar = view.findViewById(R.id.progBarLogin); final TextView createAccount = view.findViewById(R.id.createAccountButton); + final TextView createAccountWarning = view.findViewById(R.id.createAccountWarning); createAccount.setPaintFlags(createAccount.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG); createAccount.setOnClickListener(v -> IntentUtils.openInBrowser(getContext(), "https://gpodder.net/register/")); + if (GpodnetPreferences.getHosturl().startsWith("http://")) { + createAccountWarning.setVisibility(View.VISIBLE); + } password.setOnEditorActionListener((v, actionID, event) -> actionID == EditorInfo.IME_ACTION_GO && login.performClick()); diff --git a/app/src/main/res/layout/gpodnetauth_credentials.xml b/app/src/main/res/layout/gpodnetauth_credentials.xml index 291b98da3..9fcf67cff 100644 --- a/app/src/main/res/layout/gpodnetauth_credentials.xml +++ b/app/src/main/res/layout/gpodnetauth_credentials.xml @@ -29,6 +29,15 @@ android:text="@string/create_account"/> + + - \ No newline at end of file + diff --git a/core/src/main/java/de/danoeh/antennapod/core/preferences/GpodnetPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/GpodnetPreferences.java index 0a72b5d5c..209558b19 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/preferences/GpodnetPreferences.java +++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/GpodnetPreferences.java @@ -26,7 +26,7 @@ public class GpodnetPreferences { private static String username; private static String password; private static String deviceID; - private static String hostname; + private static String hosturl; private static boolean preferencesLoaded = false; @@ -40,7 +40,7 @@ public class GpodnetPreferences { username = prefs.getString(PREF_GPODNET_USERNAME, null); password = prefs.getString(PREF_GPODNET_PASSWORD, null); deviceID = prefs.getString(PREF_GPODNET_DEVICEID, null); - hostname = checkGpodnetHostname(prefs.getString(PREF_GPODNET_HOSTNAME, GpodnetService.DEFAULT_BASE_HOST)); + hosturl = prefs.getString(PREF_GPODNET_HOSTNAME, GpodnetService.DEFAULT_BASE_HOST); preferencesLoaded = true; } @@ -82,17 +82,16 @@ public class GpodnetPreferences { writePreference(PREF_GPODNET_DEVICEID, deviceID); } - public static String getHostname() { + public static String getHosturl() { ensurePreferencesLoaded(); - return hostname; + return hosturl; } - public static void setHostname(String value) { - value = checkGpodnetHostname(value); - if (!value.equals(hostname)) { + public static void setHosturl(String value) { + if (!value.equals(hosturl)) { logout(); writePreference(PREF_GPODNET_HOSTNAME, value); - hostname = value; + hosturl = value; } } @@ -113,13 +112,4 @@ public class GpodnetPreferences { UserPreferences.setGpodnetNotificationsEnabled(); } - private static String checkGpodnetHostname(String value) { - int startIndex = 0; - if (value.startsWith("http://")) { - startIndex = "http://".length(); - } else if (value.startsWith("https://")) { - startIndex = "https://".length(); - } - return value.substring(startIndex); - } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/SyncService.java b/core/src/main/java/de/danoeh/antennapod/core/sync/SyncService.java index 90dcea1e3..670a65e44 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/sync/SyncService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/sync/SyncService.java @@ -80,7 +80,7 @@ public class SyncService extends Worker { if (!GpodnetPreferences.loggedIn()) { return Result.success(); } - syncServiceImpl = new GpodnetService(AntennapodHttpClient.getHttpClient(), GpodnetPreferences.getHostname()); + syncServiceImpl = new GpodnetService(AntennapodHttpClient.getHttpClient(), GpodnetPreferences.getHosturl()); SharedPreferences.Editor prefs = getApplicationContext().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE) .edit(); prefs.putLong(PREF_LAST_SYNC_ATTEMPT_TIMESTAMP, System.currentTimeMillis()).apply(); diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetService.java b/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetService.java index 75ac42b31..cecfc0d2c 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetService.java @@ -42,24 +42,58 @@ import java.util.LinkedList; import java.util.List; import java.util.Locale; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + /** * Communicates with the gpodder.net service. */ public class GpodnetService implements ISyncService { public static final String TAG = "GpodnetService"; public static final String DEFAULT_BASE_HOST = "gpodder.net"; - private static final String BASE_SCHEME = "https"; - private static final int PORT = 443; private static final int UPLOAD_BULK_SIZE = 30; private static final MediaType TEXT = MediaType.parse("plain/text; charset=utf-8"); private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); - private final String baseHost; + private String baseScheme; + private String baseHost; + private int basePort; + private final OkHttpClient httpClient; private String username = null; - public GpodnetService(OkHttpClient httpClient, String baseHost) { + // split into schema, host and port - missing parts are null + private static Pattern urlsplit_regex = Pattern.compile("(?:(https?)://)?([^:]+)(?::(\\d+))?"); + + public GpodnetService(OkHttpClient httpClient, String baseHosturl) { this.httpClient = httpClient; - this.baseHost = baseHost; + + Matcher m = urlsplit_regex.matcher(baseHosturl); + if (m.matches()) { + this.baseScheme = m.group(1); + this.baseHost = m.group(2); + if (m.group(3) == null) { + this.basePort = -1; + } else { + this.basePort = Integer.parseInt(m.group(3)); // regex -> can only be digits + } + } else { + // URL does not match regex: use it anyway -> this will cause an exception on connect + this.baseScheme = "https"; + this.baseHost = baseHosturl; + this.basePort = 443; + } + + if (this.baseScheme == null) { // assume https + this.baseScheme = "https"; + } + + if (this.baseScheme.equals("https") && this.basePort == -1) { + this.basePort = 443; + } + + if (this.baseScheme.equals("http") && this.basePort == -1) { + this.basePort = 80; + } } private void requireLoggedIn() { @@ -74,7 +108,7 @@ public class GpodnetService implements ISyncService { public List getTopTags(int count) throws GpodnetServiceException { URL url; try { - url = new URI(BASE_SCHEME, null, baseHost, PORT, + url = new URI(baseScheme, null, baseHost, basePort, String.format(Locale.US, "/api/2/tags/%d.json", count), null, null).toURL(); } catch (MalformedURLException | URISyntaxException e) { e.printStackTrace(); @@ -108,7 +142,7 @@ public class GpodnetService implements ISyncService { public List getPodcastsForTag(@NonNull GpodnetTag tag, int count) throws GpodnetServiceException { try { - URL url = new URI(BASE_SCHEME, null, baseHost, PORT, + URL url = new URI(baseScheme, null, baseHost, basePort, String.format(Locale.US, "/api/2/tag/%s/%d.json", tag.getTag(), count), null, null).toURL(); Request.Builder request = new Request.Builder().url(url); String response = executeRequest(request); @@ -134,7 +168,7 @@ public class GpodnetService implements ISyncService { } try { - URL url = new URI(BASE_SCHEME, null, baseHost, PORT, + URL url = new URI(baseScheme, null, baseHost, basePort, String.format(Locale.US, "/toplist/%d.json", count), null, null).toURL(); Request.Builder request = new Request.Builder().url(url); String response = executeRequest(request); @@ -166,7 +200,7 @@ public class GpodnetService implements ISyncService { } try { - URL url = new URI(BASE_SCHEME, null, baseHost, PORT, + URL url = new URI(baseScheme, null, baseHost, basePort, String.format(Locale.US, "/suggestions/%d.json", count), null, null).toURL(); Request.Builder request = new Request.Builder().url(url); String response = executeRequest(request); @@ -192,7 +226,7 @@ public class GpodnetService implements ISyncService { .format(Locale.US, "q=%s&scale_logo=%d", query, scaledLogoSize) : String .format("q=%s", query); try { - URL url = new URI(BASE_SCHEME, null, baseHost, PORT, "/search.json", + URL url = new URI(baseScheme, null, baseHost, basePort, "/search.json", parameters, null).toURL(); Request.Builder request = new Request.Builder().url(url); String response = executeRequest(request); @@ -219,7 +253,7 @@ public class GpodnetService implements ISyncService { public List getDevices() throws GpodnetServiceException { requireLoggedIn(); try { - URL url = new URI(BASE_SCHEME, null, baseHost, PORT, + URL url = new URI(baseScheme, null, baseHost, basePort, String.format("/api/2/devices/%s.json", username), null, null).toURL(); Request.Builder request = new Request.Builder().url(url); String response = executeRequest(request); @@ -241,7 +275,7 @@ public class GpodnetService implements ISyncService { public List> getSynchronizedDevices() throws GpodnetServiceException { requireLoggedIn(); try { - URL url = new URI(BASE_SCHEME, null, baseHost, PORT, + URL url = new URI(baseScheme, null, baseHost, basePort, String.format("/api/2/sync-devices/%s.json", username), null, null).toURL(); Request.Builder request = new Request.Builder().url(url); String response = executeRequest(request); @@ -282,7 +316,7 @@ public class GpodnetService implements ISyncService { throws GpodnetServiceException { requireLoggedIn(); try { - URL url = new URI(BASE_SCHEME, null, baseHost, PORT, + URL url = new URI(baseScheme, null, baseHost, basePort, String.format("/api/2/devices/%s/%s.json", username, deviceId), null, null).toURL(); String content; if (caption != null || type != null) { @@ -316,7 +350,7 @@ public class GpodnetService implements ISyncService { public void linkDevices(@NonNull List deviceIds) throws GpodnetServiceException { requireLoggedIn(); try { - final URL url = new URI(BASE_SCHEME, null, baseHost, PORT, + final URL url = new URI(baseScheme, null, baseHost, basePort, String.format("/api/2/sync-devices/%s.json", username), null, null).toURL(); JSONObject jsonContent = new JSONObject(); JSONArray group = new JSONArray(); @@ -351,7 +385,7 @@ public class GpodnetService implements ISyncService { public String getSubscriptionsOfDevice(@NonNull String deviceId) throws GpodnetServiceException { requireLoggedIn(); try { - URL url = new URI(BASE_SCHEME, null, baseHost, PORT, + URL url = new URI(baseScheme, null, baseHost, basePort, String.format("/subscriptions/%s/%s.opml", username, deviceId), null, null).toURL(); Request.Builder request = new Request.Builder().url(url); return executeRequest(request); @@ -373,7 +407,7 @@ public class GpodnetService implements ISyncService { public String getSubscriptionsOfUser() throws GpodnetServiceException { requireLoggedIn(); try { - URL url = new URI(BASE_SCHEME, null, baseHost, PORT, + URL url = new URI(baseScheme, null, baseHost, basePort, String.format("/subscriptions/%s.opml", username), null, null).toURL(); Request.Builder request = new Request.Builder().url(url); return executeRequest(request); @@ -398,7 +432,7 @@ public class GpodnetService implements ISyncService { throws GpodnetServiceException { requireLoggedIn(); try { - URL url = new URI(BASE_SCHEME, null, baseHost, PORT, + URL url = new URI(baseScheme, null, baseHost, basePort, String.format("/subscriptions/%s/%s.txt", username, deviceId), null, null).toURL(); StringBuilder builder = new StringBuilder(); for (String s : subscriptions) { @@ -432,7 +466,7 @@ public class GpodnetService implements ISyncService { @NonNull Collection removed) throws GpodnetServiceException { requireLoggedIn(); try { - URL url = new URI(BASE_SCHEME, null, baseHost, PORT, + URL url = new URI(baseScheme, null, baseHost, basePort, String.format("/api/2/subscriptions/%s/%s.json", username, deviceId), null, null).toURL(); final JSONObject requestObject = new JSONObject(); @@ -468,7 +502,7 @@ public class GpodnetService implements ISyncService { String params = String.format(Locale.US, "since=%d", timestamp); String path = String.format("/api/2/subscriptions/%s/%s.json", username, deviceId); try { - URL url = new URI(BASE_SCHEME, null, baseHost, PORT, path, params, null).toURL(); + URL url = new URI(baseScheme, null, baseHost, basePort, path, params, null).toURL(); Request.Builder request = new Request.Builder().url(url); String response = executeRequest(request); @@ -510,7 +544,7 @@ public class GpodnetService implements ISyncService { throws SyncServiceException { try { Log.d(TAG, "Uploading partial actions " + from + " to " + to + " of " + episodeActions.size()); - URL url = new URI(BASE_SCHEME, null, baseHost, PORT, + URL url = new URI(baseScheme, null, baseHost, basePort, String.format("/api/2/episodes/%s.json", username), null, null).toURL(); final JSONArray list = new JSONArray(); @@ -549,7 +583,7 @@ public class GpodnetService implements ISyncService { String params = String.format(Locale.US, "since=%d", timestamp); String path = String.format("/api/2/episodes/%s.json", username); try { - URL url = new URI(BASE_SCHEME, null, baseHost, PORT, path, params, null).toURL(); + URL url = new URI(baseScheme, null, baseHost, basePort, path, params, null).toURL(); Request.Builder request = new Request.Builder().url(url); String response = executeRequest(request); @@ -575,7 +609,7 @@ public class GpodnetService implements ISyncService { public void authenticate(@NonNull String username, @NonNull String password) throws GpodnetServiceException { URL url; try { - url = new URI(BASE_SCHEME, null, baseHost, PORT, + url = new URI(baseScheme, null, baseHost, basePort, String.format("/api/2/auth/%s/login.json", username), null, null).toURL(); } catch (MalformedURLException | URISyntaxException e) { e.printStackTrace(); diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index eb4756296..e9c1d8fcd 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -654,6 +654,7 @@ Search gpodder.net Login Login + Password and data are not encrypted! Create account Username Password