易栈网-膘叔

浏览模式: 标准 | 列表 | 图文
Firefox插件:Firecookie

Firefox插件:Firecookie

Firecookie是firefox的插件。而且它是根在firebug插件里面的。所以,要安装firecookie一定要先安装firebug。安装完Firecookie后,点击F12,在Firebug里面多了一个cookies的Tab,从里面可以看到,列出了当前应用中的cookie信息。

通过这个tab可以看到有些cookie的过期时间显 示“会话”,有些显示的是具体时间。那些显示的是“会话”的cookie就被称为是“会话cookie”,即关闭了当前浏览器后,该cookie就消失 了。那些设置了具体过期时间的cookie被称为是持久cookie,浏览器就会把cookie保存到硬盘上,关闭后再次打开浏览器,这些cookie依 然有效直到超过设定的过期时间。

有些cookie被设置为http-only,是为了防止跨站点脚本攻击(XSS),以防用户重要的cookie信息被别人窃取。这点就不深入了,网上有很多资料。

Cookie的路径用于设置可以读取一个cookie的最顶层的目录,如显示为“/”说明只要在同一个域中,所有的文件都可以访问该cookie。

这个工具可以修改cookie的值、新建cookie、清除cookie等功能。在测试的过程中可以利用这个工具修改相应的cookie的值,来测试对应功能是否正确。

你试试看就知道喽。HOHO

仅用 []()+! 就足以实现几乎任意Javascript代码

仅用 []()+! 就足以实现几乎任意Javascript代码

这篇文章很强悍,看到的时候我很惊讶,传说中的大吃一斤又出现了。
没办法,人啊。。。总是会想到奇怪的方法,呵呵。。
看内容吧。不多说了,很彪悍。

G Reader里Dexter同学的分享,来自sla.ckers.org的又一神作:点我测试

GReader里看不到效果的同学请自行测试下列HTML:

<script language="javascript" type="text/javascript">
([][(![]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]()[(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]])([][(![]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]()[(![]+[])[+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][(![]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]()+[])[!+[]+!+[]]]((![]+[])[+!+[]]+(+[![]]+[])[+[]])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(+[![]]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+!+[]]]+(!![]+[])[+[]]+[][(![]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]()[(![]+[])[+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][(![]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]()+[])[!+[]+!+[]]]((![]+[])[+!+[]]+(+[![]]+[])[+[]])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]])
</script>
在线转换工具

跟Brainfuck有的一拼。。。是挂马的好办法。。。

更新:研究了一下它实现的原理,有一个码表:

(NaN+[]["filter"])[11]',
! window["atob"]("If")[0]',
" ("").fontcolor()[12]',
# window["atob"]("0iN")[1]',
$ window["atob"]("0iT")[1]',
% window["atob"]("0iW")[1]',
& window["atob"]("0ia")[1]',
' window["atob"]("0if")[1]',
( (false+[]["filter"])[20]',
) (false+[]["filter"])[21]',
* window["atob"]("0ir")[1]',
+ window["atob"]("0it")[1]',
, window["atob"]("0iy")[1]',
- (NaN+window["Date"]())[31]',
. window["atob"]("1i4")[1]',
/ (true+("")["sub"]())[10]',
0-9 ignored*/ ,,,,,,,,,,
: window["Date"]()[21]',
; window["atob"]("O0")[0]',
< ("")["sub"]()[0]',
= ("").fontcolor()[11]',
> ("")["sub"]()[10]',
? window["atob"]("0j9")[1]',
@ window["atob"]("00A")[1]',
A (+[]+[]["constructor"])[10]',
B (+[]+(false)["constructor"])[10]',
C window["atob"]("00N")[1]',
D window["btoa"](00)[1]',
E window["btoa"](01)[2]',
F (0+[]["filter"]["constructor"])[10]',
G window["btoa"]("0f")[1]',
H window["btoa"]("0t")[1]',
I ("Infinity")[0]',
J window["atob"]("00r")[1]',
K window["btoa"]("(")[0]',
L window["btoa"]("/")[0]',
M window["btoa"](0)[0]',
N ("NaN")[0]',
O window["btoa"](8)[0]',
P window["btoa"]("<")[0]',
Q window["btoa"]("a")[1]',
R window["atob"]("01I")[1]',
S window["btoa"]("I")[0]',
T window["btoa"]("N")[0]',
U window["atob"]("01W")[1]',
V window["atob"]("01a")[1]',
W (true+window)[12]',
X window["atob"]("01i")[1]',
Y window["btoa"]("a")[0]',
Z window["btoa"]("f")[0]',
[ (undefined+[]["filter"])[33]',
\ window["atob"]("01y")[1]',
] (true+[]["filter"])[40]',
^ window["atob"](014)[1]',
_ window["atob"](018)[1]',
` window["atob"]("02A")[1]',
a ("false")[1]',
b (window+[])[2]',
c ([]["filter"]+[])[3]',
d ("undefined")[2]',
e ("true")[3]',
f ("false")[0]',
g ([]+("")["constructor"])[14]',
h window["atob"]("aN")[0]',
i ([false]+undefined)[10]',
j (window+[])[3]',
k window["atob"]("a0")[0]',
l ("false")[2]',
m (Number+[])[11]',
n ("undefined")[1]',
o (true+[]["filter"])[10]',
p window["atob"]("cN")[0]',
q window["atob"]("cf")[0]',
r ("true")[1]',
s ("false")[3]',
t ("true")[0]',
u ("undefined")[0]',
v (0+[]["filter"])[30]',
w ([]["sort"]["call"]()+[])[13]',
x window["atob"]("eN")[0]',
y (NaN+[Infinity])[10]',
z window["atob"]("et")[0]',
{ (NaN+[]["filter"])[21]',
| window["atob"]("03y")[1]',
} (NaN+[]["filter"])[41]',
~ window["atob"](234)[1]'
拼接出来字符串 "eval",如何把 "eval" 变成 eval() 呢?方法是:[]["sort"]["call"]()["eval"]

其中 []["sort"]["call"]() 等于 [].sort.call() ,等价于 window,所以上面 []["sort"]["call"]()["eval"] 就等价于 window.eval。

然后就是体力活了,把码表对应转换成 eval("blah blah") 这种形式就可以执行任意代码了,不同浏览器的码表不一样。 Chrome和Firefox的index就不一样。

其实这个码表还可以通过 ·toLocal*()` 函数族扩展到Unicode,比fromCharCode要简短 :D

原文来自:http://www.cnblogs.com/pandora/archive/2010/02/27/1674833.html

再看阿凡达

再看阿凡达

再次看阿凡达,距离上次是一个月后的事了。
上次是在曹扬影城,普通3D版的,为了这个imax 3D,老婆是念叨了很久了,正好她去莱福士,看到这个加场,就买了票,最后一排的。
12点半的电影。上完课后回家睡了一个小时,11点半起床,打车去了莱福士。
15米高, 20米宽的屏幕看起来是爽。唯一不爽的是,眼镜好象有点差。(我去之前想了想,这么大的屏幕,我应该可以不用戴眼镜吧?果然,象我这种300度以内的眼镜男,不戴眼镜也看的很清楚)
效果嘛。。比普通的3D确实有改进,普通的3D看上去,就象浮在眼前,而imax的却有点身临其境 的感觉(当然这只是自己的看法,也可能每个人确实不一样)
这么大的屏幕,原来没注意的一些细节也能够完善的表现出来了。
只是午夜场看的太累。而且又是周四。

180的票加上打车费,一下子升级到了230。。。不过还算物有所值吧。虽然这个代价大了一点

思考PHP的转换?

思考PHP的转换?

我在写sbConfigure类的时候,还是采用了以前的Configure的解析方法,即get方法可以以字符串的形式来读取数组变量,就象这样

sbConfigure::get("a.b.c");
Return:
return self::$_config['a']['b']['c'];

但事实上,我为了这个返回,写了五六次代码了,但最终还是采用了foreach的方法

第一次我这么处理(采用了Eval),

//...省略
$arrkeys = "[a][b][c]"
eval("\$ret = self::\$_config$arrkeys;");
return $ret;

后来,yhustc说这样不太安全,所以我改成了foeach的方式

//....
$arr = self::$_config;
$_err = false;
foreach($names as $name){
if(isset($arr[$name])){
$arr = $arr[$name];
}else{
$_err = true;
break;
}
}
if($_err == true)return ;
return $arr;

$_err这个变量是为了防止变量在没有设定的时候仍然返回值。。。

昨天我又想用eval,但还是失败了。。。

不知道有没有更好的转换方式,查看了parse_ini_file,因为我想,ini文件中有

[test]
a.b=1
a.c=2

有这样的返回数组。所以我在想着参考。然而仍然失望 ,又想着pack?serialize?json_decode?之类的解决方式,但还是失败了。。郁闷啊。

先记录一下,如果有更好的方法,就再次更新

【新闻】易语言5.0正式版隆重发布

自从汉编被铁血论坛中批斗了之后,现在新闻就少了很多了。易语言的新闻还是很少的,低调低调。。

吴涛,仿佛是CCED的主要coder?不过也算是不错了。能够挺到现在。以前是谁说的?凡是能够挺下来的,肯定都有过人之处的。不多讲,免得被和谐,看新闻吧。

易语言5.0 相对于易语言4.x更新说明
增加静态编译功能,支持挂接第三方链接器(比如VC6中的link.exe)。
静态编译后的易语言可执行程序(exe)和动态链接库(dll),运行时不再依赖任何支持库文件,文件尺寸更小(相对以前的独立编译),PE结构更合理 (取消了“易格式体”),加载速度更快,而且有效解决了“病毒误报”和“易被脱壳”的难题。

为实现静态编译,易语言编译器、核心支持库、集成开发环境(IDE)等均有重大更新,支持库开发架框有扩展性调整,绝大多数官方支持库都已针对 静态编译完成自身改造并提供静态库。

目前绝大多数官方支持库均已支持静态编译,只有极少数不支持静态编译:vclbase.fne, jedi.fne, com.run/cominf.run/ocx.run。

第三方支持库,由源代码作者按照静态编译技术文档(参见sdkstatic_docs)完成自身改造并提供静态库后,可支持静态编译。外部OCX 组件和COM组件,不支持静态编译。

此次重大版本升级不影响以前的源代码(.e)和模块(.ec)。只要代码或模块中未用到“不支持静态编译”的支持库、COM/OCX等,都可以静 态编译。以前编译好的模块(.ec)甚至不需要重新编译即可直接支持静态编译。

支持库开发框架调整是扩展性调整,比较好的做到了向前向后兼容。即,新版支持库可被旧版易语言或易程序使用,旧版支持库也可被新版易语言或易程序 使用(只是不支持静态编译)。

静态编译后的易语言EXE/DLL之间不能再共享譬如窗口、窗口组件等类似资源,对于已经静态连接到一个EXE/DLL中的支持库,该支持库中的 数据或资源将不能再被其它EXE/DLL中所使用的同名支持库访问。这是因为代码被分别静态链接接到各个独立模块(EXE/DLL)中。

易语言5.0精简版安装包(不包括 知识库、多媒体教程)
易语言5.0完全版安装包 (包括知识库、多媒体教程)

另附预告:易语言5.1版持续开发中,其中有关键更新,将于近期(或节后)推出测试版,敬请期待。

来源:http://www.eyuyan.com/news/2010/020102.html

另:易语言居然还有Elogo,飞扬,和英文版【对于这个,我很纳闷,其他没啥】

iconv编码转换的原理

iconv编码转换的原理

乔大姐的文章,几年前的了。。不过,还是值得一观,这也是我一朋友在问过,为什么存到文件里的内容不是UTF-8的时候引申出来的事了。

以下内容是乔大姐的转载,主要内容如下【我把C的那部分做了高亮,其余不变】,关于乔大姐是谁,可以从我转载的页面中获知,http://bbs.chinaunix.net/viewthread.php?tid=807393,本人不作介绍,以防被劈。

更广义的字符集转换:iconv
在先前的章节中,我们已见到了两组 mbs 与 wcs 互转的函式,第一组对于有「状态改变」的编码系统 mbs 无法做到字符串的状态控制,故不适合做该 mbs 的转换工作;而第二组则可以直接做字符串的状态控制,故使用范围就更广了。然而,这两组字符串转换函式在某些使用场合下都有很大的限制,广义而言,它们都 属于「字符集转换函式」,然而它们都直接与 I18N、locale 机制绑在一起,也就是说在使用它们之前,程序都必须设好正确的 locale 才行。故在以下的情况使用它们就会很不方便,甚至根本行不通:
• 如果程序中需要做 A 字集编码与 B 字集编码的转换时,不幸的是这两种字集 编码都不是目前程序所处的 locale 所采用的。若使用前述的 wcs 与 mbs 转换函式,唯一的办法只有先呼叫 setlocale(),将程序的 LC_CTYPE locale 先切换到使用字集编码 A 的 locale,把字符串 A 转成 wcs 字符串后,再呼叫一次 setlocale(),将程序的 locale 切换到使用字集编码 B 的 locale,最后才把 wcs 字符串转成字符串 B。万一 都找不到任何 locale 采用字集 A 或字集 B 时,则这一招就没有用了。
• 如果程序中需要同时做多种字集编码的转换时,则这些 wcs 与 mbs 的转换 函式就无法办到了。原因是一旦 setlocale() 设定好程序的 locale 之后,其影响是遍及整个程序每个部分,我们不可能做到在转换字集编码 A 时设好 locale A,又 ``同时'' 设好 locale B 来转字集编码 B。
因此,我们需要更广义的字集转换系统,一个可以与 locale 完全无关的转换系统,才能方便地达到上述的要求。故在 XPG2 标准中另外定义了一组全新的函式接口: iconv。事实上,在 glibc 中,表面上看来那些 wcs 与 mbs 转换函式与 iconv 不太一样,但它们底层的 wcs 与 mbs 转换工作却是由 iconv 来达成的。故 iconv 可以说是字集转换系统中最基底的函式接口。
iconv 字集转换系统只有三个函式,在很多系统中是宣告在 iconv.h 里头,使用上与一般在做档案读写的概念一样,先 ``开启''、之后 ``操作''、完毕后要 ``关闭'',这些函式包括:
• iconv_t iconv_open(const char *TOENC, const char *FROMENC)
• size_t iconv (iconv_t CD, const char **INBUF,
size_t *INBYTESLEFT, char **OUTBUF, size_t *OUTBYTESLEFT)
• int iconv_close(iconv_t CD)
首先 iconv_open() 函式就是做 ``开启'' 动作,也就是当我们要将编码系统 A 转换到编码系统 B 时,必须先呼叫此函式,将 FROMENC 设成编码系统 A 的名字,同时将 TOENC 设成编码系统 B 的名字,这时此函式就会做类似档案开启的动作,传回一个代表此转换管道的数据结构 iconv_t 供后续使用。事实上,在系统的实作中真的是将 iconv_open() 当作 ``开启档案'' 来处理,故它会受到目前系统或同一行程中可开启档案数所限,如果系统或程序的其它部分已开启了太多的档案以至于逼近系统上限,则有可能这边的 iconv_open() 会失败。
如果 iconv_open() 开启失败时,它会传回 (iconv_t)-1 的值,同时设定 errno 全域变量,用以指出开启失败的原因。而开启失败的原因,不外乎就是已开启的档案数已超过上限、或系统内存不足、或系统本身无法做到编码系统 A 与 B 之间的转换。有兴趣的读者可以直接去阅读 info libc, * Character Set Handling:: 一节了解各 errno 的值与其所代表的意义。
第二个 iconv() 函式就是用来做实际编码系统转换工作的,它必须先呼叫过 iconv_open() 并取得 iconv_t 结构后才能工作。只要 iconv_open() 可以开启成功,则理论上它就可以进行转换工作,而且不论其来源编码与目标编码是 mbs 字符串或 wcs 字符串、或二者的混合互转,都没有关系。但要注意的是,如果其中有 wcs 字符串时,就算用来存放 wcs 字符串是使用 wchar_t * 形别,在传入此函式时仍然统一用 char * 来处理。
若要做字符串 A 转换成字符串 B 时,字符串 A 是经由 *INBUF 传入,而 *INBYTESLEFT 则传入数组 A 的长度,一律以字节数来计算。而转换的结果则由 *OUTBUF 传回,同样的 *OUTBYTESLEFT 则为 *OUTBUF 的长度。如果转换成功了,则 *INBUF 最后会设在存放字符串 A 的数组末尾,而 *INBYTESLEFT 会设为目前此数组还剩多少字节可以用。而 *OUTBUF 与 *OUTBYTESLEFT 也是一样。因此我们可以在相同的 A、B 数组中重复呼叫此函式。举个例子来说,如果转换过程中在 A 数组里头遇到了不合法的字符而无法进行转换时,则 *INBUF 与 *OUTBUF 就会停在无法转换的位置上,并将已转换成功的结果传回,则我们可以自行决定看是要跳过那个不合法的字符,继续转换剩余的部分,或做其它的特殊处理 ...等等。
在很多情况下有可能造成 iconv() 的转换失败,例如前面提到的在 A 数组中遇到不合法的字符,或者 A 中某个字符在 B 中找不到可对应的字。其中第二个情况是最有可能发生的,而目前 glibc-2.1.x 系统中遇到这种情况时就当做是转换失败,而不做进一步的处理。当然这并不是最好的处理方式,故未来可能会有所改变。而根据 info libc 的说明,如果转换失败了, iconv() 最后的传回值是 (size_t)-1,并设定 errno 的值说明失败的原因;如果转换成功,则传回值会是已成功转换的字符个数。但我们实际的测试结果,在 glibc-2.1.3 的系统下,如果转换成功后其传回值却永远是 0,与 info libc 上的描述不一样,这点有点奇怪,不晓得是不是目前 glibc 的 bug?
若遇到含「状态改变」的编码系统时,iconv() 也能正确工作,它能在转换的过程中随时记录、更新字符串目前的状态 (应该就是记录在 iconv_t CD 结构中),故就算是采「分期付款」方式将同一字符串切成数分一段段来转换,也不会出问题。但要注意的是,在第一次使用 iconv() 之前,必须先初始化一下 A、B 两字符串的状态,就好像我们在先前所提的 mbsrtowcs() 等函式一样,在使用前也必须先做好状能初始化,如此才能让后续可以正常工作。而对于 iconv() 而言,初始化的方式就是呼叫它时,*INBUF 与 *OUTBUF 都设为 NULL 即可。
最后一个 iconv_close() 函式,就是当整个转换结束后,用来做「关闭档案」用的。
底下我们就写了一个范例程序,用来说明 iconv 函式界面的使用方式:

#include <stdio.h>
#include <string.h>
#include <iconv.h>

int main(int argc, char **argv)
{
FILE *fin, *fout;
char *encFrom, *encTo;
char bufin[1024], bufout[1024], *sin, *sout;
int mode, lenin, lenout, ret, nline;
iconv_t c_pt;

if (argc != 5) {
printf("Usage: a.out <encFrom> <encTo> <fin> <fout>\n");
return 0;
}
encFrom = argv[1];
encTo = argv[2];
if ((fin = fopen(argv[3], "rt")) == NULL) {
printf("Cannot open file: %s\n", argv[3]);
return -1;
}
if ((fout = fopen(argv[4], "wt")) == NULL) {
printf("Cannot open file: %s\n", argv[4]);
return -1;
}

if ((c_pt = iconv_open(encTo, encFrom)) == (iconv_t)-1) {
printf("iconv_open false: %s ==> %s\n", encFrom, encTo);
return -1;
}
iconv(c_pt, NULL, NULL, NULL, NULL);

nline = 0;
while (fgets(bufin, 1024, fin) != NULL) {
nline ++;
lenin = strlen(bufin) + 1;
lenout = 1024;
sin = bufin;
sout = bufout;
ret = iconv(c_pt, &sin, &lenin, &sout, &lenout);
printf("%s -> %s: %d: ret=%d, len_in=%d, len_out=%d\n",
encFrom, encTo, nline, ret, lenin, lenout);
if (ret == -1) {
printf("stop at: %s\n", sin);
break;
}
fprintf(fout, "%s", bufout);
}
iconv_close(c_pt);
fclose(fin);
fclose(fout);
return 0;
}

这个程序可以从命令列输入来源档案与目的档案的编码系统名称,将来源档案的内容转换成目的档案。各位读者可以注意到,在程序中我们完全没有做 locale 设定等相关动作,原因正是不需要,iconv 函式接口是与 locale 完全无关的。同时,我们的程序只适合拿来做两个 mbs 编码系统间的转换,不适合拿来做其中一个有 wcs 的转换,原因是程序中我们没有特别为 wcs 的情况使用 wchar_t * 数组,同时记得我们以前也提过,wcs 字符串是不能拿来做档案输出的,而我们的程序目前正是直接做档案编码转换的工作。
这样的转码程序倒底「耐不耐用」呢?有兴趣的读者可以跟着我们一起来测试。由于先前我们已介绍过了如何在您的 GNU/Linux 系统中安装 zh_TW.Big5 与 zh_CN.GB2312 locale 环境,如果您都已安装无误的话,理论上您的系统的 Big5 与 GB2312 的 gconv 系统都有不成问题了 (在 glibc 中,gconv 系统可以说是 iconv 的心脏,我们会在下一小节详细说明),故我们就直接以 Big5 与 GB2312 两个编码系统互转为例子,测试一下我们的程序。首先,请先准备一个叫 f-big5 的档案,内容用 Big5 编码打入这样一行的内容:
我是研究生
然后,将我们的范例程序编译好,假设程序执行文件名就是 a.out,接着执行:
a.out BIG5 GB2312 f-big5 output
在 glibc-2.1.x 的系统下,应该可以正确转换,这时您应该会见到如下的程序输出:
BIG5 -> GB2312: 1: ret=0, len_in=0, len_out=1012
其中 ret=0 就表示转换成功,然后,您可以再开一个可以看 GB2312 编码的 terminal 来看 output 档的内容,您就会见到原来 f-big5 档的内容已转换成 GB2312 码了。
看起来似乎很完美,我们再进一步测试。现在请在 f-big5 档中再加一些内容,像这样:
我是研究生
目前在正在做研究测试
按照上头的指令再执行一次,我们得到如下的结果:
BIG5 -> GB2312: 1: ret=0, len_in=0, len_out=1012
BIG5 -> GB2312: 2: ret=-1, len_in=6, len_out=1008
stop at: 测试
第一行没有问题,但第二行失败了,程序指出第二行最后两个字 ``测试'' 无法做转换,为什么会这样呢?
要探讨其原因,就要更深入 iconv 的编码系统转换原理了。我们在之前已多次提过,在做 mbs 与 wcs 之间转换时,其实就是将 mbs 转换成系统的基底字集,而 iconv 的转换原理也是这般。事实上在 glibc 系统中,它在做编码系统 A 与 B 之间的转换时,有两种途径可选择:一是如果 iconv 内部已内建了 A 与 B 的对应表格时,就采用此对应表格来转换,而这也是最可信赖的转换方式。万一它找不到适当的对应表格时,它则会先将 A 转换成基底字集,再由基底字集转换成 B。也就是系统的基底字集在这里扮演了中间媒介的角色。
要注意的是,在其它的 UNIX 系统中,它们可能只提供第一种途径供转换,而 glibc 提供第二种途径的理由是,这样可以确保任意两个字集编码都有机会进行转换,只要这两个字集编码都同时被系统所支持。而且,由于 glibc 所选择的「基底字集」理论上已包含了目前世界上所有正在使用的计算机字集,故使用基底字集做为中间媒介是合理而且可行的。
但各种字集编码的问题是很复杂的玩意儿,有时候这一套也有出槌的时候。就像前面见到的 Big5 的 ``测试'' 无法转成 GB2312 一样,我们再做以下的实验,就会知道原因了。因为 glibc 是以 UCS4 做为其系统的基底字集,而 UCS4 的 mbs 形式为 UTF8 编码系统,故我们现在准备两个档案,一个是 f-big5,内含 Big5 码的 ``测试'' 两字,另一个是 f-gb,内含 GB2312 码的 ``测试'' 两字。现在我们用上头那个范例程序将这两个档案都转成 UTF8 编码:
a.out BIG5 UTF8 f-big5 output1
a.out GB2312 UTF8 f-gb output2
这两个都可以转换成功。然后,我们用 diff 程序比较一下 output1 与 output2 的内容,发现它们的内容不一样!
这就是无法转换成功的原因!因为在中文里头意义一样的两个字,在 Big5 与 GB2312 里头分别被对应到不同的 UCS4 编码里头去了。为什么会如此?这牵涉到更深刻的 UCS4 编码规则与其它编码系统的对应问题,在这里我们就先略过了,以后若有机会的话再回来讨论。现在的问题是,在 glibc 中,如果 A 与 B 的某些字分别被对应到基底字集中不同的编码中,就有可能会无法转换成功。而这往往是很有可能发生的,特别是 glibc 直接采用 UCS4 做为其基底字集时。
而且,在回顾一下我们前面谈的,在不同的 UNIX 系统下,其 iconv 底层的运作模式可能都不太一样,这就造成了更严重的问题:就算系统同时支持 A 与 B 两种编码,我们仍不能保证可以将 A 转成 B。或者,该系统中可以将 A 转成 C,也可以将 C 转成 B,但也不能保证可以将 A 直接 (或间接) 转成 B。
这的确是另人气馁的问题,现在也许读者就会问了,那 iconv 有什么用?我们的认为是,它在小字集与大字集编码间的转换是有用的。例如 Big5 与 GB2312 分别是 UTF8 的子字集,则我们可以很放心地使用 iconv 将 Big5 或 GB2312 转成 UTF8,或反方向地转换回来 (当然,前提是原来的 UTF8 字符串中没有包含 Big5 或 GB2312 所没有的字)。又或者 Big5 是 GBK 的一个子字集,我们一样也可以利用它来做转换。
但如果要直接用 iconv 来做 Big5 与 GB2312 的转换的话,唯一个可靠方法就是在 iconv 系统中加入一个 Big5 与 GB2312 直接互转的表格,并且希望此表格可以成系统标准的一部分 (至少要是 glibc 标准的一部分),如此我们的程序这样写才会有用 (至少在 glibc 的系统下)。因此,现在我们就进入下一小节,来看看 glibc 的 iconv 的核心部分,做为本章的一个结束。
新的尝试。

新的尝试。

在文章内容里加入了新的尝试,可以把页面分享至google reader;生成pdf;发送至wordpress,发送至live space。

看到很多网站有这个分享功能,我觉得我也是可以尝试一下。不知道是否有什么大用处,但或许能够有不一样的体验?
用官方的话来说,那就是:一个点击, 快速完成分享。 常在开心网或人人网看到朋友转贴的精采文章及图片吗? 【分享】就是背后的大功臣,一个强大的网页分享插件,让您将喜欢的博文、新闻等内容快速分享到社群网络上。

但其实,我还是认为这样会反而使得自己的用户在流失,不过,我这也算是一个尝试,而且bshare.cn上面有统计。所以我想试上三个月,看看有没有什么特别的用处。

分享按钮在哪里呢?是在文章的底部啦

85f3dcda65e9ba2c9c7d925f65998e9b

上面的四个按钮的顺序也是我精心挑选的。点击更多则可以分享到其他网站。其中google reader用了你自己的google帐号,如果处于登录状态,可以直接使用。生成pdf则不需要任何帐号【比较适合收藏文章】其他两个也是需要在本站输入帐号,但其实是在bshare.cn的JS代码中输入,所以我不能保证是否会有什么密码XXX的问题。官方和弹出窗的提示窗上也都说了不会收集密码等信息。。。

分类数据重整

今天上来看了看浏览量之后,发现一些问题,大量的分类充斥,让我的博客左侧 栏显得特别的长,因此,我对分类等做了调整,把一些文章较少的分类与较类似的分类进行整合,虽然整合后的数据还是很少,但毕竟比原来仅4、5篇那样的分类好多了。

其实,我还想把PHP再细分,或者再加一些分类,比如,我读别人的架构设计类的文章,这些放到哪里比较合适呢?慢慢先考虑。
sablog2远没有我想的那样优秀,暂时还是先用Sablog,不过,可能会往wordpress上面转。但文章也有点多,而且,原来的收录舍不得啊?
wordpress也可以自定义一些链接,估计可以用,show-%id-1.shtml,这样好象就差不多了。

值得思考的是文章中的代码,如果没有合适的代码编辑器,却不是特别敢转换。sablog2中的那个好象很简单只需要放在<pre>标签里就行了。有点心动。

慢慢来吧,删除了:smarty,Catchword,Learnenglish和android
smarty的新闻和学习资料太少了,就扔进了php分类里
catchword扔到了ideas里,learnenglish放进了literature中
android。。。本来想删除的,后来扔进了misc分类里,主要还是因为我已经有了另一个博客,专门用来记录android相关的资料以及我拍的照片等,它就是:http://g.52cd.net【手机记录生活】

PHP里simplexml_load_string函数一个容易犯晕的地方

PHP里simplexml_load_string函数一个容易犯晕的地方

以下内容均来自老王。说实话,simplexml的这些问题我以前遇到过,而且还是非常强烈的遇到了。
那时候是08年的事了,项目中与SOAP在交互,返回的都是XML,所以就直接采用了simplexml_load_string了。这时候就会遇到这种问题,比如我拉一个列表,但会有三种情况:1、没数据,2、1条数据,3、正常数据
1、没数据的时候,返回一个空的simplexml Object,
2、一条数据的时候,返回的也是一个simplexml Object,结果集成了这个object的元素
3、数据列表,这时候返回的却是一个Array,每一个元素是simplexml Object,等同于2。
后来我是没办法,就多写了一个函数判断,如果是object,并且不为空,直接把object强制转为array,因为,如果是空的simplexml Object,强制转的话,还是Object,转不了。。。

当时还有一个可恨的事情,我以前可能介绍过,xml在返回的时候,他的形式可能是这样的<test-name>gouki</test-name>,在返回这样的形式时,生成object时,却是test_name,在没有print_r出来时,我死活搞不定。。。后来才发现这个问题,郁闷啊

好了,说了半天,该说说老王的内容了:
这个问题遇到好几次了,今天翻看以前代码的时候看到,便记下来,先用一段代码重现一下问题:

<pre>
<?php
$string = <<<EOF
<data>
<foo><bar>hello</bar></foo>
<foo><bar>world</bar></foo>
</data>
EOF;

$data = simplexml_load_string($string);

print_r($data);
print_r($data->foo);
?>
</pre>

乍一看,结果很让人费解:

SimpleXMLElement Object
(
[foo] => Array
(
[0] => SimpleXMLElement Object
(
[bar] => hello
)
[1] => SimpleXMLElement Object
(
[bar] => world
)
)
)
SimpleXMLElement Object
(
[bar] => hello
)

明明print_r显示foo是一个有两个bar元素的数组,但是最后却仅仅显示了一个bar元素!

原因其实很简单,在如上所示simplexml_load_string的结果里,foo并不是数组,而是一个迭代对象!

可以这样确认:

foreach ($data->foo as $v) print_r($v);
foreach ($data->children() as $v) print_r($v);
看来,print_r或者var_dump之类的表象并不完全可信,自己多留心吧。
原文来自:http://hi.baidu.com/thinkinginlamp/blog/item/9dbb15ce7a621632b700c86a.html

使用GIT进行版本控制

其实本文是从GIT官网上复制而来,我本人准备开始尝试使用GIT而不是SVN,因此就用它来做参考了。
原文可以查看:http://progit.org/book/zh/index.html,这可是中文版的哦。

关于版本控制

什么是版本控制?我真的需要吗?版本控制是一种记录若干文件内容变化,以便将来查阅特定版本修订情况的系统。在本书所展示的例子中,我们仅对保存着 软件源代码的文本文件作版本控制管理,而实际上,你可以对任何类型的文件进行版本控制。

如果你是位图形或网页设计师,可能会需要保存某一幅图片或页面布局文件的所有修订版本。采用版本控制系统(VCS)是个明智的选择。有了它你就可以 将某个文件回溯到之前的状态,甚至将整个项目都回退到过去某个时间点的状态。你可以比较文件的变化细节,查出是谁最后修改了什么地方从而造成某些怪异问 题,又是谁在何时报告了某个功能缺陷,等等。使用版本控制系统通常还意味着,就算你胡来搞砸了整个项目,把文件改的改,删的删,你也可以轻松恢复到原先的 样子。而由此额外增加的工作量却微乎其微。

本地版本控制系统

许多人习惯用复制整个项目目录的方式来保存不同的版本,或许还会改名加上备份时间以示区别。这么做唯一的好处就是简单,不过坏处却不少:有时候会混 淆所在的工作目录,弄错了文件丢了数据就没了后退的路。

为了解决这个问题,人们很久以前就开发了许多种本地版本控制系统,大多都是采用某种简单的数据库来记录文件的历次更新差异(见图 1-1)。


图 1-1. 本地版本控制系统

其中最流行的一种叫做 rcs,现今许多计算机系统上都还看得到它的踪影。甚至在流行的 Mac OS X 系统上安装了开发者工具包之后,也可以使用 rcs 命令。它的工作原理基本上就是保存并管理文件补丁(patch)。文件补丁是一种特定格式的文本文件,记录着对应文件修订前后的内容变化。所以,根据每次 修订后的补丁,rcs 可以通过不断打补丁,计算出各个版本的文件内容。

集中化的版本控制系统

接下来人们又遇到一个问题,如何让在不同系统上的开发者协同工作?于是,集中化的版本控制系统( Centralized Version Control Systems,简称 CVCS )应运而生。这类系统,诸如 CVS,Subversion 以及 Perforce 等,都有一个单一的集中管理的服务器,保存所有文件的修订版本,而协同工作的人们都通过客户端连到这台服务器,取出最新的文件或者提交更新。多年以来,这 已成为版本控制系统的标准做法(见图 1-2)。


图 1-2. 集中化的版本控制系统

这种做法带来了许多好处,特别是相较于老式的本地 VCS 来说。现在,每个人都可以一定程度上看到项目中的其他人正在做些什么。而管理员也可以轻松掌控每个开发者的权限,并且管理一个 CVCS 要远比在各个客户端上维护本地数据库轻松容易得多。

事分两面,有好有坏。这么做最显而易见的缺点是中央服务器的单点故障。若是宕机一小时,那么在这一小时内,谁都无法提交更新,也就无法协同工作。如 果中央服务器的磁盘发生故障,并且没做过备份或者备份得不够及时的话,还会有丢失数据的风险。最坏的情况是彻底丢失整个项目的所有历史更改记录,被客户端 提取出来的某些快照数据除外,但这样的话依然是个问题,你不能保证所有的数据都已经有人提取出来。本地版本控制系统也存在类似问题,只要整个项目的历史记 录被保存在单一位置,就有丢失所有历史更新信息的风险。

分布式版本控制系统

于是分布式版本控制系统( Distributed Version Control System,简称 DVCS )面世了。在这类系统中,诸如 Git,Mercurial,Bazaar 还有 Darcs 等,客户端并不只提取最新版本的文件快照,而是把原始的代码仓库完整地镜像下来。这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜 像出来的本地仓库恢复。因为每一次的提取操作,实际上都是一次对代码仓库的完整备份(见图 1-3)。


图 1-3. 分布式版本控制系统

更进一步,许多这类系统都可以指定和若干不同的远端代码仓库进行交互。籍此,你就可以在同一个项目中,分别和不同工作小组的人相互协作。你可以根据 需要设定不同的协作流程,比方说层次模型式的工作流,这在以前的集中式系统中是无法实现的。

Git 的历史

同生活中的许多伟大事件一样,Git 诞生于一个极富纷争大举创新的年代。Linux 内核开源项目有着为数众广的参与者。绝大多数的 Linux 内核维护工作都花在了提交补丁和保存归档的繁琐事务上(1991-2002年间)。到 2002 年,整个项目组开始启用分布式版本控制系统 BitKeeper 来管理和维护代码。

到 2005 年的时候,开发 BitKeeper 的商业公司同 Linux 内核开源社区的合作关系结束,他们收回了免费使用 BitKeeper 的权力。这就迫使 Linux 开源社区(特别是 Linux 的缔造者 Linus Torvalds )不得不吸取教训,只有开发一套属于自己的版本控制系统才不至于重蹈覆辙。他们对新的系统订了若干目标:

* 速度 * 简单的设计 * 对非线性开发模式的强力支持(允许上千个并行开发的分支) * 完全分布式 * 有能力高效管理类似 Linux 内核一样的超大规模项目(速度和数据量)

自诞生于 2005 年以来,Git 日臻成熟完善,在高度易用的同时,仍然保留着初期设定的目标。它的速度飞快,极其适合管理大项目,它还有着令人难以置信的非线性分支管理系统(见第三 章),可以应付各种复杂的项目开发需求。

Git 基础要点

那么,简单地说,Git 究竟是怎样的一个系统呢?请注意,接下来的内容非常重要,若是理解了 Git 的思想和基本的工作原理,用起来就会知其所以然,游刃有余。在开始学习 Git 的时候,请不要尝试把各种概念和其他的版本控制系统诸如 Subversion 和 Perforce 等相比拟,否则容易混淆每个操作的实际意义。Git 在保存和处理各种信息的时候,虽然操作起来的命令形式非常相近,但它与其他版本控制系统的做法颇为不同。理解这些差异将有助于你准确地使用 Git 提供的各种工具。

直接快照,而非比较差异

Git 和其他版本控制系统的主要差别在于,Git 只关心文件数据的整体是否发生变化,而大多数其他系统则只关心文件内容的具体差异。这类系统 (CVS,Subversion,Perforce,Bazaar 等等)每次记录有哪些文件作了更新,以及都更新了哪些行的什么内容,请看图 1-4。


图 1-4. 其他系统在每个版本中记录着各个文件的具体差异

Git 并不保存这些前后变化的差异数据。实际上,Git 更像是把变化的文件作快照后,记录在一个微型的文件系统中。每次提交更新时,它会纵览一遍所有文件的指纹信息并对文件作一快照,然后保存一个指向这次快照 的索引。为提高性能,若文件没有变化,Git 不会再次保存,而只对上次保存的快照作一连接。Git 的工作方式就像图 1-5 所示。


图 1-5. Git 保存每次更新时的文件快照

这是 Git 同其他系统的重要区别。它完全颠覆了传统版本控制的套路,并对各个环节的实现方式作了新的设计。Git 更像是个小型的文件系统,但它同时还提供了许多以此为基础的超强工具,而不只是一个简单的 VCS。稍后在第三章讨论 Git 分支管理的时候,我们会再看看这样的设计究竟会带来哪些好处。

近乎所有操作都可本地执行

在 Git 中的绝大多数操作都只需要访问本地文件和资源,不用连网。但如果用 CVCS 的话,差不多所有操作都需要连接网络。因为 Git 在本地磁盘上就保存着所有有关当前项目的历史更新,所以处理起来速度飞快。

举个例子,如果要浏览项目的历史更新摘要,Git 不用跑到外面的服务器上去取数据回来,而直接从本地数据库读取后展示给你看。所以任何时候你都可以马上翻阅,无需等待。如果想要看当前版本的文件和一个月 前的版本之间有何差异,Git 会取出一个月前的快照和当前文件作一次差异运算,而不用请求远程服务器来做这件事,或是把老版本的文件拉到本地来作比较。

用 CVCS 的话,没有网络或者断开 VPN 你就无法做任何事情。但用 Git 的话,就算你在飞机或者火车上,都可以非常愉快地频繁提交更新,等到了有网络的时候再上传到远程的镜像仓库。同样,在回家的路上,不用连接 VPN 你也可以继续工作。换作其他版本控制系统,这么做几乎不可能,抑或非常麻烦。比如 Perforce,如果不连到服务器,几乎什么都做不了(译注:实际上手工修改文件权限改为可写之后是可以编辑文件的,只是其他开发者无法通过 Perforce 知道你正在对此文件进行修改。);如果是 Subversion 或 CVS,虽然可以编辑文件,但无法提交更新,因为数据库在网络上。看上去好像这些都不是什么大问题,但在实际体验过之后,你就会惊喜地发现,这其实是会带 来很大不同的。

时刻保持数据完整性

在保存到 Git 之前,所有数据都要进行内容的校验和(checksum)计算,并将此结果作为数据的唯一标识和索引。换句话说,不可能在你修改了文件或目录之后,Git 一无所知。这项特性作为 Git 的设计哲学,建在整体架构的最底层。所以如果文件在传输时变得不完整,或者磁盘损坏导致文件数据缺失,Git 都能立即察觉。

Git 使用 SHA-1 算法计算数据的校验和,通过对文件的内容或目录的结构计算出一个 SHA-1 哈希值,作为指纹字符串。该字串由 40 个十六进制字符(0-9 及 a-f)组成,看起来就像是:

24b9da6552252987aa493b52f8696cd6d3b00373

Git 的工作完全依赖于这类指纹字串,所以你会经常看到这样的哈希值。实际上,所有保存在 Git 数据库中的东西都是用此哈希值来作索引的,而不是靠文件名。

多数操作仅添加数据

常用的 Git 操作大多仅仅是把数据添加到数据库。因为任何一种不可逆的操作,比如删除数据,要回退或重现都会非常困难。在别的 VCS 中,若还未提交更新,就有可能丢失或者混淆一些修改的内容,但在 Git 里,一旦提交快照之后就完全不用担心丢失数据,特别是在养成了定期推送至其他镜像仓库的习惯的话。

这种高可靠性令我们的开发工作安心不少,尽管去做各种试验性的尝试好了,再怎样也不会弄丢数据。至于 Git 内部究竟是如何保存和恢复数据的,我们会在第九章的“幕后细节”部分再作详述。

三种状态

好,现在请注意,接下来要讲的概念非常重要。对于任何一个文件,在 Git 内都只有三种状态:已提交(committed),已修改(modified)和已暂存(staged)。已提交表示该文件已经被安全地保存在本地数据库 中了;已修改表示修改了某个文件,但还没有提交保存;已暂存表示把已修改的文件放在下次提交时要保存的清单中。

由此我们看到 Git 管理项目时,文件流转的三个工作区域:Git 的本地数据目录,工作目录以及暂存区域。


图 1-6. 工作目录,暂存区域和 git 目录

每个项目都有一个 git 目录,它是 Git 用来保存元数据和对象数据库的地方。该目录非常重要,每次克隆镜像仓库的时候,实际拷贝的就是这个目录里面的数据。

从项目中取出某个版本的所有文件和目录,用以开始后续工作的叫做工作目录。这些文件实际上都是从 git 目录中的压缩对象数据库中提取出来的,接下来就可以在工作目录中对这些文件进行编辑。

所谓的暂存区域只不过是个简单的文件,一般都放在 git 目录中。有时候人们会把这个文件叫做索引文件,不过标准说法还是叫暂存区域。

基本的 Git 工作流程如下所示:

1. 在工作目录中修改某些文件。 2. 对这些修改了的文件作快照,并保存到暂存区域。 3. 提交更新,将保存在暂存区域的文件快照转储到 git 目录中。

所以,我们可以从文件所处的位置来判断状态:如果是 git 目录中保存着的特定版本文件,就属于已提交状态;如果作了修改并已放入暂存区域,就属于已暂存状态;如果自上次取出后,作了修改但还没有放到暂存区域,就 是已修改状态。到第二章的时候,我们会进一步了解个中细节,并学会如何善用这些状态,以及如何跳过暂存环节。