<?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>某人的栖息地 &#187; Volcano</title>
	<atom:link href="http://www.ooso.net/archives/author/volcano/feed" rel="self" type="application/rss+xml" />
	<link>http://www.ooso.net</link>
	<description>Linux + Apache + Mysql + Php + Flash</description>
	<lastBuildDate>Thu, 19 Jan 2012 01:21:44 +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>干掉xcode 4.2里的performselector警告</title>
		<link>http://www.ooso.net/archives/620</link>
		<comments>http://www.ooso.net/archives/620#comments</comments>
		<pubDate>Thu, 19 Jan 2012 01:21:44 +0000</pubDate>
		<dc:creator>Volcano</dc:creator>
				<category><![CDATA[objective-c]]></category>
		<category><![CDATA[xcode]]></category>

		<guid isPermaLink="false">http://www.ooso.net/?p=620</guid>
		<description><![CDATA[xcode 4.2非常可恶，原来的代码里有调用performselector:withObject:的地方无一例外获得一个警告：

Semantic Issue
  PerformSelector may cause a leak because its selector is unknown

				<span class="readmore"><a href="http://www.ooso.net/archives/620" title="干掉xcode 4.2里的performselector警告">阅读全文（347字）</a></span>]]></description>
			<content:encoded><![CDATA[<p>xcode 4.2非常可恶，原来的代码里有调用<strong>performselector:withObject:</strong>的地方无一例外获得一个警告：</p>
<blockquote>
<p>Semantic Issue<br />
  PerformSelector may cause a leak because its selector is unknown</p>
</blockquote>
<p>warning倒是不影响程序运行，但是这人要是有点代码小洁癖的话，那日子就没法过了，这warning怎么看都碍眼。所以必须得想办法把它弄没了：</p>
<pre><code>#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
    [self performSelector:nextView];
#pragma clang diagnostic pop</code></pre>
<h2>世界清静啦</h2>
]]></content:encoded>
			<wfw:commentRss>http://www.ooso.net/archives/620/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>iOS 5的文件存储策略应对</title>
		<link>http://www.ooso.net/archives/617</link>
		<comments>http://www.ooso.net/archives/617#comments</comments>
		<pubDate>Mon, 09 Jan 2012 01:24:32 +0000</pubDate>
		<dc:creator>Volcano</dc:creator>
				<category><![CDATA[objective-c]]></category>
		<category><![CDATA[icloud]]></category>
		<category><![CDATA[ios]]></category>

		<guid isPermaLink="false">http://www.ooso.net/?p=617</guid>
		<description><![CDATA[苹果在iOS 5系统时，对app的文件存储提出了新的要求。从它的guildline来看，是推荐开发者尽量把app生成的文件放在Caches目录下的。原文如下:

  Only user-generated data or that cannot otherwise be recreated by your application, should be stored in the /Documents directory and rest should be stored to /Library/Caches directory。

				<span class="readmore"><a href="http://www.ooso.net/archives/617" title="iOS 5的文件存储策略应对">阅读全文（1442字）</a></span>]]></description>
			<content:encoded><![CDATA[<p>苹果在iOS 5系统时，对app的文件存储提出了新的要求。从<a href="https://developer.apple.com/icloud/documentation/data-storage/">它的guildline</a>来看，是推荐开发者尽量把app生成的文件放在Caches目录下的。原文如下:</p>
<blockquote><p>
  Only user-generated data or that cannot otherwise be recreated by your application, should be stored in the /Documents directory and rest should be stored to /Library/Caches directory。
</p></blockquote>
<h2>照做会怎么样？</h2>
<p>如果这么做的话，会出现两种情况</p>
<ol>
<li>如果对此置之不理，继续把应用生成的文件放在Documents目录下，那么这些文件会被备份到iTunes或者iCloud。如果这些文件很大，那么用户可能需要为了同步消耗不少流量，然后苹果可能会因此拒绝你的应用上架，这是一个悲剧。</li>
<li>如果开发者照Apple说的干，把应用生成的文件放在Caches目录下，那么苹果不会拒绝你的应用，很happy。但是iOS 5会在磁盘空间紧张的时候删除Caches目录下的文件，这对用户来说可能是一个更大的悲剧。</li>
</ol>
<h2>如何应对新的文件存储策略?</h2>
<p>开发者在这时陷入了两难的境地，但是到了iOS 5.0.1的时候，开发者多了第三种选择:</p>
<ul>
<li>继续把文件存储在Documents目录下，但是标记这些文件为不需要备份。详情请参考 technote (<a href="http://developer.apple.com/library/ios/#qa/qa1719/_index.html#//apple_ref/doc/uid/DTS40011342">QA1719</a>)</li>
</ul>
<p>原文如下:</p>
<blockquote><p>
  Q:  My app has a number of files that need to be stored on the device permanently for my app to function properly offline. However, those files do not contain user data and don&#8217;t need to be backed up. How should I store those files in iOS 5?</p>
<p>  A: Starting in iOS 5.0.1 a new &#8220;do not back up&#8221; file attribute has been introduced allowing developers to clearly specify which files should be backed up, which files are local caches only and subject to purge, and which files should not be backed up but should also not be purged. In addition, setting this attribute on a folder will prevent the folder and all of its contents from being backed up.
</p></blockquote>
<h2>代码示例</h2>
<p>给文件加上&#8221;do not back up&#8221;属性的代码如下，需要注意这个是iOS 5.0.1才有效，低于这个版本就别费劲了。</p>
<pre><code>#include &lt;sys/xattr.h&gt;
- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL
{
    const char* filePath = [[URL path] fileSystemRepresentation];

    const char* attrName = "com.apple.MobileBackup";
    u_int8_t attrValue = 1;

    int result = setxattr(filePath, attrName, &#038;attrValue, sizeof(attrValue), 0, 0);
    return result == 0;
}</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.ooso.net/archives/617/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>使用markdown格式写Todo list</title>
		<link>http://www.ooso.net/archives/615</link>
		<comments>http://www.ooso.net/archives/615#comments</comments>
		<pubDate>Mon, 26 Dec 2011 03:10:42 +0000</pubDate>
		<dc:creator>Volcano</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[chrome]]></category>
		<category><![CDATA[markdown]]></category>
		<category><![CDATA[vim]]></category>

		<guid isPermaLink="false">http://www.ooso.net/?p=615</guid>
		<description><![CDATA[上周我完成了chrome的markdown-preview扩展的修改，使它支持markdown文件的实时预览功能。现在可以考虑用这个功能来做一些更酷的事情，比如说，写Todo list?
开始干

首先我找到了一个叫topmarks的markdown样式文件，这个样式文件能给出一个漂亮的Todo list样式，我把它合并到了 修改后的markdown preview插件

				<span class="readmore"><a href="http://www.ooso.net/archives/615" title="使用markdown格式写Todo list">阅读全文（436字）</a></span>]]></description>
			<content:encoded><![CDATA[<p>上周我完成了<a href="http://www.ooso.net/archives/611">chrome的markdown-preview扩展的修改</a>，使它支持markdown文件的实时预览功能。现在可以考虑用这个功能来做一些更酷的事情，比如说，写Todo list?</p>
<h3>开始干</h3>
<ul>
<li>首先我找到了一个叫<a href="https://github.com/stuart36deg/TopMarks">topmarks的markdown样式文件</a>，这个样式文件能给出一个漂亮的Todo list样式，我把它合并到了 <a href="https://github.com/volca/markdown-preview">修改后的markdown preview插件</a></li>
<li>关注了一下markdown-preview原作者的github，他有计划增加一项功能，让用户可以自定义css文件，但是近期完成无望，所以我新增了一个topmarks的分支，采用新的样式</li>
<li>在chrome的扩展中重新加载插件</li>
</ul>
<h3>效果图</h3>
<p>如图，我采用vim编辑文件，右边摆上chrome浏览器预览，文件采用dropbox同步，保证我随时能更新这个文件。</p>
<p><img src="http://ww1.sinaimg.cn/large/72f2af1bgw1dofto6t2hfj.jpg" alt="效果图" /></p>
<h3>关于topmarks的补充说明</h3>
<p>topmarks样式采用了这些自定义标签</p>
<ul>
<li>&lt;t&gt; 新任务</li>
<li>&lt;d&gt; 已完成的任务</li>
<li>&lt;c&gt; 已取消的任务</li>
<li>http, ical, mailto, file链接有不同的图标</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.ooso.net/archives/615/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>markdown文件的编辑以及实时预览</title>
		<link>http://www.ooso.net/archives/611</link>
		<comments>http://www.ooso.net/archives/611#comments</comments>
		<pubDate>Thu, 22 Dec 2011 08:54:20 +0000</pubDate>
		<dc:creator>Volcano</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[wordpress]]></category>
		<category><![CDATA[chrome]]></category>
		<category><![CDATA[markdown]]></category>
		<category><![CDATA[vim]]></category>

		<guid isPermaLink="false">http://www.ooso.net/?p=611</guid>
		<description><![CDATA[之前看到有一款叫Mou的软件可以编辑markdown格式的文本内容并且实时预览，可是我比较喜欢用vim编辑器，所以就想着能不能用别的软件配合着来实现实时预览。
今天看到一个chrome的扩展叫markdown preview，它可以自动把md或markdown后缀的文本转换为html格式在chrome中查看，只是还欠缺一个自动刷新的功能。然后我看到它的源码已经放在github上，于是抓回来做了一些修改，加上了自动刷新的功能。
演示
尝试了一下在vim中编辑文件，然后在chrome中浏览，效果还不错，见下图：

				<span class="readmore"><a href="http://www.ooso.net/archives/611" title="markdown文件的编辑以及实时预览">阅读全文（645字）</a></span>]]></description>
			<content:encoded><![CDATA[<p>之前看到有一款叫Mou的软件可以编辑markdown格式的文本内容并且实时预览，可是我比较喜欢用vim编辑器，所以就想着能不能用别的软件配合着来实现实时预览。</p>
<p>今天看到一个chrome的扩展叫<a href="https://chrome.google.com/webstore/detail/jmchmkecamhbiokiopfpnfgbidieafmd">markdown preview</a>，它可以自动把md或markdown后缀的文本转换为html格式在chrome中查看，只是还欠缺一个自动刷新的功能。然后我看到它的源码已经放在github上，于是抓回来做了一些修改，加上了自动刷新的功能。</p>
<h2>演示</h2>
<p>尝试了一下在vim中编辑文件，然后在chrome中浏览，效果还不错，见下图：</p>
<p><img src="http://ww1.sinaimg.cn/large/72f2af1bgw1dobg6hnkn0j.jpg" alt="效果图" /></p>
<h2>更改后的扩展</h2>
<p>我把修改后的markdown preview插件放在<a href="https://github.com/volca/markdown-preview">github上</a> ， 已经尝试向原作者发起pull requests，要试用的话需要按下面几步操作:</p>
<ol>
<li>把插件的代码clone回来 <code>git clone git://github.com/volca/markdown-preview.git</code></li>
<li>开启chrome扩展的开发者模式，具体位置在<strong>窗口 -> 扩展程序</strong>里</li>
<li>载入正在开发的扩展程序</li>
<li>将<strong>允许访问文件网址</strong>勾选上</li>
</ol>
<p>然后你就可以尝试用chrome浏览器打开markdown文件预览html，采用趁手的编辑器去修改它。</p>
<h2>BTW</h2>
<ul>
<li>chrome下的插件写起来比想像的要简单，写javascript就是了</li>
<li>现在这篇blog即是我用markdown格式写成的，用到了wordpress的<strong>markdown on save</strong>扩展。</li>
</ul>
<h2>Update</h2>
<ul>
<li>测试把文件放在dropbox的Public下，修改之后的效果能够立刻在共享链接里看到效果，很完美</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.ooso.net/archives/611/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>php的异步http请求类</title>
		<link>http://www.ooso.net/archives/597</link>
		<comments>http://www.ooso.net/archives/597#comments</comments>
		<pubDate>Thu, 10 Nov 2011 08:24:07 +0000</pubDate>
		<dc:creator>Volcano</dc:creator>
				<category><![CDATA[php]]></category>
		<category><![CDATA[libevent]]></category>
		<category><![CDATA[zend framework]]></category>

		<guid isPermaLink="false">http://www.ooso.net/?p=597</guid>
		<description><![CDATA[基于上次写的关于php的libevent扩展的应用，我实现了一个异步的http请求类。
代码在github上：https://github.com/volca/AsyncHttpClient
使用示例
如下，在request的时候能够定义请求完成之后的callback函数。

				<span class="readmore"><a href="http://www.ooso.net/archives/597" title="php的异步http请求类">阅读全文（134字）</a></span>]]></description>
			<content:encoded><![CDATA[<p>基于上次写的<a href="http://www.ooso.net/archives/607" title="关于php的libevent扩展的应用">关于php的libevent扩展的应用</a>，我实现了一个异步的http请求类。</p>
<p>代码在github上：<a href="https://github.com/volca/AsyncHttpClient">https://github.com/volca/AsyncHttpClient</a></p>
<h2>使用示例</h2>
<p>如下，在request的时候能够定义请求完成之后的callback函数。</p>
<pre><code>&lt;?php
$base = event_base_new();

$uri = "http://www.baidu.com/";
$config = array(
    'eventbase' =&gt; $base
);

for($i = 0; $i &lt; 10; $i++) {
    $client = new AsyncHttpClient($uri, $config);
    $client-&gt;request(function($result) {
        echo "Result len:";
        echo strlen($result['response']);
        // parse response with Zend_Http_Response
        $response = Zend_Http_Response::fromString($result['response']);
        echo $response-&gt;getBody();
        echo "\n";
    });
}

event_base_loop($base);
echo "done\n";</code></pre>
<p>目前的实现比较初级，只做了get方法的封装，如果需要http上传或者post，还需要另外实现。另外这个类也需要<a href="http://pecl.php.net/libevent">php的libevent扩展</a>。</p>
<h2>Update 2011.11.17</h2>
<p>将这个类修改为继承自Zend_Http_Client，这样我可以少写一些代码，顺带也实现了文件http上传以及post（未经测试）,代码中的使用示例也已经更新。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ooso.net/archives/597/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>关于php的libevent扩展的应用</title>
		<link>http://www.ooso.net/archives/607</link>
		<comments>http://www.ooso.net/archives/607#comments</comments>
		<pubDate>Tue, 25 Oct 2011 14:58:04 +0000</pubDate>
		<dc:creator>Volcano</dc:creator>
				<category><![CDATA[php]]></category>
		<category><![CDATA[libevent]]></category>

		<guid isPermaLink="false">http://www.ooso.net/?p=607</guid>
		<description><![CDATA[php有个libevent扩展，在一年前我曾经拿它实现了一个thrift socket server，虽然我没有把它放在正式的场合来使用，但是我觉得这个扩展应该可以有更广泛的用途，比如：

phpDaemon — 一个异步的服务器端开发框架.
tail &#8211; 用php实现类似unix下的tail命令行

				<span class="readmore"><a href="http://www.ooso.net/archives/607" title="关于php的libevent扩展的应用">阅读全文（1038字）</a></span>]]></description>
			<content:encoded><![CDATA[<p>php有个libevent扩展，在一年前我曾经拿它<a href="http://www.ooso.net/archives/537">实现了一个thrift socket server</a>，虽然我没有把它放在正式的场合来使用，但是我觉得这个扩展应该可以有更广泛的用途，比如：</p>
<ul>
<li><a href="http://phpdaemon.net/">phpDaemon</a> — 一个异步的服务器端开发框架.</li>
<li><a href="http://abhinavsingh.com/blog/2009/11/writing-a-custom-unix-style-tail-in-php-using-libevent-api-on-mac-os-x-10-5-x-and-other-platforms">tail</a> &#8211; 用php实现类似unix下的tail命令行</li>
<li><a href="http://toys.lerdorf.com/archives/57-ZeroMQ-+-libevent-in-PHP.html">ZeroMQ + libevent in PHP</a> &#8211; 用php和ZeroMQ实现的一个事件驱动服务器端</li>
</ul>
<p>我所想到的一个比较实用的使用场景是，在页面中利用libevent请求多个http接口来获得数据。若是在从前，一个可行的办法是利用curl_multi_exec来同时请求好几个接口，但是这个办法需要用一个do &#8230; while循环来完成请求，很是坑爹。那么看看采用libevent的例子:</p>
<h2>代码实例 http.php</h2>
<pre><code>&lt;?php
$base_fd = event_base_new();
$times = 0;
$limit = 10;
$index = array();

function httpGet($host, $base_fd) {
    global $index;

    $fd = stream_socket_client("$host:80", $errno, $errstr, 3, STREAM_CLIENT_ASYNC_CONNECT | STREAM_CLIENT_CONNECT);
    $index[$fd] = 0;
    $event_fd = event_new();
    event_set($event_fd, $fd, EV_WRITE | EV_PERSIST, function($fd, $events, $arg) use($host) {
        global $times, $limit, $index;

        if(!$index[$fd]) {
            $index[$fd] = 1;
            $out = "GET / HTTP/1.1\r\n";
            $out .= "Host: $host\r\n";
            $out .= "Connection: Close\r\n\r\n";
            fwrite($fd, $out);
        } else {
            echo fread($fd, 4096);
            if(feof($fd)) {
                fclose($fd);
                $times++;
                echo "done\n";

                if($times == $limit - 1) {
                    event_base_loopexit($arg[1]);
                }
            }
        }
    }, array($event_fd, $base_fd));

    event_base_set($event_fd, $base_fd);
    event_add($event_fd);
}

for($i = 0; $i &lt; $limit; $i++) {
    echo "$i\n";
    httpGet($argv[1], $base_fd);
        //echo file_get_contents("http://$argv[1]");
}

event_base_loop($base_fd);
?&gt;</code></pre>
<p>为了省事，这个php脚本仅仅是重复抓取一个网页5次，并且回调的逻辑我没怎么做处理，仅仅是echo出来而已，可以通过下面命令行来运行这个例子:</p>
<pre><code>php http.php "www.baidu.com"</code></pre>
<p>代码中的http_get($argv[1])这行虽然是靠一个命令行顺序执行，但是不会阻塞后面的代码，直接就进行下一次请求了。而且我们看看回调方法部分是不是很像用javascript调用ajax写的回调方法？这都是php 5.3中闭包的功劳。</p>
<pre><code>event_set($event_fd, $fd, EV_WRITE | EV_PERSIST, function($fd, $events, $arg) {
    //回调方法，后续处理随意
    echo fread($fd, 4096);
    if(feof($fd)) {
        fclose($fd);
	event_base_loopexit($arg[1]);
	echo "done";
    }
}, array($event_fd, $base_fd));</code></pre>
<h2>想到更多</h2>
<p>在mysqlnd，memcached&#8230;这些php扩展中，都已经有delay回调的实现，如果能好好利用，对性能提升岂不是有莫大的帮助？或者在libevent扩展的基础上，实现一个事件驱动的开发框架，也是可行的。</p>
<h2>Update 2011.11.10</h2>
<p>在这个代码的基础上实现了一个<a href="http://www.ooso.net/archives/597" title="php的异步http请求类">异步http请求的客户端</a></p>
<h2>Update 2011.10.28</h2>
<p>event_base_loop是会阻塞后续代码执行的，所以我调整了示例代码，使用同一个event_base，并且用stream_socket_client来进行异步连接，另外在/etc/hosts指定域名的ip会对执行速度有帮助。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ooso.net/archives/607/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>实战three20的TTTableViewController自定义单元格</title>
		<link>http://www.ooso.net/archives/605</link>
		<comments>http://www.ooso.net/archives/605#comments</comments>
		<pubDate>Sun, 03 Jul 2011 03:13:09 +0000</pubDate>
		<dc:creator>Volcano</dc:creator>
				<category><![CDATA[objective-c]]></category>
		<category><![CDATA[three20]]></category>

		<guid isPermaLink="false">http://www.ooso.net/?p=605</guid>
		<description><![CDATA[three20中的TTTableCaptionItem实际使用效果是，左侧是较小字体的标题，右侧是大号字体的文本，如下图所示

但是在实际使用中，我希望左侧的字体能变大，右侧字体变小，所以我参照wiki的介绍 在TTTableViewController定制单元格 来进行调整，按文中介绍，我需要实现：


				<span class="readmore"><a href="http://www.ooso.net/archives/605" title="实战three20的TTTableViewController自定义单元格">阅读全文（2668字）</a></span>]]></description>
			<content:encoded><![CDATA[<p>three20中的TTTableCaptionItem实际使用效果是，左侧是较小字体的标题，右侧是大号字体的文本，如下图所示</p>
<p><a href="http://www.ooso.net/wp-content/uploads/2011/07/IMG_0255.PNG-2.jpg"><img src="http://www.ooso.net/wp-content/uploads/2011/07/IMG_0255.PNG-2.jpg" alt="" title="TTTableCaptionItem" width="320" height="54" class="aligncenter size-full wp-image-606" /></a></p>
<p>但是在实际使用中，我希望左侧的字体能变大，右侧字体变小，所以我参照wiki的介绍 <a href="http://three20.viewc.com/wiki/Custom-cells-in-tttableviewcontroller">在TTTableViewController定制单元格</a> 来进行调整，按文中介绍，我需要实现：</p>
<ol>
<li>自定义的tableItem</li>
<li>自定义的tableItemCell</li>
<li>自定义的datasource，以便支持新增的tableItem</li>
</ol>
<p>但是考虑到three20的代码库中已经有个半成品的TTTableRightCaptionItem，所以我只需要在这个基础上加工一下。</p>
<h2>实现TTTableTextCaptionItem</h2>
<p>我将这个自定义的类命名为TTTableTextCaptionItem以示区别</p>
<h3>TTTableTextCaptionItem</h3>
<p>TTTableTextCaptionItem.h</p>
<pre><code>#import &lt;Three20/Three20.h&gt;

@interface TTTableTextCaptionItem : TTTableRightCaptionItem {
}

@end</code></pre>
<p>TTTableTextCaptionItem.m</p>
<pre><code>#import "TTTableTextCaptionItem.h"

@implementation TTTableTextCaptionItem
@end</code></pre>
<h3>TTTableTextCaptionItemCell</h3>
<p>TTTableTextCaptionItemCell.h</p>
<pre><code>#import &lt;Three20/Three20.h&gt;

@interface TTTableTextCaptionItemCell : TTTableRightCaptionItemCell {
}
@end</code></pre>
<p>TTTableTextCaptionItemCell.m</p>
<pre><code>#import "TTTableTextCaptionItem.h"
#import "TTTableTextCaptionItemCell.h"

static const CGFloat kKeySpacing = 12;
static const CGFloat kKeyWidth = 75;

@implementation TTTableTextCaptionItemCell

///////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark -
#pragma mark UIView

///////////////////////////////////////////////////////////////////////////////////////////////////
- (void)layoutSubviews {
    [super layoutSubviews];

    self.detailTextLabel.frame = CGRectMake(kTableCellHPadding, kTableCellVPadding,
                                      kKeyWidth, self.textLabel.font.ttLineHeight);

    CGFloat valueWidth = self.contentView.width - (kTableCellHPadding*2 + kKeyWidth + kKeySpacing);
    CGFloat innerHeight = self.contentView.height - kTableCellVPadding*2;
    self.textLabel.frame = CGRectMake(kTableCellHPadding + kKeyWidth + kKeySpacing,
                                            kTableCellVPadding,
                                            valueWidth, innerHeight);
}

///////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark -
#pragma mark TTTableViewCell

///////////////////////////////////////////////////////////////////////////////////////////////////
- (void)setObject:(id)object {
    if (_item != object) {
        [super setObject:object];

        TTTableTextCaptionItem* item = object;
        self.textLabel.text = item.text;
        self.detailTextLabel.text = item.caption;
    }
}

@end</code></pre>
<h2>如何使用TTTableTextCaptionItem</h2>
<p>首先实现一个自定义的DataSource，然后在后续代码中使用这个DataSource</p>
<pre><code>#import "TTTableTextCaptionItemCell.h"
#import "TTTableTextCaptionItem.h"

@interface MyCustomDataSource : TTSectionedDataSource
@end

@implementation MyCustomDataSource

- (Class)tableView:(UITableView*)tableView cellClassForObject:(id)object {
    if ([object isKindOfClass:[TTTableTextCaptionItem class]]) {
        return [TTTableTextCaptionItemCell class];
    } else {
        return [super tableView:tableView cellClassForObject:object];
    }
}

@end</code></pre>
<h2>代码下载</h2>
<p>我把代码放到github上，方便大家参考 <a href="https://github.com/volca/TTTableTextCaptionItem">TTTableTextCaptionItem.git</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.ooso.net/archives/605/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>如何将TTURLRequest和OAuthConsumer搭配使用</title>
		<link>http://www.ooso.net/archives/602</link>
		<comments>http://www.ooso.net/archives/602#comments</comments>
		<pubDate>Fri, 01 Jul 2011 05:43:05 +0000</pubDate>
		<dc:creator>Volcano</dc:creator>
				<category><![CDATA[objective-c]]></category>
		<category><![CDATA[ios]]></category>
		<category><![CDATA[oauth]]></category>
		<category><![CDATA[three20]]></category>

		<guid isPermaLink="false">http://www.ooso.net/?p=602</guid>
		<description><![CDATA[TTURLRequest是three20开发框架提供的一个url请求类，它是NSURLRequest类的扩展，有如下优点:

post数据方便，只需要构建一个参数的dictionary就可以了，像get方法一样简单
支持磁盘缓存，而NSURLRequest仅支持内存缓存

				<span class="readmore"><a href="http://www.ooso.net/archives/602" title="如何将TTURLRequest和OAuthConsumer搭配使用">阅读全文（1647字）</a></span>]]></description>
			<content:encoded><![CDATA[<p>TTURLRequest是<a href="http://www.ooso.net/tag/three20">three20</a>开发框架提供的一个url请求类，它是NSURLRequest类的扩展，有如下优点:</p>
<ul>
<li>post数据方便，只需要构建一个参数的dictionary就可以了，像get方法一样简单</li>
<li>支持磁盘缓存，而NSURLRequest仅支持内存缓存</li>
<li>因为TTTableViewController + TTURLRequestModel的存在，搭配使用效果良好</li>
</ul>
<p>在ios的开发中我有时也用到了<a href="http://oauth.googlecode.com/svn/code/obj-c/OAuthConsumer/">OAuthConsumer</a>进行oauth授权，利用OAuthConsumer的fetcher类请求远程数据，所以我想TTURLRequest和OAuthConsumer能不能搭配使用，这样就能用上three20相关便利方法加载远程数据。于是做了点简单的测试，果然成功了:)大体思路是:</p>
<ul>
<li>先利用OAuthConsumer根据提交的参数计算出oauth的Authorization认证头</li>
<li>把Authorization头加到TTURLRequest</li>
<li>由TTURLRequest提交数据。</li>
</ul>
<p>直接上代码说话：</p>
<h2>计算Authorization头</h2>
<p>利用OAuthConsumer计算出Authorization头，为之后的请求做准备</p>
<pre><code>//start
OAConsumer * consumer = [[OAConsumer alloc] initWithKey:yourConsumerKey secret:yourSecret];
NSURL * url = [NSURL URLWithString:@"http://your-api-host/your-method"];
OAToken * authToken = [[OAToken alloc] initWithKey:yourAuthToken secret:yourAuthSecrent];
OAMutableURLRequest * request = [[OAMutableURLRequest alloc] initWithURL:url
                                                                consumer:consumer
                                                                   token:authToken
                                                                   realm:nil
                                                       signatureProvider:[[[OAPlaintextSignatureProvider alloc] init] autorelease]];
[request setHTTPMethod:@"POST"];

NSMutableArray * params = [NSMutableArray array];
OARequestParameter * p1 = [[OARequestParameter alloc] initWithName:@"param1" value:@"i'm param1"];
[params addObject:p1];

[request setParameters:params];
[request prepare];

TTDINFO(@"Authorization is %@", [request valueForHTTPHeaderField:@"Authorization"]);</code></pre>
<h2>使用TTURLRequest请求数据</h2>
<p>将Authorization头附加到TTURLRequest，然后请求远程接口</p>
<pre><code>TTURLRequest* req = [TTURLRequest requestWithURL:request.URL.absoluteString delegate:self];
req.response = [[[TTURLDataResponse alloc] init] autorelease];
req.httpMethod = @"POST";
req.cachePolicy = TTURLRequestCachePolicyNone;
[req setValue:[request valueForHTTPHeaderField:@"Authorization"] forHTTPHeaderField:@"Authorization"];
[req send];</code></pre>
<p>这个方法不需要对TTURLRequest进行修改，简单有效。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ooso.net/archives/602/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>php文档更新</title>
		<link>http://www.ooso.net/archives/548</link>
		<comments>http://www.ooso.net/archives/548#comments</comments>
		<pubDate>Sun, 26 Jun 2011 09:18:31 +0000</pubDate>
		<dc:creator>Volcano</dc:creator>
				<category><![CDATA[pear]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[vim]]></category>

		<guid isPermaLink="false">http://www.ooso.net/?p=548</guid>
		<description><![CDATA[php.net最近更新了php文档，比较有用的是新增的pman工具。pman是一个命令行小工具，方便查看php函数的本地帮助文档，但是不包含php.net的评论数据。简单的试用心得如下:
安装pman
使用传说中的pear来安装pman
sudo pear install doc.php.net/pman

				<span class="readmore"><a href="http://www.ooso.net/archives/548" title="php文档更新">阅读全文（1075字）</a></span>]]></description>
			<content:encoded><![CDATA[<p>php.net最近更新了<a href="/tag/php">php</a>文档，比较有用的是新增的pman工具。pman是一个命令行小工具，方便查看php函数的本地帮助文档，但是不包含php.net的评论数据。简单的试用心得如下:</p>
<h2>安装pman</h2>
<p>使用传说中的pear来安装pman</p>
<pre><code>sudo pear install doc.php.net/pman</code></pre>
<p>如果pear版本比较老，需要先升级pear才可以继续</p>
<pre><code>sudo pear upgrade pear</code></pre>
<h2>pman使用方法</h2>
<p>pman的使用方法很傻瓜，比如我们想查看strlen的帮助信息:</p>
<pre><code>pman strlen</code></pre>
<p>帮助文本的内容是彩色的，能和chm版本的php帮助文档媲美。pman的详细使用帮助如下</p>
<pre><code>#pman --help
man, version 1.6c

usage: man [-adfhktwW] [section] [-M path] [-P pager] [-S list]
	[-m system] [-p string] name ...

  a : find all matching entries
  c : do not use cat file
  d : print gobs of debugging information
  D : as for -d, but also display the pages
  f : same as whatis(1)
  h : print this help message
  k : same as apropos(1)
  K : search for a string in all pages
  t : use troff to format pages for printing
  w : print location of man page(s) that would be displayed
      (if no name given: print directories that would be searched)
  W : as for -w, but display filenames only

  C file   : use `file' as configuration file
  M path   : set search path for manual pages to `path'
  P pager  : use program `pager' to display pages
  S list   : colon separated section list
  m system : search for alternate system's man pages
  p string : string tells which preprocessors to run
               e - [n]eqn(1)   p - pic(1)    t - tbl(1)
               g - grap(1)     r - refer(1)  v - vgrind(1)</code></pre>
<p>还有一个好处是在vim里查看php帮助信息更方便了，结合完美</p>
<pre><code>:!pman strlen</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.ooso.net/archives/548/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>git flow使用经验小记</title>
		<link>http://www.ooso.net/archives/588</link>
		<comments>http://www.ooso.net/archives/588#comments</comments>
		<pubDate>Thu, 23 Jun 2011 02:25:43 +0000</pubDate>
		<dc:creator>Volcano</dc:creator>
				<category><![CDATA[common]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[git-flow]]></category>

		<guid isPermaLink="false">http://www.ooso.net/?p=588</guid>
		<description><![CDATA[我在半年前开始在公司内推广使用git flow，控制版本发布流程，到目前为止效果令人满意。
但是实际使用过程中有一些小小的意外流程，完全照搬git flow的模型不太容易处理好。好在git本身就很灵活，碰到问题基本上都有办法绕过去。下面是我总结的一些特例情况下的处理办法。

测试/共享单独一个feature

				<span class="readmore"><a href="http://www.ooso.net/archives/588" title="git flow使用经验小记">阅读全文（838字）</a></span>]]></description>
			<content:encoded><![CDATA[<p>我在半年前开始在公司内推广使用<a href="http://nvie.com/posts/a-successful-git-branching-model/">git flow</a>，控制版本发布流程，到目前为止效果令人满意。</p>
<p>但是实际使用过程中有一些小小的意外流程，完全照搬git flow的模型不太容易处理好。好在git本身就很灵活，碰到问题基本上都有办法绕过去。下面是我总结的一些特例情况下的处理办法。</p>
<p><img src="http://www.ooso.net/wp-content/uploads/2011/06/gitflow.png" alt="git-flow" /></p>
<h2>测试/共享单独一个feature</h2>
<p>有时候我们需要将一个feature独立测试，或者share给多人一块开发，那么可以将这个feature推到远程git库上，这可以利用git flow的publish功能搞定:</p>
<pre><code>git flow feature publish my_cool_feature</code></pre>
<p>这会将 feature/my_cool_feature 分支push到远程git库，多人开发或者单独测试毫无压力。</p>
<h2>feature在development分支测试完成，准备release的时候有另外一个未经测试的feature合并进来</h2>
<p>已经完成测试的development被未经测试的提交污染了，这时候可以先本地回滚development分支，然后再进行git flow的release流程，例如:</p>
<pre><code>git checkout development
git reset --hard 5cbadfe885d1eb514b3f07b3f269ca1a7f261e21   #假设测试通过的git rev是这个
git flow release start v1.0.1
git flow release finish v1.0.1</code></pre>
<h2>development上有个feature需要测试比较长时间，影响了一些耗时较短的feature发布 </h2>
<p>development分支上有个feature测试时间比较长一直释放不了，怎么办？—— 果断采用hotfix功能</p>
<pre><code>git br -m feature/another_cool_feature hotfix/another_cool_feature</code></pre>
<p>把耗时短的feature直接转换为hotfix，然后采用git flow的hotfix流程可以直接合并到master分支发布。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ooso.net/archives/588/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>一个关于three20开发框架的wiki</title>
		<link>http://www.ooso.net/archives/599</link>
		<comments>http://www.ooso.net/archives/599#comments</comments>
		<pubDate>Tue, 21 Jun 2011 08:22:51 +0000</pubDate>
		<dc:creator>Volcano</dc:creator>
				<category><![CDATA[objective-c]]></category>
		<category><![CDATA[iphone]]></category>

		<guid isPermaLink="false">http://www.ooso.net/?p=599</guid>
		<description><![CDATA[我最近花了不少时间做iphone上的app，由于是刚刚接触objective-c，需要从头学习的东西比较多。我从使用facebook开源的three20开发框架来学习ios应用开发，这种方式不能说是最好的学习方式，但是我也从中获得了不少乐趣。
关于three20的中文资料不是太多，所以我搜集整理翻译了一些内容，放到了wiki上:

本人才疏学浅，翻译的内容难免出错或者词不达意，欢迎批评指正。
]]></description>
			<content:encoded><![CDATA[<p>我最近花了不少时间做iphone上的app，由于是刚刚接触<a href="/tag/objective-c">objective-c</a>，需要从头学习的东西比较多。我从使用<a href="http://github.com/facebook/three20">facebook开源的three20开发框架</a>来学习ios应用开发，这种方式不能说是最好的学习方式，但是我也从中获得了不少乐趣。</p>
<p>关于three20的中文资料不是太多，所以我搜集整理翻译了一些内容，放到了wiki上:</p>
<p><a href="http://three20.viewc.com"><img src="http://img.viewc.com/three20.png" alt="three20  wiki" /></a></p>
<p>本人才疏学浅，翻译的内容难免出错或者词不达意，欢迎批评指正。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ooso.net/archives/599/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>用git部署php站点</title>
		<link>http://www.ooso.net/archives/596</link>
		<comments>http://www.ooso.net/archives/596#comments</comments>
		<pubDate>Tue, 29 Mar 2011 03:26:42 +0000</pubDate>
		<dc:creator>Volcano</dc:creator>
				<category><![CDATA[php]]></category>
		<category><![CDATA[deploy]]></category>
		<category><![CDATA[git]]></category>

		<guid isPermaLink="false">http://www.ooso.net/?p=596</guid>
		<description><![CDATA[在小站点上，直接用git来部署php代码相当方便，你的远程站点以及本地版本库都有一个版本控制，追踪问题或者回滚是很轻松的事情。下面介绍用git部署时的设置步骤
在远程服务器的设置
假定你需要部署的代码在/var/www/yoursite
cd /var/www/yoursite

				<span class="readmore"><a href="http://www.ooso.net/archives/596" title="用git部署php站点">阅读全文（488字）</a></span>]]></description>
			<content:encoded><![CDATA[<p>在小站点上，直接用git来部署php代码相当方便，你的远程站点以及本地版本库都有一个版本控制，追踪问题或者回滚是很轻松的事情。下面介绍用git部署时的设置步骤</p>
<h2>在远程服务器的设置</h2>
<p>假定你需要部署的代码在/var/www/yoursite</p>
<pre><code>cd /var/www/yoursite
git init .
git config receive.denyCurrentBranch ignore
git config --bool receive.denyNonFastForwards false
cd .git/hooks
wget http://utsl.gen.nz/git/post-update
chmod +x post-update</code></pre>
<h2>在本地git库中新增配置</h2>
<pre><code>[remote "prod"]
        url = your-ssh-username@your-host:/var/www/yoursite/</code></pre>
<p>这样就算设置完成了。</p>
<p>如果你想把本地的代码推送到远程服务器，下面简单的步骤就可以做到</p>
<pre><code>git pull
git push prod</code></pre>
<h2>注意事项</h2>
<p>如果远程服务器上git的配置目录.git暴露在外部可访问的位置，请在web服务器上设置这个目录不可见。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ooso.net/archives/596/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>jquery mobile alpha4有什么变化</title>
		<link>http://www.ooso.net/archives/594</link>
		<comments>http://www.ooso.net/archives/594#comments</comments>
		<pubDate>Tue, 29 Mar 2011 01:07:25 +0000</pubDate>
		<dc:creator>Volcano</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[jquery-mobile]]></category>
		<category><![CDATA[phonegap]]></category>

		<guid isPermaLink="false">http://www.ooso.net/?p=594</guid>
		<description><![CDATA[Jquery mobile团队即将发布alpha4，这个版本主要关注两个问题：性能以及兼容性。以下是这个版本更新的主要部分
Windows Phone 7 (WP7) 支持
JQM已经支持在WP7上运行，原来对WP7原生浏览器的支持度为C，也就是说部分核心功能不可用。而alpha4对这个做了大幅改动，支持度为A-，也就是说jquery mobile所有核心功能在WP7上都能运行良好。顺带受惠的还有桌面版的ie7, 8, 9，也能取得很好的运行效果。
名称空间data- 属性

				<span class="readmore"><a href="http://www.ooso.net/archives/594" title="jquery mobile alpha4有什么变化">阅读全文（1292字）</a></span>]]></description>
			<content:encoded><![CDATA[<p>Jquery mobile团队即将发布alpha4，这个版本主要关注两个问题：性能以及兼容性。以下是这个版本更新的主要部分</p>
<h2>Windows Phone 7 (WP7) 支持</h2>
<p>JQM已经支持在WP7上运行，原来对WP7原生浏览器的支持度为C，也就是说部分核心功能不可用。而alpha4对这个做了大幅改动，支持度为A-，也就是说jquery mobile所有核心功能在WP7上都能运行良好。顺带受惠的还有桌面版的ie7, 8, 9，也能取得很好的运行效果。</p>
<h2>名称空间data- 属性</h2>
<p>jquery mobile大量使用html5的data属性来定义html标签，比如页头是 <strong>data-role=&#8221;header&#8221;</strong>，但是其它开发框架和插件也可能使用了data来标记某些特性，为避免冲突，alpha4新增了名称空间的概念，新增了jqmData,jqmRemoveData和jqmHasData这几个方法来访问data属性，和jquery的data()相比，这几个方法支持名称空间访问。</p>
<p>举个例子，原来使用<strong>data-icon</strong>来标记一个标签使用的图标，但是如果你使用了名称空间 <strong>foo</strong>,那么这个属性应该变成 <strong>data-foo-icon</strong>。为了不影响原来基于jquery mobile开发的程序，名称空间默认为空，保持不变。</p>
<h2>统一的touch/mouse事件处理系统</h2>
<p>新的touch/mouse“虚拟”事件，详情请参考<a href="http://blogs.adobe.com/adobeandjquery/2011/03/07/the-current-state-of-touch-events/">The current state of touch events</a></p>
<h2>phonegap支持增强</h2>
<p>jquery mobile很适合和phonegap一起搭配来做原生的手机应用，但是在alpha3的时候，页面上的链接会被phonegap神奇的截断，有三个相关的问题：</p>
<ul>
<li>jQuery 1.5 截断了 file:// URLs</li>
<li>jQuery 1.5.1 修复了 file://，但是它把HTML当成是XML, 所以需要在做ajax请求的时候指定dataType.</li>
<li>原来是不允许JQM加载跨域的JQM页面，但是这个版本新增了一个配置选项 <strong>$.mobile.allowCrossDomainPages</strong> 来支持http/https页面. 这个改动会导致URL可能出现这样的情况: file://dir1/dir2/myPhoneGapApp.html#https://myHomeServer.com/dir1/dir2/foo</li>
</ul>
<p>以上这些问题在JQM alpha4里都得到了很好的解决，前提是使用jquery 1.5.1。</p>
<h2>重要的升级注意事项</h2>
<ul>
<li>列表li的html结构变化，可以用a标签直接包住li中需要链接的整个部分，比如图片,文字段落。</li>
<li>由于WP7不支持动态插入viewport meta标签，所以现在推荐的方式是在每个页面上都放上meta标签，原来是由JQM的metaViewportContent 方法动态插入的，但是以后这个方法将被取消。为了避免影响已有的站点，JQM会在缺少meta标签的页面上直接插入了一个。</li>
<li>原生的select选单将成为默认选项，这是出于性能问题考虑，如果你希望在alpha4中继续使用JQM定制的select选单，那么需要加上 <strong>data-native-menu=&#8221;false&#8221;</strong></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.ooso.net/archives/594/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>yepnope.js &#8211; 异步加载资源文件</title>
		<link>http://www.ooso.net/archives/591</link>
		<comments>http://www.ooso.net/archives/591#comments</comments>
		<pubDate>Tue, 08 Mar 2011 05:29:47 +0000</pubDate>
		<dc:creator>Volcano</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[yepnope]]></category>

		<guid isPermaLink="false">http://www.ooso.net/?p=591</guid>
		<description><![CDATA[yepnope.js是一个能够根据输入条件来选择性异步加载资源文件的js脚本，可以在页面上仅加载用户需要的js/css。
典型代码示例
yepnope({
  test : Modernizr.geolocation,

				<span class="readmore"><a href="http://www.ooso.net/archives/591" title="yepnope.js &#8211; 异步加载资源文件">阅读全文（1006字）</a></span>]]></description>
			<content:encoded><![CDATA[<p><a href="http://yepnopejs.com/">yepnope.js</a>是一个能够根据输入条件来选择性异步加载资源文件的js脚本，可以在页面上仅加载用户需要的js/css。</p>
<h2>典型代码示例</h2>
<pre><code>yepnope({
  test : Modernizr.geolocation,
  yep  : 'normal.js',
  nope : ['polyfill.js', 'wrapper.js']
});</code></pre>
<p>当Modernizr.geolocation为真时，加载yep项也就是&#8221;normal.js&#8221;，否则加载nope项——可以同时加载多个文件。</p>
<h2>yepnope和现有的xxx script loader有什么区别？</h2>
<p>个人认为主要 是这两点：</p>
<ul>
<li>可以同时处理javascript以及css</li>
<li>能够按条件加载</li>
</ul>
<h2>yepnope的全部参数</h2>
<pre><code>yepnope([{
  test : /* boolean(ish) - 你要检查真伪的表达式             */,
  yep  : /* array (of strings) | string - test为true时加载这项  */,
  nope : /* array (of strings) | string - test为false时加载这项 */,
  both : /* array (of strings) | string - 什么情况下都加载              */,
  load : /* array (of strings) | string - 什么情况下都加载              */,
  callback : /* function ( testResult, key ) | object { key : fn }   当某个url加载成功时执行相应的方法         */,
  complete : /* function   都加载完成了执行这个方法                                                   */
}, ... ]);</code></pre>
<p>这里的参数都可以是array或者object，在加载多个资源文件的时候有用。</p>
<h3>yepnope加载jquery的实例</h3>
<pre><code>yepnope([{
  load: 'http:/­/ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js',
  complete: function () {
    if (!window.jQuery) {
      yepnope('local/jquery.min.js');
    }
  }
}, {
  load: 'jquery.plugin.js',
  complete: function () {
    jQuery(function () {
      jQuery('div').plugin();
    });
  }
}]);</code></pre>
<p>这段代码异步加载了jquery和jquery.plugin.js，甚至还对jquery加载失败的情况做了一个备用处理。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ooso.net/archives/591/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>如何安装Node.js</title>
		<link>http://www.ooso.net/archives/589</link>
		<comments>http://www.ooso.net/archives/589#comments</comments>
		<pubDate>Sun, 13 Feb 2011 01:34:54 +0000</pubDate>
		<dc:creator>Volcano</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[nodejs]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://www.ooso.net/?p=589</guid>
		<description><![CDATA[下面分别介绍在Mac, Ubuntu,Centos以及Windows下安装Node.js.
Mac
在Mac下，如果你喜欢用homebrew，那么只用一行就可以装好:
brew install node

				<span class="readmore"><a href="http://www.ooso.net/archives/589" title="如何安装Node.js">阅读全文（1230字）</a></span>]]></description>
			<content:encoded><![CDATA[<p>下面分别介绍在<a href="#mac">Mac</a>, <a href="#ubuntu">Ubuntu</a>,<a href="#centos">Centos</a>以及<a href="#windows">Windows</a>下安装<a href="/tag/nodejs">Node.js</a>.</p>
<h2 id="mac">Mac</h2>
<p>在Mac下，如果你喜欢用<a href="http://github.com/mxcl/homebrew">homebrew</a>，那么只用一行就可以装好:</p>
<pre><code>brew install node</code></pre>
<p>否则，只能考虑手工安装了，步骤如下：</p>
<ul>
<ol>
<li>安装Xcode</li>
<li><a href="http://help.github.com/mac-git-installation/">安装git</a></li>
<li>运行下面的命令行编译node.js
<pre><code>git clone git://github.com/joyent/node.git
cd node
./configure
make
sudo make install</code></pre>
</li>
</ol>
</ul>
<h2 id="ubuntu">Ubuntu</h2>
<ul>
<ol>
<li>安装依赖包
<pre><code>sudo apt-get install g++ curl libssl-dev apache2-utils
sudo apt-get install git-core</code></pre>
</li>
<li>运行下面的命令行:
<pre><code>git clone git://github.com/joyent/node.git
cd node
./configure
make
sudo make install</code></pre>
</li>
</ol>
</ul>
<h2 id="windows">Windows</h2>
<p>用cygwin来安装node，步骤如下:</p>
<ul>
<ol>
<li>安装<a href="http://www.cygwin.com/">cygwin</a>
</li>
<li>在cygwin的目录下，运行setup.exe安装下面列表中的包
<ul>
<li>devel → openssl</li>
<li>devel → g++-gcc</li>
<li>devel → make
</li>
<li>python → python
</li>
<li>devel → git
</li>
</ul>
</li>
<li>运行cygwin
</li>
<li>运行下面的命令行:
<pre><code>git clone git://github.com/joyent/node.git
cd node
./configure
make
sudo make install</code></pre>
</li>
</ol>
</ul>
<h2 id="centos">Centos</h2>
<pre><code>yum install gcc-c++ openssl-devel
wget --no-check-certificate https://github.com/joyent/node/tarball/v0.3.3
tar -xzvf ry-node-v0.3.3-0-g57544ba.tar.gz
cd ry-node-v0.3.3-0-g57544bac1
./configure
make
make install</code></pre>
<h2>Hello Node.js!</h2>
<p>写一段小程序例如hello_node.js来验证安装是否正确：</p>
<pre><code>var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello Node.js\n');
}).listen(8124, "127.0.0.1");
console.log('Server running at http://127.0.0.1:8124/');</code></pre>
<p>用node来运行这段代码</p>
<pre><code>node hello_node.js
Server running at http://127.0.0.1:8124/</code></pre>
<p>现在，用浏览器打开 http://127.0.0.1:8124/ ， 应该能够看到一条好消息。</p>
<h2>参考文档</h2>
<p><a href="http://howtonode.org/how-to-install-nodejs">How to Install Node.js</a></p>
<h2>Update</h2>
<ul>
<li>补充了在centos上安装Node.js的步骤</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.ooso.net/archives/589/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>设置自动重连的ssh代理通道</title>
		<link>http://www.ooso.net/archives/586</link>
		<comments>http://www.ooso.net/archives/586#comments</comments>
		<pubDate>Wed, 09 Feb 2011 08:21:55 +0000</pubDate>
		<dc:creator>Volcano</dc:creator>
				<category><![CDATA[common]]></category>
		<category><![CDATA[chrome]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[proxy]]></category>
		<category><![CDATA[ssh]]></category>

		<guid isPermaLink="false">http://www.ooso.net/?p=586</guid>
		<description><![CDATA[我目前常用的翻墙办法就是拿ssh搭个代理通道，然后chrome + switch!插件一起配合，这就算翻墙了。这法子只要拿个机器跑一小脚本，比如：
ssh -D 7070 -qnN [username]@[server]
但是ssh通道如果闲置了一段时间，就会自动断连，等我需要用到代理的时候往往又得蛋疼的重新跑一遍，非常麻烦。所以我刻苦学习前辈的经验，找到一个解决办法，在mac或linux下都可使用，分享如下:


				<span class="readmore"><a href="http://www.ooso.net/archives/586" title="设置自动重连的ssh代理通道">阅读全文（494字）</a></span>]]></description>
			<content:encoded><![CDATA[<p>我目前常用的翻墙办法就是拿<a href="/tag/ssh">ssh</a>搭个代理通道，然后chrome + switch!插件一起配合，这就算翻墙了。这法子只要拿个机器跑一小脚本，比如：</p>
<pre><code>ssh -D 7070 -qnN [username]@[server]</code></pre>
<p>但是ssh通道如果闲置了一段时间，就会自动断连，等我需要用到代理的时候往往又得蛋疼的重新跑一遍，非常麻烦。所以我刻苦学习前辈的经验，找到一个解决办法，在mac或linux下都可使用，分享如下:</p>
<ul>
<li>把ssh配置为免密码登录，这个一搜一大把，略过不提</li>
<li>在/etc/inittab的最后一行加上:
<pre><code>tunl:345:respawn:/usr/bin/ssh -D 7070 -qnN [username]@[server] &gt; /dev/null 2&gt;&#038;1</code></pre>
</li>
<li>让修改的inittab马上生效
<pre><code>sudo init q</code></pre>
</li>
<li>在/root/.ssh/config里加上几行
<pre><code>Host *
  ServerAliveInterval 60</code></pre>
</li>
</ul>
<p>然后这个ssh通道就会自动重连了。</p>
<h2>Update</h2>
<ul>
<li>增加了一个ssh配置，要不然这个进程虽然在，但是通道已经连不上了</li>
<li>.ssh/config的配置是关键，/etc/inittab的配置只是让服务器开机即启动ssh通道</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.ooso.net/archives/586/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>git svn实战</title>
		<link>http://www.ooso.net/archives/576</link>
		<comments>http://www.ooso.net/archives/576#comments</comments>
		<pubDate>Mon, 17 Jan 2011 07:26:36 +0000</pubDate>
		<dc:creator>Volcano</dc:creator>
				<category><![CDATA[php]]></category>
		<category><![CDATA[wordpress]]></category>
		<category><![CDATA[code-prettify]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[git-svn]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[svn]]></category>

		<guid isPermaLink="false">http://www.ooso.net/?p=576</guid>
		<description><![CDATA[我之前写了几个wordpress插件，比如inline-javascript, code-prettify。这些插件都托管在wordpress.org提供的svn服务器上，但是我实在太喜欢在git下活动了，因此动了点心思，想把插件代码传到github上，开发完之后利用git-svn传到wordpress的svn服务上。
照着这个思路，捋起袖子就开干了。
用git-svn抓取插件代码
wordpress的插件svn库大且缓慢，如果直接用git-svn去clone代码，一定会慢死，所以我按照以前的笔记，用git从大型svn快速clone代码。

				<span class="readmore"><a href="http://www.ooso.net/archives/576" title="git svn实战">阅读全文（950字）</a></span>]]></description>
			<content:encoded><![CDATA[<p>我之前写了几个wordpress插件，比如<a href="http://www.ooso.net/inline-js">inline-javascript</a>, <a href="http://www.ooso.net/code-prettify">code-prettify</a>。这些插件都托管在wordpress.org提供的svn服务器上，但是我实在太喜欢在git下活动了，因此动了点心思，想把插件代码传到github上，开发完之后利用<a href="/tag/git-svn">git-svn</a>传到wordpress的svn服务上。</p>
<p>照着这个思路，捋起袖子就开干了。</p>
<h2>用git-svn抓取插件代码</h2>
<p>wordpress的插件svn库大且缓慢，如果直接用git-svn去clone代码，一定会慢死，所以我按照以前的笔记，<a href="http://www.ooso.net/archives/523">用git从大型svn快速clone代码</a>。</p>
<p>以code-prettify插件为例，首先需要读取这个插件创建时的版本号</p>
<pre>
<code>svn log http://svn.wp-plugins.org/code-prettify|tail -4|head -1</code>
</pre>
<p>得到了如下信息，获得一个版本号 318479</p>
<pre><code>r318479 | plugin-master | 2010-12-03 20:12:29 +0800 (五, 03 12 2010) | 1 line</code></pre>
<p>开始clone代码</p>
<pre><code>git svn clone -s --prefix=svn/ -r318479:HEAD http://svn.wp-plugins.org/code-prettify</code></pre>
<h2>设置git仓库</h2>
<p>首先把代码传了一份到github: <a href="https://github.com/volca/code-prettify">https://github.com/volca/code-prettify</a></p>
<p>然后操作本地git仓库</p>
<pre>
<code>git branch -m svn
git remote add origin git@github.com:volca/code-prettify.git
git checkout master</code>
</pre>
<p>本地svn分支对应svn的远程仓库，本地master分支对应github的远程仓库</p>
<h2>Happy time</h2>
<p>现在可以按照平常的习惯在git下更改代码，然后用git push到github上。</p>
<p>如果需要更新代码到svn上，按这个流程操作就可以了：</p>
<pre>
<code>git checkout svn
git merge master
git svn dcommit</code>
</pre>
<p>如果需要发布wordpress插件的新版本，这个在svn里就是一个打tag的过程，用git-svn操作非常简单，下面的例子表示发布code-prettify插件的0.3版本：</p>
<pre>
<code>git svn tag 0.3
</code>
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.ooso.net/archives/576/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>防止伪造跨站请求的小招式</title>
		<link>http://www.ooso.net/archives/581</link>
		<comments>http://www.ooso.net/archives/581#comments</comments>
		<pubDate>Mon, 17 Jan 2011 02:34:52 +0000</pubDate>
		<dc:creator>Volcano</dc:creator>
				<category><![CDATA[php]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://www.ooso.net/?p=581</guid>
		<description><![CDATA[伪造跨站请求介绍
伪造跨站请求比较难以防范，而且危害巨大，攻击者可以通过这种方式恶作剧，发spam信息，删除数据等等。这种攻击常见的表现形式有：

伪造链接，引诱用户点击，或是让用户在不知情的情况下访问

				<span class="readmore"><a href="http://www.ooso.net/archives/581" title="防止伪造跨站请求的小招式">阅读全文（357字）</a></span>]]></description>
			<content:encoded><![CDATA[<h2>伪造跨站请求介绍</h2>
<p>伪造跨站请求比较难以防范，而且危害巨大，攻击者可以通过这种方式恶作剧，发spam信息，删除数据等等。这种攻击常见的表现形式有：</p>
<ul>
<li>伪造链接，引诱用户点击，或是让用户在不知情的情况下访问</li>
<li>伪造表单，引诱用户提交。表单可以是隐藏的，用图片或链接的形式伪装。</li>
</ul>
<p>比较常见而且也很廉价的防范手段是在所有可能涉及用户写操作的表单中加入一个随机且变换频繁的字符串，然后在处理表单的时候对这个字符串进行检查。这个随机字符串如果和当前用户身份相关联的话，那么攻击者伪造请求会比较麻烦。</p>
<p>yahoo对付伪造跨站请求的办法是在表单里加入一个叫<strong>.crumb</strong>的随机串；而facebook也有类似的解决办法，它的表单里常常会有<strong>post_form_id</strong>和<strong>fb_dtsg</strong>。</p>
<h2>随机串代码实现</h2>
<p>咱们按照这个思路，山寨一个crumb的实现，代码如下：</p>
<pre><code>&lt;?php
class Crumb {                                                                                                  

    CONST SALT = "your-secret-salt";                                                         

    static $ttl = 7200;                                                                                           

    static public function challenge($data) {
        return hash_hmac('md5', $data, self::SALT);
    }                                                                                                             

    static public function issueCrumb($uid, $action = -1) {
        $i = ceil(time() / self::$ttl);
        return substr(self::challenge($i . $action . $uid), -12, 10);
    }                                                                                                             

    static public function verifyCrumb($uid, $crumb, $action = -1) {
        $i = ceil(time() / self::$ttl);                                                                           

        if(substr(self::challenge($i . $action . $uid), -12, 10) == $crumb ||
            substr(self::challenge(($i - 1) . $action . $uid), -12, 10) == $crumb)
            return true;                                                                                          

        return false;
    }                                                                                                             

}</code></pre>
<p>代码中的$uid表示用户唯一标识，而$ttl表示这个随机串的有效时间。</p>
<h2>应用示例</h2>
<p><strong>构造表单</strong><br />
在表单中插入一个隐藏的随机串crumb</p>
<pre><code>&lt;form method="post" action="demo.php"&gt;
&lt;input type="hidden" name="crumb" value="&lt;?php echo Crumb::issueCrumb($uid)?&gt;"&gt;
&lt;input type="text" name="content"&gt;
&lt;input type="submit"&gt;
&lt;/form&gt;</code></pre>
<p><strong>处理表单 demo.php</strong><br />
对crumb进行检查</p>
<pre><code>&lt;?php
if(Crumb::verifyCrumb($uid, $_POST['crumb'])) {
    //按照正常流程处理表单
} else {
    //crumb校验失败，错误提示流程
}</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.ooso.net/archives/581/feed</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>如何在jquery mobile中加载google map api</title>
		<link>http://www.ooso.net/archives/580</link>
		<comments>http://www.ooso.net/archives/580#comments</comments>
		<pubDate>Thu, 13 Jan 2011 07:03:42 +0000</pubDate>
		<dc:creator>Volcano</dc:creator>
				<category><![CDATA[google]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[google-map]]></category>
		<category><![CDATA[jquery-mobile]]></category>

		<guid isPermaLink="false">http://www.ooso.net/?p=580</guid>
		<description><![CDATA[介绍一个用jquery mobile的ajax效果加载google map api，实现地图呈现的例子。
代码示例
首先是代码示例，使用iphone或android之类的手机查看，效果更佳
google map with jquery mobile

				<span class="readmore"><a href="http://www.ooso.net/archives/580" title="如何在jquery mobile中加载google map api">阅读全文（605字）</a></span>]]></description>
			<content:encoded><![CDATA[<p>介绍一个用<a href="/tag/jquery-mobile">jquery mobile</a>的ajax效果加载google map api，实现地图呈现的例子。</p>
<h2>代码示例</h2>
<p>首先是代码示例，使用iphone或android之类的手机查看，效果更佳<br />
<a href="http://www.ooso.net/wp-content/uploads/2010/12/map/">google map with jquery mobile</a></p>
<h2>关键代码说明</h2>
<p><strong>map.js</strong></p>
<p>map.js定义了加载地图的方法initiallize()，这个和常规网页中加载google map是一致的，因此这里不再细述。</p>
<p><strong>map.html</strong></p>
<p>地图的实际页面，在这个页面中不能直接加载google map的api，因为它是采用document.write再次写入script来实现的，所以我们采用callback的方式来加载它，见下面的代码： </p>
<pre><code>head.js(
        "map.js",
        function() {
            head.js("http://maps.google.com/maps/api/js?sensor=true&#038;callback=initialize");
        }
    );</code></pre>
<p>首先用<a href="https://github.com/headjs/headjs">head.js</a>把initialize方法装载进来，然后用callback方式调用google map api。你可以试试用最平常的方式加载这段代码，看看有什么效果。</p>
<pre><code>&lt;script src="map.js"&gt;&lt;/script&gt;
&lt;script src="http://maps.google.com/maps/api/js?sensor=true&#038;callback=initialize"&gt;&lt;/script&gt;</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.ooso.net/archives/580/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>code-prettify &#8212; wordpress语法高亮插件</title>
		<link>http://www.ooso.net/archives/575</link>
		<comments>http://www.ooso.net/archives/575#comments</comments>
		<pubDate>Thu, 02 Dec 2010 12:51:28 +0000</pubDate>
		<dc:creator>Volcano</dc:creator>
				<category><![CDATA[wordpress]]></category>
		<category><![CDATA[code-pretitty]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[plugin]]></category>

		<guid isPermaLink="false">http://www.ooso.net/?p=575</guid>
		<description><![CDATA[最近基于google-code-prettify实现了一个代码高亮的wordpress插件 &#8212; code-pretttify，测试了下效果还不错，所以我马上把全站的代码高亮插件换成了这个。
这里是code-prettify的项目主页，我会把这个plugin的最新情况更新在这里。
code-prettify的特点


				<span class="readmore"><a href="http://www.ooso.net/archives/575" title="code-prettify &#8212; wordpress语法高亮插件">阅读全文（954字）</a></span>]]></description>
			<content:encoded><![CDATA[<p>最近基于<a href="http://code.google.com/p/google-code-prettify/">google-code-prettify</a>实现了一个代码高亮的<a href="/tag/wordpress">wordpress</a>插件 &#8212; <a href="/code-prettify">code-pretttify</a>，测试了下效果还不错，所以我马上把全站的代码高亮插件换成了这个。</p>
<p>这里是<a href="/code-prettify">code-prettify的项目主页</a>，我会把这个plugin的最新情况更新在这里。</p>
<h2>code-prettify的特点</h2>
<ul>
<li>完全由javascript完成代码高亮，不占用服务器资源</li>
<li>使用简单，只要用&lt;pre&gt;&lt;code&gt;和&lt;/code&gt;&lt;/pre&gt;包住代码，发布即可，这是wordpress编辑器自带的quicktag。</li>
<li>没有添加额外的hook，所以不会和别的wordpress插件产生冲突，绿色无污染</li>
<li>载入速度很快，因为js是在页面尾部加载的，不会堵塞页面的载入！</li>
</ul>
<h2>代码高亮效果演示</h2>
<p><strong>eg:</strong></p>
<pre><code>&lt;pre&gt;&lt;code&gt;
class BigBang {
    function blah() {
        echo "Hello ooso.net";
    }
}
&lt;/code&gt;&lt;/pre&gt;</code></pre>
<p><strong>Effect:</strong></p>
<pre><code>class BigBang {
    function blah() {
        echo "Hello ooso.net";
    }
}</code></pre>
<p>测试objective-c的code prettify效果</p>
<pre><code>TTImageView *thumb = [[[TTImageView alloc] initWithFrame:CGRectMake(30, 30, 0, 0)] autorelease];
[thumb setAutoresizesToImage:YES];
[thumb setURL:@"http://farm4.static.flickr.com/3163/3110335722_7a906f9d8b_m.jpg"];
[self.view addSubview:thumb];
</pre>
<p></code></p>
<h2>code-prettify下载</h2>
<p>暂时把代码托管到<a href="https://github.com/volca/code-prettify">github.com/volca/code-prettify</a>，所以你可以直接使用git下载代码，或者直接从github下载现成的zip包。</p>
<p>代码非常简单，如果你有合适修正，可以试着用github推给我。</p>
<h2>Update</h2>
<p>另外安装了一个全新的wordpress测试，发现一些bug，因为wordpress默认对文本进行格式修正，在代码后面添加了很多br以及p标签，导致插件失效，所以我不得已用php替换了一些内容保证插件的正常运行。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ooso.net/archives/575/feed</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>如何让WPTouch和WP Super Cache同时工作</title>
		<link>http://www.ooso.net/archives/566</link>
		<comments>http://www.ooso.net/archives/566#comments</comments>
		<pubDate>Wed, 01 Dec 2010 05:42:41 +0000</pubDate>
		<dc:creator>Volcano</dc:creator>
				<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://www.ooso.net/?p=566</guid>
		<description><![CDATA[为了让blog在手机上看起来更舒服，所以我安装了一个wordpress插件叫WPTouch。安装成功之后的效果图如下：

我原来还安装了一个叫WP Super Cache的插件，如果这个插件开启的话，在手机上就看不到上图的效果，应该是手机也访问了页面的缓存。简单的解决步骤如下：


				<span class="readmore"><a href="http://www.ooso.net/archives/566" title="如何让WPTouch和WP Super Cache同时工作">阅读全文（299字）</a></span>]]></description>
			<content:encoded><![CDATA[<p>为了让blog在手机上看起来更舒服，所以我安装了一个wordpress插件叫WPTouch。安装成功之后的效果图如下：</p>
<p><img src="http://static1.139js.com/system/picture/12368884/600x600/wptouch.jpg" alt="wptouch" /></p>
<p>我原来还安装了一个叫WP Super Cache的插件，如果这个插件开启的话，在手机上就看不到上图的效果，应该是手机也访问了页面的缓存。简单的解决步骤如下：</p>
<ul>
<ol>
<li>登录到wordpress后台
</li>
<li>选择设置 -&gt; WP Super Cache
</li>
<li>在Advance mode下勾选Mobile device support并保存
</li>
<li>按照提示点击&#8221;Update Mod_Rewrite Rules&#8221;</li>
</ol>
</ul>
<p>这样就生效了。</p>
<p>BTW:以上步骤实际上是更新了文件.htaccess以及wp-content/wp-cache-config.php</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ooso.net/archives/566/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>mac下的tree命令</title>
		<link>http://www.ooso.net/archives/564</link>
		<comments>http://www.ooso.net/archives/564#comments</comments>
		<pubDate>Mon, 22 Nov 2010 12:34:50 +0000</pubDate>
		<dc:creator>Volcano</dc:creator>
				<category><![CDATA[common]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[shell]]></category>
		<category><![CDATA[tree]]></category>

		<guid isPermaLink="false">http://www.ooso.net/?p=564</guid>
		<description><![CDATA[在默认安装安装的mac下没有找到tree命令，找了一下原来有个比较流氓的解决办法：
find . -print &#124; sed -e 's;[^/]*/;&#124;____;g;s;____&#124;; &#124;;g'
这个命令行跑起来类似平常tree的效果，比如：
.

				<span class="readmore"><a href="http://www.ooso.net/archives/564" title="mac下的tree命令">阅读全文（881字）</a></span>]]></description>
			<content:encoded><![CDATA[<p>在默认安装安装的mac下没有找到tree命令，找了一下原来有个比较流氓的解决办法：</p>
<pre><code>find . -print | sed -e 's;[^/]*/;|____;g;s;____|; |;g'</code></pre>
<p>这个命令行跑起来类似平常tree的效果，比如：</p>
<pre><code>.
|____extra
| |____httpd-autoindex.conf
| |____httpd-dav.conf
| |____httpd-default.conf
| |____httpd-info.conf
| |____httpd-languages.conf
| |____httpd-manual.conf
| |____httpd-mpm.conf
| |____httpd-multilang-errordoc.conf
| |____httpd-ssl.conf
| |____httpd-userdir.conf
| |____httpd-vhosts.conf
|____httpd.conf
|____magic
|____mime.types
|____original
| |____extra
| | |____httpd-autoindex.conf
| | |____httpd-dav.conf
| | |____httpd-default.conf
| | |____httpd-info.conf
| | |____httpd-languages.conf
| | |____httpd-manual.conf
| | |____httpd-mpm.conf
| | |____httpd-multilang-errordoc.conf
| | |____httpd-ssl.conf
| | |____httpd-userdir.conf
| | |____httpd-vhosts.conf
| |____httpd.conf
|____other
| |____bonjour.conf
| |____php5.conf
|____users</code></pre>
<p>写一个alias到~/.bash_profile里，就更方便了:</p>
<pre><code>alias tree="find . -print | sed -e 's;[^/]*/;|____;g;s;____|; |;g'"</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.ooso.net/archives/564/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>mysql主从同步快速设置</title>
		<link>http://www.ooso.net/archives/547</link>
		<comments>http://www.ooso.net/archives/547#comments</comments>
		<pubDate>Wed, 27 Oct 2010 06:46:52 +0000</pubDate>
		<dc:creator>Volcano</dc:creator>
				<category><![CDATA[mysql]]></category>

		<guid isPermaLink="false">http://www.ooso.net/?p=547</guid>
		<description><![CDATA[记录一个比较简便的mysql的主从同步设置步骤，方便日后使用。
安装环境
centos 5.4
mysql 5.1.xx 采用rpm直接安装

				<span class="readmore"><a href="http://www.ooso.net/archives/547" title="mysql主从同步快速设置">阅读全文（1166字）</a></span>]]></description>
			<content:encoded><![CDATA[<p>记录一个比较简便的mysql的主从同步设置步骤，方便日后使用。</p>
<h2>安装环境</h2>
<li>centos 5.4</li>
<li>mysql 5.1.xx 采用rpm直接安装</li>
<li>xtrabackup 1.2.22 采用rpm直接安装</li>
<h2>1. Master:/etc/my.cnf</h2>
<pre><code>[mysqld]
server-id = 1
log-bin
innodb_flush_log_at_trx_commit=1
sync_binlog=1
datadir=/var/lib/mysql

character-set-server=utf8
init_connect='SET NAMES utf8'</code></pre>
<p>设定了默认字符集为utf8，可以按实际情况取舍这段配置。</p>
<h2>2. Slave:/etc/my.cnf</h2>
<pre><code>[mysqld]
server-id=2
datadir=/var/lib/mysql

character-set-server=utf8
init_connect='SET NAMES utf8'</code></pre>
<h2>3. Master:在master数据库设置用来同步的slave用户权限</h2>
<pre><code>GRANT REPLICATION SLAVE ON *.*
TO '&lt;slave_username&gt;'@'&lt;slave_ip&gt;'
IDENTIFIED BY '&lt;slave_password&gt;';</code></pre>
<h2></h2>
<h2>4. Master:导出数据到slave</h2>
<p>采用xtrabackup来备份mysql，好处是在master的锁表时间很短，在实际的生产环境也可以使用，并且xtrabackup会自动记录同步日志文件的位置。</p>
<pre><code>sudo innobackupex-1.5.1 --stream=tar /tmp/ | ssh &lt;slave_host&gt; "mkdir /tmp/db; tar xfi - -C /tmp/db/"</code></pre>
<p>这个步骤会把master的数据包括表结构整个导出并压缩复制给slave，同时解压到slave的/tmp/db目录下。</p>
<h2>5. Slave:导入数据到slave</h2>
<pre><code>innobackupex-1.5.1 --apply-log /tmp/db
innobackupex-1.5.1 --copy-back /tmp/db
chown -R mysql.mysql /var/lib/mysql/*</code></pre>
<h2>6. Slave:开始同步数据</h2>
<p>查看/var/lib/mysql/xtrabackup_binlog_info，获得日志文件以及position。</p>
<pre><code>CHANGE MASTER TO
MASTER_HOST='&lt;master_host&gt;',
MASTER_USER='&lt;slave_username&gt;',
MASTER_PASSWORD='&lt;slave_password&gt;',
MASTER_LOG_FILE='&lt;see xtrabackup_binlog_info&gt;',
MASTER_LOG_POS=&lt;see xtrabackup_binlog_info&gt;;

START SLAVE;</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.ooso.net/archives/547/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>php实现的thrift socket server</title>
		<link>http://www.ooso.net/archives/537</link>
		<comments>http://www.ooso.net/archives/537#comments</comments>
		<pubDate>Fri, 25 Jun 2010 08:03:31 +0000</pubDate>
		<dc:creator>Volcano</dc:creator>
				<category><![CDATA[php]]></category>
		<category><![CDATA[libevent]]></category>
		<category><![CDATA[socket]]></category>
		<category><![CDATA[thrift]]></category>

		<guid isPermaLink="false">http://www.ooso.net/?p=537</guid>
		<description><![CDATA[这些天用php写了个thrift的socket server，因为原来thrift的源码里php部分只有基于apache的服务器端代码，再加上前些日子看到php也能直接使用libevent构建web服务器，所以才会想到写这个玩玩。
php-thrift-server源码
代码直接从apache的thrift项目clone过来，托管在github上：
http://github.com/volca/thrift

				<span class="readmore"><a href="http://www.ooso.net/archives/537" title="php实现的thrift socket server">阅读全文（2531字）</a></span>]]></description>
			<content:encoded><![CDATA[<p>这些天用php写了个thrift的socket server，因为原来thrift的源码里php部分只有基于apache的服务器端代码，再加上前些日子看到<a href="/tag/php">php</a>也能直接使用libevent构建web服务器，所以才会想到写这个玩玩。</p>
<h2>php-thrift-server源码</h2>
<p>代码直接从apache的thrift项目clone过来，托管在github上：</p>
<p><a href="http://github.com/volca/thrift">http://github.com/volca/thrift</a></p>
<p>新增或改动的代码如下:</p>
<ol>
<pre>
lib/php/
`-- src
    |-- server
    |   |-- TNonblockingServer.php
    |   `-- TServer.php
    `-- transport
        |-- TNonblockingServerSocket.php
        |-- TNonblockingSocket.php
        |-- TServerSocket.php
        |-- TServerTransport.php
test/php
|-- TestClient.php
|-- TestNonblockingServer.php
</pre>
</ol>
<h2>使用示例</h2>
<p>获取thrift的源码，并编译出thrift工具，编译过程请搜索</p>
<pre><code>git clone git://github.com/volca/thrift.git</code></pre>
<p>安装php,以及apc, libevent扩展:</p>
<pre><code>pecl install apc
#需要先libevent-devel之类的包包
pecl install libevent</code></pre>
<p>运行php的socket服务器，我直接从thrift的test代码中修改了一个独立运行的php server，见thrift/test/php/TestNonblockingServer.php，这里也包含一个测试业务代码的实现。</p>
<pre><code>cd thrift/test/php
#用thrift命令行工具生成php的测试类库
make
#启动thrift服务，会监听本机的9090端口
php TestNonblockingServer.php</code></pre>
<p>客户端的代码也一并提供，对各种数据类型比如int, float, string, list等等进行测试。</p>
<pre><code>php TestClient.php</code></pre>
<h2>性能测试</h2>
<p>apache + php的测试结果</p>
<pre><code>testVoid() = void
testString("Test") = "Test"
testByte(1) = 1
testI32(-1) = -1
testI64(-34359738368) = -34359738368
testDouble(-852.234234234) = -852.234234234
testStruct({"Zero", 1, -3, -5}) = {"Zero", 1, -3, -5}
testNest({1, {"Zero", 1, -3, -5}), 5} = {1, {"Zero", 1, -3, -5}, 5}
testMap({0 =&gt; -10, 1 =&gt; -9, 2 =&gt; -8, 3 =&gt; -7, 4 =&gt; -6}) = {0 =&gt; -10, 1 =&gt; -9, 2 =&gt; -8, 3 =&gt; -7, 4 =&gt; -6}
testSet({-2, -1, 0, 1, 2}) = {1, 1, 1, 1, 1}
testList({-2, -1, 0, 1, 2}) = {-2, -1, 0, 1, 2}
testEnum(ONE) = 1
testEnum(TWO) = 2
testEnum(THREE) = 3
testEnum(FIVE) = 5
testEnum(EIGHT) = 8
testTypedef(309858235082523) = 309858235082523
Total time: 41 ms</code></pre>
<p>php + libevent的socket server测试结果</p>
<pre><code>testVoid() = void
testString("Test") = "Test"
testByte(1) = 1
testI32(-1) = -1
testI64(-34359738368) = -34359738368
testDouble(-852.234234234) = -852.234234234
testStruct({"Zero", 1, -3, -5}) = {"Zero", 1, -3, -5}
testNest({1, {"Zero", 1, -3, -5}), 5} = {1, {"Zero", 1, -3, -5}, 5}
testMap({0 =&gt; -10, 1 =&gt; -9, 2 =&gt; -8, 3 =&gt; -7, 4 =&gt; -6}) = {0 =&gt; -10, 1 =&gt; -9, 2 =&gt; -8, 3 =&gt; -7, 4 =&gt; -6}
testSet({-2, -1, 0, 1, 2}) = {1, 1, 1, 1, 1}
testList({-2, -1, 0, 1, 2}) = {-2, -1, 0, 1, 2}
testEnum(ONE) = 1
testEnum(TWO) = 2
testEnum(THREE) = 3
testEnum(FIVE) = 5
testEnum(EIGHT) = 8
testTypedef(309858235082523) = 309858235082523
Total time: 8 ms</code></pre>
<p>这个测试中，没有耗时很长的请求，处理逻辑完全一样，php socket server耗时仅为apache + php的五分之一。</p>
<h2>thrift是什么？</h2>
<p>thrift流传的似乎不是太广泛，而且有被别的技术替代的趋势，所以下面还是引用一下别的文章的介绍：</p>
<blockquote><p>Thrift由一个软件库和一系列的代码生成工具组成，由 Facebook开发。目的是为了加快软件开发和实现高效和可扩展的后台服务。主要目标是不同程序开语言之间实现高效和可靠的通信，这需要将不同语言之间抽象出一个通用层，然后由不同语言来实现这个通用层。在这里要特别指出的是，Thrift允许开发人员定义数据类型和服务接口（定义在一个中性语言文件里），并通过这个文件生成构建RPC客户端和服务端所需的代码。</p>
<p>简单分析其机理，Thrift就是实现C/S模式，通过代码生成工具将接口定义文件生成服务器端和客户端代码（可以为不同语言），从而实现服务端和客户端跨语言的支持。</p>
<p>Thrift可以分为传输层和协议层：</p>
<p>传输层定义了数据的传输方式，可以为TCP/IP传输，内存共享或者文件共享等形式；<br />
协议层定义了数据的传输格式，可以为二进制流或者XML等形式。<br />
当服务器端使用socket协议时，可以用simple|thread-pool|threaded|nonblocking等方式运行，从而获得更好的性能。
</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.ooso.net/archives/537/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>php的filter扩展小技巧</title>
		<link>http://www.ooso.net/archives/559</link>
		<comments>http://www.ooso.net/archives/559#comments</comments>
		<pubDate>Fri, 30 Apr 2010 11:29:26 +0000</pubDate>
		<dc:creator>Volcano</dc:creator>
				<category><![CDATA[php]]></category>
		<category><![CDATA[yahoo]]></category>

		<guid isPermaLink="false">http://www.ooso.net/?p=559</guid>
		<description><![CDATA[做为一个合格的web开发人员，一定会牢记一个原则——永远不能相信用户输入的数据，行走江湖，安全第一是很重要的。用户通过表单或url传过来的数据，一定要仔细检查过了，才往后台数据库里存进去。在一个成熟的开发团队里，贯彻这个原则不成问题；但是如果在一个新人老手混搭的小team里，很容易就忽视了这个问题，那么各种安全漏洞比如跨站攻击，sql注入等等真是防不胜防。
实际上，用php 5自带的filter扩展能够较好的解决这个问题。我在从前的blog里记录了filter扩展的常规用法——直接利用filter来校验数据，这样有不少额外的代码量，所以我得介绍一个比较偷懒的办法——自动对所有输入变量进行过滤，这只需要对php.ini增加一行配置，然后重启apache或fastcgi让php配置生效。

				<span class="readmore"><a href="http://www.ooso.net/archives/559" title="php的filter扩展小技巧">阅读全文（868字）</a></span>]]></description>
			<content:encoded><![CDATA[<p>做为一个合格的web开发人员，一定会牢记一个原则——永远不能相信用户输入的数据，行走江湖，安全第一是很重要的。用户通过表单或url传过来的数据，一定要仔细检查过了，才往后台数据库里存进去。在一个成熟的开发团队里，贯彻这个原则不成问题；但是如果在一个新人老手混搭的小team里，很容易就忽视了这个问题，那么各种安全漏洞比如跨站攻击，sql注入等等真是防不胜防。</p>
<p>实际上，用php 5自带的filter扩展能够较好的解决这个问题。我在<a href="http://www.ooso.net/archives/204">从前的blog里记录了filter扩展的常规用法</a>——直接利用filter来校验数据，这样有不少额外的代码量，所以我得介绍一个比较偷懒的办法——自动对所有输入变量进行过滤，这只需要对php.ini增加一行配置，然后重启apache或fastcgi让php配置生效。</p>
<blockquote><p>filter.default=&#8221;special_chars&#8221;</p></blockquote>
<p>开启了这项配置后，会自动使用<a href="http://php.net/filter_input">filter_input</a>方法对$_GET, $_POST, $_COOKIE, $_REQUEST以及$_SERVER变量进行过滤转义。配置中special_chars是常量FILTER_SANITIZE_SPECIAL_CHARS的缩写，它能自动转义大部分危险字符例如： <strong>&#39;&quot;&lt;&gt;</strong>。而php手册对它的解释是：</p>
<blockquote><p>HTML-escape &#8216;&#8221;<>&#038; and characters with ASCII value less than 32, optionally strip or encode other special characters. </p></blockquote>
<p>在这个情况下，新人们写出这样的代码我也不会太担心:</p>
<pre><code>$foo = $_GET['foo'];
echo $foo;</code></pre>
<p>在部分场合，我们可能还是需要未转义的变量，比如某个ajax接受的参数是一段json串，用这段代码即可获得原始数据：</p>
<pre><code>$foo = filter_input (INPUT_GET, 'foo',  FILTER_UNSAFE_RAW);</code></pre>
<p>fitler扩展与yahoo使用的yiv如出一辙，印象里似乎就是yahoo对yiv做了些修改贡献给php社区，但是暂时没找到出处。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ooso.net/archives/559/feed</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
	</channel>
</rss>

