<?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>Soul Of Free Loop &#187; WordPress</title>
	<atom:link href="https://zohead.com/archives/category/wordpress/feed/" rel="self" type="application/rss+xml" />
	<link>https://zohead.com</link>
	<description>Uranus Zhou&#039;s Blog</description>
	<lastBuildDate>Sat, 19 Jul 2025 15:42:46 +0000</lastBuildDate>
	<language>zh-CN</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.8</generator>
	<item>
		<title>WordPress 3.8开启Google AMP的问题</title>
		<link>https://zohead.com/archives/wordpress-3-amp/</link>
		<comments>https://zohead.com/archives/wordpress-3-amp/#comments</comments>
		<pubDate>Tue, 01 Aug 2017 17:37:56 +0000</pubDate>
		<dc:creator><![CDATA[Uranus Zhou]]></dc:creator>
				<category><![CDATA[Google]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[AMP]]></category>
		<category><![CDATA[AMP for WP]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[qTranslate]]></category>
		<category><![CDATA[插件]]></category>

		<guid isPermaLink="false">https://zohead.com/?p=1487</guid>
		<description><![CDATA[关于 AMP Accelerated Mobile Pages（简称 AMP）是 Google 带领开发的开源项目，主要为了提升移动设备对网站的访问速度，大概包括 AMP HTML、AMP JS 和 AMP Cache 三部分，非常适合博客及新闻展示类的静态网站。 有关 AMP 的详细介绍可以参考其官方网站： https://www.ampproject.org/zh_cn/ AMP 网页只能使用 AMP HTML 中允许的有限的标签，不允许使用 AMP Runtime、AMP Components 之外的 JS，而且 AMP Runtime、Components 都必须从 cdn.amppr [&#8230;]]]></description>
				<content:encoded><![CDATA[<h2 id="about-amp">关于 AMP</h2>
<p><a href="https://en.wikipedia.org/wiki/Accelerated_Mobile_Pages" target="_blank">Accelerated Mobile Pages</a>（简称 AMP）是 Google 带领开发的开源项目，主要为了提升移动设备对网站的访问速度，大概包括 <strong>AMP HTML</strong>、<strong>AMP JS</strong> 和 <strong>AMP Cache</strong> 三部分，非常适合博客及新闻展示类的静态网站。</p>
<p>有关 AMP 的详细介绍可以参考其官方网站：</p>
<p><a href="https://www.ampproject.org/zh_cn/" target="_blank">https://www.ampproject.org/zh_cn/</a></p>
<p>AMP 网页只能使用 AMP HTML 中允许的有限的标签，不允许使用 AMP Runtime、AMP Components 之外的 JS，而且 AMP Runtime、Components 都必须从 <code>cdn.ampproject.org</code> 加载，因此目前 AMP 网页都必须在翻墙状态下才能正常浏览。</p>
<p>AMP Cache 是负责缓存并传输 AMP 页面的 CDN 服务器，用户在 Google 移动端中点击 AMP 网站时，实际访问的是缓存过的页面。</p>
<h2 id="wordpress-amp-problem">WordPress 启用 AMP 的问题</h2>
<p>WordPress 官方提供了 <a href="https://wordpress.org/plugins/amp/" target="_blank">AMP</a> 插件以支持直接为博客开启 AMP 加速，只是官方插件要求 WordPress 最低为 4.4 版本。</p>
<p>由于我的博客安装了 <a href="http://www.qianqin.de/qtranslate/" target="_blank">qTranslate</a> 这款多语言插件，而该插件却只支持到 WordPress 3.8.1 版本，如果升级 WordPress 到最新版本，qTranslate 插件就会自动禁用。然而 qTranslate 插件是对 WordPress 数据库直接进行修改的，禁用之后博客文章就可能会同时显示多种语言的内容，这样显然是不可接受的。</p>
<p>虽然网上已经有人继承 qTranslate 原作发布了例如 qTranslate X 之类的支持新版本 WordPress 的插件，但为了数据安全（其实是懒）考虑我暂时还是不打算直接升级 WordPress 了。</p>
<p>不过还好我在 WordPress 插件库里找到一款看起来支持 WordPress 3.8 的 AMP 插件：<a href="https://wordpress.org/plugins/accelerated-mobile-pages/" target="_blank">AMP for WP</a>，毕竟看此插件的介绍和评分都比官方的 AMP 插件要强哦，而且最低只要求 WordPress 3.0 版本。</p>
<p>AMP for WP 安装起来还是非常顺利的，插件选项里目前基本只提供了 Google Analytics UID 的设置选项，启用之后访问 AMP 版网站的方法是在地址后面加上 <code>?wpamp</code> 后缀。</p>
<p>不过我刚开始测试访问 AMP 首页和文章就碰到问题了，直接没有任何显示了，看网页源代码输出信息不全，显然是 AMP for WP 插件对老版本 WordPress 兼容性还是有点问题。</p>
<h2 id="mod-amp-for-wp">修改 AMP for WP</h2>
<p>首先修改 AMP for WP 插件的 <code>wp-amp-ninja/admin/common.php</code> 文件，打开 PHP 报错开关：</p>
<pre class="brush: php; title: wp-amp-ninja/admin/common.php; notranslate">
error_reporting(1);
</pre>
<p>这下访问博客首页和文章页面就能看到详细报错了：</p>
<pre class="brush: plain; title: ; notranslate">
Fatal error: Call to undefined function get_the_permalink() in /www/zohead.com/wp-content/plugins/wp-amp-ninja/includes/wpamp-front.php on line 24

Fatal error: Call to undefined function the_posts_pagination() in /www/zohead.com/wp-content/plugins/wp-amp-ninja/template/wpamp-content.php on line 53


Fatal error: Call to undefined function the_archive_title() in /www/zohead.com/wp-content/plugins/wp-amp-ninja/includes/wpamp-functions.php on line 600

Fatal error: Call to undefined function the_archive_description() in /www/zohead.com/wp-content/plugins/wp-amp-ninja/includes/wpamp-functions.php on line 601
</pre>
<p>经过查阅 WordPress 官方文档发现：</p>
<ol>
<li><a href="https://developer.wordpress.org/reference/functions/get_the_permalink/" target="_blank">get_the_permalink</a> 函数在 WordPress 3.9.0 版本开始引入，其实就是 1.0.0 版本就已经有的 <a href="https://developer.wordpress.org/reference/functions/get_permalink/" target="_blank">get_permalink</a> 函数；</li>
<li><a href="https://developer.wordpress.org/reference/functions/the_posts_pagination/" target="_blank">the_posts_pagination</a> 函数在 WordPress 4.1.0 版本开始引入，一同引入的还有 <code>the_posts_navigation</code> 函数，与 <code>get_the_permalink</code> 函数一样都位于 WordPress 代码库的 <code>wp-includes/link-template.php</code> 文件；</li>
<li>至于 <a href="https://developer.wordpress.org/reference/functions/the_archive_title/" target="_blank">the_archive_title</a> 和 <a href="https://developer.wordpress.org/reference/functions/the_archive_description" target="_blank">the_archive_description</a> 函数的功能比较类似，支持显示文章的标题和描述并在前后插入自定义代码，同样也在 WordPress 4.1.0 版本开始引入，位于 WordPress 代码库的 <code>wp-includes/general-template.php</code> 文件。</li>
</ol>
<p>由此可见，AMP for WP 实际上应该至少要求 WordPress 4.1.0 版本，只是作者并没有测试过是否兼容较低版本的 WordPress。</p>
<p>不过还好我看了下 WordPress 最新 4.8 版本的代码，上面缺少的几个 WordPress 内置函数都是功能比较独立的。</p>
<p>因此我稍微修改了一下博客目录下的 <code>link-template.php</code> 和 <code>general-template.php</code> 文件，将最新版本的 <code>get_the_permalink</code>、<code>the_posts_pagination</code>、<code>the_posts_navigation</code>、<code>the_archive_title</code>、<code>the_archive_description</code> 函数实现分别 Backport 到 WordPress 3.8 版本。Backport 完成之后再访问博客首页和文章，就没有 PHP 报错了。</p>
<p>不过初步试用下来，我还是发现 AMP for WP 插件的一些小问题：</p>
<ol>
<li>如果通过 qTranslate 插件访问博客的英文版本（通过增加 <code>?lang=en</code> 地址后缀），对应的 AMP 版页面地址会不正确，AMP for WP 插件在转换地址时并没有考虑地址中会带有其它后缀的情况；</li>
<li>AMP for WP 对于带有多种语言标题的文章直接显示数据库中多种语言合并在一起的标题效果，而并不是 qTranslate 插件根据客户端语言自动处理后的效果，这个问题在我使用的几个 WordPress 主题中都不会出现；</li>
<li>文章中插入的多行代码被合并成一行显示了，这是明显不能接受的；</li>
<li>文章的中文发表时间无法正确显示，统一显示为当前日期。</li>
</ol>
<p>第一个问题需要修改 AMP for WP 插件的 <code>wpamp-front.php</code>、<code>wpamp-functions.php</code>、<code>wpamp-header.php</code> 这几个文件中转换地址的代码，例如 <code>wpamp-front.php</code> 文件的修改：</p>
<pre class="brush: diff; title: wpamp-front.php; notranslate">
 		$the_permalink = get_the_permalink( $post-&gt;ID );
 	}
 	
-	$the_permalink = rtrim( $the_permalink, '/' ) . '/';
+	$the_permalink = rtrim( $the_permalink, '/' );
 	$perma = strpos( $the_permalink, &quot;?&quot; );
 	if ( $perma === false ) {
+		$the_permalink .= '/';
 		$sConnector = &quot;?&quot;;
 	} else {
 		$sConnector = &quot;&amp;&quot;;
</pre>
<p>第二个问题需要修改 <code>wpamp-content.php</code> 文件，文章标题要做 <code>apply_filters</code> 处理：</p>
<pre class="brush: diff; title: wpamp-content.php; notranslate">
                 &lt;div id=&quot;amp-pagination&quot;&gt;
                 	&lt;?php $prev_post = get_previous_post(); if (!empty( $prev_post )): ?&gt;
-                    	&lt;div class=&quot;prev&quot;&gt;&lt;a href=&quot;&lt;?php echo wp_amp_permalink($prev_post-&gt;ID, AMP_CONSTANT); ?&gt;&quot;&gt; &amp;laquo; &lt;?php echo $prev_post-&gt;post_title ?&gt;&lt;/a&gt;&lt;/div&gt;
+                    	&lt;div class=&quot;prev&quot;&gt;&lt;a href=&quot;&lt;?php echo wp_amp_permalink($prev_post-&gt;ID, AMP_CONSTANT); ?&gt;&quot;&gt; &amp;laquo; &lt;?php echo apply_filters( 'the_title', $prev_post-&gt;post_title, $prev_post-&gt;ID ); ?&gt;&lt;/a&gt;&lt;/div&gt;
 					&lt;?php endif ?&gt;
 					&lt;?php  $next_post = get_next_post(); if (!empty( $next_post )): ?&gt;
-                        &lt;div class=&quot;next&quot;&gt;&lt;a href=&quot;&lt;?php echo wp_amp_permalink($next_post-&gt;ID, AMP_CONSTANT); ?&gt;&quot;&gt;&lt;?php echo $next_post-&gt;post_title ?&gt; &amp;raquo; &lt;/a&gt;&lt;/div&gt;
+                        &lt;div class=&quot;next&quot;&gt;&lt;a href=&quot;&lt;?php echo wp_amp_permalink($next_post-&gt;ID, AMP_CONSTANT); ?&gt;&quot;&gt;&lt;?php echo apply_filters( 'the_title', $next_post-&gt;post_title, $next_post-&gt;ID ); ?&gt; &amp;raquo; &lt;/a&gt;&lt;/div&gt;
 					&lt;?php endif ?&gt;
                     &lt;div class=&quot;clearfix&quot;&gt;&lt;/div&gt;
                 &lt;/div&gt;
</pre>
<p>第三个问题就比较简单了，将 <code>simple_html_dom.php</code> 文件中替换回车和换行符的处理去掉就可以了。</p>
<p>第四个文章发表时间的问题也可以修改 <code>wpamp-content.php</code> 文件简化处理：</p>
<pre class="brush: diff; title: wpamp-content.php; notranslate">
                     &lt;?php endif; ?&gt;
                     By &lt;span class=&quot;amp-wp-author&quot;&gt;&lt;a href=&quot;&lt;?php echo wp_amp_permalink( NULL, AMP_CONSTANT, get_author_posts_url( get_the_author_meta( 'ID' ) ) ); ?&gt;&quot;&gt;&lt;?php echo esc_html( get_the_author() ); ?&gt;&lt;/a&gt;&lt;/span&gt;
-                    &lt;?php $the_time = date_i18n( get_option( 'date_format' ), strtotime( get_the_time('F jS, Y') ) ); ?&gt;
-                    on &lt;time datetime=&quot;&lt;?php echo $the_time; ?&gt;&quot;&gt;&lt;?php echo $the_time; ?&gt;&lt;/time&gt;
+                    on &lt;time datetime=&quot;&lt;?php echo get_the_date('c'); ?&gt;&quot;&gt;&lt;?php echo get_the_date('c'); ?&gt;&lt;/time&gt;
                 &lt;/li&gt;
</pre>
<p>另外我还对 AMP for WP 插件的页脚处理做了点小修改，将页脚上切换到博客首页桌面版本的链接改为切换到当前文章的桌面版本，方便访问者使用。</p>
<h2 id="summary">总结</h2>
<p>对 AMP for WP 插件修改完成之后就可以访问博客的 AMP 版进行验证了，例如我的博客的 AMP 版首页地址就是：</p>
<p><a href="https://zohead.com/?wpamp" target="_blank">https://zohead.com/?wpamp</a></p>
<p>普通用户可以通过安装 Google 推出的 <a href="https://chrome.google.com/webstore/detail/amp-validator/nmoffdblmcmgeicmolmhobpoocbbmknc" target="_blank">AMP Validator</a> 官方 Chrome 扩展检测所访问的 AMP 站点是否配置正确。</p>
<p>网站所有者可以用 Google 搜索的 AMP 在线测试工具进行检测：</p>
<p><a href="https://search.google.com/test/amp" target="_blank">https://search.google.com/test/amp</a></p>
<p>输入要测试的 AMP 版网址就可以开始检测，另外这个测试工具的另一个好处就是检测通过之后可以直接把你的 AMP 站点提交给 Google，让 Google 搜索蜘蛛尽快收录并进行 CDN 缓存。</p>
<p>现在通过 Google 移动端（例如 Android Chrome 浏览器）搜索我的博客，应该就能在搜索结果里看到下面的 AMP 闪电标志了：</p>
<p><img src="http://res.cloudinary.com/digwht2y0/image/upload/v1737371102/google-search-amp.jpg" alt="Google 搜索结果 AMP 标志" title="Google 搜索结果 AMP 标志"></p>
<p>点击搜索结果，你会发现访问的其实是 Google 缓存过的 AMP 地址，下面地址只有移动端浏览器才会显示 AMP 网页：</p>
<p><a href="https://www.google.com/amp/s/zohead.com/%3fwpamp" target="_blank">https://www.google.com/amp/s/zohead.com/%3fwpamp</a></p>
<p>初步启用 AMP 的大体感受就是如果你的梯子还可以，那访问 Google 缓存过的 AMP 网站速度还是非常快的，我这里估计访问 AMP 版网站所需要的流量大概为桌面版本的 1/3。</p>
<p>后面有时间的话还是希望能对 AMP for WP 插件继续改进，例如支持其它的 AMP 后缀或者使用专门的 AMP 子域名方便自己的服务器进行缓存之类的，最后祝大家玩的开心。</p>
]]></content:encoded>
			<wfw:commentRss>https://zohead.com/archives/wordpress-3-amp/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>PHP 7找回MySQL扩展解决WordPress问题</title>
		<link>https://zohead.com/archives/php7-mysql/</link>
		<comments>https://zohead.com/archives/php7-mysql/#comments</comments>
		<pubDate>Tue, 21 Feb 2017 14:38:03 +0000</pubDate>
		<dc:creator><![CDATA[Uranus Zhou]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[扩展]]></category>

		<guid isPermaLink="false">https://zohead.com/?p=1360</guid>
		<description><![CDATA[PHP 7 使用 MySQL 的问题 最近将 VPS 上的博客程序都迁移到 Bluemix 容器上之后，运行起来倒还算稳定，前两天手贱将 Bluemix 系统上的 LNMP 环境更新到了 1.3 版本，顺带地把 PHP 也更新到 7.0.7 版本了，不过更新完成之后访问博客就碰到了 WordPress 报错： 这才想起来 PHP 7 已经完全移除了 MySQL 扩展支持，通过 phpinfo 也能看到老的 mysql_ 系列的函数都不能使用了，一般建议使用新的 PHP mysqli 或者 pdo 扩展进行替换。 我的博客程序使用的还是 WordPress 3.6 版本，自然不支持 PHP 7， [&#8230;]]]></description>
				<content:encoded><![CDATA[<h2 id="php7-mysql-problem">PHP 7 使用 MySQL 的问题</h2>
<p>最近将 VPS 上的博客程序都<a href="https://zohead.com/archives/vps-anti-spider/">迁移</a>到 Bluemix 容器上之后，运行起来倒还算稳定，前两天手贱将 Bluemix 系统上的 <a href="https://lnmp.org/">LNMP</a> 环境更新到了 1.3 版本，顺带地把 PHP 也更新到 7.0.7 版本了，不过更新完成之后访问博客就碰到了 WordPress 报错：</p>
<pre class="brush: plain; title: ; notranslate">
您的 PHP 似乎没有安装运行 WordPress 所必需的 MySQL 扩展。
</pre>
<p>这才想起来 PHP 7 已经完全移除了 MySQL 扩展支持，通过 phpinfo 也能看到老的 <code>mysql_</code> 系列的函数都不能使用了，一般建议使用新的 PHP mysqli 或者 pdo 扩展进行替换。</p>
<p>我的博客程序使用的还是 WordPress 3.6 版本，自然不支持 PHP 7，如果直接升级 WordPress 的话又要考虑一堆 WordPress 插件的兼容性问题，于是像我这么懒的人就考虑如何把 PHP 7 的 MySQL 扩展找回来了。</p>
<h2 id="php7-mysql-ext">找回 PHP 7 的 MySQL 扩展</h2>
<p>由于 PHP 7 只是在发布前将对 MySQL 扩展的支持移除掉了，这样我们就可以检出遗留版本的支持 MySQL 扩展的 PHP 7 代码自行编译安装了，不过需要注意的就是 MySQL 扩展可是完全没有后续更新的了。</p>
<p>我们可以首先看看 LNMP 环境里 PHP 7 自带的扩展：</p>
<pre class="brush: bash; title: ; notranslate">
root@instance-007a20ff:/home/lnmp1.3/src/php-7.0.7/ext# ls
bcmath      date      ext_skel_win32.php  gmp        json      mysqlnd  pcre          pdo_odbc    pspell      simplexml  sqlite3   tokenizer  xsl
bz2         dba       fileinfo            hash       ldap      oci8     pdo           pdo_pgsql   readline    skeleton   standard  wddx       zip
calendar    dom       filter              iconv      libxml    odbc     pdo_dblib     pdo_sqlite  recode      snmp       sysvmsg   xml        zlib
com_dotnet  enchant   ftp                 imap       mbstring  opcache  pdo_firebird  pgsql       reflection  soap       sysvsem   xmlreader
ctype       exif      gd                  interbase  mcrypt    openssl  pdo_mysql     phar        session     sockets    sysvshm   xmlrpc
curl        ext_skel  gettext             intl       mysqli    pcntl    pdo_oci       posix       shmop       spl        tidy      xmlwriter
</pre>
<p>MySQL 扩展确实已经被移除了，我们可以直接在 <code>ext</code> 目录下检出老的 PHP MySQL 扩展代码：</p>
<pre class="brush: bash; title: ; notranslate">
root@instance-007a20ff:/home/lnmp1.3/src/php-7.0.7/ext# git clone https://github.com/php/pecl-database-mysql mysql --recursive
Cloning into 'mysql'...
remote: Counting objects: 145, done.
remote: Total 145 (delta 0), reused 0 (delta 0), pack-reused 145
Receiving objects: 100% (145/145), 88.41 KiB | 0 bytes/s, done.
Resolving deltas: 100% (65/65), done.
Checking connectivity... done.
</pre>
<p>使用 <code>phpize</code> 准备编译：</p>
<pre class="brush: bash; title: ; notranslate">
root@instance-007a20ff:/home/lnmp1.3/src/php-7.0.7/ext# cd mysql
root@instance-007a20ff:/home/lnmp1.3/src/php-7.0.7/ext/mysql# ls
config.m4  config.w32  CREDITS  LICENSE  mysql.mak  mysql_mysqlnd.h  package.xml  php_mysql.c  php_mysql.h  php_mysql_structs.h  README.md  tests
root@instance-007a20ff:/home/lnmp1.3/src/php-7.0.7/ext/mysql# /usr/local/php/bin/phpize
Configuring for:
PHP Api Version:         20151012
Zend Module Api No:      20151012
Zend Extension Api No:   320151012
root@instance-007a20ff:/home/lnmp1.3/src/php-7.0.7/ext/mysql# ./configure --with-php-config=/usr/local/php/bin/php-config
</pre>
<p>运行 <code>make</code> 编译之后 <code>make install</code> 确认 MySQL 扩展安装是否正确：</p>
<pre class="brush: bash; title: ; notranslate">
root@instance-007a20ff:/home/lnmp1.3/src/php-7.0.7/ext/mysql# make &amp;&amp; make install
root@instance-007a20ff:~# ls /usr/local/php/lib/php/extensions/no-debug-non-zts-20151012/
fileinfo.so  mysql.so  opcache.a  opcache.so
</pre>
<p>最后修改 <code>php.ini</code> 配置文件，增加一行：</p>
<pre class="brush: plain; title: ; notranslate">
extension = &quot;mysql.so&quot;
</pre>
<p>重新启动 LNMP 程序就能在 phpinfo 里看到 MySQL 扩展了：</p>
<p><img src="http://res.cloudinary.com/digwht2y0/image/upload/v1737442872/phpinfo-mysql.png" alt="PHP 7 下的 MySQL 扩展" title="PHP 7 下的 MySQL 扩展"></p>
<p>此时再访问 WordPress 博客就没有问题了，PHP 7 的问题初步搞定。另外网上也有人是直接把老的 MySQL 扩展静态编译进 PHP 7 程序中，这样用起来也还算比较方便的。当然后面我肯定还是要找机会直接升级 WordPress 了，毕竟 PHP 7 带着有各种漏洞的 WordPress 3.6 实在有点浪费哈，最后祝大家玩的开心。</p>
]]></content:encoded>
			<wfw:commentRss>https://zohead.com/archives/php7-mysql/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>考虑开启SRI防止七牛CDN HTTPS劫持</title>
		<link>https://zohead.com/archives/qiniu-https-tamper/</link>
		<comments>https://zohead.com/archives/qiniu-https-tamper/#comments</comments>
		<pubDate>Fri, 27 May 2016 14:48:28 +0000</pubDate>
		<dc:creator><![CDATA[Uranus Zhou]]></dc:creator>
				<category><![CDATA[HTTPS]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[CDN]]></category>
		<category><![CDATA[https]]></category>
		<category><![CDATA[SRI]]></category>
		<category><![CDATA[七牛]]></category>
		<category><![CDATA[云存储]]></category>
		<category><![CDATA[劫持]]></category>
		<category><![CDATA[证书]]></category>

		<guid isPermaLink="false">https://zohead.com/?p=1237</guid>
		<description><![CDATA[最近我在使用 Android 上的 Chrome 浏览器访问博客页面时发现一个奇怪的问题：博客页面底部有一个悬浮的叉，但又没有显示任何实际的内容。赶紧用 Chromebook 打开博客网页，将 User Agent 切换成 Android Chrome，这时可以看到网页里无端多了一个 iframe，该 iframe 地址为 http://dbcpm.com/locate_1/jiwei_MBpt.html，如下图所示： 由于我确定博客 VPS 后台并没有被入侵，因此初步估计是网页被万恶的运营商给劫持了，但又一想我的博客已经启用了全站 HTTPS，按说不会轻易遇到这种问题了。马上看看 Chrom [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>最近我在使用 Android 上的 Chrome 浏览器访问博客页面时发现一个奇怪的问题：博客页面底部有一个悬浮的叉，但又没有显示任何实际的内容。赶紧用 Chromebook 打开博客网页，将 User Agent 切换成 Android Chrome，这时可以看到网页里无端多了一个 iframe，该 iframe 地址为 <code>http://dbcpm.com/locate_1/jiwei_MBpt.html</code>，如下图所示：</p>
<p><img src="http://res.cloudinary.com/digwht2y0/image/upload/v1737442960/tampered-page.png" alt="博客被劫持效果" title=""></p>
<p>由于我确定博客 VPS 后台并没有被入侵，因此初步估计是网页被万恶的运营商给劫持了，但又一想我的博客已经启用了全站 HTTPS，按说不会轻易遇到这种问题了。马上看看 Chrome 浏览器上的地址栏标志，果然没有小绿锁了，浏览器控制台里也有 Mixed Content 报错：</p>
<p><img src="http://res.cloudinary.com/digwht2y0/image/upload/v1737442846/mixed-content-error.png" alt="Mixed Content 报错" title=""></p>
<p>可以看到浏览器拒绝加载 HTTP 的 JavaScript 文件，接着看看七牛 HTTPS 地址返回的数据是否正确：</p>
<p><img src="http://res.cloudinary.com/digwht2y0/image/upload/v1737442957/tampered-js.png" alt="七牛 CDN HTTPS 错误数据" title=""></p>
<p>这下立马发现返回的 JavaScript 代码不对了，开头是插入了 HTTP 形式的 JavaScript 文件地址，后面则看起来明显是广告一类的程序代码了。</p>
<p>难道是运营商做了 DNS 劫持导致我使用的七牛 CDN HTTPS 域名 <code>dn-zohead.qbox.me</code> 解析到了不正确的地址？如果是这样按说应该会出现 SSL 证书错误的，而且运营商只是为了插入广告代码而去搞 TLS 中间人攻击之类的感觉也不太合理。</p>
<p>考虑到另一种可能就是七牛 CDN 在从我的博客 VPS 地址回源的时候由于 DNS 污染之类的问题请求到了错误的数据，导致 HTTPS CDN 返回的数据也不对，这样还是登录到七牛后台管理，查看被劫持的 main.js 文件内容是否正确，下载下来对比却发现和我的博客源站内容是一致的，并没有被污染。</p>
<p>多次测试之后我发现如果再刷新页面七牛 HTTPS 劫持的问题可能又没了，而且在新标签页中打开被劫持的 HTTPS JavaScript 路径又能返回正确的数据了，这个时候通过 Chrome 调试工具看到的 HTTP 请求响应结果是这样的：</p>
<p><img src="http://res.cloudinary.com/digwht2y0/image/upload/v1737442862/normal-https-reponse.png" alt="正常七牛 CDN HTTPS 请求" title=""></p>
<p>而被劫持的 HTTP 请求响应结果则是：</p>
<p><img src="http://res.cloudinary.com/digwht2y0/image/upload/v1737442957/tampered-https-response.png" alt="被劫持的七牛 CDN HTTPS 请求" title=""></p>
<p>可以看到返回的 HTTP 头信息完全不同，而且多次刷新之后发现被劫持的 HTTPS 数据基本都来自 <code>211.142.22.13</code> 这台七牛的 CDN 服务器。查询之后发现这个 IP 地址是山西移动的（刚好我使用的是移动宽带），看起来只要浏览器是从 <code>211.142.22.13</code> 这台 CDN 服务器请求数据很可能得到的是被劫持的 JavaScript 代码，而如果七牛的 qbox.me 域名解析到的是其它 CDN 服务器地址则数据可能是正常的。</p>
<p>为了更好的重现这个问题，我们可以在 Linux 下先修改系统 hosts 文件使七牛的 qbox.me HTTPS 域名使用进行劫持操作的服务器，然后使用 wget 命令伪装 Android 移动设备以 HTTPS 地址从这台服务器请求 JavaScript 数据：</p>
<pre class="brush: bash; title: ; notranslate">
(trusty)zzm@localhost:~$ wget --referer=&quot;https://zohead.com/&quot; --user-agent=&quot;Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.114 Mobile Safari/537.36&quot; https://dn-zohead.qbox.me/test.js
--2016-05-27 00:30:37--  https://dn-zohead.qbox.me/test.js
Resolving dn-zohead.qbox.me (dn-zohead.qbox.me)... 211.142.22.13
Connecting to dn-zohead.qbox.me (dn-zohead.qbox.me)|211.142.22.13|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 2391 (2.3K) 1
Saving to: ‘test.js’

100%[===========================================================================================================&gt;] 2,391       --.-K/s   in 0.002s  

2016-05-27 00:30:38 (1.18 MB/s) - ‘test.js’ saved [2391/2391]
</pre>
<p>上面使用 wget 的 <code>--user-agent</code> 参数伪装 Android Chrome 浏览器，使用 <code>--referer</code> 参数伪装从我的博客源站发起请求，而 <code>test.js</code> 同样是一个实际不存在的 JavaScript 地址，我们可以看看返回的数据：</p>
<pre class="brush: bash; title: ; notranslate">
(trusty)zzm@localhost:~$ head test.js 
var osrc =&quot;http://dn-zohead.qbox.me/test.js&quot;;osrc+=(osrc.indexOf('?')&gt;0?'&amp;':'?')+'_t='+(new Date().getTime());document.write('&lt;script type=&quot;text/javascript&quot; src=&quot;'+osrc+'&quot;&gt;&lt;/'+'script&gt;');function withjQuery(callback){if(typeof(jQuery)==&quot;undefined&quot;){var script=document.createElement(&quot;script&quot;);scrip ......
</pre>
<p>很明显这下又得到了被篡改的数据，我们可以试试把 HTTPS 地址改成一个实际存在的 JavaScript 文件并多次运行，你会发现会有一定的概率返回被篡改的数据，有的时候也能返回正确的数据。</p>
<p>另外如果你去掉 <code>--user-agent</code> 参数或者 <code>--referer</code> 参数可能也能得到正确的数据或者正确的 404 报错（对于不存在的 JavaScript 地址），因此我想到可能是劫持方为了不让自己这种龌龊的行径被很容易的发现，而对劫持做了一些限制，如果是直接请求地址（不通过源站 referer 请求）或者通过 PC 端浏览器请求地址则基本上都返回正确的数据。</p>
<p>这下我就可以单独确认 <code>211.142.22.13</code> 这个地址到底是不是真正的七牛服务器了，我们可以修改系统 hosts 文件，例如将我的七牛 HTTPS 域名 <code>dn-zohead.qbox.me</code> 直接改为 <code>211.142.22.13</code> ，然后通过 Chrome 浏览器访问一个七牛服务器上不存在的 JavaScript 地址，确认 HTTPS 证书是否正确。</p>
<blockquote>
<p><strong>提示</strong></p>
<p>从上面 wget 命令的测试结果来看，劫持方可能做了 User Agent 和 Referer 的限制，因此直接访问地址可能并不能看到劫持效果。 <br />
  这就需要将 Chrome 浏览器 User Agent 改为 Android Chrome，另外可以考虑在控制台中输入命令在网页上创建一个链接，并点击链接实现 Referer 跳转的效果，例如：</p>
<pre class="brush: jscript; title: ; notranslate">
var aaa = document.createElement('a');
aaa.innerHTML = 'testlink';
aaa.href = 'https://dn-zohead.qbox.me/ccc8.js'; document.body.appendChild(aaa);
</pre>
</blockquote>
<p>先看看进行劫持操作的 <code>211.142.22.13</code> CDN 服务器的 HTTPS 证书：</p>
<p><img src="http://res.cloudinary.com/digwht2y0/image/upload/v1737442931/qiniu-tampered-https.png" alt="被劫持的七牛 CDN HTTPS 证书" title=""></p>
<p>看起来 SSL 服务器证书是正确的，而且从截图的内容也可以看到返回的 JavaScript 代码也明显是被篡改过的。</p>
<p>然后再修改 hosts 文件去掉添加的域名地址条目，重新访问同样不存在的 JavaScript 地址，以确认正确的七牛 CDN 服务器的 HTTPS 证书：</p>
<p><img src="http://res.cloudinary.com/digwht2y0/image/upload/v1737442931/qiniu-normal-https.png" alt="正常的七牛 CDN HTTPS 证书" title=""></p>
<p>可以发现正常的七牛 CDN 服务器对于不存在的文件是可以正确返回 Document not found 错误的，而进行劫持操作的 CDN 服务器则可能会返回篡改过的 JavaScript 代码，而最要命的是这两个服务器的 HTTPS 证书是完全一致的。</p>
<p>而我使用 HTTPS 访问博客时由于 Mixed Content 问题会导致博客页面时有些功能不正常，而且本该被篡改插入的广告反倒没显示出来，用 Android Chrome 浏览器以 HTTP 方式访问博客多次刷新之后可以看到被劫持插入页面的广告，按说也可以根据 CNZZ 统计代码追踪看看，不过这个就没太大兴趣了：</p>
<p><img src="http://res.cloudinary.com/digwht2y0/image/upload/v1737442931/qiniu-cdn-https-ad.png" alt="被劫持插入的广告" title=""></p>
<p>至此七牛 CDN HTTPS 劫持的问题基本可以明确了：</p>
<ul>
<li>重点针对 JavaScript 文件；</li>
<li>并不是七牛 CDN 上 DNS 污染而回源数据不正确导致；</li>
<li>并不是所有七牛 CDN 地址都会返回篡改的数据；</li>
<li>重点针对移动浏览器，移动网络环境下更加明显；</li>
<li>对劫持做了一定的限制，防止被轻易发现；</li>
<li>进行劫持操作的服务器使用的是正确的七牛 HTTPS 证书。</li>
</ul>
<p>至于这种恶意 CDN HTTPS 劫持到底是七牛内部人士所为，还是七牛的 HTTPS 证书泄漏被运营商利用，还需要进一步的确认。提交工单之后七牛客服人员的初步解释是：</p>
<ul>
<li>qbox.me 域名被大量客户使用比较不稳定，建议迁移到 HTTPS 自定义域名，而 HTTPS 自定义域名是收费的；</li>
<li>使用 qnssl.com HTTPS 自定义域名的话则有做回源的验证，并且节点相对较多，应该不会有劫持情况的发生。</li>
</ul>
<p>然而我查看了七牛 CDN 后台数据之后还是基本可以确认并没有回源数据被污染的情况，因此七牛给的答复并不能让我满意。</p>
<p>由此也可以看出在这片神奇的土地上，我们的网络环境除了要面临 GFW 这个几乎众所周知的阻碍在其它方面又到底是如何的恶劣，网站主们即使是开启了全站 HTTPS 也难以幸免。就算是七牛所有 CDN 服务器数据都是干净的，也不能保证网络运营商不在中间干点 DNS 污染、TLS 攻击之类的坏事。</p>
<p>如果要解决这种问题我初步想到的就是为博客开启 Subresource Integrity（SRI）安全检查功能，虽然目前支持 SRI 功能的浏览器（目前主要是 Chrome 和 Firefox）并不多，但其还是可以帮助 Web 开发者尽量避免各种网站数据可能被第三方篡改的情况。</p>
<p>SRI 的相关介绍可以参考（第二篇中文文章介绍的比较详细）：</p>
<ul>
<li><a href="https://www.srihash.org/">https://www.srihash.org/</a></li>
<li><a href="https://imququ.com/post/subresource-integrity.html">https://imququ.com/post/subresource-integrity.html</a></li>
</ul>
<p>由于 SRI 需要对网页中所有请求外部资源的地方进行修改，一个个手工通过 openssl 命令和修改网页来做实在比较麻烦。</p>
<p>对于 WordPress 博客已经有人实现了 SRI 资源管理的插件 <a href="https://wordpress.org/plugins/wp-sri/">Subresource Integrity (SRI) Manager</a>，该插件可以自动为 WordPress 博客中引用的资源添加 SRI SHA-256 校验值，这样可以减少博客被各种 HTTP、HTTPS 中间人劫持攻击的机率。不过目前还是准备先测试看看此插件稳定性如何，后续再考虑为博客整体开启 SRI 功能咯。</p>
]]></content:encoded>
			<wfw:commentRss>https://zohead.com/archives/qiniu-https-tamper/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>解决WordPress Batcache插件无法工作的问题</title>
		<link>https://zohead.com/archives/fix-wordpress-batcache/</link>
		<comments>https://zohead.com/archives/fix-wordpress-batcache/#comments</comments>
		<pubDate>Sat, 16 Nov 2013 16:26:26 +0000</pubDate>
		<dc:creator><![CDATA[Uranus Zhou]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[技术]]></category>
		<category><![CDATA[BAE]]></category>
		<category><![CDATA[Batcache]]></category>
		<category><![CDATA[cookie]]></category>
		<category><![CDATA[插件]]></category>

		<guid isPermaLink="false">http://zohead.com/?p=631</guid>
		<description><![CDATA[本文同步自（最佳显示效果请点击）：https://zohead.com/archives/fix-wordpress-batcache/ 前几天看到 AlexYang 同学写的一篇非常好的关于在百度 BAE 云平台上启用 WordPress 博客缓存全页面加速的文章，由于 BAE 云平台不支持本地文件读写，WP Super Cache 之类的 WordPress 本地缓存插件无法正常工作（也不支持 NFS 目录作为缓存目录哦），文章中使用基于 BAE cache 空间的 memcache 接口，并通过 Batcache 这个 WordPress 插件实现全页面加速，据说缓存加速效果非常明显。  [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>本文同步自（最佳显示效果请点击）：<a href="https://zohead.com/archives/fix-wordpress-batcache/" target="_blank">https://zohead.com/archives/fix-wordpress-batcache/</a></p>
<p>前几天看到 AlexYang 同学写的一篇非常好的关于在百度 BAE 云平台上启用 WordPress 博客缓存全页面加速的文章，由于 BAE 云平台不支持本地文件读写，WP Super Cache 之类的 WordPress 本地缓存插件无法正常工作（也不支持 NFS 目录作为缓存目录哦），文章中使用基于 BAE cache 空间的 memcache 接口，并通过 Batcache 这个 WordPress 插件实现全页面加速，据说缓存加速效果非常明显。</p>
<p>介绍缓存加速的文章请参考 [<a href="http://www.alexyang.me/2013/07/08/%E5%88%A9%E7%94%A8%E7%99%BE%E5%BA%A6%E4%BA%91%E7%BC%93%E5%AD%98%E5%8A%A0%E9%80%9Fbae-wordpress%E4%B9%8B%E7%BB%88%E6%9E%81%E5%8A%A0%E9%80%9F.html" target="_blank">这里</a>]，Batcache WordPress 插件可以点击 [<a href="http://wordpress.org/plugins/batcache/" target="_blank">这里</a>] 下载。</p>
<p>我按照上面文章中的介绍在 wp-content 目录中增加了 BAE 版本的 object-cache.php 文件和 Batcache 插件的 advanced-cache.php 文件，但在测试中发现始终没有看到作者所介绍的效果：首次访问站点之后缓存到内存，后续访问都会从缓存中读取，无需多余的数据库请求，网页 head 信息中始终没有 cache 的调试输出。</p>
<p>在参考 AlexYang 的文章做了多遍的检查之后，觉得一切条件都符合的，还无法正常缓存，只能看看 Batcache 的代码了。在 Batcache 代码中增加一堆调试信息，经过坑爹的调试过程（BAE 的应用日志查询功能简直是弱的让人无力吐槽的），终于发现真正原因：</p>
<p>Batcache 在判断页面请求时会检查当前请求所使用的 cookie，插件觉得某些情况下页面必须刷新，就忽略当前缓存的内容，例如：用户在文章下发表评论，这种情况下必须忽略之前的缓存，否则用户评论之后将无法看到自己评论的内容；还有一种情况就是管理员登录到后台了，这种情况下也必须禁用缓存，否则管理员对博客做的修改操作也将无法正常看到。</p>
<p>正是考虑到类似上面的情况，Batcache 在检测到一些 cookie 值时会禁用缓存，advanced-cache.php 中的判断代码如下：</p>
<p><pre class="brush: php; title: ; notranslate">
// Never batcache when cookies indicate a cache-exempt visitor.
if ( is_array( $_COOKIE) &amp;&amp; ! empty( $_COOKIE ) )
	foreach ( array_keys( $_COOKIE ) as $batcache-&gt;cookie )
		if ( $batcache-&gt;cookie != 'wordpress_test_cookie' &amp;&amp; 
			( substr( $batcache-&gt;cookie, 0, 2 ) == 'wp' || substr( $batcache-&gt;cookie, 0, 9 ) == 'wordpress' || substr( $batcache-&gt;cookie, 0, 14 ) == 'comment_author' ) )
			return;
</pre>
</p>
<p>这就表示 Batcache 发现如果请求中的 cookie 是以 wp、wordpress 或者 comment_author 开头时就禁用缓存，这样后台管理、用户评论等功能才能正常工作。</p>
<p>而通过对我访问博客时的数据进行抓包显示，由于我安装了 WordPress Mobile Pack 这个插件，访问博客时会向浏览器发送切换浏览类型的 wpmp_switcher cookie，这就刚好在 Batcache 插件的过滤范围内，当然就导致 Batcache 全页面缓存始终无法起作用。知道原因了就好办，将 wp-content 目录下的 advanced-cache.php 的判断 cookie 处改为：</p>
<p><pre class="brush: php; title: ; notranslate">
// Never batcache when cookies indicate a cache-exempt visitor.
if ( is_array( $_COOKIE) &amp;&amp; ! empty( $_COOKIE ) )
	foreach ( array_keys( $_COOKIE ) as $batcache-&gt;cookie )
		if ( $batcache-&gt;cookie != 'wordpress_test_cookie' &amp;&amp; $batcache-&gt;cookie != 'wpmp_switcher' &amp;&amp; substr( $batcache-&gt;cookie, 0, 12 ) != 'wp-settings-' &amp;&amp; 
			( substr( $batcache-&gt;cookie, 0, 2 ) == 'wp' || substr( $batcache-&gt;cookie, 0, 9 ) == 'wordpress' || substr( $batcache-&gt;cookie, 0, 14 ) == 'comment_author' ) )
			return;
</pre>
</p>
<p>刷新页面就可以看到缓存起作用了，不得不说启用内存缓存之后，页面访问速度还是有不少提升了。</p>
<p>备注：上面的修改代码中另外还增加了 wp-settings- 开头的 cookie 项，因为测试时发现有时还会有这个 cookie 导致缓存不起作用。</p>
<p>网上有不少的网友说装了 Batcache 插件之后缓存没用，可以参考这个思路看看到底是什么 cookie 之类的条件不满足导致的。本文章为个人修改经验，如果有任何问题欢迎提出指正，玩的开心 ^_^</p>
]]></content:encoded>
			<wfw:commentRss>https://zohead.com/archives/fix-wordpress-batcache/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>WordPress友言近期评论Widget更新（v1.1）</title>
		<link>https://zohead.com/archives/wordpress-uyan-recent-comment-widget-v1-1/</link>
		<comments>https://zohead.com/archives/wordpress-uyan-recent-comment-widget-v1-1/#comments</comments>
		<pubDate>Sat, 12 May 2012 11:38:27 +0000</pubDate>
		<dc:creator><![CDATA[Uranus Zhou]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[技术]]></category>
		<category><![CDATA[友言]]></category>
		<category><![CDATA[小工具]]></category>
		<category><![CDATA[编程]]></category>
		<category><![CDATA[评论]]></category>

		<guid isPermaLink="false">http://zohead.com/?p=152</guid>
		<description><![CDATA[本文同步自（如浏览不正常请点击跳转）：https://zohead.com/archives/wordpress-uyan-recent-comment-widget-v1-1 前两天写了一个友言近期评论的 WordPress Widget，初步测试还能用，但多次进行刷新，会出现不能正常登录之类的问题（Failed to authentication with uyan.cc、Invalid comments data from uyan.cc 之类的报错），而且原来每次都需要登录友言的后台管理严重影响速度，我也比较怕怕这样不断发请求会导致友言把我的脚本和博客给封掉，嘿嘿。 由于友言没有公开  [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>本文同步自（如浏览不正常请点击跳转）：<a href="https://zohead.com/archives/wordpress-uyan-recent-comment-widget-v1-1" target="_blank">https://zohead.com/archives/wordpress-uyan-recent-comment-widget-v1-1</a></p>
<p>前两天写了一个友言近期评论的 WordPress Widget，初步测试还能用，但多次进行刷新，会出现不能正常登录之类的问题（Failed to authentication with uyan.cc、Invalid comments data from uyan.cc 之类的报错），而且原来每次都需要登录友言的后台管理严重影响速度，我也比较怕怕这样不断发请求会导致友言把我的脚本和博客给封掉，嘿嘿。</p>
<p>由于友言没有公开 API 给我等码农来调用，因此今天又花了点时间做了一些改进，弄了个 1.1 版本，原介绍文章在这：</p>
<p><a href="https://zohead.com/archives/wordpress-uyan-recent-comment-widget/" target="_blank">https://zohead.com/archives/wordpress-uyan-recent-comment-widget/</a></p>
<p><strong><span style="color: #ff0000;">1.1版本更新说明：</span></strong></p>
<p><em>1、登录友言后台管理，得到近期评论等地方增加错误处理，如果服务端返回的 JSON 数据不对则报错</em><br />
<em> 2、减少 PHP 本身的 error message 输出</em><br />
<em> 3、将得到近期评论的功能分离为一个函数单独调用</em><br />
<em> 4、登录成功之后保存得到的 cookies 到同目录下的 uyan_cookie.php 文件中方便下次直接使用，而无需再重复登录，如果 cookie 过期下次获取评论时失败则再重新登录</em><br />
<em> 5、发查询近期评论请求时增加友言本身的管理地址作为 referer</em></p>
<p>此次增加了一个 uyan_cookie.php 文件用于保存 cookie，从下面的链接下载解压缩之后，请将此文件也上传到同一目录中（不上传的话 PHP 可能会报 require_once 出错），此文件默认为空，详细代码就不贴了，直接在下面下载查看吧。友言 的登录邮箱、密码、域名之类的修改请参考原始的介绍文章了。</p>
<p>这个是 1.1 版本的下载地址：</p>
<p><a href="http://miseal.googlecode.com/files/uyan_comments_v1.1.zip" target="_blank">http://miseal.googlecode.com/files/uyan_comments_v1.1.zip</a></p>
<p>当前的通过临时文件保存 cookie 方式应该还有改进空间，有任何问题欢迎指正咯 ^_^</p>
]]></content:encoded>
			<wfw:commentRss>https://zohead.com/archives/wordpress-uyan-recent-comment-widget-v1-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP实现WordPress友言近期评论Widget</title>
		<link>https://zohead.com/archives/wordpress-uyan-recent-comment-widget/</link>
		<comments>https://zohead.com/archives/wordpress-uyan-recent-comment-widget/#comments</comments>
		<pubDate>Fri, 11 May 2012 16:16:35 +0000</pubDate>
		<dc:creator><![CDATA[Uranus Zhou]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[技术]]></category>
		<category><![CDATA[post-to-host]]></category>
		<category><![CDATA[友言]]></category>
		<category><![CDATA[小工具]]></category>
		<category><![CDATA[社交网络]]></category>
		<category><![CDATA[编程]]></category>
		<category><![CDATA[评论]]></category>

		<guid isPermaLink="false">http://zohead.com/?p=120</guid>
		<description><![CDATA[本文同步自（如浏览不正常请点击跳转）：https://zohead.com/archives/wordpress-uyan-recent-comment-widget/ 现在有很多人都使用 WordPress 来搭建自己的博客系统，其中有一些是像我这样使用 友言 这个社交评论插件来替代系统原始的评论框的，友言 评论框插件对一些主流的社交网站支持比较好，很是推荐，友言官网： http://uyan.cc/ 之前我写过一个修改 友言 插件实现完美与 WordPress Mobile Pack 插件配合实现移动版博客的文章，在这里仅供参考： https://zohead.com/archives/m [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>本文同步自（如浏览不正常请点击跳转）：<a href="https://zohead.com/archives/wordpress-uyan-recent-comment-widget/" target="_blank">https://zohead.com/archives/wordpress-uyan-recent-comment-widget/</a></p>
<p>现在有很多人都使用 WordPress 来搭建自己的博客系统，其中有一些是像我这样使用 友言 这个社交评论插件来替代系统原始的评论框的，友言 评论框插件对一些主流的社交网站支持比较好，很是推荐，友言官网：</p>
<p><a href="http://uyan.cc/" target="_blank">http://uyan.cc/</a></p>
<p>之前我写过一个修改 友言 插件实现完美与 WordPress Mobile Pack 插件配合实现移动版博客的文章，在这里仅供参考：</p>
<p><a href="https://zohead.com/archives/modify-plugin-wordpress-mobile-pack/" target="_blank">https://zohead.com/archives/modify-plugin-wordpress-mobile-pack/</a></p>
<p>但现在发现还是有一点不足，由于使用了友言评论框替代 WordPress 本身的，导致 WordPress 的 ”近期评论“ Widget（小工具）显示不了，因此小折腾一个晚上，靠着还依稀记得的 PHP 编程经历，写了一个简单的显示 友言 近期评论的 WordPress Widget，先看效果图（本博客右侧就有 ^_^）：</p>
<p><a href="http://zohead.com/wp-content/uploads/wordpress-uyan-recent-comment-widget.png" target="_blank"><img src="http://zohead.com/wp-content/uploads/wordpress-uyan-recent-comment-widget.png" alt="友言近期评论Widget效果图" width="228" height="152" /></a></p>
<p><span style="color: #f00;"><strong>原理及代码：<br />
</strong></span></p>
<p>实现原理比较简单，先用工具分析 友言 评论的后台登录和评论显示之类的 HTTP 包信息，然后用 PHP 的 fsockopen 来自己发送 GET、POST 请求实现在 WordPress 上列举显示已经存在的友言评论（<span style="color: #006400;">备注：默认只显示已经经过审核的评论</span>）。</p>
<p>由于中间有几步 GET 和 POST 请求，就找了个现成的 <strong>post-to-host</strong> 这个很小的 PHP 脚本来发 GET 和 POST 请求，下载地址：</p>
<p><a href="http://code.google.com/p/post-to-host/" target="_blank">http://code.google.com/p/post-to-host/</a></p>
<p>下面是主程序 <span style="color: #006400;"><strong>uyan_comments.php</strong></span> 的代码：</p>
<pre class="brush: php; highlight: [3,4,5,6,8,13,36,40,72]; title: uyan_comments.php; notranslate">
&lt;?php
// global site information
$email = &quot;xxxx login email xxxx&quot;;
$password = &quot;xxxx encrypted password xxxx&quot;;
$domain = &quot;xxxx domain name xxxx&quot;;
$maxcomments = 10;

require_once(&quot;post_to_host.php&quot;);

header(&quot;Content-Type:text/html; charset=utf-8&quot;);

// Login to uyan.cc
$url = &quot;http://uyan.cc/index.php/youyan_login/userAutoLoginCrossDomain?email=&quot; . $email . &quot;&amp;loginPassword=&quot; . $password . &quot;&amp;rem=1&amp;domain=&quot; . $domain;

$ret_str = post_to_host($url, array(), array(), &quot;&quot;, $ret_head, 0);
$ret_str = trim($ret_str, &quot;()&quot;);

if ($ret_str == null || $ret_str == 'noData' || $ret_str == '&quot;noData&quot;') {
	echo(&quot;Failed to authentication with uyan.cc&quot;);
	return;
}

$ret_json = json_decode($ret_str, true);

// check response JSON data
if (!array_key_exists('uid', $ret_json) || !array_key_exists('uname', $ret_json)) {
	echo(&quot;Invalid data from uyan.cc&quot;);
	return;
}

// delete unneeded 'auth' cookie key
$arr_cookie = get_cookies_from_heads($ret_head);
unset($arr_cookie['auth']);

// need this to set uid and uname
$url = &quot;http://uyan.cc/setting?uid=&quot; . $ret_json['uid'] . &quot;&amp;domain=&quot; . $domain . &quot;&amp;uname=&quot; . $ret_json['uname'];
$ret_str = post_to_host($url, array(), $arr_cookie, &quot;&quot;, $ret_head, 0);

// get comment
$url = &quot;http://uyan.cc/youyan_admin/getMoreCommentsByDomain/0&quot;;
$get_comment_params = array('currentMore' =&gt; '0', 'normalCommentToogle' =&gt; '1', 'readyCommentToogle' =&gt; '0', 'trashCommentToogle' =&gt; '0', 'delCommentToogle' =&gt; '0');

$ret_str = post_to_host($url, $get_comment_params, $arr_cookie, &quot;&quot;, $ret_head);

$comment_json = json_decode($ret_str, true);
$nr_comments = 0;

echo(&quot;&lt;ul&gt;&quot;);

foreach ($comment_json as $comment) {
	$display_name = &quot;&quot;;
	$display_title = &quot;&quot;;

	if ($maxcomments &gt;= 0 &amp;&amp; $nr_comments &gt;= $maxcomments) break;

	// must with valid URL and page title
	if (!array_key_exists('page_url', $comment) || !array_key_exists('page_title', $comment) || strlen($comment['page_url']) &lt;= 0 || strlen($comment['page_title']) &lt;= 0)
		continue;

	// must with a valid display name
	if (array_key_exists('comment_author', $comment) &amp;&amp; strlen($comment['comment_author']) &gt; 0)
		$display_name = $comment['comment_author'];
	else if (array_key_exists('show_name', $comment) &amp;&amp; strlen($comment['show_name']) &gt; 0)
		$display_name = $comment['show_name'];
	else
		continue;

	$display_title = $comment['page_title'];
	$pos = strpos($display_title, ' | ');
	if ($pos &gt;= 0) $display_title = substr($display_title, 0, $pos);

	echo('&lt;li&gt;' . $display_name . '&amp;nbsp;&lt;strong&gt;&lt;font color=&quot;#0000FF&quot;&gt;&amp;gt;&amp;gt;&lt;/font&gt;&lt;/strong&gt;&amp;nbsp;&lt;a href=&quot;' . $comment['page_url'] . '&quot;&gt;' . $display_title . '&lt;/a&gt;&lt;/li&gt;');

	$nr_comments++;
}

echo(&quot;&lt;/ul&gt;&quot;);
?&gt;
</pre>
<p>代码本身比较简单，有些 PHP 基础就可以看懂了，把 <span style="color: #006400;"><strong>uyan_comments.php</strong></span> 文件最上面的 <span style="color: #006400;"><strong>$email</strong></span>、<span style="color: #006400;"><strong>$password</strong></span>、<span style="color: #006400;"><strong>$domain</strong></span>、<span style="color: #006400;"><strong>$maxcomments</strong></span> 改为实际的 友言 后台管理的登录邮箱、密码、你的域名、显示的最多评论数（备注：默认为10条，如果改为小于0的值则不限制显示的评论条数），就可以使用了。你应该已经发现这个 <span style="color: #006400;"><strong>uyan_comments.php</strong></span> 其实和 WordPress 没太大关系，完全也可以直接单独使用。</p>
<p>需要注意的是为了避免使用明文密码而可能导致的问题（安全第一 ^_^），上面的 <span style="color: #006400;"><strong>$password</strong></span> 是 友言 后台管理时实际用到的加密过的密码。这个加密过的密码可以通过 Firefox 的 Live HTTP headers 插件之类的抓取 HTTP 协议头的插件或工具来得到。</p>
<p><span style="color: #f00;"><strong>得到友言的加密登录密码：</strong></span></p>
<p>下面以 Firefox 的 Live HTTP headers 插件为例说明如何得到 友言 的实际加密的密码，打开 Live HTTP headers，该插件会自动开始抓取，然后用正确的邮箱和密码登录 友言 的后台管理，停止 Live HTTP headers 的抓取，在输出里就能找到地址为如下格式的 GET 请求，请求参数中就有加密的密码：</p>
<p><strong>http://uyan.cc/index.php/youyan_login/userAutoLoginCrossDomain?callback=jsonpxxxxxxx&amp;email=xxxxx@xxxxx.com&amp;loginPassword=<span style="color: #b22222;">xxxxxxxxxxxxxxxxx</span>&amp;rem=1&amp;domain=xxx.com<br />
</strong></p>
<p>其中的 <span style="color: #006400;"><strong>email</strong></span> 段就是登录邮箱，<span style="color: #006400;"><strong>loginPassword</strong></span> 段即为加密的密码，保存下该密码，修改 <span style="color: #006400;"><strong>uyan_comments.php</strong></span> 文件中的 <span style="color: #006400;"><strong>$email</strong></span> 和 <span style="color: #006400;"><strong>$password</strong></span> 值。</p>
<p>Live HTTP headers 的抓取截图如下所示（后面的未显示完整）：</p>
<p><a href="http://zohead.com/wp-content/uploads/uyan-login-http-headers.png" target="_blank"><img src="http://zohead.com/wp-content/uploads/uyan-login-http-headers.png" alt="友言后台管理的登录HTTP包" width="588" height="478" /></a></p>
<p><span style="color: #f00;"><strong>如何加入 WordPress Widget 列表中：</strong></span></p>
<p>你如果有真正实现一个 WordPress Widget 的心思，可以用本代码加上 WordPress 的 register_widget 之类的接口来实现。无奈我是一个超级懒人，懒人就有懒人的办法，下面介绍的就是懒人的办法，哈哈。</p>
<p>首先下载本文最下面下载链接中的 <span style="color: #006400;"><strong>post_to_host.php</strong></span> 和 <span style="color: #006400;"><strong>uyan_comments.php</strong></span>，将 <span style="color: #006400;"><strong>uyan_comments.php</strong></span> 中对应的 登录邮箱、密码、域名 改掉（参考上面），将这两个文件上传到 WordPress 根目录中（位置也可以自己修改），然后给 WordPress 安装 <strong>PHP Code Widget</strong> 插件，这是一个通用 Widget，添加之后，可以自行添加 文本、HTML、PHP 代码等，比较方便，插件地址：</p>
<p><a href="http://wordpress.org/extend/plugins/php-code-widget/" target="_blank">http://wordpress.org/extend/plugins/php-code-widget/</a></p>
<p>安装之后，在 WordPress 管理后台的 外观 - 小工具 里就能看到名为 “PHP Code”  的小工具，将其托至右侧的 “第一小工具区域”，输入自定义的标题，然后加入以下代码保存即可（如果上传的位置不在 WordPress 根目录那请自行修改）：</p>
<pre class="brush: php; highlight: [2]; title: 小工具的PHP代码; notranslate">
&lt;?php
include_once(&quot;uyan_comments.php&quot;);
?&gt;
</pre>
<p>重新访问 WordPress，如果上面的 登录邮箱、密码、域名 设定都正确的话，应该就可以出现类似上面效果图的评论列表。</p>
<p><span style="color: #f00;"><strong>不足和改进：</strong></span></p>
<p>1、uyan_comments.php 每次访问时都需要登录 友言 管理后台，请求评论列表，因此速度会有些影响，这个有空再改进了。</p>
<p>2、由于需要在 Web服务器中使用 PHP 的 fsockopen 来发 GET、POST 请求得到评论列表，因此可能对 WordPress 博客的访问速度造成一些影响，如果 PHP 空间在国内还可以，像我这样空间在国外的就稍微悲剧点了，所以建议安装 WP Super Cache WordPress 之类的插件来实现更好的缓存加速，将影响尽量降低。</p>
<p><span style="color: #f00;"><strong>下载地址（115网盘）：</strong></span></p>
<p><a href="http://115.com/file/beezjk3b" target="_blank">http://115.com/file/beezjk3b</a></p>
<p>写博客好累，准备休息，HOHO，本文件为个人作品，有任何问题欢迎指正。 ^_^</p>
]]></content:encoded>
			<wfw:commentRss>https://zohead.com/archives/wordpress-uyan-recent-comment-widget/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>修改 WordPress 插件配合 WordPress Mobile Pack 实现移动版博客</title>
		<link>https://zohead.com/archives/modify-plugin-wordpress-mobile-pack/</link>
		<comments>https://zohead.com/archives/modify-plugin-wordpress-mobile-pack/#comments</comments>
		<pubDate>Wed, 08 Feb 2012 06:16:41 +0000</pubDate>
		<dc:creator><![CDATA[Uranus Zhou]]></dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[WordPress Mobile Pack]]></category>
		<category><![CDATA[友言]]></category>
		<category><![CDATA[插件]]></category>
		<category><![CDATA[移动版]]></category>

		<guid isPermaLink="false">http://zohead.com/?p=19</guid>
		<description><![CDATA[WordPress Mobile Pack 是一款相当不错的 WordPress 移动版本转换插件，安装启用之后，可以快速生成适合手机访问的移动版本 WordPress 博客，插件安装地址如下： &#160; http://wordpress.org/extend/plugins/wordpress-mobile-pack/ &#160; 可以在 WordPress 后台配置中搜索 WordPress Mobile Pack 或者手工下载安装包进行安装。 &#160; 实际使用，在 WordPress 本身插件比较少的情况下，WordPress Mobile Pack 在手机上效果很不错，但安 [&#8230;]]]></description>
				<content:encoded><![CDATA[<div>WordPress Mobile Pack 是一款相当不错的 WordPress 移动版本转换插件，安装启用之后，可以快速生成适合手机访问的移动版本 WordPress 博客，插件安装地址如下：</div>
<div>&nbsp;</div>
<div><a href="http://wordpress.org/extend/plugins/wordpress-mobile-pack/">http://wordpress.org/extend/plugins/wordpress-mobile-pack/<br />
	</a></div>
<div>&nbsp;</div>
<div>可以在 WordPress 后台配置中搜索 WordPress Mobile Pack 或者手工下载安装包进行安装。</div>
<div>&nbsp;</div>
<div>实际使用，在 WordPress 本身插件比较少的情况下，WordPress Mobile Pack 在手机上效果很不错，但安装了一些额外的插件之后，这些插件的代码也在移动版本中显示出来，这样会明显影响移动设备上的显示效果，而且会花费比较多的流量。</div>
<div>&nbsp;</div>
<div>下面以实际经历介绍如何修改 WordPress 插件实现与 WordPress Mobile Pack 的完美配合，以社交评论插件 友言 为例。</div>
<div>&nbsp;</div>
<div>友言是一款很适合当前社交应用的 WordPress 评论插件，访问博客的用户可以使用社交网站用户连接并进行评论，而且可以和 WordPress 本身的评论进行同步，官方网站：</div>
<div>&nbsp;</div>
<div><a href="http://www.uyan.cc/">http://www.uyan.cc/<br />
	</a></div>
<div>&nbsp;</div>
<div>同时安装了 友言 和 WordPress Mobile Pack 插件，先看看在桌面浏览器上的文章显示效果：</div>
<div>&nbsp;</div>
<div><a href="http://zohead.com/image.php?file=wp-content/uploads/2012/02/wordpress-uyan-comment-desktop-interface.jpg"><img alt="" border="1" height="220" src="http://zohead.com/image.php?file=wp-content/uploads/2012/02/wordpress-uyan-comment-desktop-interface.jpg" width="336" /></a></div>
<div>&nbsp;</div>
<div>这种效果在桌面浏览器上是比较好的，但在移动浏览器是有点不能接受的，过于复杂而且耗费很多流量。</div>
<div>&nbsp;</div>
<div>WordPress Mobile Pack 会自动去除页面上的脚本等不适合移动设备显示的东西，但友言的评论框可能由于内嵌的原因，不能自动去除，而且如果直接去除的话，在移动设备中就会出现不能评论文章的问题，因此我们可以修改 友言 的插件代码，在判断 WordPress Mobile Pack 插件已经加载并且当前使用的移动版本的 WordPress 时就自动不加载 友言 的评论框，转而使用 WordPress 标准的评论框（可以同步到 友言 评论）。</div>
<div>&nbsp;</div>
<div>简单查看 友言 和 WordPress Mobile Pack 的源代码之后，做出以下修改就可以达到移动设备上的完美显示：</div>
<div>&nbsp;</div>
<div>修改 WordPress 安装目录下 wp-content/plugins/youyan-social-comment-system/uyan_plugin.php 文件，将</div>
<div>&nbsp;</div>
<div style="border: 1px solid rgb(12, 76, 122);"><span style="color:#0000cd;"><strong>add_filter(&#39;comments_template&#39;, &#39;uyan_comment&#39;);<br />
	</strong></span></div>
<div>&nbsp;</div>
<div>改为：</div>
<div>&nbsp;</div>
<div style="border: 1px solid rgb(12, 76, 122);"><span style="color:#800080;"><strong>if (!function_exists(&#39;wpmp_switcher_outcome&#39;) || wpmp_switcher_outcome() == <br />
	&nbsp;&nbsp;&nbsp; WPMP_SWITCHER_DESKTOP_PAGE) {<br />
	&nbsp;&nbsp;&nbsp; add_filter(&#39;comments_template&#39;, &#39;uyan_comment&#39;);<br />
	}<br />
	</strong></span></div>
<div>&nbsp;</div>
<div>通过 WordPress Mobile Pack 插件中的 wpmp_switcher_outcome 函数判断当前使用的移动版本还是桌面版本。</div>
<div>&nbsp;</div>
<div>更改之后，需要禁用并重新启用 WordPress Mobile Pack 插件才能起作用，然后在移动设备浏览器中查看，下面是在我的 android 手机上的效果，非常清爽，而且用的流量也很少：</div>
<div>&nbsp;</div>
<div><a href="http://zohead.com/image.php?file=wp-content/uploads/2012/02/wordpress-org-comment-mobile-interface.jpg"><img alt="" border="1" height="320" src="http://zohead.com/image.php?file=wp-content/uploads/2012/02/wordpress-org-comment-mobile-interface.jpg" width="192" /></a></div>
<div>&nbsp;</div>
<div>如果还有其它的 WordPress 也可以采取类似的方法在需要显示的地方进行修改，已经测试过 多说 插件通过这种方法修改也可以。</div>
<div>&nbsp;</div>
<div>PS：</div>
<div>1、友言 插件相对于 多说 等其它社交评论插件来说，对服务器的要求要低一些，但如果 PHP 的 cURL 等功能如果未启用，可能会出现一些错误；</div>
<div>&nbsp;</div>
<div>2、WordPress Mobile Pack 的默认配置中启用了移动图像裁剪，在 PHP 不支持 GD 等库的情况下，会出现错误，造成移动设备上图片显示不了，如果遇到这种情况，可以关闭 WordPress Mobile Pack 的图像裁剪功能；</div>
<div>&nbsp;</div>
<div>3、Android、iPhone等智能机设备上如果需要对 WordPress 站点进行管理，可以安装 WordPress for Android 等软件，通过这些 App 管理效果更好。</div>
]]></content:encoded>
			<wfw:commentRss>https://zohead.com/archives/modify-plugin-wordpress-mobile-pack/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
