Search in sources :

Example 6 with XC_MethodHook

use of de.robv.android.xposed.XC_MethodHook in project Unblock163MusicClient-Xposed by bin456789.

the class Main method handleLoadPackage.

public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {
    if (Handler.isDomainExpired())
        return;
    if (lpparam.packageName.equals(BuildConfig.APPLICATION_ID)) {
        // make current module activated
        findAndHookMethod(findClass(SettingsActivity.class.getName(), lpparam.classLoader), "getActivatedModuleVersion", XC_MethodReplacement.returnConstant(BuildConfig.VERSION_CODE));
    }
    if (lpparam.packageName.equals(CloudMusicPackage.PACKAGE_NAME)) {
        findAndHookMethod(Application.class, "attach", Context.class, new XC_MethodHook() {

            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                CloudMusicPackage.init((Context) param.thisObject);
                // main
                findAndHookMethod(CloudMusicPackage.HttpEapi.getClazz(), "a", String.class, new XC_MethodHook() {

                    @Override
                    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                        String original = (String) param.getResult();
                        if (TextUtils.isEmpty(original))
                            return;
                        String path = new CloudMusicPackage.HttpEapi(param.thisObject).getPath();
                        String modified = null;
                        if (path.startsWith("batch") || path.startsWith("album/privilege") || path.startsWith("artist/privilege") || path.startsWith("playlist/privilege") || path.startsWith("song/enhance/privilege") || path.startsWith("v1/artist") || path.startsWith("v1/album") || path.startsWith("v1/discovery/new/songs") || path.startsWith("v1/discovery/recommend/songs") || path.startsWith("v1/play/record") || path.startsWith("v1/search/get") || path.startsWith("v3/playlist/detail") || path.startsWith("v3/song/detail")) {
                            modified = Handler.modifyByRegex(original);
                            if (path.startsWith("batch")) {
                                Handler.cacheLikePlaylistId(original, param.thisObject);
                            }
                        } else if (path.startsWith("song/enhance/player/url")) {
                            modified = Handler.modifyPlayerOrDownloadApi(original, param.thisObject, "player");
                        } else if (path.startsWith("song/enhance/download/url")) {
                            modified = Handler.modifyPlayerOrDownloadApi(original, param.thisObject, "download");
                        } else if (path.startsWith("v1/playlist/manipulate/tracks")) {
                            modified = Handler.modifyPlaylistManipulateApi(original, param.thisObject);
                        } else if (path.startsWith("song/like")) {
                            modified = Handler.modifyLike(original, param.thisObject);
                        } else if (path.startsWith("cloud/pub/v2")) {
                            modified = Handler.modifyPub(original, param.thisObject);
                        }
                        if (modified != null) {
                            param.setResult(modified);
                        }
                    }
                });
                // save latest post data
                try {
                    findAndHookConstructor(CloudMusicPackage.HttpEapi.getClazz(), String.class, Map.class, String.class, boolean.class, new XC_MethodHook() {

                        @SuppressWarnings("unchecked")
                        @Override
                        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                            CloudMusicPackage.HttpEapi httpEapi = new CloudMusicPackage.HttpEapi(param.thisObject);
                            httpEapi.setPath((String) param.args[0]);
                            httpEapi.setRequestMap((Map<String, String>) param.args[1]);
                        }
                    });
                } catch (Throwable t) {
                    XposedBridge.log(t);
                }
                // replace md5
                XC_MethodHook replaceMd5 = new XC_MethodHook() {

                    final Pattern REX_MD5 = Pattern.compile("[a-f0-9]{32}", Pattern.CASE_INSENSITIVE);

                    @Override
                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                        String path = param.args[0] instanceof File ? ((File) param.args[0]).getPath() : param.args[0].toString();
                        Matcher matcher = REX_MD5.matcher(path);
                        if (matcher.find())
                            param.setResult(matcher.group());
                    }
                };
                try {
                    if (CloudMusicPackage.version.startsWith("3")) {
                        findAndHookMethod(CloudMusicPackage.NeteaseMusicUtils.getClazz(), "a", String.class, replaceMd5);
                    } else {
                        hookMethod(CloudMusicPackage.Transfer.getCalcMd5Method(), replaceMd5);
                    }
                } catch (Throwable t) {
                    XposedBridge.log(t);
                }
                // dislike confirm
                if (Settings.isConfirmDislikeEnabled()) {
                    try {
                        hookMethod(CloudMusicPackage.PlayerActivity.getLikeButtonOnClickMethod(), new XC_MethodHook() {

                            @Override
                            protected void beforeHookedMethod(final MethodHookParam param) throws Throwable {
                                Activity currentActivity = (Activity) getObjectField(param.thisObject, "a");
                                if (CloudMusicPackage.PlayerActivity.getClazz().isInstance(currentActivity)) {
                                    Object musicInfo = new CloudMusicPackage.PlayerActivity(currentActivity).getMusicInfo();
                                    long musicId = new CloudMusicPackage.MusicInfo(musicInfo).getMatchedMusicId();
                                    boolean isStarred = CloudMusicPackage.MusicInfo.isStarred(musicId);
                                    if (isStarred) {
                                        callStaticMethod(CloudMusicPackage.UIAA.getClazz(), "a", currentActivity, "确定不再收藏此歌曲吗?", "不再收藏", new View.OnClickListener() {

                                            @Override
                                            public void onClick(View v) {
                                                try {
                                                    XposedBridge.invokeOriginalMethod(param.method, param.thisObject, param.args);
                                                } catch (Throwable t) {
                                                    XposedBridge.log(t);
                                                }
                                            }
                                        });
                                        param.setResult(null);
                                    }
                                }
                            }
                        });
                    } catch (Throwable t) {
                        XposedBridge.log(t);
                    }
                }
                // off-shelf tips in quality-selected window
                try {
                    hookMethod(CloudMusicPackage.UIAA.getQualityBoxMethod(), new XC_MethodHook() {

                        @Override
                        protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                            Object currentActivity = param.args[0];
                            if (CloudMusicPackage.PlayerActivity.getClazz().isInstance(currentActivity)) {
                                Object musicInfo = new CloudMusicPackage.PlayerActivity(currentActivity).getMusicInfo();
                                if (!(boolean) callMethod(musicInfo, "hasCopyRight")) {
                                    SpannableString ssOld = (SpannableString) param.args[1];
                                    SpannableString ssNew = new SpannableString(ssOld.toString().replace("付费独享", "下架歌曲"));
                                    Object[] spans = ssOld.getSpans(0, ssOld.length(), Object.class);
                                    for (Object span : spans) {
                                        ssNew.setSpan(span, ssOld.getSpanStart(span), ssOld.getSpanEnd(span), ssOld.getSpanFlags(span));
                                    }
                                    param.args[1] = ssNew;
                                }
                            }
                        }
                    });
                } catch (Throwable t) {
                    XposedBridge.log(t);
                }
                // 3rd party
                try {
                    hookAllMethods(findClass(CloudMusicPackage.HttpEapi.getClazz().getPackage().getName() + ".a$1", lpparam.classLoader), "determineRoute", new XC_MethodHook() {

                        final Class HttpHost = findMamClass(org.apache.http.HttpHost.class);

                        final Class HttpRequestBase = findMamClass(org.apache.http.client.methods.HttpRequestBase.class);

                        final Class HttpRoute = findMamClass(org.apache.http.conn.routing.HttpRoute.class);

                        final String xapiHost = URI.create(Handler.XAPI).getHost();

                        @Override
                        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                            Object paramHttpRequest = param.args[1];
                            Object originalHttpRequest = callMethod(paramHttpRequest, "getOriginal");
                            Object resultHttpRoute = param.getResult();
                            if (HttpRequestBase.isInstance(originalHttpRequest)) {
                                URI url = (URI) callMethod(originalHttpRequest, "getURI");
                                String host = url.getHost();
                                // 防止 SocketTimeoutException 造成假死
                                int timeout = (host.endsWith("163.com") || host.endsWith(xapiHost)) ? 10000 : 3000;
                                Object requestParams = callMethod(callMethod(paramHttpRequest, "getParams"), "getRequestParams");
                                callMethod(requestParams, "setParameter", "http.socket.timeout", timeout);
                                if (host.endsWith("126.net") || host.endsWith("163.com"))
                                    return;
                                // cookie 处理
                                if (host.endsWith(xapiHost)) {
                                    // 需要发送cookie到自己的服务器
                                    String cookieString = String.format("modver=%s;%s", BuildConfig.VERSION_NAME, CloudMusicPackage.HttpEapi.getDefaultCookie());
                                    callMethod(originalHttpRequest, "setHeader", "Cookie", cookieString);
                                } else {
                                    // 避免发送网易cookie到xiami, qq ...
                                    callMethod(originalHttpRequest, "removeHeaders", "Cookie");
                                    callMethod(originalHttpRequest, "removeHeaders", "Referer");
                                }
                                // 避免开通联通流量包后听不了
                                if (callMethod(resultHttpRoute, "getProxyHost") != null) {
                                    if (host.endsWith("xiami.com") || (host.endsWith("alicdn.com"))) {
                                        callMethod(originalHttpRequest, "setHeader", "Authorization", "Basic MzAwMDAwNDU5MDpGRDYzQTdBNTM0NUMxMzFF");
                                    } else if (host.endsWith("qq.com")) {
                                        callMethod(originalHttpRequest, "removeHeaders", "Authorization");
                                        callMethod(paramHttpRequest, "setURI", URI.create(url.toString().replace("http:/", "")));
                                        Object newHttpHost = newInstance(HttpHost, "gd.unicommusic.gtimg.com", 8080);
                                        Object newHttpRoute = newInstance(HttpRoute, newHttpHost, null, false);
                                        param.setResult(newHttpRoute);
                                    } else if (host.endsWith("imusicapp.cn")) {
                                    // do nothing for now
                                    } else {
                                        // remove proxy
                                        callMethod(originalHttpRequest, "removeHeaders", "Authorization");
                                        callMethod(paramHttpRequest, "setURI", URI.create(url.getPath()));
                                        Object newHttpHost = newInstance(HttpHost, host);
                                        Object newHttpRoute = newInstance(HttpRoute, newHttpHost, null, false);
                                        param.setResult(newHttpRoute);
                                    }
                                }
                            }
                        }
                    });
                } catch (Throwable t) {
                    XposedBridge.log(t);
                }
                // 3rd party source tips
                XC_MethodHook set3rdStr = new XC_MethodHook() {

                    @Override
                    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                        Object musicInfo = param.thisObject;
                        String thirdTitle = new CloudMusicPackage.MusicInfo(musicInfo).get3rdSourceString();
                        if (thirdTitle != null) {
                            String original = (String) param.getResult();
                            boolean needToAppendSpace = "getThirdTitle".equals(param.method.getName());
                            if (needToAppendSpace) {
                                thirdTitle = " " + thirdTitle;
                            }
                            String modified = TextUtils.isEmpty(original) ? thirdTitle : original + thirdTitle;
                            param.setResult(modified);
                        }
                    }
                };
                try {
                    findAndHookMethod(CloudMusicPackage.MusicInfo.getClazz(), "getAppendCopyRight", set3rdStr);
                } catch (Throwable t) {
                    XposedBridge.log(t);
                }
                if (CloudMusicPackage.version.compareTo("3.4") >= 0) {
                    try {
                        findAndHookMethod(CloudMusicPackage.MusicInfo.getClazz(), "getThirdTitle", boolean.class, set3rdStr);
                    } catch (Throwable t) {
                        XposedBridge.log(t);
                    }
                }
                // oversea mode
                if (Settings.isOverseaModeEnabled()) {
                    try {
                        final Class AbstractHttpClient = findMamClass(org.apache.http.impl.client.AbstractHttpClient.class);
                        final Class HttpUriRequest = findMamClass(org.apache.http.client.methods.HttpUriRequest.class);
                        final Class HttpRequestBase = findMamClass(org.apache.http.client.methods.HttpRequestBase.class);
                        findAndHookMethod(AbstractHttpClient, "execute", HttpUriRequest, new XC_MethodHook() {

                            @Override
                            protected void beforeHookedMethod(MethodHookParam param) throws URISyntaxException, TextParseException, UnknownHostException {
                                if (HttpRequestBase.isInstance(param.args[0])) {
                                    Object httpRequestBase = param.args[0];
                                    URI uri = (URI) callMethod(httpRequestBase, "getURI");
                                    String host = uri.getHost();
                                    // solve server ip point to 1.1.1.1
                                    if ("m2.music.126.net".equals(host)) {
                                        String ip = Utility.getIpByHost(host);
                                        URI newUrl = new URI(uri.getScheme(), uri.getUserInfo(), ip, uri.getPort(), uri.getRawPath(), uri.getRawQuery(), uri.getRawFragment());
                                        callMethod(httpRequestBase, "setURI", newUrl);
                                        callMethod(httpRequestBase, "setHeader", "Host", host);
                                    }
                                }
                            }
                        });
                    } catch (Throwable t) {
                        XposedBridge.log(t);
                    }
                }
                if (Settings.isPreventGray()) {
                    try {
                        findAndHookMethod(CloudMusicPackage.MusicInfo.getClazz(), "hasCopyRight", new XC_MethodHook() {

                            @Override
                            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                                if (!Utility.isCallFromMyself()) {
                                    param.setResult(true);
                                }
                            }
                        });
                    } catch (Throwable t) {
                        XposedBridge.log(t);
                    }
                }
            }
        });
    }
}
Also used : XC_MethodHook(de.robv.android.xposed.XC_MethodHook) Matcher(java.util.regex.Matcher) SettingsActivity(bin.xposed.Unblock163MusicClient.ui.SettingsActivity) Activity(android.app.Activity) SpannableString(android.text.SpannableString) URI(java.net.URI) Context(android.content.Context) Pattern(java.util.regex.Pattern) View(android.view.View) SpannableString(android.text.SpannableString) XposedHelpers.findClass(de.robv.android.xposed.XposedHelpers.findClass) Mam.findMamClass(bin.xposed.Unblock163MusicClient.CloudMusicPackage.Mam.findMamClass) Map(java.util.Map) File(java.io.File)

Aggregations

XC_MethodHook (de.robv.android.xposed.XC_MethodHook)6 Context (android.content.Context)2 Intent (android.content.Intent)2 ClassNotFoundError (de.robv.android.xposed.XposedHelpers.ClassNotFoundError)2 XposedHelpers.findClass (de.robv.android.xposed.XposedHelpers.findClass)2 File (java.io.File)2 SuppressLint (android.annotation.SuppressLint)1 Activity (android.app.Activity)1 SpannableString (android.text.SpannableString)1 View (android.view.View)1 Window (android.view.Window)1 ImageView (android.widget.ImageView)1 TextView (android.widget.TextView)1 Mam.findMamClass (bin.xposed.Unblock163MusicClient.CloudMusicPackage.Mam.findMamClass)1 SettingsActivity (bin.xposed.Unblock163MusicClient.ui.SettingsActivity)1 BufferedReader (java.io.BufferedReader)1 FileInputStream (java.io.FileInputStream)1 InputStreamReader (java.io.InputStreamReader)1 Field (java.lang.reflect.Field)1 Method (java.lang.reflect.Method)1