diff --git a/TMessagesProj/build.gradle b/TMessagesProj/build.gradle index e3e72fe76..009975b5e 100644 --- a/TMessagesProj/build.gradle +++ b/TMessagesProj/build.gradle @@ -80,7 +80,7 @@ android { defaultConfig { minSdkVersion 8 targetSdkVersion 19 - versionCode 310 + versionCode 311 versionName "1.8.0" } } diff --git a/TMessagesProj/src/main/java/org/telegram/android/GcmBroadcastReceiver.java b/TMessagesProj/src/main/java/org/telegram/android/GcmBroadcastReceiver.java index e93db41a5..ebd061984 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/GcmBroadcastReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/android/GcmBroadcastReceiver.java @@ -53,13 +53,6 @@ public class GcmBroadcastReceiver extends BroadcastReceiver { FileLog.e("tmessages", e); } - /*SharedPreferences preferences = context.getSharedPreferences("Notifications", Context.MODE_PRIVATE); - boolean globalEnabled = preferences.getBoolean("EnableAll", true); - if (!globalEnabled) { - FileLog.d("tmessages", "GCM disabled"); - return; - }*/ - ConnectionsManager.getInstance().resumeNetworkMaybe(); } }); diff --git a/TMessagesProj/src/main/java/org/telegram/android/ImageLoader.java b/TMessagesProj/src/main/java/org/telegram/android/ImageLoader.java index 47ee4924a..cf08591ce 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/ImageLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/android/ImageLoader.java @@ -628,7 +628,7 @@ public class ImageLoader { } } - public BitmapDrawable getImageFromMemory(TLRPC.FileLocation url, String httpUrl, String filter) { + public BitmapDrawable getImageFromMemory(TLRPC.FileLocation url, String httpUrl, String filter, ImageReceiver imageReceiver) { if (url == null && httpUrl == null) { return null; } @@ -641,6 +641,15 @@ public class ImageLoader { if (filter != null) { key += "@" + filter; } + if (imageReceiver != null) { + Integer TAG = imageReceiver.getTag(); + if (TAG != null) { + CacheImage alreadyLoadingImage = imageLoadingByTag.get(TAG); + if (alreadyLoadingImage != null) { + alreadyLoadingImage.removeImageView(imageReceiver); + } + } + } return memCache.get(key); } @@ -668,8 +677,8 @@ public class ImageLoader { String url; String key; if (httpUrl != null) { - url = httpUrl; key = Utilities.MD5(httpUrl); + url = key + ".jpg"; } else { key = fileLocation.volume_id + "_" + fileLocation.local_id; url = key + ".jpg"; diff --git a/TMessagesProj/src/main/java/org/telegram/android/ImageReceiver.java b/TMessagesProj/src/main/java/org/telegram/android/ImageReceiver.java index 9fa11db9e..5ac403313 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/ImageReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/android/ImageReceiver.java @@ -88,14 +88,14 @@ public class ImageReceiver { if (currentImage != null) { return; } else { - img = ImageLoader.getInstance().getImageFromMemory(fileLocation, httpUrl, filter); + img = ImageLoader.getInstance().getImageFromMemory(fileLocation, httpUrl, filter, this); } } else { - img = ImageLoader.getInstance().getImageFromMemory(fileLocation, httpUrl, filter); + img = ImageLoader.getInstance().getImageFromMemory(fileLocation, httpUrl, filter, this); recycleBitmap(img); } } - img = ImageLoader.getInstance().getImageFromMemory(fileLocation, httpUrl, filter); + img = ImageLoader.getInstance().getImageFromMemory(fileLocation, httpUrl, filter, this); currentPath = key; last_path = fileLocation; last_httpUrl = httpUrl; diff --git a/TMessagesProj/src/main/java/org/telegram/android/MessagesController.java b/TMessagesProj/src/main/java/org/telegram/android/MessagesController.java index 2376f01b1..aa43c96ae 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/MessagesController.java +++ b/TMessagesProj/src/main/java/org/telegram/android/MessagesController.java @@ -963,7 +963,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter NotificationsController.getInstance().processReadMessages(null, did, 0, Integer.MAX_VALUE, false); HashMap dialogsToUpdate = new HashMap(); dialogsToUpdate.put(did, 0); - NotificationsController.getInstance().processDialogsUpdateRead(dialogsToUpdate, true); + NotificationsController.getInstance().processDialogsUpdateRead(dialogsToUpdate); } }); } @@ -1395,7 +1395,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter currentDialog.unread_count = entry.getValue(); } } - NotificationsController.getInstance().processDialogsUpdateRead(dialogsToUpdate, true); + NotificationsController.getInstance().processDialogsUpdateRead(dialogsToUpdate); NotificationCenter.getInstance().postNotificationName(NotificationCenter.dialogsNeedReload); } }); @@ -1491,7 +1491,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter dialogsServerOnly.add(d); } } - NotificationsController.getInstance().processDialogsUpdateRead(dialogsToUpdate, true); + NotificationsController.getInstance().processDialogsUpdateRead(dialogsToUpdate); NotificationCenter.getInstance().postNotificationName(NotificationCenter.dialogsNeedReload); } }); @@ -1711,12 +1711,12 @@ public class MessagesController implements NotificationCenter.NotificationCenter NotificationsController.getInstance().processReadMessages(null, dialog_id, 0, max_positive_id, false); HashMap dialogsToUpdate = new HashMap(); dialogsToUpdate.put(dialog_id, 0); - NotificationsController.getInstance().processDialogsUpdateRead(dialogsToUpdate, true); + NotificationsController.getInstance().processDialogsUpdateRead(dialogsToUpdate); } else { NotificationsController.getInstance().processReadMessages(null, dialog_id, 0, max_positive_id, true); HashMap dialogsToUpdate = new HashMap(); - dialogsToUpdate.put(dialog_id, 2000001); - NotificationsController.getInstance().processDialogsUpdateRead(dialogsToUpdate, false); + dialogsToUpdate.put(dialog_id, -1); + NotificationsController.getInstance().processDialogsUpdateRead(dialogsToUpdate); } } }); @@ -1784,7 +1784,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter } HashMap dialogsToUpdate = new HashMap(); dialogsToUpdate.put(dialog_id, 0); - NotificationsController.getInstance().processDialogsUpdateRead(dialogsToUpdate, true); + NotificationsController.getInstance().processDialogsUpdateRead(dialogsToUpdate); } }); } @@ -3417,27 +3417,6 @@ public class MessagesController implements NotificationCenter.NotificationCenter return false; } - public void dialogsUnreadCountIncr(final HashMap values) { - AndroidUtilities.RunOnUIThread(new Runnable() { - @Override - public void run() { - for (HashMap.Entry entry : values.entrySet()) { - TLRPC.TL_dialog dialog = dialogs_dict.get(entry.getKey()); - if (dialog != null) { - int value = entry.getValue(); - if (value < 0) { - dialog.unread_count = -value; - } else { - dialog.unread_count += value; - } - } - } - NotificationsController.getInstance().processDialogsUpdateRead(values, false); - NotificationCenter.getInstance().postNotificationName(NotificationCenter.dialogsNeedReload); - } - }); - } - protected void updateInterfaceWithMessages(long uid, ArrayList messages) { updateInterfaceWithMessages(uid, messages, false); } @@ -3718,7 +3697,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter NotificationsController.getInstance().processReadMessages(null, did, 0, Integer.MAX_VALUE, false); HashMap dialogsToUpdate = new HashMap(); dialogsToUpdate.put(did, 0); - NotificationsController.getInstance().processDialogsUpdateRead(dialogsToUpdate, true); + NotificationsController.getInstance().processDialogsUpdateRead(dialogsToUpdate); } }); } diff --git a/TMessagesProj/src/main/java/org/telegram/android/MessagesStorage.java b/TMessagesProj/src/main/java/org/telegram/android/MessagesStorage.java index 0cb3893ae..7ed8172e8 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/MessagesStorage.java +++ b/TMessagesProj/src/main/java/org/telegram/android/MessagesStorage.java @@ -133,42 +133,51 @@ public class MessagesStorage { database.executeFast("CREATE INDEX IF NOT EXISTS send_state_idx_messages ON messages(mid, send_state, date) WHERE mid < 0 AND send_state = 1;").stepThis().dispose(); database.executeFast("PRAGMA user_version = 3").stepThis().dispose(); } else { - int version = database.executeInt("PRAGMA user_version"); - if (version < 3) { - SQLiteCursor cursor = database.queryFinalized("SELECT count(*) FROM sqlite_master WHERE type='table' AND name='params'"); - boolean create = false; + try { + SQLiteCursor cursor = database.queryFinalized("SELECT seq, pts, date, qts, lsv, sg, pbytes FROM params WHERE id = 1"); if (cursor.next()) { - int count = cursor.intValue(0); - if (count == 0) { - create = true; - } - } else { - create = true; - } - cursor.dispose(); - if (create) { - database.executeFast("CREATE TABLE params(id INTEGER PRIMARY KEY, seq INTEGER, pts INTEGER, date INTEGER, qts INTEGER, lsv INTEGER, sg INTEGER, pbytes BLOB)").stepThis().dispose(); - database.executeFast("INSERT INTO params VALUES(1, 0, 0, 0, 0, 0, 0, NULL)").stepThis().dispose(); - } else { - cursor = database.queryFinalized("SELECT seq, pts, date, qts, lsv, sg, pbytes FROM params WHERE id = 1"); - if (cursor.next()) { - lastSeqValue = cursor.intValue(0); - lastPtsValue = cursor.intValue(1); - lastDateValue = cursor.intValue(2); - lastQtsValue = cursor.intValue(3); - lastSecretVersion = cursor.intValue(4); - secretG = cursor.intValue(5); - if (cursor.isNull(6)) { + lastSeqValue = cursor.intValue(0); + lastPtsValue = cursor.intValue(1); + lastDateValue = cursor.intValue(2); + lastQtsValue = cursor.intValue(3); + lastSecretVersion = cursor.intValue(4); + secretG = cursor.intValue(5); + if (cursor.isNull(6)) { + secretPBytes = null; + } else { + secretPBytes = cursor.byteArrayValue(6); + if (secretPBytes != null && secretPBytes.length == 1) { secretPBytes = null; - } else { - secretPBytes = cursor.byteArrayValue(6); - if (secretPBytes != null && secretPBytes.length == 1) { - secretPBytes = null; - } } } - cursor.dispose(); } + cursor.dispose(); + } catch (Exception e) { + FileLog.e("tmessages", e); + try { + database.executeFast("CREATE TABLE IF NOT EXISTS params(id INTEGER PRIMARY KEY, seq INTEGER, pts INTEGER, date INTEGER, qts INTEGER, lsv INTEGER, sg INTEGER, pbytes BLOB)").stepThis().dispose(); + database.executeFast("INSERT INTO params VALUES(1, 0, 0, 0, 0, 0, 0, NULL)").stepThis().dispose(); + } catch (Exception e2) { + FileLog.e("tmessages", e2); + } + } + + int version = database.executeInt("PRAGMA user_version"); + if (version < 3) { + updateDbToVersion3(); + } + } + } catch (Exception e) { + FileLog.e("tmessages", e); + } + loadUnreadMessages(false); + } + + public void updateDbToVersion3() { + storageQueue.postRunnable(new Runnable() { + @Override + public void run() { + try { database.executeFast("CREATE TABLE IF NOT EXISTS user_photos(uid INTEGER, id INTEGER, data BLOB, PRIMARY KEY (uid, id))").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS mid_idx_media ON media(mid);").stepThis().dispose(); @@ -200,7 +209,12 @@ public class MessagesStorage { database.executeFast("UPDATE messages SET send_state = 2 WHERE mid < 0 AND send_state = 1").stepThis().dispose(); - database.executeFast("ALTER TABLE dialogs ADD COLUMN flags INTEGER NOT NULL default 0;").stepThis().dispose(); + try { + database.executeFast("ALTER TABLE dialogs ADD COLUMN flags INTEGER NOT NULL default 0;").stepThis().dispose(); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + database.executeFast("CREATE INDEX IF NOT EXISTS unread_count_flags_idx_dialogs ON dialogs(unread_count, flags);").stepThis().dispose(); database.executeFast("PRAGMA user_version = 3").stepThis().dispose(); @@ -230,31 +244,11 @@ public class MessagesStorage { } } }); - } else { - SQLiteCursor cursor = database.queryFinalized("SELECT seq, pts, date, qts, lsv, sg, pbytes FROM params WHERE id = 1"); - if (cursor.next()) { - lastSeqValue = cursor.intValue(0); - lastPtsValue = cursor.intValue(1); - lastDateValue = cursor.intValue(2); - lastQtsValue = cursor.intValue(3); - lastSecretVersion = cursor.intValue(4); - secretG = cursor.intValue(5); - if (cursor.isNull(6)) { - secretPBytes = null; - } else { - secretPBytes = cursor.byteArrayValue(6); - if (secretPBytes != null && secretPBytes.length == 1) { - secretPBytes = null; - } - } - } - cursor.dispose(); + } catch (Exception e) { + FileLog.e("tmessages", e); } } - } catch (Exception e) { - FileLog.e("tmessages", e); - } - loadUnreadMessages(false); + }); } public void cleanUp(final boolean isLogin) { @@ -2416,36 +2410,24 @@ public class MessagesStorage { SQLitePreparedStatement state4 = database.executeFast("REPLACE INTO download_queue VALUES(?, ?, ?, ?)"); for (TLRPC.Message message : messages) { - long dialog_id = 0; + long dialog_id = message.dialog_id; + if (dialog_id == 0) { + if (message.to_id.chat_id != 0) { + dialog_id = -message.to_id.chat_id; + } else if (message.to_id.user_id != 0) { + dialog_id = message.to_id.user_id; + } + } + if (message.unread && !message.out) { if (messageIds.length() > 0) { messageIds += ","; } messageIds += message.id; - - dialog_id = message.dialog_id; - if (dialog_id == 0) { - if (message.to_id.chat_id != 0) { - dialog_id = -message.to_id.chat_id; - } else if (message.to_id.user_id != 0) { - dialog_id = message.to_id.user_id; - } - } - messagesIdsMap.put(message.id, dialog_id); } if (message.media instanceof TLRPC.TL_messageMediaVideo || message.media instanceof TLRPC.TL_messageMediaPhoto) { - if (dialog_id == 0) { - dialog_id = message.dialog_id; - if (dialog_id == 0) { - if (message.to_id.chat_id != 0) { - dialog_id = -message.to_id.chat_id; - } else if (message.to_id.user_id != 0) { - dialog_id = message.to_id.user_id; - } - } - } if (messageMediaIds.length() > 0) { messageMediaIds += ","; } @@ -2612,7 +2594,7 @@ public class MessagesStorage { if (unread_count == null) { unread_count = 0; } else { - messagesCounts.put(key, -(unread_count + old_unread_count)); + messagesCounts.put(key, unread_count + old_unread_count); } int messageId = value.id; if (value.local_id != 0) { @@ -2633,7 +2615,7 @@ public class MessagesStorage { if (withTransaction) { database.commitTransaction(); } - MessagesController.getInstance().dialogsUnreadCountIncr(messagesCounts); + MessagesController.getInstance().processDialogsUpdateRead(messagesCounts); if (!mediaCounts.isEmpty()) { state = database.executeFast("REPLACE INTO media_counts VALUES(?, ?)"); @@ -2687,6 +2669,19 @@ public class MessagesStorage { } } + public void markMessageAsSendError(final int mid) { + storageQueue.postRunnable(new Runnable() { + @Override + public void run() { + try { + database.executeFast("UPDATE messages SET send_state = 2 WHERE mid = " + mid).stepThis().dispose(); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + }); + } + private Integer updateMessageStateAndIdInternal(long random_id, Integer _oldId, int newId, int date) { if (_oldId != null && _oldId == newId && date != 0) { SQLitePreparedStatement state = null; diff --git a/TMessagesProj/src/main/java/org/telegram/android/NotificationsController.java b/TMessagesProj/src/main/java/org/telegram/android/NotificationsController.java index cfec53cc7..6286c385f 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/NotificationsController.java +++ b/TMessagesProj/src/main/java/org/telegram/android/NotificationsController.java @@ -419,7 +419,7 @@ public class NotificationsController { } if (photoPath != null) { - BitmapDrawable img = ImageLoader.getInstance().getImageFromMemory(photoPath, null, "50_50"); + BitmapDrawable img = ImageLoader.getInstance().getImageFromMemory(photoPath, null, "50_50", null); if (img != null) { mBuilder.setLargeIcon(img.getBitmap()); } @@ -596,50 +596,40 @@ public class NotificationsController { } } - public void processDialogsUpdateRead(final HashMap dialogsToUpdate, boolean replace) { + public void processDialogsUpdateRead(final HashMap dialogsToUpdate) { int old_unread_count = total_unread_count; SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Context.MODE_PRIVATE); for (HashMap.Entry entry : dialogsToUpdate.entrySet()) { long dialog_id = entry.getKey(); int notify_override = preferences.getInt("notify2_" + dialog_id, 0); - boolean isChat = (int)dialog_id < 0; - Integer currentCount = pushDialogs.get(dialog_id); - boolean canAddValue = !(notify_override == 2 || (!preferences.getBoolean("EnableAll", true) || isChat && !preferences.getBoolean("EnableGroup", true)) && notify_override == 0); + boolean canAddValue = !(notify_override == 2 || (!preferences.getBoolean("EnableAll", true) || ((int)dialog_id < 0) && !preferences.getBoolean("EnableGroup", true)) && notify_override == 0); + Integer currentCount = pushDialogs.get(dialog_id); Integer newCount = entry.getValue(); - if (replace || newCount < 0) { - if (newCount < 0) { - newCount *= -1; + if (newCount < 0) { + if (currentCount == null) { + continue; } - if (currentCount != null) { - total_unread_count -= currentCount; - } - if (newCount == 0) { - pushDialogs.remove(dialog_id); - for (int a = 0; a < pushMessages.size(); a++) { - MessageObject messageObject = pushMessages.get(a); - if (messageObject.getDialogId() == dialog_id) { - pushMessages.remove(a); - a--; - pushMessagesDict.remove(messageObject.messageOwner.id); - popupMessages.remove(messageObject); - } + newCount = currentCount + newCount; + } + if (currentCount != null) { + total_unread_count -= currentCount; + } + if (newCount == 0) { + pushDialogs.remove(dialog_id); + for (int a = 0; a < pushMessages.size(); a++) { + MessageObject messageObject = pushMessages.get(a); + if (messageObject.getDialogId() == dialog_id) { + pushMessages.remove(a); + a--; + pushMessagesDict.remove(messageObject.messageOwner.id); + popupMessages.remove(messageObject); } - } else if (canAddValue) { - total_unread_count += newCount; - pushDialogs.put(dialog_id, newCount); } } else if (canAddValue) { - if (newCount > 2000000) { - newCount = 2000000 - newCount; - } - if (currentCount == null) { - currentCount = 0; - } - currentCount += newCount; total_unread_count += newCount; - pushDialogs.put(dialog_id, currentCount); + pushDialogs.put(dialog_id, newCount); } } if (old_unread_count != total_unread_count) { diff --git a/TMessagesProj/src/main/java/org/telegram/android/SendMessagesHelper.java b/TMessagesProj/src/main/java/org/telegram/android/SendMessagesHelper.java index 60a345117..ed4f128f7 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/SendMessagesHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/android/SendMessagesHelper.java @@ -147,6 +147,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter for (int a = 0; a < arr.size(); a++) { DelayedMessage obj = arr.get(a); if (enc && obj.sendEncryptedRequest != null || !enc && obj.sendRequest != null) { + MessagesStorage.getInstance().markMessageAsSendError(obj.obj.messageOwner.id); obj.obj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SEND_ERROR; arr.remove(a); a--; @@ -392,6 +393,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter newMsg.from_id = UserConfig.getClientUserId(); newMsg.out = true; newMsg.date = ConnectionsManager.getInstance().getCurrentTime(); + UserConfig.saveConfig(false); } if (newMsg.random_id == 0) { newMsg.random_id = getNextRandomId(); @@ -453,11 +455,11 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter newMsg.ttl = encryptedChat.ttl; } - UserConfig.saveConfig(false); - final MessageObject newMsgObj = new MessageObject(newMsg, null, 2); + + MessageObject newMsgObj = new MessageObject(newMsg, null, 2); newMsgObj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SENDING; - final ArrayList objArr = new ArrayList(); + ArrayList objArr = new ArrayList(); objArr.add(newMsgObj); ArrayList arr = new ArrayList(); arr.add(newMsg); @@ -553,7 +555,6 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter delayedMessage.obj = newMsgObj; delayedMessage.documentLocation = document; delayedMessage.location = document.thumb.location; - performSendDelayedMessage(delayedMessage); } else { TLRPC.TL_inputMediaDocument media = new TLRPC.TL_inputMediaDocument(); media.id = new TLRPC.TL_inputDocument(); @@ -889,6 +890,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter } }); } else { + MessagesStorage.getInstance().markMessageAsSendError(newMsgObj.messageOwner.id); AndroidUtilities.RunOnUIThread(new Runnable() { @Override public void run() { @@ -994,6 +996,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter } }); } else { + MessagesStorage.getInstance().markMessageAsSendError(newMsgObj.messageOwner.id); AndroidUtilities.RunOnUIThread(new Runnable() { @Override public void run() { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ConnectionsManager.java b/TMessagesProj/src/main/java/org/telegram/messenger/ConnectionsManager.java index 0198496f0..5acd0bcf3 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ConnectionsManager.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ConnectionsManager.java @@ -988,7 +988,6 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection. } } catch(Exception e) { FileLog.e("tmessages", e); - return true; } return false; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileUploadOperation.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileUploadOperation.java index b2c09ab3c..b579ff271 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileUploadOperation.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileUploadOperation.java @@ -37,6 +37,7 @@ public class FileUploadOperation { private byte[] key; private byte[] iv; private byte[] ivChange; + private boolean isEncrypted = false; private int fingerprint = 0; private boolean isBigFile = false; private String fileKey; @@ -51,32 +52,7 @@ public class FileUploadOperation { public FileUploadOperation(String location, boolean encrypted) { uploadingFilePath = location; - if (encrypted) { - iv = new byte[32]; - key = new byte[32]; - ivChange = new byte[32]; - Utilities.random.nextBytes(iv); - Utilities.random.nextBytes(key); - System.arraycopy(iv, 0, ivChange, 0, 32); - try { - java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5"); - byte[] arr = new byte[64]; - System.arraycopy(key, 0, arr, 0, 32); - System.arraycopy(iv, 0, arr, 32, 32); - byte[] digest = md.digest(arr); - for (int a = 0; a < 4; a++) { - fingerprint |= ((digest[a] ^ digest[a + 4]) & 0xFF) << (a * 8); - } - } catch (Exception e) { - FileLog.e("tmessages", e); - } - } - currentFileId = Utilities.random.nextLong(); - try { - mdEnc = MessageDigest.getInstance("MD5"); - } catch (NoSuchAlgorithmException e) { - FileLog.e("tmessages", e); - } + isEncrypted = encrypted; } public void start() { @@ -101,7 +77,13 @@ public class FileUploadOperation { private void cleanup() { SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("uploadinfo", Activity.MODE_PRIVATE); - preferences.edit().remove(fileKey + "_time").remove(fileKey + "_size").remove(fileKey + "_uploaded").commit(); + preferences.edit().remove(fileKey + "_time"). + remove(fileKey + "_size"). + remove(fileKey + "_uploaded"). + remove(fileKey + "_id"). + remove(fileKey + "_iv"). + remove(fileKey + "_key"). + remove(fileKey + "_ivc").commit(); } private void startUploadRequest() { @@ -118,6 +100,12 @@ public class FileUploadOperation { totalFileSize = cacheFile.length(); if (totalFileSize > 10 * 1024 * 1024) { isBigFile = true; + } else { + try { + mdEnc = MessageDigest.getInstance("MD5"); + } catch (NoSuchAlgorithmException e) { + FileLog.e("tmessages", e); + } } uploadChunkSize = (int) Math.max(32, Math.ceil(totalFileSize / (1024.0f * 3000))); @@ -133,28 +121,72 @@ public class FileUploadOperation { totalPartsCount = (int) Math.ceil((float) totalFileSize / (float) uploadChunkSize); readBuffer = new byte[uploadChunkSize]; - fileKey = Utilities.MD5(uploadingFilePath); - /*SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("uploadinfo", Activity.MODE_PRIVATE); TODO + fileKey = Utilities.MD5(uploadingFilePath + (isEncrypted ? "enc" : "")); + SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("uploadinfo", Activity.MODE_PRIVATE); long fileSize = preferences.getLong(fileKey + "_size", 0); int currentTime = (int)(System.currentTimeMillis() / 1000); boolean rewrite = false; if (fileSize == totalFileSize) { + currentFileId = preferences.getLong(fileKey + "_id", 0); int date = preferences.getInt(fileKey + "_time", 0); long uploadedSize = preferences.getLong(fileKey + "_uploaded", 0); - if (date != 0) { + if (isEncrypted) { + String ivString = preferences.getString(fileKey + "_iv", null); + String keyString = preferences.getString(fileKey + "_key", null); + if (ivString != null && keyString != null) { + key = Utilities.hexToBytes(keyString); + iv = Utilities.hexToBytes(ivString); + ivChange = new byte[32]; + System.arraycopy(iv, 0, ivChange, 0, 32); + } else { + rewrite = true; + } + } + if (!rewrite && date != 0) { if (isBigFile && date < currentTime - 60 * 60 * 24) { date = 0; } else if (!isBigFile && date < currentTime - 60 * 60 * 1.5f) { date = 0; } if (date != 0) { - if (isBigFile) { - uploadedSize = uploadedSize / (1024 * 1024) * (1024 * 1024); - } if (uploadedSize > 0) { currentUploaded = uploadedSize; - stream.skip(uploadedSize); currentPartNum = (int) (uploadedSize / uploadChunkSize); + if (!isBigFile) { + for (int b = 0; b < currentUploaded / uploadChunkSize; b++) { + int read = stream.read(readBuffer); + int toAdd = 0; + if (isEncrypted && read % 16 != 0) { + toAdd += 16 - read % 16; + } + ByteBufferDesc sendBuffer = BuffersStorage.getInstance().getFreeBuffer(read + toAdd); + if (read != uploadChunkSize || totalPartsCount == currentPartNum + 1) { + isLastPart = true; + } + sendBuffer.writeRaw(readBuffer, 0, read); + if (isEncrypted) { + for (int a = 0; a < toAdd; a++) { + sendBuffer.writeByte(0); + } + Utilities.aesIgeEncryption(sendBuffer.buffer, key, ivChange, true, true, 0, read + toAdd); + } + sendBuffer.rewind(); + mdEnc.update(sendBuffer.buffer); + BuffersStorage.getInstance().reuseFreeBuffer(sendBuffer); + } + } else { + stream.skip(uploadedSize); + if (isEncrypted) { + String ivcString = preferences.getString(fileKey + "_ivc", null); + if (ivcString != null) { + ivChange = Utilities.hexToBytes(ivcString); + } else { + rewrite = true; + currentUploaded = 0; + currentPartNum = 0; + } + } + } } else { rewrite = true; } @@ -166,34 +198,75 @@ public class FileUploadOperation { rewrite = true; } if (rewrite) { - preferences.edit().putInt(fileKey + "_time", currentTime).putLong(fileKey + "_size", totalFileSize).commit(); - }*/ + if (isEncrypted) { + iv = new byte[32]; + key = new byte[32]; + ivChange = new byte[32]; + Utilities.random.nextBytes(iv); + Utilities.random.nextBytes(key); + System.arraycopy(iv, 0, ivChange, 0, 32); + } + currentFileId = Utilities.random.nextLong(); + SharedPreferences.Editor editor = preferences.edit(); + editor.putInt(fileKey + "_time", currentTime); + editor.putLong(fileKey + "_size", totalFileSize); + editor.putLong(fileKey + "_id", currentFileId); + editor.remove(fileKey + "_uploaded"); + if (isEncrypted) { + editor.putString(fileKey + "_iv", Utilities.bytesToHex(iv)); + editor.putString(fileKey + "_ivc", Utilities.bytesToHex(ivChange)); + editor.putString(fileKey + "_key", Utilities.bytesToHex(key)); + } + editor.commit(); + + editor.putString(fileKey + "_key", Utilities.bytesToHex(key)); + } + + if (isEncrypted) { + try { + java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5"); + byte[] arr = new byte[64]; + System.arraycopy(key, 0, arr, 0, 32); + System.arraycopy(iv, 0, arr, 32, 32); + byte[] digest = md.digest(arr); + for (int a = 0; a < 4; a++) { + fingerprint |= ((digest[a] ^ digest[a + 4]) & 0xFF) << (a * 8); + } + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } } else { - /*if (saveInfoTimes >= 4) { + if (saveInfoTimes >= 4) { saveInfoTimes = 0; } - if (saveInfoTimes == 0) { + if (isBigFile && currentUploaded % (1024 * 1024) == 0 || !isBigFile && saveInfoTimes == 0) { SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("uploadinfo", Activity.MODE_PRIVATE); - preferences.edit().putLong(fileKey + "_uploaded", currentUploaded).commit(); + SharedPreferences.Editor editor = preferences.edit(); + editor.putLong(fileKey + "_uploaded", currentUploaded); + if (isEncrypted) { + editor.putString(fileKey + "_ivc", Utilities.bytesToHex(ivChange)); + } + editor.commit(); } - saveInfoTimes++;*/ + saveInfoTimes++; } - int readed = stream.read(readBuffer); + int read = stream.read(readBuffer); int toAdd = 0; - if (key != null && readed % 16 != 0) { - toAdd += 16 - readed % 16; + if (isEncrypted && read % 16 != 0) { + toAdd += 16 - read % 16; } - ByteBufferDesc sendBuffer = BuffersStorage.getInstance().getFreeBuffer(readed + toAdd); - if (readed != uploadChunkSize || totalPartsCount == currentPartNum + 1) { + ByteBufferDesc sendBuffer = BuffersStorage.getInstance().getFreeBuffer(read + toAdd); + if (read != uploadChunkSize || totalPartsCount == currentPartNum + 1) { isLastPart = true; } - sendBuffer.writeRaw(readBuffer, 0, readed); - if (key != null) { + sendBuffer.writeRaw(readBuffer, 0, read); + if (isEncrypted) { for (int a = 0; a < toAdd; a++) { sendBuffer.writeByte(0); } - Utilities.aesIgeEncryption(sendBuffer.buffer, key, ivChange, true, true, 0, readed + toAdd); + Utilities.aesIgeEncryption(sendBuffer.buffer, key, ivChange, true, true, 0, read + toAdd); } sendBuffer.rewind(); if (!isBigFile) { @@ -213,7 +286,7 @@ public class FileUploadOperation { req.bytes = sendBuffer; finalRequest = req; } - currentUploaded += readed; + currentUploaded += read; } catch (Exception e) { FileLog.e("tmessages", e); delegate.didFailedUploadingFile(this); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java b/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java index 2160506da..7903e7684 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java @@ -166,7 +166,7 @@ public class Utilities { public static String bytesToHex(byte[] bytes) { char[] hexChars = new char[bytes.length * 2]; int v; - for ( int j = 0; j < bytes.length; j++ ) { + for (int j = 0; j < bytes.length; j++) { v = bytes[j] & 0xFF; hexChars[j * 2] = hexArray[v >>> 4]; hexChars[j * 2 + 1] = hexArray[v & 0x0F]; @@ -174,6 +174,15 @@ public class Utilities { return new String(hexChars); } + public static byte[] hexToBytes(String hex) { + int len = hex.length(); + byte[] data = new byte[len / 2]; + for (int i = 0; i < len; i += 2) { + data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4) + Character.digit(hex.charAt(i + 1), 16)); + } + return data; + } + public static boolean isGoodPrime(byte[] prime, int g) { if (!(g >= 2 && g <= 7)) { return false;