diff -Nur myspam-0.0.3/changelog.txt myspam-0.0.4a/changelog.txt
--- myspam-0.0.3/changelog.txt	2006-05-11 11:57:17.000000000 +0800
+++ myspam-0.0.4a/changelog.txt	2007-06-11 14:40:40.842885990 +0800
@@ -1,5 +1,16 @@
 ﻿MySPAM changelog (UTF-8 encoding)
 
+v0.0.4a - 2007/6/11
+    ! 修正在 register_globals 為 on 的時候 (不建議使用), 無法正常使用的問題.
+      在程式一開始, 會先 unset $username, $password 兩個變數, 以避免在 register_globals 為 on 時, 誤用這兩個值.
+
+v0.0.4 - 2007/6/11
+    ! 修正 QP 編碼的處理.
+    ! 修正 iconv 錯誤的警告.
+    ! 修正某些信件, 會標明使用 iso-8859-1 的編碼, 但裡頭不是英文. 造成解碼後的字串仍是亂碼.
+      目前針對 iso-8859-1, 如果不是英文字串, 會忽略這個編碼, 再嘗試用其他編碼去解碼.
+    + 新增搜尋的功能. (感謝 小張張 http://phorum.study-area.org/profile.php?mode=viewprofile&u=756 提供)
+
 v0.0.3 - 2006/5/11
     + 新增選取該頁所有信件的元件.
     = 更改資料的背景顏色, 由每列不同色改為每行不同色.
diff -Nur myspam-0.0.3/web/config.php myspam-0.0.4a/web/config.php
--- myspam-0.0.3/web/config.php	2006-05-11 11:57:25.000000000 +0800
+++ myspam-0.0.4a/web/config.php	2007-06-11 14:40:56.171391124 +0800
@@ -1,6 +1,6 @@
 <?php
 
-define('MYSPAM_VER', 'v0.0.3');
+define('MYSPAM_VER', 'v0.0.4a');
 define('EX_TEMPFAIL', 75);
 define('IN_MYSPAM', '1');
 define('DB_ENCODING', 'utf8');
@@ -26,8 +26,6 @@
 $spam_url = 'http://your_myspam_website';
 // notspam path
 $notspam_path = '/var/spool/myspam/notspam/';
-// item for each page
-$pagesize = 15;
 // keep days
 $keep_days = 30;
 // write debug information
diff -Nur myspam-0.0.3/web/index.php myspam-0.0.4a/web/index.php
--- myspam-0.0.3/web/index.php	2006-05-11 11:58:10.000000000 +0800
+++ myspam-0.0.4a/web/index.php	2007-06-11 14:40:50.475203415 +0800
@@ -17,6 +17,11 @@
 $smarty->left_delimiter = '<{';
 $smarty->right_delimiter = '}>';
 
+if (!isset($argc, $argv)) {
+    $argc = $_SERVER['argc'];
+    $argv = $_SERVER['argv'];
+}
+
 if ($argc == 2 && $argv[1] == 'send_notify') {
     require_once('notify.php');
     SendNotify();
@@ -42,11 +47,13 @@
     exit($ret);
 }
 
-$username = $_SESSION['username'];
+unset($username);
+unset($password);
+if (isset($_SESSION['username'])) $username = $_SESSION['username'];
 
 if (!isset($username) || empty($username)) {
-    $username = $_POST['username'];
-    $password = $_POST['password'];
+    $username = isset($_POST['username']) ? $_POST['username'] : '';
+    $password = isset($_POST['password']) ? $_POST['password'] : '';
     $errmsg = '';
 
     if (isset($username) && !empty($username)) {
@@ -78,10 +85,26 @@
     exit;
 }
 
-$start = $_GET['start'];
+$start = isset($_GET['start']) ? $_GET['start'] : 0;
 if (!isset($start) || empty($start))
     $start = 0;
 
+$name = '';
+$search_type = '';
+$search_val = '';
+$val = '';
+if (!isset($_POST['search_all'])) {
+    $val = isset($_GET['val']) ? $_GET['val'] : '';
+    if (isset($_POST['search']))
+        $val = '';
+    else if ($val !== '')
+        list ($name, $search_type, $search_val) = split (",", $val);
+    if ($search_val == '')
+        $search_val = isset($_POST['search_val']) ? $_POST['search_val'] : '';
+    if ($search_type == '')
+        $search_type = isset($_POST['search_type']) ? $_POST['search_type'] : '';
+}
+
 if (isset($_SESSION['in_filter'])) {
     if ($_POST['back_list']) {
         unset($_SESSION['in_filter']);
@@ -243,7 +266,7 @@
 }
 
 require_once('list.php');
-ShowList($start, $msg);
+ShowList($start, $search_type, $search_val, $msg);
 closelog();
 exit;
 
diff -Nur myspam-0.0.3/web/lang.php myspam-0.0.4a/web/lang.php
--- myspam-0.0.3/web/lang.php	2006-05-11 11:58:11.000000000 +0800
+++ myspam-0.0.4a/web/lang.php	2007-06-11 09:39:12.078730048 +0800
@@ -11,11 +11,11 @@
 
 // login
 $lang['DESC_LOGIN'] = '系統登入';
-$lang['DESC_USER'] = '使用者';
-$lang['DESC_PASS'] = '密碼';
+$lang['DESC_USER'] = '帳號:';
+$lang['DESC_PASS'] = '密碼:';
 $lang['DESC_LOGIN_BTN'] = '登入';
 $lang['DESC_RESET_BTN'] = '清除';
-$lang['ERROR_LOGIN'] = '登入失敗, 可能是使用者或密碼輸入錯誤!';
+$lang['ERROR_LOGIN'] = "<script language=\"JavaScript\"> alert ('登入失敗, 帳號密碼輸入錯誤\\n或郵件伺服器未開啟!');</script>";
 $lang['HELP_DESC'] = '使用說明';
 
 // list
@@ -25,6 +25,8 @@
 $lang['HEAD_DATE'] = '收件日期';
 $lang['HEAD_SIZE'] = '信件大小';
 $lang['HEAD_CHOOSE'] = '選擇';
+$lang['LIST_SEARCH'] = '搜尋';
+$lang['LIST_SEARCH_ALL'] = '全部顯示';
 $lang['LIST_DELETE'] = '刪除';
 $lang['LIST_RESEND'] = '重送';
 $lang['LIST_LOGOUT'] = '登出';
@@ -34,9 +36,10 @@
 $lang['PAGE_GOTO'] = '前往頁面';
 $lang['PAGE_NEXT'] = '下一頁';
 $lang['PAGE_PREV'] = '上一頁';
-$lang['NOTSPAM_MESSAGE'] = '總共標示 %d 封非廣告信 (選擇 %d 封)';
-$lang['RESEND_MESSAGE'] = '總共送出 %d 封信 (選擇 %d 封)';
-$lang['DELETE_MESSAGE'] = '總共刪除 %d 封信';
+$lang['NOTSPAM_MESSAGE'] = "<script language=\"JavaScript\"> alert ('總共標示 %d 封非廣告信 (選擇 %d 封)');</script>";
+$lang['RESEND_MESSAGE'] = "<script language=\"JavaScript\"> alert ('總共送出 %d 封信 (選擇 %d 封)');</script>";
+$lang['DELETE_MESSAGE'] = "<script language=\"JavaScript\"> alert ('總共刪除 %d 封信');</script>";
+$lang['NO_SELECTED_MESSAGE'] = '尚未選擇任何信件!';
 
 // notify
 $lang['NOTIFY_SUBJECT'] = '%s 的廣告信通知';
diff -Nur myspam-0.0.3/web/list.php myspam-0.0.4a/web/list.php
--- myspam-0.0.3/web/list.php	2006-05-11 11:58:14.000000000 +0800
+++ myspam-0.0.4a/web/list.php	2007-06-11 09:39:15.470752494 +0800
@@ -6,7 +6,7 @@
     exit;
 }
 
-function ShowList($start, $msg = '')
+function ShowList($start, $search_type = '', $search_val = '', $msg = '')
 {
     global $smarty, $lang;
     global $dbhost, $dbuser, $dbpass, $dbname;
@@ -26,6 +26,9 @@
             'HEAD_DATE' => $lang['HEAD_DATE'],
             'HEAD_SIZE' => $lang['HEAD_SIZE'],
             'HEAD_CHOOSE' => $lang['HEAD_CHOOSE'],
+            'NO_SELECTED_MESSAGE' => $lang['NO_SELECTED_MESSAGE'],
+            'LIST_SEARCH' => $lang['LIST_SEARCH'],
+            'LIST_SEARCH_ALL' => $lang['LIST_SEARCH_ALL'],
             'LIST_DELETE' => $lang['LIST_DELETE'],
             'LIST_RESEND' => $lang['LIST_RESEND'],
             'LIST_FILTER' => $lang['LIST_FILTER'],
@@ -47,13 +50,56 @@
                 'ERROR_END' => '-->',
                 ));
     }
+    $dName = '';
+    if ($search_type == 'subject')
+        $dName = 'email_subject';
+    else if ($search_type == 'from')
+        $dName = 'email_from';
+
+    if ($dName !== '' && $search_val !== '') {
+        $in_search = true;
+        $search_filter = '&val='.urlencode("search,$search_type,$search_val");
+        if ($search_type == 'subject') {
+            $subject_selected = ' selected';
+            $from_selected = '';
+        }
+        else {
+            $subject_selected = '';
+            $from_selected = ' selected';
+        }
+        $smarty->assign(array(
+                'SEARCH_VAL' => $search_val,
+                'SUBJECT_SELECTED' => $subject_selected,
+                'FROM_SELECTED' => $from_selected,
+                'SEARCH_ALL_BEGIN' => '',
+                'SEARCH_ALL_END' => ''
+                ));
+    }
+    else {
+        $in_search = false;
+        $search_filter = '';
+        $smarty->assign(array(
+                'SEARCH_VAL' => '',
+                'SUBJECT_SELECTED' => '',
+                'FROM_SELECTED' => '',
+                'SEARCH_ALL_BEGIN' => '<!--',
+                'SEARCH_ALL_END' => '-->'
+                ));
+    }
+
     $aData = array();
     $conn = @mysql_connect($dbhost, $dbuser, $dbpass);
     if ($conn) {
         @mysql_select_db($dbname, $conn);
         @mysql_query("SET NAMES '".DB_ENCODING."'", $conn);
 
-        $sql = "select count(*)
+        if ($in_search)
+            $sql = "select count(*)
+                from myspam_email
+                where email_user = '".@mysql_escape_string($username)."'
+                and ".@mysql_escape_string($dName)." like '%".@mysql_escape_string($search_val)."%'";
+        else
+            $sql = "select count(*)
                 from myspam_email
                 where email_user = '".@mysql_escape_string($username)."'";
         $result = @mysql_query($sql, $conn);
@@ -70,11 +116,19 @@
     }
 
     if ($total > 0) {
-        $sql = "select email_id, email_from, email_subject, email_time, email_size
-                from myspam_email
-                where email_user = '".@mysql_escape_string($username)."'
-                order by email_time desc
-                limit $start, $pagesize";
+        if ($in_search)
+            $sql = "select email_id, email_from, email_subject, email_time, email_size
+                    from myspam_email
+                    where email_user = '".@mysql_escape_string($username)."'
+                    and ".@mysql_escape_string($dName)." like '%".@mysql_escape_string($search_val)."%'
+                    order by email_time desc
+                    limit $start, $pagesize";
+        else
+            $sql = "select email_id, email_from, email_subject, email_time, email_size
+                    from myspam_email
+                    where email_user = '".@mysql_escape_string($username)."'
+                    order by email_time desc
+                    limit $start, $pagesize";
         $result = @mysql_query($sql, $conn);
         if ($result) {
             $row_num = 0;
@@ -101,7 +155,7 @@
     $msg = $lang['PAGE_GOTO'];
     if ($cur_page != 1) {
         $pagestart = $start - $pagesize;
-        $msg .= " <a href=\"?start=$pagestart\">".$lang['PAGE_PREV']."</a>";
+        $msg .= " <a href=\"?start=$pagestart$search_filter\">".$lang['PAGE_PREV']."</a>";
     }
     $last_page = 1;
     for ($i = 1; $i <= 3; $i++) {
@@ -113,7 +167,7 @@
         }
         else {
             $pagestart = ($i-1) * $pagesize;
-            $msg .= " <a href=\"?start=$pagestart\">$i</a>";
+            $msg .= " <a href=\"?start=$pagestart$search_filter\">$i</a>";
         }
         $last_page = $i;
     }
@@ -138,7 +192,7 @@
         }
         else {
             $pagestart = ($i-1) * $pagesize;
-            $msg .= " <a href=\"?start=$pagestart\">$i</a>";
+            $msg .= " <a href=\"?start=$pagestart$search_filter\">$i</a>";
         }
         $last_page = $i;
     }
@@ -160,13 +214,13 @@
         }
         else {
             $pagestart = ($i-1) * $pagesize;
-            $msg .= " <a href=\"?start=$pagestart\">$i</a>";
+            $msg .= " <a href=\"?start=$pagestart$search_filter\">$i</a>";
         }
         $last_page = $i;
     }
     if ($cur_page != $totalpage) {
         $pagestart = $start + $pagesize;
-        $msg .= " <a href=\"?start=$pagestart\">".$lang['PAGE_NEXT']."</a>";
+        $msg .= " <a href=\"?start=$pagestart$search_filter\">".$lang['PAGE_NEXT']."</a>";
     }
 
     $smarty->assign('PAGE_RIGHT', $msg);
diff -Nur myspam-0.0.3/web/list.tpl myspam-0.0.4a/web/list.tpl
--- myspam-0.0.3/web/list.tpl	2006-05-11 11:58:15.000000000 +0800
+++ myspam-0.0.4a/web/list.tpl	2007-06-11 09:39:14.986749293 +0800
@@ -108,15 +108,34 @@
 	</tr>
 	<tr align="right">
 	  <td class="catBottom" colspan="5" height="29">
-		<input type="submit" name="delete" class="liteoption" value="<{$LIST_DELETE}>" />
-		&nbsp;
-		<input type="submit" name="resend" class="liteoption" value="<{$LIST_RESEND}>" />
-		&nbsp;
-		<input type="submit" name="notspam" class="liteoption" value="<{$LIST_NOTSPAM}>" />
-		&nbsp;
-		<input type="submit" name="filter" class="liteoption" value="<{$LIST_FILTER}>" />
-		&nbsp;
-		<input type="submit" name="logout" class="liteoption" value="<{$LIST_LOGOUT}>" />
+        <table width="100%" cellpadding="0" cellspacing="0" border="0">
+          <tr>
+            <td align="left">
+              <select name="search_type">
+                <option value="subject"<{$SUBJECT_SELECTED}>><{$HEAD_SUBJECT}></option>
+                <option value="from"<{$FROM_SELECTED}>><{$HEAD_FROM}></option>
+              </select>
+              <input type="text" class="post" name="search_val" size="30" maxlength="40" value="<{$SEARCH_VAL}>" />
+              &nbsp;
+              <input type="submit" name="search" class="liteoption" value="<{$LIST_SEARCH}>" />
+              <{$SEARCH_ALL_BEGIN}>
+              &nbsp;
+              <input type="submit" name="search_all" class="liteoption" value="<{$LIST_SEARCH_ALL}>" />
+              <{$SEARCH_ALL_END}>
+            </td>
+            <td align="right">
+              <input type="submit" name="delete" class="liteoption" value="<{$LIST_DELETE}>" onclick='return checkbox_confirm()' />
+              &nbsp;
+              <input type="submit" name="resend" class="liteoption" value="<{$LIST_RESEND}>" onclick='return checkbox_confirm()' />
+              &nbsp;
+              <input type="submit" name="notspam" class="liteoption" value="<{$LIST_NOTSPAM}>" onclick='return checkbox_confirm()' />
+              &nbsp;
+              <input type="submit" name="filter" class="liteoption" value="<{$LIST_FILTER}>" />
+              &nbsp;
+              <input type="submit" name="logout" class="liteoption" value="<{$LIST_LOGOUT}>" />
+            </td>
+          </td>
+        </table>
 	  </td>
 	</tr>
 	<tr>
@@ -154,11 +173,11 @@
 	</tr>
 	<tr align="right">
 	  <td class="catBottom" colspan="5" height="29">
-		<input type="submit" name="delete" class="liteoption" value="<{$LIST_DELETE}>" />
+		<input type="submit" name="delete" class="liteoption" value="<{$LIST_DELETE}>" onclick='return checkbox_confirm()' />
 		&nbsp;
-		<input type="submit" name="resend" class="liteoption" value="<{$LIST_RESEND}>" />
+		<input type="submit" name="resend" class="liteoption" value="<{$LIST_RESEND}>" onclick='return checkbox_confirm()' />
 		&nbsp;
-		<input type="submit" name="notspam" class="liteoption" value="<{$LIST_NOTSPAM}>" />
+		<input type="submit" name="notspam" class="liteoption" value="<{$LIST_NOTSPAM}>" onclick='return checkbox_confirm()' />
 		&nbsp;
 		<input type="submit" name="filter" class="liteoption" value="<{$LIST_FILTER}>" />
 		&nbsp;
@@ -173,12 +192,36 @@
 	  <td align="right" valign="top" nowrap="nowrap"><span class="nav"><{$PAGE_RIGHT}></span></td>
     </tr>
   </table>
+<{$SEARCH_BEGIN}>
+<{$SEARCH_MESSAGE}>
+<{$SEARCH_END}>
 </form>
 
 </body>
 <script language="JavaScript">
 <!---
-  DataTable_Init();
+DataTable_Init();
+
+function checkbox_confirm()
+{
+    var re = /[\S\w]+/;
+    var n = 0;
+
+    for (var j = 0; j < document.forms.length; j++) {
+        var f = document.forms[j];
+        for (var i = 0; i < f.elements.length; i++) {
+            var e = f.elements[i];
+            if (e.checked) {
+                n++;
+            }
+        }
+    }
+    if (n == 0) {
+        alert("<{$NO_SELECTED_MESSAGE}>");
+        return false;
+    }
+    return true;
+}
 //-->
 </script>
 </html>
diff -Nur myspam-0.0.3/web/save.php myspam-0.0.4a/web/save.php
--- myspam-0.0.3/web/save.php	2006-05-11 11:58:26.000000000 +0800
+++ myspam-0.0.4a/web/save.php	2007-06-11 09:44:11.644688373 +0800
@@ -96,7 +96,7 @@
                 else if (strcasecmp($header, 'Content-Type') == 0) {
                     $p = stristr($buf, 'charset=');
                     if ($p)
-                        $txt_encoding = trim(substr($p, 8), " \"");
+                        $txt_encoding = trim(substr($p, 8), " \"\r\n\t\0\x0B");
                 }
                 $aHeader[$x]['value'] .= ' '.trim($buf);
             }
@@ -113,17 +113,29 @@
         else if (strcasecmp($header, 'Content-Type') == 0) {
             $p = stristr($header_text, 'charset=');
             if ($p)
-                $txt_encoding = trim(substr($p, 8), " \"");
+                $txt_encoding = trim(substr($p, 8), " \"\r\n\t\0\x0B");
         }
     }
     fclose($fp);
 
+    if ($debug) writelog("txt_encoding is $txt_encoding");
+    if (strcasecmp($txt_encoding, 'iso-8859-1') == 0) {
+        $txt_encoding = '';
+        if ($debug) writelog("remove encoding for iso-8859-1");
+    }
+
     $from = preg_replace("(\r\n|\n|\r)", "", $from);
     $subject = preg_replace("(\r\n|\n|\r)", "", $subject);
 
+    if ($debug) writelog("from is $from");
+    if ($debug) writelog("subject is $subject");
+
     $decode_subject = find_decode_str($subject, $txt_encoding);
     $decode_from = find_decode_str($from, $txt_encoding);
 
+    if ($debug) writelog("after decode from is $decode_from");
+    if ($debug) writelog("after decode subject is $decode_subject");
+
     for ($i = 0; $i < $cnt; $i++)
         $aHeader[$i]['value'] = find_decode_str($aHeader[$i]['value'], $txt_encoding);
 
@@ -260,14 +272,14 @@
         $force_trans = '';
 
     if ($txt_encoding != '') {
-        $utf8_str = iconv($txt_encoding, ENCODING.$force_trans, $str);
-        $test_str = iconv(ENCODING, $txt_encoding, $utf8_str);
+        $utf8_str = @iconv($txt_encoding, ENCODING.$force_trans, $str);
+        $test_str = @iconv(ENCODING, $txt_encoding, $utf8_str);
         if ($test_str == $str || $force)
             return $utf8_str;
     }
     foreach ($aEncoding as $x) {
-        $utf8_str = iconv($x, ENCODING.$force_trans, $str);
-        $test_str = iconv(ENCODING, $x, $utf8_str);
+        $utf8_str = @iconv($x, ENCODING.$force_trans, $str);
+        $test_str = @iconv(ENCODING, $x, $utf8_str);
         if ($test_str == $str || $force)
             return $utf8_str;
     }
@@ -290,10 +302,20 @@
     $str = $matches[6];
     if ($type == 'B' || $type == 'b') {
         $decode_str = base64_decode($str);
-        $utf8_str = iconv($encoding, ENCODING, $decode_str);
+        $utf8_str = @iconv($encoding, ENCODING, $decode_str);
+        // if encoding is iso-8859-1, that's English, if should be same with UTF-8 string
+        if (strcasecmp($encoding, 'iso-8859-1') == 0) {
+            // if not match, try to decode it again.
+            if ($utf8_str != $decode_str) {
+                global $debug;
+
+                if ($debug) writelog("maybe not iso-8859-1, try it later");
+                return $decode_str;
+            }
+        }
         return $utf8_str;
     }
-    $decode_str = preg_replace_callback("|(=)([0-9a-fA-F]{2})|", QP_decode, $str);
+    $decode_str = preg_replace_callback("|(=)([0-9a-fA-F]{2})|", 'QP_decode', $str);
     return $decode_str;
 }
 
