From bde86e018ade4a8d3977fa7198f5f19ee2a32ec9 Mon Sep 17 00:00:00 2001 From: daniel oeh Date: Mon, 8 Dec 2014 11:56:52 +0100 Subject: [PATCH] Handle protocol relative URLs correctly when downloading episodes and images fixes #568 --- .../test/antennapod/util/URLCheckerTest.java | 28 +++++++++++++++++++ .../core/storage/DownloadRequester.java | 12 ++++---- .../antennapod/core/util/URLChecker.java | 25 +++++++++++++++++ 3 files changed, 60 insertions(+), 5 deletions(-) diff --git a/app/src/androidTest/java/de/test/antennapod/util/URLCheckerTest.java b/app/src/androidTest/java/de/test/antennapod/util/URLCheckerTest.java index 47b58268b..aa197b6e1 100644 --- a/app/src/androidTest/java/de/test/antennapod/util/URLCheckerTest.java +++ b/app/src/androidTest/java/de/test/antennapod/util/URLCheckerTest.java @@ -73,4 +73,32 @@ public class URLCheckerTest extends AndroidTestCase { final String out = URLChecker.prepareURL(in); assertEquals("https://example.com", out); } + + public void testProtocolRelativeUrlIsAbsolute() throws Exception { + final String in = "https://example.com"; + final String inBase = "http://examplebase.com"; + final String out = URLChecker.prepareURL(in, inBase); + assertEquals(in, out); + } + + public void testProtocolRelativeUrlIsRelativeHttps() throws Exception { + final String in = "//example.com"; + final String inBase = "https://examplebase.com"; + final String out = URLChecker.prepareURL(in, inBase); + assertEquals("https://example.com", out); + + } + + public void testProtocolRelativeUrlIsHttpsWithAPSubscribeProtocol() throws Exception { + final String in = "//example.com"; + final String inBase = "antennapod-subscribe://https://examplebase.com"; + final String out = URLChecker.prepareURL(in, inBase); + assertEquals("https://example.com", out); + } + + public void testProtocolRelativeUrlBaseUrlNull() throws Exception { + final String in = "example.com"; + final String out = URLChecker.prepareURL(in, null); + assertEquals("http://example.com", out); + } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java index 148d886ae..f5ee9e28c 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java @@ -90,7 +90,7 @@ public class DownloadRequester { return true; } - private void download(Context context, FeedFile item, File dest, + private void download(Context context, FeedFile item, FeedFile container, File dest, boolean overwriteIfExists, String username, String password, boolean deleteOnFailure, Bundle arguments) { if (!isDownloadingFile(item)) { if (!isFilenameAvailable(dest.toString()) || (deleteOnFailure && dest.exists())) { @@ -129,7 +129,8 @@ public class DownloadRequester { if (BuildConfig.DEBUG) Log.d(TAG, "Requesting download of url " + item.getDownload_url()); - item.setDownload_url(URLChecker.prepareURL(item.getDownload_url())); + String baseUrl = (container != null) ? container.getDownload_url() : null; + item.setDownload_url(URLChecker.prepareURL(item.getDownload_url(), baseUrl)); DownloadRequest request = new DownloadRequest(dest.toString(), URLChecker.prepareURL(item.getDownload_url()), item.getHumanReadableIdentifier(), @@ -171,7 +172,7 @@ public class DownloadRequester { args.putInt(REQUEST_ARG_PAGE_NR, feed.getPageNr()); args.putBoolean(REQUEST_ARG_LOAD_ALL_PAGES, loadAllPages); - download(context, feed, new File(getFeedfilePath(context), + download(context, feed, null, new File(getFeedfilePath(context), getFeedfileName(feed)), true, username, password, true, args); } } @@ -183,7 +184,8 @@ public class DownloadRequester { public synchronized void downloadImage(Context context, FeedImage image) throws DownloadRequestException { if (feedFileValid(image)) { - download(context, image, new File(getImagefilePath(context), + FeedFile container = (image.getOwner() instanceof FeedFile) ? (FeedFile) image.getOwner() : null; + download(context, image, container, new File(getImagefilePath(context), getImagefileName(image)), false, null, null, false, null); } } @@ -209,7 +211,7 @@ public class DownloadRequester { dest = new File(getMediafilePath(context, feedmedia), getMediafilename(feedmedia)); } - download(context, feedmedia, + download(context, feedmedia, feed, dest, false, username, password, false, null); } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/URLChecker.java b/core/src/main/java/de/danoeh/antennapod/core/util/URLChecker.java index 4bd18c8bc..4300556d2 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/URLChecker.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/URLChecker.java @@ -1,5 +1,6 @@ package de.danoeh.antennapod.core.util; +import android.net.Uri; import android.util.Log; import org.apache.commons.lang3.StringUtils; @@ -51,4 +52,28 @@ public final class URLChecker { return url; } } + + /** + * Checks if URL is valid and modifies it if necessary. + * This method also handles protocol relative URLs. + * + * @param url The url which is going to be prepared + * @param base The url against which the (possibly relative) url is applied. If this is null, + * the result of prepareURL(url) is returned instead. + * @return The prepared url + */ + public static String prepareURL(String url, String base) { + if (base == null) { + return prepareURL(url); + } + url = StringUtils.trim(url); + base = prepareURL(base); + Uri urlUri = Uri.parse(url); + Uri baseUri = Uri.parse(base); + if (urlUri.isRelative() && baseUri.isAbsolute()) { + return urlUri.buildUpon().scheme(baseUri.getScheme()).build().toString(); + } else { + return prepareURL(url); + } + } }