- PHP5 有提供 ArrayAccess Interface 讓自製的 Classes/Objects 也有如陣列 (Array) 型別用 [] 取存方式。 SPL 也有實作 ArrayObject 。
- 但有一個關鍵的差異是新增陣列項目,一般陣列在無鍵值時是新增一個鍵值為最大整數的項目,鍵值為 null 時則新增一個鍵值為空字串的項目,自製物件是分不出兩者的差異的(無鍵值與 null 都視為 null)。請看下面範例:
<?php class ArrayAccessObject implements ArrayAccess{ private $position = 0; private $_array = array(); /* impements ArrayAccess */ public function offsetSet($offset, $value) { var_dump($offset); $this->_array[$offset] = $value; } public function offsetExists($offset) { return isset($this->_array[$offset]); } public function offsetUnset($offset) { unset($this->_array[$offset]); } public function offsetGet($offset) { return isset($this->_array[$offset]) ? $this->_array[$offset] : null; } } $a = array(); $b = new ArrayObject(); $c = new ArrayAccessObject(); $a[] = 'nothing'; $b[] = 'nothing'; $c[] = 'nothing'; $a[null] = 'null'; $b[null] = 'null'; $c[null] = 'null'; var_dump($a); var_dump($b); var_dump($c); /* output */ NULL NULL array(2) { [0]=> string(7) "nothing" [""]=> string(4) "null" } object(ArrayObject)#1 (1) { ["storage":"ArrayObject":private]=> array(2) { [0]=> string(7) "nothing" [1]=> string(4) "null" } } object(ArrayAccessObject)#2 (2) { ["position":"ArrayAccessObject":private]=> int(0) ["_array":"ArrayAccessObject":private]=> array(1) { [""]=> string(4) "null" } }
歡迎來到小豬圈!
2009-08-11
Array 、 ArrayAccess 與 ArrayObject
2009-08-03
base_convert 的限制
- 剛稍微測試 PHP 函數 base_convert() ,數字
約大於 2^54 以上轉換就會出現錯誤。 - 2009-08-06 更新:數字超過十進位的 9,007,199,254,740,992 即 2^53 以上,轉換就會出現錯誤。
- 2009-08-09 更新:MySQL 有提供相同功能的函數 CONV(),文件指出最大值為 2^64 (十進位的 18,446,744,073,709,551,615,輸入大於這個值都會傳回相同於這個值的結果),目前測試轉換沒有問題。另外有一點差異是輸出結果為英文大寫字母。
2009-08-01
Apache HTTPD 預設的 .ht* 小技巧
- httpd.conf 預設都有下列這一段,避免 .ht 開頭(無檔名)的檔案被讀取
# # The following lines prevent .htaccess and .htpasswd files from being # viewed by Web clients. # <FilesMatch "^\.ht"> Order allow,deny Deny from all Satisfy All </FilesMatch> - 雖然從網址無法存取,但依然可以從程式讀取。利用這一點,可以將設定檔取為 .htconfig 之類的。
2009-07-26
在 Windows 下編譯 Sphinx PHP 擴充模組
- 從 PECL :: Package :: sphinx 下載的原始碼,還無法直接編譯,從 config.w32 看來還需要 libsphinxclient.lib 和 sphinxclient.h。
- 雖然從 Sphinx 中 (在原始碼的 api\libsphinxclient 目錄裡) 自行編譯了 libsphinxclient.lib ,但還是派不上用場。
- 後來是修改了 config.w32 ,把這行:
EXTENSION("sphinx", "sphinx.c");改寫成EXTENSION("sphinx", "sphinx.c sphinxclient.c");加在一起編譯才成功的。 - Sphinx PHP Extension
似乎沒辨法編成獨立的 DLL 檔。將上述那行加上第三個參數為 true 就行了:EXTENSION("sphinx", "sphinx.c sphinxclient.c", true); - Sphinx 原始碼也有提供 PHP 腳本版本的 API (api/sphinxapi.php) ,直接 include 即可。
2009-07-25
Sphinx 全文檢索引擎
- Sphinx 0.9.8.1 加上 MySQL 5.1 在建立索引時會出現 column number 1 has no name 的錯誤訊息,改用目前最新 Sphinx 0.9.9 就行了。
- 安裝成 Windows Service 時要明確指定 sphinx.conf 的路徑:
searchd.exe --install --config C:\sphinx\sphinx.conf --servicename SphinxSearch
不然會無法啟動並出現 service terminated unexpectedly 錯誤訊息。 - 另外也要記得建立 log 、 query_log 、 pid_file 所指定的目錄。
- 下載 Sphinx 並壓縮至 C:\sphinx
- 依 sphinx.conf.in 或 sphinx-min.conf.in 編輯設定檔,並另存為 sphinx.conf 。
- 將工作目錄移至 cd \sphinx\bin
- 安裝成 Windows Services
searchd.exe --install --config C:\sphinx\sphinx.conf --servicename SphinxSearch
- 建立索引
indexer.exe --config C:\sphinx\sphinx.conf --all
- 測試搜尋,假設搜尋目標為 target-word
search.exe --config C:\sphinx\sphinx.conf --any target-word
- 若要移除 Windows Services
searchd.exe --delete --servicename SphinxSearch
2009-07-24
在 Windows 上自行編譯 PHP
- 自行編譯 PHP 比想像中簡單多了,PHP wiki 已經整理的很完善。文末的編譯步驟是從 PHP 文件 (PHP: Building from source - Manual) 提供簡易指南中,依我個人情況修改而來。
- 比較麻煩的地方是要收集 Library 與 Header 檔,像 Apache httpd 得選自訂安裝才有附那些檔案。「PHP: internals:windows:libs [PHP Wiki]」這裡整理了大部份的檔案。
- 我初次編譯使用的是 Windows SDK for Windows Server 2008 and .NET Framework 3.5 ,在執行 nmake 時出現下列錯誤訊息
"" -h win32\ -r ..\Release_TS\ -x ..\Release_TS\ win32\build\wsyslog.mc '-h' is not recognized as an internal or external command, operable program or batch file.
查看 Makefile 發現是少了 MC - Message Compiler (MC.exe) 這個東東,“mc.exe is missing in the Visual Studio 2008 Express SDK | Microsoft Connect”這篇指出似乎是該版本的 Windows SDK 沒附的關係。 - browscap.c 出現幾個 § (section sign) 符號造成編譯中斷,用 Firefox 瀏覽後轉存即可(我遇到?字元的問題都是這樣解決的)。
- 下載並安裝 VC ,Microsoft Visual C++ 2008 Express Edition
- 下載並安裝 Windows SDK ,Microsoft Windows SDK for Windows 7 and .NET Framework 3.5 SP1: RC
- 複製 C:\Program Files\Microsoft SDKs\Windows\v7.0\Include\WinResrc.h 並更名為 winres.h 到同一目錄下。舊的文件有這條項目,似乎是用來解決某些問題,但我並沒有遇到就是了。
- 建立一個工作目錄,這裡以 C:\php-sdk 為例。
- 下載 PHP 原始碼並解壓縮至 C:\php-sdk ,這裡以 php-5.3.0 為例。
- 下載 http://pecl2.php.net/downloads/php-windows-builds/php-libs/binary-tools.zip 並解壓縮至 C:\php-sdk 。
- 依預設的搜尋路徑 (參見原始碼中 php-5.3.0\win32\build\config.w32 第 227 行,也可以自訂 --with-php-build=..\deps) 建立一個存放相關檔案的目錄 C:\php-sdk\deps 。並至 http://wiki.php.net/internals/windows/libs 下載所需檔案解壓至該目錄。
- 從開始功能表裡執行 Windows SDK - CMD Shell ,並輸入下列指令。
- SetEnv.cmd /x86 /xp /release 設定編譯模式。
- SET PATH=%PATH%;C:\php-sdk\bin;
- cd \php-sdk\php-5.3.0 (接下來的指令必須在 PHP 原始碼的根目錄下執行)
- cscript.exe /nologo win32\build\buildconf.js
- cscript.exe /nologo configure.js --help (非必要,查看可用參數)
- cscript.exe /nologo configure.js --enable-object-out-dir=.. --disable-all (這裡參數依需求而有所不同)。
- nmake (開始編譯,需要一段時間)。
- 最終的目錄結構會類似下列這樣:
+-C:\php-sdk | +-bin | | --bison.exe | | --bison.simple | | --... | +-deps | | +-bin | | +-include | | --httpd.h (來自 Apache httpd) | | --... | | +-lib | | --libiconv.lib (來自 GNU libiconv) | | --libxml2.lib | | --... | +-php-5.3.0 (PHP 原始碼) | | +-build | | +-win32 | | +-... | +-Release_TS (輸出編譯結果的目錄) | | +-...
- nmake install (安裝編譯的結果,預設安裝至 C:\php5)。
2009-07-15
2009-07-07
The Sims 3 意外的好玩
- 因為遊戲主題並不合我胃口的關系,我並沒有玩過前面兩代,沒想到三代一玩就停不下來。不過大部份時間都在蓋房子就是了。
- 官方的人物模組做不出日式虛擬人物的風格(瓜子臉)。
- 遊戲操縱的角色在以家庭為單位,意指一個家有多少小人,你就要控制多少小人。雖然一次控制一個小人是有點少,但一次兩個(或以上)就有點麻煩了。
- 很多飾品真是只是裝飾用的,能多一點可互動的物件會更好。
- 上下班的共乘車不能取消,也不能設定成慢跑或開車。
- 目前東西還不算多,期待資料片的發行。
- 我對遊戲的評價分級:
- 好玩:玩完一遍會想繼續再玩的,就像 The Sims 3 和前陣子的 Fallout 3。
- 普通:玩過一遍就好,像是“Tom Clancy's H.A.W.X”
- 不好玩:連一遍都玩不下去,最近的例子是“Tom Clancy's End War”和“King's Bounty: The Legend”。
- 這遊戲某方面來說真實的令人感到恐怖,即便創立的角色都與我本人迥異,但還是常有在過現實生活的錯覺…
2009-06-23
[已解決] 安裝 Apache HTTPD 時出現 Installation Wizard Interrupted
- 從之前(參見:“安裝 Apache HTTPD 失敗 Installation Wizard Interrupted”一文)至今一直存在的問題,今天終於解決了!方法就是:將網路斷線再安裝即可。
2009-06-21
關於生物特徵辨識
想起之前玩過的眾多遊戲,只要是得用指紋、虹膜等個人特徵作為鑰匙才能開啟的門,最後一定得勞駕後人將當事者的手指頭、眼珠血淋淋地送到門面前開門。到底,人類要什麼時候,才會學到教訓?
出自“扁蟲窩: 戰神(God of War)十大衰尾路人”一文。- 如果要避免被截肢的情況,做手掌的指紋及靜脈辨識的同時要測量脈搏,虹膜及視網膜辨識時要順便驗一下光之類的。
2009-05-13
在 Windows Apache 上同時執行 PHP4 與 PHP5
- 將 PHP4 與 PHP5 分別以 CGI 和 Apache module 模式執行,以副檔名 .php4 與 .php 分辨執行的版本。
- 在 httpd.conf 加入
<Directory "C:/php4"> AllowOverride None Options None Order allow,deny Allow from all </Directory> # PHP 4 #"C:/php4/" 這裡尾端必須要加上斜線 ScriptAlias /php/ "C:/php4/" AddHandler php4-script .php4 Action php4-script "/php/php.exe" # PHP 5 LoadModule php5_module "C:/php5/php5apache2_2.dll" AddType application/x-httpd-php .php PHPIniDir "C:/php5"
2009-04-29
在 Google App Engine 上執行 PHP
- 執行 PHP 是我申請 Google App Engine 的主要目的,利用 Quercus 執行簡單腳本是沒有問題。但麻煩的是 Datastore 的部份,不但沒辨法用 PDO 存取,而且 Datastore 也跟關聯式資料庫差很多,存取資料庫的部份基本上得要重寫。
- 另一個麻煩是,我在 Java 5 發行之前就沒有再接觸 Java 了,熊熊看不懂 JDO Annotations 跟 JPA 這些 Java 5 以後的新功能(囧),不過還算是小事就是了。
2009-04-28
申請到了 Google App Engine 試用
- 日前在看到 Google App Engine 支援 Java 的消息同時,才知道這世界上有人實作 PHP in JAVA,一個叫 Quercus 的東西。雖然是個詭異的產品,不過這種情況(GAE不支援PHP)還真的派的上用場。
- 雖然我申請時沒辨法收到 Google 的認證簡訊 (SMS),不過再回報後兩天還是成功啟用。
2009-04-27
2009-04-25
用字串索引存取陣列要加上引號
- 陣列的索引是字串型態的話,一定要加上引號,雖然不加引號也可以執行,但 PHP 會先嘗試以常數去解譯,所以可能產生預料外的結果。而如果沒有對應到的常數,再嘗試以字串解譯,並同時會輸出 E_NOTICE 影嚮效能。
- 整數的索引也可以用字串(加引號)的方式取存,但用整數存取速度比較快。
- 在建立陣列或其項目時,索引是十進位的數字的話會自動轉成整數。
<?php define('string_index', 'unexpected'); $a = array( 'string_index' => 'string_index', 'unexpected' => 'unexpected'); $b = array( '-1' => 0, '1' => 1, '02' => 2, '0x3' => 3 ); echo $a['string_index']; // output: string_index echo $a[string_index]; // output: unexpected var_dump($b); /* output array ( -1 => int 0 1 => int 1 '02' => int 2 '0x3' => int 3 ) */ ?>
2009-04-22
將字串分割為字元陣列
- PHP 支援用陣列的方式存取字串的字元
$string[1],但不能直接將字串用在迴圈上。 - 上述方式與 str_split() 會有中文斷字的問題,preg_split() 沒有加 u (utf-8 mode)修飾字符也會有一樣問題。
- 這種情況下 mb_split 派不上用場,雖然支援 regular expression 但不能用空的 pattern (不用 start/end delimiter)。
- 兩個解決方案之一是用 mb_* 自已寫函式處理,另一個就是用 preg_split() 加上 u 修飾字符,見範例:
<?php function string_to_array ($string) { $array = array(); $strlen = mb_strlen($string); for ($i=0; $i<$strlen; $i++) { $array[] = mb_substr($string, $i, 1, 'UTF-8'); } return $array; } $string = '中文字測試'; str_split($string); preg_split("//", $string); mb_split("", $string); // Warning: mb_split(): Empty regular expression preg_split("//u", $string); //This modifier is available from PHP 4.1.0/Unix and from PHP 4.2.3/win32 var_dump(string_to_array($string)); ?>
寫 PHP 要注意的事項 效能篇
- 用 isset 取代 strlen 檢查字串最小長度,見 PHP: Strings - Manual 中 String access and modification by character 一節。
<?php $string = 'aaabbb'; $string2 = 'aaabbbcccddd'; var_dump((strlen($string) > 9) ?true:false);//false var_dump((strlen($string2) > 9)?true:false);//true var_dump((isset($string[9])) ?true:false);//false var_dump((isset($string2[9])) ?true:false);//true ?> - 字串用單引號 (') 標示比雙引號 (") 快,但在嵌入超過一、二個變數以上時,情況就相反了。
<?php $string = '中文字測試'; $string = '中文字' . $string . '測試'; $string = "中文字測試"; $string = "中文字{$string}測試"; ?> - 在相同結果的情況下,儘量使用字串類函式取代 Regular Expressions 函式
- 在存取整個檔案時 file_get_contents/file_put_contents 比自已用 fopen 快,remote 的情況似乎相反。
- is_file 比 file_exists 快四、五倍,不過似乎要注意在大量執行緒下的情況。
- 用 ++$i 比 $i++ 快,但我測試的結果差距非常小。
- 優先使用內建常數,再找內建函式,再來才考慮自行運算
- 用 PHP_VERSION 取代 phpversion(),而用 version_compare() 比較版本。
- 用 M_PI 取代 pi() ,以及其它 M_* 開頭預先計算好的值。
- DATE_ATOM 及其它 DATE_* 常數。
- 陣列的索引是字串型態的話,一定要加上引號,雖然不加引號也可以執行,但會產生 E_NOTICE 影嚮效能。整數的索引也可以用字串(加引號)的方式取存,但用整數比較快,參見:用字串索引存取陣列要加上引號。
- 類別建構式(Class constructor)使用 PHP4 版,跟類別同名的函式,比用 PHP5 版 __construct 快約兩倍,這是我在測試版本相容性時發現的,原因不明。
2009-04-21
查注音函式
- 利用 xcin 的表格做查詢注音符號的依據。
<?php function findZhuyins($word, $cinTable = 'bopomofo.cin') { static $data = null; static $keyMap = null; $result = array(); if (!$data) { $data = file_get_contents($cinTable); $pattern = "/%keyname\s+begin\s+(.+?)\s+%keyname\s+end/uis"; //找出按鍵對應字根的區段 preg_match($pattern, $data, $matches); $pattern = "/(.)\s+(.)\s+/ui"; preg_match_all($pattern, $matches[1], $matches ); $keyMap = $matches; } $pattern = "/\n(.+)\s+{$word}/ui"; preg_match_all($pattern, $data, $matches ); foreach ($matches[1] as $key => $value) { $ary = str_split($value); $result[$key] = ''; foreach ($ary as $value2) { $idx = array_search($value2, $keyMap[1]); $result[$key] .= $keyMap[2][$idx]; } } return $result; } var_dump( findZhuyins("得")); ?> - 注音符號的 cin 表格可以到 OXIM 專案的 FTP(ftp://ftp.opendesktop.org.tw/odp/others/OXIM/cin_tables/)下載,cin 表格清單。
- 中文轉注音(PHP)
2009-04-18
寫 PHP 要注意的事項
程式可攜性
- 使用內建常數 DIRECTORY_SEPARATOR
<?php include dirname(__FILE__) . DIRECTORY_SEPARATOR . 'some.php'; ?>大部份情況下直接使用 / 就可以了,除了在展開由系統取得的路徑時,如:<?php var_dump( explode(DIRECTORY_SEPARATOR, getcwd()) ); ?> - 使用內建常數 PATH_SEPARATOR
<?php $path = '/usr/lib/pear'; set_include_path(get_include_path() . PATH_SEPARATOR . $path); ?> - 使用下列兩種 PHP 標籤 (PHP: Escaping from HTML - Manual):
<?php echo phpversion(); ?> <script language="php"> echo phpversion(); </script>不要用簡短及 ASP 風格的 PHP 標籤:<? echo phpversion(); ?> <?= phpversion(); ?> <% echo phpversion(); %> <%= phpversion(); %>
- 以零開頭的整數進位制,見 PHP: Integers - Manual:
<?php $a = 1234; // decimal number $a = -123; // a negative number $a = 0123; // octal number (equivalent to 83 decimal) $a = 0x1A; // hexadecimal number (equivalent to 26 decimal) ?> - 在迴圈中使用參照 (reference) 要注意離開迴圈後參照還是有效。
<?php $array = array( 'aaa', 'bbb', 'ccc'); foreach($array as &$value) { $value = $value . 'ddd'; } $value = 'test'; var_dump($array); // $array[2] = 'test' $array2 = array( 'aaa', 'bbb', 'ccc'); foreach($array2 as $key => $item) { $array2[$key] = $item . 'ddd'; } $item = 'test'; var_dump($array2); ?>
2009-04-16
2009-04-08
強制下載及預設檔名 HTTP-Header: Content-Disposition
- 加入 Content-Disposition 這項 header 即可。
<?php $filename = 'test.htm'; header("Content-type: text/plain"); header("Content-Disposition: attachment; filename=$filename"); readfile($filename); ?>
2009-03-31
自製的 PHP 模版引擎:Classifield
- Classifield 的主要特色是將模板語法嵌入 HTML 元素的 class 屬性裡。
- 絕大部份的 HTML 元素都有 class 屬性,而且可以輸入複數的值,不會影嚮既有的 CSS class selector 。
- 沒有 class 屬性的 HTML 元素有:html 、 head 、 title 、 meta 、 link 、 param script 、 style。
- Classifield 的原始碼可以到 Google Code (http://code.google.com/p/classifield/)下載。
- Classifield 使用(接近)純碎 HTML 的模板,幾項特色或優缺點:
- 模板可以直接用瀏覽器預覽,以及可以被驗証 (參見:The W3C Markup Validation Service)。
- 分離模板邏輯與模板語法,將程式與美工人員的分工更為明確。
- 模板不需要插入 PHP 程式碼、模板專用的語法或其它 HTML 以外的語法,對負責模板設計美工的而言,較為友善。
- 模板能被任何一般文字網頁編輯器,或所見即所得的網頁編輯器正確的開啟。
- 承上,模板能在所見即所得的網頁編輯器裡編寫模板的語法。以 PHP (本身也是模板引擎) 插入變數到元素的屬性值裡為例:
<div <?php echo $var1?>="<?=$var2?>"></div>
部份編輯器會限制或自動編碼元素屬性欄位。 - 模板語法可以結合網頁結構,下為 Smarty 與 Classifield 的差別:
<ul> {foreach from=$myArray item=foo} <li>{$foo}</li> {/foreach} </ul><ul class="php-foreach-myArray-as-foo"> <li class="php-echo-foo"></li> </ul>
- 使用即有的技術,減少學習門檻。
- 需要 DOM lib 剖析模板,降低執行時的效能與提高記憶體需求。
- 需要其它選擇元素的方式,如QueryTemplates使用的 CSS selector (by phpQuery)
- 關於分離模板邏輯與模板語法,此點可參考另一個模板引擎 QueryTemplates,該模板引擎做的比較徹底。以及該作者的文章(Pure HTML templates theory « Personal devlog)。
2009-03-02
Demon's Souls 惡魔之魂 [Updated: 2009-05-18]

- 破關心得:這遊戲除了「難度」以外,沒什麼內容(汗)。NPC少、對話少(而且還嘴賤),武器、防具、道具都少,連主線劇情都是淡淡的帶過而已。遊戲畫面與氣氛設計的很棒,但如果是對像我一樣偏好受劇情而非挑戰難度的人來話,這片可以說是地雷片一枚。
- 雖然破關花了很多時間,但大部份的時間都花在重玩。主要的遊戲難度來自於每隻小怪都要小心應對,不然很容易陰溝裡翻船。第一次玩連第一關(1-1)就花了半天!
- 大部份長註魔法不能同時使用,浮游箭例外。
- 刷魂可以裝強慾之戒加白銀之鐲(女用),再加渴求(黃之魂)。
- 初期貴族的靈魂箭(魔法)超強,有耐心一點的話還可以殺龍!殺龍的地點在1-2箭塔上,趁噴火時攻擊,一次扣 19 HP ,約半小時可以擊斃火龍,可另外準備兩、三瓶香料。
- Demon's Souls デモンズソウル攻略Wiki - livedoor Wiki(ウィキ)
- Demon's Souls (Demons Souls,デモンズソウル) 攻略簿 マップ付 日文攻略,有部份地圖。
- 惡魔靈魂 哈啦板 - 巴哈姆特電玩資訊站。
- 楔之神殿之旅
- 等同於教學關卡,可以選擇跳過
- 遇到教學關卡的 BOSS (擴散尖兵;有翅膀的肥仔)時,基本上是一定會被幹掉送走的(劇情),但其實是可以打倒它的。
- 當他發動攻擊時往他揮刀的手的方向滾,飛起來的時候要後退。
- 1-1
- 這關過了以後(打倒BOSS史萊姆),才會出現火防女與要人,跟要人對話後才可以去其它關卡。
- 救王子的地方可以拿盜賊戒指,可以減少被敵人發覺的距離,其它遊戲設計類似的道具大都沒什麼用,但這個道具在本遊戲非常實用!
- 1-2 高塔 Boss 魂學魔法:絕對防護。
- 1-3 殺了貴族戴帽子可以去救魔女。
- 1-4 在這關的第二次遇到可以殺龍、打這關 BOSS 之前是最後升級的機會、被 BOSS 抓到等級會下降
- 2-1
- 純黑時,在有人丟石頭的那邊電梯下方有原生惡魔。
- 2-2
- 將這關 Boss 魂拿去給 2-1 的鐵匠,就可用 Boss 魂打造武具。
- 魔法與奇蹟雙修者刷黑,到垂直落下的路線中途,打倒黑色 NPC 可拿獸之護符。
- 2-3 龍之魂學的魔法火之嵐,威力大但耗魔也大
- 3-1 拿盜賊套裝防毒 救賢者
- 3-2
- 這關 Boss 我覺得是本遊戲最難的!除了場地狹長加上 Boss 橫衝亂撞之外,打到一定時間另一隻小惡魔就會加入混戰,建議連線合作或用魔法:死之雲。
- 原生惡魔在底層某處…。
- 3-3 Boss 建議離線、黃之魂學浮游箭(魔力31時,對有效的敵人攻擊約靈魂光的五倍)
- 4-1
- 黑骷髏後面可以拿欠月彎刀(回MP),也可以自已打造就是了。
- 肥之魂打造屠刀,該 Boss 魂還可學奇跡:再生,但除了收集完全不值得學。
- 4-2
- 刷魂(死神+黑雙刀骷髏約 11k~16k)。
- 原生惡魔在入口旁的懸崖邊。
- 勇士之魂打造打寶刀(該魂還可學奇跡:復活,死亡時會立即復活但沒有無敵時間,不如魔法:絕對防護)。
- 4-3 嵐之魂學反魔法領域
- 5-1 蟲之魂學毒之雲或治療
- 5-2 原生惡魔在往蛞蝓巢的樓梯入口處。
- 5-3
- 聖騎士的暗銀盾可以防魔法(靈魂箭之類)。
- 聖女 Boss 的純血魂可以學死之雲,對 3-2 Boss 尤是。
2009-02-20
握機車油門剎車的方法
- 我個人是用拇指、食指與小拇指握油門手把,中指與無名指按剎車。跟網路上推薦用食指和中指按剎車不同,應該是我的食指比無名指短關係。
- 僅用拇指和食指握油門的話,真的很容易在巔頗時鬆手,台灣的柏油路實在是有夠“平”的。
- Mobile01 手套穿戴問題與握油門方式?
2009-02-14
SQL identifier 識別符號
- SQLite 可以使用識別符號單引號 'keyword'、"keyword"、[keyword]、`keyword`。
- MySQL 預設是使用 `keyword` ,可以設定 ANSI_QUOTES 來使用 "keyword"。
- 石頭閒語:Oracle 的表格、欄位名稱都要大寫嗎? - 樂多日誌
- SQLite Query Language: SQLite Keywords
- MySQL :: MySQL 5.0 Reference Manual :: 8.2 Schema Object Names
- " ascii(34)
- ' ascii(39)
- [ ascii(91)
- ] ascii(93)
- ` ascii(96)
2009-01-16
2008-12-28
2008-12-25
聖誕快樂 Merry Christmas

圖片來自: everything is fantastic | wrongcards- Everything in the world is fantastic. I love the government Merry Christmas (在這世上的每件事都是如此美妙。我愛政府 聖誕快樂) (囧)
- 祝看到這篇文章的人:聖誕快樂!
2008-12-24
遠傳語音信箱 222
- 七月底的時候不曉得哪個傢伙留了語音給我,當時是第一次收語音需要設定,但設定了兩分多鐘還沒設定完,當下就先掛了再說。直到今天才想起來後再播一次,沒想到得重頭再設定一遍(囧),這次還是沒耐心弄完,反正,應該不是什麼重要的事吧。
- 這次約到期後來換一家吧。
Iron Man 鋼鐵人

圖片來至Iron Works: 2 New Iron Man Movie Photos | Marvel.com News | Marvel.com- 想不到鋼鐵人的主要武器是衝擊貝…,不,是排擊貝!不過事實証明,自動瞄準、鎖定的武器才是王道啊。
2008-12-23
2008-12-22
最近有一批記憶體,好便宜的呀!
- 當初(也沒多久以前)以為主流規格的記憶體的價格 1G 賣 1000 元就已到底了,沒想到…。
- 老哥今天在 PCHOME 買了一條創見 1G (DDR 400 終身保固,價格是我兩年前買的同規格的四分之一…囧),上午十點下單、下午不到六點就到了,有夠快的。
DOTNET 無法載入其它 .Net Framework assembly
- 以下測試環境為 PHP 5.2.8 、 Windows XP SP3 、 .NET Framework 2.0 + SDK
- PHP: DOTNET - Manual 裡的範例(載入 mscorlib)可以執行,但載入其它 assembly (我目前只有試 System.Windows.Forms )就會出現
Failed to instantiate .Net object [CreateInstance] [0x80131513]的錯誤訊息。這問題(PHP Bugs: #33188: Cannot instantiate a DOTNET object)似乎已經好幾年了。(囧) - PHP: DOTNET - Manual 文末指出加上完整的 Assembly name 方法,經測試依然失敗。
- Assembly 的資訊像是 PublicKeyToken 之類的,在 %WINDIR%\assembly 目錄裡看的到。
- Bugs: #33188 裡的一篇回覆說可用 GAC 繞過這問題,我測試的結果也是失敗的。
- gacutil.exe 要安裝 .NET Framework SDK 才有,該程式位置在 %PROGRAMFILES%\Microsoft.NET\SDK\v2.0\Bin\gacutil.exe 。
WebPageGrabber 網頁快照程式
- 利用 imagegrabwindow() 寫的網頁快照函式,我把它放在 minemine - Google Code 裡。詳細內容請見 WebPageGrabber - minemine - Google Code 。
2008-12-17
安裝 GnuPG for Windows (gpg4win)
- 到 Gpg4win - EMail-Security using GnuPG for Windows 下載、安裝。
- 到 GnuPG 安裝目錄(預設為 %PROGRAMFILES%\GNU\GnuPG\)執行
gpg.exe --gen-key,參見:GnuPG Gentoo 使用者指南 — Gentoo Linux 文件。 - 預設的輸出結果會在 %USERPROFILE%\Application Data\gnupg 目錄裡。
- 設定 GPGee 參數:
- Set program path: %PROGRAMFILES%\GNU\GnuPG\gpg.exe
- Set options file: %USERPROFILE%\Application Data\gnupg\gpg.conf
- Set keyring: %USERPROFILE%\Application Data\gnupg\pubring.gpg
- Set secret keyring: %USERPROFILE%\Application Data\gnupg\secring.gpg
- 修改 gpg.conf ,參見 GnuPG Gentoo 使用者指南的 進階功能
- 備註:我實際使用 GPG 時,所自動建立的檔名是 gpa.conf ,跟說明檔中的預設值 gpg.conf 不同,但內容是一樣的東西。
- 我安裝 Gpg4win 主要目的,是要用 GPGee 驗証下載的檔案。 GPGee 是將 GPG 和檔案總管整合的程式,在相關檔案上按右鍵即有 GPGee 的選單。
- 以 TortoiseSVN 為例,下載 TortoiseSVN-1.5.5.14361-win32-svn-1.5.4.msi 和 TortoiseSVN-1.5.5.14361-win32-svn-1.5.4.msi.asc 後放在同一目錄,在後者的 GPGee 選單中選擇 Verify/Decrypt 即可驗証檔案。
- 沒有正確設定或找不到公鑰:

Could not verify - your keyring is missing key with id 0x459E2D3E which is required to verify this file's signature. 你可以到 MIT PGP Key Server 尋找訊息裡的 ID (0x459E2D3E) ,手動匯入公鑰。 - 驗証失敗:

- 驗証成功:

2008-12-12
2008-12-05
Call of Duty, World at War
- 我已經盡量不帶著“又是另一個二戰 FPS 遊戲”的成見去玩,不過在單人 (Solo) 模式下還是玩到一半就膩了,還好有合作 (Co-op) 模式。
- 合作模式得自已一關一關重新開局,地圖也沒有照單人模式排序,還少了飛機和戰車兩關。
- 有一扮演狙擊手的關卡,很像電影“大敵當前”。
- Nazi zombie 挺好玩的,不過難度提升的太快了,兩個人撐不久,目前最多只撐到第十關而已。
- 這次收集死神卡比上次收集筆電好多了,不過只能在合作模式用。
- 在合作模式下,難度比單人模式低,大概是因為敵人的炮火多了一個目標吧。
- 不要懷疑,你身旁的同伴就是在演戲而已,除非是劇情需求,不然殺敵還是自已來吧。
2008-12-03
2008-11-27
我所使用的軟體(2011-06-13更新)
- 瀏覽器
- Chrome
- Google 文件 PDF/PowerPoint 檢視器
- Firefox
- DownThemAll! 有批次URL下載、修改 Referer、從網頁分析截取鏈結和限制同時下載數的功能,對我來說已經夠了。
- Firebug
- FireFTP
- FirePHP
- SQLite Manager
- Google Toolbar for Firefox Generate custom search 的功能相當好用,可以配合像 Wikipedia 的搜尋框。WordTranslator 也很方便。
- Linkification 有些網站貼文時不支援 HTML,所以常會有 URL 以文字的狀態呈現。只有一、兩個就還好,但量大的時候就很討厭(囧),這個外掛可以把文字 URL 轉成鏈結。
- Live HTTP Headers
- Menu Editor
- NoScript 資安相關,可以避免惡意的 Script ,不過很容易會造成瀏覽上的困擾。
- QuickProxy 單鍵開關Proxy。有些網站似乎會鎖單一IP來源的連線數,掛hinet proxy時常被擋!
- Web Developer
- 新同文堂 -- OpenFoundry 可以自動轉換繁、簡字體相當方便,方便到我一度懷疑怎麼好久沒看過簡體字…。
- Opera 內建BT下載
- Internet Explorer
- Chrome
- 文字編輯
- 媒體播放
- VLC media player
- KMPlayer
- QuickTime Alternative
- Real Alternative
- 網頁/軟體開發
- Java SDK
- Android SDK
- Eclipse
- Android Developer Tools
- PHP Development Tools - Zend PDT
- Apache HTTP Server
MySQL資料量少的就用 SQLite 取代- PHP
- TortoiseSVN
- 資安/防毒/備份
- 系統/檔案/網路工具
- NTPClock.exe 時間與頻率國家標準實驗室
- Sysinternals Suite (Install-less, Portable)
- Autoruns 查詢/修改系統啟動時會自動執行的項目(夭壽多)。
- ProcessExplorer 如同工作管理員的軟體,對我而言最主要是多了 I/O 量歷程圖
- RegMon
- Wireshark with WinPcap
- 7-Zip
- UniExtract + TrID
- UPX
- Adobe Flash Player
- VirtualBox
- DAEMON Tools Lite
- ImDisk
- Workrave
- MWsnap 螢幕截圖軟體
- Windows Live Messenger 越來越雜了。
2008-11-24
Red Alert 3
- 花了三天把三個陣營的劇情過了一遍,這次的美術風格真是詭異,尤其是主選單。
- 雖然過場還是不改廉價影片的風格,但請來的演員似乎還滿大卡的。
- 作戰單位自動偵測敵人的範圍變的好小,常在不注意的時候,一群兵從最外圍一個一個被幹掉,氣死。
- 這遊戲最讓我期待的合作模式,因為“嗶-”(消音)的關係沒能玩到,可惜。
2008-11-19
Fallout 3 異塵餘生三
- 目前只玩完好人的主線劇情,即使這樣,地圖上還有一半以上沒去過。
- 雖然是做成 FPS ,但這遊戲只開槍是玩不下去的,除了戰鬥的部份不比其它 FPS 好之外,主要還是因為劇情對話佔了很大的比例。
- 遊戲裡的世界做的不錯,歌也很好聽,尤其是在遊戲裡一邊聽著 Galaxy News Radio ,一邊探險、開槍殺敵,超有 feel ~!
- 我覺得最可惜的是東西不夠多,感覺每個項目都只有一點點。像是:武器有分大鎗、小鎗、近戰…等,但每一類就那幾把,你可以自製武器,但就那七種;可以有自已的家,但裡面只有五項設備跟六種佈景主題。
- 總和來說,還是絕對值得玩兩次以上的遊戲。(現在值得再玩一遍的遊戲不多了啊)
- 用 FO3 Archive Utility 解開 Bethesda Softworks\Fallout 3\Data\Fallout - Sound.bsa ,裡面可以找到遊戲裡 Radio 播放音樂的 mp3 。
- PC 版可以按 ` 開 console 輸入 cheat code 。
- advlevel :等級升一級,可以加超過 20 級。
- addspecialpoints x :加 x 點 SPECIAL 點數。
- addtagskills x :加 x 項 tag skill 。
- 要注意的是點數要算好,因為點數要分配完才能關閉對話框,爆了的話就關不了了。
- SPECIAL 如果加滿的話,很多加 SPECIAL 點數的效果就沒用了(像是藥物),因為單項最高就是到10 點。
- 還有技能 (skill) 除非有必要,不然點到 95 就好,剩下 5 點可以靠裝備,以節省點數(和手指連點的次數)。
- Black Widow/Lady Killer 和 Child at Heart 這兩項我覺得必點,可以增加一些額外(一定會成功)的對話選項。
- 副檔名 bik 檔,可以用 RAD Video Tools 播放。
2008-11-07
關於 nl2br
- 各系統使用不同的換行字元,常見的就是 LF 、 CR 、 CRLF ,詳見 Newline - Wikipedia, the free encyclopedia,此不贅述。
- 而 PHP 裡有 nl2br() (New Line to BReak) 這個函式,將字串裡的換行字元轉成 HTML <br> ,PHP 4.0.5 以上是換成 XHTML 相容的 <br />。
- nl2br() 的行為並不是把換行字元
取代成
<br /> ,而是在換行字元前插入
<br /> 。 nl2br("\r\r\n\n")的結果是 <br />\r<br />\r\n<br />\n- nl2br() 會先再找 \r\n 和 \n\r (!) 再找 \r 和 \n 。
nl2br("\n\r\n")的結果是 <br />\n\r<br />\n
2008-11-06
用 token_get_all 分析 PHP 原始碼
- token_get_all() 將原始碼拆成陣列,每個陣列元素可能是字串或陣列,字串的話包括像等於、分號或大小括弧等,陣列的話則依序包括 token index 、內容跟所在行數。這裡的 token index 是整數,可以用 token_name() 轉成相對應的名字。
- 以下是簡單的範例,將每個元素用 <span> 包起來,並設定 class 為 token name :
<?php
$source = file_get_contents(__FILE__);
$ary = token_get_all($source);
foreach ($ary as $key => $value) {
if (is_array($value)){
echo '<span class="' . token_name($value[0]) . '">' . htmlspecialchars($value[1]) . '</span>';
} else {
echo '<span>' . htmlspecialchars($value) . '</span>';
}
}
?> - 用 get_defined_constants 取得所有可用的 token (參見 PHP: List of Parser Tokens - Manual):
<?php
$constants = get_defined_constants(true);
var_dump($constants['tokenizer']);
?> - 首先要注意的是, token_get_all 對原始碼分析的結果跟本機環境設定有關:
- 像 <?= 在 short_open_tag = On 的時候是 T_OPEN_TAG_WITH_ECHO ,反之則是 T_INLINE_HTML 。
- 我用的 PHP 5.2.6 就沒有 T_DIR 、 T_NS_C 這些 5.3 版才定義的 token 。
- 另外要注意的是,到了 CSS 2.1 才定義可以使用底線 (
_
; underscore) 做為 class name selector ,參見 CSS2 syntax and basic data types 與 Grammar of CSS 2.1,如果要將 token name 做為 CSS class selector 的話,最好將底線換為連字號 (-
; hyphen)
Parse_Tree 分析 PHP 原始碼並輸出 XML
- 因為內建的 highlight_file 和 highlight_string 輸出的結果太醜,要改的話又太麻煩,所以找了個替代方案 PECL :: Package :: Parse_Tree 。
- 該模組只有 parse_tree_from_file() 一個函式、唯一一個參數要傳入原始碼的路徑。這份文件寫的 generate_parse_tree() 是錯的。
- 使用方法也很簡單,下例會輸出該程式本身分析後的 XML:
<?php
echo parse_tree_from_file(__FILE__);
?> - 缺點是要另外下載模組,實際要用得把 XML 轉換成 HTML ,對我而言相當不方便。
- 這研究這個模組途中,才發現 PHP 已經有內建分析原始碼的函式 token_get_all(),詳見下篇。
安裝 Glade 3.4.3 for Windows (gladewin32) 遇到的問題

圖為安裝 Glade/Gtk+ for Windows 3.4.3 版遇到的錯誤訊息。glade-3.exe - Entry Point Not Found
The procedure entry point g_assertion_message_expr could not be located in the dynamic link library libglib-2.0-0.dll.- 解決方法是將 GTK+ 的版本更新至 2.12.9 以上。為什麼我會知道?因為我電腦裡裝的是不曉得哪個程式附的 GTK+ 2.12.8 … (囧),更新(目前最新是 2.14.4)後就沒問題了。
- 如果是遇到缺什麼 dll 的情況,先確認 GTK+ 的 bin 目錄有沒有加到環境變數 PATH 裡,不行再到 GTK+ 官網下載或網上去找吧。
2008-11-01
PHP-GTK on Windows 筆記
- 到 PHP-GTK : Downloads 下載 php-gtk-2.0.1 Windows binary pack
- 到下載回來的檔案解開後的 php-gtk2 目錄裡,執行
php demos\phpgtk2-demo.php範例測試。 - 在利用既有的 PHP 環境執行時遇到下列錯誤訊息,應該是因為 PHP-GTK 是 Non-thread-safe 的,和我現有的版本不符的關係。
PHP Warning: PHP Startup: php-gtk: Unable to initialize module Module compiled with module API=20060613, debug=0, thread-safety=0 PHP compiled with module API=20060613, debug=0, thread-safety=1 These options need to match in Unknown on line 0
- 修改 php-cli.ini 檔案中 php-gtk.codepage 一項,修改為 CP850 用以在 Windows 上正常顯示繁體中文。參見:Code Pages
改變 Google Chrome 的 Cache 路徑 (2011-04-17 更新)
2011-04-17 更新
- 只設定
user-data-dir時,快取目錄會自動設定於該目錄下。 - 若要單獨指定快取目錄時,使用:
disk-cache-dir參數。 - 使用
--disk-cache-size設定快取大小。 - 更多其它的參數請參考 http://src.chromium.org/svn/trunk/src/chrome/common/chrome_switches.cc
- 裝了 Google Chrome 一陣子以來,只有偶而開個幾次,所以沒什麼心得。不過每次打開 Google Chrome 一段時間後,即使沒有正在執行的連線, Google Chrome 還是會小量而頻繁的存取硬碟(一直咔啦咔啦的)。
- 後來加上
--user-data-dir=Z:\Temp參數,將路徑改到 RAMDisk 上就好了。參見:Meme -- 教學與反省: 將 Google Chrome 的暫存檔移至 RAMDisk - 這也同時解決了隱私的問題, Google Chrome 預設首頁會顯示之前瀏覽頁面,但卻無法預設使用無痕式視窗、也無法在程式開閉後自動清除瀏覽資料。
2008-10-31
修改 Blogger Layout 筆記
- 要下載回來編輯的話,最好用像 Notepad++ 這種有收合語法功能的編輯器。
- 基本上就是 XHTML ,再加上 Google 另外定義的 Namespace "http://www.google.com/2005/gml/" (GML?)。
- 主要的標籤有:(參見 Widget Tags for Layouts)
- <b:skin> 除多了變數功能外,幾乎同等於 <style> 。
- <b:section> 分區用。
- <b:widget>
- <b:includable> 、 <b:include>
- <b:if> 、 <b:loop>
- 其中 <b:section> 的子系只允許是 <b:widget> ,而 <b:widget> 的子系只允許是 <b:includable> 。
- 預先定義的 <b:section> 有 header 、 main 、 sidebar 、 footer 四個區塊。
- <b:widget> 要有一個 id 是 main 的 <b:includable> ,若是其它的 id 的話則預設是不會顯示的( header 似乎是例外),但可以用 <b:include> 加入其中。
- 有些 data 項目沒有在 Layouts Data Tags 列出。
- navMessage :用來顯示 Showing posts with label PHP. Show all posts 之類的訊息。
- adStart :插廣告用的?
2008-10-29
Zend_Log 與 FireBug+FirePHP
- 一個 Zend_Log 可以註冊好幾個 Zend_Log_Writer ,意即一個訊息可以送多個地方記錄。
- Zend_Log 將訊息透過 HTTP Header (Zend_Wildfire) 傳到 Firebug + FirePHP 的 Console 畫面上,記得要啟用 Firebug 的 Console 和 Net 介面。
- 另一個和 FireBug 相關的元件是 Zend_Db_Profiler_Firebug ,利用一樣的原理將對資料庫的查詢資訊,傳到 FireBug 上。
Zend_Translate 與 Poedit
- 在用 Zend_Translate 和 Poedit (1.4.2) 時遇到一個問題,就是 xgettext 不吃 *.phtml 而把它當成 C 來處理,解決方法如下:(參見:using poEdit - Zend Framework Forum)

圖為 Poedit 的 File » Preferences » Parsers » PHP » Edit 截圖。- 在 extension 增加 *.phtml ,注意分號後面不能有空格。
- 在 parser command 後加上 -L php 即可,如:
xgettext --force-po -o %o %C %K %F -L php - 在 Poedit 的 Catalog » Setting » Keywords 增加 translate 一項。
- 在 Zend_View_Helper_Translate 裡沒有對應 Zend_Translate_Adapter::_ (底線,就如同 gettext 的底線函式) 這個用來省幾個字的方法。
- 真的要用底線也是有啦,只是省不到字就是了:
<?php
echo $this->translate('something');
echo $this->translate()->_('something');
?> - 做為 message id 的字串要應該考慮大小寫及前後空格與符號等,就想原文是如何就是了。
2008-10-28
Zend Framework Components 分類
- 以下分類僅供參考,有很多我都還沒用過。參見:Zend Framework: About Components。
- core
- Zend_Loader 「載入元件」的元件,提供個別載入或 autoload 的方法。
- Zend_Version
- 使用者認證/授權
- Zend_Acl
- Zend_Auth
- Zend_Captcha
- Zend_InfoCard
- Zend_Ldap
- Zend_OpenId
- Zend_Service_ReCaptcha
- 儲存/快取/暫存資料
- Zend_Cache
- Zend_Config
- Zend_Db
- Zend_Memory
- Zend_Registry
- Zend_Session
- 跟 MVC 有關的
- Zend_Controller
- Zend_Layout
- Zend_Paginator
- Zend_View
- i18n
- Zend_Currency
- Zend_Date
- Zend_Locale
- Zend_Measure
- Zend_Translate
- debug
- Zend_Debug
- Zend_Exception
- Zend_Log
- Zend_Test
- XML Manipulation
- Zend_Dom
- Zend_Feed
- 處理表單及使用者輸入資料
- Zend_File
- Zend_Filter
- Zend_Filter_Input
- Zend_Form
- Zend_Validate
- 網路服務
- Zend_Gdata
- Zend_Service_Akismet
- Zend_Service_Amazon
- Zend_Service_Audioscrobbler
- Zend_Service_Delicious
- Zend_Service_Flickr
- Zend_Service_Nirvanix
- Zend_Service_Simpy
- Zend_Service_SlideShare
- Zend_Service_StrikeIron
- Zend_Service_Technorati
- Zend_Service_Yahoo
- 跟寄 E-Mail 有關的
- Zend_Mail
- Zend_Mime
- Web Services
- Zend_Soap
- Zend_XmlRpc
- 雜
- Zend_Console_Getopt
- Zend_Dojo
- Zend_Http
- Zend_Json
- Zend_Pdf
- Zend_Rest
- Zend_Search_Lucene
- Zend_Server_Reflection
- Zend_Text
- Zend_Timesync
- Zend_Uri
- Zend_Wildfire
關於 PHP 的 closing tag
- PHP 的 closing tag (即“?>”)是可以省略的,雖然有寫在 PHP: Instruction separation - Manual 這一篇的 Note 裡,但我一直到最近才知道。
- 省略 closing tag 可以在 include 文件時,避免因文未多餘的字元而無法送出 header 的情況。
2008-10-26
戰爭機器二

- 連著兩天玩了共約十一個小時,爽!劇情還滿充實的,不會有一下就結束的感覺。現在就等第三集了。
- 只有在殺人冰雹和大嘴魚那裡卡了幾次。殺人冰雹那會有幾條「看起來」好像可以過的路,實際上卻只有眼前最短的路才是對的。而大嘴魚那裡則是不要害怕,往嘴裡衝就是了。
- 持久戰模式我們只能撐到第八波而已…被巴假的啊。(淚)
- 你說這個時候還遊戲都還沒上市?就當我是在做夢吧。
- 戰爭機器 2》遊戲搶先偷跑?數十張遊戲內容實際圖片! - SOC 電子競技職業聯盟
2008-10-21
詭異的 Zend_Mail
- 目前測試成果之一,是可以用 Gmail SMTP 寄信。
- 中文(正確來說是需要編碼的非 ASCII 字元)無法正常顯示。除了太長以外,還有中文字被截開的問題。得改寫 Zend_Mail::_encodeHeader 、 Zend_Mime::encodeQuotedPrintable 。我改寫的版本在 Gmail 測試成功,不過寫太醜了就不放上來了。
- 後來查了一下才知道,原來這問題之前就有了… Zend_Mail中文標題亂碼問題 - IT邦幫忙::IT知識分享社群。我現在用的是 1.6.1 版,依然有這個問題。
- Subject header 的格式範例:
Subject: =?UTF-8?Q?=11=22=33=44=55=66=77=88=99=AA=BB=CC=DD=EE=FF?= =?UTF-8?Q?=11=22=33=44=55=66=77=88=99=AA=BB=CC=DD=EE=FF?=
(超過 78 個字元“應該”換行) - 若只送出 BodyText 或 BodyHtml 其中一種,則不會送出 Content-Type 和 Content-Transfer-Encoding 的 header 。
- 文件第 29.5. HTML E-Mail 一節提到:同時送出 BodyText 跟 BodyHtml 會自動換成 multipart/alternative
並沒有發生。解決標題問題後,這功能也恢愎正常。 - Zend_Mail::_storeHeader 裡有一行奇怪的 comment :
// ?? $value = strtr($value,"\r\n\t",'???');
2008-10-17
再加上 PostgreSQL
- 裝完 PostgreSQL 後,重新啟動 Apache 時,出現了無法載入 php_pgsql.dll 、 php_pdo_pgsql.dll 的錯誤訊息(執行環境 Windows XP SP3 / Apache 2.2.8 / PHP 5.2.6 / PostgreSQL 8.3.4)。在 PATH 中加入 PostgreSQL\8.3\bin 路徑後重開機即可。
- 管理工具 phpPgAdmin 。
- 在 PostgreSQL 裡要達成 AUTO INCREMENT 的功能,要另外 CREATE SEQUENCE 或指定欄位資料型態為 SERIAL (意思是一樣的,不過改由 PostgreSQL 代勞)。
SQLite
- 為了測試 PDO 的通用性,以及尋找 MySQL 的替代品,選了 SQLite 試用中(下一個候選是 PostgreSQL)。
- 和 Microsoft Access 一樣無需架設伺服器,檔案式的資料庫。
- SQLite 是無資料類型“ Typeless ”這點還滿特別的,你依然可以宣告資料類型,但資料庫內部都當成 ASCII 文字處理, SQLite 3 再從 TEXT 分出 INTEGER 、 REAL 和 BLOB 。參見: Datatypes In SQLite / Datatypes In SQLite Version 3
- 一個 SQLite 管理工具 SQLite Manager :: Firefox Add-ons 。
- 從 MySQL 換過來第一個遇到問題的是 CREATE TABLE 語法,主鍵固定是用“ INTEGER PRIMARY KEY AUTOINCREMENT ”。
2008-10-15
2008-10-13
Apache 子網域對應
- 以下是使用 Apache HTTP Server 的 mod_vhost_alias 模組。
- 假設擁有的網域和 IP 是: example.com 與 256.256.256.256 。
- 在 DNS 新增一筆泛解“*”:
* IN A 256.256.256.256 - 泛解“*”是標準語法,而且不會覆蓋已設定的域名。參見 Wildcard DNS record - Wikipedia, the free encyclopedia 。
- 意思是指 example.com 的子網域 (像 www.example.com 或 ftp.example.com 之類的) 全部對應到 256.256.256.256 。
- 在 Apache httpd.conf 加入:
LoadModule vhost_alias_module modules/mod_vhost_alias.so UseCanonicalName Off VirtualDocumentRoot "C:/web/%-1/%-2/%-3"
- 上述設定會使 www.example.com 對應到 C:/web/com/example/www ,或 abc.example.com 對應到 C:/web/com/example/abc …之類的效果,這樣新增子網域只要增加子目錄即可,不需重開 Server。
- Apache 還有其它對應網域/網址的方法。參見 Mapping URLs to Filesystem Locations - Apache HTTP Server
2008-10-10
申請 Yahoo BBAuth 的 App ID 遇到的問題
- 申請步驟一直到 Check Domain 都沒有問題,但按下 Check Domain 後卻導向 Yahoo 登入頁面,登入後又被導到“申請 App ID ”的頁面,然後就鬼打牆一直重覆申請、 Check Domain 、登入的動作,試了兩天都一樣。
- 另外,今天想試用 Yahoo OpenID 時,也傳回錯誤訊息。
- 兩個事件的相同之處,只有從英文網站導回中文的登入頁面,所以我試著在主站(www.yahoo.com)新申請一個帳號,然後…就都申請成功了。
- \(囧)/
2008-10-08
OAuth
- OAuth 是一個關於提供第三方“授權”(authorization)的開放協定,參見:OAuth Core 1.0 Spec 和函式庫。
- 對於一般使用者而言,可以使用已經擁有的帳號(及其服務)。
- 對於開發者而言,可以有開放、統一的授權協定,整合網路服務。但因為授權後取得的是一組代號(Access token)而不是帳號,所以有識別使用者的問題,見:Racklin's 阿土伯程式大觀園: 另人遺憾的 Google AuthSub API 有感。
- Google Account Authentication API 已經可以使用了 OAuth,原有的 AuthSub 改為輔助,只是在 PHP 上還沒跟 Zend Framework GData 銜接上。
- Yahoo OAuth 目前還在 preview 的階段。
- 以下是一些 OAuth 名詞定義:
- User:即一般使用者。
- Consumer:第三方應用服務。
- Service Provider:服務供應者,像 Google 和 Yahoo 之類。
- Consumer Key/Secret:Service Provider 提供給 Consumer 做為簽證使用。
- Request Token:向 Service Provider 請求認證 Consumer 和向使用者要求授權的一組代號。
- Access Token:經過認證授權後,實際用來存取 Service Provider 服務的一組代號。
2008-10-07
關於密碼儲存
- 使用者傳來的密碼絕不可以直接(以明文)儲存!避免有心人士取得密碼表後直接利用。
- 一個常見的做法是利用雜湊(Hash)函數,將密碼編碼後儲存。
- 例: mypassword 這段字用 md5() 編碼的結果是 34819d7beeabb9260a5c854bc85b3e44 。
<?php
// Outputs: 34819d7beeabb9260a5c854bc85b3e44
echo md5('mypassword');
?> - 但是,這樣我就知道 34819d7beeabb9260a5c854bc85b3e44 就是 mypassword 用 md5() 計算的雜湊值啦!
- 所以有心人士可以事先將所有可能用來當密碼的字串,用 md5() 或其它雜湊函數先行編碼、記錄下來(就是所謂的 Rainbow Tables),取得密碼表後,只要一比對就可以知道密碼。
- 一個應對的方法就是加鹽(salt, see:Rainbow table - Wikipedia, the free encyclopedia),意思是將密碼加上一段字串後,再計算雜湊值。
- 例:
<?php
// Outputs: f5c8bdfe11ef33040331747636877629
echo md5('salt' . 'mypassword');
?> - 加了 salt 後,即使有心人士比對出原文,也不能直接拿來使用,還得找出 salt 才行。可針對使用 Rainbow Tables 的情況,加長 salt 的長度或使用特殊字元(鍵盤上無法直接打出來的),增加被找到的難度與所需時間。
- 在擁有大量密碼情況下,常有重覆的雜湊值出現的情況,除了碰撞外,有可能是不同的使用者使用了相同的密碼,或是像 123456 之類的隨意輸入的密碼,有心人士可能會刻意針對這些值(使用者)。
- 這時可以利用隨機函數產生 salt ,這樣即使用同樣的密碼,每次計算出來的雜湊值都不一樣。
<?php
$salt = md5(mt_rand());
echo $salt . md5($salt . 'password');
?> - 以下為簡單的範例:
-
<?php
function hash_pwd($pwd, $salt = false){
if (!$salt) {
$salt = md5(mt_rand());
}
return $salt . md5($salt . $pwd);
}
function compare_pwd($pwd, $pwd_hashed){
$salt = substr( $pwd_hashed, 0, 32 );
return $pwd_hashed === hash_pwd($pwd, $salt);
}
$user_pwd = 'password';
$user_pwd_hashed = hash_pwd($user_pwd);
var_dump( $user_pwd_hashed );
var_dump(compare_pwd($user_pwd, $user_pwd_hashed));
?> - 若使用 PHP 5.1.2 以上版本,建議改用內建的 hash() 函數,並換成其它較複雜的雜湊演算法,如 WHIRLPOOL。
- 對一般使用網站服務的使用者,要知道網站有沒有用雜湊函數之類的方法儲存你的密碼,只要使用網站提供的“忘記密碼”的服務,一般來說,網站會自動重設一組隨機密碼讓你使用,但若是網站會傳回你原本的密碼的話…。
- 在每個網站服務最好都使用不同的帳號、密碼,避免在某個網站被破,其它服務也遭殃。例如在某網站註冊時填的帳號、密碼和 E-mail,“剛好”都跟該 E-mail 用的一樣…。
2008-10-05
YUI 非同步的傳案上傳
- 使用 YUI Connection Manager 實作。
- 觸發事件不用 button.onClick 而用 form.onSubmit,其中一個考量是避免遺漏使用者以「按下 Enter 」的方式送出表單。
- 在關閉 Javascript 的情況下,也能一般的方式送出表單內容。
- 同時使用 POST 與 GET (自行在 URL 後附加參數),來判斷資料是由 AJAX 還是一般方式送出(瀏覽器有無支援 Javascript)。前者可以送出 JSON 編碼的資料方便用 Javascript 處理,而後者就出一般的網頁。
- async_file_upload.htm
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta http-equiv="Content-Language" content="zh-TW"> <title>Asynchronous File Upload With YUI 非同步檔案上傳</title> <script type="text/javascript" src="http://yui.yahooapis.com/2.6.0/build/yahoo-dom-event/yahoo-dom-event.js"></script> <script type="text/javascript" src="http://yui.yahooapis.com/2.6.0/build/connection/connection-min.js"></script> <script type="text/javascript" src="http://yui.yahooapis.com/2.6.0/build/json/json-min.js"></script> <script type="text/javascript"> function doSubmit(objForm){ // 第二個參數設成 true 允許檔案上傳 YAHOO.util.Connect.setForm(objForm, true); var callback = { upload: function(o) { var result = YAHOO.lang.JSON.parse(o.responseText); document.getElementById('log').innerHTML = 'name: ' + result.name + '<br>\n' + 'type: ' + result.type + '<br>\n' + 'size: ' + result.size + '<br>\n' + 'tmp_name: ' + result.tmp_name + '<br/>\n' + 'error: ' + result.error + '<br>\n'; } }; // 同時使用 POST 與 GET (async) 判斷資料是由 AJAX 或表單直接送出 YAHOO.util.Connect.asyncRequest('POST', objForm.action + '?async=1', callback); // 這裡傳回 false 並不能阻止 submit (原因未知) return false; } </script> </head> <body> <!-- 在 onSubmit 呼叫 doSubmit 後再傳回 false 避免以一般方式送出表單 --> <form id="form_1" action="async_file_upload_action.php" enctype="multipart/form-data" method="post" onsubmit="doSubmit(this); return false;" > <div> <input type="file" id="input_file_1" name="input_file_1"> <input type="submit" id="input_submit_1" name="input_submit_1"> </div> </form> <pre id="log"></pre> </body> </html> - async_file_upload_action.php:
<?php if (isset($_GET['async'])) { echo json_encode($_FILES['input_file_1']); } else { echo '<pre>', print_r($_FILES, true), '</pre>'; } ?>
- Yahoo! UI Library: Connection Manager The Callback Object and File Upload
- Asynchronous File Upload - YUI's Approach | Code Central
2008-10-02
reCAPTCHA
圖為 reCAPTCHA 的實例圖。- 到 PHP CAPTCHA Library for reCAPTCHA 下載 API 和範例。
- 申請一組金鑰,這裡除了要申請該站的帳號外,還要填入你要使用 reCAPTCHA 的域名。
- 在範例 (example-captcha.php) 中填入該組金鑰後就可以直接測試了,填入正確的答案的話會傳回“You got it!”。
- 如果有使用 NoScript 的話,要允許該網頁本身和 http://api.recaptcha.net 執行 Script。
- reCAPTCHA 在瀏覽器不支援 script 的情況下也可以運作,只是要多一道傳回運算值的步驟,還有,要支援 iframe 才行(也有可能被 NoScript 擋掉)。
- reCAPTCHA 除了提供一般常見的文字(圖形)測試外,還提供的語音測試(目標是辨識一串數字),但還滿難聽的出來就是了。
- reCAPTCHA Mailhide 是把網頁上顯示的 E-mail ,取代成連往 CAPTCHA 測試的鏈結,測試成功後再秀出完整的 E-mail,目地是要避免被網路 bot 收集。
- 範例:exam...@example.com。
- reCAPTCHA Mailhide 需要載入 mcrypt 模組,在此之前得先把 PHP 附的 libmcrypt.dll 複製到 %WINDIR%\system32 裡。
2008-10-01
KENWOOD UD-700 組合音響
- 幾星期前,陸續從 Benson 那搬回來的一組音響,今天第一次試用,產品型號應該是 KENWOOD UD-700。雖然有點舊,但是,是免費的就算有賺到啦!
- A-A7 擴大機兼 AM/FM 收音機,曾在搬動後出現“PROTECT”訊息,說明書上寫是有線路短路,結果用吹風機吹吹就好了。
- GE-A7 等化器 EQUALIZER,機背的接頭氧化的很嚴重。
- X-A9 雙錄音帶播放機,其中一匣播出的聲音變的很低沉、小聲,另一匣則正常。
- DP-A9 CD播放機,常讀不到片,更誇張的是,剛播完的片子就讀不到了。
- LS-A7 一對喇叭,偶而會出現小聲的“啪”的聲音,但還不確定是不是音樂的問題。
2008-09-26
申請一個泛英網域
- 下午在 Hinet 網域名稱申請服務申請了一個泛英網域,下午一點填表,兩點匯款,五點就收到 e-mail 說開通了。
- 在 Hinet 申請的泛英網域沒有提供網域代管,原本想用 ISC BIND 自行架設 DNS Server,但指定 DNS 時一直出現 637 的錯誤,改用 EveryDNS 馬上就成功了。
- 以下是 EveryDNS 提供的四組 DNS Server Name / IP():
- ns1.everydns.net / 208.76.56.56
- ns2.everydns.net / 204.152.184.150
- ns3.everydns.net / 89.188.0.57
- ns4.everydns.net / 208.96.6.134
2008-09-25
2008-09-24
查詢 IP 來自哪個地區/城市 (三) 半自動更新資料庫
- MaxMind GeoIP 提供兩個每月更新的免費資料庫: GeoLite Country (GeoIP.dat.gz) / GeoLite City (GeoLiteCity.dat.gz) ,檔案是用 gzip 壓縮,有固定鍵結可以直接下載,所以可以利用 PHP Compression Streams 下載同時解壓,然後存檔。
- 要用 compress.zlib:// 這個 wrapper,必須打開 allow_url_fopen 這項設定。
<?php $source_filename = 'http://www.maxmind.com/download/geoip/database/GeoIP.dat.gz'; // 取得解開 .gz 後要用的檔名 GeoIP.dat $base_filename = basename($source_filename, ".gz"); $destination_filename = './' . $base_filename; $file_handle = fopen('compress.zlib://' . $source_filename, 'rb'); $data = ''; if($file_handle){ while (!feof($file_handle)) { $data .= fgets($file_handle, 1024); set_time_limit(5); // 增加執行時間的上限,避免逾時 } file_put_contents($destination_filename, $data); // 預設會覆蓋同名檔案 fclose($file_handle); }else{ exit('無法開啟遠端檔案'); } ?>
2008-09-23
查詢 IP 來自哪個地區/城市 (二) 世界各國國旗
- 絕大部份的國旗圖案是來自 Icon Drawer,其它的少部份則是來自維基百科。我只是稍微整理、打包,並將圖檔檔名改為 ISO 3166-1 的二位字母代碼,圖檔格式為 PNG。按此下載:Flags_ISO_3166-1_alpha-2.zip。
- 內附從 ISO 下載的 iso_3166-1_list_en.xml是修改過的改本(把 PROVINCE 改成 REPUBLIC),嘿嘿。
- 雖然大部份都可以藉由程式照表處理,不過還是有約 50 檔案得手動修改。這也提醒自已,以後不論處理什麼資料的時候,都要考慮電腦處理的可能性。
- 我猜 Icon Drawer 應該是用“工人智慧”處理,才會出像 South Afriica.png 這樣多打一個字的錯誤(囧)。
- 註:Icon Drawer 有要求使用其提供的國旗圖檔的同時,必須在網站放置鏈結。
Subscribe to:
Posts (Atom)
個人常用鏈結
Labels
- .NET (1)
- Accessibility (3)
- ADSL (1)
- Apache (9)
- ASP.NET (1)
- Babyer (1)
- Browser (1)
- Canon MX700 (1)
- CAPTCHA (1)
- CentOS (1)
- CSS (7)
- DB:SQL (1)
- DB:SQLite (2)
- DNS (3)
- English (1)
- EXIF (1)
- filename.ext (1)
- Firefox (4)
- Firewall (1)
- Flash (4)
- Game 遊戲 (28)
- Game:PC (6)
- Game:PS3 (4)
- Game:Xbox360 (3)
- GNU (1)
- Google (6)
- Google:Android (8)
- Google:Blogger (2)
- Google:Chrome (1)
- Google:Code (2)
- GoogleAppEngine (2)
- GoogleMaps (1)
- GPG (1)
- Hinet (1)
- HTML (2)
- HTTP (1)
- i18n (1)
- IE (3)
- Java (2)
- Javascript (2)
- Linux (1)
- Microsoft (2)
- MIME (1)
- MySQL (7)
- NexusOne (2)
- OAuth (1)
- Open source 開放原始碼 (1)
- OpenID (1)
- OS (1)
- OS:Windows (33)
- PHP (49)
- PHP:GTK (2)
- PHP:PEAR (1)
- PHP:PECL (3)
- PHP:ZendFramework (4)
- PostgreSQL (1)
- PPPoE (1)
- RegularExpressions (2)
- Security (11)
- Sphinx (2)
- SQLite (1)
- TCP (1)
- Ubuntu (1)
- UDP (1)
- Usability (2)
- Virtaul PC (1)
- Wii (2)
- XML (1)
- Yahoo (2)
- Yahoo:BBAuth (1)
- Yahoo:YUI (1)
- Youtube (1)
- 不如賣雞排 (2)
- 不願役 (33)
- 中文處理 (1)
- 圖 (5)
- 媒體 (2)
- 影片 (1)
- 影音 (19)
- 思 (8)
- 攝 (9)
- 政 (7)
- 敗 (2)
- 漫畫 (5)
- 生活 (34)
- 硬體設備 (13)
- 網站開發 (16)
- 網路 (8)
- 英文 (3)
- 貓 (2)
- 資安 (1)
- 趣 (29)
- 軟體 (12)
- 遊記 (8)
- 運動 (2)
- 關於我 (1)
- 電影 (10)





