From b1ab7347b92329512bebe57f6624cae33c27036f Mon Sep 17 00:00:00 2001 From: steckbrief Date: Sun, 29 May 2016 20:33:36 +0200 Subject: FileTransfer reworked (first steps - functionality as is), HttpUpload separated, some bugfixes - HttpUpload moved into own package - FileTransfer managed by a central manager class, several FileTransferService implementation can be used - Security initializations moved to ConversationsPlusApplication - Access to PowerManager moved to ConversationsPlusApplication - Removed unused code fragments - Access to HttpConnectionManager is now static --- .../filetransfer/httpupload/HttpFileUploader.java | 120 +++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 src/main/java/de/thedevstack/conversationsplus/services/filetransfer/httpupload/HttpFileUploader.java (limited to 'src/main/java/de/thedevstack/conversationsplus/services/filetransfer/httpupload/HttpFileUploader.java') diff --git a/src/main/java/de/thedevstack/conversationsplus/services/filetransfer/httpupload/HttpFileUploader.java b/src/main/java/de/thedevstack/conversationsplus/services/filetransfer/httpupload/HttpFileUploader.java new file mode 100644 index 00000000..6352c7a7 --- /dev/null +++ b/src/main/java/de/thedevstack/conversationsplus/services/filetransfer/httpupload/HttpFileUploader.java @@ -0,0 +1,120 @@ +package de.thedevstack.conversationsplus.services.filetransfer.httpupload; + +import android.os.PowerManager; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.Scanner; + +import javax.net.ssl.HttpsURLConnection; + +import de.thedevstack.android.logcat.Logging; +import de.thedevstack.conversationsplus.Config; +import de.thedevstack.conversationsplus.ConversationsPlusApplication; +import de.thedevstack.conversationsplus.entities.DownloadableFile; +import de.thedevstack.conversationsplus.entities.Message; +import de.thedevstack.conversationsplus.http.HttpConnectionManager; +import de.thedevstack.conversationsplus.persistance.FileBackend; +import de.thedevstack.conversationsplus.utils.CryptoHelper; +import de.thedevstack.conversationsplus.utils.MessageUtil; +import de.thedevstack.conversationsplus.utils.StreamUtil; +import de.thedevstack.conversationsplus.utils.UiUpdateHelper; +import de.thedevstack.conversationsplus.utils.XmppConnectionServiceAccessor; +import de.thedevstack.conversationsplus.xmpp.httpupload.HttpUpload; + +public class HttpFileUploader implements Runnable { + private static final String HTTP_METHOD = "PUT"; + private static final String MIME_REQUEST_PROPERTY_NAME = "Content-Type"; + private static final String USER_AGENT_REQUEST_PROPERTY_NAME = "User-Agent"; + private static final int BUFFER_LENGTH = 4096; + private final HttpFileTransferEntity entity; + + public HttpFileUploader(HttpFileTransferEntity entity) { + this.entity = entity; + } + + @Override + public void run() { + this.upload(); + } + + private void upload() { + OutputStream os = null; + InputStream errorStream = null; + HttpURLConnection connection = null; + InputStream fileInputStream = null; + DownloadableFile file = this.entity.getFile(); + PowerManager.WakeLock wakeLock = ConversationsPlusApplication.createPartialWakeLock("http_upload_" + entity.getMessage().getUuid()); + try { + wakeLock.acquire(); + Logging.d(Config.LOGTAG, "uploading to " + this.entity.getPutUrl()); + URL putUrl = new URL(this.entity.getPutUrl()); + fileInputStream = this.entity.getFileInputStream(); + connection = (HttpURLConnection) putUrl.openConnection(); + + if (connection instanceof HttpsURLConnection) { + HttpConnectionManager.setupTrustManager((HttpsURLConnection) connection, true); + } + connection.setRequestMethod(HTTP_METHOD); + connection.setFixedLengthStreamingMode((int) file.getExpectedSize()); + String mime = this.entity.getFile().getMimeType(); + connection.setRequestProperty(MIME_REQUEST_PROPERTY_NAME, mime == null ? HttpUpload.DEFAULT_MIME_TYPE : mime); + connection.setRequestProperty(USER_AGENT_REQUEST_PROPERTY_NAME, ConversationsPlusApplication.getNameAndVersion()); + connection.setDoOutput(true); + connection.connect(); + os = connection.getOutputStream(); + int count = -1; + byte[] buffer = new byte[BUFFER_LENGTH]; + while (((count = fileInputStream.read(buffer)) != -1) && !this.entity.isCanceled()) { + this.entity.updateProgress(count); + os.write(buffer, 0, count); + UiUpdateHelper.updateConversationUi(); + } + os.flush(); + os.close(); + fileInputStream.close(); + int code = connection.getResponseCode(); + if (code == 200 || code == 201) { + Logging.d(Config.LOGTAG, "finished uploading file"); + this.entity.transferred(); + URL getUrl = new URL(this.entity.getGetUrl()); + if (this.entity.getKey() != null) { + getUrl = new URL(getUrl.toString() + "#" + CryptoHelper.bytesToHex(this.entity.getKey())); + } + Message message = this.entity.getMessage(); + MessageUtil.updateFileParams(message, getUrl); + FileBackend.updateMediaScanner(file, XmppConnectionServiceAccessor.xmppConnectionService); + message.setTransferable(null); + message.setCounterpart(message.getConversation().getJid().toBareJid()); + if (message.getEncryption() == Message.ENCRYPTION_DECRYPTED) { + XmppConnectionServiceAccessor.xmppConnectionService.getPgpEngine().encrypt(message, new HttpUploadedFileEncryptionUiCallback(this.entity)); + } else { + XmppConnectionServiceAccessor.xmppConnectionService.resendMessage(message, this.entity.isDelayed()); + } + } else { + errorStream = connection.getErrorStream(); + Logging.e("httpupload", "file upload failed: http code (" + code + ") " + new Scanner(errorStream).useDelimiter("\\A").next()); + this.entity.fail(); + } + } catch (IOException e) { + errorStream = (null != connection) ? connection.getErrorStream() : null; + String httpResponseMessage = null; + if (null != errorStream) { + httpResponseMessage = new Scanner(errorStream).useDelimiter("\\A").next(); + } + Logging.e("httpupload", ((null != httpResponseMessage) ? ("http response: " + httpResponseMessage + ", ") : "") + "exception message: " + e.getMessage()); + this.entity.fail(); + } finally { + StreamUtil.close(os); + StreamUtil.close(errorStream); + StreamUtil.close(fileInputStream); + if (connection != null) { + connection.disconnect(); + } + wakeLock.release(); + } + } +} \ No newline at end of file -- cgit v1.2.3