diff options
author | Christian Schneppe <christian@pix-art.de> | 2018-05-26 22:56:17 +0200 |
---|---|---|
committer | Christian Schneppe <christian@pix-art.de> | 2018-05-26 22:56:17 +0200 |
commit | a554be18a60380d624fc9c65416368775cba9bae (patch) | |
tree | be455ef73e0c047a47bd71651382f2d22dd115ab /src/main/java/de/pixart/messenger/http/HttpUploadConnection.java | |
parent | 369e48c2203a694088156574dd7c7044f68e907b (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.java | 126 |
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()); |