<?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>JeffHung.Blog &#187; Blogging</title>
	<atom:link href="http://www.jeffhung.net/blog/categories/blogging/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.jeffhung.net/blog</link>
	<description>(My smile insists of having nose. :-)</description>
	<lastBuildDate>Thu, 24 Nov 2011 07:25:31 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.2-alpha</generator>
		<item>
		<title>雜草叢生，換個 captcha 試試</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/3124/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/3124/#comments</comments>
		<pubDate>Fri, 26 Nov 2010 04:47:31 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[Blogging]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/?p=3124</guid>
		<description><![CDATA[有人在念，說我好久沒寫文章，所以... ]]></description>
			<content:encoded><![CDATA[<p>這裡雜草叢生，一堆 spam comments，清都清不完，看了就煩，所以好久都沒新文章，每次一進後台，心裡一厭煩，就直接關掉 browser 了。XD</p>
<p>可是有人在念，說我好久沒寫文章，所以就先換個 captcha 機制試試囉。這個新的 captcha 機制蠻有趣的，大家試試囉。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/3124/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>重新翻修 theme 的內裡</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/1092/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/1092/#comments</comments>
		<pubDate>Sat, 15 Mar 2008 13:19:36 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[Blogging]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/articles/jeffhung/1092/</guid>
		<description><![CDATA[這幾天心情不好，就把我的 blog 的皮脫光光，然後亂換 theme 玩弄之。之前的 theme 有以下幾個問題…]]></description>
			<content:encoded><![CDATA[<p>啊～我越來越喜歡自己的 blog 了。</p>
<p>這幾天心情不好，就把我的 blog 的皮脫光光，然後亂換 theme 玩弄之。之前的 theme 有以下幾個問題：</p>
<ul>
<li>在 firefox 下列印，會讓 firefox 當掉。後來單獨測試 sandbox 原始官方版，也會讓 firefox 當掉。</li>
<li>因為本人糟糕的 css 功力，只懂得照 manual 操課，不曉得怎麼迴避 IE 的 bug，所以畫面在 IE 上看來，非常地糟糕。</li>
</ul>
<p><a href="http://www.jeffhung.net/blog/articles/jeffhung/668/">我對 theme 的目標</a>依然不變：</p>
<ul>
<li>浮動寬度 (fluid width)：網頁不是畫板，不應該是固定大小，而該能夠隨著瀏覽器的大小，而顯示出最適合閱讀的樣貌。</li>
<li>二欄式 (2-column)：因為我的文章常常又臭又長，單欄式設計時，meta 得放在最下面，使用不方便，放在最上面又會佔據第一眼的空間。又因為我的程式常常要塞程式碼，三欄式設計的話，本文欄位通常會不夠寬。所以，二欄式設計較適合我。</li>
<li>邊欄在左 (sidebar-on-left)：因為程式碼都是 left-to-right 由左至右，又因為可能會有很長的內容，若邊欄放在右邊，就會和太長的程式碼衝突，互相遮蓋。所以邊欄要放在左邊。</li>
<li>主文在前 (main-content-first)：在 html 原始碼裡，主文內容應該擺在輔助內容的前面，有助於 SEO。這點與邊欄在左 (sidebar-on-left) 相衝突，因為 html 原始碼裡再前面的內容，會顯示在左邊，故必須要 CSS 技巧矯正。</li>
<li>雜誌封面式首頁 (magazine-styled homepage)：我想要拋棄 log 式排排站的首頁，僅在首頁依據最近發表的內容，如雜誌封面般地顯示。</li>
<li>&hellip;其他。</li>
</ul>
<p>首先我先重新尋找，看有沒有符合需求的佈景主題，最後挑中了以下幾個：</p>
<ul>
<li>Classic Beauty：在 IE6 下有問題。</li>
<li>Indigo：在 IE6 下有問題、右邊欄。</li>
<li>JustSimple：這個 theme 我最喜歡，可惜在 IE6 下還是有問題，左邊欄會跑到下面，應該是 box model 的關係，但我不會修。</li>
<li>Rational：在 IE6 下有問題。</li>
<li>Right Blue：在 IE6 下沒有問題，可是顏色太豔了，看久了眼睛不舒服。</li>
<li>SandPress：也是很讚的 theme，目錄下只有圖檔跟一個 CSS 檔，只靠 CSS 就可以弄得這麼漂亮，厲害。在 IE6 下沒有問題，可惜是右邊欄，我不會修成左邊欄。</li>
</ul>
<p>最後乾脆自己來，到網路上找到一個左邊欄的寫法，然後就著東修西改，最後被我弄出來了。在 IE6 看已經不會亂七八糟了，雖然還是有些小地方不太對勁，但至少能看了。爽。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/1092/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WordPress 備份與恢復記錄</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/1028/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/1028/#comments</comments>
		<pubDate>Wed, 12 Dec 2007 15:05:05 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[Blogging]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[opensource]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[scm]]></category>
		<category><![CDATA[subversion]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/articles/jeffhung/1028/</guid>
		<description><![CDATA[很久以前就想要好好地重整一下我的 blog 了，剛好趁著搬家重灌系統的機會，好好地整理一番。那時的目標有 真正的版本控制 資料庫瘦身 升級後台編輯用的 FCKeditor 與 Sidebar Widget 相容 IE 下的畫面極為慘烈 其中，「升級後台編輯用的 FCKeditor」已經在《WordPress 編輯器升級到 FCKeditor 2.5.x》時搞定，theme 的問題暫時先不解決，所以剩下「真正的版本控制」與「資料庫瘦身」兩個目標。 真正的版本控制 以前的作法是，用 Subversion 管理我的 WordPress 目錄，不過只是簡單的直接 checkout 出 WordPress 程式。雖然升級或更換版本很方便，svn update 或 svn switch 一下即可，不過自己在 local 端，因應自己的喜好而做的更改，就沒辦法有好的版本控制機制，加以管理了。 也就是說，我希望在能夠隨時將 WordPress 主網站的更新同步回來之外，還能夠保有自己因喜好而產生的一些小改變。如果 WordPress 主程式和我自己的改變，是存放在同一個 subversion repository 裡，那這一切就可以做到。 簡單講就是，如上圖，我希望能夠隨時 incrementally 從 WordPress 主 subversion repository 將最新的修正，mirror 到自己電腦上的 subversion repository [...]]]></description>
			<content:encoded><![CDATA[<p>很久以前就<a href="http://www.jeffhung.net/blog/articles/jeffhung/960/">想要好好地重整一下我的 blog</a> 了，剛好趁著搬家重灌系統的機會，好好地整理一番。那時的目標有</p>
<ul>
<li>真正的版本控制</li>
<li>資料庫瘦身</li>
<li>升級後台編輯用的 FCKeditor</li>
<li>與 Sidebar Widget 相容</li>
<li>IE 下的畫面極為慘烈</li>
</ul>
<p>其中，「升級後台編輯用的 FCKeditor」已經在《<a href="http://www.jeffhung.net/blog/articles/jeffhung/1017/">WordPress 編輯器升級到 FCKeditor 2.5.x</a>》時搞定，theme 的問題暫時先不解決，所以剩下「真正的版本控制」與「資料庫瘦身」兩個目標。</p>
<p><b>真正的版本控制</b></p>
<p>以前的作法是，用 <a href="http://subversion.tigris.org/">Subversion</a> 管理我的 <a href="http://www.wordpress.org/">WordPress</a> 目錄，不過只是簡單的直接 checkout 出 WordPress 程式。雖然升級或更換版本很方便，<code class="inline_code">svn update</code> 或 <code class="inline_code">svn switch</code> 一下即可，不過自己在 local 端，因應自己的喜好而做的更改，就沒辦法有好的版本控制機制，加以管理了。</p>
<p>也就是說，我希望在能夠隨時將 WordPress 主網站的更新同步回來之外，還能夠保有自己因喜好而產生的一些小改變。如果 WordPress 主程式和我自己的改變，是存放在同一個 subversion repository 裡，那這一切就可以做到。</p>
<p align="center"><a href="http://flickr.com/photos/jeffhung/2053832331/" target="_blank"><img src="http://farm3.static.flickr.com/2218/2053832331_63b137b795.jpg?v=0" alt="wordpress source maintainment" /></a></p>
<p>簡單講就是，如上圖，我希望能夠隨時 incrementally 從 WordPress 主 subversion repository 將最新的修正，mirror 到自己電腦上的 subversion repository 裡，成為一條 mirror branch。然後，又能夠有自己的一條 local branch，儲存自己的喜好，同時又能夠隨時視需要，將 mirror branch 裡的東西，merge 進我的 local branch 裡。</p>
<p>換句話說，我需要某種 subversion repository mirroring 的機制，且目的地端不能夠是 read-only，否則我就沒辦法擁有自己的 branch。</p>
<p>目前可以用的工具，有這三種：Subversion 原廠的 <code class="inline_code"><a href="http://svnbook.red-bean.com/en/1.4/svn.ref.svnsync.c.copy-revprops.html">svnsync</a></code>、<code class="inline_code"><a href="http://search.cpan.org/dist/SVN-Mirror/">SVN::Mirror</a></code> 與 <a href="http://svk.bestpractical.com/">SVK</a>。</p>
<p><b>使用 SVN::Mirror 複製 wordpress repository<br />
</b></p>
<p>Subversion 原廠的 <code class="inline_code">svnsync</code> 只能夠 mirror 出 read-only repository，目的端是來源端的完整複製，拿來做備份很好用，但不符合我的需求。SVK 有用到 <code class="inline_code">SVN::Mirror</code>，所以我先試試 <code class="inline_code">SVN::Mirror</code>。</p>
<p><code class="inline_code">SVN::Mirror</code> 有附一個叫 <code class="inline_code">svm</code> 的工具，可以讓我們直接在 command line 呼叫 <code class="inline_code">SVN::Mirror</code> 做事情，這樣就不需要寫程式了。假設目的端的 subversion repository 在 <code class="inline_code">/svn/wp</code>，使用 <code class="inline_code">svm</code> 的方法如下：</p>
<pre class="code">
SHELL&gt; env SVMREPOS=/svn/wp svm init /mirror http://svn.automattic.com/wordpress/
SHELL&gt; env SVMREPOS=/svn/wp svm sync /mirror
</pre>
<p>這樣就搞定了。<code class="inline_code">/svn/wp</code> 不需要是一個「乾淨」的 repository，只要 <code class="inline_code">file:///svn/wp/mirror</code> 目錄不存在即可。</p>
<p>接著，我就可以用 <code class="inline_code">svn copy</code> 製造自己的 local branch：</p>
<pre class="code">
SHELL&gt; svn copy file:///svn/wp/mirror file:///svn/wp/local
</pre>
<p>然後任何自己做的修改，就直接 commit 到 <code class="inline_code">file:///svn/wp/local</code>，想到時，就再 <code class="inline_code">svm sync</code> 一下，然後用 <code class="inline_code">svn merge</code> 把 <code class="inline_code">file:///svn/wp/mirror</code> 裡的新的東西，merge 到 <code class="inline_code">file:///svn/wp/local</code> 裡即可。</p>
<p><b>使用 SVK 複製 wordpress repository<br />
</b></p>
<p>用 <code class="inline_code">svn log</code> 翻閱利用 <code class="inline_code">SVN::Mirror</code> 所做出來的 mirror branch，大致如下：</p>
<pre class="code">
SHELL&gt; svn log --limit 2 file:///svn/wp/mirror
------------------------------------------------------------------------
r6353 | ryan | 2007-12-04 08:40:00 +0800 (二, 04 12 2007) | 1 line

Avoid unnecesary call to get_userdata in get_permalink function. Props
xknown. fixes #5414
------------------------------------------------------------------------
r6352 | ryan | 2007-12-04 08:19:10 +0800 (二, 04 12 2007) | 1 line
Don't save page and attachemtn uris to page_uris and page_attachment_uris.
This is not needed.  Add an option to use wildcard page rewrite rules
instead of per-page rules. see #3614
-----------------------------------------------------------------------
</pre>
<p>我們會發現，雖然 commit author/message 等資訊都還存在，可是所對應的來源端 revision number 遺失了，例如上例中的 r6353，在 wordpress repository 裡實際上是 r6352。如果說 mirror 目的端是個乾淨且完整複製的 repository，目的端的 revision number 就會剛好是來源端的 revision number，故不會有遺失的問題。但很可惜的是，我需要在 local repository 裡建立 local branch，並 commit 進自己的改變，故一定會造成 revision number 無法對應的情況。</p>
<p>因此，我只好祭出 SVK 來，改用 SVK 來進行 mirror，步驟大致如下：</p>
<pre class="code">
# 建立 local subversion repository。
SHELL&gt; svnadmin create /svn/wp

# 製造 svn-sync 專用的 svk depot。
SHELL&gt; svk depotmap sync ~/.svn-sync

# 設定將 /sync/wp/remote 映射到 wordpress 的 subversion repository URL。
SHELL&gt; svk mirror /sync/wp/remote http://svn.automattic.com/wordpress

# 設定將 /sync/wp/local 映射到 local repository 的 URL。
SHELL&gt; svk mirror /sync/wp/local file:///svn/wp/mirror

# 將 wordpress 的 changesets 複製到 svk depot 裡。
SHELL&gt; svk sync /sync/wp/remote

# 利用 smerge 進行複製，將 svk depot 裡的 wordpress changesets 複製到 local
# subversion repository 裡的 mirror branch。
# 之後的複製，都不必再加上 --baseless，只有第一次做的時候才需要。
SHELL&gt; svk smerge --incremental --log --baseless \
                  /sync/wp/remote /sync/wp/local

# 之後的複製，只需要做 svk sync 與 svk smerge 即可，且不必再加上 --baseless
# 參數，只有第一次做的時候才需要。
SHELL&gt; svk sync /sync/wp/remote
SHELL&gt; svk smerge --incremental --log /sync/wp/remote /sync/wp/local
</pre>
<p>這樣複製之後，原本在 <code class="inline_code">http://svn.automattic.com/wordpress</code> 的 changesets，就會通通被複製到 <code class="inline_code">file:///svn/wp/mirror</code> 裡。若是我們翻閱 <code class="inline_code">file:///svn/wp/mirror</code> 的 log，可以看到，log 裡完整地保留了，原始 wordpress repository 的 revision number，以及作為中介轉送站的 svk depot 的 revision number，如下：</p>
<pre class="code">
r6301 | jeffhung | 2007-11-22 08:48:33 +0800 (四, 22 11 2007) | 3 lines

 r12502@dev (orig r6300):  ryan | 2007-10-31 11:59:18 +0800
 wpdb::set_prefix(). fixes #5287

------------------------------------------------------------------------
r6300 | jeffhung | 2007-11-22 08:48:31 +0800 (四, 22 11 2007) | 3 lines

 r12501@dev (orig r6299):  ryan | 2007-10-31 11:53:32 +0800
 AJAX for link category add and delete. Props mdawaffe. fixes #5291
</pre>
<p>如範例裡的第一筆，r6301 是 local 端的 repository 的 revision number，r12502 是負責中介轉運的 SVK depot 的 revision number，而 r6300 則是官方 wordpress repository 的 revision number，ryan 則是該筆 changeset 的作者。如此一來，當有需要追蹤問題時，就可以清楚地找出對應的原始 revision number，從 wordpress 官方的角度，與 wordpress community 討論了。</p>
<p><b>迴避 SVK 的 memory leak 問題</b></p>
<p>不過，在使用 SVK 轉送 wordpress repository 內容時，卻碰到了 memory leak 的問題。</p>
<p>值此時，Wordpress 官方 repository 共有 6352 個 revisions，最後跑 <code class="inline_code">svk smerge</code> 時，使用的記憶體量會飆到 500MB 左右，然後停在 r1862 左右，不斷地印出 <code class="inline_code">perl in free(): warning: page is already free</code> 的訊息，只能用 Ctrl-C 跳開：</p>
<pre class="code">
SHELL&gt; cd ~/tmp/svk-mess-usage
SHELL&gt; svn-newrepo.sh --layout mirror wp-svn
Layout (mirror):
| /local
| /mirror
送交修訂版 1.
SHELL&gt; svk depotmap --init wp-svk wp-svk
SHELL&gt; svk mirror /wp-svk/remote http://svn.automattic.com/wordpress
SHELL&gt; svk sync   /wp-svk/remote
SHELL&gt; svk mirror /wp-svk/local file://`pwd`/wp-svn
SHELL&gt; svk smerge -I -l -B /wp-svk/remote /wp-svk/local
...
perl in free(): warning: page is already free
perl in free(): warning: page is already free
perl in free():Killed

Syncing file://`pwd`/wp-svn
Retrieving log information from 1862 to 1862
Committed revision 8205 from revision 1862.

SHELL&gt;
</pre>
<p>這種大量使用導致記憶體飆增，最後陷入 <code class="inline_code">perl in free(): warning: page is already free</code> 無窮迴圈的問題，b6s 也回報過：<a href="http://rt.openfoundry.org/Foundry/Project/Tracker/Display.html?id=26826&amp;Queue=82">#26826 - perl in free(): warning: page is already free</a>。</p>
<p>為了迴避這個問題，我修改上述的步驟，將 <code class="inline_code">sync</code>/<code class="inline_code">smerge</code> 拆成很多次做，一次只做 100 個 revisions。如此一來，每次記憶體用量僅約 20MB，不會碰到 <code class="inline_code">perl in free(): warning: page is already free</code> 無窮迴圈的問題，雖然耗時較久，但最後確實將 6352 個 revisions 完整搬動完畢。</p>
<p>我使用的 script 如下，歡迎使用：</p>
<pre class="code">
#!/bin/sh -e
# ---------------------------------------------------------------------------
# Copyright (c) 2007, Jeff Hung
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#.
#  - Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
#  - Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#  - Neither the name of the copyright holders nor the names of its
#    contributors may be used to endorse or promote products derived
#    from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# ----------------------------------------------------------------------------

svn_sync_via_svk()
{
    local name=&quot;$1&quot;; shift;
    local from_url=&quot;$1&quot;; shift;
    local to_url=&quot;$1&quot;; shift;
    local svk_depot_name=&quot;$1&quot;; shift;
    local svk_depot_path=&quot;$1&quot;; shift;
    local svk_sync_limit=&quot;$1&quot;; shift;

    # Ensure that $svk_depot_path doesn't contain '~'.
    svk_depot_path=`realpath &quot;$svk_depot_path&quot;`;

    echo &quot;[INFO] Setting up SVK transporter at $svk_depot,&quot;;
    echo &quot;[INFO] | using SVK depot '$svk_depot_name' at '$svk_depot_path',&quot;;
    echo &quot;[INFO] | which can be later accessed via 'svk depot /$svk_depot_name'.&quot;;
    svk depotmap &quot;$svk_depot_name&quot; &quot;$svk_depot_path&quot;;

    echo &quot;[INFO] Setting mirror from $from_url to /$svk_depot_name/$name/remote.&quot;;
    svk mirror &quot;/$svk_depot_name/$name/remote&quot; &quot;$arg_from_url&quot;;

    echo &quot;[INFO] Setting mirror from $arg_to_url to /$svk_depot_name/$name/local.&quot;;
    svk mirror &quot;/$svk_depot_name/$name/local&quot; &quot;$arg_to_url&quot;;

    from_url_head=`\
        svn info --xml &quot;$arg_from_url&quot; \
        | xml sel --text --template --value-of //entry/@revision \
        `;
    echo &quot;[INFO] Head revision of $arg_from_url is r$from_url_head.&quot;;

    from_url_rev_beg=0;
    from_url_rev_end=&quot;$opt_svk_sync_limit&quot;;
    while [ $from_url_rev_beg -lt $from_url_head ]; do
        echo &quot;[INFO] Syncing from -r$from_url_rev_beg:$from_url_rev_end $arg_from_url.&quot;;

        if [ $from_url_rev_end -le $from_url_head ]; then
            svk sync --torev $from_url_rev_end &quot;/$svk_depot_name/$name/remote&quot;;
        else
            svk sync &quot;/$svk_depot_name/$name/remote&quot;;
        fi;
        if [ $from_url_rev_beg -eq 0 ]; then
            svk smerge --incremental --log --baseless \
                       &quot;/$svk_depot_name/$name/remote&quot; \
                       &quot;/$svk_depot_name/$name/local&quot; \
            ;
        fi;
        svk sync &quot;/$svk_depot_name/$name/local&quot;;

        from_url_rev_beg=`expr $from_url_rev_end + 1`;
        from_url_rev_end=`expr $from_url_rev_beg + $opt_svk_sync_limit - 1`;
    done;
    echo &quot;[INFO] Done.&quot;;
}

svn_sync_via_svk $@;
</pre>
<p>其中，<code class="inline_code">xml</code> 指令來自於 <a href="http://xmlstar.sourceforge.net/">XMLStarlet</a> 這個套件，讓我得以很方便地直接在 command-line 剖析加了 <code class="inline_code">--xml</code> 選項的 <code class="inline_code">svn</code> 指令輸出，這樣就避免了 locale 對直接的 <code class="inline_code">svn</code> 指令輸出的影響。</p>
<p>另外，<code class="inline_code">$to_url</code> 這個 local repository 要自行建立，且必須先具備 <code class="inline_code">/mirror</code> 與 <code class="inline_code">/local</code> 兩個目錄。</p>
<p><b>AUTO_INCREMENT 不見了</b></p>
<p>有了完美的 source code 來源，安裝好全新的 wordpress，把<code class="inline_code">plugins/</code>、<code class="inline_code">themes/</code> 目錄與資料庫倒回去，修改好 <code class="inline_code">wp-config.php</code> 之後，理論上我的 blog 應該就恢復了，可是我卻發現，發表的新文章，卻不見蹤影，直接進 mysql 裡看才發現，新文章的 <code class="inline_code">ID</code> 居然是 <code class="inline_code">0</code>，用 <code class="inline_code">DESCRIBE wp_posts</code> 查才知道，<code class="inline_code">wp_posts.ID</code> 的 <code class="inline_code">AUTO_INCREMENT</code> 不見了。</p>
<p>我的 wordpress 資料庫備份，當初是用這樣的指令備份的：</p>
<pre class="code">
mysqldump --skip-opt         \
          --skip-quote-names \
          --complete-insert  \
          --add-drop-table   \
          --add-locks        \
          --lock-tables      \
          --user &lt;user&gt;      \
          --password         \
          &lt;wp-dbname&gt;        \
&gt; backup-wordpress.sql
</pre>
<p>打開 <code class="inline_code">backup-wordpress.sql</code> 發現，裡面所有的 <code class="inline_code">CREATE TABLE</code> 指令，該有&nbsp;<code class="inline_code">AUTO_INCREMENT</code> 的地方，都不見了，因此知道，問題出在當初 dump 資料庫的指令有問題。</p>
<p>首先，先解決錯誤的 dump 檔。因為翻遍了 <a href="http://dev.mysql.com/doc/refman/5.1/en/index.html">MySQL 文件</a>，我還是找不出，怎樣用 <a href="http://dev.mysql.com/doc/refman/5.1/en/alter-table.html"><code class="inline_code">ALTER TABLE</code></a> 直接把 <code class="inline_code">AUTO_INCREMENT</code> 加上去，因此只好直接修改 <code class="inline_code">backup-wordpress.sql</code>，將該有&nbsp;<code class="inline_code">AUTO_INCREMENT</code> 的地方手動編輯加上去，然後重新建立空的資料庫，把 <code class="inline_code">backup-wordpress.sql</code> 匯入。</p>
<p>接著，<code class="inline_code">man mysqldump</code> 發現，還有一個參數叫做 <code class="inline_code">--create-options</code>：</p>
<pre class="code">
o  --create-options

   Include all MySQL-specific table options in the CREATE TABLE
   statements.
</pre>
<p>因為 <code class="inline_code">AUTO_INCREMENT</code> 是 MySQL 特有的選項，因此如果沒有加上 <code class="inline_code">--create-options</code> 的話，<code class="inline_code">mysqldump</code> 就不會把&nbsp;<code class="inline_code">AUTO_INCREMENT</code> 也 dump 出來。因此，我的 wordpress 資料庫備份方法，應該改為：</p>
<pre class="code">
mysqldump --skip-opt         \
          --skip-quote-names \
          --complete-insert  \
          --add-drop-table   \
          --add-locks        \
          --lock-tables      \
          --create-options   \
          --user &lt;user&gt;      \
          --password         \
          &lt;wp-dbname&gt;        \
&gt; backup-wordpress.sql</pre>
<p>如此才能確保，資料庫的所有內容，被完整的備份下來。</p>
<p><b>資料庫瘦身</b></p>
<p>WordPress 很不好的一點就是，很多 plugins 會直接在資料庫裡面新增&nbsp;table，甚至是修改原有的 wordpress 的 tables，增加了新的 column。因此，倘若有一天，某個修改了資料庫 schema 的 plugin 不再被使用之後，資料庫裡就會留下一堆「垃圾」，且沒有好的方法可以清除。</p>
<p>雖然說，就算是垃圾，其實量也還不大，但有時候就是會讓我感到不爽，想要清乾淨。</p>
<p>我最初始的想法是，利用 wordpress 的 export 功能，將資料庫裡的資料，export 出來另存成一個 XML 檔，假設叫做 <code class="inline_code">wordpress-export.xml</code>。然後，用 wordpress 的安裝功能，建立全新的空資料庫，然後再用 import 功能，將 <code class="inline_code">wordpress-export.xml</code> 匯入新的 wordpress。如此一來，資料庫裡的資料，確實非常乾淨，僅剩下真的需要留在資料庫裡的資料。</p>
<p>不過，接下來我就發現，所有連往自己 blog 的文章連結，全部都亂掉了。好比連往 A 頁的鍊結，點下去卻跑到 B 頁了。仔細觀察後發現，這是因為我的 permalink 的設定，與 <code class="inline_code">AUTO_INCREMENT</code> 的關係。我的 permalink 的設定如下：</p>
<pre class="code">
/articles/%author%/%post_id%/
</pre>
<p>因為這是我個人的 blog，所以 <code class="inline_code">%author%</code> 一定是 <code class="inline_code">jeffhung</code>，所以，整個 permalink 可以用來辨別這到底是哪一篇文章的欄位，就只剩下 <code class="inline_code">%post_id%</code>，而 <code class="inline_code">%post_id%</code> 對應到資料庫裡的 <code class="inline_code">wp_posts.ID</code> 這個欄位，是設定成 <code class="inline_code">AUTO_INCREMENT</code> 的。因此，當經過 export 再 import 之後，<code class="inline_code">wp_posts.ID</code> 會重新經過&nbsp;<code class="inline_code">AUTO_INCREMENT</code> 的作用，重新產生索引值。由於 export 出來的文章順序，並不以 <code class="inline_code">wp_posts.ID</code> 排序，且刪除文章也會造成 <code class="inline_code">wp_posts.ID</code> 變成不連續。是故，當重新 <code class="inline_code">AUTO_INCREMENT</code> 之後，文章的 <code class="inline_code">wp_posts.ID</code> 就變了。可是文章裡的 <code class="inline_code">&lt;a href=&quot;...&quot;&gt;</code> 鍊結不會改變，於是就牛頭不對馬嘴了。</p>
<p>解決方法初步想來，有兩種：</p>
<ol>
<li>修改 wordpress 的 import 程式，把 <code class="inline_code">wordpress-export.xml</code> 檔裡，每篇文章所記載的 <code class="inline_code">&lt;wp:post-id&gt;</code> 值，納入 <code class="inline_code">INSERT</code> 指令。由於 <code class="inline_code">AUTO_INCREMENT</code> 是當 <code class="inline_code">INSERT INTO</code> 時卻沒有該欄位時才發揮作用，因此不會造成 <code class="inline_code">wp_posts.ID</code> 錯亂。</li>
<li>分析 <code class="inline_code">wordpress-export.xml</code>，利用 <code class="inline_code">&lt;wp:post_name&gt;</code> 的值，與 import 之後的資料庫裡的 <code class="inline_code">wp_posts.post_name</code> 欄位，來解析出原始 <code class="inline_code">%post_id%</code> 與新的 <code class="inline_code">wp_posts.ID</code> 的對應表，然後利用我在這篇《<a href="http://www.jeffhung.net/blog/articles/jeffhung/1024/">Kramer 與 get-recent-comments 的問題</a>》提到的方法，進去改所有的文章內文，修正連往自己 blog 的所有連結。最後，修改 permalinks 格式，把這個對應表 hard-code 進程式，當遇到舊格式時，就查表轉到新 permalinks。</li>
</ol>
<p>前者雖然需要改 wordpress 的程式，但只有一點點，而且可以保證 <code class="inline_code">%post_id%</code> 不變，所以應該是比較好的方式。而後者就麻煩很多，而且因為 <code class="inline_code">%post_id%</code> 的改變，必須要改變 permalinks 格式，以便接受來自外站，循著舊 permalink 過來的尋訪。</p>
<p>不過，我早就想改 permalinks 格式了，所以就試了一下第二個方法。</p>
<p><b>修改 permalink 的方法</b></p>
<p>我想要把 permalink 改成下面這個樣子：</p>
<pre class="code">
/articles/%post_name%/
</pre>
<p>沒有年月日，只有 <code class="inline_code">%post_name%</code>，也就是 wordpress 編輯畫面裡，Post Slug 那個欄位的值，相當地簡潔，乾淨。對我來說，<a href="http://en.wikipedia.org/wiki/Blog">blog</a> 的 log 成份並不大，反而比較像是一種偏文章性質的 wiki 型的個人出版媒體。事實上，<a href="http://heaven.branda.to/~thinker/GinGin_CGI.py">Thinker</a> 的 <a href="http://heaven.branda.to/~thinker/GinGin_CGI.py/show_kw_docs/GinGin">GinGin</a> 系統的那種「形式」，比較符合我理想中的樣子。因此，僅使用具有「意義」的&nbsp;<code class="inline_code">%post_name%</code> 作為 permalink 的組成元素，很合我意。</p>
<p>雖然理論上應該要將原來的 permalink 前置的 <code class="inline_code">/articles</code> 改變，好比變成 <code class="inline_code">/posts</code>，因為這將是前端據以判斷是哪種版本的 permalink 的重要依據，但是因為我原來的&nbsp;permalink 還有一個永遠是 <code class="inline_code">jeffhung</code> 的 <code class="inline_code">%author%</code> 存在，所以可以利用這個來判定新舊版本，故 permalink 仍然可以用 <code class="inline_code">/articles</code> 作為前置字串。</p>
<p>修改原始文章內容，將舊 permalinks 代換成新 permalinks 不難，只要先從資料庫裡，抓出「(舊) <code class="inline_code">%post_id%</code> 對應 <code class="inline_code">%post_name%</code>」的對應表，等到 <code class="inline_code">wordpress-export.xml</code> 匯入新灌好的 wordpress 之後，再從資料庫裡，抓出「<code class="inline_code">%post_name%</code> 對應(新) <code class="inline_code">%post_id%</code>」的對應表，兩者合併，就可以做出「舊 <code class="inline_code">%post_id%</code> 對應新 <code class="inline_code">%post_id%</code>」的對應表。</p>
<p>有了對應表之後，我們需要讓舊 permalinks 自動轉換到新 permalinks 的機制。也就是說，若 user 用舊的 permalinks 來連，就要自動用 <a href="http://tools.ietf.org/html/rfc2616#section-10.3.2">HTTP status code 301 Moved Permanently</a> 轉址到新的 permalinks。<a href="http://www.microkid.net/wordpress/permalinks-moved-permanently/">Permalinks Moved Permanently</a> 這個 wordpress plugin 正可以這麼做。</p>
<p>然而 Permalinks Moved Permanently 卻沒能發揮作用，翻 code 發現，似乎 Permalinks Moved Permanently 能夠應付任何 permalinks 格式的組合，就是不能處理 <code class="inline_code">%post_id%</code>，故我的舊 permalinks 她看不懂。又因為其所掛載的 <code class="inline_code">template_redirect</code> 這個 action，太過於「前面」，很多關於這個頁面的值，都尚未載入，因此一時之間，我找不到方法修正這個問題。</p>
<p>還好，最後我發現，<code class="inline_code">$_SERVER['REQUEST_URI']</code> 還可以用，因為舊 permalinks 的確實格是我知道，所以可以利用 regular expression 將舊的 <code class="inline_code">%post_id%</code> 擷取出來，繼而查表產生新的 permalinks。</p>
<p>至此，修改 permalinks 可能會碰到的技術問題，應該都解決了。不過，最後我還是沒有修改 permalinks，因為整個程序太過複雜，而我又急著將 blog 恢復上線，因此就暫時放棄了這個計畫。反正，過不久又將要換硬體，到時再來弄吧。</p>
<p><b>沒有對應 &lt;VirtualHost&gt; 設定的 request</b></p>
<p>最後，我終於知道了，若 http request 要連的 host，沒有對應的 <code class="inline_code">&lt;VirtualHost&gt;</code> 設定時，並不會如之前我想當然爾地，改連 global 設定 (<code class="inline_code">/usr/local/www/data</code>)，而是會對應到 httpd.conf 裡第一個出現的 <code class="inline_code">&lt;VirtualHost&gt;</code>。因此，我們需要有一組 dummy <code class="inline_code">&lt;VirtualHost&gt;</code> 擺在第一筆，以便攔截沒有對應 <code class="inline_code">&lt;VirtualHost&gt;</code> 的 http request。</p>
<p>因為搞不清楚這個機制，所以一度讓 feed大亂，張冠李戴地誤植我的文章到其他 blog 的 feed 裡。下次真的要記得看清楚設定檔裡的範例啊。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/1028/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>哈部落的匯入問題</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/1031/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/1031/#comments</comments>
		<pubDate>Wed, 28 Nov 2007 10:29:18 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[Blogging]]></category>
		<category><![CDATA[funp]]></category>
		<category><![CDATA[Industry]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/articles/jeffhung/1031/</guid>
		<description><![CDATA[FunP 改版，變成四大功能之後，基本上我還是都只有在用「我的頭版」，因為這個跟原來的 FunP 長得一樣，其他的我不太會用。剛剛試用了一下「哈部落」，結果還是以失敗收場。 首先，從右邊的「什麼是『哈部落』?」根本看不出來這是什麼樣的服務： 你一定聽過「部落格」，搞不好還有好幾個自己的部落格。「哈部落」是 funP.com 的一項服務，讓你輕易發現、訂閱、分享網路上有趣的部落格。你也可以在這裡將你的部落格分享出來，讓更多人聽見，你的觀察/日記/心聲/雜記！ 「哈部落」現在共有 2684 個部落格，把你和你喜歡的部落格一起來加進來吧！ 「發現」、「訂閱」、「分享」、「觀察」、「日記」、「心聲」、「雜記」？到底哪一個才是哈部落的功能？這麼多種截然不同的功能，讓我看不懂，沒辦法理解「哈部落」到底是什麼樣的東西。這種有跟沒有一樣的說明，看起來親切，但卻一點用處也沒有。 進去「哈部落」後，可以發現，大概有三大功能：「部落格總攬」、「我最愛的部落格」與「最新文章」，而首頁差不多就是這三大功能的綜合呈現。 部落格總攬 「部落格總攬」看起來就像是「部落格觀察」，只是似乎依據的是 FunP 內部的統計資料。我對部落格排序沒什麼興趣，就算要用，那也只是窮極無聊，沒東西可以看的時候，才會去翻。所以「部落格總攬」做的那麼大一塊，還放第一個，但對我來說，卻是沒有什麼意義。 我最愛的部落格 「我最愛的部落格」？喔，我懂了，原來「哈部落」其實是個 RSS aggregator，早說嘛！也許多了點現在流行的，號稱 social 的功能吧？！ 試著匯入我的 Google Reader 匯出的 OPML 檔，果然，跑了一個小時，還沒匯入完畢。直接開新頁面去看，已經有若干 feeds 匯入了，可是原本的分類標籤，全部不見了，所有 feeds 攤平在一起。從介面上來看，「我最愛的部落格」沒有像「部落格總攬」那樣，有分類的機制，看來原本我的分類標籤之所以會不見，是因為根本就沒有支援分類的功能。當 feeds 數量一多，基本上就會是兩個字：難用。 若干 feeds 亦尚未「登入到哈部落」，還要手動幫忙按一下才行。我搞不懂這為的是什麼？如果所謂「登入到哈部落」，並不會把這個 feed 公開，而只是個人使用，那這個功能實在是脫褲子放屁，匯入就已經是表示要加入這個 feed 了，幹麼還要再多按一下。不過搭配「某些 feed 已經被登入到了哈部落」這個事實來看，「登入到哈部落」指的應該是這個 feed 將會公開，像是加入了 planet 一樣。我想，一般人通常是不喜歡在不知情或未同意的情況之下，就被加入到某個 planet 裡，成為其可用以賺錢的內容來源 (「部落格總攬」右方有&#160;Google AdSense 區塊)，所以我不應該去按這個鈕。 最新文章 「最新文章」看來可能就是「登入到哈部落」後的那個 [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://funp.com">FunP</a> 改版，變成四大功能之後，基本上我還是都只有在用「<a href="http://funp.com/portal/">我的頭版</a>」，因為這個跟原來的 FunP 長得一樣，其他的我不太會用。剛剛試用了一下「<a href="http://funp.com/blogs/">哈部落</a>」，結果還是以失敗收場。</p>
<p>首先，從右邊的「什麼是『哈部落』?」根本看不出來這是什麼樣的服務：</p>
<blockquote>
<p>你一定聽過「部落格」，搞不好還有好幾個自己的部落格。「哈部落」是 funP.com 的一項服務，讓你輕易發現、訂閱、分享網路上有趣的部落格。你也可以在這裡將你的部落格分享出來，讓更多人聽見，你的觀察/日記/心聲/雜記！</p>
<p>「哈部落」現在共有 2684 個部落格，把你和你喜歡的部落格一起來加進來吧！</p>
</blockquote>
<p>「發現」、「訂閱」、「分享」、「觀察」、「日記」、「心聲」、「雜記」？到底哪一個才是哈部落的功能？這麼多種截然不同的功能，讓我看不懂，沒辦法理解「哈部落」到底是什麼樣的東西。這種有跟沒有一樣的說明，看起來親切，但卻一點用處也沒有。</p>
<p>進去「哈部落」後，可以發現，大概有三大功能：「<a href="http://funp.com/blogs/list.php">部落格總攬</a>」、「<a href="http://funp.com/blogs/favo.php">我最愛的部落格</a>」與「<a href="http://funp.com/blogs/latestposts.php">最新文章</a>」，而首頁差不多就是這三大功能的綜合呈現。</p>
<p><b>部落格總攬</b></p>
<p>「部落格總攬」看起來就像是「<a href="http://look.urs.tw/">部落格觀察</a>」，只是似乎依據的是 FunP 內部的統計資料。我對部落格排序沒什麼興趣，就算要用，那也只是窮極無聊，沒東西可以看的時候，才會去翻。所以「部落格總攬」做的那麼大一塊，還放第一個，但對我來說，卻是沒有什麼意義。</p>
<p><b>我最愛的部落格</b></p>
<p>「我最愛的部落格」？喔，我懂了，原來「哈部落」其實是個 <a href="http://en.wikipedia.org/wiki/Aggregator">RSS aggregator</a>，早說嘛！也許多了點現在流行的，號稱 social 的功能吧？！</p>
<p>試著匯入我的 <a href="http://www.google.com/reader/">Google Reader</a> 匯出的 <a href="http://en.wikipedia.org/wiki/OPML">OPML</a> 檔，果然，跑了一個小時，還沒匯入完畢。直接開新頁面去看，已經有若干 feeds 匯入了，可是原本的分類標籤，全部不見了，所有 feeds 攤平在一起。從介面上來看，「我最愛的部落格」沒有像「部落格總攬」那樣，有分類的機制，看來原本我的分類標籤之所以會不見，是因為根本就沒有支援分類的功能。當 feeds 數量一多，基本上就會是兩個字：難用。</p>
<p>若干 feeds 亦尚未「登入到哈部落」，還要手動幫忙按一下才行。我搞不懂這為的是什麼？如果所謂「登入到哈部落」，並不會把這個 feed 公開，而只是個人使用，那這個功能實在是脫褲子放屁，匯入就已經是表示要加入這個 feed 了，幹麼還要再多按一下。不過搭配「某些 feed 已經被登入到了哈部落」這個事實來看，「登入到哈部落」指的應該是這個 feed 將會公開，像是加入了 <a href="http://en.wikipedia.org/wiki/Planet_%28software%29">planet</a> 一樣。我想，一般人通常是不喜歡在不知情或未同意的情況之下，就被加入到某個 planet 裡，成為其可用以賺錢的內容來源 (「部落格總攬」右方有&nbsp;<a href="http://en.wikipedia.org/wiki/AdSense">Google AdSense</a> 區塊)，所以我不應該去按這個鈕。</p>
<p><b>最新文章</b></p>
<p>「最新文章」看來可能就是「登入到哈部落」後的那個 planet。一般來說，planet 是有主題性、社群性的，而且都是小眾。但即使是屬於小眾 planet，文章量總和起來，也多的驚人。哈部落目前收納了 2,684 個部落格，分類約有 12 個，先撇開實際上一個部落格可能同時屬於多個分類的問題，平均下來每個分類也有兩百多個部落格。一個聚合了兩百多個 feeds 的 planet，一天的文章量想必驚人，在資料爆炸的情況之下，這種 planet 一點價值也沒有。</p>
<p>更何況，我估計哈部落的「登入」根本沒有什麼評選機制，也只有按時間排序一種呈現方式，良莠不齊導致垃圾充斥，這種 planet 更是無用。更別提為甚麼一定要按照 FunP 提供的分類方式的問題了。</p>
<p><b>放棄</b></p>
<p>寫了這麼久，我的 OPML 還沒有完全匯入完畢，看來我只好放棄了。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/1031/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>公告：本站暫時恢復運作</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/1027/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/1027/#comments</comments>
		<pubDate>Thu, 22 Nov 2007 02:54:38 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[Blogging]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/articles/jeffhung/1027/</guid>
		<description><![CDATA[因為搬家要移機，所以公告停機一陣子，沒想到真的停了一個星期多，現在終於可以「暫時」正式上線了。 這次移機，碰到了最不應該碰到的麻煩：硬碟毀損兼備份資料缺失。還好，本站的每日備份還有正常運作，但我的 subversion repository 的備份機制，在不知道什麼時候失效了。現在只能祈禱硬碟只有開機磁區壞掉，還能夠把 subversion repositories 與 mail archives 救回來。 然後，又發現 server 的主機板也壞掉了，只好緊急徵用寶貝的 desktop 來架站，等 server 的硬體補齊之後，再換回去。 因此，基於上述兩個原因，本站只能夠「暫時」恢復運作，要等到新機器測好沒問題後，才能正常運行。另外，為了救資料，最近可能偶爾會重開機一下，如果連不到，就請暫時等待一下囉。]]></description>
			<content:encoded><![CDATA[<p>因為搬家要移機，所以<a href="http://www.jeffhung.net/blog/articles/jeffhung/1025/">公告停機</a>一陣子，沒想到真的停了一個星期多，現在終於可以「暫時」正式上線了。</p>
<p>這次移機，碰到了最不應該碰到的麻煩：硬碟毀損兼備份資料缺失。還好，本站的每日備份還有正常運作，但我的 subversion repository 的備份機制，在不知道什麼時候失效了。現在只能祈禱硬碟只有開機磁區壞掉，還能夠把 subversion repositories 與 mail archives 救回來。</p>
<p>然後，又發現 server 的主機板也壞掉了，只好緊急徵用<a href="http://www.afoofa.info/blog/">寶貝</a>的 desktop 來架站，等 server 的硬體補齊之後，再換回去。</p>
<p>因此，基於上述兩個原因，本站只能夠「暫時」恢復運作，要等到新機器測好沒問題後，才能正常運行。另外，為了救資料，最近可能偶爾會重開機一下，如果連不到，就請暫時等待一下囉。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/1027/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>移機公告：近日將因移機而停機一個星期不等</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/1025/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/1025/#comments</comments>
		<pubDate>Mon, 05 Nov 2007 01:41:31 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[Blogging]]></category>
		<category><![CDATA[announce]]></category>
		<category><![CDATA[sysadm]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/articles/jeffhung/1025/</guid>
		<description><![CDATA[因為就要搬家了，所以 ADSL 也要搬家，所以本站也要移機。但因為中華電信移機工程時間不確定，本站的新家裝修也尚未完全結束，所以本站整個移機程序，可能會耗上一個星期不等。 故，本站將於最近，不知道什麼時候停機，然後在不知道什麼時候，恢復運行。]]></description>
			<content:encoded><![CDATA[<p>因為就要搬家了，所以 ADSL 也要搬家，所以本站也要移機。但因為中華電信移機工程時間不確定，本站的新家裝修也尚未完全結束，所以本站整個移機程序，可能會耗上一個星期不等。</p>
<p>故，本站將於最近，不知道什麼時候停機，然後在不知道什麼時候，恢復運行。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/1025/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Kramer 與 get-recent-comments 的問題</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/1024/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/1024/#comments</comments>
		<pubDate>Fri, 02 Nov 2007 10:04:57 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[Blogging]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/articles/jeffhung/1024/</guid>
		<description><![CDATA[我的 Recent Backlinks 自從升級到 wordpress 2.3 之後，就一直有問題，會多顯示出 kramer_pre%--&#62; 的字樣。用這個奇怪的字樣去找，發現是 Kramer 這個 plug-in 的問題。當初會裝主要是因為 trackback 壞掉了，所以乾脆裝了 Kramer，會直接到網上找 back links，找到後代替 trackback auto-discovery 機制，插入資料到 wp_comments 表格。既然 Kramer 壞掉了，只好先拔掉再說。 沒想到拔掉 Kramer 之後，問題依舊，即使關掉 get-recent-comments 的 cache 也一樣。於是就直接進 database 裡找，發現不曉得為甚麼，Kramer 把製造出來的 wp_comments.comment_content 內容，前後加上了 &#60;!--%kramer-pre%--&#62; 與 &#60;!--%kramer_post%--&#62;。所以，只好辛苦地，寫個 script 修正 database： #!/usr/bin/perl -w use strict; use utf8; use File::Basename; use Getopt::Long; use DBI; [...]]]></description>
			<content:encoded><![CDATA[<p>我的 Recent Backlinks 自從升級到 wordpress 2.3 之後，就一直有問題，會多顯示出 <code class="inline_code">kramer_pre%--&gt;</code> 的字樣。用這個奇怪的字樣去找，發現是 <a href="http://wordpress.org/extend/plugins/kramer/">Kramer</a> 這個 plug-in 的問題。當初會裝主要是因為 trackback 壞掉了，所以乾脆裝了 Kramer，會直接到網上找 back links，找到後代替 <a href="http://www.sixapart.com/pronet/docs/trackback_spec">trackback auto-discovery</a> 機制，插入資料到 <code class="inline_code">wp_comments</code> 表格。既然 Kramer 壞掉了，只好先拔掉再說。</p>
<p>沒想到拔掉 Kramer 之後，問題依舊，即使關掉 <a href="http://wordpress.org/extend/plugins/get-recent-comments/">get-recent-comments</a> 的 cache 也一樣。於是就直接進 database 裡找，發現不曉得為甚麼，Kramer 把製造出來的 <code class="inline_code">wp_comments.comment_content</code> 內容，前後加上了 <code class="inline_code">&lt;!--%kramer-pre%--&gt;</code> 與 <code class="inline_code">&lt;!--%kramer_post%--&gt;</code>。所以，只好辛苦地，寫個 script 修正 database：</p>
<pre class="code">
#!/usr/bin/perl -w

use strict;
use utf8;
use File::Basename;
use Getopt::Long;
use DBI;

my ($__exe_name__) = (basename($0));
my ($__revision__) = ('$Rev: 26 $' =~ m/(\d+)/o);
my ($__rev_date__) = ('$Date: 2007-11-02 15:41:31 +0800 (五, 02 11 2007) $' =~ m/(\d{4}-\d{2}-\d{2})/o);

sub usage
{
    print STDERR &lt;&lt;&quot;EOF&quot;;
Usage: $__exe_name__ [ &lt;option&gt; ... ] &lt;db-name&gt;

Query wordpress database &lt;db-name&gt; and fix bad wp_comments.comment_content
generated by Kramer plug-in.

Options:

  --help                   Show this help messages.
  -h,--hostname &lt;db-host&gt;  Connect to database hosted at &lt;db-host&gt;.
  -u,--username &lt;db-user&gt;  Use username &lt;db-user&gt; to log into database.
  -p,--password &lt;db-pass&gt;  Use password &lt;db-pass&gt; to log into database.
  -v,--verbose             Show verbose messages.

Revision: r$__revision__ ($__rev_date__)
EOF
    exit;
}

sub msg_exit
{
    my $ex = ((scalar(@_) &gt; 0) ? shift @_ : 0);
    foreach my $m (@_) {
        print STDERR &quot;ERROR: $m\n&quot;;
    }
    print STDERR &lt;&lt;&quot;EOF&quot;;
Usage: $__exe_name__ [ &lt;option&gt; ... ] &lt;db-name&gt;
Type '$__exe_name__ --help' for usage.
EOF
    exit($ex);
}

my $opt_verbose = 0;
my %db_options;
if (!GetOptions('help'           =&gt; sub { usage; },
                'h|hostname=s'   =&gt; sub { $db_options{'DB_HOST'} = $_[1]; },
                'u|username=s'   =&gt; sub { $db_options{'DB_USER'} = $_[1]; },
                'p|password=s'   =&gt; sub { $db_options{'DB_PASS'} = $_[1]; },
                'v|verbose'      =&gt; \$opt_verbose)) {
    msg_exit(0);
}
$db_options{'DB_NAME'} = shift @ARGV or msg_exit(1, 'Missing &lt;db-name&gt;.');

my $dbh = DBI-&gt;connect(
    sprintf('DBI:mysql:database=%s;host=%s',
            $db_options{'DB_NAME'},
            $db_options{'DB_HOST'}),
    $db_options{'DB_USER'},
    $db_options{'DB_PASS'}
);

my @update_statements;

my $sth = $dbh-&gt;prepare(&lt;&lt;SQL
SELECT *
FROM   wp_comments
WHERE  comment_type =&quot;pingback&quot; AND
       comment_content LIKE &quot;&lt;!--%&quot;
SQL
);
$sth-&gt;execute();
while (my $row = $sth-&gt;fetchrow_hashref()) {
    my @sqlpart_setval;
    my @sqlpart_where;
    foreach my $f (keys %$row) {
        my $v = $row-&gt;{$f};
        if ($f eq 'comment_content') {
#           push(@sqlpart_setval, sprintf('-- WAS: &quot;%s&quot;', $v));
            $v =~ s/^&lt;!--%kramer-pre%--&gt;//o;
            $v =~ s/&lt;!--%kramer-post%--&gt;$//o;
            push(@sqlpart_setval, sprintf('%s = %s', $f, $dbh-&gt;quote($v)));
        }
        else {
            push(@sqlpart_where, sprintf('%s = %s', $f, $dbh-&gt;quote($v)));
        }
    }
    push(@update_statements, sprintf(
        &quot;UPDATE\n\t%s\nSET\n\t%s\nWHERE\n\t%s;&quot;,
        $arg_tab_name,
        join(&quot;,\n\t&quot;,    @sqlpart_setval),
        join(&quot; AND\n\t&quot;, @sqlpart_where)
    ));
}
$sth-&gt;finish();

foreach my $sql (@update_statements) {
    print &quot;-- --------------------------------------------- --\n$sql\n\n&quot;;
}

$dbh-&gt;disconnect();
</pre>
<p>利用這個 script，可以 dump 出一個 SQL 檔，備份好 wordpress 之後，把這個 SQL 檔餵進資料庫即修正完畢。</p>
<p>清掉 get-recent-comments 的 cache 之後，奇怪的字樣雖然不見了，不過正常該有的內容，卻又被截掉了最前面 5 個字元。繼續用 <code class="inline_code">comment_excerpt</code> 當關鍵字翻 <code class="inline_code">get-recent-comments.php</code>，發現了和 <code class="inline_code">5</code> 相關的下面這段程式：</p>
<pre class="code">
        if ($comment-&gt;comment_type == 'pingback')
        {

            $comment_type = &quot;Pingback&quot;;
            list($comment_author,$trackback_title) = kjgrc_parse_pingback($comment-&gt;comment_author);
            if(strpos($comment_excerpt,'[...]') == 0)
                $comment_excerpt = trim(substr($comment_excerpt,5));
            if(strpos($comment_excerpt,'[...]') == strlen($comment_excerpt)-5)
                $comment_excerpt = trim(substr($comment_excerpt,0,strlen($comment_excerpt)-5));
        }
</pre>
<p>意思是說，如果 <code class="inline_code">$comment_excerpt</code> 最前面的 <code class="inline_code">[...]</code> 與最後面的 <code class="inline_code">[...]</code> 移掉。看到 <code class="inline_code">strpos()</code> 我就感到不對，查了一下文件，<code class="inline_code">strpos()</code> 若找不到就會回傳 <code class="inline_code">FALSE</code>，而&nbsp;<code class="inline_code">FALSE == 0</code> 會得到真值，於是<code class="inline_code">$comment_excerpt</code> 前面的 5 個字元就被砍掉了。解法很簡單，把 <code class="inline_code">==</code> 改成 <code class="inline_code">===</code> 就可以了，如下：</p>
<pre class="code">
--- get-recent-comments.php.ori 2007-11-02 17:31:56.000000000 +0800
+++ get-recent-comments.php     2007-11-02 17:32:13.000000000 +0800
@@ -1248,7 +1248,7 @@

                        $comment_type = &quot;Pingback&quot;;
                        list($comment_author,$trackback_title) = kjgrc_parse_pingback($comment-&gt;comment_author);
-                       if(strpos($comment_excerpt,'[...]') == 0)
+                       if(strpos($comment_excerpt,'[...]') === 0)
                                $comment_excerpt = trim(substr($comment_excerpt,5));
                        if(strpos($comment_excerpt,'[...]') == strlen($comment_excerpt)-5)
                                $comment_excerpt = trim(substr($comment_excerpt,0,strlen($comment_excerpt)-5));
</pre>
<p>至此，問題全部解決，同時<a href="http://blog.jodies.de/archiv/2004/11/13/recent-comments/#comment-358898">回應給 get-recent-comments team</a>。不過，又回想了一下，共 5 個字元被砍掉，那一開始的那個奇怪的 <code class="inline_code">kramer-pre%--&gt;</code> 字樣，不就是 Kramer 塞進來的 <code class="inline_code">&lt;!--%kramer-pre%--&gt;</code> 扣掉前面 5 個字元嗎？</p>
<p>繞了一圈才發現，原來問題的癥結在於 get-recent-comments，而不是 Kramer，我錯怪它了。不過我還沒決定是否要把 Kramer 裝回去就是了。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/1024/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WordPress 編輯器升級到 FCKeditor 2.5.x</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/1017/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/1017/#comments</comments>
		<pubDate>Mon, 29 Oct 2007 04:39:15 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[Blogging]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/articles/jeffhung/1017/</guid>
		<description><![CDATA[雖然自從 WordPress 2.x 開始，就內建了 TinyMCE 這套 WYSIWYG 的編輯器，但因為之前使用 EditorMonkey 裡面的 FCKeditor 功能實在強大，又能依據我的需要進行 customization，因此我仍然還是使用 EditorMonkey。可是，EditorMonkey 內附的 FCKeditor 是 2.2 版，已經很舊了，在使用的過程中，也一再地發現某些 bug，甚至培養出了迴避這些 bug 的編輯行為。 是故，我一直在思考著，是不是什麼時候，來升級一下。就在編寫 dprintf() 系列文章的過程中，實在是受不了了舊版 FCKeditor 的一些 bug 的情況下，再加上 FCKeditor 就在 2007-10-10，剛剛釋出了 2.5 Beta 版，所以一不小心，就把 editormonkey 拔掉，搞出了個 FCKeditor 2.5.x 的 wordpress plug-in 來。 當然，我並沒有那麼厲害，能夠無中生有的憑空造出一個 plug-in 來，主要還是參考了 Dean's FCKEditor For WordPress，這是官方的 wordpress plugin directory 裡用 fckeditor [...]]]></description>
			<content:encoded><![CDATA[<p>雖然自從 <a href="http://wordpress.org/">WordPress</a> 2.x 開始，就內建了 <a href="http://tinymce.moxiecode.com/">TinyMCE</a> 這套 <a href="http://en.wikipedia.org/wiki/WYSIWYG">WYSIWYG</a> 的編輯器，但因為之前使用 <a href="http://www.wp-plugins-db.org/plugin/editormonkey/">EditorMonkey</a> 裡面的 <a href="http://www.fckeditor.net/">FCKeditor</a> 功能實在強大，又能依據我的需要進行 customization，因此我<a href="http://www.jeffhung.net/blog/articles/jeffhung/440/">仍然還是使用 EditorMonkey</a>。可是，EditorMonkey 內附的 FCKeditor 是 2.2 版，已經很舊了，在使用的過程中，也一再地發現某些 bug，甚至培養出了迴避這些 bug 的編輯行為。</p>
<p>是故，我一直在思考著，<a href="http://www.jeffhung.net/blog/articles/jeffhung/960/">是不是什麼時候，來升級一下</a>。就在編寫 <a href="http://www.jeffhung.net/blog/articles/jeffhung/1013/"><code class="inline_code">dprintf()</code> 系列文章</a>的過程中，實在是受不了了舊版 FCKeditor 的一些 bug 的情況下，再加上 FCKeditor 就在 2007-10-10，剛剛釋出了 2.5 Beta 版，所以一不小心，就把 editormonkey 拔掉，搞出了個 FCKeditor 2.5.x 的 wordpress plug-in 來。</p>
<p>當然，我並沒有那麼厲害，能夠無中生有的憑空造出一個 plug-in 來，主要還是參考了 <a href="http://www.deanlee.cn/wordpress/fckeditor-for-wordpress-plugin/">Dean's FCKEditor For WordPress</a>，這是官方的 <a href="http://wordpress.org/extend/plugins/">wordpress plugin directory</a> 裡用 fckeditor 當關鍵字，所可以找到的唯一一套真正的 fckeditor 編輯器的 plug-in。不過，<a href="http://www.deanlee.cn/">Dean Lee</a> 的版本，尚無法符合我的需求，所以我修改了一下，加了一些新功能：</p>
<ul>
<li>完全不碰觸 <code class="inline_code">FCKeditor/</code> 目錄，以便以後方便升級 fckeditor。</li>
<li>新設 <code class="inline_code">themes/</code> 目錄，裡面有 <code class="inline_code">config.js.php</code>、<code class="inline_code">fck_editorarea.css.php</code>、<code class="inline_code">fckstyles.xml.php</code> 與 <code class="inline_code">fcktemplates.xml.php</code>，這些是 fckeditor 的設定檔，改成 PHP 檔，然後於 <code class="inline_code">config.js.php</code> 修改設定，讓&nbsp;fckeditor 改到這些 theme 檔讀取設定。</li>
<li>把 smiley 與 file upload 功能拔掉。</li>
<li>除了名為 <code class="inline_code">default</code> 的 theme 以外，緩慢編修名為 <code class="inline_code">docbook</code> 的 theme。我準備慢慢地以 <a href="http://www.docbook.org/">docbook</a> 的 tag 名，標示文章各處內容的 semantics。</li>
</ul>
<p>不過，即使是這最新釋出的 FCKeditor 2.5 Beta 版，還是有著一些小問題：</p>
<ul>
<li>當 <code class="inline_code">&lt;pre&gt;</code> 裡面有 <code class="inline_code">&lt;</code>、<code class="inline_code">&gt;</code>，當切到 source 去，將其改成 <code class="inline_code">&amp;lt;</code> 與 <code class="inline_code">&amp;gt;</code> 時，切回 WYSIWYG 後，會變成 <code class="inline_code">&lt;</code> 和 <code class="inline_code">&gt;</code>。</li>
<li>找不到方法調整 hot-key 或乾脆關掉，因此 Ctrl-Tab 被綁架成 Source/WYSIWYG 切換，因而無法在 firefox 裡切換 tab，Ctrl-L 與 Ctrl-K 也被綁架成不知道什麼功能，因此無法直接將 focus 轉到網址列與搜尋框。</li>
<li>修改 <code class="inline_code">fckstyles.xml</code> 以便客制化自己常用的幾個 styles：<code class="inline_code">code</code>、<code class="inline_code">inline_code</code>、<code class="inline_code">screen</code>、<a href="http://www.jeffhung.net/blog/articles/jeffhung/505/"><code class="inline_code">footnote</code></a>、<code class="inline_code">sidenote</code> 等，結果工具列裡 style 這個 drop-down，還是會留有一個叫 <code class="inline_code">Red Title</code> 的樣式，不曉得是從哪裡來的，無法移除。</li>
</ul>
<p>第一個問題最嚴重，還好馬上在官網上看到 <a href="http://dev.fckeditor.net/ticket/1414">#1414</a> 已經列出了這個 bug，然後在 <a href="http://dev.fckeditor.net/changeset/1025">r1025</a>/<a href="http://dev.fckeditor.net/changeset/1026">r1026</a> 解掉了，幸好我沒有直接修改 <code class="inline_code">FCKeditor/</code> 目錄，而是把設定都拉到 <code class="inline_code">themes/</code> 目錄下修改，所以直接改成從 SVN 把 branch <a href="http://svn.fckeditor.net/FCKeditor/branches/versions/2.5.x">2.5.x</a> 拉下來，問題就解決了。</p>
<p>至於剩下來的問題，就只能再研究囉。</p>
<hr />
<p><b>2008-01-16 更新：</b></p>
<p>Hot-key 的問題，修改 <code class="inline_code">fckconfig.js</code> 裡的 <code class="inline_code">FCKConfig.Keystrokes</code> 這一個表格即可修正。格式就我實驗的結果，應該為：</p>
<pre class="code">
FCKConfig.Keystrokes = [
//    key-codes,       true for pass-though to browser,
//                     or string to invoke key function
// ----------------------------
//  [ CTRL + 65 /*A*/, true ],
    [ CTRL + 67 /*C*/, true ],
    [ CTRL + 75 /*K*/, true ], // add by jeffhung
    [ CTRL + 76 /*L*/, true ], // add by jeffhung
//  [ CTRL + 70 /*F*/, true ],
//  [ CTRL + 83 /*S*/, true ],
//  [ CTRL + 88 /*X*/, true ],
    [ CTRL + 86 /*V*/, 'Paste' ],
//  [ SHIFT + 45 /*INS*/, 'Paste' ],
    [ CTRL + 88 /*X*/, 'Cut' ],
//  [ SHIFT + 46 /*DEL*/, 'Cut' ],
    [ CTRL + 90 /*Z*/, 'Undo' ],
//  [ CTRL + 89 /*Y*/, 'Redo' ],
//  [ CTRL + SHIFT + 90 /*Z*/, 'Redo' ],
//  [ CTRL + 76 /*L*/, 'Link' ],
//  [ CTRL + 66 /*B*/, 'Bold' ],
//  [ CTRL + 73 /*I*/, 'Italic' ],
//  [ CTRL + 85 /*U*/, 'Underline' ],
//  [ CTRL + SHIFT + 83 /*S*/, 'Save' ],
//  [ CTRL + ALT + 13 /*ENTER*/, 'FitWindow' ],
//  [ CTRL + 9 /*TAB*/, 'Source' ]
];
</pre>
<p>所以，把「<code class="inline_code">Ctrl + 90 /*Z*/</code>」對應到「Undo (反悔)」，「<code class="inline_code">Ctrl + 88 /*X*/</code>」對應到「Cut (剪下)」、「<code class="inline_code">Ctrl + 86 /*V*/</code>」對應到「Paste (貼上)」，但「<code class="inline_code">Ctrl + 67 /*C*/</code>」必須對應到 true，直接讓 browser 處理「Copy (複製)」的功能，以避免 FCKeditor 的複製功能，被 browser 的安全機制攔阻。最後，再加上對「<code class="inline_code">Ctrl + 75 /*K*/</code>」與「<code class="inline_code">Ctrl + 76 /*L*/</code>」放行，就可以用 hot-key 把 focus 跳到 firefox 的網址列與搜尋列了。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/1017/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>移除 SiteMeter</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/855/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/855/#comments</comments>
		<pubDate>Tue, 17 Jul 2007 06:47:57 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[Blogging]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/articles/jeffhung/855/</guid>
		<description><![CDATA[(舊文) 看到 Max.Taiwan 的這篇《sitemeter加入第三方連結》，我決定也把 SiteMeter 也關掉。可惜這陣子渡蜜月去了，所以拖了十來天才有反應，在此向本站的訪客致歉。 雖然說在 SiteMeter 的 Privacy Statement 裡面有這麼一段： Third Party Advertisements The advertisements appearing on our website from time to time are provided by a variety of our third party advertising partners. We only share website usage information about our users with reputable third party advertisers for the sole purpose of [...]]]></description>
			<content:encoded><![CDATA[<p>(舊文)</p>
<p>看到 <a href="http://max.idv.tw/wordpress">Max.Taiwan</a> 的這篇《<a href="http://max.idv.tw/wordpress/archives/2007/04/06/235/">sitemeter加入第三方連結</a>》，我決定也把 <a href="http://www.sitemeter.com/">SiteMeter</a> 也關掉。可惜這陣子<a href="http://www.jeffhung.net/blog/articles/jeffhung/850/">渡蜜月</a>去了，所以拖了十來天才有反應，在此向本站的訪客致歉。</p>
<p>雖然說在 SiteMeter 的 <a href="http://www.sitemeter.com/?a=privacy">Privacy Statement</a> 裡面有這麼一段：</p>
<blockquote>
<p><em>Third Party Advertisements</em></p>
<p><em>The advertisements appearing on our website from time to time are provided by a variety of our third party advertising partners. We only share website usage information about our users with reputable third party advertisers for the sole purpose of better targeting our website banner advertisements.</em></p>
</blockquote>
<p>但所謂「<em>we only share website usage information</em>」就我的定義來說，是指 SiteMeter 自己收集好資料後，再轉交給 3rd party partners，而非直接容許未經使用者授權的 3rd party partners 直接收集使用者的網頁使用情形。</p>
<p>誰知道就這麼開放給 3rd party partners 自行放東西在我的網頁上，會造成什麼影響。若出了問題，找 SiteMeter 那 SiteMeter 能處理嗎？</p>
<p>整一個麻煩！所以我決定把 SiteMeter 移除掉，不再使用。</p>
<p>相關連結：</p>
<ul>
<li><a href="http://www.shaftek.org/blog/archives/000429.html">SiteMeter and Spyware (Sort of)</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/855/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>裝了「巴布」</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/966/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/966/#comments</comments>
		<pubDate>Mon, 16 Jul 2007 13:37:29 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[Blogging]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/articles/jeffhung/966/</guid>
		<description><![CDATA[在首頁裝了巴布的 badget，看看有沒有比 twitter 好玩。 用 IM 操控巴布，是蠻不錯的設計。不過和我用的 miranda 不相容：]]></description>
			<content:encoded><![CDATA[<p>在首頁裝了<a href="http://buboo.tw/">巴布</a>的 badget，看看有沒有比 <a href="http://www.jeffhung.net/blog/articles/jeffhung/844/">twitter</a> 好玩。</p>
<p>用 IM 操控巴布，是蠻不錯的設計。不過和我用的 <a href="http://www.miranda-im.org/">miranda</a> 不相容：</p>
<p><a href="http://flickr.com/photos/jeffhung/827848413/"><img src="http://farm2.static.flickr.com/1055/827848413_dca2aeac49.jpg?v=0" alt="" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/966/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>出清今日連結</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/961/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/961/#comments</comments>
		<pubDate>Sat, 14 Jul 2007 00:25:10 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[Blogging]]></category>
		<category><![CDATA[Links]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/articles/jeffhung/961/</guid>
		<description><![CDATA[每次都被寶貝念，drafts 積太多，所以乾脆先從最簡單的今日連結下手，一次出清。剩下來的比較麻煩，得慢慢磨。flee~]]></description>
			<content:encoded><![CDATA[<p>每次都被寶貝念，drafts 積太多，所以乾脆先從最簡單的<a href="http://www.jeffhung.net/blog/categories/links/">今日連結</a>下手，一次出清。剩下來的比較麻煩，得慢慢磨。flee~</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/961/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>想要重灌我的 blog</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/960/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/960/#comments</comments>
		<pubDate>Fri, 13 Jul 2007 14:50:03 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[Blogging]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/articles/jeffhung/960/</guid>
		<description><![CDATA[想要重灌我的 blog 了，主要有以下幾個原因，而且每個原因好像都得寫點程式才行： 真正的版本控制 現在雖然是用 subversion 在管理，每次升級都超級簡單。不過，由於並沒有實際上地把 wordpress 的 repository 給&#160;mirror 到 local repository，所以自己改動到的部份，沒有辦法納入版本控制。之前都是用 SVK 在 mirror，最近大致摸熟了 SVN::Mirror 裡的 svm 的用法，應該可以弄出 script 來做這件事。 資料庫瘦身 之前有亂玩一些 plug-in，有些 plug-in 會在 database 裡塞一些額外的 table。當 plug-in 被砍掉之後，這些 table 並不會一併被清除，導致現在的 database schema 有些「雜」。正考慮是不是要弄個 script，依據目前的 wordpress 版本，清除掉「預設」不會有的 table 資料。 升級後台編輯用的 FCKeditor 目前後台使用 EditorMonkey 這套 plug-in 裡的 FCKeditor 編輯文章。不過因為在 wordpress 2 以後，開始內建 [...]]]></description>
			<content:encoded><![CDATA[<p>想要重灌我的 blog 了，主要有以下幾個原因，而且每個原因好像都得寫點程式才行：</p>
<dl>
<dt>真正的版本控制</dt>
<dd>現在雖然是用 subversion 在管理，每次升級都超級簡單。不過，由於並沒有實際上地把 wordpress 的 repository 給&nbsp;mirror 到 local repository，所以自己改動到的部份，沒有辦法納入版本控制。之前都是用 <a href="http://svk.bestpractical.com/">SVK</a> 在 mirror，最近大致摸熟了 <a href="http://search.cpan.org/dist/SVN-Mirror/">SVN::Mirror</a> 裡的 svm 的用法，應該可以弄出 script 來做這件事。</dd>
<dt>資料庫瘦身</dt>
<dd>之前有亂玩一些 plug-in，有些 plug-in 會在 database 裡塞一些額外的 table。當 plug-in 被砍掉之後，這些 table 並不會一併被清除，導致現在的 database schema 有些「雜」。正考慮是不是要弄個 script，依據目前的 wordpress 版本，清除掉「預設」不會有的 table 資料。</dd>
<dt>升級後台編輯用的 FCKeditor</dt>
<dd>目前後台使用 <a href="http://www.rajprasad.net/plugins/editormonkey/">EditorMonkey</a> 這套 plug-in 裡的 <a href="http://www.fckeditor.net/">FCKeditor</a> 編輯文章。不過因為在 wordpress 2 以後，開始內建 TinyMCE，所以 EditorMonkey 不再繼續開發了。是故，使用的 FCKeditor 版本比較舊，一路用下來，連 bug 怎麼繞過都已經熟能生巧了。不過這畢竟不是辦法，還是要把版本換成新版才是。</dd>
<dt>與 Sidebar Widget 相容</dt>
<dd><a href="http://www.jeffhung.net/blog/articles/jeffhung/668/">現在用的 theme，是從 sandbox 0.6 改出來的</a>，那時還沒有內建 sidebar widget，所以一些&nbsp;sidebar widget 的 plug-in 都不能用。新的 <a href="http://www.plaintxt.org/2007/05/29/sandbox-v09-released/">sandbox 0.9</a> 已經相容於 sidebar widget 了，所以應該趁重灌的機會，一併把 theme 用 sandbox 0.9 重作。</dd>
<dt>IE 下的畫面極為慘烈</dt>
<dd>由於功力不到家，所以自己從 sandbox 0.6 改出來的 theme，在 IE 下畫面極為「慘烈」。所以應該要想法修正之。</dd>
</dl>
<p>列一列發現工程浩大，慢慢來好了。XD</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/960/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>加裝 google-code-prettify</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/932/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/932/#comments</comments>
		<pubDate>Sun, 17 Jun 2007 02:26:10 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[Blogging]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[opensource]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/articles/jeffhung/932/</guid>
		<description><![CDATA[看到這篇《網頁程式碼美化程式 Google Code Prettify》的介紹，我也試裝了一下。果然所有程式碼的列表，自動有了 syntax highlighting。 Google Code Prettify 的特色是，用的時候不需要指定語言，會自動偵測。我們「唯三」需要做的，就是： 在 &#60;header&#62; 引入 google-code-prettify 的 css 與 javascript 檔。 將你要做 syntax highlighting 的程式碼，寫在 &#60;pre&#62; 裡，並賦予 prettyprint 的 CSS class。 在文件全部載入之後，呼叫 prettyPrint() 函式。 由於我有一堆文章，已經把程式碼放在 &#60;pre&#62;，使用 code 這個 CSS class 標示，因此，我需要做一些額外的處理，把這些 &#60;pre class=&#34;code&#34;&#62; 找出來，再多加上 prettyprint 的 CSS class。 將 google-code-prettify 抓下來解開後，會有兩個檔：prettify.css 與 prettify.js，一起放到 theme 目錄下即可。因為 Y!UI 很好用，所以我就偷懶直接依靠 [...]]]></description>
			<content:encoded><![CDATA[<p>看到這篇《<a href="http://blog.xuite.net/emisjerry/tech/11792447">網頁程式碼美化程式 Google Code Prettify</a>》的介紹，我也試裝了一下。果然所有程式碼的列表，自動有了 syntax highlighting。</p>
<p><a href="http://code.google.com/p/google-code-prettify/">Google Code Prettify</a> 的特色是，用的時候不需要指定語言，會自動偵測。我們「唯三」需要做的，就是：</p>
<ol>
<li>在 <code class="inline_code">&lt;header&gt;</code> 引入 google-code-prettify 的 css 與 javascript 檔。</li>
<li>將你要做 syntax highlighting 的程式碼，寫在 <code class="inline_code">&lt;pre&gt;</code> 裡，並賦予 <code class="inline_code">prettyprint</code> 的 CSS class。</li>
<li>在文件全部載入之後，呼叫 <code class="inline_code">prettyPrint()</code> 函式。</li>
</ol>
<p>由於我有一堆文章，已經把程式碼放在 <code class="inline_code">&lt;pre&gt;</code>，使用 <code class="inline_code">code</code> 這個 CSS class 標示，因此，我需要做一些額外的處理，把這些 <code class="inline_code">&lt;pre class=&quot;code&quot;&gt;</code> 找出來，再多加上 <code class="inline_code">prettyprint</code> 的 CSS class。</p>
<p>將 google-code-prettify 抓下來解開後，會有兩個檔：prettify.css 與 prettify.js，一起放到 theme 目錄下即可。因為 <a href="http://developer.yahoo.com/yui/">Y!UI</a> 很好用，所以我就偷懶直接依靠 Y!UI。修改 wordpress 佈景主題的 <code class="inline_code">header.php</code> 檔，在 <code class="inline_code">&lt;/head&gt;</code> 之前，加入以下的程式碼：</p>
<pre class="code">    ...

    &lt;script type=&quot;text/javascript&quot; src=&quot;http://yui.yahooapis.com/2.2.2/build/yahoo/yahoo-min.js&quot;&gt;&lt;/script&gt;    &lt;script type=&quot;text/javascript&quot; src=&quot;http://yui.yahooapis.com/2.2.2/build/dom/dom-min.js&quot;&gt;&lt;/script&gt;    &lt;script type=&quot;text/javascript&quot; src=&quot;http://yui.yahooapis.com/2.2.2/build/event/event-min.js&quot;&gt;&lt;/script&gt;    &lt;link type=&quot;text/css&quot; href=&quot;&lt;?php echo get_template_directory_uri(); ?&gt;/prettify.css&quot; rel=&quot;stylesheet&quot;/&gt;    &lt;script type=&quot;text/javascript&quot; src=&quot;&lt;?php echo get_template_directory_uri(); ?&gt;/prettify.js&quot;&gt;&lt;/script&gt;    &lt;script type=&quot;text/javascript&quot;&gt;    YAHOO.util.Event.addListener(window, 'load', function(){        var pre_elems = YAHOO.util.Dom.getElementsByClassName('code', 'pre');        for (var i = 0; i &lt; pre_elems.length; ++i) {            YAHOO.util.Dom.addClass(pre_elems[i], 'prettyprint');        }        prettyPrint();    });    &lt;/script&gt;&lt;/head&gt;</pre>
<p>這段程式是說，利用 Y!UI 的 <a href="http://developer.yahoo.com/yui/dom/">DOM</a> library，把網頁裡，有加 <code class="inline_code">code</code> 這個 class 的 <code class="inline_code">&lt;pre&gt;</code> 全部抓出來後，另外再多加一個 <code class="inline_code">prettyprint</code> 的 class。然後，再呼叫 <code class="inline_code">prettyPrint()</code> 這個 google-code-prettify 的啟動函式。這整段程式，一樣利用 Y!UI 的 DOM，設定成在載入完畢後呼叫。</p>
<p>裝好之後，各位應該可以看到，在文件載入完全之前，程式碼列表裡面還不會有 syntax highlighting，字都是黑的。等到文件一載入完全，keywords 就會變色。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/932/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>升級到 wp-footnotes 1.4</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/929/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/929/#comments</comments>
		<pubDate>Thu, 14 Jun 2007 11:42:06 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[Blogging]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/articles/jeffhung/929/</guid>
		<description><![CDATA[自從啟用 footnotes plug-in 以後，我在編輯時，就方便了許多。不過，原本的&#160;footnotes 0.91 版，還是有一些小問題，讓我有些困擾。所以，剛剛我找了一下官方的 wordpress plug-in directory，發現 footnotes 已經更名為 wp-footnotes。測了一下，並照著原本的改法，將 &#60;span class=&#34;footnote&#34;&#62; 的標示法修正進去，再加上修了一些小 bug 後，順利升級到了 wp-footnotes 1.4 版。 在原本的 footnotes 0.91 版裡，是使用 while 迴圈搭配 strpos() 尋找註腳，也許是因為這樣，有時候在後台編輯時，會發生程式陷入無窮迴圈的錯誤。新版的 wp-footnotes 改用 preg_match_all() 搜尋註腳，希望效果會好一些。 不過，也許是因為改用了 preg_match_all()，原本只要修改 $footnote_open 與 $footnote_close 兩個常數變數的技法，反而失效了。因此我鑽了一下，發現這兩個常數，在丟給 preg_match_all() 之前，有先用 preg_quote() 先處理過。這本來是件好事，但壞就壞在，preg_quote() 預設會替很多 delimiters 前面加反斜線，包括 &#60; 與 &#62; 等。然而，在 preg_match_all() 這行的 regular expression 裡，FOOTNOTE_OPEN 與 [...]]]></description>
			<content:encoded><![CDATA[<p>自從<a href="http://www.jeffhung.net/blog/articles/jeffhung/505/">啟用 footnotes plug-in</a> 以後，我在編輯時，就方便了許多。不過，原本的&nbsp;footnotes 0.91 版，還是有一些小問題，讓我有些困擾。所以，剛剛我找了一下官方的 <a href="http://wordpress.org/extend/plugins/">wordpress plug-in directory</a>，發現 footnotes 已經更名為 <a href="http://wordpress.org/extend/plugins/wp-footnotes/">wp-footnotes</a>。測了一下，並照著原本的改法，將 <code class="inline_code">&lt;span class=&quot;footnote&quot;&gt;</code> 的標示法修正進去，再加上修了一些小 bug 後，順利升級到了 wp-footnotes 1.4 版。</p>
<p>在原本的 footnotes 0.91 版裡，是使用 <code class="inline_code">while</code> 迴圈搭配 <code class="inline_code"><a href="http://www.php.net/manual/en/function.strpos.php">strpos</a>()</code> 尋找註腳，也許是因為這樣，有時候在後台編輯時，會發生程式陷入無窮迴圈的錯誤。新版的 wp-footnotes 改用 <code class="inline_code"><a href="http://www.php.net/manual/en/function.preg-match-all.php">preg_match_all</a>()</code> 搜尋註腳，希望效果會好一些。</p>
<p>不過，也許是因為改用了 <code class="inline_code">preg_match_all()</code>，原本只要修改 <code class="inline_code">$footnote_open</code> 與 <code class="inline_code">$footnote_close</code> 兩個常數變數的技法，反而失效了。因此我鑽了一下，發現這兩個常數，在丟給 <code class="inline_code">preg_match_all()</code> 之前，有先用 <code class="inline_code"><a href="http://www.php.net/manual/en/function.preg-quote.php">preg_quote</a>()</code> 先處理過。這本來是件好事，但壞就壞在，<code class="inline_code">preg_quote()</code> 預設會替很多 delimiters 前面加反斜線，包括 <code class="inline_code">&lt;</code> 與 <code class="inline_code">&gt;</code> 等。然而，在 <code class="inline_code">preg_match_all()</code> 這行的 regular expression 裡，<code class="inline_code">FOOTNOTE_OPEN</code> 與 <code class="inline_code">FOOTNOTE_CLOSE</code> 所在的部份，其實式不需要替 <code class="inline_code">&lt;</code> 與 <code class="inline_code">&gt;</code> 加反斜線的，因而導致程式沒辦法正確地抓出註腳來。因此，我們應該告訴 <code class="inline_code">preg_quote()</code>，究竟哪些 delimiters 應該要加反斜線。改法如下：</p>
<pre class="code">
function swas_footnote($data) {
    global $post, $current_settings;

    // Check for and setup the starting number
    $start_number = (preg_match(&quot;|&lt;!\-\-startnum=(\d+)\-\-&gt;|&quot;,$data,$start_number_array)==1) ? $start_number_array[1] : 1;

    // Let's attempt this with Regex instead
    preg_match_all(&quot;/(&quot;.preg_quote(FOOTNOTE_OPEN<span class="emphasis">,'/()'</span>).&quot;|&lt;footnote&gt;)(.*)(&quot;.preg_quote(FOOTNOTE_CLOSE<span class="emphasis">,'/()'</span>).&quot;|&lt;\/footnote&gt;)/U&quot;, $data, $fo&nbsp;&nbsp;&nbsp; otnotes, PREG_SET_ORDER);

    ...
}</pre>
<p>將紅色的部份加上即可。這樣一來，我們就可以直接改程式一開頭定義 <code class="inline_code">FOOTNOTE_OPEN</code> 與&nbsp;<code class="inline_code">FOOTNOTE_CLOSE</code> 的地方，將註腳的包裹方式，換成我們的方式。如下：</p>
<pre class="code">
define('FOOTNOTE_OPEN',  '<span class="emphasis">&lt;span class=&quot;footnote&quot;&gt;</span>');
define('FOOTNOTE_CLOSE', '<span class="emphasis">&lt;/span&gt;</span>');</pre>
<p>不過，搜尋一下，可以發現原來的 <code class="inline_code">((</code> 與 <code class="inline_code">))</code>，在 <code class="inline_code">swas_footnote()</code> 的最尾端，被 <a href="http://en.wikipedia.org/wiki/Hard-coded">hard code</a> 進程式碼裡了，這當然是錯誤的。因此，將之修改成使用 <code class="inline_code">FOOTNOTE_OPEN</code> 與 <code class="inline_code">FOOTNOTE_CLOSE</code> 常數。如下：</p>
<pre class="code">
function swas_footnote($data) {
    ....

                $data = str_replace($note[0], $link_text, $data);
                <strike>$data = str_replace(' ((ref:' . ($identifer+1) . '))', $link_text, $data);</strike>
                <span class="emphasis">$data = str_replace(FOOTNOTE_OPEN.'ref:' . ($identifer+1) . FOOTNOTE_CLOSE, $link_text, $data);</span>
                $data = str_replace('&lt;footnote&gt;' . ($identifer+1) . '&lt;/footnote&gt;', $link_text, $data);
            }
            $data = $data.'&lt;/ol&gt;'.$current_settings['post_footnotes'];
        }else{
            foreach($footnotes as $identifier=&gt;$note){
                $data = str_replace($note[0], '', $data);
                <strike>$data = str_replace(' ((ref:' . ($identifer+1) . '))', '', $data);</strike>
                <span class="emphasis">$data = str_replace(FOOTNOTE_OPEN.'ref:' . ($identifer+1) . FOOTNOTE_CLOSE, '', $data);</span>
                $data = str_replace('&lt;footnote&gt;' . ($identifer+1) . '&lt;/footnote&gt;', '', $data);
            }
        }
    }
    return $data;
}</pre>
<p>另外，我在後端 note identifier options 那邊，將 before/after 設定成方括號，但在前端卻出不來。這又是一個小 bug，檢查了一下，發現原來是儲存這組設定的 <code class="inline_code">pre_identifier</code> 與 <code class="inline_code">post_identifier</code>，在真正要用時，卻被寫成了 <code class="inline_code">pre_link</code> 和 <code class="inline_code">post_link</code>。這應該是程式修改時所造成的疏漏，因為在舊版裡，這組設定確實是被叫做 <code class="inline_code">pre_link</code> 和 <code class="inline_code">post_link</code>。如下修正之即可：</p>
<pre class="code">
function swas_footnote($data) {
    ....

        if ($display) {

            $data = $data.$current_settings['pre_footnotes'].'&lt;ol start=&quot;'.$start_number.'&quot; class=&quot;footnotes&quot;&gt;';
            foreach($footnotes as $identifier=&gt;$note){
                $number = $start_number+$identifier;// What number is it? Used for back link and id.
                $data = $data.'&lt;li id=&quot;footnote-'.$number.'-'.$post-&gt;ID.'&quot; class=&quot;footnote&quot;&gt;'.$note[2].$current_settings['pre_backlink'].'&lt;a href=&quot;#footnote-link-'.$number.'-'.$post-&gt;ID.'&quot; class=&quot;footnote-link footnote-back-link&quot;&gt;'.$current_settings['backlink'].'&lt;/a&gt;'.$current_settings['post_backlink'].'&lt;/li&gt;';
                $link_text = ($current_settings['list_style_type'] != 'decimal') ? swas_convert_num($number, $current_settings['list_style_type']) : $number;
                <strike>$link_text = $current_settings['pre_link'].'&lt;a href=&quot;#footnote-'.$number.'-'.$post-&gt;ID.'&quot; id=&quot;footnote-link-'.$number.'-'.$post-&gt;ID.'&quot; class=&quot;footnote-link footnote-identifier-link&quot; title=&quot;'.strip_tags($footnotes[$number-1][2]).'&quot;&gt;'.$link_text.'&lt;/a&gt;'.$current_settings['post_link'];</strike>
                $link_text = $current_settings['<span class="emphasis">pre_identifier</span>'].'&lt;a href=&quot;#footnote-'.$number.'-'.$post-&gt;ID.'&quot; id=&quot;footnote-link-'.$number.'-'.$post-&gt;ID.'&quot; class=&quot;footnote-link footnote-identifier-link&quot; title=&quot;'.strip_tags($footnotes[$number-1][2]).'&quot;&gt;'.$link_text.'&lt;/a&gt;'.$current_settings['<span class="emphasis">post_identifier</span>'];
                if ($current_settings['superscript']) $link_text = '&lt;sup class=&quot;footnote-link-sup footnote-identifier-link-sup&quot;&gt;'.$link_text.'&lt;/sup&gt;';
    ....
}</pre>
<p>最後，再依照跑出來的 CSS classes，設定相對應的 styles 即可。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/929/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>五年前我的個人(用)網站</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/910/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/910/#comments</comments>
		<pubDate>Mon, 04 Jun 2007 18:26:56 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[Blogging]]></category>
		<category><![CDATA[Idea]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/articles/jeffhung/910/</guid>
		<description><![CDATA[今天在 IRC 裡跟 Qing 聊到怎麼爬 HemiDemi，提到五年前我自己也有寫過(個人用)的書籤模組。剛剛興起，就跑去 Internet Archive 把我以前的個人(用)網站挖出來回味。 我以前用的網址是 www.jeffhung.idv.tw，因為最便宜。以前的網站，基本上只是一個大雜燴式的首頁。從 archive 可以看出，這個大雜燴式的首頁，我從 2002 年六月，一直用到了 2005 年四月，差不多用了 3 年，然後才換成現在用的 wordpress 系統。 基本的構想是，幾乎所有事情都可以在首頁裡解決。每樣功能，被作成一個一個的區塊，我稱之為 weblet。約略在同一時期，Java 也有套類似的 framework，稱之為 portlet。我不清楚 portlet 的定義其實為何，因為我沒有研究過。但我對 weblet 的定義，約略等同於一個 desktop application 的視窗。 那時候沒有 AJAX 這種東西，所以沒有所謂「直接在 client 端執行的程式實體」這種概念。因此，weblet 後端有個 WebOS 引擎，貫穿 HTTP 的 stateless 天性，負責 weblet 的 persistency across HTTP requests。也就是說，WebOS 會負責在每次頁面切換時，將各個 weblet 喚醒，給予對應的 event，最後呼叫如 [...]]]></description>
			<content:encoded><![CDATA[<p><a target="_blank" href="http://flickr.com/photos/jeffhung/530187465/"><img border="2" align="right" alt="" style="padding: 5px; margin-left: 5px;" src="http://farm2.static.flickr.com/1253/530187465_9aba0206c0_m.jpg" /></a>今天在 IRC 裡跟 <a href="http://javaworld.com.tw/roller/page/qing">Qing</a> 聊到怎麼<a href="http://javaworld.com.tw/roller/page/qing?entry=2007_5_30_hemidemi_%E6%9B%B8%E7%B1%A4%E5%8C%AF%E5%87%BA%E5%B7%A5%E5%85%B7">爬 HemiDemi</a>，提到五年前我自己也有寫過(個人用)的書籤模組。剛剛興起，就跑去 <a href="http://www.archive.org/">Internet Archive</a> 把<a href="http://web.archive.org/web/*/http://www.jeffhung.idv.tw/">我以前的個人(用)網站</a>挖出來回味。</p>
<p>我以前用的網址是 www.jeffhung.idv.tw，因為最便宜。以前的網站，基本上只是一個大雜燴式的首頁。從 archive 可以看出，這個大雜燴式的首頁，我從 <a href="http://web.archive.org/web/20020602021642/http://www.jeffhung.idv.tw/">2002 年六月</a>，一直用到了 <a href="http://web.archive.org/web/20050412143523/http://www.jeffhung.idv.tw/">2005 年四月</a>，差不多用了 3 年，然後才換成現在用的 <a href="http://wordpress.org/">wordpress</a> 系統。</p>
<p>基本的構想是，幾乎所有事情都可以在首頁裡解決。每樣功能，被作成一個一個的區塊，我稱之為 weblet。約略在同一時期，Java 也有套類似的 framework，稱之為 <a href="http://en.wikipedia.org/wiki/Portlets">portlet</a>。我不清楚 portlet 的定義其實為何，因為我沒有研究過。但我對 weblet 的定義，約略等同於一個 desktop application 的視窗。</p>
<p>那時候沒有 AJAX 這種東西，所以沒有所謂「直接在 client 端執行的程式實體」這種概念。因此，weblet 後端有個 WebOS 引擎，貫穿 HTTP 的 stateless 天性，負責 weblet 的 persistency across HTTP requests。也就是說，WebOS 會負責在每次頁面切換時，將各個 weblet 喚醒，給予對應的 event，最後呼叫如 <code class="inline_code">OnPaint()</code> 之類的函式，讓每個 weblet 產生屬於自己那個區塊的 html。是故，靠著 WebOS 的協助，weblet 就像個簡單的 event-driven framework，成熟的 MVC 技術得以施行於其上。</p>
<p>WebOS 處理 event 的基本運作原理，和現在的 <a href="http://www.zkoss.org/">ZK</a> 差不多，不過 ZK 最後是靠 Ajax 在前端運作，但 WebOS 則是在後端命令 weblet 產生頁面。我不認為 web 應該做的跟 ZK 那樣 heavy-weight，那樣太慢了，web 沒有必要完全模擬 desktop。也因此，我將之取名作 weblet，取其「小程式」之意。</p>
<p>不過，那時的 WebOS 只有做了一些 concept prove 的工作，五年前的我，忙於準備研究所考試，然後又是繁重的碩士生活，因此我的網站，其實內部並不是真的靠 WebOS 驅動，而只是一堆簡單的 PHP 程式，把 weblet 的「外型」勾勒出來。</p>
<p align="center"><a href="http://flickr.com/photos/jeffhung/530201075/"><img src="http://farm2.static.flickr.com/1033/530201075_ad0d6e4857.jpg?v=0" alt="" /></a></p>
<p>整個網站由一塊一塊的 weblet 區塊組成，每個區塊右上角，有個控制樞紐，點按時會利用 DHTML 跑出選單，進行對這個 weblet 的各項操作，如設定、關閉、移動等，就好像 <a href="http://www.netvibes.com/">Netvibes</a> 那樣。</p>
<p>那時在市場上，我沒有看到 online rss reader 的存在，因此我最多的 weblet，就是顯示 <a href="http://en.wikipedia.org/wiki/Resource_Description_Framework">RDF</a> channel 的內容。由 crontab 定期呼叫程式抓取 channel 存成 rdf 檔，然後動態於首頁自動轉成 weblet 裡的列表。由於做 web bbs 的經驗，我認為已讀未讀標記十分的重要，因此在每個項目前面，都會有個 <code class="inline_code">[_]</code>，表示該項目未讀。</p>
<p>也許是因為我是從 rdf 開始玩起的，所以我認為 RDF/<a href="http://en.wikipedia.org/wiki/Rss">RSS</a> 應該是內容的摘要與指引，而非內容的載體。因此，weblet 並不以列出全文為目標。事實上，以 weblet 這種形式的 UI，也確實不適合全文的顯示。</p>
<p>不將 RSS視為內容的載體的另外一個原因是，我認為內容不應只包含堆砌出來的文字，連內容的呈現方式，也屬於內容的一種。舉例來說，程式碼如何在 blog 內文裡展現，文句裡的重點如何被施加各種強調的特效，都算是內容的一部分。從這個角度觀之，RSS 實在不是個足夠好的內容載體。既然全文 RSS 其實並不全文，那還不如只列出摘要，然後指引讀者回到真正內容的載體，來觀看全文。</p>
<p>那時候 blog 尚未蔚成風潮，因此我的內容來源少的可憐，但也少的剛剛好，用 weblet 統統塞在一頁，想逛的時候隨意瀏覽一下即可。但以現在來說，所訂閱的 feeds 太多，這樣的介面根本不敷使用了。這也是現在我很少用 netvibes 的原因。</p>
<p>那時用的最兇的，除了 rdf 以外，就屬右方的 Quick Links 了，這就是一開始說的，所謂我(個人用)的書籤模組。因為會統計我個人的使用偏好，所以用起來非常方便。不過，那時候書籤的對象，大都仍是以「站」為單位，而不像現在這樣，多以「內文」為單位。這個差異，我認為也是 web 2.0 的特徵之一。內容的歸納、整理、傳銷、散佈，多是在「站內」進行，因此我們需要拜訪各個「大站」，以取得內容。同時，在 web 1.0 時代，歸納、整理、傳銷、散佈做的好，就有了成為「大站」的資格。而在 web 2.0 時代，這些「內容的處理」，多是在「站際」進行。串連、social bookmarks、digg、sidebar widgets、rss reader 等等，有的以純然的中介者形式進行內容的處理，有的則化身千萬，埋藏於散佈各處的內容之中，成為 web 2.0 運行的血脈。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/910/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>升級到 wordpress 2.2</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/891/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/891/#comments</comments>
		<pubDate>Thu, 17 May 2007 02:31:37 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[Blogging]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/articles/jeffhung/891/</guid>
		<description><![CDATA[好像太簡單了：備份一下 database，下個 svn switch 就完工，成功升級到 WordPress 2.2。XD SHELL&#62; svn info 路徑: . URL: http://svn.automattic.com/wordpress/branches/2.1 檔案庫根目錄: http://svn.automattic.com/wordpress 檔案庫 UUID: 1a063a9b-81f0-0310-95a4-ce76da25c4cd 修訂版: 5173 節點種類: 目錄 排程: 正常 最後更新作者: ryan 最後修改修訂版: 5172 最後修改日期: 2007-04-03 08:33:57 +0800 (二, 03 4 2007) SHELL&#62; svn switch http://svn.automattic.com/wordpress/branches/2.2 U wp-rss.php U wp-login.php U wp-comments-post.php U wp-blog-header.php U wp-rdf.php A wp-includes/feed-rss2.php G wp-includes/default-filters.php [...]]]></description>
			<content:encoded><![CDATA[<p>好像太簡單了：備份一下 database，下個 <code class="inline_code">svn switch</code> 就完工，成功升級到 <a href="http://wordpress.org/development/2007/05/wordpress-22/">WordPress 2.2</a>。XD</p>
<pre class="code">
SHELL&gt; svn info
路徑: .
URL: http://svn.automattic.com/wordpress/branches/2.1
檔案庫根目錄: http://svn.automattic.com/wordpress
檔案庫 UUID: 1a063a9b-81f0-0310-95a4-ce76da25c4cd
修訂版: 5173
節點種類: 目錄
排程: 正常
最後更新作者: ryan
最後修改修訂版: 5172
最後修改日期: 2007-04-03 08:33:57 +0800 (二, 03  4 2007)

SHELL&gt; svn switch http://svn.automattic.com/wordpress/branches/2.2
U    wp-rss.php
U    wp-login.php
U    wp-comments-post.php
U    wp-blog-header.php
U    wp-rdf.php
A    wp-includes/feed-rss2.php
G    wp-includes/default-filters.php
U    wp-includes/plugin.php
...
U    wp-admin/categories.php
U    wp-admin/themes.php
U    wp-admin/upgrade-schema.php
更新至修訂版 5485.

SHELL&gt; svn info
路徑: .
URL: http://svn.automattic.com/wordpress/branches/2.2
檔案庫根目錄: http://svn.automattic.com/wordpress
檔案庫 UUID: 1a063a9b-81f0-0310-95a4-ce76da25c4cd
修訂版: 5485
節點種類: 目錄
排程: 正常
最後更新作者: ryan
最後修改修訂版: 5484
最後修改日期: 2007-05-17 01:48:31 +0800 (四, 17  5 2007)</pre>
<p>Switch 時，前面有 G 的是我 local 自己有改過的檔案，完整保留。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/891/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>放棄 twitter</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/844/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/844/#comments</comments>
		<pubDate>Mon, 26 Mar 2007 07:18:01 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[Blogging]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/articles/jeffhung/844/</guid>
		<description><![CDATA[一時性起，註冊了 twitter 來玩，然後裝了 twitter tools 整合進我的 blog 邊欄。剛開始用，一切還好。不過今天就出現怪問題了。 直接在編欄上要加新的 status，結果跟我說 invalid。本來以為是 twitter tools 的問題，好比說某個選項我沒有打開之類的。結果直接到 twitter 網站上寫 status，也是不行。所以，看來問題是出在 twitter 的 bug 了。 說老實話，我覺得 twitter 網站做的蠻醜的，為了這麼一個小小的功能，還要大老遠跟這個網站結上關係，個人覺得很蠢。Mash-up 的問題就在於，常會製造出無法控制的耦合問題。例如假使某天 Google Map API 改版了，然後全世界有跟 Google Map 做 mash-up 的網站就統統爆炸了。個人網站還好，自認倒楣就是了，商業網站就麻煩些，不過也可以一皮天下無難事，但若是有牽涉到金錢賠償的問題的話，那麻煩就大了。 所以我決定還是放棄 twitter 好了，其社群功能其實沒有吸引我的地方。]]></description>
			<content:encoded><![CDATA[<p>一時性起，註冊了 <a href="http://twitter.com/">twitter</a> 來玩，然後裝了 <a href="http://alexking.org/projects/wordpress">twitter tools</a> 整合進我的 blog 邊欄。剛開始用，一切還好。不過今天就出現怪問題了。</p>
<p>直接在編欄上要加新的 status，結果跟我說 invalid。本來以為是 twitter tools 的問題，好比說某個選項我沒有打開之類的。結果直接到 twitter 網站上寫 status，也是不行。所以，看來問題是出在 twitter 的 bug 了。</p>
<p>說老實話，我覺得 twitter 網站做的蠻醜的，為了這麼一個小小的功能，還要大老遠跟這個網站結上關係，個人覺得很蠢。Mash-up 的問題就在於，常會製造出無法控制的耦合問題。例如假使某天 Google Map API 改版了，然後全世界有跟 Google Map 做 mash-up 的網站就統統爆炸了。個人網站還好，自認倒楣就是了，商業網站就麻煩些，不過也可以一皮天下無難事，但若是有牽涉到金錢賠償的問題的話，那麻煩就大了。</p>
<p>所以我決定還是放棄 twitter 好了，其社群功能其實沒有吸引我的地方。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/844/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>公告：本站預定於 2007-03-24~25 移機</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/839/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/839/#comments</comments>
		<pubDate>Tue, 20 Mar 2007 04:15:26 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[Blogging]]></category>
		<category><![CDATA[announce]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/articles/jeffhung/839/</guid>
		<description><![CDATA[我要搬新家了，所以預定於 2007-03-24~25 將本站移機至新家，改用中華電信 ADSL 固定制 4M/1M，將可以提昇上傳速度，讓造訪本站的朋友，更加快速。 是故： 本站將於 2007-03-23 星期五凌晨 00:00 進行備份。也就是說，備份的時間點設於 2007-03-23 00:00。從這個時間點開始，至移機完成前，所新增的任何內容、留言，不一定能夠保留。 DNS 的轉移可能需要一點時間，如果您連不上本站，請再多等一、兩天再試試。 視移機狀況，有可能進行系統更新。但因為人生大事將屆，所以很忙，故也許不會升級系統，將另尋時間進行。 希望一切平安順利，要不然就麻煩了，因為我將有好一大段時間，沒辦法待在機器附近。]]></description>
			<content:encoded><![CDATA[<p>我要搬新家了，所以預定於 2007-03-24~25 將本站移機至新家，改用中華電信 ADSL 固定制 4M/1M，將可以提昇上傳速度，讓造訪本站的朋友，更加快速。</p>
<p>是故：</p>
<ul>
<li>本站將於 2007-03-23 星期五凌晨 00:00 進行備份。也就是說，備份的時間點設於 2007-03-23 00:00。從這個時間點開始，至移機完成前，所新增的任何內容、留言，不一定能夠保留。</li>
<li>DNS 的轉移可能需要一點時間，如果您連不上本站，請再多等一、兩天再試試。</li>
<li>視移機狀況，有可能進行系統更新。但因為人生大事將屆，所以很忙，故也許不會升級系統，將另尋時間進行。</li>
</ul>
<p>希望一切平安順利，要不然就麻煩了，因為我將有好一大段時間，沒辦法待在機器附近。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/839/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Upgrading to wordpress 2.1 trunk</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/780/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/780/#comments</comments>
		<pubDate>Tue, 23 Jan 2007 05:20:23 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[Blogging]]></category>
		<category><![CDATA[opensource]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/articles/jeffhung/780/</guid>
		<description><![CDATA[從 clsung 那邊看到，WordPress 2.1 &#8220;Ella&#8221; 出了，想想也蠻久沒升級了，再加上是應該要處理一下 WordPress 2.0.7 解掉的 security hole，所以就來升級我的 blog 版本。 照往例一樣是採 svn update 的方法升級： 先備份資料庫。 然後到主目錄下 svn update，升級到最新 trunk 版。這次我是從 r4497 升級到 r4784，差距蠻大的， 用 svn diff 檢查了一下 local modification 沒有爛掉。 用瀏覽器進管理介面，畫面顯示訊息說要 upgrade database，執行後就一切正常了。 這次的升級，應該是成功的，至少到目前為止，看起來沒什麼異狀發生。整個過程不到 5 min，簡單快速，爽。]]></description>
			<content:encoded><![CDATA[<p>從 clsung 那邊<a href="http://blog.dragon2.net/2007/01/23/426.php">看到</a>，<a href="http://wordpress.org/development/2007/01/ella-21/">WordPress 2.1 &ldquo;Ella&rdquo;</a> 出了，想想也蠻久沒升級了，再加上是應該要處理一下 <a href="http://wordpress.org/development/2007/01/wordpress-207/">WordPress 2.0.7</a> 解掉的 security hole，所以就來升級我的 blog 版本。</p>
<p>照往例一樣是採 <code class="inline_code">svn update</code> 的方法升級：</p>
<ol>
<li>先備份資料庫。</li>
<li>然後到主目錄下 <code class="inline_code">svn update</code>，升級到最新 trunk 版。這次我是從 r4497 升級到 r4784，差距蠻大的，</li>
<li>用 <code class="inline_code">svn diff</code> 檢查了一下 local modification 沒有爛掉。</li>
<li>用瀏覽器進管理介面，畫面顯示訊息說要 upgrade database，執行後就一切正常了。</li>
</ol>
<p>這次的升級，應該是成功的，至少到目前為止，看起來沒什麼異狀發生。整個過程不到 5 min，簡單快速，爽。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/780/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>安裝 DupPrevent</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/754/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/754/#comments</comments>
		<pubDate>Sun, 31 Dec 2006 05:34:14 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[Blogging]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/articles/jeffhung/754/</guid>
		<description><![CDATA[自從裝了 Google 搜尋後，就想要弄這樣一個功能。剛剛從黑米看到 ijliao 的這篇《DupPrevent》，啊哈，這正是我要的。 DupPrevent 可以幫您在非單筆文章的頁面裡，加上 NOINDEX 標籤，讓搜尋引擎不要去搜尋那些頁面。可以「避免因為重複內容而被 search engine 處罰。」 不過，我想要這個功能的原因，跟提昇 page rank 與否無關，而是這樣自己搜尋自己的 blog 才方便，不會有一堆重複內容出現啊。]]></description>
			<content:encoded><![CDATA[<p>自從裝了 Google 搜尋後，就想要弄這樣一個功能。剛剛<a href="http://www.hemidemi.com/group/WordPress/bookmark/info/40903">從黑米看到</a> ijliao 的這篇《<a href="http://blog.ijliao.info/archives/2006/12/22/2776/">DupPrevent</a>》，啊哈，這正是我要的。</p>
<p><a href="http://wpseo.com/wordpress-plugin-to-prevent-duplicate-content-penalty_47.htm">DupPrevent</a> 可以幫您在非單筆文章的頁面裡，加上 <code class="inline_code">NOINDEX</code> 標籤，讓搜尋引擎不要去搜尋那些頁面。可以「避免因為重複內容而被 search engine 處罰。」</p>
<p>不過，我想要這個功能的原因，跟提昇 page rank 與否無關，而是這樣自己搜尋自己的 blog 才方便，不會有一堆重複內容出現啊。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/754/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

