2014-12-01 18:56:31 +01:00
/ *
* This is the source code of Telegram for Android v . 2 . 0 . x .
* It is licensed under GNU GPL v . 2 or later .
* You should have received a copy of the license in this archive ( see LICENSE ) .
*
2019-01-23 18:03:33 +01:00
* Copyright Nikolai Kudashov , 2013 - 2018 .
2014-12-01 18:56:31 +01:00
* /
2015-09-24 22:52:02 +02:00
package org.telegram.messenger ;
2014-12-01 18:56:31 +01:00
import android.app.Activity ;
import android.content.Context ;
2018-07-30 04:07:02 +02:00
import android.util.LongSparseArray ;
import android.util.SparseArray ;
2019-12-31 14:08:08 +01:00
import android.util.SparseIntArray ;
2014-12-01 18:56:31 +01:00
2016-10-11 13:57:01 +02:00
import org.telegram.SQLite.SQLiteCursor ;
2016-03-06 02:49:31 +01:00
import org.telegram.tgnet.AbstractSerializedData ;
2015-09-24 22:52:02 +02:00
import org.telegram.tgnet.ConnectionsManager ;
import org.telegram.tgnet.NativeByteBuffer ;
import org.telegram.tgnet.TLClassStore ;
import org.telegram.tgnet.TLObject ;
import org.telegram.tgnet.TLRPC ;
2017-03-31 01:58:05 +02:00
import org.telegram.ui.ActionBar.AlertDialog ;
2014-12-01 18:56:31 +01:00
import java.io.File ;
import java.math.BigInteger ;
import java.util.ArrayList ;
import java.util.Collections ;
2016-10-11 13:57:01 +02:00
import java.util.Locale ;
2014-12-01 18:56:31 +01:00
import java.util.concurrent.ConcurrentHashMap ;
2019-07-18 15:01:39 +02:00
public class SecretChatHelper extends BaseController {
2014-12-01 18:56:31 +01:00
2016-03-06 02:49:31 +01:00
public static class TL_decryptedMessageHolder extends TLObject {
public static int constructor = 0x555555F9 ;
public int date ;
public TLRPC . TL_decryptedMessageLayer layer ;
public TLRPC . EncryptedFile file ;
public boolean new_key_used ;
2017-12-08 18:35:59 +01:00
public int decryptedWithVersion ;
2016-03-06 02:49:31 +01:00
public void readParams ( AbstractSerializedData stream , boolean exception ) {
2017-12-08 18:35:59 +01:00
stream . readInt64 ( exception ) ;
2016-03-06 02:49:31 +01:00
date = stream . readInt32 ( exception ) ;
layer = TLRPC . TL_decryptedMessageLayer . TLdeserialize ( stream , stream . readInt32 ( exception ) , exception ) ;
if ( stream . readBool ( exception ) ) {
file = TLRPC . EncryptedFile . TLdeserialize ( stream , stream . readInt32 ( exception ) , exception ) ;
}
new_key_used = stream . readBool ( exception ) ;
}
public void serializeToStream ( AbstractSerializedData stream ) {
stream . writeInt32 ( constructor ) ;
2017-12-08 18:35:59 +01:00
stream . writeInt64 ( 0 ) ;
2016-03-06 02:49:31 +01:00
stream . writeInt32 ( date ) ;
layer . serializeToStream ( stream ) ;
stream . writeBool ( file ! = null ) ;
if ( file ! = null ) {
file . serializeToStream ( stream ) ;
}
stream . writeBool ( new_key_used ) ;
}
}
2019-07-18 15:01:39 +02:00
public static final int CURRENT_SECRET_CHAT_LAYER = 101 ;
2014-12-01 18:56:31 +01:00
2015-01-02 23:15:07 +01:00
private ArrayList < Integer > sendingNotifyLayer = new ArrayList < > ( ) ;
2018-07-30 04:07:02 +02:00
private SparseArray < ArrayList < TL_decryptedMessageHolder > > secretHolesQueue = new SparseArray < > ( ) ;
2019-12-31 14:08:08 +01:00
private SparseArray < ArrayList < TLRPC . Update > > pendingSecretMessages = new SparseArray < > ( ) ;
private SparseArray < SparseIntArray > requestedHoles = new SparseArray < > ( ) ;
2018-07-30 04:07:02 +02:00
private SparseArray < TLRPC . EncryptedChat > acceptingChats = new SparseArray < > ( ) ;
2015-01-02 23:15:07 +01:00
public ArrayList < TLRPC . Update > delayedEncryptedChatUpdates = new ArrayList < > ( ) ;
private ArrayList < Long > pendingEncMessagesToDelete = new ArrayList < > ( ) ;
2014-12-01 18:56:31 +01:00
private boolean startingSecretChat = false ;
2019-07-18 15:01:39 +02:00
private static volatile SecretChatHelper [ ] Instance = new SecretChatHelper [ UserConfig . MAX_ACCOUNT_COUNT ] ;
2015-05-21 23:27:27 +02:00
2018-07-30 04:07:02 +02:00
public static SecretChatHelper getInstance ( int num ) {
SecretChatHelper localInstance = Instance [ num ] ;
2014-12-01 18:56:31 +01:00
if ( localInstance = = null ) {
synchronized ( SecretChatHelper . class ) {
2018-07-30 04:07:02 +02:00
localInstance = Instance [ num ] ;
2014-12-01 18:56:31 +01:00
if ( localInstance = = null ) {
2018-07-30 04:07:02 +02:00
Instance [ num ] = localInstance = new SecretChatHelper ( num ) ;
2014-12-01 18:56:31 +01:00
}
}
}
return localInstance ;
}
2018-07-30 04:07:02 +02:00
public SecretChatHelper ( int instance ) {
2019-07-18 15:01:39 +02:00
super ( instance ) ;
2018-07-30 04:07:02 +02:00
}
2016-06-24 12:27:15 +02:00
public void cleanup ( ) {
2014-12-01 18:56:31 +01:00
sendingNotifyLayer . clear ( ) ;
acceptingChats . clear ( ) ;
secretHolesQueue . clear ( ) ;
2019-12-31 14:08:08 +01:00
pendingSecretMessages . clear ( ) ;
requestedHoles . clear ( ) ;
2014-12-01 18:56:31 +01:00
delayedEncryptedChatUpdates . clear ( ) ;
pendingEncMessagesToDelete . clear ( ) ;
startingSecretChat = false ;
}
protected void processPendingEncMessages ( ) {
if ( ! pendingEncMessagesToDelete . isEmpty ( ) ) {
2016-03-06 02:49:31 +01:00
final ArrayList < Long > pendingEncMessagesToDeleteCopy = new ArrayList < > ( pendingEncMessagesToDelete ) ;
2018-08-27 10:33:11 +02:00
AndroidUtilities . runOnUIThread ( ( ) - > {
for ( int a = 0 ; a < pendingEncMessagesToDeleteCopy . size ( ) ; a + + ) {
2019-07-18 15:01:39 +02:00
MessageObject messageObject = getMessagesController ( ) . dialogMessagesByRandomIds . get ( pendingEncMessagesToDeleteCopy . get ( a ) ) ;
2018-08-27 10:33:11 +02:00
if ( messageObject ! = null ) {
messageObject . deleted = true ;
2016-03-06 02:49:31 +01:00
}
}
} ) ;
2015-01-02 23:15:07 +01:00
ArrayList < Long > arr = new ArrayList < > ( pendingEncMessagesToDelete ) ;
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . markMessagesAsDeletedByRandoms ( arr ) ;
2014-12-01 18:56:31 +01:00
pendingEncMessagesToDelete . clear ( ) ;
}
}
private TLRPC . TL_messageService createServiceSecretMessage ( final TLRPC . EncryptedChat encryptedChat , TLRPC . DecryptedMessageAction decryptedMessage ) {
TLRPC . TL_messageService newMsg = new TLRPC . TL_messageService ( ) ;
newMsg . action = new TLRPC . TL_messageEncryptedAction ( ) ;
newMsg . action . encryptedAction = decryptedMessage ;
2019-07-18 15:01:39 +02:00
newMsg . local_id = newMsg . id = getUserConfig ( ) . getNewMessageId ( ) ;
newMsg . from_id = getUserConfig ( ) . getClientUserId ( ) ;
2015-11-26 22:04:02 +01:00
newMsg . unread = true ;
newMsg . out = true ;
newMsg . flags = TLRPC . MESSAGE_FLAG_HAS_FROM_ID ;
2015-05-21 23:27:27 +02:00
newMsg . dialog_id = ( ( long ) encryptedChat . id ) < < 32 ;
2014-12-01 18:56:31 +01:00
newMsg . to_id = new TLRPC . TL_peerUser ( ) ;
newMsg . send_state = MessageObject . MESSAGE_SEND_STATE_SENDING ;
2019-07-18 15:01:39 +02:00
if ( encryptedChat . participant_id = = getUserConfig ( ) . getClientUserId ( ) ) {
2014-12-01 18:56:31 +01:00
newMsg . to_id . user_id = encryptedChat . admin_id ;
} else {
newMsg . to_id . user_id = encryptedChat . participant_id ;
}
if ( decryptedMessage instanceof TLRPC . TL_decryptedMessageActionScreenshotMessages | | decryptedMessage instanceof TLRPC . TL_decryptedMessageActionSetMessageTTL ) {
2019-07-18 15:01:39 +02:00
newMsg . date = getConnectionsManager ( ) . getCurrentTime ( ) ;
2014-12-01 18:56:31 +01:00
} else {
newMsg . date = 0 ;
}
2019-07-18 15:01:39 +02:00
newMsg . random_id = getSendMessagesHelper ( ) . getNextRandomId ( ) ;
getUserConfig ( ) . saveConfig ( false ) ;
2014-12-01 18:56:31 +01:00
2015-01-02 23:15:07 +01:00
ArrayList < TLRPC . Message > arr = new ArrayList < > ( ) ;
2014-12-01 18:56:31 +01:00
arr . add ( newMsg ) ;
2019-09-10 12:56:11 +02:00
getMessagesStorage ( ) . putMessages ( arr , false , true , true , 0 , false ) ;
2014-12-01 18:56:31 +01:00
return newMsg ;
}
public void sendMessagesReadMessage ( TLRPC . EncryptedChat encryptedChat , ArrayList < Long > random_ids , TLRPC . Message resendMessage ) {
if ( ! ( encryptedChat instanceof TLRPC . TL_encryptedChat ) ) {
return ;
}
2017-03-31 01:58:05 +02:00
TLRPC . TL_decryptedMessageService reqSend = new TLRPC . TL_decryptedMessageService ( ) ;
2015-05-21 23:27:27 +02:00
TLRPC . Message message ;
2014-12-01 18:56:31 +01:00
if ( resendMessage ! = null ) {
message = resendMessage ;
reqSend . action = message . action . encryptedAction ;
} else {
reqSend . action = new TLRPC . TL_decryptedMessageActionReadMessages ( ) ;
reqSend . action . random_ids = random_ids ;
message = createServiceSecretMessage ( encryptedChat , reqSend . action ) ;
}
reqSend . random_id = message . random_id ;
2016-05-25 23:49:47 +02:00
performSendEncryptedRequest ( reqSend , message , encryptedChat , null , null , null ) ;
2014-12-01 18:56:31 +01:00
}
protected void processUpdateEncryption ( TLRPC . TL_updateEncryption update , ConcurrentHashMap < Integer , TLRPC . User > usersDict ) {
final TLRPC . EncryptedChat newChat = update . chat ;
2015-05-21 23:27:27 +02:00
long dialog_id = ( ( long ) newChat . id ) < < 32 ;
2019-07-18 15:01:39 +02:00
TLRPC . EncryptedChat existingChat = getMessagesController ( ) . getEncryptedChatDB ( newChat . id , false ) ;
2014-12-01 18:56:31 +01:00
if ( newChat instanceof TLRPC . TL_encryptedChatRequested & & existingChat = = null ) {
int user_id = newChat . participant_id ;
2019-07-18 15:01:39 +02:00
if ( user_id = = getUserConfig ( ) . getClientUserId ( ) ) {
2014-12-01 18:56:31 +01:00
user_id = newChat . admin_id ;
}
2019-07-18 15:01:39 +02:00
TLRPC . User user = getMessagesController ( ) . getUser ( user_id ) ;
2014-12-01 18:56:31 +01:00
if ( user = = null ) {
user = usersDict . get ( user_id ) ;
}
newChat . user_id = user_id ;
2019-05-14 14:08:05 +02:00
final TLRPC . Dialog dialog = new TLRPC . TL_dialog ( ) ;
2014-12-01 18:56:31 +01:00
dialog . id = dialog_id ;
dialog . unread_count = 0 ;
dialog . top_message = 0 ;
dialog . last_message_date = update . date ;
2019-07-18 15:01:39 +02:00
getMessagesController ( ) . putEncryptedChat ( newChat , false ) ;
2018-08-27 10:33:11 +02:00
AndroidUtilities . runOnUIThread ( ( ) - > {
2019-07-18 15:01:39 +02:00
getMessagesController ( ) . dialogs_dict . put ( dialog . id , dialog ) ;
getMessagesController ( ) . allDialogs . add ( dialog ) ;
getMessagesController ( ) . sortDialogs ( null ) ;
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . dialogsNeedReload ) ;
2014-12-01 18:56:31 +01:00
} ) ;
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . putEncryptedChat ( newChat , user , dialog ) ;
2018-07-30 04:07:02 +02:00
acceptSecretChat ( newChat ) ;
2014-12-01 18:56:31 +01:00
} else if ( newChat instanceof TLRPC . TL_encryptedChat ) {
2019-05-14 14:08:05 +02:00
if ( existingChat instanceof TLRPC . TL_encryptedChatWaiting & & ( existingChat . auth_key = = null | | existingChat . auth_key . length = = 1 ) ) {
2014-12-01 18:56:31 +01:00
newChat . a_or_b = existingChat . a_or_b ;
newChat . user_id = existingChat . user_id ;
2016-10-11 13:57:01 +02:00
processAcceptedSecretChat ( newChat ) ;
2014-12-01 18:56:31 +01:00
} else if ( existingChat = = null & & startingSecretChat ) {
delayedEncryptedChatUpdates . add ( update ) ;
}
} else {
final TLRPC . EncryptedChat exist = existingChat ;
if ( exist ! = null ) {
newChat . user_id = exist . user_id ;
newChat . auth_key = exist . auth_key ;
newChat . key_create_date = exist . key_create_date ;
newChat . key_use_count_in = exist . key_use_count_in ;
newChat . key_use_count_out = exist . key_use_count_out ;
newChat . ttl = exist . ttl ;
newChat . seq_in = exist . seq_in ;
newChat . seq_out = exist . seq_out ;
2017-03-31 01:58:05 +02:00
newChat . admin_id = exist . admin_id ;
2017-12-08 18:35:59 +01:00
newChat . mtproto_seq = exist . mtproto_seq ;
2014-12-01 18:56:31 +01:00
}
2018-08-27 10:33:11 +02:00
AndroidUtilities . runOnUIThread ( ( ) - > {
if ( exist ! = null ) {
2019-07-18 15:01:39 +02:00
getMessagesController ( ) . putEncryptedChat ( newChat , false ) ;
2014-12-01 18:56:31 +01:00
}
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . updateEncryptedChat ( newChat ) ;
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . encryptedChatUpdated , newChat ) ;
2014-12-01 18:56:31 +01:00
} ) ;
}
}
public void sendMessagesDeleteMessage ( TLRPC . EncryptedChat encryptedChat , ArrayList < Long > random_ids , TLRPC . Message resendMessage ) {
if ( ! ( encryptedChat instanceof TLRPC . TL_encryptedChat ) ) {
return ;
}
2017-03-31 01:58:05 +02:00
TLRPC . TL_decryptedMessageService reqSend = new TLRPC . TL_decryptedMessageService ( ) ;
2015-05-21 23:27:27 +02:00
TLRPC . Message message ;
2014-12-01 18:56:31 +01:00
if ( resendMessage ! = null ) {
message = resendMessage ;
reqSend . action = message . action . encryptedAction ;
} else {
reqSend . action = new TLRPC . TL_decryptedMessageActionDeleteMessages ( ) ;
reqSend . action . random_ids = random_ids ;
message = createServiceSecretMessage ( encryptedChat , reqSend . action ) ;
}
reqSend . random_id = message . random_id ;
2016-05-25 23:49:47 +02:00
performSendEncryptedRequest ( reqSend , message , encryptedChat , null , null , null ) ;
2014-12-01 18:56:31 +01:00
}
public void sendClearHistoryMessage ( TLRPC . EncryptedChat encryptedChat , TLRPC . Message resendMessage ) {
if ( ! ( encryptedChat instanceof TLRPC . TL_encryptedChat ) ) {
return ;
}
2017-03-31 01:58:05 +02:00
TLRPC . TL_decryptedMessageService reqSend = new TLRPC . TL_decryptedMessageService ( ) ;
2015-05-21 23:27:27 +02:00
TLRPC . Message message ;
2014-12-01 18:56:31 +01:00
if ( resendMessage ! = null ) {
message = resendMessage ;
reqSend . action = message . action . encryptedAction ;
} else {
reqSend . action = new TLRPC . TL_decryptedMessageActionFlushHistory ( ) ;
message = createServiceSecretMessage ( encryptedChat , reqSend . action ) ;
}
reqSend . random_id = message . random_id ;
2016-05-25 23:49:47 +02:00
performSendEncryptedRequest ( reqSend , message , encryptedChat , null , null , null ) ;
2014-12-01 18:56:31 +01:00
}
public void sendNotifyLayerMessage ( final TLRPC . EncryptedChat encryptedChat , TLRPC . Message resendMessage ) {
if ( ! ( encryptedChat instanceof TLRPC . TL_encryptedChat ) ) {
return ;
}
if ( sendingNotifyLayer . contains ( encryptedChat . id ) ) {
return ;
}
sendingNotifyLayer . add ( encryptedChat . id ) ;
2017-03-31 01:58:05 +02:00
TLRPC . TL_decryptedMessageService reqSend = new TLRPC . TL_decryptedMessageService ( ) ;
2015-05-21 23:27:27 +02:00
TLRPC . Message message ;
2014-12-01 18:56:31 +01:00
if ( resendMessage ! = null ) {
message = resendMessage ;
reqSend . action = message . action . encryptedAction ;
} else {
reqSend . action = new TLRPC . TL_decryptedMessageActionNotifyLayer ( ) ;
reqSend . action . layer = CURRENT_SECRET_CHAT_LAYER ;
message = createServiceSecretMessage ( encryptedChat , reqSend . action ) ;
}
reqSend . random_id = message . random_id ;
2016-05-25 23:49:47 +02:00
performSendEncryptedRequest ( reqSend , message , encryptedChat , null , null , null ) ;
2014-12-01 18:56:31 +01:00
}
public void sendRequestKeyMessage ( final TLRPC . EncryptedChat encryptedChat , TLRPC . Message resendMessage ) {
if ( ! ( encryptedChat instanceof TLRPC . TL_encryptedChat ) ) {
return ;
}
2017-03-31 01:58:05 +02:00
TLRPC . TL_decryptedMessageService reqSend = new TLRPC . TL_decryptedMessageService ( ) ;
2015-05-21 23:27:27 +02:00
TLRPC . Message message ;
2014-12-01 18:56:31 +01:00
if ( resendMessage ! = null ) {
message = resendMessage ;
reqSend . action = message . action . encryptedAction ;
} else {
reqSend . action = new TLRPC . TL_decryptedMessageActionRequestKey ( ) ;
reqSend . action . exchange_id = encryptedChat . exchange_id ;
reqSend . action . g_a = encryptedChat . g_a ;
message = createServiceSecretMessage ( encryptedChat , reqSend . action ) ;
}
reqSend . random_id = message . random_id ;
2016-05-25 23:49:47 +02:00
performSendEncryptedRequest ( reqSend , message , encryptedChat , null , null , null ) ;
2014-12-01 18:56:31 +01:00
}
public void sendAcceptKeyMessage ( final TLRPC . EncryptedChat encryptedChat , TLRPC . Message resendMessage ) {
if ( ! ( encryptedChat instanceof TLRPC . TL_encryptedChat ) ) {
return ;
}
2017-03-31 01:58:05 +02:00
TLRPC . TL_decryptedMessageService reqSend = new TLRPC . TL_decryptedMessageService ( ) ;
2015-05-21 23:27:27 +02:00
TLRPC . Message message ;
2014-12-01 18:56:31 +01:00
if ( resendMessage ! = null ) {
message = resendMessage ;
reqSend . action = message . action . encryptedAction ;
} else {
reqSend . action = new TLRPC . TL_decryptedMessageActionAcceptKey ( ) ;
reqSend . action . exchange_id = encryptedChat . exchange_id ;
reqSend . action . key_fingerprint = encryptedChat . future_key_fingerprint ;
reqSend . action . g_b = encryptedChat . g_a_or_b ;
message = createServiceSecretMessage ( encryptedChat , reqSend . action ) ;
}
reqSend . random_id = message . random_id ;
2016-05-25 23:49:47 +02:00
performSendEncryptedRequest ( reqSend , message , encryptedChat , null , null , null ) ;
2014-12-01 18:56:31 +01:00
}
public void sendCommitKeyMessage ( final TLRPC . EncryptedChat encryptedChat , TLRPC . Message resendMessage ) {
if ( ! ( encryptedChat instanceof TLRPC . TL_encryptedChat ) ) {
return ;
}
2017-03-31 01:58:05 +02:00
TLRPC . TL_decryptedMessageService reqSend = new TLRPC . TL_decryptedMessageService ( ) ;
2015-05-21 23:27:27 +02:00
TLRPC . Message message ;
2014-12-01 18:56:31 +01:00
if ( resendMessage ! = null ) {
message = resendMessage ;
reqSend . action = message . action . encryptedAction ;
} else {
reqSend . action = new TLRPC . TL_decryptedMessageActionCommitKey ( ) ;
reqSend . action . exchange_id = encryptedChat . exchange_id ;
reqSend . action . key_fingerprint = encryptedChat . future_key_fingerprint ;
message = createServiceSecretMessage ( encryptedChat , reqSend . action ) ;
}
reqSend . random_id = message . random_id ;
2016-05-25 23:49:47 +02:00
performSendEncryptedRequest ( reqSend , message , encryptedChat , null , null , null ) ;
2014-12-01 18:56:31 +01:00
}
public void sendAbortKeyMessage ( final TLRPC . EncryptedChat encryptedChat , TLRPC . Message resendMessage , long excange_id ) {
if ( ! ( encryptedChat instanceof TLRPC . TL_encryptedChat ) ) {
return ;
}
2017-03-31 01:58:05 +02:00
TLRPC . TL_decryptedMessageService reqSend = new TLRPC . TL_decryptedMessageService ( ) ;
2015-05-21 23:27:27 +02:00
TLRPC . Message message ;
2014-12-01 18:56:31 +01:00
if ( resendMessage ! = null ) {
message = resendMessage ;
reqSend . action = message . action . encryptedAction ;
} else {
reqSend . action = new TLRPC . TL_decryptedMessageActionAbortKey ( ) ;
reqSend . action . exchange_id = excange_id ;
message = createServiceSecretMessage ( encryptedChat , reqSend . action ) ;
}
reqSend . random_id = message . random_id ;
2016-05-25 23:49:47 +02:00
performSendEncryptedRequest ( reqSend , message , encryptedChat , null , null , null ) ;
2014-12-01 18:56:31 +01:00
}
public void sendNoopMessage ( final TLRPC . EncryptedChat encryptedChat , TLRPC . Message resendMessage ) {
if ( ! ( encryptedChat instanceof TLRPC . TL_encryptedChat ) ) {
return ;
}
2017-03-31 01:58:05 +02:00
TLRPC . TL_decryptedMessageService reqSend = new TLRPC . TL_decryptedMessageService ( ) ;
2015-05-21 23:27:27 +02:00
TLRPC . Message message ;
2014-12-01 18:56:31 +01:00
if ( resendMessage ! = null ) {
message = resendMessage ;
reqSend . action = message . action . encryptedAction ;
} else {
reqSend . action = new TLRPC . TL_decryptedMessageActionNoop ( ) ;
message = createServiceSecretMessage ( encryptedChat , reqSend . action ) ;
}
reqSend . random_id = message . random_id ;
2016-05-25 23:49:47 +02:00
performSendEncryptedRequest ( reqSend , message , encryptedChat , null , null , null ) ;
2014-12-01 18:56:31 +01:00
}
2019-12-31 14:08:08 +01:00
public void sendResendMessage ( final TLRPC . EncryptedChat encryptedChat , int start , int end , TLRPC . Message resendMessage ) {
if ( ! ( encryptedChat instanceof TLRPC . TL_encryptedChat ) ) {
return ;
}
SparseIntArray array = requestedHoles . get ( encryptedChat . id ) ;
if ( array ! = null & & array . indexOfKey ( start ) > = 0 ) {
return ;
}
if ( array = = null ) {
array = new SparseIntArray ( ) ;
requestedHoles . put ( encryptedChat . id , array ) ;
}
array . put ( start , end ) ;
TLRPC . TL_decryptedMessageService reqSend = new TLRPC . TL_decryptedMessageService ( ) ;
TLRPC . Message message ;
if ( resendMessage ! = null ) {
message = resendMessage ;
reqSend . action = message . action . encryptedAction ;
} else {
reqSend . action = new TLRPC . TL_decryptedMessageActionResend ( ) ;
reqSend . action . start_seq_no = start ;
reqSend . action . end_seq_no = end ;
message = createServiceSecretMessage ( encryptedChat , reqSend . action ) ;
}
reqSend . random_id = message . random_id ;
performSendEncryptedRequest ( reqSend , message , encryptedChat , null , null , null ) ;
}
2014-12-01 18:56:31 +01:00
public void sendTTLMessage ( TLRPC . EncryptedChat encryptedChat , TLRPC . Message resendMessage ) {
if ( ! ( encryptedChat instanceof TLRPC . TL_encryptedChat ) ) {
return ;
}
2017-03-31 01:58:05 +02:00
TLRPC . TL_decryptedMessageService reqSend = new TLRPC . TL_decryptedMessageService ( ) ;
2015-05-21 23:27:27 +02:00
TLRPC . Message message ;
2014-12-01 18:56:31 +01:00
if ( resendMessage ! = null ) {
message = resendMessage ;
reqSend . action = message . action . encryptedAction ;
} else {
reqSend . action = new TLRPC . TL_decryptedMessageActionSetMessageTTL ( ) ;
reqSend . action . ttl_seconds = encryptedChat . ttl ;
message = createServiceSecretMessage ( encryptedChat , reqSend . action ) ;
2018-07-30 04:07:02 +02:00
MessageObject newMsgObj = new MessageObject ( currentAccount , message , false ) ;
2014-12-01 18:56:31 +01:00
newMsgObj . messageOwner . send_state = MessageObject . MESSAGE_SEND_STATE_SENDING ;
2015-01-02 23:15:07 +01:00
ArrayList < MessageObject > objArr = new ArrayList < > ( ) ;
2014-12-01 18:56:31 +01:00
objArr . add ( newMsgObj ) ;
2019-09-10 12:56:11 +02:00
getMessagesController ( ) . updateInterfaceWithMessages ( message . dialog_id , objArr , false ) ;
2019-07-18 15:01:39 +02:00
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . dialogsNeedReload ) ;
2014-12-01 18:56:31 +01:00
}
reqSend . random_id = message . random_id ;
2016-05-25 23:49:47 +02:00
performSendEncryptedRequest ( reqSend , message , encryptedChat , null , null , null ) ;
2014-12-01 18:56:31 +01:00
}
public void sendScreenshotMessage ( TLRPC . EncryptedChat encryptedChat , ArrayList < Long > random_ids , TLRPC . Message resendMessage ) {
if ( ! ( encryptedChat instanceof TLRPC . TL_encryptedChat ) ) {
return ;
}
2017-03-31 01:58:05 +02:00
TLRPC . TL_decryptedMessageService reqSend = new TLRPC . TL_decryptedMessageService ( ) ;
2014-12-01 18:56:31 +01:00
2015-05-21 23:27:27 +02:00
TLRPC . Message message ;
2014-12-01 18:56:31 +01:00
if ( resendMessage ! = null ) {
message = resendMessage ;
reqSend . action = message . action . encryptedAction ;
} else {
reqSend . action = new TLRPC . TL_decryptedMessageActionScreenshotMessages ( ) ;
reqSend . action . random_ids = random_ids ;
message = createServiceSecretMessage ( encryptedChat , reqSend . action ) ;
2018-07-30 04:07:02 +02:00
MessageObject newMsgObj = new MessageObject ( currentAccount , message , false ) ;
2014-12-01 18:56:31 +01:00
newMsgObj . messageOwner . send_state = MessageObject . MESSAGE_SEND_STATE_SENDING ;
2015-01-02 23:15:07 +01:00
ArrayList < MessageObject > objArr = new ArrayList < > ( ) ;
2014-12-01 18:56:31 +01:00
objArr . add ( newMsgObj ) ;
2019-09-10 12:56:11 +02:00
getMessagesController ( ) . updateInterfaceWithMessages ( message . dialog_id , objArr , false ) ;
2019-07-18 15:01:39 +02:00
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . dialogsNeedReload ) ;
2014-12-01 18:56:31 +01:00
}
reqSend . random_id = message . random_id ;
2016-05-25 23:49:47 +02:00
performSendEncryptedRequest ( reqSend , message , encryptedChat , null , null , null ) ;
2014-12-01 18:56:31 +01:00
}
2016-05-25 23:49:47 +02:00
private void updateMediaPaths ( MessageObject newMsgObj , TLRPC . EncryptedFile file , TLRPC . DecryptedMessage decryptedMessage , String originalPath ) {
TLRPC . Message newMsg = newMsgObj . messageOwner ;
2014-12-01 18:56:31 +01:00
if ( file ! = null ) {
if ( newMsg . media instanceof TLRPC . TL_messageMediaPhoto & & newMsg . media . photo ! = null ) {
TLRPC . PhotoSize size = newMsg . media . photo . sizes . get ( newMsg . media . photo . sizes . size ( ) - 1 ) ;
String fileName = size . location . volume_id + " _ " + size . location . local_id ;
size . location = new TLRPC . TL_fileEncryptedLocation ( ) ;
size . location . key = decryptedMessage . media . key ;
size . location . iv = decryptedMessage . media . iv ;
size . location . dc_id = file . dc_id ;
size . location . volume_id = file . id ;
size . location . secret = file . access_hash ;
size . location . local_id = file . key_fingerprint ;
String fileName2 = size . location . volume_id + " _ " + size . location . local_id ;
2018-07-30 04:07:02 +02:00
File cacheFile = new File ( FileLoader . getDirectory ( FileLoader . MEDIA_DIR_CACHE ) , fileName + " .jpg " ) ;
2014-12-01 18:56:31 +01:00
File cacheFile2 = FileLoader . getPathToAttach ( size ) ;
cacheFile . renameTo ( cacheFile2 ) ;
2019-05-14 14:08:05 +02:00
ImageLoader . getInstance ( ) . replaceImageInCache ( fileName , fileName2 , ImageLocation . getForPhoto ( size , newMsg . media . photo ) , true ) ;
2015-01-02 23:15:07 +01:00
ArrayList < TLRPC . Message > arr = new ArrayList < > ( ) ;
2014-12-01 18:56:31 +01:00
arr . add ( newMsg ) ;
2019-09-10 12:56:11 +02:00
getMessagesStorage ( ) . putMessages ( arr , false , true , false , 0 , false ) ;
2014-12-01 18:56:31 +01:00
2019-07-18 15:01:39 +02:00
//getMessagesStorage().putSentFile(originalPath, newMsg.media.photo, 3);
2014-12-01 18:56:31 +01:00
} else if ( newMsg . media instanceof TLRPC . TL_messageMediaDocument & & newMsg . media . document ! = null ) {
TLRPC . Document document = newMsg . media . document ;
newMsg . media . document = new TLRPC . TL_documentEncrypted ( ) ;
newMsg . media . document . id = file . id ;
newMsg . media . document . access_hash = file . access_hash ;
newMsg . media . document . date = document . date ;
2015-01-02 23:15:07 +01:00
newMsg . media . document . attributes = document . attributes ;
2014-12-01 18:56:31 +01:00
newMsg . media . document . mime_type = document . mime_type ;
newMsg . media . document . size = file . size ;
newMsg . media . document . key = decryptedMessage . media . key ;
newMsg . media . document . iv = decryptedMessage . media . iv ;
2019-01-23 18:03:33 +01:00
newMsg . media . document . thumbs = document . thumbs ;
2014-12-01 18:56:31 +01:00
newMsg . media . document . dc_id = file . dc_id ;
2019-01-23 18:03:33 +01:00
if ( newMsg . media . document . thumbs . isEmpty ( ) ) {
TLRPC . PhotoSize thumb = new TLRPC . TL_photoSizeEmpty ( ) ;
thumb . type = " s " ;
newMsg . media . document . thumbs . add ( thumb ) ;
}
2014-12-01 18:56:31 +01:00
2018-07-30 04:07:02 +02:00
if ( newMsg . attachPath ! = null & & newMsg . attachPath . startsWith ( FileLoader . getDirectory ( FileLoader . MEDIA_DIR_CACHE ) . getAbsolutePath ( ) ) ) {
2014-12-01 18:56:31 +01:00
File cacheFile = new File ( newMsg . attachPath ) ;
File cacheFile2 = FileLoader . getPathToAttach ( newMsg . media . document ) ;
if ( cacheFile . renameTo ( cacheFile2 ) ) {
2016-05-25 23:49:47 +02:00
newMsgObj . mediaExists = newMsgObj . attachPathExists ;
newMsgObj . attachPathExists = false ;
2014-12-01 18:56:31 +01:00
newMsg . attachPath = " " ;
}
}
2015-01-02 23:15:07 +01:00
ArrayList < TLRPC . Message > arr = new ArrayList < > ( ) ;
2014-12-01 18:56:31 +01:00
arr . add ( newMsg ) ;
2019-09-10 12:56:11 +02:00
getMessagesStorage ( ) . putMessages ( arr , false , true , false , 0 , false ) ;
2014-12-01 18:56:31 +01:00
}
}
}
public static boolean isSecretVisibleMessage ( TLRPC . Message message ) {
return message . action instanceof TLRPC . TL_messageEncryptedAction & & ( message . action . encryptedAction instanceof TLRPC . TL_decryptedMessageActionScreenshotMessages | | message . action . encryptedAction instanceof TLRPC . TL_decryptedMessageActionSetMessageTTL ) ;
}
public static boolean isSecretInvisibleMessage ( TLRPC . Message message ) {
return message . action instanceof TLRPC . TL_messageEncryptedAction & & ! ( message . action . encryptedAction instanceof TLRPC . TL_decryptedMessageActionScreenshotMessages | | message . action . encryptedAction instanceof TLRPC . TL_decryptedMessageActionSetMessageTTL ) ;
}
2017-12-08 18:35:59 +01:00
protected void performSendEncryptedRequest ( final TLRPC . TL_messages_sendEncryptedMultiMedia req , final SendMessagesHelper . DelayedMessage message ) {
for ( int a = 0 ; a < req . files . size ( ) ; a + + ) {
performSendEncryptedRequest ( req . messages . get ( a ) , message . messages . get ( a ) , message . encryptedChat , req . files . get ( a ) , message . originalPaths . get ( a ) , message . messageObjects . get ( a ) ) ;
}
}
2016-05-25 23:49:47 +02:00
protected void performSendEncryptedRequest ( final TLRPC . DecryptedMessage req , final TLRPC . Message newMsgObj , final TLRPC . EncryptedChat chat , final TLRPC . InputEncryptedFile encryptedFile , final String originalPath , final MessageObject newMsg ) {
2014-12-01 18:56:31 +01:00
if ( req = = null | | chat . auth_key = = null | | chat instanceof TLRPC . TL_encryptedChatRequested | | chat instanceof TLRPC . TL_encryptedChatWaiting ) {
return ;
}
2019-09-10 12:56:11 +02:00
getSendMessagesHelper ( ) . putToSendingMessages ( newMsgObj , false ) ;
2018-08-27 10:33:11 +02:00
Utilities . stageQueue . postRunnable ( ( ) - > {
try {
TLObject toEncryptObject ;
TLRPC . TL_decryptedMessageLayer layer = new TLRPC . TL_decryptedMessageLayer ( ) ;
int myLayer = Math . max ( 46 , AndroidUtilities . getMyLayerVersion ( chat . layer ) ) ;
layer . layer = Math . min ( myLayer , Math . max ( 46 , AndroidUtilities . getPeerLayerVersion ( chat . layer ) ) ) ;
layer . message = req ;
layer . random_bytes = new byte [ 15 ] ;
Utilities . random . nextBytes ( layer . random_bytes ) ;
toEncryptObject = layer ;
int mtprotoVersion = AndroidUtilities . getPeerLayerVersion ( chat . layer ) > = 73 ? 2 : 1 ;
if ( chat . seq_in = = 0 & & chat . seq_out = = 0 ) {
2019-07-18 15:01:39 +02:00
if ( chat . admin_id = = getUserConfig ( ) . getClientUserId ( ) ) {
2018-08-27 10:33:11 +02:00
chat . seq_out = 1 ;
chat . seq_in = - 2 ;
} else {
chat . seq_in = - 1 ;
2017-03-31 01:58:05 +02:00
}
2018-08-27 10:33:11 +02:00
}
2014-12-01 18:56:31 +01:00
2018-08-27 10:33:11 +02:00
if ( newMsgObj . seq_in = = 0 & & newMsgObj . seq_out = = 0 ) {
layer . in_seq_no = chat . seq_in > 0 ? chat . seq_in : chat . seq_in + 2 ;
layer . out_seq_no = chat . seq_out ;
chat . seq_out + = 2 ;
if ( AndroidUtilities . getPeerLayerVersion ( chat . layer ) > = 20 ) {
if ( chat . key_create_date = = 0 ) {
2019-07-18 15:01:39 +02:00
chat . key_create_date = getConnectionsManager ( ) . getCurrentTime ( ) ;
2014-12-01 18:56:31 +01:00
}
2018-08-27 10:33:11 +02:00
chat . key_use_count_out + + ;
2019-07-18 15:01:39 +02:00
if ( ( chat . key_use_count_out > = 100 | | chat . key_create_date < getConnectionsManager ( ) . getCurrentTime ( ) - 60 * 60 * 24 * 7 ) & & chat . exchange_id = = 0 & & chat . future_key_fingerprint = = 0 ) {
2018-08-27 10:33:11 +02:00
requestNewSecretChatKey ( chat ) ;
2017-03-31 01:58:05 +02:00
}
2014-12-01 18:56:31 +01:00
}
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . updateEncryptedChatSeq ( chat , false ) ;
2018-08-27 10:33:11 +02:00
if ( newMsgObj ! = null ) {
newMsgObj . seq_in = layer . in_seq_no ;
newMsgObj . seq_out = layer . out_seq_no ;
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . setMessageSeq ( newMsgObj . id , newMsgObj . seq_in , newMsgObj . seq_out ) ;
2018-07-30 04:07:02 +02:00
}
2018-08-27 10:33:11 +02:00
} else {
layer . in_seq_no = newMsgObj . seq_in ;
layer . out_seq_no = newMsgObj . seq_out ;
}
if ( BuildVars . LOGS_ENABLED ) {
FileLog . d ( req + " send message with in_seq = " + layer . in_seq_no + " out_seq = " + layer . out_seq_no ) ;
}
2014-12-01 18:56:31 +01:00
2018-08-27 10:33:11 +02:00
int len = toEncryptObject . getObjectSize ( ) ;
NativeByteBuffer toEncrypt = new NativeByteBuffer ( 4 + len ) ;
toEncrypt . writeInt32 ( len ) ;
toEncryptObject . serializeToStream ( toEncrypt ) ;
2014-12-01 18:56:31 +01:00
2018-08-27 10:33:11 +02:00
len = toEncrypt . length ( ) ;
int extraLen = len % 16 ! = 0 ? 16 - len % 16 : 0 ;
if ( mtprotoVersion = = 2 ) {
extraLen + = ( 2 + Utilities . random . nextInt ( 3 ) ) * 16 ;
}
2017-12-08 18:35:59 +01:00
2018-08-27 10:33:11 +02:00
NativeByteBuffer dataForEncryption = new NativeByteBuffer ( len + extraLen ) ;
toEncrypt . position ( 0 ) ;
dataForEncryption . writeBytes ( toEncrypt ) ;
if ( extraLen ! = 0 ) {
byte [ ] b = new byte [ extraLen ] ;
Utilities . random . nextBytes ( b ) ;
dataForEncryption . writeBytes ( b ) ;
}
2017-12-08 18:35:59 +01:00
2018-08-27 10:33:11 +02:00
byte [ ] messageKey = new byte [ 16 ] ;
byte [ ] messageKeyFull ;
2019-07-18 15:01:39 +02:00
boolean incoming = mtprotoVersion = = 2 & & chat . admin_id ! = getUserConfig ( ) . getClientUserId ( ) ;
2018-08-27 10:33:11 +02:00
if ( mtprotoVersion = = 2 ) {
messageKeyFull = Utilities . computeSHA256 ( chat . auth_key , 88 + ( incoming ? 8 : 0 ) , 32 , dataForEncryption . buffer , 0 , dataForEncryption . buffer . limit ( ) ) ;
System . arraycopy ( messageKeyFull , 8 , messageKey , 0 , 16 ) ;
} else {
messageKeyFull = Utilities . computeSHA1 ( toEncrypt . buffer ) ;
System . arraycopy ( messageKeyFull , messageKeyFull . length - 16 , messageKey , 0 , 16 ) ;
}
toEncrypt . reuse ( ) ;
MessageKeyData keyData = MessageKeyData . generateMessageKeyData ( chat . auth_key , messageKey , incoming , mtprotoVersion ) ;
Utilities . aesIgeEncryption ( dataForEncryption . buffer , keyData . aesKey , keyData . aesIv , true , false , 0 , dataForEncryption . limit ( ) ) ;
NativeByteBuffer data = new NativeByteBuffer ( 8 + messageKey . length + dataForEncryption . length ( ) ) ;
dataForEncryption . position ( 0 ) ;
data . writeInt64 ( chat . key_fingerprint ) ;
data . writeBytes ( messageKey ) ;
data . writeBytes ( dataForEncryption ) ;
dataForEncryption . reuse ( ) ;
data . position ( 0 ) ;
TLObject reqToSend ;
if ( encryptedFile = = null ) {
if ( req instanceof TLRPC . TL_decryptedMessageService ) {
TLRPC . TL_messages_sendEncryptedService req2 = new TLRPC . TL_messages_sendEncryptedService ( ) ;
req2 . data = data ;
req2 . random_id = req . random_id ;
req2 . peer = new TLRPC . TL_inputEncryptedChat ( ) ;
req2 . peer . chat_id = chat . id ;
req2 . peer . access_hash = chat . access_hash ;
reqToSend = req2 ;
2014-12-01 18:56:31 +01:00
} else {
2018-08-27 10:33:11 +02:00
TLRPC . TL_messages_sendEncrypted req2 = new TLRPC . TL_messages_sendEncrypted ( ) ;
2014-12-01 18:56:31 +01:00
req2 . data = data ;
req2 . random_id = req . random_id ;
req2 . peer = new TLRPC . TL_inputEncryptedChat ( ) ;
req2 . peer . chat_id = chat . id ;
req2 . peer . access_hash = chat . access_hash ;
reqToSend = req2 ;
}
2018-08-27 10:33:11 +02:00
} else {
TLRPC . TL_messages_sendEncryptedFile req2 = new TLRPC . TL_messages_sendEncryptedFile ( ) ;
req2 . data = data ;
req2 . random_id = req . random_id ;
req2 . peer = new TLRPC . TL_inputEncryptedChat ( ) ;
req2 . peer . chat_id = chat . id ;
req2 . peer . access_hash = chat . access_hash ;
req2 . file = encryptedFile ;
reqToSend = req2 ;
}
2019-07-18 15:01:39 +02:00
getConnectionsManager ( ) . sendRequest ( reqToSend , ( response , error ) - > {
2018-08-27 10:33:11 +02:00
if ( error = = null ) {
if ( req . action instanceof TLRPC . TL_decryptedMessageActionNotifyLayer ) {
2019-07-18 15:01:39 +02:00
TLRPC . EncryptedChat currentChat = getMessagesController ( ) . getEncryptedChat ( chat . id ) ;
2018-08-27 10:33:11 +02:00
if ( currentChat = = null ) {
currentChat = chat ;
}
2016-03-06 02:49:31 +01:00
2018-08-27 10:33:11 +02:00
if ( currentChat . key_hash = = null ) {
currentChat . key_hash = AndroidUtilities . calcAuthKeyHash ( currentChat . auth_key ) ;
}
2016-03-06 02:49:31 +01:00
2018-08-27 10:33:11 +02:00
if ( AndroidUtilities . getPeerLayerVersion ( currentChat . layer ) > = 46 & & currentChat . key_hash . length = = 16 ) {
try {
byte [ ] sha256 = Utilities . computeSHA256 ( chat . auth_key , 0 , chat . auth_key . length ) ;
byte [ ] key_hash = new byte [ 36 ] ;
System . arraycopy ( chat . key_hash , 0 , key_hash , 0 , 16 ) ;
System . arraycopy ( sha256 , 0 , key_hash , 16 , 20 ) ;
currentChat . key_hash = key_hash ;
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . updateEncryptedChat ( currentChat ) ;
2018-08-27 10:33:11 +02:00
} catch ( Throwable e ) {
FileLog . e ( e ) ;
2016-03-06 02:49:31 +01:00
}
}
2018-08-27 10:33:11 +02:00
sendingNotifyLayer . remove ( ( Integer ) currentChat . id ) ;
currentChat . layer = AndroidUtilities . setMyLayerVersion ( currentChat . layer , CURRENT_SECRET_CHAT_LAYER ) ;
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . updateEncryptedChatLayer ( currentChat ) ;
2018-08-27 10:33:11 +02:00
}
}
if ( newMsgObj ! = null ) {
if ( error = = null ) {
final String attachPath = newMsgObj . attachPath ;
final TLRPC . messages_SentEncryptedMessage res = ( TLRPC . messages_SentEncryptedMessage ) response ;
if ( isSecretVisibleMessage ( newMsgObj ) ) {
newMsgObj . date = res . date ;
}
2019-02-08 03:30:32 +01:00
int existFlags ;
2018-08-27 10:33:11 +02:00
if ( newMsg ! = null & & res . file instanceof TLRPC . TL_encryptedFile ) {
updateMediaPaths ( newMsg , res . file , req , originalPath ) ;
2019-02-08 03:30:32 +01:00
existFlags = newMsg . getMediaExistanceFlags ( ) ;
} else {
existFlags = 0 ;
2018-08-27 10:33:11 +02:00
}
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > {
2018-08-27 10:33:11 +02:00
if ( isSecretInvisibleMessage ( newMsgObj ) ) {
res . date = 0 ;
}
2019-09-10 12:56:11 +02:00
getMessagesStorage ( ) . updateMessageStateAndId ( newMsgObj . random_id , newMsgObj . id , newMsgObj . id , res . date , false , 0 , 0 ) ;
2018-08-27 10:33:11 +02:00
AndroidUtilities . runOnUIThread ( ( ) - > {
newMsgObj . send_state = MessageObject . MESSAGE_SEND_STATE_SENT ;
2019-09-10 12:56:11 +02:00
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . messageReceivedByServer , newMsgObj . id , newMsgObj . id , newMsgObj , newMsgObj . dialog_id , 0L , existFlags , false ) ;
2019-07-18 15:01:39 +02:00
getSendMessagesHelper ( ) . processSentMessage ( newMsgObj . id ) ;
2018-08-27 10:33:11 +02:00
if ( MessageObject . isVideoMessage ( newMsgObj ) | | MessageObject . isNewGifMessage ( newMsgObj ) | | MessageObject . isRoundVideoMessage ( newMsgObj ) ) {
2019-07-18 15:01:39 +02:00
getSendMessagesHelper ( ) . stopVideoService ( attachPath ) ;
2016-03-06 02:49:31 +01:00
}
2019-09-10 12:56:11 +02:00
getSendMessagesHelper ( ) . removeFromSendingMessages ( newMsgObj . id , false ) ;
2018-08-27 10:33:11 +02:00
} ) ;
} ) ;
} else {
2019-09-10 12:56:11 +02:00
getMessagesStorage ( ) . markMessageAsSendError ( newMsgObj , false ) ;
2018-08-27 10:33:11 +02:00
AndroidUtilities . runOnUIThread ( ( ) - > {
newMsgObj . send_state = MessageObject . MESSAGE_SEND_STATE_SEND_ERROR ;
2019-07-18 15:01:39 +02:00
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . messageSendError , newMsgObj . id ) ;
getSendMessagesHelper ( ) . processSentMessage ( newMsgObj . id ) ;
2018-08-27 10:33:11 +02:00
if ( MessageObject . isVideoMessage ( newMsgObj ) | | MessageObject . isNewGifMessage ( newMsgObj ) | | MessageObject . isRoundVideoMessage ( newMsgObj ) ) {
2019-07-18 15:01:39 +02:00
getSendMessagesHelper ( ) . stopVideoService ( newMsgObj . attachPath ) ;
2016-03-06 02:49:31 +01:00
}
2019-09-10 12:56:11 +02:00
getSendMessagesHelper ( ) . removeFromSendingMessages ( newMsgObj . id , false ) ;
2018-08-27 10:33:11 +02:00
} ) ;
2014-12-01 18:56:31 +01:00
}
2018-08-27 10:33:11 +02:00
}
} , ConnectionsManager . RequestFlagInvokeAfter ) ;
} catch ( Exception e ) {
FileLog . e ( e ) ;
2014-12-01 18:56:31 +01:00
}
} ) ;
}
2016-04-22 15:49:00 +02:00
private void applyPeerLayer ( final TLRPC . EncryptedChat chat , int newPeerLayer ) {
int currentPeerLayer = AndroidUtilities . getPeerLayerVersion ( chat . layer ) ;
if ( newPeerLayer < = currentPeerLayer ) {
return ;
}
if ( chat . key_hash . length = = 16 & & currentPeerLayer > = 46 ) {
try {
byte [ ] sha256 = Utilities . computeSHA256 ( chat . auth_key , 0 , chat . auth_key . length ) ;
byte [ ] key_hash = new byte [ 36 ] ;
System . arraycopy ( chat . key_hash , 0 , key_hash , 0 , 16 ) ;
System . arraycopy ( sha256 , 0 , key_hash , 16 , 20 ) ;
chat . key_hash = key_hash ;
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . updateEncryptedChat ( chat ) ;
2016-04-22 15:49:00 +02:00
} catch ( Throwable e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2016-04-22 15:49:00 +02:00
}
}
chat . layer = AndroidUtilities . setPeerLayerVersion ( chat . layer , newPeerLayer ) ;
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . updateEncryptedChatLayer ( chat ) ;
2016-04-22 15:49:00 +02:00
if ( currentPeerLayer < CURRENT_SECRET_CHAT_LAYER ) {
sendNotifyLayerMessage ( chat , null ) ;
}
2019-07-18 15:01:39 +02:00
AndroidUtilities . runOnUIThread ( ( ) - > getNotificationCenter ( ) . postNotificationName ( NotificationCenter . encryptedChatUpdated , chat ) ) ;
2016-04-22 15:49:00 +02:00
}
2017-12-08 18:35:59 +01:00
public TLRPC . Message processDecryptedObject ( final TLRPC . EncryptedChat chat , final TLRPC . EncryptedFile file , int date , TLObject object , boolean new_key_used ) {
2014-12-01 18:56:31 +01:00
if ( object ! = null ) {
int from_id = chat . admin_id ;
2019-07-18 15:01:39 +02:00
if ( from_id = = getUserConfig ( ) . getClientUserId ( ) ) {
2014-12-01 18:56:31 +01:00
from_id = chat . participant_id ;
}
if ( AndroidUtilities . getPeerLayerVersion ( chat . layer ) > = 20 & & chat . exchange_id = = 0 & & chat . future_key_fingerprint = = 0 & & chat . key_use_count_in > = 120 ) {
requestNewSecretChatKey ( chat ) ;
}
if ( chat . exchange_id = = 0 & & chat . future_key_fingerprint ! = 0 & & ! new_key_used ) {
chat . future_auth_key = new byte [ 256 ] ;
chat . future_key_fingerprint = 0 ;
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . updateEncryptedChat ( chat ) ;
2014-12-01 18:56:31 +01:00
} else if ( chat . exchange_id ! = 0 & & new_key_used ) {
chat . key_fingerprint = chat . future_key_fingerprint ;
chat . auth_key = chat . future_auth_key ;
2019-07-18 15:01:39 +02:00
chat . key_create_date = getConnectionsManager ( ) . getCurrentTime ( ) ;
2014-12-01 18:56:31 +01:00
chat . future_auth_key = new byte [ 256 ] ;
chat . future_key_fingerprint = 0 ;
chat . key_use_count_in = 0 ;
chat . key_use_count_out = 0 ;
chat . exchange_id = 0 ;
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . updateEncryptedChat ( chat ) ;
2014-12-01 18:56:31 +01:00
}
if ( object instanceof TLRPC . TL_decryptedMessage ) {
2015-05-21 23:27:27 +02:00
TLRPC . TL_decryptedMessage decryptedMessage = ( TLRPC . TL_decryptedMessage ) object ;
TLRPC . TL_message newMessage ;
2014-12-01 18:56:31 +01:00
if ( AndroidUtilities . getPeerLayerVersion ( chat . layer ) > = 17 ) {
newMessage = new TLRPC . TL_message_secret ( ) ;
newMessage . ttl = decryptedMessage . ttl ;
2016-03-06 02:49:31 +01:00
newMessage . entities = decryptedMessage . entities ;
2014-12-01 18:56:31 +01:00
} else {
newMessage = new TLRPC . TL_message ( ) ;
newMessage . ttl = chat . ttl ;
}
newMessage . message = decryptedMessage . message ;
newMessage . date = date ;
2019-07-18 15:01:39 +02:00
newMessage . local_id = newMessage . id = getUserConfig ( ) . getNewMessageId ( ) ;
getUserConfig ( ) . saveConfig ( false ) ;
2014-12-01 18:56:31 +01:00
newMessage . from_id = from_id ;
newMessage . to_id = new TLRPC . TL_peerUser ( ) ;
2017-12-08 18:35:59 +01:00
newMessage . random_id = decryptedMessage . random_id ;
2019-07-18 15:01:39 +02:00
newMessage . to_id . user_id = getUserConfig ( ) . getClientUserId ( ) ;
2015-11-26 22:04:02 +01:00
newMessage . unread = true ;
newMessage . flags = TLRPC . MESSAGE_FLAG_HAS_MEDIA | TLRPC . MESSAGE_FLAG_HAS_FROM_ID ;
2016-03-06 02:49:31 +01:00
if ( decryptedMessage . via_bot_name ! = null & & decryptedMessage . via_bot_name . length ( ) > 0 ) {
newMessage . via_bot_name = decryptedMessage . via_bot_name ;
newMessage . flags | = TLRPC . MESSAGE_FLAG_HAS_BOT_ID ;
}
2017-12-08 18:35:59 +01:00
if ( decryptedMessage . grouped_id ! = 0 ) {
newMessage . grouped_id = decryptedMessage . grouped_id ;
newMessage . flags | = 131072 ;
}
2015-05-21 23:27:27 +02:00
newMessage . dialog_id = ( ( long ) chat . id ) < < 32 ;
2016-03-06 02:49:31 +01:00
if ( decryptedMessage . reply_to_random_id ! = 0 ) {
newMessage . reply_to_random_id = decryptedMessage . reply_to_random_id ;
newMessage . flags | = TLRPC . MESSAGE_FLAG_REPLY ;
}
if ( decryptedMessage . media = = null | | decryptedMessage . media instanceof TLRPC . TL_decryptedMessageMediaEmpty ) {
2014-12-01 18:56:31 +01:00
newMessage . media = new TLRPC . TL_messageMediaEmpty ( ) ;
2016-03-06 02:49:31 +01:00
} else if ( decryptedMessage . media instanceof TLRPC . TL_decryptedMessageMediaWebPage ) {
newMessage . media = new TLRPC . TL_messageMediaWebPage ( ) ;
newMessage . media . webpage = new TLRPC . TL_webPageUrlPending ( ) ;
newMessage . media . webpage . url = decryptedMessage . media . url ;
} else if ( decryptedMessage . media instanceof TLRPC . TL_decryptedMessageMediaContact ) {
2014-12-01 18:56:31 +01:00
newMessage . media = new TLRPC . TL_messageMediaContact ( ) ;
newMessage . media . last_name = decryptedMessage . media . last_name ;
newMessage . media . first_name = decryptedMessage . media . first_name ;
newMessage . media . phone_number = decryptedMessage . media . phone_number ;
newMessage . media . user_id = decryptedMessage . media . user_id ;
2018-07-30 04:07:02 +02:00
newMessage . media . vcard = " " ;
2014-12-01 18:56:31 +01:00
} else if ( decryptedMessage . media instanceof TLRPC . TL_decryptedMessageMediaGeoPoint ) {
newMessage . media = new TLRPC . TL_messageMediaGeo ( ) ;
newMessage . media . geo = new TLRPC . TL_geoPoint ( ) ;
newMessage . media . geo . lat = decryptedMessage . media . lat ;
newMessage . media . geo . _long = decryptedMessage . media . _long ;
} else if ( decryptedMessage . media instanceof TLRPC . TL_decryptedMessageMediaPhoto ) {
if ( decryptedMessage . media . key = = null | | decryptedMessage . media . key . length ! = 32 | | decryptedMessage . media . iv = = null | | decryptedMessage . media . iv . length ! = 32 ) {
return null ;
}
newMessage . media = new TLRPC . TL_messageMediaPhoto ( ) ;
2017-07-23 14:56:38 +02:00
newMessage . media . flags | = 3 ;
2018-07-30 04:07:02 +02:00
newMessage . message = decryptedMessage . media . caption ! = null ? decryptedMessage . media . caption : " " ;
2014-12-01 18:56:31 +01:00
newMessage . media . photo = new TLRPC . TL_photo ( ) ;
2019-01-23 18:03:33 +01:00
newMessage . media . photo . file_reference = new byte [ 0 ] ;
2014-12-01 18:56:31 +01:00
newMessage . media . photo . date = newMessage . date ;
2015-05-21 23:27:27 +02:00
byte [ ] thumb = ( ( TLRPC . TL_decryptedMessageMediaPhoto ) decryptedMessage . media ) . thumb ;
if ( thumb ! = null & & thumb . length ! = 0 & & thumb . length < = 6000 & & decryptedMessage . media . thumb_w < = 100 & & decryptedMessage . media . thumb_h < = 100 ) {
2014-12-01 18:56:31 +01:00
TLRPC . TL_photoCachedSize small = new TLRPC . TL_photoCachedSize ( ) ;
small . w = decryptedMessage . media . thumb_w ;
small . h = decryptedMessage . media . thumb_h ;
2015-05-21 23:27:27 +02:00
small . bytes = thumb ;
2014-12-01 18:56:31 +01:00
small . type = " s " ;
small . location = new TLRPC . TL_fileLocationUnavailable ( ) ;
newMessage . media . photo . sizes . add ( small ) ;
}
2017-12-08 18:35:59 +01:00
if ( newMessage . ttl ! = 0 ) {
newMessage . media . ttl_seconds = newMessage . ttl ;
2018-07-30 04:07:02 +02:00
newMessage . media . flags | = 4 ;
2017-12-08 18:35:59 +01:00
}
2014-12-01 18:56:31 +01:00
TLRPC . TL_photoSize big = new TLRPC . TL_photoSize ( ) ;
big . w = decryptedMessage . media . w ;
big . h = decryptedMessage . media . h ;
big . type = " x " ;
big . size = file . size ;
big . location = new TLRPC . TL_fileEncryptedLocation ( ) ;
big . location . key = decryptedMessage . media . key ;
big . location . iv = decryptedMessage . media . iv ;
big . location . dc_id = file . dc_id ;
big . location . volume_id = file . id ;
big . location . secret = file . access_hash ;
big . location . local_id = file . key_fingerprint ;
newMessage . media . photo . sizes . add ( big ) ;
} else if ( decryptedMessage . media instanceof TLRPC . TL_decryptedMessageMediaVideo ) {
if ( decryptedMessage . media . key = = null | | decryptedMessage . media . key . length ! = 32 | | decryptedMessage . media . iv = = null | | decryptedMessage . media . iv . length ! = 32 ) {
return null ;
}
2016-03-06 02:49:31 +01:00
newMessage . media = new TLRPC . TL_messageMediaDocument ( ) ;
2017-07-23 14:56:38 +02:00
newMessage . media . flags | = 3 ;
2016-03-06 02:49:31 +01:00
newMessage . media . document = new TLRPC . TL_documentEncrypted ( ) ;
newMessage . media . document . key = decryptedMessage . media . key ;
newMessage . media . document . iv = decryptedMessage . media . iv ;
newMessage . media . document . dc_id = file . dc_id ;
2018-07-30 04:07:02 +02:00
newMessage . message = decryptedMessage . media . caption ! = null ? decryptedMessage . media . caption : " " ;
2016-03-06 02:49:31 +01:00
newMessage . media . document . date = date ;
newMessage . media . document . size = file . size ;
newMessage . media . document . id = file . id ;
newMessage . media . document . access_hash = file . access_hash ;
newMessage . media . document . mime_type = decryptedMessage . media . mime_type ;
if ( newMessage . media . document . mime_type = = null ) {
newMessage . media . document . mime_type = " video/mp4 " ;
}
2015-05-21 23:27:27 +02:00
byte [ ] thumb = ( ( TLRPC . TL_decryptedMessageMediaVideo ) decryptedMessage . media ) . thumb ;
2019-01-23 18:03:33 +01:00
TLRPC . PhotoSize photoSize ;
2015-05-21 23:27:27 +02:00
if ( thumb ! = null & & thumb . length ! = 0 & & thumb . length < = 6000 & & decryptedMessage . media . thumb_w < = 100 & & decryptedMessage . media . thumb_h < = 100 ) {
2019-01-23 18:03:33 +01:00
photoSize = new TLRPC . TL_photoCachedSize ( ) ;
photoSize . bytes = thumb ;
photoSize . w = decryptedMessage . media . thumb_w ;
photoSize . h = decryptedMessage . media . thumb_h ;
photoSize . type = " s " ;
photoSize . location = new TLRPC . TL_fileLocationUnavailable ( ) ;
2014-12-01 18:56:31 +01:00
} else {
2019-01-23 18:03:33 +01:00
photoSize = new TLRPC . TL_photoSizeEmpty ( ) ;
photoSize . type = " s " ;
2014-12-01 18:56:31 +01:00
}
2019-01-23 18:03:33 +01:00
newMessage . media . document . thumbs . add ( photoSize ) ;
newMessage . media . document . flags | = 1 ;
2016-03-06 02:49:31 +01:00
TLRPC . TL_documentAttributeVideo attributeVideo = new TLRPC . TL_documentAttributeVideo ( ) ;
attributeVideo . w = decryptedMessage . media . w ;
attributeVideo . h = decryptedMessage . media . h ;
attributeVideo . duration = decryptedMessage . media . duration ;
2018-07-30 04:07:02 +02:00
attributeVideo . supports_streaming = false ;
2016-03-06 02:49:31 +01:00
newMessage . media . document . attributes . add ( attributeVideo ) ;
2014-12-01 18:56:31 +01:00
if ( newMessage . ttl ! = 0 ) {
2017-12-08 18:35:59 +01:00
newMessage . media . ttl_seconds = newMessage . ttl ;
2018-07-30 04:07:02 +02:00
newMessage . media . flags | = 4 ;
}
if ( newMessage . ttl ! = 0 ) {
newMessage . ttl = Math . max ( decryptedMessage . media . duration + 1 , newMessage . ttl ) ;
2014-12-01 18:56:31 +01:00
}
} else if ( decryptedMessage . media instanceof TLRPC . TL_decryptedMessageMediaDocument ) {
if ( decryptedMessage . media . key = = null | | decryptedMessage . media . key . length ! = 32 | | decryptedMessage . media . iv = = null | | decryptedMessage . media . iv . length ! = 32 ) {
return null ;
}
newMessage . media = new TLRPC . TL_messageMediaDocument ( ) ;
2017-07-23 14:56:38 +02:00
newMessage . media . flags | = 3 ;
2018-07-30 04:07:02 +02:00
newMessage . message = decryptedMessage . media . caption ! = null ? decryptedMessage . media . caption : " " ;
2014-12-01 18:56:31 +01:00
newMessage . media . document = new TLRPC . TL_documentEncrypted ( ) ;
newMessage . media . document . id = file . id ;
newMessage . media . document . access_hash = file . access_hash ;
newMessage . media . document . date = date ;
2020-06-04 18:47:15 +02:00
newMessage . media . document . mime_type = decryptedMessage . media . mime_type ;
2016-03-06 02:49:31 +01:00
if ( decryptedMessage . media instanceof TLRPC . TL_decryptedMessageMediaDocument_layer8 ) {
TLRPC . TL_documentAttributeFilename fileName = new TLRPC . TL_documentAttributeFilename ( ) ;
fileName . file_name = decryptedMessage . media . file_name ;
newMessage . media . document . attributes . add ( fileName ) ;
} else {
newMessage . media . document . attributes = decryptedMessage . media . attributes ;
}
2016-05-25 23:49:47 +02:00
newMessage . media . document . size = decryptedMessage . media . size ! = 0 ? Math . min ( decryptedMessage . media . size , file . size ) : file . size ;
2014-12-01 18:56:31 +01:00
newMessage . media . document . key = decryptedMessage . media . key ;
newMessage . media . document . iv = decryptedMessage . media . iv ;
2015-10-29 18:10:07 +01:00
if ( newMessage . media . document . mime_type = = null ) {
newMessage . media . document . mime_type = " " ;
2020-06-04 18:47:15 +02:00
} else if ( MessageObject . isAnimatedStickerDocument ( newMessage . media . document , true ) ) {
newMessage . media . document . mime_type = " application/x-bad_tgsticker " ;
2015-10-29 18:10:07 +01:00
}
2015-05-21 23:27:27 +02:00
byte [ ] thumb = ( ( TLRPC . TL_decryptedMessageMediaDocument ) decryptedMessage . media ) . thumb ;
2019-01-23 18:03:33 +01:00
TLRPC . PhotoSize photoSize ;
2015-05-21 23:27:27 +02:00
if ( thumb ! = null & & thumb . length ! = 0 & & thumb . length < = 6000 & & decryptedMessage . media . thumb_w < = 100 & & decryptedMessage . media . thumb_h < = 100 ) {
2019-01-23 18:03:33 +01:00
photoSize = new TLRPC . TL_photoCachedSize ( ) ;
photoSize . bytes = thumb ;
photoSize . w = decryptedMessage . media . thumb_w ;
photoSize . h = decryptedMessage . media . thumb_h ;
photoSize . type = " s " ;
photoSize . location = new TLRPC . TL_fileLocationUnavailable ( ) ;
2014-12-01 18:56:31 +01:00
} else {
2019-01-23 18:03:33 +01:00
photoSize = new TLRPC . TL_photoSizeEmpty ( ) ;
photoSize . type = " s " ;
2014-12-01 18:56:31 +01:00
}
2019-01-23 18:03:33 +01:00
newMessage . media . document . thumbs . add ( photoSize ) ;
newMessage . media . document . flags | = 1 ;
2014-12-01 18:56:31 +01:00
newMessage . media . document . dc_id = file . dc_id ;
2017-07-08 18:32:04 +02:00
if ( MessageObject . isVoiceMessage ( newMessage ) | | MessageObject . isRoundVideoMessage ( newMessage ) ) {
2016-03-06 02:49:31 +01:00
newMessage . media_unread = true ;
}
2015-01-02 23:15:07 +01:00
} else if ( decryptedMessage . media instanceof TLRPC . TL_decryptedMessageMediaExternalDocument ) {
newMessage . media = new TLRPC . TL_messageMediaDocument ( ) ;
2017-07-23 14:56:38 +02:00
newMessage . media . flags | = 3 ;
2018-07-30 04:07:02 +02:00
newMessage . message = " " ;
2015-01-02 23:15:07 +01:00
newMessage . media . document = new TLRPC . TL_document ( ) ;
newMessage . media . document . id = decryptedMessage . media . id ;
newMessage . media . document . access_hash = decryptedMessage . media . access_hash ;
2019-01-23 18:03:33 +01:00
newMessage . media . document . file_reference = new byte [ 0 ] ;
2015-01-02 23:15:07 +01:00
newMessage . media . document . date = decryptedMessage . media . date ;
newMessage . media . document . attributes = decryptedMessage . media . attributes ;
newMessage . media . document . mime_type = decryptedMessage . media . mime_type ;
newMessage . media . document . dc_id = decryptedMessage . media . dc_id ;
newMessage . media . document . size = decryptedMessage . media . size ;
2019-01-23 18:03:33 +01:00
newMessage . media . document . thumbs . add ( ( ( TLRPC . TL_decryptedMessageMediaExternalDocument ) decryptedMessage . media ) . thumb ) ;
newMessage . media . document . flags | = 1 ;
2015-10-29 18:10:07 +01:00
if ( newMessage . media . document . mime_type = = null ) {
newMessage . media . document . mime_type = " " ;
}
2020-06-04 18:47:15 +02:00
if ( MessageObject . isAnimatedStickerMessage ( newMessage ) ) {
newMessage . stickerVerified = 0 ;
getMediaDataController ( ) . verifyAnimatedStickerMessage ( newMessage , true ) ;
}
2014-12-01 18:56:31 +01:00
} else if ( decryptedMessage . media instanceof TLRPC . TL_decryptedMessageMediaAudio ) {
if ( decryptedMessage . media . key = = null | | decryptedMessage . media . key . length ! = 32 | | decryptedMessage . media . iv = = null | | decryptedMessage . media . iv . length ! = 32 ) {
return null ;
}
2016-03-06 02:49:31 +01:00
newMessage . media = new TLRPC . TL_messageMediaDocument ( ) ;
2017-07-23 14:56:38 +02:00
newMessage . media . flags | = 3 ;
2016-03-06 02:49:31 +01:00
newMessage . media . document = new TLRPC . TL_documentEncrypted ( ) ;
newMessage . media . document . key = decryptedMessage . media . key ;
newMessage . media . document . iv = decryptedMessage . media . iv ;
newMessage . media . document . id = file . id ;
newMessage . media . document . access_hash = file . access_hash ;
newMessage . media . document . date = date ;
newMessage . media . document . size = file . size ;
newMessage . media . document . dc_id = file . dc_id ;
newMessage . media . document . mime_type = decryptedMessage . media . mime_type ;
2018-07-30 04:07:02 +02:00
newMessage . message = decryptedMessage . media . caption ! = null ? decryptedMessage . media . caption : " " ;
2016-03-06 02:49:31 +01:00
if ( newMessage . media . document . mime_type = = null ) {
newMessage . media . document . mime_type = " audio/ogg " ;
2014-12-01 18:56:31 +01:00
}
2016-03-06 02:49:31 +01:00
TLRPC . TL_documentAttributeAudio attributeAudio = new TLRPC . TL_documentAttributeAudio ( ) ;
attributeAudio . duration = decryptedMessage . media . duration ;
attributeAudio . voice = true ;
newMessage . media . document . attributes . add ( attributeAudio ) ;
if ( newMessage . ttl ! = 0 ) {
newMessage . ttl = Math . max ( decryptedMessage . media . duration + 1 , newMessage . ttl ) ;
2014-12-01 18:56:31 +01:00
}
2019-01-23 18:03:33 +01:00
if ( newMessage . media . document . thumbs . isEmpty ( ) ) {
TLRPC . PhotoSize thumb = new TLRPC . TL_photoSizeEmpty ( ) ;
thumb . type = " s " ;
newMessage . media . document . thumbs . add ( thumb ) ;
}
2016-03-06 02:49:31 +01:00
} else if ( decryptedMessage . media instanceof TLRPC . TL_decryptedMessageMediaVenue ) {
newMessage . media = new TLRPC . TL_messageMediaVenue ( ) ;
newMessage . media . geo = new TLRPC . TL_geoPoint ( ) ;
newMessage . media . geo . lat = decryptedMessage . media . lat ;
newMessage . media . geo . _long = decryptedMessage . media . _long ;
newMessage . media . title = decryptedMessage . media . title ;
newMessage . media . address = decryptedMessage . media . address ;
newMessage . media . provider = decryptedMessage . media . provider ;
newMessage . media . venue_id = decryptedMessage . media . venue_id ;
2017-12-08 18:35:59 +01:00
newMessage . media . venue_type = " " ;
2014-12-01 18:56:31 +01:00
} else {
return null ;
}
2018-07-30 04:07:02 +02:00
if ( newMessage . ttl ! = 0 & & newMessage . media . ttl_seconds = = 0 ) {
newMessage . media . ttl_seconds = newMessage . ttl ;
newMessage . media . flags | = 4 ;
}
2019-08-22 01:53:26 +02:00
if ( newMessage . message ! = null ) {
newMessage . message = newMessage . message . replace ( '\u202E' , ' ' ) ;
}
2014-12-01 18:56:31 +01:00
return newMessage ;
} else if ( object instanceof TLRPC . TL_decryptedMessageService ) {
2015-05-21 23:27:27 +02:00
final TLRPC . TL_decryptedMessageService serviceMessage = ( TLRPC . TL_decryptedMessageService ) object ;
2014-12-01 18:56:31 +01:00
if ( serviceMessage . action instanceof TLRPC . TL_decryptedMessageActionSetMessageTTL | | serviceMessage . action instanceof TLRPC . TL_decryptedMessageActionScreenshotMessages ) {
TLRPC . TL_messageService newMessage = new TLRPC . TL_messageService ( ) ;
if ( serviceMessage . action instanceof TLRPC . TL_decryptedMessageActionSetMessageTTL ) {
newMessage . action = new TLRPC . TL_messageEncryptedAction ( ) ;
if ( serviceMessage . action . ttl_seconds < 0 | | serviceMessage . action . ttl_seconds > 60 * 60 * 24 * 365 ) {
serviceMessage . action . ttl_seconds = 60 * 60 * 24 * 365 ;
}
chat . ttl = serviceMessage . action . ttl_seconds ;
newMessage . action . encryptedAction = serviceMessage . action ;
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . updateEncryptedChatTTL ( chat ) ;
2014-12-01 18:56:31 +01:00
} else if ( serviceMessage . action instanceof TLRPC . TL_decryptedMessageActionScreenshotMessages ) {
newMessage . action = new TLRPC . TL_messageEncryptedAction ( ) ;
newMessage . action . encryptedAction = serviceMessage . action ;
}
2019-07-18 15:01:39 +02:00
newMessage . local_id = newMessage . id = getUserConfig ( ) . getNewMessageId ( ) ;
getUserConfig ( ) . saveConfig ( false ) ;
2015-11-26 22:04:02 +01:00
newMessage . unread = true ;
newMessage . flags = TLRPC . MESSAGE_FLAG_HAS_FROM_ID ;
2014-12-01 18:56:31 +01:00
newMessage . date = date ;
newMessage . from_id = from_id ;
newMessage . to_id = new TLRPC . TL_peerUser ( ) ;
2019-07-18 15:01:39 +02:00
newMessage . to_id . user_id = getUserConfig ( ) . getClientUserId ( ) ;
2015-05-21 23:27:27 +02:00
newMessage . dialog_id = ( ( long ) chat . id ) < < 32 ;
2014-12-01 18:56:31 +01:00
return newMessage ;
} else if ( serviceMessage . action instanceof TLRPC . TL_decryptedMessageActionFlushHistory ) {
2015-05-21 23:27:27 +02:00
final long did = ( ( long ) chat . id ) < < 32 ;
2018-08-27 10:33:11 +02:00
AndroidUtilities . runOnUIThread ( ( ) - > {
2019-07-18 15:01:39 +02:00
TLRPC . Dialog dialog = getMessagesController ( ) . dialogs_dict . get ( did ) ;
2018-08-27 10:33:11 +02:00
if ( dialog ! = null ) {
dialog . unread_count = 0 ;
2019-07-18 15:01:39 +02:00
getMessagesController ( ) . dialogMessage . remove ( dialog . id ) ;
2014-12-01 18:56:31 +01:00
}
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > AndroidUtilities . runOnUIThread ( ( ) - > {
getNotificationsController ( ) . processReadMessages ( null , did , 0 , Integer . MAX_VALUE , false ) ;
2018-08-27 10:33:11 +02:00
LongSparseArray < Integer > dialogsToUpdate = new LongSparseArray < > ( 1 ) ;
dialogsToUpdate . put ( did , 0 ) ;
2019-07-18 15:01:39 +02:00
getNotificationsController ( ) . processDialogsUpdateRead ( dialogsToUpdate ) ;
2018-08-27 10:33:11 +02:00
} ) ) ;
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . deleteDialog ( did , 1 ) ;
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . dialogsNeedReload ) ;
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . removeAllMessagesFromDialog , did , false ) ;
2014-12-01 18:56:31 +01:00
} ) ;
return null ;
} else if ( serviceMessage . action instanceof TLRPC . TL_decryptedMessageActionDeleteMessages ) {
if ( ! serviceMessage . action . random_ids . isEmpty ( ) ) {
pendingEncMessagesToDelete . addAll ( serviceMessage . action . random_ids ) ;
}
return null ;
} else if ( serviceMessage . action instanceof TLRPC . TL_decryptedMessageActionReadMessages ) {
if ( ! serviceMessage . action . random_ids . isEmpty ( ) ) {
2019-07-18 15:01:39 +02:00
int time = getConnectionsManager ( ) . getCurrentTime ( ) ;
getMessagesStorage ( ) . createTaskForSecretChat ( chat . id , time , time , 1 , serviceMessage . action . random_ids ) ;
2014-12-01 18:56:31 +01:00
}
} else if ( serviceMessage . action instanceof TLRPC . TL_decryptedMessageActionNotifyLayer ) {
2016-04-22 15:49:00 +02:00
applyPeerLayer ( chat , serviceMessage . action . layer ) ;
2014-12-01 18:56:31 +01:00
} else if ( serviceMessage . action instanceof TLRPC . TL_decryptedMessageActionRequestKey ) {
if ( chat . exchange_id ! = 0 ) {
if ( chat . exchange_id > serviceMessage . action . exchange_id ) {
2018-07-30 04:07:02 +02:00
if ( BuildVars . LOGS_ENABLED ) {
FileLog . d ( " we already have request key with higher exchange_id " ) ;
}
2014-12-01 18:56:31 +01:00
return null ;
} else {
2016-10-11 13:57:01 +02:00
sendAbortKeyMessage ( chat , null , chat . exchange_id ) ; //TODO don't send?
2014-12-01 18:56:31 +01:00
}
}
byte [ ] salt = new byte [ 256 ] ;
2015-04-09 20:00:14 +02:00
Utilities . random . nextBytes ( salt ) ;
2019-07-18 15:01:39 +02:00
BigInteger p = new BigInteger ( 1 , getMessagesStorage ( ) . getSecretPBytes ( ) ) ;
BigInteger g_b = BigInteger . valueOf ( getMessagesStorage ( ) . getSecretG ( ) ) ;
2014-12-01 18:56:31 +01:00
g_b = g_b . modPow ( new BigInteger ( 1 , salt ) , p ) ;
BigInteger g_a = new BigInteger ( 1 , serviceMessage . action . g_a ) ;
if ( ! Utilities . isGoodGaAndGb ( g_a , p ) ) {
sendAbortKeyMessage ( chat , null , serviceMessage . action . exchange_id ) ;
return null ;
}
byte [ ] g_b_bytes = g_b . toByteArray ( ) ;
if ( g_b_bytes . length > 256 ) {
byte [ ] correctedAuth = new byte [ 256 ] ;
System . arraycopy ( g_b_bytes , 1 , correctedAuth , 0 , 256 ) ;
g_b_bytes = correctedAuth ;
}
g_a = g_a . modPow ( new BigInteger ( 1 , salt ) , p ) ;
byte [ ] authKey = g_a . toByteArray ( ) ;
if ( authKey . length > 256 ) {
byte [ ] correctedAuth = new byte [ 256 ] ;
System . arraycopy ( authKey , authKey . length - 256 , correctedAuth , 0 , 256 ) ;
authKey = correctedAuth ;
} else if ( authKey . length < 256 ) {
byte [ ] correctedAuth = new byte [ 256 ] ;
System . arraycopy ( authKey , 0 , correctedAuth , 256 - authKey . length , authKey . length ) ;
for ( int a = 0 ; a < 256 - authKey . length ; a + + ) {
2018-08-27 10:33:11 +02:00
correctedAuth [ a ] = 0 ;
2014-12-01 18:56:31 +01:00
}
authKey = correctedAuth ;
}
byte [ ] authKeyHash = Utilities . computeSHA1 ( authKey ) ;
byte [ ] authKeyId = new byte [ 8 ] ;
System . arraycopy ( authKeyHash , authKeyHash . length - 8 , authKeyId , 0 , 8 ) ;
chat . exchange_id = serviceMessage . action . exchange_id ;
chat . future_auth_key = authKey ;
chat . future_key_fingerprint = Utilities . bytesToLong ( authKeyId ) ;
chat . g_a_or_b = g_b_bytes ;
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . updateEncryptedChat ( chat ) ;
2014-12-01 18:56:31 +01:00
sendAcceptKeyMessage ( chat , null ) ;
} else if ( serviceMessage . action instanceof TLRPC . TL_decryptedMessageActionAcceptKey ) {
if ( chat . exchange_id = = serviceMessage . action . exchange_id ) {
2019-07-18 15:01:39 +02:00
BigInteger p = new BigInteger ( 1 , getMessagesStorage ( ) . getSecretPBytes ( ) ) ;
2014-12-01 18:56:31 +01:00
BigInteger i_authKey = new BigInteger ( 1 , serviceMessage . action . g_b ) ;
if ( ! Utilities . isGoodGaAndGb ( i_authKey , p ) ) {
chat . future_auth_key = new byte [ 256 ] ;
chat . future_key_fingerprint = 0 ;
chat . exchange_id = 0 ;
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . updateEncryptedChat ( chat ) ;
2014-12-01 18:56:31 +01:00
sendAbortKeyMessage ( chat , null , serviceMessage . action . exchange_id ) ;
return null ;
}
i_authKey = i_authKey . modPow ( new BigInteger ( 1 , chat . a_or_b ) , p ) ;
byte [ ] authKey = i_authKey . toByteArray ( ) ;
if ( authKey . length > 256 ) {
byte [ ] correctedAuth = new byte [ 256 ] ;
System . arraycopy ( authKey , authKey . length - 256 , correctedAuth , 0 , 256 ) ;
authKey = correctedAuth ;
} else if ( authKey . length < 256 ) {
byte [ ] correctedAuth = new byte [ 256 ] ;
System . arraycopy ( authKey , 0 , correctedAuth , 256 - authKey . length , authKey . length ) ;
for ( int a = 0 ; a < 256 - authKey . length ; a + + ) {
2018-08-27 10:33:11 +02:00
correctedAuth [ a ] = 0 ;
2014-12-01 18:56:31 +01:00
}
authKey = correctedAuth ;
}
byte [ ] authKeyHash = Utilities . computeSHA1 ( authKey ) ;
byte [ ] authKeyId = new byte [ 8 ] ;
System . arraycopy ( authKeyHash , authKeyHash . length - 8 , authKeyId , 0 , 8 ) ;
long fingerprint = Utilities . bytesToLong ( authKeyId ) ;
if ( serviceMessage . action . key_fingerprint = = fingerprint ) {
chat . future_auth_key = authKey ;
chat . future_key_fingerprint = fingerprint ;
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . updateEncryptedChat ( chat ) ;
2014-12-04 21:27:06 +01:00
sendCommitKeyMessage ( chat , null ) ;
2014-12-01 18:56:31 +01:00
} else {
chat . future_auth_key = new byte [ 256 ] ;
chat . future_key_fingerprint = 0 ;
chat . exchange_id = 0 ;
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . updateEncryptedChat ( chat ) ;
2014-12-01 18:56:31 +01:00
sendAbortKeyMessage ( chat , null , serviceMessage . action . exchange_id ) ;
}
} else {
chat . future_auth_key = new byte [ 256 ] ;
chat . future_key_fingerprint = 0 ;
chat . exchange_id = 0 ;
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . updateEncryptedChat ( chat ) ;
2014-12-01 18:56:31 +01:00
sendAbortKeyMessage ( chat , null , serviceMessage . action . exchange_id ) ;
}
} else if ( serviceMessage . action instanceof TLRPC . TL_decryptedMessageActionCommitKey ) {
if ( chat . exchange_id = = serviceMessage . action . exchange_id & & chat . future_key_fingerprint = = serviceMessage . action . key_fingerprint ) {
2019-12-31 14:08:08 +01:00
long old_fingerprint = chat . key_fingerprint ;
2014-12-01 18:56:31 +01:00
byte [ ] old_key = chat . auth_key ;
chat . key_fingerprint = chat . future_key_fingerprint ;
chat . auth_key = chat . future_auth_key ;
2019-07-18 15:01:39 +02:00
chat . key_create_date = getConnectionsManager ( ) . getCurrentTime ( ) ;
2014-12-01 18:56:31 +01:00
chat . future_auth_key = old_key ;
2019-12-31 14:08:08 +01:00
chat . future_key_fingerprint = old_fingerprint ;
2014-12-01 18:56:31 +01:00
chat . key_use_count_in = 0 ;
chat . key_use_count_out = 0 ;
chat . exchange_id = 0 ;
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . updateEncryptedChat ( chat ) ;
2014-12-01 18:56:31 +01:00
sendNoopMessage ( chat , null ) ;
} else {
chat . future_auth_key = new byte [ 256 ] ;
chat . future_key_fingerprint = 0 ;
chat . exchange_id = 0 ;
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . updateEncryptedChat ( chat ) ;
2014-12-01 18:56:31 +01:00
sendAbortKeyMessage ( chat , null , serviceMessage . action . exchange_id ) ;
}
} else if ( serviceMessage . action instanceof TLRPC . TL_decryptedMessageActionAbortKey ) {
if ( chat . exchange_id = = serviceMessage . action . exchange_id ) {
chat . future_auth_key = new byte [ 256 ] ;
chat . future_key_fingerprint = 0 ;
chat . exchange_id = 0 ;
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . updateEncryptedChat ( chat ) ;
2014-12-01 18:56:31 +01:00
}
} else if ( serviceMessage . action instanceof TLRPC . TL_decryptedMessageActionNoop ) {
//do nothing
} else if ( serviceMessage . action instanceof TLRPC . TL_decryptedMessageActionResend ) {
2016-10-11 13:57:01 +02:00
if ( serviceMessage . action . end_seq_no < chat . in_seq_no | | serviceMessage . action . end_seq_no < serviceMessage . action . start_seq_no ) {
return null ;
}
if ( serviceMessage . action . start_seq_no < chat . in_seq_no ) {
serviceMessage . action . start_seq_no = chat . in_seq_no ;
}
resendMessages ( serviceMessage . action . start_seq_no , serviceMessage . action . end_seq_no , chat ) ;
2014-12-01 18:56:31 +01:00
} else {
return null ;
}
} else {
2018-07-30 04:07:02 +02:00
if ( BuildVars . LOGS_ENABLED ) {
FileLog . e ( " unknown message " + object ) ;
}
2014-12-01 18:56:31 +01:00
}
} else {
2018-07-30 04:07:02 +02:00
if ( BuildVars . LOGS_ENABLED ) {
FileLog . e ( " unknown TLObject " ) ;
}
2014-12-01 18:56:31 +01:00
}
return null ;
}
2016-10-11 13:57:01 +02:00
private TLRPC . Message createDeleteMessage ( int mid , int seq_out , int seq_in , long random_id , TLRPC . EncryptedChat encryptedChat ) {
TLRPC . TL_messageService newMsg = new TLRPC . TL_messageService ( ) ;
newMsg . action = new TLRPC . TL_messageEncryptedAction ( ) ;
newMsg . action . encryptedAction = new TLRPC . TL_decryptedMessageActionDeleteMessages ( ) ;
newMsg . action . encryptedAction . random_ids . add ( random_id ) ;
newMsg . local_id = newMsg . id = mid ;
2019-07-18 15:01:39 +02:00
newMsg . from_id = getUserConfig ( ) . getClientUserId ( ) ;
2016-10-11 13:57:01 +02:00
newMsg . unread = true ;
newMsg . out = true ;
newMsg . flags = TLRPC . MESSAGE_FLAG_HAS_FROM_ID ;
newMsg . dialog_id = ( ( long ) encryptedChat . id ) < < 32 ;
newMsg . to_id = new TLRPC . TL_peerUser ( ) ;
newMsg . send_state = MessageObject . MESSAGE_SEND_STATE_SENDING ;
newMsg . seq_in = seq_in ;
newMsg . seq_out = seq_out ;
2019-07-18 15:01:39 +02:00
if ( encryptedChat . participant_id = = getUserConfig ( ) . getClientUserId ( ) ) {
2016-10-11 13:57:01 +02:00
newMsg . to_id . user_id = encryptedChat . admin_id ;
} else {
newMsg . to_id . user_id = encryptedChat . participant_id ;
}
newMsg . date = 0 ;
newMsg . random_id = random_id ;
return newMsg ;
}
private void resendMessages ( final int startSeq , final int endSeq , final TLRPC . EncryptedChat encryptedChat ) {
if ( encryptedChat = = null | | endSeq - startSeq < 0 ) {
return ;
}
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > {
2018-08-27 10:33:11 +02:00
try {
int sSeq = startSeq ;
2019-07-18 15:01:39 +02:00
if ( encryptedChat . admin_id = = getUserConfig ( ) . getClientUserId ( ) & & sSeq % 2 = = 0 ) {
2018-08-27 10:33:11 +02:00
sSeq + + ;
}
2016-10-11 13:57:01 +02:00
2019-07-18 15:01:39 +02:00
SQLiteCursor cursor = getMessagesStorage ( ) . getDatabase ( ) . queryFinalized ( String . format ( Locale . US , " SELECT uid FROM requested_holes WHERE uid = %d AND ((seq_out_start >= %d AND %d <= seq_out_end) OR (seq_out_start >= %d AND %d <= seq_out_end)) " , encryptedChat . id , sSeq , sSeq , endSeq , endSeq ) ) ;
2018-08-27 10:33:11 +02:00
boolean exists = cursor . next ( ) ;
cursor . dispose ( ) ;
if ( exists ) {
return ;
}
2016-10-11 13:57:01 +02:00
2018-08-27 10:33:11 +02:00
long dialog_id = ( ( long ) encryptedChat . id ) < < 32 ;
SparseArray < TLRPC . Message > messagesToResend = new SparseArray < > ( ) ;
final ArrayList < TLRPC . Message > messages = new ArrayList < > ( ) ;
2019-12-31 14:08:08 +01:00
for ( int a = sSeq ; a < = endSeq ; a + = 2 ) {
2018-08-27 10:33:11 +02:00
messagesToResend . put ( a , null ) ;
}
2019-07-18 15:01:39 +02:00
cursor = getMessagesStorage ( ) . getDatabase ( ) . queryFinalized ( String . format ( Locale . US , " SELECT m.data, r.random_id, s.seq_in, s.seq_out, m.ttl, s.mid FROM messages_seq as s LEFT JOIN randoms as r ON r.mid = s.mid LEFT JOIN messages as m ON m.mid = s.mid WHERE m.uid = %d AND m.out = 1 AND s.seq_out >= %d AND s.seq_out <= %d ORDER BY seq_out ASC " , dialog_id , sSeq , endSeq ) ) ;
2018-08-27 10:33:11 +02:00
while ( cursor . next ( ) ) {
TLRPC . Message message ;
long random_id = cursor . longValue ( 1 ) ;
if ( random_id = = 0 ) {
random_id = Utilities . random . nextLong ( ) ;
2016-10-11 13:57:01 +02:00
}
2018-08-27 10:33:11 +02:00
int seq_in = cursor . intValue ( 2 ) ;
int seq_out = cursor . intValue ( 3 ) ;
int mid = cursor . intValue ( 5 ) ;
NativeByteBuffer data = cursor . byteBufferValue ( 0 ) ;
if ( data ! = null ) {
message = TLRPC . Message . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
2019-07-18 15:01:39 +02:00
message . readAttachPath ( data , getUserConfig ( ) . clientUserId ) ;
2018-08-27 10:33:11 +02:00
data . reuse ( ) ;
message . random_id = random_id ;
message . dialog_id = dialog_id ;
message . seq_in = seq_in ;
message . seq_out = seq_out ;
message . ttl = cursor . intValue ( 4 ) ;
} else {
message = createDeleteMessage ( mid , seq_out , seq_in , random_id , encryptedChat ) ;
2016-10-11 13:57:01 +02:00
}
2018-08-27 10:33:11 +02:00
messages . add ( message ) ;
messagesToResend . remove ( seq_out ) ;
}
cursor . dispose ( ) ;
if ( messagesToResend . size ( ) ! = 0 ) {
for ( int a = 0 ; a < messagesToResend . size ( ) ; a + + ) {
2019-12-31 14:08:08 +01:00
int seq = messagesToResend . keyAt ( a ) ;
messages . add ( createDeleteMessage ( getUserConfig ( ) . getNewMessageId ( ) , seq , seq + 1 , Utilities . random . nextLong ( ) , encryptedChat ) ) ;
2016-10-11 13:57:01 +02:00
}
2019-07-18 15:01:39 +02:00
getUserConfig ( ) . saveConfig ( false ) ;
2016-10-11 13:57:01 +02:00
}
2018-08-27 10:33:11 +02:00
Collections . sort ( messages , ( lhs , rhs ) - > AndroidUtilities . compare ( lhs . seq_out , rhs . seq_out ) ) ;
ArrayList < TLRPC . EncryptedChat > encryptedChats = new ArrayList < > ( ) ;
encryptedChats . add ( encryptedChat ) ;
AndroidUtilities . runOnUIThread ( ( ) - > {
for ( int a = 0 ; a < messages . size ( ) ; a + + ) {
TLRPC . Message message = messages . get ( a ) ;
MessageObject messageObject = new MessageObject ( currentAccount , message , false ) ;
messageObject . resendAsIs = true ;
2019-07-18 15:01:39 +02:00
getSendMessagesHelper ( ) . retrySendMessage ( messageObject , true ) ;
2018-08-27 10:33:11 +02:00
}
} ) ;
2019-09-10 12:56:11 +02:00
getSendMessagesHelper ( ) . processUnsentMessages ( messages , null , new ArrayList < > ( ) , new ArrayList < > ( ) , encryptedChats ) ;
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getDatabase ( ) . executeFast ( String . format ( Locale . US , " REPLACE INTO requested_holes VALUES(%d, %d, %d) " , encryptedChat . id , sSeq , endSeq ) ) . stepThis ( ) . dispose ( ) ;
2018-08-27 10:33:11 +02:00
} catch ( Exception e ) {
FileLog . e ( e ) ;
2016-10-11 13:57:01 +02:00
}
} ) ;
}
2014-12-01 18:56:31 +01:00
public void checkSecretHoles ( TLRPC . EncryptedChat chat , ArrayList < TLRPC . Message > messages ) {
2016-03-06 02:49:31 +01:00
ArrayList < TL_decryptedMessageHolder > holes = secretHolesQueue . get ( chat . id ) ;
2014-12-01 18:56:31 +01:00
if ( holes = = null ) {
return ;
}
2018-08-27 10:33:11 +02:00
Collections . sort ( holes , ( lhs , rhs ) - > {
if ( lhs . layer . out_seq_no > rhs . layer . out_seq_no ) {
return 1 ;
} else if ( lhs . layer . out_seq_no < rhs . layer . out_seq_no ) {
return - 1 ;
2014-12-01 18:56:31 +01:00
}
2018-08-27 10:33:11 +02:00
return 0 ;
2014-12-01 18:56:31 +01:00
} ) ;
boolean update = false ;
for ( int a = 0 ; a < holes . size ( ) ; a + + ) {
2016-03-06 02:49:31 +01:00
TL_decryptedMessageHolder holder = holes . get ( a ) ;
2014-12-01 18:56:31 +01:00
if ( holder . layer . out_seq_no = = chat . seq_in | | chat . seq_in = = holder . layer . out_seq_no - 2 ) {
2016-04-22 15:49:00 +02:00
applyPeerLayer ( chat , holder . layer . layer ) ;
2014-12-01 18:56:31 +01:00
chat . seq_in = holder . layer . out_seq_no ;
2016-10-11 13:57:01 +02:00
chat . in_seq_no = holder . layer . in_seq_no ;
2014-12-01 18:56:31 +01:00
holes . remove ( a ) ;
a - - ;
update = true ;
2017-12-08 18:35:59 +01:00
if ( holder . decryptedWithVersion = = 2 ) {
chat . mtproto_seq = Math . min ( chat . mtproto_seq , chat . seq_in ) ;
}
TLRPC . Message message = processDecryptedObject ( chat , holder . file , holder . date , holder . layer . message , holder . new_key_used ) ;
2014-12-01 18:56:31 +01:00
if ( message ! = null ) {
messages . add ( message ) ;
}
} else {
break ;
}
}
if ( holes . isEmpty ( ) ) {
secretHolesQueue . remove ( chat . id ) ;
}
if ( update ) {
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . updateEncryptedChatSeq ( chat , true ) ;
2017-12-08 18:35:59 +01:00
}
}
private boolean decryptWithMtProtoVersion ( NativeByteBuffer is , byte [ ] keyToDecrypt , byte [ ] messageKey , int version , boolean incoming , boolean encryptOnError ) {
if ( version = = 1 ) {
incoming = false ;
}
MessageKeyData keyData = MessageKeyData . generateMessageKeyData ( keyToDecrypt , messageKey , incoming , version ) ;
Utilities . aesIgeEncryption ( is . buffer , keyData . aesKey , keyData . aesIv , false , false , 24 , is . limit ( ) - 24 ) ;
int len = is . readInt32 ( false ) ;
byte [ ] messageKeyFull ;
if ( version = = 2 ) {
messageKeyFull = Utilities . computeSHA256 ( keyToDecrypt , 88 + ( incoming ? 8 : 0 ) , 32 , is . buffer , 24 , is . buffer . limit ( ) ) ;
if ( ! Utilities . arraysEquals ( messageKey , 0 , messageKeyFull , 8 ) ) {
if ( encryptOnError ) {
Utilities . aesIgeEncryption ( is . buffer , keyData . aesKey , keyData . aesIv , true , false , 24 , is . limit ( ) - 24 ) ;
is . position ( 24 ) ;
}
return false ;
}
} else {
int l = len + 28 ;
if ( l < is . buffer . limit ( ) - 15 | | l > is . buffer . limit ( ) ) {
l = is . buffer . limit ( ) ;
}
messageKeyFull = Utilities . computeSHA1 ( is . buffer , 24 , l ) ;
if ( ! Utilities . arraysEquals ( messageKey , 0 , messageKeyFull , messageKeyFull . length - 16 ) ) {
if ( encryptOnError ) {
Utilities . aesIgeEncryption ( is . buffer , keyData . aesKey , keyData . aesIv , true , false , 24 , is . limit ( ) - 24 ) ;
is . position ( 24 ) ;
}
return false ;
}
2014-12-01 18:56:31 +01:00
}
2017-12-08 18:35:59 +01:00
if ( len < = 0 | | len > is . limit ( ) - 28 ) {
return false ;
}
int padding = is . limit ( ) - 28 - len ;
if ( version = = 2 & & ( padding < 12 | | padding > 1024 ) | | version = = 1 & & padding > 15 ) {
return false ;
}
//
return true ;
2014-12-01 18:56:31 +01:00
}
protected ArrayList < TLRPC . Message > decryptMessage ( TLRPC . EncryptedMessage message ) {
2019-07-18 15:01:39 +02:00
final TLRPC . EncryptedChat chat = getMessagesController ( ) . getEncryptedChatDB ( message . chat_id , true ) ;
2014-12-01 18:56:31 +01:00
if ( chat = = null | | chat instanceof TLRPC . TL_encryptedChatDiscarded ) {
return null ;
}
2015-01-02 23:15:07 +01:00
2016-03-06 02:49:31 +01:00
try {
2019-12-31 14:08:08 +01:00
if ( chat instanceof TLRPC . TL_encryptedChatWaiting ) {
ArrayList < TLRPC . Update > updates = pendingSecretMessages . get ( chat . id ) ;
if ( updates = = null ) {
updates = new ArrayList < > ( ) ;
pendingSecretMessages . put ( chat . id , updates ) ;
}
TLRPC . TL_updateNewEncryptedMessage updateNewEncryptedMessage = new TLRPC . TL_updateNewEncryptedMessage ( ) ;
updateNewEncryptedMessage . message = message ;
updates . add ( updateNewEncryptedMessage ) ;
return null ;
}
2016-03-06 02:49:31 +01:00
NativeByteBuffer is = new NativeByteBuffer ( message . bytes . length ) ;
is . writeBytes ( message . bytes ) ;
is . position ( 0 ) ;
long fingerprint = is . readInt64 ( false ) ;
byte [ ] keyToDecrypt = null ;
boolean new_key_used = false ;
if ( chat . key_fingerprint = = fingerprint ) {
keyToDecrypt = chat . auth_key ;
} else if ( chat . future_key_fingerprint ! = 0 & & chat . future_key_fingerprint = = fingerprint ) {
keyToDecrypt = chat . future_auth_key ;
new_key_used = true ;
2015-01-02 23:15:07 +01:00
}
2017-12-08 18:35:59 +01:00
int mtprotoVersion = AndroidUtilities . getPeerLayerVersion ( chat . layer ) > = 73 ? 2 : 1 ;
int decryptedWithVersion = mtprotoVersion ;
2015-01-02 23:15:07 +01:00
2016-03-06 02:49:31 +01:00
if ( keyToDecrypt ! = null ) {
byte [ ] messageKey = is . readData ( 16 , false ) ;
2019-07-18 15:01:39 +02:00
boolean incoming = chat . admin_id = = getUserConfig ( ) . getClientUserId ( ) ;
2017-12-08 18:35:59 +01:00
boolean tryAnotherDecrypt = true ;
if ( decryptedWithVersion = = 2 & & chat . mtproto_seq ! = 0 ) {
tryAnotherDecrypt = false ;
2015-10-29 18:10:07 +01:00
}
2017-12-08 18:35:59 +01:00
if ( ! decryptWithMtProtoVersion ( is , keyToDecrypt , messageKey , mtprotoVersion , incoming , tryAnotherDecrypt ) ) {
if ( mtprotoVersion = = 2 ) {
decryptedWithVersion = 1 ;
if ( ! tryAnotherDecrypt | | ! decryptWithMtProtoVersion ( is , keyToDecrypt , messageKey , 1 , incoming , false ) ) {
return null ;
}
} else {
decryptedWithVersion = 2 ;
if ( ! decryptWithMtProtoVersion ( is , keyToDecrypt , messageKey , 2 , incoming , tryAnotherDecrypt ) ) {
return null ;
}
}
2014-12-01 18:56:31 +01:00
}
2016-03-06 02:49:31 +01:00
TLObject object = TLClassStore . Instance ( ) . TLdeserialize ( is , is . readInt32 ( false ) , false ) ;
is . reuse ( ) ;
if ( ! new_key_used & & AndroidUtilities . getPeerLayerVersion ( chat . layer ) > = 20 ) {
chat . key_use_count_in + + ;
}
if ( object instanceof TLRPC . TL_decryptedMessageLayer ) {
final TLRPC . TL_decryptedMessageLayer layer = ( TLRPC . TL_decryptedMessageLayer ) object ;
if ( chat . seq_in = = 0 & & chat . seq_out = = 0 ) {
2019-07-18 15:01:39 +02:00
if ( chat . admin_id = = getUserConfig ( ) . getClientUserId ( ) ) {
2016-03-06 02:49:31 +01:00
chat . seq_out = 1 ;
2017-07-08 18:32:04 +02:00
chat . seq_in = - 2 ;
2016-03-06 02:49:31 +01:00
} else {
2017-07-08 18:32:04 +02:00
chat . seq_in = - 1 ;
2016-03-06 02:49:31 +01:00
}
2014-12-01 18:56:31 +01:00
}
2016-03-06 02:49:31 +01:00
if ( layer . random_bytes . length < 15 ) {
2018-07-30 04:07:02 +02:00
if ( BuildVars . LOGS_ENABLED ) {
FileLog . e ( " got random bytes less than needed " ) ;
}
2014-12-01 18:56:31 +01:00
return null ;
}
2018-07-30 04:07:02 +02:00
if ( BuildVars . LOGS_ENABLED ) {
FileLog . d ( " current chat in_seq = " + chat . seq_in + " out_seq = " + chat . seq_out ) ;
FileLog . d ( " got message with in_seq = " + layer . in_seq_no + " out_seq = " + layer . out_seq_no ) ;
}
2017-07-08 18:32:04 +02:00
if ( layer . out_seq_no < = chat . seq_in ) {
2016-03-06 02:49:31 +01:00
return null ;
}
2017-12-08 18:35:59 +01:00
if ( decryptedWithVersion = = 1 & & chat . mtproto_seq ! = 0 & & layer . out_seq_no > = chat . mtproto_seq ) {
return null ;
}
if ( chat . seq_in ! = layer . out_seq_no - 2 ) {
2018-07-30 04:07:02 +02:00
if ( BuildVars . LOGS_ENABLED ) {
FileLog . e ( " got hole " ) ;
}
2019-12-31 14:08:08 +01:00
sendResendMessage ( chat , chat . seq_in + 2 , layer . out_seq_no - 2 , null ) ;
2016-03-06 02:49:31 +01:00
ArrayList < TL_decryptedMessageHolder > arr = secretHolesQueue . get ( chat . id ) ;
if ( arr = = null ) {
arr = new ArrayList < > ( ) ;
secretHolesQueue . put ( chat . id , arr ) ;
}
if ( arr . size ( ) > = 4 ) {
secretHolesQueue . remove ( chat . id ) ;
final TLRPC . TL_encryptedChatDiscarded newChat = new TLRPC . TL_encryptedChatDiscarded ( ) ;
newChat . id = chat . id ;
newChat . user_id = chat . user_id ;
newChat . auth_key = chat . auth_key ;
newChat . key_create_date = chat . key_create_date ;
newChat . key_use_count_in = chat . key_use_count_in ;
newChat . key_use_count_out = chat . key_use_count_out ;
newChat . seq_in = chat . seq_in ;
newChat . seq_out = chat . seq_out ;
2018-08-27 10:33:11 +02:00
AndroidUtilities . runOnUIThread ( ( ) - > {
2019-07-18 15:01:39 +02:00
getMessagesController ( ) . putEncryptedChat ( newChat , false ) ;
getMessagesStorage ( ) . updateEncryptedChat ( newChat ) ;
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . encryptedChatUpdated , newChat ) ;
2016-03-06 02:49:31 +01:00
} ) ;
declineSecretChat ( chat . id ) ;
return null ;
}
2014-12-01 18:56:31 +01:00
2016-03-06 02:49:31 +01:00
TL_decryptedMessageHolder holder = new TL_decryptedMessageHolder ( ) ;
holder . layer = layer ;
holder . file = message . file ;
holder . date = message . date ;
holder . new_key_used = new_key_used ;
2017-12-08 18:35:59 +01:00
holder . decryptedWithVersion = decryptedWithVersion ;
2016-03-06 02:49:31 +01:00
arr . add ( holder ) ;
return null ;
}
2017-12-08 18:35:59 +01:00
if ( decryptedWithVersion = = 2 ) {
chat . mtproto_seq = Math . min ( chat . mtproto_seq , chat . seq_in ) ;
}
2016-04-22 15:49:00 +02:00
applyPeerLayer ( chat , layer . layer ) ;
2016-03-06 02:49:31 +01:00
chat . seq_in = layer . out_seq_no ;
2016-10-11 13:57:01 +02:00
chat . in_seq_no = layer . in_seq_no ;
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . updateEncryptedChatSeq ( chat , true ) ;
2016-03-06 02:49:31 +01:00
object = layer . message ;
2017-03-31 01:58:05 +02:00
} else if ( ! ( object instanceof TLRPC . TL_decryptedMessageService & & ( ( TLRPC . TL_decryptedMessageService ) object ) . action instanceof TLRPC . TL_decryptedMessageActionNotifyLayer ) ) {
return null ;
2014-12-01 18:56:31 +01:00
}
2016-03-06 02:49:31 +01:00
ArrayList < TLRPC . Message > messages = new ArrayList < > ( ) ;
2017-12-08 18:35:59 +01:00
TLRPC . Message decryptedMessage = processDecryptedObject ( chat , message . file , message . date , object , new_key_used ) ;
2016-03-06 02:49:31 +01:00
if ( decryptedMessage ! = null ) {
messages . add ( decryptedMessage ) ;
}
checkSecretHoles ( chat , messages ) ;
return messages ;
} else {
is . reuse ( ) ;
2018-07-30 04:07:02 +02:00
if ( BuildVars . LOGS_ENABLED ) {
FileLog . e ( String . format ( " fingerprint mismatch %x " , fingerprint ) ) ;
}
2014-12-01 18:56:31 +01:00
}
2016-03-06 02:49:31 +01:00
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2014-12-01 18:56:31 +01:00
}
2016-03-06 02:49:31 +01:00
2014-12-01 18:56:31 +01:00
return null ;
}
public void requestNewSecretChatKey ( final TLRPC . EncryptedChat encryptedChat ) {
if ( AndroidUtilities . getPeerLayerVersion ( encryptedChat . layer ) < 20 ) {
return ;
}
final byte [ ] salt = new byte [ 256 ] ;
2015-04-09 20:00:14 +02:00
Utilities . random . nextBytes ( salt ) ;
2014-12-01 18:56:31 +01:00
2019-07-18 15:01:39 +02:00
BigInteger i_g_a = BigInteger . valueOf ( getMessagesStorage ( ) . getSecretG ( ) ) ;
i_g_a = i_g_a . modPow ( new BigInteger ( 1 , salt ) , new BigInteger ( 1 , getMessagesStorage ( ) . getSecretPBytes ( ) ) ) ;
2014-12-01 18:56:31 +01:00
byte [ ] g_a = i_g_a . toByteArray ( ) ;
if ( g_a . length > 256 ) {
byte [ ] correctedAuth = new byte [ 256 ] ;
System . arraycopy ( g_a , 1 , correctedAuth , 0 , 256 ) ;
g_a = correctedAuth ;
}
2019-07-18 15:01:39 +02:00
encryptedChat . exchange_id = getSendMessagesHelper ( ) . getNextRandomId ( ) ;
2014-12-01 18:56:31 +01:00
encryptedChat . a_or_b = salt ;
encryptedChat . g_a = g_a ;
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . updateEncryptedChat ( encryptedChat ) ;
2014-12-01 18:56:31 +01:00
sendRequestKeyMessage ( encryptedChat , null ) ;
}
public void processAcceptedSecretChat ( final TLRPC . EncryptedChat encryptedChat ) {
2019-07-18 15:01:39 +02:00
BigInteger p = new BigInteger ( 1 , getMessagesStorage ( ) . getSecretPBytes ( ) ) ;
2014-12-01 18:56:31 +01:00
BigInteger i_authKey = new BigInteger ( 1 , encryptedChat . g_a_or_b ) ;
if ( ! Utilities . isGoodGaAndGb ( i_authKey , p ) ) {
declineSecretChat ( encryptedChat . id ) ;
return ;
}
i_authKey = i_authKey . modPow ( new BigInteger ( 1 , encryptedChat . a_or_b ) , p ) ;
byte [ ] authKey = i_authKey . toByteArray ( ) ;
if ( authKey . length > 256 ) {
byte [ ] correctedAuth = new byte [ 256 ] ;
System . arraycopy ( authKey , authKey . length - 256 , correctedAuth , 0 , 256 ) ;
authKey = correctedAuth ;
} else if ( authKey . length < 256 ) {
byte [ ] correctedAuth = new byte [ 256 ] ;
System . arraycopy ( authKey , 0 , correctedAuth , 256 - authKey . length , authKey . length ) ;
for ( int a = 0 ; a < 256 - authKey . length ; a + + ) {
2018-08-27 10:33:11 +02:00
correctedAuth [ a ] = 0 ;
2014-12-01 18:56:31 +01:00
}
authKey = correctedAuth ;
}
byte [ ] authKeyHash = Utilities . computeSHA1 ( authKey ) ;
byte [ ] authKeyId = new byte [ 8 ] ;
System . arraycopy ( authKeyHash , authKeyHash . length - 8 , authKeyId , 0 , 8 ) ;
long fingerprint = Utilities . bytesToLong ( authKeyId ) ;
if ( encryptedChat . key_fingerprint = = fingerprint ) {
encryptedChat . auth_key = authKey ;
2019-07-18 15:01:39 +02:00
encryptedChat . key_create_date = getConnectionsManager ( ) . getCurrentTime ( ) ;
2017-07-08 18:32:04 +02:00
encryptedChat . seq_in = - 2 ;
2014-12-01 18:56:31 +01:00
encryptedChat . seq_out = 1 ;
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . updateEncryptedChat ( encryptedChat ) ;
getMessagesController ( ) . putEncryptedChat ( encryptedChat , false ) ;
2019-12-31 14:08:08 +01:00
ArrayList < TLRPC . Update > pendingUpdates = pendingSecretMessages . get ( encryptedChat . id ) ;
if ( pendingUpdates ! = null ) {
getMessagesController ( ) . processUpdateArray ( pendingUpdates , null , null , false , 0 ) ;
pendingSecretMessages . remove ( encryptedChat . id ) ;
}
2018-08-27 10:33:11 +02:00
AndroidUtilities . runOnUIThread ( ( ) - > {
2019-07-18 15:01:39 +02:00
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . encryptedChatUpdated , encryptedChat ) ;
2018-08-27 10:33:11 +02:00
sendNotifyLayerMessage ( encryptedChat , null ) ;
2014-12-01 18:56:31 +01:00
} ) ;
} else {
final TLRPC . TL_encryptedChatDiscarded newChat = new TLRPC . TL_encryptedChatDiscarded ( ) ;
newChat . id = encryptedChat . id ;
newChat . user_id = encryptedChat . user_id ;
newChat . auth_key = encryptedChat . auth_key ;
newChat . key_create_date = encryptedChat . key_create_date ;
newChat . key_use_count_in = encryptedChat . key_use_count_in ;
newChat . key_use_count_out = encryptedChat . key_use_count_out ;
newChat . seq_in = encryptedChat . seq_in ;
newChat . seq_out = encryptedChat . seq_out ;
2017-03-31 01:58:05 +02:00
newChat . admin_id = encryptedChat . admin_id ;
2017-12-08 18:35:59 +01:00
newChat . mtproto_seq = encryptedChat . mtproto_seq ;
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . updateEncryptedChat ( newChat ) ;
2018-08-27 10:33:11 +02:00
AndroidUtilities . runOnUIThread ( ( ) - > {
2019-07-18 15:01:39 +02:00
getMessagesController ( ) . putEncryptedChat ( newChat , false ) ;
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . encryptedChatUpdated , newChat ) ;
2014-12-01 18:56:31 +01:00
} ) ;
declineSecretChat ( encryptedChat . id ) ;
}
}
public void declineSecretChat ( int chat_id ) {
TLRPC . TL_messages_discardEncryption req = new TLRPC . TL_messages_discardEncryption ( ) ;
req . chat_id = chat_id ;
2019-07-18 15:01:39 +02:00
getConnectionsManager ( ) . sendRequest ( req , ( response , error ) - > {
2014-12-01 18:56:31 +01:00
} ) ;
}
public void acceptSecretChat ( final TLRPC . EncryptedChat encryptedChat ) {
if ( acceptingChats . get ( encryptedChat . id ) ! = null ) {
return ;
}
acceptingChats . put ( encryptedChat . id , encryptedChat ) ;
TLRPC . TL_messages_getDhConfig req = new TLRPC . TL_messages_getDhConfig ( ) ;
req . random_length = 256 ;
2019-07-18 15:01:39 +02:00
req . version = getMessagesStorage ( ) . getLastSecretVersion ( ) ;
getConnectionsManager ( ) . sendRequest ( req , ( response , error ) - > {
2018-08-27 10:33:11 +02:00
if ( error = = null ) {
TLRPC . messages_DhConfig res = ( TLRPC . messages_DhConfig ) response ;
if ( response instanceof TLRPC . TL_messages_dhConfig ) {
if ( ! Utilities . isGoodPrime ( res . p , res . g ) ) {
2014-12-01 18:56:31 +01:00
acceptingChats . remove ( encryptedChat . id ) ;
declineSecretChat ( encryptedChat . id ) ;
return ;
}
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . setSecretPBytes ( res . p ) ;
getMessagesStorage ( ) . setSecretG ( res . g ) ;
getMessagesStorage ( ) . setLastSecretVersion ( res . version ) ;
getMessagesStorage ( ) . saveSecretParams ( getMessagesStorage ( ) . getLastSecretVersion ( ) , getMessagesStorage ( ) . getSecretG ( ) , getMessagesStorage ( ) . getSecretPBytes ( ) ) ;
2018-08-27 10:33:11 +02:00
}
byte [ ] salt = new byte [ 256 ] ;
for ( int a = 0 ; a < 256 ; a + + ) {
salt [ a ] = ( byte ) ( ( byte ) ( Utilities . random . nextDouble ( ) * 256 ) ^ res . random [ a ] ) ;
}
encryptedChat . a_or_b = salt ;
encryptedChat . seq_in = - 1 ;
encryptedChat . seq_out = 0 ;
2019-07-18 15:01:39 +02:00
BigInteger p = new BigInteger ( 1 , getMessagesStorage ( ) . getSecretPBytes ( ) ) ;
BigInteger g_b = BigInteger . valueOf ( getMessagesStorage ( ) . getSecretG ( ) ) ;
2018-08-27 10:33:11 +02:00
g_b = g_b . modPow ( new BigInteger ( 1 , salt ) , p ) ;
BigInteger g_a = new BigInteger ( 1 , encryptedChat . g_a ) ;
if ( ! Utilities . isGoodGaAndGb ( g_a , p ) ) {
acceptingChats . remove ( encryptedChat . id ) ;
declineSecretChat ( encryptedChat . id ) ;
return ;
}
2014-12-01 18:56:31 +01:00
2018-08-27 10:33:11 +02:00
byte [ ] g_b_bytes = g_b . toByteArray ( ) ;
if ( g_b_bytes . length > 256 ) {
byte [ ] correctedAuth = new byte [ 256 ] ;
System . arraycopy ( g_b_bytes , 1 , correctedAuth , 0 , 256 ) ;
g_b_bytes = correctedAuth ;
}
2014-12-01 18:56:31 +01:00
2018-08-27 10:33:11 +02:00
g_a = g_a . modPow ( new BigInteger ( 1 , salt ) , p ) ;
byte [ ] authKey = g_a . toByteArray ( ) ;
if ( authKey . length > 256 ) {
byte [ ] correctedAuth = new byte [ 256 ] ;
System . arraycopy ( authKey , authKey . length - 256 , correctedAuth , 0 , 256 ) ;
authKey = correctedAuth ;
} else if ( authKey . length < 256 ) {
byte [ ] correctedAuth = new byte [ 256 ] ;
System . arraycopy ( authKey , 0 , correctedAuth , 256 - authKey . length , authKey . length ) ;
for ( int a = 0 ; a < 256 - authKey . length ; a + + ) {
correctedAuth [ a ] = 0 ;
2014-12-01 18:56:31 +01:00
}
2018-08-27 10:33:11 +02:00
authKey = correctedAuth ;
2014-12-01 18:56:31 +01:00
}
2018-08-27 10:33:11 +02:00
byte [ ] authKeyHash = Utilities . computeSHA1 ( authKey ) ;
byte [ ] authKeyId = new byte [ 8 ] ;
System . arraycopy ( authKeyHash , authKeyHash . length - 8 , authKeyId , 0 , 8 ) ;
encryptedChat . auth_key = authKey ;
2019-07-18 15:01:39 +02:00
encryptedChat . key_create_date = getConnectionsManager ( ) . getCurrentTime ( ) ;
2018-08-27 10:33:11 +02:00
TLRPC . TL_messages_acceptEncryption req2 = new TLRPC . TL_messages_acceptEncryption ( ) ;
req2 . g_b = g_b_bytes ;
req2 . peer = new TLRPC . TL_inputEncryptedChat ( ) ;
req2 . peer . chat_id = encryptedChat . id ;
req2 . peer . access_hash = encryptedChat . access_hash ;
req2 . key_fingerprint = Utilities . bytesToLong ( authKeyId ) ;
2019-07-18 15:01:39 +02:00
getConnectionsManager ( ) . sendRequest ( req2 , ( response1 , error1 ) - > {
2018-08-27 10:33:11 +02:00
acceptingChats . remove ( encryptedChat . id ) ;
if ( error1 = = null ) {
final TLRPC . EncryptedChat newChat = ( TLRPC . EncryptedChat ) response1 ;
newChat . auth_key = encryptedChat . auth_key ;
newChat . user_id = encryptedChat . user_id ;
newChat . seq_in = encryptedChat . seq_in ;
newChat . seq_out = encryptedChat . seq_out ;
newChat . key_create_date = encryptedChat . key_create_date ;
newChat . key_use_count_in = encryptedChat . key_use_count_in ;
newChat . key_use_count_out = encryptedChat . key_use_count_out ;
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . updateEncryptedChat ( newChat ) ;
getMessagesController ( ) . putEncryptedChat ( newChat , false ) ;
2018-08-27 10:33:11 +02:00
AndroidUtilities . runOnUIThread ( ( ) - > {
2019-07-18 15:01:39 +02:00
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . encryptedChatUpdated , newChat ) ;
2018-08-27 10:33:11 +02:00
sendNotifyLayerMessage ( newChat , null ) ;
} ) ;
}
2019-12-31 14:08:08 +01:00
} , ConnectionsManager . RequestFlagInvokeAfter ) ;
2018-08-27 10:33:11 +02:00
} else {
acceptingChats . remove ( encryptedChat . id ) ;
2014-12-01 18:56:31 +01:00
}
} ) ;
}
public void startSecretChat ( final Context context , final TLRPC . User user ) {
2015-02-26 02:32:51 +01:00
if ( user = = null | | context = = null ) {
2014-12-01 18:56:31 +01:00
return ;
}
startingSecretChat = true ;
2019-01-23 18:03:33 +01:00
final AlertDialog progressDialog = new AlertDialog ( context , 3 ) ;
2014-12-01 18:56:31 +01:00
TLRPC . TL_messages_getDhConfig req = new TLRPC . TL_messages_getDhConfig ( ) ;
req . random_length = 256 ;
2019-07-18 15:01:39 +02:00
req . version = getMessagesStorage ( ) . getLastSecretVersion ( ) ;
final int reqId = getConnectionsManager ( ) . sendRequest ( req , ( response , error ) - > {
2018-08-27 10:33:11 +02:00
if ( error = = null ) {
TLRPC . messages_DhConfig res = ( TLRPC . messages_DhConfig ) response ;
if ( response instanceof TLRPC . TL_messages_dhConfig ) {
if ( ! Utilities . isGoodPrime ( res . p , res . g ) ) {
AndroidUtilities . runOnUIThread ( ( ) - > {
try {
if ( ! ( ( Activity ) context ) . isFinishing ( ) ) {
progressDialog . dismiss ( ) ;
2014-12-01 18:56:31 +01:00
}
2018-08-27 10:33:11 +02:00
} catch ( Exception e ) {
FileLog . e ( e ) ;
}
} ) ;
return ;
2014-12-01 18:56:31 +01:00
}
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . setSecretPBytes ( res . p ) ;
getMessagesStorage ( ) . setSecretG ( res . g ) ;
getMessagesStorage ( ) . setLastSecretVersion ( res . version ) ;
getMessagesStorage ( ) . saveSecretParams ( getMessagesStorage ( ) . getLastSecretVersion ( ) , getMessagesStorage ( ) . getSecretG ( ) , getMessagesStorage ( ) . getSecretPBytes ( ) ) ;
2018-08-27 10:33:11 +02:00
}
final byte [ ] salt = new byte [ 256 ] ;
for ( int a = 0 ; a < 256 ; a + + ) {
salt [ a ] = ( byte ) ( ( byte ) ( Utilities . random . nextDouble ( ) * 256 ) ^ res . random [ a ] ) ;
}
2014-12-01 18:56:31 +01:00
2019-07-18 15:01:39 +02:00
BigInteger i_g_a = BigInteger . valueOf ( getMessagesStorage ( ) . getSecretG ( ) ) ;
i_g_a = i_g_a . modPow ( new BigInteger ( 1 , salt ) , new BigInteger ( 1 , getMessagesStorage ( ) . getSecretPBytes ( ) ) ) ;
2018-08-27 10:33:11 +02:00
byte [ ] g_a = i_g_a . toByteArray ( ) ;
if ( g_a . length > 256 ) {
byte [ ] correctedAuth = new byte [ 256 ] ;
System . arraycopy ( g_a , 1 , correctedAuth , 0 , 256 ) ;
g_a = correctedAuth ;
}
2014-12-01 18:56:31 +01:00
2018-08-27 10:33:11 +02:00
TLRPC . TL_messages_requestEncryption req2 = new TLRPC . TL_messages_requestEncryption ( ) ;
req2 . g_a = g_a ;
2019-07-18 15:01:39 +02:00
req2 . user_id = getMessagesController ( ) . getInputUser ( user ) ;
2018-08-27 10:33:11 +02:00
req2 . random_id = Utilities . random . nextInt ( ) ;
2019-07-18 15:01:39 +02:00
getConnectionsManager ( ) . sendRequest ( req2 , ( response1 , error1 ) - > {
2018-08-27 10:33:11 +02:00
if ( error1 = = null ) {
AndroidUtilities . runOnUIThread ( ( ) - > {
2014-12-01 18:56:31 +01:00
startingSecretChat = false ;
if ( ! ( ( Activity ) context ) . isFinishing ( ) ) {
try {
progressDialog . dismiss ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2014-12-01 18:56:31 +01:00
}
}
2018-08-27 10:33:11 +02:00
TLRPC . EncryptedChat chat = ( TLRPC . EncryptedChat ) response1 ;
chat . user_id = chat . participant_id ;
chat . seq_in = - 2 ;
chat . seq_out = 1 ;
chat . a_or_b = salt ;
2019-07-18 15:01:39 +02:00
getMessagesController ( ) . putEncryptedChat ( chat , false ) ;
2019-05-14 14:08:05 +02:00
TLRPC . Dialog dialog = new TLRPC . TL_dialog ( ) ;
dialog . id = DialogObject . makeSecretDialogId ( chat . id ) ;
2018-08-27 10:33:11 +02:00
dialog . unread_count = 0 ;
dialog . top_message = 0 ;
2019-07-18 15:01:39 +02:00
dialog . last_message_date = getConnectionsManager ( ) . getCurrentTime ( ) ;
getMessagesController ( ) . dialogs_dict . put ( dialog . id , dialog ) ;
getMessagesController ( ) . allDialogs . add ( dialog ) ;
getMessagesController ( ) . sortDialogs ( null ) ;
getMessagesStorage ( ) . putEncryptedChat ( chat , user , dialog ) ;
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . dialogsNeedReload ) ;
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . encryptedChatCreated , chat ) ;
2018-08-27 10:33:11 +02:00
Utilities . stageQueue . postRunnable ( ( ) - > {
if ( ! delayedEncryptedChatUpdates . isEmpty ( ) ) {
2019-07-18 15:01:39 +02:00
getMessagesController ( ) . processUpdateArray ( delayedEncryptedChatUpdates , null , null , false , 0 ) ;
2018-08-27 10:33:11 +02:00
delayedEncryptedChatUpdates . clear ( ) ;
}
} ) ;
} ) ;
} else {
delayedEncryptedChatUpdates . clear ( ) ;
AndroidUtilities . runOnUIThread ( ( ) - > {
if ( ! ( ( Activity ) context ) . isFinishing ( ) ) {
startingSecretChat = false ;
try {
progressDialog . dismiss ( ) ;
} catch ( Exception e ) {
FileLog . e ( e ) ;
}
AlertDialog . Builder builder = new AlertDialog . Builder ( context ) ;
2020-03-29 13:42:09 +02:00
builder . setTitle ( LocaleController . getString ( " NekoX " , R . string . NekoX ) ) ;
2018-08-27 10:33:11 +02:00
builder . setMessage ( LocaleController . getString ( " CreateEncryptedChatError " , R . string . CreateEncryptedChatError ) ) ;
builder . setPositiveButton ( LocaleController . getString ( " OK " , R . string . OK ) , null ) ;
builder . show ( ) . setCanceledOnTouchOutside ( true ) ;
}
} ) ;
}
} , ConnectionsManager . RequestFlagFailOnServerErrors ) ;
} else {
delayedEncryptedChatUpdates . clear ( ) ;
AndroidUtilities . runOnUIThread ( ( ) - > {
startingSecretChat = false ;
if ( ! ( ( Activity ) context ) . isFinishing ( ) ) {
try {
progressDialog . dismiss ( ) ;
} catch ( Exception e ) {
FileLog . e ( e ) ;
2014-12-01 18:56:31 +01:00
}
2018-08-27 10:33:11 +02:00
}
} ) ;
2014-12-01 18:56:31 +01:00
}
2015-09-24 22:52:02 +02:00
} , ConnectionsManager . RequestFlagFailOnServerErrors ) ;
2019-07-18 15:01:39 +02:00
progressDialog . setOnCancelListener ( dialog - > getConnectionsManager ( ) . cancelRequest ( reqId , true ) ) ;
2015-02-26 15:36:15 +01:00
try {
progressDialog . show ( ) ;
} catch ( Exception e ) {
//don't promt
}
2014-12-01 18:56:31 +01:00
}
}