<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>ls /proc &#187; Program&amp;Database</title>
	<atom:link href="http://www.lsproc.com/blog/category/program/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.lsproc.com/blog</link>
	<description>lsproc.com</description>
	<lastBuildDate>Fri, 18 Nov 2011 09:22:52 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Nginx/PHP 文件类型错误解析漏洞：fix_pathinfo</title>
		<link>http://www.lsproc.com/blog/nginx_php_pathinfo_securit/</link>
		<comments>http://www.lsproc.com/blog/nginx_php_pathinfo_securit/#comments</comments>
		<pubDate>Fri, 21 May 2010 03:34:47 +0000</pubDate>
		<dc:creator>lostsnow</dc:creator>
				<category><![CDATA[Program&Database]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[pathinfo]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://www.lsproc.com/blog/?p=410</guid>
		<description><![CDATA[转载时请标明文章原始出处和作者信息, 作者: lostsnow.http://www.lsproc.com/blog/nginx_php_pathinfo_securit/ 漏洞介绍：nginx是一款高性能的web服务器，使用非常广泛，其不仅经常被用作反向代理，也可以非常好的支持PHP的运行。80sec发现其中存在一个较为严重的安全问题，默认情况下可能导致服务器错误的将任何类型的文件以PHP的方式进行解析，这将导致严重的安全问题，使得恶意的攻击者可能攻陷支持php的nginx服务器。 漏洞分析：nginx默认以cgi的方式支持php的运行，譬如在配置文件当中可以以 location ~ \.php$ { root html; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; include fastcgi_params; } 的方式支持对php的解析，location对请求进行选择的时候会使用URI环境变量进行选择，其中传递到后端Fastcgi的关键变量 SCRIPT_FILENAME由nginx生成的$fastcgi_script_name决定，而通过分析可以看到$fastcgi_script_name是直接由URI环境变量控制的，这里就是产生问题的点。而为了较好的支持PATH_INFO的提取，在PHP 的配置选项里存在cgi.fix_pathinfo选项，其目的是为了从SCRIPT_FILENAME里取出真正的脚本名。 那么假设存在一个http://www.lsproc.com/a.jpg，我们以如下的方式去访问 http://www.lsproc.com/a.jpg/xxx.php 将会得到一个URI /a.jpg/xxx.php 经过location指令，该请求将会交给后端的fastcgi处理，nginx为其设置环境变量SCRIPT_FILENAME，内容为 /scripts/a.jpg/xxx.php 而在其他的webserver如lighttpd当中，我们发现其中的SCRIPT_FILENAME被正确的设置为 /scripts/a.jpg 所以不存在此问题。 后端的fastcgi在接受到该选项时，会根据fix_pathinfo配置决定是否对SCRIPT_FILENAME进行额外的处理，一般情况下如果不对fix_pathinfo进行设置将影响使用PATH_INFO进行路由选择的应用，所以该选项一般配置开启。Php通过该选项之后将查找其中真正的脚本文件名字，查找的方式也是查看文件是否存在，这个时候将分离出SCRIPT_FILENAME和PATH_INFO分别为 /scripts/a.jpg和xxx.php 最后，以/scripts/a.jpg作为此次请求需要执行的脚本，攻击者就可以实现让nginx以php来解析任何类型的文件了。 PHP为什么会接受这样的参数, 并且把a.jpg解析呢? 这就要说到PHP的cgi SAPI中的参数, &#8230; <a href="http://www.lsproc.com/blog/nginx_php_pathinfo_securit/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>转载时请标明文章原始出处和作者信息, 作者: <a href="http://www.lsproc.com/blog/">lostsnow</a>.<br /><a href="http://www.lsproc.com/blog/nginx_php_pathinfo_securit/">http://www.lsproc.com/blog/nginx_php_pathinfo_securit/</a></p>
<p>漏洞介绍：nginx是一款高性能的web服务器，使用非常广泛，其不仅经常被用作反向代理，也可以非常好的支持PHP的运行。80sec发现其中存在一个较为严重的安全问题，默认情况下可能导致服务器错误的将任何类型的文件以PHP的方式进行解析，这将导致严重的安全问题，使得恶意的攻击者可能攻陷支持php的nginx服务器。</p>
<p>漏洞分析：nginx默认以cgi的方式支持php的运行，譬如在配置文件当中可以以</p>
<pre class="brush: text">
location ~ \.php$ {
    root html;
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
    include fastcgi_params;
}
</pre>
<p>的方式支持对php的解析，location对请求进行选择的时候会使用URI环境变量进行选择，其中传递到后端Fastcgi的关键变量 SCRIPT_FILENAME由nginx生成的$fastcgi_script_name决定，而通过分析可以看到$fastcgi_script_name是直接由URI环境变量控制的，这里就是产生问题的点。而为了较好的支持PATH_INFO的提取，在PHP 的配置选项里存在cgi.fix_pathinfo选项，其目的是为了从SCRIPT_FILENAME里取出真正的脚本名。<br />
那么假设存在一个http://www.lsproc.com/a.jpg，我们以如下的方式去访问</p>
<pre class="brush: text">

http://www.lsproc.com/a.jpg/xxx.php
</pre>
<p>将会得到一个URI</p>
<pre class="brush: text">
/a.jpg/xxx.php
</pre>
<p>经过location指令，该请求将会交给后端的fastcgi处理，nginx为其设置环境变量SCRIPT_FILENAME，内容为</p>
<pre class="brush: text">
/scripts/a.jpg/xxx.php
</pre>
<p>而在其他的webserver如lighttpd当中，我们发现其中的SCRIPT_FILENAME被正确的设置为</p>
<pre class="brush: text">
/scripts/a.jpg
</pre>
<p>所以不存在此问题。<br />
后端的fastcgi在接受到该选项时，会根据fix_pathinfo配置决定是否对SCRIPT_FILENAME进行额外的处理，一般情况下如果不对fix_pathinfo进行设置将影响使用PATH_INFO进行路由选择的应用，所以该选项一般配置开启。Php通过该选项之后将查找其中真正的脚本文件名字，查找的方式也是查看文件是否存在，这个时候将分离出SCRIPT_FILENAME和PATH_INFO分别为</p>
<pre class="brush: text">
/scripts/a.jpg和xxx.php
</pre>
<p>最后，以/scripts/a.jpg作为此次请求需要执行的脚本，攻击者就可以实现让nginx以php来解析任何类型的文件了。</p>
<p>PHP为什么会接受这样的参数, 并且把a.jpg解析呢?<br />
这就要说到PHP的cgi SAPI中的参数, fix_pathinfo了:</p>
<pre class="brush: text">
; cgi.fix_pathinfo provides *real* PATH_INFO/PATH_TRANSLATED support for CGI. PHP&#039;s
; previous behaviour was to set PATH_TRANSLATED to SCRIPT_FILENAME, and to not grok
; what PATH_INFO is. For more information on PATH_INFO, see the cgi specs. Setting
; this to 1 will cause PHP CGI to fix it&#039;s paths to conform to the spec. A setting
; of zero causes PHP to behave as before. Default is 1. You should fix your scripts
; to use SCRIPT_FILENAME rather than PATH_TRANSLATED.
cgi.fix_pathinfo=1
</pre>
<p>如果开启了这个选项, 那么就会触发在PHP中的如下逻辑:</p>
<pre class="brush: php">
/*
 * if the file doesn&#039;t exist, try to extract PATH_INFO out
 * of it by stat&#039;ing back through the &#039;/&#039;
 * this fixes url&#039;s like /info.php/test
 */
if (script_path_translated &amp;&amp;
     (script_path_translated_len = strlen(script_path_translated)) &gt; 0 &amp;&amp;
     (script_path_translated[script_path_translated_len-1] == &#039;/&#039; ||
//....以下省略.
</pre>
<p>到这里, PHP会认为SCRIPT_FILENAME是a.jpg, 而xxx.php是PATH_INFO, 然后PHP就把a.jpg当作一个PHP文件来解释执行… So…</p>
<p>POC： 访问一个nginx来支持php的站点，在一个任何资源的文件如robots.txt后面加上/xxx.php，这个时候你可以看到如下的区别：</p>
<p>访问http://www.lsproc.com/robots.txt</p>
<pre class="brush: text">
HTTP/1.1 200 OK
Server: nginx/0.6.32
Date: Thu, 20 May 2010 10:05:30 GMT
Content-Type: text/plain
Content-Length: 18
Last-Modified: Thu, 20 May 2010 06:26:34 GMT
Connection: keep-alive
Keep-Alive: timeout=20
Accept-Ranges: bytes
</pre>
<p>访问http://www.lsproc.com/robots.txt/xxx.php</p>
<pre class="brush: text">
HTTP/1.1 200 OK
Server: nginx/0.6.32
Date: Thu, 20 May 2010 10:06:49 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
Keep-Alive: timeout=20
X-Powered-By: PHP/5.2.6
</pre>
<p>其中的Content-Type的变化说明了后端负责解析的变化，该站点就可能存在漏洞。</p>
<p>漏洞厂商：http://www.nginx.org</p>
<p>解决方案：</p>
<p>1. 修改php.ini中的cgi.fix_pathinfo为0 (即使你在php.ini中没有找到，也要设置，默认为1)<br />
2. 把nginx的判断正则修改为去除/</p>
<pre class="brush: text">
if ( $fastcgi_script_name ~ \..*\/.*php ) {
    return 403;
}
</pre>
<p>3. 如果上传的文件类型为图片, 使用 gd/imagemagick 等进行处理后再保存, 原始文件务必删除<br />
4. 上传的文件放到一个静态文件server, 此 server 不允许php 文件执行</p>
<p>本文参考链接</p>
<ul>
<li><a href="http://www.80sec.com/nginx-securit.html">http://www.80sec.com/nginx-securit.html</a></li>
<li><a href="http://www.laruence.com/2010/05/20/1495.html">http://www.laruence.com/2010/05/20/1495.html</a></li>
<li><a href="http://www.54chen.com/php-tech/nginx-php-cgi-of-security-hole.html">http://www.54chen.com/php-tech/nginx-php-cgi-of-security-hole.html</a></li>
</ul>
<p>-- EOF --</p>
<h2  class="related_post_title">Related Posts</h2><ul class="related_post"><li>2010-04-12 -- <a href="http://www.lsproc.com/blog/nginx_userid_decode/" title="nginx userid 模块客户端 cookie 解码">nginx userid 模块客户端 cookie 解码</a> (0)</li><li>2010-03-08 -- <a href="http://www.lsproc.com/blog/use_ob_flush_on_nginx_fastcgi/" title="nginx+factcgi 下使用 ob_flush">nginx+factcgi 下使用 ob_flush</a> (0)</li><li>2009-03-29 -- <a href="http://www.lsproc.com/blog/nginx_ssl_config/" title="Nginx SSL 配置">Nginx SSL 配置</a> (23)</li><li>2008-10-23 -- <a href="http://www.lsproc.com/blog/nginx_rewrite_param/" title="nginx rewrite 的一些参数  ">nginx rewrite 的一些参数  </a> (1)</li><li>2008-06-15 -- <a href="http://www.lsproc.com/blog/lighttpd_phpfastcgi_config/" title="lighttpd + PHP(fastcgi) 配置">lighttpd + PHP(fastcgi) 配置</a> (0)</li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.lsproc.com/blog/nginx_php_pathinfo_securit/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>复制到剪切板 - 兼容 ie, firefox, chrome &amp; flash10</title>
		<link>http://www.lsproc.com/blog/copy_to_clipboard/</link>
		<comments>http://www.lsproc.com/blog/copy_to_clipboard/#comments</comments>
		<pubDate>Tue, 13 Apr 2010 06:48:44 +0000</pubDate>
		<dc:creator>lostsnow</dc:creator>
				<category><![CDATA[Program&Database]]></category>
		<category><![CDATA[clipboard]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[XHTML]]></category>

		<guid isPermaLink="false">http://www.lsproc.com/blog/?p=397</guid>
		<description><![CDATA[转载时请标明文章原始出处和作者信息, 作者: lostsnow.http://www.lsproc.com/blog/copy_to_clipboard/ 从 discuz! 里扒出来的(简易实现), 代码如下: var clipboardswfdata; var setcopy_gettext = function(){ clipboardswfdata = document.getElementById(&#039;data&#039;).value; window.document.clipboardswf.SetVariable(&#039;str&#039;, clipboardswfdata); } var floatwin = function(){ alert(&#039;copy success, &#039; + clipboardswfdata); } &#60;input type=&#34;text&#34; name=&#34;data&#34; value=&#34;xxxxx11111&#34; id =&#34;data&#34; /&#62; &#60;div id=&#34;clipboard_content&#34;&#62; &#60;span class=&#34;clipinner&#34; &#8230; <a href="http://www.lsproc.com/blog/copy_to_clipboard/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>转载时请标明文章原始出处和作者信息, 作者: <a href="http://www.lsproc.com/blog/">lostsnow</a>.<br /><a href="http://www.lsproc.com/blog/copy_to_clipboard/">http://www.lsproc.com/blog/copy_to_clipboard/</a></p>
<p>从 discuz! 里扒出来的(简易实现), 代码如下:</p>
<pre class="brush: javascript">
var clipboardswfdata;

var setcopy_gettext = function(){
    clipboardswfdata = document.getElementById(&#039;data&#039;).value;
    window.document.clipboardswf.SetVariable(&#039;str&#039;, clipboardswfdata);
}

var floatwin = function(){
    alert(&#039;copy success, &#039; + clipboardswfdata);
}
</pre>
<pre class="brush: xhtml">
&lt;input type=&quot;text&quot; name=&quot;data&quot; value=&quot;xxxxx11111&quot; id =&quot;data&quot; /&gt;
&lt;div id=&quot;clipboard_content&quot;&gt;
&lt;span class=&quot;clipinner&quot; id=&quot;clipinner&quot;&gt;点此复制到剪贴板
&lt;embed name=&quot;clipboardswf&quot; class=&quot;clipboardswf&quot; id=&quot;clipboardswf&quot; onmouseover=&quot;setcopy_gettext()&quot; devicefont=&quot;false&quot; src=&quot;./clipboard.swf&quot; menu=&quot;false&quot; allowscriptaccess=&quot;sameDomain&quot; swliveconnect=&quot;true&quot; wmode=&quot;transparent&quot; type=&quot;application/x-shockwave-flash&quot; height=&quot;20&quot; width=&quot;100&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
</pre>
<pre class="brush: css">
&lt;style type=&quot;text/css&quot;&gt;
body {font-size:12px;}
.clipinner {position:relative;}
.clipboardswf {position:absolute; left:0; top:0;}
&lt;/style&gt;
</pre>
<p>实现稍微有些恶心, 用 onmouseover 事件往 flash 中传递数据<br />
另: 没有对ie单独处理, ie中推荐使用 window.clipboardData</p>
<p>演示地址: <a href="http://www.lsproc.com/demo/clipboard/demo.html">http://www.lsproc.com/demo/cliboard/demo.html</a><br />
演示代码下载: http://www.lsproc.com/wiki/_media/snippets:clipboard.zip</p>
<p>另: google code 上有个 zeroclipboard 的项目, 如果想要方便的话, 也可以使用<br />
地址: <a href="http://code.google.com/p/zeroclipboard/">http://code.google.com/p/zeroclipboard/</a>
<p>-- EOF --</p>
<h2  class="related_post_title">Related Posts</h2><ul class="related_post"><li>2009-01-08 -- <a href="http://www.lsproc.com/blog/ajax_char_lose/" title="Ajax 提交数据加号与连接符丢失">Ajax 提交数据加号与连接符丢失</a> (0)</li><li>2008-01-23 -- <a href="http://www.lsproc.com/blog/limit_textarea_length_by_js/" title="Js控制输入字符数限制">Js控制输入字符数限制</a> (0)</li><li>2008-01-12 -- <a href="http://www.lsproc.com/blog/auto_resize_images/" title="自动等比例缩放网页中的图片">自动等比例缩放网页中的图片</a> (0)</li><li>2007-05-13 -- <a href="http://www.lsproc.com/blog/html_or_xhtml/" title="HTML or XHTML, 关于web标准">HTML or XHTML, 关于web标准</a> (0)</li><li>2006-03-01 -- <a href="http://www.lsproc.com/blog/div-and-table-tags/" title="使用DIV之后,什么时候使用TABLE?">使用DIV之后,什么时候使用TABLE?</a> (1)</li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.lsproc.com/blog/copy_to_clipboard/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>nginx userid 模块客户端 cookie 解码</title>
		<link>http://www.lsproc.com/blog/nginx_userid_decode/</link>
		<comments>http://www.lsproc.com/blog/nginx_userid_decode/#comments</comments>
		<pubDate>Mon, 12 Apr 2010 01:59:32 +0000</pubDate>
		<dc:creator>lostsnow</dc:creator>
				<category><![CDATA[Program&Database]]></category>
		<category><![CDATA[base64]]></category>
		<category><![CDATA[decode]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.lsproc.com/blog/?p=387</guid>
		<description><![CDATA[转载时请标明文章原始出处和作者信息, 作者: lostsnow.http://www.lsproc.com/blog/nginx_userid_decode/ 在网上看到用 ruby 解码的一段程序 http://forum.nginx.org/read.php?2,52592,52592 &#62; cookie_uid = &#34;0Cvz4ktwVPEdbRcMAwMFAg==&#34;; cc = cookie_uid.unpack(&#039;m*&#039;).first; rr = cc.split(&#34;&#34;).map{&#124;c&#124; c[0].to_i}.inject([]) {&#124;v,s&#124; v.push sprintf(&#34;%02X&#34;, s); v; }.values_at(3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12).join(&#34;&#34;) =&#62; &#8230; <a href="http://www.lsproc.com/blog/nginx_userid_decode/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>转载时请标明文章原始出处和作者信息, 作者: <a href="http://www.lsproc.com/blog/">lostsnow</a>.<br /><a href="http://www.lsproc.com/blog/nginx_userid_decode/">http://www.lsproc.com/blog/nginx_userid_decode/</a></p>
<p>在网上看到用 ruby 解码的一段程序<br />
<a href="http://forum.nginx.org/read.php?2,52592,52592">http://forum.nginx.org/read.php?2,52592,52592</a></p>
<pre class="brush: ruby">
&gt; cookie_uid = &quot;0Cvz4ktwVPEdbRcMAwMFAg==&quot;; cc = cookie_uid.unpack(&#039;m*&#039;).first; rr = cc.split(&quot;&quot;).map{|c| c[0].to_i}.inject([]) {|v,s| v.push sprintf(&quot;%02X&quot;, s); v; }.values_at(3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12).join(&quot;&quot;)
=&gt; &quot;E2F32BD0F154704B0C176D1D02050303&quot;
</pre>
<p>我用 PHP 写了一个</p>
<pre class="brush: php">
&lt;?php
function nginx_userid_decode($str)
{
    $str_unpacked =  unpack(&#039;h*&#039;, base64_decode(str_replace(&#039; &#039;, &#039;+&#039;, $str)));
    $str_split = str_split(current($str_unpacked), 8);
    $str_map = array_map(&#039;strrev&#039;, $str_split);
    $str_dedoded = strtoupper(implode(&#039;&#039;, $str_map));

    return $str_dedoded;
}

// uid=8380A8C09A7E8C4B0A112CC202030303
echo nginx_userid_decode(&#039;wKiAg0uMfprCLBEKAwMDAg==&#039;);
</pre>
<p>update:</p>
<blockquote><p>
<strong>如果 base64 后的编码中含有 '+' , 在 url 传递中或是 $_COOKIE 数组读取中会被转换为空格</strong>
</p></blockquote>
<p>-- EOF --</p>
<h2  class="related_post_title">Related Posts</h2><ul class="related_post"><li>2010-05-21 -- <a href="http://www.lsproc.com/blog/nginx_php_pathinfo_securit/" title="Nginx/PHP 文件类型错误解析漏洞：fix_pathinfo">Nginx/PHP 文件类型错误解析漏洞：fix_pathinfo</a> (2)</li><li>2010-03-08 -- <a href="http://www.lsproc.com/blog/use_ob_flush_on_nginx_fastcgi/" title="nginx+factcgi 下使用 ob_flush">nginx+factcgi 下使用 ob_flush</a> (0)</li><li>2009-03-29 -- <a href="http://www.lsproc.com/blog/nginx_ssl_config/" title="Nginx SSL 配置">Nginx SSL 配置</a> (23)</li><li>2008-10-23 -- <a href="http://www.lsproc.com/blog/nginx_rewrite_param/" title="nginx rewrite 的一些参数  ">nginx rewrite 的一些参数  </a> (1)</li><li>2008-06-15 -- <a href="http://www.lsproc.com/blog/lighttpd_phpfastcgi_config/" title="lighttpd + PHP(fastcgi) 配置">lighttpd + PHP(fastcgi) 配置</a> (0)</li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.lsproc.com/blog/nginx_userid_decode/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>python 抓取页面</title>
		<link>http://www.lsproc.com/blog/python_spider/</link>
		<comments>http://www.lsproc.com/blog/python_spider/#comments</comments>
		<pubDate>Mon, 01 Feb 2010 06:34:31 +0000</pubDate>
		<dc:creator>lostsnow</dc:creator>
				<category><![CDATA[Program&Database]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[spider]]></category>

		<guid isPermaLink="false">http://www.lsproc.com/blog/?p=363</guid>
		<description><![CDATA[转载时请标明文章原始出处和作者信息, 作者: lostsnow.http://www.lsproc.com/blog/python_spider/ #coding=utf-8 import sys import urllib2 import gzip import StringIO # 页面url url = &#34;http://china.toocle.com/company/show/pdetail--1000436--10532651.html&#34; # 页面编码 page_encode = &#34;gbk&#34; request = urllib2.Request(url) request.add_header(&#34;Accept-encoding&#34;, &#34;gzip&#34;) usock = urllib2.urlopen(request) page = usock.read() # 处理gzip过的页面 if usock.headers.get(&#039;content-encoding&#039;, None) == &#039;gzip&#039;: &#8230; <a href="http://www.lsproc.com/blog/python_spider/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>转载时请标明文章原始出处和作者信息, 作者: <a href="http://www.lsproc.com/blog/">lostsnow</a>.<br /><a href="http://www.lsproc.com/blog/python_spider/">http://www.lsproc.com/blog/python_spider/</a></p>
<pre class="brush: python">
#coding=utf-8

import sys
import urllib2
import gzip
import StringIO

# 页面url
url = &quot;http://china.toocle.com/company/show/pdetail--1000436--10532651.html&quot;
# 页面编码
page_encode = &quot;gbk&quot;

request = urllib2.Request(url)
request.add_header(&quot;Accept-encoding&quot;, &quot;gzip&quot;)
usock = urllib2.urlopen(request)
page = usock.read()
# 处理gzip过的页面
if usock.headers.get(&#039;content-encoding&#039;, None) == &#039;gzip&#039;:
    page = gzip.GzipFile(fileobj=StringIO.StringIO(page)).read()

# 转unicode(gbk/utf8)
if not isinstance(page, unicode):
    page = unicode(page, page_encode)

print(page)
</pre>
<p>-- EOF --</p>
<h2  class="related_post_title">Related Posts</h2><ul class="related_post"><li>2008-11-10 -- <a href="http://www.lsproc.com/blog/python_pil/" title="python图形处理库Python Imaging Library (PIL)">python图形处理库Python Imaging Library (PIL)</a> (0)</li><li>2008-11-05 -- <a href="http://www.lsproc.com/blog/configure_python_and_django_on_dreamhost/" title="Dreamhost 上编译python并安装django">Dreamhost 上编译python并安装django</a> (7)</li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.lsproc.com/blog/python_spider/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ajax 提交数据加号与连接符丢失</title>
		<link>http://www.lsproc.com/blog/ajax_char_lose/</link>
		<comments>http://www.lsproc.com/blog/ajax_char_lose/#comments</comments>
		<pubDate>Thu, 08 Jan 2009 03:09:48 +0000</pubDate>
		<dc:creator>lostsnow</dc:creator>
				<category><![CDATA[Program&Database]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jquery]]></category>

		<guid isPermaLink="false">http://www.lostk.com/blog/?p=195</guid>
		<description><![CDATA[转载时请标明文章原始出处和作者信息, 作者: lostsnow.http://www.lsproc.com/blog/ajax_char_lose/ 采用Ajax传递数据时，通常会将数据整理为data="var1=abc&#038;var2=def"。而当数据中存在加号(+)或是连接符(&#038;)时，服务器端接收数据时会有部分数据丢失现象。分析一下Ajax传递数据的格式与Javascript的语法不难发现： 1. "+"号：JavaScript解析为字符串连接符，所以服务器端接收数据时"+"会丢失。 2. "&#038;"：JavaScript解析为变量连接符，所以服务器端接收数据时&#038;符号以后的数据都会丢失。 解决办法也相当简单，只需要为+与&#038;符号编码即可： function vchar(str) { str = str.replace(/\+/g, &#34;%2B&#34;); str = str.replace(/\&#38;/g, &#34;%26&#34;); return str; } var1 = &#34;abc+kef&#34;; var2 = &#34;abc&#38;kef&#34;; var1 = vchar(var1); var2 = vchar(var2); alert(var1); alert(var2); 使用jquery的话可以使用如下方式提交 var params &#8230; <a href="http://www.lsproc.com/blog/ajax_char_lose/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>转载时请标明文章原始出处和作者信息, 作者: <a href="http://www.lsproc.com/blog/">lostsnow</a>.<br /><a href="http://www.lsproc.com/blog/ajax_char_lose/">http://www.lsproc.com/blog/ajax_char_lose/</a></p>
<p>采用Ajax传递数据时，通常会将数据整理为data="var1=abc&#038;var2=def"。而当数据中存在加号(+)或是连接符(&#038;)时，服务器端接收数据时会有部分数据丢失现象。分析一下Ajax传递数据的格式与Javascript的语法不难发现：</p>
<p>1. "+"号：JavaScript解析为字符串连接符，所以服务器端接收数据时"+"会丢失。</p>
<p>2. "&#038;"：JavaScript解析为变量连接符，所以服务器端接收数据时&#038;符号以后的数据都会丢失。</p>
<p>解决办法也相当简单，只需要为+与&#038;符号编码即可：</p>
<pre class="brush: javascript">
function vchar(str) {
    str = str.replace(/\+/g, &quot;%2B&quot;);
    str = str.replace(/\&amp;/g, &quot;%26&quot;);
    return str;
}
var1 = &quot;abc+kef&quot;;
var2 = &quot;abc&amp;kef&quot;;   

var1 = vchar(var1);
var2 = vchar(var2);   

alert(var1);
alert(var2);
</pre>
<p>使用jquery的话可以使用如下方式提交</p>
<pre class="brush: javascript">
var params = $(&#039;input, textarea&#039;).serialize();
$.ajax({
    type: &#039;post&#039;,
    url: &#039;xxxx.php&#039;,
    data: params,
    success: function(response){
        ......
    }
});
</pre>
<p>参考: http://www.phplamp.org/2008/11/javascript-ajax-char-lose/
<p>-- EOF --</p>
<h2  class="related_post_title">Related Posts</h2><ul class="related_post"><li>2010-04-13 -- <a href="http://www.lsproc.com/blog/copy_to_clipboard/" title="复制到剪切板 &#8211; 兼容 ie, firefox, chrome &#038; flash10">复制到剪切板 &#8211; 兼容 ie, firefox, chrome &#038; flash10</a> (5)</li><li>2008-01-23 -- <a href="http://www.lsproc.com/blog/limit_textarea_length_by_js/" title="Js控制输入字符数限制">Js控制输入字符数限制</a> (0)</li><li>2008-01-12 -- <a href="http://www.lsproc.com/blog/auto_resize_images/" title="自动等比例缩放网页中的图片">自动等比例缩放网页中的图片</a> (0)</li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.lsproc.com/blog/ajax_char_lose/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>python图形处理库Python Imaging Library (PIL)</title>
		<link>http://www.lsproc.com/blog/python_pil/</link>
		<comments>http://www.lsproc.com/blog/python_pil/#comments</comments>
		<pubDate>Mon, 10 Nov 2008 08:03:10 +0000</pubDate>
		<dc:creator>lostsnow</dc:creator>
				<category><![CDATA[Program&Database]]></category>
		<category><![CDATA[pil]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.lostk.com/blog/?p=170</guid>
		<description><![CDATA[转载时请标明文章原始出处和作者信息, 作者: lostsnow.http://www.lsproc.com/blog/python_pil/ pil站点: http://www.pythonware.com/products/pil/index.htm pil下载: http://effbot.org/downloads/Imaging-1.1.6.tar.gz pil文档: http://www.pythonware.com/library/pil/handbook/index.htm 　　 [安装] $ tar zxvf Imaging-1.1.6.tar.gz $ cd Imaging-1.1.6 $ python setup.py build_ext -i $ python selftest.py $ python setup.py install 安装完毕后,可在python安装目录下的site-packages找到PIL安装目录。 -- EOF -- Related Posts2010-02-01 -- python 抓取页面 (0)2008-11-05 &#8230; <a href="http://www.lsproc.com/blog/python_pil/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>转载时请标明文章原始出处和作者信息, 作者: <a href="http://www.lsproc.com/blog/">lostsnow</a>.<br /><a href="http://www.lsproc.com/blog/python_pil/">http://www.lsproc.com/blog/python_pil/</a></p>
<p>pil站点: http://www.pythonware.com/products/pil/index.htm<br />
pil下载: http://effbot.org/downloads/Imaging-1.1.6.tar.gz<br />
pil文档: http://www.pythonware.com/library/pil/handbook/index.htm<br />
　　<br />
[安装]</p>
<pre class="brush: bash">$ tar zxvf Imaging-1.1.6.tar.gz
$ cd Imaging-1.1.6
$ python setup.py build_ext -i
$ python selftest.py
$ python setup.py install</pre>
<p>安装完毕后,可在python安装目录下的site-packages找到PIL安装目录。
<p>-- EOF --</p>
<h2  class="related_post_title">Related Posts</h2><ul class="related_post"><li>2010-02-01 -- <a href="http://www.lsproc.com/blog/python_spider/" title="python 抓取页面">python 抓取页面</a> (0)</li><li>2008-11-05 -- <a href="http://www.lsproc.com/blog/configure_python_and_django_on_dreamhost/" title="Dreamhost 上编译python并安装django">Dreamhost 上编译python并安装django</a> (7)</li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.lsproc.com/blog/python_pil/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ZendFramework 使用数据表前缀</title>
		<link>http://www.lsproc.com/blog/use_dbprefix_in_zendframework/</link>
		<comments>http://www.lsproc.com/blog/use_dbprefix_in_zendframework/#comments</comments>
		<pubDate>Thu, 17 Jan 2008 15:07:15 +0000</pubDate>
		<dc:creator>lostsnow</dc:creator>
				<category><![CDATA[Program&Database]]></category>
		<category><![CDATA[dbprefix]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[zendframework]]></category>

		<guid isPermaLink="false">http://www.lostk.com/blog/use_dbprefix_in_zendframework/</guid>
		<description><![CDATA[转载时请标明文章原始出处和作者信息, 作者: lostsnow.http://www.lsproc.com/blog/use_dbprefix_in_zendframework/ 目录结构 在 config.ini 定义 prefix [general] adapter = PDO_MYSQL host = localhost username = root password = 123456 dbname = test charset = utf8 prefix = pf_ //表前缀 index.php 中将 prefix 注册 // 读取数据库配置 $dbconfig = new &#8230; <a href="http://www.lsproc.com/blog/use_dbprefix_in_zendframework/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>转载时请标明文章原始出处和作者信息, 作者: <a href="http://www.lsproc.com/blog/">lostsnow</a>.<br /><a href="http://www.lsproc.com/blog/use_dbprefix_in_zendframework/">http://www.lsproc.com/blog/use_dbprefix_in_zendframework/</a></p>
<p>目录结构<br />
<img src="http://www.lsproc.com/blog/wp-content/uploads/2008/01/zfstruc.png" width="166" height="360" alt="zend framework dirs" title="zend framework dirs" /></p>
<p>在 config.ini 定义 prefix</p>
<pre class="brush: php">[general]
adapter  = PDO_MYSQL
host     = localhost
username = root
password = 123456
dbname   = test
charset  = utf8
prefix   = pf_    //表前缀</pre>
<p>index.php 中将 prefix 注册</p>
<pre class="brush: php">// 读取数据库配置
$dbconfig = new Zend_Config_Ini(&#039;../config/config.ini&#039;, &#039;general&#039;);
// 配置数据库
$database = Zend_Db::factory($dbconfig-&gt;adapter,$dbconfig-&gt;toArray());
// 设置数据库编码
$database-&gt;query(&quot;set names {$dbconfig-&gt;charset};&quot;);
Zend_Db_Table::setDefaultAdapter($database);
Zend_Registry::set(&#039;database&#039;,$database);
// 数据表前缀
Zend_Registry::set(&#039;dbprefix&#039;,$dbconfig-&gt;prefix);</pre>
<p>在 library/Custom 目录下新建文件 Db.php 继承 Zend_Db_Table 类</p>
<pre class="brush: php">class Custom_Db extends Zend_Db_Table
{
    public function __construct()
    {
        $dbprefix = Zend_Registry::get(&#039;dbprefix&#039;);
        $this-&gt;_name = $dbprefix.$this-&gt;_name;
        parent::__construct();
    }
}</pre>
<p>最后在 model 中继承 Custom_Db 即可</p>
<pre class="brush: php">class User extends Custom_Db
{
    protected $_name = &#039;users&#039;;     //在Custom_Db中会自动加上表名的前缀
    protected $_primary = &#039;userid&#039;; //主键
}</pre>
<p>-- EOF --</p>
<h2  class="related_post_title">Related Posts</h2><ul class="related_post"><li>2010-05-21 -- <a href="http://www.lsproc.com/blog/nginx_php_pathinfo_securit/" title="Nginx/PHP 文件类型错误解析漏洞：fix_pathinfo">Nginx/PHP 文件类型错误解析漏洞：fix_pathinfo</a> (2)</li><li>2010-04-12 -- <a href="http://www.lsproc.com/blog/nginx_userid_decode/" title="nginx userid 模块客户端 cookie 解码">nginx userid 模块客户端 cookie 解码</a> (0)</li><li>2010-03-08 -- <a href="http://www.lsproc.com/blog/use_ob_flush_on_nginx_fastcgi/" title="nginx+factcgi 下使用 ob_flush">nginx+factcgi 下使用 ob_flush</a> (0)</li><li>2008-06-15 -- <a href="http://www.lsproc.com/blog/lighttpd_phpfastcgi_config/" title="lighttpd + PHP(fastcgi) 配置">lighttpd + PHP(fastcgi) 配置</a> (0)</li><li>2008-03-18 -- <a href="http://www.lsproc.com/blog/configure_lamp/" title="lamp 相关配置 [Debian]">lamp 相关配置 [Debian]</a> (2)</li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.lsproc.com/blog/use_dbprefix_in_zendframework/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>为wordpress添加coolcode插件的quicktag</title>
		<link>http://www.lsproc.com/blog/add_coolcode_quicktag_for_wordpress/</link>
		<comments>http://www.lsproc.com/blog/add_coolcode_quicktag_for_wordpress/#comments</comments>
		<pubDate>Sat, 12 Jan 2008 17:39:52 +0000</pubDate>
		<dc:creator>lostsnow</dc:creator>
				<category><![CDATA[Program&Database]]></category>
		<category><![CDATA[coolcode]]></category>
		<category><![CDATA[plugins]]></category>
		<category><![CDATA[quicktags]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://www.lostk.com/blog/add_coolcode_quicktag_for_wordpress/</guid>
		<description><![CDATA[转载时请标明文章原始出处和作者信息, 作者: lostsnow.http://www.lsproc.com/blog/add_coolcode_quicktag_for_wordpress/ 修改 wp-includes/js/quicktags.js 文件 1. 找到 edButtons[edButtons.length] = new edButton(&#039;ed_code&#039; ,&#039;code&#039; ,&#039;&#60;code&#62;&#039; ,&#039;&#60;/code&#62;&#039; ,&#039;c&#039; ); 在后面添加 edButtons[edButtons.length] = new edButton(&#039;ed_coolcode&#039; ,&#039;coolcode&#039; ,&#039;&#039; ,&#039;&#60;/coolcode&#62;&#039; ,&#039;x&#039; ); 2. 找到 else if (button.id == &#039;ed_link&#039;) { document.write(&#039;&#60;input type=&#34;button&#34; id=&#34;&#039; + button.id &#8230; <a href="http://www.lsproc.com/blog/add_coolcode_quicktag_for_wordpress/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>转载时请标明文章原始出处和作者信息, 作者: <a href="http://www.lsproc.com/blog/">lostsnow</a>.<br /><a href="http://www.lsproc.com/blog/add_coolcode_quicktag_for_wordpress/">http://www.lsproc.com/blog/add_coolcode_quicktag_for_wordpress/</a></p>
<p>修改 wp-includes/js/quicktags.js 文件</p>
<p>1. 找到</p>
<pre class="brush: javascript">
edButtons[edButtons.length] =
new edButton(&#039;ed_code&#039;
,&#039;code&#039;
,&#039;&lt;code&gt;&#039;
,&#039;&lt;/code&gt;&#039;
,&#039;c&#039;
);</pre>
<p>在后面添加</p>
<pre class="brush: javascript">
edButtons[edButtons.length] =
new edButton(&#039;ed_coolcode&#039;
,&#039;coolcode&#039;
,&#039;&#039;
,&#039;&lt;/coolcode&gt;&#039;
,&#039;x&#039;
);</pre>
<p>2. 找到</p>
<pre class="brush: javascript">
	else if (button.id == &#039;ed_link&#039;) {
		document.write(&#039;&lt;input type=&quot;button&quot; id=&quot;&#039; + button.id + &#039;&quot; accesskey=&quot;&#039; + button.access + &#039;&quot; class=&quot;ed_button&quot; onclick=&quot;edInsertLink(edCanvas, &#039; + i + &#039;);&quot; value=&quot;&#039; + button.display + &#039;&quot; /&gt;&#039;);
	}</pre>
<p>在后面添加</p>
<pre class="brush: javascript">
    else if (button.id == &#039;ed_coolcode&#039;) {
		document.write(&#039;&lt;input type=&quot;button&quot; id=&quot;&#039; + button.id + &#039;&quot; accesskey=&quot;&#039; + button.access + &#039;&quot; class=&quot;ed_button&quot; onclick=&quot;edInsertCoolcode(edCanvas, &#039; + i + &#039;);&quot; value=&quot;&#039; + button.display + &#039;&quot; /&gt;&#039;);
	}</pre>
<p>3. 在文件末尾添加</p>
<pre class="brush: javascript">
function edInsertCoolcode(myField, i, defaultLang, defaultLine) {
    if (!defaultLang) {
		defaultLang = &#039;php&#039;;
	}
    if (!defaultLine) {
		defaultLine = &#039;off&#039;;
	}
    if (!edCheckOpenTags(i)) {
        var codeLang = prompt(&#039;输入需要加亮的程序语言&#039;, defaultLang);
        var codeLine = prompt(&#039;是否显示行号(on, off)&#039;, defaultLine);
        edButtons[i].tagStart = &#039;&lt;&#039; + &#039;coolcode&#039;;
        if (codeLang) {
            edButtons[i].tagStart = edButtons[i].tagStart + &#039; lang=&quot;&#039;
                                    + codeLang + &#039;&quot;&#039;
        }
        if (codeLine) {
            edButtons[i].tagStart = edButtons[i].tagStart + &#039; linenum=&quot;&#039;
                                    + codeLine + &#039;&quot;&#039;;
        }
        edButtons[i].tagStart = edButtons[i].tagStart + &#039;&gt;&#039;;
        edInsertTag(myField, i);
    }
    else {
		edInsertTag(myField, i);
	}
}</pre>
<p>-- EOF --</p>
<h2  class="related_post_title">Related Posts</h2><ul class="related_post"><li>2007-04-05 -- <a href="http://www.lsproc.com/blog/top_30_wordpress_plugins_in_blogosphere/" title="博客世界最受欢迎的30个插件">博客世界最受欢迎的30个插件</a> (0)</li><li>2007-05-16 -- <a href="http://www.lsproc.com/blog/wordpress_22_final/" title="WordPress 2.2 final">WordPress 2.2 final</a> (0)</li><li>2007-03-18 -- <a href="http://www.lsproc.com/blog/wordpress_shortcut_key/" title="wordpress 快捷键">wordpress 快捷键</a> (2)</li><li>2006-12-27 -- <a href="http://www.lsproc.com/blog/mysql_encode_error_in_wordpress/" title="再谈Wordpress的MySQL乱码问题解决方法">再谈Wordpress的MySQL乱码问题解决方法</a> (3)</li><li>2006-07-03 -- <a href="http://www.lsproc.com/blog/mysql-encode-wordpress/" title="Mysql4.1编码详解及WordPress编码完善">Mysql4.1编码详解及WordPress编码完善</a> (1)</li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.lsproc.com/blog/add_coolcode_quicktag_for_wordpress/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cakephp 笔记</title>
		<link>http://www.lsproc.com/blog/cakephp_note/</link>
		<comments>http://www.lsproc.com/blog/cakephp_note/#comments</comments>
		<pubDate>Mon, 12 Nov 2007 17:31:06 +0000</pubDate>
		<dc:creator>lostsnow</dc:creator>
				<category><![CDATA[Program&Database]]></category>
		<category><![CDATA[cakephp]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[笔记]]></category>

		<guid isPermaLink="false">http://localhost/lost/blog/webdesign/cakephp_note/</guid>
		<description><![CDATA[转载时请标明文章原始出处和作者信息, 作者: lostsnow.http://www.lsproc.com/blog/cakephp_note/ 1. 自定义 layout 在 cakephp 中 layout 默认指向 /app/views/layouts/default.thtml 如果要自定义 layout，需要在 controller 中定义： var $layout = 'mydefault'; layout 则指向了 /app/views/layouts/mydefault.thtml 2. 创建不使用数据库表的 model 或者改变 model 对应的表名 我需要创建一个不使用任何表的model。例如，我想通过 $validate 数组方便底验证输入数据，保持model逻辑的正确性。但创建 model 时对应的表不存在，CakePHP 就会报错。通过在 model 中加入以下代码可以解决这个问题： var $useTable = &#8230; <a href="http://www.lsproc.com/blog/cakephp_note/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>转载时请标明文章原始出处和作者信息, 作者: <a href="http://www.lsproc.com/blog/">lostsnow</a>.<br /><a href="http://www.lsproc.com/blog/cakephp_note/">http://www.lsproc.com/blog/cakephp_note/</a></p>
<p>1. 自定义 layout</p>
<p>在 cakephp 中 layout 默认指向 /app/views/layouts/default.thtml<br />
如果要自定义 layout，需要在 controller 中定义：<br />
<code>var $layout = 'mydefault';</code><br />
layout 则指向了 /app/views/layouts/mydefault.thtml</p>
<p>2. 创建不使用数据库表的 model 或者改变 model 对应的表名</p>
<p>我需要创建一个不使用任何表的model。例如，我想通过 $validate 数组方便底验证输入数据，保持model逻辑的正确性。但创建 model 时对应的表不存在，CakePHP 就会报错。通过在 model 中加入以下代码可以解决这个问题：</p>
<p><code>var $useTable = false;</code></p>
<p>你也可以通过这种方法改变model对应的表名。</p>
<p>var $useTable = 'some_table';</p>
<p>3. 快速创建后台管理</p>
<p>如果你需要创建后台管理程序，并且希望所有管理action都位于某个特定文件夹下，那么打开 config/core.php 并将下面这一行的注释去掉：</p>
<p><code>define('CAKE_ADMIN', 'admin');</code></p>
<p>这样所有以"admin_"开头的action都可以通过 /admin/yourcontroller/youraction 来访问。例如，如果在 posts controller 中创建了名为 "admin_add" 的 action，那么可以通过 www.example.com/admin/posts/add 访问这个action。这样就可以方便地为 admin 目录设置密码以避免他人随意访问。</p>
<p>4. 自定义404页面</p>
<p>如果你需要自定义404页面，只需创建 /app/views/errors/error404.thtml。</p>
<p>5. 让controller使用其他model</p>
<p>如果你的controller需要调用来自不同model的数据，只要在controller开头使用如下代码：</p>
<p><code>class yourController extends AppController {<br />
var $uses = array('Post','User');<br />
}</code></p>
<p>这样controller就能访问Post和User model了。
<p>-- EOF --</p>
<h2  class="related_post_title">Related Posts</h2><ul class="related_post"><li>2007-11-13 -- <a href="http://www.lsproc.com/blog/cakephp_callback_function/" title="Cakephp 的回调函数">Cakephp 的回调函数</a> (0)</li><li>2007-11-09 -- <a href="http://www.lsproc.com/blog/zend_framework_summary/" title="Zend 框架摘要">Zend 框架摘要</a> (0)</li><li>2007-10-31 -- <a href="http://www.lsproc.com/blog/cakephp_conventions/" title="CakePHP 命名规则">CakePHP 命名规则</a> (1)</li><li>2007-09-07 -- <a href="http://www.lsproc.com/blog/php_mysql_study_4/" title="PHP 和 Mysql 学习笔记（四）">PHP 和 Mysql 学习笔记（四）</a> (0)</li><li>2007-06-22 -- <a href="http://www.lsproc.com/blog/php_mysql_study_2/" title="PHP 和 Mysql 学习笔记（二）">PHP 和 Mysql 学习笔记（二）</a> (0)</li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.lsproc.com/blog/cakephp_note/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cakephp 的回调函数</title>
		<link>http://www.lsproc.com/blog/cakephp_callback_function/</link>
		<comments>http://www.lsproc.com/blog/cakephp_callback_function/#comments</comments>
		<pubDate>Mon, 12 Nov 2007 17:20:05 +0000</pubDate>
		<dc:creator>lostsnow</dc:creator>
				<category><![CDATA[Program&Database]]></category>
		<category><![CDATA[cakephp]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://localhost/lost/blog/webdesign/cakephp_callback_function/</guid>
		<description><![CDATA[转载时请标明文章原始出处和作者信息, 作者: lostsnow.http://www.lsproc.com/blog/cakephp_callback_function/ Model的Callbacks 我们在model中增加了一些回调函数以帮助你在model操作前后能够织入一些业务逻辑（原文为sneak in，借用了AOP中的织入一词，因为从操作来看这些回调函数等同于AOP中的advice）。为了获得这样的能力，需要使用model中的一些参数并且在你的model中覆写这些方法。 beforeFind(string $conditions) beforeFind()回调函数是在model的find方法执行前的前置操作。你可以加入任何检索前的业务逻辑。你覆写该方法只要保证在前置操作成功后返回true来执行真正的find方法，返回false中断find方法就可以了。（译注：在一些复杂场景中，需多次持久化的情况下请慎用）。 afterFind(array $results) 使用afterFind回调函数能够更改find方法的返回结果集，或者在检索动作完成后加上一些业务逻辑。该函数的参数$results为经过回调函数处理以后的find检索结果集。 beforeValidate() beforeValidate回调函数能够在model校验数据之前更改model中的一些数据。同样也可以用来在model校验之前加入更为复杂的额外校验规则。和beforeFind一样，必须保证返回true来调用真正的操作，返回false来中断校验乃至save操作。 beforeSave() 和先前介绍的回调函数类似，在校验完成之后，保存动作之前加入额外的处理（如果校验失败是不会触发该回调函数的）。返回true或者false，不再赘述。 一个比较常见的beforeSave的应用场景就是在保存动作之前格式化日期属性以适应不同的数据库： // Date/time fields created by HTML Helper: // This code would be seen in a view $html-&#62;dayOptionTag(&#039;Event/start&#039;); $html-&#62;monthOptionTag(&#039;Event/start&#039;); $html-&#62;yearOptionTag(&#039;Event/start&#039;); $html-&#62;hourOptionTag(&#039;Event/start&#039;); $html-&#62;minuteOptionTag(&#039;Event/start&#039;); /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ // &#8230; <a href="http://www.lsproc.com/blog/cakephp_callback_function/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>转载时请标明文章原始出处和作者信息, 作者: <a href="http://www.lsproc.com/blog/">lostsnow</a>.<br /><a href="http://www.lsproc.com/blog/cakephp_callback_function/">http://www.lsproc.com/blog/cakephp_callback_function/</a></p>
<p><strong>Model的Callbacks</strong></p>
<p>我们在model中增加了一些回调函数以帮助你在model操作前后能够织入一些业务逻辑（原文为sneak in，借用了AOP中的织入一词，因为从操作来看这些回调函数等同于AOP中的advice）。为了获得这样的能力，需要使用model中的一些参数并且在你的model中覆写这些方法。</p>
<p>beforeFind(string $conditions)</p>
<p>beforeFind()回调函数是在model的find方法执行前的前置操作。你可以加入任何检索前的业务逻辑。你覆写该方法只要保证在前置操作成功后返回true来执行真正的find方法，返回false中断find方法就可以了。（译注：在一些复杂场景中，需多次持久化的情况下请慎用）。</p>
<p>afterFind(array $results)</p>
<p>使用afterFind回调函数能够更改find方法的返回结果集，或者在检索动作完成后加上一些业务逻辑。该函数的参数$results为经过回调函数处理以后的find检索结果集。</p>
<p>beforeValidate()<br />
beforeValidate回调函数能够在model校验数据之前更改model中的一些数据。同样也可以用来在model校验之前加入更为复杂的额外校验规则。和beforeFind一样，必须保证返回true来调用真正的操作，返回false来中断校验乃至save操作。</p>
<p>beforeSave()</p>
<p>和先前介绍的回调函数类似，在校验完成之后，保存动作之前加入额外的处理（如果校验失败是不会触发该回调函数的）。返回true或者false，不再赘述。<br />
一个比较常见的beforeSave的应用场景就是在保存动作之前格式化日期属性以适应不同的数据库：</p>
<pre class="brush: php">// Date/time fields created by HTML Helper:
// This code would be seen in a view 

$html-&gt;dayOptionTag(&#039;Event/start&#039;);
$html-&gt;monthOptionTag(&#039;Event/start&#039;);
$html-&gt;yearOptionTag(&#039;Event/start&#039;);
$html-&gt;hourOptionTag(&#039;Event/start&#039;);
$html-&gt;minuteOptionTag(&#039;Event/start&#039;); 

/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ 

// Model callback functions used to stitch date
// data together for storage
// This code would be seen in the Event model: 

function beforeSave()
{
    $this-&gt;data[&#039;Event&#039;][&#039;start&#039;] = $this-&gt;_getDate(&#039;Event&#039;, &#039;start&#039;); 

    return true;
} 

function _getDate($model, $field)
{
    return date(&#039;Y-m-d H:i:s&#039;, mktime(
        intval($this-&gt;data[$model][$field . &#039;_hour&#039;]),
        intval($this-&gt;data[$model][$field . &#039;_min&#039;]),
        null,
        intval($this-&gt;data[$model][$field . &#039;_month&#039;]),
        intval($this-&gt;data[$model][$field . &#039;_day&#039;]),
        intval($this-&gt;data[$model][$field . &#039;_year&#039;])));
}
</pre>
<p>afterSave()</p>
<p>放置任何你想要在保存后执行的代码在这个回调函数中。[ToDo 如果保存出错是否会触发？]</p>
<p>beforeDelete()</p>
<p>放置删除前的逻辑代码。想要删除操作执行则返回true，否则返回false。</p>
<p>afterDelete()</p>
<p>放置任何你想要在删除后执行的代码在这个回调函数中。</p>
<p><strong>controller中的回调函数</strong></p>
<p>Cake的controller特别提供了许多回调方法，你可以用它们在一些重要的controller方法之前或者之后插入一些逻辑。如果要利用这些功能，请在你的controller中用这里描述的参数和返回值定义这些方法。</p>
<p>beforeFilter</p>
<p>在每个controller action调用前执行。它是一个检查当前sessoin状态和检查用户角色的好地方。</p>
<p>afterFilter</p>
<p>在每个controller action调用后执行。</p>
<p>beforeRender</p>
<p>在controller逻辑之后，并且在输出视图之前被调用。
<p>-- EOF --</p>
<h2  class="related_post_title">Related Posts</h2><ul class="related_post"><li>2007-11-13 -- <a href="http://www.lsproc.com/blog/cakephp_note/" title="Cakephp 笔记">Cakephp 笔记</a> (0)</li><li>2007-10-31 -- <a href="http://www.lsproc.com/blog/cakephp_conventions/" title="CakePHP 命名规则">CakePHP 命名规则</a> (1)</li><li>2010-05-21 -- <a href="http://www.lsproc.com/blog/nginx_php_pathinfo_securit/" title="Nginx/PHP 文件类型错误解析漏洞：fix_pathinfo">Nginx/PHP 文件类型错误解析漏洞：fix_pathinfo</a> (2)</li><li>2010-04-12 -- <a href="http://www.lsproc.com/blog/nginx_userid_decode/" title="nginx userid 模块客户端 cookie 解码">nginx userid 模块客户端 cookie 解码</a> (0)</li><li>2010-03-08 -- <a href="http://www.lsproc.com/blog/use_ob_flush_on_nginx_fastcgi/" title="nginx+factcgi 下使用 ob_flush">nginx+factcgi 下使用 ob_flush</a> (0)</li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.lsproc.com/blog/cakephp_callback_function/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

