Tuesday, December 20, 2011

apache2.2 日志中的一些注意事项

一些说明
出于安全考虑,从2.0.46版本开始,%r, %i, %o 中的特殊字符,除了双引号(")和反斜线(\)分别用 \" 和 \\ 进行转义、空白字符用C风格(\n, \t 等)进行转义以外,非打印字符和其它特殊字符使用 \xhh 格式进行转义(hh是该字符的16进制编码)。在2.0.46以前的版本中,这些内容会被完整的按原样记录。这种做法将导致客户端可以在日志中插入控制字 符,所以你在处理这些日志文件的时候要特别小心。

在2.0版本中(不同于1.3),%b 和 %B 格式字符串并不表示发送到客户端的字节数,而只是简单的表示HTTP应答字节数(在连接中断或使用SSL时与前者有所不同)。mod_logio提供的 %O 格式字符串将会记录发送的实际字节数。


String replaced = url.replaceAll("\\\\x", "%");
String decode = URLDecoder.decode(replaced, "utf-8");

Saturday, July 02, 2011

clear run history in gnome panel

run "gconf-editor" and find "gnome-panel", modify "history-gnome-run".

Xen and ntpdate

ntpdate在XEN虚拟机上执行后,不能更新当前时间。
修复方法:
将下面的指令加入/etc/rc.local文件后重启机器就可以,不重启的话手动在命令行中运行此命令。


echo 1 > /proc/sys/xen/independent_wallclock
ntpdate ntp.ubuntu.com > /dev/null

nginx rewrite command spec

rewrite
syntax: rewrite regex replacement flag

default: none

context: server, location, if

This directive changes URI in accordance with the regular expression and the replacement string. Directives are carried out in order of appearance in the configuration file.

Flags make it possible to end the execution of rewrite directives.

If the replacement string begins with http:// then the client will be redirected, and any further rewrite directives are terminated.

Flags can be any of the following:

last - completes processing of rewrite directives, after which searches for corresponding URI and location
break - completes processing of rewrite directives
redirect - returns temporary redirect with code 302; it is used if the substituting line begins with http://
permanent - returns permanent redirect with code 301
Note that if a redirect is relative (has no host part), then when redirecting Nginx uses the "Host" header if the header match name of server_name directive or the first name of server_name directive, if the header does not match or is absent. If no server_name is set, then the local hostname is used. If you want Nginx to always use the "Host" header, you can use a wildcard "*" server_name (but see the restrictions on doing so). Example:


rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 last;
rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra last;
return 403;

But if we place these directives in location /download/, then it is necessary to replace flag "last" by "break", otherwise Nginx will hit the 10 cycle limit and return error 500:

location /download/ {
rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 break;
rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra break;
return 403;
}

If in the line of replacement arguments are indicated, then the rest of the request arguments are appended to them. To avoid having them appended, place a question mark as the last character:

rewrite ^/users/(.*)$ /show?user=$1? last;

Note: for curly braces( { and } ), as they are used both in regexes and for block control, to avoid conflicts, regexes with curly braces are to be enclosed with double quotes (or single quotes). For example, to rewrite URLs like:

/photos/123456
to:

/path/to/photos/12/1234/123456.png
use the following (note the quotes enclosing the regex):

rewrite "/photos/([0-9] {2})([0-9] {2})([0-9] {2})" /path/to/photos/$1/$1$2/$1$2$3.png;

If you specify a ? at the end of a rewrite then Nginx will drop the original $args (arguments). When using $request_uri or $uri&$args you should specify the ? at the end of the rewrite to avoid Nginx doubling the query string.

Example using $request_uri in a rewrite from www.example.com to example.com

server {
server_name www.example.com;
rewrite ^ http://example.com$request_uri? permanent;
}

Also rewrite operates only on path, not parameters. To rewrite a URL with parameters to another URL, use this instead:

if ($args ^~ post=100){
rewrite ^ http://example.com/new-address.html? permanent;
}

Note that the $args variable is not decoded, unlike URIs during location matching.

phpunit error in ubuntu 11.04

Got below warning when run phpunit in ubuntu 11.04:

PHP Warning: require_once(PHP/CodeCoverage/Filter.php): failed to open stream: No such file or directory in /usr/bin/phpunit on line 38
PHP Stack trace:
PHP 1. {main}() /usr/bin/phpunit:0
PHP Fatal error: require_once(): Failed opening required 'PHP/CodeCoverage/Filter.php' (include_path='.:/usr/share/php:/usr/share/pear') in /usr/bin/phpunit on line 38
PHP Stack trace:
PHP 1. {main}() /usr/bin/phpunit:0

repair commands:


sudo apt-get remove phpunit
sudo pear channel-discover pear.phpunit.de
sudo pear channel-discover pear.symfony-project.com
sudo pear channel-discover components.ez.no
sudo pear update-channels
sudo pear upgrade-all
sudo pear install --alldeps phpunit/PHPUnit
sudo apt-get install phpunit

修复 ubuntu 11.04 亮度调节组合键功能

安装N卡驱动之后,Thinkpad的Fn+Home调节亮度的组合键失效。
修改/etc/X11/xorg.conf 文件,加入Option那一行,重启生效。


Section "Device"
Identifier "Device0"
Driver "nvidia"
VendorName "NVIDIA Corporation"
BoardName "NVS 3100M"
Option "RegistryDwords" "EnableBrightnessControl=1"
EndSection

IDE aptana menu problem in ubuntu 11.04


#!/bin/bash
export UBUNTU_MENUPROXY=0
/path/to/AptanaStudio3

Modifying the Query String In mod_rewrite of Apache2

RewriteRule backreferences: These are backreferences of the form $N (0 <= N <= 9), which provide access to the grouped parts (in parentheses) of the pattern, from the RewriteRule which is subject to the current set of RewriteCond conditions..
RewriteCond backreferences: These are backreferences of the form %N (1 <= N <= 9), which provide access to the grouped parts (again, in parentheses) of the pattern, from the last matched RewriteCond in the current set of conditions.

By default, the query string is passed through unchanged. You can, however, create URLs in the substitution string containing a query string part. Simply use a question mark inside the substitution string to indicate that the following text should be re-injected into the query string. When you want to erase an existing query string, end the substitution string with just a question mark. To combine new and old query strings, use the [QSA] flag.


# rewrite without old query string
RewriteCond %{QUERY_STRING} ^page_id=(.*)$
RewriteRule ^index.php$ /index/%1.php? [R=301,L]

# rewrite with new query string
RewriteCond %{QUERY_STRING} ^page_id=(.*)$
RewriteRule ^index.php$ /index/%1.php\?test=1 [R=301,L]

# rewrite with combined old query string
RewriteCond %{QUERY_STRING} ^page_id=(.*)$
RewriteRule ^index.php$ /index/%1.php\?test=1 [QSA,R=301,L]

globalEval function of jQuery changed in version 1.6

globalEval function of jquery before version 1.6, such as 1.5.2 and 1.2.6, source code:

// Evalulates a script in a global context
globalEval: function( data ) {
if ( data && rnotwhite.test(data) ) {
// Inspired by code by Andrea Giammarchi
// http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
var head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement,
script = document.createElement( "script" );

if ( jQuery.support.scriptEval() ) {
script.appendChild( document.createTextNode( data ) );
} else {
script.text = data;
}

// Use insertBefore instead of appendChild to circumvent an IE6 bug.
// This arises when a base node is used (#2709).
head.insertBefore( script, head.firstChild );
head.removeChild( script );
}
},

globalEval function of jquery 1.6 source code:
// Evaluates a script in a global context
// Workarounds based on findings by Jim Driscoll
// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
globalEval: function( data ) {
if ( data && rnotwhite.test( data ) ) {
// We use execScript on Internet Explorer
// We use an anonymous function so that context is window
// rather than jQuery in Firefox
( window.execScript || function( data ) {
window[ "eval" ].call( window, data );
} )( data );
}
},

rails 3.0.7 在ubuntu 11.04中安装问题


$> sudo gem install rails

This is the problematic part:

File not found: lib
ERROR: While generating documentation for rails-3.0.7
... MESSAGE: exit
...

这个问题是因为Rails新版本使用了最新的Rdoc/ri版本,而系统中原来的版本有些功能不是兼容的,因此报错。
卸载已经安装的rails3,先安装rdoc-data成功后再安装rails3。

$> sudo gem uninstall rails --version 3.0.7
$> sudo gem install rdoc-data
$> sudo rdoc-data --install
$> sudo gem install rails

安装成功信息:
Successfully installed rails-3.0.7
1 gem installed
Installing ri documentation for rails-3.0.7...
Installing RDoc documentation for rails-3.0.7...

Wednesday, May 18, 2011

configure php xdebug in ubuntu

先安装php和xdebug,并配置php.ini文件
$> sudo apt-get install apache2 php5 xdebug
$> sudo vi /etc/php5/apache2/php.ini
在php.ini文件最后面添加下面3行内容,其他如zend_extension的值ubuntu在xdebug安装完会自动在/etc/php5/conf.d/xdebug.ini中设置:


[Xdebug]
xdebug.remote_autostart=On
xdebug.remote_enable=On


然后从eclipse.org官网下载eclipse for php版本:
我的电脑是ubuntu 11.04 64位的机器,所以下载64位的版本:
$> wget http://www.eclipse.org/downloads/download.php?file=/technology/epp/downloads/release/helios/SR2/eclipse-cpp-helios-SR2-linux-gtk-x86_64.tar.gz&url=http://mirrors.ustc.edu.cn/eclipse/technology/epp/downloads/release/helios/SR2/eclipse-cpp-helios-SR2-linux-gtk-x86_64.tar.gz&mirror_id=1093

打开eclipse之后,进入window-Performances-PHP-Debug设置面板,在右边的“PHP Debuger”中选择Xdebug,然后点击Xdebug的Configure,再选择其中的Xdebug进行编辑,将"Accept remote session(JIT)"的值设置为"localhost",(默认值为off时,是不会开启xdebug调试功能的),这个设置和php.ini设置必须要都做到才会开启debug功能。
这样配置就完成了,可以打开浏览器访问PHP页面,在eclipse中的PHP源码,如果有设置断点就会进入Debug模式。

在Debug模式中的Server就使用默认的http://localhost,"PHP Executeable"原来是"None Defined",这个没有关系,也可以手动设置一个值,如"/usr/bin/php5",这个不影响debug功能。

抄录部分xdebug远程调试相关的参数说明,官网可参考http://xdebug.org/docs/remote中的说明。

xdebug.remote_autostart
类型:布尔型 默认值:0
一般来说,你需要使用明确的HTTP GET/POST变量来开启远程debug。而当这个参数设置为On,xdebug将经常试图去开启一个远程debug session并试图去连接客户端,即使GET/POST/COOKIE变量不是当前的。

xdebug.remote_enable
类型:布尔型 默认值:0
这个开关控制xdebug是否应该试着去连接一个按照xdebug.remote_host和xdebug.remote_port来设置监听主机和端口的debug客户端。

xdebug.remote_host
类型:字符串 默认值:localhost
选择debug客户端正在运行的主机,你不仅可以使用主机名还可以使用IP地址

xdebug.remote_port
类型:整型 默认值:9000
这个端口是xdebug试着去连接远程主机的。9000是一般客户端和被绑定的debug客户端默认的端口。许多客户端都使用这个端口数字,最好不要去修改这个设置。

Windows的设置可以参考下面这个链接中说明:http://be-evil.org/post-70.html
Mac中可以下载一个MacGDBp,这个用来调试PHP,非常好用,与IDE就完全脱离关系了。

Tuesday, April 19, 2011

get window scroll bar width

浏览器因为操作系统或者系统主题不同,导致当前窗口中的scrollbar的宽度不一致,在web应用中影响了页面布局,下述方法可以获取到当前浏览器的滚动条宽度:


function getScrollBarWidth () {
var inner = document.createElement('p');
inner.style.width = "100%";
inner.style.height = "200px";

var outer = document.createElement('div');
outer.style.position = "absolute";
outer.style.top = "0px";
outer.style.left = "0px";
outer.style.visibility = "hidden";
outer.style.width = "200px";
outer.style.height = "150px";
outer.style.overflow = "hidden";
outer.appendChild (inner);

document.body.appendChild (outer);
var w1 = inner.offsetWidth;
outer.style.overflow = 'scroll';
var w2 = inner.offsetWidth;
if (w1 == w2) w2 = outer.clientWidth;

document.body.removeChild (outer);

return (w1 - w2);
};


Reference:http://www.alexandre-gomes.com/?p=115
http://www.softcomplex.com/docs/get_window_size_and_scrollbar_position.html

Monday, April 18, 2011

The classpath*: prefix of java

When constructing an XML-based application context, a location string may use the special classpath*: prefix:


ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath*:conf/appContext.xml");

This special prefix specifies that all classpath resources that match the given name must be obtained (internally, this essentially happens via a ClassLoader.getResources(...) call), and then merged to form the final application context definition.

Classpath*: portability
The wildcard classpath relies on the getResources() method of the underlying classloader. As most application servers nowadays supply their own classloader implementation, the behavior might differ especially when dealing with jar files. A simple test to check if classpath* works is to use the classloader to load a file from within a jar
on the classpath:

getClass().getClassLoader().getResources("someFileInsideTheJar").

Try this test with files that have the same name but are placed inside two different locations.
In case an inappropriate result is returned, check the application server documentation for settings that might affect the classloader behavior.

The "classpath*:" prefix can also be combined with a PathMatcher pattern in the rest of the location path, for example "classpath*:META-INF/*-beans.xml". In this case, the resolution strategy is fairly simple: a ClassLoader.getResources() call is used on the last non-wildcard path segment to get all the matching resources in the class loader hierarchy, and then off each resource the same PathMatcher resoltion strategy described above is used for the wildcard subpath.

Memo: This article content copied from spring 3.0 framework reference PDF file.

linux命令nc使用实例说明

使用netcat检查服务器的指定的端口是否开通:
root@localhost:~$ nc -z -v 192.168.1.242 80
linux.local [192.168.1.242] 80 (www) open

使用netcat扫描端口:
root@localhost:~$ nc -z -v -w 1 192.168.1.242 1-100
linux.local [192.168.1.242] 80 (www) open
linux.local [192.168.1.242] 22 (ssh) open

使用netcat模拟HTTP请求:
root@localhost:~$ nc www.google.com.hk 80
GET / HTTP/1.1
Host: www.google.com.hk
User-Agent: google-chrome9

HTTP/1.1 200 OK
Date: Mon, 18 Apr 2011 08:56:03 GMT
Expires: -1
Cache-Control: private, max-age=0
Content-Type: text/html; charset=Big5
Set-Cookie: PREF=ID=5006f5c292697224:FF=0:NW=1:TM=1303116963:LM=1303116963:S=Lr6ijyXSbmjA6bmZ; expires=Wed, 17-Apr-2013 08:56:03 GMT; path=/; domain=.google.com.hk
Set-Cookie: NID=46=ky6egq_YajJNEzdnM39_2u3CFq2hJLvSVuQm6BokYXSBKhAefFIuL-ZsZOvnDpMISnI2glY25IZxS8_5G0V-EHj-oEc7KRGW4rSZk9yIRnCgsPnm43qhLUMb9hJuKeVW; expires=Tue, 18-Oct-2011 08:56:03 GMT; path=/; domain=.google.com.hk; HttpOnly
Server: gws
X-XSS-Protection: 1; mode=block
Transfer-Encoding: chunked
[......]

Friday, January 28, 2011

Tomcat URL 支持中文文件名

在tomcat的默认配置情况下,如果访问一个"中文.html"页面,服务器会抛出文件找不到的错误提示,这需要对tomcat的配置文件略作改动,为Connector设置URIEncoding的参数。
在server.xml文件中找到8080服务器配置的一段设置:

<Connector port="8080" maxThreads="150" minSpareThreads="25" maxSpareThreads="75" enableLookups="false" redirectPort="8443" acceptCount="100" debug="0" connectionTimeout="20000" disableUploadTimeout="true" URIEncoding="UTF-8"/>


加上 URIEncoding="UTF-8" 这句就可以识别中文文件名了,同时如果url中的参数值有中文,服务器端也可以正常解析对应的参数,否则服务器端Java程序中取到的参数是以ISO-8859-1编码的,有中文字符的参数值是乱码的,加了URIEncoding="UTF-8"之后,就可以正确获取到参数值了。
对于这个参数的说明,可以查看tomcat目录中的doc帮助文件,也可以从官网中找到此参数的解释。

References: 官方文档
Configure tomcat's uri encoding

IE throw null object exception when flash call javascript function

用open flash chart第一次正常载入一个图表到页面之后,当使用jQuery.fn.empty()方法移除此图表时,IE中会抛出一个错误,其他浏览器都是正常的,内容如下:


JScript - script block, line 1 character 124
'null' is null or not an object

通过IE8的debug工具可以看到出错时,javascript正在执行的代码如下:

try { document.getElementById("report-charts").SetReturnValue(__flash__toXML(ofc_resize([66,-96,66,-87])) ); } catch (e) { document.getElementById("report-charts").SetReturnValue("<undefined/>"); }

这个并不是页面中的javascript代码,应该是flash中调用外部javascript方法时,所使用的javascript代码,在IE8中断点调试,可以发现document.getElementById("report-charts")的结果为null,所以抛出了以上错误。
避过此问题的办法是在陊除已经载入的图表时,不调用jQuery.fn.empty()方法,而是直接使用jQuery.fn.html(''),将flash所在父元素的内容置空:

$('#report-charts').parent().html('');
// 如果使用$('#report-charts').parent().empty();在IE中则会报错
// ... 重新生成report-charts对象并载入新的flash图表
swfobject.embedSWF(ofc, "report-charts", "100%", "300", "9.0.0", "expressInstall.swf", {"get-data":"get_chart_0"});

Thursday, January 27, 2011

sqlite3 database disk image is malformed

sqlite3 报错提示: database disk image is malformed

看提示意思是指数据库的数据文件格式发生异常,所以数据查询和写入不正常,在网上google了一些文章,找到了一个解决方法。
一般来说,sqlite3的数据文件发生这个问题,想直接修复数据是行不通了,
在进入sqlite3后的命令行中,运行以下命令:
PRAGMA integrity_check
*** in database main ***
On tree page 120611 cell 0: 3 of 4 pages missing from overflow list starting at 120617
On tree page 120616 cell 0: 3 of 4 pages missing from overflow list starting at 120621
On tree page 3309 cell 0: 3 of 4 pages missing from over

假设原数据库名: abc.db

运行命令:
$> sqlite3 abc.db

.output "data.sql"
.dump
.quit

再建个新数据库 abcd.db
$> sqlite3 abcd.db

然后

.read "data.sql"
.quit

然后修复原来的数据库名和文件权限,应该就没事了。

References: sqlite3 database disk image malformed

Open Flash Chart IO ERROR Loading test data Error #2032

在IE6中使用open flash chart2加载图表的json数据时,第一次载入数据,图表渲染正常,第二次就会报一个错误,提示数据加载错误:


Open Flash Chart
IO ERROR
Loading test data
Error #2032

而在其他的浏览器,如IE8/firefox/chrome中都是正常的,在网上搜索了一些回答,其中有人提到说这是因为浏览器的缓存造成的问题,只要在用swfobject加载open-flash-chart.swf时,在url后面加上一个动态参数,让浏览器不要使用本地缓存:

swfobject.embedSWF("open-flash-chart.swf?t=" + (new Date()).getTime(), "charts-div-id", "100%", "300", "9.0.0", "expressInstall.swf", {"get-data":"get_chart_0"});


References: Open Flash Chart IO ERROR Loading test data Error #2032

Thursday, January 13, 2011

springmvc 中ajax提交发生乱码问题

这个问题目前只是在springmvc项目中碰到,在IE和Chrome中,当用jQuery.post()方法发起ajax请求时,Controller中收到的中文内容变成乱码了,而在firefox中用jQuery.post()进行ajax请求时是正常的。
在Controller中调用如下代码(项目为UTF-8编码):


// name 是post收到的字符串变量名
System.out.println(new String(name.getBytes(HTTP.ISO_8859_1), HTTP.UTF_8));

可以看到乱码恢复正常,说明IE和Chrome提交的ajax请求中的内容被编码成 ISO-8859-1 编码了。
而实际上,对于IE而已,所有的ajax请求都是以UTF-8方式发起的,通过以下方式设置ajax请求的编码为GBK实际是没有用的,服务器收到仍然是UTF-8编码的请求体:

xmlhttp.setRequestHeader( "Content-Type", "text/html;charset=GBK" );
// or
xmlhttp.setRequestHeader( "Content-Type", "application/x-www-form-urlencoded; charset=GBK");

因此可以肯定是springmvc在收到POST请求后,将请求体的数据用 ISO-8859-1 编码来处理了,最后传到Controller中时变成了乱码,但是为何firefox中提交的却仍然是正确的呢?
在firebug中观察firefox中的ajax请求头,可以看到firebug中的提示:

Content-Type application/x-www-form-urlencoded; charset=UTF-8

而在IE中用http analysis工具看到的却是:

Content-Type application/x-www-form-urlencoded

google Chrome中与IE一样,ajax请求头中没有指明编码,所以Chrome和IE一样将发生乱码了。
查看jquery-1.4.4.js源码可以看到,jQuery中原来的 contentType设置为"application/x-www-form-urlencoded",IE和Chrome中的请求头显示是正确的,没有问题,反而是firefox将contentType中设置了编码。
从这个请求头分析来看,应该是springmvc没有得到请求的编码,而将其内容设置为ISO-8859-1了,因此发生了乱码的情况。

解决方法还是参考firefox的请求头,在contentType中指定编码,明确告诉服务器端,当前请求体的编码方式为UTF-8。

xmlhttp.setRequestHeader( "Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");

如果使用jQuery发起ajax请求,javascript的代码改为如下方式发起ajax请求,而不是以$.post()和$.get()等快捷方法:

$.ajax({
url: url,
type: "POST",
dataType: "html",
contentType: "application/x-www-form-urlencoded; charset=UTF-8",
data: data,
complete:function(data) {
}
});