解决Windows 8中VLC的字幕乱码

一大早就惊闻人人影视将关闭资源下载栏目,只提供字幕下载,心想这下惨了,又要回到满世界找匹配字幕的时代了。

我一直在人人影视下载压制好的片子,原因有两个,一是人人的字幕做得非常好,不仅有下方的中英文对照,影片中的一些文字,比如海报或者餐馆名称,也会加上中文翻译,非常有助于理解影片;二是 HR-HD 影片的性价比不错,下载时间短,清晰度也可以接受。虽然字幕组的人手有限,对于美剧的覆盖面还不够,但它提供的片源也足以支撑日常的休闲娱乐了。

自从去年开始,国内外媒体集体对影视网站施压,能稳定提供下载的网站越来越少了,有时候找一部高质量的译制电影都要找很久。如果人人再停止提供片源的话,那就雪上加霜了……

当然我不是拒绝正版电影,我愿意为正版电影付费,但前提是商家必须提供中文字幕。前段时间试用过 Netflix,发现几乎没有中文字幕的片子,而且它的播放器不支持外挂字幕。即便 Netflix 的用户体验做得非常好,那也只好对不起了。我可以勉强看看原版的好莱坞脑残英雄主义电影,但其它大部分影片还是依赖中文字幕的。

为了防止下载不到 HR-HD 而造成的不适应,我先演练了一遍 B 计划。目标影片是《忍者神龟:变种时代》,人人影视中显示“由于版权原因本资源已完全关闭”,于是我就去了上述图片所代表的网站(大家都懂的)下到了 720p 的无字幕版。下载工具用的是迅雷极速版,貌似没什么问题。迅雷很人性化地自动搜索了字幕,字幕列表有一排,也不知道哪个好,就下了第一个。

播放工具继续使用 VLC,很不错的播放器,只是……字幕显示成一个个方块。唉,这也是我不喜欢外挂字幕的一个原因。我用的是 VLC 2.1.5(32位)版本,应该是目前最新的了。Windows 8 也升级到最新的更新,中文字体也不缺。另外我还把字幕文件转换成了 UTF-8 格式的。问题依然存在…………

就在我尝试了一大堆设置(和它们的组合)还是没解决快要放弃的时候,突然搜到这么一个贴子,说是:如果中文字体的名称不是拉丁字母开头,VLC 会无法识别这个字体文件,于是就造成乱码。也就是说,使用“微软雅黑”就不行,而“Arial Unicode MS”就是可以的。我的机器上没有装 Office,所以没有 Arial Unicode MS 字体,但有其它字体可选,比如:DFKai-SB, Microsoft JhengHei等。这个问题貌似在 2011 年就存在了,至令没有修好,VLC 的开发效率也蛮让人担心的。

虽然遇到了一点小问题,但 B 计划总体来说还是可行的。当然我也不希望短期内被迫使用B计划。

顺便说一句,VLC 中使用快捷键 G 或 H 可以提前或延后字幕的时间,对于时间不匹配的字幕可以简单处理一下。

计算网页中某个元素的位置

由于项目的需要,测试中需要对网页元素进行截图,以确保它看上去没有问题。之前我写过一篇文章介绍过一种方法,先使用 WebDriver 进行全屏截图,然后根据目标元素(DOM Element)所在的位置,再对截下来的图片进行剪裁,保留我们需要的位置即可。

那段代码一直都工作得很好,直到我知道了一个东西:iframe。iframe(普通的 frame 也是一样的,不过 frame 现在不太常见,这里只用 iframe 举例)中的内容被视为一个独立的网页,连 Window 对象也是和它的父级网页分开的。而 WebDriver 中的 WebElement.getLocation()方法只能返回这个 WebElement 和它所在的 Window 的位置关系,它的实现没什么问题,但全屏截图不仅包含了 iframe 的内容,可能也包含了它的父级页面的内容,剪裁的时候需要知道目标元素在截图中的位置。那么问题来了,挖掘机技术哪家强?如何计算一个元素相对于截图的位置?

这个问题还要分类讨论,原因是:Chrome 和 Firefox 中截图的行为是不一样的。Chrome 的截图是当前可见(viewport)的网页内容,比方说,当网页的实际大小超过 Chrome 窗口大小时,根据滚动条的位置不同,窗口中显示的内容不同,Chrome 的截图就是显示出来的内容。于是我们要计算目标元素相对于当前可见内容的位置。而 Firefox 用了一个方法,可以截到整个网页的内容,无视当前窗口大小。于是对于 Firefox 我们要计算元素的绝对位置(Absolute Position)。

获得一个元素的位置,需要用到一个方法:Element.getBoundingClientRect()。这个方法返回这个元素相对于它所处的 Windows 在当前可见内容的位置,用 top、left、right、bottom 四个值来表示。我们只关心其中的 top 和 left,至于剪裁的尺寸,我们可以通过元素本身的长和宽来得到,不需要计算。要计算目标元素对于顶级 Window的位置,我们只需要依次加上它的父级 Window的 top 和 left 即可。代码如下:

以上代码适用于 Chrome ,而在 Firefox 中,我们还需要计算元素的绝对位置。这里需要用到 Window.pageXOffset。pageXOffset,或者 scrollX,表示当前 Window 的横向滚动条滚动的位置,把这个值和上述的 left 相加,即可得到目标元素的横向绝对位置。当然,iframe 也可以特殊处理的:

由于 IE8 不支持 pageXOffset 和 scrollX,于是在 IE8 中需要一些特殊处理,即代码中标注“IE8”的部分。把这两段 Javascript 代码,替换之前文中的 WebElement.getLocation(),即可实现在 iframe 中对特定元素截图。

ShellShock,炫酷特性引发的严重漏洞

ShellShock 是昨天刚刚被公开的一个 Linux 的漏洞,如果你手头有 Linux 机器(比如工作站、博客主机、笔记本等),并且正在使用 Bash,请尽快升级。如果你手头没有 Linux 机器,也不想了解 ShellShock 的深入细节,那就不用继续往下阅读了。

这个漏洞来自Bash,Bash 是 Linux 中常用的一个脚本运行环境。在 Bash 中有这样一个鲜为人知的“特性”,它可以定义一个函数,然后开启一个新的 Bash 环境来运行这个函数。比如下面这一行代码,它就定义了函数 foo,然后打开一个新的 Bash 来运行 foo,继而输出“hello”。

这是一个很有趣,可能也很有用的特性。当然,“有用”的前提是,你知道你在运行什么样的代码。如果你不知道,那就成了一个“远程代码执行”(Remote Code Execution,简称RCE)的漏洞。RCE 通常都是非常非常严重的漏洞,不及时修补,就毫无安全性可言。这不,网页服务器就在这次事件是充当了“不知道”的那个角色。

网页服务器,如 Apache,会接收来自客户端的 HTTP 请求,这些请求的内容是不受控制的。也就是说,用户只要写一段代码,就可以发送任何的内容给服务器(Apache),而 Apache,以及其连带的各种服务器端语言,如 PHP、Java等,有责任安全地处理这些内容。

根据上面的两点,只要黑客写了一段自动运行的 Bash 脚本,把它放在 HTTP 请求中发给服务器,服务器又恰好(以任何一种方式)使用了 Bash 来处理这个 HTTP 请求,只要 Bash 看到了那段有害的代码,就会造成 RCE。上述的代码只是打印一行文字,如果黑客把它写成“开放远程登录权限”或者“发送管理员帐号给我”,那后果就不堪设想了。

有评论说 ShellShock 比起前段时间的心脏出血漏洞有过之而无不及,原因是显而易见的。

不过还好,官方补丁已出,只要升级过 Bash,或者根本不用 Bash(部分 Linux 发行版使用了其它替代软件),就可以暂时不受黑客攻击。但是官方补丁还没有把这个漏洞补完,它只是尝试避免 RCE 攻击,但并没有阻止用户定义新的函数,比如下面这段代码:

如果用户提交的 HTTP 请求中,包含这样一个 Cookie,那么一个名为 HTTP_Cookie 的函数会被定义出来。虽然它不会自动运行,也看上去不像会被其它代码调用的样子,但依然还是蛮让人胆战心惊的。网站管理员估计又要睡不好觉了。

由于 ShellShock 还没有被完整修复,打了补丁的朋友们也要保持一颗警惕的心,随时留意事件的进展,及时更新后续的补丁。