2011-03-19

在 Cygwin 下编译 netcat_1.10-38

我在《Linux下用nc实现 DuplexPipe》中提到,Win 版的 netcat 无法实现 DuplexPipe 的功能。
其实 Cygwin 版的 netcat 也是如此。Cygwin 用的是 netcat 原生的 1.10 版本(项目地址是:http://nc110.sourceforge.net/),该版本没提供 -c 选项。因为我最近在做的项目需要一个这样的工具来帮助测试,于是就决定自己编译 1.10-38 版的 nc。

编译

首先到 debian 下 netcat 的主页下载源代码(http://packages.qa.debian.org/n/netcat.html),测试版已 经到 1.10-39 版本了,我选择稳定版 v1.10-38(http://packages.debian.org/source/stable/netcat)。需要下载两个文件:其中 netcat_1.10.orig.tar.gz 是原生的 nc;netcat_1.10-38.diff.gz 是升级包。
下载完成后先解压:
$ ls
netcat_1.10-38.diff.gz*  netcat_1.10.orig.tar.gz*
$ tar xvf netcat_1.10.orig.tar.gz
...
$ ls
netcat-1.10.orig/  netcat_1.10-38.diff.gz*  netcat_1.10.orig.tar.gz*
接着是释放补丁
$ cd netcat-1.10.orig
$ ls
Changelog  README  generic.h     netcat.c  stupidh*
Makefile   data/   netcat.blurb  scripts/
$ zcat ../netcat_1.10-38.diff.gz | patch -p1
$ ls
Changelog  README  debian/    nc.1          netcat.c  stupidh*
Makefile   data/   generic.h  netcat.blurb  scripts/
补丁被释放到 debian 目录下。然后就是给源代码打补丁了。
$ sed 's#^#patch -Np1 -i debian/patches/#' debian/patches/series | sh
patching file Makefile
patching file netcat.c
patching file netcat.c
patching file netcat.c
patching file netcat.c
patching file netcat.c
patching file netcat.c
patching file netcat.c
patching file netcat.c
patching file netcat.c
patching file netcat.c
patching file netcat.c
patching file debian/nc.1
patching file netcat.c
patching file debian/nc.1
patching file netcat.c
patching file debian/nc.1
patching file data/rservice.c
patching file netcat.c
patching file netcat.c
patching file netcat.c
patching file netcat.c
patching file netcat.c
patching file scripts/webproxy
$
最后,为了能使用 -c 和 -e 选项,还要再修改一下 Makefile 文件。将 Makefile 的第 11 行“# DFLAGS = - DTEST -DDEBUG”替换成“DFLAGS = -DDEBIAN_VERSION='"1.10-38"' -DGAPING_SECURITY_HOLE -DIP_TOS -DTELNET”,保存退出。这样,就可以运行“make nc”来编译了。

安装

编译完成后会在当前目录下生成一个“nc.exe”。将它拷贝到“/bin”目录下,并将“nc.1”复制到 “/usr/share/man/man1”目录里。这样就安装完成了。你可以试试运行“nc -h”看看版本号是否正确。
$ nc -h
[v1.10-38]
connect to somewhere:   nc [-options] hostname port[s] [ports] ...
listen for inbound:     nc -l -p port [-options] [hostname] [port]
options:
        -c shell commands       as `-e'; use /bin/sh to exec [dangerous!!]
        -e filename             program to exec after connect [dangerous!!]
        -b                      allow broadcasts
        -g gateway              source-routing hop point[s], up to 8
        -G num                  source-routing pointer: 4, 8, 12, ...
        -h                      this cruft
        -i secs                 delay interval for lines sent, ports scanned
        -k                      set keepalive option on socket
        -l                      listen mode, for inbound connects
        -n                      numeric-only IP addresses, no DNS
        -o file                 hex dump of traffic
        -p port                 local port number
        -r                      randomize local and remote ports
        -q secs                 quit after EOF on stdin and delay of secs
        -s addr                 local source address
        -T tos                  set Type Of Service
        -t                      answer TELNET negotiation
        -u                      UDP mode
        -v                      verbose [use twice to be more verbose]
        -w secs                 timeout for connects and final net reads
        -z                      zero-I/O mode [used for scanning]
port numbers can be individual or ranges: lo-hi [inclusive];
hyphens in port names must be backslash escaped (e.g. 'ftp\-data').

模拟 WireShark

在项目中,我们有时会需要截获客户端和服务端之间发送的消息。WireShark 可以监听本地的通信,可是我觉得它操作比较麻烦。现在,有了 1.10-38 版的 nc,就可以很简单地实现这个功能!
$ nc -l -p 1234 -c 'tee 1234.txt | nc remotehost 1235 | tee 1235.txt'
执行了上面的命令后,再用客户端连接本地的 1234 端口,nc 就会自动去连接远程的 1235 端口。并且客户端发送的消息会保留一份副本到 1234.txt 文件中;服务器反馈的信息则会保存到 1235.txt 中。

2011-02-13

AutoHotKey 新手入门教程

AutoHotKey 真是一个好玩的工具!短短几行代码就是先了“窗口置顶”、“窗口透明”等功能,之前我还特意为此装了好几个小工具,现在都可以卸掉了。闲来无事,就把 Quick Start 翻译了一下,我没有逐字逐句地翻译,有时候我嫌原文罗嗦就用自己的话概括地描述了一下。
原文地址:http://www.autohotkey.com/docs/Tutorial.htm

教程目录

创建脚本

每个脚本都是一个纯文本文件,由一些能被 AutoHotKey.exe 执行的命令组成。一个脚本可能还包含热键热字符串。如果没有热键和热字符串,脚本在启动的时候就会从头依次执行到尾。
创建一个新的脚本:
  1. 下载并安装 AutoHotkey。
  2. 右击鼠标,选择 新建 -> 文本文档
  3. 输入文件名并确保以 .ahk 结尾。例如:Test.ahk。
  4. 右击文件,选择 编辑脚本
  5. 输入以下内容:#space::Run www.google.com
上一行的第一个字符 "#" 代表键盘上的 Windows 键;所以 #space 表示在按住 Windows 键后再按空格键。"::" 后面的命令会在热键激活后执行,在本例中则会打开谷歌主页。继续按下面步骤操作,来执行这个脚本:
  1. 保存并关闭该文件。
  2. 双击该文件来启动它。在系统托盘里会出现一个新图标。
  3. 按下 Windows 和空格键,网页会在默认的浏览器里打开。
  4. 右击系统托盘里的绿色图标可以退出或编辑当前脚本。
注意:

启动程序

命令 Run 可以运行程序、打开文档、网页链接或快捷键。请参看以下示例:
Run Notepad
Run C:\My Documents\Address List.doc
Run C:\My Documents\My Shortcut.lnk
Run www.yahoo.com
Run mailto:someone@somedomain.com
可以给这些命令设置任何热键。下面第一个例子的快捷键是 Win+N ,第二个是 Control+Alt+C:
#n::Run Notepad
^!c::Run calc.exe
上例是单行热键,因为每个热键之包含一条命令。如果命令多余一条,则热键定义必须单独放一行,其后每条命令放一行,且最后一行必须是 return。例如:
#n::
Run http://www.google.com
Run Notepad.exe
return
如果待执行的程序或文档没有集成到系统中,则需要指定完整路径:
Run %A_ProgramFiles%\Winamp\Winamp.exe
上例中 %A_ProgramFiles% 是内建变量。比起直接使用诸如 C:\Program Files 这样的绝对路径,推荐使用内建变量,它使得脚本的可移植性更好,即能在其他机器上正常运行。注意:命令和变量都是大小写无关的。例如 "Run" 与 "run"、"A_ProgramFiles"与"a_programfiles"都是一样的。
RunWait 代替 Run,脚本就会一直等在,直到刚才运行程序退出。在下例中 MsgBox 命令直到记事本被关闭后才执行:
RunWait Notepad
MsgBox The user has finished (Notepad has been closed).
更多关于启动程序的内容 -- 像附带参数、制定工作路径以及获取程序返回值 -- 请点击这里

模拟鼠标键盘

Send 命令可以向当前活动窗口发送键盘击键消息。下例中定义了热键 Control+Alt+S 来输入签名:
^!s::
Send Sincerely,{Enter}John Smith
return
上例中{Enter}是模拟回车键,其他字符都是字面意思。下一个例子展示了其他几个特殊字符:
Send ^c!{tab}pasted:^v
代码会依次发送 Control+C、Alt+Tab、字符串 "pasted:"和 Control+V。完整的特殊字符列表请参阅 Send 命令。
最后,按键序列还可以用于定义字符串的缩写,即热字符串。例如,下例将 btw 定义为 by the way 的缩写,无论何时你输入 btw 后再输入空格或逗号,都会被替换成 "by the way":
::btw::by the way

鼠标点击
在发送鼠标点击事件前要先确定鼠标的位置(X, Y 坐标值)。AutoHotKey 自带的 Window Spy 可以很方便地确定鼠标的位置:
  1. 启动 Window Spy 。
  2. 激活你感兴趣的窗口 (Window Spy 默认置于窗口顶端)。
  3. 鼠标指针移到目标位置,Window Spy 就能显示出鼠标的坐标位置(在 Windows XP 或之前的版本中,按下 Shift-Alt-Tab 来激活 Window Spy,以便复制和粘贴 "冻结" 的坐标位置)。
  4. 将上面的坐标位置应用于 Click 命令。下例中鼠标在 112, 223 出单击一下左键:
    Click 112, 223
移动鼠标(未按键)用 MouseMove;拖动鼠标(有按键) MouseClickDrag

操纵窗口

WinActivate 来激活一个窗口;用 IfWinExistWinWait 判断某个窗口是否存在。以下示例演示这些命令的用法:
IfWinExist Untitled - Notepad
{
    WinActivate
}
else
{
    Run Notepad
    WinWait Untitled - Notepad
    WinActivate
}
例子中首先搜索标题以 "Untitled - Notepad"(忽略大小写)开头的窗口。如果找到了就激活它;否则就启动记事本程序 ,等到窗口以出现就激活它。上例中还使用了上一次找到的的窗口避免在每个 WinActivate 后面再次指定标题。
一些常用的窗口管理命令:
  • IfWinActive:检查指定的窗口是否处于激活状态。
  • WinWaitActive:等待指定的窗口处于激活状态(通常在发送窗口激活指令——比如按下 Control-F 来弹出查找窗口——后使用)。
  • WinClose:关闭指定的窗口。
  • WinMove:移动或/且调整窗口大写。
  • WinMinimizeWinMaximizeWinRestore:分别是最小化、最大化和恢复指定的窗口。

输入

下例显示一个对话框,它有两个按钮(YES 和 NO):
MsgBox, 4, , Would you like to continue?
IfMsgBox, No
    return
; Otherwise, the user picked yes.
MsgBox You pressed YES.
使用 InputBox 提示用户输入一个字符串;FileSelectFileFileSelectFolder 供用户选择文件和文件夹;更高级的任务使用 Gui 命令来自定义界面。
提示:从其他例子中你可能已经注意到第一个逗号往往被忽略(除非第一个参数为空或执行 := 、 = 或当前命令是后续语句唯一的顶部命令)。例如:
MsgBox This is ok.
MsgBox, This is ok too (it has an explicit comma).

变量与剪切板

变量是脚本用于存储文本或数值的内存区域。在数学运算和比较运算里,只包含数字(可以附带可选的小数点)的变量会自动解析成数值。
除了函数里的局部变量,所有其他变量都是全局变量。即,它们的值可在脚本的任意地方读取和修改。此外,变量在使用前无需声明,直接使用即可(初始值为空)。
下例演示如何给变量赋字符串:
MyVar1 = 123
MyVar2 = my string
下例演示将变量的值与字符串或数值进行比较:
if MyVar2 = my string
{
    MsgBox MyVar2 contains the string "my string".
}
if MyVar1 >= 100
{
    MsgBox MyVar1 contains %MyVar1%, which is a number greater than or equal to 100.
}
你可能注意到第二个 MsgBox 语句中 MyVar1 被两个百分号包围着。此处会显示 MyVar1 变量的值。在给变量赋值时也可以使用相同的技巧。例如:
MyVarConcatenated = %MyVar1% %MyVar2%
上例中变量 MyVarConcatenated 的值是 "123 my string"(不含引号)。
考虑下面这个例子,它演示两个变量相互比较:
if (ItemCount > ItemLimit)
{
    MsgBox The value in ItemCount, which is %ItemCount%, is greater than %ItemLimit%.
}
注意到上例的第一行包含一对小括号。小括号表示这个 if 语句包含一个表达式;缺少它们则看作 "非表达式 if 语句",于是需要用百分号将 ItemLimit 括起(因此非表达式 if 语句#1限定只使用一个比较运算符,即它们不能包含数学运算符或连词 "AND" 和 "OR")。

数学
:如下例所示,使用冒号等号(:=)运算符可以将表达式的计算结果赋值给一个变量:
NetPrice := Price * (1 - Discount/100)
完整的数学运算符请参阅表达式一节。

剪切板Clipboard是一个特殊变量,它代表 Windows 的系统剪切板。虽然如此,你还是可以像普通变量一样使用它。下例会显示当前剪切板里的内容:
MsgBox %clipboard%
考虑下面的例子,它用一段新的文本替代剪切板里当前的内容:
clipboard = A line of text.`r`nA second line of text.`r`n
上面的 `r 和 `n (第一个字符是倒引号,键盘 1 左边的那个键)分别代表回车符和换行符。这两个字符会将文本换到新的一行,效果等价于键入键盘上的 Enter 键。
下例演示将文本追加到剪切板(或其他任何变量):
clipboard = %clipboard% And here is the text to append.
更多内容请参阅剪切板变量两节。

循环

loop 可以连续地执行一段代码。下例中弹出 MsgBox 窗口三次:
Loop 3
{
    MsgBox This window will be displayed three times.
}
你也可以在 Loop 后面指定一个变量,在迭代次数不确定时这个方法很奏效:
Loop %RunCount%
{
    Run C:\Check Server Status.exe
    Sleep 60000  ; Wait 60 seconds.
}
上例中,除非 RunCount 小于或等于 0,否则循环体至少能执行一次。
根据不同的条件,可以中途跳出循环。执行下例程序后,当用户按住 F1 键,程序就会不断地发送点击鼠标左键事件:
$F1::  ; Make the F1 key into a hotkey (the $ symbol facilitates the "P" mode of GetKeyState below).
Loop  ; Since no number is specified with it, this is an infinite loop unless "break" or "return" is encountered inside.
{
    if not GetKeyState("F1", "P")  ; If this statement is true, the user has physically released the F1 key.
        break  ; Break out of the loop.
    ; Otherwise (since the above didn't "break"), keep clicking the mouse.
    Click  ; Click the left mouse button at the cursor's current position.
}
return
上例中,当用户放开 F1 键,程序就能知道并通过 break 命令终止循环。Break使得程序跳到循环体外。
一个替代方案是使用 "while" 循环
$F1::
while GetKeyState("F1", "P")  ; While the F1 key is being held down physically.
{
    Click
}
return
上例演示了通用的循环结构。下面的循环结构适用于一些特殊场合:
File-reading/writing loop:逐行获取文件内容。它可用于将基于行结构的文件转换成其他格式。还可以用于搜索特定内容。
Files and folders loop:逐个遍历文件和文件夹。它允许你逐个处理文件或文件夹。
Parsing loop:从字符串中逐个获取子串。比如将 "Red,Green,Blue" 分成三个字段。
Registry loop:逐个遍历注册表中的键。

操纵文件

下例中使用 FileAppend 将文本追加到文件末尾(或创建一个新文件)。注意:它使用 `n (换行符)来换行:
FileAppend, A line of text to append.`n, C:\My Documents\My Text File.txt
使用 FileDelete 删除一个已存在的文件。例如:
FileDelete, C:\My Documents\My Text File.txt
其他一些常用的、和文件和文件夹相关的命令:

其他特性

参阅命令列表


#1 原文是 if-statements,但我感觉是 non-expression if-statements 更合理。

2011-01-20

人所不欲,勿施于人

谁说博客也要像论文一样结构清晰、有条理?!

软件卸载

昨天整理自己的本本,卸载了 VMware 7.0 + 深度XP,MS Office 2007 以及 Visual Basic 6.0。我承认这些都是盗版软件,不过剩下的应用程序都是自由软件(freeware)或免费软件(freeware),这下我的计算机“干净”了。闲来无事,我就细数了一下当初装这些软件的原因:

  1. VMware + XP:当初刚买本本的时候,正好在上软件工程实践,紧遵老师的教导“将自己的开发环境随身携带”,自然第一款软件就是装了虚拟机(学校机房里是肆无忌惮地用盗版 VMware),另外上课指定使用 Visio 作图,那也只好一起装了;当然,也有部分原因是因为某些人的计算机装的是 XP,我这边有个 XP 环境也是为了方便问题重现(我的本本预装了 Vista)。
  2. MS Office 2007:在毕设期间,我也还是用 Open Office 和 WPS 2010,但现在公司用的却是 Office 2007(正版)。我这次卸载这款办公软件其实也是在提醒自己:工作的事情要在工作时间里完成!
  3. VB 6:你可能无法想象在我们科班的毕业设计中有多少是 VB6 项目,从大二开始,每逢毕业将至,总会有人来找我帮忙看那些不晓得从哪儿搜罗来的 VB6 代码,经不住软磨硬泡,我总会帮着改改;另一个原因在我自己,我一直下不了决心去学 MFC 等,所以但凡要做 GUI 程序,我都是拿 VB6 来画界面,再调用由 C 语言开发的 DLL 库,不过现在改用 QT,于是 VB6 可以功成身退了。

己所不欲,勿施于人

有些人就喜欢把自己的事全盘交托给别人来做,我一直不明白他们既然有精力去说服别人,为什么就没耐心自己去完成(所以我下面说人和人之间是无法理解的)。既然自己都认为这是无聊的事情,为什么偏偏又假设其他人会愿意无偿地帮你来完成呢?

两千多年前,孔老夫子提出“己所不欲,勿施于人”的观点,但到了今天,我听到关于这句话时的语境普遍是,A说:“那个XX东西你也不要了(或要了也没用),不如就让给我吧?”,B就义正言辞地反对:“那怎么可以!己所不欲,勿施于人嘛。”

己所甚欲,勿施于人

易中天老师在《百家讲坛》讲解诸子百家时提到庄子的思想比起“己所不欲,勿施于人”更进一步:“己所甚欲,勿施于人。”

如果你对此还不甚了解,建议去看看《武林外传》第五十八回:小师妹现身七侠镇,大师姐难解心头愤。故事大意就是小师妹南宫残花是个极端的素食主义者,不顾及营养均衡,一味地强调、推广素食,要求每个人都做到所谓的“天人合一”。一旦有人心存不满,就有如唐僧附体一般地给众人施加压力。这种人就像装在套子里的人——别里科夫一样,固执己见,食古不化,还要将自己的想法强加给别人,不认同这个世界的多元性。也许这种人活在黑白的世界里是最适合的。

现实中将自己喜爱的事物强加给别人的例子比比皆是。中国传统的“子承父业”,有多少人是满心欢喜地从父辈手里接过担子的(就中国这十几亿人口来说,即使是一万分之一那也很大,所以不要真去讨论数量)?父母教育孩子的时候,普遍会将自己年轻时候无法实现的理想强加于孩子身上。

人所不欲,勿施于人

虽然孔老夫子和庄老夫子所言都有道理,但我很奇怪作为大师的他们为什么都只臆断他人的想法。既然问题的关键在于“是否施于人”,那理所当然要考虑他人是否接受了,而两位老先生却一个说“己所不欲”另一个谈“己所甚欲”,都是将自己的想法强加给他人。尤其是庄老夫子自己也会说“子非我,安知我不知鱼之乐?”(《庄子——庄子与惠子游于濠梁之上》),那他也晓得人与人是不一样的,又怎会拿自己的喜恶无衡量他人的想法。

因此我信奉的是“人所不欲,勿施于人”。

不过追根究底,上面两句话也都不是他们两位老人家自己说的:“己所不欲,勿施于人”出自《论语》,而《论语》是由孔子的弟子及其再传弟子编撰而成。其中多少话真的是子曰过的,咱也无从考证了;而“己所甚欲,勿施于人”更是出自当代的易中天老师之口,正是一千个观众眼中有一千个哈姆雷特,这句话是否切中庄子的想法就不讨论了,但终究不是庄子自己说的。

人与人之间无法理解

猫舒服的时候会发出呼噜呼噜的声音,而这种声音在狗看来是威胁对方的一种信号;狗高兴时爱摇尾巴,而猫认为这样做是讨厌什么东西的标志。所以猫和狗一见面就会打架,因为它们相互不能理解对方的好意。而人与人之间又何尝不是这样?就像我爸爸不懂我为什么会学计算机,我也无法想象整天背书的日子有多好玩。

前段时间重温了一下卡通《幽游白书》,小时候光看着他们打来打去,现在才多少有点理解。让我最有感触的人是“仙水 忍”,仙水的个性非常单纯,但天生拥有强大的灵气,最后甚至有圣光气围绕全身(对人类而言,全身被金光包围的就是天使)。他从小斩妖除魔、以保卫人类为己任,直到后来,在一次执行任务的过程中,发现那些富豪们虐待和屠杀小妖来取乐,仙水无法接受自己舍命保护的人类反而比妖怪更加凶残;后来他去偷看了灵界的禁物——黑之章(上面记录了人类所有的恶行),更是分裂出七种人格,从此在矛盾中活下去。

在《千秋英烈传——刺秦》中,荆轲在燕国看到的是哀鸿遍野,满街都是乞丐,百姓生活朝不保夕。而燕太子丹将此归咎于秦王野心勃勃,欲将各国吞并,导致民不聊生,并且施计让荆轲答应去刺秦。等到荆轲来到秦都咸阳,见识到秦王英明神武,百姓生活富裕,街上更是连一个乞丐也没有,荆轲对大秦的升平景象充满赞叹,但势成骑虎,荆轲也只能无奈。

这些故事都是虚构的,但我们的现实生活又何尝不是如此呢:比如我看日本人就像《幽游白书》里人类看到妖怪一样的厌恶,非除之而后快;而那些小日本看我们中国人不也像妖怪看见人类一样觉得是异类?我前些天还傻乎乎地跑去问去过美国的同事:“美国大街上是不是也有乞丐?”好在据同事所言,那儿不仅有乞丐,而且比中国的乞丐嚣张多了。于是我又想起那句话——中国这只绝对不会(周星驰的《国产凌凌漆》)。

严以律己,宽以待人

我从小喜欢看武侠,而老爸要看“领导很忙、中国人民很幸福、外国人民生活水深火热”的新闻联播,他觉得这些古装剧听着就头疼,所以每次都会拿遥控器去换频道。因此我从小就渴望着独立、能有自己的空间,也不晓得是不是经济发展了,总感觉现在父母与子女的关系也是赤裸裸的商业交易:我把你养大,你花我的钱,你就得听我的,我让你好好学习,你就不会辜负我的期望。当然,这些话从来没有哪个父母说过,但周围的环境总让我有意无意地感受到这种压力。所以我要工作,自己养活自己(以后能力强了就回过去养父母),这样就不会有“寄人篱下”的感觉,我的地盘也可以我做主。

如果物质条件真的非常优越,《老子》的小国寡民政策也挺不错,因为大家都能自我满足,彼此不必太相互依赖:我在我的个人空间里可以尽情地看我喜欢的电视节目,永远不必当心老爸过来换台,呵呵。但目前而言,显然无法做到全世界每个人人手一台电脑、一台电视、一间房子……更何况老聃所处的时代,所以老子委曲求全,希望通过降低人民对物质生活的欲望,来实现这个理想,这就有点舍本求末了。

我们目前能实现的就是共享资源(全家人看一台电视),这点倒是很像我们开发并行程序:如果多进程或多线程之间没有任何资源共享(小国寡民,老死不相往来),那编程还算简单的,但往往是需要共享内存等等,就会有同步、脏读等一系列问题。程序上的事情由算法解决,现实生活中的事情,我崇尚“严以律己,宽以待人”。

编程的时候,每个人都会有自己的编码风格(花括号的布置、变量的声明、TAB的大小等),看到别人编写的风格混乱的代码时,就用包容的心去对待即可(尤其是代码格式化工具如此昌盛的时代),只要自己编码的时候坚持使用统一的风格即可。软件的一个好处就是只要你拥有一片属于自己的可用的磁盘空间,就可以将代码 check 下来,然后格式化成你喜欢的风格,而且通常情况下获得一片属于自己的磁盘空间花费会比获取一片属于自己的土地空间要便宜。因此,在计算机的世界里,你能按照自己喜欢的方式生活。

以前有人问我:“你学习为了什么?”我猜问的人也不会答应我很矫情地学周总理说“为了中华崛起而读书”,我的答案是:“学知识是为了让自己生活得更美好!”


Pig 更新: 发布 0.7 版本

关于 Pig

Pig 是一款文件格式化工具,它可以将“金山词霸”生词本软件导出的格式混乱的文件整理成网页格式,方便大家打印。更多内容可以参考以前的文章《和 Pig 一起学英语》

Pig 距离上一次更新有快两年的时间了,期间发生了很多事。其中一个原因是我后来对自己电脑上的软件进行了正版化清理:诸如 Visual Basic 6.0 精简版、VMWare 等盗版软件都被我卸载了,而 Pig 之前的版本都是用 VB6 精简版 + Dev-C++ 开发的。

姗姗来迟的新版本

事隔这么久,期间也有几位热心网友发邮箱报告程序 Bug,并对程序新功能提出了展望。可惜这次的更新不仅没添加任何新功能,反而还砍掉了一些比较鸡肋的功能。

Pig v0.7.0

程序界面如右图所示,与以前的界面相比变化不大(这正是我想要的)。不过本质区别是:以前的 Pig 是一个独立的可执行程序调用一堆动态链接库来完成任务;如今的 Pig 只是一张网页,通过执行 JScript 和极少量的 VBScript 来实现功能。

新版本解决的问题有:

  1. 这次的开发编辑器用的是 Emacs,语言选的是 JavaScript 和 HTML。开发环境方面没有版权问题。
  2. 随着金山词霸本身的升级,生词本导出文件的格式出现了调整。有网友反映 Pig 不能处理这些新文件。这次更新也增强了这方面功能,现在 Pig 能处理到目前为止的所有版本生词本导出的文件。
  3. Pig 之前的版本是用 VB 和 C 语言写的,源代码并没有随程序一起发布。这回简单了,JavaScript 和 VBScript 天生具有开源性质,源代码就是程序,你想怎么改都行。
  4. 更新了帮助文档。

砍掉的功能有:

  1. 合并“指定输出路径”和“生成单个文件”两个功能;
  2. 删除“输出卡片风格”(这功能真的没人用),统一用“列表”形式;
  3. 删除“图片格式”(当初有这个功能是因为 IE6 不能显示 Unicode 编码的音标,哪知我是费力不讨好:大家背单词并不关心音标);
  4. 删除“PDF格式”(也是费力不讨好的活);
  5. 删除“字段排序”功能(目前还没人把音标或解释放到单词前面来打印)。

下一步预期:

  1. 我自己的系统是 Vista,必须找台 XP 的电脑测试一下(毕竟目前的用户都是用 XP 的);(Done @ 2011-01-03)
  2. 生成 Excel 格式的文件;
  3. 在已安装了金山词霸的电脑上能自动分析生词本数据库,用户无需导出成文本文件;
  4. 去支持其他词典软件,比如有道、灵格斯等。

版权问题

和我的其他玩具一样:源代码都给你了,那还不是想怎么样就怎么样了?

说真的,其实我懒得搭理这种事情。我认识的人都知道这玩意儿是我为他们开发的,其他人怎么想我就不在乎了。

先睡觉,醒来我会把程序发布到 Google Code 上,到时再更新链接。

后记

今天白天在 XP + IE6 下做了简单的测试,并升级到 v0.7.1 版本,不过在 IE6 里选项卡之间切换时会出现一片空白(如下图),是 jQuery 的插件 jdMenu 的问题,它并不影响功能,所以暂时不去修复了。

Bug for Pig in IE6

程序已经发布到 Google Code 上,下载地址是:http://code.google.com/p/pig-formatter/downloads/list