<?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>Brian Pane &#187; Uncategorized</title>
	<atom:link href="http://www.brianp.net/category/uncategorized/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.brianp.net</link>
	<description>Occasional Writings</description>
	<lastBuildDate>Fri, 15 Jan 2010 15:10:14 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Validation</title>
		<link>http://www.brianp.net/2010/01/15/validation/</link>
		<comments>http://www.brianp.net/2010/01/15/validation/#comments</comments>
		<pubDate>Fri, 15 Jan 2010 15:10:14 +0000</pubDate>
		<dc:creator>brianp</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.brianp.net/?p=237</guid>
		<description><![CDATA[<p>People from Computer Science backgrounds often use the word &#8220;orthogonal.&#8221;  I think that&#8217;s partly because it concisely describes an often-important concept, but mostly because it&#8217;s one of the few impressive words in our vernacular.  (&#8220;Idempotent&#8221; is my other favorite CS term.)</p>
<p>Other professions get to use a variety of big words.  Physicians, for [...]]]></description>
			<content:encoded><![CDATA[<p>People from Computer Science backgrounds often use the word &#8220;<a href="http://en.wikipedia.org/wiki/Orthogonal">orthogonal</a>.&#8221;  I think that&#8217;s partly because it concisely describes an often-important concept, but mostly because it&#8217;s one of the few impressive words in our vernacular.  (&#8220;<a href="http://en.wikipedia.org/wiki/Idempotent">Idempotent</a>&#8221; is my other favorite CS term.)</p>
<p>Other professions get to use a variety of big words.  Physicians, for example, have a rich, domain-specific vocabulary.  So do economists.  Lawyers have perhaps the best lexicon; not only do they get to use big, fancy words, but half of those words are in <i>Latin</i>.</p>
<p>Thus it was a pleasant surprise to read that a lawyer had adopted our humble &#8220;orthogonal&#8221; and <a href="http://www.washingtonpost.com/wp-dyn/content/article/2010/01/11/AR2010011103690.html">earned kudos</a> from the Justices of the United States Supreme Court for it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.brianp.net/2010/01/15/validation/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The perception of performance</title>
		<link>http://www.brianp.net/2009/12/08/the-perception-of-performance/</link>
		<comments>http://www.brianp.net/2009/12/08/the-perception-of-performance/#comments</comments>
		<pubDate>Wed, 09 Dec 2009 01:15:12 +0000</pubDate>
		<dc:creator>brianp</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.brianp.net/?p=230</guid>
		<description><![CDATA[<p>I&#8217;ve found myself using Safari more and more, instead of Firefox, because Firefox is slow.</p>
<p>&#8220;Slow&#8221;?  What does that mean?</p>
<p>It means that when I start up Firefox, even if it&#8217;s already in the filesystem cache, the app&#8217;s Mac dock icon completes two full bounces before the browser window appears.  Safari&#8217;s doc icon completes approximately [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve found myself using Safari more and more, instead of Firefox, because Firefox is slow.</p>
<p>&#8220;Slow&#8221;?  What does that mean?</p>
<p>It means that when I start up Firefox, even if it&#8217;s already in the filesystem cache, the app&#8217;s Mac dock icon completes two full bounces before the browser window appears.  Safari&#8217;s doc icon completes approximately half of one bounce before its window appears.  The just-released Chrome for Mac also displays its window in half a bounce.</p>
<p>Each icon bounce takes approximately one second.  Thus I&#8217;ve developed a preference not to use Firefox&#8211;an otherwise excellent product&#8211;because it takes 1.5 seconds longer to start than the competition.</p>
<p>I&#8217;ll typically keep my web browser running for hours or even days after starting it up, so Firefox&#8217;s extra startup time is immaterial when amortized over the time between restarts.  That&#8217;s my quantitative assessment, anyway.  In practice, though, I tend to click the Safari icon because, qualitatively, it&#8217;s the fast one.</p>
<p>In software, <em>speed matters</em>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.brianp.net/2009/12/08/the-perception-of-performance/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Integrating Mobwrite with nginx</title>
		<link>http://www.brianp.net/2009/11/16/integrating-mobwrite-with-nginx/</link>
		<comments>http://www.brianp.net/2009/11/16/integrating-mobwrite-with-nginx/#comments</comments>
		<pubDate>Mon, 16 Nov 2009 16:32:42 +0000</pubDate>
		<dc:creator>brianp</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.brianp.net/?p=227</guid>
		<description><![CDATA[<p>I recently helped an old friend with some prototyping and strategy for a stealth-mode project he&#8217;s doing.  He wanted to use MobWrite, a framework that allows multiple users to do real-time, collaborative editing of content in a web page.</p>
<p>There was one technical challenge: the project was using nginx as a webserver, and none of [...]]]></description>
			<content:encoded><![CDATA[<p>I recently helped an old friend with some prototyping and strategy for a stealth-mode project he&#8217;s doing.  He wanted to use <a href="http://code.google.com/p/google-mobwrite/">MobWrite</a>, a framework that allows multiple users to do real-time, collaborative editing of content in a web page.</p>
<p>There was one technical challenge: the project was using nginx as a webserver, and none of the existing web gateway implementations for MobWrite were well-suited for use with nginx.  MobWrite has a back-end server that speaks a custom protocol, and it needs a bit of additional software to translate HTTP requests from web browsers into the server&#8217;s protocol.  The MobWrite distribution contains PHP, JSP, and Python pages that do this translation.</p>
<p>It is possible to add support for any and all of those languages to nginx, but doing so adds substantial complexity.  Specifically, the event-driven design of nginx works well only with plugins that do their work in small, event-driven steps and do not block for I/O or lengthy computation.  PHP, mod_python, and JSP, in contrast, all are based on a programming model where the code that handles the request expects to run synchronously until completion.  Running such code inside the single-threaded, asynchronous nginx could allow a long-running PHP/Python/JSP request to block all other requests.  One common solution is to use an nginx gateway plugin like mod_scgi that dispatches requests for these synchronous languages to a separate pool of processes.  This enables a single nginx server to handle both synchronous PHP/Python/JSP requests and asynchronous static-content or HTTP-proxy requests without either type of request starving out the other.  However, adding a separate process pool for the synchronous requests means adding configuration and tuning complexity, thus diminishing one of the inherent advantages of using nginx.</p>
<p>Determined to have my cake and eat it too&#8211;i.e., to support MobWrite and other types of content in a single nginx server while still enjoying nginx&#8217;s single-process simplicity and efficiency&#8211;I made a new nginx plugin called nginx-mobwrite.  This plugin translates incoming HTTP requests from MobWrite clients into the MobWrite internal format and proxies them asynchronously to the MobWrite server.  The nginx architecture includes an &#8220;upstream&#8221; framework that manages requests to back end servers as part of nginx&#8217;s event loop.  The nginx-mobwrite uses this framework to dispatch translated requests to the MobWrite server and send the responses back to clients in an asynchronous manner, without blocking any other requests the nginx server might be handling at the same time.</p>
<p>The nginx-mobwrite plugin is available as open source, under v2.0 of the Apache License, on <a href="http://github.com/brianpane/nginx-mobwrite">GitHub</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.brianp.net/2009/11/16/integrating-mobwrite-with-nginx/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tips for installing Windows 7 on a Mac</title>
		<link>http://www.brianp.net/2009/11/04/tips-for-installing-windows-7-on-a-mac/</link>
		<comments>http://www.brianp.net/2009/11/04/tips-for-installing-windows-7-on-a-mac/#comments</comments>
		<pubDate>Wed, 04 Nov 2009 07:06:42 +0000</pubDate>
		<dc:creator>brianp</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.brianp.net/?p=221</guid>
		<description><![CDATA[<p>I decided recently to try installing Windows 7 on my iMac, in a Boot Camp dual-boot configuration alongside OS X.  I ultimately got it working, but I ran into one perplexing problem along the way.  Here&#8217;s a summary of the symptoms and the solution, in case the information is helpful to other people.</p>
<p>I [...]]]></description>
			<content:encoded><![CDATA[<p>I decided recently to try installing Windows 7 on my iMac, in a Boot Camp dual-boot configuration alongside OS X.  I ultimately got it working, but I ran into one perplexing problem along the way.  Here&#8217;s a summary of the symptoms and the solution, in case the information is helpful to other people.</p>
<p>I used the installation process described <a href="http://www.simplehelp.net/2009/01/15/using-boot-camp-to-install-windows-7-on-your-mac-the-complete-walkthrough/">here</a>.  After I clicked the &#8220;Start Installation&#8221; button in step 8, the computer rebooted and greeted me with a blank black screen with a blinking white underline cursor in the upper left.</p>
<p>A bit of web searching led me to a solution that worked: I had to reset the computer&#8217;s PRAM.  The PRAM apparently is an area of nonvolatile memory containing information about USB devices such as keyboards and mice.  The full process I had to use was:</p>
<ul>
<li>Power off the computer.</li>
<li>Unplug the keyboard and plug it into a different USB port.</li>
<li>Turn on the computer.</li>
<li>Immediately press the Command, Option, P, and R keys and hold them down until the system restarts.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.brianp.net/2009/11/04/tips-for-installing-windows-7-on-a-mac/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>When Bad Monopolies Happen to Good Products</title>
		<link>http://www.brianp.net/2009/10/29/when-bad-monopolies-happens-to-good-products/</link>
		<comments>http://www.brianp.net/2009/10/29/when-bad-monopolies-happens-to-good-products/#comments</comments>
		<pubDate>Fri, 30 Oct 2009 06:30:47 +0000</pubDate>
		<dc:creator>brianp</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.brianp.net/?p=208</guid>
		<description><![CDATA[<p>I use a lot of Apple products, and I like them.  I&#8217;ve come to depend on the versatility of Mac OS X: rather than having to choose between Windows for good productivity tools and Linux for good engineering tools, I can have all those tools together in one OS X system.  The iPhone [...]]]></description>
			<content:encoded><![CDATA[<p>I use a lot of Apple products, and I like them.  I&#8217;ve come to depend on the versatility of Mac OS X: rather than having to choose between Windows for good productivity tools and Linux for good engineering tools, I can have all those tools together in one OS X system.  The iPhone combines a lot of useful functionality in a compact device that allows me to stay connected wherever I go.  The Time Capsule combines two essential features, a backup drive and a wireless router, in one turnkey appliance.  MobileMe synchronizes my calendar and address book seamlessly across all these devices.</p>
<p>Among the themes that unite these products are vertical integration and a consistent, centrally-controlled design language.  Those themes are not always virtues, however.</p>
<p>With the iPhone, Apple controls not only the design of the device and its built-in software, but also the only distribution channel for third-party software.  Yes, be fair, there is at least one <a href="http://cydia.saurik.com/">independent alternative</a> to Apple&#8217;s App Store.  To shop there, though, a consumer must &#8220;jailbreak&#8221; the iPhone.  Because there is no supported way of installing an alternate operating system on the iPhone, the people who provide jailbreaking tools have to engage in reverse-engineering and clever hacking simply to enable a customer to install their choice of software on the hardware they&#8217;ve bought.</p>
<p>The lack of an alternate distribution channel might not be troubling to me if the official App Store were an open marketplace.  Alas, vendors can only sell their software in the App Store if Apple approves and reviews it.  Apple has <a href="http://www.techcrunch.com/2009/07/31/fcc-takes-on-apple-and-att-over-google-voice-rejection/">blocked</a> products from competitors such as Google.  Greeting card parody website <a href="http://www.someecards.com">someecards</a> recently submitted an iPhone application for Apple&#8217;s approval.  Apple refused to allow the app to be sold in the App Store because it contained &#8220;<a href="http://www.techcrunch.com/2009/10/07/apple-rejects-someecards-app-for-being-full-of-someecards-content/">content that ridicules public figures</a>&#8220;&#8211;specifically Roman Polanski and Adolf Hitler.  Presumably Apple was just enforcing editorial standards in order to maintain a high quality of content in the App Store, right?  Well, maybe not.  When someeecards relented and created a version of their app without the contentious content, Apple finally approved it for sale in the App Store, right alongside other apps that met Apple&#8217;s standards for quality and tastefulness: apps like, well, <a href="http://www.techcrunch.com/2009/10/29/someecards-gives-in-to-apple-to-take-on-asian-boobs/">I&#8217;ll let TechCrunch explain that part</a>.</p>
<p>As a consumer, I&#8217;ve come to expect that retailers will apply their own biases in deciding what products to sell.  And in a free market, I will buy from businesses whose biases are compatible with my own.  Thus what bothers me about Apple is not the apparent hypocrisy of an App Store that banned the dark humor of someecards but approved the <a href="http://www.msnbc.msn.com/id/33310411/ns/technology_and_science-tech_and_gadgets/">controversial</a> Pepsi &#8220;Amp up before you score&#8221; app.  No, what bothers me is that Apple owns the only store and has <a href="http://www.eff.org/deeplinks/2009/02/apple-says-jailbreaking-illegal">attempted</a> to wield the DMCA as a means to prevent anyone from building a competing store.</p>
<p>Even OS X, my favorite part of the Apple ecosystem, allows me no choice other than vertical integration.  I can buy Windows and install it on any compatible brand of computer.  I can download Linux and install it on any compatible brand of computer.  I can buy OS X and install it on, well, any &#8220;<a href="http://store.apple.com/Catalog/US/Images/MacOSX.htm">Apple-labeled computer</a>.&#8221;</p>
<p>Apple&#8217;s strategy of centrally controlled, vertical integration has yielded some fine products.  Furthermore, it has produced substantial profits for the company.  As a <em>user</em> of Apple products, I am happy.  As a <em>shareholder</em> of AAPL, I am happy.  As a <em>customer</em>, I am increasingly disappointed.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.brianp.net/2009/10/29/when-bad-monopolies-happens-to-good-products/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ruby + MySQL dynamic library problems</title>
		<link>http://www.brianp.net/2009/10/06/ruby-mysql-dynamic-library-problems/</link>
		<comments>http://www.brianp.net/2009/10/06/ruby-mysql-dynamic-library-problems/#comments</comments>
		<pubDate>Tue, 06 Oct 2009 19:21:51 +0000</pubDate>
		<dc:creator>brianp</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.brianp.net/?p=201</guid>
		<description><![CDATA[<p>I wanted to try out Ruby on Rails with MySQL on OS X 10.6.  I ran into a few common problems along the way, so I am documenting the process here in case it might be helpful to others.</p>
Step 1: Install MySQL
<p>I grabbed the .tar.gz distribution of the latest MySQL 5.1 release and installed [...]]]></description>
			<content:encoded><![CDATA[<p>I wanted to try out Ruby on Rails with MySQL on OS X 10.6.  I ran into a few common problems along the way, so I am documenting the process here in case it might be helpful to others.</p>
<h2>Step 1: Install MySQL</h2>
<p>I grabbed the .tar.gz distribution of the latest <a href="http://dev.mysql.com/downloads/">MySQL 5.1</a> release and installed it in a nonstandard location on my computer.  &#8220;Nonstandard&#8221; in this case means &#8220;somewhere other than /usr/local/mysql.&#8221;  This detail would be important in a later step.</p>
<h2>Step 2: Install the Ruby mysql gem</h2>
<p>I&#8217;d installed a 64-bit version of MySQL, so the installation process for the mysql gem was:</p>
<pre>
sudo env ARCHFLAGS="-arch x86_64" gem install -t mysql \
  -- --with-mysql-config=<i>/path/to/my/mysql/installation</i>/bin/mysql_config
</pre>
<p>For a 32-bit MySQL installation, replace the &#8220;x86_64&#8243; with &#8220;x86&#8243; in the ARCHFLAGS.</p>
<h2>Step 3: Set the DYLD_LIBRARY_PATH</h2>
<p>I omitted this step initially, and when I tried to run &#8220;rake db:migrate&#8221; for my Rails application, I got an error message:</p>
<pre>
uninitialized constant MysqlCompat::MysqlRes
</pre>
<p>In the environment of each user account where you plan to run Ruby apps that depend on MySQL, do this:</p>
<pre>
export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:<i>/path/to/my/mysql/installation</i>/lib
</pre>
<p>Note that most of the command-line tools supplied with binary builds of MySQL appear to be statically linked with libmysqlclient.  This means that these tools may work flawlessly even if you&#8217;ve neglected to set the DYLD_LIBRARY_PATH.  The Ruby mysql gem, however, is dynamically linked to libmysqlclient, so it is essential that the MySQL lib directory be included in your DYLD_LIBRARY_PATH if MySQL is installed in a nonstandard location.</p>
<p>For most other Unix systems, the environment variable to set is LD_LIBRARY_PATH rather than DYLD_LIBRARY_PATH.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.brianp.net/2009/10/06/ruby-mysql-dynamic-library-problems/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Sequentially assigned IDs and giving away competitive intelligence</title>
		<link>http://www.brianp.net/2009/10/06/sequentially-assigned-ids-and-giving-away-competitive-intelligence/</link>
		<comments>http://www.brianp.net/2009/10/06/sequentially-assigned-ids-and-giving-away-competitive-intelligence/#comments</comments>
		<pubDate>Tue, 06 Oct 2009 07:40:26 +0000</pubDate>
		<dc:creator>brianp</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.brianp.net/?p=192</guid>
		<description><![CDATA[<p>This post on TechCrunch contains quite a nice analysis of Twitter&#8217;s user behavior:</p>
<p>Twitter Data Analysis: An Investor&#8217;s Perspective</p>
<p>As the author notes, it was possible to deduce so many key metrics because &#8220;Twitter uses auto-incrementing ID numbers (1,2,3,4…) for both users and tweets.&#8221;</p>
<p>Auto-incremented ID numbers are a common web development practice.  When you run an [...]]]></description>
			<content:encoded><![CDATA[<p>This post on TechCrunch contains quite a nice analysis of Twitter&#8217;s user behavior:</p>
<p><a href="http://www.techcrunch.com/2009/10/05/twitter-data-analysis-an-investors-perspective/">Twitter Data Analysis: An Investor&#8217;s Perspective</a></p>
<p>As the author notes, it was possible to deduce so many key metrics because &#8220;Twitter uses auto-incrementing ID numbers (1,2,3,4…) for both users and tweets.&#8221;</p>
<p>Auto-incremented ID numbers are a common web development practice.  When you run an online business, you and/or your users create data&#8211;hopefully lots of data.  Each record of data needs a unique identifier that you can use to go find that bit of data for later use.  Automatically-incrementing integer IDs are a common implementation choice because they have some desirable properties:</p>
<ul>
<li><strong>Compactness</strong> &#8211; Shorter URLs are generally a good thing.  In addition, IDs that can fit into a 32- or 64-bit integer representation allow for efficient storage in a database and efficient manipulation within most programming languages.</li>
<li><strong>Uniqueness</strong> &#8211; It is trivially easy to generate unique IDs with an auto-incrementing approach: keep track of the last ID you generated, and add one.</li>
<li><strong>Efficiency</strong> &#8211; Generating the next sequential ID value doesn&#8217;t take very long.  In more precise terms, it takes O(1) time; the speed with which you can generate the next integer is a constant, and this operation will not get slower as your data size grows.</li>
<li><strong>Convenience</strong> &#8211; Most databases have a built-in feature that can auto-generate auto-incrementing IDs.</li>
</ul>
<p>Despite these virtues, auto-incrementing IDs can reveal information about the rate at which you are accumulating customers or content.  If your user IDs are sequentially generated, for example, a competitor need only sign up for a new account on your website once a day to determine how fast your user base is growing.  You may not mind that risk; the engineering team at Twitter probably discussed this issue when designing their data model and consciously decided not to obscure their ID values.</p>
<p>In cases where you do want to avoid using auto-incrementing ID values, some alternative ID generation strategies are:</p>
<ul>
<li><strong>Random</strong> &#8211; Generate a random number every time you need a new ID.  Guaranteeing uniqueness requires a bit more work with this approach, though.</li>
<li><strong>Random increment</strong> &#8211; When generating a new ID, instead of adding one to the previously generated ID, add a random number.  This approach will exhaust the range of your chosen integer representation more quickly than the traditional auto-increment, though, so it is perhaps best used with a 64-bit representation.</li>
<li><strong>UUID</strong> &#8211; Use <a ref="http://en.wikipedia.org/wiki/Universally_Unique_Identifier">UUIDs</a> instead of integers as IDs.  UUIDs have the properties of efficiency and uniqueness (even with random UUID generation, there are enough bits to make duplicates very rare) but are less compact than a typical auto-incrementing numeric ID.  A UUID occupies 36 bytes in human-readable form or 16 bytes (128 bits) in binary form.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.brianp.net/2009/10/06/sequentially-assigned-ids-and-giving-away-competitive-intelligence/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>OpenID and Facebook authentication support for blog comments</title>
		<link>http://www.brianp.net/2009/09/24/openid-and-facebook-authentication-support-for-blog-comments/</link>
		<comments>http://www.brianp.net/2009/09/24/openid-and-facebook-authentication-support-for-blog-comments/#comments</comments>
		<pubDate>Thu, 24 Sep 2009 08:57:31 +0000</pubDate>
		<dc:creator>brianp</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.brianp.net/?p=188</guid>
		<description><![CDATA[<p>
This blog now allows readers to post comments if they authenticate via OpenID.
</p>
<p>
As described earlier, I tried the OpenID plugin for WordPress, but that plugin required a PHP extension not supported by my web hosting provider.
</p>
<p>
I subsequently found the WordPress RPX plugin that supports OpenID.  RPX is an outsourced authentication service run by a [...]]]></description>
			<content:encoded><![CDATA[<p>
This blog now allows readers to post comments if they authenticate via <a href="http://openid.net/">OpenID</a>.
</p>
<p>
As described <a href="/2009/09/23/openid-1-brianp-0/">earlier</a>, I tried the OpenID plugin for WordPress, but that plugin required a PHP extension not supported by my web hosting provider.
</p>
<p>
I subsequently found the WordPress <a href="http://wordpress.org/extend/plugins/rpx/">RPX plugin</a> that supports OpenID.  <a href="http://rpxnow.com/">RPX</a> is an outsourced authentication service run by a company called <a href="http://www.janrain.com/">JanRain</a>.  The WordPress RPX plugin calls the RPX servers, which in turn do the OpenID handshaking with one&#8217;s OpenID provider.
</p>
<p>
Conveniently, RPX also supports authentication via one&#8217;s Facebook login.  In all cases, the user&#8217;s password is sent only to the identity provider (Yahoo, Google, Facebook, etc) and is never shared with the RPX servers or my own site.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.brianp.net/2009/09/24/openid-and-facebook-authentication-support-for-blog-comments/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>OpenID: 1, brianp: 0</title>
		<link>http://www.brianp.net/2009/09/23/openid-1-brianp-0/</link>
		<comments>http://www.brianp.net/2009/09/23/openid-1-brianp-0/#comments</comments>
		<pubDate>Thu, 24 Sep 2009 00:06:54 +0000</pubDate>
		<dc:creator>brianp</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.brianp.net/?p=184</guid>
		<description><![CDATA[<p>
I wanted to add OpenID support to my blog so that people could authenticate using their credentials from other sites (Yahoo and Google, for example) to post comments.
</p>
<p>
There is a plugin for WordPress that adds OpenID support.  I downloaded it, installed it, and was soon up and running with a non-working OpenID implementation.
</p>
<p>
When I [...]]]></description>
			<content:encoded><![CDATA[<p>
I wanted to add OpenID support to my blog so that people could authenticate using their credentials from other sites (Yahoo and Google, for example) to post comments.
</p>
<p>
There is a <a href="http://wordpress.org/extend/plugins/openid/">plugin</a> for WordPress that adds OpenID support.  I downloaded it, installed it, and was soon up and running with a non-working OpenID implementation.
</p>
<p>
When I entered the service provider endpoint URI for one of my OpenID-providing accounts into the right field in the WordPress login form, the WordPress OpenID plugin replied with a cryptic error message: &#8220;Could not discover an OpenID identity server endpoint at the url.&#8221;
</p>
<p>
After a couple of hours of troubleshooting, including adding debugging code to the OpenID plugin, I found the root cause of the problem.  OpenID uses a standard called XRDS.  XRDS is based on XML.  The OpenID plugin for WordPress supports two specific XML-supporting extensions for PHP (the programming language in which WordPress and its plugins are written), one named &#8220;domxml&#8221; for PHP4 and another named &#8220;dom&#8221; for PHP5.  My web host provides PHP, but not either of those XML extensions.
</p>
<p>
On the bright side, my web host&#8217;s PHP installation does appear to have a <i>different</i> XML-supporting extension for PHP, one called simply &#8220;xml.&#8221;  If I succeed in modifying the WordPress OpenID plugin to work with that as a third option, I&#8217;ll submit a patch to the maintainers.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.brianp.net/2009/09/23/openid-1-brianp-0/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Scanning paper documents into PDF under OS X 10.6</title>
		<link>http://www.brianp.net/2009/09/17/3/</link>
		<comments>http://www.brianp.net/2009/09/17/3/#comments</comments>
		<pubDate>Fri, 18 Sep 2009 00:04:31 +0000</pubDate>
		<dc:creator>brianp</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.brianp.net/?p=162</guid>
		<description><![CDATA[<p>
For a couple of years, I&#8217;ve used an HP all-in-one printer/scanner device.  Up through OS X 10.5, HP provided a scanning application that made it reasonably easy to scan paper documents into multi-page PDFs.  That application, however, stopped working under OS X 10.6 Snow Leopard.
</p>
The good news
<p>
The printer support in 10.6 already includes [...]]]></description>
			<content:encoded><![CDATA[<p>
For a couple of years, I&#8217;ve used an <a href="http://www.wired.com/politics/security/news/2006/09/71730">HP</a> all-in-one printer/scanner device.  Up through OS X 10.5, HP provided a scanning application that made it reasonably easy to scan paper documents into multi-page PDFs.  That application, however, stopped working under OS X 10.6 <a href="http://mashable.com/2009/08/25/apple-censored-snow-leopard/">Snow Leopard</a>.
</p>
<h2>The good news</h2>
<p>
The printer support in 10.6 already includes a built-in scanning application.  In the Finder, navigate to your home directory, then Library -&gt; Printers.  Click on the entry for your scanner, and you&#8217;ll get a window with Printer and/or Scanner tabs (depending on the capabilities of the device).  From the Scanner tab, you can scan documents into PDF or various image formats.
</p>
<p><img src="/i/162/print-scan.png" width=600" height="489" /></p>
<h2>The bad news</h2>
<p>
If the document you want to scan is more than one page long, this Scanner app will produce a multi-page PDF only if you use the document feeder on the scanner.  The document feeder is a fine solution if the documents are printed on only one side of the paper.  If you have two-sided documents to scan, and your scanner doesn&#8217;t have a duplex feeder, you can use the flatbed scanning mode to scan a page at a time&#8211;but you&#8217;ll end up with a collection of separate PDFs, one per page.
</p>
<h2>Solution</h2>
<p>
I haven&#8217;t found a way to produce a multiple-page PDF in one step without either 1) getting a different scanning application or 2) getting a scanner with a duplex document feeder. I have, though, managed to automate the process of concatenating multiple PDFs into a single document.
</p>
<p>The first step is to create an application that concatenates PDFs.  This is much easier than it sounds:
</p>
<ol>
<li>Start up the Automator application</li>
<li>Automator will ask you to &#8220;choose a template for your workflow.&#8221;  Pick the one named &#8220;Application.&#8221;</li>
<li>Drag and drop Actions from the menus on the left to create a workflow that looks like this:<br/><br />
<img src="/i/162/automator.png" width="500" height="322"/>
</li>
<li>From the Automator, save this workflow somewhere.  You now have an application that concatenates PDFs.</li>
<li>Optionally, put this application in your Pictures folder, or put it somewhere else and make a symlink to it in your pictures folder.
</ol>
<p>
Now that you have a PDF-concatenator application, you can use it from the Finder by selecting the PDFs that you want to concatenate and then dragging-and-dropping them onto the app.
</p>
<h2>Usage</h2>
<p>
When you scan documents from the Printer/Scanner app, they end up by default in your Pictures folder with names like <code>Scan.pdf</code>, <code>Scan 1.pdf</code>, etc.   I created an empty file called <code>Scan.pdf</code> in that directory to make sure that all my actual scans would be named sequentially as <code>Scan 1.pdf</code>, <code>Scan 2.pdf</code>, and so on.
</p>
<p>
Based on this setup, my procedure for scanning a multi-page document into a single PDF using the flatbed scanner is:
</p>
<ol>
<li>Open up the Printer/Scanner window and use it to scan each page.</li>
<li>In the Finder, go to the Pictures folder.</li>
<li>Select the PDFs representing the scanned pages.</li>
<li>Drag and drop the selected files onto the PDF-concatenator application&#8217;s icon.</li>
<li>The combined document will open in Preview.  From Preview, <b>save</b> it as whatever file name you like.</li>
</ol>
<p>
That last step&#8211;saving the file from Preview&#8211;is essential.  The Automator action that does the actual concatenation puts the temporary file in a randomly-named file under <code>/var/folders</code>.  My automator script, though, moves this temporary file to the Trash after opening it in Preview.  If the document you&#8217;ve just scanned contains sensitive data, such as a bank statement, I recommend that you 1) from Preview, save your document someplace secure, like an <a href="http://support.apple.com/kb/HT1578">encrypted disk image</a>, and 2) from the finder menu, use the Secure Empty Trash operation to delete the temporary file.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.brianp.net/2009/09/17/3/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
