aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java/de/thedevstack/conversationsplus/services/filetransfer/httpupload/HttpFileUploader.java
blob: 6352c7a7ccc3cc8ca9ea43f0e44817510af2ecb0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
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();
        }
    }
}