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(); } } }