aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java/de/thedevstack/conversationsplus/utils/AvatarUtil.java
blob: 32883c3b4743d8fec8486e40b1ba1807a32fbabc (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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
package de.thedevstack.conversationsplus.utils;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.util.Base64;
import android.util.Base64OutputStream;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.security.DigestOutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import de.thedevstack.android.logcat.Logging;
import de.thedevstack.conversationsplus.ConversationsPlusApplication;
import de.thedevstack.conversationsplus.Config;
import de.thedevstack.conversationsplus.dto.Avatar;

/**
 * This util provides access to saved avatars, creating avatars.
 */
public final class AvatarUtil {

    /**
     * Get the PEP Avatar.
     * TODO: Why PEP Avatar?
     * @param image the uri to the avatar's image
     * @param size the image width/height to resize to
     * @param format the format for the avatar
     * @return the avatar
     */
    public static Avatar getPepAvatar(Uri image, int size, Bitmap.CompressFormat format) {
        try {
            Avatar avatar = new Avatar();
            Bitmap bm = ImageUtil.cropCenterSquare(image, size);
            if (bm == null) {
                return null;
            }
            ByteArrayOutputStream mByteArrayOutputStream = new ByteArrayOutputStream();
            Base64OutputStream mBase64OutputSttream = new Base64OutputStream(
                    mByteArrayOutputStream, Base64.DEFAULT);
            MessageDigest digest = MessageDigest.getInstance("SHA-1");
            DigestOutputStream mDigestOutputStream = new DigestOutputStream(
                    mBase64OutputSttream, digest);
            if (!bm.compress(format, 75, mDigestOutputStream)) {
                return null;
            }
            mDigestOutputStream.flush();
            mDigestOutputStream.close();
            avatar.sha1sum = CryptoHelper.bytesToHex(digest.digest());
            avatar.image = new String(mByteArrayOutputStream.toByteArray());
            return avatar;
        } catch (NoSuchAlgorithmException e) {
            return null;
        } catch (IOException e) {
            return null;
        }

    }

    public static Avatar getStoredPepAvatar(String hash) {
        if (hash == null) {
            return null;
        }
        Avatar avatar = new Avatar();
        File file = new File(getAvatarPath(hash));
        FileInputStream is = null;
        try {
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeFile(file.getAbsolutePath(), options);
            is = new FileInputStream(file);
            ByteArrayOutputStream mByteArrayOutputStream = new ByteArrayOutputStream();
            Base64OutputStream mBase64OutputStream = new Base64OutputStream(mByteArrayOutputStream, Base64.DEFAULT);
            MessageDigest digest = MessageDigest.getInstance("SHA-1");
            DigestOutputStream os = new DigestOutputStream(mBase64OutputStream, digest);
            byte[] buffer = new byte[4096];
            int length;
            while ((length = is.read(buffer)) > 0) {
                os.write(buffer, 0, length);
            }
            os.flush();
            os.close();
            avatar.sha1sum = CryptoHelper.bytesToHex(digest.digest());
            avatar.image = new String(mByteArrayOutputStream.toByteArray());
            avatar.height = options.outHeight;
            avatar.width = options.outWidth;
            return avatar;
        } catch (IOException e) {
            return null;
        } catch (NoSuchAlgorithmException e) {
            return null;
        } finally {
            StreamUtil.close(is);
        }
    }

    /**
     * Returns whether the avatar is cached or not.
     * @param avatar the avatar to check the existance
     * @return <code>true</code> if the file of the avatar exists, <code>false</code> otherwise
     */
    public static boolean isAvatarCached(Avatar avatar) {
        File file = new File(getAvatarPath(avatar.getFilename()));
        return file.exists();
    }

    /**
     * Saves an avatar to the file system.
     * All exceptions are silently ignored.
     * TODO: Move real saving operation to FileBackend
     * @param avatar the avatar to save
     * @return <code>true</code> if the avatar was saved successfully, <code>false</code> otherwise.
     */
    public static boolean save(Avatar avatar) {
        File file;
        if (isAvatarCached(avatar)) {
            file = new File(getAvatarPath(avatar.getFilename()));
        } else {
            String filename = getAvatarPath(avatar.getFilename());
            file = new File(filename + ".tmp");
            file.getParentFile().mkdirs();
            OutputStream os = null;
            try {
                file.createNewFile();
                os = new FileOutputStream(file);
                MessageDigest digest = MessageDigest.getInstance("SHA-1");
                digest.reset();
                DigestOutputStream mDigestOutputStream = new DigestOutputStream(os, digest);
                mDigestOutputStream.write(avatar.getImageAsBytes());
                mDigestOutputStream.flush();
                mDigestOutputStream.close();
                String sha1sum = CryptoHelper.bytesToHex(digest.digest());
                if (sha1sum.equals(avatar.sha1sum)) {
                    file.renameTo(new File(filename));
                } else {
                    Logging.d(Config.LOGTAG, "sha1sum mismatch for " + avatar.owner);
                    file.delete();
                    return false;
                }
            } catch (FileNotFoundException e) {
                return false;
            } catch (IOException e) {
                return false;
            } catch (NoSuchAlgorithmException e) {
                return false;
            } finally {
                StreamUtil.close(os);
            }
        }
        avatar.size = file.length();
        return true;
    }

    /**
     * Returns the avatar for an uri.
     * @param avatar the avatar's uri
     * @param size the height/width the avatar should have
     * @return the bitmap of the uri
     */
    public static Bitmap getAvatar(String avatar, int size) {
        if (avatar == null) {
            return null;
        }
        Bitmap bm = ImageUtil.cropCenter(getAvatarUri(avatar), size, size);
        if (bm == null) {
            return null;
        }
        return bm;
    }

    /**
     * Returns the path to an avatar
     * @param avatar the name of the avatar.
     * @return the path as string
     */
    public static String getAvatarPath(String avatar) {
        return ConversationsPlusApplication.getInstance().getFilesDir().getAbsolutePath()+ "/avatars/" + avatar;
    }

    /**
     * Returns the path to an avatar as an uri.
     * @param avatar the name of the avatar
     * @return the path as uri
     */
    public static Uri getAvatarUri(String avatar) {
        return Uri.parse("file:" + getAvatarPath(avatar));
    }

    /**
     * Avoid instantiation it's an helper class.
     */
    private AvatarUtil() {
        // Static helper class
    }
}