Using Telnet with a POP3 Mail Server


mysql中insert into和replace into以及insert ignore用法區別:
insert into表示插入數據,數據庫會檢查主鍵,如果出現重複會報錯;
replace into表示插入替換數據,需求表中有PrimaryKey,或者unique索引,如果數據庫已經存在數據,則用新數據替換,如果沒有數據效果則和insert into一樣;
insert ignore表示,如果中已經存在相同的記錄,則忽略當前新數據;
create table testtb(
id int not null primary key,
name varchar(50),
age int
insert into testtb(id,name,age)values​​(1,"bb",13);
select * from testtb;
insert ignore into testtb(id,name,age)values​​(1,"aa",13);
select * from testtb;//仍是1,“bb”,13,因為id是主鍵,出現主鍵重複但使用了ignore則錯誤被忽略
replace into testtb(id,name,age)values​​(1,"aa",12);
select * from testtb; //數據變為1,"aa",12

Simulator 和 Emulator的差異

行動裝置(mobile device) 自從PDA, Smart Phone上市之後,不斷的發展
也是百家爭鳴的一塊大餅,Symbian、Windows Mobile, iPhone OS and Android等

*Symbian是由Ericsson、Panasonic、NOKIA、Simens AG、Ericsson等公司所共同開發並擁用的專為手機硬體而設計的作業系統
*Windows Mobile 是由微軟針對行動裝置而設計的作業系統
*iPhone OS是由Apple公司發售的iPhone手機的作業系統



Simulator : 透過您電腦的硬體環境運作軟體,因此效能會比較好
Emulator : 完完全全的硬體模擬,讓你了解軟體在實機上運作的結果


Google Chart API Online





{$} {* PHP方式:$_GET[“page"] *}

{$} {* PHP方式:$_POST[“page"] *}

{$smarty.cookies.username} {* PHP方式:$_COOKIE[“username"] *}

{$} {* PHP方式:$_SESSION[“id"] *}

{$smarty.server.SERVER_NAME} {* PHP方式:$_SERVER[“SERVER_NAME"] *}

{$smarty.env.PATH} {* PHP方式:$_ENV[“PATH"]*}

{$smarty.request.username} {* PHP方式:$_REQUEST[“username"] *}


{$smarty.const._MY_CONST_VAL} {* 輸出PHP腳本中自定義的常量*}

{$smarty.const.__FILE__} {* 通過保留變量數組直接輸出系統常量*}


可以用date_format調節器格式化輸出. 例如{$|date_format:"%Y-%m-%d %H:%M:%S"}


你可以直接訪問PHP常量. 例如{$smarty.const._MY_CONST_VAL}


可以通過{capture}..{/capture}結構截取的輸出可以使用{$smarty} 變量訪問.




{$smarty.section}, {$smarty.foreach}

{$smarty} 變量可以訪問’section’和’foreach’循環的屬性.

{$smarty.template} 顯示當前被處理的模板的名字.



{$smarty.ldelim} 顯示左分隔符

{$smarty.rdelim} 顯示右分隔符

Say Goodbye to the Menu Button

Before Android 3.0 (Honeycomb), all Android-powered devices included a dedicated Menu button. As a developer, you could use the Menu button to display whatever options were relevant to the user, often using the activity’s built-in options menu. Honeycomb removed the reliance on physical buttons, and introduced the ActionBar class as the standard solution to make actions from the user options immediately visible and quick to invoke. In order to provide the most intuitive and consistent user experience in your apps, you should migrate your designs away from using the Menu button and toward using the action bar. This isn’t a new concept — the action bar pattern has been around on Android even before Honeycomb — but as Ice Cream Sandwich rolls out to more devices, it’s important that you begin to migrate your designs to the action bar in order to promote a consistent Android user experience.

You might worry that it’s too much work to begin using the action bar, because you need to support versions of Android older than Honeycomb. However, it’s quite simple for most apps because you can continue to support the Menu button on pre-Honeycomb devices, but also provide the action bar on newer devices with only a few lines of code changes.

If I had to put this whole post into one sentence, it’d be: Set targetSdkVersion to 14 and, if you use the options menu, surface a few actions in the action bar with showAsAction="ifRoom".

Don’t call it a menu

Not only should your apps stop relying on the hardware Menu button, but you should stop thinking about your activities using a “menu button” at all. Your activities should provide buttons for important user actions directly in the action bar (or elsewhere on screen). Those that can’t fit in the action bar end up in the action overflow.

In the screenshot here, you can see an action button for Search and the action overflow on the right side of the action bar.

Even if your app is built to support versions of Android older than 3.0 (in which apps traditionally use the options menu panel to display user options/actions), when it runs on Android 3.0 and beyond, there’s no Menu button. The button that appears in the system/navigation bar represents the action overflow for legacy apps, which reveals actions and user options that have “overflowed off the screen.”

This might seem like splitting hairs over terminology, but the name action overflow promotes a different way of thinking. Instead of thinking about a menu that serves as a catch-all for various user options, you should think more about which user options you want to display on the screen as actions. Those that don’t need to be on the screen can overflow off the screen. Users can reveal the overflow and other options by touching an overflow button that appears alongside the on-screen action buttons.

Action overflow button for legacy apps

If you’ve already developed an app to support Android 2.3 and lower, then you might have noticed that when it runs on a device without a hardware Menu button (such as a Honeycomb tablet or Galaxy Nexus), the system adds the action overflow button beside the system navigation.

This is a compatibility behavior for legacy apps designed to ensure that apps built to expect a Menu button remain functional. However, this button doesn’t provide an ideal user experience. In fact, in apps that don’t use an options menu anyway, this action overflow button does nothing and creates user confusion. So you should update your legacy apps to remove the action overflow from the navigation bar when running on Android 3.0+ and begin using the action bar if necessary. You can do so all while remaining backward compatible with the devices your apps currently support.

If your app runs on a device without a dedicated Menu button, the system decides whether to add the action overflow to the navigation bar based on which API levels you declare to support in the <uses-sdk> manifest element. The logic boils down to:

  • If you set either minSdkVersion or targetSdkVersion to 11 or higher, the system will not add the legacy overflow button.
  • Otherwise, the system will add the legacy overflow button when running on Android 3.0 or higher.
  • The only exception is that if you set minSdkVersion to 10 or lower, set targetSdkVersion to 11, 12, or 13, and you do not use ActionBar, the system will add the legacy overflow button when running your app on a handset with Android 4.0 or higher.

That exception might be a bit confusing, but it’s based on the belief that if you designed your app to support pre-Honeycomb handsets and Honeycomb tablets, it probably expects handset devices to include a Menu button (but it supports tablets that don’t have one).

So, to ensure that the overflow action button never appears beside the system navigation, you should set the targetSdkVersion to 14. (You can leaveminSdkVersion at something much lower to continue supporting older devices.)

Migrating to the action bar

If you have activities that use the options menu (they implement onCreateOptionsMenu()), then once the legacy overflow button disappears from the system/navigation bar (because you’ve set targetSdkVersion to 14), you need to provide an alternative means for the user to access the activity’s actions and other options. Fortunately, the system provides such a means by default: the action bar.

Add showAsAction="ifRoom" to the <item> elements representing the activity’s most important actions to show them in the action bar when space is available. For help deciding how to prioritize which actions should appear in the action bar, see Android Design’s Action Bar guide.

To further provide a consistent user experience in the action bar, we suggest that you use action icons designed by the Android UX Team where appropriate. The available icons support common user actions such as Refresh, Delete, Attach, Star, Share and more, and are designed for the light and dark Holo themes. Here they are!

If these icons don’t accommodate your needs and you need to create your own, you should follow the Iconography design guide.

Removing the action bar

If you don’t need the action bar, you can remove it from your entire app or from individual activities. This is appropriate for apps that never used the options menu or for apps in which the action bar doesn’t meet design needs (such as games). You can remove the action bar using a theme such asTheme.Holo.NoActionBar or Theme.DeviceDefault.NoActionBar.

In order to use such a theme and remain backward compatible, you can use Android’s resource system to define different themes for different platform versions, as described by Adam Powell’s post, Holo Everywhere. All you need is your own theme, which you define to inherit different platform themes depending on the current platform version.

For example, here’s how you can declare a custom theme for your application:

<application android:theme="@style/NoActionBar">

Or you can instead declare the theme for individual <activity> elements.

For pre-Honeycomb devices, include the following theme in res/values/themes.xml that inherits the standard platform theme:

    <style name="NoActionBar" parent="@android:style/Theme">
        <!-- Inherits the default theme for pre-HC (no action bar) -->

For Honeycomb and beyond, include the following theme in res/values-v11/themes.xml that inherits a NoActionBar theme:

    <style name="NoActionBar" parent="@android:style/Theme.Holo.NoActionBar">
        <!-- Inherits the Holo theme with no action bar; no other styles needed. -->

At runtime, the system applies the appropriate version of the NoActionBar theme based on the system’s API version.


    • Android no longer requires a dedicated Menu button, some devices don’t have one, and you should migrate away from using it.
    • Set targetSdkVersion to 14, then test your app on Android 4.0.
    • Add showAsAction="ifRoom" to menu items you’d like to surface in the action bar.


    • If the ActionBar doesn’t work for your app, you can remove it with Theme.Holo.NoActionBar or Theme.DeviceDefault.NoActionBar.


For information about how you should design your action bar, see Android Design’s Action Bar guide. More information about implementing the action bar is also available in the Action Bar developer guide.

The Latest in HTML 5

WebSockets vs Server-Sent Events vs Long-polling

Apparently social networking is the banner of the nowadays web. Everybody intends bringing some features into his projects. Some of them require immediate notification. That is getting common, if you open a page with upcoming messages (status feed, notification subsystem, friends-list), you expected them being updated as soon as a new message (status, notification, friend-making action) arrives. As you well know, original web design allowed only one-way client-server communication (one requests, another one responds), though now HTML5 working group doing their best to fix it or rather to patch it. However, the web-projects are still using long-polling trick to emulate server-client communication.

Well, now new web browser versions appear every few months. Besides they update automatically. Thus a huge number of users have the latest browser versions, which support HTML 5 communication APIs. Is that the time to put long-polling away? Let’s find out.

Our test task will be something you may likely need if you have on your site any sort of user communication. That is notification of user actions. In the simplest case when the user gets a private message, the number of unread notifications increases in the user panel. We will solve the task using long-polling, Server-Sent Events and WebSockets. Then we compare the results.

First of all let’s examine the common code used in the examples. We will need configuration file, a library to access DB, a model to retrieve unread notification number and to add a new notification.

Usually such communication API examples don’t include any business logic, but execution delays to emulate the model working. I would like to make it close to the real application, what is meant to help when comparing memory/CPU usage on the server for each of the cases.

So, we will need a dump DB table:


CREATE TABLE IF NOT EXISTS `notification` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `recipientUid` int(10) unsigned NOT NULL, `eventId` int(10) unsigned NOT NULL, `isNew` tinyint(1) unsigned NOT NULL DEFAULT '1', PRIMARY KEY (`id`), KEY `IX_recipientUid` (`recipientUid`), KEY `IX_isNew` (`isNew`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='User notifications';


Here is the model:

<?php class Model_UserNotification {    private $_db;    public function  __construct(Lib_Db $db)    {         $this->_db = $db;    }    /**     *     * @param int $recipientUid     * @return int     */    public function fetchNumberByRecipientUid($recipientUid)    {        return $this->_db->fetch("SELECT count(*) as count "            . " FROM notification WHERE recipientUid = %d AND isNew = 1"            , $recipientUid)->count;    }    /**     *     * @param int $recipientUid     * @param int $eventId     */    public function add($recipientUid, $eventId)    {        $this->_db->update("INSERT INTO "            . " notification (`id`, `recipientUid`, `eventId`, `isNew`) VALUES (NULL, '%d', '%d', '1')"            , $recipientUid, $eventId);    }    /**     *     * @param int $recipientUid     */    public function removeAll($recipientUid)    {        $this->_db->update("DELETE FROM "            . " notification WHERE recipientUid = %d"            , $recipientUid);    } }


Long pulling

 Long-polling technique explanation


How it works

Client application (browser) sends a request with event recipient id (here is the user, registered on the page) and current state (the displayed number of unread notification) to the server via HTTP. It creates an Apache process, which repeatedly checks DB until the state is changed in there. When the state eventually changed, the client gets the server response and sends next request to the server.



Client side contains simple HTML with two input fields to show response data (updated number of unread notifications and time of the response event). JS module sends recipient user id and current state (unread notification number) to the server as XMLHttpRequest. To make possible cross-domain communication, we use JSONP and that means the handler must of the public scope.


... <p>Recipient id: <?= $recipientUid ?></p> <p>Notifications: <input id="notificationNum" size="4" name="some" value="<?= $displayedNotificationNum ?>" /></p> <p>Last event arrived at: <input id="time" size="12" name="some" value="0" /></p> <script type="text/javascript"> (function( $ ) { var UID = <?= $recipientUid ?>; $.NotifierLongPolling = (function() {     var _stateNode = $('#notificationNum'), _timeNode = $('#time');     return {         onMessage : function(data) {             _stateNode.val(data.updatedNotificationNum);             _timeNode.val(data.time);             setTimeout($.NotifierLongPolling.send, 3000);         },         send : function() {                        $.ajax({                     'url': 'server.php',                     'type': 'POST',                     'dataType': 'jsonp',                     'jsonpCallback': '$.NotifierLongPolling.onMessage',                     'data': 'recipientUid=' + UID + '&displayedNotificationNum='                         + _stateNode.val()             });         }     } }()); // Document is ready $(document).bind('', function() {    setTimeout($.NotifierLongPolling.send, 40);  }); })( jQuery ); </script>


Server waits 3 second than check if the updated state matches the given one. If the state has changed in the DB, the server responds otherwise it repeats the cycle.


//... $recipientUid = (int)$_REQUEST["recipientUid"]; $displayedNotificationNum = (int)$_REQUEST["displayedNotificationNum"]; $secCount = 0; do {     sleep(IDLE_TIME);     $updatedNotificationNum = $model->fetchNumberByRecipientUid($recipientUid); } while ($updatedNotificationNum == $displayedNotificationNum); header("HTTP/1.0 200"); printf ('%s({"time" : "%s", "updatedNotificationNum" : "%d"});'     , $_REQUEST["callback"], date('d/m H:i:s'), $updatedNotificationNum);


Client side receives new state from the server, displays and sends to the server the new state to repeat the workflow.


 Long-polling technique usage example screenshot


Server-Sent Events


 Server-Sent Event API explanation


How it works

Client (browser) sends a request to the server via HTTP. It creates a process, which fetches latest state in the DB and responds back. Client gets server response and in 3 seconds sends next request to the server.



HTML on client-size has again two input fields to show response data. JS module opens EventSource and passes though the connection recipient user id.


... <p>Recipient id: <?= $recipientUid ?></p> <p>Notifications: <input id="notificationNum" size="4" name="some" value="<?= $displayedNotificationNum ?>" /></p> <p>Last event arrived at: <input id="time" size="12" name="some" value="0" /></p> <script type="text/javascript"> (function( $ ) { var UID = <?= $recipientUid ?>; NotifierSSE = (function() {     var _stateNode = $('#notificationNum'),         _timeNode = $('#time'),         _src,         _handler = {         onMessage : function(event) {                          var data = JSON.parse(;             _stateNode.val(data.updatedNotificationNum);             _timeNode.val(data.time);         }     };     return {         init : function () {         _src = new EventSource("server.php?recipientUid=" + UID);         _src.addEventListener('message', _handler.onMessage, false);         }     } }()); // Document is ready $(document).bind('', function() {    setTimeout(NotifierSSE.init, 40);  }); })( jQuery ); </script>


Server responds into the data stream with the last state (unread notification number) regarding the recipient user id.


//... header('Content-Type: text/event-stream'); header('Cache-Control: no-cache'); // recommended to prevent caching of event data. $recipientUid = (int)$_REQUEST["recipientUid"]; function send($updatedNotificationNum) {     printf ("id: %s\n\n", PROC_ID);     printf ('data: {"time" : "%s", "updatedNotificationNum" : "%d"}' . "\n\n"         ,date('d/m H:i:s') , $updatedNotificationNum);     ob_flush();     flush(); } while (true) {     send($model->fetchNumberByRecipientUid($recipientUid));     sleep(IDLE_TIME); }  //...


Client gets onMessage event handler invoked, the data displayed. Browser will repeat request every 3 second unless you close the connection (close method). You can change delay between requests by passing into the data stream on the server “retry: 


 Server-Sent Event API usage example screenshot




 WebSocket API explanation


How it works

Client notifies web-socket server (EventMachine) of an event, giving ids of recipients. The server immediately notifies all the active clients (subscribed to that type of event). Clients process event when given recipient Id matches the client’s one.



Here we need an Event Machine supporting WebSockets. The easiest way, I see, is to deployWaterSpout Server . You write your own controller (notification_controller.php) based on locke_controller.php.

Client opens WebSocket connection and subscribes a handler for events on /notification/updates post. Now let’s add a button in the HTML which sends on /notification/presents recipient user and action ids. That will cause broadcast message on the all open connections. So every active client receives the notification. The client event handler checks if the recipient user id matches client’s logged in user id and if so increment unread notification number.


<p>Recipient id: <?= $recipientUid ?></p>     <p>Notification: <span id="display"></span></p>     <button id="test">Fire an event</button> <script>     realtime = new realtimeComm( + ":20001");     realtime.addListener('/notification/updates', function(response) {         $('#display').html('Client #' + + ' broadcast an action #' +;     });     $('#test').bind('click', this, function(e){         e.preventDefault();         realtime.send('/notification/presence', {             'actionId': 1,             'recipientUid': <?= $recipientUid ?>         }, function() {});     }); </script>


Working a bit on the controller, you can make the system responds exclusively to the client of the given recipient user id.

You’ve probably noticed the example working perfect on Chrome, but for Firefox 6.0 it switches for long-polling. It announced that Firefox 6 supports WebSockets, but you ain’t going to find WebSocket object defined. Well, let’s change WebSocket availability check in the top of realtime.js with following:


if (!window.WebSocket) {             window.WebSocket = window.MozWebSocket ? window.MozWebSocket : undefined;  }


Oops, it doesn’t work anyway. Firefox 6 supports hybi-07 specification version, when Chrome and WaterSpout – hybi-00 (hixie-76). So, you will hardly able the connection through reverse-proxies and gateways. Besides, the old specification was disabled in Firefox and Opera due to security issues. The only browsers now supporting the latest WebSocket specification are betas of Firefox 7/8 and Chrome 14. As for EventMachine server implementations, I found none.


 WebSocket API usage example screenshot




.. Long-polling Server-Sent Events WebSockets
Browser support Supported by the most of currently used browsers Supported by Chrome 9+, Firefox 6+, Opera 11+, Safari 5+ The latest hybi-10 protocol supported by Chrome 14, Firefox 7 betas, hybi-07 supported by Firefox 6
Server-loading Takes little of CPU resources, but creates idle processes per user expending server memory Works in many ways as long-polling, unless SSE doesn’t need to close connection every time when response is sent The best possible solution. Server has the only process serving any requests. No loops, memory/CPU expense per client, but per client action
Client-loading Depends on implementation, though it always an asynchronous process. Natively implemented in the browser, takes minimum resources Natively implemented in the browser, takes minimum resources
Timeliness Near real-time, though black out period between sending response and making a new request adds some delay Default delay 3 sec., but can be changed True real-time
Complexity of implementation Very easy Even easier Requires an EventMachine server and a custom port being open

GPU Comparisons – Performance Comparison Benchmarks

Android and the HTTP download file headers