<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-17096219</id><updated>2011-10-27T00:42:26.323-07:00</updated><category term='linux'/><category term='apache'/><category term='ISP'/><category term='wikka'/><category term='dom'/><category term='javascript'/><category term='mysql'/><category term='php'/><category term='drupal'/><category term='cakephp'/><category term='vbs'/><category term='design'/><category term='cranky'/><category term='hosting'/><category term='vim'/><category term='ubuntu'/><category term='hg'/><category term='stupid python tricks'/><category term='svn'/><title type='text'>Phosphorus and Lime</title><subtitle type='html'>A Developer's Broadsheet</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default?start-index=101&amp;max-results=100'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>283</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-17096219.post-6574162407524368098</id><published>2008-12-30T20:08:00.000-08:00</published><updated>2009-01-01T18:59:59.142-08:00</updated><title type='text'>Farewell</title><content type='html'>In the course of human events, to paraphrase a famous document, it is sometimes necessary to say goodbye.  And I'm saying goodbye to Blogger.  For this blog anyway.  I'm finally moving to WordPress.&lt;br /&gt;&lt;br /&gt;Blogger is a solid platform with many user-friendly (not to mention, spammer-friendly) features.  It has continued to improve steadily since Google acquired it.  But you're still at the mercy of Google's sometimes &lt;a href="http://lastgeist.blogspot.com/search?q=%22Lastgoogle+Blog%22"&gt;inconsistent censorship policies&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Beyond the control it affords the blogging developer, WordPress is a really impressive platform.  It has rich features and, in spite of this, an easy intuitive interface.&lt;br /&gt;&lt;br /&gt;This blog will continue to exist as an archive, so long as Google is gracious enough to host it.  But beginning with the New Year, all futures posts will be posted to my &lt;a href="http://www.klenwell.com/press/"&gt;new Klenwell blog&lt;/a&gt;.  Hope to see you there.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-6574162407524368098?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/6574162407524368098/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=6574162407524368098' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/6574162407524368098'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/6574162407524368098'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2008/12/farewell.html' title='Farewell'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-4228430024562317745</id><published>2008-12-22T19:59:00.000-08:00</published><updated>2009-03-03T21:15:24.609-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='php'/><category scheme='http://www.blogger.com/atom/ns#' term='apache'/><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><title type='text'>PHP4 and PHP5 on the Same Apache Server</title><content type='html'>&lt;div class="updated_post"&gt;This post has been updated.  Please see: &lt;a href="http://www.klenwell.com/press/2009/02/php4-php5-one-server/"&gt;http://www.klenwell.com/press/2009/02/php4-php5-one-server/&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;My goal seemed pretty simple: put PHP4 and PHP5 on my local Apache server so that I can easily test a couple applications that still need to work with PHP4.  This is for Ubuntu.&lt;br /&gt;&lt;br /&gt;I found a pretty good guide here:&lt;br /&gt;&lt;a href="http://www.howtoforge.com/apache2_with_php5_and_php4"&gt;http://www.howtoforge.com/apache2_with_php5_and_php4&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The only problem is that php4-cgi is no longer in the Ubuntu repositories.&lt;br /&gt;&lt;br /&gt;The solution turned out to be pretty easy in the end.  Just add one of the old repositories that still has it to your sources list.  But it took me the better part of an evening to hunt down that solution.&lt;br /&gt;&lt;br /&gt;So here's my step-by-step guide to installing PHP4 to run along side PHP5 on my Apache server on Ubuntu 7.10:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;# add breezy to sources&lt;br /&gt;$ sudo gedit /etc/apt/sources.list&lt;br /&gt;&lt;br /&gt;# added the following lines&lt;br /&gt;deb http://old-releases.ubuntu.com/ubuntu/ breezy-updates main restricted&lt;br /&gt;deb http://old-releases.ubuntu.com/ubuntu/ breezy-security main restricted&lt;br /&gt;deb http://old-releases.ubuntu.com/ubuntu/ breezy main restricted&lt;br /&gt;deb http://old-releases.ubuntu.com/ubuntu/ breezy universe&lt;br /&gt;deb http://old-releases.ubuntu.com/ubuntu/ breezy-security universe&lt;br /&gt;&lt;br /&gt;$ apt-get update&lt;br /&gt;&lt;br /&gt;# back up apache2 config file&lt;br /&gt;$ sudo cp apache2.conf /tmp/apache2.conf&lt;br /&gt;&lt;br /&gt;# install php4-cgi&lt;br /&gt;$ sudo apt-get install php4-cgi&lt;br /&gt;&lt;br /&gt;# install php4 packages&lt;br /&gt;$ sudo apt-get install php4-curl php4-domxml php4-gd php4-imap php4-ldap php4-mcal php4-mcrypt php4-mhash php4-mysql php4-odbc php4-snmp php4-xslt curl libwww-perl imagemagick&lt;br /&gt;&lt;br /&gt;# edit apache2 config&lt;br /&gt;$ /etc/apache2/apache2.conf.&lt;br /&gt;&lt;br /&gt;# replace line:&lt;br /&gt;DirectoryIndex index.html index.cgi index.pl index.php index.xhtml&lt;br /&gt;&lt;br /&gt;# with:&lt;br /&gt;DirectoryIndex index.html index.htm index.shtml index.cgi index.pl index.php index.php4 index.xhtml&lt;br /&gt;&lt;br /&gt;# And add lines:&lt;br /&gt;AddHandler php-script .php4&lt;br /&gt;Action php-script /cgi-bin/php4&lt;br /&gt;&lt;br /&gt;# enable mods and restart&lt;br /&gt;$ sudo a2enmod actions&lt;br /&gt;$ /etc/init.d/apache2 restart&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;If you need to deviate from this, I probably won't be much help.  But I hope it saves someone a little precious time.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-4228430024562317745?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/4228430024562317745/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=4228430024562317745' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/4228430024562317745'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/4228430024562317745'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2008/12/php4-and-php5-on-same-apache-server.html' title='PHP4 and PHP5 on the Same Apache Server'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-3976068245459683212</id><published>2008-11-27T12:29:00.000-08:00</published><updated>2008-11-27T13:04:47.665-08:00</updated><title type='text'>Troubleshooting Your AT&amp;T/Yahoo DSL Connection</title><content type='html'>Once every few months, my internet connection disappears.  I don't have a lot of interest in networking, so it's one of those things I just want to work without thinking about too much and without having to call tech support and go through one of those god-damned automated phone trees.&lt;br /&gt;&lt;br /&gt;Anyway, today was one of those morning.  There was a big thunderstorm last night (rare around here) and the power went out briefly.  So maybe it was connected to that.  Whatever the case, the modem (a Speedstream 4100B) was on, but the internet light was out, like this:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_qkEr9USi0xI/SS8Kc1ReK3I/AAAAAAAAAEg/Z32mSC0hJ3s/s1600-h/modem-dysfunctional.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 277px;" src="http://3.bp.blogspot.com/_qkEr9USi0xI/SS8Kc1ReK3I/AAAAAAAAAEg/Z32mSC0hJ3s/s320/modem-dysfunctional.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5273445179127114610" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;So after calling tech support and taking care notes, this is my new recommended guide to fixing your internet connection yourself.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;1. Login to Modem&lt;/span&gt;&lt;br /&gt;This is what ultimately solved the problem for me this time.  So try this first.  Open a browser, connect to the modem at &lt;a href="http://192.168.0.1/"&gt;http://192.168.0.1/&lt;/a&gt;.  And login with your AT&amp;T or SBC or Yahoo account, or whatever it is.&lt;br /&gt;&lt;br /&gt;According to what the tech told me, when the internet light is out, it means the modem can't connect out to the AT&amp;T upstream node (i.e., the internet) and the likely cause, if the network is up, is that the modem is not providing the proper credential.  Doing this may fix that.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;2. Power Cycle (Reboot)&lt;/span&gt;&lt;br /&gt;Turn off modem&lt;br /&gt;Unplug router*&lt;br /&gt;Turn off computer&lt;br /&gt;-- Wait 30s --&lt;br /&gt;Start modem -&gt; wait 10s&lt;br /&gt;Start router -&gt; wait 10s*&lt;br /&gt;Turn on computer&lt;br /&gt;&lt;small&gt;*If you have a router&lt;/small&gt;&lt;br /&gt;&lt;br /&gt;If either of the above succeeds, your modem should now look like this:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_qkEr9USi0xI/SS8KoOoZR0I/AAAAAAAAAEo/ThbBxhaoGwI/s1600-h/modem-functional.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 277px;" src="http://3.bp.blogspot.com/_qkEr9USi0xI/SS8KoOoZR0I/AAAAAAAAAEo/ThbBxhaoGwI/s320/modem-functional.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5273445374912710466" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;If not, proceed to step 3:&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;3. Call AT&amp;T Tech Support&lt;/span&gt;&lt;br /&gt;1-877-722-3755&lt;br /&gt;&lt;br /&gt;Good luck!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-3976068245459683212?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/3976068245459683212/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=3976068245459683212' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/3976068245459683212'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/3976068245459683212'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2008/11/troubleshooting-your-at-dsl-connection.html' title='Troubleshooting Your AT&amp;T/Yahoo DSL Connection'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_qkEr9USi0xI/SS8Kc1ReK3I/AAAAAAAAAEg/Z32mSC0hJ3s/s72-c/modem-dysfunctional.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-1405451955758158215</id><published>2008-10-17T21:43:00.000-07:00</published><updated>2008-10-18T11:40:25.416-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cakephp'/><title type='text'>Creating Custom Behaviors in CakePHP</title><content type='html'>The CakePHP manual leaves a lot to be desired on &lt;a href="http://book.cakephp.org/view/595/Creating-Custom-Behaviors"&gt;this topic&lt;/a&gt;.  Here's one important tip that I couldn't find mentioned on the site:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Every method in your behavior class must have a reference to the model passed as its first argument.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Another tip:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;If calling another method from within your behavior class, you must include the model reference as your first argument.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I've added a gratuitous example to the test method below.&lt;br /&gt;&lt;br /&gt;A simple behavior class that can be used as a template:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&amp;lt;?php&lt;br /&gt;&lt;br /&gt;class NormalizerBehavior extends ModelBehavior {  &lt;br /&gt;    &lt;br /&gt;    public $name = 'Normalizer';    &lt;br /&gt;    &lt;br /&gt;    /*&lt;br /&gt;        Initiate behaviour for the model using specified settings.&lt;br /&gt;     */&lt;br /&gt;    function setup(&amp;$Model, $settings = array())&lt;br /&gt;    {&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    /*&lt;br /&gt;        Run before a model is saved.&lt;br /&gt;     */&lt;br /&gt;    function beforeSave(&amp;$Model)&lt;br /&gt;    {&lt;br /&gt;    }&lt;br /&gt;   &lt;br /&gt;    &lt;br /&gt;    function normalize_date(&amp;$Model, $date_str)&lt;br /&gt;    {&lt;br /&gt;        return date('Y-m-d', strtotime(trim($date_str)));&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;&lt;br /&gt;    function test(&amp;$Model) &lt;br /&gt;    {&lt;br /&gt;        $date = $this-&amp;gt;normalize_date($Model, date('Y-m-d'));&lt;br /&gt;        printf('testing behavior %s for model %s on %s', __CLASS__, $Model-&amp;gt;name, $date);&lt;br /&gt;    } &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;?&amp;gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;If I discover any other noteworthy tips, I'll add them here.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-1405451955758158215?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/1405451955758158215/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=1405451955758158215' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/1405451955758158215'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/1405451955758158215'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2008/10/creating-custom-behaviors-in-cakephp.html' title='Creating Custom Behaviors in CakePHP'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-2708616839622507148</id><published>2008-10-17T20:24:00.000-07:00</published><updated>2008-10-17T21:48:57.905-07:00</updated><title type='text'>A Better Turing Machine</title><content type='html'>Slashdot reported &lt;a href="http://tech.slashdot.org/article.pl?sid=08/10/13/1450205"&gt;the results of this year's Loebner Turing Tournament&lt;/a&gt;.  There's a $100k for whomever can write a chatbot that fools 30% of human interacting with it that it's a human at a keyboard somewhere and not a program.  Apparently, one team fooled 25% of the judges.&lt;br /&gt;&lt;br /&gt;Slashdot commentors were quick to pounce on the judging and show up online versions of the contestants.  &lt;a href="http://tech.slashdot.org/comments.pl?sid=993861&amp;cid=25357087"&gt;One comment&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;It took me three questions before Elbot replied with a non sequitur and about five minutes before it started repeating answers. It didn't take me long to realise that it had no concept of context - every reply was a reply to what I had just said, and had no relation to the last-but-one thing I'd said. Some things that tripped it up:&lt;br /&gt;&lt;br /&gt;    * Asking 'why?' about anything.&lt;br /&gt;    * Trying to teach it a new word.&lt;br /&gt;    * Asking it the square root of minus two (odd, since last year one of the judges asked questions like this to all of the bots).&lt;br /&gt;    * Anything about religion.&lt;br /&gt;&lt;br /&gt;That 25% of the judges thought it was human is quite alarming.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Fair enough.  But imagine now if you adopted the premise that half the people you engage with on a daily basis are nothing more than scripted chatbots covered in meat.  If you made it your mission to figure out who were the bots and who the humans, you'd alienate most the humans pretty quickly.&lt;br /&gt;&lt;br /&gt;Which suggests that the most convincing feature a chatbot might have is a well-scripted sense of personal insult or irritation.  Things like:&lt;br /&gt;&lt;br /&gt;"Dude, what the hell are you talking about?"&lt;br /&gt;&lt;br /&gt;Or:&lt;br /&gt;&lt;br /&gt;"Why the fuck are you asking me?"&lt;br /&gt;&lt;br /&gt;In fact, I wouldn't be surprised if that wasn't the secret ingredient in some of the more successful contestants.  (That, and the careful distribution of typos and misspellings.)  Nor would I be surprised if it's a feature they turn off in the online non-competitive version of their bots.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-2708616839622507148?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/2708616839622507148/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=2708616839622507148' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/2708616839622507148'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/2708616839622507148'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2008/10/better-turing-machine.html' title='A Better Turing Machine'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-3897616892282420668</id><published>2008-10-14T20:23:00.000-07:00</published><updated>2008-10-14T20:28:11.335-07:00</updated><title type='text'>NoScript Full Steam Ahead</title><content type='html'>After reading &lt;a href="http://yro.slashdot.org/article.pl?sid=08/10/14/1656251"&gt;this article&lt;/a&gt; on slashdot today, I visited &lt;a href="http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager07.html"&gt;the Adobe site&lt;/a&gt;, purged my Flash cookies, and set &lt;a href="http://noscript.net/"&gt;NoScript&lt;/a&gt; to full power.  A friend at work had warned me about the Flash hole a while back, but this article finally got me off my ass.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-3897616892282420668?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/3897616892282420668/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=3897616892282420668' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/3897616892282420668'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/3897616892282420668'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2008/10/noscript-full-steam-ahead.html' title='NoScript Full Steam Ahead'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-4059288603145672476</id><published>2008-10-09T21:30:00.000-07:00</published><updated>2008-10-09T21:40:55.665-07:00</updated><title type='text'>Sonnet Monkey (alpha)</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.sonnetmonkey.com/"&gt;&lt;img style="cursor:pointer; cursor:hand; float:left; margin-right:16px;" src="http://2.bp.blogspot.com/_qkEr9USi0xI/SO7bewou71I/AAAAAAAAAD0/AHdnm9rzK3A/s320/sm.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5255379136686255954" /&gt;&lt;/a&gt;&lt;br /&gt;A project I've been tinkering with for a couple years now.  I've released working versions before (and the &lt;a href="http://milf.sonnetmonkey.com/"&gt;MILF&lt;/a&gt; was released earlier this year).  But I recently refactored the javascript interface and reframed the presentation with cakephp.  This is the first version approaching stability.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.sonnetmonkey.com/"&gt;www.sonnetmonkey.com&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;There's even a &lt;a href="https://twitter.com/chimpinson"&gt;Twitter stream&lt;/a&gt;, if that's your sort of thing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-4059288603145672476?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/4059288603145672476/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=4059288603145672476' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/4059288603145672476'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/4059288603145672476'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2008/10/sonnet-monkey-alpha.html' title='Sonnet Monkey (alpha)'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_qkEr9USi0xI/SO7bewou71I/AAAAAAAAAD0/AHdnm9rzK3A/s72-c/sm.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-1727668891519247722</id><published>2008-09-10T19:29:00.001-07:00</published><updated>2008-09-10T19:49:15.401-07:00</updated><title type='text'>The Shepherds Comical</title><content type='html'>Recently developed the website for &lt;a href="http://www.shepherdscomical.com/"&gt;this webcomic&lt;/a&gt;, the first Elizabethan-themed comic strip I've seen.  The emphasis was on simple and straightforward with a couple minor tricks behind the scene.  My favorite strip from the site (notice the headlines on the cover):&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.shepherdscomical.com/leaf/1220511600/"&gt;&lt;!-- http://3.bp.blogspot.com/_qkEr9USi0xI/SMiDxuLO33I/AAAAAAAAADk/gAxnDcg6Qy8/s1600-h/o4_08_democracy.png --&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_qkEr9USi0xI/SMiETdjbUQI/AAAAAAAAADs/FFk1QFt_XJU/s320/o4_05_qmagazine.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5244587235958542594" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;(click image to see full-size strip at site)&lt;br /&gt;&lt;br /&gt;I was wondering if there was a semantic web RDF standard for web comics.  I'm thinking about implementing some semantic web-friendly markup for the strips.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-1727668891519247722?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/1727668891519247722/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=1727668891519247722' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/1727668891519247722'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/1727668891519247722'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2008/09/shepherds-comical.html' title='The Shepherds Comical'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_qkEr9USi0xI/SMiETdjbUQI/AAAAAAAAADs/FFk1QFt_XJU/s72-c/o4_05_qmagazine.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-6772994437999439314</id><published>2008-08-09T11:46:00.000-07:00</published><updated>2008-08-09T12:00:55.088-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><title type='text'>JS: Cursor Manipulation</title><content type='html'>Some code I wrote a while back (well, collated is probably the more apt term) to simplify selecting text, unselecting text, and placing the cursor using javascript. &lt;tt&gt;&lt;a href="http://phosphorusandlime.blogspot.com/2008/07/javascript-logger.html"&gt;l&lt;/a&gt;&lt;/tt&gt; is a shortcut for console.log.&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;/* Class: TheDom&lt;br /&gt;  Class to manage the manipulation and output of assorted DOM and DOM-related&lt;br /&gt;  elements.  Most methods are offered as static methods.&lt;br /&gt;  &lt;br /&gt;  Methods:&lt;br /&gt;  TheDom.getSelectedText(el)&lt;br /&gt;  TheDom.selectRange(el, p1, p2)&lt;br /&gt;  TheDom.placeCursor(el, pos)&lt;br /&gt;  TheDom.insertString(insert, wrapper, pt1, pt2)&lt;br /&gt;  TheDom.wrapInTag(text, tag, id, class, style)&lt;br /&gt;*/&lt;br /&gt;var TheDom = {};&lt;br /&gt;&lt;br /&gt;// arguments: el (DOM element)&lt;br /&gt;TheDom.getSelectedText = function(el)&lt;br /&gt;{&lt;br /&gt;  selected = [false, 0, 0];   // returns array: [ selected text, start_pos, end_pos ]&lt;br /&gt;  l('getSelectedText from DOM [type,id]:', el.tagName, ',', el.id );&lt;br /&gt;  &lt;br /&gt;  // get start/end&lt;br /&gt;  var s1 = 0; var s2 = 0;&lt;br /&gt;  if ( typeof document.selection != 'undefined' )&lt;br /&gt;  {&lt;br /&gt;    var r = document.selection.createRange();&lt;br /&gt;    s1 = r.start;&lt;br /&gt;    s2 = r.end;&lt;br /&gt;  }&lt;br /&gt;  else if ( typeof el.selectionStart != 'undefined' )&lt;br /&gt;  {&lt;br /&gt;    s1 = el.selectionStart;&lt;br /&gt;    s2 = el.selectionEnd;&lt;br /&gt;  }&lt;br /&gt;  else&lt;br /&gt;  {&lt;br /&gt;    l('getSelectedText handle not found');&lt;br /&gt;    return selected;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  // trim selection&lt;br /&gt;  while ( s2 &amp;lt; s1 &amp;&amp; el.value.charAt(s2-1) == ' ' ) s2--;&lt;br /&gt;&lt;br /&gt;  // no selection  &lt;br /&gt;  if ( s2 - s1 == 0 ) sel_text = '';&lt;br /&gt;  if ( s2 - s1 &amp;gt; 0 ) return selected;&lt;br /&gt;  &lt;br /&gt;  sel_text = el.value.substring(s1, s2);&lt;br /&gt;  l('getSelectedText returning:', sel_text, s1, s2);&lt;br /&gt;  return [sel_text, s1, s2];&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;// arguments: el [DOM element], p1 [int], p2 [int] &lt;br /&gt;TheDom.selectRange = function(el, p1, p2)&lt;br /&gt;{&lt;br /&gt;  // return void&lt;br /&gt;  l('selectRange:', el, p1, p2);&lt;br /&gt;  &lt;br /&gt;  if(el.setSelectionRange) &lt;br /&gt;  {&lt;br /&gt;    el.focus();&lt;br /&gt;    el.setSelectionRange(p1,p2);&lt;br /&gt;  }&lt;br /&gt;  else if(el.createTextRange)&lt;br /&gt;  {&lt;br /&gt;    range=el.createTextRange();&lt;br /&gt;    range.collapse(true);&lt;br /&gt;    range.moveEnd('character',p2);&lt;br /&gt;    range.moveStart('character',p1);&lt;br /&gt;    range.select();&lt;br /&gt;  }&lt;br /&gt;  else&lt;br /&gt;  {&lt;br /&gt;    l('selectRange: no selection handle');&lt;br /&gt;  }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;// arguments: el [DOM object], pos [int]&lt;br /&gt;TheDom.placeCursor = function(el, pos)&lt;br /&gt;{&lt;br /&gt;  l('placeCursor:',el.id, pos);&lt;br /&gt;  TheDom.selectRange(el, pos, pos);&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;// arguments: insert [string], wrapper [string], pt1 [int], pt2 [int]&lt;br /&gt;TheDom.insertString = function(insert, wrapper, pt1, pt2)&lt;br /&gt;{&lt;br /&gt;  var new_test = '';    // return&lt;br /&gt;  l('insertString:', insert, wrapper, pt1, pt2);&lt;br /&gt;  if ( pt2 == undefined ) pt2 = pt1;&lt;br /&gt;  new_text = wrapper.substring(0, pt1) + insert + wrapper.substr(pt2);&lt;br /&gt;  return new_text;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;// arguments: text, tag name, [tag id, class, style] [str]&lt;br /&gt;TheDom.wrapInTag = function(text, tag, id, class, style)&lt;br /&gt;{&lt;br /&gt;  var wrap = '';    // return&lt;br /&gt;  l('wrapInTag:', text, tag, id, class, style);&lt;br /&gt;  var id = ( id != undefined ) ? ' id="'+id+'"' : '';&lt;br /&gt;  var class = ( class != undefined ) ? ' class="'+class+'"' : '';&lt;br /&gt;  var style = ( style != undefined ) ? ' id="'+style+'"' : '';&lt;br /&gt;  var t1 = '&amp;gt;' + tag + id + class + style + '&amp;lt;';&lt;br /&gt;  var t2 = '&amp;lt;/' + tag + '&amp;lt;';&lt;br /&gt;  wrap = t1 + text + t2;&lt;br /&gt;  l('wrapInTag return:', wrap);&lt;br /&gt;  return wrap;&lt;br /&gt;};&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-6772994437999439314?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/6772994437999439314/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=6772994437999439314' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/6772994437999439314'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/6772994437999439314'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2008/08/js-cursor-manipulation.html' title='JS: Cursor Manipulation'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-5223400215188409034</id><published>2008-07-19T11:08:00.000-07:00</published><updated>2008-07-19T11:10:40.834-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><title type='text'>JS: Firebug Lite</title><content type='html'>As a follow-up to my last post, I was poking around the Firebug site and discovered this: &lt;a href="http://getfirebug.com/lite.html"&gt;Firebug Lite&lt;/a&gt;.  A version of Firebug for IE.  Cool!&lt;br /&gt;&lt;br /&gt;More info: &lt;a href="http://getfirebug.com/lite.html"&gt;http://getfirebug.com/lite.html&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-5223400215188409034?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/5223400215188409034/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=5223400215188409034' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/5223400215188409034'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/5223400215188409034'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2008/07/js-firebug-lite.html' title='JS: Firebug Lite'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-8770819161183401999</id><published>2008-07-19T10:30:00.000-07:00</published><updated>2008-07-23T20:12:10.785-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><title type='text'>Javascript Logger</title><content type='html'>As every developer knows, one of the killer extensions for &lt;a href="http://www.mozilla.com/en-US/firefox/"&gt;Firefox&lt;/a&gt; is &lt;a href="http://getfirebug.com/"&gt;Firebug&lt;/a&gt;.  And I was using it for months (years?) before I discovered one of its coolest features: &lt;a href="http://getfirebug.com/console.html"&gt;console.log&lt;/a&gt;.  It's a simple method that allows you to send your own output to the Firebug console.&lt;br /&gt;&lt;br /&gt;This was one of those little things that changed my life.  What an improvement over the old alert function.  I told all my friends, all co-workers.  I was a console.log evangelist.&lt;br /&gt;&lt;br /&gt;One problem -- the obvious one: Internet Explorer.  It doesn't have Firebug.  It doesn't know what a console object is.  So if you want to use this, you have to figure out how get IE to ignore, else you get errors.&lt;br /&gt;&lt;br /&gt;Anyway, that is what the logger class below does.  It logs messages to the Firebug console.  Its major feature is doing this transparently.  You can also set the pop_interval value so that, in Firebug-less browsers, an alert message will pop up every one in a while dumping the complete log contents.  (Probably could be a problem if it gets too long, but I'll worry about that in the future.)&lt;br /&gt;&lt;br /&gt;Now, without further ado, the class:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;/***  DOCUMENTATION LAYER&lt;br /&gt;&lt;br /&gt;  Javascript Logger&lt;br /&gt;  Author: Tom at klenwell@gmail.com&lt;br /&gt;  License: LGPL License&lt;br /&gt;&lt;br /&gt;______________________________________________________________________________*/&lt;br /&gt;&lt;br /&gt;var NBSP = ' ', DEBUG = 1, INFO = 2;&lt;br /&gt;var Logger = Class.create({&lt;br /&gt;    &lt;br /&gt;    /* Javascript Logger&lt;br /&gt;      There are probably better versions out there, but this is my own.  Its&lt;br /&gt;      most significant feature is that it determines whether Firebug is loaded&lt;br /&gt;      or not and adjusts its output accordingly.&lt;br /&gt;    */&lt;br /&gt;    &lt;br /&gt;    levelTag        : ['', 'DEBUG', 'INFO'],&lt;br /&gt;    has_firebug     : false,&lt;br /&gt;    Journal         : [],&lt;br /&gt;    pop_interval    : 5,    // when firebug absent, how often we want to dump an alert&lt;br /&gt;    max_pop_length  : 20,   // when firebug absent, max length of items in pop-up window&lt;br /&gt;    &lt;br /&gt;    initialize: function(level)&lt;br /&gt;    {&lt;br /&gt;        if ( level == null ) this.level == DEBUG;&lt;br /&gt;        this.has_firebug = this.is_firebug_installed();&lt;br /&gt;        this.debug("has_firebug:", this.has_firebug);&lt;br /&gt;    },&lt;br /&gt;    &lt;br /&gt;    _log: function(lvl, msg)&lt;br /&gt;    {&lt;br /&gt;        if ( this.level &lt; lvl ) return;&lt;br /&gt;        timestamp = '[' + this.now().toString() + ']';&lt;br /&gt;        level = this.levelTag[lvl] + ' &gt;&gt;&gt;';&lt;br /&gt;        this.log(timestamp + NBSP + level + NBSP + msg);&lt;br /&gt;    },&lt;br /&gt;    &lt;br /&gt;    log: function(message)&lt;br /&gt;    {&lt;br /&gt;        this.Journal.push(message);&lt;br /&gt;        if ( !this.has_firebug )&lt;br /&gt;        {&lt;br /&gt;            if ( !(this.Journal.length % this.pop_interval) )&lt;br /&gt;            {&lt;br /&gt;                this.alert(this.Journal.join("\n"));&lt;br /&gt;                if ( this.Journal.length &gt; this.max_pop_length )&lt;br /&gt;                {&lt;br /&gt;                    this.Journal.splice(0, Math.ceil(this.max_pop_length / 4))&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;            return;&lt;br /&gt;        }&lt;br /&gt;        console.log(message);&lt;br /&gt;    },&lt;br /&gt;    &lt;br /&gt;    debug: function()&lt;br /&gt;    {&lt;br /&gt;        var msg='';&lt;br /&gt;        for (i=0; i &lt; arguments.length; i++) { msg+=arguments[i]+' '; }&lt;br /&gt;        this._log(DEBUG, msg);&lt;br /&gt;    },&lt;br /&gt;    &lt;br /&gt;    info: function()&lt;br /&gt;    {&lt;br /&gt;        var msg='';&lt;br /&gt;        for (i=0; i &lt; arguments.length; i++) { msg+=arguments[i]+' '; }&lt;br /&gt;        this._log(INFO, msg);&lt;br /&gt;    },&lt;br /&gt;    &lt;br /&gt;    is_firebug_installed: function() { return ! eval('typeof(console)=="undefined"'); },&lt;br /&gt;    now: function() { D = new Date(); return D.toLocaleTimeString() + ':' + D.getMilliseconds().toString(); },&lt;br /&gt;    t: function(t0) { return ( ( new Date() ) - t0 ) / 1000; },&lt;br /&gt;    alert: function(msg) { alert(msg); }&lt;br /&gt;});&lt;br /&gt;&lt;br /&gt;GlobalLogger = new Logger(INFO);&lt;br /&gt;function l() { GlobalLogger.debug($A(arguments).join(' ')); }&lt;br /&gt;l("Logger loaded");&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Usage:&lt;br /&gt;&lt;div class="code"&gt;    Logger = new Logger();&lt;br /&gt;    Logger.pop_interval = 3;&lt;br /&gt;    Logger.log('a log message');&lt;br /&gt;    Logger.debug('a debug message');&lt;br /&gt;    Logger.info('an info message');&lt;br /&gt;    Logger.info('if no firebug, we should put up an alert now');&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;This has been tested successfully on IE6 and, of course, Firefox.  It does require the &lt;a href="http://www.prototypejs.org/api"&gt;prototypejs library&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-8770819161183401999?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/8770819161183401999/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=8770819161183401999' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/8770819161183401999'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/8770819161183401999'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2008/07/javascript-logger.html' title='Javascript Logger'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-8091706904098417474</id><published>2008-06-02T19:18:00.000-07:00</published><updated>2008-08-03T14:19:12.377-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='stupid python tricks'/><title type='text'>A Pythonic Tribute to xkcd</title><content type='html'>This started with a simple question: "is it possible to call isset($foo) in python like in php?"  This is probably going about it ass-backwards, or at least it's asking &lt;a href="http://mail.python.org/pipermail/python-list/2005-June/328228.html"&gt;the wrong question&lt;/a&gt;.  But then genius of this magnitude doesn't arise from asking the right question.&lt;br /&gt;&lt;br /&gt;In the end, I had an answer to my question.  I had, perhaps, the stupidest &lt;a href="http://www.p-nand-q.com/python/stupid_lambda_tricks.html"&gt;stupid lambda trick&lt;/a&gt; ever.  And I had a loving pythonic tribute to &lt;a href="http://xkcd.com/"&gt;xkcd&lt;/a&gt; (for a loving xkcd tribute to python, &lt;a href="http://xkcd.com/353/"&gt;click here&lt;/a&gt;):&lt;br /&gt;&lt;br /&gt;&lt;div class="code" style="overflow-x:auto;font-size:12px;"&gt;#!/usr/bin/python&lt;br /&gt;&lt;br /&gt;"""&lt;br /&gt;a pythonic tribute to xkcd&lt;br /&gt;http://phosphorusandlime.blogspot.com/2008/06/pythonic-tribute-to-xkcd.html&lt;br /&gt;"""&lt;br /&gt;&lt;br /&gt;xkcd = lambda x,k,c,d: (({k:False},c,d,c)[int(''.join([str(int(k in i)) for i in [d,c]]),2)])[k] or x&lt;br /&gt;&lt;br /&gt;X = 'webcomic'&lt;br /&gt;K = 'romance'&lt;br /&gt;C = {'romance': 'at last!', 'sarcasm':'grep -R soulmate /'}&lt;br /&gt;D = {'math':complex(6,9j), 'language':'to be or not to be'}&lt;br /&gt;&lt;br /&gt;print xkcd(X,'language',C,D)&lt;br /&gt;print xkcd(X,'math',{'math':1+1},D)&lt;br /&gt;print xkcd(X,'microsoft',C,D)&lt;br /&gt;print xkcd(X,K,C,D)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;# Alternate version&lt;br /&gt;xkcd = lambda x,k,c,d: c.get(k,d.get(k,x))&lt;br /&gt;print xkcd(X,'language',C,D)&lt;br /&gt;print xkcd(X,'math',{'math':1+1},D)&lt;br /&gt;print xkcd(X,'microsoft',C,D)&lt;br /&gt;print xkcd(X,K,C,D)&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;There are a couple moments of sheer pythonic bliss in there if you pay attention.&lt;br /&gt;&lt;br /&gt;Still haven't figured out what it does?  Here's a hint:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&amp;lt;?php print $x = ( isset($C[$k]) ) ? $C[$k] : ( isset($D[$k]) ? $D[$k] : $x); ?&amp;gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;update&lt;/b&gt;: added extra c for case where both dicts contain key as pointed out &lt;a href="http://forums.xkcd.com/viewtopic.php?f=11&amp;t=23249#p693676"&gt;here&lt;/a&gt; and added test case&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-8091706904098417474?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/8091706904098417474/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=8091706904098417474' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/8091706904098417474'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/8091706904098417474'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2008/06/pythonic-tribute-to-xkcd.html' title='A Pythonic Tribute to xkcd'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-3781131745381052886</id><published>2008-05-17T18:17:00.000-07:00</published><updated>2008-05-18T20:36:15.029-07:00</updated><title type='text'>Google App Engine</title><content type='html'>I got my Google App Engine invite a couple weeks ago but didn't have a chance to really play with it until this weekend.  I built a couple little demos on my sandbox app today:&lt;br /&gt;&lt;br /&gt;I have to say I'm very impressed with it thus far.  I can see how this could be truly revolutionary.   Indeed, this is just the tool I've been looking for for the past, what, four years.  The things I really like about it:&lt;br /&gt;&lt;a href="http://kwap.appspot.com/"&gt;&lt;br /&gt;http://kwap.appspot.com/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;1. It uses &lt;a href="http://www.python.org/"&gt;Python&lt;/a&gt;&lt;br /&gt;2. Simple &lt;a href="http://kwap.appspot.com/introspect"&gt;mvc organization&lt;/a&gt; using the Google webapp framework&lt;br /&gt;3. Easy to move between test and production environments&lt;br /&gt;4. It's designed to be scalable&lt;br /&gt;5. It's free&lt;br /&gt;&lt;br /&gt;Downsides?  The big one I keep reading about is the datastore, which uses an &lt;a href="http://en.wikipedia.org/wiki/Object-relational_mapping"&gt;ORM&lt;/a&gt; model rather than the more familiar SQL relational.  I haven't found the adjustment that hard at all, but then I've never fancied myself a DBA wizard and my usage of the datastore thus far has been trivial.&lt;br /&gt;&lt;br /&gt;But believe me, I have big plans for the future!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-3781131745381052886?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/3781131745381052886/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=3781131745381052886' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/3781131745381052886'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/3781131745381052886'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2008/05/google-app-engine.html' title='Google App Engine'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-212038321886989402</id><published>2008-05-10T13:11:00.000-07:00</published><updated>2008-05-10T13:14:10.556-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='design'/><title type='text'>The Perfect Heart Shape</title><content type='html'>If not perfect, symmetrical at least.  The graphic below says it all:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_qkEr9USi0xI/SCYB3Bg4tEI/AAAAAAAAADc/R4Pe4tFlrlc/s1600-h/perfect_heart.png"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_qkEr9USi0xI/SCYB3Bg4tEI/AAAAAAAAADc/R4Pe4tFlrlc/s320/perfect_heart.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5198844864656618562" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;From here, it just a matter of tweaking with your favorite vector editor.&lt;br /&gt;&lt;br /&gt;Got this from an old cookbook recipe for heart-shaped cakes.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-212038321886989402?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/212038321886989402/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=212038321886989402' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/212038321886989402'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/212038321886989402'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2008/05/perfect-heart-shape.html' title='The Perfect Heart Shape'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_qkEr9USi0xI/SCYB3Bg4tEI/AAAAAAAAADc/R4Pe4tFlrlc/s72-c/perfect_heart.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-8132202176769348114</id><published>2008-05-03T10:56:00.000-07:00</published><updated>2010-05-13T23:08:51.197-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><title type='text'>Ubuntu: Command Line Email</title><content type='html'>&lt;div class="updated_post"&gt;For a simpler, updated version of this guide, please see: &lt;a href="http://klenwell.com/is/UbuntuCommandLineGmail"&gt;http://klenwell.com/is/UbuntuCommandLineGmail&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;problem&lt;/h4&gt;I want to send email using the command line on my laptop Ubuntu system.  Mainly for cron jobs and automated backups.  I want to be able to do so without having to set up a full-fledged MTA like sendmail or exim.  And I want to be able to use either my ISP email account or a Gmail account. &lt;br /&gt;&lt;br /&gt;Seemed simple enough and it probably is for people who do this type of thing for a living.  Took me all night.  So hopefully this will save someone else (perhaps me again in the future) hours of unnecessary frustration.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;solution&lt;/h4&gt;First, look at &lt;a href="http://en.wikipedia.org/wiki/Email#Workings"&gt;this diagram from Wikipedia&lt;/a&gt;.  Without being able to find a simple step-by-step tutorial to guide me, the biggest problem I was having was sorting out what was my &lt;a href="http://en.wikipedia.org/wiki/E-mail_client"&gt;MUA&lt;/a&gt;, what was my &lt;a href="http://en.wikipedia.org/wiki/Mail_transfer_agent"&gt;MTA&lt;/a&gt;, and what if anything I needed to connect the two.  Long story short, they are as follows:&lt;br /&gt;&lt;br /&gt;MUA (the client): nail (you can also use mailx or mutt or even evolution)&lt;br /&gt;MTA (the mail server): your isp or gmail&lt;br /&gt;MSA (smtp middle man): msmtp (a simple MTA that gets mail from your client to your real MTA or mailhub)&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;step-by-step&lt;/h4&gt;&lt;h5&gt;Install the needed programs&lt;/h5&gt;&lt;div class="code"&gt;$ sudo apt-get install msmtp&lt;br /&gt;$ sudo apt-get install nail&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;h5&gt;Install Thawte certificate for Gmail&lt;/h5&gt;This is necessary (I think) for Gmail.  Probably the most complicated step, though not too bad thanks to instructions &lt;a href="http://laurentbois.com/2007/10/20/activemailer-using-msmtp-and-gmail/"&gt;here&lt;/a&gt;:&lt;br /&gt;&lt;div class="code"&gt;$ mkdir -p ~/etc/.certs&lt;br /&gt;$ chmod 0700 ~/etc/.certs&lt;br /&gt;$ cd ~/etc/.certs&lt;br /&gt;$ wget https://www.verisign.com/support/thawte-roots.zip --no-check-certificate&lt;br /&gt;$ unzip thawte-roots.zip&lt;br /&gt;$ cp Thawte\ Server\ Roots/ThawtePremiumServerCA_b64.txt ThawtePremiumServerCA.crt&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;h5&gt;Configure msmtp&lt;/h5&gt;Replace UPPERCASE text with your personal settings&lt;br /&gt;&lt;div class="code"&gt;$ gedit ~/.msmtprc&lt;/div&gt;&lt;br /&gt;This will open up an msmtp configuration file where you'll want to copy the following lines, with your correct settings, of course:&lt;br /&gt;&lt;div class="ipod"&gt;# config options: http://msmtp.sourceforge.net/doc/msmtp.html#A-user-configuration-file&lt;br /&gt;defaults&lt;br /&gt;logfile /tmp/msmtp.log&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;# isp account&lt;br /&gt;account isp&lt;br /&gt;auth login&lt;br /&gt;host SMTP.YOURISP.COM&lt;br /&gt;port 25&lt;br /&gt;user YOURNAME@ISP.COM&lt;br /&gt;from YOURNAME@ISP.COM&lt;br /&gt;password *****&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;# gmail account&lt;br /&gt;account gmail&lt;br /&gt;auth on&lt;br /&gt;host smtp.gmail.com&lt;br /&gt;port 587&lt;br /&gt;user YOURNAME@gmail.com&lt;br /&gt;password *****&lt;br /&gt;from YOURNAME@gmail.com&lt;br /&gt;tls on&lt;br /&gt;tls_trust_file /home/USER/etc/.certs/ThawtePremiumServerCA.crt&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;# set default account to use (from above)&lt;br /&gt;account default : isp&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Change permission on this file or msmtp will complain:&lt;br /&gt;&lt;div class="code"&gt;$ chmod 600 ~/.msmtprc&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;h5&gt;Configure nail&lt;/h5&gt;&lt;div class="code"&gt;$ gedit ~/.mailrc&lt;/div&gt;&lt;br /&gt;The key line below is "set message-sendmail-extra-arguments".  It seemed like I should have been able to add this to the set sendmail command.  Suffice to say, not well documented.&lt;br /&gt;&lt;div class="ipod"&gt;# set smtp for nail&lt;br /&gt;# ref: http://ubuntuforums.org/showpost.php?p=4531994&amp;postcount=6&lt;br /&gt;# docs: http://msmtp.sourceforge.net/doc/msmtp.html#Configuration-files&lt;br /&gt;&lt;br /&gt;# isp account (default)&lt;br /&gt;# $ nail -s "subject line" -a /path/file recipient@email.com &lt; /path/body.txt&lt;br /&gt;set from="YOURNAME@ISP.COM"&lt;br /&gt;set sendmail="/usr/bin/msmtp"&lt;br /&gt;set message-sendmail-extra-arguments="-a isp"&lt;br /&gt;&lt;br /&gt;# gmail account &lt;br /&gt;# $ nail -A gmail -s "subject line" -a /path/file recipient@email.com &lt; /path/body.txt&lt;br /&gt;account gmail {&lt;br /&gt;  set from="YOURNAME@gmail.com (YOURNAME)"&lt;br /&gt;  set sendmail="/usr/bin/msmtp"&lt;br /&gt;  set message-sendmail-extra-arguments="-a gmail"&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;h5&gt;Send test messages for both accounts&lt;/h5&gt;&lt;br /&gt;&lt;div class="code"&gt;$ echo -e "testing email from the command line" &gt; /tmp/test_email&lt;br /&gt;$ nail -s "isp test" YOURNAME@gmail.com &lt; /tmp/test_email&lt;br /&gt;$ nail -A gmail -s "gmail test" YOURNAME@gmail.com &lt; /tmp/test_email&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Check your gmail account and you should have two new messages -- one from that account and one from your ISP account.  To check your log:&lt;br /&gt;&lt;div class="code"&gt;$ gedit /tmp/msmtp.log&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Conclusion&lt;/h4&gt;Only took me all Friday night to figure this out.  But, hey, better than getting drunk, stoned, and laid. :)&lt;br /&gt;&lt;br /&gt;I've added this post to ubuntuforums.org: &lt;a href="http://ubuntuforums.org/showthread.php?t=780509"&gt;http://ubuntuforums.org/showthread.php?t=780509&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-8132202176769348114?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/8132202176769348114/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=8132202176769348114' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/8132202176769348114'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/8132202176769348114'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2008/05/ubuntu-command-line-email.html' title='Ubuntu: Command Line Email'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-5091041676244200024</id><published>2008-05-01T21:19:00.001-07:00</published><updated>2008-05-01T21:25:24.255-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='hg'/><title type='text'>Removing a File from a Hg Repository</title><content type='html'>Removing a file from a mercurial repository without deleting it: &lt;code&gt;&lt;span style="font-weight:bold;"&gt;hg rm -A&lt;/span&gt;&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Example:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;hg rm -A dir/*&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;I think this works.  The docs aren't exactly clear on the point:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.selenic.com/pipermail/mercurial/2007-April/012917.html"&gt;http://www.selenic.com/pipermail/mercurial/2007-April/012917.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;If you use &lt;code&gt;hg rm file&lt;/code&gt;, it just deletes the file.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-5091041676244200024?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/5091041676244200024/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=5091041676244200024' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/5091041676244200024'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/5091041676244200024'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2008/05/removing-file-from-hg-repository.html' title='Removing a File from a Hg Repository'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-5895891714511258669</id><published>2008-04-27T17:00:00.000-07:00</published><updated>2008-04-27T17:11:57.118-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>PHP str_to_word Challenge</title><content type='html'>This is the challenge I faced: tokenize a string into words.  Easy enough you say, just use one of the many built-in PHP functions, like str_count_words().  But now, do it successfully with a string like this:&lt;br /&gt;&lt;br /&gt;&lt;div class="ipod"&gt;I 'said', "This   is  my test's   string of over '8.8' words.About 16 to   be  ex-act!"&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;I think I've found the solution:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;function str_to_words($str)&lt;br /&gt;{&lt;br /&gt;  $re = '%[^A-Za-z0-9\-\'\.]+|([A-Za-z]+)\.([A-Za-z]+)%';&lt;br /&gt;  $CHR = str_split('abcdefghijklmnopqrstuvwxyz0123456789');&lt;br /&gt;  $W = preg_split($re, $str, -1, PREG_SPLIT_NO_EMPTY|PREG_SPLIT_DELIM_CAPTURE);&lt;br /&gt;  &lt;br /&gt;  // make sure first and last characters are alphanumeric&lt;br /&gt;  // do we sacrifice ' in plural possessive (e.g. the girls' toys)? no&lt;br /&gt;  foreach ( $W as $w0 )&lt;br /&gt;  {&lt;br /&gt;    $w1 = ( !in_array(strtolower(substr($w0,0,1)),$CHR) ) ? substr($w0,1) : $w0;&lt;br /&gt;    $w1 = ( !in_array(strtolower(substr($w1,-1)),$CHR + array("'")) ) ? substr($w1,0,-1) : $w1;&lt;br /&gt;    $WORDS[] = $w1;&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  return $WORDS;&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Result:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;Array&lt;br /&gt;        (&lt;br /&gt;            [0] =&gt; I&lt;br /&gt;            [1] =&gt; said&lt;br /&gt;            [2] =&gt; This&lt;br /&gt;            [3] =&gt; is&lt;br /&gt;            [4] =&gt; my&lt;br /&gt;            [5] =&gt; test's&lt;br /&gt;            [6] =&gt; string&lt;br /&gt;            [7] =&gt; of&lt;br /&gt;            [8] =&gt; over&lt;br /&gt;            [9] =&gt; 8.8&lt;br /&gt;            [10] =&gt; words&lt;br /&gt;            [11] =&gt; About&lt;br /&gt;            [12] =&gt; 16&lt;br /&gt;            [13] =&gt; to&lt;br /&gt;            [14] =&gt; be&lt;br /&gt;            [15] =&gt; ex-act&lt;br /&gt;        )&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Of course, there are a few fringe cases it won't.  And bear in mind that it's about 200x slower than str_count_words().  Fortunately, it's still fast enough for my purposes.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-5895891714511258669?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/5895891714511258669/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=5895891714511258669' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/5895891714511258669'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/5895891714511258669'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2008/04/php-strtoword-challenge.html' title='PHP str_to_word Challenge'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-3290923845926271529</id><published>2008-04-25T20:16:00.000-07:00</published><updated>2008-04-27T17:15:36.350-07:00</updated><title type='text'>Komodo Edit Macros</title><content type='html'>Well, as soon as I had settled upon gvim as my new editor de riguer, a friend at work pointed me to &lt;a href="http://www.activestate.com/Products/komodo_ide/komodo_edit.mhtml"&gt;Komodo Edit&lt;/a&gt;.  Now this is what I was looking for.  What a weight off my mind.&lt;br /&gt;&lt;br /&gt;Never been a big macro-head, but there's a couple things I wanted to do that you can't do through the preferences menu alone.  So I figured out a couple tricks and wrote the following macros.  (What is cool is that you can use either javascript or python for the macros.  Sweet!)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;add html comment&lt;/span&gt;&lt;br /&gt;&lt;div class="code"&gt;// comment_html: &amp;lt;!-- {|} --&amp;gt;&lt;br /&gt;// author: klenwell@gmail.com&lt;br /&gt;komodo.assertMacroVersion(2);&lt;br /&gt;&lt;br /&gt;var addLeft = '&amp;lt;!-- ';&lt;br /&gt;var addRight = ' --&amp;gt;';&lt;br /&gt;var currentPos = komodo.editor.currentPos;&lt;br /&gt;var selText = komodo.editor.selText;&lt;br /&gt;var newText = addLeft + selText + addRight;&lt;br /&gt;var selTextPos = currentPos - selText.length + newText.length;&lt;br /&gt;var noSelTextPos = currentPos + newText.length - addRight.length;&lt;br /&gt;var newPos = ( selText != '' ) ? selTextPos : noSelTextPos;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;if (komodo.view.scintilla) { komodo.view.scintilla.focus(); }&lt;br /&gt;//if (komodo.view) { komodo.view.setFocus() };&lt;br /&gt;&lt;br /&gt;komodo.view.selection = newText;&lt;br /&gt;komodo.editor.gotoPos(newPos);&lt;br /&gt;komodo.view.selection = '';&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;this will wrap any select text like so: &lt;code&gt;&amp;lt;!-- {select text} --&amp;gt;&lt;/code&gt; or add an empty wrapper with the cursor in the middle: &lt;code&gt;&amp;lt;!-- | --&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;The same principle can be applied to many situations:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;echo php inline&lt;/span&gt;&lt;br /&gt;&lt;div class="code"&gt;// echo_php_inline: &amp;lt;?php echo {|} ?&amp;gt;&lt;br /&gt;// author: klenwell@gmail.com&lt;br /&gt;komodo.assertMacroVersion(2);&lt;br /&gt;&lt;br /&gt;var pcmd = 'echo';    // echo or print&lt;br /&gt;var addLeft = '&amp;lt;?php '+pcmd+' ';&lt;br /&gt;var addRight = '; ?&amp;gt;';&lt;br /&gt;var currentPos = komodo.editor.currentPos;&lt;br /&gt;var selText = komodo.editor.selText;&lt;br /&gt;var newText = addLeft + selText + addRight;&lt;br /&gt;var selTextPos = currentPos - selText.length + newText.length -3;&lt;br /&gt;var noSelTextPos = currentPos + newText.length - addRight.length;&lt;br /&gt;var newPos = ( selText != '' ) ? selTextPos : noSelTextPos;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;if (komodo.view.scintilla) { komodo.view.scintilla.focus(); }&lt;br /&gt;//if (komodo.view) { komodo.view.setFocus() };&lt;br /&gt;&lt;br /&gt;komodo.view.selection = newText;&lt;br /&gt;komodo.editor.gotoPos(newPos);&lt;br /&gt;komodo.view.selection = '';&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Add a key-binding through the properties menu and you're a rockstar.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-3290923845926271529?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/3290923845926271529/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=3290923845926271529' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/3290923845926271529'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/3290923845926271529'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2008/04/komodo-edit-macros.html' title='Komodo Edit Macros'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-7068417855534991855</id><published>2008-04-21T22:20:00.001-07:00</published><updated>2008-04-21T22:26:36.836-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='vim'/><title type='text'>Cutting, Copying, and Pasting in Vim</title><content type='html'>Got a new laptop a couple weeks ago and finally jumped in the deep-end of the Linux pool.  Probably the most painful part of the transition has been abandoning my reliable old html-kit editor and trying to find a new one.  After a few dead-ends, I finally bit the bullet and committed to Vim (gVim to be exact).  For the first few hours, I was ready to cry.  But after doing some research on key-mappings, I'm starting to get the hang of it.&lt;br /&gt;&lt;br /&gt;The biggest frustration was trying to break my Pavlovian conditioning to use Ctrl-X,-C,-V.  Of course, once I figured out mapping, I could remap the keys.  It is not recommended to remap Ctrl-C, so I compromised and use y like you're supposed to.&lt;br /&gt;&lt;br /&gt;Here's the relevant portion of my .gvimrc file:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;" --- KEY MAPPINGS --- "&lt;br /&gt;" Visual Cut/Copy/Paste : http://www.vim.org/tips/tip.php?tip_id=866&lt;br /&gt;" Cut -- using register '+' [Ctrl-o -&gt; jump to last pos]&lt;br /&gt;map  &lt;C-x&gt; "+d&lt;br /&gt;vmap &lt;C-x&gt; "+d&lt;br /&gt;imap &lt;C-x&gt; &lt;C-o&gt;"+d&lt;br /&gt;" Copy -- yank to register '+' [not needed for imode]&lt;br /&gt;noremap  y     "+y&lt;br /&gt;vnoremap y     "+y&lt;br /&gt;" Copy All&lt;br /&gt;imap &lt;C-a&gt; &lt;C-o&gt;gg&lt;C-o&gt;gH&lt;C-o&gt;G&lt;Esc&gt;&lt;br /&gt;vmap &lt;C-a&gt; &lt;C-o&gt;gggH&lt;C-o&gt;G&lt;Esc&gt;i&lt;br /&gt;" Select Line&lt;br /&gt;map  &lt;C-l&gt; 0v$&lt;br /&gt;vmap &lt;C-l&gt; &lt;Esc&gt;0v$&lt;br /&gt;imap &lt;C-l&gt; &lt;Esc&gt;0v$&lt;br /&gt;" Paste&lt;br /&gt;map  &lt;C-v&gt; "+gP&lt;br /&gt;vmap &lt;C-v&gt; "+gP&lt;br /&gt;imap &lt;C-v&gt; &lt;C-o&gt;"+gP&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Still miss html-kit, but I'm adapting.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-7068417855534991855?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/7068417855534991855/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=7068417855534991855' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/7068417855534991855'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/7068417855534991855'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2008/04/cutting-copying-and-pasting-in-vim.html' title='Cutting, Copying, and Pasting in Vim'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-5661191491684834930</id><published>2008-03-10T19:04:00.000-07:00</published><updated>2008-03-10T19:12:38.835-07:00</updated><title type='text'>HTTP_X_BLUECOAT_VIA</title><content type='html'>Get an error message at one of my sites now and again.  It's a special page that requires a cookie setting from a previous page else it throws an error.  So I suspected  a bot of some sort.&lt;br /&gt;&lt;br /&gt;I added a server dump to test my theory a few months ago.  Today I got several error messages, all with this 'HTTP_X_BLUECOAT_VIA' header.  Apparently it's a proxy crawler.  Full details &lt;a href="http://andrewu.co.uk/webtech/archive/?bluecoat_precaching_proxy_problem"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-5661191491684834930?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/5661191491684834930/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=5661191491684834930' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/5661191491684834930'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/5661191491684834930'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2008/03/httpxbluecoatvia.html' title='HTTP_X_BLUECOAT_VIA'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-123709565363980342</id><published>2007-12-30T19:21:00.000-08:00</published><updated>2007-12-30T19:23:29.791-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='apache'/><title type='text'>Apache: ModRewrite Test</title><content type='html'>A simple test for ModRewrite that I needed this week and find myself searching for every now and again:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;# Turn Engine On&lt;br /&gt;RewriteEngine on&lt;br /&gt;&lt;br /&gt;# Rewrite Test&lt;br /&gt;RewriteRule ^test_rewrite\.htm$ http://www.klenwell.com/is/ApacheModRewriteTestOk [R]&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Full explanation on the wiki: &lt;a href="http://www.klenwell.com/is/ApacheModRewriteTestOk"&gt;www.klenwell.com/is/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-123709565363980342?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/123709565363980342/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=123709565363980342' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/123709565363980342'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/123709565363980342'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/12/apache-modrewrite-test.html' title='Apache: ModRewrite Test'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-8980815333347163482</id><published>2007-12-27T19:18:00.000-08:00</published><updated>2007-12-30T19:21:50.208-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>PHP: File Upload Errors</title><content type='html'>Here's an array for use with file uploads:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;$PHP_FILE_ERROR = array&lt;br /&gt;(&lt;br /&gt;   UPLOAD_ERR_OK =&gt; "There is no error, the file uploaded with&lt;br /&gt;success",&lt;br /&gt;   UPLOAD_ERR_INI_SIZE =&gt; "The uploaded file exceeds the&lt;br /&gt;upload_max_filesize directive in php.ini",&lt;br /&gt;   UPLOAD_ERR_FORM_SIZE =&gt; "The uploaded file exceeds the MAX_FILE_SIZE&lt;br /&gt;directive that was specified in the HTML form",&lt;br /&gt;   UPLOAD_ERR_PARTIAL =&gt; "The uploaded file was only partially&lt;br /&gt;uploaded",&lt;br /&gt;   UPLOAD_ERR_NO_FILE =&gt; "No file was uploaded",&lt;br /&gt;   UPLOAD_ERR_NO_TMP_DIR =&gt; "Missing a temporary folder",&lt;br /&gt;   UPLOAD_ERR_CANT_WRITE =&gt; "Failed to write file to disk",&lt;br /&gt;   UPLOAD_ERR_EXTENSION =&gt; "File upload stopped by extension",&lt;br /&gt;);&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;More info: &lt;a href="http://php.net/features.file-upload"&gt;Handling file uploads&lt;/a&gt; (php.net)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-8980815333347163482?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/8980815333347163482/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=8980815333347163482' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/8980815333347163482'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/8980815333347163482'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/12/php-file-upload-errors.html' title='PHP: File Upload Errors'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-8636036672233883458</id><published>2007-12-24T19:21:00.000-08:00</published><updated>2007-12-25T19:29:25.178-08:00</updated><title type='text'>Why You Lock Down Your Server</title><content type='html'>Scanning my (Yule) logs and found this:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;205.237.78.206 - - [21/Dec/2007:15:33:22 -0800] "GET /phpMyAdmin-2.5.6/main.phpmain.php HTTP/1.0" 404 346 "-" "-"&lt;br /&gt;205.237.78.206 - - [21/Dec/2007:15:33:22 -0800] "GET /phpMyAdmin-2.5.4/main.phpmain.php HTTP/1.0" 404 346 "-" "-"&lt;br /&gt;205.237.78.206 - - [21/Dec/2007:15:33:23 -0800] "GET /phpMyAdmin-2.5.1/main.phpmain.php HTTP/1.0" 404 346 "-" "-"&lt;br /&gt;205.237.78.206 - - [21/Dec/2007:15:33:23 -0800] "GET /phpMyAdmin-2.2.3/main.phpmain.php HTTP/1.0" 404 346 "-" "-"&lt;br /&gt;205.237.78.206 - - [21/Dec/2007:15:33:23 -0800] "GET /phpMyAdmin-2.9.1/main.phpmain.php HTTP/1.0" 404 346 "-" "-"&lt;br /&gt;205.237.78.206 - - [21/Dec/2007:15:33:23 -0800] "GET /phpMyAdmin-2.9.0/main.phpmain.php HTTP/1.0" 404 346 "-" "-"&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;And this:&lt;br /&gt;&lt;div class="code"&gt;122.126.109.119 - - [24/Dec/2007:13:40:18 -0800] "CONNECT mail2.xps.idv.tw:25 HTTP/1.0" 405 353 "-" "-"&lt;br /&gt;122.126.109.119 - - [24/Dec/2007:14:23:26 -0800] "CONNECT mail2.xps.idv.tw:25 HTTP/1.0" 405 353 "-" "-"&lt;br /&gt;122.126.109.119 - - [24/Dec/2007:14:57:22 -0800] "CONNECT mail3.xps.idv.tw:25 HTTP/1.0" 405 353 "-" "-"&lt;br /&gt;122.126.109.119 - - [24/Dec/2007:15:18:50 -0800] "CONNECT mail3.xps.idv.tw:25 HTTP/1.0" 405 353 "-" "-"&lt;br /&gt;122.126.109.119 - - [24/Dec/2007:16:07:36 -0800] "CONNECT mail3.xps.idv.tw:25 HTTP/1.0" 405 353 "-" "-"&lt;br /&gt;122.126.109.119 - - [24/Dec/2007:16:52:45 -0800] "CONNECT mail3.xps.idv.tw:25 HTTP/1.0" 405 353 "-" "-"&lt;br /&gt;122.126.109.119 - - [24/Dec/2007:17:53:10 -0800] "CONNECT mail2.xps.idv.tw:25 HTTP/1.0" 405 353 "-" "-"&lt;br /&gt;122.126.109.119 - - [24/Dec/2007:18:34:42 -0800] "CONNECT mail3.xps.idv.tw:25 HTTP/1.0" 405 353 "-" "-"&lt;br /&gt;122.126.109.119 - - [24/Dec/2007:18:56:36 -0800] "CONNECT mail2.xps.idv.tw:25 HTTP/1.0" 405 353 "-" "-"&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;I suspect &lt;a href="http://205.237.78.206/security/index.php"&gt;205.237.78.206&lt;/a&gt; must be hacked.&lt;br /&gt;&lt;br /&gt;Merry Christmas.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-8636036672233883458?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/8636036672233883458/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=8636036672233883458' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/8636036672233883458'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/8636036672233883458'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/12/why-you-lock-down-your-server.html' title='Why You Lock Down Your Server'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-2576409292064912951</id><published>2007-12-08T15:42:00.000-08:00</published><updated>2007-12-08T23:12:55.315-08:00</updated><title type='text'>7-Zip from the Command Line</title><content type='html'>Looking for practical examples for using 7-Zip from the command line with Linux or Cygwin? I was and wasn't finding much love on the internet.  I finally discovered the documentation that comes packaged with 7-Zip and that helped me figure out what I wanted to do.&lt;br /&gt;&lt;br /&gt;I've added the examples to my wiki:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.klenwell.com/is/CategoryCygwin7zip"&gt;7-Zip Command Line Examples&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;(I'd add them here, but the lines are kinda long and would probably get cut off or broken weirdly.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-2576409292064912951?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/2576409292064912951/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=2576409292064912951' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/2576409292064912951'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/2576409292064912951'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/12/7-zip-from-command-line.html' title='7-Zip from the Command Line'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-5754629546252326312</id><published>2007-12-03T20:45:00.000-08:00</published><updated>2007-12-03T20:49:13.009-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>PHP: Is Machine Online?</title><content type='html'>If you're running PHP on a Windows like I am, the following code will quickly tell you whether you are online:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;// is machine online? (for XP)&lt;br /&gt;// returns ip if machine is online, false if offline (per ipconf)&lt;br /&gt;/*____________________________________________________________________________*/&lt;br /&gt;function is_machine_online() &lt;br /&gt;{&lt;br /&gt;  $ip = false;   // return&lt;br /&gt;  &lt;br /&gt;  $re_ip = '%(([0-9]+\.){3}([0-9]+))%'; // ip regex&lt;br /&gt;  &lt;br /&gt;  // WIN only (add ifconfig in future for Unix)&lt;br /&gt;  if ( substr( PHP_OS, 0, 3 ) != 'WIN' )&lt;br /&gt;  {&lt;br /&gt;    trigger_error("this fx currently only works with WIN", E_USER_WARNING);&lt;br /&gt;    return false;&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  exec('ipconfig', $OUT, $failed);&lt;br /&gt;  if ( $failed ) return false;&lt;br /&gt;&lt;br /&gt;  foreach ( $OUT as $ln )&lt;br /&gt;  {&lt;br /&gt;    if ( stripos($ln, 'ip address') === FALSE ) continue;&lt;br /&gt;    if ( preg_match($re_ip, $ln, $MATCH) )&lt;br /&gt;    {&lt;br /&gt;      $ip = $MATCH[0];&lt;br /&gt;      break;&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  return $ip;&lt;br /&gt;} &lt;br /&gt;/*____________________________________________________________________________*/&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Usage:&lt;br /&gt;&lt;div class="code"&gt;if ( $test = 1 )&lt;br /&gt;{&lt;br /&gt;  $debug = 0;&lt;br /&gt;  print 'testing is_machine_online()';&lt;br /&gt;  print '&amp;lt;pre&amp;gt;';&lt;br /&gt;  &lt;br /&gt;  // test code here&lt;br /&gt;  print $is = ( is_machine_online() ) ? 'is online' : 'not online';&lt;br /&gt;  &lt;br /&gt;  print '&amp;lt;/pre&amp;gt;'; &lt;br /&gt;}&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-5754629546252326312?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/5754629546252326312/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=5754629546252326312' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/5754629546252326312'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/5754629546252326312'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/12/php-is-machine-online.html' title='PHP: Is Machine Online?'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-5148875716776115405</id><published>2007-12-02T18:14:00.000-08:00</published><updated>2007-12-03T20:45:43.955-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><title type='text'>The Greps of Wrath</title><content type='html'>Careful using grep recursively on directories containing images.  I wasn't actually using grep, but the code below to change some relatively specific numeric sequences:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;# multiple files&lt;br /&gt;# NOTE: in cygwin on XP must have parameter "-i.tmpbak" which create a backup of each file&lt;br /&gt;# which then get deleted below (remove .tmpbak on Unix to edit directly)&lt;br /&gt;find /dirname -name "*"|xargs perl -w -i.tmpbak -p -e "s/search_text/replace_text/g"&lt;br /&gt;&lt;br /&gt;# delete temp files&lt;br /&gt;# with prompt before each delete&lt;br /&gt;find -name "*.tmpbak" -ok rm {} \;&lt;br /&gt;&lt;br /&gt;# with no prompt (list first then run again with delete command)&lt;br /&gt;find -name "*.tmpbak"&lt;br /&gt;find -name "*.tmpbak" -delete&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;End up corrupting all my images -- I assume because it matched the search text I had using.  But maybe there was another reason.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-5148875716776115405?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/5148875716776115405/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=5148875716776115405' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/5148875716776115405'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/5148875716776115405'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/12/greps-of-wrath.html' title='The Greps of Wrath'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-1575609126253590809</id><published>2007-11-10T14:26:00.000-08:00</published><updated>2007-11-10T16:36:01.636-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>PHP: array_sort_by_key</title><content type='html'>&lt;a href="http://phosphorusandlime.blogspot.com/2005/12/php-sort-array-by-one-field-in-array.html"&gt;A while back&lt;/a&gt;, I posted a function here that sorts an array of arrays, like that returned by &lt;code&gt;mysql_assoc_array&lt;/code&gt;.  I've redone it as part of a new data object class I'm developing for my php framework and added it to my google code repository.  Find it here:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://klenwell.googlecode.com/svn/trunk/PHP/array/array_sort.inc.php"&gt;http://klenwell.googlecode.com/svn/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Comparable to &lt;a href="http://www.php.net/manual/en/function.array-multisort.php"&gt;&lt;code&gt;array_multisort&lt;/code&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-1575609126253590809?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/1575609126253590809/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=1575609126253590809' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/1575609126253590809'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/1575609126253590809'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/11/php-arraysortbykey.html' title='PHP: array_sort_by_key'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-5135768966175407201</id><published>2007-10-11T22:06:00.000-07:00</published><updated>2007-10-11T22:20:17.587-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>PHP: Singleton Pattern for Composed Objects</title><content type='html'>I usually use a variation of the method below in classes that include a composed object (e.g., a database object):&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;// method: load composed object&lt;br /&gt;function _load_object()&lt;br /&gt;{&lt;br /&gt;  // already loaded&lt;br /&gt;  if ( is_object($this-&gt;ComposedObject) ) return;&lt;br /&gt;  &lt;br /&gt;  require_once($this-&gt;PATH['composed_object_class']);&lt;br /&gt;  &lt;br /&gt;  // create composite object&lt;br /&gt;  $this-&gt;ComposedObject = new ComposedObject();&lt;br /&gt;  // add additional config steps here&lt;br /&gt;  &lt;br /&gt;  return;&lt;br /&gt;}&lt;br /&gt;// END method&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;For an example, see the _load_phpmailer method in my &lt;a href="http://klenwell.googlecode.com/svn/trunk/PHP/ceo/php_ceo/framework.class.php"&gt;CeoFramework class&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-5135768966175407201?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/5135768966175407201/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=5135768966175407201' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/5135768966175407201'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/5135768966175407201'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/10/php-singleton-pattern-for-composed.html' title='PHP: Singleton Pattern for Composed Objects'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-4282706135610983428</id><published>2007-10-02T20:37:00.000-07:00</published><updated>2007-10-02T20:39:49.131-07:00</updated><title type='text'>Firefox Crashing?</title><content type='html'>Running Firefox 2.0.0.7.  All of the sudden it's been crashing like mad the last couple days.  (I'm running it on Windows XP.)&lt;br /&gt;&lt;br /&gt;Haven't been able to identify a common thread.  I have a page with Google AdWords on it and it crashed it repeatedly.  &lt;br /&gt;&lt;br /&gt;Saw something somewhere (sorry, didn't bookmark) that suggested disabling Firebug.  My AdWords page opened.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-4282706135610983428?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/4282706135610983428/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=4282706135610983428' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/4282706135610983428'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/4282706135610983428'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/10/firefox-crashing.html' title='Firefox Crashing?'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-5432823829893330330</id><published>2007-09-19T22:45:00.000-07:00</published><updated>2009-05-18T19:49:27.379-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>PHP: HTML Validator Class</title><content type='html'>This class was developed as part of the form library of the CEO framework I'm working on.  Useful for the case where you have a textarea in your form and want to allow HTML but make sure it's not broken (especially if you're planning to display it on a page).&lt;br /&gt;&lt;br /&gt;Class and test can be found in the repository:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://klenwell.googlecode.com/svn/branches/archive2008/PHP/ceo/test/__REPOSITORY/html_validator.class.php"&gt;html_validator.class.php&lt;/a&gt;&lt;br /&gt;&lt;a href="http://klenwell.googlecode.com/svn/branches/archive2008/PHP/ceo/test/__REPOSITORY/unit.html_validator.php"&gt;unit.html_validator.php&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Based on the script found &lt;a href="http://simon.incutio.com/code/php/SafeHtmlChecker.class.php.txt"&gt;here&lt;/a&gt; with a couple bells and whistles added.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-5432823829893330330?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/5432823829893330330/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=5432823829893330330' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/5432823829893330330'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/5432823829893330330'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/09/php-html-validator-class.html' title='PHP: HTML Validator Class'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-8081256619054350198</id><published>2007-09-08T09:16:00.000-07:00</published><updated>2007-09-08T09:27:50.816-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cranky'/><category scheme='http://www.blogger.com/atom/ns#' term='hosting'/><title type='text'>hosting: 1and1.com technical support</title><content type='html'>So I buckled down and sacrificed my Friday night to finally getting DNS operating on my VPS.  Over the last 2 weeks I've scoured the web, bought books, read books, and thought I had it all figured out.  The final piece was to just point my domain registered with 1and1.com to my nameservers on my VPS.  That's where the wheels fell off.&lt;br /&gt;&lt;br /&gt;I posted a summary of my problem on the &lt;a href="http://www.webhostingtalk.com/showthread.php?t=633897"&gt;webhostingtalk.com forum&lt;/a&gt;.  What really annoyed me, however, was 1and1.com support.  I called them for assistance, knowing full well both from my own experience and the account of others, that their phone support is pretty useless.  But I hoped at least they would (A) point me to a web page explaining how to do it, (B) wonder of wonders, be able to walk me through this, or (C) pass me up to a tech who could handle it for me.  Instead I went around in circles for 10 minutes (remaining patient and polite the whole time) with a clueless rep who then disconnected me without warning.&lt;br /&gt;&lt;br /&gt;Fantastic customer support.  I've read that godaddy.com makes it easier for you to manage DNS yourself.  Not that they're without their detractors.  But I figure I'll set up an account as they're almost as cheap as 1and1.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-8081256619054350198?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/8081256619054350198/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=8081256619054350198' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/8081256619054350198'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/8081256619054350198'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/09/hosting-1and1com.html' title='hosting: 1and1.com technical support'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-704516930656591305</id><published>2007-09-03T16:37:00.000-07:00</published><updated>2007-09-03T16:40:28.698-07:00</updated><title type='text'>reCAPTCHA</title><content type='html'>&lt;a href="http://recaptcha.net/"&gt;Recaptcha&lt;/a&gt; is one of the more ingenious web-based distributed-computing widget-thingies I've seen.  Just came across it on Lawrence Lessig's site.  Plan to sign up for it myself as soon as I have a reason to.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-704516930656591305?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/704516930656591305/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=704516930656591305' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/704516930656591305'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/704516930656591305'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/09/recaptcha.html' title='reCAPTCHA'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-6394336931587509793</id><published>2007-08-30T13:10:00.000-07:00</published><updated>2007-08-30T13:13:05.678-07:00</updated><title type='text'>Slashdot on Earthlink Wi-Fi</title><content type='html'>&lt;a href="http://hardware.slashdot.org/article.pl?sid=07/08/30/1617226"&gt;More news&lt;/a&gt; on the failings of Earthlink wi-fi.  I found &lt;a href="http://hardware.slashdot.org/comments.pl?sid=284087&amp;cid=20414303"&gt;this comment&lt;/a&gt; insightful:&lt;br /&gt;&lt;div class="quote"&gt;Earthlink badly overreached themselves here with two major mistakes - first, deciding to use Tropos equipment to paint an entire city. Most of the money you burn in setting up a wifi installation is in the install and then trying to get everything to work when your planning tools are out of sync with reality (which is almost always). Tropos's mesh equipment is crap, so they've wasted months and burned untold money trying to nail jello to a wall.&lt;br /&gt;&lt;br /&gt;Second, trying to blanket an entire city at once is doable, but it's far more practical to grow the network from little seed areas (while keeping future growth in mind) - blanket a six block area of downtown, for instance, and then expand from that. This lets you get everything right for a small area before you apply that to larger areas - it's the way almost all WISP (wireless ISPs) operate and it works fairly well.&lt;br /&gt;&lt;br /&gt;I think Earthlink finally realized it wasn't gonna work, which of course makes all the assumptions under which they signed contracts not so great for them.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-6394336931587509793?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/6394336931587509793/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=6394336931587509793' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/6394336931587509793'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/6394336931587509793'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/08/slashdot-on-earthlink-wi-fi.html' title='Slashdot on Earthlink Wi-Fi'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-5292622338544352356</id><published>2007-08-30T12:41:00.000-07:00</published><updated>2007-08-30T13:06:09.950-07:00</updated><title type='text'>Greqo Licensing</title><content type='html'>A few weeks ago, I noted a reference to Greqo in what looked like a Russian forum for spammers:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://phosphorusandlime.blogspot.com/2007/07/greqo-russian-blog-spammers-class-of.html"&gt;Greqo: The Russian Blog-Spammer's Class of Choice?&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;A couple days ago I received an email from a Russian PHP developer drawing my attention to &lt;a href="http://blogoferma.com/"&gt;the Blogoferma site&lt;/a&gt;.  The Russian developer pointed out that this product appears to be marketed in violation of Greqo's GPL license and he said that the marketer claims that he is selling it with my endorsement.&lt;br /&gt;&lt;br /&gt;On the first point: as I noted in my previous post, my understanding of the GPL is that the marketer is free to use my code in his product just so long as he extends the GPL to his source (which I believe requires him including a GPL notice with his product) and makes his source code available upon request.  As long as he does that, he is not under any obligation to me and can charge whatever he whatever he wants for it.&lt;br /&gt;&lt;br /&gt;Of course, if it is true, as the PHP developer claims, that this product is little more than my code repackaged, anyone interested in the product would probably be better served just grabbing my code themselves for free at &lt;a href="http://code.google.com/p/greqo/downloads/list"&gt;the project site&lt;/a&gt;.  Also, I still look on Greqo as a beta release at best, so I'd be hesitant to trust anything too critical to it at this point.&lt;br /&gt;&lt;br /&gt;On the second point: although I believe the marketer of Blogoferma has contacted me and even commented on my previous point, we have never discussed his product.  If he claims I have endorsed or approved of it in any way, that's not true.  As noted above, he can use it under the terms of the GPL, so my permission is not really necessary.  The license is the authority with which he needs to reconcile himself.&lt;br /&gt;&lt;br /&gt;And while I don't really like the idea of Greqo being used solely for the purposes of blogspam (or SEO if you will, which is often little more than a bagful of spamming tricks), that's a matter for which Blogger ultimately takes responsibility &amp;ndash; and does a pretty good job of it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-5292622338544352356?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/5292622338544352356/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=5292622338544352356' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/5292622338544352356'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/5292622338544352356'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/08/greqo-licensing.html' title='Greqo Licensing'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-4059481238021384453</id><published>2007-08-29T08:51:00.000-07:00</published><updated>2007-08-29T08:55:09.291-07:00</updated><title type='text'>Earthlink Layoffs</title><content type='html'>Just came across this in NY Times this morning:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.nytimes.com/2007/08/29/technology/29online.html?th&amp;emc=th"&gt;EarthLink to Trim Work Force and Close Offices&lt;/a&gt;&lt;br /&gt;&lt;div class="quote"&gt;The company is struggling to attract dial-up customers who are turning to high-speed alternatives and is studying the performance of its municipal wireless Internet networks in four cities before deciding how to move forward with similar networks elsewhere.&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Looks like I got out just in time.  I get the feeling their muni services are a bust.  I know they were for me.  Too bad, because it would have been a pretty good deal if it performed like advertised.&lt;br /&gt;&lt;br /&gt;I just hope they really canceled my service.  (Waiting for next invoice to show up in inbox...)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-4059481238021384453?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/4059481238021384453/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=4059481238021384453' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/4059481238021384453'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/4059481238021384453'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/08/earthlink-layoffs.html' title='Earthlink Layoffs'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-1274953765909464027</id><published>2007-08-27T21:50:00.000-07:00</published><updated>2007-08-27T22:09:16.676-07:00</updated><title type='text'>PHP: Get Base Domain</title><content type='html'>The problem: take a url (in this case, we'll specify an absolute url, http and all) and return only the base domain.  For instance, given 'www.domain.com' or 'sub.subdomain.domain.com', it should return 'domain.com'.&lt;br /&gt;&lt;br /&gt;Simple enough, but now consider: 'http://www.example_site.com.pk' or 'http://damnlimies.co.uk' or 'http://username:password@this.is.a.worst.shortly.subdomain.thisIsMyMainWebsite.com.cl'&lt;br /&gt;&lt;br /&gt;It is an anvil upon which many a hammer has been broken:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://lists.evolt.org/archive/Week-of-Mon-20031201/152316.html"&gt;http://lists.evolt.org/archive/Week-of-Mon-20031201/152316.html&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.webmasterworld.com/forum88/10656.htm"&gt;http://www.webmasterworld.com/forum88/10656.htm&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Anyway, I think I have a solution.  I won't bother with the details of how I arrived at it.  Suffice to say, you just need to break down your own url parsing process.  It  passed the battery of tests at the end:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;// get base domain (domain.tld)&lt;br /&gt;/*____________________________________________________________________________*/&lt;br /&gt;function get_base_domain($url) &lt;br /&gt;{&lt;br /&gt;  $debug = 0;  &lt;br /&gt;  $base_domain = '';&lt;br /&gt;  &lt;br /&gt;  // generic tlds (source: http://en.wikipedia.org/wiki/Generic_top-level_domain)&lt;br /&gt;  $G_TLD = array(&lt;br /&gt;    'biz','com','edu','gov','info','int','mil','name','net','org',&lt;br /&gt;    'aero','asia','cat','coop','jobs','mobi','museum','pro','tel','travel',&lt;br /&gt;    'arpa','root',&lt;br /&gt;    'berlin','bzh','cym','gal','geo','kid','kids','lat','mail','nyc','post','sco','web','xxx',&lt;br /&gt;    'nato',&lt;br /&gt;    'example','invalid','localhost','test',&lt;br /&gt;    'bitnet','csnet','ip','local','onion','uucp',&lt;br /&gt;    'co'   // note: not technically, but used in things like co.uk&lt;br /&gt;  );&lt;br /&gt;  &lt;br /&gt;  // country tlds (source: http://en.wikipedia.org/wiki/Country_code_top-level_domain)&lt;br /&gt;  $C_TLD = array(&lt;br /&gt;    // active&lt;br /&gt;    'ac','ad','ae','af','ag','ai','al','am','an','ao','aq','ar','as','at','au','aw','ax','az',&lt;br /&gt;    'ba','bb','bd','be','bf','bg','bh','bi','bj','bm','bn','bo','br','bs','bt','bw','by','bz',&lt;br /&gt;    'ca','cc','cd','cf','cg','ch','ci','ck','cl','cm','cn','co','cr','cu','cv','cx','cy','cz',&lt;br /&gt;    'de','dj','dk','dm','do','dz','ec','ee','eg','er','es','et','eu','fi','fj','fk','fm','fo',&lt;br /&gt;    'fr','ga','gd','ge','gf','gg','gh','gi','gl','gm','gn','gp','gq','gr','gs','gt','gu','gw',&lt;br /&gt;    'gy','hk','hm','hn','hr','ht','hu','id','ie','il','im','in','io','iq','ir','is','it','je',&lt;br /&gt;    'jm','jo','jp','ke','kg','kh','ki','km','kn','kr','kw','ky','kz','la','lb','lc','li','lk',&lt;br /&gt;    'lr','ls','lt','lu','lv','ly','ma','mc','md','mg','mh','mk','ml','mm','mn','mo','mp','mq',&lt;br /&gt;    'mr','ms','mt','mu','mv','mw','mx','my','mz','na','nc','ne','nf','ng','ni','nl','no','np',&lt;br /&gt;    'nr','nu','nz','om','pa','pe','pf','pg','ph','pk','pl','pn','pr','ps','pt','pw','py','qa',&lt;br /&gt;    're','ro','ru','rw','sa','sb','sc','sd','se','sg','sh','si','sk','sl','sm','sn','sr','st',&lt;br /&gt;    'sv','sy','sz','tc','td','tf','tg','th','tj','tk','tl','tm','tn','to','tr','tt','tv','tw',&lt;br /&gt;    'tz','ua','ug','uk','us','uy','uz','va','vc','ve','vg','vi','vn','vu','wf','ws','ye','yu',&lt;br /&gt;    'za','zm','zw',&lt;br /&gt;    // inactive&lt;br /&gt;    'eh','kp','me','rs','um','bv','gb','pm','sj','so','yt','su','tp','bu','cs','dd','zr'&lt;br /&gt;    );&lt;br /&gt;  &lt;br /&gt;  &lt;br /&gt;  // get domain&lt;br /&gt;  if ( !$full_domain = get_url_domain($url) )&lt;br /&gt;  {&lt;br /&gt;    return $base_domain;&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  // now the fun&lt;br /&gt;  &lt;br /&gt;    // break up domain, reverse&lt;br /&gt;    $DOMAIN = explode('.', $full_domain);&lt;br /&gt;    if ( $debug ) print_r($DOMAIN);&lt;br /&gt;    $DOMAIN = array_reverse($DOMAIN);&lt;br /&gt;    if ( $debug ) print_r($DOMAIN);&lt;br /&gt;    &lt;br /&gt;    // first check for ip address&lt;br /&gt;    if ( count($DOMAIN) == 4 &amp;&amp; is_numeric($DOMAIN[0]) &amp;&amp; is_numeric($DOMAIN[3]) )&lt;br /&gt;    {&lt;br /&gt;      return $full_domain;&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    // if only 2 domain parts, that must be our domain&lt;br /&gt;    if ( count($DOMAIN) &lt;= 2 ) return $full_domain;&lt;br /&gt;    &lt;br /&gt;    /* &lt;br /&gt;      finally, with 3+ domain parts: obviously D0 is tld &lt;br /&gt;      now, if D0 = ctld and D1 = gtld, we might have something like com.uk&lt;br /&gt;      so, if D0 = ctld &amp;&amp; D1 = gtld &amp;&amp; D2 != 'www', domain = D2.D1.D0&lt;br /&gt;      else if D0 = ctld &amp;&amp; D1 = gtld &amp;&amp; D2 == 'www', domain = D1.D0&lt;br /&gt;      else domain = D1.D0&lt;br /&gt;      these rules are simplified below &lt;br /&gt;    */&lt;br /&gt;    if ( in_array($DOMAIN[0], $C_TLD) &amp;&amp; in_array($DOMAIN[1], $G_TLD) &amp;&amp; $DOMAIN[2] != 'www' )&lt;br /&gt;    {&lt;br /&gt;      $full_domain = $DOMAIN[2] . '.' . $DOMAIN[1] . '.' . $DOMAIN[0];&lt;br /&gt;    }&lt;br /&gt;    else&lt;br /&gt;    {&lt;br /&gt;      $full_domain = $DOMAIN[1] . '.' . $DOMAIN[0];;&lt;br /&gt;    }&lt;br /&gt;  &lt;br /&gt;  // did we succeed?  &lt;br /&gt;  return $full_domain;&lt;br /&gt;} &lt;br /&gt;/*____________________________________________________________________________*/&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// get domain from url&lt;br /&gt;/*____________________________________________________________________________*/&lt;br /&gt;function get_url_domain($url) &lt;br /&gt;{&lt;br /&gt;  $domain = '';&lt;br /&gt;  &lt;br /&gt;  $_URL = parse_url($url);&lt;br /&gt;  &lt;br /&gt;  // sanity check&lt;br /&gt;  if ( empty($_URL) || empty($_URL['host']) )&lt;br /&gt;  {&lt;br /&gt;    $domain = '';&lt;br /&gt;  }&lt;br /&gt;  else&lt;br /&gt;  {&lt;br /&gt;    $domain = $_URL['host'];&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  return $domain;&lt;br /&gt;} &lt;br /&gt;/*____________________________________________________________________________*/&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// Testbed&lt;br /&gt;/*____________________________________________________________________________*/&lt;br /&gt;&lt;br /&gt;if ( 1 )&lt;br /&gt;{&lt;br /&gt; // test code here&lt;br /&gt;  $TESTURL[] = 'http://127.0.0.1'; &lt;br /&gt;  $TESTURL[] = 'http://www.examplesite.com.pk'; &lt;br /&gt;  $TESTURL[] = 'http://domain.tv.com';&lt;br /&gt;  $TESTURL[] = 'http://domain.com.tv';&lt;br /&gt;  $TESTURL[] = 'http://domain.tv';&lt;br /&gt;  $TESTURL[] = 'http://domain.com';&lt;br /&gt;  $TESTURL[] = 'http://secure.email.website.co.uk'; &lt;br /&gt;  $TESTURL[] = 'http://username:password@this.is.a.worst.shortly.subdomain.thisIsMyMainWebsite.com.cl'; &lt;br /&gt;  &lt;br /&gt;  foreach ( $TESTURL as $url )&lt;br /&gt;  {&lt;br /&gt;    echo $url . ' -&gt; ' . get_base_domain($url) . '&lt;br&gt;';&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/*____________________________________________________________________________*/&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;results:&lt;br /&gt;&lt;div class="code"&gt;http://127.0.0.1 -&gt; 127.0.0.1&lt;br /&gt;http://www.examplesite.com.pk -&gt; examplesite.com.pk&lt;br /&gt;http://domain.tv.com -&gt; tv.com&lt;br /&gt;http://domain.com.tv -&gt; domain.com.tv&lt;br /&gt;http://domain.tv -&gt; domain.tv&lt;br /&gt;http://domain.com -&gt; domain.com&lt;br /&gt;http://secure.email.website.co.uk -&gt; website.co.uk&lt;br /&gt;http://username:password@this.is.a.worst.shortly.subdomain.thisIsMyMainWebsite.com.cl -&gt; thisIsMyMainWebsite.com.cl&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The source will eventually end up in the &lt;a href="http://bafflegate.googlecode.com/svn/trunk/"&gt;bafflegate repository&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-1274953765909464027?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/1274953765909464027/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=1274953765909464027' title='13 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/1274953765909464027'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/1274953765909464027'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/08/php-get-base-domain.html' title='PHP: Get Base Domain'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>13</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-8899749977407657223</id><published>2007-08-27T08:56:00.000-07:00</published><updated>2007-08-27T19:38:21.446-07:00</updated><title type='text'>New York Times on Micropayments</title><content type='html'>Micropayments &amp;ndash; currency in general &amp;ndash; has always been a fascination of mine.  The New York Times has a brief report this morning on the state of online micropayments:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.nytimes.com/2007/08/27/technology/27micro.html?th&amp;emc=th"&gt;In Online World, Pocket Change Is Not Easily Spent&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;From the article:&lt;br /&gt;&lt;div class="quote"&gt;But the problems proved insurmountable. Many micropayments companies have shut down, been acquired or changed their business models over the years. Among them: DigiCash, CyberCash, First Virtual Holdings and Peppercoin.&lt;br /&gt;&lt;br /&gt;They used various systems, but in general users paid into accounts with their credit cards and then drew from those accounts. In the mid- to late ’90s, electronic cash had become such a popular concept that some politicians worried that it might threaten the stability of the nation’s currency.&lt;br /&gt;&lt;br /&gt;But the economic and technical challenges were enormous. Consumers were reluctant to pay even a tenth of a cent for something they believed should be free. “There is a certain amount of anxiety involved in any decision to buy, no matter how small,” Mr. Shirky wrote in 2000.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-8899749977407657223?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/8899749977407657223/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=8899749977407657223' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/8899749977407657223'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/8899749977407657223'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/08/new-times-on-micropayments.html' title='New York Times on Micropayments'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-7945833645551479512</id><published>2007-08-23T17:19:00.000-07:00</published><updated>2007-08-23T17:26:43.202-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='drupal'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>PHP: Drupal Theme "abstruct"</title><content type='html'>This is a revision of the &lt;a href="http://phosphorusandlime.blogspot.com/2007/08/php-drupal-theme-wtfm.html"&gt;wtfm theme&lt;/a&gt; I posted last week.  I posted &lt;a href="http://drupal.org/node/167470"&gt;a brief overview&lt;/a&gt; in the drupal forums. &lt;br /&gt;&lt;br /&gt;Some links:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.klenwell.net/wtfm/"&gt;demo&lt;/a&gt;&lt;br /&gt;&lt;a href="http://code.google.com/p/klenwell/downloads/list"&gt;download&lt;/a&gt;&lt;br /&gt;&lt;a href="http://klenwell.googlecode.com/svn/trunk/PHP/drupal/themes/abstruct/"&gt;source&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Also, I discovered this page which I found very helpful:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://drupal.org/node/11812"&gt;http://drupal.org/node/11812&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;It lists all the page.tpl.php variables&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-7945833645551479512?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/7945833645551479512/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=7945833645551479512' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/7945833645551479512'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/7945833645551479512'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/08/php-drupal-theme-abstruct.html' title='PHP: Drupal Theme &quot;abstruct&quot;'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-7195466670301042348</id><published>2007-08-16T17:57:00.001-07:00</published><updated>2007-08-16T18:14:37.467-07:00</updated><title type='text'>CSS: The Rounded Corner Fairy</title><content type='html'>Technically, it's a sprite.  A single image used to round all four corners of a div block.  The idea was inspired by &lt;a href="http://www.alistapart.com/articles/sprites/"&gt;this ALA article&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Previously, I've used the clever &lt;a href="http://phosphorusandlime.blogspot.com/2006/07/nifty-cube-css-file-autoloader.html"&gt;nifty corners javascript package&lt;/a&gt;.  It's more elegant on the development side.  But in operation, it's a bit clunky and results in a noticeable bounce as the tweaks are applied to the output.&lt;br /&gt;&lt;br /&gt;Css-defined background images fill in more smoothly, but require additional sweat in putting together the page.  First, you must create the appropriate image(s) (the background and foreground colors must match the css settings.)  You only need one 16x16 round image like this:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_qkEr9USi0xI/RsT1UUQfKmI/AAAAAAAAABw/nzY7yREBZA0/s1600-h/c16.ccddcc.png"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_qkEr9USi0xI/RsT1UUQfKmI/AAAAAAAAABw/nzY7yREBZA0/s320/c16.ccddcc.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5099470407474293346" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;But you must add four additional empty divs:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&amp;lt;div id="col1" class="column"&amp;gt;&amp;lt;div class="tl"&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div class="tr"&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div class="child"&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!-- content --&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;div class="clear"&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;&amp;lt;/div&amp;gt;&amp;lt;div class="bl"&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div class="br"&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;You must include the css settings:&lt;br /&gt;&lt;br /&gt;&lt;div class="ipod"&gt;/* note: parent block must have position setting of relative or absolute */&lt;br /&gt;.column { position:relative; }&lt;br /&gt;.tl { top:0px; left:0px; }&lt;br /&gt;.tr { top:0px; right:0px; background-position:8px 0px; }&lt;br /&gt;.bl { bottom:0px; left:0px; background-position:0px 8px; }&lt;br /&gt;.br { bottom:0px; right:0px; background-position:8px 8px; }&lt;br /&gt;.tl, .tr, .bl, .br { background-image:url('c16.ccddcc.png'); position:absolute; height:8px; width:8px; overflow:hidden } &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;And, as noted above, you have to make sure you give the parent block the proper &lt;code&gt;position&lt;/code&gt; setting.&lt;br /&gt;&lt;br /&gt;Also, while it works in Firefox and IE7, it doesn't quite work in IE6 and I haven't tested it any other browsers.&lt;br /&gt;&lt;br /&gt;You can see the technique in action here: &lt;a href="http://klenwell.googlepages.com/demo.corner_sprite.htm"&gt;klenwell google page&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Not perfect.  But it has it virtues.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-7195466670301042348?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/7195466670301042348/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=7195466670301042348' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/7195466670301042348'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/7195466670301042348'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/08/css-rounded-corner-fairy.html' title='CSS: The Rounded Corner Fairy'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_qkEr9USi0xI/RsT1UUQfKmI/AAAAAAAAABw/nzY7yREBZA0/s72-c/c16.ccddcc.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-4728753937899942891</id><published>2007-08-15T20:02:00.000-07:00</published><updated>2007-08-15T20:10:23.662-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cranky'/><title type='text'>Earthlink Cancelled</title><content type='html'>At last.  I haven't even used it for the last 3 months.  My year-long contract didn't expire until last month so wasn't much I could do in the meantime, except pay my $20/mo subscription.&lt;br /&gt;&lt;br /&gt;It took me three phone calls and about a half-hour waiting on hold to finally find someone who could help me.  The call-center agent offered me 2 months free to stay, a sign that things as fucked up now as when I last used it.&lt;br /&gt;&lt;br /&gt;Earthlink was my first ISP ever (over 10 years ago!) and I always kinda rooted for them as the underdog.  No more.  I would have been patient with the crappy muni wifi service if only their technical support wasn't so totally ineffective.  No email support, maddening phone trees (where there isn't even a wifi option!) and interminable wait times.&lt;br /&gt;&lt;br /&gt;Need to cancel (or just get a couple months of service for free)?  &lt;br /&gt;&lt;br /&gt;888-327-8454&lt;br /&gt;&lt;br /&gt;Good riddance!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-4728753937899942891?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/4728753937899942891/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=4728753937899942891' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/4728753937899942891'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/4728753937899942891'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/08/earthlink-cancelled.html' title='Earthlink Cancelled'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-1740587786575969727</id><published>2007-08-14T17:33:00.000-07:00</published><updated>2007-08-14T17:37:38.731-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='drupal'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>PHP: Drupal Theme "wtfm"</title><content type='html'>wtfm is my first full drupal theme.  It's primary goal is to function as a basic template for other themes, but I have made it the theme of my new drupal site, &lt;a href="http://www.klenwell.net/wtfm/"&gt;wtfm&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;More info:&lt;br /&gt;&lt;a href="http://www.klenwell.net/wtfm/node/1"&gt;features&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.klenwell.net/wtfm/"&gt;demo&lt;/a&gt;&lt;br /&gt;&lt;a href="http://klenwell.googlecode.com/svn/trunk/PHP/drupal/themes/wtfm/"&gt;source code&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-1740587786575969727?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/1740587786575969727/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=1740587786575969727' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/1740587786575969727'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/1740587786575969727'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/08/php-drupal-theme-wtfm.html' title='PHP: Drupal Theme &quot;wtfm&quot;'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-6766493459099734941</id><published>2007-08-08T20:03:00.000-07:00</published><updated>2007-08-08T16:08:50.323-07:00</updated><title type='text'>Games: boomshine</title><content type='html'>Not much of a gamer.  Not anymore.  My favorite game?  Probably Texas hold 'em.  Or Monopoly.  On the computer, it's Sim City or good old Free Cell.&lt;br /&gt;&lt;br /&gt;Anyway, came across boomshine today on bored.com via digg.  The original home page seems to be here (though it did not load for me here):&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.k2xl.com/games/boomshine/"&gt;http://www.k2xl.com/games/boomshine/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Can't say much for the creator's web design sense, but I think the game is beautiful and elegant in its simplicity.  And fun to play.  A little masterpiece.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-6766493459099734941?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/6766493459099734941/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=6766493459099734941' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/6766493459099734941'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/6766493459099734941'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/08/games-boomshine.html' title='Games: boomshine'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-2543134015155115019</id><published>2007-08-07T10:05:00.000-07:00</published><updated>2007-08-07T10:10:13.483-07:00</updated><title type='text'>New Yorker: Damn Spam</title><content type='html'>A well-written article from The New Yorker this week on the state of spam.  Old news to anyone who casually follows the issue.  And not at all encouraging.  But an intelligent summary for technical and non-technical readers:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.newyorker.com/reporting/2007/08/06/070806fa_fact_specter?printable=true"&gt;Damn Spam: The losing war on junk e-mail&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://it.slashdot.org/it/07/08/07/0321204.shtml"&gt;slashdot commentary&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-2543134015155115019?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/2543134015155115019/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=2543134015155115019' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/2543134015155115019'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/2543134015155115019'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/08/new-yorker-damn-spam.html' title='New Yorker: Damn Spam'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-3100127366164681130</id><published>2007-08-03T16:50:00.000-07:00</published><updated>2007-08-03T17:03:48.883-07:00</updated><title type='text'>OneKeyAway</title><content type='html'>&lt;blockquote&gt; Before parties, guests register online and complete questionnaires. The answers are then transferred to digital memory devices -- red, plastic squares slightly larger than a matchbox -- that the guests wear like necklaces.&lt;br /&gt;&lt;br /&gt;During a party, people point their devices at one another to check how compatible they are. The devices flash red, yellow or green, depending on their level of compatibility.&lt;br /&gt;&lt;br /&gt;&amp;ndash; &lt;a href="http://news.yahoo.com/s/nm/20070803/wr_nm/dating_tech_dc;_ylt=AgX7bZ51AsfJ52H8d2jjgL0RSLMF"&gt;New way for singles to meet -- the digital zap&lt;/a&gt; (Yahoo! News)&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;The bad news for me is that I had an idea for an "icebreaker" device very similar to this a couple years ago.  &lt;br /&gt;&lt;br /&gt;The good news is, &lt;a href="http://www.onekeyaway.com/pages/index.php"&gt;OneKeyAway&lt;/a&gt; over-complicated their device to the point that it will never be more than a novelty gadget "for professionals who want to meet other professionals" in a speed-dating environment.  &lt;br /&gt;&lt;br /&gt;The bad news is that a better marketer will simply copy this, figure out how to mainstream it, and make a social networking gadget that's more popular than the iPod -- and it won't be me.&lt;br /&gt;&lt;br /&gt;The other good news is that the article notes that the inventor of this started working on it in 2004, which was before I had my idea.  So I don't feel so bad after all.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-3100127366164681130?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/3100127366164681130/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=3100127366164681130' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/3100127366164681130'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/3100127366164681130'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/08/onekeyaway.html' title='OneKeyAway'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-2473769825533293223</id><published>2007-08-02T10:59:00.000-07:00</published><updated>2007-08-02T11:04:44.512-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><title type='text'>JS: balancing columns</title><content type='html'>A common problem: set two html blocks to the same height using only css and without tables. I've usually solved this in the past by using tables.  But I figured it was time to grow up and figure out the "modern" div-based method for setting two side-by-side blocks to the same height.&lt;br /&gt;&lt;br /&gt;Here's a javascript function that returns the max height for two html blocks:&lt;br /&gt;&lt;br /&gt;&lt;div class="ipod"&gt;function get_max_div_height(id1, id2)&lt;br /&gt;{&lt;br /&gt;  var Dom1 = document.getElementById(id1);&lt;br /&gt;  var Dom2 = document.getElementById(id2);&lt;br /&gt;  var h1 = Dom1.offsetHeight;&lt;br /&gt;  var h2 = Dom2.offsetHeight;&lt;br /&gt;  max_ht = Math.max(h1, h2);&lt;br /&gt; &lt;br /&gt;  // debug&lt;br /&gt;  // alert("compare " + id1 + " &amp; " + id2 + " heights: " + h1 + " / " + h2 + " -&gt; max: " + max_ht);&lt;br /&gt;  &lt;br /&gt;  return max_ht;&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;From here, it's just a matter of setting each block to the max height:&lt;br /&gt;&lt;br /&gt;&lt;div class="ipod"&gt;document.getElementById(dom_id).style.height = max_ht + "px";&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;I'm working on a version of this that can take n elements and equalize the height.  I'll post that to the klenwell repository when complete and tested.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-2473769825533293223?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/2473769825533293223/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=2473769825533293223' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/2473769825533293223'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/2473769825533293223'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/08/js-balancing-columns.html' title='JS: balancing columns'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-416357707586416650</id><published>2007-07-30T12:23:00.000-07:00</published><updated>2007-07-30T12:37:00.429-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>PHP: In Support of Heredoc</title><content type='html'>One of the thing that puzzles me about many of the projects I've worked on is the seeming aversion to heredocs.  The neat freak in me love heredocs.  They make it so much easier to separate business logic and presentation logic.  And that helps make code much cleaner.&lt;br /&gt;&lt;br /&gt;I figured there were two reasons why they aren't used more extensively.  1) Programmers used to other languages don't know about them or feel comfortable with them.  2) There's a significant efficiency cost.&lt;br /&gt;&lt;br /&gt;On the second point, I just discovered this: &lt;a href="http://php.net/manual/en/language.types.string.php#74257"&gt;PHP string benchmark&lt;/a&gt; (php.net)&lt;br /&gt;&lt;br /&gt;Cutting to the chase:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;single quotes : 173ms&lt;br /&gt;double quotes : 161ms&lt;br /&gt;heredoc : 130ms&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;So I'm going to be a little more outspoken in my support of heredocs.  Until I see some compelling evidence to the contrary, at least.  Of course, it should be noted that this does not compare directly escaping PHP.&lt;br /&gt;&lt;br /&gt;Here's my model for implementing heredocs in a web page framework: &lt;a href="http://klenwell.googlecode.com/svn/trunk/templates/php/scriptframe.blank.php"&gt;klenwell scriptframe&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-416357707586416650?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/416357707586416650/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=416357707586416650' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/416357707586416650'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/416357707586416650'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/07/php-in-support-of-heredoc.html' title='PHP: In Support of Heredoc'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-3018180582278111328</id><published>2007-07-28T09:02:00.000-07:00</published><updated>2007-07-28T09:15:45.131-07:00</updated><title type='text'>Greqo: The Russian Blog-Spammer's Class of Choice?</title><content type='html'>Noticed a few clicks on my &lt;a href="http://www.klenwell.net/is/HomePage"&gt;Klenwell wiki&lt;/a&gt; from a site called &lt;a href="http://klikforum.com/"&gt;klikforum.com&lt;/a&gt;.  (It's worth clicking just to see the banner art.)  Traced it to this post:  &lt;br /&gt;&lt;br /&gt;&lt;a href="http://klikforum.com/viewtopic.php?p=69237&amp;sid=8537724fccc19fb7d5be0ea25ef6376a#69237"&gt;Main Forum &gt; Spam &gt; What to think! To blogoFermu it is must!&lt;/a&gt; (Babelfish translation)&lt;br /&gt;&lt;br /&gt;Ran the page through Babelfish and I think I got the gist of it.  Someone is promoting some kind of spamming tool which may be using the Greqo class.  If this was the case, it might be a violation of the Greqo GPL license (unless they were making the source code available.)&lt;br /&gt;&lt;br /&gt;In any event, although I'm not thrilled to learn spammers might be misappropriating Greqo, I'm not too concerned about it.  Yes, you could use it to spew blog spam, but there are plenty of tools out there that probably do a much better job.  And Blogger limits the number of posts one can post a day (as the &lt;a href="http://lastgoogle.blogspot.com/"&gt;Last Google blog&lt;/a&gt; regularly discovers.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-3018180582278111328?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/3018180582278111328/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=3018180582278111328' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/3018180582278111328'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/3018180582278111328'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/07/greqo-russian-blog-spammers-class-of.html' title='Greqo: The Russian Blog-Spammer&apos;s Class of Choice?'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-3668159692030357421</id><published>2007-07-20T11:09:00.000-07:00</published><updated>2007-07-20T11:11:24.131-07:00</updated><title type='text'>The Ultimate Psychic Challenge</title><content type='html'>Open up a browser.  Browse to your webmail page (e.g. Gmail).  And then invite them to log into your account.  To be fair, they are allowed to look into your eyes or massage your temples before they attempt to do so.  But they are not allowed to look at any of the post-its attached to your monitor.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-3668159692030357421?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/3668159692030357421/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=3668159692030357421' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/3668159692030357421'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/3668159692030357421'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/07/ultimate-psychic-challenge.html' title='The Ultimate Psychic Challenge'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-5463898706275476239</id><published>2007-07-15T22:37:00.000-07:00</published><updated>2007-07-15T22:43:25.321-07:00</updated><title type='text'>moshi 2.0 released</title><content type='html'>&lt;a href="http://myspacecivilized.blogspot.com/2007/07/moshi-v20-released.html"&gt;click here for the details and to pick up your copy&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The first new moshi myspace stylesheet in, what, 6 months?  And now that the mainstream media has launched the &lt;a href="http://myspacecivilized.blogspot.com/2007/07/just-in-time-for-moshi-20.html"&gt;myspace death watch&lt;/a&gt;, probably the last.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-5463898706275476239?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/5463898706275476239/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=5463898706275476239' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/5463898706275476239'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/5463898706275476239'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/07/moshi-20-released.html' title='moshi 2.0 released'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-1864376191307604534</id><published>2007-07-15T21:55:00.000-07:00</published><updated>2007-07-15T22:04:20.266-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>PHP: Memory Usage Script</title><content type='html'>The following function can give you an idea of how much memory your script is using.  It's based off a script found on the &lt;a href="http://www.php.net/manual/en/function.memory-get-usage.php#64156"&gt;php.net site&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;function memory_get_usage($echo=0)&lt;br /&gt;{&lt;br /&gt; $mb_usage = '';  // return&lt;br /&gt; &lt;br /&gt; static $last_measure = 0;&lt;br /&gt; &lt;br /&gt; $_OUT = array();&lt;br /&gt;&lt;br /&gt; // Windows (requires tasklist.exe in C:\WINDOWS\system32)&lt;br /&gt; // to download: http://www.computerhope.com/download/winxp.htm&lt;br /&gt; if ( substr(PHP_OS,0,3) == 'WIN' )&lt;br /&gt; {&lt;br /&gt;  exec( 'tasklist /FI "PID eq ' . getmypid() . '" /FO LIST', $_OUT );&lt;br /&gt;  if ( isset($_OUT[5]) )&lt;br /&gt;  {&lt;br /&gt;   $usage = preg_replace( '/[\D]/', '', $_OUT[5] ) * 1024;&lt;br /&gt;   $mb_usage = round(($usage / 1024 / 1024), 3);&lt;br /&gt;  }&lt;br /&gt;  else&lt;br /&gt;  {&lt;br /&gt;   trigger_error('tasklist failed to exec');&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; // Unix&lt;br /&gt; else&lt;br /&gt; {&lt;br /&gt;  $pid = getmypid(); &lt;br /&gt;  exec("ps -eo%mem,rss,pid | grep $pid", $_OUT); &lt;br /&gt;  $output = explode("  ", $_OUT[0]);&lt;br /&gt;  $usage = $_OUT[1] * 1024; &lt;br /&gt;  $mb_usage = round(($usage / 1024 / 1024), 3); &lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; if ( !empty($last_measure) &amp;amp;&amp;amp; $echo )&lt;br /&gt; {&lt;br /&gt;  $m3m = $mb_usage - $last_measure; &lt;br /&gt;  $m3k = $m3m * 1000;&lt;br /&gt;  echo "&amp;lt;pre style='color:#c33;'&amp;gt;memory usage: $last_measure -&amp;gt; $mb_usage | difference: $m3m MB, $m3k KB&amp;lt;/pre&amp;gt;"; &lt;br /&gt; }&lt;br /&gt; $last_measure = $mb_usage;&lt;br /&gt; &lt;br /&gt; if ( $echo ) echo "&amp;lt;pre&amp;gt;mem usage in MB: &amp;lt;b&amp;gt;$mb_usage&amp;lt;/b&amp;gt;&amp;lt;/pre&amp;gt;"; &lt;br /&gt; return $mb_usage;&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Find a test script in the Klenwell code repository: &lt;a href="http://klenwell.googlecode.com/svn/trunk/PHP/_unit_tests/test.mem_usage.php"&gt;test.mem_usage.php&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-1864376191307604534?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/1864376191307604534/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=1864376191307604534' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/1864376191307604534'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/1864376191307604534'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/07/php-memory-usage-script.html' title='PHP: Memory Usage Script'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-6701401285681597834</id><published>2007-07-12T17:28:00.000-07:00</published><updated>2007-07-12T17:48:41.348-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='php'/><category scheme='http://www.blogger.com/atom/ns#' term='wikka'/><title type='text'>Wikka: A New Page Handler Model</title><content type='html'>A while ago, I was looking at wiki packages for the LAMP platform.  I had worked with mediawiki, but felt it was a bit too much for what I wanted to do: lightweight wikis for a few small websites and my local development server.&lt;br /&gt;&lt;br /&gt;I found &lt;a href="http://wikkawiki.org/HomePage"&gt;wikka&lt;/a&gt;, tried it out, &lt;a href="http://www.klenwell.net/is/HomePage"&gt;installed it&lt;/a&gt;, and haven't had any regrets.  Still, for all its virtues, one thing I discovered with wikka is, from a web designer's point-of-view, it's not the easiest thing in the world to modify.  Granted, you can edit most features through the stylesheet easily enough.  But if you want to &lt;span style="font-style:italic;"&gt;really&lt;/span&gt; re-arrange the layout and need to touch the html markup, well, that's where things get a little hairy.&lt;br /&gt;&lt;br /&gt;You can see what I mean &lt;a href="http://wush.net/trac/wikka/browser/trunk/handlers/show/show.php"&gt;here&lt;/a&gt; -- that's the latest version of the code in question.  Here is &lt;a href="http://wikkawiki.org/KlenWell#handler_source"&gt;my proposed revision&lt;/a&gt;.  It preserves all the current elements of the code and implements a controller logic to make everything a little more orderly.  I've brought it attention to the developers of wikka (&lt;a href="http://wush.net/trac/wikka/ticket/532"&gt;Ticket #532&lt;/a&gt;).  I suspect it may conflict with some of their project conventions.  Nevertheless, conceptually, I believe it would provide a much cleaner basis for rendering display pages and I imagine it would be relatively easy from here to integrate into the main framework class as a simple templating system.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-6701401285681597834?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/6701401285681597834/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=6701401285681597834' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/6701401285681597834'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/6701401285681597834'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/07/wikka.html' title='Wikka: A New Page Handler Model'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-8951060593569571265</id><published>2007-07-06T17:51:00.000-07:00</published><updated>2007-07-06T17:56:05.218-07:00</updated><title type='text'>Praise for Greqo Blogger</title><content type='html'>Just noticed &lt;a href="http://phosphorusandlime.blogspot.com/2007/06/vbs-vbprintr.html"&gt;this comment from last week&lt;/a&gt;.  Funny, at first I thought the comment was just blog spam because of the Grego.  Then I thought Klenwell or Tom must translate as "Grego".  Finally, it dawned on my that Grego must be Google's translation from Russian of "Greqo".&lt;br /&gt;&lt;br /&gt;In any event, happy to be of service.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-8951060593569571265?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/8951060593569571265/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=8951060593569571265' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/8951060593569571265'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/8951060593569571265'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/07/praise-for-greqo-blogger.html' title='Praise for Greqo Blogger'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-6201489601052221556</id><published>2007-07-06T17:15:00.000-07:00</published><updated>2007-07-06T17:49:00.279-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='vbs'/><title type='text'>VBS: vbDataset</title><content type='html'>One of the first things that struck me when I first started working with vbscript was, "Wow, arrays in vbscript are really crappy."  I was ready to go on a whiny little tirade when I caught myself and said, "Well, maybe I'm just being spoiled after working with Php and Javascript.  I'm sure in the old days, C programmers had to build their arrays with raw bits using their bare hands."  I soon learned, however, that I'm not alone in lamenting vbscript array support:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.oreillynet.com/cs/user/view/cs_msg/28017"&gt;VBScript Weaknesses: Unforgivably Bad Array Support&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Still, I've tried to resist the temptation to bitch and moan and, instead, just make it work.  Since vbscript does support classes, I figured I could whip up my own list-like data structure.  While it has not been a slam dunk, I think I've come upon a decent solution that isn't outrageously convoluted.  I call it vbDataset.&lt;br /&gt;&lt;br /&gt;It's tailored to the project I'm working on at the moment, but may have more general applications.  I've added it to my google code repository.  If interested, you can find it there:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://klenwell.googlecode.com/svn/trunk/VBS/vbdataset/"&gt;svn repository: vbDataset&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;It includes a test script.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-6201489601052221556?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/6201489601052221556/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=6201489601052221556' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/6201489601052221556'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/6201489601052221556'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/07/vbs-vbdataset.html' title='VBS: vbDataset'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-8662908685556565570</id><published>2007-06-27T18:51:00.000-07:00</published><updated>2007-06-27T18:58:04.014-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='vbs'/><title type='text'>VBS: vbPrintR</title><content type='html'>Another vbscript function: &lt;a href="http://klenwell.googlecode.com/svn/trunk/VBS/vbprintr/printr.inc.vbs"&gt;vbPrintR&lt;/a&gt; is a function that will recursively print a vbscript variable for you.  Similar to &lt;a href="http://www.php.net/manual/en/function.print-r.php"&gt;PHP's print_r function&lt;/a&gt;.  Looked around the web for a pre-existing solution but couldnt find one, so I rolled my own.  Find it in the klenwell code repository:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://klenwell.googlecode.com/svn/trunk/VBS/vbprintr/"&gt;http://klenwell.googlecode.com/svn/trunk/VBS/vbprintr/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Includes a &lt;a href="http://klenwell.googlecode.com/svn/trunk/VBS/vbprintr/test.printr.vbs"&gt;test script&lt;/a&gt;.  On Windows, just right-click and open with Microsoft Window-Based Script Host.  On anything else, why would you even care?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-8662908685556565570?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/8662908685556565570/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=8662908685556565570' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/8662908685556565570'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/8662908685556565570'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/06/vbs-vbprintr.html' title='VBS: vbPrintR'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-3840527653371755747</id><published>2007-06-27T10:58:00.000-07:00</published><updated>2007-06-27T11:45:31.669-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='vbs'/><title type='text'>VBS: Autoload External Files</title><content type='html'>Working in vbscript for the first time in a while and one of the first things to do was to write a script to autoload external files.  This seems to work:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;' *** FILE INCLUDE HANDLER&lt;br /&gt;' Set Files to Include Here&lt;br /&gt;dim aINCLUDE(2)&lt;br /&gt;aINCLUDE(1) = "file1.inc.vbs"&lt;br /&gt;aINCLUDE(2) = "file2.inc.vbs"&lt;br /&gt;&lt;br /&gt;' Show Errors?&lt;br /&gt;Const SHOW_ERRORS = True&lt;br /&gt;Const HTML_BR = "&lt;br /&gt;"&lt;br /&gt;&lt;br /&gt;' *** SCRIPT ERROR HANDLER&lt;br /&gt;' Config&lt;br /&gt;dim oDictErr, iErrCount&lt;br /&gt;Set oDictErr = CreateObject("Scripting.Dictionary")&lt;br /&gt;iErrCount = 0&lt;br /&gt;&lt;br /&gt;' Klenwell Error Trigger&lt;br /&gt;Function kwTriggerError(sMessage)&lt;br /&gt; iErrCount = iErrCount + 1&lt;br /&gt; oDictErr.Add iErrCount, sMessage&lt;br /&gt; If SHOW_ERRORS Then: MsgBox("Error #" &amp; iErrCount &amp; " : " &amp; sMessage)&lt;br /&gt; Err.Clear()&lt;br /&gt;End Function&lt;br /&gt;&lt;br /&gt;' Klenwell Error Dump&lt;br /&gt;Sub kwDumpErrors&lt;br /&gt; dim sOut, vKey&lt;br /&gt; sOut = "Error Dump ("&amp;iErrCount&amp;" Errors): " &amp; VbCrLf&lt;br /&gt; For Each vKey In oDictErr&lt;br /&gt;  sOut = sOut &amp; "Error " &amp; vKey &amp; " in oDictErr: " &amp; oDictErr.Item(vKey) &amp; VbCrLf&lt;br /&gt; Next&lt;br /&gt; MsgBox(sOut)&lt;br /&gt;End Sub&lt;br /&gt;' *** END SCRIPT ERROR HANDLER&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;' *** FILE INCLUDE HANDLER&lt;br /&gt;' include file&lt;br /&gt;Function kwIncludeFile(sFilePath)&lt;br /&gt; On Error Resume Next&lt;br /&gt; dim oFsoInc, oFileHandler, sIncContent&lt;br /&gt; Set oFsoInc = CreateObject ("Scripting.FileSystemObject")&lt;br /&gt; &lt;br /&gt; If sFilePath = "" Then: Exit Function: End If&lt;br /&gt; &lt;br /&gt; If NOT oFsoInc.FileExists(sFilePath) Then&lt;br /&gt;  kwTriggerError("unable to load " &amp; sFilePath &amp; " : file not found")&lt;br /&gt;  Exit Function&lt;br /&gt; End If&lt;br /&gt; &lt;br /&gt; Set oFileHandler = oFsoInc.OpenTextFile(sFilePath,1)&lt;br /&gt; If Err.number &lt;&gt; 0 Then&lt;br /&gt;  kwTriggerError("file " &amp; sFilePath &amp; " could not be opened")&lt;br /&gt;  Exit Function&lt;br /&gt; End If&lt;br /&gt; &lt;br /&gt;  sIncContent = oFileHandler.ReadAll&lt;br /&gt;  oFileHandler.close&lt;br /&gt;  ExecuteGlobal sIncContent&lt;br /&gt;&lt;br /&gt; Set oFsoInc = Nothing&lt;br /&gt; Set oFileHandler = Nothing&lt;br /&gt;&lt;br /&gt;End Function&lt;br /&gt;&lt;br /&gt;' include all files&lt;br /&gt;Sub kwIncludeFiles&lt;br /&gt; dim sFile&lt;br /&gt; For Each sFile In aINCLUDE&lt;br /&gt;  kwIncludeFile(sFile)&lt;br /&gt; Next&lt;br /&gt;End Sub&lt;br /&gt;&lt;br /&gt;Call kwIncludeFiles&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Includes error handling.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-3840527653371755747?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/3840527653371755747/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=3840527653371755747' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/3840527653371755747'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/3840527653371755747'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/06/vbs-autoload-external-files.html' title='VBS: Autoload External Files'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-3548445128732629158</id><published>2007-06-26T07:59:00.000-07:00</published><updated>2008-09-02T19:59:46.137-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cranky'/><title type='text'>How to Cancel Domain Auto-Renewal for 1and1.com</title><content type='html'>&lt;span style="font-weight:bold;"&gt;Update&lt;/span&gt; (thank you anonymous commentor):&lt;br /&gt;&lt;br /&gt;Cancel here: &lt;a href="https://cancel.1and1.com"&gt;https://cancel.1and1.com&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;&lt;br /&gt;After 15 minutes searching the admin control panel, I emailed support.  8 hours later I received a reply with this link:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://faq.1and1.com/miscellaneous/2.html"&gt;http://faq.1and1.com/miscellaneous/2.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Hint: it's a separate login.  Could they make this any more difficult?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-3548445128732629158?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/3548445128732629158/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=3548445128732629158' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/3548445128732629158'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/3548445128732629158'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/06/how-to-cancel-domain-auto-renewal-for.html' title='How to Cancel Domain Auto-Renewal for 1and1.com'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-7106593795055056856</id><published>2007-06-24T18:55:00.001-07:00</published><updated>2007-06-24T19:01:41.933-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mysql'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>LampBack: Automated MySQL Backups with PHP</title><content type='html'>I started working on this &lt;a href="http://phosphorusandlime.blogspot.com/2006/12/phpmysql-mysqldump-automated-backup.html"&gt;last December&lt;/a&gt;.  Picked it up this weekend and refactored it as a PHP class.  Simplifies a number of things.&lt;br /&gt;&lt;br /&gt;What I wanted: a simple way to make regular backups of my mysql databases on shared host sites using PHP and crontabs.  LampBack does this.&lt;br /&gt;&lt;br /&gt;To try it out, visit the &lt;a href="http://code.google.com/p/lampback/"&gt;LampBack google project site&lt;/a&gt;.  Documentation can be found on the &lt;a href="http://www.klenwell.net/is/CategoryLampback"&gt;klenwell wiki&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-7106593795055056856?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/7106593795055056856/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=7106593795055056856' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/7106593795055056856'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/7106593795055056856'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/06/lampback-automated-mysql-backups-with.html' title='LampBack: Automated MySQL Backups with PHP'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-2205014630585298681</id><published>2007-06-21T18:52:00.000-07:00</published><updated>2007-06-21T19:26:08.809-07:00</updated><title type='text'>bayimg: new image host</title><content type='html'>Lot of buzz around this today.  I'm always looking for an easy-to-use free image hosting service.  My current favorite: &lt;a href="http://imageshack.us/"&gt;imageshack.com&lt;/a&gt;  &lt;br /&gt;&lt;br /&gt;Anyway, this is a test of bayimg:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://bayimg.com/FaapCAaBh"&gt;&lt;img src="http://thumbs.bayimg.com/fa/ap/ca/ab/h.jpg" alt="failed" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Well, it looks like it worked -- except it continues to enlarge it even after I disabled resizing.  Hopefully that will be fixed.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-2205014630585298681?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/2205014630585298681/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=2205014630585298681' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/2205014630585298681'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/2205014630585298681'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/06/bayimg-new-image-host.html' title='bayimg: new image host'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-6477971871269961196</id><published>2007-06-13T13:30:00.001-07:00</published><updated>2007-06-13T13:36:39.382-07:00</updated><title type='text'>How to Sign Up for Google Books</title><content type='html'>Ok, finally figured it out.&lt;br /&gt; &lt;br /&gt;After you've filled out &lt;a href="https://books.google.com/partner/signon-g"&gt;the first form&lt;/a&gt;.  You must:&lt;br /&gt;&lt;br /&gt;1. Select "I have an email address and password I already use with Google services like Adwords, Gmail, Orkut, or the personalized home page."&lt;br /&gt;&lt;br /&gt;2. Select "I'd like to choose a new login name and password just for Books."&lt;br /&gt;&lt;br /&gt;3. Use a non-Gmail email address to set up a new account&lt;br /&gt;&lt;br /&gt;Getting started is easy.  Once you know what you're doing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-6477971871269961196?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/6477971871269961196/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=6477971871269961196' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/6477971871269961196'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/6477971871269961196'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/06/how-to-sign-up-for-google-books.html' title='How to Sign Up for Google Books'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-5133804211769582062</id><published>2007-06-13T11:54:00.000-07:00</published><updated>2007-06-13T11:58:21.824-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cranky'/><title type='text'>Google Books Signup Saga, Part III</title><content type='html'>Got the following response to my second message:&lt;br /&gt;&lt;br /&gt;&lt;div class="email"&gt;Hello Tom,&lt;br /&gt;&lt;br /&gt;Thank you for your reply. I have reviewed the screenshot you provided,&lt;br /&gt;and it appears that you were unable to sign up for a Google Book Search&lt;br /&gt;account using your Gmail address. As I mentioned previously, technical&lt;br /&gt;issues are currently preventing partners from signing up for Google Book&lt;br /&gt;Search accounts with their existing Google accounts. As we work to resolve&lt;br /&gt;this issue, please feel free to sign up for a Google Book Search account&lt;br /&gt;using an email address that was not created with Gmail. I apologize for&lt;br /&gt;any inconvenience this may cause.&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;My response:&lt;br /&gt;&lt;br /&gt;&lt;div class="email"&gt;As far as I can tell, the only options you are given are to use an&lt;br /&gt;existing Google account or signup for a new one:&lt;br /&gt;&lt;br /&gt;1) I have an email address and password I already use with Google&lt;br /&gt;services like Adwords, Gmail, Orkut, or the personalized home page.&lt;br /&gt;&lt;br /&gt;2) I do not use these other services. I would like to create a new&lt;br /&gt;Google Account.&lt;br /&gt;&lt;br /&gt;screenshot: &lt;a href="http://3.bp.blogspot.com/_qkEr9USi0xI/Rm63EZEZKDI/AAAAAAAAAA0/JPbzDhzmIec/s1600-h/gbooks.bug1.png"&gt;http://3.bp.blogspot.com/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Neither option worked for me.  Is there another option that I am missing?&lt;br /&gt;&lt;br /&gt;Thanks,&lt;br /&gt;Tom&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Still unable to signup.  And it doesn't look like anyone else has been able to either.  Wonder how long this has been going on.  Will probably end up being banned as a nuisance before the problem gets resolved.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-5133804211769582062?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/5133804211769582062/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=5133804211769582062' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/5133804211769582062'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/5133804211769582062'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/06/google-books-signup-saga-part-iii.html' title='Google Books Signup Saga, Part III'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-1851830629860799932</id><published>2007-06-13T08:41:00.000-07:00</published><updated>2007-06-13T08:48:01.539-07:00</updated><title type='text'>PHP: Greqo Analytics Released</title><content type='html'>An alpha version, but it has succeeded in accomplishing what I set out for it to do: deliver an email summary of stats &lt;span style="font-style:italic;"&gt;in-text&lt;/span&gt; from my Google Analytics account.&lt;br /&gt;&lt;br /&gt;It comes with &lt;a href="http://greqo.googlecode.com/svn/trunk/analytics.class.php"&gt;Greqo Analytics&lt;/a&gt;, a PHP class that will query you Google Analytics account and collect the data for a given profile, and &lt;a href="http://greqo.googlecode.com/svn/trunk/gmail.class.php"&gt;Greqo Gmailer&lt;/a&gt;, a class that can email the results to you using that same Google Accounts account.&lt;br /&gt;&lt;br /&gt;Download: &lt;a href="http://code.google.com/p/greqo/"&gt;Greqo project site&lt;/a&gt;&lt;br /&gt;Documentation: &lt;a href="http://www.klenwell.net/is/GreqoAnalytics"&gt;klenwell wiki&lt;/a&gt;&lt;br /&gt;Feedback: &lt;a href="mailto:klenwell@gmail.com"&gt;email&lt;/a&gt;&lt;br /&gt;Issues: &lt;a href="http://code.google.com/p/greqo/issues/list"&gt;Greqo project site&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-1851830629860799932?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/1851830629860799932/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=1851830629860799932' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/1851830629860799932'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/1851830629860799932'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/06/php-greqo-analytics-released.html' title='PHP: Greqo Analytics Released'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-4841710608390056510</id><published>2007-06-12T17:02:00.000-07:00</published><updated>2007-06-12T17:09:32.255-07:00</updated><title type='text'>Has Anyone Been Able to Sign Up with Google Books?</title><content type='html'>Got the following response from Google to my note about &lt;a href="http://phosphorusandlime.blogspot.com/2007/06/google-books-signup-bug.html"&gt;signup bug&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;div class="email"&gt;Technical issues are currently preventing our partners from signing up for a Google Book Search account with their existing Google logins. Our specialists are working hard to resolve this issue, and we apologize for the inconvenience.&lt;br /&gt;&lt;br /&gt;If you would prefer not to wait until this issue is resolved, I encourage you to submit a Google Book Search application with a different email address.&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;So I followed the advice and tried to sign up with a new email address.  The result:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_qkEr9USi0xI/Rm81PZEZKGI/AAAAAAAAABM/dC2DlzsAOpk/s1600-h/gbooks.bug3.png"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_qkEr9USi0xI/Rm81PZEZKGI/AAAAAAAAABM/dC2DlzsAOpk/s320/gbooks.bug3.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5075333843613460578" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;At the moment, it appears impossible to sign up for the Google Books Partner Program.  I've followed up with Google.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-4841710608390056510?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/4841710608390056510/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=4841710608390056510' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/4841710608390056510'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/4841710608390056510'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/06/has-anyone-been-able-to-sign-up-with.html' title='Has Anyone Been Able to Sign Up with Google Books?'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_qkEr9USi0xI/Rm81PZEZKGI/AAAAAAAAABM/dC2DlzsAOpk/s72-c/gbooks.bug3.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-1224511262713180986</id><published>2007-06-12T08:04:00.001-07:00</published><updated>2007-06-13T08:48:57.645-07:00</updated><title type='text'>Google Books Signup Bug</title><content type='html'>I have tried a couple times now to sign up with Google Books using this account and I always end up with the following problem:&lt;br /&gt;&lt;br /&gt;Screen 1:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_qkEr9USi0xI/Rm63EZEZKDI/AAAAAAAAAA0/JPbzDhzmIec/s1600-h/gbooks.bug1.png"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_qkEr9USi0xI/Rm63EZEZKDI/AAAAAAAAAA0/JPbzDhzmIec/s320/gbooks.bug1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5075195116169799730" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Screen 2:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_qkEr9USi0xI/Rm63QpEZKEI/AAAAAAAAAA8/oO-p7OuDKFw/s1600-h/gbooks.bug2.png"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_qkEr9USi0xI/Rm63QpEZKEI/AAAAAAAAAA8/oO-p7OuDKFw/s320/gbooks.bug2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5075195326623197250" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Tried the new account option, too.  That didn't work.  Frustrating.  Using Firefox.  Wonder if it works any better in IE?  &lt;a href="https://books.google.com/partner/contact"&gt;Dropped a note&lt;/a&gt; to Google.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-1224511262713180986?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/1224511262713180986/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=1224511262713180986' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/1224511262713180986'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/1224511262713180986'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/06/google-books-signup-bug.html' title='Google Books Signup Bug'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_qkEr9USi0xI/Rm63EZEZKDI/AAAAAAAAAA0/JPbzDhzmIec/s72-c/gbooks.bug1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-8062856865041660453</id><published>2007-06-08T11:51:00.001-07:00</published><updated>2007-06-08T12:02:50.846-07:00</updated><title type='text'>Sharepoint Markup</title><content type='html'>I used to think Myspace markup was a travesty.  Until I saw Sharepoint.  I realize that some degree of cruftiness is inevitable, given how Sharepoint works.  But that still doesn't excuse this:&lt;br /&gt;&lt;br /&gt;&lt;div class="ipod"&gt; &amp;lt;TR&amp;gt;&lt;br /&gt;   &amp;lt;TD class="ms-leftareacell" valign=top height=100% id="LeftNavigationAreaCell"&amp;gt;&lt;br /&gt;    &amp;lt;table class=ms-nav width=100% height=100% cellpadding=0 cellspacing=0&amp;gt;&lt;br /&gt;  &amp;lt;tr&amp;gt;&lt;br /&gt;   &amp;lt;td&amp;gt;&lt;br /&gt;    &amp;lt;TABLE height="100%" class=ms-navframe CELLPADDING=0 CELLSPACING=0 border="0"&amp;gt;&lt;br /&gt;     &amp;lt;tr valign="top"&amp;gt;&lt;br /&gt;   &amp;lt;td width="4px"&amp;gt;&amp;lt;IMG SRC="/_layouts/images/blank.gif" width=4 height=1 alt=""&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;   &amp;lt;td valign="top" width="100%"&amp;gt;&lt;br /&gt;     &amp;lt;asp:ContentPlaceHolder id="PlaceHolderLeftNavBarDataSource" runat="server" /&amp;gt;&lt;br /&gt;     &amp;lt;asp:ContentPlaceHolder id="PlaceHolderCalendarNavigator" runat="server" /&amp;gt;&lt;br /&gt;     &amp;lt;asp:ContentPlaceHolder id="PlaceHolderLeftNavBarTop" runat="server"/&amp;gt;&lt;br /&gt;     &amp;lt;asp:ContentPlaceHolder id="PlaceHolderLeftNavBar" runat="server"&amp;gt;&lt;br /&gt;    &amp;lt;div class="ms-quicklaunchouter"&amp;gt;&lt;br /&gt;    &amp;lt;div class="ms-quickLaunch" style="width:100%"&amp;gt;&lt;br /&gt;    &amp;lt;h3 class="ms-standardheader"&amp;gt;&amp;lt;label class="ms-hidden"&amp;gt;&lt;br /&gt;    &amp;lt;SharePoint:EncodedLiteral runat="server" text="&amp;lt;%$Resources:wss,quiklnch_pagetitle%&amp;gt;" EncodeMethod="HtmlEncode"/&amp;gt;&amp;lt;/label&amp;gt;&lt;br /&gt;    &amp;lt;Sharepoint:SPSecurityTrimmedControl runat="server" PermissionsString="ViewFormPages"&amp;gt;&lt;br /&gt;    &amp;lt;div class="ms-quicklaunchheader"&amp;gt;&amp;lt;SharePoint:SPLinkButton id="idNavLinkViewAll" runat="server" NavigateUrl="~site/_layouts/viewlsts.aspx" Text="&amp;lt;%$Resources:wss,quiklnch_allcontent%&amp;gt;" AccessKey="&amp;lt;%$Resources:wss,quiklnch_allcontent_AK%&amp;gt;"/&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;    &amp;lt;/SharePoint:SPSecurityTrimmedControl&amp;gt;&lt;br /&gt;    &amp;lt;/h3&amp;gt;&lt;br /&gt;    &amp;lt;Sharepoint:SPNavigationManager&lt;br /&gt;    id="QuickLaunchNavigationManager"&lt;br /&gt;    runat="server"&lt;br /&gt;    QuickLaunchControlId="QuickLaunchMenu"&lt;br /&gt;    ContainedControl="QuickLaunch"&lt;br /&gt;    EnableViewState="false"&amp;gt;&lt;br /&gt;    &amp;lt;div&amp;gt;&lt;br /&gt;     &amp;lt;SharePoint:DelegateControl runat="server"&lt;br /&gt;      ControlId="QuickLaunchDataSource"&amp;gt;&lt;br /&gt;      &amp;lt;Template_Controls&amp;gt;&lt;br /&gt;      &amp;lt;asp:SiteMapDataSource&lt;br /&gt;      SiteMapProvider="SPNavigationProvider"&lt;br /&gt;      ShowStartingNode="False"&lt;br /&gt;      id="QuickLaunchSiteMap"&lt;br /&gt;      StartingNodeUrl="sid:1025"&lt;br /&gt;      runat="server"&lt;br /&gt;      /&amp;gt;&lt;br /&gt;      &amp;lt;/Template_Controls&amp;gt;&lt;br /&gt;     &amp;lt;/SharePoint:DelegateControl&amp;gt;&lt;br /&gt;     &amp;lt;SharePoint:AspMenu&lt;br /&gt;     id="QuickLaunchMenu"&lt;br /&gt;     DataSourceId="QuickLaunchSiteMap"&lt;br /&gt;     runat="server"&lt;br /&gt;     Orientation="Vertical"&lt;br /&gt;     StaticDisplayLevels="2"&lt;br /&gt;     ItemWrap="true"&lt;br /&gt;     MaximumDynamicDisplayLevels="0"&lt;br /&gt;     StaticSubMenuIndent="0"&lt;br /&gt;     SkipLinkText=""&lt;br /&gt;     &amp;gt;&lt;br /&gt;     &amp;lt;LevelMenuItemStyles&amp;gt;&lt;br /&gt;      &amp;lt;asp:MenuItemStyle CssClass="ms-navheader"/&amp;gt;&lt;br /&gt;      &amp;lt;asp:MenuItemStyle CssClass="ms-navitem"/&amp;gt;&lt;br /&gt;     &amp;lt;/LevelMenuItemStyles&amp;gt;&lt;br /&gt;     &amp;lt;LevelSubMenuStyles&amp;gt;&lt;br /&gt;      &amp;lt;asp:SubMenuStyle CssClass="ms-navSubMenu1"/&amp;gt;&lt;br /&gt;      &amp;lt;asp:SubMenuStyle CssClass="ms-navSubMenu2"/&amp;gt;&lt;br /&gt;     &amp;lt;/LevelSubMenuStyles&amp;gt;&lt;br /&gt;     &amp;lt;LevelSelectedStyles&amp;gt;&lt;br /&gt;      &amp;lt;asp:MenuItemStyle CssClass="ms-selectednavheader"/&amp;gt;&lt;br /&gt;      &amp;lt;asp:MenuItemStyle CssClass="ms-selectednav"/&amp;gt;&lt;br /&gt;     &amp;lt;/LevelSelectedStyles&amp;gt;&lt;br /&gt;    &amp;lt;/SharePoint:AspMenu&amp;gt;&lt;br /&gt;    &amp;lt;/div&amp;gt;&lt;br /&gt;    &amp;lt;/Sharepoint:SPNavigationManager&amp;gt;&lt;br /&gt;    &amp;lt;Sharepoint:SPNavigationManager&lt;br /&gt;    id="TreeViewNavigationManager"&lt;br /&gt;    runat="server"&lt;br /&gt;    ContainedControl="TreeView"&amp;gt;&lt;br /&gt;      &amp;lt;table class="ms-navSubMenu1" cellpadding="0" cellspacing="0" border="0"&amp;gt;&lt;br /&gt;     &amp;lt;tr&amp;gt;&lt;br /&gt;       &amp;lt;td&amp;gt;&lt;br /&gt;      &amp;lt;table class="ms-navheader" width="100%" cellpadding="0" cellspacing="0" border="0"&amp;gt;&lt;br /&gt;        &amp;lt;tr&amp;gt;&lt;br /&gt;       &amp;lt;td nowrap id="idSiteHierarchy"&amp;gt;&lt;br /&gt;         &amp;lt;SharePoint:SPLinkButton runat="server" NavigateUrl="~site/_layouts/viewlsts.aspx" id="idNavLinkSiteHierarchy" Text="&amp;lt;%$Resources:wss,treeview_header%&amp;gt;" AccessKey="&amp;lt;%$Resources:wss,quiklnch_allcontent_AK%&amp;gt;"/&amp;gt;&lt;br /&gt;       &amp;lt;/td&amp;gt;&lt;br /&gt;        &amp;lt;/tr&amp;gt;&lt;br /&gt;      &amp;lt;/table&amp;gt;&lt;br /&gt;       &amp;lt;/td&amp;gt;&lt;br /&gt;     &amp;lt;/tr&amp;gt;&lt;br /&gt;      &amp;lt;/table&amp;gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;(I still think myspace html is a travesty.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-8062856865041660453?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/8062856865041660453/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=8062856865041660453' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/8062856865041660453'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/8062856865041660453'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/06/sharepoint-markup.html' title='Sharepoint Markup'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-3076489243288122720</id><published>2007-06-04T15:19:00.001-07:00</published><updated>2007-06-08T12:02:20.116-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='svn'/><title type='text'>Difference between Branch and Tag</title><content type='html'>I still get these confused, so I thought it might help me remember if I explained it to myself:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;branch&lt;/span&gt;&lt;br /&gt;a separate &lt;span style="font-style:italic;"&gt;branch&lt;/span&gt; of development that is usually merged back into the trunk&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;tag&lt;/span&gt;&lt;br /&gt;a branch &lt;span style="font-style:italic;"&gt;tagged&lt;/span&gt; for versioning or historical reasons&lt;br /&gt;&lt;br /&gt;If you're using Tortoise, right-click for more help.&lt;br /&gt;&lt;br /&gt;source: &lt;a href="http://tortoisesvn.net/docs/release/TortoiseSVN_en/tsvn-dug-branchtag.html#tsvn-dug-branch-1"&gt;Tortoise SVN help&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-3076489243288122720?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/3076489243288122720/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=3076489243288122720' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/3076489243288122720'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/3076489243288122720'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/06/difference-between-branch-and-tag.html' title='Difference between Branch and Tag'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-8965214990011376767</id><published>2007-05-30T12:00:00.000-07:00</published><updated>2007-05-30T12:09:46.745-07:00</updated><title type='text'>HTA Template</title><content type='html'>As much as I don't love Microsoft, if you're creating an HTML application for a strictly Windows environment (as I am for the moment), HTAs can be very handy.  I've created a generic template for use with VBScript that can get you started, available for download here:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://code.google.com/p/klenwell/downloads/list"&gt;HTA VBScript Template&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;More info on HTAs can be found at the Microsoft site:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.microsoft.com/technet/scriptcenter/topics/htas/tutorial2.mspx"&gt;HTAs for Beginners&lt;/a&gt; (microsoft.com)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-8965214990011376767?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/8965214990011376767/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=8965214990011376767' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/8965214990011376767'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/8965214990011376767'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/05/hta-template.html' title='HTA Template'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-7902205153661502352</id><published>2007-05-10T15:26:00.000-07:00</published><updated>2010-04-10T07:34:44.429-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>PHPMailer with Gmail</title><content type='html'>&lt;a href="http://phpmailer.sourceforge.net/"&gt;PHPMailer&lt;/a&gt; is my open source class-of-choice for handling email operation in PHP.  &lt;a href="http://www.klenwell.com/is/PhpGmailMailer"&gt;GmailMailer&lt;/a&gt; is an extension of PHPMailer that allows you to use PHPMailer with a Gmail account.  I found a few other hacks of PHPMailer that accomplished this.  But they did so by tweaking the PHPMailer code itself.  I wanted something that enabled PHPMailer to work with Gmail without touching the underlying code.&lt;br /&gt;&lt;br /&gt;Documentation is available at the &lt;a href="http://www.klenwell.com/is/PhpGmailMailer"&gt;klenwell wiki&lt;/a&gt;.  The class can be downloaded from the &lt;a href="http://code.google.com/p/klenwell/downloads/list"&gt;klenwell google code site&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-7902205153661502352?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/7902205153661502352/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=7902205153661502352' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/7902205153661502352'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/7902205153661502352'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/05/phpmailer-with-gmail.html' title='PHPMailer with Gmail'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-7658148940471720492</id><published>2007-04-18T08:53:00.000-07:00</published><updated>2007-04-18T09:09:19.520-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='dom'/><title type='text'>JS : IE lacks class</title><content type='html'>Encountered a problem yesterday on IE trying to apply style sheet setting to a class name that had been dynamically set using DOM.  Worked on Firefox, failing on IE.  Isolated the problem and summarized it as:&lt;br /&gt;&lt;br /&gt;"ie set class name css"&lt;br /&gt;&lt;br /&gt;That is &lt;a href="http://www.google.com/search?hl=en&amp;q=ie+set+class+name+css&amp;btnG=Google+Search"&gt;the search&lt;/a&gt; that led to &lt;a href="http://blogs.gsl.com/dougclinton/2006/10/02/setting-the-css-class-name-on-dom-elements-created-in-javascript/"&gt;this nice write-up&lt;/a&gt; which offers a solution and also links by comment to &lt;a href="http://mykenta.blogspot.com/2006/07/standardise-ie-setattribute-part-2.html"&gt;this more thorough solution&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Anyway, I'm starting &lt;a href="http://www.klenwell.net/is/JavascriptExceptions"&gt;a page on my wiki&lt;/a&gt; for all the aggravating little exceptions I find in javascript/DOM implementation.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-7658148940471720492?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/7658148940471720492/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=7658148940471720492' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/7658148940471720492'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/7658148940471720492'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/04/js-ie-lacks-class.html' title='JS : IE lacks class'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-960351271977086322</id><published>2007-04-13T11:51:00.000-07:00</published><updated>2007-04-13T11:57:52.991-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><title type='text'>JS : Kwyption</title><content type='html'>Kwyption is a javascript class that uses javascript implementations of md5 and rc4 to provide a simple object interface for encrypting and decrypting strings.  A demo can be found here:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://klenwell.googlepages.com/demo.kwyption.htm"&gt;http://klenwell.googlepages.com/demo.kwyption.htm&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-960351271977086322?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/960351271977086322/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=960351271977086322' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/960351271977086322'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/960351271977086322'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/04/js-kwyption.html' title='JS : Kwyption'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-7301081385047599943</id><published>2007-04-11T15:06:00.000-07:00</published><updated>2007-04-11T15:17:15.228-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><title type='text'>J.ini Javascript Micro-Framework</title><content type='html'>I've been working with Javascript a lot lately and that has led me back to an old challenge: developing a simple, clean framework for dynamically loading javascript classes.  Most the mature javascript and AJAX frameworks have this, but upon examination, most proved too involved.  I wanted something that could be set up simply for a new class and, ideally, be used for multiple classes in coordination.  &lt;br /&gt;&lt;br /&gt;After much research, trial, and tribulation, I think I've arrived at something that accomplishes this.  I call it J.ini, or jini.  More details can be found here:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.klenwell.net/is/JavascriptJini"&gt;http://www.klenwell.net/is/JavascriptJini&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;A simple demo:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://klenwell.googlepages.com/demo.jini.htm"&gt;http://klenwell.googlepages.com/demo.jini.htm&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-7301081385047599943?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/7301081385047599943/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=7301081385047599943' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/7301081385047599943'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/7301081385047599943'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/04/jini-javascript-micro-framework.html' title='J.ini Javascript Micro-Framework'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-490718011292651819</id><published>2007-03-16T16:13:00.000-07:00</published><updated>2007-03-16T16:19:57.943-07:00</updated><title type='text'>PHP: Secure Login</title><content type='html'>After some difficulties in trying to integrate a PHP/MySQL login library using the shared SSL certificate on a cheap, shared host, I started thinking about ways to implement a login class that didn't require SSL but would still not send sensitive info in the clear.  I googled the terms "php javascript login hash" and found this page:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://marakana.com/blog/examples/php-implementing-secure-login-with-php-javascript-and-sessions-without-ssl.html"&gt;PHP - Implementing Secure Login with PHP, JavaScript, and Sessions (without SSL)&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The same basic idea -- even uses the &lt;a href="http://pajhome.org.uk/crypt/md5/"&gt;JS md5 library&lt;/a&gt; I had used in my &lt;a href="http://mushpup.org/"&gt;mushpup site&lt;/a&gt;.  Mine would be a little different in that it would query a SQL database, raising questions about the compatability of the JS md5 function and MySQL's.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-490718011292651819?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/490718011292651819/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=490718011292651819' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/490718011292651819'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/490718011292651819'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/03/php-secure-login.html' title='PHP: Secure Login'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-3853546115294206520</id><published>2007-03-16T12:35:00.000-07:00</published><updated>2007-03-16T16:24:53.845-07:00</updated><title type='text'>What Adsense Thinks of My Site (or its audience)</title><content type='html'>Headline of ad currently running on &lt;a href="http://myspacecivilized.blogspot.com/"&gt;another one of my sites&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Buy Gay Friendly Autos&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-3853546115294206520?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/3853546115294206520/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=3853546115294206520' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/3853546115294206520'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/3853546115294206520'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/03/what-adsense-thinks-of-my-site-or-its.html' title='What Adsense Thinks of My Site (or its audience)'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-4135638884633070756</id><published>2007-03-12T15:39:00.000-07:00</published><updated>2007-03-12T15:44:17.130-07:00</updated><title type='text'>The Sonnet Monkiad</title><content type='html'>After a few tweaks to its editing and publishing engines, the Sonnet Monkiad (the first epic poem of the internet age written by a digital monkey dictating to a virtual editor publishing to a blog), is now running more or less smoothly.  The plan is for it to steadily evolve and go on forever.&lt;br /&gt;&lt;br /&gt;You can follow the post-epic epic here:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://sonnetmonkiad.blogspot.com/"&gt;sonnetmonkiad.blogspot.com&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-4135638884633070756?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/4135638884633070756/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=4135638884633070756' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/4135638884633070756'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/4135638884633070756'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/03/sonnet-monkiad.html' title='The Sonnet Monkiad'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-2254095554076499944</id><published>2007-03-03T10:31:00.000-08:00</published><updated>2007-03-03T10:33:32.611-08:00</updated><title type='text'>bloggerstack</title><content type='html'>The &lt;a href="http://bloggerstack.blogspot.com/"&gt;bloggerstack project&lt;/a&gt; has been &lt;a href="http://bloggerstack.blogspot.com/2007/03/bloggerstack-revived.html"&gt;updated&lt;/a&gt; to reflect the changes following the blogger re-release.  More information on bloggerstack and how you can use it to edit your blog template are available at the &lt;a href="http://bloggerstack.blogspot.com/"&gt;bloggerstack blog&lt;/a&gt; and &lt;a href="http://code.google.com/p/bloggerstack/"&gt;google project page&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-2254095554076499944?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/2254095554076499944/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=2254095554076499944' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/2254095554076499944'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/2254095554076499944'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/03/bloggerstack.html' title='bloggerstack'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-1614708083396261412</id><published>2007-02-20T13:38:00.000-08:00</published><updated>2007-02-20T13:40:39.273-08:00</updated><title type='text'>sonnetmonkey.com</title><content type='html'>&lt;a href="http://www.sonnetmonkey.com/"&gt;sonnetmonkey.com&lt;/a&gt; is finally a reality.  The typical unexpected difficulties in getting the server set up, but our host was great in assisting us.&lt;br /&gt;&lt;br /&gt;Celebrate with the sonnet monkeys at their new artist's retreat at &lt;a href="http://www.sonnetmonkey.com/colony/"&gt;Bananaloaf&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-1614708083396261412?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/1614708083396261412/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=1614708083396261412' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/1614708083396261412'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/1614708083396261412'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/02/sonnetmonkeycom.html' title='sonnetmonkey.com'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-417803005898478896</id><published>2007-02-09T08:34:00.000-08:00</published><updated>2007-02-08T18:08:49.253-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ISP'/><category scheme='http://www.blogger.com/atom/ns#' term='cranky'/><title type='text'>Earthlink Downgraded to Sell</title><content type='html'>This response to &lt;a href="http://phosphorusandlime.blogspot.com/2007/02/earthlink-wifi-update.html"&gt;my support request&lt;/a&gt; a couple days ago utterly ignores the details of my report and shows me nothing but polite contempt.  Take that back.  Assuming I use IE: &lt;span style="font-style:italic;"&gt;utter&lt;/span&gt; contempt.&lt;br /&gt;&lt;br /&gt;&lt;div class="email"&gt;Dear Tom,&lt;br /&gt;&lt;br /&gt;Thank you for contacting us.&lt;br /&gt;&lt;br /&gt;Please accept our sincere apologies for the inconvenience caused to you.&lt;br /&gt;&lt;br /&gt;We understand that you are experiencing a slow Wi-Fi connection and are unable to browse any web sites except Google. You would like to know how   to get these issues resolved.&lt;br /&gt;&lt;br /&gt;To resolve these issues, we suggest you follow all the instructions given below:&lt;br /&gt;&lt;br /&gt;If you use Internet Explorer, please reset its settings by following the steps below:&lt;br /&gt;1. Open Internet Explorer, click on Tools, click on Internet Options.&lt;br /&gt;2. On the General tab, under Temporary Internet Files, please click&lt;br /&gt;  Delete Cookies.&lt;br /&gt;3. When asked if you are sure, please click Yes.&lt;br /&gt;4. Still in the Temporary Internet Files area, please click Delete&lt;br /&gt;  Files.&lt;br /&gt;  In the box that pops up, please put a check in Delete All Offline&lt;br /&gt;  Content, and click OK.&lt;br /&gt;5. Click Settings to the right of Delete Files.&lt;br /&gt;6. Set the Amount of disk space to use: to 10 MB&lt;br /&gt;7. Click OK&lt;br /&gt;8. Click the Programs tab.&lt;br /&gt;9. Click the Reset Web Settings button towards the bottom&lt;br /&gt;  Uncheck the Reset Homepage box if you want to keep your current&lt;br /&gt;  Homepage.&lt;br /&gt;10. Click Yes, Click OK&lt;br /&gt;11. Click on the Advanced tab, Click on the Restore Defaults button at the bottom.&lt;br /&gt;12. Click on the Security tab, select the globe that says Internet.&lt;br /&gt;13. Click on the Default Level button at the bottom of the page.&lt;br /&gt;14. In the same way select all other icons next to the globe (Internet), one at a time and click on the corresponding 'Default Level' buttons.&lt;br /&gt;15. Click Apply.&lt;br /&gt;16. Click OK.&lt;br /&gt;&lt;br /&gt;If you follow the above steps, you will be able to reset the settings of Internet Explorer.&lt;br /&gt;&lt;br /&gt;Also, please disable the proxy server in Internet Explorer by following the steps given below:&lt;br /&gt;&lt;br /&gt;1. Open Internet Explorer.&lt;br /&gt;2. Click on Tools again and select Internet Options.&lt;br /&gt;3. Click on the Connections tab.&lt;br /&gt;4. Select the radio box next to Never dial a connection (if it is not grayed out).&lt;br /&gt;5. Click on the LAN Settings button and UNCHECK all boxes except the one next to 'Automatically detect settings'.&lt;br /&gt;6. Click OK.&lt;br /&gt;7. Click Apply.&lt;br /&gt;8. Click OK.&lt;br /&gt;&lt;br /&gt;If you follow the above steps, you will be able to disable any proxy options that may have been enabled.&lt;br /&gt;&lt;br /&gt;Please follow all the instructions provided in the link below:&lt;br /&gt;&lt;br /&gt;http://kb.earthlink.net/case.asp?article=187618&lt;br /&gt;&lt;br /&gt;However, if the issue still persists, it will require active troubleshooting that can only be accomplished by working with someone in real time.&lt;br /&gt;&lt;br /&gt;In order to help you as efficiently as possible, we recommend that you contact Technical Support by phone on 877.Wifi-Help (877.943-4435).&lt;br /&gt;&lt;br /&gt;As you can understand, email medium has its own limitations in that it cannot be interactive and active step-by-step troubleshooting is not possible via email. For this reason we are asking you to contact us in real time. Email/Chat support for EarthLink Wi-Fi is currently unavailable.&lt;br /&gt;&lt;br /&gt;We can understand it could be frustrating if a technical issue does not get resolved quickly. Due to the nature of the issue and its complexity, it is not possible to assist you via email, and we are asking you to contact in real time.&lt;br /&gt;&lt;br /&gt;We apologize for any inconvenience. Your patience and understanding are highly commendable.&lt;br /&gt;&lt;br /&gt;Rodriguez K 4141&lt;br /&gt;EarthLink Electronic Customer Support&lt;br /&gt;EarthLink, Inc.&lt;br /&gt;Case ID 79827574&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-417803005898478896?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/417803005898478896/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=417803005898478896' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/417803005898478896'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/417803005898478896'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/02/earthlink-downgraded-to-sell.html' title='Earthlink Downgraded to Sell'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-4325460108929886893</id><published>2007-02-08T17:49:00.000-08:00</published><updated>2007-02-08T18:01:24.522-08:00</updated><title type='text'>PHP: Create Your Own Richter Scale</title><content type='html'>This formula provides a way to take any set of somewhat arbitrary data and put it on a scale of your choosing.  I used it specifically for frequency values in a wordlist I had, but it has a variety of applications.&lt;br /&gt;&lt;br /&gt;The key to this formula is the conversion of bases, using this formula:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;exp = log(result) / log(base)&lt;/div&gt;  &lt;br /&gt;&lt;br /&gt;Here's the code (values are configurable):&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt; // 100 pt logarithmic scale&lt;br /&gt; $max_raw_value = 18349;&lt;br /&gt; $scale_max = 100;&lt;br /&gt;&lt;br /&gt; $scaled_value = round( log($raw_value)/log(pow($max_raw_value,1/$scale_max)) );&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Note that a $raw_value of 1 will equal 0, which wasn't valid for my use.  So I converted raw values of 1 to 1.1, which resulted in a scaled value of 1.&lt;br /&gt;&lt;br /&gt;I might also note that this lead me to my first practical application of logarithms.  (I just wish my calculus teacher in high school would have offered a practical example like this.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-4325460108929886893?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/4325460108929886893/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=4325460108929886893' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/4325460108929886893'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/4325460108929886893'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/02/php-create-your-own-richter-scale.html' title='PHP: Create Your Own Richter Scale'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-5340139335900887970</id><published>2007-02-08T08:54:00.000-08:00</published><updated>2007-02-08T17:57:42.405-08:00</updated><title type='text'>Proposal for an User ID API</title><content type='html'>As a website developer and administrator, I've explored the &lt;a href="http://openid.net/"&gt;OpenID site&lt;/a&gt;, read the recent articles about Microsoft's tentative endorsement of it, studied the &lt;a href="http://yro.slashdot.org/article.pl?sid=07/02/06/2152214"&gt;comments about the announcement on Slashdot&lt;/a&gt;, and I confess it still doesn't fully make sense to me.  What would make sense is a User ID API along the lines of what Google is now offering with their &lt;a href="http://code.google.com/apis/gdata/index.html"&gt;GData API suite&lt;/a&gt;.  It wouldn't necessarily have to be Google, but it would probably have to be an established email or login broker like Google, Yahoo!, MSN, perhaps even Wikipedia or Myspace.  More ideally, still, it might be a non-profit or government organization.  (If we're going to have a SSN or national ID card, why not a national email address?  The states of CA or MA could lead the way if necessary, though I admit I'd have more faith in a Google or Yahoo.)  More than one API would be fine, as long as they were simple to deploy, as protective as possible of user's privacy, reliable and convenient, and attractive to smaller site admins.&lt;br /&gt;&lt;br /&gt;How would it work?  Here's a rough scenario based on how the Google API functions.  Imagine you have a blog where you'd like to limit comments from new, unidentified visitors but don't want to put them through the hassle of registering with your site or solving a CAPTCHA every time they visit.  You have your comment form with email field.  When unknown visitor submits comment, the info gets relayed to the appropriate API server, which then could return relevant authenticating data.  This data might include:&lt;br /&gt;&lt;br /&gt;boolean indicating if active cookie is currently set for visitor&lt;br /&gt;unix timestamp indicating when this account was created/registered&lt;br /&gt;unix timestamp indicating last time this account was active&lt;br /&gt;user's display name&lt;br /&gt;url for hot-linkable user profile image (opt-in)&lt;br /&gt;other opt-in profile information&lt;br /&gt;&lt;br /&gt;The API would enable the site admin to define restrictions and hurdles based on the data returned.  For instance, if the site admin finds she is getting a lot of spam for Gmail account created within the last three days, she could create script to require CAPTCHA validation for accounts less than 3 days old, etc.&lt;br /&gt;&lt;br /&gt;The incentive for account authenticating services like Google or Yahoo would be obvious.&lt;br /&gt;&lt;br /&gt;The drawbacks?  The first one that springs to mind would be the leviathan one: do we want to centralize this service and trust public ID authentication to a large corporation (Auth Super Site) like Google or Yahoo?  Wouldn't they be in perfect position to abuse this power down the line?  Perhaps.  The service would necessarily require aggregation of data with a large, central authority.  But this has already been done with the major webmail and social networking site, which is why they make perfect candidates.  And the data does not have to be that personal.  Basically, just a user id and something indicating that the user has been around for a while and is not a spammer or hacker.&lt;br /&gt;&lt;br /&gt;Also, the service could allow site admins to send data back to the Auth Super Site on abusive behavior.  For example, code:900 (possible spam) user input:love your site, hey check out mine.&lt;br /&gt;&lt;br /&gt;Such a service would seem to fit hand-in-glove with what Google is doing with their ClientLogin API and Analytics and Website Tool services.  (Perhaps they have something like this in the works?)  I'm a big proponent of this kind of service.  Is anyone else hoping for something like this?  Is there some falsifier or are there other drawbacks that I'm missing?&lt;br /&gt;&lt;br /&gt;I'm going to start circulating this idea in the hope of getting a discussion going.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-5340139335900887970?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/5340139335900887970/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=5340139335900887970' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/5340139335900887970'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/5340139335900887970'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/02/proposal-for-user-id-api.html' title='Proposal for an User ID API'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-5322508790314435853</id><published>2007-02-07T16:53:00.000-08:00</published><updated>2007-02-08T17:59:19.297-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ISP'/><category scheme='http://www.blogger.com/atom/ns#' term='cranky'/><title type='text'>Earthlink Wifi Update</title><content type='html'>My Earthlink wireless account has been virtually unusable the last 2 weeks.  As this is more than 6 months after it was deployed, it seems to me a bad sign that things are getting worse, rather than better.&lt;br /&gt;&lt;br /&gt;And, of course, now the support line just leaves me on hold, leading me to suspect a general degradation in service.&lt;br /&gt;&lt;br /&gt;Sent the following message using their website "email" form.&lt;br /&gt;&lt;br /&gt;&lt;div class="email"&gt;I signed up for Earthlink Anaheim last August after first hearing about its release.  (See http://phosphorusandlime.blogspot.com/2006/08/earthlink-wifi-anaheim.html)  Until two weeks ago, the service had been adequate if not great.  Over the last two weeks, however, my frustration with it has boiled over.  These are the main issues causing my dissatisfaction:&lt;br /&gt;&lt;br /&gt;1. Service has been all but useless last two weeks.  Before noon, service is intermittent.  After noon, I am usually unable to load any pages except for Google -- even when the modem says the connection is good or better.  I have tried repowering the modem, repositioning the antenna, etc.  Nothing helps.  It seems like there has been some kind of degradation with the signal -- or a problem with some kind of a proxy server?&lt;br /&gt;&lt;br /&gt;2. I have never been able to connect with my wireless card, even when I have been across the street from City Hall.&lt;br /&gt;&lt;br /&gt;3. I'd like an email address for a support tech.  I was unable to find one in my signup package or on your website.  I have been unable to get a hold of anyone on your support line.  Online chat only intensifies my frustration.&lt;br /&gt;&lt;br /&gt;Please reply to me at my email address.  Thanks,&lt;br /&gt;&lt;br /&gt;Tom&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-5322508790314435853?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/5322508790314435853/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=5322508790314435853' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/5322508790314435853'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/5322508790314435853'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/02/earthlink-wifi-update.html' title='Earthlink Wifi Update'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-3860824959032263943</id><published>2007-02-04T17:03:00.000-08:00</published><updated>2007-02-08T18:04:44.261-08:00</updated><title type='text'>Greedy Phonotactic Coordination</title><content type='html'>This was the puzzle I was trying to solve: I have a long list of English words (over 100,000 words).  It includes a phonetic representation of each word.  I want to break the phonetic representation of the word up into syllables.  Specifically, I want an algorithm that will do this for me.&lt;br /&gt;&lt;br /&gt;I'm not the first person to confront this problem:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://listserv.linguistlist.org/cgi-bin/wa?A2=ind9511b&amp;L=linguist&amp;D=0&amp;P=2559"&gt;summary of responses to syllabification algorithm query&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Surprisingly, however, I couldn't find a working algorithm to solve this problem.  Well, there was this: &lt;a href="http://www.ale.cs.toronto.edu/docs/man/ale_trale_man/ale_trale_man-node83.html"&gt;ale-trale man node 83&lt;/a&gt;.  But hell if I knew what it meant.&lt;br /&gt;&lt;br /&gt;Greedy Phonotactic Coordination is my solution.  I'm still testing it.  But there were only about 50 words that it couldn't handle in the 100,000+ list, and the majority of those were either outright foreign appropriations or mistranscriptions. &lt;br /&gt;&lt;br /&gt;A couple examples:&lt;br /&gt;&lt;br /&gt;encourages -&gt; E.n.k.3r.I.J.I.z -&gt; En.k3r.I.JIz&lt;br /&gt;mackler -&gt; m.{.k.l.3r -&gt; m{.kl3r&lt;br /&gt;petunia -&gt; p.V.t.u.n.i.V -&gt; pV.tu.ni.V&lt;br /&gt;&lt;br /&gt;How it works: basically, it finds a vowel phoneme, finds the next, and then looks at every coda/onset break between the two vowels looking for a valid combination.  It favors onsets at the outset and moves left so that it ends up with an empty onset to the next syllable and all the consonants in the coda of the current syllable.&lt;br /&gt;&lt;br /&gt;I created functions for valid onsets and codas with the information on &lt;a href="http://en.wikipedia.org/wiki/English_phonology#Phonotactics"&gt;this wikipedia page&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Not perfect.  But pretty good.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-3860824959032263943?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/3860824959032263943/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=3860824959032263943' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/3860824959032263943'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/3860824959032263943'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/02/greedy-phonotactic-coordination.html' title='Greedy Phonotactic Coordination'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-8375619559114109478</id><published>2007-01-31T09:59:00.000-08:00</published><updated>2007-01-31T10:03:40.813-08:00</updated><title type='text'>sonnet monkeys</title><content type='html'>I created the first version of my sonnetmonkey poetry project early last year but had to abandon it for other projects.  Recently, I've had some time to revisit it and I'm in the process of building what I hope will come to be the definitive digital-monkeys-typing-poetry site on the web.  Here's the first beta release:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://klenwell.net/sonnet/"&gt;sonnetmonkey beta&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;And here are some of the monkey's work:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://sonnetmonkeymanuscripts.blogspot.com/"&gt;sonnetmonkey manuscripts&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-8375619559114109478?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/8375619559114109478/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=8375619559114109478' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/8375619559114109478'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/8375619559114109478'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/01/sonnet-monkeys.html' title='sonnet monkeys'/><author><name>klenwell</name><uri>http://www.blogger.com/profile/14678597803373234378</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://klenwell.googlepages.com/self.photocopy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-116787672306143711</id><published>2007-01-03T18:00:00.000-08:00</published><updated>2007-01-03T18:13:37.623-08:00</updated><title type='text'>accountant summer</title><content type='html'>My sister, an accountant, asked me if I could whip something up for her to help her crunch some numbers.  Four months later...&lt;br /&gt;&lt;br /&gt;What she wanted specifically was a program that could be given a set of numbers and a target amount and find the combination of numbers in the set that equals (or gets really close to) the target.  I said surely there must be something in Excel that can do this for you.  Apparently not.  (Although I know now that I've finished someone will immediately point me to the Excel formula that does it.)  So I came up with a ingenious brute force attack that could handle all of 16 or 17 numbers.  Her sample set had 27.&lt;br /&gt;&lt;br /&gt;It turns out this is a variation on a well-known and somewhat complex class of math problems: &lt;a href="http://en.wikipedia.org/wiki/Combinatorial_optimization"&gt;combinatorial optimization&lt;/a&gt;.  A little further research led me to some strategies for pseudo-polynomial (as opposed to exponential) time algorithms (as an English major, I'm very proud to say that and say it every chance I get.)  Eventually I put together something that seems to do the job.&lt;br /&gt;&lt;br /&gt;Find the script here: &lt;a href="http://klenwell.net/sos/acct_summer.php"&gt;klenwell.net&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Here's the dataset my sister gave me:&lt;br /&gt;&lt;pre style="width:480px; padding:4px; border:1px solid #99f;"&gt;373,643.70 27,232,550.00 7,820.80 113,089.00&lt;br /&gt;10,250.00 13,919.75 30,763.08 83,165.38&lt;br /&gt;46,572.53 7,500.00 2,000.00 263,912.00&lt;br /&gt;1,056,367.56 275,892.42 3,000.00 60,486.01&lt;br /&gt;248.24 165,513.08 4,708.25 200.00&lt;br /&gt;1,427.28 300,000.00 400,000.00 178.77&lt;br /&gt;151,802.82 210,250.00 266,700.00&lt;/pre&gt;&lt;br /&gt;Here's the target: &lt;input name="target" value="2265923" size="8" /&gt;&lt;br /&gt;&lt;br /&gt;You can just copy and paste those in.  I found the results surprising.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-116787672306143711?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/116787672306143711/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=116787672306143711' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/116787672306143711'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/116787672306143711'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2007/01/accountant-summer.html' title='accountant summer'/><author><name>Tom</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://photos1.blogger.com/img/36/1021/640/tgaprof.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-116724683234203780</id><published>2006-12-27T11:08:00.000-08:00</published><updated>2006-12-27T11:15:43.226-08:00</updated><title type='text'>wikka makeover</title><content type='html'>I like the &lt;a href="http://wikkawiki.org/HomePage"&gt;wikka wiki engine&lt;/a&gt; because it is written in PHP/MySQL and does all the things I want a wiki to do but is a lot smaller than the feature-heavy wikimedia engine.&lt;br /&gt;&lt;br /&gt;I also like the philosophy behind its simple look and interface but decided I wanted to change it around a little.  The end result actually looks a lot like the wikimedia interface but gives you a few more options in customizing your layout:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/x/blogger/6050/389/1600/403621/wikka_makeover.png"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/x/blogger/6050/389/320/520903/wikka_makeover.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Details here:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.klenwell.net/is/WikkaSkinCustomization"&gt;klenwell.net/is/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-116724683234203780?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/116724683234203780/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=116724683234203780' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/116724683234203780'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/116724683234203780'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2006/12/wikka-makeover.html' title='wikka makeover'/><author><name>Tom</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://photos1.blogger.com/img/36/1021/640/tgaprof.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-116665122830112546</id><published>2006-12-20T13:44:00.000-08:00</published><updated>2006-12-20T13:47:08.303-08:00</updated><title type='text'>klenwell.net redesign</title><content type='html'>Been redesigning &lt;a href="http://www.klenwell.net/"&gt;klenwell.net&lt;/a&gt; in the in-between times over the last couple weeks.  The theme is appropriately wintery.  Plan to invest more time in coming year in transforming it into my flagship site.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-116665122830112546?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/116665122830112546/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=116665122830112546' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/116665122830112546'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/116665122830112546'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2006/12/klenwellnet-redesign.html' title='klenwell.net redesign'/><author><name>Tom</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://photos1.blogger.com/img/36/1021/640/tgaprof.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-116501532858236365</id><published>2006-12-01T15:16:00.000-08:00</published><updated>2006-12-01T15:22:08.600-08:00</updated><title type='text'>PHP/MySQL: mysqldump automated backup script</title><content type='html'>This based on the script I found here:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://blog.tvlgiao.com/2006/05/09/php-cron-job-backups.html"&gt;http://blog.tvlgiao.com/2006/05/09/php-cron-job-backups.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I've simply cleaned up the code a bit, added some sanity checks, and focused it on databases.&lt;br /&gt;&lt;br /&gt;It does the following things:&lt;br /&gt;&lt;br /&gt;1) backup 1 or more databases&lt;br /&gt;2) option to do all tables in db or selected ones&lt;br /&gt;3) compress files&lt;br /&gt;4) email compressed files as attachment&lt;br /&gt;&lt;br /&gt;It can be called directly from the browser but is best utilized as a cron job.&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&amp;lt;?php&lt;br /&gt;&lt;br /&gt;$_tx1 = microtime();&lt;br /&gt;&lt;br /&gt;// ** Documentation&lt;br /&gt;/*______________________________________________________________________________&lt;br /&gt;&lt;br /&gt; AMVC MySQL Backup Script&lt;br /&gt;&lt;br /&gt; Last Update: Dec 2006&lt;br /&gt; Author: Tom at klenwell@gmail.com&lt;br /&gt;&lt;br /&gt; SUMMARY&lt;br /&gt;  A simple mysql backup script designed to do the following things:&lt;br /&gt;  &lt;br /&gt;   - backup 1 or more databases&lt;br /&gt;   - option to do all tables in db or selected ones&lt;br /&gt;   - compress files&lt;br /&gt;   - email compressed files as attachment&lt;br /&gt;  &lt;br /&gt; NOTES&lt;br /&gt;  Requires system() function and your db user must have sufficient privileges&lt;br /&gt;  &lt;br /&gt;  Can be called directly (useful for testing) but intended for cronjob usage &lt;br /&gt;  &lt;br /&gt;  Sample $_CFG['DB'] settings:&lt;br /&gt;   1) 'db1' =&amp;gt; '*', -&amp;gt; backs up selected table inside the array&lt;br /&gt;   2) 'db2' =&amp;gt; array('table1', 'table2'), -&amp;gt; backs up all tables in database&lt;br /&gt;   &lt;br /&gt;  Note: keys (database names) must be different -- if duplicated, only the last one&lt;br /&gt;  will run &lt;br /&gt; &lt;br /&gt; CREDIT&lt;br /&gt;  Giao Trinh (http://blog.tvlgiao.com/2006/05/09/php-cron-job-backups.html)&lt;br /&gt;  &lt;br /&gt; LICENSE&lt;br /&gt;  GPL (http://www.opensource.org/licenses/gpl-license.php)  &lt;br /&gt;  &lt;br /&gt;______________________________________________________________________________*/&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// *** PRE-SCRIPT (Configuration)&lt;br /&gt;/*____________________________________________________________________________*/&lt;br /&gt;&lt;br /&gt;// keep it safe!&lt;br /&gt;$_CFG['db_user'] = '';&lt;br /&gt;$_CFG['db_pass'] = '';&lt;br /&gt;$_CFG['email_to'] = '';&lt;br /&gt;$_CFG['email_subject_prefix'] = date('Ymd') . ' mysqldump';&lt;br /&gt;$_CFG['email_from'] = 'amvc-mysqldump-client';&lt;br /&gt;&lt;br /&gt;// databases and tables ( keys=databases, values=array( tables ) or * - all tables )&lt;br /&gt;$_CFG['DB'] = array&lt;br /&gt;(&lt;br /&gt; #'db1' =&amp;gt; '*',&lt;br /&gt; #'db2' =&amp;gt; array( 'table1', 'table2' ),&lt;br /&gt;);&lt;br /&gt;&lt;br /&gt;// Flags&lt;br /&gt;$_FLAG['tar'] = 1; // tar compress?&lt;br /&gt;$_FLAG['debug'] = 0; // outputs command line (with password!)&lt;br /&gt;&lt;br /&gt;// path to mysqldump&lt;br /&gt;$_CFG['md_path'] = '/usr/local/bin/mysqldump';&lt;br /&gt;&lt;br /&gt;// mysql dump default options (see http://dev.mysql.com/doc/refman/4.1/en/mysqldump.html)&lt;br /&gt;$_CFG['md_opt'] = '--opt --quote-names';&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// internal variables&lt;br /&gt;$tbl_cmd = '';&lt;br /&gt;$tbl_list = '';&lt;br /&gt;$_subject = '';&lt;br /&gt;&lt;br /&gt;/*============================================================================*/&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// *** Backup Script&lt;br /&gt;/*____________________________________________________________________________*/&lt;br /&gt;&lt;br /&gt;// sanity check&lt;br /&gt;if ( empty($_CFG['DB']) || !is_array($_CFG['DB']) )&lt;br /&gt;{&lt;br /&gt; trigger_error('no databases set -- please update config settings', E_USER_WARNING);&lt;br /&gt; die(' -&amp;gt; aborting script');&lt;br /&gt;} &lt;br /&gt;&lt;br /&gt;// set user and password&lt;br /&gt;if ( !empty($_CFG['db_user']) &amp;amp;&amp;amp; !empty($_CFG['db_pass']) )&lt;br /&gt;{&lt;br /&gt; $login_cmd = "-u {$_CFG['db_user']} -p{$_CFG['db_pass']}";&lt;br /&gt;}&lt;br /&gt;else&lt;br /&gt;{&lt;br /&gt; trigger_error('user name or password empty -- please update config settings', E_USER_WARNING);&lt;br /&gt; die(' -&amp;gt; aborting script');&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;foreach ( $_CFG['DB'] as $db_name =&amp;gt; $_TABLE ) &lt;br /&gt;{&lt;br /&gt; // start timer&lt;br /&gt; $_t1 = microtime();&lt;br /&gt;&lt;br /&gt; // set tables&lt;br /&gt; if ( $_TABLE == '*' )&lt;br /&gt; {&lt;br /&gt;  $tbl_cmd = '';&lt;br /&gt; }&lt;br /&gt; elseif ( is_array($_TABLE) )&lt;br /&gt; {&lt;br /&gt;  $tbl_list = implode(' ', $_TABLE);&lt;br /&gt;  $tbl_cmd = " --tables $tbl_list";&lt;br /&gt; }&lt;br /&gt; else&lt;br /&gt; {&lt;br /&gt;  trigger_error("invalid table settings for db $db_name, will back up all tables", E_USER_WARNING);&lt;br /&gt;  $tbl_cmd = '';&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; // set file name&lt;br /&gt; $_sql_file = $db_name . '.sql';&lt;br /&gt; $_tar_file = $db_name . '.tar.gz';&lt;br /&gt; &lt;br /&gt; // build mysqldump command&lt;br /&gt; $sql_cmd = "{$_CFG['md_path']} {$_CFG['md_opt']} $login_cmd -B $db_name{$tbl_cmd} &amp;gt; $_sql_file";&lt;br /&gt; if ( $_FLAG['debug'] ) echo "&amp;lt;p style='font-size:11px; color:#ccc;'&amp;gt;mysql dump command: &amp;lt;code&amp;gt;$sql_cmd&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;";&lt;br /&gt; &lt;br /&gt; // run mysqldump&lt;br /&gt; system($sql_cmd);&lt;br /&gt; &lt;br /&gt; // run tar&lt;br /&gt; if ( $_FLAG['tar'] ) system("tar -zcf $_tar_file $_sql_file");&lt;br /&gt; &lt;br /&gt; // mail file as attachment&lt;br /&gt; &lt;br /&gt;  // which file&lt;br /&gt;  $_attach_file = ( $_FLAG['tar'] ) ? $_tar_file : $_sql_file;&lt;br /&gt; &lt;br /&gt;  // create attachment and mail&lt;br /&gt;  if ( !empty($_CFG['email_to']) )&lt;br /&gt;  {&lt;br /&gt;   $_subject = $_CFG['email_subject_prefix'] . ' for db ' . $db_name . ' : ' . $_attach_file;&lt;br /&gt;   mail_attachment($_CFG['email_to'], $_CFG['email_from'], $_subject, '', $_attach_file);&lt;br /&gt;  }&lt;br /&gt;  else&lt;br /&gt;  {&lt;br /&gt;   trigger('no email set -- please update config settings', E_USER_WARNING);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt; // remove file&lt;br /&gt; system("rm $_sql_file");&lt;br /&gt; if ( $_FLAG['tar'] ) system ("rm $_tar_file");&lt;br /&gt; &lt;br /&gt; // end timer&lt;br /&gt; $_t2 = microtime();&lt;br /&gt; $_t3 = number_format(((substr($_t2,0,9)) + (substr($_t2,-10)) - (substr($_t1,0,9)) - (substr($_t1,-10))),4);&lt;br /&gt; echo "&amp;lt;p&amp;gt;db &amp;lt;b&amp;gt;{$db_name}&amp;lt;/b&amp;gt; backed up in &amp;lt;b&amp;gt;{$_t3}&amp;lt;/b&amp;gt; s&amp;lt;/p&amp;gt;";&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/*============================================================================*/&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// *** Post-Script&lt;br /&gt;/*____________________________________________________________________________*/&lt;br /&gt;&lt;br /&gt;$_tx2 = microtime();&lt;br /&gt;$_tx3 = number_format(((substr($_tx2,0,9)) + (substr($_tx2,-10)) - (substr($_tx1,0,9)) - (substr($_tx1,-10))),4);&lt;br /&gt;echo "&amp;lt;p style='color:green;'&amp;gt;backup script completed in $_tx3 s&amp;lt;/p&amp;gt;";&lt;br /&gt;echo '&amp;lt;h6&amp;gt;end script&amp;lt;/h6&amp;gt;';&lt;br /&gt;&lt;br /&gt;/*============================================================================*/&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// *** fx mail_attachement&lt;br /&gt;// credit: Giao Trinh (http://blog.tvlgiao.com/2006/05/09/php-cron-job-backups.html)&lt;br /&gt;/*____________________________________________________________________________*/&lt;br /&gt;&lt;br /&gt;function mail_attachment($email, $from = '', $subject = '', $body = '', $file = '') &lt;br /&gt;{&lt;br /&gt; $_debug = 0;&lt;br /&gt; $boundary = '-----=' . md5( uniqid ( rand() ) );&lt;br /&gt; &lt;br /&gt; if ($file) {&lt;br /&gt;  $basename = basename($file);&lt;br /&gt;  $message .= "--".$boundary."\n";&lt;br /&gt;  $message .= "Content-Type: application/binary; name=\"$basename\"\n";&lt;br /&gt;  $message .= "Content-Transfer-Encoding: base64\n";&lt;br /&gt;  $message .= "Content-Disposition: attachment; filename=\"$basename\"\n\n";&lt;br /&gt;  &lt;br /&gt;  $content = file_get_contents($file);&lt;br /&gt;  $content_encode = chunk_split(base64_encode($content));&lt;br /&gt;  $message .= $content_encode . "\n\n";&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; if ($body) {&lt;br /&gt;  # Text Version&lt;br /&gt;  $message .= "--".$boundary."\n";&lt;br /&gt;  $message .= "Content-Type: text/plain; charset=iso-8859-1\n";&lt;br /&gt;  $message .= "Content-Transfer-Encoding: 8bit\n";&lt;br /&gt;  $message .= "This is a multi-part message in MIME format.\n";&lt;br /&gt;  $message .= strip_tags($body)."\n\n";&lt;br /&gt;&lt;br /&gt;  # HTML Version&lt;br /&gt;  $message .= "--".$boundary."\n";&lt;br /&gt;  $message .= "Content-Type: text/html; charset=iso-8859-1\n";&lt;br /&gt;  $message .= "Content-Transfer-Encoding: 8bit\n";&lt;br /&gt;  $message .= $body."\n\n"; &lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; # Finished&lt;br /&gt; $message .= "--".$boundary."--\n\n";  // finish with two eol's for better security. see&lt;br /&gt; &lt;br /&gt; $headers = '';&lt;br /&gt; if ($from)&lt;br /&gt;  $headers .= "From: $from" . "\r\n";&lt;br /&gt; $headers .= "MIME-Version: 1.0" . "\r\n";&lt;br /&gt; $headers .= "Content-Type: multipart/mixed; boundary=\"$boundary\"";&lt;br /&gt; if ( !mail($email, $subject, $message, $headers) )&lt;br /&gt; {&lt;br /&gt;  trigger_error('mail failed', E_USER_WARNING);&lt;br /&gt;  return 0;&lt;br /&gt; }&lt;br /&gt; if ( $_debug ) echo "&amp;lt;pre&amp;gt;$message\n*************&amp;lt;/pre&amp;gt;";&lt;br /&gt; return 1;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/*============================================================================*/&lt;br /&gt;&lt;br /&gt;?&amp;gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-116501532858236365?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/116501532858236365/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=116501532858236365' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/116501532858236365'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/116501532858236365'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2006/12/phpmysql-mysqldump-automated-backup.html' title='PHP/MySQL: mysqldump automated backup script'/><author><name>Tom</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://photos1.blogger.com/img/36/1021/640/tgaprof.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-116483198943546228</id><published>2006-11-29T12:20:00.000-08:00</published><updated>2006-11-29T12:26:29.453-08:00</updated><title type='text'>PHP/MySQL: updating rows with ADOdb Lite</title><content type='html'>Two ways to create a ADODB Lite object.  The second, using DSN (Data Source Name) allows you to set a flag that will count updated rows even when they aren't changed.  (This is significant if you are a defensive programmer like me.)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Simple Instantiation&lt;/span&gt;&lt;br /&gt;&lt;div class="code"&gt;$DBSingle =&amp; ADONewConnection($db_type);&lt;br /&gt;$DBSingle-&gt;db_name = $db_name;&lt;br /&gt;if ( !$DBSingle-&gt;Connect($db_server, $db_user, $db_pass, $db_name) ) trigger_error('unable to connect to database [' . $db_name . ']', E_USER_WARNING);&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;DSN Instantiation&lt;/span&gt;&lt;br /&gt;&lt;div class="code"&gt;$_pw = urlencode($db_pass);&lt;br /&gt;$_flags = 2;&lt;br /&gt;$_dsn = "mysql://$db_user:$_pw@$db_server/$db_name?clientflags=$_flags";&lt;br /&gt;if ( !$DBSingle =&amp; ADONewConnection($_dsn) ) trigger_error('unable to connect to database [' . $db_name . ']', E_USER_WARNING);&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;References:&lt;br /&gt;&lt;a href="http://phplens.com/lens/adodb/docs-adodb.htm#dsnsupport"&gt;ADO Documentation: DSN Support&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;keywords: php, mysql, adodb, adodb_lite, update, count, dsn&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-116483198943546228?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/116483198943546228/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=116483198943546228' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/116483198943546228'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/116483198943546228'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2006/11/phpmysql-updating-rows-with-adodb-lite.html' title='PHP/MySQL: updating rows with ADOdb Lite'/><author><name>Tom</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://photos1.blogger.com/img/36/1021/640/tgaprof.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-116474062775992367</id><published>2006-11-28T10:53:00.000-08:00</published><updated>2006-11-28T12:00:54.586-08:00</updated><title type='text'>PHP Greqo: Blogger Post Demo</title><content type='html'>I've updated the Greqo code to handle classic and beta accounts transparently -- well, almost.  If you set up your script with the basic undifferentiated settings, like this, it will still work for either type of account.  However, since it will try to authenticate using the Google Account ClientLogin interface as a first step, classic accounts will throw an error here.  Nevertheless, as in the test script linked above, the request should still succeed.&lt;br /&gt;&lt;br /&gt;To clarify how it works, consider the following code samples.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;User Settings and Greqo Setup&lt;/span&gt;&lt;br /&gt;&lt;div class="code" style="font-size:11px;"&gt;// *** Google User Settings (keep safe!)&lt;br /&gt;$_GOOGLE['user'] = 'jqblogger';&lt;br /&gt;$_GOOGLE['pw'] = 'supersafe123';&lt;br /&gt; &lt;br /&gt;// *** Blogger User Settings (for Blogger beta accounts, these will be the same)&lt;br /&gt;$_BLOGGER['user'] = $_GOOGLE['user'];&lt;br /&gt;$_BLOGGER['pw'] = $_GOOGLE['pw'];&lt;br /&gt;$_BLOGGER['blog_id'] = '123456';  // if not sure, right click on link in your Blogger dashboard';&lt;br /&gt;&lt;br /&gt;// *** Load Files&lt;br /&gt;error_reporting(E_ALL);&lt;br /&gt;session_start();&lt;br /&gt;$_path_to_greqodir = dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR;&lt;br /&gt;require_once($_path_to_greqodir . 'greqo_driver.inc.php');&lt;br /&gt;&lt;br /&gt;// Important! (this function will globalize user settings and is required)&lt;br /&gt;greqo_blogger_set_user_data($_BLOGGER['user'], $_BLOGGER['pw'], $_BLOGGER['blog_id']);&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Generic Blogger Post&lt;/span&gt;&lt;br /&gt;note: this will work for either type of account but will throw an error for classic account when it tries to authenticate under the new Google Accounts API&lt;br /&gt;&lt;div class="code" style="font-size:11px;"&gt; // prepare request (this will throw an error with classic Blogger accounts but post should still succeed)&lt;br /&gt; if ( !greqo_request_clientlogin_token($_GOOGLE['user'], $_GOOGLE['pw'], 'blogger', 0) ) trigger_error('unable to get token');&lt;br /&gt; if ( !greqo_blogger_request_api_url(0) ) $_SESSION['GDATA']['BLOGGER']['api_url'] = 'http://www.blogger.com';&lt;br /&gt; &lt;br /&gt; // post&lt;br /&gt; if ( $POST_DATA = greqo_blogger_post_entry($test_post_body, $test_post_title)&lt;br /&gt; {&lt;br /&gt;  echo '&amp;lt;p style="color:green;"&amp;gt;post succeeded&amp;lt;/p&amp;gt;';&lt;br /&gt;  $_response = print_r($POST_DATA,1);&lt;br /&gt;  echo "&amp;lt;pre&amp;gt;{$_response}&amp;lt;/pre&amp;gt;";&lt;br /&gt;  echo "&amp;lt;p&amp;gt;&amp;lt;a href=\"{$POST_DATA['self_link']}\"&amp;gt;click to see post&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;";&lt;br /&gt; }&lt;br /&gt; else&lt;br /&gt; {&lt;br /&gt;  echo '&amp;lt;p style="color:red;"&amp;gt;post failed&amp;lt;/p&amp;gt;';&lt;br /&gt; }&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Now, if you know you are dealing with a classic (non-beta) account and wished to avoid the error warnings, remove the Google authentication part and just manually set the Blogger api url:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Classic Blogger Post&lt;/span&gt;&lt;br /&gt;&lt;div class="code" style="font-size:11px;"&gt; // prepare request (removed for Classic Blogger -- uncomment for new beta)&lt;br /&gt; #if ( !greqo_request_clientlogin_token($_GOOGLE['user'], $_GOOGLE['pw'], 'blogger', 0) ) trigger_error('unable to get token');&lt;br /&gt; #if ( !greqo_blogger_request_api_url(0) ) $_SESSION['GDATA']['BLOGGER']['api_url'] = 'http://www.blogger.com';&lt;br /&gt;&lt;br /&gt; // manually set Blogger api url&lt;br /&gt; $_SESSION['GDATA']['BLOGGER']['api_url'] = 'http://www.blogger.com';&lt;br /&gt; &lt;br /&gt; // post&lt;br /&gt; if ( $POST_DATA = greqo_blogger_post_entry($test_post_body, $test_post_title)&lt;br /&gt; {&lt;br /&gt;  echo '&amp;lt;p style="color:green;"&amp;gt;post succeeded&amp;lt;/p&amp;gt;';&lt;br /&gt;  $_response = print_r($POST_DATA,1);&lt;br /&gt;  echo "&amp;lt;pre&amp;gt;{$_response}&amp;lt;/pre&amp;gt;";&lt;br /&gt;  echo "&amp;lt;p&amp;gt;&amp;lt;a href=\"{$POST_DATA['self_link']}\"&amp;gt;click to see post&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;";&lt;br /&gt; }&lt;br /&gt; else&lt;br /&gt; {&lt;br /&gt;  echo '&amp;lt;p style="color:red;"&amp;gt;post failed&amp;lt;/p&amp;gt;';&lt;br /&gt; }&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://code.google.com/p/greqo/"&gt;Greqo Google Code Home&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-116474062775992367?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/116474062775992367/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=116474062775992367' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/116474062775992367'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/116474062775992367'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2006/11/php-greqo-blogger-post-demo.html' title='PHP Greqo: Blogger Post Demo'/><author><name>Tom</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://photos1.blogger.com/img/36/1021/640/tgaprof.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-116414914357993328</id><published>2006-11-21T14:43:00.000-08:00</published><updated>2006-11-26T19:04:02.266-08:00</updated><title type='text'>PHP: Greqo Google Data API</title><content type='html'>A couple weeks ago, &lt;a href="http://google-code-featured.blogspot.com/2006/11/ngeblog.html"&gt;Google announced&lt;/a&gt; the release of a new Blogger Data API for PHP: &lt;a href="http://www.phpclasses.org/browse/package/3450.html"&gt;Ngeblog&lt;/a&gt;.  Ngeblog uses the Zend Framework's HTTP Client to authorize Google accounts -- and therein lies its one fatal shortcoming, at least for me.  The Zend Framework requires PHP 5 -- and most my hosts are still on PHP 4.4.&lt;br /&gt;&lt;br /&gt;So I've developed an alternative that uses the PEAR HTTP Client and Magpie XML classes.  It's called Greqo (Google REQuest Object -- though it's not really an object-oriented architecture.)  I've created a &lt;a href="http://code.google.com/p/greqo/"&gt;Google Project for it&lt;/a&gt; and uploaded it there.  Right now, it can authenticate a Google account (using the ClientLogin interface), retrieve a Blogger feed, and post a new entry to a Blogger blog.  I'll add functions to edit and delete posts as I have time.&lt;br /&gt;&lt;br /&gt;It's simple to load.  Just start a session and call the greqo_driver.  An example:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&amp;lt;?php&lt;br /&gt;&lt;br /&gt;// *** Load Files&lt;br /&gt;session_start();&lt;br /&gt;$_parent_dir = dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR;&lt;br /&gt;require_once($_parent_dir . 'greqo_driver.inc.php');&lt;br /&gt;&lt;br /&gt;?&amp;gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;A full demo is available in the Google Code repository:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://greqo.googlecode.com/svn/trunk/test/basic_get_control.php"&gt;http://greqo.googlecode.com/svn/trunk/test/basic_get_control.php&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-116414914357993328?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/116414914357993328/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=116414914357993328' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/116414914357993328'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/116414914357993328'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2006/11/php-greqo-google-data-api.html' title='PHP: Greqo Google Data API'/><author><name>Tom</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://photos1.blogger.com/img/36/1021/640/tgaprof.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-116404722849959982</id><published>2006-11-20T10:09:00.000-08:00</published><updated>2007-03-21T08:49:17.733-07:00</updated><title type='text'>wikka comment spam</title><content type='html'>Noticed I was getting an unusual number of hits all of the sudden on my mushpup wikka wiki.  At first, I thought: "At last, people are finally catching on."&lt;br /&gt;&lt;br /&gt;Then I looked where they were coming from.  Primarily, Google.  But they weren't searching for "mushpup" or "passwords".  Instead, it was more like, "nubile rapidshare" and "Aneta TeenPinkVideo".  Hmmmm... I don't remember posting anything about pink videos.&lt;br /&gt;&lt;br /&gt;Well, I did a Google search on these terms, found the mushpup listing and figured it out: wikka comment spam.&lt;br /&gt;&lt;br /&gt;Googled for a shotgun solution.  Didn't really find one but came up with one pretty quickly.&lt;br /&gt;&lt;br /&gt;Three steps:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;1. Backup your database&lt;/span&gt;&lt;br /&gt;Now as good as time as any.  Especially if you screw up one of the next two steps.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;2. Change &lt;code&gt;wikka.config.php&lt;/code&gt; settings&lt;/span&gt;&lt;br /&gt;The key ones &lt;code&gt;default_write_acl&lt;/code&gt; and &lt;code&gt;default_comment_acl&lt;/code&gt;.  Set to the following:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;'default_write_acl' =&gt; '+',&lt;br /&gt;'default_comment_acl' =&gt; '+',&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;This will limit page editing and commenting privileges to registered users.&lt;br /&gt;&lt;br /&gt;These are the global settings.  Access can also be limited on a per-page basis by the through the admin web interface.&lt;br /&gt;&lt;br /&gt;info on other settings here: &lt;a href="http://wikkawiki.org/ConfigurationOptions"&gt;http://wikkawiki.org/ConfigurationOptions&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;3. Delete any existing spam comments&lt;/span&gt;&lt;br /&gt;This is pretty easy since they're all in a simple table named something like &lt;code&gt;wikka_comments&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;phpMyAdmin makes it simple to delete the offenders.  Or you could use a statement like this:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;DELETE FROM `wikka_comments` WHERE user="81.177.22.243"&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;(81.177.22.243 was the actual ip adding most the spam.)&lt;br /&gt;&lt;br /&gt;keywords: wiki, wikka, spam, comments, comment spam, mysql, phpmyadmin&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-116404722849959982?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/116404722849959982/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=116404722849959982' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/116404722849959982'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/116404722849959982'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2006/11/wikka-comment-spam.html' title='wikka comment spam'/><author><name>Tom</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://photos1.blogger.com/img/36/1021/640/tgaprof.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-116292597118374039</id><published>2006-11-07T10:50:00.000-08:00</published><updated>2006-11-07T10:59:31.216-08:00</updated><title type='text'>HTML: XHTML links</title><content type='html'>This is one of those things I keep having to look up.  It involves the old &lt;code&gt;target&lt;/code&gt; attribute you use in &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; links to open the link in a new window.  This attribute is deprecated in XHTML strict and HTML 4.0 -- or so I hear.  &lt;br /&gt;&lt;br /&gt;Here, in any event, is the workaround:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;onclick="window.open(this.href,'_blank');return false;"&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;So this:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&amp;lt;a href="http://www.flametag.com" target="_blank"&amp;gt;flametag.com&amp;lt;/a&amp;gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Would become this:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&amp;lt;a href="http://www.flametag.com" rel="external" onclick="window.open(this.href,'_blank');return false;"&amp;gt;flametag.com&amp;lt;/a&amp;gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;(The &lt;code&gt;rel&lt;/code&gt; attribute is not necessary but can be used for javascript functions to the same effect.)&lt;br /&gt;&lt;br /&gt;credit: &lt;a href="http://www.phpfreaks.com/quickcode/XHTML_target%3D%22_blank%22_Alternative/231.php"&gt;phpfreaks.com&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;keywords: link, links, anchor, blank, _blank, target, xhtml&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-116292597118374039?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/116292597118374039/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=116292597118374039' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/116292597118374039'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/116292597118374039'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2006/11/html-xhtml-links.html' title='HTML: XHTML links'/><author><name>Tom</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://photos1.blogger.com/img/36/1021/640/tgaprof.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-116266152901142216</id><published>2006-11-04T09:16:00.000-08:00</published><updated>2006-11-04T09:34:44.426-08:00</updated><title type='text'>PHP: filepath to URL</title><content type='html'>I've been wrestling with some complication with sessions and domains names recently, so &lt;a href="http://groups-beta.google.com/group/comp.lang.php/browse_thread/thread/0a855ea78f25bbf4/6bcf84da785a92ce#6bcf84da785a92ce"&gt;this thread&lt;/a&gt; on comp.lang.php caught my attention.  It says basically, if you're not careful, you could have a user on your site lose their session if they were to somehow move from say http://yourdomain.com to http://www.yourdomain.com, your user will lose their session.&lt;br /&gt;&lt;br /&gt;I offer my solution to this problem &lt;a href="http://groups-beta.google.com/groups/profile?enc_user=oGx5ZhIAAABG5aU4AKXk_OFa2kWT3Qxz8rhlH0Pnl47z4AZhN98BFg"&gt;here&lt;/a&gt; (I think this is the same concept used by most popular applications such as Joomla).  The functions below may also be useful.  The first has evolved over a long period of time.  It hasn't failed me yet, though I don't know that it is the optimal solution to this particular challenge.&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;// filepath_to_url&lt;br /&gt;/*____________________________________________________________________________*/&lt;br /&gt;function amvc_filepath_to_url($filepath) &lt;br /&gt;{&lt;br /&gt; // *** DATA&lt;br /&gt; &lt;br /&gt;  // internal&lt;br /&gt;  $_slash = '/';&lt;br /&gt;  $_url_rel = '';&lt;br /&gt; &lt;br /&gt;  // paths&lt;br /&gt;  $PATH = array();&lt;br /&gt;  $PATH['file'] = amvc_normalize_path($filepath, $_slash);&lt;br /&gt;  $PATH['www'] = 'http://' . $_SERVER['HTTP_HOST'] . $_slash;&lt;br /&gt;&lt;br /&gt;  // directory arrays&lt;br /&gt;  $_DIRS = array();&lt;br /&gt;  $_DIRS['filepath'] = explode($_slash, $PATH['file']);&lt;br /&gt;  $_DIRS['doc_root'] = explode($_slash, amvc_normalize_path($_SERVER['DOCUMENT_ROOT'],$_slash));&lt;br /&gt;  $_DIRS['diff'] = '';&lt;br /&gt;  &lt;br /&gt;  // return&lt;br /&gt;  $url = '';&lt;br /&gt;  &lt;br /&gt; &lt;br /&gt; // *** MANIPULATE&lt;br /&gt; &lt;br /&gt;  // * DEBUG&lt;br /&gt;  #trigger_notice($filepath);&lt;br /&gt;  #trigger_notice($_DIRS);&lt;br /&gt; &lt;br /&gt;    // path is url&lt;br /&gt;    if ( preg_match('%^(http)s?://%i', $PATH['file']) ) return $PATH['file'];&lt;br /&gt;&lt;br /&gt;  // compute path differences&lt;br /&gt;  $_DIRS['diff'] = array_values(array_diff($_DIRS['filepath'], $_DIRS['doc_root']));&lt;br /&gt;  &lt;br /&gt;  // DEBUG&lt;br /&gt;  #trigger_notice($_DIRS);&lt;br /&gt;  &lt;br /&gt;  // shift empty cells&lt;br /&gt;  if ( empty($_DIRS['diff'][0]) ) array_shift($_DIRS['diff']);&lt;br /&gt;  &lt;br /&gt;  // get URL relative path&lt;br /&gt;  $_url_rel = implode('/', $_DIRS['diff']);&lt;br /&gt;&lt;br /&gt;  // build URL&lt;br /&gt;  $url = $PATH['www'] . $_url_rel;&lt;br /&gt;  &lt;br /&gt; &lt;br /&gt; // *** RETURN&lt;br /&gt; &lt;br /&gt;  return $url; &lt;br /&gt;}&lt;br /&gt;/*____________________________________________________________________________*/&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;// amvc_normalize_path&lt;br /&gt;/*____________________________________________________________________________*/&lt;br /&gt;function amvc_normalize_path($path, $slash) &lt;br /&gt;{&lt;br /&gt; // *** DATA&lt;br /&gt; &lt;br /&gt;  // internal&lt;br /&gt;  $_ds = DIRECTORY_SEPARATOR;&lt;br /&gt; &lt;br /&gt;  // return var&lt;br /&gt;  $new_path = '';  &lt;br /&gt;&lt;br /&gt;&lt;br /&gt; // *** MANIPULATE&lt;br /&gt;&lt;br /&gt;  // replace forward slashes&lt;br /&gt;  $new_path = str_replace('/', $slash, $path);&lt;br /&gt;  &lt;br /&gt;  // replace backslashes&lt;br /&gt;  $new_path = str_replace('\\', $slash, $new_path);&lt;br /&gt;  &lt;br /&gt;  &lt;br /&gt; // *** RETURN&lt;br /&gt; &lt;br /&gt;  return $new_path; &lt;br /&gt;}&lt;br /&gt;/*____________________________________________________________________________*/&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-116266152901142216?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/116266152901142216/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=116266152901142216' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/116266152901142216'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/116266152901142216'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2006/11/php-filepath-to-url.html' title='PHP: filepath to URL'/><author><name>Tom</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://photos1.blogger.com/img/36/1021/640/tgaprof.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-116235111401268141</id><published>2006-10-31T19:13:00.000-08:00</published><updated>2006-10-31T19:18:34.013-08:00</updated><title type='text'>More Google News: PHP API</title><content type='html'>Been waiting for this -- announced earlier today: &lt;a href="http://framework.zend.com/download/gdata"&gt;Google Data API for PHP released&lt;/a&gt;.  Available here:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://framework.zend.com/download/gdata"&gt;http://framework.zend.com/download/gdata&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Can they be used independently of the Zend Framework?  Not sure.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-116235111401268141?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/116235111401268141/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=116235111401268141' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/116235111401268141'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/116235111401268141'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2006/10/more-google-news-php-api.html' title='More Google News: PHP API'/><author><name>Tom</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://photos1.blogger.com/img/36/1021/640/tgaprof.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-116235061375687248</id><published>2006-10-31T19:03:00.000-08:00</published><updated>2006-10-31T19:10:13.846-08:00</updated><title type='text'>The Google Wiki</title><content type='html'>A few weeks ago I was looking at the web 2.0 wikis and trying to decide which was the easiest to use.  I ended up going with &lt;a href="http://pbwiki.com/"&gt;pbwiki.com&lt;/a&gt;.  Today, apparently, &lt;a href="http://googleblog.blogspot.com/2006/10/what-joe-said.html"&gt;Google made its choice&lt;/a&gt;.  I remember looking at jotspot and preferring pbwiki for some reason.&lt;br /&gt;&lt;br /&gt;Curious to see what becomes of this.  I've been very impressed with the new Gmail Suite, which includes Analytics, Spreadsheets &amp; Docs (which I've found very useful), and the webmaster tools among other things.  The Groups makeover looks intriguing, too.  It will be interesting to see how this gets incorporated.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-116235061375687248?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/116235061375687248/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=116235061375687248' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/116235061375687248'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/116235061375687248'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2006/10/google-wiki.html' title='The Google Wiki'/><author><name>Tom</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://photos1.blogger.com/img/36/1021/640/tgaprof.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-116222846123895830</id><published>2006-10-30T09:10:00.000-08:00</published><updated>2006-10-30T09:14:21.296-08:00</updated><title type='text'>PHP: Optimization</title><content type='html'>I've been asking questions about PHP optimization for a while now.  Finally found an answer today:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://talks.php.net/show/hackday06/1"&gt;Getting Rich with PHP 5 (a slideshow)&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The bad news is it looks like I have a lot of work to do.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-116222846123895830?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/116222846123895830/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=116222846123895830' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/116222846123895830'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/116222846123895830'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2006/10/php-optimization.html' title='PHP: Optimization'/><author><name>Tom</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://photos1.blogger.com/img/36/1021/640/tgaprof.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-116200462849167863</id><published>2006-10-27T20:02:00.000-07:00</published><updated>2006-10-27T20:07:26.863-07:00</updated><title type='text'></title><content type='html'>&lt;span style="color:green; font-size:2em;"&gt;mod_rewrite successful!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;more info on Apache's mod_rewrite engine on &lt;a href="http://www.google.com/search?hl=en&amp;q=url+mod+rewrite&amp;btnG=Google+Search"&gt;Google&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-116200462849167863?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/116200462849167863/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=116200462849167863' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/116200462849167863'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/116200462849167863'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2006/10/modrewrite-successful-more-info-on.html' title=''/><author><name>Tom</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://photos1.blogger.com/img/36/1021/640/tgaprof.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-116120940845404149</id><published>2006-10-18T15:07:00.000-07:00</published><updated>2006-10-18T15:10:08.490-07:00</updated><title type='text'>PHP: html-kit codefinder plugin</title><content type='html'>Because I'm usually on an XP (I'd love to use Linux, but it's just hard to switch!), I use &lt;a href="http://www.chami.com/html-kit/"&gt;html-kit&lt;/a&gt; to do my coding.  And one must-have plug-in for PHP coding is the codefinder plug-in:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.html-kit.com/html-kit/download/plugin/cmcodefinder/"&gt;http://www.html-kit.com/html-kit/download/plugin/cmcodefinder/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.chami.com/html-kit/plugins/Dir/Keywords/PHP/"&gt;all php-related plug-ins&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-116120940845404149?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/116120940845404149/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=116120940845404149' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/116120940845404149'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/116120940845404149'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2006/10/php-html-kit-codefinder-plugin.html' title='PHP: html-kit codefinder plugin'/><author><name>Tom</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://photos1.blogger.com/img/36/1021/640/tgaprof.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-116093645165061708</id><published>2006-10-15T11:13:00.000-07:00</published><updated>2006-10-15T11:20:51.666-07:00</updated><title type='text'>The Rise and Fall of Friendster</title><content type='html'>From today's New York Times:&lt;br /&gt;&lt;br /&gt;&lt;div class="quote"&gt;The venture capitalists considered shutting down the company. But a sense of obligation (“It was my feeling that the investors and the board had done something of a disservice to Friendster,” Mr. Siegelman said) and economics (Friendster still had a well-known brand and millions of registered users, even if most had not visited the site in some time) prompted Kleiner Perkins, Benchmark and some of the private investors to sink an additional $3 million into the company at the start of 2006.&lt;br /&gt;&lt;br /&gt;-- &lt;a href="http://www.nytimes.com/2006/10/15/business/yourmoney/15friend.html"&gt;Wallflower at the Web Party&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;It's funny because I was on Friendster just yesterday for the first time in weeks.  (It was in response to some spam message someone had sent me.  Still spamming on Friendster?  Talk about out of touch...)  One thing I noticed was that they no longer tell you how long since that last time someone checked in.  I took that as a bad sign.&lt;br /&gt;&lt;br /&gt;The article did set straight one misconception:  I've read more than once that Friendster failed because it didn't innovate enough but instead focused on fixing technical problems.  The article makes clear that slow page loads was a major reason for its downfall.  That and it's cliquey network structure -- but I've addressed that elsewhere.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-116093645165061708?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/116093645165061708/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=116093645165061708' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/116093645165061708'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/116093645165061708'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2006/10/rise-and-fall-of-friendster.html' title='The Rise and Fall of Friendster'/><author><name>Tom</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://photos1.blogger.com/img/36/1021/640/tgaprof.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-116086084086550147</id><published>2006-10-14T13:55:00.000-07:00</published><updated>2006-10-14T15:42:13.056-07:00</updated><title type='text'>hosting : My Selections</title><content type='html'>I signed up with the two web hosting companies I selected this week.  I contacted all 6 companies on &lt;a href="http://phosphorusandlime.blogspot.com/2006/09/hosting-short-list.html"&gt;my short list&lt;/a&gt;.  Based on their responses, they neatly divided into three categories and my decision was relatively easy:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:1.2em; color:#006600;"&gt;My Picks&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Myriad Network&lt;/span&gt; &lt;span style="font-size:75%;"&gt;&lt;a href="http://myriadnetwork.com/"&gt;home&lt;/a&gt; &lt;a href="http://webhostingtalk.com/search.php?searchid=1570865"&gt;webhostingtalk&lt;/a&gt; &lt;a href="http://www.google.com/search?hl=en&amp;q=myriadnetwork&amp;btnG=Google+Search"&gt;google&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;I was very impressed with the responses I received from Jeff Peterson at Myriad Network.  He replied quickly and knowledgeably.  He was quite frank in spelling out for me what his company could do and couldn't do for me.  No sales pitches.  No evasions or vagaries.  And as I've already noted, he helped me solve &lt;a href="http://phosphorusandlime.blogspot.com/2006/10/php-session-array-bug-clarified.html"&gt;a nagging issue with PHP&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;We exchanged over a dozen emails back and forth.  The following is representative of one of Jeff's responses:&lt;br /&gt;&lt;br /&gt;&lt;div class="quote"&gt;Any time someone is found to be using an excessive amount of resources, we try to deal with the situation in a way that interferes with the customer's account as little as humanly possible. For example, the last time this happened, the server reported a higher load than usual, and investigation showed about 5 PHP scripts running under their account that were each using about 20% CPU a piece. 5 scripts x 20% CPU = 100% of one CPU. The issue is that the scripts didn't just run and exit quickly after, but they cotinued to run for minutes at a time, taking a large part of the total available CPU resources on the server. Our action was to stop the scripts from executing, then immediately notify the customer (or the reseller, if this was one of their customers).&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Because, as Jeff made clear, MN does not provide the kind of fully managed hosting on the VPS plans that I was looking for, they are not necessarily my ideal provider.  But shared hosting will satisfy this project for a while, so I signed up with them and hope to stay with them as long as possible.&lt;br /&gt;&lt;br /&gt;Package: &lt;a href="http://myriadnetwork.com/services/hosting/compare.php"&gt;smart source&lt;/a&gt; with dedicated IP&lt;br /&gt;Total Cost for First 3-months (w/ set-up): $45.61 &lt;br /&gt;Project Quarterly Cost: $42.61/qtr&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;West Host&lt;/span&gt; &lt;span style="font-size:75%;"&gt;&lt;a href="http://westhost.com/"&gt;home&lt;/a&gt; &lt;a href="http://webhostingtalk.com/search.php?searchid=1570873"&gt;webhostingtalk&lt;/a&gt; &lt;a href="http://www.google.com/search?hl=en&amp;q=westhost&amp;btnG=Google+Search"&gt;google&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;Matt Platis with West Host promptly replied to my query and we exchanged at least 8 emails back and forth.  I get the impression that West Host give a great deal of attention to their sales and customer support (which I distinguish from technical support.)  That said, Matt quickly and informatively answered my questions. The following is characteristic:&lt;br /&gt;&lt;br /&gt;&lt;div class="quote"&gt;You are automatically warned multiple times if you start getting close to your limit at the end of the month for data transfer AND disk space. When you hit your limit for either one, you are warned again. At this point, I would recommend upgrading your account (if not sooner). Once you hit approximately 110% (I believe it's a little higher than this), your site will slow down and eventually be disabled. We do not upgrade (and bill) automatically, but with all the warnings and notifications, you should have no problem upgrading your limits if/when you reach them.&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;West Host offers more a more complete bridge between shared hosting and higher end managed hosting, so they are a better fit in that respect.  There were a couple minor nuisances in setting up my account.  (They also do that thing where they post discount prices that require somewhat unrealistic commitments, e.g. 24 months.)  But I opened a test support ticket (of sorts, it was actually a legitimate question I had about changing php.ini settings for my account) as soon as I signed up and received a useful, detailed response within an hour.&lt;br /&gt;&lt;br /&gt;Package: &lt;a href="http://www.westhost.com/starter-business-hosting.html"&gt;business starter&lt;/a&gt; with dedicated IP&lt;br /&gt;Total Cost for First 3-months (w/ set-up): $39.80 &lt;br /&gt;Project Quarterly Cost: $29.95/qtr&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:1.2em; color:#003300;"&gt;Honorable Mentions&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Future Hosting&lt;/span&gt; &lt;span style="font-size:75%;"&gt;&lt;a href="http://futurehosting.biz/"&gt;home&lt;/a&gt; &lt;a href="http://www.google.com/search?hl=en&amp;q=futurehosting&amp;btnG=Google+Search"&gt;google&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;Vik responded to the second query email I sent to Future Hosting.  He was detailed and candid in his reponses, acknowledging for instance a recent brief server outage.  I decided against FH on this occasion because there seemed to be a bit of a gap between their shared hosting and VPS plans.  But I will look at them again when I am in the market for VPS or dedicated hosting.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Liquid Web&lt;/span&gt; &lt;span style="font-size:75%;"&gt;&lt;a href="http://liquidweb.com/"&gt;home&lt;/a&gt; &lt;a href="http://www.google.com/search?hl=en&amp;q=liquidweb&amp;btnG=Google+Search"&gt;google&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;Travis at Liquid Web initiated contact with me by private message on the Web Hosting Talk site and invited me to contact him personally.  In response to my query email, he asked me not to share details of his reponse publically, though I found his reponses fairly vague -- much less detailed, in any event, than the others responses I received.  He didn't respond to my follow-up letter.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:1.2em; color:#666600;"&gt;No Response&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Host Gator&lt;/span&gt; &lt;span style="font-size:75%;"&gt;&lt;a href="http://hostgator.com/"&gt;home&lt;/a&gt; &lt;a href="http://www.google.com/search?hl=en&amp;q=hostgator&amp;btnG=Google+Search"&gt;google&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;In response to my email, I received an automatic ticketing system reply.  I then got an email inviting me to call them at their toll-free number.  If I had not received more detailed responses from the other companies, I probably would have called.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;A Small Orange&lt;/span&gt; &lt;span style="font-size:75%;"&gt;&lt;a href="http://asmallorange.com/"&gt;home&lt;/a&gt; &lt;a href="http://www.google.com/search?hl=en&amp;q=asmallorange&amp;btnG=Google+Search"&gt;google&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;I contacted ASO twice.  I received an automatic ticketing system reply, but no further reply after that.  When I tried to look up my ticket, I got a PHP error. I have a shared hosting account with ASO and know that they have a devoted community and offer an informative forum and wiki.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:1.2em;"&gt;Summary&lt;/span&gt;&lt;br /&gt;I wouldn't rule out any of these companies on the basis of my experience here.  They all made my short list on the basis of the favorable reviews and reports on them I read online.&lt;br /&gt;&lt;br /&gt;I should also note that I am not a network or systems admin, so I have little basis for evaluating the technical merits of these companies.  However, I do have experience with customer service.  When I say that, I mean to discriminate between what I consider polished but ineffective customer service (a la companies like HP that outsource support and often make you jump through a ring or two of utter unhelpfulness) and genuine interest and concern for one's customers.  I think I am also reasonably sensitive to both the importance and the limitations of first impressions.  With that background as a reference, I have to say that I was very favorably impressed with myriadnetwork.com, westhost.com, and futurehosting.biz.&lt;br /&gt;&lt;br /&gt;I plan, to the best of my ability, to follow up with quarterly reports on my hosting picks.  I also hope to put up a page somewhere listing all the companies with which I've done business.  So please accept this summary with those qualifiers and stay tuned.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-size:1.2em;"&gt;Links&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Blog Posts&lt;/span&gt;&lt;br /&gt;&lt;a href="http://phosphorusandlime.blogspot.com/2006/10/letter-to-companies-on-web-hosting.html"&gt;Letter to Companies on Web Hosting Short List&lt;/a&gt;&lt;br /&gt;&lt;a href="http://phosphorusandlime.blogspot.com/2006/09/hosting-server-requirements_28.html"&gt;Hosting : Server Requirements&lt;/a&gt;&lt;br /&gt;&lt;a href="http://phosphorusandlime.blogspot.com/2006/09/hosting-short-list.html"&gt;Hosting : Short List&lt;/a&gt;&lt;br /&gt;&lt;a href="http://phosphorusandlime.blogspot.com/2006/09/wanted-reliable-web-hosting.html"&gt;Wanted: Reliable Web Hosting&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Web Hosting Talk Threads&lt;/span&gt;&lt;br /&gt;&lt;a href="http://webhostingtalk.com/showthread.php?t=554889"&gt;Web Hosting: My Selections&lt;/a&gt;&lt;br /&gt;&lt;a href="http://webhostingtalk.com/showthread.php?t=550731"&gt;Choosing a Host -- My Short List&lt;/a&gt;&lt;br /&gt;&lt;a href="http://webhostingtalk.com/showthread.php?t=549527"&gt;Web Hosting Strategy&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-116086084086550147?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/116086084086550147/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=116086084086550147' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/116086084086550147'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/116086084086550147'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2006/10/hosting-my-selections.html' title='hosting : My Selections'/><author><name>Tom</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://photos1.blogger.com/img/36/1021/640/tgaprof.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-116035333316176016</id><published>2006-10-08T17:13:00.000-07:00</published><updated>2006-10-08T18:01:05.216-07:00</updated><title type='text'>PHP: Get Memory Usage</title><content type='html'>In the final stages of setting up hosting service.  Going with a shared host to start and really trying to get a grasp of how efficiently my scripts run, how well they scale up, and how many users they can accommodate before we'll need to step up to VPS or dedicated hosting.&lt;br /&gt;&lt;br /&gt;I adapted the following script from the &lt;a href="http://www.php.net/manual/en/function.memory-get-usage.php#64156"&gt;PHP site&lt;/a&gt;.  It needs to be directly included so I've compressed the formatting as much as possible:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;function inmem() {&lt;br /&gt;if ( substr(PHP_OS,0,3) == 'WIN') {&lt;br /&gt; exec( 'tasklist /FI "PID eq ' . getmypid() . '" /FO LIST', $output ); &lt;br /&gt; $mb_usage = round(preg_replace( '/[\D]/', '', $output[5] ) / 1024, 3); }&lt;br /&gt;else {&lt;br /&gt; $pid = getmypid(); &lt;br /&gt; exec("ps -eo%mem,rss,pid | grep $pid", $output); &lt;br /&gt; $output = explode("  ", $output[0]); &lt;br /&gt; $mb_usage = round(($output[1] / 1024), 3); }&lt;br /&gt;echo "&amp;lt;h4&amp;gt;current script MB usage : $mb_usage&amp;lt;/h4&amp;gt;"; } // end Fx&lt;br /&gt;&lt;br /&gt;inmem();&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Running it on my current script on my local laptop server, I find it jumps from 28 MB at the beginning of my script, before my codebase has loaded, 34 MB by the end -- which as far as I can tell at this point is not too bad.&lt;br /&gt;&lt;br /&gt;keywords: php, server, resources, usage, optimization&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-116035333316176016?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/116035333316176016/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=116035333316176016' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/116035333316176016'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/116035333316176016'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2006/10/php-get-memory-usage.html' title='PHP: Get Memory Usage'/><author><name>Tom</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://photos1.blogger.com/img/36/1021/640/tgaprof.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17096219.post-116007229558448197</id><published>2006-10-05T11:07:00.000-07:00</published><updated>2006-10-07T11:12:21.343-07:00</updated><title type='text'>PHP: SESSION array bug clarified</title><content type='html'>First posted on this &lt;a href="http://phosphorusandlime.blogspot.com/2006/09/php-php-4-array-namespace-bug.html"&gt;here&lt;/a&gt;.  I hastily posted some code there that summarizes the problem but doesn't actually reproduce it.  The following code in fact reproduces it:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&amp;lt;?php&lt;br /&gt;&lt;br /&gt;session_start();&lt;br /&gt;&lt;br /&gt;if ( empty($_SESSION['is_reloaded']) )&lt;br /&gt;{&lt;br /&gt; $_SESSION['is_reloaded'] = 1;&lt;br /&gt; $_SESSION['ARRAY'] = array( 1, 2, 3, 4);&lt;br /&gt; session_write_close();&lt;br /&gt; header("Location: {$_SERVER['PHP_SELF']}");&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;$ARRAY = array( 'new', 'values' );&lt;br /&gt;&lt;br /&gt;if ( $_SESSION['ARRAY'][0] != 1 ) echo "you've been victimized by the PHP4 array namespace bug";&lt;br /&gt;else { echo "bug not detected"; }&lt;br /&gt;&lt;br /&gt;?&amp;gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;An online demo can be seen here:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://westerndep.com/code/phparraybugtest.php"&gt;http://westerndep.com/code/phparraybugtest.php&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This is a really critical issue for me in choosing a host for some of my projects.&lt;br /&gt;&lt;br /&gt;NOTE: just found this on the PHP bug site:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://bugs.php.net/bug.php?id=36366"&gt;http://bugs.php.net/bug.php?id=36366&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The developer's response:&lt;br /&gt;&lt;br /&gt;&lt;div class="quote"&gt;Thank you for taking the time to write to us, but this is not&lt;br /&gt;a bug. Please double-check the documentation available at&lt;br /&gt;http://www.php.net/manual/ and the instructions on how to report&lt;br /&gt;a bug at http://bugs.php.net/how-to-report.php&lt;br /&gt;&lt;br /&gt;Turn off register_globals if you don't want this behaviour.&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;I have followed &lt;a href="http://www.php.net/manual/en/ini.core.php#ini.register-globals"&gt;the instructions on php.net&lt;/a&gt; and turned off register globals using an .htaccess file (the site notes that you can't use ini_set to turn off in runtime).  I also tried &lt;a href="http://www.php.net/manual/en/faq.misc.php#faq.misc.registerglobals"&gt;this method&lt;/a&gt;.  Nevertheless, I am still getting the error.&lt;br /&gt;&lt;br /&gt;Correction: the .htaccess file appears to have fixed the problem.  I had to restart my browser, however, before I could detect the change.&lt;br /&gt;&lt;br /&gt;This site was quite helpful for me in solving this problem:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.nyphp.org/phundamentals/ini.php"&gt;http://www.nyphp.org/phundamentals/ini.php&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I'd also like to thank Jeff Petersen at &lt;a href="http://myriadnetwork.com/"&gt;Myriad Network&lt;/a&gt; for his assistance in sorting this out.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17096219-116007229558448197?l=phosphorusandlime.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phosphorusandlime.blogspot.com/feeds/116007229558448197/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17096219&amp;postID=116007229558448197' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/116007229558448197'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17096219/posts/default/116007229558448197'/><link rel='alternate' type='text/html' href='http://phosphorusandlime.blogspot.com/2006/10/php-session-array-bug-clarified.html' title='PHP: SESSION array bug clarified'/><author><name>Tom</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://photos1.blogger.com/img/36/1021/640/tgaprof.jpg'/></author><thr:total>1</thr:total></entry></feed>
