<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-2069539672100748782</id><updated>2012-02-24T04:24:21.399-08:00</updated><category term='node.js'/><category term='hack'/><category term='tools'/><category term='Web Prog.'/><category term='CSS'/><category term='security'/><category term='Image Processing'/><category term='Software Modeling'/><category term='Windows'/><category term='cloud'/><category term='bash'/><category term='Java'/><category term='Apple'/><category term='Google'/><category term='HTTP'/><category term='Requirement Engineering'/><category term='PHP'/><category term='Vim'/><category term='Ruby'/><category term='Database'/><category term='Linux'/><category term='TextMate'/><category term='spam'/><category term='Eclipse'/><category term='Mac'/><category term='HTML'/><category term='Lua'/><category term='network'/><category term='Configuraiton Management'/><category term='iOS'/><category term='Job Interview'/><category term='JavaScript'/><category term='hardware'/><title type='text'>Hack into the LIFE ;-)</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>86</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-1499081040583315590</id><published>2012-02-15T23:54:00.000-08:00</published><updated>2012-02-16T23:06:15.939-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='Vim'/><title type='text'>Janus with jslint Vim plugin</title><content type='html'>Nowadays, I write quite a bit of JavaScript and uses JSLint command line tool quite a lot. A co-worker recommends a nice &lt;a href="https://github.com/hallettj/jslint.vim"&gt;Vim plugin&lt;/a&gt; that validates your JavaScript code when you are editing and when you save it.&lt;br /&gt;&lt;br /&gt;While I was trying to install it for &lt;a href="https://github.com/carlhuda/janus"&gt;Janus&lt;/a&gt; (a Macvim clone that I uses), I ran into two issues:&lt;br /&gt;&lt;br /&gt;1. By default, when you run rake inside the git cloned directory, the plugin gets installed into ~/.vim. For Janus, user customized plugins should go to ~/.janus, and Janus will load them automatically. For details, please check out &lt;a href="https://github.com/carlhuda/janus/wiki/Customization"&gt;the Customization section&lt;/a&gt; of the Janus documents.&lt;br /&gt;&lt;br /&gt;So, to get around:&lt;br /&gt;&lt;br /&gt;- create a jslint directory in ~/.janus&lt;br /&gt;- edit &lt;a href="https://github.com/hallettj/jslint.vim/blob/master/Rakefile"&gt;vim plugin's Rake file&lt;/a&gt;, replace line 38 &lt;span class="Apple-style-span" style="color: #333333; font-family: 'Bitstream Vera Sans Mono', Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"&gt;&lt;span class="no" style="color: teal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;File&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #333333; font-family: 'Bitstream Vera Sans Mono', Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"&gt;&lt;span class="o" style="font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #333333; font-family: 'Bitstream Vera Sans Mono', Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"&gt;&lt;span class="n" style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;expand_path&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #333333; font-family: 'Bitstream Vera Sans Mono', Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"&gt;&lt;span class="p" style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #333333; font-family: 'Bitstream Vera Sans Mono', Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"&gt;&lt;span class="s2" style="color: #dd1144; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;"~/.vim"&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #333333; font-family: 'Bitstream Vera Sans Mono', Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"&gt;&lt;span class="p" style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;)&lt;/span&gt;&lt;/span&gt; with&amp;nbsp;&lt;span class="Apple-style-span" style="color: #333333; font-family: 'Bitstream Vera Sans Mono', Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"&gt;&lt;span class="no" style="color: teal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;File&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #333333; font-family: 'Bitstream Vera Sans Mono', Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"&gt;&lt;span class="o" style="font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #333333; font-family: 'Bitstream Vera Sans Mono', Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"&gt;&lt;span class="n" style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;expand_path&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #333333; font-family: 'Bitstream Vera Sans Mono', Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"&gt;&lt;span class="p" style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #333333; font-family: 'Bitstream Vera Sans Mono', Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"&gt;&lt;span class="s2" style="color: #dd1144; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;"~/.janus/jslint"&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #333333; font-family: 'Bitstream Vera Sans Mono', Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"&gt;&lt;span class="p" style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;)&lt;/span&gt;&lt;/span&gt;, you get the idea.&lt;br /&gt;- run rake from inside vim plugin directory and it should install into the correct Janus directory&lt;br /&gt;&lt;br /&gt;2. The second issue is that I keep getting warning when I start trying out the plugin, something like "s:cmd" not defined. Did some poking around and it seems like&amp;nbsp;&lt;span class="Apple-style-span" style="color: #333333; font-family: 'Bitstream Vera Sans Mono', Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"&gt;&lt;span class="no" style="color: teal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;a href="https://github.com/hallettj/jslint.vim/blob/master/ftplugin/javascript/jslint.vim"&gt;ftplugin/javascript/jslint.vim&lt;/a&gt;&lt;/span&gt;&lt;span class="no" style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;/span&gt;is trying to find a JavaScript interpreter (line 62 to 75 for *UNIX systems) and somehow failed.&lt;br /&gt;&lt;br /&gt;I am on Snow Leopard, which comes with an acceptable interpreter "jsc" at&amp;nbsp;&lt;span class="Apple-style-span" style="color: #dd1144; font-family: 'Bitstream Vera Sans Mono', Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"&gt;/System/Library/Frameworks/JavaScriptCore.framework/Resources/jsc&lt;/span&gt;, so not really sure why it did not work. I ended up just install Node.JS (for Mac users, highly recommend using Homebrew, just &lt;a href="http://shapeshed.com/setting-up-nodejs-and-npm-on-mac-osx/"&gt;follow instructions here&lt;/a&gt;) and added node to my PATH. And it takes care of these errors.&lt;br /&gt;&lt;br /&gt;Now, enjoy the jslint plugin and be a good JS developer ;-)&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-3kSDwuFkb-E/Tz38UErbiAI/AAAAAAAALdM/VIIdPjBMCNk/s1600/Janus-jslint-vim.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="292" src="http://4.bp.blogspot.com/-3kSDwuFkb-E/Tz38UErbiAI/AAAAAAAALdM/VIIdPjBMCNk/s640/Janus-jslint-vim.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;P.S. For people not happy with Crockford's personal styles (some styles don't make sense to me either), you can update options in ~/.jslintrc (&lt;a href="https://github.com/hallettj/jslint.vim"&gt;see examples&lt;/a&gt; on jslint.vim site). Or simply use &lt;a href="https://github.com/wookiehangover/jshint.vim"&gt;jshint vim plugin&lt;/a&gt; instead. &lt;a href="http://www.jshint.com/"&gt;JSHint&lt;/a&gt; is a more relaxed and reasonable fork of JSLint.&lt;br /&gt;&lt;br /&gt;Sorry for going off the topic, but it is quite funny to read about &lt;a href="http://anton.kovalyov.net/2011/02/20/why-i-forked-jslint-to-jshint/"&gt;why the original developer forked JSLint&lt;/a&gt;, especially entertaining are the comments. For example, Crockford's response to JSHint:&lt;br /&gt;&lt;blockquote class="tr_bq"&gt;&lt;span class="Apple-style-span" style="font-size: 14px;"&gt;When asked for his "feelings on JSHint" Crockford replied "There are many stupid people in this world, and now there is a tool for them."&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-1499081040583315590?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/1499081040583315590/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2012/02/janus-with-jslint-vim-plugin.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/1499081040583315590'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/1499081040583315590'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2012/02/janus-with-jslint-vim-plugin.html' title='Janus with jslint Vim plugin'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-3kSDwuFkb-E/Tz38UErbiAI/AAAAAAAALdM/VIIdPjBMCNk/s72-c/Janus-jslint-vim.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-1841974686346717143</id><published>2012-01-28T13:04:00.000-08:00</published><updated>2012-01-28T14:47:10.174-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Eclipse'/><category scheme='http://www.blogger.com/atom/ns#' term='Lua'/><title type='text'>Lua Development Tools Koneki, IDE based on Eclipse</title><content type='html'>Just got a comment from developers of Lua IDE Koneki on &lt;a href="http://mwebhack.blogspot.com/2010/10/luaeclipse-setup-on-snow-leopard_29.html"&gt;my previous post&lt;/a&gt; about setting up Eclipse-based Lua IDE. So, I gave it a try and it is quite neat, I really hope the developers can keep it moving and make it a great default IDE for Lua developers ;-) As of now, I feel it is not yet conveniently as useful as LuaEclipse I posted about a while back. But the project is under active development and it will become better every day, I am sure.&lt;br /&gt;&lt;br /&gt;Here is a quick rundown what I have tried so far:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1. Installation:&lt;/b&gt; they offer both standalone and update site, I just installed through update site following &lt;a href="http://www.eclipse.org/koneki/ldt/#installation"&gt;their instructions&lt;/a&gt;. I am on Eclipse 3.7.1, btw. I also got lua and luarocks installed through &lt;a href="http://mxcl.github.com/homebrew/"&gt;Homebrew&lt;/a&gt;&amp;nbsp;(by default they are installed in /usr/local/bin).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;2. Create a new Lua project:&lt;/b&gt; create a new Lua project, add source files under src, similar to the typical Java projects.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;3. Ready to run?&lt;/b&gt; I feel stuck at this step at first since there is no launch configuration that allows me to configure the local Lua environment. After running through several threads, it seems &lt;a href="http://www.eclipse.org/forums/index.php/t/273959/"&gt;Koneki does not support launch configuration yet&lt;/a&gt;. It only supports "remote debug launch configuration".&lt;br /&gt;&lt;br /&gt;But the developer also provides this workaround using "External Tools" and I got it to run and show the results in Console View. This is the sample configuration (you need to select the main.lua before run this external tool configuration). For the meaning of Eclipse variables like ${workspace_loc}, ${resource_loc}, see &lt;a href="http://help.eclipse.org/helios/index.jsp?topic=%2Forg.eclipse.platform.doc.user%2Ftasks%2Ftasks-exttools-running.htm"&gt;Eclipse external tools documentation&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-BEGdsR0UvPI/TyRd5LBaLXI/AAAAAAAALZU/bcaJKKqKiR8/s1600/Lua-Koneki.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="433" src="http://4.bp.blogspot.com/-BEGdsR0UvPI/TyRd5LBaLXI/AAAAAAAALZU/bcaJKKqKiR8/s640/Lua-Koneki.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;b&gt;4. Debugging.&lt;/b&gt; LDT supports remote debugging via DBGP, you can follow &lt;a href="http://wiki.eclipse.org/Koneki/LDT/User_Guide"&gt;the LDT user guide&lt;/a&gt; to set it up.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Many thanks to the LDT developers for this nice IDE. I wish the launch configuration can be added so beginners like me can get started with Lua and LDT quickly. Also, I wish the configuration of debugging and remote debugging can be integrated into LDT.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-1841974686346717143?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/1841974686346717143/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2012/01/lua-development-tools-koneki-ide-based.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/1841974686346717143'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/1841974686346717143'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2012/01/lua-development-tools-koneki-ide-based.html' title='Lua Development Tools Koneki, IDE based on Eclipse'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-BEGdsR0UvPI/TyRd5LBaLXI/AAAAAAAALZU/bcaJKKqKiR8/s72-c/Lua-Koneki.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-3153329254495226945</id><published>2012-01-23T09:38:00.000-08:00</published><updated>2012-01-23T09:39:37.043-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><title type='text'>Unbounded function wrappers</title><content type='html'>I was reading "JavaScript Garden" (highly recommend for JS beginner/intermediate) and could not understand the concept of the "fast, unbound wrappers" for functions. See &lt;a href="http://bonsaiden.github.com/JavaScript-Garden/#function.arguments"&gt;Function arguments&lt;/a&gt; for the example.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: js; ruler: true; highlight: 9"&gt;function Foo() {}&lt;br /&gt;&lt;br /&gt;Foo.prototype.method = function(a, b, c) {&lt;br /&gt;    console.log(this, a, b, c);&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;// Create an unbound version of "method" &lt;br /&gt;// It takes the parameters: this, arg1, arg2...argN&lt;br /&gt;Foo.method = function() {&lt;br /&gt;&lt;br /&gt;    // Result: Foo.prototype.method.call(this, arg1, arg2... argN)&lt;br /&gt;    Function.call.apply(Foo.prototype.method, arguments);&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Luckily I found &lt;a href="http://stackoverflow.com/questions/7459769/whats-the-purpose-of-using-function-call-apply-in-javascript"&gt;this Stackoverflow post&lt;/a&gt; that explains the idea behind it. It took me a while to wrap my head around Function.call.apply ;-)&lt;br /&gt;&lt;br /&gt;So, the basic idea is that we have a function defined in a class, but we want to use it without binding to specific object, maybe the concept of static method in Java? So, instead of creating an object and invoke the function on the object, we define the function as a property of the class, not on its prototype.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-3153329254495226945?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/3153329254495226945/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2012/01/unbounded-function-wrappers.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/3153329254495226945'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/3153329254495226945'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2012/01/unbounded-function-wrappers.html' title='Unbounded function wrappers'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-5936448106489972464</id><published>2011-12-28T11:51:00.000-08:00</published><updated>2012-01-04T15:46:13.319-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tools'/><category scheme='http://www.blogger.com/atom/ns#' term='Vim'/><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><title type='text'>useful vim tips</title><content type='html'>Vim is definitely a text editor you need to &lt;a href="http://news.ycombinator.com/item?id=2936670"&gt;learn progressively&lt;/a&gt;&amp;nbsp;because it has &lt;a href="http://www.terminally-incoherent.com/blog/2006/08/01/text-editor-learning-curves/"&gt;an interesting learning curve&lt;/a&gt;. If you have not read "&lt;a href="http://www.moolenaar.net/habits.html"&gt;&lt;b&gt;Seven Habits of Effective Text Editing&lt;/b&gt;&lt;/a&gt;" from Bram Moolenaar (main author of Vim), please do that first. There is also an updated version of this article that can be found &lt;a href="http://www.moolenaar.net/vim.html"&gt;here&lt;/a&gt;. Basically, there are three steps to improve your Vim skills through daily work:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;find repeated actions that are not efficient or quick enough&lt;/li&gt;&lt;li&gt;find a quicker way (search online, ask around, read documentation and tutorials, etc.)&lt;/li&gt;&lt;li&gt;practice the new tricks and make it a habbit&lt;/li&gt;&lt;/ol&gt;So, basically I am trying to take notes about some new tricks I learned over the past week. Hopefully, I will do the iterations and find even more efficient ways to do these in the future.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Quickly move around on a line.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="color: red;"&gt;0&lt;/span&gt;&lt;/b&gt; (zero) moves the cursor to the beginning of a line (white spaces are considered as characters)&lt;br /&gt;&lt;b&gt;&lt;span style="color: red;"&gt;$&lt;/span&gt;&lt;/b&gt; moves the cursor to the end of a line (white space are considered)&lt;br /&gt;&lt;b&gt;&lt;span style="color: red;"&gt;^&lt;/span&gt;&lt;/b&gt; moves the cursor to the beginning of a line (white space ignored)&lt;br /&gt;&lt;b&gt;&lt;span style="color: red;"&gt;g_&lt;/span&gt;&lt;/b&gt; moves to cursor to the end of a line (white space ignored)&lt;br /&gt;&lt;br /&gt;For example (using + to stand for space here for illustration purpose):&lt;br /&gt;&lt;pre class="brush: text; gutter: false"&gt;++a line++&lt;br /&gt;- -    - - &lt;br /&gt;0 ^    $ g_&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="color: red;"&gt;w, W&lt;/span&gt;&lt;/b&gt; move the cursor forward to the beginning of a word, the difference between the two is W uses white space as separator. So, for me w is quite useful in code, W is useful in the textual sentences.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="color: red;"&gt;e, E&lt;/span&gt;&lt;/b&gt; move the cursor forward to the end of a word, same difference as in w and W.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="color: red;"&gt;b, B&lt;/span&gt;&lt;/b&gt; move the cursor backward to the beginning of a word, difference is again the separator.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="color: red;"&gt;ge, gE&lt;/span&gt;&lt;/b&gt; move the cursor backward to the end of a word.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="color: red;"&gt;*, #&lt;/span&gt;&lt;/b&gt; to quickly move forward and backward to the same word under the cursor. This is faster than search using / and press N and n.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="color: red;"&gt;o&lt;/span&gt;&lt;/b&gt; adds a new line under current line and start insert.&lt;br /&gt;&lt;b&gt;&lt;span style="color: red;"&gt;O&lt;/span&gt;&lt;/b&gt; adds a new line above current line and start insert.&lt;br /&gt;&lt;b&gt;&lt;span style="color: red;"&gt;s&lt;/span&gt;&lt;/b&gt; deletes the character under cursor and start insert.&lt;br /&gt;&lt;b&gt;&lt;span style="color: red;"&gt;S&lt;/span&gt;&lt;/b&gt; deletes the current line and start insert.&lt;br /&gt;&lt;b&gt;&lt;span style="color: red;"&gt;D&lt;/span&gt;&lt;/b&gt; deletes from cursor to the end of line.&lt;br /&gt;&lt;b&gt;&lt;span style="color: red;"&gt;C&lt;/span&gt;&lt;/b&gt; deletes from the cursor to the end of line and start insert.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Quickly move around in code.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="color: red;"&gt;%&lt;/span&gt;&lt;/b&gt; matches the parenthesis, bracket and curly brace. For example, put the cursor on a closing curly brace &amp;nbsp;and % takes the cursor to the matching opening brace.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="color: red;"&gt;[{&lt;/span&gt;&lt;/b&gt; and &lt;b&gt;&lt;span style="color: red;"&gt;]}&lt;/span&gt;&lt;/b&gt; to match the opening and closing curly braces. Place the cursor inside a code block, using these two to quickly move to the beginning and end of the closes curly braces pair.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="color: red;"&gt;gd&lt;/span&gt;&lt;/b&gt; jumps to the local variable definition when the cursor is on a variable name.&lt;br /&gt;&lt;b&gt;&lt;span style="color: red;"&gt;gD&lt;/span&gt;&lt;/b&gt; jumps to the global variable definition.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Use &lt;span style="color: red;"&gt;.&lt;/span&gt; (dot) command to repeat the last change in normal mode.&lt;/b&gt;&amp;nbsp;See&amp;nbsp;&lt;a href="http://vim.wikia.com/wiki/Repeat_last_change"&gt;Vim Twiki "repeat last change"&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;You can also do &lt;b&gt;&lt;span style="color: red;"&gt;N.&lt;/span&gt;&lt;/b&gt; to repeat the change N times. For example, dd command delete the current line, use . to delete another line, use 5. to delete additional 5 lines.&lt;br /&gt;&lt;br /&gt;There is also a similar repeat trick &lt;b&gt;&lt;span style="color: red;"&gt;@:&lt;/span&gt;&lt;/b&gt; for last command made on command line. For example, on the command line, we do :!ls to list files in the current directory. Then, we can do &lt;b&gt;@:&lt;/b&gt; to repeat it again.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Copy/cut and paste text in visual mode.&lt;/b&gt; See &lt;a href="http://vim.wikia.com/wiki/Cut/copy_and_paste_using_visual_selection"&gt;Vim Twiki "copy and paste using visual selection"&lt;/a&gt;.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;put cursor to the beginning of the desired text&lt;/li&gt;&lt;li&gt;enter visual mode: use v to begin character-based selection, V to begin line based selection, ctrl-v to begin vertical block based selection (move the cursor will select the whole columns of text)&lt;/li&gt;&lt;li&gt;put cursor to the end of the desired text&lt;/li&gt;&lt;li&gt;use d to cut, y to copy&lt;/li&gt;&lt;li&gt;put the cursor to the paste position&lt;/li&gt;&lt;li&gt;use p to paste after the desired position, P to paste before the desired position&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;On the Vim twiki, there is also the tip to overwrite the same amount of text using the copied/cut text using &lt;b&gt;&lt;span style="color: red;"&gt;Nvp, NVp, N^Vp&lt;/span&gt;&lt;/b&gt; depending on the selection mode (character, line or block).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;b&gt;Disable auto-indentation, manual indentation.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Sometimes, I had one annoying problem when I copy and paste formatted source code from another application - Vim will reformat the content and mess up with the indentations. To prevent Vim from retabbing, use &lt;b&gt;&lt;span style="color: red;"&gt;:set paste&lt;/span&gt;&lt;/b&gt;. After you are done, use &lt;span style="color: red;"&gt;&lt;b&gt;:set nopaste&lt;/b&gt;&lt;/span&gt; to diable paste. You can also add a key binding using &lt;b&gt;&lt;span style="color: red;"&gt;set pastetoggle&lt;/span&gt;&lt;/b&gt; in your .vimrc file. See &lt;a href="http://vim.wikia.com/wiki/Toggle_auto-indenting_for_code_paste"&gt;Vim Twiki "Toggle auto-indenting for code paste"&lt;/a&gt; for more details.&lt;br /&gt;&lt;br /&gt;Instead, you want manual indentation. In normal mode, &lt;b&gt;&lt;span style="color: red;"&gt;==&lt;/span&gt;&lt;/b&gt; indents the current line. In line-based visual mode (V or shift-v), select several lines and &lt;b&gt;&lt;span style="color: red;"&gt;=&lt;/span&gt;&lt;/b&gt; indents them all.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Jump in the change list, moving back and forth in changed positions in the current file.&lt;/b&gt; One common task is to jump back and forth between edit positions. See &lt;a href="http://vim.wikia.com/wiki/VimTip1300"&gt;Vim Twiki "list changes to the current file"&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="color: red;"&gt;&lt;b&gt;`.&lt;/b&gt;&amp;nbsp;&lt;/span&gt; jumps to the last edit position&lt;/li&gt;&lt;li&gt;&lt;b&gt;&lt;span style="color: red;"&gt;g;&lt;/span&gt;&lt;/b&gt; jumps back in the change list&lt;/li&gt;&lt;li&gt;&lt;b&gt;&lt;span style="color: red;"&gt;g,&lt;/span&gt;&lt;/b&gt; jumps forward in the change list&lt;/li&gt;&lt;li&gt;&lt;b&gt;&lt;span style="color: red;"&gt;:changes&lt;/span&gt;&lt;/b&gt; to show the change list&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;Interestingly, there is another (probably less useful) jump list that records the default last 100 positions a user makes a jump. A jump is one of search, substitute and mark. See Vim Twiki "jumping to previously visited locations".&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;&lt;span style="color: red;"&gt;ctrl-O&lt;/span&gt;&lt;/b&gt; to jump back in jump list&lt;/li&gt;&lt;li&gt;&lt;b&gt;&lt;span style="color: red;"&gt;ctrl-I&lt;/span&gt;&lt;/b&gt; to jump forward in jump list&lt;/li&gt;&lt;li&gt;&lt;b&gt;&lt;span style="color: red;"&gt;:jumps&lt;/span&gt;&lt;/b&gt; to show the jump list&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Auto expansion, adding comments, etc.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;One common case when coding is to add comments. So, how do you add something like these lines:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;///////////////////////////&lt;/li&gt;&lt;li&gt;/*------------------*/&lt;/li&gt;&lt;li&gt;/*************** &amp;lt;multiple lines of text&amp;gt; *************/&lt;/li&gt;&lt;/ul&gt;&lt;b&gt;&lt;span style="color: red;"&gt;Ni/&amp;lt;esc&amp;gt;&lt;/span&gt;&lt;/b&gt; inserts N / (slash), quite useful for N repeating characters.&lt;br /&gt;&lt;br /&gt;Another way is to use auto expansion. For example, you can add these into your .vimrc:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: text; gutter: false"&gt;:ab #b /************************************************&lt;br /&gt;:ab #e ************************************************/&lt;br /&gt;:ab #l /*----------------------------------------------*/&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Then, in the edit mode, you can type &lt;b&gt;&lt;span style="color: red;"&gt;#b&amp;lt;enter&amp;gt;&lt;/span&gt;&lt;/b&gt; to automatically insert /*******.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Text objects.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Last, I found out about &lt;b&gt;&lt;span style="color: red;"&gt;Vim text objects&lt;/span&gt;&lt;/b&gt;, it is so powerful and convenient that saved me a lot of time. For details, please read this great post &lt;a href="http://blog.carbonfive.com/2011/10/17/vim-text-objects-the-definitive-guide/"&gt;"Vim Text Objects: The Definitive Guide"&lt;/a&gt; and &lt;a href="http://vimdoc.sourceforge.net/htmldoc/motion.html"&gt;Vim documentation on text objects&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Note that text object is more convenient than motion when you want to delete a chunk of text, you don't need to move cursor to particular position. For example, the difference between &lt;b&gt;&lt;span style="color: red;"&gt;dw&lt;/span&gt;&lt;/b&gt; and &lt;span style="color: red;"&gt;&lt;b&gt;diw&lt;/b&gt;&lt;/span&gt; is that when you want to use &lt;b&gt;&lt;span style="color: red;"&gt;dw&lt;/span&gt;&lt;/b&gt; to delete a word, you must move the cursor to the beginning of that word first. For &lt;b&gt;&lt;span style="color: red;"&gt;diw&lt;/span&gt;&lt;/b&gt;, you can place the cursor anywhere inside that word.&lt;br /&gt;&lt;br /&gt;For example, I want to refactor code that has a string value hard coded to use a variable:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;public class Hello {&lt;br /&gt;&lt;br /&gt;    public static void main(String[] args) {&lt;br /&gt;        System.out.println("hello, world");&lt;br /&gt;        showMe();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public static void showMe() {&lt;br /&gt;        System.out.println("hello, world");&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// refectored&lt;br /&gt;public class Hello {&lt;br /&gt;&lt;br /&gt;    public final static String hi = "hello, world";&lt;br /&gt;    public static void main(String[] args) {&lt;br /&gt;        System.out.println(hi);&lt;br /&gt;        showMe();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public static void showMe() {&lt;br /&gt;        System.out.println(hi);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So, I can add a variable hi="hello world", then replace the string value "hello, world" on line 4 and line 9 using text object:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;move to line 4, a position before the string "hello, world", in normal mode, type ca", this will delete the string value including the quotes and change to insert mode.&lt;/li&gt;&lt;li&gt;type the new variable name hi&lt;/li&gt;&lt;li&gt;move to line 9, a position before the same string&lt;/li&gt;&lt;li&gt;type . to repeat the replacement&lt;/li&gt;&lt;li&gt;done!&lt;/li&gt;&lt;/ol&gt;One extra tip. Using text objects, you can delete/update the content inside the double quotes, but how do you delete the double quotes only? You can do this:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;move cursor to one of the double quotes&lt;/li&gt;&lt;li&gt;use % to jump to the matching double quotes, delete it using x&lt;/li&gt;&lt;li&gt;use Ctrl-o or two back-ticks (``) to jump back to the first double quote, delete it using x&lt;/li&gt;&lt;li&gt;done!&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;span style="color: blue;"&gt;Other related tips:&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;- &lt;a href="http://vimdoc.sourceforge.net/htmldoc/motion.html"&gt;Vim documentation: motions&lt;/a&gt;&lt;br /&gt;- &lt;a href="http://stackoverflow.com/questions/2861627/vim-paste-in-insert-mode"&gt;Vim paste in insert mode&lt;/a&gt;&lt;br /&gt;- &lt;a href="http://amix.dk/blog/post/19083"&gt;10 kick-ass Vim tips&lt;/a&gt;&lt;br /&gt;- &lt;a href="http://blog.carbonfive.com/2011/10/17/vim-text-objects-the-definitive-guide/"&gt;Vim Text Objects: The Definitive Guide&lt;/a&gt;&lt;br /&gt;- &lt;a href="http://stackoverflow.com/questions/2084210/remove-a-pair-of-parentheses-brackets-or-braces-in-vim"&gt;Remove a pair of&amp;nbsp;parenthesis&amp;nbsp;in Vim&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-5936448106489972464?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/5936448106489972464/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2011/12/some-vim-tips.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/5936448106489972464'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/5936448106489972464'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2011/12/some-vim-tips.html' title='useful vim tips'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-8049702222074289254</id><published>2011-12-18T01:30:00.000-08:00</published><updated>2011-12-18T01:31:11.386-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='security'/><title type='text'>Web application security readings</title><content type='html'>&lt;b&gt;Articles:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="https://wiki.mozilla.org/WebAppSec"&gt;Mozilla Web Application Security&lt;/a&gt;&amp;nbsp;(quick reading, 10 min)&lt;/li&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/browsersec/"&gt;Browser Security Handbook&lt;/a&gt;&amp;nbsp;(quick reading, 30 min)&lt;/li&gt;&lt;li&gt;&lt;a href="https://www.owasp.org/index.php/Cheat_Sheets"&gt;OWASP Cheat Sheets&lt;/a&gt;&amp;nbsp;(quite comprehensive reading, several hours)&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.html5rocks.com/en/tutorials/internals/howbrowserswork/"&gt;How Browsers Work&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;b&gt;Slides:&lt;/b&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.slideshare.net/michael_coates/cross-site-scripting-mozilla-security-learning-center"&gt;Cross Site Scripting (XSS)&lt;/a&gt;&amp;nbsp;Slides from Mozilla Security Learning Center (38 pages, 10 min)&lt;/li&gt;&lt;li&gt;&lt;a href="http://people.mozilla.org/~mcoates/WebAppSec-Training.html"&gt;Web Application Security: Hands On&lt;/a&gt; Slides from Michael Coates&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;b&gt;Specifications:&lt;/b&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="https://dvcs.w3.org/hg/content-security-policy/raw-file/tip/csp-specification.dev.html"&gt;CSP (Content Security Policy)&lt;/a&gt;: a W3C draft spec that defines fine grained security policies for resource loading to mitigate the risk of injection attacks such as XSS. The policy per resource representation is defined in new header is &lt;b&gt;&lt;i&gt;Content-Security-Policy&lt;/i&gt;&lt;/b&gt;. Firefox and Chrome is experimenting in headers &lt;b&gt;&lt;i&gt;X-Content-Security-Policy&lt;/i&gt;&lt;/b&gt; and &lt;b&gt;&lt;i&gt;X-WebKit-CSP&lt;/i&gt;&lt;/b&gt; respectively. The spec also defines a report-only mode without browser enforcing the policy but sending violation reports to the server, which is helpful for gradually enforcing the right policy.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;b&gt;Books:&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.amazon.com/Web-Application-Hackers-Handbook-Exploiting/dp/1118026470/"&gt;"The Web Application Hacker's Handbook (2nd)"&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.amazon.com/Web-Security-Privacy-Commerce-2nd/dp/0596000456/"&gt;"Web Security, Privacy and Commerce"&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.amazon.com/Hacking-Next-Generation-Animal-Guide/dp/0596154577/"&gt;"Hacking: the Next Generation"&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-8049702222074289254?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/8049702222074289254/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2011/12/web-application-security-readings.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/8049702222074289254'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/8049702222074289254'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2011/12/web-application-security-readings.html' title='Web application security readings'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-343283501895901972</id><published>2011-11-22T00:42:00.001-08:00</published><updated>2011-11-22T01:18:35.996-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='HTTP'/><title type='text'>so many cookies</title><content type='html'>I was reading upon &lt;a href="http://en.wikipedia.org/wiki/HTTP_cookie"&gt;HTTP cookies&lt;/a&gt; and it is actually quite confusing. Because there are many different cookie specs and browsers not necessarily support all of them.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Original Netscape Cookie Spec:&lt;/b&gt;&amp;nbsp;&lt;a href="http://curl.haxx.se/rfc/cookie_spec.html"&gt;http://curl.haxx.se/rfc/cookie_spec.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Very simple and straightforward format:&lt;br /&gt;&lt;br /&gt;&lt;pre style="background-color: white;"&gt;Set-Cookie: &lt;i&gt;NAME&lt;/i&gt;=&lt;i&gt;VALUE&lt;/i&gt;; expires=&lt;i&gt;DATE&lt;/i&gt;;&lt;br /&gt;path=&lt;i&gt;PATH&lt;/i&gt;; domain=&lt;i&gt;DOMAIN_NAME&lt;/i&gt;; secure&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;RFC 2109 (based on Netscape spec with minor tweaks):&lt;/b&gt;&amp;nbsp;&lt;a href="http://tools.ietf.org/html/rfc2109"&gt;http://tools.ietf.org/html/rfc2109&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="newpage" style="background-color: white; font-size: 1em; page-break-before: always;"&gt;The syntax for the Set-Cookie response header is&lt;br /&gt;&lt;br /&gt;   set-cookie      =       "Set-Cookie:" cookies&lt;br /&gt;   cookies         =       1#cookie&lt;br /&gt;   cookie          =       NAME "=" VALUE *(";" cookie-av)&lt;br /&gt;   NAME            =       attr&lt;br /&gt;   VALUE           =       value&lt;br /&gt;   cookie-av       =       "Comment" "=" value&lt;br /&gt;                   |       "Domain" "=" value&lt;br /&gt;                   |       "Max-Age" "=" value&lt;br /&gt;                   |       "Path" "=" value&lt;br /&gt;                   |       "Secure"&lt;br /&gt;                   |       "Version" "=" 1*DIGIT&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;RFC 2965, obsoletes RFC 2109:&lt;/b&gt; &lt;a href="http://tools.ietf.org/html/rfc2965"&gt;http://tools.ietf.org/html/rfc2965&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;It adds more syntax items. It is very interesting to read 9.1 section about the compatibility with existing cookie implementation. Basically, it should overwrite an existing cookie value set by Set-Cookie if domain and path both matches.&lt;br /&gt;&lt;br /&gt;&lt;pre class="newpage" style="background-color: white; font-size: 1em; page-break-before: always;"&gt;The syntax for the Set-Cookie2 response&lt;br /&gt;   header is&lt;br /&gt;&lt;br /&gt;   set-cookie      =       "Set-Cookie2:" cookies&lt;br /&gt;   cookies         =       1#cookie&lt;br /&gt;   cookie          =       NAME "=" VALUE *(";" set-cookie-av)&lt;br /&gt;   NAME            =       attr&lt;br /&gt;   VALUE           =       value&lt;br /&gt;   set-cookie-av   =       "Comment" "=" value&lt;br /&gt;                   |       "CommentURL" "=" &amp;lt;"&amp;gt; http_URL &amp;lt;"&amp;gt;&lt;br /&gt;                   |       "Discard"&lt;br /&gt;                   |       "Domain" "=" value&lt;br /&gt;                   |       "Max-Age" "=" value&lt;br /&gt;                   |       "Path" "=" value&lt;br /&gt;                   |       "Port" [ "=" &amp;lt;"&amp;gt; portlist &amp;lt;"&amp;gt; ]&lt;br /&gt;                   |       "Secure"&lt;br /&gt;                   |       "Version" "=" 1*DIGIT&lt;br /&gt;   portlist        =       1#portnum&lt;br /&gt;   portnum         =       1*DIGIT&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;RFC 6265, obsoletes RFC 2965:&lt;/b&gt;&amp;nbsp;&lt;a href="http://tools.ietf.org/html/rfc6265"&gt;http://tools.ietf.org/html/rfc6265&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;It admits the same confusion that I had, and deprecates the Cookie2 and Set-Cookie2 headers introduced in RFC 2965!&lt;br /&gt;&lt;br /&gt;"&lt;span class="Apple-style-span" style="font-family: monospace; font-size: 13px; white-space: pre;"&gt;Prior to this document, there were at least three descriptions of&lt;/span&gt;&lt;br /&gt;&lt;pre class="newpage" style="font-size: 1em; page-break-before: always;"&gt;   cookies: the so-called "Netscape cookie specification" [&lt;a href="http://tools.ietf.org/html/rfc6265#ref-Netscape" title="&amp;quot;Persistent Client State -- HTTP Cookies&amp;quot;"&gt;Netscape&lt;/a&gt;],&lt;br /&gt;   &lt;a href="http://tools.ietf.org/html/rfc2109"&gt;RFC 2109&lt;/a&gt; [&lt;a href="http://tools.ietf.org/html/rfc2109" title="&amp;quot;HTTP State Management Mechanism&amp;quot;"&gt;RFC2109&lt;/a&gt;], and &lt;a href="http://tools.ietf.org/html/rfc2965"&gt;RFC 2965&lt;/a&gt; [&lt;a href="http://tools.ietf.org/html/rfc2965" title="&amp;quot;HTTP State Management Mechanism&amp;quot;"&gt;RFC2965&lt;/a&gt;].  However, none of these&lt;br /&gt;   documents describe how the Cookie and Set-Cookie headers are actually&lt;br /&gt;   used on the Internet (see [&lt;a href="http://tools.ietf.org/html/rfc6265#ref-Kri2001" title="&amp;quot;HTTP Cookies: Standards, Privacy, and Politics&amp;quot;"&gt;Kri2001&lt;/a&gt;] for historical context).  In&lt;br /&gt;   relation to previous IETF specifications of HTTP state management&lt;br /&gt;   mechanisms, this document requests the following actions:&lt;br /&gt;&lt;br /&gt;   1.  Change the status of [&lt;a href="http://tools.ietf.org/html/rfc2109" title="&amp;quot;HTTP State Management Mechanism&amp;quot;"&gt;RFC2109&lt;/a&gt;] to Historic (it has already been&lt;br /&gt;       obsoleted by [&lt;a href="http://tools.ietf.org/html/rfc2965" title="&amp;quot;HTTP State Management Mechanism&amp;quot;"&gt;RFC2965&lt;/a&gt;]).&lt;br /&gt;&lt;br /&gt;   2.  Change the status of [&lt;a href="http://tools.ietf.org/html/rfc2965" title="&amp;quot;HTTP State Management Mechanism&amp;quot;"&gt;RFC2965&lt;/a&gt;] to Historic.&lt;br /&gt;&lt;br /&gt;   3.  Indicate that [&lt;a href="http://tools.ietf.org/html/rfc2965" title="&amp;quot;HTTP State Management Mechanism&amp;quot;"&gt;RFC2965&lt;/a&gt;] has been obsoleted by this document.&lt;br /&gt;&lt;br /&gt;   In particular, in moving &lt;a href="http://tools.ietf.org/html/rfc2965"&gt;RFC 2965&lt;/a&gt; to Historic and obsoleting it, this&lt;br /&gt;   document deprecates the use of the Cookie2 and Set-Cookie2 header&lt;br /&gt;   fields."&lt;/pre&gt;&lt;br /&gt;The actual format is getting updated as well. Notice that now both Expires and Max-Age are supported with Max-Age overriding Expires if both exist. If not, the cookie is kept by user agent till the current session ends.&lt;br /&gt;&lt;br /&gt;&lt;pre class="newpage" style="background-color: white; font-size: 1em; page-break-before: always;"&gt; set-cookie-header = "Set-Cookie:" SP set-cookie-string&lt;br /&gt; set-cookie-string = cookie-pair *( ";" SP cookie-av )&lt;br /&gt; cookie-pair       = cookie-name "=" cookie-value&lt;br /&gt; cookie-name       = token&lt;br /&gt; cookie-value      = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE )&lt;br /&gt; cookie-octet      = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E&lt;br /&gt;                       ; US-ASCII characters excluding CTLs,&lt;br /&gt;                       ; whitespace DQUOTE, comma, semicolon,&lt;br /&gt;                       ; and backslash&lt;br /&gt; token             = &amp;lt;token, defined in &lt;a href="http://tools.ietf.org/html/rfc2616#section-2.2"&gt;[RFC2616], Section&amp;nbsp;2.2&lt;/a&gt;&amp;gt;&lt;br /&gt;&lt;br /&gt; cookie-av         = expires-av / max-age-av / domain-av /&lt;br /&gt;                     path-av / secure-av / httponly-av /&lt;br /&gt;                     extension-av&lt;br /&gt; expires-av        = "Expires=" sane-cookie-date&lt;br /&gt; sane-cookie-date  = &amp;lt;&lt;a href="http://tools.ietf.org/html/rfc1123"&gt;rfc1123&lt;/a&gt;-date, defined in &lt;a href="http://tools.ietf.org/html/rfc2616#section-3.3.1"&gt;[RFC2616], Section&amp;nbsp;3.3.1&lt;/a&gt;&amp;gt;&lt;br /&gt; max-age-av        = "Max-Age=" non-zero-digit *DIGIT&lt;br /&gt;                       ; In practice, both expires-av and max-age-av&lt;br /&gt;                       ; are limited to dates representable by the&lt;br /&gt;                       ; user agent.&lt;br /&gt; non-zero-digit    = %x31-39&lt;br /&gt;                       ; digits 1 through 9&lt;br /&gt; domain-av         = "Domain=" domain-value&lt;br /&gt; domain-value      = &amp;lt;subdomain&amp;gt;&lt;br /&gt;                       ; defined in &lt;a href="http://tools.ietf.org/html/rfc1034#section-3.5"&gt;[RFC1034], Section&amp;nbsp;3.5&lt;/a&gt;, as&lt;br /&gt;                       ; enhanced by &lt;a href="http://tools.ietf.org/html/rfc1123#section-2.1"&gt;[RFC1123], Section&amp;nbsp;2.1&lt;/a&gt;&lt;br /&gt; path-av           = "Path=" path-value&lt;br /&gt; path-value        = &amp;lt;any CHAR except CTLs or ";"&amp;gt;&lt;br /&gt; secure-av         = "Secure"&lt;br /&gt; httponly-av       = "HttpOnly"&lt;br /&gt; extension-av      = &amp;lt;any CHAR except CTLs or ";"&amp;gt;&lt;/pre&gt;&lt;pre class="newpage" style="font-size: 1em; page-break-before: always;"&gt;&lt;/pre&gt;&lt;pre class="newpage" style="font-size: 1em; page-break-before: always;"&gt;&lt;/pre&gt;&lt;br /&gt;To conclude, here is a paper providing a good overview and discussion about the cookie: "&lt;a href="http://arxiv.org/abs/cs.SE/0105018"&gt;HTTP Cookie: Standards, Privacy and Politics&lt;/a&gt;".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-343283501895901972?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/343283501895901972/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2011/11/different-types-of-cookies.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/343283501895901972'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/343283501895901972'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2011/11/different-types-of-cookies.html' title='so many cookies'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-601414847461208860</id><published>2011-11-14T12:09:00.001-08:00</published><updated>2011-11-14T12:10:45.873-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='spam'/><title type='text'>SPAM: Please get a new EIN</title><content type='html'>Another spam I got today, it looks fairly serious ;-), maybe the "Dear Sirs" part sold itself. Anyways, here it is for fun:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Title: Please get a new EIN&lt;br /&gt;From: Clementina Evans&lt;br /&gt;To the ATTENTION of: Accounting Department&lt;br /&gt;Dear Sirs,&lt;br /&gt;please be informed that you need to get a new EIN in connection&lt;br /&gt;with the probability of fraudulent actions on your behalf. We&lt;br /&gt;are sorry for the inconveniences that might be caused to you&lt;br /&gt;by this measure. Please use the following link for instructions:&lt;br /&gt;&lt;span class="s1"&gt;http://onesourceprocess.com/7wmzwt/index.html&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Yours sincerely,&lt;br /&gt;Clementina Evans&lt;br /&gt;Office of Professional Responsibility&lt;br /&gt;Internal Revenue Service&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-601414847461208860?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/601414847461208860/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2011/11/spam-please-get-new-ein.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/601414847461208860'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/601414847461208860'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2011/11/spam-please-get-new-ein.html' title='SPAM: Please get a new EIN'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-4782417653596152141</id><published>2011-11-08T13:49:00.000-08:00</published><updated>2011-11-08T13:50:44.883-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='spam'/><category scheme='http://www.blogger.com/atom/ns#' term='security'/><title type='text'>SPAM: New EIN</title><content type='html'>&lt;div class="tr_bq"&gt;Just found it interesting to publish some lastest spams I got each day here, hopefully this would be helpful to non-tech people. Please don't try the links inside ;-)&lt;/div&gt;&lt;br /&gt;&lt;blockquote&gt;Title: New EIN&lt;br /&gt;From: Robert Glass&lt;br /&gt;Content:&lt;br /&gt;To the ATTENTION of: Accounting Department&lt;br /&gt;Dear Sirs,&lt;br /&gt;we would like to notify you that you are required to receive&lt;br /&gt;a new EIN in order to prevent fraud. We are sorry for any troubles&lt;br /&gt;that might be caused to you by this measure. Please use the following&lt;br /&gt;link for instructions:&lt;br /&gt;&lt;span class="s1"&gt;http://web.knauf.es/5nse63/index.html&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Yours sincerely,&lt;br /&gt;Robert Glass&lt;br /&gt;Office of Professional Responsibility&lt;br /&gt;Internal Revenue Service&amp;nbsp;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-4782417653596152141?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/4782417653596152141/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2011/11/spam-new-ein.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/4782417653596152141'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/4782417653596152141'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2011/11/spam-new-ein.html' title='SPAM: New EIN'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-5534968158118846576</id><published>2011-10-09T18:00:00.000-07:00</published><updated>2011-10-10T14:04:09.772-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tools'/><category scheme='http://www.blogger.com/atom/ns#' term='hardware'/><title type='text'>Unwanted Comcast features</title><content type='html'>After multiple&amp;nbsp;occurrences&amp;nbsp;of AT&amp;amp;T dropping connections over the past months, I finally decided to switch to Comcast (yes, I have heard many terrible stories about their billing department, sales fraud, etc.). Plus, I got a really good deal from my colleague ($19 per month for the first year, $35 per month for the second year for their &lt;a href="http://www.comcast.com/Corporate/Learn/HighSpeedInternet/new-highspeedinternet.html?"&gt;performance package&lt;/a&gt;, 15MB upload and 5MB download.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Based on advice, I did not choose to rent their modem and bought my own from Amazon: &lt;a href="http://www.amazon.com/Motorola-SB6121-SURFboard-DOCSIS-Cable/dp/B004XC6GJ0/"&gt;Motorola SB6121&lt;/a&gt; and it worked great. There is an older model SB6120 that is a bit cheaper, but my friend had problems. Please check with the technician and confirm that those models work in your area.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Today, they came in and installed it for me. The overall process worked fine except for three complaints:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="color: blue;"&gt;&lt;b&gt;1. &amp;nbsp;They kept calling for confirmation.&lt;/b&gt;&lt;/span&gt; In the past week, they called so many times for confirmation, 3 days before, yesterday, and this morning. I understand that some people might be forgetting things very quickly, but I am not that type of people. Plus, I have confirmed at the first call already and they are still calling as early as 7am in the morning! Since I did not get this morning's phone call, they left a message and said I would have to reschedule it, WTF. So, I ended up calling them again so they can send the technician in without rescheduling.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="color: blue;"&gt;&lt;b&gt;2. Some technicians are un-professional.&lt;/b&gt;&lt;/span&gt; I am quite busy with work and life, so my appointment is 8-10am, earliest I could get so I don't miss the work. For the first appointment, the technician waited outside for 1 hour before he came in (I saw his van and went out to tell him I am ready, but he kept sitting in his var for another half an hour). When he came in, I showed him where I want the setup and the pole to pull the signal from. He shrugged his shoulder and said "it will take at least 4-5 hours". I said I thought it'd be only 1-2 hours and I had no choice but to reschedule. Somehow from the look on his face, I felt that he did not want to do installation (bad mood, lazy, etc.) and I am fairly pissed. If you don't want to work, then don't come to waste your time and my time.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Today, another technician came in and he is much better. He finished the whole job in 1 hr and told me the previous technician "must be lazy".&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="color: blue;"&gt;&lt;b&gt;3. The installation process forces you to install the desktop installer to activate.&lt;/b&gt;&lt;/span&gt; After the hardware is set up, I hooked up my wireless router and was directed to an activation page, which asked me to create a new Comcast user account. But the last step is to install Comcast desktop installer and there seems to be no way around according to the technician. &lt;span style="color: blue;"&gt;(Update: according to my colleague, you don't need to install it, just restart the modem, shutdown router, connect router with modem, start the router. But I did not try this personally, not sure if it would work.)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The installer file is "&lt;a href="http://www.megaupload.com/?d=X6U7U87G"&gt;ComcastDesktopInstaller_MMF3.pkg&lt;/a&gt;" in my case. I &lt;a href="http://www.megaupload.com/?d=X6U7U87G"&gt;uploaded it online&lt;/a&gt; if you are interested.&amp;nbsp;Luckily I unchecked "install browser toolbar" option during installation. People are suffering from this toolbar since it hijacks browser preferences and homepage. If you are the victim, please follow &lt;a href="http://blog.ryanparman.com/2011/07/07/remove-comcastxfinity-start-page-from-firefox-mac/"&gt;instructions on this page&lt;/a&gt; to get your previous setting restored.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;After the network is up and running, I want to uninstall it but could not find much info. I did my best, and &lt;b&gt;&lt;span style="color: blue;"&gt;my conclusion is it might not do as much harm. It executed some Ruby scripts and installed some crap on the desktop, which you can delete easily.&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="color: blue;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="color: blue;"&gt;Cleanup actions in summary:&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;span style="color: blue;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: blue;"&gt;1. Delete the two website shortcuts installed on my desktop.&lt;/span&gt;&lt;br /&gt;&lt;span style="color: blue;"&gt;2. Delete ~/.cim_install_log.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: blue;"&gt;3. I am not familiar with Ruby, but the scripts seems to just create Xfinity bookmarks for Safari, Firefox and Chrome. For details in the script, see the gist below.&lt;/span&gt;&lt;br /&gt;&lt;span style="color: blue;"&gt;4. Besides those, I did not seem to find other suspicious malware or unwanted junks.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;b&gt;Detailed checkups for the Comcast app:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;1. Did a grep for "comcast" and found a log file in home directory: ~/.cim_install_log. It contains all the output during installation process.&lt;/div&gt;&lt;div&gt;2. Used &lt;a href="http://freemacsoft.net/"&gt;AppCleaner&lt;/a&gt; to check installed applications, does not find any malicious app installed from Comcast installer.&lt;/div&gt;&lt;div&gt;3. Used pkgutil command to search for anything related to comcast in package receipt database. See &lt;a href="http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man1/pkgutil.1.html"&gt;pkgutil manpage&lt;/a&gt; for details how to use it. I could not find any new applications installed from this installer pkg.&lt;/div&gt;&lt;div&gt;4. Used &lt;a href="http://www.charlessoft.com/"&gt;Pacifist&lt;/a&gt; to check the content of the pkg file. Did not see much suspicious content except for several Ruby and shell scripts to run during installation.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-jdbwSAZ4EIA/TpJhzyi2IAI/AAAAAAAALE8/J4jpRP-egnY/s1600/comcast-no-ff-toolbar.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-jdbwSAZ4EIA/TpJhzyi2IAI/AAAAAAAALE8/J4jpRP-egnY/s1600/comcast-no-ff-toolbar.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;Don't install Firefox Toolbar&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-uut5iA3_A2g/TpJh-QD_ksI/AAAAAAAALFA/FSvrIjxZXlk/s1600/comcast-links.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-uut5iA3_A2g/TpJh-QD_ksI/AAAAAAAALFA/FSvrIjxZXlk/s1600/comcast-links.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;By default, these website shortcuts are install on your desktop, remove them&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-P8XLBzMQD5k/TpJDbXllmzI/AAAAAAAALE4/HUKfalAvMuU/s1600/Pacifist-ComcastDesktopInstaller_MMF.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="640" src="http://4.bp.blogspot.com/-P8XLBzMQD5k/TpJDbXllmzI/AAAAAAAALE4/HUKfalAvMuU/s640/Pacifist-ComcastDesktopInstaller_MMF.png" width="616" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;Content of ComcastDesktopInstaller_MMF3.pkg&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/1274427.js?file=add_bookmarks.rb"&gt;&lt;/script&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/1274428.js?file=add_bookmarks.sh"&gt;&lt;/script&gt;&lt;/div&gt;&lt;div&gt;&lt;script src="https://gist.github.com/1274424.js?file=install_ff_plugin.rb"&gt;&lt;/script&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/1274430.js?file=install_ff_plugin.sh"&gt;&lt;/script&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp;Reference:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;1. &lt;a href="http://blog.ryanparman.com/2011/07/07/remove-comcastxfinity-start-page-from-firefox-mac/"&gt;How to remove Comcast/Xfinity home page from Firefox (Mac)&lt;/a&gt;&lt;/div&gt;&lt;div&gt;2. &lt;a href="http://forums.comcast.com/t5/Macintosh/Comcast-installed-something-on-my-Mac-without-permission/td-p/1052657"&gt;Comcast installing something on my Mac without permission&lt;/a&gt;&lt;/div&gt;&lt;div&gt;3. &lt;a href="http://geekyninja.com/archives/how-to-uninstall-mac-os-x-pkg-packages/"&gt;How to uninstall Mac OSX pkg packages&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-5534968158118846576?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/5534968158118846576/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2011/10/comcast-experience.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/5534968158118846576'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/5534968158118846576'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2011/10/comcast-experience.html' title='Unwanted Comcast features'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-jdbwSAZ4EIA/TpJhzyi2IAI/AAAAAAAALE8/J4jpRP-egnY/s72-c/comcast-no-ff-toolbar.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-4790464501653908561</id><published>2011-09-10T00:59:00.000-07:00</published><updated>2011-09-10T00:59:23.968-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='Web Prog.'/><title type='text'>Big list of things to get started with frontend development</title><content type='html'>Quickly ran though "&lt;a href="http://rockablepress.com/books/getting-good-with-javascript/"&gt;Getting Good with JavaScript&lt;/a&gt;", this is a very short and basic introduction to JavaScript for someone new to the language. Deep and difficult concepts are avoided or explained in an easy to understand way for the reader to explore further by him/herself.&lt;br /&gt;&lt;br /&gt;I found these two resources in the "Further Study" section very helpful and interesting, both are from Rey Bango's blog:&lt;br /&gt;&lt;br /&gt;1. &lt;a href="http://blog.reybango.com/2010/12/15/what-to-read-to-get-up-to-speed-in-javascript/"&gt;What to read to get up to speed in JavaScript&lt;/a&gt;&lt;br /&gt;2. &lt;a href="http://blog.reybango.com/the-big-list-of-javascript-css-and-html-development-tools-libraries-projects-and-books/"&gt;The big list of JavaScript, CSS, and HTML development tools, libraries, projects and books&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-4790464501653908561?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/4790464501653908561/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2011/09/big-list-of-things-to-get-started-with.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/4790464501653908561'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/4790464501653908561'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2011/09/big-list-of-things-to-get-started-with.html' title='Big list of things to get started with frontend development'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-9161216996544853277</id><published>2011-08-31T23:59:00.000-07:00</published><updated>2011-09-01T00:01:13.161-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web Prog.'/><category scheme='http://www.blogger.com/atom/ns#' term='Apple'/><category scheme='http://www.blogger.com/atom/ns#' term='HTML'/><title type='text'>display Apple keys in HTML</title><content type='html'>Just saw an interesting &lt;a href="http://meta.stackoverflow.com/questions/78068/add-keyboard-shortcuts-for-the-kbd-tag"&gt;kbd tag supported on Stackoverflow&lt;/a&gt; and started wondering how to display Apple keys like command, shift, control, option, etc. on the Web page.&lt;br /&gt;&lt;br /&gt;And it actually is very straightforward using HTML character entities. The concept is well explained in &lt;a href="http://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references"&gt;this Wikipedia article&lt;/a&gt;. There are two forms: &lt;i&gt;numeric character reference&lt;/i&gt; and &lt;i&gt;character entity reference:&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;br /&gt;&lt;b&gt;numeric character reference:&lt;/b&gt;&amp;nbsp;either in decimal form (&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;amp;#dddd;&lt;/span&gt;) or in hexadecimal form (&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;amp;#xhhhh;&lt;/span&gt;), e.g. "less than" character can be expressed as &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;amp;#60;&lt;/span&gt; or &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;amp;#x3c;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;character entity reference:&lt;/b&gt;&amp;nbsp;in the form of &amp;amp;name; the same "less than" character can be expressed as &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;amp;lt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Now, it is very clear how to display these special Apple keys with the help of entity tables such as &lt;a href="http://macbiblioblog.blogspot.com/2005/05/special-key-symbols.html"&gt;this unicode table&lt;/a&gt;. Somehow I could not find the corresponding character entity reference table for the same keys.&lt;br /&gt;&lt;br /&gt;These are the most common Apple keys you might use:&lt;br /&gt;&lt;br /&gt;⌘ Command: &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;amp;#x2318;&lt;/span&gt;&lt;br /&gt;⇧ Shift: &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;amp;#x21E7;&lt;/span&gt;&lt;br /&gt;⌃ Control: &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;amp;#x2303;&lt;/span&gt;&lt;br /&gt;⌥ Option: &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;amp;#x2325;&lt;/span&gt;&lt;br /&gt;⎋ Esc: &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;amp;#x238B;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If you use TextMate, there is &lt;a href="http://blog.macromates.com/2006/multi-stroke-key-bindings/"&gt;a convenient HTML bundle feature&lt;/a&gt; that helps to insert these special characters in an HTML document. Create a new HTML document, then goto Bundles menu =&amp;gt; HTML =&amp;gt; Entities =&amp;gt; Pick the character you want. You can also use the autocomplete, e.g. type "command" and press tab.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-9161216996544853277?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/9161216996544853277/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2011/08/display-apple-keys-in-html.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/9161216996544853277'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/9161216996544853277'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2011/08/display-apple-keys-in-html.html' title='display Apple keys in HTML'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-22860550491822472</id><published>2011-08-31T10:42:00.000-07:00</published><updated>2011-09-08T23:17:54.304-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tools'/><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><title type='text'>migrate from TextMate to Vim/MacVim</title><content type='html'>Choosing text editor is like choosing your religion. One popular/natural choice on Mac is &lt;a href="http://macromates.com/"&gt;TextMate&lt;/a&gt;. However, since I do lots of work on the server/dev linux box directly, I had to switch back and forth from Vim. Probably it is time to migrate to use Vim on Mac as well, especially given the fact that there are nice distro made for Mac specifically: &lt;a href="http://code.google.com/p/macvim/"&gt;MacVim&lt;/a&gt; and a customized MacVim packaged with many useful plugins called &lt;a href="https://github.com/carlhuda/janus"&gt;Janus&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Here are two good testimony from other migrants:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://henrik.nyh.se/2011/01/textmate-to-vim-with-training-wheels"&gt;TextMate to Vim with training wheels&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://blog.danielfischer.com/2010/11/19/a-starting-guide-to-vim-from-textmate/"&gt;A Starting Guide to Vim from TextMate&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;b&gt;Here are several useful learning resources:&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.fprintf.net/vimCheatSheet.html"&gt;Vim Commands Cheat Sheet&lt;/a&gt; (for good reference, there are multiple other similar cheat sheets)&lt;/li&gt;&lt;li&gt;vimtutor (simply open your terminal and type vimtutor)&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.swaroopch.com/notes/Vim"&gt;A Byte of Vim&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://vim.runpaint.org/"&gt;Vim Recipes&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://net.tutsplus.com/sessions/vim-essential-plugins/"&gt;Essential Vim Plugins&lt;/a&gt; (plugins are very helpful to create your effective workflow)&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Plugins shipped with Janus:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Spend 5 minutes to go through the brief introduction for all the plugins that ships with Janus. Janus also includes a handy way to allow you to create/edit&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt; ~/.janus.rake&lt;/span&gt; file to add more plugins and you can run &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;rake&lt;/span&gt; inside &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;~/.vim&lt;/span&gt; to update these plugins.&lt;br /&gt;&lt;br /&gt;Sample &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;~/.janus.rake&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre class="brush: text"&gt;vim_plugin_task "zencoding", "git://github.com/mattn/zencoding-vim.git"&lt;br /&gt;vim_plugin_task "minibufexpl", "git://github.com/fholgado/minibufexpl.vim.git"&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;a href="https://github.com/scrooloose/nerdtree"&gt;NERDTree&lt;/a&gt;: provides a file browser, use&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt; \n &lt;/span&gt;to show/hide.&lt;br /&gt;&lt;br /&gt;&lt;a href="https://wincent.com/products/command-t"&gt;Command-T&lt;/a&gt;: provides an efficient way to search for files in current working directory. Use &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;⌘+T&lt;/span&gt; to show/hide.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.vim.org/scripts/script.php?script_id=2540"&gt;snipMate&lt;/a&gt;:&amp;nbsp;provides the same Textmate Snippet feature. As you do in TextMate, you can simply type snippet keywords and press tab to expand to code snippets and use tab to jump through various locations in the snippets. You can find all snippet definitions for various languages in &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;~/.vim/snippets&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.vim.org/scripts/script.php?script_id=610"&gt;ctags&lt;/a&gt;: TagList plugin is shipped with Janus. Use &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;:Tlist&lt;/span&gt; to show/hide it. But I like &lt;a href="http://www.vim.org/scripts/script.php?script_id=3465"&gt;Tagbar&lt;/a&gt; better than TagList (see below for installation instructions).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Other handy plugins I installed:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.vim.org/scripts/script.php?script_id=2736"&gt;Syntastic&lt;/a&gt;: syntax checker, you can also go to the jslint route. &lt;a href="http://stackoverflow.com/questions/473478/vim-jslint/5893447#5893447"&gt;This Stackoverflow post&lt;/a&gt; covers the setup in details.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.vim.org/scripts/script.php?script_id=3465"&gt;Tagbar&lt;/a&gt;: displays tags of the current file in a sidebar, sorta like &lt;a href="http://www.vim.org/scripts/script.php?script_id=273"&gt;TagList&lt;/a&gt;, but more comprehensive and orders tags under correct scope/context.&lt;br /&gt;&lt;br /&gt;&lt;a href="https://github.com/mozilla/doctorjs"&gt;doctorjs&lt;/a&gt;: previously known as jstags, provides a set of static analysis tools for JavaScript. Combined with Tagbar, it provides a more detailed code structure navigation than TagList. See &lt;a href="http://stackoverflow.com/questions/4777366/recommended-vim-plugins-for-javascript-coding"&gt;this Stackoverflow post&lt;/a&gt; for instructions how to set it up. Note that you need to install NodeJS as a prerequisite.&lt;br /&gt;&lt;br /&gt;There are two issues to get doctorjs set up properly that is not covered in that Stackoverflow post:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;It seems that installing doctorjs needs sudo (sudo make install inside doctorjs git clone directory) to get around permission issue.&lt;/li&gt;&lt;li&gt;I also got errors about &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;underscore&lt;/span&gt; module and &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;ctags&lt;/span&gt;&amp;nbsp;NodeJS module cannot be found. They are located at &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;/usr/local/lib/jsctags/&lt;/span&gt; after doctorjs is installed. But&amp;nbsp;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;node&lt;/span&gt; cannot locate them somehow. To fix it, I installed &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;underscore&lt;/span&gt; using &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;npm&lt;/span&gt; (&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;npm install underscore -g&lt;/span&gt;), then I updated my &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;NODE_PATH&lt;/span&gt; environment variable to include&amp;nbsp;/usr/local/lib/jsctags/.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-22860550491822472?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/22860550491822472/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2011/08/migrate-from-textmate-to-vimmacvim.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/22860550491822472'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/22860550491822472'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2011/08/migrate-from-textmate-to-vimmacvim.html' title='migrate from TextMate to Vim/MacVim'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-5909862890313365371</id><published>2011-08-05T23:15:00.000-07:00</published><updated>2011-08-08T16:43:20.630-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><title type='text'>file system based on a single file and loop device</title><content type='html'>Worked on a task to test performance of read/write on various file system options on my RHEL5 box:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;native ext3&lt;/li&gt;&lt;li&gt;virtual ext3 based on a zero-filled image file&lt;/li&gt;&lt;li&gt;virtual ext3 based on a &lt;a href="http://en.wikipedia.org/wiki/Sparse_file"&gt;sparse image file&lt;/a&gt;&lt;/li&gt;&lt;li&gt;virtual ext2 based on a sparse image file&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;The virtual file system is basically based on a big file connected as a &lt;a href="http://en.wikipedia.org/wiki/Loop_device"&gt;loop device&lt;/a&gt;. &lt;a href="http://www.drydeadfish.co.uk/junk/linux_disk_quotas/index.php"&gt;This tutorial&lt;/a&gt; about setting up disk quota based on virtual file system has more details. For example, this is the basic steps to set up a virtual ext3 file system based on a sparse file:&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;pre class="brush: text"&gt;dd if=/dev/null of=/tmp/vfs/sparse.image bs=1M seek=100&lt;br /&gt;mkfs -t ext3 -q /tmp/vfs/sparse.image -F&lt;br /&gt;mkdir /tmp/quota&lt;br /&gt;sudo mount -t ext3 -o rw,loop /tmp/vfs/full.image /tmp/quota&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;The experiment is quite preliminary: basically, I copy over files in different sizes (1, 5, 10, 25, 50MB) into the mounted file system directory or the native file system directory to test write latency, then read the copied files to test read latency. The read/write latency is averaged over 10 iterations.&lt;br /&gt;&lt;br /&gt;A couple of quick points from the experiments:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;read latency is similar for all four cases.&lt;/li&gt;&lt;li&gt;write latency for native ext3 is around half of the virtual ext3 based either on a sparse file or a zero-filled file.&lt;/li&gt;&lt;li&gt;write latency for native ext3 is roughly the same as virtual ext2, maybe because ext2 gets rid of the journaling overhead.&lt;/li&gt;&lt;li&gt;creating a virtual file system based on a sparse file has many advantages over a zero-filled file: the creation time is way much faster 6-8 order of magnitude for the file sizes we tried, the bigger the file, the bigger the difference; the sparse file does not occupy physical disk space and grows when content is actually written to disc.&lt;/li&gt;&lt;li&gt;virtual ext3 has spikes for write, sometimes as big as 80x the average write latency, not exactly what caused it.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;This is final the performance graph for comparison. I am using the average number here, notice that the high average latency for write on virtual ext3 is caused by the spikes mentioned above.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: -webkit-auto;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-rOrdTqGfNso/TjzbfLJJh6I/AAAAAAAAK7c/Nm2AZq1EvG0/s1600/fs-quota-perf.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="472" src="http://3.bp.blogspot.com/-rOrdTqGfNso/TjzbfLJJh6I/AAAAAAAAK7c/Nm2AZq1EvG0/s640/fs-quota-perf.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;After removing the spikes, using virtual ext3 based on a sparse file or zero-filled file creates around 2X the latency for native ext2 or ext2 based on a sparse file, as show in the second graph:&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/--Nk33hxOqwE/Tj9nUhQYTYI/AAAAAAAAK7g/Ah-vKbhhbL4/s1600/fs-quota-perf-no-spikes.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="467" src="http://2.bp.blogspot.com/--Nk33hxOqwE/Tj9nUhQYTYI/AAAAAAAAK7g/Ah-vKbhhbL4/s640/fs-quota-perf-no-spikes.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-5909862890313365371?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/5909862890313365371/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2011/08/file-system-based-on-single-file-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/5909862890313365371'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/5909862890313365371'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2011/08/file-system-based-on-single-file-and.html' title='file system based on a single file and loop device'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-rOrdTqGfNso/TjzbfLJJh6I/AAAAAAAAK7c/Nm2AZq1EvG0/s72-c/fs-quota-perf.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-3663910798850914029</id><published>2011-07-22T00:39:00.000-07:00</published><updated>2011-07-22T00:44:04.137-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web Prog.'/><title type='text'>Multi-language support for a website</title><content type='html'>I am not a frontend developer, just stumbled upon this problem helping out my friend to set up a website that is supposed to serve multi-language content based on the language setting of the user. This is actually an interesting problem (maybe already solved and I did not know).&lt;br /&gt;&lt;br /&gt;There are several different solutions that I found through after doing some study:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;- Server side detection based on &lt;a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4"&gt;Accept-Language request header&lt;/a&gt;.&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;For example, apache &lt;a href="http://httpd.apache.org/docs/2.2/mod/mod_negotiation.html"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;mod_negotiation&lt;/span&gt;&lt;/a&gt; allows you to define a set of html pages in different languages (index.html.en, index.html.zh, etc.) and based on the user preferences from Accept-Language header, apache picks the right index.html language page to return.&lt;br /&gt;&lt;br /&gt;You can also use &lt;a href="http://httpd.apache.org/docs/current/mod/mod_rewrite.html"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;mod_rewrite&lt;/span&gt;&lt;/a&gt; to perform the similar trick. Just set up the rewrite condition based on the value of the AL header and map to the correct language.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;- Client side detection and action using JavaScript and navigator object.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;In IE, &lt;span class="Apple-style-span" style="color: #0b5394; font-family: 'Courier New', Courier, monospace;"&gt;navigator.userLanguage&lt;/span&gt; returns the operating system region and language setting, in Firefox, Opera, Safari and Chrome, &lt;span class="Apple-style-span" style="color: #0b5394; font-family: 'Courier New', Courier, monospace;"&gt;navigator.language&lt;/span&gt; returns the browser application language setting. So, we can use them to get the user language and decide what language content to return.&lt;br /&gt;&lt;br /&gt;For example, this code snippet (&lt;a href="http://jsfiddle.net/ambiguous/hDM3T/2/"&gt;borrowed from an example on jsfiddle&lt;/a&gt;) defines multi-language content on the same page and use JavaScript to show or hide it based on the detected language.&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/1099029.js?file=gistfile1.txt"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;The drawback of this approach is that a large part of the content is not needed and invisible. It is a waste of time to download.&lt;br /&gt;&lt;br /&gt;Another approach is to use JavaScript to redirect to individual language content pages using &lt;span class="Apple-style-span" style="color: #0b5394; font-family: 'Courier New', Courier, monospace;"&gt;window.location.href="redirected_page_url"&lt;/span&gt; or &lt;span class="Apple-style-span" style="color: #0b5394; font-family: 'Courier New', Courier, monospace;"&gt;window.location.replace("redirected_page_url")&lt;/span&gt;. See &lt;a href="http://www.w3schools.com/jsref/obj_location.asp"&gt;Location object&lt;/a&gt; for more details on how to use them. The downside is this approach may not be search engine friendly (spiders may not be able to follow redirection).&lt;br /&gt;&lt;br /&gt;One last note how to test multi-lang website. I tried in Firefox, simple change the language ranking in Preferences-&amp;gt;Content Tab-&amp;gt;Language Choose button and FF will start sending different &lt;span class="Apple-style-span" style="color: #0b5394; font-family: 'Courier New', Courier, monospace;"&gt;Accept-Language&lt;/span&gt; headers based on the ranking. You can also play with the operating system language settings.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-3663910798850914029?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/3663910798850914029/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2011/07/multi-language-support-for-website.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/3663910798850914029'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/3663910798850914029'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2011/07/multi-language-support-for-website.html' title='Multi-language support for a website'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-8665486213617969607</id><published>2011-06-13T17:56:00.000-07:00</published><updated>2011-07-01T00:20:42.180-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='node.js'/><title type='text'>node.js testing frameworks</title><content type='html'>There are &lt;a href="https://github.com/joyent/node/wiki/modules#testing"&gt;so many&lt;/a&gt; testing frameworks for node.js, start to evaluate some &lt;a href="http://stackoverflow.com/questions/4308786/what-is-the-best-testing-framework-to-use-with-node-js"&gt;most mentioned&lt;/a&gt;/&lt;a href="http://stackoverflow.com/questions/4713751/node-js-programming-workflow-tests-code-tests"&gt;used ones&lt;/a&gt;. Criteria that I am looking for:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;easy to understand concept and constructs&lt;/li&gt;&lt;li&gt;nice support for async calls and flow control&lt;/li&gt;&lt;li&gt;easy integration with CI tools such as Hudson&lt;/li&gt;&lt;li&gt;code coverage report&lt;/li&gt;&lt;li&gt;mocks and stubs&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://vows.heroku.com/"&gt;Vows&lt;/a&gt;+&lt;a href="http://blog.nodejitsu.com/rest-easy-test-any-api-in-nodejs"&gt;APIeasy&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://visionmedia.github.com/expresso/"&gt;Expresso&lt;/a&gt;+&lt;a href="https://github.com/visionmedia/node-jscoverage"&gt;node-jscoverage&lt;/a&gt;: really like its code coverage feature&lt;/li&gt;&lt;li&gt;&lt;a href="http://developer.yahoo.com/yui/3/test/"&gt;YUITest&lt;/a&gt;: somehow had issues writing async operations in setUp and tearDown, also had issues using flow control libraries such as async inside each test&lt;/li&gt;&lt;li&gt;&lt;a href="https://github.com/pivotal/jasmine/wiki"&gt;Jasimine&lt;/a&gt;: very clean and easy to understand concept and constructs&lt;/li&gt;&lt;li&gt;&lt;a href="https://github.com/caolan/nodeunit"&gt;Nodeunit&lt;/a&gt;: &lt;a href="http://caolanmcmahon.com/posts/unit_testing_in_node_js"&gt;a detailed tutorial&lt;/a&gt; from the author&lt;/li&gt;&lt;li&gt;&lt;a href="http://docs.jquery.com/QUnit"&gt;node-qunit+jscoverage&lt;/a&gt;, qunit is used for JQuery testing and has fairly good async support, &lt;a href="http://net.tutsplus.com/tutorials/javascript-ajax/how-to-test-your-javascript-code-with-qunit/"&gt;here is a fairly detailed article&lt;/a&gt; for async testing with qunit&lt;/li&gt;&lt;li&gt;&lt;a href="https://github.com/masylum/testosterone"&gt;testosterone&lt;/a&gt;+&lt;a href="https://github.com/felixge/node-gently"&gt;gently&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://sinonjs.org/"&gt;Sinon.JS&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;Among those, I like Jasimine most, it is easy to understand and has rich feature set. The only feature missing is lack of code coverage report. &lt;a href="https://github.com/larrymyers/jasmine-reporters"&gt;jasimine-reporters&lt;/a&gt; supports output of JUnit format unit test results. &lt;a href="https://github.com/mhevery/jasmine-node"&gt;jasimine-node&lt;/a&gt; brings Jasimine to node.js. You can check out "&lt;a href="http://tinnedfruit.com/2011/03/03/testing-backbone-apps-with-jasmine-sinon.html"&gt;Testing Backbone applications with Jasimine and Sinon&lt;/a&gt;" for a practical example.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-8665486213617969607?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/8665486213617969607/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2011/06/nodejs-testing-frameworks.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/8665486213617969607'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/8665486213617969607'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2011/06/nodejs-testing-frameworks.html' title='node.js testing frameworks'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-647212459314868497</id><published>2011-06-05T00:01:00.000-07:00</published><updated>2011-06-05T00:02:03.698-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='Web Prog.'/><title type='text'>dealing with multiple nesting callbacks in asynchronous code</title><content type='html'>If you are annoyed that you have to write multiple nesting asynchronous callback functions when you work with Node.js, you are not alone. Getting used to the asynchronous programming style and always keep in mind everything runs in the event loop is a bit tricky at the beginning.&lt;br /&gt;&lt;br /&gt;There are many libraries and articles that addresses this nesting callback issue. This should help you to avoid those ugly pyramid shaped code now ;-)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.infoq.com/articles/surviving-asynchronous-programming-in-javascript"&gt;InfoQ: how to survive asynchronous programming in JavaScript&lt;/a&gt; (includes a list of libraries with comparisons and Q&amp;amp;A from their developers)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://stackoverflow.com/questions/4234619/how-to-avoid-long-nesting-of-asynchronous-functions-in-node-js"&gt;Stackoverflow post about how to deal with the nesting callbacks&lt;/a&gt; (also includes a list of libraries)&lt;br /&gt;&lt;br /&gt;&lt;a href="https://github.com/isaacs/slide-flow-control/raw/master/nodejs-controlling-flow.pdf"&gt;Isaacs's presentation on the topic and his library Slide&lt;/a&gt; (he is the author of npm)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://howtonode.org/control-flow"&gt;Tim Caswell (creationix)'s series on control flow in Node&lt;/a&gt;&amp;nbsp;(II and III can be found on the right column, other articles by the same author)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://wiki.commonjs.org/wiki/Promises"&gt;CommonJS Promises&lt;/a&gt; is another way trying to address this issue by defining a standard interface for interacting with the result object of asynchronous actions. Roughly speaking, a promise object is a placeholder for the value for the asynchronous action. And you can treat is as normal object, assign values to another variable, pass it around, etc. Right now, &lt;a href="https://github.com/coolaj86/futures"&gt;FuturesJS&lt;/a&gt; implements this and it is not solely for server-side JS. &lt;a href="http://www.sitepen.com/blog/2010/05/03/robust-promises-with-dojo-deferred-1-5/"&gt;dojo.Deferred&lt;/a&gt; is another similar effort. &lt;a href="http://www.sitepen.com/blog/2010/01/19/commonjsjsgi-the-emerging-javascript-application-server-platform/"&gt;This SitePen blog post&lt;/a&gt; has some easier to understand coverage about the promises.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://onilabs.com/stratifiedjs"&gt;StratifiedJS&lt;/a&gt; extends the JavaScript language to achieve similar goals of allowing asynchronous control flow to be expressed in a synchronous way. Very neat work indeed. &lt;a href="http://onilabs.com/presentations/amsterdamjs/index.html"&gt;This&lt;/a&gt; is a short overview presentation about it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-647212459314868497?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/647212459314868497/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2011/06/dealing-with-multiple-nesting-callbacks.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/647212459314868497'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/647212459314868497'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2011/06/dealing-with-multiple-nesting-callbacks.html' title='dealing with multiple nesting callbacks in asynchronous code'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-7937416606705737809</id><published>2011-05-13T17:44:00.000-07:00</published><updated>2011-05-13T17:45:48.604-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tools'/><category scheme='http://www.blogger.com/atom/ns#' term='Mac'/><category scheme='http://www.blogger.com/atom/ns#' term='TextMate'/><title type='text'>get rid of annoying ._filename working with TextMate on a mounted NFS</title><content type='html'>Just had this annoying experience of working on an NFS mounted file system with TextMate. Basically, it tries to store metadata such as cursor position, etc. into metadata files. Since these mounted file system does not support extended attributes, so OSX instead writes to &lt;span class="Apple-style-span" style="color: blue;"&gt;._filename&lt;/span&gt;, which is really annoying since the directory is under version control and you see many of these metadata files showing up.&lt;br /&gt;&lt;br /&gt;After poking around, I figured out how to turn this metadata feature off, yes, I lost a bit convenience feature, but no more cleanup of these ._filename anymore!&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: text"&gt;defaults write com.macromates.textmate OakDocumentDisableFSMetaData 1&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;References:&lt;/b&gt; &lt;a href="http://manual.macromates.com/en/expert_preferences.html"&gt;TextMate Expert Preferences&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-7937416606705737809?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/7937416606705737809/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2011/05/get-rid-of-annoying-filename-working.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/7937416606705737809'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/7937416606705737809'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2011/05/get-rid-of-annoying-filename-working.html' title='get rid of annoying ._filename working with TextMate on a mounted NFS'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-8341145000083961051</id><published>2011-04-23T23:45:00.000-07:00</published><updated>2011-07-14T19:34:52.004-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cloud'/><category scheme='http://www.blogger.com/atom/ns#' term='node.js'/><title type='text'>Hello, Cloud Foundry running node.js</title><content type='html'>Contrary to most people's view on the &lt;a href="http://newstabulous.com/amazon-still-facing-computer-problems/9452/"&gt;Amazon cloud outage incident&lt;/a&gt;, I believe this actually shows the power and outreach of the cloud computing. The technology needs some time to mature and become reliable, let's just be patient. It is very exciting to see even big sites like reddit, quora was affected, and even the cloud service provider Heroku was one of the victims.&lt;br /&gt;&lt;br /&gt;There are many new players in the cloud computing field and &lt;a href="http://www.cloudfoundry.com/faq"&gt;Cloud Foundry&lt;/a&gt; from VMWare is definitely a very disruptive force to the current market. Currently, it supports Spring for Java apps, Rails and Sinatra for Ruby apps, JVM frameworks like Grails and Node.js! Best of all, the whole platform is &lt;a href="https://github.com/cloudfoundry"&gt;open sourced&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;CF provides a Micro Cloud for individual developers, for free now ;-) This is how to get a helloworld node.js app running:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1. Preparation&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;- Sign up for the free &lt;a href="http://www.cloudfoundry.com/"&gt;Micro Cloud for Cloud Foundry&lt;/a&gt; (http://www.cloudfoundry.com/).&lt;br /&gt;- Wait a few days (mine took 9 days) and you will receive an approval email.&lt;br /&gt;- Cloud Foundry uses a CLI tool called vmc for interactions with your Micro Cloud instance. Follow the instructions and use the credentials in the approval email to set up vmc (see "&lt;a href="http://support.cloudfoundry.com/entries/20012337-getting-started-guide-command-line-vmc-users"&gt;vmc getting started guide&lt;/a&gt;", really wish it is available not only in PDF format).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;2. Write a helloworld node.js app&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;As of this writing, CF supports node.js-0.4.5 (use "vmc runtimes" to find out). The only thing that is different in the CF environment is that the system will assign a host and port to your application. CF adds several environment variables accessible through process.env.&lt;br /&gt;&lt;br /&gt;For our helloworld, we are interested in &lt;b&gt;VCAP_APP_HOST&lt;/b&gt; and &lt;b&gt;VCAP_APP_PORT &lt;/b&gt;(there are also VMC_APP_HOST and VMC_APP_PORT, which seems still exist but will be deprecated).&lt;br /&gt;&lt;br /&gt;So, you basically create a directory (I use the same appid as the directory name) and create an &lt;b&gt;app.js&lt;/b&gt; for hello world like this:&lt;br /&gt;&lt;pre class="brush: javascript; highlight: [2, 3]"&gt;var http = require('http'),&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;port = Number(process.env.VCAP_APP_PORT || 3000),&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;host = process.env.VCAP_APP_HOST || 'localhost';&lt;br /&gt;&lt;br /&gt;http.createServer(function (req, res) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;res.writeHead(200, {'Content-Type': 'text/plain'});&lt;br /&gt;&amp;nbsp;&amp;nbsp;res.end('Welcome to Cloud Foundry!\n' +&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;host + ':' + port + '\n' +&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;require('util').inspect(process.env, false, null));&lt;br /&gt;}).listen(port, host);&lt;br /&gt;&lt;br /&gt;console.log('Server running at http://' + host + ':' + port + '/');&lt;br /&gt;&lt;/pre&gt;This simple app just prints out "Welcome to Cloud Foundry!" and a bunch of environment variables ;-) Note that we put localhost and 3000 there so that it is easier to debug the app on a local node.js installation.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;3. Deploy using vmc&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The very first time you deploy the app, you run "vmc push &amp;lt;appid&amp;gt;". Note that you need to pick an id that is not being used, otherwise, you will get an error. It would be really nice for CF to provide a Web UI to check what appid is still available. You just follow the instructions and see the output. If everything goes well, you will see your app running at http://&amp;lt;appid&amp;gt;.cloudfoundry.com/.&lt;br /&gt;&lt;br /&gt;To update your app, you need to run "vmc update &amp;lt;appid&amp;gt;" instead of "vmc push &amp;lt;appid&amp;gt;". You can also delete your app using "vmc delete &amp;lt;appid&amp;gt;".&lt;br /&gt;&lt;br /&gt;vmc CLI provides many operations, "vmc -h" is your best friend to find and try them out.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;4. Add npm module dependencies&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;In most cases, you will need to use dependent NPM modules such as Connect, Express, etc. With the current node.js 0.4.5 supported on CF, it is very straightforward.&lt;br /&gt;&lt;br /&gt;- You create a package.json that defines your app/module with dependencies.&lt;br /&gt;- Then you run "npm bundle", which creates a node_modules directory with all the required NPM modules.&lt;br /&gt;- Finally, you do "vmc update &amp;lt;appid&amp;gt;" and you are done.&lt;br /&gt;&lt;br /&gt;Here is a quick sample:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;package.json&lt;/b&gt;&lt;br /&gt;&lt;pre class="brush: javascript"&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;"name": "helloworld-node",&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;"version": "0.0.1",&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;"dependencies":&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;"connect": "*"&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;app.js&lt;/b&gt;&lt;br /&gt;&lt;pre class="brush: javascript"&gt;var connect = require('connect');&lt;br /&gt;&lt;br /&gt;connect.createServer(function(req, res) {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;var body = 'hello, cloud foundry';&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;res.setHeader('Content-Length', body.length);&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;res.end(body);&lt;br /&gt;}).listen(process.env.VCAP_APP_PORT || 3000);&lt;br /&gt;&lt;br /&gt;console.log('connect server listening...');&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;dir structure:&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&lt;pre class="brush: text"&gt;app.js, package.json, node_modules&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;5. To learn more&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;I will try to update this helloworld guide and add a bit about bundling dependent npm modules. To learn more about Cloud Foundry, read the CF &lt;a href="http://blog.cloudfoundry.com/"&gt;blog&lt;/a&gt; and &lt;a href="https://github.com/cloudfoundry"&gt;code&lt;/a&gt;, since it is open sourced, you can simply install it from &lt;a href="https://github.com/cloudfoundry"&gt;github&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Updated: found a recent post about &lt;a href="http://blog.mongodb.org/post/6587009156/cloudfoundry-mongodb-and-nodejs"&gt;using MongoDB on cloudfoundry&lt;/a&gt; ;-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-8341145000083961051?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/8341145000083961051/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2011/04/hello-cloud-foundry-running-nodejs.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/8341145000083961051'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/8341145000083961051'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2011/04/hello-cloud-foundry-running-nodejs.html' title='Hello, Cloud Foundry running node.js'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-3136156045430907396</id><published>2011-04-19T20:11:00.000-07:00</published><updated>2011-04-19T20:11:59.893-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='Web Prog.'/><title type='text'>Free ebooks and tutorials for PHP, JavaScript and Ruby Beginners</title><content type='html'>Many thanks to R&lt;a href="http://www.readwriteweb.com/"&gt;ReadWriteWeb&lt;/a&gt; for these links:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://blog.socialware.com/wp-content/uploads/2009/12/readwriteweb_logo.png" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.readwriteweb.com/hack/2011/04/5-free-e-books-and-tutorials-f.php"&gt;5 Free E-books and Tutorials for Learning PHP&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.readwriteweb.com/hack/2010/12/6-free-javascript-e-books.php"&gt;7 Free JavaScript E-books and Tutorials&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.readwriteweb.com/hack/2011/04/10-free-e-books-on-ruby-for-be.php"&gt;10 Free E-books on Ruby for Beginners&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-3136156045430907396?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/3136156045430907396/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2011/04/free-ebooks-and-tutorials-for-php.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/3136156045430907396'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/3136156045430907396'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2011/04/free-ebooks-and-tutorials-for-php.html' title='Free ebooks and tutorials for PHP, JavaScript and Ruby Beginners'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-481483025870642596</id><published>2011-04-14T00:08:00.000-07:00</published><updated>2011-04-14T11:59:47.791-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='node.js'/><title type='text'>interesting node modules</title><content type='html'>There are &lt;a href="http://search.npmjs.org/"&gt;so many node modules&lt;/a&gt; out there to the point that sometimes you can have several different ones that appear to solve the same problem.&lt;br /&gt;&lt;br /&gt;node.js on GitHub has a&lt;a href="https://github.com/joyent/node/wiki/modules"&gt; list of classified node modules&lt;/a&gt;, but still it is quite difficult to pick the best one (in terms of node version compatibility, easy to use, still actively developed, good performance, etc.).&lt;br /&gt;&lt;br /&gt;It would be really cool to have some sites that actually give reviews and code samples of using these node modules. If performance comparison can be provided, that is even better.&lt;br /&gt;&lt;br /&gt;Inspired by "&lt;a href="http://blog.nodejitsu.com/6-must-have-nodejs-modules"&gt;6 Must Have Node.js Modules&lt;/a&gt;", I am listing the modules that I found quite interesting and useful to the current work:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;HTTP clients:&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="https://github.com/pfleidi/node-wwwdude"&gt;node-wwwdude&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="https://github.com/pfleidi/node-wwwdude"&gt;&lt;/a&gt;&lt;a href="https://github.com/mikeal/request"&gt;request&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;XML to object conversion:&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="https://github.com/maqr/node-xml2js"&gt;node-xml2js&lt;/a&gt;, a fairly lightweight and fast xml to object conversion library&lt;/li&gt;&lt;li&gt;&lt;a href="https://github.com/astro/node-expat"&gt;node-expat&lt;/a&gt;, a very high performance SAX lib, native binding to libexpat, it has &lt;a href="https://github.com/shimondoodkin/node-expat"&gt;a fork&lt;/a&gt; with object conversion support&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;b&gt;Image processing:&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="https://github.com/LearnBoost/node-canvas"&gt;node-canvas&lt;/a&gt;: canvas implementation based on Cairo&lt;/li&gt;&lt;li&gt;&lt;a href="https://github.com/soldair/node-qrcode"&gt;node-qrcode&lt;/a&gt;: QR code generator&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-481483025870642596?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/481483025870642596/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2011/04/interesting-node-modules.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/481483025870642596'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/481483025870642596'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2011/04/interesting-node-modules.html' title='interesting node modules'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-3915738439546206261</id><published>2011-03-20T14:40:00.000-07:00</published><updated>2011-04-19T19:50:58.795-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='node.js'/><title type='text'>resources to get started with node.js</title><content type='html'>There are quite some blogs and websites about "getting started with node.js". Here are some resources that I found most useful:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://howtonode.org/"&gt;How To Node&lt;/a&gt;: maybe the best blog covering latest development in node.js with many core node.js developers and users.&lt;/li&gt;&lt;li&gt;&lt;a href="http://ofps.oreilly.com/titles/9781449398583/index.html"&gt;Up and Running with Node.js&lt;/a&gt;: OReilly's new book, freely available online as of now&lt;/li&gt;&lt;li&gt;&lt;a href="http://visionmedia.github.com/masteringnode/book.html"&gt;Mastering Node&lt;/a&gt;: another great online book&lt;/li&gt;&lt;li&gt;&lt;a href="http://blog.osbutler.com/categories/node-by-example/?page=3"&gt;Node by Example&lt;/a&gt;: a series of examples to get you started with node.js&lt;/li&gt;&lt;li&gt;&lt;a href="http://nodebeginner.org/"&gt;The Node Beginner Book&lt;/a&gt; (&lt;span class="Apple-style-span" style="color: red;"&gt;WIP new&lt;/span&gt;)&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-3915738439546206261?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/3915738439546206261/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2011/03/resources-to-get-started-with-nodejs.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/3915738439546206261'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/3915738439546206261'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2011/03/resources-to-get-started-with-nodejs.html' title='resources to get started with node.js'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-7793995995620589223</id><published>2011-03-19T19:39:00.000-07:00</published><updated>2011-03-19T19:41:18.954-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='hardware'/><title type='text'>set up Linksys WRT54GL as a WiFi repeater with Tomato</title><content type='html'>Since I &lt;a href="http://mwebhack.blogspot.com/2010/12/asus-rt-n16-hack.html"&gt;got the new ASUS RT-N16&lt;/a&gt;, the old Linksys WRT54GL v1.1 router has been sitting there and collecting dust. There is only one phone line at home at one corner of the house, so I have been thinking of using the idle router as a WiFi repeater so that I can get decent WiFi coverage for each room.&lt;br /&gt;&lt;br /&gt;Finally I found some time this weekend and studied about it. &lt;a href="http://www.dd-wrt.com/wiki/index.php/Repeater_Bridge"&gt;Many online tutorials&lt;/a&gt; cover how to do it using DD-WRT, another great customized firmware for WiFi routers. Since my RT-N16 already runs &lt;a href="http://www.polarcloud.com/tomato"&gt;Tomato&lt;/a&gt;, I'd want to find a way to have Tomato on WRT54GL and work as the repeater as well.&lt;br /&gt;&lt;br /&gt;After digging into the Web searches, finally I found &lt;a href="http://www.polarcloud.com/tomatofaq#how_do_i_use_wds"&gt;Tomator author's FAQ for WDS&lt;/a&gt;, it is very straightforward. Basically, both both master and repeater routers need to set "Wireless Mode" into "AP and WDS". You also need to turn off dhcp and wan (turn WAN/Internet type into "disabled"). Then you configure WDS to "Link with..." each other's MAC address.&lt;br /&gt;&lt;br /&gt;WDS stands for Wireless Distribution System, it enables interconnections between access points (AP). &lt;a href="http://en.wikipedia.org/wiki/Wireless_Distribution_System"&gt;Wikipedia definition&lt;/a&gt; has more technical details. Ideally, using WDS we can chain more APs together, just make sure you don't keep any loop ;-)&lt;br /&gt;&lt;br /&gt;The beautify of this is that it uses the same ssid, so when you move around, it switches to the router with the best signal strength automatically.&lt;br /&gt;&lt;br /&gt;To test the signal strength, there is a nice free tool for Mac called &lt;a href="http://www.chimoosoft.com/products/apgrapher/#downloads"&gt;AP Grapher&lt;/a&gt;, very handy indeed.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-7793995995620589223?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/7793995995620589223/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2011/03/set-up-linksys-wrt54gl-as-wifi-repeater.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/7793995995620589223'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/7793995995620589223'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2011/03/set-up-linksys-wrt54gl-as-wifi-repeater.html' title='set up Linksys WRT54GL as a WiFi repeater with Tomato'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-3968582730393047815</id><published>2011-03-05T15:37:00.000-08:00</published><updated>2011-03-05T15:37:43.284-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='network'/><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><category scheme='http://www.blogger.com/atom/ns#' term='Apple'/><title type='text'>wireshark no network interface issue</title><content type='html'>&lt;a href="http://www.wireshark.org/"&gt;wireshark&lt;/a&gt; is one of the best tool to deep network analysis. But due to the permission issue on BPF devices on Mac OSX (by default only root can read and write BPF devices), you won't see network interfaces in wireshare on Mac ;-(&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There are two ways to fix:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;- run &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;sudo chown &amp;lt;your_user_id&amp;gt; /dev/bpf*&lt;/span&gt; on command line before you start wireshark, you will need to do it again after reboot&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;- add a startup script to fix this permanently (see instructions that comes with wireshark, D&amp;amp;D &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Utilities/ChmodBPF&lt;/span&gt; directory in the installation package into &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;/Library/StartupItems&lt;/span&gt;&lt;/div&gt;. You can adjust the script for your needs as well, for details, see the documentation that comes with wireshare.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-3968582730393047815?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/3968582730393047815/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2011/03/wireshark-no-network-interface-issue.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/3968582730393047815'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/3968582730393047815'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2011/03/wireshark-no-network-interface-issue.html' title='wireshark no network interface issue'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-3622908209098495172</id><published>2011-02-26T20:25:00.000-08:00</published><updated>2011-02-26T20:46:03.749-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='node.js'/><title type='text'>node.js hosting in Amazon EC2</title><content type='html'>node.js has rapid growth and there are so many hosting services available. Ryan maintains&lt;a href="https://github.com/joyent/node/wiki/hosting"&gt; a long list of providers on github&lt;/a&gt; already and new ones like &lt;a href="http://code.danyork.com/2011/01/18/nodefu-free-hosting-of-your-node-js-apps-in-the-cloud/"&gt;NodeFu&lt;/a&gt; keeps coming out every day. I have personally tried two managed hosting services duostack and JSApp.US, both are very easy to set up and use. The only drawback is that they pose limitations on installed modules, etc.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Amazon is offering 1 year free trial for its cloud services, so called "&lt;a href="http://aws.amazon.com/free/"&gt;AWS Free Usage Tier&lt;/a&gt;". I decided to give it a try and set up an EC2 instance for node.js.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The whole process is not quite user friendly (not as friendly as the shopping experience on Amazon). There are quite several choices for the image to choose. My first attempt with a SuSE 64bit image also got permission issues when I install gcc somehow. Finally, from the Web search results, I found&lt;a href="http://www.embracingthecloud.com/2010/12/05/InstallingNodejsOnAmazonEC2.aspx"&gt; Mike Leach's step-by-step guide "Installing node.js on Amazon EC2"&lt;/a&gt;, which is really helpful. &lt;a href="http://phon.me/?p=25"&gt;Jim Smith's blog post added a nginx as the front end&lt;/a&gt;, a nice addition since node.js is not multi-threading out of box.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Some minor differences when I followed Mike's steps:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;instead of ssh to the vm using ec2-user@ec2-public-dns, I had to use ec2-user@&amp;lt;address you can find in AWS management console by right clicking on the instance and then clicking connect&amp;gt;, note that the instructions there told you to ssh as root@&amp;lt;address&amp;gt;, but it did not work for me, saying I had to use ec2-user@&lt;/li&gt;&lt;li&gt;instead of --without-ssl option to ./configure, I added openssl and openssl-devel&lt;/li&gt;&lt;li&gt;I did node and npm installation using the "node-and-npm-in-30-seconds.sh" script from this gist mentioned in the Joyeur post "&lt;a href="http://joyeur.com/2010/12/10/installing-node-and-npm/"&gt;Installing Node and npm&lt;/a&gt;"&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-3622908209098495172?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/3622908209098495172/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2011/02/nodejs-hosting-in-amazon-ec2.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/3622908209098495172'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/3622908209098495172'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2011/02/nodejs-hosting-in-amazon-ec2.html' title='node.js hosting in Amazon EC2'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-851733480672190482</id><published>2011-02-12T23:31:00.000-08:00</published><updated>2011-02-12T23:32:02.850-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bash'/><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><title type='text'>handy tutorials</title><content type='html'>Just found several handy tutorials/references that could quickly refresh your knowledge about the tools and get work done easily.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://bash.cyberciti.biz/guide/Main_Page"&gt;Linux Shell Scripting Tutorial&lt;/a&gt;, I am a big fan of &lt;a href="http://www.cyberciti.biz/"&gt;nixCraft&lt;/a&gt; site for its quick tips on *NIX. I found this one easier to navigate and understand than &lt;a href="http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO.html"&gt;BASH programming - Introduction HOW-TO&lt;/a&gt; or &lt;a href="http://tldp.org/LDP/abs/html/"&gt;Advanced Bash-Scripting Guide&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://projects.serenity.de/textmate/tutorials/basics/"&gt;TextMate Basics Tutorial&lt;/a&gt;, a nicely written piece that walks you through the basics of TextMate, I especially like the organization of the shortcut keys&lt;/li&gt;&lt;li&gt;&lt;a href="http://gitref.org/"&gt;Git Reference&lt;/a&gt;, a much shorter quick guide than &lt;a href="http://www.kernel.org/pub/software/scm/git/docs/user-manual.html"&gt;Git User's Manual&lt;/a&gt; (too long and boring)&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;Again, reading a lot is not as useful as coding a lot. But if you don't use it for day-to-day work, you might easily forget many tricks. So, some quick references are handy in this situation to bring you quickly up to speed.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-851733480672190482?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/851733480672190482/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2011/02/handy-tutorials.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/851733480672190482'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/851733480672190482'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2011/02/handy-tutorials.html' title='handy tutorials'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-691871393788958606</id><published>2011-02-05T15:05:00.000-08:00</published><updated>2011-02-05T23:40:27.351-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='Web Prog.'/><title type='text'>what does "new" do in JavaScript</title><content type='html'>Today, a colleague asked about exactly what is the difference between using "new" and calling the function directly. Only thing I can think of is the meaning for "this" inside the function. With "new", this means the object being created, but without "new", this means the global object, either window or something else. And I am also not clear what exactly happens behind the scene.&lt;br /&gt;&lt;br /&gt;So, did some search and found some good readings that explains this topic fairly clearly. Lots of related answers from Stack Overflow is also quite helpful:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/1646698/what-is-the-new-keyword-in-javascript"&gt;What is the 'new' keyword in JavaScript&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://howtonode.org/object-graphs"&gt;Tim Caswell's "Learning JavaScript with Object Graphs" series&lt;/a&gt; (perfect for visual person like me, in &lt;a href="http://howtonode.org/object-graphs-2"&gt;II&lt;/a&gt;, he specifically mentions about how to create objects besides using new: use Object.create and object factory)&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;Here is &lt;a href="http://joost.zeekat.nl/constructors-considered-mildly-confusing.html"&gt;a good article&lt;/a&gt; that tests your understanding of "new" keyword ;-)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now, whether or not you should use "new" is another question:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/383402/is-javascript-s-new-keyword-considered-harmful"&gt;Is JavaScript's 'new' keyword considered harmful?&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;br /&gt;Using "new" to instantiate a class has both pros (great performance) and cons (can cause nightmare if you forget to use new). Many people including &lt;a href="http://javascript.crockford.com/code.html"&gt;Douglas Crockford&lt;/a&gt; discourages the use of new. &lt;a href="http://yuiblog.com/blog/2007/06/12/module-pattern/"&gt;A module pattern&lt;/a&gt; is a more preferable way. John Resig also has &lt;a href="http://ejohn.org/blog/simple-class-instantiation/"&gt;a simple solution&lt;/a&gt; to avoid using new directly without much performance sacrifice.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-691871393788958606?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/691871393788958606/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2011/02/what-does-new-do-in-javascript.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/691871393788958606'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/691871393788958606'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2011/02/what-does-new-do-in-javascript.html' title='what does &quot;new&quot; do in JavaScript'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-726923084449785192</id><published>2010-12-05T14:30:00.000-08:00</published><updated>2010-12-06T14:09:15.088-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='network'/><category scheme='http://www.blogger.com/atom/ns#' term='hardware'/><title type='text'>Hack ASUS RT-N16 to enable NAS, media server, offline BT/emule, etc.</title><content type='html'>&lt;img src="http://ecx.images-amazon.com/images/I/41iHDiIOIWL._SL500_AA300_.jpg" /&gt;&lt;br /&gt;&lt;a href="http://www.amazon.com/ASUS-RT-N16-Wireless-N-Gigabit-Router/dp/B00387G6R8/ref=sr_1_1?ie=UTF8&amp;amp;qid=1291586498&amp;amp;sr=8-1"&gt;ASUS RT-N16&lt;/a&gt; is the most affordable and versatile wireless router out there. I was previously looking for a NAS solution and then found that this router has 2 USB ports that could turn a printer into network printer and an external USB hard drive into a network storage.&lt;br /&gt;&lt;br /&gt;The default firmware works ok so far. What I did is first configure it and then upgrade to the latest firmware version from ASUS website. UPnP and Samba file sharing worked fine out of box.&lt;br /&gt;&lt;br /&gt;But after doing some online search, to really unleash the real power of this router, we need to install third-party firmware such as &lt;a href="http://en.wikipedia.org/wiki/Tomato_(firmware)"&gt;Tomato&lt;/a&gt; (it actually needs Tomato variants that support USB such as &lt;a href="http://tomatousb.org/"&gt;Tomato USB&lt;/a&gt;) and &lt;a href="http://www.dd-wrt.com/site/index"&gt;DD-WRT&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;There are also several Tomato variants from Taiwan and mainland China: &lt;a href="http://www.dualwan.cn/index.php/tomato-overview"&gt;Tomato DualWAN&lt;/a&gt;, &lt;a href="http://blog4tomato.appspot.com/"&gt;Tomato Pandora&lt;/a&gt;&amp;nbsp;(&lt;a href="http://blog4tomato.appspot.com/?p=35001"&gt;supported routers&lt;/a&gt;) that supports web-based tools such as Chinese Web interface, BT, file system access, etc. I also found &lt;a href="http://digiland.tw/viewforum.php?id=42"&gt;a Taiwan forum&lt;/a&gt; that discusses these variants, quite cool actually.&lt;br /&gt;&lt;br /&gt;Searching on Tomato USB site gives &lt;a href="http://tomatousb.org/search:site/a/p/q/asus%20rt-n16"&gt;several tutorials&lt;/a&gt;, &lt;b&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;but t&lt;/span&gt;&lt;/b&gt;&lt;a href="http://patricksheedy.net/blog/simple-tomato-firmware-install-on-asus-rt-n16-router/"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;his one&lt;/span&gt;&lt;/b&gt;&lt;/a&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt; recommended by a colleague seems to be most straightforward and I am going to try it out now ;-)&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="color: red;"&gt;Update:&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The whole processing following the above tutorial went like a breeze. The only thing (not really an issue) that I encountered is that the restoration tool got stuck at 33% for quite a while and then gave a scary error message. But then I tested and the router is actually already running Tomato. So, simply ignore that error!&lt;br /&gt;&lt;br /&gt;Note that you need to enable the USB option to get your external USB hard disk working. &lt;a href="http://www.society9.com/setting-up-a-low-cost-nas-using-tomato/"&gt;Here is an article&lt;/a&gt; that walks you through setting up a poor man's NAS with more detailed settings and controls. &lt;a href="http://www.society9.com/so_how_fast_is_nas_under_tomato/"&gt;He also did some benchmark&lt;/a&gt; on a USB flash drive and found out that the flash drive has a better performance attached to the router than attached to the windows computer, unbelievable...&lt;br /&gt;&lt;br /&gt;So, the next step will be to &lt;a href="http://tomatousb.org/tut:optware-installation"&gt;install&lt;/a&gt; &lt;a href="http://tomatousb.org/doc:optware"&gt;Optware&lt;/a&gt; and get a lot of interesting toys (amule, transmission, unix tools, web servers, vpn, asterisk voip pbx, etc.) on it! Also heard there is another better UPnP solution that does transcoding for iOS devices (iPhone/iPad has many UPnP apps such as &lt;a href="http://www.plugplayer.com/"&gt;PlugPlayer&lt;/a&gt;, Apple TV supports &lt;a href="http://xbmc.org/download/"&gt;XBMC&lt;/a&gt;), haha...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-726923084449785192?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/726923084449785192/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/12/asus-rt-n16-hack.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/726923084449785192'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/726923084449785192'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/12/asus-rt-n16-hack.html' title='Hack ASUS RT-N16 to enable NAS, media server, offline BT/emule, etc.'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-8945833241373557216</id><published>2010-12-01T13:58:00.000-08:00</published><updated>2010-12-02T15:02:18.607-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='Web Prog.'/><title type='text'>quiz time!</title><content type='html'>If you are confident about your JavaScript knowledge, try out these quizzes, it just made my brain stop working...&lt;br /&gt;&lt;ul&gt;&lt;li&gt;"&lt;a href="http://dmitry.baranovskiy.com/post/91403200"&gt;So, you think you know JavaScript?&lt;/a&gt;", &lt;a href="http://www.nczonline.net/blog/2010/01/26/answering-baranovskiys-javascript-quiz/"&gt;answers explained by Zakas&lt;/a&gt;&lt;/li&gt;&lt;li&gt;"&lt;a href="http://james.padolsey.com/javascript/another-javascript-quiz/"&gt;Another JavaScript Quiz&lt;/a&gt;" by James Padolsey&lt;/li&gt;&lt;li&gt;"&lt;a href="http://perfectionkills.com/javascript-quiz/"&gt;JavaScript Quiz&lt;/a&gt;" from &lt;a href="http://perfectionkills.com/"&gt;Perfection kills (exploring JavaScript by example)&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;Now, if you feel how twisted/unreasonable/difficult/loose JavaScript syntax is, you are not alone.&lt;br /&gt;&lt;br /&gt;Several good readings that might help to clear things a bit:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.nczonline.net/blog/2010/01/26/answering-baranovskiys-javascript-quiz/"&gt;Zakas explained a bit about the first quiz&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;It is interesting that a variable can be declared after it is being used because the engine will hoist the variable declarations to the top of execution context. &amp;nbsp;Also interesting to see that the engine breaks "var i = 1" into declaration part "var i;" and initialization part "i = 1;", and move the declaration to the top.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Another interesting note is that function declaration overrides a variable declaration with the same name, but cannot override the variable declaration+initialization.&lt;/div&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://perfectionkills.com/understanding-delete/"&gt;Understanding delete from Perfection kills&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;Really a comprehensive explanation about how execution context, scope, variable attributes, etc. work in JavaScript. Now, finally I understand the difference between variable declaration+initialization (cannot be deleted) and undeclared assignment (can be deleted) because of the former one has DontDelete flag and the latter one does not.&lt;br /&gt;&lt;br /&gt;After reading this article, it is now apparent why the function declaration has strange override behavior for the variable with a same name. The variable declaration+initialization gets a DontDelete flag and thus cannot be overridden.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://kangax.github.com/nfe/"&gt;Named function expressions demystified&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;This one explained what is function declaration, function expression and named function expression and bugs handling named function expression in various JavaScript engines. One note is that for the named function expression, the name/identifier can only be accessed in its function body.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf"&gt;ECMA-262 3rd edition specification&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;The ultimate reference for underlying mechanisms of JavaScript.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-8945833241373557216?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/8945833241373557216/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/12/quiz-time.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/8945833241373557216'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/8945833241373557216'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/12/quiz-time.html' title='quiz time!'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-7030719732962884176</id><published>2010-11-22T11:19:00.000-08:00</published><updated>2010-11-22T11:19:42.034-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='Web Prog.'/><title type='text'>what this means in JavaScript</title><content type='html'>As someone new to JavaScript programming, there are many language features that are so uncomfortable. What *this* really means and referring to is one of the pains.&lt;br /&gt;&lt;br /&gt;Finally, after reading some nice articles, I think I start to get the idea: it basically means the context/scope the function is called and can change at runtime.&lt;br /&gt;&lt;br /&gt;Two great articles that explains this clearly:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;&lt;a href="http://www.quirksmode.org/js/this.html"&gt;The basics about this from quirksmode&lt;/a&gt;&lt;/b&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;&lt;a href="http://www.digital-web.com/articles/scope_in_javascript/"&gt;A more in-depth look at this and how to use it in real world from DWM&lt;/a&gt;&lt;/b&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-7030719732962884176?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/7030719732962884176/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/11/what-this-means-in-javascript.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/7030719732962884176'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/7030719732962884176'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/11/what-this-means-in-javascript.html' title='what this means in JavaScript'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-506338068303544145</id><published>2010-11-20T00:29:00.000-08:00</published><updated>2010-11-20T15:47:43.624-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='Web Prog.'/><title type='text'>Execute JavaScript from TextMate</title><content type='html'>TextMate is the most popular text editor for frontend development (of course, people also use emacs, vim/gvim/macvim, Aptana, Eclipse, etc.). I have been using TM for PHP development and really enjoyed the convenience of ctrl+shift+R to execute the PHP CLI scripts and view the output from TM.&lt;br /&gt;&lt;br /&gt;I know most of people develop and debug JavaScript from development tools provided by the browser, e.g. firebug, developer tools in Chrome, Safari, etc. But it will be really neat if I can just run JavaScript and view output directly from TM.&lt;br /&gt;&lt;br /&gt;So, I searched and searched. There are many existing blog posts on this topic already. It basically consists of two steps:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1. get a JavaScript engine that executes the JavaScript code&lt;/b&gt;, here are some options:&lt;br /&gt;&lt;br /&gt;- Mac/Safari has a JS engine (SquirrelFish Extreme) built in already, it is located at&amp;nbsp;&lt;span class="Apple-style-span" style="font-family: 'Courier New', monospace; font-size: 11px; line-height: 12px; white-space: pre;"&gt;/System/Library/Frameworks/JavaScriptCore.framework/Versions/A/Resources/jsc&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;- Node.js: Node.js is a event-based JS platform based on the V8 JS engine, see &lt;a href="http://mwebhack.blogspot.com/2010/11/nodejs-setup-on-mac.html"&gt;my previous post&lt;/a&gt; on how to set it up&lt;br /&gt;&lt;br /&gt;- Mozilla JS engines: installation guide to build/install &lt;a href="https://dev.mozilla.jp/localmdc/developer.mozilla.org/en/spidermonkey/build_documentation.html"&gt;SpiderMonkey&lt;/a&gt;, &lt;a href="http://www.phpied.com/installing-rhino-on-mac/"&gt;Rhino&lt;/a&gt;, &lt;a href="http://www.nakedjavascript.com/installing-tracemonkey-on-mac-os-x-and-linux"&gt;TraceMonkey&lt;/a&gt; on Mac&lt;br /&gt;&lt;br /&gt;- For o&lt;a href="http://en.wikipedia.org/wiki/JavaScript_engine"&gt;ther JS engines&lt;/a&gt;, do a Web search for installation instructions&lt;br /&gt;&lt;br /&gt;&lt;b&gt;2. define new TM commands for JavaScript in TM bundle editor and assign ctrl+shift+R key binding to the commands.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;For command setup to use Node.js, see &lt;a href="https://gist.github.com/403284"&gt;this github snippet&lt;/a&gt; by beastaugh, it basically creates a script that executes another script given the file path.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_H6rVU2Zp9jA/TOeFkVuVG6I/AAAAAAAAJBQ/vL65Mt9PXCM/s1600/TM-bundle-editor.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="280" src="http://3.bp.blogspot.com/_H6rVU2Zp9jA/TOeFkVuVG6I/AAAAAAAAJBQ/vL65Mt9PXCM/s400/TM-bundle-editor.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;For command to set up other engines, you specify the path to the engine executable, execute the JavaScript and output in a popup window. You can also use another command and open up a terminal to show the results, see &lt;a href="http://www.metaskills.net/2010/7/9/interactive-javascript-console-with-textmate"&gt;this post&lt;/a&gt; for how to do that.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_H6rVU2Zp9jA/TOeFqMsSFcI/AAAAAAAAJBU/Gz_7r6ThQTQ/s1600/TM-bundle-editor-2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="282" src="http://2.bp.blogspot.com/_H6rVU2Zp9jA/TOeFqMsSFcI/AAAAAAAAJBU/Gz_7r6ThQTQ/s400/TM-bundle-editor-2.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Then, you are all set. This is a screen shot that allows me to pick one of the three engines to run my JavaScript from TM ;-)&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_H6rVU2Zp9jA/TOeG048DihI/AAAAAAAAJBY/8y5pPt2OcBw/s1600/pick-engine.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="196" src="http://2.bp.blogspot.com/_H6rVU2Zp9jA/TOeG048DihI/AAAAAAAAJBY/8y5pPt2OcBw/s400/pick-engine.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_H6rVU2Zp9jA/TOeG4lyKV8I/AAAAAAAAJBc/YAJASZVmNd0/s1600/show_result.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="86" src="http://4.bp.blogspot.com/_H6rVU2Zp9jA/TOeG4lyKV8I/AAAAAAAAJBc/YAJASZVmNd0/s400/show_result.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-506338068303544145?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/506338068303544145/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/11/execute-javascript-from-textmate.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/506338068303544145'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/506338068303544145'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/11/execute-javascript-from-textmate.html' title='Execute JavaScript from TextMate'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_H6rVU2Zp9jA/TOeFkVuVG6I/AAAAAAAAJBQ/vL65Mt9PXCM/s72-c/TM-bundle-editor.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-2761965540514913145</id><published>2010-11-19T23:01:00.000-08:00</published><updated>2010-11-19T23:41:01.348-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='Web Prog.'/><title type='text'>to var or not to var</title><content type='html'>It's a quite interesting and yet confusing question:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;What is the difference between declaration of a variable with and without "var"?&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;After reading &lt;a href="http://stackoverflow.com/questions/1470488/difference-between-using-var-and-not-using-var-in-javascript"&gt;the question and answers on Stack Overflow&lt;/a&gt;, I finally start to get it.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;First, it affects the scope of the variable.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The variable defined &lt;b&gt;without var&lt;/b&gt; means the nearest scope in the case of a hierarchical structure, e.g. embedding one function inside another function. In most cases, a declaration without var in a function means global scope (in many cases this means window object). The variable defined &lt;b&gt;with var&lt;/b&gt; is bound to the scope of that function.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Second, it affects the delete behavior.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The variable defined with var cannot be deleted. The variable defined without var (actually, this is a property, not a variable in the true sense) can be deleted. The reason behind this that variable defined with var has a flag of DontDelete. See &lt;a href="http://stackoverflow.com/questions/1470488/difference-between-using-var-and-not-using-var-in-javascript#answer-1471738"&gt;this nicely explained Stack Overflow post&lt;/a&gt; for details.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Lastly, the general guide is to always use var.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: javascript"&gt;var i = 'hello';&lt;br /&gt;j = 'world';&lt;br /&gt;print("i=" + i + ", j=" + j); // i=hello, j=world&lt;br /&gt;(testFunc = function() {&lt;br /&gt; var i = 'foo';&lt;br /&gt; print("inside function: i=" + i); // inside function: i=foo&lt;br /&gt; print("inside function: j=" + j); // inside function: j=world&lt;br /&gt;})();&lt;br /&gt;delete i;&lt;br /&gt;print("i=" + i); // i=hello, ha, i still exists!&lt;br /&gt;delete j;&lt;br /&gt;print("j=" + j); // ReferenceError: j is not defined, j got deleted&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Ok, one last exercise before I close this post. Guess what is the output for this code snippet:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: javascript"&gt;func2_var = 'var outside';&lt;br /&gt;func2_var2 = 'var2 outside';&lt;br /&gt;func2 = function() {&lt;br /&gt; var func2_var = 'var in func2 body';&lt;br /&gt; this.func2_var2 = 'var2 in func2 this';&lt;br /&gt;}&lt;br /&gt;func2.prototype.func2_var = 'var in func2 prototype';&lt;br /&gt;&lt;br /&gt;f2 = new func2();&lt;br /&gt;print("which var it is: " + f2.func2_var);&lt;br /&gt;print("which var2 it is: " + f2.func2_var2);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The END.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-2761965540514913145?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/2761965540514913145/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/11/to-var-or-not-to-var.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/2761965540514913145'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/2761965540514913145'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/11/to-var-or-not-to-var.html' title='to var or not to var'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-9213017594564451070</id><published>2010-11-18T22:24:00.000-08:00</published><updated>2010-11-18T23:10:21.974-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='Web Prog.'/><title type='text'>Lint for JavaScript</title><content type='html'>&lt;a href="http://en.wikipedia.org/wiki/Lint_(software)"&gt;Lint&lt;/a&gt; tools are very useful to detect syntax and style errors in your code. It of course has variants for JavaScript. There are many different tool setup based on your editor. On the Mac, maybe the most popular/handy editor is TextMate.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;1. &lt;a href="http://jslint.com/"&gt;jslint.com&lt;/a&gt;: a Web tool&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;This is the tool developed by Douglas Crockford. It has a simple Web interface. You copy and paste your code and click JSLint button, it is that simple. The drawback is every time you make a change, you need to re-copy-n-paste and repeat the validation.&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;&lt;b&gt;2. TextMate bundles:&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="https://github.com/johnmuhl/javascript-tools-tmbundle"&gt;johnmuhl's javascript tools tmbudle&lt;/a&gt;&lt;br /&gt;It provides a toolkit for working with JavaScript in Textmate: JSLint, various formatters, obfuscators, and compressors.&lt;br /&gt;&lt;br /&gt;&lt;a href="https://github.com/subtleGradient/javascript-tools.tmbundle"&gt;subtleGradient's javascript tools tmbundle&lt;/a&gt;&lt;br /&gt;This is very similar to the previous tmbundle except that it uses JavaScript Lint instead of JSLint. Also, the timestamp seems more up-to-date. The installation is very straightforward, download the src, rename it to be a TextMate bundle file and let TextMate install it. Then, you access it via various key combinations.&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;&lt;b&gt;3. TextMate integration with JSLint:&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Stoyan has &lt;a href="http://www.phpied.com/jslint-on-mac-textmate/"&gt;a nice post&lt;/a&gt; with all the detailed instructions. It is a bit complicated than using method #2.&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;&lt;b&gt;4. Vim integration with JSLint:&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Only saw &lt;a href="http://stackoverflow.com/questions/473478/vim-jslint"&gt;some discussions&lt;/a&gt; on Stack Overflow, did not actually try it out.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-9213017594564451070?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/9213017594564451070/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/11/lint-for-javascript.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/9213017594564451070'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/9213017594564451070'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/11/lint-for-javascript.html' title='Lint for JavaScript'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-8065717074522870652</id><published>2010-11-17T22:40:00.000-08:00</published><updated>2010-11-18T22:48:49.342-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tools'/><category scheme='http://www.blogger.com/atom/ns#' term='hack'/><title type='text'>Android on iPhone</title><content type='html'>First, this does not make much sense unless you are someone who just wants to try out crazy stuff. Somehow I was in an unstable mode that day and jumped right in when I saw &lt;a href="http://www.redmondpie.com/install-android-2.2.1-froyo-on-iphone-3g-2g-using-bootlace-in-cydia-no-computer-required/"&gt;this article&lt;/a&gt; that details all the steps how to run Android 2.2.1 on iPhone.&lt;br /&gt;&lt;br /&gt;And it turned out to be a disaster and waste of time.&lt;br /&gt;&lt;br /&gt;The installation process all went fine. And I can boot into Android, though the boot process is a bit long (maybe because mine is iPhone 2G?)&lt;br /&gt;&lt;br /&gt;After booting into Android, everything looked fine, except that I could not find the Market to download apps -_- !!!&lt;br /&gt;&lt;br /&gt;I played around with existing apps. The camera is not really working and crashed several times on me. The phone dial seemed to be working fine and I can make phone calls.&lt;br /&gt;&lt;br /&gt;Then I got bored and booted back into iOS. To my surprise, iTunes cannot recognize the iPhone anymore. This means I cannot sync and do backups, which really really sucks. The tutorial should have warned me in advance.&lt;br /&gt;&lt;br /&gt;Another strange thing is that many settings are changed in iOS. All the name in my contacts are gone, so basically I only see the phone numbers now. Also settings like screenlock, wifi and others are also changed somehow.&lt;br /&gt;&lt;br /&gt;I tried to restore and jailbreak again. It took me quite some time to find the right firmware and tool. Finally, everything is back to normal and data was restored.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="color: red;"&gt;So, I highly discourage this experiment to anyone since the software is still not stable.&lt;/span&gt;&lt;/b&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-8065717074522870652?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/8065717074522870652/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/11/android-on-iphone.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/8065717074522870652'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/8065717074522870652'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/11/android-on-iphone.html' title='Android on iPhone'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-2268052196477575492</id><published>2010-11-09T23:15:00.000-08:00</published><updated>2010-11-18T22:48:07.506-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='Web Prog.'/><title type='text'>JavaScript links</title><content type='html'>Saw this interesting discussion about &lt;a href="http://stackoverflow.com/questions/134845/href-for-javascript-links-or-javascriptvoid0"&gt;whether we should use href="javascript:void(0)" or href="#" with onClick event handler&lt;/a&gt;&amp;nbsp;on Stack Overflow.&lt;br /&gt;&lt;br /&gt;I think the best solution is to avoid using link element &amp;lt;a&amp;gt; in the first place and use CSS to style an element to make it "look" like a link and attach the event handler to that element. &lt;a href="http://tom.me.uk/scripting/links.html"&gt;This article&lt;/a&gt; has more discussions and comparisons why we should not use links in this particular case.&lt;br /&gt;&lt;br /&gt;As for why the event handler need to return false, it is because we want to avoid the default behavior of the &amp;nbsp;link element, i.e. to follow the href and go to another page. &lt;a href="http://www.quirksmode.org/js/events_early.html"&gt;This quirksmode article&lt;/a&gt; has it very clearly explained.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-2268052196477575492?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/2268052196477575492/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/11/javascript-links.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/2268052196477575492'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/2268052196477575492'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/11/javascript-links.html' title='JavaScript links'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-1401503335432193635</id><published>2010-11-08T22:04:00.000-08:00</published><updated>2010-11-18T22:48:35.281-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='node.js'/><title type='text'>node.js setup on Mac</title><content type='html'>&lt;a href="http://en.wikipedia.org/wiki/Node.js"&gt;node.js&lt;/a&gt; has been getting a lot tractions lately due to its high performance on V8 engine, event-based model and reusability of client side JavaScript on server side without any changes.&lt;br /&gt;&lt;br /&gt;There are several articles discussing how to set it up on the Mac and I found t&lt;a href="http://www.florian-kubis.de/2010/09/howto-install-node-js-on-mac-snow-leopard-with-express/"&gt;his one from Florian Kubis&lt;/a&gt; to be the easiest to follow.&lt;br /&gt;&lt;br /&gt;If you are using homebrew as your package management system instead of MacPorts, you should use&lt;a href="http://shapeshed.com/journal/setting-up-nodejs-and-npm-on-mac-osx/"&gt; this tutorial&lt;/a&gt; instead.&lt;br /&gt;&lt;br /&gt;The tutorials also cover &lt;a href="http://npmjs.org/"&gt;npm&lt;/a&gt; (the package manager for node.js) and &lt;a href="http://expressjs.com/guide.html"&gt;express&lt;/a&gt; (a Web app framework built for node.js)&lt;br /&gt;&lt;br /&gt;There is no MacPorts ports for npm and express yet, maybe someone should create them?&lt;br /&gt;&lt;br /&gt;Several slides and quick intro about node.js:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;"&lt;a href="http://www.slideshare.net/simon/evented-io-based-web-servers-explained-using-bunnies"&gt;Evented I/O based web servers, explained using bunnies&lt;/a&gt;", the idea behind node.js in 10 pages&lt;/li&gt;&lt;li&gt;"&lt;a href="http://www.slideshare.net/kompozer/nodejs-and-websockets-intro"&gt;Node.js and websockets intro&lt;/a&gt;", a bit more technical than the bunnies example&lt;/li&gt;&lt;li&gt;"&lt;a href="http://www.slideshare.net/sh1mmer/nodejs-and-how-javascript-is-changing-server-programming"&gt;Node.js: how JavaScript is changing server programming&lt;/a&gt;", more details in 65 pages&lt;/li&gt;&lt;li&gt;"&lt;a href="http://www.slideshare.net/apmoore/running-yui-3-on-nodejs"&gt;Running YUI3 on node.js&lt;/a&gt;", integration with YUI3, moving client js to server side without any changes!&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-1401503335432193635?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/1401503335432193635/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/11/nodejs-setup-on-mac.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/1401503335432193635'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/1401503335432193635'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/11/nodejs-setup-on-mac.html' title='node.js setup on Mac'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-8773245958492671759</id><published>2010-10-31T22:21:00.000-07:00</published><updated>2010-10-31T22:21:16.470-07:00</updated><title type='text'>syntax highlight with gist</title><content type='html'>Another much simpler way to add syntax highlight is using gist, which is a github tool to share code snippets. Each gist is basically a git repository that is versioned and forked. Syntax highlight happens to be a feature of it.&lt;br /&gt;&lt;br /&gt;Simple head over to&amp;nbsp;&lt;a href="http://gist.github.com/"&gt;http://gist.github.com/&lt;/a&gt;, paste your code snippet there and select the language, then select "create public gist". On the next page, click on "embed" and it becomes a JavaScript snippet. Just embed it in your page and you are done!&lt;br /&gt;&lt;br /&gt;No need to change Blogger template and no need to understand the configuration and syntax of SyntaxHighlighter ;-)&lt;br /&gt;&lt;br /&gt;Here is a quick example:&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/657657.js?file=gistfile1.html"&gt;&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-8773245958492671759?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/8773245958492671759/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/syntax-highlight-with-gist.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/8773245958492671759'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/8773245958492671759'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/syntax-highlight-with-gist.html' title='syntax highlight with gist'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-4923926737910934026</id><published>2010-10-31T14:30:00.000-07:00</published><updated>2010-10-31T22:14:01.576-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tools'/><category scheme='http://www.blogger.com/atom/ns#' term='Web Prog.'/><title type='text'>syntax highlight with SyntaxHighlighter (for Blogger)</title><content type='html'>&lt;a href="http://alexgorbatchev.com/SyntaxHighlighter/"&gt;SyntaxHighlighter&lt;/a&gt; is the standard way to put syntax highlight for your code snippets on a Web page. It is very straightforward to set up for Blogger (thanks to &lt;a href="http://www.shirmanov.com/2010/09/adding-syntaxhighlighter-30-to-blogger.html"&gt;Leonid's excellent Blogger post&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;Here is a quick summary of what you need to do (a bit variations for better performance):&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;i&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;1. Go to Design-&amp;gt;Edit HTML, update the template with SyntaxHighlighter CSS and Javascript elements.&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Splitting the CSS part and JavaScript part:&lt;/b&gt; put CSS that inside (not before) the &amp;lt;head&amp;gt; element. The JavaScript part goes right before the closing &amp;lt;body&amp;gt; element.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Comment out or delete AutoLoader JavaScript (the line with shAutoLoader.js)&lt;/b&gt; since we are not using it (I could not get it working either, although &lt;a href="http://ordinary-linux-user.blogspot.com/2010/09/installing-syntaxhighlighter-to-blogger.html"&gt;some people claimed it worked for them&lt;/a&gt;). The new AutoLoader basically loads the JavaScript brushes on demand instead of load from a list and use only one of them.&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: monospace;"&gt;&lt;span class="Apple-style-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-family: Times;"&gt;&lt;span class="Apple-style-span" style="white-space: normal;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;b&gt;Limit the list of JavaScript brushes to what you need only.&lt;/b&gt; Leonid lists all the brush types he is using, you can adjust that for your own needs. Since these JavaScripts will be loaded each time, it is better to keep the list short to get good performance. &lt;a href="http://alexgorbatchev.com/SyntaxHighlighter/manual/api/autoloader.html"&gt;Here is the list of all existing brush JavaScript files&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;OK, the Blogger template update is done. Now, let's use it in the actual post.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;i&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;2. In your new post, simply insert code inside a pair of &amp;lt;pre&amp;gt;&amp;lt;/pre&amp;gt; elements and specify brush type based on language like this:&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: html; gutter: false; toolbar: false"&gt;&amp;lt;pre class="brush: _brush_lang_"&amp;gt;your code&amp;lt;/pre&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;&lt;i&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;3. More adjustments and tips.&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Use a different CSS theme.&lt;/b&gt; Leonid uses Midnight theme (shThemeMidnight.css), I am using the Eclipse theme. You can choose a theme that you like, here is &lt;a href="http://alexgorbatchev.com/SyntaxHighlighter/manual/themes/"&gt;the list of available themes&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Customize different styles for individual code block.&lt;/b&gt; The changes in the Blogger template applies to all the code blocks. You can also specify/override styles for individual blocks. The simplest way is use the parameters in the &amp;lt;pre&amp;gt; class attributes. You can read available parameters on &lt;a href="http://alexgorbatchev.com/SyntaxHighlighter/manual/configuration/"&gt;SyntaxHighlighter configuration page&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;For example, I can easily highlight line #1 and #12 using&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: html; gutter: false; toolbar: false"&gt;&amp;lt;pre class="brush: javascript; highlight: [1, 12]"&amp;gt;your_code&amp;lt;/pre&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This is what it looks like:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: javascript; highlight: [1, 12]"&gt;var stringArray = new Array();&lt;br /&gt;  stringArray[0] = "A";&lt;br /&gt;  stringArray[1] = "B";&lt;br /&gt;  stringArray[2] = "C";&lt;br /&gt;  stringArray[3] = "D";&lt;br /&gt;  stringArray[4] = "E";&lt;br /&gt;  stringArray[5] = "F";&lt;br /&gt;  stringArray[6] = "G";&lt;br /&gt;&lt;br /&gt;  document.write("String value");&lt;br /&gt;  for (var i = 0; i &amp;lt; stringArray.length; i++) {&lt;br /&gt;    document.write(i + 1 + ". " + stringArray[i] + "");&lt;br /&gt;  }&lt;br /&gt;  document.write('&lt;br /&gt;');&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;Host your own SyntaxHighlighter scripts.&lt;/b&gt; You can use the hosted CSS and Javascript like the URLs in Leonid's example, which always points to the current/latests SyntaxHighlighter code base. If you want, you can also host it on you own.&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: x-large;"&gt;&lt;u&gt;References:&lt;/u&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://alexgorbatchev.com/SyntaxHighlighter/manual/installation.html"&gt;Official user guid&lt;/a&gt;e, it talks about another way that uses &amp;lt;script&amp;gt; tag instead of &amp;lt;pre&amp;gt;, &amp;lt;pre&amp;gt; has limitation of handling &amp;lt; character&lt;/li&gt;&lt;li&gt;&lt;a href="http://alexgorbatchev.com/SyntaxHighlighter/manual/brushes/"&gt;List of brushes&lt;/a&gt;&amp;nbsp;and how to make your own&lt;/li&gt;&lt;li&gt;&lt;a href="http://alexgorbatchev.com/SyntaxHighlighter/manual/themes/"&gt;List of Themes&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://alexgorbatchev.com/SyntaxHighlighter/manual/configuration/"&gt;List of configuration options and parameters&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-4923926737910934026?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/4923926737910934026/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/test-syntax-highlight.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/4923926737910934026'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/4923926737910934026'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/test-syntax-highlight.html' title='syntax highlight with SyntaxHighlighter (for Blogger)'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-4314412081944341415</id><published>2010-10-30T14:20:00.000-07:00</published><updated>2010-10-30T14:25:24.538-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cloud'/><category scheme='http://www.blogger.com/atom/ns#' term='Web Prog.'/><category scheme='http://www.blogger.com/atom/ns#' term='Google'/><title type='text'>exploring Google App Engine</title><content type='html'>&lt;img src="http://www.internetnews.com/img/2008/04/Google.App.Engine-tb-cs.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;Started to explore the &lt;a href="http://en.wikipedia.org/wiki/Google_App_Engine"&gt;Google App Engine&lt;/a&gt;, a cloud computing platform that enables developers to plug into the Google platform and services. It supports Python and Java (with some limitations) Web app frameworks.&lt;br /&gt;&lt;br /&gt;Here are some links that I found useful to begin with:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://code.google.com/appengine/kb/"&gt;FAQ&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://code.google.com/appengine/docs/whatisgoogleappengine.html"&gt;Getting Started Guide&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://code.google.com/appengine/docs/"&gt;Developer's Guide&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;Many books already available for this topic:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;O'Reilly: &lt;a href="http://www.amazon.com/Programming-Google-App-Engine-Infrastructure/dp/059652272X/ref=sr_1_1?ie=UTF8&amp;amp;qid=1288473355&amp;amp;sr=8-1"&gt;Programming Google App Engine (Nov 2009)&lt;/a&gt;, &lt;a href="http://www.amazon.com/Using-Google-Engine-Charles-Severance/dp/059680069X/ref=sr_1_2?ie=UTF8&amp;amp;qid=1288473355&amp;amp;sr=8-2"&gt;Using Google App Engine (May 2009)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Apress: &lt;a href="http://www.amazon.com/Developing-Google-App-Engine-Firstpress/dp/1430218312/ref=sr_1_5?ie=UTF8&amp;amp;qid=1288473355&amp;amp;sr=8-5"&gt;Developing with Google App Engine&lt;/a&gt; (Feb 2009), &lt;a href="http://www.amazon.com/Beginning-Java-Google-App-Engine/dp/143022553X/ref=sr_1_4?ie=UTF8&amp;amp;qid=1288473355&amp;amp;sr=8-4"&gt;Beginning Java Google App Engine (Dec 2009)&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;It is a pity that PHP is not supported so far, but &lt;a href="http://www.webdigi.co.uk/blog/2009/run-php-on-the-google-app-engine/"&gt;people have found ways to get around it&lt;/a&gt; by using a pure Java implementation of the PHP called &lt;a href="http://www.caucho.com/resin-3.0/quercus/"&gt;Quercus&lt;/a&gt;.&lt;ul&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-4314412081944341415?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/4314412081944341415/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/exploring-google-app-engine.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/4314412081944341415'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/4314412081944341415'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/exploring-google-app-engine.html' title='exploring Google App Engine'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-6452637534138798462</id><published>2010-10-29T23:15:00.000-07:00</published><updated>2010-10-29T23:18:42.825-07:00</updated><title type='text'>move posts from blogsome to Blogger</title><content type='html'>I used to like free wordpress blog service provided by blogsome and occasionally update my technical notes at &lt;a href="http://woshiadai.blogsome.com/"&gt;woshiadai.blogsome.com&lt;/a&gt;. But its online editor is really painful to use and way behind the Blogger editor.&lt;br /&gt;&lt;br /&gt;Today, after tried and failed to set up the SyntaxHighlighter javascript code highlighter on blogsome. I decided to move from blogsome to Blogger.&lt;br /&gt;&lt;br /&gt;But how to export existing posts and import into Blogger? After a bit Google search, here is what you should do (assuming your blogsome blog is foo.blogsome.com)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1. export existing blogsome posts in RSS 2.0 format in an XML file&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;- log into blogsome as admin&lt;br /&gt;- go to manage-&amp;gt;posts, write down the id of your latest post, say 125, this is the total number of posts you have for your blogsome blog&lt;br /&gt;- go to options-&amp;gt;reading-&amp;gt;syndication feeds, change "show most recent" from x (e.g. default is 10) to 125, also change "for each article, show" to full text&lt;br /&gt;- open a new browser window, enter http://foo.blogsome.com/feed/, you will get all existing posts in RSS 2.0 format, save the current page as feed.xml&lt;br /&gt;&lt;br /&gt;&lt;b&gt;2. convert exported blogsome feed.xml to a format that Blogger can recognize/accept&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Blogger has some strange behavior, if you directly import this feed.xml, Blogger gives a very hard to understand error with the slide bar keeping going back and forward (&lt;span class="Apple-style-span" style="color: red;"&gt;Blogger, please fix this bug, at least provide some more meaningful explanation about this error&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: 13px; line-height: 18px;"&gt;&lt;i&gt;&lt;span class="Apple-style-span" style="color: red;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;"&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: 13px; line-height: 18px;"&gt;&lt;i&gt;&lt;span class="Apple-style-span" style="color: red;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;Sorry, the import failed due to a server error. The error code is bX-tjg9ds"&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I also tried to export blogsome posts in atom format, which is supported by google, but no luck, still the same. Then I googled the error and &lt;a href="http://www.manvstech.com/2010/10/overcome-bx-tjg9ds-blogger-import-error.html"&gt;someone has a solution already&lt;/a&gt;!&lt;br /&gt;&lt;br /&gt;You simply go to &lt;a href="http://wordpress2blogger.appspot.com/"&gt;wordpress2blogger conversion tool site&lt;/a&gt;, use "choose file" to upload your feed.xml and click "convert", and then save the result to feed-converted.xml&lt;br /&gt;&lt;br /&gt;&lt;b&gt;3. import feed-converted.xml to Blogger&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;blogger has a &lt;a href="http://www.google.com/support/blogger/bin/answer.py?hl=en&amp;amp;answer=97416"&gt;detailed tutorial&lt;/a&gt; on that already, so I don't want to repeat that. Just follow the instructions there. Unless you need to hide some posts, you should select "automatically publish all imported posts" on the import page.&lt;br /&gt;&lt;br /&gt;That's it, you have a new life on Blogger!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;i&gt;References:&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;a href="http://www.blog-tutorials.com/blog-tutorial/importing-from-blogsome-to-wordpress/"&gt;Tutorial for importing from blogsome to another wordpress site&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.google.com/support/blogger/bin/answer.py?hl=en&amp;amp;answer=97416"&gt;How do I import and export blogs on Blogger&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.manvstech.com/2010/10/overcome-bx-tjg9ds-blogger-import-error.html"&gt;Overcome the bX-tjg9ds Blogger import error&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://wordpress2blogger.appspot.com/"&gt;wordpress to Blogger conversion tool&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-6452637534138798462?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/6452637534138798462/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/move-posts-from-blogsome-to-blogger.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/6452637534138798462'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/6452637534138798462'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/move-posts-from-blogsome-to-blogger.html' title='move posts from blogsome to Blogger'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-896969821745460417</id><published>2010-10-29T22:45:00.046-07:00</published><updated>2010-10-29T22:46:04.110-07:00</updated><title type='text'>Hello world!</title><content type='html'>&lt;p&gt;Welcome to WordPress. This is your first post. Edit or delete it, then start blogging!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-896969821745460417?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/896969821745460417/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/hello-world.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/896969821745460417'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/896969821745460417'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/hello-world.html' title='Hello world!'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-1251504382191189622</id><published>2010-10-29T22:45:00.045-07:00</published><updated>2010-10-29T23:44:24.113-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web Prog.'/><title type='text'>Firefox: 50000000 downloads</title><content type='html'>Firefox is celebrating 50 million downloads now&lt;br /&gt;&lt;br /&gt;I have been using it for a long time now, it is quite neat and fast. You don’t have to worry about IE security holes and non-standard M$ tags anymore.&lt;br /&gt;&lt;br /&gt;BTW, this is a test post using &lt;a href="http://blogjet.com/"&gt;BlogJet&lt;/a&gt;. The only thing I found annoying with this desktop blog publishing tool is that it has poor support for encoding, e.g. I cannot post Simplified Chinese contents&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-1251504382191189622?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/1251504382191189622/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/firefox-50000000.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/1251504382191189622'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/1251504382191189622'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/firefox-50000000.html' title='Firefox: 50000000 downloads'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-8083317487859911932</id><published>2010-10-29T22:45:00.044-07:00</published><updated>2010-10-29T23:39:41.844-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Database'/><title type='text'>check if a database foo exist in MySQL</title><content type='html'>&lt;strong&gt;Problem: I want to see if a database named “foo” exist in MySQL server&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;This should not be a tough problem at first sight. However, I googled the topic and did not find an official answer except several quick&amp;amp;dirty solutions. Please let me know if there are better and clean ways to do it right.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Setup: MySQL v4.1.9 + mysql-connector-java v3.1.6 + J2SE v1.4.2_06&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Solution 1: Catch the exception for “unknown database %s” (I used this one finally).&lt;/u&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;If you create a new Connection to the URL that points to a non-existent database in MySQL, an SQLException is thrown with the message “unknown database %s” where %s is the database name. The exception has error code of 1049 (int) and SQL state of 42000 (String). Check &lt;a href="http://dev.mysql.com/doc/mysql/en/error-handling.html"&gt;MySQL error code list &lt;/a&gt;for the full list of possible errors for MySQL.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;So, I just check the SQLException error code and/or SQL state to make sure this exception happens so that I know a database with the given name exist or not.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #8080c0; font-family: Arial; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; boolean isExistRepos = true;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; connection = DriverManager.getConnection(reposURL, “root”, “rootpassword”);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }catch (SQLException se){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; while(se != null &amp;amp;&amp;amp; isExistRepos){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; String logMessage = “\n\n An SQL Error Occured: “&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; + se.getMessage() + “\n\t”&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; + “Error Code: ” + se.getErrorCode()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; + “\n\t” + “SQLState: “&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; + se.getSQLState() + “\n”;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.err.println(logMessage);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //repos does not exist and the connection cannot set up&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //MySQL error list (&lt;/span&gt;&lt;a href="http://dev.mysql.com/doc/mysql/en/error-handling.html"&gt;&lt;span style="color: #8080c0; font-family: Arial; font-size: x-small;"&gt;http://dev.mysql.com/doc/mysql/en/error-handling.html&lt;/span&gt;&lt;/a&gt;&lt;span style="color: #8080c0; font-family: Arial; font-size: x-small;"&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //#Error: 1049 SQLSTATE: 42000 (ER_BAD_DB_ERROR)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Message: Unknown database ‘%s’&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if((se.getErrorCode() == 1049) &amp;amp;&amp;amp; (se.getSQLState().equalsIgnoreCase(”42000″)))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; isExistRepos = false;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; se = se.getNextException();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Solution 2: Call mysql command line client using Runtime class.&lt;/u&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I did not try it, but here is the general idea. MySQL comes with a command line client program called “mysql” where users can interact with the database server. You can type in “show databases” and a list of existing databases will be presented.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In Java, we can use Runtime.getRuntime().exec(“mysql -u root -p rootpassword”) to get a handle on a Process object, then we can use OutputStream and InputStream to input “show databases” and parse the output to see if the database foo exist in the list of databases.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Solution 3: Check if the directory corresponding to the database exists in MySQL data directory.&lt;/u&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I just found that for each database, there exist a directory with the same name in MySQL data directory, e.g. &lt;em&gt;C:\Program Files\MySQL\MySQL Server 4.1\data&lt;/em&gt; for my case. So, you can juse check if the directory foo exist in that directory to tell if the corresponding database exist or not. I am not sure about MySQL internals, so this solution is not stable and portable.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-8083317487859911932?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/8083317487859911932/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/does-database-foo-exist-in-mysql.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/8083317487859911932'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/8083317487859911932'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/does-database-foo-exist-in-mysql.html' title='check if a database foo exist in MySQL'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-9205340949158027519</id><published>2010-10-29T22:45:00.043-07:00</published><updated>2010-10-29T23:39:19.324-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Database'/><title type='text'>create a new database foo in MySQL using JDBC</title><content type='html'>&lt;strong&gt;Problem: want to create a new database in MySQL using JDBC&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Usually when people work with JDBC, they need a Connection object to the destination database, but since we need to create a new database, where to find an existing connection?&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Setup: MySQL v4.1.9 + mysql-connector-java v3.1.6 + J2SE v1.4.2_06&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Solution 1: Create a Connection to “mysql” admin database and use it to create the new database.&lt;/u&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;There are two preloaded databases when you install MySQL: mysql and test. mysql is the admin database that keeps metadata like access control information. We can just create a Connection object to mysql admin database and use it to create another new database.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Solution 2: Use Runtime.exec(command) to call mysql command line client.&lt;/u&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Solution 3: Create a directory with the same name as the new database name in MySQL data directory&lt;/u&gt;, e.g., C:\Program Files\MySQL\MySQL Server 4.1\data. And MySQL server will “think” a new database is created. This method might have risk of corrupted metadata although I&amp;nbsp;have tried this method before and no abnormal behavior was observed.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-9205340949158027519?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/9205340949158027519/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/how-can-i-create-new-database-foo-in.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/9205340949158027519'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/9205340949158027519'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/how-can-i-create-new-database-foo-in.html' title='create a new database foo in MySQL using JDBC'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-1958263879238720712</id><published>2010-10-29T22:45:00.042-07:00</published><updated>2010-10-29T22:46:03.967-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Modeling'/><title type='text'>Represent inner classes in UML</title><content type='html'>&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;&lt;img alt="" src="http://www.omg.org/images/logos/uml2.gif" border="0" /&gt;&lt;/strong&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;Problem: How to represent inner classes in the class diagram in UML?&lt;/strong&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;I am doing TA for &lt;a href="http://www.soe.ucsc.edu/classes/cmps115/Spring05/"&gt;Software Methodology class &lt;/a&gt;this quarter and we use lots of UML diagrams. When grading students&amp;rsquo; homework, I found this problem about representing inner classes in the class diagram.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;After consulting the UML 1.5 spec and other resources, there are two ways.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;u&gt;Solution 1: (from &lt;/u&gt;&lt;a href="http://www.holub.com/goodies/uml/"&gt;Holub Associates: UML Reference Card&lt;/a&gt;&lt;u&gt;)&lt;/u&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;img alt="" src="http://www.holub.com/goodies/uml/images/nested.gif" align="left" border="0" /&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;!--StartFragment --&gt;&amp;nbsp;&lt;b&gt;Nesting, Inner Class.&lt;/b&gt;. Identifies nesting (containment) relationships in all diagrams. In a class diagram: an &amp;#8220;inner&amp;#8221; class whose definition is nested within the another class definition. Typically puts the inner class in the name space of the outer class. &lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;u&gt;Solution 2: Use a package symbol (from UML 1.5 spec, &lt;/u&gt;&lt;a href="http://www.omg.org/docs/formal/03-03-10.pdf"&gt;chapter 3 UML Notations&lt;/a&gt;&lt;u&gt; (PDF), 3.48.2)&lt;/u&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p align="left"&gt;&amp;ldquo;Note that nested notation is not the correct way to show a class declared within another class. Such a declared class is not a structural part of the enclosing class but merely has scope within the namespace of the enclosing class, which acts like a package toward the inner class. Such a namescope containment may be shown by &lt;strong&gt;placing a package symbol in the upper right corner of the class symbol.&lt;/strong&gt; A tool can allow a user to click on the package symbol to open the set of elements declared within it. &lt;strong&gt;The &amp;ldquo;anchor notation&amp;rdquo; (a cross in a circle on the end of a line)&lt;/strong&gt; may also be used on a line between two class boxes to show that the class with the anchor icon declares the class on the other end of the line.&amp;rdquo;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-1958263879238720712?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/1958263879238720712/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/represent-inner-classes-in-uml.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/1958263879238720712'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/1958263879238720712'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/represent-inner-classes-in-uml.html' title='Represent inner classes in UML'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-5083359262330914480</id><published>2010-10-29T22:45:00.041-07:00</published><updated>2010-10-29T22:46:03.941-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>Using Jakarta Commons CLI</title><content type='html'>&lt;p&gt;&lt;img alt="" src="http://proquest.safaribooksonline.com/images/059600706X/jakartackbk_xs.gif" border="0" /&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Several examples from Jakarta Commons Cookbook by Timothy M. O&amp;rsquo;Brien, O&amp;rsquo;Reilly, Nov 2004&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;&lt;u&gt;Example 1: Parsing a Simple Command Line&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;!--StartFragment --&gt;&lt;font size="2"&gt;&lt;/font&gt;&lt;font face="Garamond"&gt;&lt;b&gt;import org.apache.&lt;font class="docTextHighlight"&gt;commons&lt;/font&gt;.cli.CommandLineParser;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;import org.apache.&lt;font class="docTextHighlight"&gt;commons&lt;/font&gt;.cli.BasicParser;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;import org.apache.&lt;font class="docTextHighlight"&gt;commons&lt;/font&gt;.cli.Options;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;import org.apache.&lt;font class="docTextHighlight"&gt;commons&lt;/font&gt;.cli.CommandLine;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;public static void&lt;/b&gt; main(String[] args) &lt;b&gt;throws&lt;/b&gt; Exception {&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Create a Parser&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CommandLineParser parser = &lt;b&gt;new&lt;/b&gt; BasicParser( );&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Options options = &lt;b&gt;new&lt;/b&gt; Options( );&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; options.addOption(&amp;#8221;h&amp;#8221;, &amp;#8220;help&amp;#8221;, &lt;b&gt;false&lt;/b&gt;, &amp;#8220;Print this usage information&amp;#8221;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; options.addOption(&amp;#8221;v&amp;#8221;, &amp;#8220;verbose&amp;#8221;, &lt;b&gt;false&lt;/b&gt;, &amp;#8220;Print out VERBOSE information&amp;#8221; );&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; options.addOption(&amp;#8221;f&amp;#8221;, &amp;#8220;file&amp;#8221;, &lt;b&gt;true&lt;/b&gt;, &amp;#8220;File to save program output to&amp;#8221;);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Parse the program arguments&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CommandLine commandLine = parser.parse( options, args );&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Set the appropriate variables based on supplied options&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;boolean&lt;/b&gt; verbose = &lt;b&gt;false&lt;/b&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; String file = &amp;#8220;&amp;#8221;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;if&lt;/b&gt;( commandLine.hasOption(&amp;#8217;h') ) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.out.println( &amp;#8220;Help Message&amp;#8221;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.exit(0);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if&lt;/b&gt;( commandLine.hasOption(&amp;#8217;v') ) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; verbose = &lt;b&gt;true&lt;/b&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if&lt;/b&gt;( commandLine.hasOption(&amp;#8217;f') ) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; file = commandLine.getOptionValue(&amp;#8217;f');&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;&lt;u&gt;Example 2: Using OptionGroup&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;!--StartFragment --&gt;&lt;font size="2"&gt;&lt;/font&gt;&lt;font face="Garamond"&gt;&lt;b&gt;import org.apache.&lt;font class="docTextHighlight"&gt;commons&lt;/font&gt;.cli.CommandLineParser;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;import org.apache.&lt;font class="docTextHighlight"&gt;commons&lt;/font&gt;.cli.BasicParser;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;import org.apache.&lt;font class="docTextHighlight"&gt;commons&lt;/font&gt;.cli.Options;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;import org.apache.&lt;font class="docTextHighlight"&gt;commons&lt;/font&gt;.cli.OptionBuilder;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;import org.apache.&lt;font class="docTextHighlight"&gt;commons&lt;/font&gt;.cli.OptionGroup;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;import org.apache.&lt;font class="docTextHighlight"&gt;commons&lt;/font&gt;.cli.CommandLine;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;public&lt;/b&gt; &lt;b&gt;static&lt;/b&gt; &lt;b&gt;void&lt;/b&gt; main(String[] args) &lt;b&gt;throws&lt;/b&gt; Exception {&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Create a Parser&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CommandLineParser parser = &lt;b&gt;new&lt;/b&gt; BasicParser( );&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Options options = &lt;b&gt;new&lt;/b&gt; Options( );&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; options.addOption(&amp;#8221;h&amp;#8221;, &amp;#8220;help&amp;#8221;, &lt;b&gt;false&lt;/b&gt;, &amp;#8220;Print this usage information&amp;#8221;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; options.addOption(&amp;#8221;v&amp;#8221;, &amp;#8220;verbose&amp;#8221;, &lt;b&gt;false&lt;/b&gt;, &amp;#8220;Print out VERBOSE information&amp;#8221; );&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; OptionGroup optionGroup = &lt;b&gt;new&lt;/b&gt; OptionGroup( ); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; optionGroup.addOption( OptionBuilder.hasArg(&lt;b&gt;true&lt;/b&gt;).create(&amp;#8217;f') );&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; optionGroup.addOption( OptionBuilder.hasArg(&lt;b&gt;true&lt;/b&gt;).create(&amp;#8217;m') );&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; options.addOptionGroup( optionGroup );&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Parse the program arguments&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CommandLine commandLine = parser.parse( options, args );&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // &amp;#8230; do important stuff &amp;#8230;&lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;&lt;u&gt;Example 3: Print Usage Info&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;!--StartFragment --&gt;&lt;font size="2"&gt;&lt;/font&gt;&lt;font face="Garamond"&gt;&lt;b&gt;import org.apache.&lt;font class="docTextHighlight"&gt;commons&lt;/font&gt;.cli.CommandLineParser;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;import org.apache.&lt;font class="docTextHighlight"&gt;commons&lt;/font&gt;.cli.BasicParser;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;import org.apache.&lt;font class="docTextHighlight"&gt;commons&lt;/font&gt;.cli.Options;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;import org.apache.&lt;font class="docTextHighlight"&gt;commons&lt;/font&gt;.cli.OptionBuilder;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;import org.apache.&lt;font class="docTextHighlight"&gt;commons&lt;/font&gt;.cli.OptionGroup;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;import org.apache.&lt;font class="docTextHighlight"&gt;commons&lt;/font&gt;.cli.CommandLine;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;import org.apache.&lt;font class="docTextHighlight"&gt;commons&lt;/font&gt;.cli.HelpFormatter;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;public class SomeApp {&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static final String USAGE = &amp;#8220;[-h] [-v] [-f &amp;lt;file&amp;gt; | -m &amp;lt;email&amp;gt;]&amp;#8221;;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static final String HEADER =&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#8220;SomeApp - A fancy and expensive program, Copyright 2010 Blah.&amp;#8221;;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static final String FOOTER =&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#8220;For more instructions, see our website at: http://www.blah123.org&amp;#8221;;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public&lt;/b&gt; &lt;b&gt;static&lt;/b&gt; &lt;b&gt;void&lt;/b&gt; main(String[] args) &lt;b&gt;throws&lt;/b&gt; Exception {&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Create a Parser&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CommandLineParser parser = &lt;b&gt;new&lt;/b&gt; BasicParser( );&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Options options = &lt;b&gt;new&lt;/b&gt; Options( );&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; options.addOption(&amp;#8221;h&amp;#8221;, &amp;#8220;help&amp;#8221;, &lt;b&gt;false&lt;/b&gt;, &amp;#8220;Print this usage &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; information&amp;#8221;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; options.addOption(&amp;#8221;v&amp;#8221;, &amp;#8220;verbose&amp;#8221;, &lt;b&gt;false&lt;/b&gt;, &amp;#8220;Print out VERBOSE &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; information&amp;#8221; );&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; OptionGroup optionGroup = new OptionGroup( ); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; optionGroup.addOption( OptionBuilder.hasArg(true).withArgName(&amp;#8221;file&amp;#8221;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .withLongOpt(&amp;#8221;file&amp;#8221;).create(&amp;#8217;f') );&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; optionGroup.addOption( OptionBuilder.hasArg(true).withArgName(&amp;#8221;email&amp;#8221;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .withLongOpt(&amp;#8221;email&amp;#8221;).create(&amp;#8217;m') );&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; options.addOptionGroup( optionGroup );&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Parse the program arguments&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CommandLine commandLine = parser.parse( options, args );&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;if&lt;/b&gt;( commandLine.hasOption(&amp;#8217;h') ) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; printUsage( options );&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.exit(0);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // &amp;#8230; do important stuff &amp;#8230;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } catch( Exception e ) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.out.println( &amp;#8220;You provided bad program arguments!&amp;#8221; );&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; printUsage( options );&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.exit(1);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private&lt;/b&gt; static &lt;b&gt;void&lt;/b&gt; printUsage(Options options) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; HelpFormatter helpFormatter = &lt;b&gt;new&lt;/b&gt; HelpFormatter( );&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; helpFormatter.setWidth( 80 );&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; helpFormatter.printHelp( USAGE, HEADER, options, FOOTER );&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-5083359262330914480?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/5083359262330914480/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/using-jakarta-commons-cli.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/5083359262330914480'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/5083359262330914480'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/using-jakarta-commons-cli.html' title='Using Jakarta Commons CLI'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-3487061477399232025</id><published>2010-10-29T22:45:00.040-07:00</published><updated>2010-10-29T22:46:03.912-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Configuraiton Management'/><title type='text'>About BitKeeper not free anymore</title><content type='html'>&lt;p&gt;Recently, I am working on an assessment paper about various existing SCM systems. Basically, we see feature comparison matrices all the time as the marketing tool to sell SCM-X, however people general don&amp;rsquo;t explicitly state the scenarios for the feature comparisons. For example, you can claim SCM-X does commits 20% faster than SCM-Y, but how big is the commit size, change size, etc., are not clearly explained. We want to fill the void.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Back to the topic, the reading about BitKeeper starts from its feature comparison matrix with Subversion: &lt;a href="http://www.bitkeeper.com/Comparisons.Subversion.html"&gt;http://www.bitkeeper.com/Comparisons.Subversion.html&lt;/a&gt;. Then, on Subversion site, developers jumped out and tried to debunk BitKeeper&amp;rsquo;s false claim: &lt;a href="http://subversion.tigris.org/bitmover-svn.html"&gt;http://subversion.tigris.org/bitmover-svn.html&lt;/a&gt;. Then it turned out that BitMover, BitKeeper&amp;rsquo;s company&amp;nbsp;is going to &lt;a href="http://kerneltrap.org/node/4966"&gt;withdraw this free product &lt;/a&gt;because of many attempts of reverse-engineering in open-source world. Although &lt;a href="http://kerneltrap.org/node/4968"&gt;Linus himself enjoyed a lot using BitKeeper &lt;/a&gt;for kernel development, it will happen soon and kerneltrap.org has a detailed coverage about that, also Linus&amp;rsquo;s original email. Apparently, &lt;a href="http://kerneltrap.org/node/4968"&gt;Linus does not like Subversion at all &lt;/a&gt;(P.S. part) and Karl Fogel, on behalf of the Subversion team, &lt;a href="http://subversion.tigris.org/subversion-linus.html" target="_blank"&gt;reponded to Linus&amp;rsquo; comments on Subversion&lt;/a&gt;.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Watching a war like this quite fresh experience for me: previously I thought all those open-source developers are shy, gentle, silient people with long hair or no hair. Well, it is my first time watching the flames between them.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Interestingly enough, there is a survey about &amp;ldquo;my favorite FOSS source control system&amp;rdquo; at the side bar of the &lt;a href="http://kerneltrap.org/node/4966"&gt;editorial&lt;/a&gt;.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Total votes: 2393&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Subversion: 37%&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;CVS: 24%&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Darcs: 10%&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Depends on project: 7%&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;GNU Arch: 6%, not listed: 6%&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Bazaar-NG: 3%&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Bazaar: 1%&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Vesta: 0%, Codeville: 0%&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-3487061477399232025?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/3487061477399232025/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/about-bitkeeper-not-free-anymore.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/3487061477399232025'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/3487061477399232025'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/about-bitkeeper-not-free-anymore.html' title='About BitKeeper not free anymore'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-925670038208238475</id><published>2010-10-29T22:45:00.039-07:00</published><updated>2010-10-29T23:37:54.447-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Configuraiton Management'/><title type='text'>Subversion experience</title><content type='html'>&amp;nbsp;&lt;strong&gt;&lt;a href="http://www.chiark.greenend.org.uk/~sgtatham/svn.html" target="_blank"&gt;My Experiences With Subversion &lt;/a&gt;&lt;/strong&gt;&lt;em&gt;by &lt;/em&gt;&lt;a href="http://pobox.com/%7Eanakin/"&gt;&lt;em&gt;Simon Tatham&lt;/em&gt;&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;strong&gt;&amp;nbsp;1. Introduction&lt;/strong&gt;&lt;/u&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;When I’m not at work, I’m a free software developer. I maintain a variety of published projects, ranging from fairly major things like &lt;a href="http://www.chiark.greenend.org.uk/%7Esgtatham/putty/"&gt;PuTTY&lt;/a&gt; to tiny little &lt;a href="http://www.chiark.greenend.org.uk/%7Esgtatham/utils/"&gt;Unix utilities&lt;/a&gt;; and I have almost as wide a variety of unpublished projects as well, ranging from half-finished major programs to my personal &lt;code&gt;.bashrc&lt;/code&gt;. Until November 2004, all these projects were stored in CVS, along with probably 90% of the other free software in the world. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Then I migrated to &lt;a href="http://subversion.tigris.org/"&gt;Subversion&lt;/a&gt;. This took a fair amount of thought and effort to do well, and shortly afterwards I was asked by a colleague if I could write something about my experiences. He was probably expecting something more like a couple of paragraphs, but I thought, hey, why not do the job right? &lt;img alt=":-)" class="wp-smiley" src="http://woshiadai.blogsome.com/wp-images/smilies/icon_smile.gif" /&gt;  &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;This article is not a rant. In general, I have found Subversion to be linearly superior to CVS and I certainly don’t regret migrating to it. The article is just an attempt to share my experiences: things to watch out for, how to get the most out of Subversion, that sort of thing. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.chiark.greenend.org.uk/~sgtatham/svn.html"&gt;More &amp;gt;&amp;gt;&amp;gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-925670038208238475?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/925670038208238475/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/subversion-experience-report-by-simon.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/925670038208238475'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/925670038208238475'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/subversion-experience-report-by-simon.html' title='Subversion experience'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-3079519478526962886</id><published>2010-10-29T22:45:00.038-07:00</published><updated>2010-10-29T22:46:03.857-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Configuraiton Management'/><title type='text'>BitKeeper Testdrive</title><content type='html'>&lt;p&gt;&lt;a href="http://www.bitkeeper.com/Test.html"&gt;BitKeeper test drive documentation&lt;/a&gt; from their website.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;a href="http://xaxxon.slackworks.com/"&gt;A discontinued tutorial for BitKeeper&lt;/a&gt; by &lt;a href="http://xaxxon.slackworks.com/"&gt;Zac&lt;/a&gt;, it is quite interesting to see the reason for discontinuing the tutorial writing:&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&amp;#8220;(DISCONTINUED) A guide for starting into the world of Bit Keeper, a really cool source control system. This is the document I wish I had when I was getting started.. [UPDATE] Cancelled to do me finding out what the company behind the product is really like. Too bad, because it seems like it&amp;#8217;s actually a pretty good product.&amp;#8221;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;I think sometimes people enjoy free lunches should not blame too much for not having free lunches suddenly. Everyone has family to support and needs money. But I would rather say at the very beginning clearly rather than giving the impression that I want to make money from the user base which were attracted because of the free services.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-3079519478526962886?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/3079519478526962886/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/bitkeeper-testdrive.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/3079519478526962886'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/3079519478526962886'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/bitkeeper-testdrive.html' title='BitKeeper Testdrive'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-1843288974208666601</id><published>2010-10-29T22:45:00.037-07:00</published><updated>2010-10-29T22:46:03.836-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web Prog.'/><title type='text'>Notes for by Craig Grannell</title><content type='html'>&lt;p&gt;&lt;strong&gt;1. CSS shorthand for boxes:&lt;/strong&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;margin: 10px                                        &amp;#8212; applies to all edges&lt;br/&gt;margin: 10px, 20px                          &amp;#8212; 10px applies to the top and bottom edges; 20px applies to left and right edges&lt;br/&gt;margin: 10px, 20px, 30px                &amp;#8212; 10px applies to the top, 20px to the left and right, 30px to the bottom&lt;br/&gt;margin: 10px, 20px, 30px, 40px  &amp;#8212; clockwise order starting from the top (top, right, bottom, and left)&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;2. Applying styles to a Web page:&lt;/strong&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;a) use a link tag:&lt;br/&gt;[link rel=&amp;#8221;stylesheet&amp;#8221; type=&amp;#8221;text/css&amp;#8221; href=&amp;#8221;mystylesheet.css&amp;#8221; /]&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;b) use import:&lt;br/&gt;[style type=&amp;#8221;text/css&amp;#8221;]&lt;br/&gt;@import url(mystylesheet.css);&lt;br/&gt;[/style]&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;c) embed styles in HTML document:&lt;br/&gt;[head]&lt;br/&gt;[style type=&amp;#8221;text/css&amp;#8221; media=&amp;#8221;all&amp;#8221;]&lt;br/&gt;p{&lt;br/&gt;color: black;&lt;br/&gt;}&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;h1&gt;navigation p{&lt;/h1&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;color: blue;&lt;br/&gt;font-weight: bold;&lt;br/&gt;font-size: 120%;&lt;br/&gt;}&lt;br/&gt;[/style]&lt;br/&gt;[/head]&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;d) inline styles:&lt;br/&gt;[p style=&amp;#8221;color: red;&amp;#8221;]This is painted in Red.[/p]&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;3. DOCTYPE declarations:&lt;/strong&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;a) XHTML strict:&lt;br/&gt;[!DOCTYPE html PUBLIC &amp;#8220;-//W3C//DTD XHTML 1.0 Strict//EN&amp;#8221;&lt;br/&gt;        &amp;#8220;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&amp;#8221;]&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;b) XHTML transitional: good for depreciated tags&lt;br/&gt;[!DOCTYPE html PUBLIC &amp;#8220;-//W3C//DTD XHTML 1.0 Transitional//EN&amp;#8221;&lt;br/&gt;        &amp;#8220;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&amp;#8221;]&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;c) XHTML frameset: &lt;br/&gt;[!DOCTYPE html PUBLIC &amp;#8220;-//W3C//DTD XHTML 1.0 Frameset//EN&amp;#8221;&lt;br/&gt;        &amp;#8220;http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd&amp;#8221;]&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;4. Go to top of a page:&lt;/strong&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;a) [a id=&amp;#8221;top&amp;#8221; name=&amp;#8221;top&amp;#8221;][/a]&lt;br/&gt;   [a href=&amp;#8221;#top&amp;#8221;]Back to top[/a]&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;b) some browsers ignore empty elements, so we need to put a single&lt;br/&gt;space in between; if we use XHTML Strict, we need to put elements into&lt;br/&gt;a block element such as [p] or [div].&lt;br/&gt;   [div id=&amp;#8221;topOfPageAnchor&amp;#8221;]&lt;br/&gt;   [a id=&amp;#8221;top&amp;#8221; name=&amp;#8221;top&amp;#8221;] [/a][/div]&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;define CSS&lt;br/&gt; div#topOfPageAnchor{&lt;br/&gt; position: absolute;&lt;br/&gt; top: 0;&lt;br/&gt; left: 0;&lt;br/&gt; height: 0;&lt;br/&gt; }&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;c) use Javascript:&lt;br/&gt;   [div id=&amp;#8221;topOfPageAnchor&amp;#8221;]&lt;br/&gt;   [a id=&amp;#8221;top&amp;#8221; name=&amp;#8221;top&amp;#8221;] [/a][/div]&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;[a href=&amp;#8221;#top&amp;#8221; onclick=&amp;#8221;javascript: scrollTo(0,0);&amp;#8221;]Top of page[/a]&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;5. Attaching Javascript:&lt;/strong&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;a) External&lt;br/&gt;[script type=&amp;#8221;text/javascript&amp;#8221; src=&amp;#8221;javascriptfile.js&amp;#8221;][/script]&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;b) Internal&lt;br/&gt;[script type=&amp;#8221;text/javascript&amp;#8221;] script content [/script]&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;6. Toggling div visibility with Javascript:&lt;/strong&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;function swap(targetID){&lt;br/&gt;    if(document.getElementByID){&lt;br/&gt;        target = document.getElementById(targetId);&lt;br/&gt;        if(target.style.display == &amp;#8220;none&amp;#8221;){&lt;br/&gt;            target.style.display == &amp;#8220;block&amp;#8221;;&lt;br/&gt;        }else{&lt;br/&gt;            target.style.display == &amp;#8220;none&amp;#8221;;&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;}&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;[div][a href=&amp;#8221;#&amp;#8221; title=&amp;#8221;show text&amp;#8221; onclick=&amp;#8221;swap(&amp;#8217;hiddenDiv&amp;#8217;);return false;&amp;#8221;]show text[/a][/div]&lt;br/&gt;[div id=&amp;#8221;hiddenDiv&amp;#8221; style=&amp;#8221;display: none;&amp;#8221;][p]hello[/p][/div]&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;7. pseudo-class selectors:&lt;/strong&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;For anchors&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;a{color: #3366cc;}&lt;br/&gt;a:link{color: #3366cc;}&lt;br/&gt;a:visited{color:#777700;}&lt;br/&gt;a:active{color:#cc00ff;}&lt;br/&gt;a:hover{color:#0066ff;}&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;h1&gt;Useful resources:&lt;/h1&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;a href="http://centricle.com/ref/css/filters/"&gt;CSS hacks for different Web browsers&lt;/a&gt; &lt;br/&gt;&lt;a href="http://validator.w3.org/"&gt;W3C Markup Validation&lt;/a&gt;&lt;br/&gt;&lt;a href="http://validator.w3.org/checklink"&gt;W3C Link Checker&lt;/a&gt;&lt;br/&gt;&lt;a href="http://jigsaw.w3.org/css-validator/"&gt;W3C CSS Validation&lt;/a&gt;&lt;br/&gt;&lt;a href="http://www.danvine.com/icapture/"&gt;iCapture shows your page in Safari&lt;/a&gt;&lt;br/&gt;&lt;a href="http://www.csszengarden.com/"&gt;CSS switcher demo&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-1843288974208666601?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/1843288974208666601/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/notes-for-by-craig-grannell.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/1843288974208666601'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/1843288974208666601'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/notes-for-by-craig-grannell.html' title='Notes for by Craig Grannell'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-2189290582704899328</id><published>2010-10-29T22:45:00.036-07:00</published><updated>2010-10-29T22:46:03.784-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Configuraiton Management'/><title type='text'>Experiment with Perforce</title><content type='html'>&lt;p&gt;&lt;img src="http://www.perforce.com/images/logo.gif" alt=""  /&gt;&lt;br/&gt;&lt;a href="http://www.perforce.com/" target="_blank"&gt;Perforce&lt;/a&gt; is one of the popular SCM system used by many IT companies. It uses RCS ,v file format for history archive file. The network communication model is client/server over TCP/IP. I am not sure about the detailed protocol Perforce uses.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Some quick points after reading Perforce user guide and administration guide:&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;ul&gt;&lt;br/&gt;&lt;li&gt;&lt;br/&gt;1)  Configuration and setup is a bit complicated. The document is not very straightforward about the setup process, meaning of basic concepts and usage of the environment variables. After reading the whole user guide, you finally get the basic ideas about various elements of Perforce and how they should be used, but not at the very beginning. &lt;br/&gt;&lt;/li&gt;&lt;br/&gt;&lt;li&gt;&lt;br/&gt;2)  Too many commands and options. There are just too many commands and options to get a job done. And the worst part is that some commands have different names from CVS&amp;rsquo;s or Subversion&amp;rsquo;s commands, which are well-known to SCM users. Perforce also uses their own terms for well-understood concepts, e.g. integrate v.s. merge.&lt;br/&gt;&lt;/li&gt;&lt;br/&gt;&lt;li&gt;&lt;br/&gt;3)  Perforce provides support for a wide range of platforms and offers multi-language API for 3rd-party developers. The Web client interface is really cool and it should save a lot of time for beginners.&lt;br/&gt;&lt;/li&gt;&lt;br/&gt;&lt;li&gt;&lt;br/&gt;4)  Perforce reuses RCS history archive file format and maybe this is why it does not support directory versioning.&lt;br/&gt;&lt;/li&gt;&lt;br/&gt;&lt;li&gt;&lt;br/&gt;5)  Internally, Perforce keeps a mapping between file extension and file type to distinguish binary and text files. Binary files are stored in whole while text files are stored in deltas.&lt;br/&gt;&lt;/li&gt;&lt;br/&gt;&lt;li&gt;&lt;br/&gt;6)  Transaction is well supported in Perforce. Either all changed files get submitted in a changelist or none of them.&lt;br/&gt;&lt;/li&gt;&lt;br/&gt;&lt;li&gt;&lt;br/&gt;7)  Branching is basically copy operation, and Perforce can keep track of the branching internally so that the history information is preserved.&lt;br/&gt;&lt;/li&gt;&lt;br/&gt;&lt;li&gt;&lt;br/&gt;8)  In Perforce, a job records what needs to be done and a changelist stores the actual changes. They can be linked to represent the scenario of a bug report and how the bug is fixed.&lt;br/&gt;&lt;/li&gt;&lt;br/&gt;&lt;/ul&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Concepts in Perforce:&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;Depot&lt;/strong&gt;: repository on Perforce server, it is a directory called &amp;ldquo;depot&amp;rdquo; in the perforce root directory on the server.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;Workspace&lt;/strong&gt;: isolated place where users get their job done. Users define a mapping between depot directory structure and workspace directory structure.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;View&lt;/strong&gt;: a mapping between files in depot and files in workspace.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;Changelist&lt;/strong&gt;: similar in spirit to the changeset concept. It records changes made as a transaction. There is a default changelist and users can define individual chagnelist called &amp;ldquo;numbered changelist&amp;rdquo; as well.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;Job&lt;/strong&gt;: a description of problems that should be solved, e.g. a bug report. Jobs are linked to changelists that actually make changes happen and fix the problems.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;Label&lt;/strong&gt;: similar to label in RCS, CVS and Subversion. Use label to make logic group of file, e.g. alpha release, bug fix, etc.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;Branch&lt;/strong&gt;: copy of files at a different directory. There are two approaches for branching: based on file specifications (from-files to-files) or branch specifications (name the branch mapping).&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;a href="http://www.perforce.com/perforce/doc.051/manuals/p4guide/index.html" target="_blank"&gt;Perforce User Guide (2005.1)&lt;/a&gt;Perforce User Guide (2005.1)&lt;br/&gt;&lt;a href="http://www.perforce.com/perforce/doc.051/manuals/p4sag/index.html"&gt;Perforce Admin Guide&lt;/a&gt;Perforce Admin Guide&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-2189290582704899328?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/2189290582704899328/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/experiment-with-perforce.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/2189290582704899328'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/2189290582704899328'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/experiment-with-perforce.html' title='Experiment with Perforce'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-2529867963751856021</id><published>2010-10-29T22:45:00.035-07:00</published><updated>2010-10-29T23:38:51.910-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Modeling'/><title type='text'>MDA and Software Factories</title><content type='html'>I just read some recent articles and literatures about the idea of “building software at a higher level (than raw source code)” such as MDA, software workbench, software factories, etc. It seems like people are starting or have started (e.g. tools like OptimalJ from Compuware) using models as an efficient way of building software and leave the complexity issues to automation (as much as possible). Also, it appears to me that domain specific languages might appear as the major programming languages for specific domains. Actually, lots of XML documents have been serving as configuration files, preferences and options for quite some time, those in some sense are DSLs too. &lt;br /&gt;&lt;br /&gt;Here are some interesting projects and articles from Eclipse and VS.NET 2005: &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img alt="" border="0" src="http://www.eclipse.org/images/EclipseBannerPic.jpg" /&gt;&lt;br /&gt;1) EMF+GEF+GMF: those are the modeling frameworks in Eclipse. EMF is quite similar in spirit to MDA proposed by OMG, GEF provides the framework to write graphical editors for editing EMF models. GMF (&lt;a class="moz-txt-link-freetext" href="http://www.eclipse.org/gmf/"&gt;http://www.eclipse.org/gmf/&lt;/a&gt;) is a newly proposed project that aims to add automatic generation of GEF editors for EMF models, which bridges the gap between EMF and GEF. &lt;br /&gt;&lt;br /&gt;2) Other MDA-related projects at Eclipse: GMT (&lt;a class="moz-txt-link-freetext" href="http://www.eclipse.org/gmt/"&gt;http://www.eclipse.org/gmt/&lt;/a&gt;) is a set of research tools for generative model transformation. This one seems quite interesting because we are thinking about model transformation as well for our wizard-based design tools.MDDi (&lt;a class="moz-txt-link-freetext" href="http://www.eclipse.org/proposals/eclipse-mddi/index.html"&gt;http://www.eclipse.org/proposals/eclipse-mddi/index.html&lt;/a&gt;) seems quite intersting as well, but it is also in its infancy. &lt;br /&gt;&lt;img alt="" border="1" src="http://lab.msdn.microsoft.com/teamsystem/art/factory150.gif" /&gt;&lt;br /&gt;3) MS has been pushing about software modeling in VS.NET 2005 and there are ideas and tools about “software factotires” (&lt;a class="moz-txt-link-freetext" href="http://lab.msdn.microsoft.com/teamsystem/workshop/sf/default.aspx"&gt;http://lab.msdn.microsoft.com/teamsystem/workshop/sf/default.aspx&lt;/a&gt;). They have a series of articles about software factories by Jack Greenfield. He also wrote a book (&lt;a class="moz-txt-link-freetext" href="http://www.wiley.com/WileyCDA/WileyTitle/productCd-0471202843.html"&gt;http://www.wiley.com/WileyCDA/WileyTitle/productCd-0471202843.html&lt;/a&gt;).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-2529867963751856021?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/2529867963751856021/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/interesting-links-about-mda-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/2529867963751856021'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/2529867963751856021'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/interesting-links-about-mda-and.html' title='MDA and Software Factories'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-3556193654083899923</id><published>2010-10-29T22:45:00.034-07:00</published><updated>2010-10-29T22:46:03.707-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Modeling'/><title type='text'>A quick comparison of UML 1.4 and 2.0</title><content type='html'>&lt;p&gt;From &lt;strong&gt;&lt;a href=\"http://www.amazon.com/exec/obidos/tg/detail/-/0764526049/102-1470263-0979341?v=glance\"&gt;UML Bible by Tom Pender&lt;/a&gt;&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&amp;ldquo;The UML authors of both 1.4 and 2.0 endeavored to uphold the four-layer meta-model (M0&amp;ndash;M3) architecture, an approach that supports the distribution of concepts across many levels of abstraction. The layering supports the specification of concepts for different purposes such as object modeling (UML) and data modeling (CWM), customization for different domains, and ultimately for different implementations.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;In the UML 1.4 architecture:&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;ul&gt;&lt;br/&gt;&lt;li&gt;The MOF provides the foundation for the UML&lt;/li&gt;&lt;br/&gt;&lt;li&gt;The UML defines a Foundation package as well as the Behavioral and Model Management features. Together these packages define all of the essential features needed to create the modeling elements used to build UML diagrams.&lt;/li&gt;&lt;/ul&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;In the UML 2.0 architecture:&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;ul&gt;&lt;br/&gt;&lt;li&gt;The new architecture defines an Infrastructure and a Superstructure&lt;/li&gt;&lt;br/&gt;&lt;li&gt;The Infrustructure redefines the highest level of the architecture used to create the MOF and all other MDA components.&lt;/li&gt;&lt;br/&gt;&lt;li&gt;The Superstructure is the UML portion of the architecture. The Superstructure derives all of its components from both the Infrastructure and the MOF.&lt;/li&gt;&lt;br/&gt;&lt;li&gt;The Superstructure is organized according to the three types of diagrams defined by UML, that is structural (Class, Object, and so on), behavioral (Sequence, Timing, State Machine, and the like), and supplemental (information flows, profiles, and templates).&lt;/li&gt;&lt;/ul&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Diagram changes from 1.4 to 2.0:&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;ul&gt;&lt;br/&gt;&lt;li&gt;2.0 replaced the Collaboration diagram with a more limited Communication diagram.&lt;/li&gt;&lt;br/&gt;&lt;li&gt;2.0 added two new interaction diagrams: the Interaction Overview diagram and the Timing diagram.&lt;/li&gt;&lt;br/&gt;&lt;li&gt;2.0 added the Protocol State Machine.&lt;/li&gt;&lt;br/&gt;&lt;li&gt;2.0 added the Composite Structure diagram&lt;/li&gt;&lt;br/&gt;&lt;li&gt;2.0 isolated the Activity diagram with its own semantics separate from the State Machine.&amp;rdquo;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-3556193654083899923?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/3556193654083899923/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/quick-comparison-of-uml-14-and-20.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/3556193654083899923'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/3556193654083899923'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/quick-comparison-of-uml-14-and-20.html' title='A quick comparison of UML 1.4 and 2.0'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-5480344711361727271</id><published>2010-10-29T22:45:00.033-07:00</published><updated>2010-10-29T22:46:03.667-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Requirement Engineering'/><title type='text'>Requirment Management Tools</title><content type='html'>&lt;p&gt;From a Gartner report: &lt;em&gt;Agile Requirements Definition and Management Will Benefit Application Development&lt;/em&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Principal Tools:&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;ul&gt;&lt;br/&gt;&lt;li&gt;&lt;a href="http://www-306.ibm.com/software/awdtools/reqpro/" target="_blank"&gt;IBM Rational RequisitePro&lt;/a&gt;&lt;/li&gt;&lt;br/&gt;&lt;li&gt;&lt;a href="http://www.borland.com/us/products/caliber/index.html" target="_blank"&gt;Borland CaliberRM&lt;/a&gt;&lt;/li&gt;&lt;br/&gt;&lt;li&gt;&lt;a href="http://www.serena.com/Products/rtm/home.asp" target="_blank"&gt;Serena Requirements &amp;amp; Traceability Management&lt;/a&gt;&lt;/li&gt;&lt;br/&gt;&lt;li&gt;&lt;a href="http://www.telelogic.com/corp/products/doors/doors/" target="_blank"&gt;Telelogic Doors&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Less Known Tools:&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;ul&gt;&lt;br/&gt;&lt;li&gt;Apptero &amp;ndash; Apptero 2004&lt;/li&gt;&lt;br/&gt;&lt;li&gt;Axure Software Solutions Rapid Prototyper&lt;/li&gt;&lt;br/&gt;&lt;li&gt;Compuware Reconcile (with QACenter, DevPartner)&lt;/li&gt;&lt;br/&gt;&lt;li&gt;Goda Software Analyst Pro&lt;/li&gt;&lt;br/&gt;&lt;li&gt;&lt;a href="http://www.irise.com/" target="_blank"&gt;iRise Application Simulator&lt;/a&gt;&lt;/li&gt;&lt;br/&gt;&lt;li&gt;MKS Requirements 2005 (with Integrity Manager)&lt;/li&gt;&lt;br/&gt;&lt;li&gt;&lt;a href="http://www.sofeainc.com/product_overview.htm" target="_blank"&gt;Sofea Profesy&lt;/a&gt;&lt;/li&gt;&lt;br/&gt;&lt;li&gt;SpeeDev &amp;ndash; SpeeDev RM&lt;/li&gt;&lt;br/&gt;&lt;li&gt;SteelTrace Catalyze&lt;/li&gt;&lt;br/&gt;&lt;li&gt;TCP Integral Requisite Analyzer&lt;/li&gt;&lt;/ul&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Others:&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;ul&gt;&lt;br/&gt;&lt;li&gt;3SL Cradle&lt;/li&gt;&lt;br/&gt;&lt;li&gt;UGS Teamcenter&lt;/li&gt;&lt;br/&gt;&lt;li&gt;ViewSet Pace&lt;/li&gt;&lt;br/&gt;&lt;li&gt;Vitech Core&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-5480344711361727271?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/5480344711361727271/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/requirment-management-tools.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/5480344711361727271'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/5480344711361727271'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/requirment-management-tools.html' title='Requirment Management Tools'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-633197123200166236</id><published>2010-10-29T22:45:00.032-07:00</published><updated>2010-10-29T23:39:58.959-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Requirement Engineering'/><title type='text'>requirement engineering tools</title><content type='html'>&lt;strong&gt;iRise&lt;/strong&gt;&lt;br /&gt;-iRise Studio: requirement development environment&lt;br /&gt;-iRise Manager: middleware to manage requirements&lt;br /&gt;-iRise Reader: client&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;&lt;strong&gt;RequisitePro&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;-Dynamic integration between Word and requirement database&lt;br /&gt;-Integration with other IBM software development tools, for coding, testing, and mantanence&lt;br /&gt;-Distributed access to requirement repository (not sure about the detailed mechanisms)&lt;br /&gt;-Traceability and coverage analysis (among requirements)&lt;br /&gt;-Impact of requirement changes (among requirements)&lt;br /&gt;-Query capabilities based on attributes&lt;br /&gt;-Requirement audit trail&lt;br /&gt;-Central requirement repos&lt;br /&gt;-Controlled access to repos&lt;br /&gt;-Customizalbe requirement structure (define requirement types, each type has a unique set of atts)&lt;br /&gt;-Requirement project templates (not sure what is diff with req types) &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;RequisitePro has several ways to edit requirements:&lt;br /&gt;1) Use Word plugin: insert new requirements directly by selecting the plugin toolbar or the right-click menu.&lt;br /&gt;2) use requirement editor &lt;br /&gt;3) use requirement viewer&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Because all requirements are stored in the database, searching and revision control have been taken care of easily.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Coverage anaylysis uses queries to create views that shows the relationship between requirements, requirement and&lt;br /&gt;use cases, etc.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Change impact analysis: my understanding of how this works. Links are set up between a requirement and a use case,&lt;br /&gt;for example. When the text of the requirement changes, the link will be marked as a suspect link.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;RequisiteWeb: a web interface to the requisitePro&lt;br /&gt;see demo (&lt;a href="http://www3.software.ibm.com/ibmdl/pub/software/rational/web/demos/viewlets/reqpro/RequisiteWeb_V2002_viewlet.html"&gt;http://www3.software.ibm.com/ibmdl/pub/software/rational/web/demos/viewlets/reqpro/RequisiteWeb_V2002_viewlet.html&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In RequisitePro we can create four types of items:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;1)Package: just like a folder to group things together&lt;br /&gt;2)Document: 5 templates are provided: glossary, requirement management plan, supplementary requirement specification,&lt;br /&gt;use case specification, vision&lt;br /&gt;3)View: attribute matrix, traceability matrix, traceability tree (in or out)&lt;br /&gt;4)Requirement: can have the attributes of type, priority, status, difficulty, stability, origin, contact, enhancement-request&lt;br /&gt;defect (the last two are connected with clearquest tool)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;&lt;strong&gt;CaliberRM from Borland&lt;/strong&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://info.borland.com/techpubs/caliber_rm/"&gt;http://info.borland.com/techpubs/caliber_rm/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;features and functions are quite similar to RequisitePro&lt;br /&gt;It has a document factory to generate Word document from Word templates. &lt;br /&gt;Import and export of project data support many different formats like Word doc, ASCII files, etc.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Requirement types and attributes can be customized.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Advanced version history and traceability, integrates with SCM tools like Borland StarTeam, Merant PVCS, Microsoft SourceSafe,&lt;br /&gt;Rational ClearCase.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The tool integrtes with a line of Borland requirement engineering tools, e.g. estimate professional for workload/cost estimation,&lt;br /&gt;datamart+BusinessObjects for advanced query/analysis to support decision making process, &lt;br /&gt;Mercury quality center/testDirector.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;&lt;strong&gt;Telelogic DOORS&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;1)DOORS:&lt;br /&gt;2)DOORS XT: distributed requirement management&lt;br /&gt;3)DOORS/Analyst: using UML diagrams to draw requirement models, a visual modeling environment&lt;br /&gt;4)DOORSnet: enable Web access to the requirement management functions&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;DOORS:&lt;br /&gt;=change tracking&lt;br /&gt;=traceability&lt;br /&gt;=scalability&lt;br /&gt;=inherant small-scale test environment, integration with Mercury quality center/testDirectory for large-scale testing&lt;br /&gt;=integration with other telelogic products&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;&lt;strong&gt;Serena Requirements Traceability Management(RTM)&lt;/strong&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Requirements authoring using Word, or visual models defined using Serena Composer, or Wb client&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;A&amp;nbsp;uniqe polling feature that allows people to vote to make decisions&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Built on Oracle DB&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;On-line ability to collaborate, in real-time with live data while keeping a history of that collaboration.&lt;/li&gt;&lt;li&gt;A true data repository that provides full traceability; with no ‘limitations’ or special proprietary scripting languages&lt;/li&gt;&lt;li&gt;User interfaces, Word and Web, that are industry standards and commonly used in every organization&lt;/li&gt;&lt;li&gt;The hybrid capability of viewing requirements data in both document form and object form&lt;/li&gt;&lt;li&gt;True baselining and versioning capability with full history of all changes&lt;/li&gt;&lt;li&gt;User designed forms to capture and manage any engineering information such as defects, enhancement requests and change requests, to name a few&lt;/li&gt;&lt;li&gt;icAdvisor for requirements correctness&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;&lt;strong&gt;Documents and Papers&lt;/strong&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Increasing Business/IT Relevance and Adaptability: Adopting Requirements Visualization&lt;br /&gt;(a META Group White Paper)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;META group estimates that 60%-80% of project failures can be attributed directly to poor &lt;br /&gt;requirements gathering, analysis, and management.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-633197123200166236?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/633197123200166236/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/quick-notes-for-requirement-engineering.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/633197123200166236'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/633197123200166236'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/quick-notes-for-requirement-engineering.html' title='requirement engineering tools'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-7464144402830652322</id><published>2010-10-29T22:45:00.031-07:00</published><updated>2010-10-29T22:46:03.608-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web Prog.'/><title type='text'>config Tomcat for JNDI</title><content type='html'>&lt;p&gt;Had a hard time configuring Tomcat to use JNDI to access MySQL, here is how to do it. Basically, we need to add a datasource resource, then define a resource link in server.xml.&lt;br/&gt;&lt;server&gt;&lt;br/&gt;  &amp;#8230;&lt;br/&gt;  &lt;globalnamingresources&gt;&lt;br/&gt;    &amp;#8230;&lt;br/&gt;    &lt;resource name="jdbc/testdb"&lt;br/&gt;      type="javax.sql.DataSource"&lt;br/&gt;      password="1234ge"&lt;br/&gt;      driverClassName="com.mysql.jdbc.Driver"&lt;br/&gt;      maxIdle="2"&lt;br/&gt;      maxWait="5000"&lt;br/&gt;      username="guozheng"&lt;br/&gt;      url="jdbc:mysql://localhost:3306/testdb"&lt;br/&gt;      maxActive="4"/&gt;&lt;br/&gt;  &lt;/globalnamingresources&gt;&lt;br/&gt;  &lt;service name="Catalina"&gt;&lt;br/&gt;    &amp;#8230;&lt;br/&gt;      &lt;host appBase="webapps"&lt;br/&gt;          name="localhost"&gt;&lt;br/&gt;        &lt;context path="/login-session"&gt;&lt;br/&gt;          &lt;resourcelink global="jdbc/testdb" name="jdbc/testdb" type="javax.sql.DataSource"/&gt;&lt;br/&gt;        &lt;/context&gt;&lt;br/&gt;      &lt;/host&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;/service&gt;&lt;br/&gt;&lt;/server&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-7464144402830652322?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/7464144402830652322/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/config-tomcat-for-jndi.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/7464144402830652322'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/7464144402830652322'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/config-tomcat-for-jndi.html' title='config Tomcat for JNDI'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-641922929219702154</id><published>2010-10-29T22:45:00.030-07:00</published><updated>2010-10-29T22:46:03.581-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Database'/><title type='text'>jdbc connections to DB</title><content type='html'>&lt;ol&gt;&lt;br/&gt;&lt;li&gt;&lt;p&gt;MySQL(http://www.mysql.com)mm.mysql-2.0.2-bin.jar&lt;br/&gt;Class.forName( &amp;#8220;org.gjt.mm.mysql.Driver&amp;#8221; );&lt;br/&gt;cn = DriverManager.getConnection( &amp;#8220;jdbc:mysql://MyDbComputerNameOrIP:3306/myDatabaseName&amp;#8221;, sUsr, sPwd );&lt;/p&gt;&lt;/li&gt;&lt;br/&gt;&lt;li&gt;&lt;p&gt;PostgreSQL(http://www.de.postgresql.org)pgjdbc2.jar&lt;br/&gt;Class.forName( &amp;#8220;org.postgresql.Driver&amp;#8221; );&lt;br/&gt;cn = DriverManager.getConnection( &amp;#8220;jdbc:postgresql://MyDbComputerNameOrIP/myDatabaseName&amp;#8221;, sUsr, sPwd );&lt;/p&gt;&lt;/li&gt;&lt;br/&gt;&lt;li&gt;&lt;p&gt;Oracle(http://www.oracle.com/ip/deploy/database/oracle9i/)classes12.zip&lt;br/&gt;Class.forName( &amp;#8220;oracle.jdbc.driver.OracleDriver&amp;#8221; );&lt;br/&gt;cn = DriverManager.getConnection( &amp;#8220;jdbc:oracle:thin:@MyDbComputerNameOrIP:1521:ORCL&amp;#8221;, sUsr, sPwd );&lt;/p&gt;&lt;/li&gt;&lt;br/&gt;&lt;li&gt;&lt;p&gt;Sybase(http://jtds.sourceforge.net)jconn2.jar&lt;br/&gt;Class.forName( &amp;#8220;com.sybase.jdbc2.jdbc.SybDriver&amp;#8221; );&lt;br/&gt;cn = DriverManager.getConnection( &amp;#8220;jdbc:sybase:Tds:MyDbComputerNameOrIP:2638&amp;#8243;, sUsr, sPwd );&lt;br/&gt;// (Default-Username/Password: &amp;#8220;dba&amp;#8221;/&amp;#8221;sql&amp;#8221;)&lt;/p&gt;&lt;/li&gt;&lt;br/&gt;&lt;li&gt;&lt;p&gt;Microsoft SQLServer(http://jtds.sourceforge.net)&lt;br/&gt;Class.forName( &amp;#8220;net.sourceforge.jtds.jdbc.Driver&amp;#8221; );&lt;br/&gt;cn = DriverManager.getConnection( &amp;#8220;jdbc:jtds:sqlserver://MyDbComputerNameOrIP:1433/master&amp;#8221;, sUsr, sPwd );&lt;/p&gt;&lt;/li&gt;&lt;br/&gt;&lt;li&gt;&lt;p&gt;Microsoft SQLServer(http://www.microsoft.com)&lt;br/&gt;Class.forName( &amp;#8220;com.microsoft.jdbc.sqlserver.SQLServerDriver&amp;#8221; );&lt;br/&gt;cn = DriverManager.getConnection( &amp;#8220;jdbc:microsoft:sqlserver://MyDbComputerNameOrIP:1433;databaseName=master&amp;#8221;, sUsr, sPwd );&lt;/p&gt;&lt;/li&gt;&lt;br/&gt;&lt;li&gt;&lt;p&gt;ODBC&lt;br/&gt;Class.forName( &amp;#8220;sun.jdbc.odbc.JdbcOdbcDriver&amp;#8221; );&lt;br/&gt;Connection cn = DriverManager.getConnection( &amp;#8220;jdbc:odbc:&amp;#8221; + sDsn, sUsr, sPwd );&lt;/p&gt;&lt;/li&gt;&lt;br/&gt;&lt;/ol&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;8.DB2&lt;br/&gt;Class.forName(&amp;#8221;Com.ibm.db2.jdbc.net.DB2Driver&amp;#8221;);&lt;br/&gt;String url=&amp;#8221;jdbc:db2://192.9.200.108:6789/SAMPLE&amp;#8221;&lt;br/&gt;cn = DriverManager.getConnection( url, sUsr, sPwd ); &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-641922929219702154?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/641922929219702154/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/jdbc-connections-to-db.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/641922929219702154'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/641922929219702154'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/jdbc-connections-to-db.html' title='jdbc connections to DB'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-7456853995474804816</id><published>2010-10-29T22:45:00.029-07:00</published><updated>2010-10-29T23:41:14.344-07:00</updated><title type='text'>A dive into Web app frameworks</title><content type='html'>Started to look for a good Web application framework to do my last piece of dissertation. I am quite a newbie in the world of Web app development and suddenly got swamped by the vast amount of existing frameworks. Most of these use MVC architecture–using MySQL/Postgresql as RDBMS, Hibernate/iBatis as the ORM layer, Spring to implement business logic and a presentation framework such as Spring MVC, Struts/Struts2(merge of Struts and WebWork2), JSF, Tapestry, etc. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I tried to take a look at &lt;a href="http://raibledesigns.com/"&gt;Matt Raible&lt;/a&gt;’s appfuse project, which is a ready-to-use framework that provides customized stacks of existing frameworks at various layers. It’s quite cool, but still I need quite a lot of time to learn.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Then, I read about comparisons of many existing frameworks and found the new trend to favor much simpler and easy-to-use frameworks such as &lt;a href="http://wicket.sourceforge.net/"&gt;Wicket&lt;/a&gt;, &lt;a href="http://mc4j.org/confluence/display/stripes/Home"&gt;Stripes&lt;/a&gt;, &lt;a href="http://click.sourceforge.net/"&gt;Click&lt;/a&gt;. After reading their documentation, quick start guide and sample applications. I decided to try Wicket.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Wicket is a bit different from those MVC frameworks in that it cleanly separates UI design (in html) and application implementation (in Java code). Also opposite to frameworks that use a lot of XML configuration files, Wicket does not use any XML configuration or Java annotations. From its rich set of live examples, ajax integration is quite good.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;So, I set out and started to learn and use Wicket. First, I tried to follow its online example code. However, those code is quite outdated and its maven pom.xml file did not even work properly. I had to use mvn eclipse plugin (mvn eclipse:eclipse) to import code into eclipse. After many attempts to fix the pom file, I finally gave up. It appears to be a Wicket plugin for eclipse (&lt;a href="http://www.laughingpanda.org/mediawiki/index.php/Wicket_Bench"&gt;Wicket Bench from Laughing Panda&lt;/a&gt;), however this plugin is quite primitive and showed many errors in my eclipse 3.2.2.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Then, luckily I found a wicket module for Netbeans 5.5 (module is the plugin for Netbeans). It has well-documented steps to develop wicket applications and everything is made so simple in Netbeans. I even did not have to worry about libraries and dependency configurations, etc. The bundled Tomcat 5.5.17 is launched automatically when you run the Web application and the browser page is brought out automatically as well. Nice features like HTTP monitor, log messages are also available to help. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I think now I need to explore more about Netbeans 5.5. It’s really a quite sharp and neat tool, in some aspects better than eclipse/MyEclipse 5.1.1 I am using now.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;A note to configure Tomcat and use log4j 1.2 and commons-logging:&lt;br /&gt;1. Shutdown Tomcat if it is currently running.&lt;br /&gt;2. Download the Commons Logging package from the Apache web site (unless you already have it).&lt;br /&gt;3. Copy the commons-logging.jar file from the distribution into your Tomcat common/lib directory.&lt;br /&gt;4. Download the Log4j package from the Apache web site (unless you already have it).&lt;br /&gt;5. Copy the log4j.jar file from the distribution into your Tomcat common/lib directory.&lt;br /&gt;6. Create a log4j.properties file in your Tomcat common/classes directory (see next section).&lt;br /&gt;7. Restart Tomcat.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Sample log4j.properties file:&lt;br /&gt;#&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;Configures Log4j as the Tomcat system logger&lt;/h1&gt;&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;Configure the logger to output info level messages into a rolling log file.&lt;/h1&gt;&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;log4j.rootLogger=INFO, R&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;To continue using the “catalina.out” file (which grows forever),&lt;/h1&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;comment out the above line and uncomment the next.&lt;/h1&gt;&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;log4j.rootLogger=ERROR, A1&lt;/h1&gt;&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;Configuration for standard output (”catalina.out”).&lt;/h1&gt;&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;log4j.appender.A1=org.apache.log4j.ConsoleAppender&lt;br /&gt;log4j.appender.A1.layout=org.apache.log4j.PatternLayout&lt;br /&gt;#&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;Print the date in ISO 8601 format&lt;/h1&gt;&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p %c - %m%n&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;Configuration for a rolling log file (”tomcat.log”).&lt;/h1&gt;&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;log4j.appender.R=org.apache.log4j.DailyRollingFileAppender&lt;br /&gt;log4j.appender.R.DatePattern=’.'yyyy-MM-dd&lt;br /&gt;#&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;Edit the next line to point to your logs directory.&lt;/h1&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;The last part of the name is the log file name.&lt;/h1&gt;&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;log4j.appender.R.File=/usr/local/tomcat/logs/tomcat.log&lt;br /&gt;log4j.appender.R.layout=org.apache.log4j.PatternLayout&lt;br /&gt;#&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;Print the date in ISO 8601 format&lt;/h1&gt;&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;log4j.appender.R.layout.ConversionPattern=%d [%t] %-5p %c - %m%n&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;Application logging options&lt;/h1&gt;&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;log4j.logger.org.apache=DEBUG&lt;/h1&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;log4j.logger.org.apache=INFO&lt;/h1&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;log4j.logger.org.apache.struts=DEBUG&lt;/h1&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;log4j.logger.org.apache.struts=INFO&lt;/h1&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-7456853995474804816?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/7456853995474804816/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/web-apps.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/7456853995474804816'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/7456853995474804816'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/web-apps.html' title='A dive into Web app frameworks'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-1959096342320862744</id><published>2010-10-29T22:45:00.028-07:00</published><updated>2010-10-29T22:46:03.533-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>Some Hibernate Lessons</title><content type='html'>&lt;p&gt;I have started using Hibernate in my project and it turns out to be more difficult for a beginner than I thought, especially when the domain model is a bit complicated. But I guess it is worthwhile to do the learning and fix the problems along the way because it will be even more problematic if I choose to brew a layer like that by myself.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;So, here are some of the lessons I learned.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;1) Inheritance: I chose the 3rd strategy, subclass per table because it is the most beautiful solution to my problem. The lesson I learned is that I don&amp;#8217;t need to add an extra ID to the subclass since it will use the parent class&amp;#8217;s ID anyways. But for the database table schema, you should have an ID for the subclass table.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;2) One-to-many mapping: it is a bit similar to 1) except that now it is a foreign key reference that you don&amp;#8217;t need to put into the many-to-one end POJO definition. For example, we have a parent p and a child c, p contains a set of c and c contains a single p, so this is a bi-directional one-to-many mapping. In the table&lt;em&gt;c, there should be a column like p&lt;/em&gt;id that references id column in table&lt;em&gt;p. But you don&amp;#8217;t need to have a property called p&lt;/em&gt;id in the c mapping file. Otherwise, you will see duplicated mapping error. You don&amp;#8217;t need to have an attribute p_id with getter and setter defined in c POJO either. Otherwise, you will see a null value returned from c.getPId() method.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Here are two links for examples:&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;a href="http://www.java2s.com/Code/Java/Hibernate/OneToManyMappingbasedonSet.htm"&gt;1-to-many&lt;/a&gt; &lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;a href="http://www.javalobby.org/java/forums/t18300.html"&gt;subclass per table&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-1959096342320862744?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/1959096342320862744/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/some-hibernate-lessons.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/1959096342320862744'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/1959096342320862744'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/some-hibernate-lessons.html' title='Some Hibernate Lessons'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-1626681263997265629</id><published>2010-10-29T22:45:00.027-07:00</published><updated>2010-10-29T22:46:03.515-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Windows'/><title type='text'>Windows 2003 Standard Server</title><content type='html'>&lt;p&gt;Microsoft started offering many software to students for FREE at &lt;a href="https://downloads.channel8.msdn.com/"&gt;DreamSpark&lt;/a&gt;. I got a copy of Windows 2003 Standard Server and installed it over the weekend. It is much faster and memory efficient than my old Windows 2000 server. But it is quite annoying to configure it as a daily workstation too. Here are some tips that I want to take a note for.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;1) Add a new user:&lt;/strong&gt; Start -&gt; Run&amp;#8230;, type lusrmgr.msc and this opens the user and group management. Select Users, right click and select New User, then create a new user. &lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;If you want to add admin right to the new user, right click on the newly create user. Select properties, open Member Of tab, click Add&amp;#8230; , in the Enter the object names to select textbox, type Administrators and hit Check Names button (it will fill the full name of admin role), then click OK.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;2) IE security tuning:&lt;/strong&gt; IE&amp;#8217;s default security profile is set to High, and this makes is very unusable because it keeps bugging you to add virtually every website to trusted zone. Here is how to set to a lower security level: open IE, go to Tools&amp;#8230;, go to Internet Options&amp;#8230;, select Security tab, in &amp;#8220;Security Level for this zone&amp;#8221; change High to Medium and confirm the change.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;3) Install Kaspersky 6 desktop version:&lt;/strong&gt; Kaspersky is for desktop computers only and there exists server version and it is quite expensive. I have successfully installed KAV 6 on Windows 2000 server before, but installing it on Windows 2003 server SP2 is much trickier.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;ul&gt;&lt;br/&gt;&lt;li&gt;Modify KAV msi file using ORCA MSI editor: open KAV msi file using ORCA, then do a ctrl-F search for &amp;#8220;MsiNTProductType=1&amp;#8243;, replace each occurrence with &amp;#8220;MsiNTProductType&gt;=1&amp;#8243; and save the msi file. Then you can install it without any problem.&lt;/li&gt;&lt;br/&gt;&lt;br/&gt;&lt;li&gt;After installation and adding the license file, when you restart, Windows 2003 server will show a blue screen. Press the famous F8 and select &amp;#8220;safe mode with command line&amp;#8221;. I tried to select GUI safe mode, but it just didn&amp;#8217;t respond to keyboard. &lt;/li&gt;&lt;br/&gt;&lt;br/&gt;&lt;li&gt;On the command line. Type &amp;#8220;edit&amp;#8221; command and this will give you a basic text editor, create a file called kav.reg with the following content:&lt;br/&gt;&lt;code&gt;&lt;br/&gt;Windows Registry Editor Version 5.00 &lt;br/&gt;[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\kl1] &lt;br/&gt;"Start"=dword:00000001&lt;br/&gt;&lt;/code&gt;&lt;br/&gt;&lt;/li&gt;&lt;br/&gt;&lt;br/&gt;&lt;li&gt;Save it and exit the editor. Then, type &amp;#8220;regedit /s kav.reg&amp;#8221; to import this change to the registry. Reboot the machine using &amp;#8220;shutdown /r&amp;#8221; command.&lt;/li&gt;&lt;br/&gt;&lt;br/&gt;&lt;li&gt;Finally, no more blue screen!&lt;/li&gt;&lt;br/&gt;&lt;/ul&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;4) Hardware drivers:&lt;/strong&gt; driver support is not so good on 2003 server. I could not find a driver for my RAID IDE-SATA converter card. I should have used software to backup drivers before upgrading. Here is a good one called &lt;a href="http://www.drivergenius.com/"&gt;Driver Genius&lt;/a&gt;.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;5) Adding &amp;#8220;show desktop&amp;#8221; icon to the task bar:&lt;/strong&gt; for the newly created user, there is no show desktop icon. You can either copy a file called Show Desktop.scf from C:\Documents and Settings\Administrator\Application Data\Microsoft\Internet Explorer\Quick Launch\ to C:\Documents and Settings\&lt;username&gt;\Application Data\Microsoft\Internet Explorer\Quick Launch.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Or you can directly create a new Desktop.scf in C:\Documents and Settings\&lt;/username&gt;&lt;username&gt;\Application Data\Microsoft\Internet Explorer\Quick Launch\, here is the file content:&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;code&gt;&lt;br/&gt;[Shell]&lt;br/&gt;Command=2&lt;br/&gt;IconFile=explorer.exe,3&lt;br/&gt;[Taskbar]&lt;br/&gt;Command=ToggleDesktop&lt;br/&gt;&lt;/code&gt;&lt;/username&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-1626681263997265629?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/1626681263997265629/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/windows-2003-standard-server.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/1626681263997265629'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/1626681263997265629'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/windows-2003-standard-server.html' title='Windows 2003 Standard Server'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-140991327483762441</id><published>2010-10-29T22:45:00.026-07:00</published><updated>2010-10-29T23:42:12.825-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='CSS'/><category scheme='http://www.blogger.com/atom/ns#' term='HTML'/><category scheme='http://www.blogger.com/atom/ns#' term='Job Interview'/><title type='text'>XHTML and CSS notes</title><content type='html'>&lt;h3&gt;&lt;img src="http://ecx.images-amazon.com/images/I/51AkhH7EiGL._AA240_.jpg" /&gt; &lt;/h3&gt;&lt;a href="http://www.amazon.com/Stylin-CSS-Designers-Voices-Matter/dp/0321525566/ref=pd_bbs_sr_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1205995835&amp;amp;sr=8-1"&gt;Stylin with CSS&lt;/a&gt;&lt;br /&gt;&lt;h3&gt;&amp;nbsp;&lt;/h3&gt;&lt;h3&gt;XHTML Structure&lt;/h3&gt;&lt;h4&gt;&amp;nbsp;&lt;/h4&gt;&lt;h4&gt;DOCTYPE declarations:&lt;/h4&gt;&lt;strong&gt;Strict:&lt;/strong&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="background-color: white;"&gt;&amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"&lt;/span&gt;&lt;br /&gt;&lt;span style="background-color: white;"&gt;&amp;nbsp; "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&amp;gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;strong&gt;Transitional:&lt;/strong&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="background-color: white;"&gt;&amp;lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"&lt;/span&gt;&lt;br /&gt;&lt;span style="background-color: white;"&gt;&amp;nbsp; "http://www.w3.org/TR/html4/loose.dtd"&amp;gt;&lt;/span&gt;&lt;/blockquote&gt;Frameset:&lt;br /&gt;&lt;blockquote&gt;&lt;span style="background-color: white;"&gt;&amp;lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN"&lt;/span&gt;&lt;br /&gt;&lt;span style="background-color: white;"&gt;&amp;nbsp; "http://www.w3.org/TR/html4/frameset.dtd"&amp;gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;h4&gt;XML namespace declaration:&lt;/h4&gt;&amp;lt;html xmlns=&lt;a href="http://www.w3.org/1999/xhtml"&gt;http://www.w3.org/1999/xhtml&lt;/a&gt; lang="en" xml:lang="en"&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Content type declaration:&lt;/h4&gt;&amp;lt;meta http-equiv="Content-type" content="text/html; charset=iso-8859-1" /&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Symbols such as &amp;lt;, &amp;amp;:&lt;/h4&gt;&lt;a href="http://htmlhelp.com/reference/html40/entities/" title="http://htmlhelp.com/reference/html40/entities/"&gt;http://htmlhelp.com/reference/html40/entities/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;A simple template:&lt;/h4&gt;&lt;span style="background-color: white;"&gt;&amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"&lt;/span&gt;&lt;br /&gt;&lt;span style="background-color: white;"&gt;&amp;nbsp; "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;lt;html xmlns=&lt;a href="http://www.w3.org/1999/xhtml"&gt;http://www.w3.org/1999/xhtml&lt;/a&gt; lang="en" xml:lang="en"&amp;gt;&lt;br /&gt;&lt;blockquote&gt;&amp;lt;head&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;meta http-equiv="Content-type" content="text/html; charset=iso-8859-1" /&amp;gt;&lt;/blockquote&gt;&lt;blockquote&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;title&amp;gt;Title for your Web page&amp;lt;/title&amp;gt;&lt;/blockquote&gt;&lt;blockquote&gt;&amp;lt;/head&amp;gt;&lt;/blockquote&gt;&lt;blockquote&gt;&amp;lt;body&amp;gt;&lt;/blockquote&gt;&lt;blockquote&gt;&amp;lt;/body&amp;gt;&lt;/blockquote&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Four ways of CSS declaration:&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;embed &amp;lt;style&amp;gt;&amp;lt;/style&amp;gt; section in the head element &lt;/li&gt;&lt;li&gt;link to external CSS file: &amp;lt;link href="my&lt;em&gt;style&lt;/em&gt;sheet&lt;em&gt;print.css" media="screen" rel="stylesheet" type="text/css"&amp;gt;, for print, just change media="print" &lt;/em&gt;&lt;/li&gt;&lt;em&gt;&lt;li&gt;in-line style, just specify at each tag, e.g. &amp;lt;p style="font-size: 25pt; color: red;"&amp;gt; &lt;/li&gt;&lt;li&gt;use @import in &amp;lt;style&amp;gt;&amp;lt;/style&amp;gt; section in the head element. The only downside is that IE6 might have so called FOUC (Flash of Un-styled Content) problem, meaning the content will be momentarily displayed without CSS formatting. See more at &lt;a href="http://bluerobot.com/web/css/fouc.asp"&gt;http://bluerobot.com/web/css/fouc.asp&lt;/a&gt; &lt;/li&gt;&lt;/em&gt;&lt;/ol&gt;&lt;em&gt;&lt;/em&gt;&lt;br /&gt;&lt;em&gt;&lt;br /&gt;&lt;h3&gt;CSS syntax-related stuff:&lt;/h3&gt;&lt;br /&gt;&lt;h4&gt;Contextual selector:&lt;/h4&gt;this limits style to parent element, e.g. p em{color:green;} makes only those &amp;lt;em&amp;gt; within &amp;lt;p&amp;gt; elements green color.&lt;br /&gt;&lt;h4&gt;Class selector:&lt;/h4&gt;e.g. p.green{color:green;} &amp;lt;p class="green"&amp;gt;green text&amp;lt;/p&amp;gt;, note that if multiple classes exist, the last one declared in CSS definition file wins.&lt;br /&gt;&lt;h4&gt;Id selector:&lt;/h4&gt;p#green{color:green;} &amp;lt;p id="green"&amp;gt;green text&amp;lt;/p&amp;gt;&lt;br /&gt;Difference between id and class selector is that one id value is unique to one element and id is usually used in javascript as well. So, for those styles unique to an element, use id, for styles that can be shared among different elements, use class selector.&lt;br /&gt;&lt;h4&gt;Attribute selector: &lt;/h4&gt;select element based on attribute existence or values, e.g. this example add a pdf icon after links to pdf files, use [href|="foo"] to specify link names that start with "foo"&lt;br /&gt;a[href$=".pdf"] {&lt;/em&gt;&lt;br /&gt;&lt;em&gt;background:transparent url(images/icon&lt;/em&gt;pdf.gif) no-repeat scroll right center;&lt;br /&gt;padding-right:18px;&lt;br /&gt;}&lt;br /&gt;&lt;h4&gt;Unit measurement:&lt;/h4&gt;try to use relative units: em (from the width of a character), ex (from the height of character x), or percentage.&lt;br /&gt;&lt;h4&gt;Colors: &lt;/h4&gt;many different ways to specify a color: #RRGGBB, (R%, G%, B%), or use color name. There are only 16 color names in the spec: aqua, black, blue, fuchsia, gray, green, lime, maroon, navy, olive, purple, red, silver, teal, white, yellow.&lt;br /&gt;&lt;h4&gt;Fonts:&lt;/h4&gt;serif, sans-serif, monospace, fantasy, cursive, e.g. p{font-family:sans-serif;}&lt;br /&gt;&lt;h4&gt;Round corners: &lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.editsite.net/blog/rounded_corners.html"&gt;Rounded Corners from Editsite.net&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.spiffycorners.com/"&gt;Spiffy Corners from Spiffy Corners.com&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.html.it/articoli/niftycube/index.html"&gt;Nifty Corners&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.vertexwerks.com/tests/sidebox"&gt;Thrash Box from VertexWorks&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-140991327483762441?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/140991327483762441/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/xhtml-and-css-notes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/140991327483762441'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/140991327483762441'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/xhtml-and-css-notes.html' title='XHTML and CSS notes'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-5875668384236805554</id><published>2010-10-29T22:45:00.025-07:00</published><updated>2010-10-29T22:46:03.465-07:00</updated><title type='text'>Website Performance</title><content type='html'>&lt;p&gt;&lt;img src="http://ecx.images-amazon.com/images/I/51ATkHaUd9L._AA240_.jpg" /&gt; &lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.amazon.com/dp/0596529309?tag=stevsoud-20&amp;amp;camp=14573&amp;amp;creative=327641&amp;amp;linkCode=as1&amp;amp;creativeASIN=0596529309&amp;amp;adid=1S1KP4EV129EN37422C0&amp;amp;"&gt;This is a very nice book&lt;/a&gt; by the creator of &lt;a href="http://developer.yahoo.com/yslow/"&gt;Yslow&lt;/a&gt;, an addon to &lt;a href="http://addons.mozilla.org/firefox/addon/1843"&gt;Firebug&lt;/a&gt;. It lists 14 rules for high performance websites. Very useful.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://davidherron.com/book-page/190-measuring-website-speed"&gt;DavidHerron.com&lt;/a&gt; also has many resources for high performance websites.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-5875668384236805554?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/5875668384236805554/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/website-performance.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/5875668384236805554'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/5875668384236805554'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/website-performance.html' title='Website Performance'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-5171837203980256485</id><published>2010-10-29T22:45:00.024-07:00</published><updated>2010-10-29T23:40:42.521-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Job Interview'/><title type='text'>What happens when you open a URL in your Web browser</title><content type='html'>&lt;a href="http://weblogs.mozillazine.org/hyatt/archives/2004_05.html#005496"&gt;Here&lt;/a&gt; is a nice article touching this topic.&lt;br /&gt;Since it is not that long, I simply copy&amp;amp;past here:&lt;br /&gt;&lt;blockquote&gt;Testing Page Load Speed     &lt;br /&gt;Posted at 2:27 PM &lt;br /&gt;One of the most problematic tasks when working on a Web browser is getting an accurate measurement of how long you’re taking to load Web pages. In order to understand why this is tricky, we’ll need to understand what exactly browsers do when you ask them to load a URL. &lt;br /&gt;So what happens when you go to a URL like cnn.com? Well, the first step is to start fetching the data from the network. This is typically done on a thread other than the main UI thread. &lt;br /&gt;As the data for the page comes in, it is fed to an HTML tokenizer. It’s the tokenizer’s job to take the data stream and figure out what the individual tokens are, e.g., a start tag, an attribute name, an attribute value, an end tag, etc. The tokenizer then feeds the individual tokens to an HTML parser. &lt;br /&gt;The parser’s job is to build up the DOM tree for a document. Some DOM elements also represent subresources like stylesheets, scripts, and images, and those loads need to be kicked off when those DOM nodes are encountered. &lt;br /&gt;In addition to building up a DOM tree, modern CSS2-compliant browsers also build up separate rendering trees that represent what is actually shown on your screen when painting. It’s important to note two things about the rendering tree vs. the DOM tree. &lt;br /&gt;(1) If stylesheets are still loading, it is wasteful to construct the rendering tree, since you don’t want to paint anything at all until all stylesheets have been loaded and parsed. Otherwise you’ll run into a problem called FOUC (the flash of unstyled content problem), where you show content before it’s ready. &lt;br /&gt;(2) Image loads should be kicked off as soon as possible, and that means they need to happen from the DOM tree rather then the rendering tree. You don’t want to have to wait for a CSS file to load just to kick off the loads of&amp;nbsp; images. &lt;br /&gt;There are two options for how to deal with delayed construction of the render tree because of stylesheet loads. You can either block the parser until the stylesheets have loaded, which has the disadvantage of keeping you from parallelizing resource loads, or you can allow parsing to continue but simply prevent the construction of the render tree. Safari does the latter. &lt;br /&gt;External scripts must block the parser by default (because they can document.write). An exception is when defer is specified for scripts, in which case the browser knows it can delay the execution of the script and keep parsing. &lt;br /&gt;What are some of the relevant milestones in the life of a loading page as far as figuring out when you can actually reliably display content? &lt;br /&gt;(1) All stylesheets have loaded.     &lt;br /&gt;(2) All data for the HTML page has been received.      &lt;br /&gt;(3) All data for the HTML page has been parsed.      &lt;br /&gt;(4) All subresources have loaded (the onload handler time). &lt;br /&gt;Benchmarks of page load speed tend to have one critical flaw, which is that all they typically test is (4). Take, for example, the aforementioned cnn.com. Frequently cnn.com is capable of displaying virtually all of its content at about the 350ms mark, but because it can’t finish parsing until an external script that wants to load an advertisement has completed, the onload handler typically doesn’t fire until the 2-3 second mark! &lt;br /&gt;A browser could clearly optimize for only overall page load speed and show nothing until 2-3 seconds have gone by, thus enabling a single layout and paint. That browser will likely load the overall page faster, but feel literally 10 times slower than the browser that showed most of the page at the 300 ms mark, but then did a little more work as the remaining content came in. &lt;br /&gt;Furthermore benchmarks have to be very careful if they measure only for onload, because there’s no rule that browsers have to have done any layout or painting by the time onload fires. Sure, they have to have parsed the whole page in order to find all the subresources, and they have to have loaded all of those subresources, but they may have yet to lay out the objects in the rendering tree. &lt;br /&gt;It’s also wise to wait for the onload handler to execute before laying out anyway, because the onload handler could redirect you to another page, in which case you don’t really need to lay out or paint the original page at all, or it could alter the DOM of the page (and if you’d done a layout before the onload, you’d then see the changes that the onload handler made happen in the page, such as flashy DHTML menu initialization). &lt;br /&gt;Benchmarks that test only for onload are thus fundamentally flawed in two ways, since they don’t measure how quickly a page is initially displayed and they rely on an event (onload) that can fire before layout and painting have occurred, thus causing those operations to be omitted from the benchmark. &lt;br /&gt;i-bench 4 suffers from this problem. i-bench 5 actually corrected the problem by setting minimal timeouts to scroll the page to the offsetTop of a counter element on the page. In order to compute offsetTop browsers must necessarily do a layout, and by setting minimal timers, all browsers paint as well. This means i-bench 5 is doing an excellent job of providing an accurate assessment of overall page load time. &lt;br /&gt;Because tests like i-bench only measure overall page load time, there is a tension between performing well on these sorts of tests and real-world perception, which typically involves showing a page as soon as possible. &lt;br /&gt;A naive approach might be to simply remove all delays and show the page as soon as you get the first chunk of data. However, there are drawbacks to showing a page immediately. Sure, you could try to switch to a new page immediately, but if you don’t have anything meaningful to show, you’ll end up with a "flashy" feeling, as the old page disappears and is replaced by a blank white canvas, and only later does the real page content come in. Ideally transitions between pages should be smooth, with one page not being replaced by another until you can know reliably that the new page will be reasonably far along in its life cycle. &lt;br /&gt;In Safari 1.2 and in Mozilla-based browsers, the heuristic for this is quite simple. Both browsers use a time delay, and are unwilling to switch to the new page until that time threshold has been exceeded. This setting is configurable in both browsers (in the former using WebKit preferences and in the latter using about:config). &lt;br /&gt;When I implemented this algorithm (called "paint suppression" in Mozilla parlance) in Mozilla I originally used a delay of 1 second, but this led to the perception that Mozilla was slow, since you frequently didnt see a page until it was completely finished. Imagine for example that a page is completely done except for images at the 50ms mark, but that because you’re a modem user or DSL user, the images aren’t finished until the 1 second mark. Despite the fact that all the readable content could have been shown at the 50ms mark, this delay of 1 second in Mozilla caused you to wait 950 more ms before showing anything at all. &lt;br /&gt;One of the first things I did when working on Chimera (now Camino) was lower this delay in Gecko to 250ms. When I worked on Firefox I made the same change. Although this negatively impacts page load time, it makes the browser feel substantially faster, since the user clicks a link and sees the browser react within 250ms (which to most users is within a threshold of immediacy, i.e., it makes them feel like the browser reacted more or less instantly to their command). &lt;br /&gt;Firefox and Camino still use this heuristic in their latest releases. Safari actually uses a delay of one second like older Mozilla builds used to, and so although it is typically faster than Mozilla-based browsers on overall page load, it will typically feel much slower than Firefox or Camino on network connections like cable modem/modem/DSL. &lt;br /&gt;However, there is also a problem with the straight-up time heuristic. Suppose that you hit the 250ms mark but all the stylesheets haven’t loaded or you haven’t even received all the data for a page. Right now Firefox and Camino don’t care and will happily show you what they have so far anyway. This leads to the "white flash" problem, where the browser gets flashy as it shows you a blank white canvas (because it doesn’t yet know what the real background color for the page is going to be, it just fills in with white). &lt;br /&gt;So what I wanted to achieve in Safari was to replicate the rapid response feel of Firefox/Camino, but to temper that rapid response when it would lead to gratuitous flashing. Here’s what I did. &lt;br /&gt;(1) Create two constants, cMinimumLayoutThreshold and cTimedLayoutDelay. At the moment the settings for these constants are 250ms and 1000ms respectively. &lt;br /&gt;(2) Don’t allow layouts/paints at all if the stylesheets haven’t loaded and if you’re not over the minimum layout threshold (250ms). &lt;br /&gt;(3) When all data is received for the main document, immediately try to parse as much as possible. When you have consumed all the data, you will either have finished parsing or you’ll be stuck in a blocked mode waiting on an external script. &lt;br /&gt;If you’ve finished parsing or if you at least have the body element ready and if all the stylesheets have loaded, immediately lay out and schedule a paint for as soon as possible, but only if you’re over the minimum threshold (250ms). &lt;br /&gt;(4) If stylesheets load after all data has been received, then they should schedule a layout for as soon as possible (if you’re below the minimum layout threshold, then schedule the timer to fire at the threshold). &lt;br /&gt;(5) If you haven’t received all the data for the document, then whenever a layout is scheduled, you set it to the nearest multiple of the timed layout delay time (so 1000ms, 2000ms, etc.). &lt;br /&gt;(6) When the onload fires, perform a layout immediately after the onload executes. &lt;br /&gt;This algorithm completely transforms the feel of Safari over DSL and modem connections. Page content usually comes screaming in at the 250ms mark, and if the page isn’t quite ready at the 250ms, it’s usually ready shortly after (at the 300-500ms mark). In the rare cases where you have nothing to display, you wait until the 1 second mark still. This algorithm makes "white flashing" quite rare (you’ll typically only see it on a very slow site that is taking a long time to give you data), and it makes Safari feel orders of magnitude faster on slower network connections. &lt;br /&gt;Because Safari waits for a minimum threshold (and waits to schedule until the threshold is exceeded, benchmarks won’t be adversely affected as long as you typically beat the minimum threshold. Otherwise the overall page load speed will degrade slightly in real-world usage, but I believe that to be well-worth the decrease in the time required to show displayable content.&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-5171837203980256485?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/5171837203980256485/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/what-happens-when-you-open-url-in-your.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/5171837203980256485'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/5171837203980256485'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/what-happens-when-you-open-url-in-your.html' title='What happens when you open a URL in your Web browser'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-3620645020455749779</id><published>2010-10-29T22:45:00.023-07:00</published><updated>2010-10-29T23:41:45.947-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='HTTP'/><category scheme='http://www.blogger.com/atom/ns#' term='Job Interview'/><title type='text'>HTTP Notes</title><content type='html'>From &lt;a href="http://developer.yahoo.com/performance/rules.html"&gt;Best Practices for Speeding Up Your Web Site&lt;/a&gt;&lt;br /&gt;&lt;h4&gt;1. Redirection&lt;/h4&gt;&lt;blockquote&gt;HTTP/1.1 301 Moved Permanently     &lt;br /&gt;Location: &lt;a href="http://example.com/newuri"&gt;http://example.com/newuri&lt;/a&gt;      &lt;br /&gt;Content-Type: text/html&lt;/blockquote&gt;&lt;h4&gt;2. About ETag&lt;/h4&gt;&lt;blockquote&gt;Entity tags (ETags) are a mechanism that web servers and browsers use to determine whether the component in the browser’s cache matches the one on the origin server. (An "entity" is another word for what I’ve been calling a "component": images, scripts, stylesheets, etc.) ETags were added to provide a mechanism for validating entities that is more flexible than the last-modified date. An ETag is a string that uniquely identifies a specific version of a component. The only format constraints are that the string be quoted. The origin server specifies the component’s ETag using the ETag response header. &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; HTTP/1.1 200 OK     &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Last-Modified: Tue, 12 Dec 2006 03:03:59 GMT      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ETag: "10c24bc-4ab-457e1c1f"      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Content-Length: 12195 &lt;br /&gt;Later, if the browser has to validate a component, it uses the If-None-Match header to pass the ETag back to the origin server. If the ETags match, a 304 status code is returned reducing the response by 12195 bytes for this example. &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GET /i/yahoo.gif HTTP/1.1     &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Host: us.yimg.com      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; If-Modified-Since: Tue, 12 Dec 2006 03:03:59 GMT      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; If-None-Match: "10c24bc-4ab-457e1c1f"      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; HTTP/1.1 304 Not Modified &lt;br /&gt;The problem with ETags is that they typically are constructed using attributes that make them unique to a specific server hosting a site. ETags won’t match when a browser gets the original component from one server and later tries to validate that component on a different server, a situation that is all too common on Web sites that use a cluster of servers to handle requests. By default, both Apache and IIS embed data in the ETag that dramatically reduces the odds of the validity test succeeding on web sites with multiple servers. &lt;br /&gt;The ETag format for Apache 1.3 and 2.x is inode-size-timestamp. Although a given file may reside in the same directory across multiple servers, and have the same file size, permissions, timestamp, etc., its inode is different from one server to the next. &lt;br /&gt;IIS 5.0 and 6.0 have a similar issue with ETags. The format for ETags on IIS is Filetimestamp:ChangeNumber. A ChangeNumber is a counter used to track configuration changes to IIS. It’s unlikely that the ChangeNumber is the same across all IIS servers behind a web site. &lt;br /&gt;The end result is ETags generated by Apache and IIS for the exact same component won’t match from one server to another. If the ETags don’t match, the user doesn’t receive the small, fast 304 response that ETags were designed for; instead, they’ll get a normal 200 response along with all the data for the component. If you host your web site on just one server, this isn’t a problem. But if you have multiple servers hosting your web site, and you’re using Apache or IIS with the default ETag configuration, your users are getting slower pages, your servers have a higher load, you’re consuming greater bandwidth, and proxies aren’t caching your content efficiently. Even if your components have a far future Expires header, a conditional GET request is still made whenever the user hits Reload or Refresh. &lt;br /&gt;If you’re not taking advantage of the flexible validation model that ETags provide, it’s better to just remove the ETag altogether. The Last-Modified header validates based on the component’s timestamp. And removing the ETag reduces the size of the HTTP headers in both the response and subsequent requests. This Microsoft Support article describes how to remove ETags. In Apache, this is done by simply adding the following line to your Apache configuration file:      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FileETag none&lt;/blockquote&gt;3. HTTP Status Code&lt;br /&gt;Those codes can be found &lt;a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html"&gt;here&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-3620645020455749779?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/3620645020455749779/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/notes-related-to-http.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/3620645020455749779'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/3620645020455749779'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/notes-related-to-http.html' title='HTTP Notes'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-8407493731450966260</id><published>2010-10-29T22:45:00.022-07:00</published><updated>2010-10-29T22:46:03.405-07:00</updated><title type='text'>Javascript Notes</title><content type='html'>&lt;p&gt;&lt;p&gt;Found several nice short tutorials for JS:&lt;/p&gt;  &lt;p&gt;by &lt;a href="https://mail.google.com/mail?view=cm&amp;amp;tf=0&amp;amp;ui=1&amp;amp;to=sergio_pereira@msn.com"&gt;Sergio Pereira&lt;/a&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;&lt;a href="http://www.sergiopereira.com/articles/advjs.html"&gt;Quick guide to somewhat advanced Javascript&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.sergiopereira.com/articles/prototype.js.html"&gt;Using prototype.js v1.5.0&lt;/a&gt;&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;by &lt;a href="http://fallenlord.blogbus.com/"&gt;fallenlord blog&lt;/a&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;&lt;a href="http://fallenlord.blogbus.com/logs/10912295.html"&gt;Class definitions in JS&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://fallenlord.blogbus.com/logs/10912579.html"&gt;Inheritance in JS&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://fallenlord.blogbus.com/logs/8125653.html"&gt;Event model in JS&lt;/a&gt;&lt;/li&gt; &lt;/ol&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-8407493731450966260?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/8407493731450966260/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/javascript-notes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/8407493731450966260'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/8407493731450966260'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/javascript-notes.html' title='Javascript Notes'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-5006042575605805947</id><published>2010-10-29T22:45:00.021-07:00</published><updated>2010-10-29T22:46:03.389-07:00</updated><title type='text'>Updated High Performance Website Tips</title><content type='html'>&lt;p&gt;&lt;p&gt;Latest presentation from Yahoo! Exceptional Performance Group&lt;/p&gt;  &lt;div id="__ss_310612" style="width: 425px; text-align: left"&gt;&lt;embed src="http://static.slideshare.net/swf/ssplayer2.swf?doc=high-performance-web-pages-20-new-best-practices-120577522992998-3" width="425" height="355" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" /&gt;    &lt;div style="font-size: 11px; padding-top: 2px; font-family: tahoma,arial; height: 26px"&gt;&lt;a href="http://www.slideshare.net/?src=embed"&gt;&lt;img style="border-right: 0px; border-top: 0px; margin-bottom: -5px; border-left: 0px; border-bottom: 0px" alt="SlideShare" src="http://static.slideshare.net/swf/logo_embd.png" /&gt;&lt;/a&gt; | &lt;a title="View this slideshow on SlideShare" href="undefined"&gt;View&lt;/a&gt; | &lt;a href="http://www.slideshare.net/upload"&gt;Upload your own&lt;/a&gt;&lt;/div&gt; &lt;/div&gt; &lt;img style="visibility: hidden; width: 0px; height: 0px" height="0" src="http://counters.gigya.com/wildfire/CIMP/Jmx*PTEyMDY*MDgzODgyMDAmcHQ9MTIwNjQwODQwMjE4MCZwPTEwMTkxJmQ9Jm49.jpg" width="0" border="0" /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-5006042575605805947?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/5006042575605805947/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/updated-high-performance-website-tips.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/5006042575605805947'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/5006042575605805947'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/updated-high-performance-website-tips.html' title='Updated High Performance Website Tips'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-3541243332310661561</id><published>2010-10-29T22:45:00.020-07:00</published><updated>2010-10-29T22:46:03.375-07:00</updated><title type='text'>Regex for javascript to detect a URL</title><content type='html'>&lt;p&gt;&lt;code&gt;var regex = /\b([\d\w\.\/\+\-\?\:]*)((ht|f)tp(s|)\:\/\/|[\d\d\d|\d\d]\.[\d\d\d|\d\d]&lt;br/&gt;\.|www\.|\.tv|\.ac|\.com|\.edu|\.gov|\.int|\.mil|\.net|\.org|\.biz|\.info|\.name|\.pro&lt;br/&gt;|\.museum|\.co)([\d\w\.\/\%\+\-\=\&amp;amp;amp;\?\:\\\&amp;amp;quot;\'\,\|\~\;]*)\b/gi;&lt;/code&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Online tester for javascript regex:&lt;/h3&gt;  &lt;p&gt; &lt;a title="http://www.regular-expressions.info/javascriptexample.html" href="http://www.regular-expressions.info/javascriptexample.html"&gt;http://www.regular-expressions.info/javascriptexample.html&lt;/a&gt;&lt;/p&gt;  &lt;h3&gt;Short tutorial for regex in javascript:&lt;/h3&gt;  &lt;p&gt; &lt;a title="http://www.regular-expressions.info/javascript.html" href="http://www.regular-expressions.info/javascript.html"&gt;http://www.regular-expressions.info/javascript.html&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-3541243332310661561?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/3541243332310661561/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/regex-for-javascript-to-detect-url.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/3541243332310661561'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/3541243332310661561'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/regex-for-javascript-to-detect-url.html' title='Regex for javascript to detect a URL'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-2587972483345192887</id><published>2010-10-29T22:45:00.019-07:00</published><updated>2010-10-29T22:46:03.361-07:00</updated><title type='text'>Firefox 3 Beta</title><content type='html'>&lt;p&gt;&lt;a href="http://tinypic.com" target="_blank"&gt;&lt;img alt="Image and video hosting by TinyPic" src="http://i29.tinypic.com/21e98nr.png" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;I run three browsers on my computer with Opear the most frequently used one. Firefox sometimes consumes too much memory, either because of the memory leak problem or its cache implementation.&lt;/p&gt;  &lt;p&gt;Firefox betas are out for quite sometime and I tried its latest 3.0pre from &lt;a href="http://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/latest-trunk/"&gt;nightly build trunk&lt;/a&gt;. It is much faster and polished and I really love it. The only problem is that most plugins are not officially compatible with Firefox 3 betas right now.&lt;/p&gt;  &lt;p&gt;There are several FF plugins that I cannot live without:&lt;/p&gt;  &lt;h3&gt;Greasemoney:&lt;/h3&gt;  &lt;p&gt;this animal allows you to write customized scripts to control the actual rendering of any page. One most useful script is &lt;a href="http://userscripts.org/scripts/show/2254"&gt;Linkify ting&lt;/a&gt;, it automatically turns text URLs into clickable links by adding &amp;lt;a&amp;gt; tags. But the original script has bugs that it cannot handle many types of URLs. So, what you can do is to open that script and replace &amp;quot;var regex = blah blah&amp;quot; with the following:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&amp;quot;var regex = /\b([\d\w\.\/\+\-\?\:]*)((ht|f)tp(s|)\:\/\/|[\d\d\d|\d\d]\.[\d\d\d|\d\d]\.|www\.|\.tv|\.ac|\.com|\.edu|\.gov|\.int|\.mil|\.net|\.org|\.biz|\.info|\.name|\.pro|\.museum|\.co)([\d\w\.\/\%\+\-\=\&amp;amp;\?\:\\\&amp;quot;\&amp;#8217;\,\|\~\;]*)\b/gi;&amp;quot;.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;There are also many scripts on &lt;a href="http://userscripts.org"&gt;UserScripts.org&lt;/a&gt; including many hacks on iGoogle and Gmail. There are also tutorials like &lt;a href="http://www.google.com/url?sa=t&amp;amp;ct=res&amp;amp;cd=1&amp;amp;url=http%3A%2F%2Fdiveintogreasemonkey.org%2F&amp;amp;ei=WGPxR9fwFIWIpATJiZV0&amp;amp;usg=AFQjCNHUKFsdgpQkOk6igDVXUY887iebmg&amp;amp;sig2=SSvticGlrS5hNqD7IjSbmQ"&gt;Dive into Greasemonkey&lt;/a&gt; and books like &lt;a href="http://userscripts.org/"&gt;Greasemonkey Hacks&lt;/a&gt; if you want to write your own scripts. It is really a lot of fun.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Firebug:&lt;/h3&gt;  &lt;p&gt;this is the ultimate toolbox for Web developers, it includes many powerful features to detect JavaScript errors, and design your XHTML and CSS files. There is another addon to Firebug called YSlow! from Yahoo extreme performance group that evaluates a Web site based on several performancing-improving guidelines.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Del.icio.us: &lt;/h3&gt;  &lt;p&gt;this is the Web-based bookmark solution. Although they have a new version that integrates with Firefox bookmark manager, I still like the classic version that adds to buttons on the browser toolbar better.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;So, how to make these plugins working with FF3.0 betas? It is quite straightforward actually. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;1. Manually download XPI file:&lt;/strong&gt; Instead of click install button on these plugin website (actually, those buttons are greyed out and you cannot click at all), you go to the bottom of a plugin page where there is a link for &amp;quot;advanced details&amp;quot;, expand that section and click on &amp;quot;complete version history&amp;quot;, then download the xpi file manually using &amp;quot;save as&amp;#8230;&amp;quot;.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;2. Open XPI file with WinRAR and edit install.rdf file:&lt;/strong&gt; in target application element, there is an element called &amp;lt;em:maxVersion&amp;gt;, just change the value to 3.0pre. Save the install.rdf and put it back to the XPI file.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;3. In FF3, use &amp;quot;open file&amp;#8230;&amp;quot; to open the modified XPI file. &lt;/strong&gt;Bingo! You got those old buddies back &lt;img src='http://woshiadai.blogsome.com/wp-images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /&gt;  &lt;/p&gt;  &lt;p&gt;For del.icio.us plugin, there is a bit more extra work due to the signature files. FF3 will have some error for &amp;quot;signing could not be verified&amp;quot; error. Simply open the XPI file with WinRAR and delete META-INF folder and save the XPI file. Here we go, del.icio.us buttons back too!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-2587972483345192887?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/2587972483345192887/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/firefox-3-beta.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/2587972483345192887'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/2587972483345192887'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/firefox-3-beta.html' title='Firefox 3 Beta'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://i29.tinypic.com/21e98nr_th.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-6302322728140819377</id><published>2010-10-29T22:45:00.018-07:00</published><updated>2010-10-29T22:46:03.340-07:00</updated><title type='text'>Java Garbage Collection</title><content type='html'>&lt;p&gt;&lt;a href="http://www.ibm.com/developerworks/java/library/j-jtp10283/index.html?S_TACT=105AGX02&amp;amp;S_CMP=EDU"&gt;   &lt;h4&gt;&lt;a href="http://www.ibm.com/developerworks/java/library/j-jtp10283/index.html?S_TACT=105AGX02&amp;amp;S_CMP=EDU"&gt;A short article&lt;/a&gt; about different types of garbage collectors in Java&lt;/h4&gt;    &lt;p&gt;&lt;font color="#9c9969"&gt;&lt;/font&gt;&lt;/p&gt; &lt;/a&gt;  &lt;p&gt;Never know that Java could have memory leak problem before since I believed that GC will do all the trick to reclaim unreachable objects. But actually it does due to &amp;quot;unintentional object retention&amp;quot;. &lt;a href="http://www.ibm.com/developerworks/java/library/j-jtp11225/index.html"&gt;This is a good article&lt;/a&gt; explaining about this problem and providing suggestions to deal with it using things like WeakHashMap (finally I understand what this class is useful for).&lt;/p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-6302322728140819377?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/6302322728140819377/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/java-garbage-collection.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/6302322728140819377'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/6302322728140819377'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/java-garbage-collection.html' title='Java Garbage Collection'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-3201714043505452864</id><published>2010-10-29T22:45:00.017-07:00</published><updated>2010-10-29T22:46:03.302-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><title type='text'>OpenSUSE 10.3</title><content type='html'>&lt;p&gt;It&amp;#8217;s been quite some time since I last used my OpenSUSE (I have a dual-boot machine and do most of my research projects using Windows tools). Now I am looking for a job and UNIX familiarity seems a precious resource. So&amp;#8230; I switched back to OpenSUSE. I have been using SUSE since version 8. I tried Ubuntu again and again, the device driver problems bited me again and again while OpenSuSe always came to my rescure.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Here are something I did to set up the OpenSUSE 10.3 box as my daily development machine.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;1) &lt;strong&gt;Install Sun J2SE&lt;/strong&gt;. The default gcj is cool but I&amp;#8217;d prefer Sun&amp;#8217;s JDK more. Here is a reasonably good tutorial to set up J2SE: http://fedorasolved.org/browser-solutions/sun-jdk. Besides using update-alternatives to add java, I also added javac in a similar manner. &lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;There is one thing that I found incorrect in this tutorial: if you add his java.sh into /etc/profile.d/, this messed up the PATH variable somehow and gdm even cannot start correctly. So, instead I added these to my ~/.profile:&lt;br/&gt;&lt;code&gt;export JAVA&lt;em&gt;HOME=/opt/jdk1.6.0&lt;/em&gt;06&lt;br/&gt;export PATH=$PATH:$JAVA&lt;em&gt;HOME/bin&lt;br/&gt;export MANPATH=$MANPATH:$JAVA&lt;/em&gt;HOME/man&lt;br/&gt;&lt;/code&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;ol&gt;&lt;br/&gt;&lt;li&gt;&lt;strong&gt;Install &lt;a href="http://www.netbeans.org/"&gt;Netbeans&lt;/a&gt;&lt;/strong&gt; (as of writing, 6.1 is still RC2). Netbeans 6 caught up very quickly to Eclipse and it did a great job to integrate lots of useful things in nice packages. Since it also has good support for C/C++ development and Ruby, I decided to use it on OpenSuSe. &lt;/li&gt;&lt;br/&gt;&lt;/ol&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;However, no matter what I did, there are always problems during installation. First, even though there is only one installation wizard running, it always says &amp;#8220;there is another installation instance running, are you sure you want to start a new instance?&amp;#8221;, yes, of course. Then it dies and Bug-Buddy, a GUI-based bug reporting application shows up and installation wizard simply crashes. I found &lt;a href="http://blogs.sun.com/abhi/entry/netbeans_6_and_java_6"&gt;someone having the same problem&lt;/a&gt; and his solution is to uninstall Bug-Buddy and try installation again, it worked!!!&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;BTW, you can choose to download and install JDK together with Netbeans. In this case, you still need to add Java plugin to Firefox and update alternatives for java and javac.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;ol&gt;&lt;br/&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Install &lt;a href="http://www.aptana.com/"&gt;Aptana Studio&lt;/a&gt;&lt;/strong&gt;. This is my current Web application IDE. It support ajax, PHP, RoR, AIR, and iPhone development, covering all major ajax libraries you will find today. And its community version is FREE! You can forget about Dreamweaver, Frontpage, M$ Expression Web, etc. Well, if you are into ASP.NET development, probably you still need VS.NET though.&lt;/p&gt;&lt;/li&gt;&lt;br/&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Add several software update sources&lt;/strong&gt; (I installed OpenSUSE using a live Gnome CD): OpenSUSE non-open source and open source, Mozilla, Gnome stable, etc. With these update sources, you can install software unavailable to the live Gnome installation CD.&lt;/p&gt;&lt;/li&gt;&lt;br/&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Update Firefox to the latest stable version&lt;/strong&gt;. It is still 2.0.0.x as of now. I have been using FF3pre, code named Minefield for sometime on Windows now and it simply blew me away with performance and new features like smart URL address field. &lt;/p&gt;&lt;/li&gt;&lt;br/&gt;&lt;/ol&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Install these plugins for FF: Greasemonkey, BetterGmail2, Firebug, Session Manager, del.icio.us.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;ol&gt;&lt;br/&gt;&lt;li&gt;&lt;strong&gt;Update pidgin&lt;/strong&gt;, the IM application for linux, to latest stable version. Activate two plugins &amp;#8220;historys&amp;#8221; and &amp;#8220;conversion colors&amp;#8221;. The default font size is 12, too big for me and I changed it to 10. The default theme is quite ugly, especially the system tray icon. So, you can find a Pidgin theme on gnome-look made by Embrace. &lt;/li&gt;&lt;br/&gt;&lt;/ol&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Go download this Human Pidgin Theme (I guess it is made for Ubuntu based on colors) from &lt;a href="http://www.gnome-look.org/content/show.php/Human+Pidgin%2BGaim+Theme?content=59616"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Then, login as root. Unpack the package and you will see two directories: pidgin and Style. Use pidgin to replace /usr/share/pixmaps/pidgin directory, which contains original theme. Make a backup if you want to roll back later. The Style directory is a bit confusing and it actually adds a background image. To use it, simply copy pidgin_bg.jpg and .gtkrc-2.0 to your home directory. &lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Now, start pidgin and you will see a more polished interface.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;ol&gt;&lt;br/&gt;&lt;li&gt;&lt;strong&gt;Install new login window themes, gnome application window themes and mouse icon themes.&lt;/strong&gt; I like Mac themes but don&amp;#8217;t have the money right now to buy a Macbook Pro, so I can tune my OpenSUSE at least look similar.&lt;/li&gt;&lt;br/&gt;&lt;/ol&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;Application Themes: &lt;/strong&gt;Go to http://art.gnome.org/themes/gtk2/ first using Firefox. Then, open &amp;#8220;Appearance Preference&amp;#8221; window (computer-&gt;control center-&gt;Appearance (under look and feel). Then, just drag a theme to your &amp;#8220;Appearance Preference&amp;#8221; window and it will get installed automatically. Then, choose that newly installed theme. I am using Glossy P theme and it looks like Mac style.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;Login Themes: &lt;/strong&gt;login as root first. Type &amp;#8220;gdmsetup&amp;#8221; on the terminal and this opens up gdm settings. In &amp;#8220;Local&amp;#8221; tab, you will see currently installed login themes. Choose one you like.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Or, go to http://art.gnome.org/themes/gdm_greeter/, download a new login theme and install it in gdmsetup window. It says you can drag and drop to install, but I did not succeeded somehow and choosed &amp;#8220;Add&amp;#8230;&amp;#8221; to manually install the themes. I am using &amp;#8220;Sunergos Blue GDM Theme&amp;#8221; and I like it a lot, simple and beautiful.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;Mouse themes:&lt;/strong&gt; you can download a theme pack from gnome-looks.org and unpack it to ~/.icons. For example, mine icon pack name is Obsidian. Then, after you unpack it into .icons directory, it becomes ~/.icons/Obsidian, rename it to ~/.icons/default and logout and login to see the new effect. I am using a theme called &amp;#8220;Shere&lt;em&gt;Khan&lt;/em&gt;X&amp;#8221; to match the Mac window theme.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;You can also customize splash screen, but I will leave it for later.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-3201714043505452864?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/3201714043505452864/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/opensuse-103.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/3201714043505452864'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/3201714043505452864'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/opensuse-103.html' title='OpenSUSE 10.3'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-974256180952796748</id><published>2010-10-29T22:45:00.016-07:00</published><updated>2010-10-29T22:46:03.275-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><title type='text'>OpenSUSE 10.3 - Part 2</title><content type='html'>&lt;p&gt;There is one last software that I need to use daily, &lt;strong&gt;an email client&lt;/strong&gt;. I have been using &lt;a href="http://www.mozilla.com/en-US/thunderbird/"&gt;Thunderbird&lt;/a&gt; for quite some time on Windows and I am very happy about its interface and performance. &lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Our school email server gets quite slow sometimes and I use &lt;a href="http://www.washington.edu/alpine/"&gt;Alpine&lt;/a&gt; text-based email client. This is the open source version of the popular Pine email client on UNIX and people ported it to various other platforms including Windows. It is lightweight and has a great performance. &lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;So, which one to use on OpenSUSE? I am kinda lazy and copied over my .pinerc from Windows home directory to OpenSUSE home directory. The source code from Alpine website does not compile on my machine, complaining some strange problems and I directly downloaded a copy from &lt;a href="http://rpm.pbone.net/index.php3?stat=3&amp;amp;search=alpine&amp;amp;srodzaj=3"&gt;here&lt;/a&gt;. It installed very nicely and with my existing .pinerc, all my settings from Windows are back into action.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;However, I had a problem with &amp;#8220;backspace&amp;#8221; key. Instead of deleting the character before it, it deletes the character after it, which is the same behavior as delete key. This seems to be a known issue for Linux keyboard mapping and the correct &amp;#8220;backspace&amp;#8221; behavior is ctrl+H. I tried to set default editor to &lt;a href="http://www.nano-editor.org/"&gt;nano&lt;/a&gt; and avoid using &lt;a href="http://en.wikipedia.org/wiki/Pico_(text_editor)"&gt;pico&lt;/a&gt;, the default editor that comes with Alpine, but it did not work.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;So, I had to choose another email client. Since &lt;a href="http://www.gnome.org/projects/evolution/"&gt;Evolution&lt;/a&gt; is the default email client, I decided to give it a try. But very disappointedly, the performance really sucks and it took very long to render the interface as well as email content. Although it has nice features like notes, schedule, contacts, etc., I gave it up right away.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Finally, I installed and configured Thunderbird. World is in peace now. It runs smoothly and grabs content very fast. To emulate the Mac style, I also installed &lt;a href="https://addons.mozilla.org/en-US/thunderbird/addon/2694"&gt;CrossOver X theme&lt;/a&gt; for Thunderbird. There are some other nice Mac-related themes such as CrossOver and Cutebird. Now, it feels that I am using a Mac now, haha!&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;=====================&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Since I use English and Chinese at the same time, I need a Chinese input tool. On WindowsXP I use &lt;a href="http://tools.google.com/pinyin/"&gt;Google Pinyin&lt;/a&gt; and on Win2003 Server I use &lt;a href="http://www.sogou.com/pinyin/"&gt;sogo&lt;/a&gt;. &lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;SCIM is one of the language input platform available and it supports a wide variety of input languages. Someone ported FIT Chinese input tool onto linux and it is called &lt;a href="http://code.google.com/p/fitx/"&gt;Fitx&lt;/a&gt;. It has a sister WeFit, which is the most popular Chinese input software on iPhone.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;To install Fitx with least hassle, go to &lt;a href="http://software.opensuse.org/search"&gt;openSUSE software search engine&lt;/a&gt; and search for fitx, then click &amp;#8220;1-click install&amp;#8221; button. When the installation is finished, log out and log in to see it in action. You can configure hot keys to activate and deactivate Fitx.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-974256180952796748?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/974256180952796748/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/opensuse-103-part-2.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/974256180952796748'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/974256180952796748'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/opensuse-103-part-2.html' title='OpenSUSE 10.3 - Part 2'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-4200426487548254813</id><published>2010-10-29T22:45:00.015-07:00</published><updated>2010-10-29T22:46:03.253-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><title type='text'>OpenSUSE extreme makeover</title><content type='html'>&lt;p&gt;First, SCIM (fitx) did not work out well for me. It works but even after I have completed Chinese input, the floating window still dangles around and giving me suggestions for the same word over and over again. Plus, I heard people say that some applications might crash SCIM input tool.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;So, I simply uninstalled SCIM and got Fcitx, a lightweight input tool. This time, everything worked out very beautifully. The easiest way to install is from &lt;a href="http://software.opensuse.org/search"&gt;OpenSUSE online search&lt;/a&gt; and use &amp;#8220;one-click install&amp;#8221;. The homepage for Fcitx is &lt;a href="http://www.fcitx.org/main/"&gt;here&lt;/a&gt; and people are really saying good words about it.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;============= Make your OpenSUSE look like Mac ================&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;There are many tutorials from Google and &lt;a href="http://www.howtoforge.com/mac4lin_make_linux_look_like_a_mac"&gt;this&lt;/a&gt; is one of the best I found that treats every aspects including bootup screen, GDM login window, GDM splash picture, window theme, Compiz/Fusion theme, Firefox theme, pidgin theme, music player theme, wallpapers, etc. This is an open source project called Mac4Lin, really solid job!&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;I also tried the docking application &lt;a href="https://launchpad.net/awn"&gt;Avant Window Navigator&lt;/a&gt;, which emulates Mac dock for application launchers. Maybe I did not configure it right, it only shows icons representing active application windows, not application launchers that you can use to open applications. So, I did not install this docking application.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Other parts are perfectly fine and I am quite satisfied with the look and feel of my OpenSUSE now. Maybe someday when I save enough money, I will go get a Macbook Pro&amp;#8230;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-4200426487548254813?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/4200426487548254813/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/opensuse-extreme-makeover.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/4200426487548254813'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/4200426487548254813'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/opensuse-extreme-makeover.html' title='OpenSUSE extreme makeover'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-7782732017707030827</id><published>2010-10-29T22:45:00.014-07:00</published><updated>2010-10-29T22:46:03.233-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><title type='text'>instanceof OR getClass()</title><content type='html'>&lt;p&gt;First, wanna share a nice vim/gvim theme called &lt;a href="http://dengmao.wordpress.com/2007/01/22/vim-color-scheme-wombat/"&gt;Wombat&lt;/a&gt;. Just download it and put it into $HOME/.vim/colors and set&lt;code&gt;colors wombat&lt;/code&gt; in your $HOME/.vimrc and .gvimrc.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;I have seen several interview questions asking you to override equals() method for your class. There are two ways to check the classname. Take a Foo class for example:&lt;br/&gt;&lt;code&gt;&lt;br/&gt;public class Foo{&lt;br/&gt;  private int id;&lt;br/&gt;  public boolean equals(Object o){&lt;br/&gt;    if (this == o)&lt;br/&gt;      return true;&lt;br/&gt;    &lt;strong&gt;if (!(o instanceof Foo))&lt;/strong&gt;&lt;br/&gt;      return false;&lt;br/&gt;    if (o == null)&lt;br/&gt;      return false;&lt;br/&gt;    Foo other = (Foo)o;&lt;br/&gt;    return (this.id == other.id) ? true : false;&lt;br/&gt;}&lt;/code&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Another way:&lt;br/&gt;&lt;code&gt;&lt;br/&gt;public class Foo{&lt;br/&gt;  private int id;&lt;br/&gt;  public boolean equals(Object o){&lt;br/&gt;    if (this == o)&lt;br/&gt;      return true;&lt;br/&gt;    &lt;strong&gt;if (getClass() != o.getClass())&lt;/strong&gt;&lt;br/&gt;      return false;&lt;br/&gt;    if (o == null)&lt;br/&gt;      return false;&lt;br/&gt;    Foo other = (Foo)o;&lt;br/&gt;    return (this.id == other.id) ? true : false;&lt;br/&gt;}&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Basically, it is a question of using instanceof or getClass(). Josh Bloch in his Effective Java and his interview with Altima argues that instanceof should be used because of &lt;a href="http://en.wikipedia.org/wiki/Liskov_substitution_principle"&gt;Liskov substitution principle&lt;/a&gt;, meaning that one subclass object should be able to replace occurrences of its superclass object without making changes for correctness. &lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;a href="http://www.artima.com/weblogs/viewpost.jsp?thread=4744"&gt;Cay Horstmann&lt;/a&gt; does not agree with the use of instanceof and argues that getClass() method should be used instead to enforce the contract of equals method. He presents a superclass-subclass example where reflexive contract for equals method is broken: parent.equals(child) is true, but child.equals(parent) is false if we stick to the instanceof approach.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;I think with some special conditional checks on the inheritance structure, you can still use instanceof and satisfy reflexive contract. But getClass() is much simpler.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;So, basically, the question is like this: if Eric is a manager, he is represented as an object &lt;strong&gt;e&lt;/strong&gt; of Employee class and an object &lt;strong&gt;m&lt;/strong&gt; of Manager class which extends Employee class. Do you think e equals m (because they are actually representing a same person, using instanceof approach) or do you think they are not equals (because they are of different classes, using getClass() approach)?&lt;/code&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-7782732017707030827?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/7782732017707030827/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/instanceof-or-getclass.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/7782732017707030827'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/7782732017707030827'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/instanceof-or-getclass.html' title='instanceof OR getClass()'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-7326835944934300537</id><published>2010-10-29T22:45:00.013-07:00</published><updated>2010-10-29T22:46:03.213-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web Prog.'/><title type='text'>imagick for XAMPP on Mac Leopard</title><content type='html'>&lt;p&gt;There are different options to install/use PHP on Mac Leopard: use the default installation, use MacPort to install, or use XAMPP.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;I like the all-in-one bundle XAMPP, it is easy to manage and includes most commonly used options. So, I use it for the most of the time. However, when I need to install imagick, a PHP wrapper for ImageMagick, I got into some troubles.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;First, this package is not available via PEAR or PECL (PECL got into some errors). So, I end up manually compile imagick and copy the imagick.so into XAMPP extension directory. Here is what I did:&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;ol&gt;&lt;br/&gt;&lt;li&gt;change PATH to use default Leopard PHP installation, i.e. put /usr/bin ahead of XAMPP bin directory in PATH setting&lt;/li&gt;&lt;br/&gt;&lt;li&gt;use MacPort to install ImageMagick (assume you have MacPort installed, Yahoo! it if you did not know how to)&lt;/li&gt;&lt;br/&gt;&lt;li&gt;go to http://pecl.php.net/package/imagick, and find out the latest release&lt;/li&gt;&lt;br/&gt;&lt;li&gt;manually build imagick and copy to XAMPP PHP extension directory (assuming using PHP5)&lt;br/&gt;&lt;code&gt;&lt;br/&gt;curl -O http://pecl.php.net/get/imagick-2.2.2RC1.tgz&lt;br/&gt;tar xvfz imagick-2.2.2RC1&lt;br/&gt;cd imagick-2.2.2RC1&lt;br/&gt;phpize&lt;br/&gt;./configure --with-imagick=/opt/local &lt;br/&gt;make&lt;br/&gt;sudo make install (we are using /usr/bin/php, so the imagick.so is created in /usr/lib/php/extensions/no-debug-non-zts-20060613/)&lt;br/&gt;sudo cp /usr/lib/php/extensions/no-debug-non-zts-20060613/imagick.so /Applications/xampp/xamppfiles/lib/php/php5/extensions/no-debug-non-zts-20060613/imagick.so&lt;br/&gt;&lt;/code&gt;&lt;/li&gt;&lt;br/&gt;&lt;li&gt;edit /Applications/xampp/etc/php.ini, find &amp;#8220;Dynamic Extensions&amp;#8221; block, add&lt;br/&gt;&lt;code&gt;extension=imagick.so&lt;/code&gt;&lt;br/&gt;6. testing, add this test.php file to /Applications/xampp/htdocs and try it at http://localhost/test.php, you will see this jpg turned 45 degree clockwise (get santa-claus.jpg from &lt;a href="http://www.purseblog.com/images/santa-claus.jpg"&gt;here&lt;/a&gt;)&lt;br/&gt;&lt;code&gt;&lt;br/&gt;&lt; ?php&lt;br/&gt;$img = new Imagick('santa-claus.jpg');&lt;br/&gt;$img-&gt;rotateImage(&amp;#8217;#fff&amp;#8217;, 45);&lt;br/&gt;header(&amp;#8217;Content-type: image/jpeg&amp;#8217;);&lt;br/&gt;echo $img;&lt;br/&gt;?&gt;&lt;br/&gt;&lt;/code&gt;&lt;br/&gt;&lt;/li&gt;&lt;br/&gt;&lt;/ol&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;Reference:&lt;/strong&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;ul&gt;&lt;br/&gt;&lt;li&gt;&lt;a href="http://davidwinter.me.uk/articles/2008/11/22/php5-lighttpd-and-imagick-on-mac-os-x-leopard/"&gt;Install PHP5, lighttpd and Imagick on Mac OSX Leopard&lt;/a&gt; (talks about using MacPorts to install these things)&lt;/li&gt;&lt;br/&gt;&lt;li&gt;&lt;a href="http://translate.google.com/translate?hl=en&amp;#038;sl=ja&amp;#038;u=http://blog.rakugaki.jp/archives/20081106,32.html&amp;#038;sa=X&amp;#038;oi=translate&amp;#038;resnum=8&amp;#038;ct=result&amp;#038;prev=/search%3Fq%3Dchecking%2BImageMagick%2BMagickWand%2BAPI%2Bconfiguration%2Bprogram...%2Bconfigure:%2Berror:%2Bnot%2Bfound.%2BPlease%2Bprovide%2Ba%2Bpath%2Bto%2BMagickWand-config%2Bor%2BWand-config%2Bprogram%26hl%3Den%26client%3Dsafari%26rls%3Den-us"&gt;Mac with PHP / Imagick to install&lt;/a&gt;&lt;/li&gt;&lt;br/&gt;&lt;li&gt;&lt;a href="http://pecl.php.net/package/imagick"&gt;PECL::Package::imagick&lt;/a&gt;&lt;/li&gt;&lt;br/&gt;&lt;li&gt;&lt;a href="http://www.imagemagick.org/script/binary-releases.php#macosx"&gt;Install ImageMagick on Mac&lt;/a&gt;&lt;/li&gt;&lt;br/&gt;&lt;li&gt;&lt;a href="http://php.oregonstate.edu/manual/en/install.pecl.phpize.php"&gt;Compiling shared PECL extensions&lt;/a&gt;&lt;/li&gt;&lt;br/&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-7326835944934300537?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/7326835944934300537/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/imagick-for-xampp-on-mac-leopard.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/7326835944934300537'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/7326835944934300537'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/imagick-for-xampp-on-mac-leopard.html' title='imagick for XAMPP on Mac Leopard'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-8205973369449631131</id><published>2010-10-29T22:45:00.012-07:00</published><updated>2010-10-29T23:42:52.714-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iOS'/><category scheme='http://www.blogger.com/atom/ns#' term='Apple'/><title type='text'>iPhone notes</title><content type='html'>Getting interested in iPhone development after I hacked a 2G iPhone recently. Just ordered P&lt;a href="http://www.amazon.com/Programming-Objective-C-2-0-Developers-Library/dp/0321566157"&gt;rogramming in Objective-C 2.0&lt;/a&gt; from Amazon, Objective-C seems to be a quite difficult yet powerful language with a lot of nice OO features.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Here are two nice tutorials from Cocoa Dev Central:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;a href="http://cocoadevcentral.com/articles/000081.php"&gt;C Language Tutorial for Cocoa&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://cocoadevcentral.com/d/learn_objectivec/"&gt;Learn Objective-C&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-8205973369449631131?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/8205973369449631131/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/iphone.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/8205973369449631131'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/8205973369449631131'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/iphone.html' title='iPhone notes'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-1319450840256245057</id><published>2010-10-29T22:45:00.011-07:00</published><updated>2010-10-29T22:46:03.162-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='Image Processing'/><title type='text'>Use Imagick to create images with transparent canvas</title><content type='html'>&lt;p&gt;&lt;strong&gt;update: just found an easier way to create a transparent canvas &lt;img src='http://woshiadai.blogsome.com/wp-images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /&gt; &lt;br/&gt;so, you can pretty much ignore all these options listed below now&lt;/strong&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;code&gt;&lt;br/&gt;$im = new Imagick();&lt;br/&gt;$im-&gt;newImage(100, 200, new ImagickPixel('transparent')); // use this predefined transparent color string&lt;br/&gt;$im-&gt;setImageFormat('png32'); &lt;br/&gt;//$im-&gt;setImageFormat('gif');&lt;br/&gt;//$im-&gt;setImageFormat('jpg'); // note that jpg does not support transparency, so you see a default black background&lt;br/&gt;&lt;/code&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;==== ignore the rest of the post ====&lt;/strong&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;According to &lt;a href="http://www.imagemagick.org/Usage/canvas/#other"&gt;ImageMagick Examples canvas page&lt;/a&gt;, there are multiple ways to create a transparent canvas.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;It is a pity that Imagick PHP library lacks enough documentation, so I had to try my luck with it. For example, I want to create a transparent background, then copy an image with transparency on top of it.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;code&gt;&lt;br/&gt;&amp;lt; ?php&lt;br/&gt;try&lt;br/&gt;{&lt;br/&gt;    $icon = new Imagick('play.png');&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;pre&gt;&lt;code&gt;$im = new Imagick();&lt;br/&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;// put code here to create the transparent canvas, use options below&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;pre&gt;&lt;code&gt;$im-&amp;gt;compositeImage($icon, Imagick::COMPOSITE_COPY, 0, 0);&lt;br/&gt;&lt;br/&gt;header('Content-Type: image/png');&lt;br/&gt;echo $im;&lt;br/&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;}&lt;br/&gt;catch (Exception $ex)&lt;br/&gt;{&lt;br/&gt;    echo &amp;#8216;Exception: &amp;#8216; . $ex-&gt;getMessage() . &amp;#8220;\n&amp;#8221;;&lt;br/&gt;    echo $ex-&gt;getTraceAsString();&lt;br/&gt;}&lt;br/&gt;?&gt;&lt;br/&gt;&lt;/code&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;a) setImageOpacity&lt;br/&gt;&lt;code&gt;&lt;br/&gt;    $im-&gt;newImage(200, 200, '#000000', 'png');&lt;br/&gt;    $im-&gt;setImageOpacity(0.0);&lt;br/&gt;&lt;/code&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;b) paintTransparentImage&lt;br/&gt;&lt;code&gt;&lt;br/&gt;    $transparent = new ImagickPixel('#000000');&lt;br/&gt;    $im-&gt;newImage(200, 200, '#000000', 'png');&lt;br/&gt;    $im-&gt;paintTransparentImage($transparent, 0, 10);&lt;br/&gt;&lt;/code&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;c) matteFloodfillImage&lt;br/&gt;&lt;code&gt;&lt;br/&gt;$transparent = new ImagickPixel('#000000');&lt;br/&gt;$im-&gt;newImage(200, 200, '#000000', 'png');&lt;br/&gt;$im-&gt;setImageBorderColor($transparent);&lt;br/&gt;$im-&gt;matteFloodfillImage(0.0, 0.0, $transparent, 200, 200);&lt;br/&gt;&lt;/code&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;d) thresholdImage &lt;br/&gt;&lt;code&gt;&lt;br/&gt;$im-&gt;newImage(200, 200, '#000000', 'png');&lt;br/&gt;$im-&gt;thresholdImage(-1, Imagick::CHANNEL_ALPHA);&lt;br/&gt;&lt;/code&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;e) fxImage&lt;br/&gt;&lt;code&gt;&lt;br/&gt; $im-&gt;newImage(200, 200, '#000000', 'png');&lt;br/&gt; $im = $im-&gt;fxImage('0', Imagick::CHANNEL_ALPHA);&lt;br/&gt;&lt;/code&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;For ImageMagick 6.2.9 12/17/07 Q16, Imagick 2.2.2RC1&lt;/strong&gt;&lt;br/&gt;a) does not work at all&lt;br/&gt;e) gives the correct result, transparent background for play.png and transparent background for the whole image&lt;br/&gt;others give transparent background for play.png, but black background for the whole image&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;For ImageMagick 6.4.9-6 2009-03-25 Q16, Imagick 2.2.2&lt;/strong&gt;&lt;br/&gt;a) b) gives transparent background for play.png and whole image&lt;br/&gt;c) gives an exception&lt;br/&gt;others give white background for play.png, black background for whole image&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;Images (note that you may want to save the images and open it in a viewer with non-white background to see the difference, especially the last two):&lt;/strong&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;ol&gt;&lt;br/&gt;&lt;li&gt;Desired ouptput: transparent play button background and transparent canvas:&lt;br/&gt;&lt;img src='http://woshiadai.blogsome.com/images/transparent.php.png' alt='desired output' /&gt;&lt;/li&gt;&lt;br/&gt;&lt;li&gt;White play button background and black canvas&lt;br/&gt;&lt;img src='http://woshiadai.blogsome.com/images/transparent.php2.png' alt="white play bg, black canvas"/&gt;&lt;/li&gt;&lt;br/&gt;&lt;li&gt;Transparent play button background and black canvas&lt;br/&gt;&lt;img src='http://woshiadai.blogsome.com/images/transparent.php3.png' alt="transparent play bg, black canvas"/&gt;&lt;/li&gt;&lt;br/&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-1319450840256245057?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/1319450840256245057/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/use-imagick-to-create-images-with.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/1319450840256245057'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/1319450840256245057'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/use-imagick-to-create-images-with.html' title='Use Imagick to create images with transparent canvas'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-3823867340605730897</id><published>2010-10-29T22:45:00.010-07:00</published><updated>2010-10-29T22:46:03.146-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='Image Processing'/><title type='text'>Transparent gif with smooth edge using Imagick</title><content type='html'>&lt;p&gt;&lt;p&gt;If you have a PNG with transparency and then you want to convert it to a GIF with transparency preserved. Since GIF has only 1-bit transparency, the edge will look jacky. However, if you know a color that will be used as solid background color or an average color for a gradient background, you can still achieve a smooth edge for the transparent gif.  Here is how (assuming the original PNG is circle.png, the edge antialias color is RED):  &lt;/p&gt;  &amp;lt;?php $red = new ImagickPixel(&amp;#8217;red&amp;#8217;); $transparent = new ImagickPixel(&amp;#8217;transparent&amp;#8217;); $im = new Imagick(&amp;#8217;circle.png&amp;#8217;); $im-&amp;gt;setImageBorderColor($red); $im-&amp;gt;frameImage($red, 0, 0, 0, 0); //or use $im-&amp;gt;borderImage($red, 0.0, 0.0); $im-&amp;gt;paintOpaqueImage($red, $transparent, 0.0); //replacing RED color with transparent color $im-&amp;gt;setImageFormat(&amp;#8217;gif&amp;#8217;); header(&amp;#8217;Content-Type: image/gif&amp;#8217;); echo $im; ?&amp;gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt;   &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-3823867340605730897?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/3823867340605730897/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/transparent-gif-with-smooth-edge-using.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/3823867340605730897'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/3823867340605730897'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/transparent-gif-with-smooth-edge-using.html' title='Transparent gif with smooth edge using Imagick'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-9141358485688936193</id><published>2010-10-29T22:45:00.009-07:00</published><updated>2010-10-29T22:46:03.125-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><title type='text'>cachegrind for Mac</title><content type='html'>&lt;p&gt;Start to learn how to do profiling and optimization for PHP code. Found Kcachegrind is handy to visualize XDebug data. There are other similar cachegrind tools:&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;ol&gt;&lt;br/&gt;&lt;li&gt;&lt;p&gt;&lt;a href="http://kcachegrind.sourceforge.net/html/Home.html"&gt;Kcachegrind&lt;/a&gt;: you can get it from &lt;a href="http://www.macports.org/ports.php?by=name&amp;amp;substr=kcachegrind"&gt;Macports&lt;/a&gt;, check out &lt;a href="http://www.macports.org/install.php"&gt;this&lt;/a&gt; if you don&amp;#8217;t know how to get started with Macports. Note this might take a long time to install. In my case, I also need to install &lt;a href="http://www.macports.org/ports.php?by=library&amp;amp;substr=graphviz"&gt;graphviz&lt;/a&gt; to see the call graph.&lt;/p&gt;&lt;/li&gt;&lt;br/&gt;&lt;li&gt;&lt;p&gt;&lt;a href="http://www.maccallgrind.com/"&gt;MacCallGrind&lt;/a&gt;: this displays the data in a table structure.&lt;/p&gt;&lt;/li&gt;&lt;br/&gt;&lt;li&gt;&lt;p&gt;&lt;a href="http://code.google.com/p/cachegrindvisualizer/"&gt;cachegrindvisualizer&lt;/a&gt;: this is a google code project, installed/coded using Adobe AIR, fairly cool UI. If you only need to see the call graph, you probably don&amp;#8217;t need Kcachegrind anymore.&lt;/p&gt;&lt;/li&gt;&lt;br/&gt;&lt;li&gt;&lt;p&gt;&lt;a href="http://code.google.com/p/webgrind/"&gt;webgrind&lt;/a&gt;: a Web UI for the cachegrind data, also shows a table-like structure.&lt;/p&gt;&lt;/li&gt;&lt;br/&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-9141358485688936193?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/9141358485688936193/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/cachegrind-for-mac_29.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/9141358485688936193'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/9141358485688936193'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/cachegrind-for-mac_29.html' title='cachegrind for Mac'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-58281982466793319</id><published>2010-10-29T22:45:00.008-07:00</published><updated>2010-10-29T22:46:03.093-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='Image Processing'/><title type='text'>ICO image processing with Imagick</title><content type='html'>&lt;p&gt;Used to have an issue with Imagick when I convert ICO image into png. Somehow when I create the Imagick object from image content string, the final result is a crappy image. But when I create the Imagick object directly from a file, it works fine, with only the problem of a different size.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;So, I filed a bug (http://pecl.php.net/bugs/bug.php?id=15701), but still got no resolution. &lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Got some time recently and did a bit research, found that the problem is with the ICO format: it may contain the same image with different sizes. So, when you convert the format directly, it will not work. It is similar in the case when you try to convert an animated GIF image into JPG or PNG, you get one of the frames instead of an animated image.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;There are two solutions:&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;ol&gt;&lt;br/&gt;&lt;li&gt;use foreach($ico as $im) loop to get one image and just convert that image&lt;/li&gt;&lt;br/&gt;&lt;li&gt;use flattenImages function before the format conversion&lt;/li&gt;&lt;br/&gt;&lt;/ol&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Note that after the format conversion, the image dimensions might be different from when you directly open the ICO image from a browser or image viewer. You probably need to resize the image manually.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;a href="http://pecl.php.net/bugs/bug.php?id=15701"&gt;The bug report&lt;/a&gt; has some code snippets if you want to try it out.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-58281982466793319?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/58281982466793319/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/ico-image-processing-with-imagick_29.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/58281982466793319'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/58281982466793319'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/ico-image-processing-with-imagick_29.html' title='ICO image processing with Imagick'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-8312101366587171647</id><published>2010-10-29T22:45:00.007-07:00</published><updated>2010-10-29T22:46:03.057-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Mac'/><category scheme='http://www.blogger.com/atom/ns#' term='Apple'/><title type='text'>Screen Sharing</title><content type='html'>&lt;p&gt;I have been using Mac for quite a while, but did not have much time to explore many of its features. Today, I managed to find how to do easy VNC to my linux box using Screen Share application, a hidden treasure.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;First, &lt;a href="http://www.macworld.com/article/131094/2007/12/screensharepower.html"&gt;follow the instructions here&lt;/a&gt; to set up the Screen Share application. Somehow I could get the advanced toolbar working.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Second, you need to set up the VNC server on your linux box. In my case, Redhat Enterprise comes with VNC server installed already. All I need is to configure it properly. &lt;a href="http://www.redhat.com/magazine/006apr05/features/vnc/"&gt;Follow this nicely written tutorial &lt;/a&gt;to start your VNC server. There are two ways in this tutorial: use the build-in remote desktop setup, or the DIY configuration. I chose the 2nd option since it is much flexible and the first one did not really worked for me.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Third, connect to your VNC server. In my case, I just typed in hostname:5091 and clicked connect in Screen Sharing, then it starts working, really cool!&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;I think you should be able to do the same with a Windows machine running VNC server, but I did not try that.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-8312101366587171647?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/8312101366587171647/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/screen-sharing_29.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/8312101366587171647'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/8312101366587171647'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/screen-sharing_29.html' title='Screen Sharing'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-2325322762494304407</id><published>2010-10-29T22:45:00.006-07:00</published><updated>2010-10-29T22:46:03.015-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Mac'/><category scheme='http://www.blogger.com/atom/ns#' term='Apple'/><title type='text'>Subversion and SSH setup in Netbeans 6.7 RC3 on Mac OS X</title><content type='html'>&lt;p&gt;Netbeans has been making a lot of progress since version 6 and the &lt;a href="http://download.netbeans.org/netbeans/6.7/rc/"&gt;latest 6.7 RC3&lt;/a&gt; is even better. For those Eclipse fans, I strongly suggest that you check out Netbeans. It feels much faster and consumes less memory. The plugins are more organized and easy to manage (I think the plugin management in Eclipse is really messy).&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;The PHP plugin for Netbeans is out of beta and it is quite user friendly and versatile. So, I decided to switch from PDT to Netbeans for my PHP development.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Netbeans comes with Subversion support. However, it is not so smooth to set up Subversion over SSH on Mac OS X due to the ssh-askpass problem. This is a Mac OS X issue, not a Netbeans issue. &lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;ol&gt;&lt;br/&gt;&lt;li&gt;Download and install Netbeans 6.7 RC3 (as of June 25, 2009).&lt;br/&gt;&lt;/li&gt;&lt;li&gt;The subversion that comes with Mac OS X (/usr/bin/svn, 1.4.4 (r25188)) is quite outdated and it has problems working with newer versions of the SVN server, probably due to different format of the metadata. You need to use MacPorts to install a more recent subversion (if you don&amp;#8217;t know how to install MacPorts, check out &lt;a href="http://www.macports.org/install.php"&gt;this&lt;/a&gt;). Just type this in your terminal: &lt;code&gt;port install subversion&lt;/code&gt;, it might take a white. The subversion from MacPorts is installed in /opt/local/bin, so make sure you put /opt/local/bin before /usr/bin in your PATH environment variable.&lt;br/&gt;&lt;/li&gt;&lt;li&gt;Add SVNROOT and SVN_SSH environment variables to your .bashrc: &lt;br/&gt;&lt;code&gt;&lt;br/&gt;export SVNROOT=svn+ssh://your_svn_server/ &lt;br/&gt;export export SVN_SSH=/usr/bin/ssh&lt;br/&gt;&lt;/code&gt;&lt;br/&gt;&lt;/li&gt;&lt;li&gt;Launch Netbeans, go to preferences-&gt;Miscellaneous-&gt;Versioning-&gt;Subversion, for &amp;#8220;path to SVN executable file&amp;#8221;, enter /opt/local/bin&lt;br/&gt;&lt;/li&gt;&lt;li&gt;Now, it seems like everything is ready. However, when you try to do update/diff and other operations, you get error: ssh_askpass: exec(/usr/libexec/ssh-askpass): No such file or directory. I did some Yahoo! search and the problem is that Netbeans wants to communicate with SVN server over ssh without asking your password using ssh-askpass, but it is not available. This is a general ssh issue on Mac OS X.&lt;br/&gt;&lt;br/&gt;I found two solutions: &lt;a href="http://paulofierro.com/archives/506/"&gt;solution 1&lt;/a&gt; and &lt;a href="http://www.retep.org/2009/04/ssh-askpass-on-osx-105.html"&gt;solution 2&lt;/a&gt;. I only tried solution 2 and it worked perfectly for me. Here are the simple steps:&lt;br/&gt;&lt;br/&gt;a) download script from here (note that I had to add .jpg since blogsome only supports image upload) and save it in /usr/libexec. Change ssh-askpass script to executable: &lt;br/&gt;&lt;code&gt;wget wget http://woshiadai.blogsome.com/images/sshaskpass.jpg -O ssh-askpass &lt;br/&gt;sudo cp ssh-askpass /usr/libexec/ssh-askpass&lt;br/&gt;sudo chmod a+x /usr/libexec/ssh-askpass&lt;br/&gt;&lt;/code&gt;&lt;br/&gt;b) add two more environment variables: &lt;br/&gt;&lt;code&gt;&lt;br/&gt;export SSH_ASKPASS=macos-askpass &lt;br/&gt;export DISPLAY=:0&lt;br/&gt;&lt;/code&gt;&lt;br/&gt;&lt;br/&gt;&lt;/li&gt;&lt;li&gt;Finally, you can use subversion actions from inside Netbeans. You will be asked for password for the first time, then it will be remembered for future activities.&lt;br/&gt;&lt;br/&gt;Enjoy the Netbeans! &lt;img src='http://woshiadai.blogsome.com/wp-images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /&gt; &lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-2325322762494304407?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/2325322762494304407/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/subversion-and-ssh-setup-in-netbeans-67_29.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/2325322762494304407'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/2325322762494304407'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/subversion-and-ssh-setup-in-netbeans-67_29.html' title='Subversion and SSH setup in Netbeans 6.7 RC3 on Mac OS X'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-2582138400675200152</id><published>2010-10-29T22:45:00.005-07:00</published><updated>2010-10-29T22:46:02.964-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Mac'/><category scheme='http://www.blogger.com/atom/ns#' term='Apple'/><title type='text'>upgrading to snow leopard</title><content type='html'>&lt;p&gt;Finally, I decided to do the upgrade. It was not as smooth as it looks, especially that I turned on 64 bit as default. Normally, SL runs in 32 bit mode, you need to hold 6 and 4 keys during the boot process to get into 64 bit mode. But you can also change the config to run it as default, instruction is &lt;a href="http://www.overclock.net/mac/564147-how-enable-64-bit-default-os.html" target="_blank"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Most of the applications still runs fine, here is a few exceptions that I encountered and luckily all of them have solutions so far. &lt;a href="http://snowleopard.wikidot.com/" target="_blank"&gt;Here&lt;/a&gt; is a list of compatibility check for SL, note that it is not the default 64 bit mode.&amp;nbsp;&lt;/p&gt;&lt;p&gt;1. menumeter: This is a small monitoring tool that I use every day, to check network, CPU, memory usage. Good thing is it displays info on the menu bar. Old installation not working anymore, just &lt;a href="http://snowleopard.wikidot.com/" target="_blank"&gt;get the latest&lt;/a&gt; and reinstall.&lt;/p&gt;&lt;p&gt;2. delicioussafari: This is a plugin for Safari that saves and opens your delicious online bookmarks. To fix the issue, just &lt;a href="http://delicioussafari.com/" target="_blank"&gt;get the latest and reinstall&lt;/a&gt;. The new version even has a new BMW-like button &lt;img src='http://woshiadai.blogsome.com/wp-images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /&gt; &amp;nbsp;&lt;/p&gt;&lt;p&gt;3. macfuse: This is a handy tool to help mount various file systems. Here is &lt;a href="http://rackerhacker.com/2009/08/28/fix-macfusion-on-snow-leopard/" target="_blank"&gt;the fix for 32 bit SL mode&lt;/a&gt;, however it did not work for 64 bit mode. You can use &lt;a href="http://groups.google.com/group/macfuse/msg/f7de55623e8b8f57?" target="_blank"&gt;this pre-compiled dmg&lt;/a&gt; for 64 bit mode. It runs great for me. You can also roll your own following the instructions &lt;a href="http://www.5dollarwhitebox.org/drupal/node/97" target="_blank"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;4. TextMate: It has &lt;a href="http://wiki.macromates.com/Troubleshooting/SnowLeopard" target="_blank"&gt;lots of issues&lt;/a&gt; with SL, especially due to the upgrade of Ruby. First, try to get the latest release possible. But still, I am having issues with&amp;nbsp;&lt;span class="Apple-style-span"&gt;⌘R. &lt;/span&gt;Textmate blog has some workarounds and I have not tried them yet, hopefully they will fix the problems in the next release.&lt;/p&gt;&lt;p&gt;5. MacPorts: This is another thing that caused many headache until I found &lt;a href="http://www.libertypages.com/clarktech/?p=743" target="_blank"&gt;this nice blog&lt;/a&gt; that suggests a fresh install. It worked all fine. However, occasionally, some ports will still report error of unmatched architecture. This blog also covers &amp;quot;Upgrading to Snow Leopard Part 1 to 7&amp;quot;, talking about &lt;a href="http://www.libertypages.com/clarktech/?p=719" target="_blank"&gt;python&lt;/a&gt;, &lt;a href="http://www.libertypages.com/clarktech/?p=751" target="_blank"&gt;mysql&lt;/a&gt; and other upgrade &lt;a href="http://www.libertypages.com/clarktech/?p=736" target="_blank"&gt;tips&lt;/a&gt;, very handy! He also talks about &lt;a href="http://www.libertypages.com/clarktech/?p=777" target="_blank"&gt;building 32 bit packages using arch and lipo&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;6. VMWare Fusion: The old 2.x version even won&amp;#8217;t start in 64 bit and asks you to restart SL in 32 bit. So, you need to get the latest &lt;a href="http://www.vmware.com/products/fusion/" target="_blank"&gt;Fusion 3.0&lt;/a&gt;. The upgrade is not free.&lt;/p&gt;&lt;p&gt;After a week of being little white mouse running 64 bit SL. I&amp;#8217;d say maybe running 64 bit does cause more issues than benefits. But we can debate over it. &lt;a href="http://arstechnica.com/apple/reviews/2009/08/mac-os-x-10-6.ars/5" target="_blank"&gt;Here&lt;/a&gt; is a good intro if you are interested.&lt;/p&gt;&lt;p&gt;The best part for me is that I got back 12G free space, very interesting. It seems to be a combination of using 1000 for 1024 in calculation and cut the new OS installation size.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-2582138400675200152?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/2582138400675200152/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/upgrading-to-snow-leopard_29.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/2582138400675200152'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/2582138400675200152'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/upgrading-to-snow-leopard_29.html' title='upgrading to snow leopard'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-2166373203679151029</id><published>2010-10-29T22:45:00.004-07:00</published><updated>2010-10-29T22:46:02.817-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='Mac'/><title type='text'>set up PHP and Apache on Snow Leopard</title><content type='html'>&lt;p&gt;It took me quite some trouble to get imagick working on the snow leopard.&amp;nbsp;&lt;/p&gt;&lt;p&gt;First, I tried to install xampp and mamp, which are two easy ways to get PHP, apache, mysql up and running. I used to have no issue with xampp, but the snow leopard has problems with locally complied imagick.so in xampp. So, I tried mamp as well, imagick simply does not work and kept getting me &amp;quot;cannot find Imagick class&amp;quot; error.&lt;/p&gt;&lt;p&gt;So, I had to try to use the PHP and apache that ships with snow leopard. I simply followed the instructions in &lt;a href="http://blog.xeonxai.com/category/tools/apache/" target="_blank"&gt;this blog post&lt;/a&gt; and it worked out well for the most part. &lt;/p&gt;&lt;p&gt;The only problem I am having is with the userdir apache module. Using the userdir module, you can just drop web applications to /Users/&amp;lt;username&amp;gt;/Sites. But no matter how hard I tried, I just could not get this working and had to give up.&lt;/p&gt;&lt;p&gt;UPDATE: found &lt;a href="http://www.macosxhints.com/article.php?story=200906100223537" target="_blank"&gt;this post&lt;/a&gt; saying the permission denied problem is related to the user permission of _www. Apache runs as _www under _www group that need to have access to /Users/&amp;lt;username&amp;gt;/Sites. I&amp;#8217;ve added xr to everyone on that directory, not sure why it is still not working. If you want to give it a try you can do it.&amp;nbsp;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-2166373203679151029?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/2166373203679151029/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/set-up-php-and-apache-on-snow-leopard_29.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/2166373203679151029'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/2166373203679151029'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/set-up-php-and-apache-on-snow-leopard_29.html' title='set up PHP and Apache on Snow Leopard'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-8861219653292831962</id><published>2010-10-29T22:45:00.003-07:00</published><updated>2010-10-29T22:46:02.740-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Lua'/><title type='text'>setting up Lua on Mac</title><content type='html'>&lt;p&gt;Recently, fell insterested in Lua due to some work with lighttpd. So, want to share some experience setting up an IDE-ish environment (of course, VIM is always the best editor).&lt;/p&gt; &lt;p&gt;&lt;strong&gt;1. install lua and luarocks through MacPorts:&lt;/strong&gt; &lt;a href="http://www.macports.org/ports.php?by=name&amp;#038;substr=lua"&gt;http://www.macports.org/ports.php?by=name&amp;amp;substr=lua&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;2. failed attempt setting up LuaEclipse following instructions at&lt;/strong&gt; &lt;a href="http://luaeclipse.luaforge.net/manual.html#luadoc"&gt;http://luaeclipse.luaforge.net/manual.html#luadoc&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;font color="#990000"&gt;&lt;strong&gt;Update: Finally I got LuaEclipse set up correctly, please see my latest post for instructions.&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;LuaEclipse is a great IDE, however developers did not seem to be updating the project often and it does not work due to some 64bit jni library issues on Snow Leopard.&lt;/p&gt;&lt;p&gt;I first tried to install through update manager from Aptana Studio 2.0, got this error:&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;blockquote style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; border-top-style: none; border-right-style: none; border-bottom-style: none; border-left-style: none; border-width: initial; border-color: initial; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "&gt;&lt;p&gt;&lt;font color="#0000FF"&gt; /Applications/Aptana Studio 2.0/configuration/org.eclipse.osgi/bundles/224/1/.cp/libluajava-1.1.jnilib: no suitable image found. Did find: /Applications/Aptana Studio 2.0/configuration/org.eclipse.osgi/bundles/224/1/.cp/libluajava-1.1.jnilib: mach-o, but wrong architecture&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000FF"&gt; Could not initialize class org.keplerproject.luajava.LuaState  &lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Then I tried to install a 64bit Eclipse and install the LuaEclipse through update site and manually install the plugin zip, both failed&lt;/p&gt; &lt;blockquote style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; border-top-style: none; border-right-style: none; border-bottom-style: none; border-left-style: none; border-width: initial; border-color: initial; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "&gt;   &lt;p&gt;a) through the update site, it does not work, always complaining one dependent package is missing from update site&lt;/p&gt; &lt;/blockquote&gt; &lt;blockquote style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; border-top-style: none; border-right-style: none; border-bottom-style: none; border-left-style: none; border-width: initial; border-color: initial; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "&gt;   &lt;p&gt;b) download the plugin and install manually, installed fine, but cannot run, got error a specific directory is missing&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;&lt;strong&gt;&lt;font color="#990000"&gt;Conclusion: forget about LuaEclipse&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;3. Install a TextMate bundle:&lt;/strong&gt; http://netcetera.org/cgi-bin/tmbundles.cgi?bundle=%4C%75%61&lt;/p&gt; &lt;p&gt;TextMate is the choice of text editor for Mac. This Lua bundle worked perfectly for me. The only thing is that TextMate might be installed differently, so you may need to tweak the script to the &lt;font color="#0000FF"&gt;&amp;quot;Library/Application Support/TextMate/Bundles&amp;quot;&lt;/font&gt; in your home directory, at least I had to do that. Also note that you need to configure the PATH variable in TextMate so that the lua executable can be found by TextMate.&lt;/p&gt;&lt;p&gt;If you are interested in Lua, &lt;a href="http://www.amazon.com/Programming-Lua-Second-Roberto-Ierusalimschy/dp/8590379825/ref=sr_1_1?ie=UTF8&amp;#038;s=books&amp;#038;qid=1276984982&amp;#038;sr=8-1" target="_self" title="Programming in Lua (2nd)"&gt;Programming in Lua (2nd)&lt;/a&gt; is the best book to cover the basics from the original Lua developer.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-8861219653292831962?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/8861219653292831962/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/setting-up-lua-on-mac_29.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/8861219653292831962'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/8861219653292831962'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/setting-up-lua-on-mac_29.html' title='setting up Lua on Mac'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-2352206113810863474</id><published>2010-10-29T22:45:00.002-07:00</published><updated>2010-10-29T22:46:02.706-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Lua'/><title type='text'>LuaEclipse setup on Snow Leopard</title><content type='html'>&lt;p&gt;So, the instructions on the LuaEclipse main site won&amp;#8217;t work for the latest Eclipse and I had many errors last time. Today, I finally got LuaEclipse 1.3.1 set up and running now. Here are the steps:&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;a href="http://www.macports.org/ports.php?by=name&amp;#038;substr=lua" target="_blank"&gt;install lua and luarocks from MacPorts&lt;/a&gt; (sudo port install lua luarocks)&lt;/li&gt;&lt;li&gt;&lt;a href="http://luaprofiler.luaforge.net/manual.html#install" target="_blank"&gt;install LuaProfiler using luarocks&lt;/a&gt; (luarocks install luaprofiler)&amp;nbsp;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.eclipse.org/downloads/packages/eclipse-classic-342/ganymedesr2" target="_blank"&gt;download and install Eclipse 3.4.2&lt;/a&gt;, this version works with current LuaEclipse release&lt;/li&gt;&lt;li&gt;install LuaEclipse 1.3.1 from the update site, note that the official LuaEclipse installation guide only shows update site for 1.0 and 1.2. You need to use this update site:&amp;nbsp;http://luaeclipse.luaforge.net/preview/update-site/macosx.carbon/, for other OS, you can use the update sites found from &lt;a href="http://luaeclipse.luaforge.net/preview/update-site/" target="_blank"&gt;here&lt;/a&gt;&lt;/li&gt;&lt;li&gt;configure LuaEclipse through Eclipse Preferences &amp;gt; Lua, add Lua Interpreter (point it to /opt/local/bin/lua) and Lua Profiler (point it to /opt/local/var/luarocks/lib/5.1/profiler.so)&lt;/li&gt;&lt;li&gt;all set, you can create a new Lua project and start writing Lua and debugging, profiling it&amp;#8230;&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;Interestingly, LuaEclipse developers have started working on LuaEclipse 2. Here is &lt;a href="http://wiki.github.com/KINFOO/LuaEclipse/install-luaeclipse-2" target="_blank"&gt;the installation instruction&lt;/a&gt; and &lt;a href="http://github.com/KINFOO/LuaEclipse" target="_blank"&gt;the main site on GitHub&lt;/a&gt;.&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-2352206113810863474?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/2352206113810863474/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/luaeclipse-setup-on-snow-leopard_29.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/2352206113810863474'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/2352206113810863474'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/luaeclipse-setup-on-snow-leopard_29.html' title='LuaEclipse setup on Snow Leopard'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-3224019336656839266</id><published>2010-10-29T22:45:00.001-07:00</published><updated>2010-10-29T22:46:02.654-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='Image Processing'/><title type='text'>Creating shadows with ImageMagick</title><content type='html'>&lt;p&gt;&lt;p&gt;&lt;font color="#990000"&gt;&lt;strong&gt;1. Shadows for an image (create a shadow using Imagick::shadowImage and overlay the original image on top)&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;&amp;lt;?php&lt;/font&gt;&lt;/div&gt;&lt;div&gt;&lt;font color="#0000FF"&gt;/* Read the image into the object &lt;em&gt;/&lt;/font&gt;&lt;/div&gt;&lt;div&gt;&lt;font color="#0000FF"&gt;$im = new Imagick( &amp;#8216;totoro.png&amp;#8217; );&lt;/font&gt;&lt;/div&gt;&lt;div&gt;&lt;font color="#0000FF"&gt;$im-&amp;gt;setImageFormat(&amp;quot;png&amp;quot;);&lt;/font&gt;&lt;/div&gt;&lt;div&gt;&lt;font color="#0000FF"&gt;&lt;br /&gt; &lt;/font&gt;&lt;/div&gt;&lt;div&gt;&lt;font color="#0000FF"&gt;/&lt;/em&gt; Make the image a little smaller, maintain aspect ratio &lt;em&gt;/&lt;/font&gt;&lt;/div&gt;&lt;div&gt;&lt;font color="#0000FF"&gt;$im-&amp;gt;thumbnailImage( 200, null );&lt;/font&gt;&lt;/div&gt;&lt;div&gt;&lt;font color="#0000FF"&gt;&lt;br /&gt; &lt;/font&gt;&lt;/div&gt;&lt;div&gt;&lt;font color="#0000FF"&gt;/&lt;/em&gt; Clone the current object &lt;em&gt;/&lt;/font&gt;&lt;/div&gt;&lt;div&gt;&lt;font color="#0000FF"&gt;$shadow = $im-&amp;gt;clone();&lt;/font&gt;&lt;/div&gt;&lt;div&gt;&lt;font color="#0000FF"&gt;&lt;br /&gt; &lt;/font&gt;&lt;/div&gt;&lt;div&gt;&lt;font color="#0000FF"&gt;/&lt;/em&gt; Set image background color to black (the color of the shadow) &lt;em&gt;/&lt;/font&gt;&lt;/div&gt;&lt;div&gt;&lt;font color="#0000FF"&gt;$shadow-&amp;gt;setImageBackgroundColor( new ImagickPixel( &amp;#8216;black&amp;#8217; ) );&lt;/font&gt;&lt;/div&gt;&lt;div&gt;&lt;font color="#0000FF"&gt;&lt;br /&gt; &lt;/font&gt;&lt;/div&gt;&lt;div&gt;&lt;font color="#0000FF"&gt;/&lt;/em&gt; Create the shadow &lt;em&gt;/&lt;/font&gt;&lt;/div&gt;&lt;div&gt;&lt;font color="#0000FF"&gt;$shadow-&amp;gt;shadowImage( 80, 3, 5, 5 );&lt;/font&gt;&lt;/div&gt;&lt;div&gt;&lt;font color="#0000FF"&gt;&lt;br /&gt; &lt;/font&gt;&lt;/div&gt;&lt;div&gt;&lt;font color="#0000FF"&gt;/&lt;/em&gt; Imagick::shadowImage only creates the shadow. That is why the original image is composited over it &lt;em&gt;/&lt;/font&gt;&lt;/div&gt;&lt;div&gt;&lt;font color="#0000FF"&gt;$shadow-&amp;gt;compositeImage( $im, Imagick::COMPOSITE_OVER, 0, 0 );&lt;/font&gt;&lt;/div&gt;&lt;div&gt;&lt;font color="#0000FF"&gt;$content = $shadow-&amp;gt;getImageBlob();&lt;/font&gt;&lt;/div&gt;&lt;div&gt;&lt;font color="#0000FF"&gt;&lt;br /&gt; &lt;/font&gt;&lt;/div&gt;&lt;div&gt;&lt;font color="#0000FF"&gt;$shadow-&amp;gt;destroy();&lt;/font&gt;&lt;/div&gt;&lt;div&gt;&lt;font color="#0000FF"&gt;$im-&amp;gt;destroy();&amp;nbsp;&lt;/font&gt;&lt;/div&gt;&lt;div&gt;&lt;font color="#0000FF"&gt;&lt;br /&gt; &lt;/font&gt;&lt;/div&gt;&lt;div&gt;&lt;font color="#0000FF"&gt;/&lt;/em&gt; Display the image */&lt;/font&gt;&lt;/div&gt;&lt;div&gt;&lt;font color="#0000FF"&gt;header( &amp;quot;Content-Type: image/jpeg&amp;quot; );&lt;/font&gt;&lt;/div&gt;&lt;div&gt;&lt;font color="#0000FF"&gt;header(&amp;#8217;Content-Length: &amp;#8216; . strlen($content));&amp;nbsp;&lt;/font&gt;&lt;/div&gt;&lt;div&gt;&lt;font color="#0000FF"&gt;echo $content;&lt;/font&gt;&lt;/div&gt;&lt;div&gt;&lt;font color="#0000FF"&gt;?&amp;gt;&lt;/font&gt;&lt;/div&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#990000"&gt;2. Shadow for text&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;   &lt;p&gt;Note that the trick for multi-line text is to insert a new line character (\n) in your string. You can also use the rotation degree to control the layout, but make sure you use the correct size text canvas image because when you queryFontMetrics, it is based on the horizontal layout.&lt;/p&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;&amp;lt;?php&lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;// overlay the text&lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;$draw = new ImagickDraw();&lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;$draw-&amp;gt;setFont(&amp;#8217;Helvetica&amp;#8217;);&lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;$draw-&amp;gt;setFontSize(13);&lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;$draw-&amp;gt;setFillColor(new ImagickPixel(&amp;#8217;#B8B8B8&amp;#8242;));&lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;&lt;br /&gt; &lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;$text = &amp;quot;HELLO\nWORLD!&amp;quot;; // for multi-line text, insert new line char&lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;&lt;br /&gt; &lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;$textcanvas = new Imagick();&lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;$textprops = $textcanvas-&amp;gt;queryFontMetrics($draw, $text, true); //you need to turn multiline on, the last param&lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;$text&lt;em&gt;w = intval($textprops[&amp;#8217;textWidth&amp;#8217;]);&lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;$text&lt;/em&gt;h = intval($textprops[&amp;#8217;textHeight&amp;#8217;]);&lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;$textcanvas-&amp;gt;newImage($text&lt;em&gt;w+20, $text&lt;/em&gt;h+20, new ImagickPixel(&amp;#8217;transparent&amp;#8217;)); //give 20 pixel spaces around the text&lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;$textcanvas-&amp;gt;setImageFormat(&amp;#8217;png&amp;#8217;);&lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;$textcanvas-&amp;gt;annotateImage($draw, 10, $text&lt;em&gt;h, 0, $text);&lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;&lt;br /&gt; &lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;// create shadow&lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;$shadow = $textcanvas-&amp;gt;clone();&lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;$shadow-&amp;gt;setImageBackgroundColor(new ImagickPixel(&amp;#8217;black&amp;#8217;));&lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;$shadow-&amp;gt;shadowImage(80, 3, 5, 5);&lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;$shadow-&amp;gt;compositeImage($textcanvas, Imagick::COMPOSITE&lt;/em&gt;OVER, 0, 0);&lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;$shadow&lt;em&gt;w = $shadow-&amp;gt;getImageWidth();&lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;$shadow&lt;/em&gt;h = $shadow-&amp;gt;getImageHeight();&lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;&lt;br /&gt; &lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;// overlay the shadowed text on the given background image&lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;$bg = new Imagick(&amp;#8217;background.png&amp;#8217;);&lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;$bg-&amp;gt;setImageFormat(&amp;#8217;png&amp;#8217;);&lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;$bg&lt;em&gt;w = $bg-&amp;gt;getImageWidth();&lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;$bg&lt;/em&gt;h = $bg-&amp;gt;getImageHeight();&lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;&lt;br /&gt; &lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;//$bg-&amp;gt;compositeImage($shadow, Imagick::COMPOSITE&lt;em&gt;OVER, 0, ($bg&lt;/em&gt;h-$shadow&lt;em&gt;h));&lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;$bg-&amp;gt;compositeImage($shadow, Imagick::COMPOSITE&lt;/em&gt;OVER, 0, 0);&lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;&lt;br /&gt; &lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;// let&amp;#8217;s show the image&lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;$content = $bg-&amp;gt;getImageBlob();&lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;$textcanvas-&amp;gt;destroy();&lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;$shadow-&amp;gt;destroy();&lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;$bg-&amp;gt;destroy();&lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;&lt;br /&gt; &lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;header(&amp;#8217;Content-Type: image/png&amp;#8217;);&lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;header(&amp;#8217;Content-Length: &amp;#8216; . strlen($content));&lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;echo $content;&lt;/font&gt;&lt;/div&gt; &lt;div&gt;&lt;font color="#0000FF"&gt;?&amp;gt;&amp;nbsp;&lt;/font&gt;&lt;/div&gt; &lt;p&gt;&lt;br /&gt; &lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Somehow, I still don&amp;#8217;t know how to adjust the line spacing between multi-lines. I also found that ImagickDraw::setFontWeight did not work for me. Anyone knows how to fix those two issues?&amp;nbsp;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt;           &lt;p&gt;&lt;strong&gt;Reference:&lt;/strong&gt;&lt;/p&gt;           &lt;p&gt;1. &lt;a href="http://valokuva.org/?cat=1&amp;amp;paged=2" target="_blank"&gt;Mikko&amp;#8217;s blog&lt;/a&gt; (the best place for ImageMagick samples, who can beat the IM developer himself)&amp;nbsp;&lt;/p&gt;      &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-3224019336656839266?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/3224019336656839266/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/creating-shadows-with-imagemagick_29.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/3224019336656839266'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/3224019336656839266'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/creating-shadows-with-imagemagick_29.html' title='Creating shadows with ImageMagick'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2069539672100748782.post-371605859481574990</id><published>2010-10-29T22:45:00.000-07:00</published><updated>2010-10-29T22:46:02.590-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Mac'/><category scheme='http://www.blogger.com/atom/ns#' term='Configuraiton Management'/><title type='text'>failed to run code reformat in TextMate</title><content type='html'>&lt;p&gt;&lt;p&gt;All of a sudden, I cannot format/reformat the code in Textmate. Got this error:&lt;/p&gt; &lt;blockquote style=""&gt;&lt;span class="Apple-style-span"&gt;&lt;strong&gt;&lt;font color="#990000"&gt; PHP Warning: require(/lib/beautify.php): failed to open stream: No such file or directory in /private/tmp/temp&lt;em&gt;textmate.4tD2ED on line 19 &lt;/font&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/blockquote&gt; &lt;p&gt;Searched around the Web and it seems to be caused by php not setting $&lt;/em&gt;ENV property due to the variables&lt;em&gt;order not properly set in /etc/php.ini (assuming you are using php shipped with Mac, if you are using php from Macports, do it accordingly).&lt;/p&gt;&lt;p&gt;The fix is to add/update the variables&lt;/em&gt;order value to something like &lt;strong&gt;variables&lt;em&gt;order = &amp;quot;EGPCS&amp;quot;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;References:&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;a href="http://echodittolabs.org/blog/2010/03/fixing-textmates-php-commands-macports-php" target="_blank"&gt;Fixing Textmate&amp;#8217;s PHP Commands with MacPorts PHP&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://php.net/manual/en/ini.core.php" target="_blank"&gt;PHP core directives for php.ini explaining variables&lt;/em&gt;order&amp;nbsp;&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2069539672100748782-371605859481574990?l=mwebhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mwebhack.blogspot.com/feeds/371605859481574990/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mwebhack.blogspot.com/2010/10/failed-to-run-code-reformat-in-textmate_29.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/371605859481574990'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2069539672100748782/posts/default/371605859481574990'/><link rel='alternate' type='text/html' href='http://mwebhack.blogspot.com/2010/10/failed-to-run-code-reformat-in-textmate_29.html' title='failed to run code reformat in TextMate'/><author><name>guozheng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_H6rVU2Zp9jA/Sq8WhyTIBkI/AAAAAAAAGsE/hoz3ZEjcosU/S220/blackcat.gif'/></author><thr:total>0</thr:total></entry></feed>
