2009年5月23日星期六

如何花动漫人物的脸的教程

2009年5月18日星期一

youtube封了,用Vimeo

Vimeo也是国外比较著名的视频网站,而且它提供的画质较高。

以下是一个Vimeo上的片子:
<object width="400" height="230"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=4576801&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=4576801&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="230"></embed></object><p><a href="http://vimeo.com/4576801">Eole</a> from <a href="http://vimeo.com/user1731857">Eole</a> on <a href="http://vimeo.com">Vimeo</a>.</p>

Google Blogger被封的解决方案

首先是发帖问题,最好的方法是用Gmail发帖,在Blogger的控制台里可以设置使用邮箱发帖。

然后是RSS订阅的问题,如果不使用Google Reader,那么可以用feedburner烧制一个新的RSS地址,提供给他人使用,这个地址经过了feedburner服务器一层所以即是不用代理或是google reader也可以访问。

本博客烧制的新的RSS地址是:http://feeds2.feedburner.com/blogspot/swinging

[推荐]ACG游戏人物之爱

这部视频包含了上百个ACG游戏的图片,配乐的节奏和图片的播放的配合还不错。视频的作者一定是ACG游戏的达人!

话说我唯一玩通的ACG游戏只有两个:FATE stay night和智代After。

视频如下:

C语言动态分配二维数组内存

前几天学习Matlab与C++的混合编程,不了最难得是matlab所有的数据的结构都是mxArray结构,而此结构不是与C类似的按行来取二维数组,而是Fortune类似的以列来取二维数组。

谈的远了点。总之我需要动态申请一个二维数组,而一般方法:先申请一个指针数组再给每元素指针申请一个数组,这种方法得到的数组内存空间是不连续的,而int a[8][7]这样形式的申请的静态空间是连续的。由于上面提到的原因为了将数组赋值到mxArray结构所以需要的数组时内存连续的。google之后发现了一个方法,下改后代码如下:
void **darray_new(int row, int column, int size)
{
void **ptdhead = NULL; //////////在后面说明为什么要用void**类型
void **ptdBody = NULL;//////////在后面说明为什么要用void**类型
//
ptdhead = (void **)malloc(sizeof(void*)*row + sizeof(double)*row*column);
//sizeof(void*)*row是指针大小,sizeof(double)*row*column是所存元素大小

if(!ptdhead)
return NULL;

ptdBody = ptdhead + row ;

for(int ncount = 0; ncount < row; ncount++)
ptdhead[ncount] = ptdBody + ncount * column* sizeof(double)/sizeof(void*);

return ptdhead;
}
原理是先申请一块连续的空间ptdhead (是最终的空间大小),但是只是这样无法通过a[1][2]的形式访问所以需要修改ptdhead[ncount](每个指针数组的元素指针的指向)使其指向正确的位置。

Blogger被和谐了

用Google的AppEngine代理还是可以上的,但是不用代理就不行,可见终于被和谐了。

诶!

2009年5月13日星期三

[转]用Prism剥离WebQQ,超越QQ for linux!

Mozilla Prism,Mozilla的推出的新玩意,在前几天介绍过这个软件的用途。说明介绍请阅读:Mozilla Prism v1.0发布,感觉到QQ for Linux的功能还不如WebQQ,那还不如用Mozilla Prism剥离一个出来比较好用。

说明:Mozilla Prism Firefox插件版在3.0.10上无法使用。
Mozilla Prism下载地址:[/url]http://prism.mozilla.com/started[/url]

Mozilla Prism的使用很简单,启动prism,出现如下界面:

URL:填写你将要分离的web地址(只要这一栏为没有填错就行了)
Name:随意填写。

一个独立的web程序就剥离出来了,脱离了firefox本身,现在就算firefox崩溃了,prism依然继续运行。


登录webqq后的界面,看起来完全是个独立程序,qq for linux真的可以下岗了!


prism看上去光秃秃的,唯一的设置按钮在右下角,可以设定字体颜色大小、代理地址、打印、甚至还有扩展插件。


通过Prism剥离出来的twitter,相信还有更好玩的一些web可以通过prism剥离出来应用。


转自:http://www.linuxhobby.com/article.asp?id=336

2009年5月12日星期二

推荐两款主题

最近一直没怎么上Gnome-Look。今天有空上去转转,发现了两款很符合我口味的淡系的主题。

redhumanLight

预览图:

redhuman



Light

都是很耐看的主题,很不错!

[转]多态的理解

封装(wrap)、继承(inheritance)、重载(override)还是多态(polymorphism),亦或是其他?
在我看来,答案无疑将是多态。封装是优点,继承是基础,重载是特点,而多态则是特征。

虽然这四者缺一不可,无论少了哪一个,就像一个人缺胳膊少腿,使OO将不再是完整的,但是前三者对于OO来说好比鼻子耳朵,而多态则是生殖器,没有多态的OO就象是被阉割的雄性,已经失去其典征。

什么是多态?

简单来说,多态是具有表现多种形态的能力的特征,在OO中是指,语言具有根据对象的类型以不同方式处理之,特别是重载方法和继承类这种形式,的能力。多态被认为是面向对象语言的必备特性。

多态有多种分类,通过了解这些分类可以更丰满对其认识,在这里就不再罗列,请各位参考 wiki大百科 和 javaworld .

多态与泛型(generic)

多态实际上就是泛型。

所谓泛型就是指我们不为特定的类型进行专门编码,而采用对不同类型进行通用编码的方式,无论是数据结果还是算法。

传统的泛型是指类似以Template function的方式使参数一般化,典型的应用是C++ STL,比如List、Vector以及algorithm。

而OO已能通过接口(Interface)和抽象类(Abstract Class)进行真正意义上的泛型了。在我看来,这就是OO最精彩的地方,也就是多态的威力。而对于传统意义上的Generic,我始终觉得其作用已经今不如昔了。

多态和继承(Inheritance)

严格来说,多态与继承、重载并不是孤立的,他们之间存在着紧密的联系,多态是建立在这两者的基础之上的(实际上继承就有用重载这一特性)。

传统的多态实际上就是由虚函数(Virtual Function)利用虚表(Virtual Table)实现的(早期C模拟OO特性时使用最多,C++的实现也是,后来的技术未作研究,是否使用VT不得而知),自然是离不开继承,换句话说多态实际上覆盖了继承。

正是由于继承与多态的紧密联系,使得我们很容易张冠李戴,那么如何区别呢?

举个常用的例子:

Abstract Class Sharp implement IHaveSide {
public bool isSharp(){
return true;
}
public abstract int getSides();
}

Class Triangle extends Sharp {
public override int getSides() {
return 3;
}
}

Class Rectangle extends Sharp {
pubilc override int getSides() {
return 4;
}
}

那么这种类的关系叫做继承,下面这种使用方式也是继承所带来的:
Triangel tri = new Triangle();
println("Triangle is a type of sharp? " + tri.isSharp());

而这种方式则是多态:
Sharp sharp = new Rectangle();
println("My sharp has " + sharp.getSides() + " sides.");

这两者区别在哪?很显然,继承是子类使用父类的方法,而多态则是父类使用子类的方法。

其技术上的区别是绑定时期,晚期绑定一定是多态。

现代软件设计

现代软件大量的使用框架、模式(非特指Deisgn Pattern),也就是将软件开发的一些共性进行抽象,提出普遍适用的软件结构。

无论是框架还是模式,他们都有一些明显的共同点 — 使用xml配置对象,大量使用接口采用所谓面向接口的方法,利用反射实现。

为什么要接口?因为需要抽象,需要将未知的对象在已有的框架中表现。

如何实现接口?多态!所谓反射,实际上就是一种晚期绑定的技术,这个技术实质上表现出来的就是多态这一特征。

面向方面开发(Aspect Oriented Programming)是一个热点,也是现代软件发展的趋势。定制、组件装配的软件开发方式在应用越来越复杂、需求变化越来越快的今天显得日趋重要。那么如何才能使今天的软件能够适应明天需要呢?如何使我开发速度更快?如何能更容易的修改应用?AOP则是解决这些问题的有效手段。

让我们看看框架容器的主要模式,Inversion of Control Containers(IoC)/Dependency Injection(包括setter injection, construct injection, interface injection等),其主要好处就是类之间的依赖,通过运行期的查找来进行绑定。那么他的基础是什么呢?还是多态!

我们可以看到,在现代软件的开发中,无数的思想象火花一样跳动。其中一类很重要的思想就是建立在多态这样一个很基本的特性,甚至可以说是一个语言概念之上的。在这里希望通过这篇文章抛砖引玉,引起更多的对与当今软件发展发向的思考,同时探究其根源。

网页代理看youtube

今天通过斗牛士新闻网,发现了一个不错的网页代理,可以免费使用访问墙外网站。好久没上youtube了,墙外风光无限好啊!
代理网站:http://sneakme.net/

网页代理的优势就是不用装什么东西,各平台通吃,O(∩_∩)O哈哈~,太爽了!

可以看flash,不过教育较慢,网通还可以!

还有另一种方法:在浏览器的地址栏输入https://soproxy.appspot/####,其中“####”是你要访问的网址去掉“www.”部分。比如,你要绕过GFW翻墙访问www.youtube.com,只要输入https://soproxy.appspot.com/youtube.com即可。

ps:实验室不能用...

2009年5月11日星期一

技巧:Linux I/O重定向的一些小技巧

Linux I/O 重定向虽然很简单,但在脚本编写、系统管理时却要常常打交道,搞清其中使用技巧非常有用。

首先说一下什么是I/O重定向,所谓I/O重定向简单来说就是一个过程,这个过程捕捉一个文件,或者命令,程序,脚本,甚至脚本中的代码块(code block)的输出,然后把捕捉到的输出,作为输入发送给另外一个文件,命令,程序,或者脚本。

如 果谈到I/O重定向,就涉及到文件标识符(File Descriptor)的概念, 在Linux系统中,系统为每一个打开的文件指定一个文件标识符以便系统对文件进行跟踪,这里有些和C语言编程里的文件句柄相似,文件标识符是一个数字, 不同数字代表不同的含义,默认情况下,系统占用了3个,分别是0标准输入(stdin),1标准输出(stdout), 2标准错误(stderr), 另外3-9是保留的标识符,可以把这些标识符指定成标准输入,输出或者错误作为临时连接。通常这样可以解决很多复杂的重定向请求。

标准输入通常指键盘的输入
标准输出通常指显示器的输出
标准错误通常也是定向到显示器

请看以下例子,来描述一下他们的关系

#ls /dev

这个命令列出/dev目录下的所有文件,在屏幕上输出结果。

这里 /dev 就是作为命令ls的标准输入(从键盘输入),而打印在屏幕的结果就是标准输出(/dev目录中的内容)

还是回到标题,重定向就是把标准的输入或者输出更改成其他的方式,请参看如下例子
或者等同于

#ls /dev 1>filename                                  #注意:"1"和">"中间没有空格

以上命令会把命令的标准输出重新定向到一个文件filename,而不是显示到屏幕上,如果不指明文件标识符,系统默认的就是1, 因此1可以省略

如果把上面例子重的">"改成">>"则表示把输出追加到filename文件的末尾,如果文件不存在则创建它。如下

#ls /dev >>filename

也可以把标准错误重新定向到文件

#ls -qw  /dev  2>filename

显然 -qw是一个错误参数,通常会在显示器上报告一个错误信息,但由于把2标准错误(stderr)重新定向到了文件filename,因此显示器没有错误信息,而信息写到了文件里面

以下命令是把标准输出和错误都定向到文件

#ls /dev &>filename

"&"在这里代表标准输出和标准错误,这里无论是正常输出还是错误信息都写到filename中了。

重新定义标准输入,输出,和错误的文件标识符

重新定义文件标识符可以用i>&j命令,表示把文件标识符i重新定向到j,你可以把"&"理解为"取地址"

请看以下例子

#exec 5>&1

表示把文件标识符5定向到标准输出,这个命令通常用来临时保存标准输入。

同样标准输入也是可以重新定向的,请参考下面例子

# grep search-word < filename或者grep word="" 0="">

一般来说grep命令在给定文件中搜索字符串,以上命令把文件filename作为grep命令的标准输入,而不是从键盘输入。

前面曾经提到,系统为每一个打开的文件指定一个文件标识符以便系统对文件进行跟踪,那么默认的文件标识符是什么呢?答案是0,也就是标准输入,或者可以说从键盘输入。当然这个文件标识符也可以自己指定,请参考下面例子

#echo 123456789 >filename   把字符串写到文件filename中
#exec 3<>filename 把文件filename打开,并指定文件标识符为3
#read -n 4 <&3 从文件中读4个字符,句柄已经指到第四个字符末尾 #echo -n . >&3 在第5个字符处写一个点,覆盖第5个字符,-n表示不换行
#exec 3>&- 关闭文件标识符3

现在cat filename文件的结果就成了1234.6789

命令j<>filename表示把文件打开,并指明文件标识符为j
"&-"表示关闭文件标识符

有关关闭文件标识符的操作请参考下面

n<&- 关闭输入文件标识符n 0<&-或<&- 关闭标准输入stdin n>&- 关闭输出文件标识符n
1>&-或>&-关闭标准输出stdout

另外还有一些其他命令,如下参考

2. :> filename 或者 > filename

表示把文件filename设置成空,也就是清空文件内容,如果文件不存在,则创建一个空文件,(等同于touch命令) :表示一个空输出,两个命令的唯一区别就是>filename不是在所有shell都可以正常工作的。

2009年5月9日星期六

Blender 基金会的下一部开源电影: 榴莲(Durian)

Blender 基金会的下一部开源电影,“榴莲(Durian)”项目已经宣布了,看起来很不错哦。这第三部开源电影项目很快就要启动,虽然 Blender 目前最紧要的还是为 Blender 2.5 版本垒代码,通过榴莲,测试和改良 Blender 2.5x 系列。Durian 团队希望能够在九月一日启动项目,在 2010 年四五月结束。

Durian

更多信息,请参考 Durian Project Announcement

2009年5月8日星期五

想发起一个开源项目,集思广益下

一直想发起一个开源项目,最近突然有了一个想法,主要是受到:https://wiki.ubuntu.com/Artwork/Incoming/Jaunty/SimpleFlatWindow的启发。想法是这个软件主要用于Gnome环境,简单的说就是:把所有用GTK编写界面的程序的菜单栏全部移动到窗口上。

“将菜单栏放到窗口上比起Mac的放到任务栏上更美观,而且这样可以极大的利用屏幕的空间,充分利用窗口的空间,这种方法也类似于一些国产的软件——遨游”

但是这样也存在一个问题:“菜单项过多会影响窗口栏上的点击范围”。

至于程序的可行性,主要要完成的有两个方面,一个是新的窗口管理器,另一个是gtk程序去掉菜单栏(这个Gnome下已经有全局菜单Global Menu Bar项目实现了这个功能,可以参考它们的源码),所以主要是窗口管理器,可以hack现有的Metacity或者是再重写一个。

现在想集思广益下!谁有什么更好的想法?

预计能在7月中旬完成可行性分析,再决定是否继续!

Firefox下的Gnome do——Ubiquity

Gnome环境下有一个很著名的新兴软件:Gnome do。有了他就可以用命令而不用鼠标方便的做任何事,这对于笔记本用户有很大的吸引力。现在Firefox也有了这样一个插件——Ubiquity。它努力的方向就是web上的Gnome do。有了它就可以方便的打几个字母就完成自己要做的事。

看一下它的宣传视频就知道了。这已经不是一个新项目了,我最近才试用它,个人感觉非常棒!

Ubiquity for Firefox from Aza Raskin on Vimeo.

2009年5月7日星期四

介绍一个不错的学习软件设计的网站

http://sourcemaking.com/
这个网站:sourcemaking相当适合于学习软件的设计,它提供这方面的知识,主要分为四个部分:设计模式、重构、UML和AntiPattern。

[转]缓冲区溢出攻击

“十年来攻击和防卫的弱点”——缓冲区溢出*攻击

寒路

大凡上网久点的网人对缓冲区溢出应该是知道的,因为它的确是一个众人皆知、非常危险的漏洞,它是个不分什么系统、什么程序,都广泛存在的一个漏洞。以缓冲 区溢出为类型的安全漏洞是最为常见,也是被黑客最多使用的攻击漏洞。所以了解缓冲区溢出方面的知识对于黑客也好或者管理员也好也或者是一般的网人也好都相 对是有必要的。


缓冲区溢出的概念和原理

缓冲区是内存中存放数据的地方。在程序试图将数据放到机器内存中的某一个位置的时候,因为没有足够的空间就会发生缓冲区溢出。而人为的溢出则是有一定企图 的,攻击者写一个超过缓冲区长度的字符串,然后植入到缓冲区,而再向一个有限空间的缓冲区中植入超长的字符串可能会出现两个结果,一是过长的字符串覆盖了 相邻的存储单元,引起程序运行失败,严重的可导致系统崩溃;另有一个结果就是利用这种漏洞可以执行任意指令,甚至可以取得系统root特级权限。大多造成 缓冲区溢出的原因是程序中没有仔细检查用户输入参数而造成的。

缓冲区是程序运行的时候机器内存中的一个连续块,它保存了给定类型的数据,随着动态分配变量会出现问题。大多时为了不占用太多的内存,一个有动态分配变量 的程序在程序运行时才决定给它们分配多少内存。这样想下去的话,如果说要给程序在动态分配缓冲区放入超长的数据,它就会溢出了。一个缓冲区溢出程序使用这 个溢出的数据将汇编语言代码放到机器的内存里,通常是产生root权限的地方,这就不是什么好现象了。仅仅就单个的缓冲区溢出惹眼,它并不是最大的问题根 本所在。但如果溢出送到能够以root权限运行命令的区域,一旦运行这些命令,那可就等于把机器拱手相让了。



?缓冲区溢出漏洞攻击方式

缓冲区溢出漏洞可以使任何一个有黑客技术的人取得机器的控制权甚至是最高权限。一般利用缓冲区溢出漏洞攻击root程序,大都通过执行类似 “exec(sh)”的执行代码来获得root 的shell。黑客要达到目的通常要完成两个任务,就是在程序的地址空间里安排适当的代码和通过适当的初始化寄存器和存储器,让程序跳转到安排好的地址空 间执行。


●在程序的地址空间里安排适当的代码:

其实在程序的地址空间里安排适当的代码往往是相对简单的,但也同时要看运气如何。如果说要攻击的代码在所攻击程序中已经存在了,那么就简单的对代码传递一 些参数,然后使程序跳转到目标中就可以完成了。攻击代码要求执行“exec(‘/bin/sh’)”,而在libc库中的代码执行 “exec(arg)”,当中的“arg”是个指向字符串的指针参数,只要把传入的参数指针修改指向“/bin/sh”,然后再跳转到libc库中的响应 指令序列就OK了。当然了,很多时候这个可能性是很小的,那么就得用一种叫“植入法”的方式来完成了。当向要攻击的程序里输入一个字符串的话,程序就会把 这个字符串放到缓冲区里,这个字符串包含的数据是可以在这个所攻击的目标的硬件平台上运行的指令序列。缓冲区可以设在像:堆栈(自动变量)、堆(动态分配 的)和静态数据区(初始化或者未初始化的数据)等的任何地方。也可以不必为达到这个目的而溢出任何缓冲区,只要找到足够的空间来放置这些攻击代码就够了。


●将控制程序转移到攻击代码的形式:

所有的这些方法都是在寻求改变程序的执行流程,使它跳转到攻击代码,最为基本就是溢出一个没有检查或者其它漏洞的缓冲区,这样做就会扰乱程序的正常执行次 序。通过溢出某缓冲区,可以改写相近程序的空间而直接跳转过系统对身份的验证。原则上来讲攻击时所针对的缓冲区溢出的程序空间可为任意空间。但因不同地方 的定位相异,所以也就带出了多种转移方式。

1、 unction Pointers(函数指针)

在程序中,“void (* foo) ( )”声明了个返回值为“void” Function Pointers的变量“foo”。Function Pointers可以用来定位任意地址空间,攻击时只需要在任意空间里的Function Pointers邻近处找到一个能够溢出的缓冲区,然后用溢出来改变Function Pointers。当程序通过Function Pointers调用函数,程序的流程就会实现。这个你可调用Linux下的superprobe程序体验一下。

2、 ctivation Records(激活记录)

当一个函数调用发生时,堆栈中会留驻一个Activation Records,它包含了函数结束

时返回的地址。执行溢出这些自动变量,使这个返回的地址指向攻击代码,再通过改变程序的返回地址。当函数调用结束时,程序就会跳转到事先所设定的地址,而 不是原来的地址。这样的溢出方式也是较常见的。你在使用漏洞扫描(Unix下的SATAN或者NT下的Retina)器时,最好是多注意“stack smashing attack”的字样。呵呵。

3、 Longjmp buffers(长跳转缓冲区)

在C语言中包含了一个简单的检验/恢复系统,称为“setjmp/longjmp”,意思是在

检验点设定“setjmp(buffer)”,用longjmp(buffer)“来恢复检验点。如果攻击时能够进入缓冲区的空间,感觉 “longjmp(buffer)”实际上是跳转到攻击的代码。像Function Pointers一样,longjmp缓冲区能够指向任何地方,所以找到一个可供溢出的缓冲区是最先应该做的事情。



●植入综合代码和流程控制

常见的溢出缓冲区攻击类是在一个字符串里综合了代码植入和ctivation Records。攻击时定位在一个可供溢出的自动变量,然后向程序传递一个很大的字符串,在引发缓冲区溢出改变ctivation Records的同时植入代码(权因C在习惯上只为用户和参数开辟很小的缓冲区)。植入代码和缓冲区溢出不一定要一次性完成,可以在一个缓冲区内放置代码 (这个时候并不能溢出缓冲区),然后通过溢出另一个缓冲区来转移程序的指针。这样的方法一般用于可供溢出的缓冲区不能放入全部代码时的。如果想使用已经驻 留的代码不需要再外部植入的时候,通常必须先把代码做为参数。在libc(熟悉C的朋友应该知道,现在几乎所有的C程序连接都是利用它来连接的)中的一部 分代码段会执行“exec(something)”,当中的something就是参数,使用缓冲区溢出改变程序的参数然后利用另一个缓冲区溢出使程序指 针指向libc中的特定的代码段。

对缓冲区溢出有兴趣的朋友,有必要找找eEye公司开发的Retina发现IIS4.0的那个缓冲区溢出漏洞引起的很多黑客攻击实例来看看。你可以在 http://www.safefan.com(傲气雄鹰网络安全小组)找到关于它们的资料,做为网络管理人员最因该熟悉它们。

程序编写的错误造成网络的不安全性也当受到重视,因为它的不安全性已被缓冲区溢出表现的淋漓尽致了。


█缓冲区溢出的防患

缓冲区溢出的漏洞被发现到利用以来一直都是网络安全领域的最大隐患,很多安全人士均对这些漏洞做了仔细的研究,但是缓冲区溢出的完全防止往往因为这样那样的人为或者其它的因素仍显得有点力不从心。在这篇文章里,就目前缓冲区溢出漏洞的几种保护方法做个简单的描述。

正确的编写代码

我想在编写代码的时候一般不会有人故意想要发生错误的,但是丝毫的错误往往会造成严重后果(C语言多是字符串因0收尾,往往就是一个很不安全例子)。所以正确的编写代码是很关键的。

在编写时以免错误发生最原始的方法就是用gerp来找出源代码中较容易产生的漏洞的库的调用。像对sprintf和strcpy的调用,这两个函数都不会 检查参数输入的长度。有的在编写的时候采用了sprintf和strcpy的替代函数来防止,但是还是会有问题发生的。因为这些错误的隐蔽性,所以就出现 了查错工具faultin-jection。faultin-jection可以通过人为随时产生一些缓冲区溢出来找到代码的安全漏洞。只能说 faultin-jection等类似的工具可以让编写时缓冲区溢出的漏洞更少一点,而完全的没有则是不现实的。因为它们确实不可能找到所有的溢出缓冲区 的漏洞。编写时重复的检查代码的漏洞可以使程序更加完美和安全。

?非执行的缓冲区

在老版的UNIX系统中,程序的数据段地址空间是不可执行的,这样就使得黑客在利用缓冲区植入代码时不能执行。但是现在的UNIX和Windows系统考 虑到性能和功能的速率和使用合理化,大多在数据段中动态形式的放入了可执行的代码,为了保证程序的兼容性不可能使用所有程序的数据段不可执行间。但可以通 过只设定堆栈数据段不可执行,这样就很大程度上保证了程序的兼容性能。UNIX、Linux、Windows、Solaris都已经发布了这方面的补丁。

检查数组边界

数组边界检查完全没有缓冲区溢出的产生,所以只要保证数组不溢出,那么缓冲区溢出攻击也就只能是望梅止渴了。实现数组边界检查,所有的对数组的读写操作都 应该被检查,这样可以保证对数组的操作在正确的范围之内。检查数组是一件叫人头大的事情,所以利用一些优化技术来检查就减少了负重。可以使用Compaq 公司专门为Alpha CPU开发的Compaq C编译器、Jones&Kelly的C的数组边界检查、Purify存储器存取检查等等来检查。

所有的缓冲区溢出漏洞都归于C语言的“功劳”。如果只有类型-安全的操作才可以被允许执行,这样就不会出现对变量的强制操作。类型-安全的语言被认定为 Java和ML等,但作为Java执行平台的Java虚拟机是C程序,所以攻击JVM的途径就是使JVM的缓冲区溢出。。。。。。。

程序指针完整性检查

程序指针完整性检查在程序指针被引用之前检测到它的改变,这个时候即便是有人改变了程序的指针,也辉因为系统早先已经检测到了指针的改变而不会造成指针对 利用的。但程序指针完整性检查不能解决所有的缓冲区溢出问题;如果有人使用了其它的缓冲区溢出,那么程序指针完整性检查就不可能检测到了。可话又说回来 了,程序指针完整性检查在性能上却有着很大的优势,并且有良好的兼容性。

2009年5月6日星期三

[转]ldconfig命令的用途

动态链接库管理命令

为了让动态链接库为系统所共享,还需运行动态链接库的管理命令--ldconfig.此执行程序存放在/sbin目录下.

ldconfig命令的用途,主要是在默认搜寻目录(/lib和/usr/lib)以及动态库配置文 件/etc/ld.so.conf内所列的目录下,搜索出可共享的动态链接库(格式如前介绍,lib*.so*),进而创建出动态装入程序(ld.so) 所需的连接和缓存文件.缓存文件默认为/etc/ld.so.cache,此文件保存已排好序的动态链接库名字列表.

ldconfig通常在系统启动时运行,而当用户安装了一个新的动态链接库时,就需要手工运行这个命令.

ldconfig命令行用法如下:

ldconfig [-v|--verbose] [-n] [-N] [-X] [-f CONF] [-C CACHE] [-r ROOT] [-l] [-p|--print-cache] [-c FORMAT] [--format=FORMAT] [-V] [-?|--help|--usage] path...

ldconfig可用的选项说明如下:

(1) -v或--verbose : 用此选项时,ldconfig将显示正在扫描的目录及搜索到的动态链接库,还有它所创建的连接的名字.

(2) -n : 用此选项时,ldconfig仅扫描命令行指定的目录,不扫描默认目录(/lib,/usr/lib),也不扫描配置文件/etc/ld.so.conf所列的目录.

(3) -N : 此选项指示ldconfig不重建缓存文件(/etc/ld.so.cache).若未用-X选项,ldconfig照常更新文件的连接.

(4) -X : 此选项指示ldconfig不更新文件的连接.若未用-N选项,则缓存文件正常更新.

(5) -f CONF : 此选项指定动态链接库的配置文件为CONF,系统默认为/etc/ld.so.conf.

(6) -C CACHE : 此选项指定生成的缓存文件为CACHE,系统默认的是/etc/ld.so.cache,此文件存放已排好序的可共享的动态链接库的列表.

(7) -r ROOT : 此选项改变应用程序的根目录为ROOT(是调用chroot函数实现的).选择此项时,系统默认的配置文件/etc/ld.so.conf,实际对应的为ROOT/etc/ld.so.conf.如用-r /usr/zzz时,打开配置文件/etc/ld.so.conf时,实际打开的是/usr/zzz/etc/ld.so.conf文件.用此选项,可以大大增加动态链接库管理的灵活性.

(8) -l : 通常情况下,ldconfig搜索动态链接库时将自动建立动态链接库的连接.选择此项时,将进入专家模式,需要手工设置连接.一般用户不用此项.

(9) -p或--print-cache : 此选项指示ldconfig打印出当前缓存文件所保存的所有共享库的名字.

(10) -c FORMAT 或 --format=FORMAT : 此选项用于指定缓存文件所使用的格式,共有三种:old(老格式),new(新格式)和compat(兼容格式,此为默认格式).

(11) -V : 此选项打印出ldconfig的版本信息,而后退出.

(12) -? 或 --help 或 --usage : 这三个选项作用相同,都是让ldconfig打印出其帮助信息,而后退出.

举三个例子:

例1:

# ldconfig -p
793 libs found in cache `/etc/ld.so.cache'
libzvt.so.2 (libc6) =>; /usr/lib/libzvt.so.2
libzvt.so (libc6) =>; /usr/lib/libzvt.so
libz.so.1.1.3 (libc6) =>; /usr/lib/libz.so.1.1.3
libz.so.1 (libc6) =>; /lib/libz.so.1
......
#

注: 有时候用户想知道系统中有哪些动态链接库,或者想知道系统中有没有某个动态链接库,这时,可用-p选项让ldconfig输出缓存文件中的动态链接库列 表,从而查询得到.例子中,ldconfig命令的输出结果第1行表明在缓存文件/etc/ld.so.cache中找到793个共享库,第2行开始便是 一系列共享库的名字及其全名(绝对路径).因为实际输出结果太多,为节省篇幅,以......表示省略的部分.


例2:

# ldconfig -v
/lib:
liby.so.1 ->; liby.so.1
libnss_wins.so ->; libnss_wins.so
......
/usr/lib:
libjscript.so.2 ->; libjscript.so.2.0.0
libkspell.so.2 ->; libkspell.so.2.0.0
......
/usr/X11R6/lib:
libmej-0.8.10.so ->; libmej-0.8.10.so
libXaw3d.so.7 ->; libXaw3d.so.7.0
......
#

注: ldconfig命令在运行正常的情况下,默认不输出什么东西.本例中用了-v选项,以使ldconfig在运行时输出正在扫描的目录及搜索到的共享库, 用户可以清楚地看到运行的结果.执行结束后,ldconfig将刷新缓存文件/etc/ld.so.cache.

例3:

# ldconfig /usr/zhsoft/lib

2009年5月5日星期二

设计模式学习的一点心得

工厂模式(Factory)
简单例子:
public class Factory{
public static Sample creator(){
....
if (which==1)
return new MySample();
else if (which==2)
return new HisSample();
}
}
使用工厂的原因:当Sample类的构造函数中的需要的大量的操作时,就违背了面向对象的原则.封装(Encapsulation)和分派(Delegation);我们需要将创建实例的责任与使用实例的责任分开, 使得语句
Sample sample=new Sample(参数);

就是简单的责任:使用Sample 这个实例;至于创建Sample 的任务就交给了Factory 工厂模式.还有,如果Sample 有个继承如MySample, 按照面向接口编程,我们需要将Sample 抽象成一个接口.现在Sample 是接口,有两个子类MySample 和HisSample .我们要实例化他们时,如下:
Sample mysample=new MySample();
Sample hissample=new HisSample();

随着项目的深入,Sample 可能还会"生出很多儿子出来", 那么我们要对这些儿子一个个实例化,更糟糕的是,可能还要对以前的代码进行修改:加入后来生出儿子的实例.这在传统程序中是无法避免的.但如果你一开始就有意识使用了工厂模式,这些麻烦就没有了.

设计模式之Builder
简单例子:
public interface Builder {
//创建部件A 比如创建汽车车轮
void buildPartA();
//创建部件B 比如创建汽车方向盘
void buildPartB();
//创建部件C 比如创建汽车发动机
void buildPartC();
//返回最后组装成品结果 (返回最后装配好的汽车)
//成品的组装过程不在这里进行,而是转移到下面的Director 类中
进行.
//从而实现了解耦过程和部件
Product getResult();
}

public class Director {
private Builder builder;
public Director( Builder builder ) {
this.builder = builder;
}
// 将部件partA partB partC 最后组成复杂对象
//这里是将车轮 方向盘和发动机组装成汽车的过程
public void construct() {
builder.buildPartA();
builder.buildPartB();
builder.buildPartC();
}
}
使用Builder的原因:在Java 实际使用中,我们经常用到"池"(Pool)的概念,当资源提供者无法提供足够的资源,并且这些资源需要被很多用户反复共享时,就需要使用池."池"实际是一段内存,当池中有一些复杂的资源的"断肢"(比如数据库的连接池,也许有时一个连接会中断),如果循环再利用这些"断肢",将提高内存使用效率,提高池的性能.修改Builder 模式中Director 类使之能诊断"断肢"断在哪个部件上,再修复这个部件。

设计模式之Singleton(单例模式)
简单例子:
public class Singleton {
private static Singleton _instance = new Singleton();
public static Singleton getInstance() {
return _instance;
}
}
调用方法:
Singleton.getInstance()
应用反向:整个系统中类的实例只有一个。

设计模式之Facade(外观)
Facade 的定义: 为子系统中的一组接口提供一个一致的界面.
较易理解,或许你在不知不觉中已经用过了,不再阐述。

设计模式之Proxy(代理)
Proxy 是比较有用途的一种模式,而且变种较多,应用场合覆盖从小结构到整个系统的大结构,Proxy 是代理的意思,我们也许有代理服务器等概念,代理概念可以解释为:在出发点到目的地之间有一道中间层,意为代理.
设计模式中定义: 为其他对象提供一种代理以控制对这个对象的访问.

为什么要使用Proxy?
1.授权机制 不同级别的用户对同一对象拥有不同的访问权利,如Jive 论坛系统中,就使用Proxy 进行授权机制控制,访问论坛有两种人:注册用户和游客(未注册用户),Jive 中就通过类似ForumProxy 这样的代理来控制这两种用户对论坛的访问权限.
2.某个客户端不能直接操作到某个对象,但又必须和那个对象有所互动.
举例两个具体情况:
(1)如果那个对象是一个是很大的图片,需要花费很长时间才能显示出来,那么当这个图片包含在文档中时,使用编辑器或浏览器打开这个文档,打开文档必须很迅速,不能等待大图片处理完成,这时需要做个图片Proxy 来代替真正的图片.
(2)如果那个对象在Internet 的某个远端服务器上,直接操作这个对象因为网络速度原因可能比较慢,那我们可以先用Proxy 来代替那个对象.总之原则是,对于开销很大的对象,只有在使用它时才创建,这个原则可以为我们节省很多宝贵的Java 内存.
所以,有些人认为Java 耗费资源内存,我以为这和程序编制思路也有一定的关系.

*简单例子:
以Jive 论坛系统为例,Forum 是Jive 的核心接口,在Forum 中陈列了有关论坛操作的主要行为,如论坛名称 论坛描
述的获取和修改,帖子发表删除编辑等.
在ForumPermissions 中定义了各种级别权限的用户:
public class ForumPermissions implements Cacheable {
/**
* Permission to read object.
*/
public static final int READ = 0;
/**
* Permission to administer the entire sytem.
*/
public static final int SYSTEM_ADMIN = 1;
/**
* Permission to administer a particular forum.
*/
public static final int FORUM_ADMIN = 2;
/**
* Permission to administer a particular user.
*/
public static final int USER_ADMIN = 3;
/**
* Permission to administer a particular group.
*/
public static final int GROUP_ADMIN = 4;
/**
* Permission to moderate threads.
*/
public static final int MODERATE_THREADS = 5;
/**
* Permission to create a new thread.
*/
public static final int CREATE_THREAD = 6;
/**
* Permission to create a new message.
*/
public static final int CREATE_MESSAGE = 7;
/**
* Permission to moderate messages.
*/
public static final int MODERATE_MESSAGES = 8;
.....
public boolean isSystemOrForumAdmin() {
return (values[FORUM_ADMIN] || values[SYSTEM_ADMIN]);
}
.....
}

因此,Forum 中各种操作权限是和ForumPermissions 定义的用户级别有关系的,作为接口Forum 的实现:ForumProxy 正是将这种对应关系联系起来.比如,修改Forum 的名称,只有论坛管理者或系统管理者可以修改,代码如下:
public class ForumProxy implements Forum {
private ForumPermissions permissions;
private Forum forum;
this.authorization = authorization;
public ForumProxy(Forum forum, Authorization authorization,
ForumPermissions permissions)
{
this.forum = forum;
this.authorization = authorization;
this.permissions = permissions;
}
.....
public void setName(String name) throws UnauthorizedException,
ForumAlreadyExistsException
{
//只有是系统或论坛管理者才可以修改名称
if (permissions.isSystemOrForumAdmin()) {
forum.setName(name);
}
else {
throw new UnauthorizedException();
}
}
...
}
而DbForum 才是接口Forum 的真正实现,以修改论坛名称为例:
public class DbForum implements Forum, Cacheable {
...
public void setName(String name) throws
ForumAlreadyExistsException {
....
this.name = name;
//这里真正将新名称保存到数据库中
saveToDb();
....
}
...
}

凡是涉及到对论坛名称修改这一事件,其他程序都首先得和ForumProxy 打交道,由
ForumProxy 决定是否有权限做某一样事情,ForumProxy 是个名副其实的"网关","安全代理
系统".

先写这么多了,懒了

2009年5月4日星期一

在这里,读聋中国

今日《南方周末》刊出我的短评《人性光亮在民间》,发表时标题改成了《人性光芒在人间》。“在民间”与“在人间”,一字之差,意境全失,一下子就将我含沙射影的腹诽,变成了《读者》式的低俗感动,同时营造出企业雇佣童工演唱《感恩的心》的动人气氛。

结尾也被删节得厉害,我的原作是“去年,有杂志做过一项关于中国人信用的调查,结果显示,官员信用最差而农民信用最好。联系到上述两案中那些普通人,甚至是引车卖浆者流的底层普通人的美好表现,我忍不住想起一句话:“礼失而求诸野”。也无妨,至少人性光亮,仍在民间”,见报时成了“上述那些普通人,甚至是引车卖浆者流的底层普通人的美好表现,让我忍不住想说一句话:人性光芒仍在人间”。一下子就将我这个三十多岁的人,穿越为一个天真无邪的喜欢写“不要问我的名字,请叫我红领巾”一类句子的小学生。

我向笑蜀老师抗议,得到回复是,目前南周有难言之隐,言论空间非常逼仄(不止南周,也包括南都。笑蜀尚有极沉痛语,不宜放出,暂略)。我对笑蜀说,捂住你们的嘴巴就是捂住读者的耳朵,所以,你们不妨把自己的广告语改成这样来抗议:在这里,读聋中国。

顺便说一下,我的讥刺决不是针对南周,而是针对让南周如此谨小慎微如履薄冰的幕后铁手。网络与平媒唇亡齿寒,南周每失去一寸言论与新闻的空间,则网络的言论与新闻空间,也同样狭窄一分。

人性光亮在民间

刊于今日《南方周末》宋石男

1935年,纽约一名老妇人因偷面包被审。她流着泪水乞求法官原谅,说只是需要面包去喂养嗷嗷待哺的孙子。法官依然判她有罪,不过可选择10美元罚款或10天拘役。这时,时任纽约市长的拉瓜迪亚站起来,脱下帽子,放进5美元,对其余人说:“请各位另交50美分罚款,为我们的冷漠付费,也为我们生活在一个老祖母要去偷面包来喂养孙子的城市而受罚。”

时光流转,在今日之广州,有一些良善的普通人,也放进了他们的5美元。

421日,重庆开县来广州务工的张氏两兄弟,持刀劫持女人质,与警方对峙90分钟后被擒。他们称,抢劫是想为其母筹集医药费。说法被媒体证实后,不少热心民众愿为张母捐款,其中一位说:“这不是鼓励犯罪,而是出于最起码的同情心”。

依靠“最起码的同情心”,另一起悲剧也得到妥善调停。418日,12岁黄姓男童在高楼抛砖玩,砸死路过女婴。男童家境贫寒,其父为筹钱赔偿,一度想卖掉亲子,其母则向死者家属下跪道歉。数日后,普通民众与企业捐款12万余元,助黄家支付9万元赔偿金,死者家属也与黄家达成谅解。剩余的3万元捐款,以遇难女婴的名义捐给福利机构。

在上述事件中,不同立场的普通人均闪现出人性的光亮。

张 氏兄弟铤而走险的背后,是对母亲的热爱与责任感,是无奈与绝望中迸发的担当(当然,美好的出发点并不能为之脱罪,他们的行为也绝对不应提倡)。而为张氏母 亲捐款的普通民众,则如墨子说的“有力者疾以助人,有财者勉以分人”,尽显“兼爱”光辉,也为他们生活在一个儿子需要去抢劫来为母亲治病的国家而救赎。

在坠砖杀婴案中,肇事者家长表现出相当扎实的责任感,愿为赎罪付出一切,受害者家长则报以难得一见的宽宏与谅解。而10多名热心捐款的普通民众,更让洋溢人性光辉的溪水流淌成江河。他们三方,共同证明了罗尔斯所说的“道德人格”并非乌托邦——人有能力获得善的观念,人还有能力获得正义感。

孟 子曾说,“无恻隐之心,非人也;无羞恶之心,非人也……恻隐之心,仁之端也;羞恶之心,义之端也。”张氏兄弟抢劫案及幼童坠砖杀婴案中诸人的表现,说穿了 就是“恻隐之心”与“羞恶之心”——前者酿出悲天悯人的情怀以及由此生发的善行,如春天的树般指向天空;后者酿出无所逃天地间的责任感以及由此生发的义 举,如夏日山峰矗立大地。

去年,有杂志做过一项关于中国人信用的调查,结果显示,官员信用最差而农民信用最好。联系到上述两案中那些普通人,甚至是引车卖浆者流的底层普通人的美好表现,我忍不住想起一句话:“礼失而求诸野”。也无妨,至少人性光亮,仍在民间。

2009年5月3日星期日

认识下linux下程序的国际化(C语言实例)

要让程序能够根据操作系统的环境的不同而显示不同的UI界面,需要将程序的本地化;如果手工将源程序中的字符串替换为与环境相符的字符来实现本地化的方法 不具有通用性,因为针对每一种操作系统环境都要重复以上操作工作量很大,一般的方法是先将程序国际化,然后再进行本地化;linux上的这个过程主要用到 了两个工具:xgettext和msgfmt;
not: xgettext是国际化的工具,提取出源文件中的字符串,生成*.po的文件,而msgfmt是本地化的工具,首先是人工的翻译*.po文件中的字符串,然后使用msgfmt生成*.mo文件,再编译后,程序启动时会扫描系统环境提取mo文件中的字符串代替原来的英文。
测试实例(helloworld):
#include ;
#include ;
#include ; //包含了两个头文件

#define _(STRING) gettext(STRING) //定义了_(STRING)宏,只是为了简化
#define PACKAGE "test_locale" //定义了软件包的名字,最后生成的.mo文件名应该命名为这个
#define LOCALEDIR "./po" //定义了mo文件将要存放的位置

int main(int argv,int*argc[])
{
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR); //bind软件包与mo文件存放的位置
textdomain (PACKAGE);

printf(_("hello,world!\n")); //将_(STRING)宏应用到了字符串上
}
将程序这样改写以后,就叫国际化了,简单吧?但不是说这样程序就能根据系统环境显示相应的界面了,我们还需要将它本地化;我们将程序保存为test_locale.c;
利用xgettext生成test_locale.po文件
xgettext -k_ -o test_locale.po test_locale.c
-k 指定翻译字符以何种宏定义括起,我们在前面使用的是 _( ) 所以用 -k_
编辑test_locale.po文件成:

# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR , YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-05-03 23:25+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" //注意修改charset的值
"Content-Transfer-Encoding: 8bit\n"

#: hello_I18N.c:15
#, c-format
msgid "hello,world!\n"
msgstr "你好,世界!\n" //翻译
接下来再利用msgfmt生成test_locale.mo文件
msgfmt -o test_locale.mo test_locale.po
将test_locale.mo文件放在之前设定的LOCALEDIR/xxxx/yyyyy目录下,其中的xxxx和yyyy稍后就明白了;
现在再来看看程序的运行结果
当系统环境 LANG=en_US的时候,结果如下:
hello,world!
当系统环境 LANG=zh_CN.UTF-8的时候,结果如下:
你好,世界!
就是说,在程序运行时,会根据LANG自动到LOCALEDIR/zh_CN/LC_MESSAGES寻找mo文件,从而正确显示;所以上文中的xxxx和yyyy就是zh_CN和LC_MESSAGES。

[转]国际化(I18N)、本地化(L10N)、多语言化(M17N)和全球化(G11N)的概念

这里所提到的国际化(I18N)、本地化(L10N)、多语言化(M17N)和全球化(G11N)都是软件开发和测试的相关术语。理解这几个概念会 对于开源软件有更深刻的认识,因为对于开源软件,大到开源的Linux操作系统,小到GNU的小软件,本地化和国际化都做得不错。具一个最简单的例子:Wordpress开源博客程序,只要您愿意,就可以对照官方提供的POT英文语言包文件制作不同国家的要地化语言包mo文件。(这个拉下来的几篇文章我们会提到,这里打一个埋伏)。对于闭源的Windows操作系统来讲,随心所欲地本地化简直就是天方夜谭。

国际化(I18N)

在英文中, 国际化(Internationalization)被缩写为I18N,,即只 取首尾两个字母,中间字母为18个。

通俗地讲,”国际化”是指把原来为英文设计的计算机系统或应用软件改写为同时支持多种语言和文化习俗的过程。即在软件创作的初期,一般的编程语言, 编译,开发都是只支持英文的,为了适应更广的语言和文化习俗,软件有必要在设计结构和机制上支持多语言的扩展特性, 这一过程称为国际化。

国际化仅仅是在软件设计上提供了使用多语 言的可能。是使产品或软件具有不同国际市场的普遍适应性,从而无需重新设计就可适应多种语言。

真正的国际化要在软件设计和文档开发过程中,使产品或软件的功能和代码设计能处理多种语言和文化习俗,具有良好的本地化能力。

本地化(L10N)

是“Localization”的缩写,中间的 10 代表在首字母“L”和尾字母“N”之间省略了 10 个字母。

简单讲,本地化(L10N)是将操作系统或软件针对特定国际语言和文化进行加工,使之符合特定区域市场的过程。即把计算机系统或者应用软件转变为使 用并兼容某种特定语言的过程.比如,把原来为英文设计软件制作为支持中文的软件就是本地化的一种.它主要包括翻译文本信息,界面信息,重新设计图标等等.

真正的本地化要考虑目标区域市场的语言、文化、习俗、特征和标准。通常包括改变软件的书写系统(输入法)、键盘使用、字体、日期、时间和货币格式等。

多语言化(M17N)

M17N为英文Multilingualization(多语言化)的缩写。

在国际化部分中只处理语言的部分叫”多语言化”.比方说, 一个 “多语言化”的软件可以同时管理诸如英语,法语,中日韩文,阿拉伯语等.

全球化(G11N)

全球化(G11N)是“Globalization”的缩写。

这个概念我们了解一下就好了。全球化简单来讲就是本地化和国际化的合称。

全球化(G11N)是是使产品或软件进入全球市场而进行的有关的商务活动。包括正确的国际化设计,本地化集成,以及在全球市场进行的市场推广、销售 和支持的全部过程。企业通过 全球化实现其全球化发展战略,实现全球化业务,扩大市场规模,降低软件成本,提升综合竞争力,展现企业发展实力,增强用户信心,树立市场形象。

2009年5月1日星期五

看《南京!南京》有感

今天师兄以及一撮同学一起去看了现在吵的比较火的电影——《南京!南京》。

从电影欣赏的角度来讲,这绝对是中国难得的一部好片。整个电影也并不是以一个日本兵的角度来讲整个故事,而是一个很宏大的不是单一的一个角度来讲南京大屠杀。或许可能是在电影院里看的原因,这部片子的音效相当好,配乐也很能烘托出当时的场景与角色的心里活动。

还有就是黑白片的形式很特别。故事也还不错,编剧还是比较用心的。一定程度上还原了当时的情形。

演员的功力也着实不错,特别是那位日本演员演技真的很不错。不过让我莫名其妙的是刘烨的出场时间不到20分钟,但在确实主角,而且在放字幕时是第一位,表现的也没有日本演员出彩。

比起流行的爱情片或者是武打片之类的电影(类似《赤壁》),放上一个为大义牺牲的之类的精神,完全给人一种架空的感觉。而这部电影讲的是南京大屠杀,引发的不是什么民族精神或是要自强不息之类的空口号。更多的是人性与灵魂的救赎(的确如导演所说)。最后那个日本兵角川自杀前说的一句话烘托出了电影的主旨。那句话就是:“死了比活着更容易”。另外要申明的是这不是一部给日本看让他们反省的片子。因为获得救赎的不止是角川而已,具体可以看电影。

总之,《南京!南京》是一部难得的好电影。

*反思:
一直很讨厌把电影看成是说教的人,《南京》热映之后,有人认为这是一部教育篇,引发了一些其他的讨论(比如牛博上有人提出:也该反思毛**害死的人)。这实在是太无聊了,电影就是电影不是说教。当然那些把《南京》宣扬成是爱国教育的人也是无聊。娱乐与政治无关。

*趣闻:
电影中有一段很有意思,关于一句上海话:“吃饭当心点。”这本是一句生离死别的最后的牵挂的表现。话没问题很符合角色的文化程度与当时的环境。但是这本该是用上海话讲得。结果“吃饭”两字是上海话,“当心点”是普通话。当时把我搞笑了,还好没大声笑出来。这只能说是标准的现代上海话,非正统的上海话,更不是南京大屠杀那时可能有的。