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

<channel>
	<title>The Sarth Repository</title>
	<atom:link href="http://blog.yimingliu.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.yimingliu.com</link>
	<description>source control for my (useless) knowledge</description>
	<lastBuildDate>Thu, 28 Jan 2010 21:34:04 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>fixing a scrambled IPython command history on stock OS X 10.6</title>
		<link>http://blog.yimingliu.com/2009/12/22/fixing-a-scrambled-ipython-command-history-on-stock-os-x-10-6/</link>
		<comments>http://blog.yimingliu.com/2009/12/22/fixing-a-scrambled-ipython-command-history-on-stock-os-x-10-6/#comments</comments>
		<pubDate>Tue, 22 Dec 2009 09:42:10 +0000</pubDate>
		<dc:creator>yiming</dc:creator>
				<category><![CDATA[Solutions]]></category>
		<category><![CDATA[bug]]></category>
		<category><![CDATA[compilation]]></category>
		<category><![CDATA[IPython]]></category>
		<category><![CDATA[OS X]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[readline]]></category>

		<guid isPermaLink="false">http://blog.yimingliu.com/?p=584</guid>
		<description><![CDATA[So I started over with a fresh install of OS X 10.6 recently, and wanted to restore my Python development environment.  In doing so, IPython is absolutely essential if you want a sane interpreter environment to test out code.  I had a bit of trouble with it though.
The Problem
The stock Python 2.6 shipped [...]]]></description>
			<content:encoded><![CDATA[<p>So I started over with a fresh install of OS X 10.6 recently, and wanted to restore my Python development environment.  In doing so, <a href="http://ipython.scipy.org/moin/">IPython</a> is absolutely essential if you want a sane interpreter environment to test out code.  I had a bit of trouble with it though.</p>
<h2>The Problem</h2>
<p>The stock Python 2.6 shipped with OS X 10.6 Snow Leopard has a <tt>readline</tt> module linked to <tt>libedit</tt>, the BSD alternative to the GPL&#8217;ed readline.  The <a href="http://tiswww.case.edu/php/chet/readline/rltop.html">readline module</a>, if you are not aware, is (among other things) responsible for keeping command history in the IPython interpreter.  This causes command history in the IPython 0.10 interpreter to behave in very odd ways.  When backtracking through the command history buffer using the up-arrow key, for example, the previous command is only partially recalled, and appears completely scrambled.  Indents, too, seem off &#8212; in a whitespace-sensitive language like Python, this is annoying.  (See first figure)<br />
<div id="attachment_586" class="wp-caption alignright" style="width: 310px"><a href="http://blog.yimingliu.com/wp-content/uploads/2009/12/ipython-libedit.png"><img src="http://blog.yimingliu.com/wp-content/uploads/2009/12/ipython-libedit-300x191.png" alt="IPython command interpreter is broken when using libedit with command history" title="ipython-libedit" width="300" height="191" class="size-medium wp-image-586" /></a><p class="wp-caption-text">IPython command interpreter is broken when using libedit with command history</p></div></p>
<p>Fixing IPython&#8217;s bugs are beyond my ability.  While I certainly don&#8217;t want to delve into the quagmire that is GPL vs BSD licensing, I do understand why Apple would want to avoid the viral nature of the GPL and ship libedit instead.  However, using a genuine Readline library is going to be the best recourse for this problem.  I already have a copy of readline compiled and ready to go, and just need a new version of <tt>readline.so</tt>, the library that links Python to readline.</p>
<h2>The easy solution</h2>
<p>Sifting through my records, I came across a <a href="http://selfsolved.com/">SelfSolved</a> problem record from my  good friend <a href="http://www.backin.de/">Hannes</a> who had issues with his <a href="http://selfsolved.com/problems/ipython-indents-and-command-history-broken">IPython command history</a>.</p>
<p>The solution: <code>sudo easy_install readline</code>, which uses <tt>setuptools</tt> to install a precompiled package of readline.so statically linked to genuine GNU readline.  Restart your IPython console and everything should work.  (See second figure)</p>
<div id="attachment_590" class="wp-caption alignright" style="width: 310px"><a href="http://blog.yimingliu.com/wp-content/uploads/2009/12/ipython-readline.png"><img src="http://blog.yimingliu.com/wp-content/uploads/2009/12/ipython-readline-300x186.png" alt="IPython with readline" title="ipython-readline" width="300" height="186" class="size-medium wp-image-590" /></a><p class="wp-caption-text">IPython with readline</p></div>
<h2>The hard solution</h2>
<p>Being the inquisitive sort, I also wondered how I would be able to reproduce this work from scratch.  <tt>readline.so</tt> ships with the Python source package, but surely I would not be required to compile a whole new copy of Python for one measly module library?</p>
<p>I documented this process in SelfSolved again: <a href="http://selfsolved.com/problems/building-just-readlineso-for-pyt">building readline.so for Python</a>.  At some point I should write an interface between SelfSolved and Wordpress so that I don&#8217;t have to reproduce a lot of my work here manually.</p>
<h4>Compiling readline.so</h4>
<p>This is actually fairly easy.</p>
<ol>
<li>Get a copy of the Python source code.  In OS X 10.6, it ships with <a href="http://www.python.org/download/releases/2.6.1/">Python 2.6.1</a>.</li>
<li>Unpack it and go into its directory.  You should find a <tt>Modules</tt> subdirectory.  In it is <tt>readline.c</tt>, the source file for readline.so.</li>
<li>Compile the source file.  The appropriate incantation is:<br />
<code>gcc -O2 -arch x86_64 -arch i386 -shared -o readline.so readline.c -I/usr/local/include -I/System/Library/Frameworks/Python.framework/Versions/2.6/include/python2.6 -L/usr/local/lib -lreadline -ltermcap -framework Python<br />
</code><br />
where the -arch flags should be whatever processors you wish to support, the -I arguments should point to the directories that contain header files for the readline library and the Python framework, and the -L argument should point to the path for the readline library.  Use whatever optimization flags you feel comfortable with, instead of -O2, if you wish.</li>
</ol>
<h4>Replacing readline.so</h4>
<p>So now we have a readline.so that&#8217;s properly linked to readline.dylib.  The thornier question is how to override the system-provided readline.so.  The system version is located at <tt>/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/lib-dynload/readline.so</tt>, and the naive would simply overwrite it with their new readline.so.  This is a bad idea.</p>
<p>As I have <a href="http://blog.yimingliu.com/2009/02/24/missing-library-symbols-while-compiling-php-528/">mentioned in the past</a>, overwriting system libraries in OS X is an unhealthy thing to do.  The problem is that Apple furnishes no official package management system &#8212; anything you personally change is considered fair game for the next official system update.  On the next system update, if the Python component is affected by the update, the Apple updater will happily clobber your compiled files with its own, leaving you suddenly back at square one.  You don&#8217;t know how many times I&#8217;ve had to recompile <tt>emacs</tt> (for X11 support) on OS X 10.4 because of this little annoyance.  Leave things in the <tt>/System/Library</tt> directory hierarchy alone, for your own sanity.</p>
<p>However, in this case <tt>/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/lib-dynload</tt> comes ahead of the user-modifiable <tt>/Library/Python/2.6/site-packages</tt> directory on Python&#8217;s <tt>sys.path</tt>.  So if you just drop readline.so into site-packages, the system version still takes priority.</p>
<p>There are a few ways to do this.  For one, you can create a sitecustomize.py in /Library/Python2.6/site-packages.  In this file, arbitrary Python statements can be written, and the interpreter will automatically execute them at runtime.  So, you can add a <code>sys.path = ["/dir/here"] + sys.path</code> statement and point it to a directory containing your readline.so file.  Alternatively, you can abuse the technique used in the easy_install.pth file.  It turns out that if you ever used easy_install, directories pointed to by the easy_install.pth file takes priority over the system paths.  They use an interesting way to accomplish this, which you can copy.  Or, you can just insert your directory containing readline.so into easy_install.pth.  In any case, this will force the readline-based readline.so to take precedence over the libedit-based readline.so, without overwriting anything.</p>
<h2>Discussion</h2>
<p>So for any sane person, the easy solution should be enough.  For the rest, the hard solution is an interesting exploration of how some of Python&#8217;s built-in modules can be compiled and inserted individually.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yimingliu.com/2009/12/22/fixing-a-scrambled-ipython-command-history-on-stock-os-x-10-6/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Upgrading the Seagate Barracuda 7200.11 to firmware SD1A</title>
		<link>http://blog.yimingliu.com/2009/07/08/upgrading-the-seagate-barracuda-720011-to-firmware-sd1a/</link>
		<comments>http://blog.yimingliu.com/2009/07/08/upgrading-the-seagate-barracuda-720011-to-firmware-sd1a/#comments</comments>
		<pubDate>Thu, 09 Jul 2009 06:44:24 +0000</pubDate>
		<dc:creator>yiming</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Solutions]]></category>
		<category><![CDATA[Barracuda 7200.11]]></category>
		<category><![CDATA[bug]]></category>
		<category><![CDATA[firmware]]></category>
		<category><![CDATA[gotcha]]></category>
		<category><![CDATA[Seagate]]></category>
		<category><![CDATA[SelfSolved]]></category>

		<guid isPermaLink="false">http://blog.yimingliu.com/?p=564</guid>
		<description><![CDATA[So perhaps you have heard of Seagate&#8217;s little manufacturing issue with its internal 3.5-inch Barracuda 7200.11 1TB drives a while back &#8212; namely, that some drives shipping with SD15 firmware are dying horribly.  I had the unfortunate experience of buying such a hard drive &#8212; the ST31000340AS &#8212; as a scratch disk for my [...]]]></description>
			<content:encoded><![CDATA[<p>So perhaps you have heard of <a href="http://www.theregister.co.uk/2009/01/16/barracuda_failure_plague/" rel="nofollow">Seagate&#8217;s little manufacturing issue</a> with its internal 3.5-inch Barracuda 7200.11 1TB drives a while back &#8212; namely, that some drives shipping with SD15 firmware are dying horribly.  I had the unfortunate experience of buying such a hard drive &#8212; the ST31000340AS &#8212; as a scratch disk for my main machine, a MacBook Pro with a mere 240 GB internal drive (a pre-unibody revision, where the HD is insanely difficult to replace).  </p>
<p>Seagate did in fact <a href="http://seagate.custkb.com/seagate/crm/selfservice/search.jsp?DocId=207951&#038;NewLang=en">issue a firmware update</a> &#8212; SD1A &#8212; that supposedly addressed this issue, but of course, there&#8217;s one catch: you can&#8217;t install the firmware through an external drive enclosure.  In communication with Seagate support, a representative confirmed that for those of us without a desktop tower that has a SATA bay, we&#8217;re hosed:</p>
<blockquote><p>Unfortunately, due to the nature of firmware updates and the way external drives work, the firmware update program cannot directly communicate with the drive in the manner it needs to in order to be able to upload the new firmware to the drive.  It must be plugged into an internal SATA controller in order to update the drive.</p></blockquote>
<p>Fair enough.  That makes technical sense &#8212; but of course, it doesn&#8217;t work for me.  I asked whether they would handle a mail-in repair, given that I have no easy access to such a desktop.  The answer, of course, is No.</p>
<p>I have to find a desktop, open it up, jam this baby in (possibly in place of the existing drive if there&#8217;s only one bay), update the firmware, and put everything back together.  Sadly, most of my friends who still own desktops would not trust me that far.</p>
<p>Half a year passes, and I finally find a <strike>sucker</strike> good friend who&#8217;s <strike>gullible</strike> awesome enough for me to try this procedure on his machine.  The fellow owns a nice if aging Dell Precision T5400, which comes with two SATA bays (so I don&#8217;t have to inflict undue harm onto the existing system).  Since this thing can run two drives at once, I can use the first method (a Windows-based firmware updater), though I burned a boot CD for the second method just in case.  I popped in the drive, fired up Windows XP, downloaded the Windows-based Firmware Update Utility, double-clicked, and thought it was the (triumphant) end.  In fact, it took 3 hours of my life to find out just how deep this rabbit hole goes.</p>
<p><!-- more --></p>
<h3>Problem 1:  The lying updater</h3>
<p>The firmware updater will give a bunch of scary warnings and then reboot the machine.  It will automatically reboot to a Seagate Loader screen, which attempts to apply the patch to all eligible SATA drives.  To its credit, it&#8217;ll skip the non-qualifying (i.e. non-Seagate, non-Barracuda, etc.) drives, but it&#8217;ll still try them out first.  At the end of the process, it will report &#8220;firmware downloaded&#8221; and &#8220;SUCCESSFUL&#8221; or some variant thereof, and automatically reboot back into Windows.</p>
<p>At this point, I advise you to use the <a href="http://www.seagate.com/support/seatools/">SeaTools</a> utility to verify that the firmware update actually <em>applied</em>.  Despite its claims, if you were on a stock setup Dell T5400 (or perhaps other models as well), this will prove that the updater is a lying scumbag.  And in fact, this particular drive still reported firmware SD15, the broken one.</p>
<h3>Problem 2: The broken Boot CD</h3>
<p>To save both me and my gracious host (who&#8217;s starting to suspect my computer-fixin&#8217; skills now) some time, I decided to try the boot CD method, rather than pounding my head trying to see why the updater was lying.  I downloaded the boot CD from the same Seagate Support site above, burned it to disk, and tried it out.</p>
<p>The result is a new SelfSolved posting: <a href="http://selfsolved.com/problems/getfatblock-error-when-upgarding">SelfSolved #59: getFatBlock error when upgrading Seagate Barracuda 7200.11 firmware</a>.  In essence:</p>
<blockquote><p>The FreeDOS boot CD reports a number of &#8221; error reading partition table drive 01 sector 0 &#8221; errors. This is followed by &#8221; get Fatblock failed:0&#215;000000e8 &#8221; or some variant of &#8221; getFatBlock failed : &#8221; The FreeDOS boot process appears to stall at this stage, and does not continue to the firmware flasher program.</p></blockquote>
<p>That was lovely.</p>
<h3>The Solution</h3>
<p>I chased some red herrings.  I came across postings about failures in various FreeDOS-based Seagate tools.  One such post mentioned that it took a long time for the boot disc to get over the &#8220;error reading partition table&#8221; errors, but I waited forever (well, 15 minutes) and the boot process did appear to be frozen / stalled.  I reformatted the drive via <tt>diskpart clean</tt>, thinking that the <tt>getFatBlock</tt> and <tt>error reading partition</tt> errors were related to a non-MBR partition table (I had it set to GPT).  I should have realized, of course, that the errors were completely unrelated to filesystems, despite the &#8220;fat block&#8221; to which it refers.</p>
<p>The actual solution is deceptively simple &#8212; the boot disc &#038; flasher appears to handle <a href="http://en.wikipedia.org/wiki/Advanced_Host_Controller_Interface" rel="nofollow">AHCI-based SATA</a> mode badly.  The Dell I was using was set to AHCI mode, out of the three possible Legacy, AHCI, and RAID options for SATA.  Apparently the boot disc simply doesn&#8217;t handle this mode correctly on the Dell machine (and may also be related to why the Windows-based updater lies).  When the machine switches on, use F12 to enter the boot menu, and select Setup to enter the BIOS.  Then, on the list of Drive Options, skip past the SATA drives and down to SATA options.  Pick the Legacy option to use ATA mode, instead of AHCI.  Once this is done, the boot disc will function correctly, and the updated firmware will be applied without incident.  Remember to switch the mode back to AHCI &#8212; it&#8217;s default for reason, no doubt.</p>
<p>The &#8220;error reading partition&#8221; messages were completely red herrings.  They appear whether you are in the right SATA mode or not, and does not appear to affect the operation of the firmware updater or the boot process.  It should not take very long to get to the flasher on this particular setup, so don&#8217;t wait on that message too long &#8212; it&#8217;s a good sign something&#8217;s not quite right.</p>
<p>In the end, I did recover my $100 hard drive, and the confidence of my peer in my mad hardware skillz (actually, quite non-existent).</p>
<h3>Discussion</h3>
<p>In the end, I&#8217;m quite appalled at Seagate.  This sort of failure shouldn&#8217;t have happened, of course.  Once it did, Seagate should have offered to take back and replace broken drives &#8212; the data I had on there was non-critical.  I would have been perfectly willing to pay shipping costs to get a fixed replacement through mail-in service.  I should not have been forced to search my social network for a person willing to let me tear his desktop computer apart, for a dubious and unsure firmware update procedure that fails mysteriously.  I spent an additional 3 hours tracing mystery failures, for which the error messages were rather useless.  Without my trusty iPhone and access to the Internet, I would not been able to solve this problem.  How should I have known what &#8220;getFatBlock failed&#8221; means?</p>
<p>This little episode has convinced me to never buy a Seagate drive again &#8212; I simply cannot afford the time and energy for these sort of firmware upgrade adventures.  While I was looking for a desktop to tear apart, I bought a <a href="http://www.newegg.com/Product/Product.aspx?Item=N82E16822136284">Western Digital Caviar Black</a> 1TB drive instead.  Another $100, but at least I had a scratch drive for my work.</p>
<p>The moral of the story: Seagate, you are the worst storage vendor I&#8217;ve had to work with so far.  I hope this record is not broken in the future.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yimingliu.com/2009/07/08/upgrading-the-seagate-barracuda-720011-to-firmware-sd1a/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Subversion 1.6.2 runtime error on network access on OS X 10.5</title>
		<link>http://blog.yimingliu.com/2009/05/27/subversion-162-runtime-error-on-network-access-on-os-x-105/</link>
		<comments>http://blog.yimingliu.com/2009/05/27/subversion-162-runtime-error-on-network-access-on-os-x-105/#comments</comments>
		<pubDate>Thu, 28 May 2009 06:45:40 +0000</pubDate>
		<dc:creator>yiming</dc:creator>
				<category><![CDATA[Solutions]]></category>
		<category><![CDATA[bug]]></category>
		<category><![CDATA[compilation]]></category>
		<category><![CDATA[gotcha]]></category>
		<category><![CDATA[Makefile]]></category>
		<category><![CDATA[OS X]]></category>
		<category><![CDATA[Subversion]]></category>
		<category><![CDATA[SVN]]></category>

		<guid isPermaLink="false">http://blog.yimingliu.com/?p=543</guid>
		<description><![CDATA[A new SelfSolved solution is up for perusal.  The problem I tried to solve:

After compiling Subversion 1.6.2 from source on OS X 10.5 Leopard, the compilation is apparently successful, but svn dies when it tries to connect to the network for the first time. Crash log reports that symbols are missing from libneon.dylib.
Crash report [...]]]></description>
			<content:encoded><![CDATA[<p>A new SelfSolved solution is up for perusal.  The problem I tried to solve:</p>
<blockquote><p>
After compiling Subversion 1.6.2 from source on OS X 10.5 Leopard, the compilation is apparently successful, but svn dies when it tries to connect to the network for the first time. Crash log reports that symbols are missing from libneon.dylib.</p>
<p>Crash report from shell:<br />
<code><br />
dyld: lazy symbol binding failed: Symbol not found: _ne_set_connect_timeout<br />
  Referenced from: /usr/local/lib/libsvn_ra_neon-1.0.dylib<br />
  Expected in: dynamic lookup</p>
<p>dyld: Symbol not found: _ne_set_connect_timeout<br />
  Referenced from: /usr/local/lib/libsvn_ra_neon-1.0.dylib<br />
  Expected in: dynamic lookup<br />
</code>
</p></blockquote>
<p>Check out the places that I googled and my final solution writeup &#8230; at SelfSolved <a href="http://selfsolved.com/problems/subversion-162-explodes-on-first">#49: Subversion 1.6.2 explodes on first network access</a>.</p>
<p>The problem is very similar to a <a href="http://blog.yimingliu.com/2009/02/24/missing-library-symbols-while-compiling-php-528/">previous compilation issue I solved for PHP</a>.  In essence, the -L library search path passed to GCC at compilation time has <tt>/usr/lib</tt> in front of everything else.  This means whatever library path you might have given to it at configure time, it&#8217;ll always look for the library in /usr/lib first, picking up the old system libneon in the process.  Since the bad libneon dynamically linked, the problem doesn&#8217;t manifest itself until runtime &#8212; and only at runtime with network access involved.</p>
<p>As with the PHP issue, change the very first -L/usr/lib to -L/usr/local/lib (or wherever your newer libneon is located), and it&#8217;ll link correctly.  </p>
<p>Out of curiosity, I checked MacPorts first.  The MacPorts solution of disabling libneon version checking is odd &#8212; it also works, but I dunno if it&#8217;s linking to the right thing or not.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yimingliu.com/2009/05/27/subversion-162-runtime-error-on-network-access-on-os-x-105/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>finding a fault-tolerant HTML parser for iPhone SDK</title>
		<link>http://blog.yimingliu.com/2009/05/15/a-fault-tolerant-html-parser-for-iphone-sdk/</link>
		<comments>http://blog.yimingliu.com/2009/05/15/a-fault-tolerant-html-parser-for-iphone-sdk/#comments</comments>
		<pubDate>Fri, 15 May 2009 22:16:01 +0000</pubDate>
		<dc:creator>yiming</dc:creator>
				<category><![CDATA[Solutions]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[parser]]></category>
		<category><![CDATA[UIKit]]></category>
		<category><![CDATA[XHTML]]></category>

		<guid isPermaLink="false">http://blog.yimingliu.com/?p=530</guid>
		<description><![CDATA[A new SelfSolved problem is ready for perusal:

A couple of my iPhone projects require a decent HTML/XHTML parser. On OS X, Cocoa ships with NSXMLDocument, which includes dirty HTML parsing functionality from libtidy. Unfortunately, NSXMLDocument is not part of the actual iPhone 2.2 SDK (though it is part of the 2.2 Simulator &#8212; so it&#8217;ll [...]]]></description>
			<content:encoded><![CDATA[<p>A new SelfSolved problem is ready for perusal:</p>
<blockquote><p>
A couple of my iPhone projects require a decent HTML/XHTML parser. On OS X, Cocoa ships with NSXMLDocument, which includes dirty HTML parsing functionality from libtidy. Unfortunately, NSXMLDocument is not part of the actual iPhone 2.2 SDK (though it is part of the 2.2 Simulator &#8212; so it&#8217;ll compile just fine at dev time but break when deploying &#8212; a big gotcha if you never tested against a real iPhone).</p>
<p>NSXMLParser is a part of the iPhone SDK&#8230;This is not a reasonable alternative.
</p></blockquote>
<p>Check out my writeup at <a href="http://selfsolved.com/problems/html-or-xhtml-parser-for-iphone">SelfSolved #42: HTML or XHTML Parser for iPhone SDK 2.x </a></p>
<p>Finally, all out of all the potential alternatives I found (all referenced at the SelfSolved writeup &#8212; including one that requires a license fee to use), this one seems to be the most promising and requires the least amount of pain (read: interaction with the libxml C API &#8212; god knows I&#8217;ve done enough of that while building prototypes at Yahoo! Research Berkeley)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yimingliu.com/2009/05/15/a-fault-tolerant-html-parser-for-iphone-sdk/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MenuMeters integer overflow in memory stats</title>
		<link>http://blog.yimingliu.com/2009/05/01/menumeters-integer-overflow-in-memory-stats/</link>
		<comments>http://blog.yimingliu.com/2009/05/01/menumeters-integer-overflow-in-memory-stats/#comments</comments>
		<pubDate>Fri, 01 May 2009 10:40:13 +0000</pubDate>
		<dc:creator>yiming</dc:creator>
				<category><![CDATA[Solutions]]></category>

		<guid isPermaLink="false">http://blog.yimingliu.com/?p=512</guid>
		<description><![CDATA[MenuMeters is a very cool, free (as in freedom) system monitoring tool for OS X that sits in the menu bar and shows you live statistics, including such values as current bandwidth usage, current network activity, memory usage, page faults, etc.
One thing that has been irritating me lately is that there&#8217;s a cosmetic error MenuMeters [...]]]></description>
			<content:encoded><![CDATA[<p>MenuMeters is a very cool, free (as in freedom) system monitoring tool for OS X that sits in the menu bar and shows you live statistics, including such values as current bandwidth usage, current network activity, memory usage, page faults, etc.</p>
<p>One thing that has been irritating me lately is that there&#8217;s a cosmetic error MenuMeters 1.3 that causes negative values to appear in the VM Statistics section of the memory stats display.  For example, the page faults value can roll over INT_MAX to report -1,800,000 page faults, when I&#8217;ve used the same OS X session for a long time without rebooting.</p>
<p>Since MenuMeters is GPL&#8217;ed, a quick lookthrough at its codebase reveals the problem.  The details of this problem and solution is currently documented as <a href="http://selfsolved.com/problems/menumeters-memory-meter-reports-negative-page-fa">#32 MenuMeters Memory Meter reports negative page faults</a> at <a href="http://selfsolved.com">SelfSolved</a>, a new web application I&#8217;ve written to keep track of these things.</p>
<p>More details to follow.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yimingliu.com/2009/05/01/menumeters-integer-overflow-in-memory-stats/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SSH, Subversion through SOCKS proxy on Mac OS X</title>
		<link>http://blog.yimingliu.com/2009/03/05/ssh-subversion-through-socks-proxy-on-mac-os-x/</link>
		<comments>http://blog.yimingliu.com/2009/03/05/ssh-subversion-through-socks-proxy-on-mac-os-x/#comments</comments>
		<pubDate>Thu, 05 Mar 2009 15:37:21 +0000</pubDate>
		<dc:creator>yiming</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Solutions]]></category>
		<category><![CDATA[compilation]]></category>
		<category><![CDATA[MacPorts]]></category>
		<category><![CDATA[OS X]]></category>
		<category><![CDATA[SOCKS]]></category>
		<category><![CDATA[SOCKS proxy]]></category>
		<category><![CDATA[SSH]]></category>
		<category><![CDATA[Subversion]]></category>
		<category><![CDATA[tsocks]]></category>

		<guid isPermaLink="false">http://blog.yimingliu.com/?p=471</guid>
		<description><![CDATA[One persistent problem that I run into is that I need to access certain network resources through a SOCKS proxy server.  This is all well and good if they are web resources &#8212; Safari, Firefox, etc. support SOCKS proxies quite well.  However, I also need, for example, SSH and Subversion access to some [...]]]></description>
			<content:encoded><![CDATA[<p>One persistent problem that I run into is that I need to access certain network resources through a SOCKS proxy server.  This is all well and good if they are web resources &#8212; Safari, Firefox, etc. support SOCKS proxies quite well.  However, I also need, for example, SSH and Subversion access to some resources.  SOCKS support is woefully inadequate or nonexistent in these tools.</p>
<p>In the case of SSH, even if you google for this, you&#8217;ll run through thousands of examples of using ssh as a SOCKS server, but not through one as a SOCKS client.  There are some <a href="http://bent.latency.net/bent/git/goto-san-connect-1.85/src/openssh-socks.html">convoluted solutions</a>, but none of them I can use directly on an OS X 10.5 machine.</p>
<h3>TSocks: the solution&#8230;if it were that easy</h3>
<p>Now, <a href="http://tsocks.sourceforge.net/">tsocks</a> is a nifty little tool to transparently divert network calls through a SOCKS 4 or SOCKS 5 proxy.  This allows even non-SOCKS-aware applications to function through a SOCKS server.</p>
<p>Unfortunately it is very old, unmaintained code (1.8 beta 5 was released in 2002).  It doesn&#8217;t compile cleanly on OS X due to this, nor will it compile under GCC 4.x.  Further, it won&#8217;t work out of the box either if you do manage to compile it.  The problem is that it relies on the Linux-only <tt>LD_PRELOAD</tt> functionality to use a shared library to hijack network system calls.  This mechanism is called <tt>DYLD_INSERT_LIBRARIES</tt> on OS X and only works if <tt> DYLD_FORCE_FLAT_NAMESPACES</tt> is active.</p>
<h4>Getting a working tsocks: MacPorts</h4>
<p>There is an easy way to get tsocks.  MacPorts ships a <a href="http://trac.macports.org/browser/trunk/dports/net/tsocks">ported tsocks package</a>.  If you use MacPorts, <tt>sudo port install tsocks</tt> should do it.</p>
<p>Unfortunately on several machines I don&#8217;t use MacPorts, and don&#8217;t want to pull down an entire third-party package manager with its own library tree on each of these boxes.  So I have do to this the hard way.</p>
<h4>Getting a working tsocks: rolling my own</h4>
<p>First to notice is that there are two tsocks distributions.  One is the original <a href="http://tsocks.sourceforge.net/">tsocks 1.8b5</a>, last updated in the first half of this decade.  To make it work, follow the <a href="http://marc-abramowitz.com/archives/2006/01/29/building-tsocks-on-mac-os-x/">instructions provided by Marc Abramowitz</a> in 2006.  Note that his patch is actually located at <a href="http://marc-abramowitz.com/download/tsocks-1.8_macosx.patch">his new domain address</a> instead of the old, linked one.</p>
<p>The MacPorts distribution, on the other hand, is based on <a href="https://giig.ugr.es/~rgarcia/tsocks/">R. Garcia&#8217;s patched tsocks distribution</a>, incorporating some modernization and new features by the <a href="http://tor.org">Tor team</a>.  This distribution is numbered 1.8.x, with the last being 1.8.4.  Unfortunately it is also no longer maintained, as the Tor devs forked this into a custom version to use with the Tor network only.  Unfortunate, but for now, it still compiles, and works a bit better than the 2002 original.</p>
<p>To roll your own tsocks via source out of the MacPorts distribution, you will want the patches from <a href="http://trac.macports.org/browser/trunk/dports/net/tsocks/files">the MacPorts repository</a>.  An outline of the compilation procedure:</p>
<ol>
<li>Download tsocks 1.8.4 from <a href="https://giig.ugr.es/~rgarcia/tsocks/">the author&#8217;s page</a></li>
<li>Download all the patches from <a href="http://trac.macports.org/browser/trunk/dports/net/tsocks/files">the MacPorts repository</a></li>
<li>Concatenate all of the patches together:
<pre><code>cat patch-* &gt; tsocks.osx.patch</code></pre>
</li>
<li>Put the concatenated <tt> tsocks.osx.patch </tt> file into the tsocks source directory.  Apply the patches:
<pre><code>patch -p0 &lt; tsocks.osx.patch</code></pre>
</li>
<li>Regenerate the configure script:
<pre><code>autoreconf</code></pre>
</li>
<li>Configure the package:
<pre><code>./configure --prefix=/usr/local --bindir=/usr/local/bin --mandir=/usr/local/man --sysconfdir=/etc --libdir=/usr/local/lib</code></pre>
</li>
<li>Install the library and binaries:
<pre><code>sudo make install</code></pre>
</li>
<li>Install the conf file:
<pre><code>sudo cp ./tsocks.conf.complex.example /etc/tsocks.conf</code></pre>
</li>
<li>Edit the conf file.  Make sure that if you&#8217;re not using tor, that you write in the conf file
<pre><code>tordns_enable = false</code></pre>
</li>
</ol>
<h4>Configuring tsocks</h4>
<p>The complex configuration file example should have explained all of the features to be set.  For my configuration:</p>
<p>Some important settings:
<ul>
<li><tt>local</tt> &#8211; this setting, in the format of <tt>IP/netmask</tt> can be repeated several times, each time to exclude a set of IPs from being diverted to the SOCKS server.  For obvious reasons, your SOCKS server will have to exist in one of these excluded IP ranges &#8211; otherwise you will never even reach your proxy server.</li>
<li><tt>server</tt> and <tt>server_port</tt> &#8211; these should point to the IP address and port of your SOCKS server</li>
<li><tt>server_type</tt> &#8211; <tt>tsocks</tt> defaults to SOCKS4 mode.  You may wish to set it to <tt>5</tt> for SOCKS5 usage.</li>
<li><tt>tordns_enable</tt> &#8211; this needs to be set as <tt>false</tt> if you don&#8217;t use Tor.</li>
</ul>
<h4>Using tsocks</h4>
<p>Once this is set up, simply prefixing the network command you want to run with <tt>tsocks</tt> will force a diversion through the proxy connection.  For example:</p>
<pre><code>tsocks ssh example.com</code></pre>
<p>The same can be applied to Subversion.  </p>
<pre><code>tsocks svn update</code></pre>
<p> will force the svn client to act through the proxy set in <tt>tsocks.conf</tt>.</p>
<h4>SOCKS on localhost</h4>
<p>Note that SOCKS services on <tt>127.0.0.1</tt> has a minor gotcha.  Sometimes, you are able to SSH into a remote machine, and use that connection as your SOCKS server.  This is described in my post about  <a href="http://blog.yimingliu.com/2008/03/19/ssh-and-socks-proxy-almost-as-good-as-a-vpn/">using SSH as a pseudo-VPN</a>, which describes the <tt>-D</tt> switch.  My use case here is that once you do this, all further local SSH connections to <em>other</em> machines should be diverted through the first SSH.  For example, I&#8217;d like to do:</p>
<pre><code>my-machine$ ssh -D 40000 gateway.example.com # establish a SOCKS server on localhost:40000 to the gateway host</code></pre>
<p>and then:</p>
<pre><code>my-machine$ ssh lan-1.example.com # access the protected lan-1 machine through the SOCKS, which will see me as gateway.example.com </code></pre>
<p>This is very doable in the tsocks setup if you set tsocks.conf:<br />
<code>
<pre>server = 127.0.0.1/255.255.255.255
server_port = 40000</pre>
<p></code></p>
<p>and then:<br />
<code>
<pre>
my-machine$ ssh -D 40000 gateway.example.com
my-machine$ tsocks ssh lan-1.example.com</pre>
<p></code> </p>
<p>This is the gotcha: make sure the netmask is set correctly to 255.255.255.255.  Otherwise tsocks will die with a cryptic:</p>
<pre>IP (127.0.0.1) &#038; SUBNET (0.0.0.0) != IP on line 22 in configuration file, ignored</pre>
<p>It is apparently fairly sensitive about the subnet mask setup to conform to exact standards.</p>
<p>With this tsocks setup, you won&#8217;t have to create special VPNs to lock a LAN machine behind a gateway.  As long as you can SSH into the gateway machine from your local machine, you can access the resources behind it with any application on your local machine via tsocks.  Nifty, huh?</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yimingliu.com/2009/03/05/ssh-subversion-through-socks-proxy-on-mac-os-x/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Fixing undefined library symbols for compiling PHP 5.2.8</title>
		<link>http://blog.yimingliu.com/2009/02/24/missing-library-symbols-while-compiling-php-528/</link>
		<comments>http://blog.yimingliu.com/2009/02/24/missing-library-symbols-while-compiling-php-528/#comments</comments>
		<pubDate>Tue, 24 Feb 2009 08:08:04 +0000</pubDate>
		<dc:creator>yiming</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Solutions]]></category>
		<category><![CDATA[bug]]></category>
		<category><![CDATA[compilation]]></category>
		<category><![CDATA[GCC]]></category>
		<category><![CDATA[gotcha]]></category>
		<category><![CDATA[OS X]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://blog.yimingliu.com/?p=426</guid>
		<description><![CDATA[So while compiling PHP 5.2.8 on OS X 10.5, you might run into something like:
Undefined symbols for architecture i386:
  "_xmlTextReaderSchemaValidate", referenced from:
      _zim_xmlreader_setSchema in php_xmlreader.o
  "_xmlTextReaderSetup", referenced from:
      _zim_xmlreader_XML in php_xmlreader.o
ld: symbol(s) not found for architecture i386
collect2: ld returned 1 exit status
Undefined symbols [...]]]></description>
			<content:encoded><![CDATA[<p>So while compiling PHP 5.2.8 on OS X 10.5, you might run into something like:</p>
<pre><code>Undefined symbols for architecture i386:
  "_xmlTextReaderSchemaValidate", referenced from:
      _zim_xmlreader_setSchema in php_xmlreader.o
  "_xmlTextReaderSetup", referenced from:
      _zim_xmlreader_XML in php_xmlreader.o
ld: symbol(s) not found for architecture i386
collect2: ld returned 1 exit status
Undefined symbols for architecture x86_64:
  "_xmlTextReaderSchemaValidate", referenced from:
      _zim_xmlreader_setSchema in php_xmlreader.o
  "_xmlTextReaderSetup", referenced from:
      _zim_xmlreader_XML in php_xmlreader.o
ld: symbol(s) not found for architecture x86_64
</code></pre>
<p>The MacPorts folks have encounted similar issues in <a href="http://trac.macports.org/ticket/15891">ticket 15891</a>, but <tt>WONTFIX</tt>&#8216;ed the issue.  Apparently the PHP devs are also <a href="http://bugs.php.net/bug.php?id=44294">punting on the problem</a>.</p>
<p>The immediate cause is that you have multiple versions of some shared libraries.  For example, in the case above, I have two <tt>libxml</tt> versions &#8212; one in <tt>/usr/lib</tt>, and another in <tt>/usr/local/lib</tt>.  This is because I do not want to overwrite the Apple-provided libxml version, but still needed new features provided in later <tt>libxml</tt> versions.  The arrangement works fine in every other software compile except this one, so I investigated further.</p>
<h3>The root of the problem</h3>
<p>Despite the developers&#8217; airy dismissal of the issue, the underlying problem is indeed that the Makefile generated by PHP at configure time is slightly broken.  In Makefile and Makefile.global, you&#8217;re going to see this line:</p>
<pre><code>libs/libphp$(PHP_MAJOR_VERSION).bundle: $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS)
        $(CC) $(MH_BUNDLE_FLAGS) $(CFLAGS_CLEAN) $(EXTRA_CFLAGS) $(LDFLAGS) $(EXTRA_LDFLAGS) $(PHP_GLOBAL_OBJS:.lo=.o) $(PHP_SAPI_OBJS:.lo=.o) $(PHP_FRAMEWORKS) $(EXTRA_LIBS) $(ZEND_EXTRA_LIBS) -o $@ &#038;&#038; cp $@ libs/libphp$(PHP_MAJOR_VERSION).so
</code></pre>
<p>where <tt>$MH_BUNDLE_FLAGS</tt> is usually defined as something like </p>
<pre><code>MH_BUNDLE_FLAGS = -bundle -bundle_loader /usr/sbin/httpd -L/usr/lib \
 -L/usr/lib -laprutil-1 -lsqlite3 -lexpat -liconv -L/usr/lib -lapr-1 -lpthread</code></pre>
<p>The problem is that this hardcodes the search paths for linking shared libraries.  GCC searches for shared libraries to link in the order of the provided -L paths.  In this case,  <tt>MH_BUNDLE_FLAGS</tt> is expanded immediately after <tt>$CC</tt> &#8212; so the load order is:</p>
<ol>
<li><tt>/usr/lib</tt></li>
<li><tt>/usr/lib</tt> (these are redundant, and so will probably be collapsed into one path)</li>
<li>&#8230;every other custom library path you specify</li>
</ol>
<p>Now you see the issue.  No matter what your library paths are set to, the PHP compilation system will insist that whatever shared libraries in <tt>/usr/lib</tt> take precedence.  Therefore, even if you specified that another version (say, <tt>libxml.dylib</tt> in <tt>/usr/local/lib</tt>) should be used instead, the invocation to link against <tt>-lxml2</tt> will search in <tt>/usr/lib</tt> first.  And since it finds the old version, which may be missing a number of symbols, the compilation blows up right there.</p>
<h3>Evidence</h3>
<p>And indeed, if you look at the (rather long and massive) compilation/link command right before it fails, you&#8217;ll see:</p>
<pre><code>gcc -bundle -bundle_loader /usr/sbin/httpd <strong>-L/usr/lib</strong> -L/usr/lib \
-laprutil-1 -lsqlite3 -lexpat  -liconv -L/usr/lib -lapr-1 -lpthread -O2 -I/usr/include -DZTS   \
-arch i386 -arch x86_64 <strong>-L/usr/local/lib</strong> ... </code></pre>
<p>emphasis mine, where <tt>/usr/local/lib</tt> might be <tt>/opt/lib</tt> or whatever custom path you provided to <tt>configure</tt>.</p>
<h3>Solutions</h3>
<p>The trivial solution is to manually invoke that last line of compilation, but swapping the -L load paths.</p>
<pre><code>gcc -bundle -bundle_loader /usr/sbin/httpd <strong>-L/usr/local/lib</strong> <strong>-L/usr/lib</strong> \
-L/usr/lib -laprutil-1 -lsqlite3 -lexpat  -liconv -L/usr/lib -lapr-1 -lpthread -O2 -I/usr/include -DZTS   \
-arch i386 -arch x86_64  ... </code></pre>
<p>This is easy to do and takes just a second.</p>
<p>Another possible solution is to patch the Makefile, such that  <tt>MH_BUNDLE_FLAGS</tt> comes later in the compilation line:</p>
<pre><code>libs/libphp$(PHP_MAJOR_VERSION).bundle: $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS)
        $(CC) $(CFLAGS_CLEAN) $(EXTRA_CFLAGS) $(LDFLAGS) $(EXTRA_LDFLAGS) $(PHP_GLOBAL_OBJS:.lo=.o) $(PHP_SAPI_OBJS:.lo=.o) $(PHP_FRAMEWORKS) $(EXTRA_LIBS) $(ZEND_EXTRA_LIBS) $(MH_BUNDLE_FLAGS) -o $@ &#038;&#038; cp $@ libs/libphp$(PHP_MAJOR_VERSION).so
</code></pre>
<p>This will force your library paths to be searched before <tt>/usr/lib</tt>, thus resolving the link problem. </p>
<p><strong>update 7/18/09</strong><br />
An anonymous reader mentions that you could also specify the right libxml by full path, instead of letting it use -lxml.  Basically, in the last compilation line, you would remove any mentions of -lxml and replace that with the full path to your library e.g. /usr/local/lib/libxml.dylib.  In fact, this is probably the way that has the least possible side-effects, since you aren&#8217;t changing the search order for any other libraries.</p>
<h3>Discussion</h3>
<p>This is not the first time that PHP core developers have refused to fix <a href="http://blog.yimingliu.com/2008/01/26/php-525-compile-error-macro-issue/">a compilation issue that is arguably preventable</a> through actual testing under different installation scenarios.  This is an &#8220;edgier&#8221; edge case than the tidy.h issue, but still should be fairly noticeable for a substantial number of people. </p>
<p>The &#8220;You should only have one library installed&#8221; argument is, to be honest, unnecessarily arrogant (sadly, <a href="http://blog.yimingliu.com/2008/09/09/perian-and-xcode-dylib-fetish/">not as a rare a problem as you&#8217;d like</a> in some open source development projects ).  On OS X, due to the lack of official Apple package management systems, no one should be overwriting system default libraries &#8212; down that way lies insanity, especially at every system or security update.  And yet, this build system is obviously broken any time there is a substantial difference between user-installed libraries and system libraries.  This bad behavior is especially egregious, because the <tt>configure</tt> command allows you specify your own library path &#8212; misleading users into thinking that the path they specified would be obeyed at compile time.  If you only intend for the system library to be used and no other, perhaps the configure script should auto-detect this on OS X and disable that command-line option.  Basic user interface design should apply even to command-line interfaces.</p>
<p>Note that changing link ordering may have some unforseen consequences, since the devs obviously never tested this path.  For example, you should make sure the dynamic libraries are <strong>loaded in the right order</strong> at runtime.  On OS X, the load path is typically hard-coded into the dylib, so usually there won&#8217;t be a problem &#8212; but there may be edge cases.  Test your build (and any PHP extensions you built) before using it in production!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yimingliu.com/2009/02/24/missing-library-symbols-while-compiling-php-528/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Testing a POP3 server via telnet or OpenSSL</title>
		<link>http://blog.yimingliu.com/2009/01/23/testing-a-pop3-server-via-telnet-or-openssl/</link>
		<comments>http://blog.yimingliu.com/2009/01/23/testing-a-pop3-server-via-telnet-or-openssl/#comments</comments>
		<pubDate>Sat, 24 Jan 2009 02:06:25 +0000</pubDate>
		<dc:creator>yiming</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Solutions]]></category>
		<category><![CDATA[command line]]></category>
		<category><![CDATA[OpenSSL]]></category>
		<category><![CDATA[POP3]]></category>
		<category><![CDATA[server]]></category>
		<category><![CDATA[telnet]]></category>

		<guid isPermaLink="false">http://blog.yimingliu.com/?p=344</guid>
		<description><![CDATA[Sometimes you can&#8217;t be bothered to install and setup a command-line mail client and/or VPN, but you still need to access a POP 3 server from a remote machine.  Sometimes you just need to know if a POP3 server is working or not.  As a largely text-based protocol much like the HTTP protocol, [...]]]></description>
			<content:encoded><![CDATA[<p>Sometimes you can&#8217;t be bothered to install and setup a command-line mail client and/or VPN, but you still need to access a POP 3 server from a remote machine.  Sometimes you just need to know if a POP3 server is working or not.  As a largely text-based protocol <a href="http://blog.yimingliu.com/2008/02/04/testing-https-with-openssl/">much like the HTTP protocol</a>, <tt>telnet</tt> or <tt>openssl</tt> can be used to talk to a POP3 server and read some mail directly from the command line.</p>
<h3>Establishing a connection</h3>
<p>To start with, the usual process is to telnet to a POP3 server port, usually on TCP port 110.  This would be very simple:<br />
<code>telnet mail.example.com 110</code></p>
<p>Nowadays, though, most POP3 servers are secured via SSL, usually sitting on port 995.  If you try to use telnet on an SSL-only POP3 server, you&#8217;ll either get an error &#8220;Command is not valid in this state&#8221;, such as:</p>
<pre><code>
Trying 127.0.0.1...
Connected to mail.example.com.
+OK The Microsoft Exchange POP3 service is ready.
USER yiming
-ERR Command is not valid in this state.</code></pre>
<p>or you&#8217;ll get a rather brusque brushoff</p>
<pre><code>
Trying 10.0.1.202...
Connected to mail2.example.com.
Escape character is '^]'.
USER yiming
Connection closed by foreign host.</code></pre>
<p>When this is encountered, OpenSSL&#8217;s <tt>s_client</tt> should be used instead to perform the necessary SSL negotiations.</p>
<pre><code>openssl s_client -connect mail.example.com:995</code></pre>
<p>or</p>
<pre><code>openssl s_client -crlf -connect mail.example.com:110 -starttls pop3</code></pre>
<p>The second incantation is typically used for Microsoft Exchange servers.  Note the <tt>-crlf</tt> option, which tells s_client to send <tt>\r\n</tt> line endings.  If the wrong line ending is used for a server, the symptom is that the server will not respond to any commands.  It will only sit there and wait for further input, while you are staring at a blank responses or blank lines in your telnet session.</p>
<h3>Authentication</h3>
<p>Having established a connection, it is now necessary to authenticate as a POP3 user.  In the simplest case, plain text authentication is used.  In this case, the command <tt>USER [username]</tt> is used to establish the username, and <tt>PASS [password]</tt> is used to establish the password in plaintext.  (Since the connection is under SSL encryption, presumably this plaintext won&#8217;t matter).</p>
<pre><code>
+OK Server ready
USER yiming
+OK
PASS foobar
+OK Logged in.
</code></pre>
<h3>Server interactions</h3>
<p>Several commands are useful here.</p>
<ul>
<li><tt>LIST</tt> &#8211; lists the messages available in the user&#8217;s account, returning a status message and list with each row containing a message number and the size of that message in bytes</li>
<li><tt>STAT</tt> &#8211; returns a status message, the number of messages in the mailbox, and the size of the mailbox in bytes</li>
<li><tt>RETR [message_num]</tt> &#8211; returns the message identified by the message number, which is the same as the message number shown in the LIST command output</li>
<li><tt>TOP [message_num] [n]</tt> &#8211; returns the top <tt>n</tt> lines of the message denoted by message number.</li>
</ul>
<p>When finished, the <tt>QUIT</tt> command will end the session.</p>
<h3>Conclusion</h3>
<p>For other POP3 commands, such as commands marking deletion of a message, refer to <a href="http://www.ietf.org/rfc/rfc1939.txt">RFC 1939</a>, the canonical document defining the Post Office Protocol Version 3 ( POP3 ).  At some point, if the commands to be tested become complicated, it may be more efficient use of time to install a mail client such as <a href="http://www.washington.edu/alpine/">alpine</a>.</p>
<p>See also my previous post on <a href="http://blog.yimingliu.com/2008/02/04/testing-https-with-openssl/">chatting with HTTP / HTTPS servers</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yimingliu.com/2009/01/23/testing-a-pop3-server-via-telnet-or-openssl/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Building from source package on Debian / Ubuntu to fix sudo PATH issue</title>
		<link>http://blog.yimingliu.com/2009/01/03/building-from-source-package-on-debian/</link>
		<comments>http://blog.yimingliu.com/2009/01/03/building-from-source-package-on-debian/#comments</comments>
		<pubDate>Sat, 03 Jan 2009 09:45:00 +0000</pubDate>
		<dc:creator>yiming</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Solutions]]></category>
		<category><![CDATA[compilation]]></category>
		<category><![CDATA[dpkg]]></category>
		<category><![CDATA[package manager]]></category>
		<category><![CDATA[PATH]]></category>
		<category><![CDATA[secure_path]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[source package]]></category>
		<category><![CDATA[sudo]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[workaround]]></category>

		<guid isPermaLink="false">https://blog.yimingliu.com/2009/01/03/building-from-source-package-on-debian-ubuntu-to-fix-sudo-path-issue/</guid>
		<description><![CDATA[So I&#8217;ve been kicking around an Ubuntu installation, hoping to replace my aging Fedora 5 deployment.  Last time I touched a Debian distro was&#8230;well&#8230;sufficiently long ago that it&#8217;s more or less all new to me.
What&#8217;s less new is the sudo path inheritance issue &#8212; this one&#8217;s been around.  Ubuntu&#8217;s sudo hard-codes its PATH [...]]]></description>
			<content:encoded><![CDATA[<p>So I&#8217;ve been kicking around an Ubuntu installation, hoping to replace my aging Fedora 5 deployment.  Last time I touched a Debian distro was&#8230;well&#8230;sufficiently long ago that it&#8217;s more or less all new to me.</p>
<p>What&#8217;s less new is the <tt>sudo</tt> path inheritance issue &#8212; this one&#8217;s been around.  Ubuntu&#8217;s <tt>sudo</tt> hard-codes its <tt>PATH</tt> variable at compile-time with a <tt>--secure-path</tt> option.  I&#8217;m sure this sounded like a good idea to the security goon who decided to fix this at fsckin&#8217; COMPILE TIME with no way to override it in sudoers, or at runtime with <tt>-E</tt> after an <tt>env_reset</tt>.  The policy may have been reasonable when it was set on a typical Debian stable server (where software is basically left to fossilize over decades), but certainly not on a constantly changing desktop distro.  You can&#8217;t even sudo to any <tt>/opt/bin</tt> binaries!  Read <a href="https://bugs.launchpad.net/ubuntu/+source/sudo/+bug/50797">the Ubuntu bug report on sudo not preserving PATH</a>.</p>
<p>Long story short, after a lot of experiments looking for workarounds (that won&#8217;t eventually take years off my life, one sudo command at a time), I decided to cut the Gordian knot and recompile sudo.  Since I didn&#8217;t want to roll this from source (and incur all the maintenance hassle of removing/updating the software later on), this meant figuring out compiling source packages with dpkg &#8212; oh joy.</p>
<h3>Debian source package compilation: the general process</h3>
<p>It&#8217;s surprisingly non-painful compared with my RPM experience.  The long way around:</p>
<ol>
<li><tt>cd</tt> into a temp or source-keeping directory in your user account</li>
<li> retrieve the source package:  <code>apt-get source [packagename]</code></li>
<li> grab missing build dependencies: <code>sudo apt-get build-dep [packagename]</code></li>
<li><tt>cd</tt> into the directory created for the package in your <tt>pwd</tt> (you can safely ignore the original tarball and the patch file, which have been untarred and applied for you already, respectively).  Make edits to the source as needed.</li>
<li>If you need to change configure options for the source package, look in the file <tt>debian/rules</tt> in the source directory</li>
<li>when satisfied, build the binary package by issuing this incantation in the <tt>$PWD</tt> ( you&#8217;ll need the <tt>fakeroot</tt> package if you don&#8217;t already have it ):<br />
<code>dpkg-buildpackage -rfakeroot -uc -b</code></li>
<li>The completed <tt>.deb</tt> packages are placed in the parent directory, one level up from the source directory.  <tt>cd</tt> back up one level.</li>
<li> install: <code>sudo dpkg -i [packagename].deb</code></li>
</ol>
<p>If you&#8217;re screwing around with sudo, you will want to have a sudo tty session open before installing your replacement package, in case you screw up everything and lock yourself out.</p>
<p>A shortcut is potentially available using the <tt>-b</tt> switch to apt-get when you grab from source.  However, I needed to look through configuration files and source code, so I took the long way around.</p>
<p>The easiest way to fix the sudo secure_path issue is to remove the <tt>--with-secure-path</tt> configuration option in <tt>debian/rules</tt>, in two places in that file.  If you do this, pay attention to your <tt>$PATH</tt> and make sure they are sane (for example: it shouldn&#8217;t contain a globally writeable directory), as it will be inherited in sudo shells.  In sudo 1.7, there is a runtime <tt>secure_path</tt> option for the sudoers file, so that would be the ideal, non-annoying solution to this issue.</p>
<p>Hard-coding the sudo PATH at compile-time tilts heavily toward security in the security/usability tradeoff &#8212; YMMV, but I find it entirely not worth it on a desktop distribution.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yimingliu.com/2009/01/03/building-from-source-package-on-debian/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>check last exit status code in bash shell</title>
		<link>http://blog.yimingliu.com/2009/01/01/check-last-exit-status-code-in-bash-shell/</link>
		<comments>http://blog.yimingliu.com/2009/01/01/check-last-exit-status-code-in-bash-shell/#comments</comments>
		<pubDate>Thu, 01 Jan 2009 21:39:00 +0000</pubDate>
		<dc:creator>yiming</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Solutions]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[exit code]]></category>
		<category><![CDATA[exit status]]></category>
		<category><![CDATA[shell]]></category>

		<guid isPermaLink="false">https://blog.yimingliu.com/2009/01/01/check-last-exit-status-code-in-bash-shell/</guid>
		<description><![CDATA[In case you&#8217;re curious (while debugging a program or a script) about the exit status code returned by the last shell command you ran, the incantation to retrieve it in the bash shell is:
echo $?
Given the nature of this variable (no one indexes text like &#8216;$?&#8217;), it&#8217;s annoyingly hard to Google for.
]]></description>
			<content:encoded><![CDATA[<p>In case you&#8217;re curious (while debugging a program or a script) about the exit status code returned by the last shell command you ran, the incantation to retrieve it in the bash shell is:</p>
<p><code>echo $?</code></p>
<p>Given the nature of this variable (no one indexes text like &#8216;$?&#8217;), it&#8217;s annoyingly hard to Google for.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yimingliu.com/2009/01/01/check-last-exit-status-code-in-bash-shell/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Apple Remote Desktop black screen and old machines</title>
		<link>http://blog.yimingliu.com/2009/01/01/apple-remote-desktop-black-screen-and-old-machines/</link>
		<comments>http://blog.yimingliu.com/2009/01/01/apple-remote-desktop-black-screen-and-old-machines/#comments</comments>
		<pubDate>Thu, 01 Jan 2009 11:05:00 +0000</pubDate>
		<dc:creator>yiming</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Solutions]]></category>
		<category><![CDATA[Apple Remote Desktop]]></category>
		<category><![CDATA[black screen]]></category>
		<category><![CDATA[bug]]></category>
		<category><![CDATA[color depth]]></category>
		<category><![CDATA[OS X]]></category>
		<category><![CDATA[workaround]]></category>

		<guid isPermaLink="false">https://blog.yimingliu.com/2009/01/01/apple-remote-desktop-black-screen-and-old-machines/</guid>
		<description><![CDATA[
There appears to be some sort of limitation on screen colors when using ARD 3.2.2 to control an older Mac remotely.  The symptom of this is a black screen when you attempt to Observe or Control the remote machine.  Unfortunately, this same symptom usually pears when you have a blocked network port (ARD [...]]]></description>
			<content:encoded><![CDATA[<p><img id="BLOGGER_PHOTO_ID_5286468232887832722" style="float: right; margin: 0 0 10px 10px; cursor: hand; width: 320px; height: 182px;" src="http://3.bp.blogspot.com/_ZfWK3G30UEA/SV1O2VGqkJI/AAAAAAAAAKM/GuWl7js1x8A/s320/ard-blackscreen.png" border="0" alt="" /></p>
<p>There appears to be some sort of limitation on screen colors when using ARD 3.2.2 to control an older Mac remotely.  The symptom of this is a black screen when you attempt to Observe or Control the remote machine.  Unfortunately, this same symptom usually pears when you have a blocked network port (ARD uses TCP and UDP ports 3283 and 5900), so it may be confusing as to which is the issue.</p>
<p>After verifying all network settings and router port forwardings are set up correctly, you might try this if you have an older Mac as the target: move the color slider on the top-right corner of your ARD admin panel to a lower value, and then try to reconnect.</p>
<p>The story is that I was trying to remote control a G4 dual 500 ( Mystic ) from a MacBook Pro (early 2008).  This used to work until recently, when I had nothing but a black screen.  Keyboard commands still worked (I can blindly log in from the loginwindow), though mouse movements did not pass through to the old Mac.</p>
<p><img style="float: right; margin: 0 0 10px 10px; cursor: hand; width: 320px; height: 138px;" src="http://4.bp.blogspot.com/_ZfWK3G30UEA/SV1O24Cte3I/AAAAAAAAAKU/9okgwG7NB_U/s320/ard-blackscreen-fixed.png" border="0" alt="" /></p>
<p>After fruitlessly chasing network issues with my AirPort router, <a href="http://discussions.apple.com/thread.jspa?threadID=800941">the last post at an Apple Discussions</a> thread pointed me to the right direction.  Once I used the color control on the ARD application to lower the color depth by 1 notch, the next connection worked just fine, with the screen showing up and behaving normally.</p>
<p>Now this poor old G4 tower is running 10.4.11 with an ancient Rage 128 Pro graphics card, but it handles its 17inch screen just fine at &#8220;million of colors&#8221; color depth when sitting in front of it.  Very odd how it just stopped working at that depth over ARD.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yimingliu.com/2009/01/01/apple-remote-desktop-black-screen-and-old-machines/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>DocPreview &#8211; browser plug-in to view Microsoft Word documents in Safari</title>
		<link>http://blog.yimingliu.com/2008/12/25/docpreview-plug-in-to-view-word/</link>
		<comments>http://blog.yimingliu.com/2008/12/25/docpreview-plug-in-to-view-word/#comments</comments>
		<pubDate>Fri, 26 Dec 2008 02:45:00 +0000</pubDate>
		<dc:creator>yiming</dc:creator>
				<category><![CDATA[Projects]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Solutions]]></category>
		<category><![CDATA[browser plug-in]]></category>
		<category><![CDATA[Microsoft Office]]></category>
		<category><![CDATA[Microsoft Word]]></category>
		<category><![CDATA[OS X]]></category>
		<category><![CDATA[Safari]]></category>
		<category><![CDATA[WebKit]]></category>
		<category><![CDATA[Word]]></category>

		<guid isPermaLink="false">https://blog.yimingliu.com/2008/12/25/docpreview-browser-plug-in-to-view-word-documents-inside-safari-on-os-x/</guid>
		<description><![CDATA[UPDATE: As of v3.0, finally released in early 2009, Schubert&#124;IT&#8217;s Word Browser Plugin has been made a Universal binary.  Therefore, DocPreview is no longer needed.  This post remains for historical curiosity.  The Word Browser Plugin offers a more polished interface for the same task.  Go try it out first.  I [...]]]></description>
			<content:encoded><![CDATA[<p><strong>UPDATE: As of v3.0, finally released in early 2009, Schubert|IT&#8217;s Word Browser Plugin has been made a Universal binary</strong>.  Therefore, <strong>DocPreview is no longer needed</strong>.  This post remains for historical curiosity.  The Word Browser Plugin offers a more polished interface for the same task.  Go try it out first.  I will tweak DocPreview ( more as a challenge to myself to see if I can do what the good folks at SchubertIt have done ), though the original purpose of this plugin (filling the gap for Word Browser Plugin) has been served.  Thanks for trying it out.</p>
<p>01/24/2010 &#8211; DocPreview updated for 64-bit Safari and 10.6.  Still seems to work.<br />
&#8212;</p>
<p>DocPreview is a lightweight WebKit browser plugin I wrote to display a text-only preview of Microsoft Word <tt> .doc </tt> documents, inline and within Safari 3.x (and, apparently, 4.x) on both Intel and PowerPC Macs.  This behavior is much like the functionality provided by the PPC-only <a href="http://www.schubert-it.com/pluginword/">Word Browser Plugin</a> from <a href="http://www.schubert-it.com/">Schubert|IT</a>.  DocPreview, of course, is a universal binary plug-in &#8212; since Word Browser&#8217;s lack of Intel support is really why I wrote this plug-in.<br />
<a href="http://3.bp.blogspot.com/_ZfWK3G30UEA/SVRqV4yVrMI/AAAAAAAAAJc/QCznVkg6KuM/s1600-h/docpreview-full_mode.png"><img id="BLOGGER_PHOTO_ID_5283965187065752770" style="float: right; margin: 10px 0 10px 10px; cursor: hand; width: 320px; height: 207px;" src="http://3.bp.blogspot.com/_ZfWK3G30UEA/SVRqV4yVrMI/AAAAAAAAAJc/QCznVkg6KuM/s320/docpreview-full_mode.png" border="0" alt="" /></a></p>
<p>DocPreview only supports WebKit-based browsers that can use .webplugin files.  I am currently unable to support other browsers, since DocPreview is built against the WebKit API instead of the Netscape plug-in API.  Frankly, the Netscape API is a mess, and I haven&#8217;t had the time to figure it out.  A NSAPI guru who could point me in the right direction would be much appreciated.</p>
<p><strong>Download</strong><br />
<a href="http://static.yimingliu.com/software/DocPreview-0.1.zip">DocPreview.zip (10.5+)</a> &#8211; v0.1<br />
<a href="http://static.yimingliu.com/software/DocPreview-0.1-10.4.zip">DocPreview.zip (10.4)</a> &#8211; v0.1</p>
<p>This is a proof-of-concept release.  It passes the worked-for-me test &#8212; as in, I&#8217;m using this plug-in daily.  While I believe it functions correctly, I make no guarantees as to stability and usefulness, and am not liable for blowing up your browser or any harm that might befall you through your adventurous use of this plug-in.  Although, I do want this thing to work for everyone, so <strong>please leave me a note</strong> here if it doesn&#8217;t work.</p>
<p><strong>(UPDATE 02/24/2009)</strong> &#8211; I see a few downloads already in my server logs, but no comments at all on this post.  Can I assume it works for all of you out there?  Or was it so broken that no one&#8217;s browser lived to tell the tale?  <img src='http://blog.yimingliu.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><a href="http://3.bp.blogspot.com/_ZfWK3G30UEA/SVRTGW6_khI/AAAAAAAAAJE/VimHAdwvCKo/s1600-h/docpreview_originaldoc_full.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img id="BLOGGER_PHOTO_ID_5283939631509770770" style="float: right; margin: 0 0 15px 10px; cursor: hand; width: 320px; height: 303px;" src="http://3.bp.blogspot.com/_ZfWK3G30UEA/SVRTGW6_khI/AAAAAAAAAJE/VimHAdwvCKo/s320/docpreview_originaldoc_full.png" border="0" alt="" /></a></p>
<p>DocPreview features &amp; limitations:</p>
<ul>
<li>Universal binary support, for use on both PPC and Intel Macs.  No Windows Safari support &#8212; and plus, there are already good solutions for inline doc browsing on the Windows side.  If you&#8217;re on PPC, I suggest you use <a href="http://www.schubert-it.com/pluginword/">Word Browser Plugin</a> instead unless you desperately need find-on-page using Safari&#8217;s built-in facilities with Word docs.</li>
<li>Tested extensively on Safari 4.0b1, 3.2.x, and somewhat with Shiira 2.x.  May also work on earlier Safari versions, but I simply do not have the ability to test the plugin against them.</li>
<li>Uses OS X&#8217;s internal engine for opening and processing Word files.  DocPreview performs as well (or as badly, depending on your opinion) as OS X itself for the same task.</li>
<li>Supported on OS X 10.5 for .doc, .docx, and .odt files.  On OS X 10.5, the plugin can parse Microsoft&#8217;s new OpenXML (.docx) and <a href="http://openoffice.org/">OO.org</a>&#8217;s ODF Text (.odt) documents.  On 10.4, the plugin will still work, but only for .doc files.</li>
<li>Support for full document view mode or embedded mode (if the page author uses object and embed tags, like with Flash objects &#8212; although, who actually does that with .doc files? )</li>
<li>In full document view mode, DocPreview uses Safari&#8217;s built-in Find and Text Zoom abilities.  Any command that can be run on a normal Safari webpage can be performed on a DocPreview rendering.</li>
<li>In embedded mode, Find on Page and Text Zoom support are implemented separately.  I&#8217;m still thinking about how I can hook into Safari&#8217;s built-in system from within an embedded plugin.  Since no one ever uses embedded .doc files anyway, the point is fairly moot for most users.</li>
</ul>
<p><a href="http://2.bp.blogspot.com/_ZfWK3G30UEA/SVRTFyLks3I/AAAAAAAAAI8/l4BIlN_AjWA/s1600-h/docpreview-embedded_mode.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img id="BLOGGER_PHOTO_ID_5283939621647201138" style="float: right; margin: 0 0 10px 15px; cursor: hand; width: 320px; height: 217px;" src="http://2.bp.blogspot.com/_ZfWK3G30UEA/SVRTFyLks3I/AAAAAAAAAI8/l4BIlN_AjWA/s320/docpreview-embedded_mode.png" border="0" alt="" /></a><br />
To install, drag DocPreview.webplugin into<br />
<tt>/Users/&lt;your name&gt;/Library/Internet Plug-ins</tt><br />
or<br />
<tt>/Library/Internet Plug-ins</tt>.</p>
<p>Screenshots of the plug-in in operation can be seen to the right of this post.  The first pair of images are .doc files in full document mode in the browser and in Word 2008.  The second pair of images are two documents embedded inline using <tt>object</tt> tags, and one of them shown in Word 2008.  As you can see, the conversion fidelity is fairly decent &#8212; this is the same level of fidelity that you would have gotten by importing Word data into TextEdit, or using <tt>textutil</tt> on the command-line.</p>
<p>DocPreview serves the same purpose as Word Browser.  It&#8217;s intended as a quick <em>preview</em> (much like how Google indexes the text in .doc files), so you don&#8217;t blindly download any Word files that actually don&#8217;t interest you.</p>
<p>( As an aside, I cannot understand people who want to <a href="http://www.macosxhints.com/article.php?story=20050422040229515">disable built-in PDF support</a> in Safari :p .  That feature has singlehandedly improved my productivity/research output by a magnitude. )</p>
<p><a href="http://2.bp.blogspot.com/_ZfWK3G30UEA/SVRTHDQXQhI/AAAAAAAAAJM/9sIZQwHwXJc/s1600-h/docpreview_original_doc_embedded.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img id="BLOGGER_PHOTO_ID_5283939643410563602" style="float: right; margin: 0 0 10px 15px; cursor: hand; width: 320px; height: 190px;" src="http://2.bp.blogspot.com/_ZfWK3G30UEA/SVRTHDQXQhI/AAAAAAAAAJM/9sIZQwHwXJc/s320/docpreview_original_doc_embedded.png" border="0" alt="" /></a></p>
<p>In any case, this is a quick hack, since I expect Apple to support .doc previews with the next version(s) of Safari, very soon.  MobileSafari on the iPhone already provides .doc viewing support (and .xls, if I remember correctly).  On Windows, MS provides read support for .doc files within the browser.  DocPreview is just a temporary solution for Safari users until official Apple support (or better yet, better Microsoft Office integration) arrives.</p>
<p>If the thing doesn&#8217;t work for you, let me know via the comment thread.  If it does work, let me know too <img src='http://blog.yimingliu.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />   Any suggestions and comments welcome.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yimingliu.com/2008/12/25/docpreview-plug-in-to-view-word/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Change IP address via (ab)use of DHCP client id</title>
		<link>http://blog.yimingliu.com/2008/12/25/getting-new-ip-address-via-abuse-of/</link>
		<comments>http://blog.yimingliu.com/2008/12/25/getting-new-ip-address-via-abuse-of/#comments</comments>
		<pubDate>Thu, 25 Dec 2008 20:58:00 +0000</pubDate>
		<dc:creator>yiming</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Solutions]]></category>
		<category><![CDATA[AirPort]]></category>
		<category><![CDATA[DHCP]]></category>
		<category><![CDATA[IP address]]></category>
		<category><![CDATA[ISP]]></category>
		<category><![CDATA[networking]]></category>

		<guid isPermaLink="false">https://blog.yimingliu.com/2008/12/25/change-ip-address-via-abuse-of-dhcp-client-id/</guid>
		<description><![CDATA[Nowadays customers using cable modems tend to be re-assigned the same IP address once they get one.  This is apparently done based on the client MAC address &#8212; unless that IP was already taken from the pool when the client connects, the DHCP server will tend to re-issue the old IP.  Fairly nice, [...]]]></description>
			<content:encoded><![CDATA[<p>Nowadays customers using cable modems tend to be re-assigned the same IP address once they get one.  This is apparently done based on the client MAC address &#8212; unless that IP was already taken from the pool when the client connects, the DHCP server will tend to re-issue the old IP.  Fairly nice, in that even for &#8220;dynamic IP addresses&#8221;, the actual IP address assigned rarely changes unless you go offline for an extended period of time.<br />
<a href="http://1.bp.blogspot.com/_ZfWK3G30UEA/SVVJCN2hK7I/AAAAAAAAAKE/e8fWE8xtnVk/s1600-h/airport_dhcp_client_id_field.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img id="BLOGGER_PHOTO_ID_5284210040216038322" style="float: right; margin: 10px 0 10px 10px; cursor: hand; width: 320px; height: 307px;" src="http://1.bp.blogspot.com/_ZfWK3G30UEA/SVVJCN2hK7I/AAAAAAAAAKE/e8fWE8xtnVk/s320/airport_dhcp_client_id_field.png" border="0" alt="" /></a><br />
Problem comes when you actually want to change to a new IP, and can&#8217;t wait around for days without a network connection.  Usually this is accomplished by <a href="http://www.mydigitallife.info/2008/06/30/how-to-change-or-spoof-mac-address-in-windows-xp-vista-server-20032008-mac-os-x-unix-and-linux/">changing the MAC address on your machine or router</a>, in a process called spoofing or cloning.  Most routers will also have a MAC cloning feature.  Swap out the MAC address, and you will be assigned a new IP the next time you connect to the DHCP server.</p>
<p>Except, of course, the Apple AirPort and AirPort Express routers don&#8217;t actually have this feature.  This is understandable, considering that MAC addresses are supposed to be globally unique so as to avoid network problems &#8212; allowing the user to change it willy-nilly will probably not serve that goal.  Nevertheless, it is quite annoying in this case, as you won&#8217;t be able to change IP with an AirPort router using the MAC cloning method.</p>
<p>There&#8217;s one trick that might work for you here, though.  A few ISPs&#8217; DHCP servers are set up to accept DHCP Client IDs &#8212; an optional field that identifies a DHCP client.  While they default to use MAC address as a client identifier by default, they will treat you as a different DHCP client for IP assignment if you start using or change a Client ID.  All that is required to obtain a new IP address, then, is to add a Client ID or change it.  There is an interface for this in the AirPort Utility, as seen in the screenshot.  This is far easier than trying to clone a MAC address on AirPort routers.</p>
<p>Not all ISPs support use of the DHCP Client ID, so this may not work for everyone.  Since there are <a href="http://www.dhcp-handbook.com/dhcp_faq.html#wiaci">uniqueness requirements</a> involved with these client IDs, it is a good way to screw up DHCP assignments if two clients claim the same ID.  If your ISP does support this, make sure to pick a unique client ID.</p>
<p>This trick appears to work for Cox Cable at my current location.  It does <strong>not</strong> appear to work for Comcast.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yimingliu.com/2008/12/25/getting-new-ip-address-via-abuse-of/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Bad Google cookie kills Safari</title>
		<link>http://blog.yimingliu.com/2008/12/11/bad-google-cookie-kills-safari/</link>
		<comments>http://blog.yimingliu.com/2008/12/11/bad-google-cookie-kills-safari/#comments</comments>
		<pubDate>Fri, 12 Dec 2008 04:10:00 +0000</pubDate>
		<dc:creator>yiming</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Solutions]]></category>
		<category><![CDATA[bug]]></category>
		<category><![CDATA[cookies]]></category>
		<category><![CDATA[crash]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[Google OS X]]></category>
		<category><![CDATA[OS X]]></category>
		<category><![CDATA[query suggestion]]></category>
		<category><![CDATA[Safari]]></category>
		<category><![CDATA[WebCore]]></category>

		<guid isPermaLink="false">https://blog.yimingliu.com/2008/12/11/bad-google-cookie-kills-safari/</guid>
		<description><![CDATA[In a bizarre case of digital food poisoning, I experienced a series of mysterious, persistent, reproducible crashes with Safari 3.2.1 this morning, traceable to a bad Google cookie.
The symptoms
Google has a nifty query suggestion feature that is turned on by default on its homepage search box.   Whenever I typed in a phrase query [...]]]></description>
			<content:encoded><![CDATA[<p>In a bizarre case of digital food poisoning, I experienced a series of mysterious, persistent, reproducible crashes with Safari 3.2.1 this morning, traceable to a bad Google cookie.</p>
<h3>The symptoms</h3>
<p>Google has a nifty query suggestion feature that is turned on by default on its homepage search box.   Whenever I typed in a phrase query (e.g. <tt>+"query suggestion" +"Google features"</tt>) with the suggestion feature turned on, the browser crashed with a SIGSEGV around 30% of the time.</p>
<p>Excerpt from the crash log:</p>
<pre>Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x000000001bdca240
Crashed Thread:  0

Thread 0 Crashed:
0   ???                            0x16619e75 0 + 375496309
1   com.apple.WebCore              0x94325ea0 WebCore::AutoTableLayout::fullRecalc() + 704
2   com.apple.WebCore              0x9432581a WebCore::AutoTableLayout::calcPrefWidths(int&amp;, int&amp;) + 26
3   com.apple.WebCore              0x943252b8 WebCore::RenderTable::calcPrefWidths() + 56
4   com.apple.WebCore              0x9431c04b WebCore::RenderBox::minPrefWidth() const + 27
5   com.apple.WebCore              0x9432507c WebCore::RenderTable::calcWidth() + 124
6   com.apple.WebCore              0x943241a8 WebCore::RenderTable::layout() + 392
...</pre>
<p>In the remainder of the cases, when it does not crash immediately, a JavaScript error is logged to the browser error console (to access, go to Develop -&gt; Show Error Console)<br />
<code>SyntaxError: Invalid regular expression: nothing to repeat<br />
http://www.google.com/extern_js/f/CgJlbhICdXMrMAc4AiwrMAo4EywrMA44AywrMBg4Ayw/nMD0sKnpeG0.js (line 21)</code><br />
for every letter that I type into the search box.  During this time, no query suggestion is made.</p>
<h3>Diagnostics</h3>
<ul>
<li>I have never used an InputManager or &#8220;plug-in&#8221; to Safari</li>
<li>The same crash does NOT happen under a fresh new user account created for diagnostic purposes</li>
<li>Clearing the browser cache, temp files, hidden cache files ( <tt>getconf DARWIN_USER_CACHE_DIR</tt> ), etc. did not help.</li>
<li>Deleting Safari preferences did not help.</li>
</ul>
<h3>Solution</h3>
<p>After applying a divide-and-conquer strategy to the entire <tt>~/Library</tt> directory (not made any easier by Finder&#8217;s obstinate resistance to my attempt to move subdirectories within the Library directory, despite having the appropriate permissions &#8212; had to drop to Terminal for this), I traced it to the <tt>~/Library/Cookies</tt> directory.  Moving away the Cookies.plist file contained within cured the crash, the lack of query suggestions, and the Javascript error.  More specifically, deleting all Google-related cookies within the Cookies file also accomplished the same thing.</p>
<h3>Remarks</h3>
<p>Some combination of a bad cookie and bad regexes appears to have triggered a crash bug in this version of WebKit / WebCore.   You wouldn&#8217;t think a bad cookie could take down a browser.  But apparently it does.</p>
<p>I dearly hope this is not a potential buffer overflow or other security problem within WebKit.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yimingliu.com/2008/12/11/bad-google-cookie-kills-safari/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Email servers and the MAIL FROM syntax</title>
		<link>http://blog.yimingliu.com/2008/11/26/email-servers-and-mail-from-syntax/</link>
		<comments>http://blog.yimingliu.com/2008/11/26/email-servers-and-mail-from-syntax/#comments</comments>
		<pubDate>Wed, 26 Nov 2008 21:43:00 +0000</pubDate>
		<dc:creator>yiming</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Solutions]]></category>
		<category><![CDATA[email]]></category>
		<category><![CDATA[SMTP]]></category>

		<guid isPermaLink="false">https://blog.yimingliu.com/2008/11/26/email-servers-and-the-mail-from-syntax/</guid>
		<description><![CDATA[If you&#8217;re into chatting with SMTP servers via telnet ( only for debugging purposes, I swear :p ), be aware that some new email servers strictly interpret RFC 2821 and appears to reject MAIL FROM and RCPT TO addresses of the form foo@example.com.  Instead, it will return a 555 5.5.2 Syntax error.  The [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re into chatting with SMTP servers via telnet ( only for debugging purposes, I swear :p ), be aware that some new email servers strictly interpret <a href="http://www.faqs.org/rfcs/rfc2821.html">RFC 2821</a> and appears to reject <tt>MAIL FROM</tt> and <tt>RCPT TO</tt> addresses of the form <tt>foo@example.com</tt>.  Instead, it will return a <tt>555 5.5.2 Syntax error</tt>.  The proper solution is to enclose the address brackets, as in <tt>&lt;foo@example.com&gt;</tt>.</p>
<p>A redacted transcript:<br />
<code><br />
HELO example.com<br />
250 Hello<br />
MAIL FROM: foo@example.com<br />
555 5.5.2 Syntax error.<br />
MAIL FROM: &lt;foo@example.com&gt;<br />
250 2.1.0 OK<br />
RCPT TO: bar@example.com<br />
555 5.5.2 Syntax error.<br />
RCPT TO: &lt;bar@example.com&amp;gt<br />
250 2.1.5 OK<br />
DATA</code></p>
<p><code> </code></p>
<p><code>....<br />
</code><br />
I&#8217;m sure this is intended so that clients that send &#8220;Joe Schmoe &lt;joe@example.com&gt;&#8221; are correctly interpreted.  I&#8217;m not sure if the RFC asks for this strict enforcement (on my admittedly cursory reading), though and yet a fair number of servers are rejecting the alternate address-only syntax.  Wacky.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yimingliu.com/2008/11/26/email-servers-and-mail-from-syntax/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Romance of the Three Kingdoms XI game event stills</title>
		<link>http://blog.yimingliu.com/2008/10/25/romance-of-three-kingdoms-xi-event/</link>
		<comments>http://blog.yimingliu.com/2008/10/25/romance-of-three-kingdoms-xi-event/#comments</comments>
		<pubDate>Sat, 25 Oct 2008 08:09:00 +0000</pubDate>
		<dc:creator>yiming</dc:creator>
				<category><![CDATA[Games]]></category>
		<category><![CDATA[game]]></category>
		<category><![CDATA[guide]]></category>
		<category><![CDATA[Romance of the Three Kingdoms XI]]></category>
		<category><![CDATA[RotTK XI]]></category>

		<guid isPermaLink="false">https://blog.yimingliu.com/2008/10/25/romance-of-the-three-kingdoms-xi-game-event-stills/</guid>
		<description><![CDATA[In Koei&#8217;s Romance of the Three Kingdoms XI for Windows PC (non PUK, English edition), there are a total of 30 event stills ( basically, pictures of important events during a campaign, viewable under Settings -&#62; Reference -&#62; View Event Stills ). Upon collecting all 30 and winning any scenario to unite China, you will [...]]]></description>
			<content:encoded><![CDATA[<p>In Koei&#8217;s <a href="http://www.koei.com/rtkxipc/">Romance of the Three Kingdoms XI for Windows PC</a> (non PUK, English edition), there are a total of 30 event stills ( basically, pictures of important events during a campaign, viewable under <tt>Settings -&gt; Reference -&gt; View Event Stills</tt> ). Upon collecting all 30 <em>and</em> winning any scenario to unite China, you will unlock top-tier skill sets and all historical portraits when you use Create Officer for your own custom officers. It&#8217;s one of the things required for <a href="http://tvtropes.org/pmwiki/pmwiki.php/Main/HundredPercentCompletion">One Hundred Percent Completion</a> of the game.  However, there has not been a very good guide as to how to achieve all 30 events, especially with problematic and rare ones like <tt>Secret Meeting</tt>.</p>
<p>This post is my attempt to catalog all the event stills and how to obtain them in game.  The events are listed below in order of their appearance on the View Event Stills page.  In general, you only need to view the Event Still once. That means that you can start a game, obtain the Events you want, without actually completing or even saving the game once. Even if you abandon that game later, once you&#8217;ve viewed the event, it counts toward your completion of collecting all 30.</p>
<p>Note that I will not suggest any unreasonably contrived means to get events, even if that might be faster, because I consider these tactics basically cheating.  For example, I will not suggest that you send your sovereign out to die deliberately to get the Sovereign Death event, even if you might be able to do that.  You may also create officers with birth and death dates to your exact specification, to achieve some of these events, but that, too, is basically cheating.  Most of the fun in these events is trying to obtain them fairly while playing a game &#8212; it adds an additional dimension of strategic planning.  If you&#8217;re just going to cheat, stop reading this and go download the fully unlocked sysfile that&#8217;s floating around the Web.</p>
<p><strong>Page 1</strong></p>
<ul>
<li><strong>Plague</strong> &#8211; when a city receives a <tt>Plague</tt> event, causing all sorts of havoc.  You will likely get at least one in any scenario.</li>
<li><strong>Locusts</strong> &#8211; when a city receives a <tt>Locusts</tt> event, decreasing food production in that city.  You will likely get at least one in any scenario.</li>
<li><strong>Plenty</strong> &#8211; when a city receives a <tt>Plenty</tt> event during harvest season, increasing food production in that city.  You will likely get at least one in any scenario.</li>
<li><strong>Bandits</strong> &#8211; when bandits appear in your territories, as the name suggests.  The easiest way to obtain this still is to start the <tt>Yellow Turban Rebellion</tt> scenario.  During the story intro sequence, the Yellow Turbans will rise against the Han court, and this will unlock the event still.</li>
<li><strong>Coronation</strong> &#8211; when an Emperor is crowned, or when you declare support for the Emperor after capturing the capital (Luoyang, Chang&#8217;an, or Xu Chang, depending on the scenario).  Easily achievable in most scenarios if you&#8217;re winning.</li>
<li><strong>Unity: Male</strong> &#8211; when you unite China under a male sovereign.  This event will be unlocked when you win a scenario with a male sovereign.  I prefer Liu Bei, but YMMV <img src='http://blog.yimingliu.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </li>
<li><strong>Unity: Female</strong> &#8211; <em>notes not yet available</em></li>
<li><strong>Downfall</strong> &#8211; when one of the forces in the game is eliminated.  At least one ruler will fall in any game, so this is trivial to obtain.  You can also get this by losing your city in Tutorial 3, <tt>Going into Battle</tt>.</li>
<li><strong>Independence</strong> &#8211; when a prefect or viceroy declares independence and forms his or her own force in a game.  In Tutorial 6, <tt>Capturing Cheng Du</tt>, there is a good chance that Jian Ning will declare independence under the prefect Yong Kai, but it is not guaranteed.  In the 190 scenario, the free cities in Jiangdong may declare independence under their prefects within the first two years.  In any scenario, foment an independence movement in an enemy city via the strategy <tt>Collaborate</tt>.  Alternatively, wait until one of your district viceroys&#8217; or city prefects&#8217; loyalty falls below a certain threshold, at which point an AI force is likely to foment a revolt in that prefecture or district.  Finally, when you&#8217;re winning a full scenario, at the very end of the game one of your officers will ask you to investigate another officer for treason.  If you choose to do so, that officer will be proven innocent, but will revolt anyway due to your distrust of him.  This revolt will trigger an Independence event.</li>
<li><strong>Omen</strong> &#8211; This event is displayed at the start of the year, when your strategist warns that one of your officers is about to die (of natural causes, not in battle).  If you play through a game with historical age settings, quite a few of your officers will die.  Pick a middle scenario, when there are a lot of older officers around.</li>
<li><strong>Sovereign Death</strong> &#8211; when your own sovereign dies of natural causes.  The easiest way to get this one, short of deliberate regicide on your part, is to use Tao Qian in 194, Rival Warlords.  He will most likely die within the next two years, giving you this event.</li>
</ul>
<p><strong>Page 2</strong></p>
<ul>
<li><strong>Officer Death : Male</strong> &#8211; When one of your male officers die.  This is relatively trivial to get &#8211; one will come within the year, after an Omen, for example.  Your officer may also be killed by a cavalry charge or in a duel, if officer deaths are on.</li>
<li><strong>Officer Death : Female</strong> &#8211; When one of your female officers die.  This is a little more annoying, given the sparsity of female officers.  Still, at least one should die in any game.  Your officer may also be killed by a cavalry charge or in a duel.</li>
<li><strong>Funeral</strong> &#8211; When any sovereign (except yours) dies of natural causes &#8212; that is, of illness or old age, <em>not</em> in battle.  In the 194 scenarios, Tao Qian will die within the next two years.  Play the scenario as a ruler other than him, and you will trigger this event still.  </li>
<li><strong>2 Sworn Brothers</strong> &#8211; when you arrange for two male officers to swear brotherhood with each other.  Officers with sworn brothers on the same force will not defect, and will obtain bonuses when both are assigned to the same unit.  You&#8217;ll need two officers of the male gender and at least 500 in Deeds each. You will also need 500 technique points (TPs).  At that point, <tt>Sovereign -&gt; Mediate</tt> will allow you to mediate sworn brotherhood between these two officers and unlock this event.</li>
<li><strong>2 Sworn Sisters</strong> &#8211; when you arrange for two female officers to swear sisterhood with each other.  Officers with sworn sisters on the same force will not defect, and will obtain bonuses when both are assigned to the same unit.  You&#8217;ll need two officers of the female persuasion and at least 500 in Deeds each. You will also need 500 technique points (TPs).  At that point, <tt>Sovereign -&gt; Mediate</tt> will allow you to mediate sworn sisterhood between these two officers and unlock this event.</li>
<li><strong>Male Officer Appears</strong> &#8211; Triggers at the start of a new year, when a male officer (who is related to one of your current officers) arrives to offer his services to your ruler.  For example, as Liu Bei in <tt>211 Liu Bei in Shu</tt> scenario, you will likely receive Zhang Bao &#8211; Zhang Fei&#8217;s son, in 212.  Note that your sovereign should be within a city for this event to occur.</li>
<li><strong>Marriage</strong> &#8211; when you marry one of your officers to another &#8211; married officers will not defect, and obtain bonuses when assigned to the same unit.  You&#8217;ll need two officers of opposite gender, at least 500 in Deeds, and unmarried status. You will also need as 500 technique points (TPs).  At that point, <tt>Sovereign -&gt; Mediate</tt> will allow you to conduct a marriage between these officers and unlock this event.</li>
<li><strong>Fem. Officer Appears</strong> &#8211; Triggers at the start of a new year, when a female officer (who is related to one of your current officers) arrives to offer her services to your ruler.  This one is fairly tricky, because there aren&#8217;t that many female officers.  In general, play one of the middle scenarios as a prominent family.  For example, if you play as Sun Quan in 211, you will get a female officer from the Sun family in 215.</li>
<li><strong>Resignation</strong> &#8211; when an officer resigns from your force due to low loyalty.  This is also a hard one to get if you are a decent player, since you&#8217;d never let an officer&#8217;s loyalty drop low enough.  Note that if your sovereign dies and your officers resign, you will <em>not</em> receive this event still.  You must have this officer resign through low loyalty.  Officers with loyalty less than 70 will tend to resign, and they usually do so on Jan of a new year.  Best way to do this may be to play as Dong Zhuo in 190.  Use your overwhelming starting forces to take down Cao Cao, then hire his wife Bian Shi.  Use Bian Shi to hire Cao Cao.  Dong Zhuo and Cao Cao are disliked officers, so Cao Cao&#8217;s loyalty will start in the 70s and drop fast.  However, since you have his wife in your service, he will not be hired away by another sovereign.  At the start of the next year, Cao Cao will most likely resign from your force.</li>
<li><strong>Decree</strong> &#8211; when an imperial decree arrives.  For example, when the Emperor promotes your sovereign to the rank of Duke, he will use this kind of decree.  Since to win a game, you&#8217;ll likely surpass the rank of Duke, this event is trivial to unlock if you win a game.</li>
<li><strong>Orders</strong> &#8211; when a different type of imperial order arrives.  If you start <tt>190 Cao Cao's Ascent</tt>, the story intro sequence to the scenario involves Cao Cao&#8217;s forged imperial edict arriving at Yuan Shao&#8217;s city.  This will grant you the event still.</li>
</ul>
<p><strong>Page 3</strong></p>
<ul>
<li><strong>Fallen Castle</strong> &#8211; when a city falls to your forces.  You are likely to receive this in Tutorial 6, <tt>Capturing Cheng Du</tt>&#8230;when you capture Cheng Du.  Otherwise, take any city or base, and the event is yours.  Trivial.</li>
<li><strong>Conversation</strong> &#8211; when one of your civil officers head off to search for a friend in the area and obtains his or her services after a debate.  This seems to occur randomly, when your sovereign is in the same city as certain civil officers on his force.  It is the analogous event to &#8220;Search&#8221;, which applies only to military (high WAR) officers.  The event represents the &#8220;conversation&#8221; between your officer and his friend.  This obviously only triggers when there are hidden officers to find in a city &#8212; so start an early scenario with lots of hidden officers for a better shot at the event.</li>
<li><strong>Coalition</strong> &#8211; pick up this event when the coalition against Dong Zhuo forms in <tt>190 Cao Cao's Ascent</tt>, at the very beginning during the story intro sequence.  Otherwise, play as a strong army (say, Cao Cao in 207), and eventually two of your weaker enemies will merge to form a coalition against you.</li>
<li><strong>Search</strong> &#8211; when one of your military officers head off to search for a famous hero in the area and obtains his or her services after a duel.  This seems to occur either randomly or scripted to resemble randomness.  This obviously only triggers when there are hidden officers to find in a city &#8212; so start an early scenario with lots of hidden officers for a better shot at the event.  The 190 scenario with Cao Cao in Xu Chang or Chen Liu should be an easy way to get this event, as you recruit various notables like Dian Wei or Xu Chu.</li>
<li><strong>Secret Meeting</strong> &#8211; when you meet a hidden character for a philosophical discussion.  This one is ridiculously <strong>obscure</strong> and difficult to obtain, to the effect that many people do not know how to obtain it.  Forum posts and such suggest that you&#8217;d receive this when the AI foments unrest with one of your viceroys or prefects (one of the in-game log messages say &#8220;your prefect blah is meeting someone secretly&#8221;.  However, that is a red herring.  One post correctly identifies that the Secret Meeting event is awarded for <a href="http://www.gamespot.com/pc/strategy/romanceofthethreekingdomsxi/show_msgs.php?topic_id=m-1-45918990&amp;pid=931351">meeting a hidden character such as Xu Shao during a Search</a>.  As Cao Cao in <tt>190 Cao Cao's Ascent</tt>, if you keep Searching the area around Chen Liu or Ru Nan, against your strategist&#8217;s advice that nothing would be found, you will eventually encounter Xu Shao, who will do a physiogamy reading for you, unlocking this event.   One of the early scenarios, such as Rise of Dong Zhuo, is preferred for obtaining this event.  Just keep Searching your city, a lot, and fruitlessly most of the time.  You&#8217;ll get this eventually ( took me under two game years of on-and-off searching in Chen Liu while holding off Dong Zhuo&#8217;s army ).  A comment from <strong>Lance Lidner</strong> reports that using Kong Zhou in Rise of Dong Zhuo works best, as Xu Shao appears in Ru Nan at that time.  Kong Zhou is also out of immediate reach from most hostile factions in that scenario, so you can afford to take your time.</li>
<li><strong>Appoint</strong> &#8211; when the emperor issues a new title to you.  This occurs when you&#8217;ve captured enough cities to reach the next rank, and that your sovereign is currently in a city (as opposed to being on campaign).  As Liu Bei in the <tt>211 Liu Bei in Shu</tt> scenario, taking Xiang Yang (via Jiang Ling &#8211; you&#8217;ve got Zhuge Liang, Pang Tong, Zhang Fei, Liu Bei, Sun Shang Xiang, Zhao Yun &#8230; that&#8217;s plenty to take the city from Cao Ren early on) and Yong An will bump you up to Field Marshal, and Emperor Xian will award you the title and this event.  As Cao Cao in <tt>190 Cao Cao's Ascent</tt>, taking the free cities of Xu Chang and Xin Ye will grant the title of Lt. Governor, which once again easily unlocks this event.</li>
<li><strong>3 Sworn Brothers</strong> &#8211; when you arrange for three male officers to swear brotherhood, much like the historical <a href="http://en.wikipedia.org/wiki/Oath_of_the_Peach_Garden">Oath of the Peach Garden</a> of Liu Bei, Guan Yu, and Zhang Fei.  Officers with sworn brothers on the same force will not defect, and will obtain bonuses when two or more are assigned to the same unit.  You&#8217;ll need three officers of the male gender and at least 500 in Deeds each. You will also need 500 technique points (TPs).  At that point, <tt>Sovereign -&gt; Mediate</tt> will allow you to mediate sworn brotherhood between these officers and unlock this event.</li>
<li><strong>3 Sworn Sisters</strong> &#8211; when you arrange for three female officers to swear sisterhood.  Officers with sworn sisters on the same force will not defect, and will obtain bonuses when two or more are assigned to the same unit.  You&#8217;ll need three officers of the female persuasion and at least 500 in Deeds each. You will also need 500 technique points (TPs).  At that point, <tt>Sovereign -&gt; Mediate</tt> will allow you to mediate sworn sisterhood between these officers and unlock this event.  The hardest part of this is rounding up 3 female officers to begin with.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.yimingliu.com/2008/10/25/romance-of-three-kingdoms-xi-event/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>redhillonrails_core and broken MySQL empty string defaults</title>
		<link>http://blog.yimingliu.com/2008/10/16/redhillonrailscore-and-broken-mysql/</link>
		<comments>http://blog.yimingliu.com/2008/10/16/redhillonrailscore-and-broken-mysql/#comments</comments>
		<pubDate>Thu, 16 Oct 2008 09:39:00 +0000</pubDate>
		<dc:creator>yiming</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Solutions]]></category>
		<category><![CDATA[bug]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[redhillonrails_core]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[workaround]]></category>

		<guid isPermaLink="false">https://blog.yimingliu.com/2008/10/16/redhillonrails_core-and-broken-mysql-empty-string-defaults/</guid>
		<description><![CDATA[While hacking on a side project in Ruby on Rails, I ran across this weird error when trying to insert new data:
ActiveRecord::StatementInvalid: Mysql::Error: Column 'attr2' cannot be null: INSERT INTO `foo` (`attr1`, `attr2`) ...  VALUES ('1', NULL) 
where attr2 is a varchar (or t.string, in Rails lingo) and set to not null default '' [...]]]></description>
			<content:encoded><![CDATA[<p>While hacking on a side project in Ruby on Rails, I ran across this weird error when trying to insert new data:</p>
<p><code>ActiveRecord::StatementInvalid: Mysql::Error: Column 'attr2' cannot be null: INSERT INTO `foo` (`attr1`, `attr2`) ...  VALUES ('1', NULL) </code></p>
<p>where <tt>attr2</tt> is a <tt>varchar</tt> (or <tt>t.string</tt>, in Rails lingo) and set to <tt>not null default ''</tt> (or, in other words, <tt>:null=&gt;false, :default=&gt;''</tt>).  Strangely enough, instead of the default value of &#8221;, ActiveRecord was setting the value to <tt>nil</tt> instead, which translates into a NULL.  Since the schema explicitly forbids NULLs on that column, the statement explodes.</p>
<p>After an hour of poking around and hacking up a spike solution, it turns out  a plugin was to blame.  I&#8217;d pulled in the <a href="http://www.redhillonrails.org/foreign_key_migrations.html">foreign_key_migrations</a> plugin (a highly recommended add-on) to automatically install foreign key constraints (in this day and age, the foremost web framework still can&#8217;t automatically handle FOREIGN KEY constraints, the most basic tool for ensuring data integrity in relational databases, for its migrations?  Bah!).</p>
<p>This plugin has a dependency on <a href="http://www.redhillonrails.org/redhillonrails_core.html">redhillonrails_core</a>, which has a known bug: <a href="http://rubyforge.org/tracker/index.php?func=detail&amp;aid=9003&amp;group_id=1699&amp;atid=6632">Incorrectly overwrites mysql empty-string default with nil for string/text/binary types</a>.</p>
<p>The bug is apparently not being worked on as of the time of this writing.  The dev doesn&#8217;t consider this a bug, as he claims that &#8220;[he considers] empty strings to be semantically identical to NULL&#8221;.</p>
<p>This position, unfortunately, is not supported by the SQL standard.  Wikipedia has a section on <a href="http://en.wikipedia.org/wiki/Sql_null#Common_mistakes">common SQL NULL mistakes</a> documenting some of the potential problems involved in making such an assumption.  <a href="http://philip.greenspun.com/sql/data-modeling.html">Philip Greenspun</a> has further notes on this.  Using NULLs trigger the all the arcane annoyances of three-valued logic, and you must be prepared to consider True, False, and NULL values as comparison outcomes.  Someone not very versed in three-valued logic can easily cause a number of subtle mistakes trying to compare values.</p>
<p>To workaround this bug, you will need to comment out the <tt>initializer</tt> function in</p>
<p><tt>vendor/plugins/redhillonrails_core/lib/red_hill_consulting/core/active_record/connection_adapters/mysql_column.rb</tt></p>
<p>Alternatively, you can delete the file, and remove relevant references to it..</p>
<p>If you agree with dev&#8217;s position that NULLs are &#8220;semantically identical&#8221; to empty strings, remember to pay attention when you formulate your SQL queries (and when Rails formulates those queries) &#8212; your results may not be what you expect, if implemented naively.  Get your three-valued logic truth tables out <img src='http://blog.yimingliu.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yimingliu.com/2008/10/16/redhillonrailscore-and-broken-mysql/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>APR and 32-bit/64-bit universal binary compilation</title>
		<link>http://blog.yimingliu.com/2008/10/14/apr-and-32-bit64-bit-universal-binary-compilation/</link>
		<comments>http://blog.yimingliu.com/2008/10/14/apr-and-32-bit64-bit-universal-binary-compilation/#comments</comments>
		<pubDate>Tue, 14 Oct 2008 09:53:00 +0000</pubDate>
		<dc:creator>yiming</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Solutions]]></category>
		<category><![CDATA[10.5]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[APR]]></category>
		<category><![CDATA[bug]]></category>
		<category><![CDATA[compilation]]></category>
		<category><![CDATA[Leopard]]></category>
		<category><![CDATA[OS X]]></category>
		<category><![CDATA[Subversion]]></category>

		<guid isPermaLink="false">https://blog.yimingliu.com/2008/10/14/apr-and-32-bit64-bit-universal-binary-compilation/</guid>
		<description><![CDATA[When compiling APR, the Apache Portable Runtime 1.3.3 (as a part of Subversion 1.5.3 as I am doing here, or not) on OS X 10.5 Leopard, you may encounter the following error at compile time.
/bin/sh /tmp/subversion-1.5.3/apr/libtool --silent --mode=compile gcc-4.2 -Os -arch i386 -arch x86_64 -DHAVE_CONFIG_H -DDARWIN -DSIGPROCMASK_SETS_THREAD_MASK -no-cpp-precomp   -I./include -I/tmp/subversion-1.5.3/apr/include/arch/unix -I./include/arch/unix -I/tmp/subversion-1.5.3/apr/include/arch/unix -I/tmp/subversion-1.5.3/apr/include [...]]]></description>
			<content:encoded><![CDATA[<p>When compiling APR, the Apache Portable Runtime 1.3.3 (as a part of Subversion 1.5.3 as I am doing here, or not) on OS X 10.5 Leopard, you may encounter the following error at compile time.</p>
<p><code>/bin/sh /tmp/subversion-1.5.3/apr/libtool --silent --mode=compile gcc-4.2 -Os -arch i386 -arch x86_64 -DHAVE_CONFIG_H -DDARWIN -DSIGPROCMASK_SETS_THREAD_MASK -no-cpp-precomp   -I./include -I/tmp/subversion-1.5.3/apr/include/arch/unix -I./include/arch/unix -I/tmp/subversion-1.5.3/apr/include/arch/unix -I/tmp/subversion-1.5.3/apr/include  -o strings/apr_snprintf.lo -c strings/apr_snprintf.c &amp;&amp; touch strings/apr_snprintf.lo<br />
strings/apr_snprintf.c: In function ‘conv_os_thread_t’:<br />
strings/apr_snprintf.c:500: error: duplicate case value<br />
strings/apr_snprintf.c:498: error: previously used here<br />
strings/apr_snprintf.c: In function ‘conv_os_thread_t_hex’:<br />
strings/apr_snprintf.c:671: error: duplicate case value<br />
strings/apr_snprintf.c:669: error: previously used here</code></p>
<p>This will most likely happen when you are configured to build a dual 32-bit / 64-bit universal binary, whether it be ppc / ppc64, or i386 / x86_64, or any permutation thereof.  <a href="https://trac.macports.org/ticket/15523">This ticket</a> over at MacPorts documents a particular instance of this problem, with no apparent solution.</p>
<p>The symptom is easy to explain.  Somehow, two case labels in the relevant switch statement in <tt>strings/apr_snprintf.c:500</tt>:</p>
<pre><code>switch(sizeof(u.tid)) {
    case sizeof(apr_int32_t):
        return conv_10(u.u32, TRUE, &amp;is_negative, buf_end, len);
    case sizeof(apr_int64_t):
        return conv_10_quad(u.u64, TRUE, &amp;is_negative, buf_end, len);
    default:
        /* not implemented; stick 0 in the buffer */
        return conv_10(0, TRUE, &amp;is_negative, buf_end, len);
    }</code></pre>
<p>have evaluated to the same value.  In particular, it believes that <tt>sizeof(apr_int32_t)</tt> and <tt>sizeof(apr_int64_t)</tt> are the same value.  As we all know in C, you cannot have two identical case labels in the same switch statement.  However, the <em>root</em> of the problem is a bit more subtle.</p>
<p>In <tt>$SRCDIR/include/apr.h</tt>, you&#8217;re likely to see this fragment of code.</p>
<pre><code>typedef  long       apr_int64_t;
typedef  unsigned long  apr_uint64_t;</code></pre>
<p>Notice that it has typdef&#8217;ed <tt> apr_int64_t</tt> as a <tt>long</tt> and <tt> apr_uint64_t</tt> as <tt>unsigned long</tt>.  This is because at configure time, the script detected that long values are 64-bit on this system, so it assigned the apache 64-bit types to longs.  However, this only holds true for <em>half</em> of the compilation &#8211; because you are building a universal binary for a 32-bit architecture as well.  Remember that in 32-bit GCC on OS X, longs are 32-bit rather than 64-bit.  Your run-of-the-mill autoconf script, done by a non-OS X programmer, isn&#8217;t going to be able to detect this subtlety &#8211; if the 64-bit part worked, it&#8217;ll keep thinking <tt>long</tt>s are 64-bit, end of story &#8211; and happily generate the incorrect typedef expressions.  When you apply <tt>sizeof</tt> to these types in apr_snprintf.c, both evaluate to 4 bytes under 32-bit compilation, thus blowing up the compile run.</p>
<p>To truly fix the root of the problem requires rewriting the autoconf script to detect Mac OS X and its universal binary building, which can potentially throw quadruple architectures at the same compilation script.  However, a quick hack to make this particular problem go away is to change apr.h such that:</p>
<pre><code>typedef  long long       apr_int64_t;
typedef  unsigned long long apr_uint64_t;</code></pre>
<p>Now that we ensure in either 32-bit or 64-bit compilation, apr_int64_t and apr_uint64_t are always typedef&#8217;ed to appropriate, guaranteed 64-bit types.  The compilation of APR (and Subversion) will proceed normally.</p>
<p>Note that <tt>long long</tt> is not an standard C type.  As a GCC extension, this fix is a kludge.  A kludge that works (for me), though.</p>
<p>UPDATE:<br />
There may also be an issue with sizeof definitions that may cause the library to crash.  In particular, there may be occurrences of</p>
<pre><code>#define APR_SIZEOF_VOIDP 8</code></pre>
<p>that were generated by configure.  To fix this, you will need to remove the define and have the compiler check for 64-bit at compile-time:</p>
<pre>
<code>#ifndef __LP64__
    #define APR_SIZEOF_VOIDP 4
#else
    #define APR_SIZEOF_VOIDP 8
#endif</code></pre>
<p>In general, any predefined sizeofs need to be changed.  I am not sure why the APR developers do hard-coded defines like this, given that the point of having <tt>sizeof()</tt> calls is to avoid such issues.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yimingliu.com/2008/10/14/apr-and-32-bit64-bit-universal-binary-compilation/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>using ffmpeg for cutting media files &#8211; and the gotchas involved</title>
		<link>http://blog.yimingliu.com/2008/10/07/ffmpeg-encoding-gotchas/</link>
		<comments>http://blog.yimingliu.com/2008/10/07/ffmpeg-encoding-gotchas/#comments</comments>
		<pubDate>Wed, 08 Oct 2008 07:56:00 +0000</pubDate>
		<dc:creator>yiming</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Solutions]]></category>
		<category><![CDATA[ffmpeg]]></category>
		<category><![CDATA[gotcha]]></category>

		<guid isPermaLink="false">https://blog.yimingliu.com/2008/10/07/using-ffmpeg-for-cutting-media-files-and-the-gotchas-involved/</guid>
		<description><![CDATA[So here I was, trying to complete some ordinary transcoding / media file cutting tasks with ffmpeg.  Turns out there are some weird gotchas when using some versions of ffmpeg (in my case, SVN-r10571) on the commandline.
Problem 1:  transcoding to mp3 insists on using 64kbits/s or 128kbits/s bitrate
So a simple task is to [...]]]></description>
			<content:encoded><![CDATA[<p>So here I was, trying to complete some ordinary transcoding / media file cutting tasks with ffmpeg.  Turns out there are some weird gotchas when using some versions of ffmpeg (in my case, SVN-r10571) on the commandline.</p>
<h3>Problem 1:  transcoding to mp3 insists on using 64kbits/s or 128kbits/s bitrate</h3>
<p>So a simple task is to transcode an audio file of some arbitrary format to MP3.  In my case, I only wanted a 30-second piece of the original file, converted to MP3.  The original was in 256kbits/s, and I decided to use the same bitrate for the output, just for kicks.  Reading the man page, <tt>-b</tt> is for video bitrate, and <tt>-ab</tt> is for audio bitrate.  So I executed:</p>
<p><span style="color: #ff0000;">wrong:</span>  <code>ffmpeg -ss 00:00:30.00 -t 25 -i foo.mp3 -ab 256 foo-new.mp3</code></p>
<p>The output, of course, was this:<br />
<code><br />
Input #0, mp3, from 'foo.mp3':<br />
...<br />
mdb:109, lastbuf:0 skipping granule 0<br />
size=     393kB time=25.2 bitrate= 128.0kbits/s<br />
video:0kB audio:393kB global headers:0kB muxing overhead 0.007950%<br />
</code></p>
<p>128 kbits/s.  That was&#8230;not what I wanted.</p>
<p>Turns out, as the ffmpeg man page hints but does not specify clearly, a &#8220;k&#8221; is required to label the units of the new bitrate.  As in:</p>
<p><span style="color: #33ff33;">right</span>:  <code>ffmpeg -ss 00:00:30.00 -t 25 -i foo.mp3 -ab 256k foo-new.mp3</code></p>
<p>This time, the output was:<br />
<code>Input #0, mp3, from 'foo.mp3':<br />
...<br />
mdb:109, lastbuf:0 skipping granule 0<br />
size=     782kB time=25.0 bitrate= 256.0kbits/s<br />
video:0kB audio:782kB global headers:0kB muxing overhead 0.003996%</code></p>
<p>Much better.  It&#8217;s very strange how that if I don&#8217;t give it the ending &#8220;k&#8221; but do give it a higher value than 64, it always bumps up the bitrate to 128kbits/s, from the default of 64k (but not to the number I actually wanted).</p>
<p> </p>
<h3>Problem 2:  cutting media file without re-encoding</h3>
<p>So ffmpeg can be used to cut a media file, without reencoding the media stream.  You simply pass the raw copy codec to the -acodec (or the -vcodec for video) at encode time.  For my MP3, I thought it was a pretty trivial problem, so I issued:</p>
<p><span style="color: #ff0000;">wrong</span>: <code>ffmpeg -i bar.mp3 -ss 00:00:30.00 -t 25 -acodec copy bar-new.mp3</code></p>
<p>This seemed to process correctly, except it created a 555-byte empty file with no content in it.  What&#8217;s even weirder, if you issued:</p>
<p><span style="color: #ff0000;">wrong</span>: <code>ffmpeg -i bar.mp3 -ss 00:00:10.00 -t 25 -acodec copy bar-new.mp3</code></p>
<p>That is, <tt>-ss 00:00:10.00</tt> to seek to the 10th second, and <tt>-t 25</tt> to record 25 seconds worth of audio.  Strangely enough, the output file had 15 seconds of audio, the subtraction of 25 by 10.  Curiouser and curiouser.  Now,</p>
<p><span style="color: #ff0000;">wrong</span>: <code>ffmpeg -i bar.mp3 -ss 00:00:10.00 -t 25 -acodec mp3 bar-new.mp3</code></p>
<p>does in fact create a 25-second MP3 file.  Only, of course, a re-encoded one at 64kbits/s.  Something that we are not looking for.  But strange.</p>
<p>A <a href="http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/2006-November/018277.html">post on ffmpeg-devel</a> finally provided enough hints to clue me into the problem.  Unlike many command line apps, the order of arguments passed to ffmpeg seem to be silently significant.  The correct incantation is:</p>
<p><span style="color: #33ff33;">right</span>: <code>ffmpeg -ss 00:00:30.00 -t 25 -i bar.mp3 -acodec copy bar-new.mp3</code></p>
<p>Note the switched order for the arguments <tt>-i</tt> and the args <tt>-ss</tt> and <tt>-t</tt>, where the -i must follow the other two.  Now, the desired 25-second file, cut from the original, is correctly produced.</p>
<p>When arguments are missing some arbitrary text or in the wrong order, ffmpeg doesn&#8217;t sanity-check or warn you of these&#8230;it just silently proceeds and does some very strange things.  Things that make you scratch your head and wonder, &#8220;wtf?  did I mistype an argument somewhere?&#8221;</p>
<p>Ah,  and of course, you make me have to track down all these little idiosyncrasies, wading through blog posts and mailing lists and forums.  Agh.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yimingliu.com/2008/10/07/ffmpeg-encoding-gotchas/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Subversion and undefined symbols</title>
		<link>http://blog.yimingliu.com/2008/09/29/subversion-and-undefined-symbols/</link>
		<comments>http://blog.yimingliu.com/2008/09/29/subversion-and-undefined-symbols/#comments</comments>
		<pubDate>Tue, 30 Sep 2008 06:13:00 +0000</pubDate>
		<dc:creator>yiming</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Solutions]]></category>
		<category><![CDATA[bug]]></category>
		<category><![CDATA[glibtool]]></category>
		<category><![CDATA[libtool]]></category>
		<category><![CDATA[OS_X]]></category>
		<category><![CDATA[Subversion]]></category>
		<category><![CDATA[SVN]]></category>
		<category><![CDATA[workaround]]></category>

		<guid isPermaLink="false">https://blog.yimingliu.com/2008/09/29/subversion-and-undefined-symbols/</guid>
		<description><![CDATA[This is fast turning out to be a blog about compiling open source software.  Maybe I should change the title.
You may get this error while trying to compile Subversion 1.5.2:ld: Undefined symbols:_svn_fs_txn_root_base_revision referenced from libsvn expected to be defined in libsvn_svn_fs_change_txn_props referenced from libsvn expected to be defined in libsvn_svn_fs_get_mergeinfo referenced from libsvn expected [...]]]></description>
			<content:encoded><![CDATA[<p>This is fast turning out to be a blog about compiling open source software.  Maybe I should change the title.</p>
<p>You may get this error while trying to compile Subversion 1.5.2:<br /><code>ld: Undefined symbols:<br />_svn_fs_txn_root_base_revision referenced from libsvn expected to be defined in libsvn<br />_svn_fs_change_txn_props referenced from libsvn expected to be defined in libsvn<br />_svn_fs_get_mergeinfo referenced from libsvn expected to be defined in libsvn<br />_svn_fs_recover referenced from libsvn expected to be defined in libsvn<br />_svn_fs_upgrade referenced from libsvn expected to be defined in libsvn<br />_svn_fs_node_origin_rev referenced from libsvn expected to be defined in libsvn<br />/usr/bin/libtool: internal link edit command failed<br />make: *** [subversion/libsvn_ra_local/libsvn_ra_local-1.la] Error 1</code></p>
<p>Turns out there may be a bug in the libtool script shipped with the source tarball, under certain circumstances with OS X 10.4, that causes it to fail to link.  Ah, libtool, you make my life so much harder sometimes.</p>
<p>If you copy <tt>/usr/bin/glibtool</tt> over <tt>$SRCDIR/libtool</tt> (that is, into the directory for the subversion source code, replacing the one that is placed there by the package itself), the package should compile with no further complaints.  <tt>make test</tt> also shows success on all tests, so this seems a satisfactory solution.</p>
<p><strong>UPDATE 1/31/2009</strong><br />
I&#8217;ve been informed in the comments that MacPorts may rely on source compilation from tarball, and thus have this issue.  If you&#8217;re having this issue with the MacPorts SVN package, please check out the advice in the comment section from <strong>farkinga</strong>, who has additional notes.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yimingliu.com/2008/09/29/subversion-and-undefined-symbols/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>GNUMake 3.80 and failed malloc</title>
		<link>http://blog.yimingliu.com/2008/09/16/gnumake-380-and-failed-malloc/</link>
		<comments>http://blog.yimingliu.com/2008/09/16/gnumake-380-and-failed-malloc/#comments</comments>
		<pubDate>Tue, 16 Sep 2008 23:02:00 +0000</pubDate>
		<dc:creator>yiming</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Solutions]]></category>
		<category><![CDATA[compilation]]></category>
		<category><![CDATA[GNU Make]]></category>
		<category><![CDATA[OS X]]></category>

		<guid isPermaLink="false">https://blog.yimingliu.com/2008/09/16/gnumake-380-and-failed-malloc/</guid>
		<description><![CDATA[Wacky compilation error:

Creating config.mak and config.h...
make(4162) malloc: *** vm_allocate(size=4272971776) failed (error code=3)
make(4162) malloc: *** error: can't allocate region
make(4162) malloc: *** set a breakpoint in szone_error to debug
make[1]: *** virtual memory exhausted.  Stop.

This error has nothing to do with the particular code you&#8217;re compiling.  Turns out GNU Make 3.80 has a bug, in which [...]]]></description>
			<content:encoded><![CDATA[<p>Wacky compilation error:<br />
<code><br />
Creating config.mak and config.h...<br />
make(4162) malloc: *** vm_allocate(size=4272971776) failed (error code=3)<br />
make(4162) malloc: *** error: can't allocate region<br />
make(4162) malloc: *** set a breakpoint in szone_error to debug<br />
make[1]: *** virtual memory exhausted.  Stop.<br />
</code></p>
<p>This error has nothing to do with the particular code you&#8217;re compiling.  Turns out GNU Make 3.80 has a bug, in which it sometimes sends a ridiculous requested block size to malloc(), which then fails to allocate the space.</p>
<p>The solution is to upgrade to GNUMake 3.81.  Particularly pernicious on OS X 10.4 and Xcode 2.4.1.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yimingliu.com/2008/09/16/gnumake-380-and-failed-malloc/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>AVCodecContext, Perian, and the Xcode dylib fetish</title>
		<link>http://blog.yimingliu.com/2008/09/09/perian-and-xcode-dylib-fetish/</link>
		<comments>http://blog.yimingliu.com/2008/09/09/perian-and-xcode-dylib-fetish/#comments</comments>
		<pubDate>Tue, 09 Sep 2008 21:22:00 +0000</pubDate>
		<dc:creator>yiming</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Solutions]]></category>
		<category><![CDATA[compilation]]></category>
		<category><![CDATA[dynamic library]]></category>
		<category><![CDATA[OS X]]></category>
		<category><![CDATA[Perian]]></category>
		<category><![CDATA[workaround]]></category>
		<category><![CDATA[Xcode]]></category>

		<guid isPermaLink="false">https://blog.yimingliu.com/2008/09/09/avcodeccontext-perian-and-the-xcode-dylib-fetish/</guid>
		<description><![CDATA[The Context
So recently I was trying to interact with an avi file with a video stream encoded in H.264 and an audio stream encoded in MP3.  To my surprise, my trusty Perian 1.1 failed to even play the video and gave me a black screen (though the audio played just fine).  With some [...]]]></description>
			<content:encoded><![CDATA[<h4>The Context</h4>
<p>So recently I was trying to interact with an avi file with a video stream encoded in H.264 and an audio stream encoded in MP3.  To my surprise, my trusty Perian 1.1 failed to even play the video and gave me a black screen (though the audio played just fine).  With some Google-fu, it was found in a <a href="http://forums.cocoaforge.com/viewtopic.php?f=25&amp;t=16525&amp;st=0&amp;sk=t&amp;sd=a">forum post</a> that the SVN version of Perian fixed this error.</p>
<p>So compile my own Perian 1.1.1b1 from SVN, right?  No big deal.  Heh.  And thus begins our story.  (Note that this procedure is accurate as of the time of writing.  OSS projects change rapidly as bugfixes are checked in.  You may not have this problem at all.  But it&#8217;s still useful as a reference in the future, in case similar problems arise).</p>
<h4>Problem 1: AVCodecContext.bits_per_sample</h4>
<p>The first problem you hit is probably:<br />
<code>/tmp/perian-orig/ff_private.c:181: error: ‘struct AVCodecContext’ has no member named ‘bits_per_sample’</code><br />
&#8230;<br />
<code>/tmp/perian-orig/FFissionCodec/FFissionDecoder.cpp:289: error: ‘struct AVCodecContext’ has no member named ‘bits_per_sample’</code><br />
<a href="http://4.bp.blogspot.com/_ZfWK3G30UEA/SMbyAqf19wI/AAAAAAAAAIA/We58PiRrAio/s1600-h/avcodec_bits_per_sample.png"><img id="BLOGGER_PHOTO_ID_5244144909341292290" style="float:right; margin:20px 10px 10px 10px;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_ZfWK3G30UEA/SMbyAqf19wI/AAAAAAAAAIA/We58PiRrAio/s320/avcodec_bits_per_sample.png" border="0" alt="" /></a><br />
Turns out that the upstream project FFMPEG, who is responsible for libavcodec, has very recently changed the API in one of its latest revisions.  <tt>bits_per_sample</tt> has become<br />
<tt>bits_per_coded_sample</tt> in <a href="http://svn.mplayerhq.hu/ffmpeg/trunk/libavcodec/avcodec.h?revision=15262&amp;view=markup">revision 15262</a>.  Because Perian&#8217;s SVN does an external SVN checkout of the HEAD of libavcodec, it pulled these API-breaking changes without considering whether that breaks its own compilation or not.</p>
<p>The fix is simple enough: global search and replace the member variable to <tt>bits_per_coded_sample</tt>.</p>
<h4>Problem 2: Xcode&#8217;s unnatural fondness for dynamic libraries</h4>
<p>At this point, libavcodec compiles, so you think you&#8217;re home free.  For <strong>most users</strong>, that is probably the case.  For some of us, though, there&#8217;s one more hurdle.</p>
<p>While compiling Perian.component, you might get something like:<br />
<code>ld warning: in /Developer/SDKs/MacOSX10.4u.sdk/usr/local/lib/libavcodec.dylib, file is not of required architecture</code><br />
<code>Undefined symbols:<br />
"_avcodec_close", referenced from:</code><br />
&#8230;and so on</p>
<p>Closer examination reveals that at some point, you might have compiled FFMPEG or MPlayer or any of the many media projects that depend on FFMPEG libraries (for me, that was <a href="http://www.transcoding.org/cgi-bin/transcode">transcode</a>, whose own <a href="http://sarth.thallos.org/2008/07/transcode-105-error-on-intel-os-x.html">compilation idiosyncracies</a> I documented in an earlier post).   When you installed these libraries, they went into your library search path.  Note the Perian compilation line immediately preceding the compile failure:<br />
<code>/Developer/usr/bin/g++ ... -read_only_relocs suppress -lavcodec -lavformat -lavutil -lebml -lmatroska ... /tmp/perian/UniversalDetector/build/Release/libuniversaldetector.a -lbz2 -o /tmp/perian/build/Deployment/Perian.component/Contents/MacOS/Perian</code></p>
<p><a href="http://1.bp.blogspot.com/_ZfWK3G30UEA/SMb2st7uH_I/AAAAAAAAAII/h8NZLtTfLSs/s1600-h/xcode_static_link_fallacy.png"><img id="BLOGGER_PHOTO_ID_5244150064224280562" style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_ZfWK3G30UEA/SMb2st7uH_I/AAAAAAAAAII/h8NZLtTfLSs/s320/xcode_static_link_fallacy.png" border="0" alt="" /></a>As you can see, the <tt>-lavcodec</tt> linker argument will cause the linker go on the search path and try to find the library.  It of course first finds your pre-installed library in /usr/local/lib or some other system lib path, and tries to use it.  If you compiled that library as Intel only or PPC only and you tried to build a universal Perian, that would obvious fail and generate an architecture error.  If you, like me, compiled only for x86_64 or ppc64, that would also trigger the same architecture problem (as Perian builds as x86 32-bit).</p>
<p>This problem stumped a user &#8220;vs&#8221;, in this <a href="http://groups.google.com/group/perian-discuss/browse_thread/thread/9f844cee48e54449/b7946570c52a52c1">Perian-discuss Google groups thread</a>.  Notice how the devs didn&#8217;t get the root of the problem, and answered snarkily and defensively to the user bug report.</p>
<p>The devs aren&#8217;t wrong, though.  Didn&#8217;t we just see a statically compiled target, <tt>libavcodec.a</tt>, in the <a href="http://1.bp.blogspot.com/_ZfWK3G30UEA/SMb2st7uH_I/AAAAAAAAAII/h8NZLtTfLSs/s1600-h/xcode_static_link_fallacy.png">target list for the Perian Xcode project</a>?  Why yes, yes we did!  In fact, there are static targets for all of the <tt>-lav*</tt> libraries in the Xcode project.  So why did the linker go off and use <tt>-lavcodec</tt> rather than, say, <tt>$PERIAN_DIR/build/Universal/libavcodec.a</tt>, as instructed?</p>
<h5>The workaround</h5>
<p>In short: Xcode is screwing things up.  Xcode 3.1 has a distinct (some say, unnatural) preference for dynamic libraries.  When you add a library to the &#8220;Link Binary With Library&#8221; listing under Targets, it simply adds a <tt>-l&lt;libname&gt;</tt> to the link line to pass to <tt>ld</tt> at link time.  When this happens, it will look for lib&lt;libname&gt;.dylib (in this case, libavcodec.dylib, libavformat.dylib, libavutil.dylib, etc in your library path.  If it finds one, it will use that one rather than the static library you provided in the Xcode project file.  Obviously, this ends up linking the wrong library, perhaps with the wrong architecture or the wrong version.  Compilation explodes.</p>
<p>The workarounds are not very clean.  There seems to be no good way to instruct Xcode to forget its dynamic library fetish and use the static versions you provide.  You could remove the dylibs from the system library path entirely &#8212; when the linker fails to find the .dylib version, it will fall back to the .a.</p>
<p>Alternatively, you can explicitly instruct it to use static linking as an environment flag and remove the built-in Xcode linker relationships:</p>
<ol>
<li>Right-click on your Target (in this case, Perian) and Get Info to bring up the Target Info box.</li>
<li>Go to the <tt>Build</tt> tab</li>
<li>Select your Build configuration &#8211; in this case, probably <tt>Deployment</tt></li>
<li>Find or locate OTHER_LD_FLAGS, also called &#8220;Other Linker Flags&#8221;</li>
<li>Manually add the paths to the .a files in this field, one at a time.  If you don&#8217;t know the path, right-click -&gt; Get Info on the desired libraries under <tt>Link Binary With Library</tt>, and it should show you a field called Full Path on the <tt>General</tt> tab.  That&#8217;s the path to use.  Should look something like <tt>/tmp/perian/build/Universal/libavcodec.a</tt></li>
<li>Do the same for all offending libraries &#8211; this may include libavcodec, libavformat, libavutil, libmatroska, etc.</li>
<li><strong>Remove</strong> the libraries you added to Other Linker Flags from your Xcode&#8217;s <tt>Target -&gt; Target Name -&gt; Link Binary With Library</tt> section, to stop Xcode from auto-generating broken linker flags.  This is <strong>important</strong>.</li>
</ol>
<p>If done correctly, this should no longer find the wrong type of the library.  Your compilation of Perian should proceed as normal.</p>
<h4>The Moral of the Story</h4>
<p>Xcode has some weird idiosyncratic ways of building its projects.  It&#8217;s useful to poke at things and find out about these behaviors.  Its unnatural preference for dynamic libraries over your explicit instructions is disturbing, though.</p>
<p>Don&#8217;t attack your users when they pose a problem, and drop the attitude of: ooo, we&#8217;re doing this for free, so fsck off, users.  In both problems, the exact same attitude surfaced amongst a few of the devs.  Arrogance (<em>&#8220;we don&#8217;t have the responsibility to do anything for you&#8221;</em>) and snarky dismissal (<em>&#8216;Well, there&#8217;s your problem.  We don&#8217;t build libavcodec.dylib nor do we  place it in /usr/local/lib.&#8217;</em>) helps no one.  No matter what you thought your build script did, the linker is heading off toward /usr/local/lib, and you better damn well find out why.</p>
<p>It&#8217;s obvious that there&#8217;s something peculiar going on with the link process, and the user tried to make it clear multiple times (<em>&#8220;You missed my point.  We build a .a file and we don&#8217;t put it in /usr/local/lib.&#8221;</em>), but no one seems to pay attention.  Following that thread, the user is increasingly frustrated and expresses that, and now the dev&#8217;s hammer of arrogance comes down hard ( <em>&#8220;You looked like a prick here, to  be honest.&#8221;</em> &#8212; really?  not your obtuse-ness or your blindness to a user need?)</p>
<p>When you have a &#8220;works-for-me&#8221; situation, it&#8217;s especially important to communicate effectively with the user.  In most cases, you have no idea why it blows up for the user and not for you.  Admitting it is fine &#8212; could be a very localized issue for that user, or could reveal a subtle systemic problem in your code &#8211; either way, it&#8217;s useful to have that established.  I realize we&#8217;re all very busy people, but at the end of the day it&#8217;s still your project.  Either acknowledge you have no idea what&#8217;s going on and solicit help and cooperation with the user who&#8217;s having this issue, or man up, put on your detective hat, and fix your own damn problems.  The rest of us are busy with our own issues.</p>
<p>The Free Software culture seems to breed this sort of contempt for the user in some devs.  Might be a paper in analyzing how corrosive this can be.</p>
<p>UPDATED:  I certainly do not mean this last section as a criticism for all Free Software devs.  The vast majority of people I&#8217;ve talked to in the various communities are really knowledgeable, helpful folks.  There are just a few people in some cases, though, who seem to think that if the user can&#8217;t make the software work, it&#8217;s somehow the user&#8217;s fault.  It&#8217;s a joint problem to be solved together, not &#8220;you&#8217;re an idiot if you can&#8217;t make it work&#8221;.</p>
<p>UPDATED 2 (9-29-2008): <a href="http://perian.org/#download">Perian</a> 1.1.1 has been released.  This should fix the original problem with H.264 and .avi files that prompted this post.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yimingliu.com/2008/09/09/perian-and-xcode-dylib-fetish/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>transcode 1.0.5 invalid immediate error on Intel OS X</title>
		<link>http://blog.yimingliu.com/2008/07/29/transcode-105-error-on-intel-os-x/</link>
		<comments>http://blog.yimingliu.com/2008/07/29/transcode-105-error-on-intel-os-x/#comments</comments>
		<pubDate>Tue, 29 Jul 2008 15:09:00 +0000</pubDate>
		<dc:creator>yiming</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Solutions]]></category>
		<category><![CDATA[assembly]]></category>
		<category><![CDATA[compilation]]></category>
		<category><![CDATA[error]]></category>
		<category><![CDATA[OS X]]></category>
		<category><![CDATA[transcode]]></category>
		<category><![CDATA[x86]]></category>

		<guid isPermaLink="false">https://blog.yimingliu.com/2008/07/29/transcode-105-invalid-immediate-error-on-intel-os-x/</guid>
		<description><![CDATA[If you&#8217;re compiling transcode 1.0.5 from source on OS X Intel (for some odd reason, as I&#8217;ve just had to do on 10.5.4), your compile run may blow up in aclib with:

tcmemcpy.c:30:missing or invalid immediate expression `0b111' taken as 0
tcmemcpy.c:30:suffix or operands invalid for `and'
tcmemcpy.c:42:missing or invalid immediate expression `0b1000' taken as 0
tcmemcpy.c:42:suffix or operands [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re compiling transcode 1.0.5 from source on OS X Intel (for some odd reason, as I&#8217;ve just had to do on 10.5.4), your compile run may blow up in <tt>aclib</tt> with:</p>
<p><code><br />
tcmemcpy.c:30:missing or invalid immediate expression `0b111' taken as 0<br />
tcmemcpy.c:30:suffix or operands invalid for `and'<br />
tcmemcpy.c:42:missing or invalid immediate expression `0b1000' taken as 0<br />
tcmemcpy.c:42:suffix or operands invalid for `test'<br />
tcmemcpy.c:52:missing or invalid immediate expression `0b1111' taken as 0<br />
</code></p>
<p>The problem here appears to be that the code in <tt>tcmemcpy.c</tt> under x86 and x86_64 relies on some inline assembly features not supported by all compiler/assemblers.  Namely, the use of <tt>0b</tt> (binary immediate) operands in assembly instructions is not apparently supported during compilation under Apple gcc and gcc-4.2.</p>
<p>Setting the CCAS flag did not seem to help.  A quick fix, then, is to <em>convert all binary immediates</em> in the asm instructions to hex or decimal.</p>
<p>Thankfully, these operands only existed in tcmemcpy, so there&#8217;s not too much work.  Look for 0bxxxx immediates and convert them to their hex or decimal equivalent.  For example, 0b111 is 0&#215;7, 0b1000 is 0&#215;8, 0b1111 is 0xf.  Thus, a line like:<br />
<code> and $0b111, %%eax       # ... which is the number of bytes to copyn </code></p>
<p>becomes<br />
<code> and $0x7, %%eax         # ... which is the number of bytes to copyn </code></p>
<p>Once these operands are modified, the compiler should no longer complain about  invalid immediate expressions.</p>
<p>In any case, the latest CVS version of transcode should have resolved these problems already.  The workaround should only be necessary if you still must compile the release tarball for 1.0.5.</p>
<p>Updated:  There is a second potential problem if you were using ffmpeg-SVN and transcode 1.0.5, in which its hard-coded include lookup for avcodec.h always looks for ffmpeg/avcodec.h.  The SVN version of ffmpeg has moved these headers to libavcodec/avcodec.h.  <a href="http://fr-de.lunar-linux.org/lunar/patches/transcode-1.0.5-lavc-paths.patch">A path patch for transcode 1.0.5 and ffmpeg</a> is available, which basically boils down to changing the <tt>#include</tt> headers and the configure.in file to look for the new path.</p>
<p>Updated:  A third problem has now cropped up, with the ffmpeg API change that moved AVCodecContext&#8217;s bits_per_sample to bits_per_coded_sample.  A global search and replace seems to work for now.  See this also in my <a href="http://sarth.thallos.org/2008/09/perian-and-xcode-dylib-fetish.html">post on compiling Perian</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yimingliu.com/2008/07/29/transcode-105-error-on-intel-os-x/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>libpng12.*.dylib related compile failures on OS X 10.5</title>
		<link>http://blog.yimingliu.com/2008/07/27/libpng12dylib-related-compile-failures-on-os-x-105/</link>
		<comments>http://blog.yimingliu.com/2008/07/27/libpng12dylib-related-compile-failures-on-os-x-105/#comments</comments>
		<pubDate>Mon, 28 Jul 2008 05:37:00 +0000</pubDate>
		<dc:creator>yiming</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Solutions]]></category>
		<category><![CDATA[compilation]]></category>
		<category><![CDATA[error]]></category>
		<category><![CDATA[libpng]]></category>
		<category><![CDATA[libtool]]></category>
		<category><![CDATA[OS X]]></category>

		<guid isPermaLink="false">https://blog.yimingliu.com/2008/07/27/libpng12dylib-related-compile-failures-on-os-x-105/</guid>
		<description><![CDATA[
If you&#8217;ve been having problems compiling various Unix packages on OS X 10.5.4, and that your compile run fails mysteriously with something like: 
i686-apple-darwin9-gcc: /usr/X11/lib/libpng12.0.26.0.dylib: No such file or directory
One strange yet very likely explanation:  your libtool archive file /usr/X11/lib/libpng12.la is lying about the location of the shared library for libpng12 &#8212; namely, that [...]]]></description>
			<content:encoded><![CDATA[<div class="separator" style="text-align: center; clear: both;"><a href="http://4.bp.blogspot.com/_ZfWK3G30UEA/SI1d5Ozo3BI/AAAAAAAAAHg/Lp2BPWfNLwI/s1600-h/lying-libpng-la.png" style="background-color: transparent; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; clear: right; margin-bottom: 1em; float: right; margin-left: 1em;"><img alt="broken libpng screenshot" src="http://4.bp.blogspot.com/_ZfWK3G30UEA/SI1d5Ozo3BI/AAAAAAAAAHg/Vv20ekvNLFg/s320-R/lying-libpng-la.png" style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial;" /></a></div>
<p>If you&#8217;ve been having problems compiling various Unix packages on OS X 10.5.4, and that your compile run fails mysteriously with something like: </p>
<p><code>i686-apple-darwin9-gcc: /usr/X11/lib/libpng12.0.26.0.dylib: No such file or directory</code></p>
<p>One strange yet very likely explanation:  your libtool archive file <tt>/usr/X11/lib/libpng12.la</tt> is lying about the location of the shared library for libpng12 &#8212; namely, that a file called <tt>/usr/X11/lib/libpng12.0.26.0.dylib</tt> exists and should be used for linking against libpng12.  However, if you actually look in <tt>/usr/X11/lib</tt>, no such file exists &#8211; perhaps you might have <tt>libpng.0.24.0.dylib</tt>, but not .26.  Therefore, packages that make use of this incorrect libtool archive metadata are suitably confused, causing the compiler to bail out when trying to link against this non-existent file.</p>
<p>Since libtool archive (.la) files are text-based, you can open it up in emacs.  The quick and dirty fix to this is to simply change the offending <tt>library_names</tt> and the <tt>current</tt> and <tt>age</tt> properties to the correct numbers.  In my case, the libpng sitting in <tt>/usr/X11/lib</tt> was .24, and so I string-replaced all the values in those three properties from 26 to 24.  The compilation then proceeded normally.</p>
<p>The long term solution, of course, is to track down what put a wrong .la file there in the first place.  I suspect Xcode 3.1 and Mac OS X SDK 10.5, which shipped with the latest iPhone SDK.</p>
<p>UPDATED 9/8/2008:<br />In the comments section, I&#8217;ve been informed that the X11SDK package in Xcode 3.1 in the culprit.  Thanks Anonymous!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yimingliu.com/2008/07/27/libpng12dylib-related-compile-failures-on-os-x-105/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Processing monitoring and Settlers of Catan save failure</title>
		<link>http://blog.yimingliu.com/2008/06/22/processing-monitoring-and-settlers-of-catan-save-failure/</link>
		<comments>http://blog.yimingliu.com/2008/06/22/processing-monitoring-and-settlers-of-catan-save-failure/#comments</comments>
		<pubDate>Sun, 22 Jun 2008 15:34:00 +0000</pubDate>
		<dc:creator>yiming</dc:creator>
				<category><![CDATA[Games]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Solutions]]></category>
		<category><![CDATA[bug]]></category>
		<category><![CDATA[Process Monitor]]></category>
		<category><![CDATA[ProcMon]]></category>
		<category><![CDATA[Sysinternals]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[XP]]></category>

		<guid isPermaLink="false">https://blog.yimingliu.com/2008/06/22/processing-monitoring-and-settlers-of-catan-save-failure/</guid>
		<description><![CDATA[Some versions of Bigfish Games&#8217; Settlers of Catan (a faithful reproduction of the board game) have a strange issue, in which under certain operating contexts, it will not save a game.  The error message reported is a generic and not-at-all useful &#8221; an error has occurred while saving &#8220;.  I suspected this was [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://3.bp.blogspot.com/_ZfWK3G30UEA/SF586zr_T_I/AAAAAAAAAHQ/f-bw1Tfq_Ic/s1600-h/procmon-catan.png"><img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_ZfWK3G30UEA/SF586zr_T_I/AAAAAAAAAHQ/f-bw1Tfq_Ic/s320/procmon-catan.PNG" border="0" alt="process monitor finding Catan issues" id="BLOGGER_PHOTO_ID_5214742768290582514" /></a><br />Some versions of Bigfish Games&#8217; <span style="font-style:italic;">Settlers of Catan</span> (a faithful reproduction of the board game) have a strange issue, in which under certain operating contexts, it will not save a game.  The error message reported is a generic and not-at-all useful &#8221; an error has occurred while saving &#8220;.  I suspected this was due to the fact that it failed to create a savegame directory, and indeed, a bit of sleuthing indicates that on Windows XP, the directory at <tt>C:\Documents and Settings\All Users\Application Data\Microsoft\MSN Games\Catan</tt> is missing (obviously on Vista, this would be somewhere else &#8211; probably C:\Users\&#8230;).  Instead of creating this directory, Catan simply fails to save the game.  The program runs fine otherwise.</p>
<p>Of course, it was not obvious where Catan was trying to save its games &#8211; finding out that missing directory was the culprit took a bit of investigation.  I took a wild stab at the start by creating a &#8220;save&#8221; directory in its own program files directory.  No such luck.  Time to bring out the big guns.</p>
<p>A number of ways could have been used, but one is to use the awesome Sysinternals tool <a href="http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx">Process Monitor</a>, or Procmon.exe.  It tracks events and calls from a process, such as filesystem accesses, and has advanced filtering capability to organize and show only the events of interest to a debugging human.</p>
<p>With ProcMon, I simply filtered on the Catan process and tried to save a game as <tt>foo</tt>.  Then, viewing the event log (screenshot 1), it was obvious that <tt>CreateFile</tt> calls to create <tt>foo.sav</tt> failed, with the exact target path specified.  A quick Windows Explorer excursion confirms that the path does not exist.  Creating that directory, of course, solved the savegame problem.</p>
<p>The moral of the story is that ProcMon is a fine tool for tracking mysterious interactions between an application and a system.  For something like failing to make a saved game (in this narrow gamig context) or various system-related errors in general (especially when you lack the source code to debug in depth), it sometimes pays to examine the exact sequence of calls and events that led up to the failure.  The solution could be very trivial, if you only knew what and where things failed.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yimingliu.com/2008/06/22/processing-monitoring-and-settlers-of-catan-save-failure/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Changing keyboard shortcut for &quot;Find Next&quot; in Word 2008</title>
		<link>http://blog.yimingliu.com/2008/05/20/changing-keyboard-shortcut-for-find-next-in-word-2008/</link>
		<comments>http://blog.yimingliu.com/2008/05/20/changing-keyboard-shortcut-for-find-next-in-word-2008/#comments</comments>
		<pubDate>Wed, 21 May 2008 04:29:00 +0000</pubDate>
		<dc:creator>yiming</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Solutions]]></category>
		<category><![CDATA[keyboard shortcuts]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[Microsoft Office]]></category>
		<category><![CDATA[Word]]></category>

		<guid isPermaLink="false">https://blog.yimingliu.com/2008/05/20/changing-keyboard-shortcut-for-find-next-in-word-2008/</guid>
		<description><![CDATA[Pierre Igot over at Betalogue writes of a way to reassign the keyboard shortcut for the &#8220;Find Next&#8221; command in Word 2008.
This has bothered me for a very long time.  In essence, Office 2008 maps Command-G, the customary Mac OS keyboard shortcut for &#8220;Find Next&#8221; (in essence, to find the next instance of a [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://1.bp.blogspot.com/_ZfWK3G30UEA/SGnP0x7WrTI/AAAAAAAAAHY/yoYICltaGd0/s1600-h/msword-goto.png"><img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_ZfWK3G30UEA/SGnP0x7WrTI/AAAAAAAAAHY/yoYICltaGd0/s320/msword-goto.png" border="0" alt="changing Find Next... shortcut in Microsoft Word 2008" id="BLOGGER_PHOTO_ID_5217930148947864882" /></a><br />Pierre Igot over at Betalogue writes of a way to <a href="http://www.betalogue.com/2008/05/20/word-2008-how-to-assign-command-g-to-find-next/">reassign the keyboard shortcut</a> for the &#8220;Find Next&#8221; command in Word 2008.</p>
<p>This has bothered me for a very long time.  In essence, Office 2008 maps Command-G, the customary Mac OS keyboard shortcut for &#8220;Find Next&#8221; (in essence, to find the next instance of a string match and part of the set of standard Find/Replace [All] functions in any good text editor / word processor), to &#8220;Go To&#8221;.</p>
<p>To its credit, Word allows customization of its keyboard shortcuts.  Unfortunately, I just could not locate the &#8220;FindNext&#8221; keyboard shortcut in Tools -> Customize Keyboard to apply customizations to.  Turns out it&#8217;s actually named &#8220;RepeatFind&#8221;, as opposed to &#8220;EditFindNext&#8221;, which you&#8217;d expect when the &#8220;Find&#8230;&#8221; command is simply &#8220;EditFind&#8221;.</p>
<p>Further, it turns out that wouldn&#8217;t have mattered anyway.  Microsoft overrides the keyboard shortcut selection behavior in View -> Customize Toolbars and Menus.  It does so in a ridiculously arcane way, by which the menu name &#8220;&#038;Go To&#8221; fixes the shortcut key to Command-G.  Therefore, no matter what shortcut is set in Customize Keyboard, Command-G will always map to Go To and not Find Next.  ARGH.</p>
<p>Even knowing this, it was not obvious how to edit the name either (screenshot).  Apparently the solution is to use the fake menu bars that pop up after selecting Customize Toolbars and Menus, and then <span style="font-style:italic;">right-click</span> or Control-click the Go To menu item.  That will pop up an edit box with the name of the menu item, at which point you can remove the gratuitous &#038;, such that Command-G will map correctly based on Customize Keyboard.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yimingliu.com/2008/05/20/changing-keyboard-shortcut-for-find-next-in-word-2008/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Baldur&#8217;s Gate 1 graphics glitch and disabling NVidia hardware acceleration</title>
		<link>http://blog.yimingliu.com/2008/04/16/baldurs-gate-1-graphics-glitch-and-disabling-nvidia-hardware-acceleration/</link>
		<comments>http://blog.yimingliu.com/2008/04/16/baldurs-gate-1-graphics-glitch-and-disabling-nvidia-hardware-acceleration/#comments</comments>
		<pubDate>Wed, 16 Apr 2008 09:19:00 +0000</pubDate>
		<dc:creator>yiming</dc:creator>
				<category><![CDATA[Games]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Solutions]]></category>
		<category><![CDATA[Baldur's Gate]]></category>
		<category><![CDATA[bug]]></category>
		<category><![CDATA[DirectX]]></category>
		<category><![CDATA[hardware acceleration]]></category>
		<category><![CDATA[NVidia]]></category>
		<category><![CDATA[Vista]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[workaround]]></category>

		<guid isPermaLink="false">https://blog.yimingliu.com/2008/04/16/baldurs-gate-1-graphics-glitch-and-disabling-nvidia-hardware-acceleration/</guid>
		<description><![CDATA[If you have a series 8 NVidia graphics card (say, an 8600M GT) with current drivers (as of the time of this post, of course), you&#8217;re likely to see graphics glitches (screenshot 1) in Baldur&#8217;s Gate 1.  One workaround is to use 16-bit color and software transparent BLT.  Another strategy, if your CPU [...]]]></description>
			<content:encoded><![CDATA[<p>If you have a series 8 NVidia graphics card (say, an 8600M GT) with current drivers (as of the time of this post, of course), you&#8217;re likely to see graphics glitches (screenshot 1) in Baldur&#8217;s Gate 1.  One workaround is to use 16-bit color and software transparent BLT.  Another strategy, if your CPU is powerful enough to shoulder some 2D graphics work, is to temporarily turn off hardware acceleration for DirectDraw and avoid the bug entirely.  <a href="http://2.bp.blogspot.com/_ZfWK3G30UEA/SAXnecVJY7I/AAAAAAAAAGQ/XuisYwZ0rqM/s1600-h/bg1-vista-broken.png"><img id="BLOGGER_PHOTO_ID_5189808655801344946" style="float:right; margin:10px 0 10px 10px;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_ZfWK3G30UEA/SAXnecVJY7I/AAAAAAAAAGQ/XuisYwZ0rqM/s320/bg1-vista-broken.png" border="0" alt="black boxes in Baldur's Gate under Nvidia 2D acceleration" /></a></p>
<p>However, disabling hardware acceleration under Vista is apparently easier said than done.  Instead of using the Personalization -&gt; Display Settings control panel (as one might think to do based on Windows XP experience), the correct solution is to use the <a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=572BE8A6-263A-4424-A7FE-69CFF1A5B180&amp;displaylang=en">DirectX SDK</a> and dxcpl.exe, the DirectX Control Panel (located within the SDK distribution under <tt>Utilities\bin\[cpu_arch]\</tt>.  From within this control panel, pick DirectDraw on the upper tab bar.  Amongst the various configuration options available on that tab, the only one you care about is the box to turn on or turn off hardware acceleration.  Turn that off (temporarily, of course) and you&#8217;re good to go.</p>
<h3>The Context</h3>
<p>Baldur&#8217;s Gate 1 performs surprisingly well under Windows Vista, despite being a venerable (some might say, &#8216;ancient&#8217;) 10-year old RPG.  Unfortunately it&#8217;s plagued by a number of graphics glitches when running on NVidia cards.  In essence, a number of items and sprites (items on the belt, the timepiece to the lower left corner, birds flying overhead, for example) will be surrounded by black outlines.  Further, on your character paper doll in the Inventory screen, giant black boxes obscure much of the figure.  In some cases, the &#8216;fog of war&#8217; on the unexplored regions of a map will be rectangular black boxes, rather than the &#8216;foggy&#8217; darkness you&#8217;re used to.  <a href="http://forums.bioware.com/viewtopic.html?topic=618432&amp;forum=11">These glitches</a> are <a href="http://www.shsforums.net/index.php?showtopic=30840">widely</a> <a href="http://www.gamespot.com/pc/rpg/baldursgate/show_msgs.php?topic_id=m-1-42316077&amp;pid=75251">experienced</a>.</p>
<p>For this very annoying problem, two workarounds are available.</p>
<h4>1.  Trade color depth for correctness</h4>
<p>The prevalent strategy, as noted in <a href="http://www.shsforums.net/index.php?showtopic=30840">a forum post at Spellhold Studios</a>, is to switch on Software Transparent BLT <em>and</em> use 16-bit color depth.  This apparently routes around whatever strange bug NVidia managed to introduce in their graphics acceleration layer.</p>
<p>This method works just fine, but was not ideal for me.  The game runs at 640 x 480, and is already quite pixelated when scaled up to full screen.  16-bit vs 32-bit color is somewhat noticeable, once at that scale.</p>
<h4>2.  Trade performance for correctness</h4>
<p>Here&#8217;s another classic trade-off.  Since the problem is obviously arising from the DirectX layer and its interaction with NVidia graphics hardware (boot into safe mode and run BG1 to verify this), another solution is to just kick NVidia out of the loop by disabling hardware acceleration for DirectDraw.  This is feasible if you&#8217;re doing this on a fast machine (and if you&#8217;re using a series-8 card in that box, I&#8217;d assume it&#8217;s pretty fast anyway) &#8211; after all, BG1 is a 10-year old game.  Your Core 2 Duo or quad-core Xeon can use some exercise anyway.</p>
<h3>Of Hardware Acceleration Controls</h3>
<p>In the glory days of XP, this simply meant right-click on <tt>Desktop -&gt; Properties -&gt; Settings -&gt; Advanced -&gt; Troubleshoot -&gt; Hardware Acceleration slider</tt> (dear god that&#8217;s convoluted).  In Vista, the analogous experience is right-click on <tt>Desktop -&gt; Personalize -&gt; Display Settings -&gt; Advanced Settings -&gt; Troubleshoot -&gt; Change Settings</tt> (I see you still haven&#8217;t hired that user experience designer, Microsoft).</p>
<p>The problem now is that if you try this with your NVidia card and Vista, you&#8217;ll just be staring at a disabled &#8216;Change Settings&#8217; button and a terse message: <tt>'Your current display driver does not allow changes to be made to hardware acceleration settings.'</tt> If you also try the old standby <tt>dxdiag</tt>, you might be surprised to know that the <tt>Disable</tt> buttons have been removed from the <tt>DirectX Features</tt> box on the <tt>Display</tt> tab.  Thanks, NVidia and Microsoft.  Apparently they really don&#8217;t want us changing these settings.</p>
<p>But we don&#8217;t really want to change much &#8211; just the DirectX technologies, and in fact, just the 2D-based DirectDraw (since 3D is more or less irrelevant for BG1), and only for a short while.  Enter the DirectX SDK.</p>
<p>The SDK is meant for developing and debugging DirectX-based programs, but it comes with a fair suite of nifty utilities, one of which being the DirectX Control Panel: dxcpl.exe.  Download the 400+ MB <a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=572BE8A6-263A-4424-A7FE-69CFF1A5B180&amp;displaylang=en">SDK</a> and grab the control panel in Utilities\bin (starting from where you installed the SDK to).  Make sure that if you are on x64 (x86_64) that you also use the x86 architecture switches for BG1 (see comments for this post for more details).</p>
<p>In the control panel, use the DirectDraw tab &#8211; in the set of checkboxes, uncheck the &#8220;Use Hardware Acceleration&#8221; box.  Fire up BG1 and see the non-black-boxed goodness of 1998 graphics (screenshot 2).<br />
<a href="http://1.bp.blogspot.com/_ZfWK3G30UEA/SAXnfMVJY8I/AAAAAAAAAGY/zn3E8m_1kJ4/s1600-h/bg1-vista-fixed.png"><img id="BLOGGER_PHOTO_ID_5189808668686246850" style="float:right; margin:10px 0 10px 10px;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_ZfWK3G30UEA/SAXnfMVJY8I/AAAAAAAAAGY/zn3E8m_1kJ4/s320/bg1-vista-fixed.png" border="0" alt="Baldur's Gate playing normally after disabling Nvidia-accelerated DirectDraw" /></a><br />
If you were disabling acceleration for another reason, this control panel should work for you too &#8211; pick the appropriate tab and have at it.  <strong>Do not forget to turn acceleration back on</strong> after the session.  You probably do not want unaccelerated graphics performance in your normal, non-glitchy apps.</p>
<p>Turning off hardware accelerated DirectDraw avoids the BG1 black-box bug.  You&#8217;ll have to assess for yourself which is more expendable: color depth (trivial to change directly from BG1&#8217;s Options configuration) or graphics performance (more difficult to tweak, but perhaps compensated by CPU performance).</p>
<h4>DirectX SDK vs Settings slider</h4>
<p>In any case, the DirectX control panel is a somewhat useful trick to know in general, especially when faced with Vista&#8217;s obstinate insistence on not letting you change graphics acceleration settings.  The control panel provides all the functionality that the old XP Settings slider would have give you &#8211; except in a much more technical interface.  In fact, the old slider more or less tweaked settings in the Direct3D and DirectDraw tabs, except in a coarse-grained, all-or-nothing kind of way.  Here at least you have fine-grained control on most of the detailed options in each panel.</p>
<p>Still, such a pain.</p>
<p>Know that tweaking these settings are done at your own risk (NVidia and MS obviously are against it), and may or may not work at all depending on your setup, your driver version, and pure luck.  On the plus side, if you ever need to write some DirectX apps, the SDK is now just a few clicks and SDK path text fields away from Visual Studio 2005/2008, so the 400 MB bandwidth and disk space isn&#8217;t completely wasted.  Hopefully.</p>
<p><strong>UPDATE 9/8/2008</strong><br />
It&#8217;s come to my attention that some people still have problems after applying this fix &#8211; namely, there are cursor trails on menu screens.  I cannot reproduce this issue locally on my 8600M GT, but it&#8217;s possible that there are new problems introduced with newer series-8 cards and drivers.  If this is the case, I&#8217;d recommend using the first workaround &#8212; that is, using Software BLT and 16-bit color, rather than the DirectDraw workaround.</p>
<p><strong>UPDATE 7/15/2009</strong><br />
There is now a <a href="http://www.shsforums.net/index.php?showtopic=30840">Nvidia driver .dll patcher</a> available for BG1-era Infinity Engine games at Spellhold Studios.  They also explain what the underlying issue is and what the DLL wrapper does to work around the bug.  I have not personally tested this fix.  It does install a new graphics DLL that overrides existing calls, so it is theoretically possible that it may introduce other issues, but I am told by others that it works quite well.  Check it out &#8212; it saves you a lot of trouble of ticking DirectDraw boxes on and off.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yimingliu.com/2008/04/16/baldurs-gate-1-graphics-glitch-and-disabling-nvidia-hardware-acceleration/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>SSH and SOCKS proxy &#8211; almost as good as a VPN</title>
		<link>http://blog.yimingliu.com/2008/03/19/ssh-and-socks-proxy-almost-as-good-as-a-vpn/</link>
		<comments>http://blog.yimingliu.com/2008/03/19/ssh-and-socks-proxy-almost-as-good-as-a-vpn/#comments</comments>
		<pubDate>Wed, 19 Mar 2008 08:17:00 +0000</pubDate>
		<dc:creator>yiming</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Solutions]]></category>
		<category><![CDATA[networking]]></category>
		<category><![CDATA[SSH]]></category>

		<guid isPermaLink="false">https://blog.yimingliu.com/2008/03/19/ssh-and-socks-proxy-almost-as-good-as-a-vpn/</guid>
		<description><![CDATA[OpenSSH has a port forwarding feature, which can be used as a SOCKS proxy server.  This is useful if you are trying to reach a firewalled server which only accepts connections with from within its own local network (but doesn&#8217;t offer a VPN service to let you onto its local network).  
If you [...]]]></description>
			<content:encoded><![CDATA[<p>OpenSSH has a port forwarding feature, which can be used as a SOCKS proxy server.  This is useful if you are trying to reach a firewalled server which only accepts connections with from within its own local network (but doesn&#8217;t offer a VPN service to let you onto its local network).  </p>
<p>If you have SSH access to any other machine on that local network, you can use the forwarding feature and the SOCKS 4 or 5 protocol to get to the server from your home box.  The connection is mediated and forwarded by the machine on the network that you can reach, and to the firewalled server, you appear to be this internal machine.</p>
<p>The appropriate incantation is simply:<br /><code>ssh -D port_num ssh_hostname</code></p>
<p>where port_num is a local port number (I like 50000, but any non-privileged port would be good)</p>
<p>Then, simply point your system or browser (in Firefox, for example, this would be in Preferences/Options -> Advanced -> Network -> Settings ) to use a SOCKS proxy at localhost, port port_num.  Now accesses from that browser will be proxied through the ssh_hostname machine to the actual remote_host.</p>
<p>The context is that there was an application server that I had to reach from my home machine.  The application server sits on machine <span style="font-style:italic;">R</span>, which is restricted to an organization internal network <span style="font-style:italic;">I</span>.  There is no VPN service for <span style="font-style:italic;">I</span>.  SSH to machine <span style="font-style:italic;">H</span> was available, which is also in <span style="font-style:italic;">I</span> and is reachable from the public Internet.  For small things, I could run commands from <span style="font-style:italic;">H</span>, but it would have been really helpful to reach <span style="font-style:italic;">R</span> directly from my home development box.  I could use X11 forwarding to get an xterm for various tools there, but the overhead is huge.  The administrator of network <span style="font-style:italic;">I</span> has yet to grant me external access.</p>
<p>With this trick, just SSH&#8217;ed into machine <span style="font-style:italic;">H</span>, set up the proxy port via -D, set up my browser to proxy through the local port, and easily accessed <span style="font-style:italic;">R</span> from home.  Nifty.</p>
<p>If you happen to have SSH access to a number of servers (as I seem to have for some reason&#8230;), this same trick can be used as a way to rotate through them fairly quickly.  Just log out of your existing connection and ssh into a new  host with the -D switch.  This allows you to test various network apps from a number of different machines.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yimingliu.com/2008/03/19/ssh-and-socks-proxy-almost-as-good-as-a-vpn/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cannot populate a select element under IE 6 using the innerHTML property</title>
		<link>http://blog.yimingliu.com/2008/02/12/cannot-populate-select-element-under-ie/</link>
		<comments>http://blog.yimingliu.com/2008/02/12/cannot-populate-select-element-under-ie/#comments</comments>
		<pubDate>Tue, 12 Feb 2008 09:30:00 +0000</pubDate>
		<dc:creator>yiming</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Solutions]]></category>
		<category><![CDATA[bug]]></category>
		<category><![CDATA[gotcha]]></category>
		<category><![CDATA[innerHTML]]></category>
		<category><![CDATA[Internet Explorer]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[select]]></category>

		<guid isPermaLink="false">https://blog.yimingliu.com/2008/02/12/cannot-populate-a-select-element-under-ie-6-using-the-innerhtml-property/</guid>
		<description><![CDATA[On the other hand, here is an obvious bug in IE 6 that I managed to run into.  In IE 6, if you attempt to dynamically change the contents of a &#60;select&#62; element in Javascript, via assigning a new string containing &#60;option&#62; elements to its innerHTML property, the select element will not be populated. [...]]]></description>
			<content:encoded><![CDATA[<p>On the other hand, here is an obvious bug in IE 6 that I managed to run into.  In IE 6, if you attempt to dynamically change the contents of a &lt;select&gt; element in Javascript, via assigning a new string containing &lt;option&gt; elements to its innerHTML property, the <tt>select</tt> element will not be populated.  In fact, if you output the string after the assignment, it will be truncated and malformed.</p>
<p>This is documented via <a href="http://support.microsoft.com/kb/276228">Microsoft KB article 276228</a>.  Microsoft&#8217;s proposed fix, in abstract: &#8220;don&#8217;t do that&#8221;.</p>
<p>So I was trying my hand at some fancy AJAX to dynamically populate a select dropdown menu based on a previous select menu.  An xmlhttprequest is triggered onChange of the first menu. We hit up an API, parse and transform the response into this HTML fragment consisting of &lt;option&gt; tags and values, and assign to the innerHTML property.  Simple and quick.  Works on Safari, Firefox&#8230;and of course, not on IE 6.</p>
<p>Some time wasted later, an alert() on the innerHTML property shows that in fact, the string there is malformed.  The first &lt;option&gt; start tag is truncated from the innerHTML.  No wonder it doesn&#8217;t work; it&#8217;s malformed.  And it wasn&#8217;t, to start with, when my transformation finished and delivered the final string.</p>
<p>The apparent solution is to follow Microsoft&#8217;s advice on that page and do something else:<br />
- assign to the options collection<br />
- workaround using outerHTML</p>
<p>I&#8217;m sure there&#8217;s a way to jury rig it so that IE is fooled into concat&#8217;ing an &#8220;&lt;option&gt;&#8221; back onto the innerHTML, and disabling this workaround for other user agents.  But that&#8217;s rather inelegant, no?  I opted to use the options collection, which seems a reasonable (if slightly more complicated) method than just a simple assignment to innerHTML.</p>
<p>The KB article lists this as a problem with IE 5, but it recurs in IE 6.  Does it persist in IE 7?</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yimingliu.com/2008/02/12/cannot-populate-select-element-under-ie/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>IE 6 renders a blank page on XHTML-style script end tag</title>
		<link>http://blog.yimingliu.com/2008/02/11/ie-6-renders-blank-page-on-xhtml-style/</link>
		<comments>http://blog.yimingliu.com/2008/02/11/ie-6-renders-blank-page-on-xhtml-style/#comments</comments>
		<pubDate>Tue, 12 Feb 2008 07:33:00 +0000</pubDate>
		<dc:creator>yiming</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Solutions]]></category>
		<category><![CDATA[blank page]]></category>
		<category><![CDATA[gotcha]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[Internet Explorer]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[XHTML]]></category>

		<guid isPermaLink="false">https://blog.yimingliu.com/2008/02/11/ie-6-renders-a-blank-page-on-xhtml-style-script-end-tag/</guid>
		<description><![CDATA[On IE 6, a well-formed and validated web page may be rendered as a blank page if you close &#60;script&#62; tags in XHTML style.  As in, &#60;script type="text/javascript" ... src="foo.js" /&#62;, rather than the HTML style &#60;script type="text/javascript" ... src="foo.js"&#62;&#60;/script&#62; 
So one of my web pages renders great in Safari and Firefox, but in [...]]]></description>
			<content:encoded><![CDATA[<p>On IE 6, a well-formed and validated web page may be rendered as a blank page if you close <tt>&lt;script&gt;</tt> tags in XHTML style.  As in, <tt>&lt;script type="text/javascript" ... src="foo.js" /&gt;</tt>, rather than the HTML style <tt>&lt;script type="text/javascript" ... src="foo.js"&gt;&lt;/script&gt; </tt></p>
<p>So one of my web pages renders great in Safari and Firefox, but in IE 6, it is a completely blank page, devoid of content.  Puzzled, I ran it through the W3C validator &#8211; no problem at all.  Selected a View Source in IE, and noted that the entire HTML output looked OK.</p>
<p>Eventually I narrowed down the problem to a <tt>&lt;script&gt;</tt> tag in the markup.  Namely, a <tt>&lt;script type="text/javascript" ... src="foo.js" /&gt;</tt> kind of tag.  IE rendered the page when I removed the tag, and goes blank when I put it back.  Curiously enough, I hadn&#8217;t actually invoked any functions from that .js file, so it was definitely not any code I was executing.  Replacing the .js file with a dummy .js file also triggered the blank page.  Changing or omitting the other attributes did not help.</p>
<p>The problem is fairly obvious now.  When I close the tag in HTML style, with an actual <tt>&lt;/script&gt;</tt> tag, IE proceeds to render just fine.</p>
<p>The obvious conclusion is that IE is buggy, but that may not necessarily true (well, in this one instance anyway).  Despite most pages&#8217; &#8220;compliance&#8221; with XHTML, DOCTYPE&#8217;ed and all, most web servers still serve these &#8220;XHTML&#8221; files as mimetype <tt>text/html</tt> instead of the recommended <tt>application/xhtml+xml</tt>.  This is pragmatic, since IE 6 doesn&#8217;t even bother to render <tt>application/xhtml+xml</tt>, and user agents are required to stop rendering upon encountering non-valid markup (imagine the chaos that would cause).</p>
<p>However, it seems this might introduce a cause for the gotcha.  Interpreted in actual text/html mode, one might imagine that to a HTML parser, <tt>&lt;script .... /&gt;</tt> doesn&#8217;t really appear to close the <tt>&lt;script&gt;</tt> tag at all &#8211; in fact, it might merely look like a rather malformed start script tag and no end tag.   If I were a dumbly compliant parser+renderer, I might just start walking down the response string looking for that mythical end to this start tag.  And end up rendering nothing.  Of course, if I were a slightly smarter parser, I would look for a DOCType, but then I&#8217;d contradict the server&#8217;s mimetype, and down that road <a href="http://sarth.thallos.org/2007/08/windows-ie-ignores-textplain-mimetype.html">lies even more madness</a>.</p>
<p>Nevertheless, the solution, when staring at a blank page in IE when the markup seems fine, is to check your script tags, if any.</p>
<p>I&#8217;m no expert at this soup of SGML/HTML/XHTML/XML standards thing, so the above is just my random opinion plus some observations.  Still, it seems that MS should patch this particular problem, since it&#8217;s fairly non-obvious (many people, I&#8217;d surmise, would use the this kind of shorthand close tag in an XHTML file, especially since it validates fine) and upsets the status quo compromise of incremental Web standards compliance through browser compliance modes, content negotiation, and occasionally bad mimetype service.  But of course, that&#8217;s never going to happen.</p>
<p>Update: I&#8217;ve been made aware in the comments section that the same issue occurs in IE 7.  Just great.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yimingliu.com/2008/02/11/ie-6-renders-blank-page-on-xhtml-style/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>
