diff --git a/app/src/main/java/com/vk/im/ui/components/common/DialogAction.java b/app/src/main/java/com/vk/im/ui/components/common/DialogAction.java index ead3934b1..1079e7ef8 100644 --- a/app/src/main/java/com/vk/im/ui/components/common/DialogAction.java +++ b/app/src/main/java/com/vk/im/ui/components/common/DialogAction.java @@ -33,5 +33,7 @@ public enum DialogAction { DNT_ON, DNT_OFF, pinmsg, - unpinmsg + unpinmsg, + ENCRYPT_SETT, + ENCRYPT } diff --git a/app/src/main/java/ru/vtosters/lite/dnr/DNRInjector.java b/app/src/main/java/ru/vtosters/lite/dnr/DNRInjector.java index 5ccf34e46..c014d2eca 100644 --- a/app/src/main/java/ru/vtosters/lite/dnr/DNRInjector.java +++ b/app/src/main/java/ru/vtosters/lite/dnr/DNRInjector.java @@ -1,9 +1,12 @@ package ru.vtosters.lite.dnr; import static com.vk.im.engine.h.im_ic_done; +import static com.vk.im.engine.h.im_ic_edit_msg; +import static com.vk.im.engine.h.im_ic_more_vertical; import static com.vk.im.engine.h.im_ic_pinned_msg_hide; import static com.vk.im.engine.h.im_ic_pinned_msg_show; import static com.vk.im.engine.h.im_ic_write_msg; +import static com.vk.im.ui.c.im_ic_keyboard; import static ru.vtosters.lite.dnr.DNRModule.hookDNR; import static ru.vtosters.lite.dnr.DNRModule.hookDNT; import static ru.vtosters.lite.dnr.DNRModule.isDnrEnabledFor; @@ -37,6 +40,9 @@ import java.util.List; import okhttp3.Headers; import okhttp3.OkHttpClient; import okhttp3.Request; +import ru.vtosters.lite.encryption.EncryptProvider; +import ru.vtosters.lite.encryption.base.IMProcessor; +import ru.vtosters.lite.hooks.CryptImHook; import ru.vtosters.lite.ui.dialogs.Translate; import ru.vtosters.lite.utils.AndroidUtils; @@ -44,30 +50,39 @@ public class DNRInjector { public static void inject(Dialog dialog, List list) { int peerId = dialog.getId(); - list.add(DialogAction.valueOf("pinmsg")); - list.add(DialogAction.valueOf("unpinmsg")); + list.add(DialogAction.pinmsg); + list.add(DialogAction.unpinmsg); if (isDnrEnabledFor(peerId)) { - list.add(DialogAction.valueOf("DNR_OFF")); + list.add(DialogAction.DNR_OFF); } else { - list.add(DialogAction.valueOf("DNR_ON")); + list.add(DialogAction.DNR_ON); } if (isDntEnabledFor(peerId)) { - list.add(DialogAction.valueOf("DNT_OFF")); + list.add(DialogAction.DNT_OFF); } else { - list.add(DialogAction.valueOf("DNT_ON")); + list.add(DialogAction.DNT_ON); + } + + list.add(DialogAction.ENCRYPT); + IMProcessor prov = EncryptProvider.getProcessorFor(peerId); + if (prov != null && !prov.isPublic()) { + list.add(DialogAction.ENCRYPT_SETT); } } public static LinkedHashMap injectToHashMap(LinkedHashMap hashMap) { - hashMap.put(DialogAction.valueOf("DNR_ON"), getIdentifier("DNR_ON", "string")); - hashMap.put(DialogAction.valueOf("DNR_OFF"), getIdentifier("DNR_OFF", "string")); - hashMap.put(DialogAction.valueOf("DNT_ON"), getIdentifier("DNT_ON", "string")); - hashMap.put(DialogAction.valueOf("DNT_OFF"), getIdentifier("DNT_OFF", "string")); + hashMap.put(DialogAction.DNR_ON, getIdentifier("DNR_ON", "string")); + hashMap.put(DialogAction.DNR_OFF, getIdentifier("DNR_OFF", "string")); + hashMap.put(DialogAction.DNT_ON, getIdentifier("DNT_ON", "string")); + hashMap.put(DialogAction.DNT_OFF, getIdentifier("DNT_OFF", "string")); - hashMap.put(DialogAction.valueOf("pinmsg"), getIdentifier("pinmsg", "string")); - hashMap.put(DialogAction.valueOf("unpinmsg"), getIdentifier("unpinmsg", "string")); + hashMap.put(DialogAction.ENCRYPT, getIdentifier("encryption", "string")); + hashMap.put(DialogAction.ENCRYPT_SETT, getIdentifier("encryption_sett", "string")); + + hashMap.put(DialogAction.pinmsg, getIdentifier("pinmsg", "string")); + hashMap.put(DialogAction.unpinmsg, getIdentifier("unpinmsg", "string")); return hashMap; } @@ -78,10 +93,13 @@ public class DNRInjector { list.add(new DialogActionsListView.b.a(DialogAction.DNR_ON, 2, im_ic_pinned_msg_hide, getIdentifier("DNR_ON", "string"))); // DialogAction, Int, Icon, String list.add(new DialogActionsListView.b.a(DialogAction.DNR_OFF, 2, im_ic_pinned_msg_show, getIdentifier("DNR_OFF", "string"))); // DialogAction, Int, Icon, String - list.add(new DialogActionsListView.b.a(DialogAction.DNT_ON, 2, im_ic_write_msg, getIdentifier("DNT_ON", "string"))); // DialogAction, Int, Icon, String - list.add(new DialogActionsListView.b.a(DialogAction.DNT_OFF, 2, im_ic_write_msg, getIdentifier("DNT_OFF", "string"))); // DialogAction, Int, Icon, String + list.add(new DialogActionsListView.b.a(DialogAction.DNT_ON, 2, im_ic_edit_msg, getIdentifier("DNT_ON", "string"))); // DialogAction, Int, Icon, String + list.add(new DialogActionsListView.b.a(DialogAction.DNT_OFF, 2, im_ic_edit_msg, getIdentifier("DNT_OFF", "string"))); // DialogAction, Int, Icon, String - list.add(new DialogActionsListView.b.a(DialogAction.MARK_AS_READ, 3, im_ic_done, getIdentifier("vkim_dialogs_list_option_mark_as_read", "string"))); // DialogAction, Int, Icon, String + list.add(new DialogActionsListView.b.a(DialogAction.ENCRYPT, 3, im_ic_keyboard, getIdentifier("encryption", "string"))); // DialogAction, Int, Icon, String + list.add(new DialogActionsListView.b.a(DialogAction.ENCRYPT_SETT, 3, im_ic_more_vertical, getIdentifier("encryption_sett", "string"))); // DialogAction, Int, Icon, String + + list.add(new DialogActionsListView.b.a(DialogAction.MARK_AS_READ, 4, im_ic_done, getIdentifier("vkim_dialogs_list_option_mark_as_read", "string"))); // DialogAction, Int, Icon, String return list; } @@ -107,6 +125,12 @@ public class DNRInjector { actions.add(DialogAction.DNT_ON); } + actions.add(DialogAction.ENCRYPT); + IMProcessor prov = EncryptProvider.getProcessorFor(peerId); + if (prov != null && !prov.isPublic()) { + actions.add(DialogAction.ENCRYPT_SETT); + } + actions.add(DialogAction.MARK_AS_READ); return actions; } @@ -139,40 +163,56 @@ public class DNRInjector { return true; } + if (action == DialogAction.ENCRYPT_SETT) { + CryptImHook.hookPref(id); + return true; + } else if (action == DialogAction.ENCRYPT) { + CryptImHook.hook(id, dialog); + return true; + } + return false; } public static boolean onClick(Dialog dialog, DialogAction action) { var id = dialog.getId(); - if (action == DialogAction.valueOf("MARK_AS_READ")) { + if (action == DialogAction.MARK_AS_READ) { DNRModule.hookRead(dialog); } - if (action == DialogAction.valueOf("DNR_ON")) { + if (action == DialogAction.DNR_ON) { setDnr(dialog, true); return true; - } else if (action == DialogAction.valueOf("DNR_OFF")) { + } else if (action == DialogAction.DNR_OFF) { setDnr(dialog, false); return true; } - if (action == DialogAction.valueOf("DNT_ON")) { + if (action == DialogAction.DNT_ON) { setDnt(dialog, true); return true; - } else if (action == DialogAction.valueOf("DNT_OFF")) { + } else if (action == DialogAction.DNT_OFF) { setDnt(dialog, false); return true; } - if (action == DialogAction.valueOf("pinmsg")) { + if (action == DialogAction.pinmsg) { pinnedMsg(id, true); return true; - } else if (action == DialogAction.valueOf("unpinmsg")) { + } else if (action == DialogAction.unpinmsg) { pinnedMsg(id, false); return true; } + if (action == DialogAction.ENCRYPT_SETT) { + CryptImHook.hookPref(id); + return true; + } else if (action == DialogAction.ENCRYPT) { + CryptImHook.hook(id, dialog); + return true; + } + return false; } diff --git a/app/src/main/java/ru/vtosters/lite/hooks/CryptImHook.java b/app/src/main/java/ru/vtosters/lite/hooks/CryptImHook.java new file mode 100644 index 000000000..e110faebc --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/hooks/CryptImHook.java @@ -0,0 +1,117 @@ +package ru.vtosters.lite.hooks; +import static ru.vtosters.lite.dnr.DNRInjector.forceInvalidateDialogActions; +import static ru.vtosters.lite.utils.AndroidUtils.dp2px; +import static ru.vtosters.lite.utils.AndroidUtils.sendToast; +import static ru.vtosters.lite.utils.LifecycleUtils.getCurrentActivity; + +import android.content.Context; +import android.content.res.ColorStateList; +import android.text.Editable; +import android.util.Log; +import android.view.ViewGroup; +import android.widget.EditText; +import android.widget.LinearLayout; + +import androidx.appcompat.app.AlertDialog; + +import com.vk.im.engine.models.dialogs.Dialog; + +import java.util.List; + +import ru.vtosters.lite.encryption.EncryptProvider; +import ru.vtosters.lite.encryption.base.IMProcessor; +import ru.vtosters.lite.utils.ThemesUtils; + +public class CryptImHook{ + public static boolean isPrivateProcessor(int peerID){ + for (IMProcessor processor : EncryptProvider.processors) { + if (processor.isUsedToEncrypt(peerID)) { + return !processor.isPublic(); + } + } + + return false; + } + + public static void hook(int peerId, Dialog d){ + List processors = EncryptProvider.processors; + + IMProcessor enabled = null; + int enabledPosition = 0; + + String[] titles = new String[processors.size() + 1]; + titles[0] = "Отключить шифрование"; + + for (int i = 0; i < processors.size(); i++) { + IMProcessor proc = processors.get(i); + + titles[i + 1] = proc.getUIName(); + + if (proc.isUsedToEncrypt(peerId)) { + enabled = proc; + enabledPosition = i + 1; + } + } + + Log.e("CryptImHook", "crash2 " + titles.length + " " + enabledPosition); + + IMProcessor finalEnabled = enabled; + new AlertDialog.Builder(getCurrentActivity()) + .setTitle("Настройки шифрования") + .setSingleChoiceItems(titles, enabledPosition, (dialog, which) -> { + if (which == 0) { + if (finalEnabled != null) finalEnabled.disableEncryptFor(peerId); + } else { + IMProcessor proc = processors.get(which - 1); + + if (proc.isUsedToEncrypt(peerId)) { + proc.disableEncryptFor(peerId); + } else { + proc.enableEncryptFor(peerId); + if (finalEnabled != null) finalEnabled.disableEncryptFor(peerId); + } + } + + dialog.dismiss(); + forceInvalidateDialogActions(d); + }).create().show(); + } + + public static void hookPref(int peerId){ + IMProcessor enabled = null; + for (IMProcessor processor : EncryptProvider.processors) { + if (processor.isUsedToEncrypt(peerId)) { + enabled = processor; + } + } + + if (enabled != null && enabled.isPublic()) { + sendToast("Выбранный алгоритм публичный и не имеет настроек!"); + return; + } + + Context ctx = getCurrentActivity(); + + LinearLayout linearLayout = new LinearLayout(ctx); + + final EditText editText = new EditText(ctx); + editText.setHintTextColor(ThemesUtils.getSTextAttr()); + editText.setBackgroundTintList(ColorStateList.valueOf(ThemesUtils.getSTextAttr())); + + linearLayout.addView(editText); + editText.getLayoutParams().width = ViewGroup.LayoutParams.MATCH_PARENT; + ViewGroup.MarginLayoutParams margin = ((ViewGroup.MarginLayoutParams) editText.getLayoutParams()); + margin.setMargins(dp2px(24f), 0, dp2px(24f), 0); + editText.setLayoutParams(margin); + + IMProcessor finalEnabled = enabled; + new AlertDialog.Builder(ctx) + .setTitle("Введите ключ шифрования") + .setMessage("Используемый алгоритм: " + enabled.getUIName() + ".\nУчтите, что если поле будет пустым, то будет использоваться ключ по умолчанию.") + .setView(linearLayout) + .setPositiveButton(android.R.string.ok, (dialog, which) -> { + Editable edit = editText.getText(); + finalEnabled.setEncryptionKeyFor(peerId, edit == null ? null : edit.toString()); + }).setNegativeButton(android.R.string.cancel, null).create().show(); + } +} \ No newline at end of file diff --git a/app/src/main/java/ru/vtosters/lite/hooks/MainActivityInjector.java b/app/src/main/java/ru/vtosters/lite/hooks/MainActivityInjector.java index a4fa61a3f..802494156 100644 --- a/app/src/main/java/ru/vtosters/lite/hooks/MainActivityInjector.java +++ b/app/src/main/java/ru/vtosters/lite/hooks/MainActivityInjector.java @@ -4,7 +4,6 @@ import static ru.vtosters.lite.ui.dialogs.ServerDialog.sendRequest; import static ru.vtosters.lite.utils.CacheUtils.getInstance; import static ru.vtosters.lite.utils.DeletedMessagesHandler.reloadMessagesList; import static ru.vtosters.lite.utils.Preferences.checkupdates; -import static ru.vtosters.lite.utils.ProxyUtils.setProxy; import static ru.vtosters.lite.utils.ThemesUtils.isDarkTheme; import static ru.vtosters.lite.utils.ThemesUtils.setNeededTheme; @@ -22,7 +21,6 @@ import ru.vtosters.lite.ui.dialogs.Start; public class MainActivityInjector { public static void inject(Activity activity) { - setProxy(); setNeededTheme(activity); ServerDialog.activity = activity; sendRequest(); diff --git a/smali/res/values-ru/strings.xml b/smali/res/values-ru/strings.xml index 8b3938fc5..75f594487 100644 --- a/smali/res/values-ru/strings.xml +++ b/smali/res/values-ru/strings.xml @@ -6151,4 +6151,7 @@ Engrave фильтр Flea фильтр Эффект снега - + + Метод шифрования + Настройки шифрования + \ No newline at end of file diff --git a/smali/res/values/strings.xml b/smali/res/values/strings.xml index f71a59215..7d61b90d0 100644 --- a/smali/res/values/strings.xml +++ b/smali/res/values/strings.xml @@ -6289,4 +6289,7 @@ May look like a fake leaving the online" Engrave filter Flea filter Snow effect + + Encryption method + Encryption settings diff --git a/smali/smali_classes4/com/vtosters/lite/VKApplication.smali b/smali/smali_classes4/com/vtosters/lite/VKApplication.smali index ec40f57d9..9ffa51c4a 100644 --- a/smali/smali_classes4/com/vtosters/lite/VKApplication.smali +++ b/smali/smali_classes4/com/vtosters/lite/VKApplication.smali @@ -2519,6 +2519,8 @@ .method public onCreate()V .locals 11 + invoke-static {p0}, Lru/vtosters/lite/utils/Preferences;->init(Landroid/app/Application;)V + .line 1 invoke-static {p0}, Lcom/squareup/leakcanary/LeakCanary;->isInAnalyzerProcess(Landroid/content/Context;)Z