aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java/de/pixart/messenger/http/HttpUploadConnection.java
diff options
context:
space:
mode:
authorChristian Schneppe <christian@pix-art.de>2018-05-26 22:56:17 +0200
committerChristian Schneppe <christian@pix-art.de>2018-05-26 22:56:17 +0200
commita554be18a60380d624fc9c65416368775cba9bae (patch)
treebe455ef73e0c047a47bd71651382f2d22dd115ab /src/main/java/de/pixart/messenger/http/HttpUploadConnection.java
parent369e48c2203a694088156574dd7c7044f68e907b (diff)
add support for S3 file transfers
Diffstat (limited to 'src/main/java/de/pixart/messenger/http/HttpUploadConnection.java')
-rw-r--r--src/main/java/de/pixart/messenger/http/HttpUploadConnection.java126
1 files changed, 60 insertions, 66 deletions
diff --git a/src/main/java/de/pixart/messenger/http/HttpUploadConnection.java b/src/main/java/de/pixart/messenger/http/HttpUploadConnection.java
index e598db080..9acdfa11a 100644
--- a/src/main/java/de/pixart/messenger/http/HttpUploadConnection.java
+++ b/src/main/java/de/pixart/messenger/http/HttpUploadConnection.java
@@ -9,11 +9,11 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
-import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
+import java.util.Scanner;
import javax.net.ssl.HttpsURLConnection;
@@ -22,47 +22,43 @@ import de.pixart.messenger.entities.Account;
import de.pixart.messenger.entities.DownloadableFile;
import de.pixart.messenger.entities.Message;
import de.pixart.messenger.entities.Transferable;
-import de.pixart.messenger.parser.IqParser;
import de.pixart.messenger.persistance.FileBackend;
import de.pixart.messenger.services.AbstractConnectionManager;
import de.pixart.messenger.services.XmppConnectionService;
+import de.pixart.messenger.utils.Checksum;
import de.pixart.messenger.utils.CryptoHelper;
-import de.pixart.messenger.utils.Namespace;
import de.pixart.messenger.utils.WakeLockHelper;
-import de.pixart.messenger.xml.Element;
-import de.pixart.messenger.xmpp.stanzas.IqPacket;
-import rocks.xmpp.addr.Jid;
public class HttpUploadConnection implements Transferable {
- private static final List<String> WHITE_LISTED_HEADERS = Arrays.asList(
+ public static final List<String> WHITE_LISTED_HEADERS = Arrays.asList(
"Authorization",
"Cookie",
"Expires"
);
- private HttpConnectionManager mHttpConnectionManager;
- private XmppConnectionService mXmppConnectionService;
-
+ private final HttpConnectionManager mHttpConnectionManager;
+ private final XmppConnectionService mXmppConnectionService;
+ private final SlotRequester mSlotRequester;
+ private final Method method;
+ private final boolean mUseTor;
private boolean canceled = false;
private boolean delayed = false;
private DownloadableFile file;
private Message message;
private String mime;
- private URL mGetUrl;
- private URL mPutUrl;
- private HashMap<String,String> mPutHeaders;
- private boolean mUseTor = false;
-
+ private SlotRequester.Slot slot;
private byte[] key = null;
private long transmitted = 0;
private InputStream mFileInputStream;
- public HttpUploadConnection(HttpConnectionManager httpConnectionManager) {
+ public HttpUploadConnection(Method method, HttpConnectionManager httpConnectionManager) {
+ this.method = method;
this.mHttpConnectionManager = httpConnectionManager;
this.mXmppConnectionService = httpConnectionManager.getXmppConnectionService();
+ this.mSlotRequester = new SlotRequester(this.mXmppConnectionService);
this.mUseTor = mXmppConnectionService.useTorToConnect();
}
@@ -118,6 +114,21 @@ public class HttpUploadConnection implements Transferable {
mXmppConnectionService.getRNG().nextBytes(this.key);
this.file.setKeyAndIv(this.key);
}
+
+ final String md5;
+
+ if (method == Method.P1_S3) {
+ try {
+ md5 = Checksum.md5(AbstractConnectionManager.createInputStream(file, true).first);
+ } catch (Exception e) {
+ Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": unable to calculate md5()", e);
+ fail(e.getMessage());
+ return;
+ }
+ } else {
+ md5 = null;
+ }
+
Pair<InputStream, Integer> pair;
try {
pair = AbstractConnectionManager.createInputStream(file, true);
@@ -129,50 +140,19 @@ public class HttpUploadConnection implements Transferable {
this.file.setExpectedSize(pair.second);
message.resetFileParams();
this.mFileInputStream = pair.first;
- String http_upload_namespace = account.getXmppConnection().getFeatures().http_upload_namespace;
- Jid host = account.getXmppConnection().findDiscoItemByFeature(http_upload_namespace);
- IqPacket request = mXmppConnectionService.getIqGenerator().requestHttpUploadSlot(host, file, mime, http_upload_namespace);
- mXmppConnectionService.sendIqPacket(account, request, (a, packet) -> {
- if (packet.getType() == IqPacket.TYPE.RESULT) {
- Element slot = packet.findChild("slot", http_upload_namespace);
- if (slot != null) {
- try {
- final Element put = slot.findChild("put");
- final Element get = slot.findChild("get");
- final String putUrl;
- final String getUrl;
- if (http_upload_namespace == Namespace.HTTP_UPLOAD) {
- putUrl = put == null ? null : put.getAttribute("url");
- getUrl = get == null ? null : get.getAttribute("url");
- } else {
- putUrl = put == null ? null : put.getContent();
- getUrl = get == null ? null : get.getContent();
- }
- if (getUrl != null && putUrl != null) {
- this.mGetUrl = new URL(getUrl);
- this.mPutUrl = new URL(putUrl);
- this.mPutHeaders = new HashMap<>();
- for (Element child : put.getChildren()) {
- if ("header".equals(child.getName())) {
- final String name = child.getAttribute("name");
- final String value = child.getContent();
- if (WHITE_LISTED_HEADERS.contains(name) && value != null && !value.trim().contains("\n")) {
- this.mPutHeaders.put(name, value.trim());
- }
- }
- }
- if (!canceled) {
- new Thread(this::upload).start();
- }
- return;
- }
- } catch (MalformedURLException e) {
- //fall through
- }
+ this.mSlotRequester.request(method, account, file, mime, md5, new SlotRequester.OnSlotRequested() {
+ @Override
+ public void success(SlotRequester.Slot slot) {
+ if (!canceled) {
+ HttpUploadConnection.this.slot = slot;
+ new Thread(HttpUploadConnection.this::upload).start();
}
}
- Log.d(Config.LOGTAG, account.getJid().toString() + ": invalid response to slot request " + packet);
- fail(IqParser.extractErrorMessage(packet));
+
+ @Override
+ public void failure(String message) {
+ fail(message);
+ }
});
message.setTransferable(this);
mXmppConnectionService.markMessage(message, Message.STATUS_UNSEND);
@@ -186,11 +166,11 @@ public class HttpUploadConnection implements Transferable {
final int expectedFileSize = (int) file.getExpectedSize();
final int readTimeout = (expectedFileSize / 2048) + Config.SOCKET_TIMEOUT; //assuming a minimum transfer speed of 16kbit/s
wakeLock.acquire(readTimeout);
- Log.d(Config.LOGTAG, "uploading to " + mPutUrl.toString() + " w/ read timeout of " + readTimeout + "s");
+ Log.d(Config.LOGTAG, "uploading to " + slot.getPutUrl().toString() + " w/ read timeout of " + readTimeout + "s");
if (mUseTor) {
- connection = (HttpURLConnection) mPutUrl.openConnection(HttpConnectionManager.getProxy());
+ connection = (HttpURLConnection) slot.getPutUrl().openConnection(HttpConnectionManager.getProxy());
} else {
- connection = (HttpURLConnection) mPutUrl.openConnection();
+ connection = (HttpURLConnection) slot.getPutUrl().openConnection();
}
if (connection instanceof HttpsURLConnection) {
mHttpConnectionManager.setupTrustManager((HttpsURLConnection) connection, true);
@@ -198,14 +178,14 @@ public class HttpUploadConnection implements Transferable {
connection.setUseCaches(false);
connection.setRequestMethod("PUT");
connection.setFixedLengthStreamingMode(expectedFileSize);
- connection.setRequestProperty("Content-Type", mime == null ? "application/octet-stream" : mime);
connection.setRequestProperty("User-Agent", mXmppConnectionService.getIqGenerator().getIdentityName());
- if (mPutHeaders != null) {
- for (HashMap.Entry<String, String> entry : mPutHeaders.entrySet()) {
+ if (slot.getHeaders() != null) {
+ for (HashMap.Entry<String, String> entry : slot.getHeaders().entrySet()) {
connection.setRequestProperty(entry.getKey(), entry.getValue());
}
}
connection.setDoOutput(true);
+ connection.setDoInput(true);
connection.setConnectTimeout(Config.SOCKET_TIMEOUT * 1000);
connection.setReadTimeout(readTimeout * 1000);
connection.connect();
@@ -222,12 +202,26 @@ public class HttpUploadConnection implements Transferable {
os.close();
mFileInputStream.close();
int code = connection.getResponseCode();
+ InputStream is = connection.getErrorStream();
+ if (is != null) {
+ try (Scanner scanner = new Scanner(is)) {
+ scanner.useDelimiter("\\Z");
+ Log.d(Config.LOGTAG, "body: " + scanner.next());
+ }
+ }
if (code == 200 || code == 201) {
Log.d(Config.LOGTAG, "finished uploading file");
+ final URL get;
if (key != null) {
- mGetUrl = CryptoHelper.toAesGcmUrl(new URL(mGetUrl.toString() + "#" + CryptoHelper.bytesToHex(key)));
+ if (method == Method.P1_S3) {
+ get = new URL(slot.getGetUrl().toString() + "#" + CryptoHelper.bytesToHex(key));
+ } else {
+ get = CryptoHelper.toAesGcmUrl(new URL(slot.getGetUrl().toString() + "#" + CryptoHelper.bytesToHex(key)));
+ }
+ } else {
+ get = slot.getGetUrl();
}
- mXmppConnectionService.getFileBackend().updateFileParams(message, mGetUrl);
+ mXmppConnectionService.getFileBackend().updateFileParams(message, get);
mXmppConnectionService.getFileBackend().updateMediaScanner(file);
message.setTransferable(null);
message.setCounterpart(message.getConversation().getJid().asBareJid());