Sunday 11 October 2015

知乎 - DIY 问题重定向

今天我们来玩重定向游戏~

logout 知乎网页。 然后浏览 http://www.zhihu.com/question/20381025

就会看见 5 秒后将会跳转信息:


五秒过后, 跳去 www.zhihu.com/question/19694728?rf=20381025:



五秒过后, 又再跳去 www.zhihu.com/question/22447061?rf=19694728:



还没跳完,五秒过后, 又再跳去 www.zhihu.com/question/20135771?rf=22447061:



五秒过后, 跳去 www.zhihu.com/question/24531839?rf=20135771:



终于跳完 liao~ 是不是很好玩叻。当然你会觉得知乎 desgin 到酱真的是。。。

为什么我要强调 logout ? 因为 login 对知乎的重定向很大影响哦。如果没有 login, 以上所有的重定向都是交给了 js 来处理。 如果有 login,第一个重定向交给 302 处理 (所以你看不见第一页, 而是直接跳到第二页。

来证明一下,login 知乎后, 然后打开  http://www.zhihu.com/question/20381025



留意 URL bar, 是不是很奇怪叻, 直接 skip 掉 20381025 跳第二页。哦, 我还没讲上述 URL 的结构。

http://www.zhihu.com/question/问题_ID?rf=上一个重定向问题_ID

就这样, rf 猜到就是 referer 的简称。

不止这个特别,还会出现从什么问题跳转过来的信息。这就是 login 的特别之处。不但 skip 掉第一个 302, 而且会留意从哪里来。

那么如果想看回重定向之前的那页怎么办 ? 只要来得及按 "从问题 xxxxx  跳转而来" 就能看回之前那页, 并且不再重定向。这种设计,用户怎么可能懂呢 ?

login 的影响 inconsistent 的 behavior 还没完。"从问题 xxxxx  跳转而来" 本身就是 URL 加上 nr=1, 即是 no-redirect 的简称。 如果你没有 login, 你看不见 "从问题 xxxxx  跳转而来" 这行字也就算了,可是如果你手动把 URL 加上 nr=1, 比如 www.zhihu.com/question/20381025?nr=1:


还是会再跳的哦, 也就是说 login 不仅仅影响 302+js 重定向以及 block 掉 rf 信息, 而且也不允许 nr 的功能。

当然我是能想到 302+js 的初衷。302 省一次重定向, 然后又不想用户完全不懂第一页的题目, 所以只 302 静悄悄重定向一次, 接下来就用 "从问题 xxxxx  跳转而来" + js 方法重定向下一页。至于为什么要 login only 就感觉像 bug 多一点。

你可能看不懂我讲什么鬼, 简单一句, 如果是 http://www.zhihu.com/question/问题_ID?rf=上一个重定向问题_ID 链接就加上 &nr=1, 改成
http://www.zhihu.com/question/问题_ID?rf=上一个重定向问题_ID&nr=1 ,如果是 http://www.zhihu.com/question/问题_ID 链接就改成 http://www.zhihu.com/question/问题_ID?nr=1, 并且在 login 的情况下,链接是不会自动重定向的哦。

接下来让我们 DIY 两种重定向规则。

先准备 google chrome 浏览器。目标是自制 chrome extension。

准备两个 file, hello_inject.js 以及 manifest.json 放在同一个 directory/folder:



hello_inject.js 源码:

chrome.webRequest.onBeforeRequest.addListener(
        function(details) {
                if (details.url && /^https?:\/\/www.zhihu.com\/question\/\d+/i.test(details.url)) {
                        var url = details.url;
                        var paramName = "nr";
                        var paramValue = "1";

                        var splitAtAnchor = url.split('#');
                        url = splitAtAnchor[0];
                        var anchor = typeof splitAtAnchor[1] === 'undefined' ? '' : '#' + splitAtAnchor[1];
                        if (url.indexOf(paramName + "=") >= 0) {
                                var prefix = url.substring(0, url.indexOf(paramName));
                                var suffix = url.substring(url.indexOf(paramName));
                                suffix = suffix.substring(suffix.indexOf("=") + 1);
                                suffix = (suffix.indexOf("&") >= 0) ? suffix.substring(suffix.indexOf("&")) : "";
                                url = prefix + paramName + "=" + paramValue + suffix;
                        }
                        else {
                                if (url.indexOf("?") < 0)
                                        url += "?" + paramName + "=" + paramValue;
                                else
                                        url += "&" + paramName + "=" + paramValue;
                        }
 
                        console.log("injected url: " + url + anchor);
                        return {redirectUrl: url + anchor};
                }
        },
        {urls: ["<all_urls>"]},
        ["blocking"]);


manifest.json 源码:

{
  "name": "URL Injector",
  "version": "1.0",
  "description": "Injet url.",
  "background": {
    "scripts": ["hello_inject.js"]
     },
   "manifest_version": 2,
   "permissions": [ "contextMenus", "storage", "webRequest", "webRequestBlocking", "tabs", "http://*/*", "https://*/*" ]
}


然后去 chrome://extensions, 右手边打勾 Developer mode, 然后按 Load unpacked extension...:


选你刚才那个 directory/folder, 按 Open:



源码有 console.log 函数, 所以要看 log 就按 background page 打开 debug 窗口,然后选 Console Tab:



login 情况下,然后浏览 http://www.zhihu.com/question/20381025



yeah, inject nr=1 成功 :)。现在每一跳问题都会自动加上 nr=1 不再跳转。当然, 必须 login 哟。

如果你不要 print log 就前面加上 // 来 comment out console.log,
//console.log("redirect url: " + url + anchor);

如果更改储存 hello_inject.js 源码文件后, 必须在 chrome://extensions/ 页面, Ctrl+r 更新 take effect。

另一种玩法是选择直接强迫它 302 redirect。原理就是依赖 login + 把 rf 丢掉。因前面研究过,我们已经懂第一页是 302, 特征就是第一页没有 rf 然后接下来有 rf。

hello_inject.js 源码:
chrome.webRequest.onBeforeRequest.addListener(
        function(details) {
                if (details.url && /^https?:\/\/www.zhihu.com\/question\//i.test(details.url)) {
                        var url = details.url;
                        var base = url.substring(0, url.indexOf("?"));
                        var queryString = url.substring(url.indexOf("?") + 1);
                        var params = queryString.split("&");
                        var valid_param = 0;
                        var invalid_param = 0;
                        for (var i = 0; i < params.length; i++) {
                                var p = params[i].split("=");
                                if ((params[i] !== p[0]) && ( p[0] == "rf" )) {
                                        invalid_param+=1;
                                } else {
                                        if (valid_param !== 0) {
                                                base+=params[i];
                                                valid_param+=1;
                                        } else {
                                                base = base + "?" + params[i];
                                        }
                                }
                        }
                        if (invalid_param !== 0) {
                                console.log("redirect base: " + base);
                                return {redirectUrl: base};
                        }
                }
        },
        {urls: ["<all_urls>"]},
        ["blocking"]);


Ctrl+r 更新 extension, login 情况下浏览 http://www.zhihu.com/question/20381025 就会直接 skip 到最后一页 24531839:




如果 Inspect element 检测, 就能看到 302 -> 307(Internal Redirect) -> 302 -> 307 -> 302 -> 307 -> 302 -> 307 skip 到最后一页 200 OK。省下中间的 download。











Saturday 3 October 2015

pdf - 如何丢掉图片


声明: 看过我的 blog 的人应该懂我几乎都不写这种教你下载看不到 source 或非官方的 exe,我写这篇文章主要是急救个朋友吧了,那个 exe 是不是恶意的我可不负责。

选择 1: 下载安装开源的 libreoffice。缺点是字体有些会走位。

选择 2: 下载安装 Acrobat Pro XI 付费才能用的 edit pdf 功能。本人参考这个教学后,整理出比较小白的步骤。


步骤:
1.  这里下载注册器。点击 Click to Download Content 即可。


2. 下载后,先不要管它。等下才打开 xf-aarpxi。


3. 去这里下载 Acrobat XI Pro。选 File 1 of 1 即可。


4.  浏览 C:\Windows\System32, 找 cmd 这个文件。

5. 滑鼠对着 cmd, 右键选 Run as administrator。


6. [cmd] 输入 cd drivers\etc ,按 Enter 键。再输入 notepad hosts , 按 Enter 键。


7. [notepad] 把下面的内容 copy-paste 去刚才那个 notepad 的最下面。

127.0.0.1 activate.adobe.com
127.0.0.1 activate.adobe.com
127.0.0.1 practivate.adobe.com
127.0.0.1 ereg.adobe.com
127.0.0.1 activate.wip3.adobe.com
127.0.0.1 wip3.adobe.com
127.0.0.1 3dns-3.adobe.com
127.0.0.1 3dns-2.adobe.com
127.0.0.1 adobe-dns.adobe.com
127.0.0.1 adobe-dns-2.adobe.com
127.0.0.1 adobe-dns-3.adobe.com
127.0.0.1 ereg.wip3.adobe.com
127.0.0.1 activate-sea.adobe.com
127.0.0.1 wwis-dubc1-vip60.adobe.com
127.0.0.1 activate-sjc0.adobe.com
127.0.0.1 lmlicenses.wip4.adobe.com
127.0.0.1 lm.licenses.adobe.com


8. [notepad] Save 起来。然后可以关掉 notepad 和 cmd 了。


9. 如果你是用 wifi 就关掉你的 wifi 。 如果是用 network cable 就拔掉 cable。


10.. 双击之前 unrar 的 xf-aarpxi 打开 [注册器] standby。


11. 双击之前下载的 AcrobatPro_11_Web_WWMUI 打开 [acrobat]。 点选 Overwrite。按 Next


12. [acrobat] Preparing files...Extracting, 等它跑完。


13. [acrobat] Files Are Ready。已经勾上 Launch Adobe Acrobat XI。按 Finish

14.  如果出现 [UAC dialog] , 按 Yes 允许 program 更改。


15. [Setup] English (United States) -> 按 OK。稍等。


16.  [Setup] InstallShield----, 按 Next

17. [Setup] 打勾 Make Adobe Acrobat my default PDF viewer。按 Next


18. [Setup] User Name 填上 email 。点选 "I have a serial number"。

19. [注册器] 去注册器按 "Generate" 左下角的按钮。Serial 栏出现长长的 code。右键 higlight copy 那个 code。


20.  [Setup] paste 那个 code 进去 Serial Number: 栏。按 Next

21. [Setup] Notcie: Adobe License Activation。按 Next


22. [Setup] Typical/Complete/Custom。多好过少,点选 Complete。 按 Next


23. [Setup] Destination Folder。按 Next


24. [Setup] Ready to Install the Program。按 Install

25.  [Setup] Status: Copying new files/Patching files/...。 等它跑完。

26.  [Setup] Setup Completed. 按 Finish


27. 在 desktop 双击安装好的 Adobe Acrobat XI Pro shotcut。


28. [Acrobat XI Pro] Adobe Software License Agreement。 按 Accept




29.  [Acrobat XI Pro] Serial Number Validation。 请按 "Having trouble connecting to the internet?" 蓝色字。不要按 Validate


30. [Acrobat XI Pro] No Internet Connection。按 "Offline Activation"


31. [Acrobat XI Pro] Offline Activation。按 "Generate Request Code"。


32. [Acrobat XI Pro] Offline Activation。滑鼠 highlight/右键 copy "Request Code:" 下面的长长 code。


33. [注册器] 去注册器。弄干净第二行的 "Request:" 栏。右键 paste 进去第二行。


34. [注册器] 按 "Generate"。第三行的 "Activation:" 栏出现长长 code。右键 higlight copy 那个 code。


35. [Acrobat XI Pro]  paste 进去 "Response Code:" 栏。按 Activate

36. [Acrobat XI Pro] Offline Activation Complete。按 Launch


37. [Acrobat XI Pro] Help 菜单看得出已经 Activate 了。中间 Select a Task, 选 Edit PDF。选你要 edit 的 pdf 文件。


38. [Acrobat XI Pro] Ctrl+滑鼠轮子放大。 对着图片按会出现格子。按 Delete 键即可丢掉图片。


39. 对着 pdf 右键可以直接打开 Edit。