Skip to content

Commit

Permalink
chore: optimize RevokeMsgHook
Browse files Browse the repository at this point in the history
  • Loading branch information
cinit committed Jul 16, 2023
1 parent a641cee commit 4df14eb
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 38 deletions.
71 changes: 36 additions & 35 deletions app/src/main/java/cc/ioctl/hook/msg/RevokeMsgHook.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import android.view.View;
import androidx.annotation.Keep;
import androidx.annotation.NonNull;
import cc.hicore.QApp.QAppUtils;
import cc.ioctl.fragment.RevokeMsgConfigFragment;
import cc.ioctl.util.HookUtils;
import cc.ioctl.util.HostInfo;
Expand Down Expand Up @@ -178,40 +179,43 @@ public void setEnabled(boolean value) {

@Override
public boolean initOnce() throws Exception {
nativeInitNtKernelRecallMsgHook();
Method revokeMsg = null;
for (Method m : _QQMessageFacade().getDeclaredMethods()) {
if (m.getReturnType().equals(void.class)) {
Class<?>[] argt = m.getParameterTypes();
if (argt.length == 2 && argt[0].equals(ArrayList.class) && argt[1]
.equals(boolean.class)) {
revokeMsg = m;
break;
if (QAppUtils.isQQnt()) {
nativeInitNtKernelRecallMsgHook();
} else {
Method revokeMsg = null;
for (Method m : _QQMessageFacade().getDeclaredMethods()) {
if (m.getReturnType().equals(void.class)) {
Class<?>[] argt = m.getParameterTypes();
if (argt.length == 2 && argt[0].equals(ArrayList.class) && argt[1]
.equals(boolean.class)) {
revokeMsg = m;
break;
}
}
}
}
HookUtils.hookBeforeIfEnabled(this, revokeMsg, -10086, param -> {
mQQMsgFacade = param.thisObject;
ArrayList<?> list = (ArrayList<?>) param.args[0];
param.setResult(null);
if (list == null || list.isEmpty()) {
return;
}
for (Object revokeMsgInfo : list) {
try {
onRevokeMsg(revokeMsgInfo);
} catch (Exception | LinkageError | AssertionError t) {
traceError(t);
HookUtils.hookBeforeIfEnabled(this, revokeMsg, -10086, param -> {
mQQMsgFacade = param.thisObject;
ArrayList<?> list = (ArrayList<?>) param.args[0];
param.setResult(null);
if (list == null || list.isEmpty()) {
return;
}
}
list.clear();
});
for (Object revokeMsgInfo : list) {
try {
onRevokeMsgLegacy(revokeMsgInfo);
} catch (Exception | LinkageError | AssertionError t) {
traceError(t);
}
}
list.clear();
});
}
return true;
}

private native boolean nativeInitNtKernelRecallMsgHook();

private void onRevokeMsg(Object revokeMsgInfo) throws Exception {
private void onRevokeMsgLegacy(Object revokeMsgInfo) throws Exception {
RevokeMsgInfoImpl info = new RevokeMsgInfoImpl((Parcelable) revokeMsgInfo);
// 1. C2C chat session, istroop=0, RevokeMsgInfo is always the same on both side. e.g.
// istroop=0, shmsgseq=***(valid),
Expand Down Expand Up @@ -251,7 +255,7 @@ private void onRevokeMsg(Object revokeMsgInfo) throws Exception {
return;
}

Object msgObject = getMessage(aioSessionUin, istroop, shmsgseq, info.msgUid);
Object msgObject = getMessageLegacy(aioSessionUin, istroop, shmsgseq, info.msgUid);
// long id = getMessageUid(msgObject);
long newMsgUid;
if (info.msgUid != 0) {
Expand Down Expand Up @@ -392,15 +396,10 @@ private void onRecallSysMsgForNT(int chatType, String peerUid, String recallOpUi
Log.e("onRecallSysMsgForNT fatal: chatType is not c2c or troop");
return;
}
String operatorUin = RelationNTUinAndUidApi.getUinFromUid(recallOpUid);
// operatorUin may be empty, in the case when in a group chat, someone recalled a message by an admin or owner,
// but your NT kernel are not so familiar with the admin or owner, and it doesn't know the uin of the admin or owner.
String selfUin = AppRuntimeHelper.getAccount();
String selfUid = RelationNTUinAndUidApi.getUidFromUin(selfUin);
if (TextUtils.isEmpty(operatorUin)) {
Log.e("onRecallSysMsgForNT fatal: recallOpUin is empty");
// dump all available info
Log.e("onRecallSysMsgForNT dump: chatType=" + chatType + ", peerUid=" + peerUid + ", recallOpUid=" + recallOpUid + ", toUid=" + toUid + ", random64=" + random64 + ", timeSeconds=" + timeSeconds + ", msgUid=" + msgUid + ", msgSeq=" + msgSeq + ", msgClientSeq=" + msgClientSeq + ", operatorUin=" + operatorUin + ", selfUin=" + selfUin + ", selfUid=" + selfUid);
return;
}
if (TextUtils.isEmpty(selfUid)) {
Log.e("onRecallSysMsgForNT fatal: selfUid is empty");
return;
Expand Down Expand Up @@ -447,6 +446,8 @@ private void onRecallSysMsgForNT(int chatType, String peerUid, String recallOpUi
}
} else if (chatType == ChatTypeConstants.GROUP) {
String operatorName = ContactUtils.getDisplayNameForUid(recallOpUid, peerUid);
String operatorUin = RelationNTUinAndUidApi.getUinFromUid(recallOpUid);
// note: operatorUin may be empty, in the case when in a group chat, NT kernel are not so familiar with the one
// do we have the original message?
if (msgObject != null && !(msgObject.getMsgType() == 5 && msgObject.getSubMsgType() == 4)) {
// good, we have the original message
Expand Down Expand Up @@ -564,7 +565,7 @@ private void addHightlightItem(Object msgForGreyTip, int start, int end, Bundle
}
}

private Object getMessage(String uin, int istroop, long shmsgseq, long msgUid) {
private Object getMessageLegacy(String uin, int istroop, long shmsgseq, long msgUid) {
List<?> list = null;
try {
// message is query by shmsgseq, not by time ---> queryMessagesByShmsgseqFromDB
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,13 @@ public String toString() {

public static class UserItem implements Item {

// after testing, uin is not really required, but better to keep it
private final String mUin;
private final String mUid;
private final String mNick;

public UserItem(@NonNull String uin, @NonNull String uid, @NonNull String nick) {
mUin = requireValidUin(uin);
public UserItem(@Nullable String uin, @NonNull String uid, @NonNull String nick) {
mUin = uin;
mUid = requireValidUid(uid);
mNick = Objects.requireNonNull(nick);
}
Expand All @@ -115,7 +116,9 @@ public JSONObject toJson() throws JSONException {
json.put("tp", "0");
json.put("type", "qq");
json.put("uid", mUid);
json.put("uin", mUin);
if (isValidateUin(mUin)) {
json.put("uin", mUin);
}
return json;
}

Expand Down Expand Up @@ -223,4 +226,23 @@ public static String requireValidUid(String uid) {
return uid;
}

public static boolean isValidateUid(String uid) {
if (TextUtils.isEmpty(uid)) {
return false;
}
return uid.length() == 24 && uid.startsWith("u_");
}

public static boolean isValidateUin(String uin) {
if (TextUtils.isEmpty(uin)) {
return false;
}
try {
// allow uid such as 9915
return Long.parseLong(uin) > 0;
} catch (NumberFormatException e) {
return false;
}
}

}

0 comments on commit 4df14eb

Please sign in to comment.