<?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>Sun, 15 Jan 2012 00:50:12 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Outlook 2011 for Mac still adding arbitrary line breaks into plaintext emails</title>
		<link>http://blog.yimingliu.com/2011/12/25/outlook-2011-still-mangling-plaintext-emails/</link>
		<comments>http://blog.yimingliu.com/2011/12/25/outlook-2011-still-mangling-plaintext-emails/#comments</comments>
		<pubDate>Sun, 25 Dec 2011 10:00:22 +0000</pubDate>
		<dc:creator>yiming</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[bug]]></category>
		<category><![CDATA[email]]></category>
		<category><![CDATA[email client]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[Microsoft Office]]></category>
		<category><![CDATA[opinion]]></category>
		<category><![CDATA[OS X]]></category>
		<category><![CDATA[Outlook 2011]]></category>

		<guid isPermaLink="false">http://blog.yimingliu.com/?p=956</guid>
		<description><![CDATA[Outlook 2011 on Mac OS X, v14.1.3, for whatever reason, still does not properly support &#8220;format=flowed&#8221; content-type or &#8220;quoted-printable&#8221; extensions for plaintext emails. This causes plaintext emails to be sent as mangled messes, full of arbitrarily inserted linebreaks. This appears to be a regression from Entourage, as far as I recall, which never handled plaintext [...]]]></description>
			<content:encoded><![CDATA[<p>Outlook 2011 on Mac OS X, v14.1.3, for whatever reason, still does not properly support &#8220;format=flowed&#8221; content-type or &#8220;quoted-printable&#8221; extensions for plaintext emails.  This causes plaintext emails to be sent as mangled messes, full of arbitrarily inserted linebreaks.  This appears to be a regression from Entourage, as far as I recall, which never handled plaintext quite this badly, and this is also despite <a href="http://answers.microsoft.com/en-us/mac/forum/macoffice2011-macoutlook/text-wrapping-in-outlook-for-mac-2011/04da9a43-8c52-4fc8-be82-4c13d2b7629c">Microsoft&#8217;s promises</a> to have <a href="http://www.officeformachelp.com/outlook/faqs/#faq8">&#8220;implemented format=flowed&#8221;</a>.</p>
<p>This is the last straw.  I&#8217;ve been a loyal MS Entourage / MS Outlook user since the days of Outlook Express for Mac and Office 2001.  But at this point, this software has actively impeded my communications with my friends and colleagues.  We&#8217;re done.</p>
<h3>The Problem</h3>
<p>Here&#8217;s a really simple illustration of the problem, from the receiver&#8217;s end:</p>
<p><a href="http://blog.yimingliu.com/wp-content/uploads/2011/12/outlook-mangled-url.png"><img style="border: 1px solid #ccc" src="http://blog.yimingliu.com/wp-content/uploads/2011/12/outlook-mangled-url-300x193.png" alt="" title="outlook-mangled-url" width="300" height="193" class="aligncenter size-medium wp-image-1001" /></a></p>
<p>See how the URL, which was composed as one plaintext line, gets split up into two lines?</p>
<p>Here is another example, purely from the editor UI (and not even being sent yet).  I start with a perfectly good reply saved as a draft:</p>
<div style = "text-align:center">
<div style="display: inline-block; margin-right: 5px">
<a href="http://blog.yimingliu.com/wp-content/uploads/2011/12/outlook-mangling-1.png"><img  style="border: 1px solid #ccc" src="http://blog.yimingliu.com/wp-content/uploads/2011/12/outlook-mangling-1-300x125.png" alt="" title="outlook-mangling-1" width="300" height="125" class="aligncenter size-medium wp-image-961" style="border: 1px solid #ccc" /></a>
 </div>
<div style="display: inline-block">
<a href="http://blog.yimingliu.com/wp-content/uploads/2011/12/outlook-mangling-1b.png"><img src="http://blog.yimingliu.com/wp-content/uploads/2011/12/outlook-mangling-1b-300x173.png" style="border: 1px solid #ccc" alt="" title="outlook-mangling-1b" width="300" height="173" class="aligncenter size-medium wp-image-962" /></a> </div>
</div>
<p>I make a small wording change and resave:</p>
<div style = "text-align:center">
<div style="display: inline-block; margin-right: 5px">
<a href="http://blog.yimingliu.com/wp-content/uploads/2011/12/outlook-mangling-2.png"><img style="border: 1px solid #ccc"src="http://blog.yimingliu.com/wp-content/uploads/2011/12/outlook-mangling-2-300x194.png" alt="" title="outlook-mangling-2" width="300" height="194" class="aligncenter size-medium wp-image-963" /></a> </div>
<div style="display: inline-block">
<a href="http://blog.yimingliu.com/wp-content/uploads/2011/12/outlook-mangling-2b.png"><img style="border: 1px solid #ccc" src="http://blog.yimingliu.com/wp-content/uploads/2011/12/outlook-mangling-2b-300x188.png" alt="" title="outlook-mangling-2b" width="300" height="188" class="aligncenter size-medium wp-image-964" /></a>
 </div>
</div>
<p>See that third line?  Thanks to the hard line breaks inserted by Outlook (even at composition stage), the line wrap has been mangled.  This draft has to be re-wrapped manually, by the tedious process of deleting the newline-based hard line breaks from every line following in the paragraph.  That was a short paragraph.  Imagine doing that in a long paragraph, from the first line.  </p>
<p>To add insult to injury, there is not even a &#8220;re-wrap&#8221; functionality in the editor, to at least solve this user-interface level problem (as opposed to the protocol level problem).  Obviously no one at Microsoft sends plaintext emails anymore.</p>
<h3>The Issue</h3>
<p>Back when email was first devised, servers didn&#8217;t have a lot of memory, and people had pretty tiny terminals with fixed line widths and not a whole lot of processing power to deal with it.  The Internet standards for email messages <a href="http://www.ietf.org/rfc/rfc2822.txt">http://www.ietf.org/rfc/rfc2822.txt</a>, RFC2822 Section 2.1.1, defines recommendations for email body text transferred over SMTP:</p>
<blockquote><p>There are two limits that this standard places on the number of<br />
   characters in a line. Each line of characters MUST be no more than<br />
   998 characters, and SHOULD be no more than 78 characters, excluding<br />
   the CRLF.</p>
<p>   The 998 character limit is due to limitations in many implementations<br />
   which send, receive, or store Internet Message Format messages that<br />
   simply cannot handle more than 998 characters on a line. Receiving<br />
   implementations would do well to handle an arbitrarily large number<br />
   of characters in a line for robustness sake&#8230;</p>
<p>   The more conservative 78 character recommendation is to accommodate<br />
   the many implementations of user interfaces that display these<br />
   messages which may truncate, or disastrously wrap, the display of<br />
   more than 78 characters per line&#8230;</p>
<p>   &#8230;it is encumbant upon implementations which display messages<br />
   to handle an arbitrarily large number of characters in a line<br />
   (certainly at least up to the 998 character limit) for the sake of<br />
   robustness.</p></blockquote>
<p>Basically, the SMTP server can count on messages that come in 80 characters per line (and always less than 1000 characters per line), and email clients can trust that they only have to render up to the 78th column of text.  This limitation is hardly useful in the modern age, but persists since it&#8217;s part of the standard.  And it&#8217;s a fine, conservative design model.  But now we write some pretty long lines without linebreaking ourselves, so something magical has to happen in the email client itself, like Outlook 2011.</p>
<p>The naive solution, of course, is to slap arbitrary line breaks into the user&#8217;s email message at every 78 characters, which is what ye olde email clients from yesteryears did (and Outlook 2011 still does).  It&#8217;s a matter of personal preference whether this is a reasonable solution.  Proponents argue that the email will &#8220;always look the same&#8221; on all devices, including those limited to 78 chars per line.  </p>
<p>I (and many others), on the other hand, think the spirit of the RFC is to allow the actual handling client to decide where to break lines.  With the exception of source code, it is almost always better for the email client to use the full width of their display, however many characters that might be.  Even in the case of source code, it should also <strong>not be mangled by the insertion of arbitrary line breaks in them</strong> &#8212; what if newlines are meaningful in this language, and the author used more than 78 characters per line?  The example with the URI is illustrative of this problem &#8212; the URI got an arbitrary newline in the middle, destroying its meaning.  Users who copy-paste the two lines will end up getting a 404, due to that stupid inserted newline in the middle of it.  This should not be allowed to happen.</p>
<p>Because this naive solution was not perfect, an <a href="http://www.ietf.org/rfc/rfc2646.txt">extension was proposed as RFC 2646</a>.  In the email header, if the Content-type was set to have the format=flowed parameter, such as </p>
<p><tt>Content-type: text/plain; charset=US-ASCII; <strong>format=flowed</strong></tt> </p>
<p>(emphasis mine), the sending and receiving email clients are allowed to reflow the text based on user linebreaks.  It follows some simple reflowing rules, but in short it will preserve user-inserted hard line breaks while adjusting the rest of the message for the proper line length while the message is &#8220;on the wire&#8221;, and recombining the lines on receipt and display.  Modern email clients like Thunderbird, designed for user comfort and the generous system limitations of the year 2011, implement this standard.</p>
<p>Guess what header Outlook 2011 sends?</p>
<p><tt>Content-type: text/plain; charset="US-ASCII"</tt></p>
<p>Not even an option to change that behavior.  It does not appear that Outlook 2011 deals with any of this.  It just inserts some line breaks and calls it a day.</p>
<p>An alternative, implemented by Apple&#8217;s Mail.app, is to send messages with the <tt>Content-Transfer-Encoding</tt> header set to <a href="http://en.wikipedia.org/wiki/Quoted-printable">&#8220;quoted-printable&#8221;</a>, as per <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>.  In this model, soft line breaks are sent explicitly with the character &#8220;=&#8221; representing it, breaking at the usual 70-odd character column.  On the receiving end, the client processes this character as a no-op and concats the line back together for display.</p>
<p>Outlook doesn&#8217;t do that either.  It just wants to mangle your emails.</p>
<h3>Conclusion</h3>
<p>The world moved on and adopted HTML emails, which doesn&#8217;t have this newline problem.  For those of us who do think HTML emails are an atrocity to be used sparingly, if at all, the idiosyncrasies of plaintext email have to be addressed.  Outlook 2011 appears to do even worse than Entourage 2008 at this problem, by not dealing with it at all.  And apparently getting a bunch of Microsoft &#8220;MVPs&#8221; on their forums to cloud the issue with promises of support and unrelated commentary.</p>
<p>Given the sad state of email clients on the Mac, I believe Thunderbird is now my only option for sane plaintext messaging.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yimingliu.com/2011/12/25/outlook-2011-still-mangling-plaintext-emails/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dragon Age 2: modding the Edge of Night axe into a longsword</title>
		<link>http://blog.yimingliu.com/2011/10/22/dragon-age-2-modding-the-edge-of-night-axe-into-a-longsword/</link>
		<comments>http://blog.yimingliu.com/2011/10/22/dragon-age-2-modding-the-edge-of-night-axe-into-a-longsword/#comments</comments>
		<pubDate>Sun, 23 Oct 2011 00:45:36 +0000</pubDate>
		<dc:creator>yiming</dc:creator>
				<category><![CDATA[Games]]></category>

		<guid isPermaLink="false">http://blog.yimingliu.com/?p=902</guid>
		<description><![CDATA[Having a bit of fun with Dragon Age 2 in my spare time. The selection of longswords in Dragon Age 2 leaves much to be desired. Call me old-fashioned, but when I play fantasy RPGs, my warriors are always sword-and-shield (munchkin min-maxing be damned), because&#8230;that&#8217;s how heroic fantasy warriors are supposed to be. As TvTropes [...]]]></description>
			<content:encoded><![CDATA[<p>Having a bit of fun with Dragon Age 2 in my spare time.  The selection of longswords in Dragon Age 2 leaves much to be desired.  Call me old-fashioned, but when I play fantasy RPGs, my warriors are always sword-and-shield (munchkin min-maxing be damned), because&#8230;that&#8217;s how heroic fantasy warriors are supposed to be.  As TvTropes succinctly put it, <a href="http://tvtropes.org/pmwiki/pmwiki.php/Main/HeroesPreferSwords">Heroes Prefer Swords</a>.  I actually shelled out money for the Warrior Item Pack DLC hoping to find a better longsword.  Unfortunately, the only decent one-handed weapon in the pack is an axe.  An axe?!  What are we, woodcutting barbarians?</p>
<p>So I went about looking for a way to switch this otherwise beautiful weapon, <a href="http://dragonage.wikia.com/wiki/The_Edge_of_Night">The Edge of Night</a>, into a longsword.  The similarly named <a href="http://dragonage.wikia.com/wiki/Edge_of_Song_and_Glory" title="Edge of Song and Glory">Edge of Song and Glory</a> is the ideal target for the transformation.</p>
<p>There is not much modding possible for DA2 &#8212; the game is very much locked down to drive DLC sales.  Nevertheless, the base game itself is at least unencrypted; however, there is no official mod editor support.  The DLCs, however, are encrypted &#8212; you cannot even view the data contained within these files.  The following modding method requires that you decrypt the DLC&#8217;s designeritems.erf file first, then extracting the Edge of Night&#8217;s item file for editing.  This only works for PC versions of DA2.</p>
<p>Note that <a href="http://social.bioware.com/project/4468/#files">there is already a mod</a> floating around for this.  There is a good thing and a bad thing about this mod.  The good thing is that it uses a less questionable method that does not need to decrypt the ERF file.  On the other hand, because of the limitations of such a method, that mod doesn&#8217;t change the item icon or the item description.  It will still look like an axe and call itself an axe in the character&#8217;s inventory screen &#8212; only the actual gameplay model is changed to a longsword.  Some people would be satisfied with that; I wasn&#8217;t.</p>
<h4>Decrypting designeritems.erf</h4>
<p>DLC items are in found in <tt>${DRAGON AGE 2 INSTALLDIR}/addins</tt>.  In this case, it is the <tt>DA2_MTX_WAR</tt> addin.  The ERF file is<br />
<tt>${DRAGON AGE 2 INSTALLDIR}/addins/da2_mtx_war/core/data/designeritems.erf</tt>, and the UTI file is [dd9ea6bb335cfa89].uti.</p>
<p><strong>Make a backup copy of the da2_mtx_war directory.</strong></p>
<p>To decrypt the ERF file, you need the decrypt key and a decrypter.  There is a tool called &#8220;slurpda2.exe&#8221;, usually distributed with the <tt>deda2drm</tt> decrypter package.  I will not explain how to obtain this package, but it&#8217;s pretty easily found.  If you legitimately own this game, slurpda2 will give you a list of all the decrypt keys, one for each DLC package.  Use the right key (have to do trial-and-error here, as it doesn&#8217;t tell you which key belongs to which package) and <tt>deda2drm</tt> by cd&#8217;ing to the deda2drm directory and executing from the command prompt:</p>
<p><code>deda2drm.exe DA2_MTX_WAR [key]</code></p>
<p>The output will tell you whether this succeeded. If so, this will decrypt the ERF. </p>
<h4>Extracting the UTI</h4>
<p>A tool like <a href="http://social.bioware.com/project/1936/" title="PyGFF">PyGFF</a> will open the decrypted ERF file.  Look for the dd9ea6bb335cfa89 hash key and extract that UTI.  For reference, the UTI should contain an item with the tag war100im_warrior_1h_sword.  Save the UTI file as war100im_warrior_1h_sword.uti (though technically you can name the filename anything you want, as long as it ends in uti).  As you can see by the name, even the original designers thought it should be a sword and not an axe :p</p>
<h4>Editing the UTI</h4>
<p>Using a tool like <a href="http://social.bioware.com/forum/1/topic/307/index/6677553/1">TlkEdit</a>, open the UTI file.  Change the ModelVariation field to 123 (which is the Edge of Song and Glory, as listed in 2da.rim&#8217;s <tt> item_variations.gda</tt> file).  I believe 132 is Glandivalis / Vigilance, if you prefer that look.  Change the Icon field to &#8220;ico_1h_sword_5.dds&#8221;.  Save the UTI file.</p>
<p>Here you can choose to restore the original encrypted copy of da2_mtx_war or not.  If so, this reverses the decryption so it doesn&#8217;t confuse DA2 when you open it again.  Alternatively, you can edit the manifest.xml file in the decrypted copy of da2_mtx_war to tell it to skip the authorization requirement by setting RequiresAuthorization=0. I left mine unencrypted, but I think this gets into legal gray territory, and the UTI mod should work even with the original encrypted version.</p>
<p>Drop the final modded uti file into <tt>packages/core/override</tt> in either the DA2 install directory or the user directory in Documents/Bioware (create the override directory if needed).</p>
<h4>Result</h4>
<p><a href="http://blog.yimingliu.com/wp-content/uploads/2011/10/edge_of_night.jpg"><img src="http://blog.yimingliu.com/wp-content/uploads/2011/10/edge_of_night-300x201.jpg" alt="Edge of Night sword" title="Edge of Night sword" width="300" height="201" class="alignleft size-medium wp-image-910" /></a> <a href="http://blog.yimingliu.com/wp-content/uploads/2011/10/edge_of_night_action.jpg"><img src="http://blog.yimingliu.com/wp-content/uploads/2011/10/edge_of_night_action-300x219.jpg" alt="The Edge of Night sword in action" title="The Edge of Night sword in action" width="300" height="219" class="alignleft size-medium wp-image-914" /></a></p>
<div  style="clear: left; padding-top: 2em">Isn&#8217;t that pretty?  Wielding a sword, as a hero should.  One of these days I&#8217;ll mod the TLK file to change the occurrences of &#8220;axe&#8221; to sword in its Codex file, and this change would be perfect.</div>
<p>I have a copy of the modded UTI file, but I think distributing it might violate the EULA.  Oh well.  If you can&#8217;t figure out the instructions, leave a comment here (with your email address) and I&#8217;ll try to help.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yimingliu.com/2011/10/22/dragon-age-2-modding-the-edge-of-night-axe-into-a-longsword/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>A wishlist for a native Mac email client</title>
		<link>http://blog.yimingliu.com/2011/08/21/a-wishlist-for-a-native-mac-email-client/</link>
		<comments>http://blog.yimingliu.com/2011/08/21/a-wishlist-for-a-native-mac-email-client/#comments</comments>
		<pubDate>Sun, 21 Aug 2011 20:46:20 +0000</pubDate>
		<dc:creator>yiming</dc:creator>
				<category><![CDATA[Personal]]></category>
		<category><![CDATA[email]]></category>
		<category><![CDATA[email client]]></category>
		<category><![CDATA[opinion]]></category>
		<category><![CDATA[OS X]]></category>

		<guid isPermaLink="false">http://blog.yimingliu.com/?p=856</guid>
		<description><![CDATA[As the tech-savvy sort, I often do some things that the typical consumer might not care about. However, it is strange that I simply cannot find a native Mac email client on the market that fulfills what I consider to be very basic features for decent email management. While everyone is gushing over the latest [...]]]></description>
			<content:encoded><![CDATA[<p>As the tech-savvy sort, I often do some things that the typical consumer might not care about.  However, it is strange that I simply cannot find a native Mac email client on the market that fulfills what I consider to be very basic features for decent email management.  While everyone is gushing over the latest social network to be jammed into an email client, I just want my email to work in a sane way.</p>
<p>The features I&#8217;m looking for:</p>
<ul>
<li><b>POP3/IMAP + SSL support</b></li>
<li><b>Full-text search, or indexable by OS X&#8217;s Spotlight</b></li>
<li><b>Multiple account support</b></li>
<li><b>Archival</b> &#8212; if I delete an email account, it <strong><em>should not</em></strong> wipe out all emails from local storage that belonged to this account, especially if said account was POP3</li>
<li><b>Plaintext composition</b> &#8212; I&#8217;m taking the side of format=flowed in plaintext composition.  Manually formatting hard line breaks at char 78 is an insane holdover from a bygone age when dumb ASCII terminals were still the primary user interface.  At least allow this as an option, or support the quoted-printable content type and soft line-breaks during composition.</li>
<li><b>Filtering rules</b> &#8212; Basic filters that let me decide where to put messages based on mail headers and subject is enough</li>
<li><b>mbox import/export</b> &#8212; I need to be able to import mail from my previous client.  Similarly, in the scenario that this app is no longer supported, I need the option of moving to another client.</li>
<li>Bonus: <b>auto-bcc to an arbitrary email address</b> &#8212; I&#8217;ve never solved my problem with <a href="https://blog.yimingliu.com/2007/11/22/sent-mail-archival-episode-3/">archiving sent mail</a>.  All you really need to do is auto-populate the BCC field on any &#8220;New Mail&#8221; composition window with this address.  That&#8217;s all I really need to be happy here.</li>
</ul>
<p>Amazingly enough, there is not a single Mac mail client that fulfills all of these basic conditions.  Especially egregious problems for the top three mail clients:</p>
<ul>
<li>Microsoft Outlook Mac 2011 &#8212; mangles all outgoing plaintext emails by inserting hard line breaks.  <a href="http://blog.yimingliu.com/2011/12/25/outlook-2011-still-mangling-plaintext-emails/">No support for flowed plaintext, despite promises to the contrary, and no support for quoted-printable content-type and soft line breaks</a>. No provision for auto-bcc.</li>
<li>Apple Mail (Snow Leopard) &#8212; deleting an old email account deletes ALL mail belonging to this account, even for downloaded POP3 mail.  WTF.  Can only auto-bcc &#8220;myself&#8221;, which is a fixed email address corresponding to the sending account; if you allow autobcc, why not let the user pick the email to autobcc to?</li>
<li>Mozilla Thunderbird 8 &#8212; deleting an account deletes all downloaded mail belonging to this account, unless messages are stored to the &#8220;local folder&#8221; rather than its inbox abstractions.</li>
</ul>
<p>For fear of accidental data loss, I&#8217;ve stuck to the Microsoft offering, despite its incredible inability to keep plaintext mail intact.  The newer social clients are all Thunderbird-based and leave little else worth examining &#8212; they seem far more interested in integrating ever more social network APIs than to support more basic email features.  The rest of my friends are all sworn Gmail webmail users and think I&#8217;m a strange luddite for even considering native clients.  I&#8217;ll leave the webmail vs native client debate for fear of going on a page-long rant; suffice to say that the user experience between the two options is not comparable at all.</p>
<p>It almost makes me want to start writing a new email client for myself, or hire someone to start some skeleton code at least, because obviously no one else is going to scratch this itch of mine.  That kind of spare time and money, however, would probably never come unless I manage to actually sell a company or two (rather than just founding unsuccessful ones).</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yimingliu.com/2011/08/21/a-wishlist-for-a-native-mac-email-client/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Brief Guide to Golems of Amgarrak with a New Character</title>
		<link>http://blog.yimingliu.com/2011/05/26/a-guide-to-golems-of-amgarrak-with-a-new-character/</link>
		<comments>http://blog.yimingliu.com/2011/05/26/a-guide-to-golems-of-amgarrak-with-a-new-character/#comments</comments>
		<pubDate>Fri, 27 May 2011 04:25:45 +0000</pubDate>
		<dc:creator>yiming</dc:creator>
				<category><![CDATA[Games]]></category>
		<category><![CDATA[Personal]]></category>

		<guid isPermaLink="false">http://blog.yimingliu.com/?p=708</guid>
		<description><![CDATA[So I&#8217;ve been playing Dragon Age: Origins in the few spare hours I get every week. Having never finished Baldur&#8217;s Gate 2, this is redemption for my neglected gamer soul, I think. In general, it&#8217;s pretty easy. However, several of the most annoying battles so far has to be from the Golems of Amgarrak DLC. [...]]]></description>
			<content:encoded><![CDATA[<p>So I&#8217;ve been playing <em>Dragon Age: Origins</em> in the few spare hours I get every week.  Having never finished Baldur&#8217;s Gate 2, this is redemption for my neglected gamer soul, I think.  In general, it&#8217;s pretty easy.  However, several of the most annoying battles so far has to be from the Golems of Amgarrak DLC.  So far, all of the FAQs and guides I&#8217;ve seen (including videos on YouTube) are about absurdly min-maxed level 35 characters imported from Origins and Awakening, with elite gear, hundreds of poultices and potions, and incredibly overpowered skillsets (Most inexcusable: the people who are exploiting the Legion of the Dead heraldry&#8217;s bugged +20 to all attributes to power up their maxed out characters).</p>
<p><strong>This note is not about trouncing the Harvester with level 35 ubergeared supermen</strong>.  Any halfwit can do that &#8212; just go get the gear, follow any YouTube min-maxing guide for DAO, and start whacking away. You can do this with any properly geared character.  This note is about how to complete Golems of Amgarrak on Nightmare difficulty with a newly created, level 20 mage, with stock gear and sneaky tactics.  This is not to claim it&#8217;s the best way to accomplish the feat &#8212; just the way I managed it.  If you have better ideas about how to use a newly created level 20 character to win, contribute them in the comments.</p>
<p><strong>This note only applies to DA:O as played on the PC.</strong>  On some console-based versions, the pet bronto cannot be controlled, making the final battle even more annoying than usual.</p>
<h3>Background</h3>
<p>If you don&#8217;t know yet, completing Golems of Amgarrak on Nightmare (or Hard, actually) difficulty awards all of the other characters in other campaigns (even existing campaigns&#8217; characters) some really nifty items &#8212; but only nifty for lower level characters.  This includes the amulet The High Regard of House Dace, which gives +6 cunning so Daveth can open up all those annoying chests in Ostagar, and The Reaper&#8217;s Cudgel, which is worth well over 300 sovereigns.  The early cash allows you to buy the Blood Dragon Armor, the Spellward, and the Arcane Knowledge and Physical skill tomes from Bodahn immediately after Lothering before his store restocks; you can then buy another copy of these items after the restock.</p>
<p>With my time constraints, I will most likely play DAO only once.  So I&#8217;d like to have these items in my Origins campaign, without having to complete the game first to get an absurdly well geared character to do Amgarrak.  I thought I can just start a new Amgarrak campaign with a new character, and finish it  to get my gear.  Boy, was I wrong.  People call this the hardest DLC for Origins, and for good reason.  I played a warrior and simply could not win an initial fight against 4 elite golems, and had to delete, restart the campaign, and rethink my strategy.</p>
<h3>General Setup</h3>
<p>Despite claims, the module is not impossible, even with a new level 20 character.  It is simply very poorly balanced for new characters, and forces you to proceed carefully and methodically.  This is Dragon Age, not Diablo &#8212; as a new character, you cannot just rush into every battle, aggro&#8217;ing all the mobs at once.  Separate mobs from each other, killing them one at a time, withdraw backwards to avoid being surrounded, pause frequently to issue new orders as the situation requires and don&#8217;t rely on the Combat Tactics scripts, and you should have very little difficulty dealing with most creatures in the module.</p>
<p>To win, I strongly suggest playing a mage.  In fact, the best character for completing the DLC with is probably the mage, regardless of level.  The main reason: <strong>there are no merchants</strong>, <strong>not nearly enough healing poultices</strong>, and most unfortunate of all, <strong>no other playable mage</strong> in the entire module.  The objective is to preserve all potions and consumables until the final battle with the Harvester, which means the party will need to rely on mage healing spells.</p>
<p>The party at the start consists of a duel-wielding rogue, a bronto (with a charge attack and a Taunt), and the PC.  The party at the end adds a sword-and-shield warrior (without Taunt!) and a Runic Golem with some typical golem abilities, plus a weak Group Heal, a Cleansing Aura, and Chain Lightning/Tempest spells.  All of these characters are poorly configured with mediocre equipment, and the party only has one respec tome (Memoirs of the Grey Wardens).</p>
<p>Save the tome for the rogue.  He&#8217;s going to be the main DPS character against the Harvester, but only if he&#8217;s an archer and standing far away from the action.</p>
<h4>Attributes and Specializations</h4>
<p>If starting this without having beaten Awakening, then the mage is restricted to three base specializations: Spirit Healer, Arcane Warrior, and Shapeshifter.  Since Shapeshifter is worthless, the two specializations are decided already.  If you have started Awakening, you might consider the Battle Mage instead of Arcane Warrior for additional utility, but Spirit Healer is an absolute must as a new character.</p>
<p>As a mage, 60+ magic is necessary for spells to have decent effect.  The rest should be spent in willpower to pad out the mana supply.  Usually, when you build a Mage for Origins or Awakening, you don&#8217;t want to put any points in Willpower.  However, remember here, there are very few, very precious lyrium potions and no way to buy more; there are no special attribute bonuses that boost the mana pool for free; and the PC&#8217;s starting equipment is subpar and does not provide a large mana boost (and again, there is no way to buy better equipment).  If you don&#8217;t take additional Willpower, you will not be able to cast during the long endgame battle against the Harvester, and that would be very unfortunate.</p>
<p>The mage should have maxed Combat Training to ensure that spells aren&#8217;t interrupted by ordinary attacks.  Survival is a plus for the nature resistances, and the first level Vitality and Mana skills from Awakening.  This is a pure combat module, with no ingredients for crafting and a grand total of two conversations &#8212; no need for Coercion or any of the crafting skills.</p>
<h4>Talents</h4>
<p>One might be tempted to build an armored arcane warrior, since this is a popular &#8220;I win&#8221; character build.</p>
<p>This would be &#8230; <em>unfortunate</em>.  Normally, the arcane warrior is very overpowered: all the gear of a tank and the firepower of a mage.  In this module, with a new character, you have neither of these advantages.  The small module does not offer a merchant or any sort of decent armor, and a stock character does not have enough willpower to have a deep mana pool after putting up the arcane warrior defensive abilities.  Wearing a robe, swinging a Warden&#8217;s Companion longsword with a mediocre shield, while not being able to cast healing spells &#8212; this is a recipe for disaster.  Further, Brogan, the warrior in the party, is configured as a tank &#8212; a poor tank, but he can&#8217;t be respec&#8217;ed as a DPS due to lack of tomes, while the PC can be a DPS. Therefore, playing a support + nuker mage is probably a better choice.  Some of the advice that follows will assume a mage with an assortment of crowd control and attack spells.</p>
<p>As for specific talents, since it&#8217;s a stock character, there aren&#8217;t that many points available.  Here is my advice:</p>
<ul>
<li>
The Healing tree up to Regeneration is a must.  As Spirit Healer, also take at minimum Group Healing, because both the golem enemies and the Harvester at the end have area-of-effect attack abilities that can damage an entire party.  Remember that this character will be the only healer until the Runic Golem is fully upgraded, and even so, the Golem is a terrible healer.  These healing spells are basically critical to finishing the module, and is why stock level 20 Warriors or Rogues have a hard time surviving.</li>
<li>Make sure to get Force Field, for several possible reasons.  Crushing Prison is nice, but only if there are points for it.</li>
<li>It would be wise to take Mana Clash, at the top of the Mana Drain tree.  In several battles (unfortunately, not the end battle), the party will face several spellcasters along with hard-hitting warriors.  Mana Clash will immediately remove the casters from the scene, which trivializes the encounter.</li>
<li>For me, I took Tempest and Blizzard (from the Lightning and Cold trees), since I already have Spell Might from the Mana Drain tree.  This sets up the Storm of the Century combination that was useful in one instance, but this is optional.  I strongly recommend Cone of Cold in any case as it is an absurdly overpowered spell with a freezing effect that applies even to elites and bosses.</li>
<li>If taking Storm of the Century, or <em>not</em> taking Mana Clash, then Glyph of Neutralization is desirable.  As for the other glyphs, since the main enemies are almost always elite or boss level golems and undead, they are often resisted &#8212; except the Paralysis Explosion combination, if set up correctly.</li>
<li>I did not use any other spells.  If you have a favorite set, use the remaining points to take them.  Remember that practically all enemies worth using mana on are Elite or above, so some spells that have minimum effect on elites are not worth taking.</li>
</ul>
<p>Remember that only one party member will get a chance to respec, and the rogue should use it to reconfigure as a survival-minded DEX-based archer.  This is because this underpowered party simply cannot stand toe-to-toe against any of the major enemies, and will rely on kiting (and not even simple kiting either, given the setup of the final battle) and off-tanking to survive many fights.</p>
<h4>Jerrik, the Archer</h4>
<p>Jerrik will be the main non-magical DPS.  Unfortunately, he is setup as a frontline fighter.  Because the tank is terrible, and can&#8217;t even manage threat effectively (no Taunt!), plus both enemy Golems and the Harvester have area-of-effect attacks to damage everyone in their immediate vicinity, this is a bad configuration.  He must respec into a DEX-based DPS archer (enough STR to wear his armor, then all DEX), with Master Archer or Scattershot, Arrow of Slaying, and Feign Death (for the many times when the tank loses threat and the enemy rushes the archer).  Optionally, he could take a few cunning and take Stealth to lose threat, though the final battle involves an elite boss and hordes of minions. </p>
<h3>Major Battles</h3>
<p>On Nightmare difficulty, in general, proceed slowly and cautiously, withdraw backwards into chokepoints when needed, and there should be minimal pain.  In particular, when faced with multiple spellcasters, hit Mana Clash to remove most (if not all), and then rush them.  Play this as a normal RPG and use the pause key frequently to strategize and adjust tactics.  Try not to use <em>any</em> consumables until the final fight.  For a general walkthrough, follow <a href="http://gamebanshee.com/dragonageorigins/walkthrough/dlc-goa-amgarrak.php">Gamebanshee&#8217;s Amgarrak guide</a>.</p>
<p>There are two battles that takes some strategy to pull off, however.  Some people are stumped here and can&#8217;t proceed further.  They&#8217;re not hard, but you can&#8217;t use the normal tank-and-spank tactic with a level 20 Warden and a crappy party.</p>
<h4>The ancient hall of golems</h4>
<p>As soon as the party enters Amgarrak, there are three directions to go, two of which are sealed off at the start.  In the third direction, there is a room with four stationary golems.  Two of them are called Watchers, the other two are elites called Sentinels.  When the party proceeds far enough into the room, these four will activate.</p>
<p>This is one of the toughest fights because the party does not have its warrior tank yet.  Further, these four golems will open the battle by hurling rocks &#8212; which deals heavy area-of-effect damage and knocks down any character beside the Runic Golem.  They will then follow by using Slam on the incapacitated character, and then Hurl Rock again, basically going into a stunlock until the character is dead.</p>
<p>Careful pulling is impossible, because all four activate at the same time.  However, there is one good way to deal with these golems: The Hallway of Doom.</p>
<p>There is a chokepoint hallway going into the hall of golems.  The party could fight the golems one-on-one at the doorway, but they&#8217;ll jut use Slam to knock the blocker out of the way and rush into the room.  Then again, they won&#8217;t be able to do that &#8230;if the blocker is force-fielded.</p>
<p>Have the party hold position.  Use the Runic Golem to trigger the four enemy golems, and then run back to the door.  At the doorway, use the Runic Golem to block the door and force field the golem before he gets Slammed.  Have the ranged DPS open fire.  Force Field your own golem, because the enemy golems are elite and will have shorter Force Field durations.</p>
<p>For even better effect, throw down a Blizzard to slow the enemy as the Runic Golem approaches.  Then, trigger Storm of the Century using Tempest, and then Force Field your Runic Golem before it gets seriously damaged.  Now the enemy will stand in the massive electrical storm, be drained of stamina by the lightning storm&#8217;s side effect (so they can&#8217;t Hurl Rock or Slam anymore), and run around uselessly.  When the Force Field expires, withdraw the Runic Golem and slaughter the heavily injured enemies (or heal the Golem until you&#8217;re able to Force Field again &#8212; the enemy should no longer have enough stamina for another Slam).</p>
<p>Make sure the mage is standing off to the side as the Runic Golem runs toward the party, because the enemy could see the mage and interrupt the casting with a hurled rock.  If you cast the Force Field too late, the enemy will Slam the blocker out of the way, which will probably cause a party wipe.</p>
<p>I really wish I had two mages in this module, which would be able to keep this little trick going forever.  Alas, that is not to be.</p>
<p><em>NOTE: If you didn&#8217;t take Storm of the Century Force Field, or if you can&#8217;t get the blocking trick to work, there is another way.  You need to have respec&#8217;ed Jerrik with at least Combat Stealth.  Have the party hold position far away from the action, have Jerrik walk into the hallway and trigger the golems.  When the golems activate, Stealth immediately and walk away.  Using Jerrik, carefully pull the now activated golems, one or two at a time, and kill them individually as they follow you down the hallway.  This is arguably easier, if less impressive, than the hallway blockade trick.</em></p>
<h4>The green room</h4>
<p>Again, a horde of golems.  </p>
<p><a href="http://blog.yimingliu.com/wp-content/uploads/2011/05/b2_green_room.jpg"><img src="http://blog.yimingliu.com/wp-content/uploads/2011/05/b2_green_room-300x187.jpg" alt="all golems hostile in the golem room" title="Green Phase Golem Room" width="300" height="187" class="alignright size-medium wp-image-793" /></a><br />
This time, the party needs to flip a switch in the green phase, which triggers an encounter with four boss golems and two elite golems.  If you didn&#8217;t feel enough hurled rocks and full-bodied rock slams in that previous golem encounter, this one will surely give enough.  Even with Brogan the warrior, no one in a level 20 party can tank through that.  There is a doorway chokepoint, but boss golems have huge resistances, and even a full Storm of the Century will only take off 1/3 of their hitpoints on Nightmare.  The blocker golem won&#8217;t survive too long after the Force Field expires; certainly not long enough to get another Force Field up.  Once again, they all activate at the same time, so you can&#8217;t pull one away by itself&#8230;<em>or can you</em>?</p>
<p>This one needs an underhanded trick.  Remember, there was a room next to the starting chamber of the Amgarrak level with a blue and a purple switch.  Both of these switches will throw the party out-of-phase with the golems, meaning that they disappear from the map.  When this happens, the hostility chase trigger is also reset.  If you can somehow kite the golems to other rooms, then run to the switch to go into blue or purple phase, walk away while phased out, and then switch back into normal phase when you&#8217;re far away enough&#8230;these golems will lose sight of you and stand still.  Furthermore, now they&#8217;re isolated from each other, and you can pull each one independently instead of triggering all six at once!  This means you can pull each golem, kill it, heal, and repeat.<br />
<a href="http://blog.yimingliu.com/wp-content/uploads/2011/05/b2_switch_room.jpg"><img src="http://blog.yimingliu.com/wp-content/uploads/2011/05/b2_switch_room-300x187.jpg" alt="Run back into this room and hit a switch to avoid the chasing golems" title="The switch room" width="300" height="187" class="alignright size-medium wp-image-796" /></a><br />
So the strategy is as follows: after you hit the green room switch to activate the golems, immediately run back out of the room, down the stairs, and toward the starting chamber.  The faster you run, the more the enemy golems aren&#8217;t going to keep up, and will be strung out along the way.  As you arrive in the switch chamber, switch phase.   All the golems disappear as you go out of phase with them.</p>
<p>Walk back to the green room, switch phase again, rob the chests if you need to, and return to normal phase.  Slowly go down the stairs again, pull each golem one at a time along the way, kill them one by one until you arrive at the switch room again.  Problem solved.</p>
<h3>The Final Battle</h3>
<p>This is the fight that few people seem to win as a poorly geared level 20.  This is because they are going toe-to-toe with the Harvester flesh golem.  There are two major problems with this.</p>
<ol>
<li>The Harvester hits for 90+ damage, and crits for 100+ damage on Brogan or the tank, due to the crappy equipment setup of the stock party.  There are not enough healing poultices or spells to keep the tank alive at that rate.</li>
<li>There is a second problem &#8212; the Harvester in the Flesh Golem phase periodically summons a skeleton, either with his Vile Disembowelment skill, or they just wander into the room.  As the flesh golem takes damage, the skeletons spawn faster.  The skeleton is usually elite, which hits really hard, or boss, which can seriously damage even the tank.  This isn&#8217;t even the main problem &#8212; the real problem is that the skeletons go after the DPS&#8217;ers.  Because Brogan has terrible threat management, the skeletons will wander into the room, go immediately for the caster or the archer, use Riposte to stun them, and hit for 50+ on leather and even higher on cloth.  If the mage and/or the golem goes down, it&#8217;s a guaranteed wipe. </li>
</ol>
<p>Since the tank can&#8217;t hold up, the only strategy is to kite the Harvester around the room.  There is plenty of space to maneuver, but there is not enough DPS with a stock party to take it down quickly enough.  Jerrik hits for 80 to 100 per arrow on the Harvester, and crits for a bit higher.  The mage hits at around 30 or 40 with the staff and more with spells if not resisted, but she can&#8217;t cast too many attack spells as healing is very needed and there are about 10 to 20 lyrium potions in all.  The rest of the party is fairly useless in terms of DPS, since they&#8217;re melee and can&#8217;t get a good hit in on the Harvester as it walks around.  The room is going to be filled with skeletons.  They all have stun skills.  If the kiter take a stun or two, he will get swarmed and probably die.</p>
<h4>Preparation</h4>
<p>The party needs to set some basic tactics. </p>
<ul>
<li>Brogan needs to take the least powerful health poultice at 25% health or less</li>
<li>Jerrik needs to set typical archer tactics, and feign death at health < 10%</li>
<li>The PC&#8217;s mage needs to drink a least powerful lyrium potion at 25% mana, cast Regeneration on an ally when the ally&#8217;s health is < 50%</li>
<li>The Runic Golem should turn off his Hurl Rock and Quake tactics, and cast Group Heal when an ally&#8217;s health < 50%</li>
</ul>
<p>Have the Runic Golem set Flame Weapons.  When the battle begins, coat weapons with the highest level poison you have available.</p>
<h4>Phase One</h4>
<p>In Phase One, the Harvester will jump inside a flesh golem and attack with Vile Disembowelment as an area-of-effect attack, which spawns a new skeleton.  </p>
<p><a href="http://blog.yimingliu.com/wp-content/uploads/2011/05/harvester_f1.jpg"><img src="http://blog.yimingliu.com/wp-content/uploads/2011/05/harvester_f1-300x187.jpg" alt="The initial setup against the Harvester" title="Harvester Fight" width="300" height="187" class="alignright size-medium wp-image-802" /></a></p>
<p>As the battle begins, set the party to Hold Position, and manually move the party members into position.   The mage and the archer should go stand by the switch that appears, but far enough apart that they don&#8217;t get nailed by the same Harvester attack at the same time.  Brogan needs to stand close by as the off-tank.  The Runic Golem should stand at the center of room with his Cleansing Aura.  The bronto (which actually has Taunt and runs faster than any other character in combat) should attack the Harvester, throw down a Taunt, and then start kiting the Harvester around the Runic Golem&#8217;s aura radius.</p>
<p>If a normal skeleton appears, Brogan should go tank it immediately, and the mage can help freeze it with a Cone of Cold.  If an elite or boss skeleton appears, or if there are more than 3 skeletons, have the mage pull the switch immediately to destroy all the skeletons.  Jerrik should always focus on the Harvester.  If either the archer or the mage is under attack, have the bronto run over and Taunt, then run the mage and/or archer away.  The skeleton should lose interest and focus on the bronto.  If not, Brogan needs to pick it up and tank it while the DPS&#8217;ers run far away.</p>
<p>Heal the bronto constantly, as it&#8217;ll inevitably get hit by the Harvester and its skeletons.  If the bronto is stunned, or if it is killed, Brogan must pick up threat and resume kiting immediately until Jerrik is able to resummon the bronto.  Switch back once the bronto is up again.</p>
<p>Keep an eye on the archer and mage while you&#8217;re kiting with the bronto.  Make sure no skeleton has wandered into the room and started attacking them.  Pause a lot if you need to.<br />
<a href="http://blog.yimingliu.com/wp-content/uploads/2011/05/harvester_f3.jpg"><img src="http://blog.yimingliu.com/wp-content/uploads/2011/05/harvester_f3-300x187.jpg" alt="Nearing the end of the First Phase of the Harvester Fight" title="Harvester Fight" width="300" height="187" class="alignright size-medium wp-image-804" /></a><br />
If this is executed correctly, eventually the Harvester will fall.  When its health gets very low, try to avoid hitting the switch and save it for just before Phase Two.  The switch will not appear again at that point, and there may be several skeletons that need killing at the end.  </p>
<p>There is a bit of luck involved.  If the switch is hit too early, and elite skeletons emerge while the switch is inactive, then this is probably bad.  If it&#8217;s a boss skeleton, you might consider using Brogan to kite it around until the switch is available again.  Controlling two kiters is very difficult, so pause a lot.</p>
<h4>Phase Two</h4>
<p>When the flesh golem is killed, the Harvester will jump out and attack.  If the party made it this far, and the switch is still available, then the battle is more or less won.  The Harvester lizard-form is far, far weaker than its previous flesh golem body.  It hits for about 60 on Brogan, but hits slowly and misses a lot, so it can be tanked.  It also disengages a lot to channel a skeleton summoning spell, so it doesn&#8217;t have a lot of DPS to hit the party with.  The best news: skeletons will no longer wander into the room in large packs &#8212; at this point, the Harvester has to summon one with his spell.</p>
<p>When the game screen comes back from the cutscene, hit the switch one last time to clear out all remaining skeletons if it&#8217;s still available.  If not, resume the kiting strategy and quickly remove the remaining skeletons.  Then, have the party resume normal attack stance from hold position and focus fire on the Harvester&#8217;s lizard form.  If it uses the jump ability, cast Crushing Prison (it won&#8217;t resist nearly as much now) or the Runic Golem&#8217;s Slam attack to slow it down while the melee attackers catch up.  It can also be frozen solid with Cone of Cold, though it can&#8217;t be shattered obviously.  Jerrik and the mage are still going to be the main DPS.  If the Harvester finishes channeling a normal or elite skeleton, tank it with Brogan and blast it down quickly.  If it&#8217;s a boss skeleton, Force Field it or have the bronto kite it around the room while the remaining party members continue to blast the Harvester.  It is only a matter of time before the Harvester dies.</p>
<p>The Grim Reaper achievement should hit the screen after a short cutscene.  Woot!</p>
<p>The first time I did this, it took me three tries and about an hour of playing, but is definitely a reproducible strategy on Nightmare difficulty.  If playing on Hard, this is actually really easy, as most skeletons will be normal skeletons and can be frozen and shattered.  It does take a lot of micromanagement, but since you can pause the game and issue new orders, this management shouldn&#8217;t be too hard &#8212; kinds of reminds of me Baldur&#8217;s Gate 1, where I auto-paused after every combat round and barely took any damage.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yimingliu.com/2011/05/26/a-guide-to-golems-of-amgarrak-with-a-new-character/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>musings on self and search</title>
		<link>http://blog.yimingliu.com/2010/03/05/musings_on_se/</link>
		<comments>http://blog.yimingliu.com/2010/03/05/musings_on_se/#comments</comments>
		<pubDate>Fri, 05 Mar 2010 22:48:18 +0000</pubDate>
		<dc:creator>yiming</dc:creator>
				<category><![CDATA[Personal]]></category>
		<category><![CDATA[musings]]></category>
		<category><![CDATA[SelfSolved]]></category>

		<guid isPermaLink="false">http://blog.yimingliu.com/?p=627</guid>
		<description><![CDATA[So as you may be aware, I developed SelfSolved in order to avoid cluttering up this blog with &#8220;I fixed this!&#8221; posts. I&#8217;m trying to get into a habit of writing at a higher conceptual level, instead of this repository being just yet another technical problems blog. It turns out that without writing about random [...]]]></description>
			<content:encoded><![CDATA[<p>So as you may be aware, I developed <a href="http://selfsolved.com">SelfSolved</a> in order to avoid cluttering up this blog with &#8220;I fixed this!&#8221; posts.  I&#8217;m trying to get into a habit of writing at a higher conceptual level, instead of this repository being just yet another technical problems blog.  It turns out that without writing about random things that I fixed, I have little else to say.  When I wrote up problems for this blog, I had monthly posts.  Now I&#8217;ve gone 3 months without writing anything.</p>
<p>It&#8217;s odd, as Ph.D. students (and former startup founders) can hold forth via very long and extensive blog posts, especially on technical topics they care about (and sometimes on topics that they don&#8217;t).  It may speak to my lack of aptitude for Ph.D. work; I hope not.</p>
<p>When I implemented SelfSolved, I created a <a href="http://selfsolved.com/sitemap.xml">sitemap</a> for search engine crawlers as a matter of course, but did not do so immediately.  Lots of content were present on the site before I completed the sitemap feature.  It turns out that search engines like the GOOG seem to ignore certain content in the sitemap &#8212; so much for indexing all the world&#8217;s knowledge.  I thought the crawler would get around to it eventually, but it doesn&#8217;t appear to be the case after nearly a year.</p>
<p>It&#8217;s interesting, because there doesn&#8217;t to be any rules.  For example,  <a href="http://selfsolved.com/problems/pylons-how-to-turn-off-caching-completely">&#8220;turning caching off completely in Pylons&#8221;</a> has a very short problem statement and solution.  Other posts, however, are fairly normal: <a href="http://selfsolved.com/problems/svn-directory-is-viewable-through-apache">&#8220;SVN directory is viewable through Apache&#8221;</a> is by all accounts a normal sized SelfSolved problem, with references and a full solution writeup.  As of this post, neither are indexed.</p>
<p>As soon as I wrote this blog post on this WordPress installation, the post became available in GOOG&#8217;s main index.  If I search on the phrases above, I get an entry back immediately.  But for a site like SelfSolved, these indexes aren&#8217;t available for days or weeks, even though SelfSolved publishes an Atom feed of its content as well, and pings the same GOOG notification URIs.  This does suggest that if you build your site on a well-used CMS, rather than custom-designed software, it will get you into indexes in almost real-time vs in days.  If you run a for-profit content-driven site (which SelfSolved is not), that could mean a fair bit of money. </p>
<p>It&#8217;s no wonder that SEO consultancies are flourishing.  There are certain hidden rules with crawling that go beyond the simple &#8220;create good content&#8221; and &#8220;get a sitemap&#8221; guidelines that the GOOG wants you to believe.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yimingliu.com/2010/03/05/musings_on_se/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<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>2</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[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 main [...]]]></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:0x000000e8 &#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>11</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 [...]]]></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 [...]]]></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>Musings on the state of popular science fiction</title>
		<link>http://blog.yimingliu.com/2009/05/10/musings-on-the-state-of-popular-science-fiction/</link>
		<comments>http://blog.yimingliu.com/2009/05/10/musings-on-the-state-of-popular-science-fiction/#comments</comments>
		<pubDate>Sun, 10 May 2009 17:32:47 +0000</pubDate>
		<dc:creator>yiming</dc:creator>
				<category><![CDATA[Personal]]></category>
		<category><![CDATA[opinion]]></category>
		<category><![CDATA[science fiction]]></category>
		<category><![CDATA[Star Trek]]></category>

		<guid isPermaLink="false">http://blog.yimingliu.com/?p=514</guid>
		<description><![CDATA[Received an email from a good friend on the &#8220;new and improved&#8221; Star Trek: I gave this some thought, and perhaps one could say that blowing up Vulcan is a symbolic &#8220;fuck you&#8221; to the core values of Trek, to wit: &#8220;Logic, reason, humanism&#8211;fuck these things! Do what feels right regardless of the consequences. Or [...]]]></description>
			<content:encoded><![CDATA[<p>Received an email from a good friend on the &#8220;new and improved&#8221; Star Trek:</p>
<blockquote><p>I gave this some thought, and perhaps one could say that blowing up Vulcan is a symbolic &#8220;fuck you&#8221; to the core values of Trek, to wit:  &#8220;Logic, reason, humanism&#8211;fuck these things!  Do what feels right regardless of the consequences.  Or you&#8217;ll get sucked into a black hole.&#8221;  Vulcan, I think, represented a key component of the Federation&#8217;s philosophy, and now they expect us to accept its destruction so they could thrill some casual viewers?</p>
<p>To my mind, the interesting tension in the Trek universe prior to this travesty resulted from Federation principles being tested against competing internal and external forces.  However, in Trek: Rebooted land, there&#8217;s one hand clapping&#8211;it&#8217;s all barbarism all the time; there were no discernible Federation principles in the first place.  You know, in Star Trek VI, Spock said &#8220;Logic is the beginning of wisdom, not the end.&#8221;  New version: &#8220;Fuck all that shit man, party on the Enterprise!&#8221;  Logic is apparently a trifle to be jettisoned whenever your adrenaline glands act up.  </p></blockquote>
<p>I think this has become a fairly general problem in what is considered &#8220;mainstream&#8221; sci-fi &#8212; the shows that &#8220;ordinary people&#8221; would accept.  The so-called more real vision of the future espoused by these things can roughly be generalized into &#8220;darker, edgier, younger&#8221;.  Reality, as it seems, must be full of angst, petty problems, and on the occasion, explosions.</p>
<p>A far cry from when the thoughtful visions of TNG garnered mainstream viewers by the millions.</p>
<p>There&#8217;s a quote attributed to AI pioneer Marvin Minsky:  </p>
<blockquote><p>&#8220;General fiction is pretty much about ways that people get into problems and screw their lives up. Science fiction is about everything else.&#8221; </p></blockquote>
<p>The point of science fiction is to imagine what is possible beyond the confining frameworks of everyday reality and drudgery.  It is supposed to illustrate what humanity is capable of and what they should aspire toward.</p>
<p>TNG, for example, aimed to explore a post-scarcity human society where the driving force is no longer personal economic gain.  Of course it would not be &#8220;real&#8221;, so much as matter replication and warp drive are also &#8220;not real&#8221;.  An average man of today would have to have to stretch his imagination to understand the motivations of those characters and their society &#8212; but that&#8217;s <i>precisely the point</i>.  If we all spun in place forever, mired in the minutiae of what is (rather than what <em>should</em> and <em>will be</em>), there would never be any progress &#8212; only more of the same.</p>
<p>This is also part of a rather annoying trend in popular culture to treat technology as something to be feared, and how curiosity should be punished.  How many recent sci-fi successes can be boiled down to: &#8220;Don&#8217;t research/develop technology X, because it&#8217;ll just destroy all humans/blow up the world/nuke us and all of our colonies!&#8221;.  It is trivially easy to spin a cautionary tale of fear for the new and unknown, to play to the most primitive parts of the human mind &#8212; such fearmongering undoubtedly holds TV ratings and sells movie tickets.  It takes a true visionary to look into what might be the next step for human progress, and instead of fearing the unknown, embrace it.</p>
<p>The Original Series inspired a generation of young people to become scientists and engineers.  The Next Generation taught the value of deliberation, diplomacy, and teamwork, creating a vision of a humanity pulling away from the basest parts of its past &#8212; and moving onto bigger and better things.  While they are still quite entertaining, they are part of that grand tradition of science fiction, opening the minds of ordinary people and pushing them, if only a little bit, toward exploring &#8220;final frontiers&#8221;.  </p>
<p>What do the latest and leading &#8220;sci-fi&#8221; do for that vision?</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yimingliu.com/2009/05/10/musings-on-the-state-of-popular-science-fiction/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 [...]]]></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[UPDATE Nov 1, 2010 Due to the complete lack of updates for tsocks, I recommend the use of proxychains over tsocks on OS X 10.5+. It still does not resolve DNS properly (proxychains &#8212; as of this post&#8217;s publication time &#8212; uses a hack by calling to dig @4.2.2.2 for DNS), but at least is [...]]]></description>
			<content:encoded><![CDATA[<p class="update-box">
UPDATE Nov 1, 2010<br />
Due to the complete lack of updates for tsocks, I recommend the use of <a href="http://proxychains.sourceforge.net/">proxychains</a> over tsocks on OS X 10.5+.  It still does not resolve DNS properly (proxychains &#8212; as of this post&#8217;s publication time &#8212; uses a hack by calling to <tt>dig</tt> @4.2.2.2 for DNS), but at least is far easier to make work than tsocks.
</p>
<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>9</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 for architecture x86_64: "_xmlTextReaderSchemaValidate", referenced from: _zim_xmlreader_setSchema in [...]]]></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>This doesn&#8217;t only happen with libxml.  If you&#8217;ve installed any extra updated libraries, like iconv or tidy or any library that has significant symbol changes between versions, it&#8217;ll die in similar ways.  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 ).  I understand that it&#8217;s an open source project, and no self-respecting software engineer likes to use time on project plumbing / build systems rather than work on the product.  However, 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.  PHP&#8217;s 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>17</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, telnet or [...]]]></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>1</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 variable [...]]]></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><br />
Use -nc if you mess up and need to continue a build.
</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>1</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 appears when you have a blocked network port (ARD uses TCP [...]]]></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 appears 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: 7/21/2011 &#8211; DocPreview DOES NOT work with Safari 5.1 on OS X 10.6+. This is because the WebKit Plugin APIs it depended on are deprecated by Apple. This has broken a number of .webplugin extensions, including some of my favorites like the current (as of today) version of XML View. If you have upgraded [...]]]></description>
			<content:encoded><![CDATA[<div class="update-box">UPDATE:<br />
7/21/2011 &#8211; DocPreview <b>DOES NOT work with Safari 5.1 on OS X 10.6+</b>.  This is because the WebKit Plugin APIs it depended on are <a href="http://developer.apple.com/library/mac/#documentation/InternetWeb/Conceptual/WebKit_PluginProgTopic/Tasks/WebKitPlugins.html">deprecated</a> by Apple.  This has broken a number of .webplugin extensions, including some of my favorites like the current (as of today) version of <a href="http://www.entropy.ch/software/macosx/xmlviewplugin/">XML View</a>.  If you have upgraded to Safari 5.1, on OS X 10.6 or 10.7, then please uninstall DocPreview 0.1 (by removing it from the /Library/Internet Plugins or ~/Library/Internet Plugins directories, depending on where you initially installed it).  For those still on Safari 5.0 and below, this will still work.</p>
<p>Only NPAPI plugins are apparently allowed from 5.1 forward.  This API does not give native access to the browser window as before; therefore the old methods of converting .doc files to HTML no longer works.  Because I still need Word preview capability for myself, I have a few ideas on how to make DocPreview work for 5.1+.  However, this requires a complete re-write of the entire code.  Apple obviously already has .doc preview capability on iOS but hasn&#8217;t shared that with us on OS X.  I&#8217;m not sure it&#8217;ll be worth it to make these modifications, only for Apple to release .doc preview as a native capability to Safari a few months later.</p>
<p>Again, any NPAPI experts willing to work with me on this issue &#8212; please contact me.</p>
<p>12/1/2010 &#8211; As promised, DocPreview is now <a href="http://code.google.com/p/docpreview/">open sourced at Google Code</a>.</p>
<p>01/24/2010 &#8211; <del datetime="2011-07-22T04:07:30+00:00">DocPreview updated for 64-bit Safari and 10.6.  Still seems to work.</del></p>
<p>early 2009 &#8211; Schubert|IT&#8217;s <a href="http://www.schubert-it.com/free/">Word Browser Plugin</a> has been made a Universal binary.  Therefore, DocPreview is no longer needed, as I originally wrote this plugin to fill in the gap when Word Browser Plugin was PPC-only.  Word Browser Plugin offers a more advanced user interface than DocPreview.  You should try it out first.  I will continue to tweak DocPreview, more as a challenge to myself.  I will probably open source the package &#8212; at soon as I fix a hack or two and no longer feel ashamed of my code.
</div>
<p>&#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/free/">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/was really why I wrote this plug-in.<br />
<a href="http://blog.yimingliu.com/wp-content/uploads/2008/12/docpreview-full_mode.png"><img src="http://blog.yimingliu.com/wp-content/uploads/2008/12/docpreview-full_mode-300x194.png" alt="" title="docpreview-full_mode" width="300" height="194" class="alignright size-medium wp-image-671" /></a></p>
<p>DocPreview only supports WebKit-based browsers that can use .webplugin files.  Therefore, this includes Safari, Shiira, etc., but not Chrome (as of the time of this update).  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 (Safari 5.0 and below on 10.5, 10.6)</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 work-in-progress.  It passes the &#8220;dogfooding&#8221; test; as in, I&#8217;m using this plug-in daily (eating my own dogfood, as they say).  While I believe it functions correctly &#8212; at least on my machines, 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.  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><a href="http://blog.yimingliu.com/wp-content/uploads/2008/12/docpreview_originaldoc_full.png"><img src="http://blog.yimingliu.com/wp-content/uploads/2008/12/docpreview_originaldoc_full-300x284.png" alt="" title="docpreview_originaldoc_full" width="300" height="284" class="alignright size-medium wp-image-670" /></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.x, 3.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.  Does not work on Chrome, but I&#8217;m sure there are better solutions using Chrome extensions.</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>&#8216;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://blog.yimingliu.com/wp-content/uploads/2008/12/docpreview-embedded_mode.png"><img src="http://blog.yimingliu.com/wp-content/uploads/2008/12/docpreview-embedded_mode-300x203.png" alt="" title="docpreview-embedded_mode" width="300" height="203" class="alignright size-medium wp-image-672" /></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>I expect Apple to support .doc previews with the next version(s) of Safari, very soon (ok, so not in 4.x, but surely in 5.x.  Anyone on the Apple Safari team reading this: come on, this feature is trivial &#8212; even I can do it ).  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 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.  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>8</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, in that [...]]]></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>2</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[03-10-2010: I believe this is fixed in latest Safari versions. The contents of this post remain for historical purposes only. 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 [...]]]></description>
			<content:encoded><![CDATA[<div class="update-box">
03-10-2010:  I believe this is fixed in latest Safari versions.  The contents of this post remain for historical purposes only.
</div>
<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 proper solution [...]]]></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>2</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>38</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 -o [...]]]></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>14</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 [...]]]></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 Google-fu, [...]]]></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>4</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 [...]]]></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>
	</channel>
</rss>

