Added authentication support to DownloadRequester and HttpDownloader

This commit is contained in:
daniel oeh 2014-03-17 13:02:37 +01:00
parent 6cb3a30307
commit 3b5e83c74f
5 changed files with 96 additions and 30 deletions

View File

@ -100,6 +100,7 @@
<string name="download_error_unsupported_type">Unsupported Feed type</string> <string name="download_error_unsupported_type">Unsupported Feed type</string>
<string name="download_error_connection_error">Connection error</string> <string name="download_error_connection_error">Connection error</string>
<string name="download_error_unknown_host">Unknown host</string> <string name="download_error_unknown_host">Unknown host</string>
<string name="download_error_unauthorized">Authentication error</string>
<string name="cancel_all_downloads_label">Cancel all downloads</string> <string name="cancel_all_downloads_label">Cancel all downloads</string>
<string name="download_cancelled_msg">Download cancelled</string> <string name="download_cancelled_msg">Download cancelled</string>
<string name="download_report_title">Downloads completed</string> <string name="download_report_title">Downloads completed</string>

View File

@ -8,6 +8,8 @@ public class DownloadRequest implements Parcelable {
private final String destination; private final String destination;
private final String source; private final String source;
private final String title; private final String title;
private final String username;
private final String password;
private final long feedfileId; private final long feedfileId;
private final int feedfileType; private final int feedfileType;
@ -17,7 +19,7 @@ public class DownloadRequest implements Parcelable {
protected int statusMsg; protected int statusMsg;
public DownloadRequest(String destination, String source, String title, public DownloadRequest(String destination, String source, String title,
long feedfileId, int feedfileType) { long feedfileId, int feedfileType, String username, String password) {
if (destination == null) { if (destination == null) {
throw new IllegalArgumentException("Destination must not be null"); throw new IllegalArgumentException("Destination must not be null");
} }
@ -33,14 +35,28 @@ public class DownloadRequest implements Parcelable {
this.title = title; this.title = title;
this.feedfileId = feedfileId; this.feedfileId = feedfileId;
this.feedfileType = feedfileType; this.feedfileType = feedfileType;
this.username = username;
this.password = password;
} }
public DownloadRequest(String destination, String source, String title,
long feedfileId, int feedfileType) {
this(destination, source, title, feedfileId, feedfileType, null, null);
}
private DownloadRequest(Parcel in) { private DownloadRequest(Parcel in) {
destination = in.readString(); destination = in.readString();
source = in.readString(); source = in.readString();
title = in.readString(); title = in.readString();
feedfileId = in.readLong(); feedfileId = in.readLong();
feedfileType = in.readInt(); feedfileType = in.readInt();
if (in.dataAvail() > 0) {
username = in.readString();
password = in.readString();
} else {
username = null;
password = null;
}
} }
@Override @Override
@ -174,4 +190,12 @@ public class DownloadRequest implements Parcelable {
public void setStatusMsg(int statusMsg) { public void setStatusMsg(int statusMsg) {
this.statusMsg = statusMsg; this.statusMsg = statusMsg;
} }
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
} }

View File

@ -8,6 +8,7 @@ import de.danoeh.antennapod.R;
import de.danoeh.antennapod.util.DownloadError; import de.danoeh.antennapod.util.DownloadError;
import de.danoeh.antennapod.util.StorageUtils; import de.danoeh.antennapod.util.StorageUtils;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Header; import org.apache.http.Header;
import org.apache.http.HttpEntity; import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse; import org.apache.http.HttpResponse;
@ -54,6 +55,9 @@ public class HttpDownloader extends Downloader {
new UsernamePasswordCredentials(parts[0], parts[1]), new UsernamePasswordCredentials(parts[0], parts[1]),
"UTF-8", false)); "UTF-8", false));
} }
} else if (StringUtils.isEmpty(request.getUsername()) && request.getPassword() != null) {
httpGet.addHeader(BasicScheme.authenticate(new UsernamePasswordCredentials(request.getUsername(),
request.getPassword()), "UTF-8", false));
} }
HttpResponse response = httpClient.execute(httpGet); HttpResponse response = httpClient.execute(httpGet);
HttpEntity httpEntity = response.getEntity(); HttpEntity httpEntity = response.getEntity();
@ -67,8 +71,16 @@ public class HttpDownloader extends Downloader {
Log.d(TAG, "Response code is " + responseCode); Log.d(TAG, "Response code is " + responseCode);
if (responseCode != HttpURLConnection.HTTP_OK || httpEntity == null) { if (responseCode != HttpURLConnection.HTTP_OK || httpEntity == null) {
onFail(DownloadError.ERROR_HTTP_DATA_ERROR, final DownloadError error;
String.valueOf(responseCode)); final String details;
if (responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) {
error = DownloadError.ERROR_UNAUTHORIZED;
details = String.valueOf(responseCode);
} else {
error = DownloadError.ERROR_HTTP_DATA_ERROR;
details = String.valueOf(responseCode);
}
onFail(error, details);
return; return;
} }
@ -132,7 +144,8 @@ public class HttpDownloader extends Downloader {
"Download completed but size: " + "Download completed but size: " +
request.getSoFar() + request.getSoFar() +
" does not equal expected size " + " does not equal expected size " +
request.getSize()); request.getSize()
);
return; return;
} }
onSuccess(); onSuccess();

View File

@ -1,28 +1,28 @@
package de.danoeh.antennapod.storage; package de.danoeh.antennapod.storage;
import java.io.File;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.util.Log; import android.util.Log;
import android.webkit.URLUtil; import android.webkit.URLUtil;
import de.danoeh.antennapod.AppConfig; import de.danoeh.antennapod.AppConfig;
import de.danoeh.antennapod.feed.EventDistributor; import de.danoeh.antennapod.feed.*;
import de.danoeh.antennapod.feed.Feed;
import de.danoeh.antennapod.feed.FeedFile;
import de.danoeh.antennapod.feed.FeedImage;
import de.danoeh.antennapod.feed.FeedMedia;
import de.danoeh.antennapod.preferences.UserPreferences; import de.danoeh.antennapod.preferences.UserPreferences;
import de.danoeh.antennapod.service.download.DownloadRequest; import de.danoeh.antennapod.service.download.DownloadRequest;
import de.danoeh.antennapod.service.download.DownloadService; import de.danoeh.antennapod.service.download.DownloadService;
import de.danoeh.antennapod.util.FileNameGenerator; import de.danoeh.antennapod.util.FileNameGenerator;
import de.danoeh.antennapod.util.URLChecker; import de.danoeh.antennapod.util.URLChecker;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import java.io.File;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Sends download requests to the DownloadService. This class should always be used for starting downloads,
* otherwise they won't work correctly.
*/
public class DownloadRequester { public class DownloadRequester {
private static final String TAG = "DownloadRequester"; private static final String TAG = "DownloadRequester";
@ -45,8 +45,34 @@ public class DownloadRequester {
return downloader; return downloader;
} }
/**
* Starts a new download with the given DownloadRequest. This method should only
* be used from outside classes if the DownloadRequest was created by the DownloadService to
* ensure that the data is valid. Use downloadFeed(), downloadImage() or downloadMedia() instead.
*
* @param context Context object for starting the DownloadService
* @param request The DownloadRequest. If another DownloadRequest with the same source URL is already stored, this method
* call will return false.
* @return True if the download request was accepted, false otherwise.
*/
public boolean download(Context context, DownloadRequest request) {
if (context == null) throw new IllegalArgumentException("context = null");
if (request == null) throw new IllegalArgumentException("request = null");
if (downloads.containsKey(request.getSource())) {
if (AppConfig.DEBUG) Log.i(TAG, "DownloadRequest is already stored.");
return false;
}
downloads.put(request.getSource(), request);
Intent launchIntent = new Intent(context, DownloadService.class);
launchIntent.putExtra(DownloadService.EXTRA_REQUEST, request);
context.startService(launchIntent);
EventDistributor.getInstance().sendDownloadQueuedBroadcast();
return true;
}
private void download(Context context, FeedFile item, File dest, private void download(Context context, FeedFile item, File dest,
boolean overwriteIfExists) { boolean overwriteIfExists, String username, String password) {
if (!isDownloadingFile(item)) { if (!isDownloadingFile(item)) {
if (!isFilenameAvailable(dest.toString()) || dest.exists()) { if (!isFilenameAvailable(dest.toString()) || dest.exists()) {
if (AppConfig.DEBUG) if (AppConfig.DEBUG)
@ -88,14 +114,9 @@ public class DownloadRequester {
DownloadRequest request = new DownloadRequest(dest.toString(), DownloadRequest request = new DownloadRequest(dest.toString(),
item.getDownload_url(), item.getHumanReadableIdentifier(), item.getDownload_url(), item.getHumanReadableIdentifier(),
item.getId(), item.getTypeAsInt()); item.getId(), item.getTypeAsInt(), username, password);
downloads.put(request.getSource(), request); download(context, request);
Intent launchIntent = new Intent(context, DownloadService.class);
launchIntent.putExtra(DownloadService.EXTRA_REQUEST, request);
context.startService(launchIntent);
EventDistributor.getInstance().sendDownloadQueuedBroadcast();
} else { } else {
Log.e(TAG, "URL " + item.getDownload_url() Log.e(TAG, "URL " + item.getDownload_url()
+ " is already being downloaded"); + " is already being downloaded");
@ -124,8 +145,11 @@ public class DownloadRequester {
public void downloadFeed(Context context, Feed feed) public void downloadFeed(Context context, Feed feed)
throws DownloadRequestException { throws DownloadRequestException {
if (feedFileValid(feed)) { if (feedFileValid(feed)) {
String username = (feed.getPreferences() != null) ? feed.getPreferences().getUsername() : null;
String password = (feed.getPreferences() != null) ? feed.getPreferences().getPassword() : null;
download(context, feed, new File(getFeedfilePath(context), download(context, feed, new File(getFeedfilePath(context),
getFeedfileName(feed)), true); getFeedfileName(feed)), true, username, password);
} }
} }
@ -133,7 +157,7 @@ public class DownloadRequester {
throws DownloadRequestException { throws DownloadRequestException {
if (feedFileValid(image)) { if (feedFileValid(image)) {
download(context, image, new File(getImagefilePath(context), download(context, image, new File(getImagefilePath(context),
getImagefileName(image)), true); getImagefileName(image)), true, null, null);
} }
} }
@ -142,7 +166,8 @@ public class DownloadRequester {
if (feedFileValid(feedmedia)) { if (feedFileValid(feedmedia)) {
download(context, feedmedia, download(context, feedmedia,
new File(getMediafilePath(context, feedmedia), new File(getMediafilePath(context, feedmedia),
getMediafilename(feedmedia)), false); getMediafilename(feedmedia)), false, null, null
);
} }
} }
@ -278,7 +303,8 @@ public class DownloadRequester {
context, context,
MEDIA_DOWNLOADPATH MEDIA_DOWNLOADPATH
+ FileNameGenerator.generateFileName(media.getItem() + FileNameGenerator.generateFileName(media.getItem()
.getFeed().getTitle()) + "/"); .getFeed().getTitle()) + "/"
);
return externalStorage.toString(); return externalStorage.toString();
} }
@ -305,7 +331,8 @@ public class DownloadRequester {
} }
String URLBaseFilename = URLUtil.guessFileName(media.getDownload_url(), String URLBaseFilename = URLUtil.guessFileName(media.getDownload_url(),
null, media.getMime_type());; null, media.getMime_type());
;
if (titleBaseFilename != "") { if (titleBaseFilename != "") {
// Append extension // Append extension

View File

@ -18,7 +18,8 @@ public enum DownloadError {
ERROR_NOT_ENOUGH_SPACE(10, R.string.download_error_insufficient_space), ERROR_NOT_ENOUGH_SPACE(10, R.string.download_error_insufficient_space),
ERROR_UNKNOWN_HOST(11, R.string.download_error_unknown_host), ERROR_UNKNOWN_HOST(11, R.string.download_error_unknown_host),
ERROR_REQUEST_ERROR(12, R.string.download_error_request_error), ERROR_REQUEST_ERROR(12, R.string.download_error_request_error),
ERROR_DB_ACCESS_ERROR(13, R.string.download_error_db_access); ERROR_DB_ACCESS_ERROR(13, R.string.download_error_db_access),
ERROR_UNAUTHORIZED(14, R.string.download_error_unauthorized);
private final int code; private final int code;
private final int resId; private final int resId;