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

<channel>
	<title>IONCANNON &#187; utilities</title>
	<atom:link href="http://www.ioncannon.net/category/utilities/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.ioncannon.net</link>
	<description>Thoughts on Software Development and Engineering</description>
	<lastBuildDate>Tue, 03 Jan 2012 13:59:08 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
	<atom:link rel='hub' href='http://www.ioncannon.net/?pushpress=hub'/>
		<item>
		<title>Segmenting WebM Video and the MediaSource API</title>
		<link>http://www.ioncannon.net/utilities/1515/segmenting-webm-video-and-the-mediasource-api/</link>
		<comments>http://www.ioncannon.net/utilities/1515/segmenting-webm-video-and-the-mediasource-api/#comments</comments>
		<pubDate>Tue, 03 Jan 2012 13:59:08 +0000</pubDate>
		<dc:creator>carson</dc:creator>
				<category><![CDATA[utilities]]></category>

		<guid isPermaLink="false">http://www.ioncannon.net/?p=1515</guid>
		<description><![CDATA[For a while now I&#039;ve seen people ask when support for Apple&#039;s Pantos HTTP live streaming would make it past Safari and iOS. The answer seems to have been that it wasn&#039;t clear that Pantos streaming was the best option and something else would come about eventually that would be more flexible. There have been [...]]]></description>
			<content:encoded><![CDATA[<p>For a while now I&#039;ve seen people ask when support for Apple&#039;s <a href="http://tools.ietf.org/html/draft-pantos-http-live-streaming-07">Pantos HTTP live streaming</a> would make it past Safari and iOS. The answer seems to have been that it wasn&#039;t clear that Pantos streaming was the best option and something else would come about eventually that would be more flexible. There have been other options but they involve either Flash or Silverlight and most people want something that works with html5 video. After a long wait it seems like the time is getting close now with the <a href="http://html5-mediasource-api.googlecode.com/svn/trunk/draft-spec/mediasource-draft-spec.html">MediaSource API</a>.</p>
<p>The MediaSource API has experimental support in Chrome and can be enabled by using the chrome://flags option. To see it in action you can go to the <a href="http://d28nuaxr58rcpu.cloudfront.net/MediaSourceAPIDemo/demo.html">MediaSource demo page</a>. You can also read a litte more about it <a href="http://updates.html5rocks.com/2011/11/Stream-video-using-the-MediaSource-API">here</a> although the spec linked to above is probably a better place to learn about it.</p>
<p>A while ago I created a tool for <a href="http://www.ioncannon.net/projects/http-live-video-stream-segmenter-and-distributor/">segmenting H264 video</a> in a Pantos compliant way. When I saw the MediaSource API I wondered how the same type of tool might fit in. The first thing to note is that the Pantos draft describes a complete technique for video streaming while the MediaSource API gives you the tools to stream video and leaves the technique. What follows is a simple technique for segmenting a WebM video in a way that allows standard streaming with the MediaSource API in the same fasion as the Pantos draft technique. While this example will not support variable rate streams it could be expanded to do so and would be the next logical step.</p>
<p><span id="more-1515"></span></p>
<p>The basics of how the Pantos technique works are simple. A video is broken down into chunks and each of those chunks is downloaded, buffered and played. In older drafts this ment splitting a video file into multiple files but in later drafts support was added for range requests allowing the large file to remain intact. With that understanding there are two major parts that need to be addressed:</p>
<ul>
<li>Segmenting a WebM video &#8211; This will require some understanding of the container format for WebM and the result will be something like a playlist for the video.</li>
<li>Javascript to play the video &#8211; This will use the playlist created by segmenting the WebM video to drive the MediaSource API.</li>
</ul>
<h2>Segmenting a WebM Video</h2>
<p>Before reading on take a second to read the <a href="http://www.webmproject.org/about/">about WebM</a> page. It describes that WebM specifies a video/audio codec and a container format. We are only interested in the format of the container. If you want all the details you can read the <a href="http://www.webmproject.org/code/specs/container/">WebM container</a> format specs. It is enough to know that the WebM container is a modified version of the <a href="http://matroska.org/">Matroska Container</a> format and both containers use <a href="http://ebml.sourceforge.net/specs/">EBML</a> to specify their structure.</p>
<p>EBML is basically a binary XML format. There are a number of tools available for readin EBML and for my perposes I found the Python <a href="https://github.com/jspiros/python-ebml">python-ebml</a> implementation to be the easiest to get working.</p>
<p>The MediaSource API wants to be fed chunks of video data in a specific way. First it wants header information and then it wants what are called <a href="http://www.webmproject.org/code/specs/container/#cluster">clusters</a> from the WebM container. Each cluster contains various information but the most likely reason for wanting a cluster as input is that each cluster starts with a keyframe. A keyframe is an important reference point in the video stream and one that gets built on until the next keyframe.</p>
<p>The following code will take as input a WebM file and output a playlist for that file in JSON format. The playlist will contain the offsets of each cluster in the given WebM video and we will use it later to fetch the header and each cluster as chunks and feed those to a video element:</p>
<pre class="brush: python; title: ; notranslate">
from ebml.schema import EBMLDocument, UnknownElement, CONTAINER, BINARY

def fill_video_info(element, offset, video_info):
  if element.name == 'Duration':
    video_info['duration'] = element.value

  if element.name == 'DisplayWidth':
    video_info['width'] = element.value

  if element.name == 'DisplayHeight':
    video_info['height'] = element.value

  if element.name == 'Cluster':
    video_info['clusters'].append({'offset': offset})

  if element.name == 'Timecode':
    video_info['clusters'][-1]['timecode'] = element.value

  if element.type == CONTAINER:
    for sub_el in element.value:
      fill_video_info(sub_el, offset + element.head_size, video_info)
      offset += sub_el.size

if __name__ == '__main__':
  import sys
  import json
  import os

  mod_name, _, cls_name = 'ebml.schema.matroska.MatroskaDocument'.rpartition('.')
  try:
    doc_mod = __import__(mod_name, fromlist=[cls_name])
    doc_cls = getattr(doc_mod, cls_name)
  except ImportError:
    parser.error('unable to import module %s' % mod_name)
  except AttributeError:
    parser.error('unable to import class %s from %s' % (cls_name, mod_name))

  video_info = {}
  video_info['filename'] = sys.argv[1]
  video_info['total_size'] = os.stat(sys.argv[1]).st_size
  video_info['clusters'] = []

  with open(sys.argv[1], 'rb') as stream:
    doc = doc_cls(stream)
    offset = 0
    for el in doc.roots:
      fill_video_info(el, offset, video_info)
      offset += el.size

  print json.dumps(video_info)
</pre>
<p>To run the script you will want to save the above script and install the module then do something like this:</p>
<pre class="brush: bash; title: ; notranslate">
git clone https://github.com/jspiros/python-ebml.git
PYTHONPATH=python-ebml python create_playlist.py test.webm
</pre>
<p>Running the script will result in JSON output that can be piped to a file and used as a playlist.</p>
<h2>Javascript to Play the WebM Segmented Playlist</h2>
<p>Feeding data to the MediaSource API is done with Javascript. The first thing to do is read in the JSON playlist file created by the Python script when the page is finished loading. To do that I&#039;m using the Snack JS framework, it is micro-framework that has some of the features of JQuery. After reading in the playlist chunks of the WebM file need to be read in with range requests.</p>
<p>A while ago I made created a post about <a href="http://www.ioncannon.net/programming/1506/range-requests-with-ajax/">range requests with ajax</a> and that comes in handy here. The main difference between that post and what we need here is that the MediaSource API expects a typed array as input so we need to use <a href="http://www.w3.org/TR/XMLHttpRequest2/">XHR2</a>.</p>
<p>The following Javascript code is bare bones. One of the most obvious limitations is that it doesn&#039;t have the ability to seek to a portion of the stream, it will only play the stream start to finish or if the player has the content buffered it should allow for seeking in the buffered portion. It demonstrates that the API works and should be a good starting point for experimenting more with multi-rate streaming which is my short term goal.</p>
<pre class="brush: jscript; title: ; notranslate">
  /**
   * This fetches a chunk of video using a range request.
   *   video_name - The relative filename of the video to fetch
   *   start_bytes - The start byte of the chunk to fetch
   *   end_bytes - The last byte of the chunk to fetch
   *   is_last - True if this is the last chunk to fetch
   */
  function fetch_chunk(video, video_name, start_bytes, end_bytes, is_last)
  {
    var range_req = 'bytes=' + start_bytes + '-' + end_bytes;

    var xhr = new XMLHttpRequest();
    xhr.open('GET', video_name, true);
    xhr.setRequestHeader(&quot;Range&quot;, range_req);
    xhr.responseType = 'arraybuffer';

    xhr.onload = function(e)
    {
      video.webkitSourceAppend(new Uint8Array(this.response));

      if(is_last)
      {
        video.webkitSourceEndOfStream(HTMLMediaElement.EOS_NO_ERROR);
      }
    };

    xhr.send();
  }

  /**
   * Fetch the header portion of the video file.
   */
  function fetch_header(video, video_info)
  {
    fetch_chunk(video, video_info.filename, 0, video_info.clusters[0].offset-1, video_info.clusters.length == 1);
  }

  var current_cluster = 0;

  /**
   * Fetch the next cluster of the video file.
   */
  function fetch_next_cluster(video, video_info)
  {
    if(video_info.clusters.length == current_cluster+1)
    {
      fetch_chunk(video, video_info.filename, video_info.clusters[current_cluster].offset, video_info.total_size, true);
    }
    else
    {
      fetch_chunk(video, video_info.filename, video_info.clusters[current_cluster].offset, video_info.clusters[current_cluster+1].offset-1, false);
    }

    current_cluster++;
  }

  /**
   * Enable the video for MediaSource and attach event listeners to drive the fetching of video chunks.
   */
  function video_setup(video_info)
  {
    current_cluster = 0;

    video.src = video.webkitMediaSourceURL;

    video.addEventListener('webkitsourceopen', function(e)
    {
      var video = this;

      fetch_header(video, video_info);
      fetch_next_cluster(video, video_info);
    }, false);

    video.addEventListener('progress', function(e)
    {
      var video = this;

      if( video.webkitSourceState != HTMLMediaElement.SOURCE_ENDED )
      {
        fetch_next_cluster(video, video_info);
      }
    });
  }

  /**
   * When the page is done loading read in the JSON playlist and get the video set up.
   */
  snack.ready(function()
  {
    if (!video.webkitMediaSourceURL)
    {
      alert('webkitMediaSourceURL is not available');
      return;
    }

    snack.request({ method: 'get', url: 'test.json', }, function (err, res)
    {
      if (err)
      {
        alert(err);
        return;
      }

      video_setup(snack.parseJSON(res));
    });
  });
</pre>
<p>Assuming you have enabled support in Chrome (currently the only browser to support the API) you can see everything in action by checking out my <a href="http://d28nuaxr58rcpu.cloudfront.net/MediaSourceAPIDemo/demo.html">MediaSource API demo</a> page.</p>
<p>I have glossed over a lot of details but the main take aways are that the MediaSource API gives you the interface to build a Pantos streaming system, segment WebM on clusters to feed to the MediaSource API and use XHR2 to fetch the WebM data with range requests. As one last point a lot of the best practices for encoding video for Pantos streaming will work here as well.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ioncannon.net/utilities/1515/segmenting-webm-video-and-the-mediasource-api/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Google Analytics Dashboard WordPress Plugin Version 2.0 Released</title>
		<link>http://www.ioncannon.net/utilities/1460/google-analytics-dashboard-wordpress-plugi-version-2-0-released/</link>
		<comments>http://www.ioncannon.net/utilities/1460/google-analytics-dashboard-wordpress-plugi-version-2-0-released/#comments</comments>
		<pubDate>Tue, 22 Feb 2011 14:13:22 +0000</pubDate>
		<dc:creator>carson</dc:creator>
				<category><![CDATA[utilities]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://www.ioncannon.net/?p=1460</guid>
		<description><![CDATA[It has taken me a while but I&#039;ve finally been able to release version 2 of the Google Analytics Dashboard WordPress Plugin. The primary enhancement of this version is that it no longer blocks the dashboard, posts or pages interfaces while loading. The next major change is an upgrade to using Google&#039;s OAuth login system [...]]]></description>
			<content:encoded><![CDATA[<p>It has taken me a while but I&#039;ve finally been able to release version 2 of the <a href="http://www.ioncannon.net/projects/google-analytics-dashboard-wordpress-widget/">Google Analytics Dashboard WordPress Plugin</a>. The primary enhancement of this version is that it no longer blocks the dashboard, posts or pages interfaces while loading. The next major change is an upgrade to using Google&#039;s OAuth login system (see my <a href="http://www.ioncannon.net/programming/1443/google-oauth-for-installed-apps-php-example/">Google OAuth example using PHP</a> for more information on how I did that if you are interested). The old login system is still available but the OAuth login is the one to use going forward and I may remove the old one at some point. The move to OAuth along with the refactoring I did to the code will allow support for other Google sites such as Feedburner. As a bonus I also moved the caching system to the newer WordPress transient storage interface. The use of the transient storage interface should fix one of the biggest issues people have seen in the past so no more worrying about finding a temp directory that is writable.</p>
<p>Here are a list of the major changes:</p>
<ul>
<li>The dashboard panel now loads asynchronously so the entire dashboard doesn&#039;t block while it is loading</li>
<li>Made the analytics column in posts and pages load asynchronously so that it doesn&#039;t block the loading of the page</li>
<li>Added support for Google OAuth logins</li>
<li>Use transient API support with wordpress version 2.8+</li>
<li>Added ability to support multiple analytics sources</li>
</ul>
<p>Some other minor changes:</p>
<ul>
<li>Stop unlink warnings when caching won&#039;t work</li>
<li>Refactored code so that major parts are split into classes</li>
<li>Refactored code to better seperate UI code</li>
<li>Fixed mime type not being sent correctly for admin area javascript file</li>
<li>Fix bug in wordpress version checking</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.ioncannon.net/utilities/1460/google-analytics-dashboard-wordpress-plugi-version-2-0-released/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Java AirPlay Client</title>
		<link>http://www.ioncannon.net/utilities/1436/java-airplay-client/</link>
		<comments>http://www.ioncannon.net/utilities/1436/java-airplay-client/#comments</comments>
		<pubDate>Tue, 25 Jan 2011 14:36:04 +0000</pubDate>
		<dc:creator>carson</dc:creator>
				<category><![CDATA[utilities]]></category>
		<category><![CDATA[airplay]]></category>
		<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://www.ioncannon.net/?p=1436</guid>
		<description><![CDATA[Ever since getting one of the new AppleTV devices I have been wanting to fiddle with AirPlay. I finally got around to looking at a dump of the traffic between an iPad and the AppleTV over Christmas and was surprised at how simple it was. Soon after I noticed a blog post about AirFlick for [...]]]></description>
			<content:encoded><![CDATA[<p>Ever since getting one of the new AppleTV devices I have been wanting to fiddle with AirPlay. I finally got around to looking at a dump of the traffic between an iPad and the AppleTV over Christmas and was surprised at how simple it was. Soon after I noticed a blog post about <a href="http://ericasadun.com/ftp/AirPlay/">AirFlick</a> for the Mac. AirFlick was close to what I was wanting at the time but I really wanted something that would let me control AirPlay from Linux or Windows.</p>
<p>I decided to make something that could run anywhere so I created my own AirPlay client called <a href="http://www.ioncannon.net/projects/ap4j-player-java-airplay-player/">AP4J</a>. I used Java and a pure Java Bonjour implementation called <a href="http://jmdns.sourceforge.net/">JmDNS</a> so AP4J can run anywhere Java runs.</p>
<p>The current version only has the ability to control an AirPlay device. That means you have to supply a location that has a compatible video (h264 encoded) but once playing you will have control over the video just as you would using the iPad or iPhone. The next step will be to add the ability to directly serve videos instead of only being able to control the playback of videos. My goal will be the ability to run AP4J on my Windows Home Media server where I can have it stream videos to my AppleTV.</p>
<p>I have tested AP4J on Linux, Windows and Mac but only extensively on Linux. I have also tested a number of sites that have compatible videos available, a few of those are listed here:</p>
<ul>
<li><a href="http://blip.tv/">http://blip.tv/</a></li>
<li><a href="http://blip.tv/">http://www.archives.org/</a></li>
<li><a href="http://blip.tv/">http://confreaks.net/</a></li>
</ul>
<p>Now for a couple screen shots. This is what you see after starting the server and going to the web interface:</p>
<p><a href="http://www.ioncannon.net/wp-content/uploads/2011/01/ap4jmain.png"><img src="http://www.ioncannon.net/wp-content/uploads/2011/01/ap4jmain.png" alt="" title="Java AirPlay Application Main Menu" width="353" height="204" class="alignnone size-full wp-image-1431" /></a></p>
<p>This is what it looks like when a video is playing:</p>
<p><a href="http://www.ioncannon.net/wp-content/uploads/2011/01/ap4jpopup.png"><img src="http://www.ioncannon.net/wp-content/uploads/2011/01/ap4jpopup.png" alt="" title="Java AirPlay Application Play Popup" width="698" height="407" class="alignnone size-full wp-image-1432" /></a> <br/></p>
]]></content:encoded>
			<wfw:commentRss>http://www.ioncannon.net/utilities/1436/java-airplay-client/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>VNC on OS X + Devil&#039;s Pie = seamless desktop</title>
		<link>http://www.ioncannon.net/linux/164/vnc-on-os-x-devils-pie-seamless-desktop/</link>
		<comments>http://www.ioncannon.net/linux/164/vnc-on-os-x-devils-pie-seamless-desktop/#comments</comments>
		<pubDate>Mon, 09 Feb 2009 12:28:34 +0000</pubDate>
		<dc:creator>carson</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[utilities]]></category>
		<category><![CDATA[devilspie]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[vnc]]></category>

		<guid isPermaLink="false">http://www.ioncannon.net/?p=164</guid>
		<description><![CDATA[I&#039;ve been doing iPhone development lately using a mac mini. When we first started looking at developing for the iPhone it seemed like overkill to go out and buy multiple macbooks or one macbook to share between developers so instead we got a mac mini to share using Vine VNC. For reference we are able [...]]]></description>
			<content:encoded><![CDATA[<p>I&#039;ve been doing iPhone development lately using a mac mini. When we first started looking at developing for the iPhone it seemed like overkill to go out and buy multiple macbooks or one macbook to share between developers so instead we got a mac mini to share using <a href="http://www.testplant.com/products/vine_viewer">Vine VNC</a>. </p>
<p>For reference we are able to share the mac mini by taking advantage of <a href="http://en.wikipedia.org/wiki/Fast_user_switching">fast user switching</a> for more information see this guide on using <a href="http://www.testplant.com/products/vine_viewer/multidesktop">Multiple Desktop Sessions on Mac OS X</a>.</p>
<p>The VNC part is pretty easy once you have the multiple desktop sessions working. I&#039;ve been doing development on a linux box that has two monitors connected so I will open the desktop in one window and all the non-mac stuff in the other. After using the VNC desktop like that for a while I started to get annoyed by the window decorations so I looked to see what I could do to remove them and that is when I ran into <a href="http://burtonini.com/blog/computers/devilspie">Devil&#039;s Pie</a>.</p>
<p>Devil&#039;s Pie runs as an application in the background and watches for window events that you set up in a configuration file. When it sees the events it can do all kinds of fancy things to the window like remove decorations and set position. It turns out there isn&#039;t a lot of documentation on the configuration language but I did find a <a href="http://live.gnome.org/DevilsPie">configuration language reference</a>, a <a href="http://code.google.com/p/gdevilspie/">gnome configuration file editor</a> that kind of works depending on what you need it to do, a <a href="https://help.ubuntu.com/community/Devilspie">decent reference</a>, some <a href="http://foosel.org/linux/devilspie">configuration examples</a>, and best of all an <a href="http://ubuntu-tutorials.com/2007/07/25/how-to-set-default-workspace-size-and-window-effects-in-gnome/">example of how to remove window effects</a>. With all that I was able to cobble together the following configuration file:</p>
<div class="codesnip-container" >
<div class="text codesnip" style="font-family:monospace;">(if (contains (window_name) &quot;VNC:&quot;) (begin (undecorate) (maximize) (geometry &quot;+1280+0&quot;)))</div>
</div>
<p>This says to undecorate, maximize, and set the geometry of any window that contains the value &#034;VNC:&#034;. The undecorate will strip the title bar and any border from the window, the maximize does what it says to the window, and the geometry in my case puts the window on the right hand screen. I tweaked the background for my account in OS X and the resulting combination of it all looks like this:</p>
<p><a href="http://d28nuaxr58rcpu.cloudfront.net/remotemac/macdesktop-1024.png"><img width="520" src="http://d28nuaxr58rcpu.cloudfront.net/remotemac/macdesktop-800.png"/></a><br/>(Click the image to see a larger version)<br/></p>
<p>So now I have what feels like an OS X box integrated right into my normal desktop.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ioncannon.net/linux/164/vnc-on-os-x-devils-pie-seamless-desktop/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using scrub to destroy a hard drive</title>
		<link>http://www.ioncannon.net/system-administration/272/using-scrub-to-destroy-a-hard-drive/</link>
		<comments>http://www.ioncannon.net/system-administration/272/using-scrub-to-destroy-a-hard-drive/#comments</comments>
		<pubDate>Tue, 20 Jan 2009 12:33:40 +0000</pubDate>
		<dc:creator>carson</dc:creator>
				<category><![CDATA[system administration]]></category>
		<category><![CDATA[utilities]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[shred]]></category>

		<guid isPermaLink="false">http://www.ioncannon.net/?p=272</guid>
		<description><![CDATA[Recently I had a hard drive failure that pushed me into getting a little NAS device that I could back up to S3 easily. After consolidating a lot of data to the NAS I was left with a few old hard drives that I needed to do something with as well as some existing hard [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I had a hard drive failure that pushed me into getting a little <a href="http://www.dlink.com/products/?pid=509">NAS device</a> that I could back up to <a href="http://aws.amazon.com/s3/">S3</a> easily. After consolidating a lot of data to the NAS I was left with a few old hard drives that I needed to do something with as well as some existing hard drives that I&#039;ve collected over the years. Some of the drives I have are from family members that I have recycled computers for but kept the hard drives out of fear that personal data might still be on them. At the same time this was happening I read an article claiming that a <a href="http://www.securityfocus.com/brief/888">single drive wipe protects data</a>.</p>
<p><span id="more-272"></span></p>
<p>I started digging a little more to see just how effective a single drive wipe might be and found the old wisdom in this article: <a href="http://www.cs.auckland.ac.nz/~pgut001/pubs/secure_del.html">Secure Deletion of Data from Magnetic and Solid-State Memory</a>. Scanning over this older article I noticed that it had been updated with a response to the <a href="http://sansforensics.wordpress.com/2009/01/15/overwriting-hard-drive-data/">latest article</a> on the <a href="http://www.springerlink.com/content/408263ql11460147/?p=650ee5e3e45d4e1e845e2bfe8a959f1a&#038;pi=20">effectiveness overwriting a drive with a single pass random data</a>. After reading through the articles I decided that overwriting was good enough. I figure if it doesn&#039;t completely destroy the data it will make it hard enough to not be worth recovering. </p>
<p>The first step I took was to get a <a href="http://www.knoppix.org/">Knoppix</a> live CD. Doing this let me remove data on any drive that I could connect to the PC. The next step was to run the <b>shred</b> command on each disk that I wanted to destroy (<b>shred</b> happens to be on the Knoppix live CD):</p>
<div class="codesnip-container" >
<div class="bash codesnip" style="font-family:monospace;"><span class="kw2">shred</span> <span class="re5">-zv</span> <span class="re5">-n</span> <span class="nu0">3</span> <span class="sy0">/</span>dev<span class="sy0">/</span>hda</div>
</div>
<p>The options I used have the following meaning:</p>
<p>z &#8211; zero the drive once the random passes are done<br />
v &#8211; verbose, shows the progress<br />
n &#8211; number of passes to make writing random data</p>
<p>You can have <b>shred</b> make as many passes as you want and the default is 25 passes as described in <a href="http://www.cs.auckland.ac.nz/~pgut001/pubs/secure_del.html">Secure Deletion of Data from Magnetic and Solid-State Memory</a>. Depending on how fast and how large the drive is this command can take a really long time to run. I decided that 3 passes would be good enough for me. I will still probably hold on to most of the disks in question just in case I want to use them later but I now don&#039;t feel like I can&#039;t toss them if I no longer need them.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ioncannon.net/system-administration/272/using-scrub-to-destroy-a-hard-drive/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>The Search for Timezone Maps</title>
		<link>http://www.ioncannon.net/utilities/137/the-search-for-timezone-maps/</link>
		<comments>http://www.ioncannon.net/utilities/137/the-search-for-timezone-maps/#comments</comments>
		<pubDate>Fri, 17 Oct 2008 03:25:46 +0000</pubDate>
		<dc:creator>carson</dc:creator>
				<category><![CDATA[gis]]></category>
		<category><![CDATA[meta]]></category>
		<category><![CDATA[utilities]]></category>

		<guid isPermaLink="false">http://www.ioncannon.net/?p=137</guid>
		<description><![CDATA[For a while I had been casually searching for a way to overlay US time zones over a map for a project I was working on. It was never important enough to have a solution that required paying for something so I was searching for some type of government data source. My first attempt was [...]]]></description>
			<content:encoded><![CDATA[<p>For a while I had been casually searching for a way to overlay US time zones over a map for a project I was working on. It was never important enough to have a solution that required paying for something so I was searching for some type of government data source. </p>
<p><span id="more-137"></span></p>
<p>My first attempt was to use <a href="http://aa.usno.navy.mil/graphics/TimeZoneMap0802.jpg">this large international timezone map</a>, <a href="http://en.wikipedia.org/wiki/Image:National-atlas-timezones-2006.gif">this wikipedia map</a> or <a href="http://en.wikipedia.org/wiki/List_of_U.S._states_by_time_zone">the list of US states by time zone</a> and then trace and outline over the states. This turned out to be a non-starter because the maps aren&#039;t detailed enough and the list of states doesn&#039;t give you enough information.</p>
<p>I figured I would end up looking for <a href="http://www.esri.com/news/arcuser/0401/topo.html">ESRI shape files</a> at some point and that is where I turned next. An initial google search got me to <a href="http://laughingmeme.org/2004/04/09/timezone-shape-files/">a post</a> that led to a <a href="http://fri.sfasu.edu/data/geographic/world/shape/">link to what should have been a set of shape files</a>. Of course the link was dead so I turned to archive.org and <a href="http://web.archive.org/web/20030705005855/http://fri.sfasu.edu/data/geographic/world/shape/">found that the archive was incomplete</a>.</p>
<p>I reverted back to looking for another source and found <a href="http://data.crgsc.org/geographic/world/shape/">a set of shapes that ended up being just a bunch of squares</a>. At this point I had gone over a lot of random links that didn&#039;t get me anything and I was about to give up for good when I finally found <a href="http://www-atlas.usgs.gov/atlasftp.html?openChapters=chpbound#chpref">the USGS atlas site&#039;s time zone data</a>. This was the jackpot, not only do they have time zone shapefiles but they have a large number of other shapefiles that could come in handy some day. This quest has made it apparent to me that the government doesn&#039;t do a great job of getting their data found.</p>
<p>One helpful tool in my shapefile search was <a href="http://www.esri.com/software/arcexplorer/index1.html">ESRI&#039;s free Arc Explorer</a>. It was a quick way to validate the shapefiles where or where not what I was looking for before landing on a set of files that would work.</p>
<p>Now that I had a valid set of time zone shapes I created a simple java application using <a href="http://www.osgeo.org/geotools">geotools</a> to read the files in and generate a resulting map graphic that I could overlay in the project. The shapefiles are easily converted to lat/lon polygons so using this data to overlay on something like a google map would be even easier.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ioncannon.net/utilities/137/the-search-for-timezone-maps/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>PowerDNS Makes Custom DNS Backends Easy</title>
		<link>http://www.ioncannon.net/system-administration/135/powerdns-custom-dns-backend/</link>
		<comments>http://www.ioncannon.net/system-administration/135/powerdns-custom-dns-backend/#comments</comments>
		<pubDate>Sun, 14 Sep 2008 22:55:41 +0000</pubDate>
		<dc:creator>carson</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[system administration]]></category>
		<category><![CDATA[utilities]]></category>

		<guid isPermaLink="false">http://www.ioncannon.net/?p=135</guid>
		<description><![CDATA[I ran into PowerDNS recently when I needed to find a DNS server that would allow me to produce custom responses to domain queries. I needed to have a request for a DNS entry return a different IP depending on some factors in a database and I needed that data to always be accurate (not [...]]]></description>
			<content:encoded><![CDATA[<p>I ran into <a href="http://www.powerdns.com/">PowerDNS</a> recently when I needed to find a DNS server that would allow me to produce custom responses to domain queries. I needed to have a request for a DNS entry return a different IP depending on some factors in a database and I needed that data to always be accurate (not cached locally). I found that PowerDNS allows for a lot of customization and I ended up using its <a href="http://doc.powerdns.com/pipebackend-dynamic-resolution.html">piped backend for dynamic queries</a> feature.</p>
<p>With this level of customization you can do things like write your own <a href="http://en.wikipedia.org/wiki/DNS_Blacklist">DNS black list</a>, track who is making DNS requests, give out IP addresses based on a servers availability or use geographic information to return a different IP.</p>
<p><span id="more-135"></span></p>
<p>The following is an overview of how to set up your own PowerDNS piped backend process. To start out it may help to read the <a href="http://doc.powerdns.com/backends-detail.html">overview of the PowerDNS backend</a>. </p>
<p>Here is an example program that is run directly by PowerDNS using pipes:</p>
<div class="codesnip-container" >
<div class="java codesnip" style="font-family:monospace;"><span class="kw1">import</span> <span class="co2">java.io.BufferedReader</span><span class="sy0">;</span><br />
<span class="kw1">import</span> <span class="co2">java.io.InputStreamReader</span><span class="sy0">;</span><br />
<span class="kw1">import</span> <span class="co2">java.io.IOException</span><span class="sy0">;</span></p>
<p><span class="kw1">public</span> <span class="kw1">class</span> PowerDNSPipeTest<br />
<span class="br0">&#123;</span><br />
&nbsp; <span class="kw1">public</span> <span class="kw1">static</span> <span class="kw4">void</span> main<span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a><span class="br0">&#91;</span><span class="br0">&#93;</span> args<span class="br0">&#41;</span> <span class="kw1">throws</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aexception+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">Exception</span></a><br />
&nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Abufferedreader+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">BufferedReader</span></a> reader <span class="sy0">=</span> <span class="kw1">new</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Abufferedreader+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">BufferedReader</span></a><span class="br0">&#40;</span><span class="kw1">new</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Ainputstreamreader+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">InputStreamReader</span></a><span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Asystem+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">System</span></a>.<span class="me1">in</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></p>
<p>&nbsp; &nbsp; readIntro<span class="br0">&#40;</span>reader<span class="br0">&#41;</span><span class="sy0">;</span></p>
<p>&nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> line<span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">while</span><span class="br0">&#40;</span><span class="br0">&#40;</span>line <span class="sy0">=</span> reader.<span class="me1">readLine</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="sy0">!=</span> <span class="kw2">null</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; processLine<span class="br0">&#40;</span>line<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; <span class="kw1">private</span> <span class="kw1">static</span> <span class="kw4">void</span> processLine<span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> line<span class="br0">&#41;</span><br />
&nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> values<span class="br0">&#91;</span><span class="br0">&#93;</span> <span class="sy0">=</span> line.<span class="me1">split</span><span class="br0">&#40;</span><span class="st0">&quot;<span class="es0">\t</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>values.<span class="me1">length</span> <span class="sy0">==</span> <span class="nu0">6</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span class="co1">// Testing any a response to the ANY or A record request</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span><span class="st0">&quot;ANY&quot;</span>.<span class="me1">equalsIgnoreCase</span><span class="br0">&#40;</span>values<span class="br0">&#91;</span>3<span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="sy0">||</span> <span class="st0">&quot;A&quot;</span>.<span class="me1">equalsIgnoreCase</span><span class="br0">&#40;</span>values<span class="br0">&#91;</span>3<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Asystem+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">System</span></a>.<span class="me1">out</span>.<span class="me1">println</span><span class="br0">&#40;</span><span class="st0">&quot;DATA<span class="es0">\t</span>&quot;</span> <span class="sy0">+</span> values<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span> <span class="sy0">+</span> <span class="st0">&quot;<span class="es0">\t</span>IN<span class="es0">\t</span>A<span class="es0">\t</span>0<span class="es0">\t</span>1800<span class="es0">\t</span>127.0.0.5&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Asystem+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">System</span></a>.<span class="me1">out</span>.<span class="me1">println</span><span class="br0">&#40;</span><span class="st0">&quot;LOG<span class="es0">\t</span>PowerDNS sent unpareable string&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Asystem+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">System</span></a>.<span class="me1">out</span>.<span class="me1">println</span><span class="br0">&#40;</span><span class="st0">&quot;FAIL&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Asystem+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">System</span></a>.<span class="me1">out</span>.<span class="me1">println</span><span class="br0">&#40;</span><span class="st0">&quot;END&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Asystem+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">System</span></a>.<span class="me1">out</span>.<span class="me1">flush</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; <span class="kw1">private</span> <span class="kw1">static</span> <span class="kw4">void</span> readIntro<span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Abufferedreader+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">BufferedReader</span></a> reader<span class="br0">&#41;</span> <span class="kw1">throws</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aioexception+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">IOException</span></a><br />
&nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> line <span class="sy0">=</span> reader.<span class="me1">readLine</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>line <span class="sy0">!=</span> <span class="kw2">null</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> values<span class="br0">&#91;</span><span class="br0">&#93;</span> <span class="sy0">=</span> line.<span class="me1">split</span><span class="br0">&#40;</span><span class="st0">&quot;<span class="es0">\t</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>values.<span class="me1">length</span> <span class="sy0">==</span> <span class="nu0">2</span> <span class="sy0">&amp;&amp;</span> <span class="st0">&quot;HELO&quot;</span>.<span class="me1">equals</span><span class="br0">&#40;</span>values<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="sy0">&amp;&amp;</span> <span class="st0">&quot;1&quot;</span>.<span class="me1">equals</span><span class="br0">&#40;</span>values<span class="br0">&#91;</span>1<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Asystem+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">System</span></a>.<span class="me1">out</span>.<span class="me1">println</span><span class="br0">&#40;</span><span class="st0">&quot;OK<span class="es0">\t</span>Backend starting&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Asystem+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">System</span></a>.<span class="me1">out</span>.<span class="me1">println</span><span class="br0">&#40;</span><span class="st0">&quot;FAIL&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Asystem+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">System</span></a>.<span class="me1">out</span>.<span class="me1">flush</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Asystem+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">System</span></a>.<span class="me1">exit</span><span class="br0">&#40;</span><span class="sy0">-</span>1<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></div>
</div>
<p>I found that for some reason PowerDNS didn&#039;t want to run the java command directly so I copied that class to /tmp and wrapped the command in a small shell script like this to see if that would fix the problem:</p>
<div class="codesnip-container" >
<div class="bash codesnip" style="font-family:monospace;"><span class="co0">#!/bin/sh</span><br />
<span class="sy0">/</span>usr<span class="sy0">/</span>local<span class="sy0">/</span>java<span class="sy0">/</span>bin<span class="sy0">/</span>java <span class="re5">-cp</span> <span class="sy0">/</span>tmp<span class="sy0">/</span> PowerDNSPipeTest</div>
</div>
<p>In the configuration file I then added:</p>
<div class="codesnip-container" >
<div class="text codesnip" style="font-family:monospace;">launch=pipe<br />
pipe-command=/tmp/powerdns.sh</div>
</div>
<p>This works fine but PowerDNS spawns multiple backend processes to run the piped application and with java that seemed like a bad idea since it would create an entire JVM instance each time. So I decided to modify their sample perl program to send the requests to a long running java background process that would then just use threads.</p>
<div class="codesnip-container" >
<div class="perl codesnip" style="font-family:monospace;"><span class="co1">#!/usr/bin/perl -w</span></p>
<p><span class="kw2">use</span> strict<span class="sy0">;</span></p>
<p><span class="co5">$|</span><span class="sy0">=</span><span class="nu0">1</span><span class="sy0">;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1"># no buffering</span></p>
<p><span class="kw1">my</span> <span class="re0">$line</span><span class="sy0">=&lt;&gt;;</span><br />
<a href="http://perldoc.perl.org/functions/chomp.html"><span class="kw3">chomp</span></a><span class="br0">&#40;</span><span class="re0">$line</span><span class="br0">&#41;</span><span class="sy0">;</span></p>
<p><span class="kw1">unless</span><span class="br0">&#40;</span><span class="re0">$line</span> <span class="kw1">eq</span> <span class="st0">&quot;HELO<span class="es0">\t</span>1&quot;</span><span class="br0">&#41;</span> <br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://perldoc.perl.org/functions/print.html"><span class="kw3">print</span></a> <span class="st0">&quot;FAIL<span class="es0">\n</span>&quot;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://perldoc.perl.org/functions/print.html"><span class="kw3">print</span></a> <span class="kw2">STDERR</span> <span class="st0">&quot;Recevied &#039;$line&#039;<span class="es0">\n</span>&quot;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sy0">&lt;&gt;;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://perldoc.perl.org/functions/exit.html"><span class="kw3">exit</span></a><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<a href="http://perldoc.perl.org/functions/print.html"><span class="kw3">print</span></a> <span class="st0">&quot;OK &nbsp; &nbsp; &nbsp; Sample backend firing up<span class="es0">\n</span>&quot;</span><span class="sy0">;</span> &nbsp; &nbsp;<span class="co1"># print our banner</span></p>
<p><span class="kw1">while</span><span class="br0">&#40;</span><span class="sy0">&lt;&gt;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://perldoc.perl.org/functions/print.html"><span class="kw3">print</span></a> <span class="kw2">STDERR</span> <span class="st0">&quot;$$ Received: $_<span class="es0">\n</span>&quot;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://perldoc.perl.org/functions/chomp.html"><span class="kw3">chomp</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">my</span> <span class="re0">@arr</span><span class="sy0">=</span><a href="http://perldoc.perl.org/functions/split.html"><span class="kw3">split</span></a><span class="br0">&#40;</span><span class="co2">/\t/</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span><span class="re0">@arr</span><span class="sy0">&lt;</span>6<span class="br0">&#41;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a href="http://perldoc.perl.org/functions/print.html"><span class="kw3">print</span></a> <span class="st0">&quot;LOG &nbsp; &nbsp; &nbsp;PowerDNS sent unparseable line<span class="es0">\n</span>&quot;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a href="http://perldoc.perl.org/functions/print.html"><span class="kw3">print</span></a> <span class="st0">&quot;FAIL<span class="es0">\n</span>&quot;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">next</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://perldoc.perl.org/functions/print.html"><span class="kw3">print</span></a> <span class="kw2">STDERR</span> <span class="st0">&quot;$$ Sent A records<span class="es0">\n</span>&quot;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://perldoc.perl.org/functions/print.html"><span class="kw3">print</span></a> <span class="re0">&amp;sendRequest</span><span class="br0">&#40;</span><span class="co5">$_</span> <span class="sy0">.</span> <span class="st0">&quot;<span class="es0">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://perldoc.perl.org/functions/print.html"><span class="kw3">print</span></a> <span class="kw2">STDERR</span> <span class="st0">&quot;$$ End of data<span class="es0">\n</span>&quot;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://perldoc.perl.org/functions/print.html"><span class="kw3">print</span></a> <span class="st0">&quot;END<span class="es0">\n</span>&quot;</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span></p>
<p><span class="kw2">sub</span> sendRequest <br />
<span class="br0">&#123;</span><br />
&nbsp; <span class="kw2">use</span> Socket<span class="sy0">;</span><br />
&nbsp; <span class="kw1">my</span><span class="br0">&#40;</span><span class="re0">$sockaddr</span><span class="sy0">,</span> <span class="re0">$this</span><span class="sy0">,</span> <span class="re0">$that</span><span class="sy0">,</span> <span class="re0">$thataddr</span><span class="sy0">,</span> <span class="re0">$thisaddr</span><span class="sy0">,</span> <span class="re0">$remote</span><span class="sy0">,</span> <span class="re0">$port</span><span class="sy0">,</span> <span class="re0">$iaddr</span><span class="sy0">,</span> <span class="re0">$paddr</span><span class="sy0">,</span> <span class="re0">$proto</span><span class="sy0">,</span> <span class="re0">$line</span><span class="sy0">,</span> <span class="re0">@output</span><span class="br0">&#41;</span><span class="sy0">;</span></p>
<p>&nbsp; <span class="re0">$remote</span> <span class="sy0">=</span> <span class="st0">&quot;127.0.0.1&quot;</span><span class="sy0">;</span><br />
&nbsp; <span class="re0">$port</span> <span class="sy0">=</span> <span class="nu0">4444</span><span class="sy0">;</span><br />
&nbsp; <span class="re0">$sockaddr</span> <span class="sy0">=</span> <span class="st_h">&#039;S n a4 x8&#039;</span><span class="sy0">;</span></p>
<p>&nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re0">$port</span> <span class="sy0">=~</span> <span class="co2">/\D/</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="re0">$port</span> <span class="sy0">=</span> <a href="http://perldoc.perl.org/functions/getservbyname.html"><span class="kw3">getservbyname</span></a><span class="br0">&#40;</span><span class="re0">$port</span><span class="sy0">,</span> <span class="st_h">&#039;tcp&#039;</span><span class="br0">&#41;</span> <span class="br0">&#125;</span><br />
&nbsp; <a href="http://perldoc.perl.org/functions/die.html"><span class="kw3">die</span></a> <span class="st0">&quot;No port&quot;</span> <span class="kw1">unless</span> <span class="re0">$port</span><span class="sy0">;</span><br />
&nbsp; <span class="re0">$thisaddr</span> &nbsp; <span class="sy0">=</span> <a href="http://perldoc.perl.org/functions/gethostbyname.html"><span class="kw3">gethostbyname</span></a><span class="br0">&#40;</span><span class="st0">&quot;localhost&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; <span class="re0">$thataddr</span> &nbsp; <span class="sy0">=</span> <a href="http://perldoc.perl.org/functions/gethostbyname.html"><span class="kw3">gethostbyname</span></a><span class="br0">&#40;</span><span class="re0">$remote</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; <span class="re0">$this</span> &nbsp; <span class="sy0">=</span> <a href="http://perldoc.perl.org/functions/pack.html"><span class="kw3">pack</span></a><span class="br0">&#40;</span><span class="re0">$sockaddr</span><span class="sy0">,</span> AF_INET<span class="sy0">,</span> 0<span class="sy0">,</span> <span class="re0">$thisaddr</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; <span class="re0">$that</span> &nbsp; <span class="sy0">=</span> <a href="http://perldoc.perl.org/functions/pack.html"><span class="kw3">pack</span></a><span class="br0">&#40;</span><span class="re0">$sockaddr</span><span class="sy0">,</span> AF_INET<span class="sy0">,</span> <span class="re0">$port</span><span class="sy0">,</span> <span class="re0">$thataddr</span><span class="br0">&#41;</span><span class="sy0">;</span></p>
<p>&nbsp; <span class="re0">$proto</span> &nbsp; <span class="sy0">=</span> <a href="http://perldoc.perl.org/functions/getprotobyname.html"><span class="kw3">getprotobyname</span></a><span class="br0">&#40;</span><span class="st_h">&#039;tcp&#039;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; <a href="http://perldoc.perl.org/functions/socket.html"><span class="kw3">socket</span></a><span class="br0">&#40;</span>SOCK<span class="sy0">,</span> PF_INET<span class="sy0">,</span> SOCK_STREAM<span class="sy0">,</span> <span class="re0">$proto</span><span class="br0">&#41;</span> &nbsp;<span class="sy0">||</span> <a href="http://perldoc.perl.org/functions/die.html"><span class="kw3">die</span></a> <span class="st0">&quot;socket: $!&quot;</span><span class="sy0">;</span><br />
&nbsp; <a href="http://perldoc.perl.org/functions/bind.html"><span class="kw3">bind</span></a><span class="br0">&#40;</span>SOCK<span class="sy0">,</span> <span class="re0">$this</span><span class="br0">&#41;</span> &nbsp; &nbsp;<span class="sy0">||</span> <a href="http://perldoc.perl.org/functions/die.html"><span class="kw3">die</span></a> <span class="st0">&quot;bind: $!&quot;</span><span class="sy0">;</span><br />
&nbsp; <a href="http://perldoc.perl.org/functions/connect.html"><span class="kw3">connect</span></a><span class="br0">&#40;</span>SOCK<span class="sy0">,</span> <span class="re0">$that</span><span class="br0">&#41;</span> &nbsp; &nbsp;<span class="sy0">||</span> <a href="http://perldoc.perl.org/functions/die.html"><span class="kw3">die</span></a> <span class="st0">&quot;connect: $!&quot;</span><span class="sy0">;</span><br />
&nbsp; <a href="http://perldoc.perl.org/functions/select.html"><span class="kw3">select</span></a><span class="br0">&#40;</span>SOCK<span class="br0">&#41;</span><span class="sy0">;</span> <span class="co5">$|</span> <span class="sy0">=</span> <span class="nu0">1</span><span class="sy0">;</span> <a href="http://perldoc.perl.org/functions/select.html"><span class="kw3">select</span></a><span class="br0">&#40;</span><span class="kw2">STDOUT</span><span class="br0">&#41;</span><span class="sy0">;</span></p>
<p>&nbsp; <a href="http://perldoc.perl.org/functions/print.html"><span class="kw3">print</span></a> SOCK <span class="co5">@_</span><span class="sy0">;</span><br />
&nbsp; <span class="re0">@output</span> <span class="sy0">=</span> <span class="re4">&lt;SOCK&gt;</span><span class="sy0">;</span></p>
<p>&nbsp; <a href="http://perldoc.perl.org/functions/close.html"><span class="kw3">close</span></a> <span class="br0">&#40;</span>SOCK<span class="br0">&#41;</span> <span class="sy0">||</span> <a href="http://perldoc.perl.org/functions/die.html"><span class="kw3">die</span></a> <span class="st0">&quot;close: $!&quot;</span><span class="sy0">;</span><br />
&nbsp; <span class="re0">@output</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span></div>
</div>
<p>Here is the code for the threaded java server modified from the above pipe example:</p>
<div class="codesnip-container" >
<div class="java codesnip" style="font-family:monospace;"><span class="kw1">import</span> <span class="co2">java.net.ServerSocket</span><span class="sy0">;</span><br />
<span class="kw1">import</span> <span class="co2">java.net.Socket</span><span class="sy0">;</span><br />
<span class="kw1">import</span> <span class="co2">java.io.*</span><span class="sy0">;</span><br />
<span class="kw1">import</span> <span class="co2">java.util.concurrent.PriorityBlockingQueue</span><span class="sy0">;</span><br />
<span class="kw1">import</span> <span class="co2">java.util.concurrent.ThreadPoolExecutor</span><span class="sy0">;</span><br />
<span class="kw1">import</span> <span class="co2">java.util.concurrent.TimeUnit</span><span class="sy0">;</span></p>
<p><span class="kw1">public</span> <span class="kw1">class</span> PowerDNSServerTest<br />
<span class="br0">&#123;</span><br />
&nbsp; <span class="kw1">public</span> <span class="kw1">static</span> <span class="kw4">void</span> main<span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a><span class="br0">&#91;</span><span class="br0">&#93;</span> args<span class="br0">&#41;</span> <span class="kw1">throws</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aexception+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">Exception</span></a><br />
&nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; PriorityBlockingQueue<span class="sy0">&lt;</span>Runnable<span class="sy0">&gt;</span> queue <span class="sy0">=</span> <span class="kw1">new</span> PriorityBlockingQueue<span class="sy0">&lt;</span>Runnable<span class="sy0">&gt;</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; ThreadPoolExecutor threadPool <span class="sy0">=</span> <span class="kw1">new</span> ThreadPoolExecutor<span class="br0">&#40;</span>5, 30, 30, TimeUnit.<span class="me1">SECONDS</span>, queue<span class="br0">&#41;</span><span class="sy0">;</span></p>
<p>&nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aserversocket+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">ServerSocket</span></a> serverSocket <span class="sy0">=</span> <span class="kw1">new</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aserversocket+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">ServerSocket</span></a><span class="br0">&#40;</span>4444<span class="br0">&#41;</span><span class="sy0">;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">while</span><span class="br0">&#40;</span><span class="kw2">true</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; threadPool.<span class="me1">execute</span><span class="br0">&#40;</span><span class="kw1">new</span> PowerDNSServerClientThread<span class="br0">&#40;</span>serverSocket.<span class="me1">accept</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; <span class="kw1">private</span> <span class="kw1">static</span> <span class="kw1">class</span> PowerDNSServerClientThread <span class="kw1">implements</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Arunnable+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">Runnable</span></a><br />
&nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">private</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Asocket+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">Socket</span></a> clientSocket<span class="sy0">;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">public</span> PowerDNSServerClientThread<span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Asocket+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">Socket</span></a> clientSocket<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">this</span>.<span class="me1">clientSocket</span> <span class="sy0">=</span> clientSocket<span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">void</span> run<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">try</span><br />
&nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Abufferedreader+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">BufferedReader</span></a> input <span class="sy0">=</span> <span class="kw1">new</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Abufferedreader+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">BufferedReader</span></a><span class="br0">&#40;</span><span class="kw1">new</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Ainputstreamreader+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">InputStreamReader</span></a><span class="br0">&#40;</span>clientSocket.<span class="me1">getInputStream</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Abufferedwriter+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">BufferedWriter</span></a> output <span class="sy0">=</span> <span class="kw1">new</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Abufferedwriter+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">BufferedWriter</span></a><span class="br0">&#40;</span><span class="kw1">new</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aoutputstreamwriter+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">OutputStreamWriter</span></a><span class="br0">&#40;</span>clientSocket.<span class="me1">getOutputStream</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> command <span class="sy0">=</span> input.<span class="me1">readLine</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Asystem+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">System</span></a>.<span class="me1">err</span>.<span class="me1">println</span><span class="br0">&#40;</span><span class="st0">&quot;[&quot;</span> <span class="sy0">+</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Athread+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">Thread</span></a>.<span class="me1">currentThread</span><span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">getName</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">+</span> <span class="st0">&quot;] Received: &quot;</span> <span class="sy0">+</span> command<span class="br0">&#41;</span><span class="sy0">;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> values<span class="br0">&#91;</span><span class="br0">&#93;</span> <span class="sy0">=</span> command.<span class="me1">split</span><span class="br0">&#40;</span><span class="st0">&quot;<span class="es0">\t</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>values.<span class="me1">length</span> <span class="sy0">==</span> <span class="nu0">6</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Testing any a response to the ANY or A record request</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span><span class="st0">&quot;ANY&quot;</span>.<span class="me1">equalsIgnoreCase</span><span class="br0">&#40;</span>values<span class="br0">&#91;</span>3<span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="sy0">||</span> <span class="st0">&quot;A&quot;</span>.<span class="me1">equalsIgnoreCase</span><span class="br0">&#40;</span>values<span class="br0">&#91;</span><span class="nu0">3</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; output.<span class="me1">write</span><span class="br0">&#40;</span><span class="st0">&quot;DATA<span class="es0">\t</span>&quot;</span> <span class="sy0">+</span> values<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span> <span class="sy0">+</span> <span class="st0">&quot;<span class="es0">\t</span>IN<span class="es0">\t</span>A<span class="es0">\t</span>0<span class="es0">\t</span>1800<span class="es0">\t</span>127.0.0.5<span class="es0">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; output.<span class="me1">write</span><span class="br0">&#40;</span><span class="st0">&quot;LOG<span class="es0">\t</span>PowerDNS sent unpareable string<span class="es0">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; output.<span class="me1">write</span><span class="br0">&#40;</span><span class="st0">&quot;FAIL<span class="es0">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; output.<span class="me1">write</span><span class="br0">&#40;</span><span class="st0">&quot;END<span class="es0">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; output.<span class="me1">flush</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; output.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; input.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; clientSocket.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">catch</span> <span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aioexception+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">IOException</span></a> e<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; e.<span class="me1">printStackTrace</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></div>
</div>
<p>In the config file I replaced the above entries with:</p>
<div class="codesnip-container" >
<div class="text codesnip" style="font-family:monospace;">launch=pipe<br />
pipe-command=/tmp/powerdns.pl</div>
</div>
<p>That is all there is to it. So far this is the easiest way I have found of passing requests on to an application. The configuration for PowerDNS also allows you to force a request to the backend with every query eliminating the internal cache. For me that was a needed feature since every request could potentially change from second to second and the latest IP would need to be given out. I found that there are a lot of options for small tweaks like this that are probably on the fringe of what 99% of users need but are very handy to be able to change when you need to change them.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ioncannon.net/system-administration/135/powerdns-custom-dns-backend/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>10 Tips For Creating Good Looking Diagrams Using Inkscape</title>
		<link>http://www.ioncannon.net/utilities/123/10-tips-for-creating-good-looking-diagrams-using-inkscape/</link>
		<comments>http://www.ioncannon.net/utilities/123/10-tips-for-creating-good-looking-diagrams-using-inkscape/#comments</comments>
		<pubDate>Wed, 11 Jul 2007 13:58:07 +0000</pubDate>
		<dc:creator>carson</dc:creator>
				<category><![CDATA[utilities]]></category>

		<guid isPermaLink="false">http://www.ioncannon.net/utilities/123/10-tips-for-creating-good-looking-diagrams-using-inkscape/</guid>
		<description><![CDATA[After multiple attempts to find a good free diagraming application I think I have found a decent solution. I&#039;m not creating enough diagrams to justify buying something expensive and I don&#039;t feel like finding a graphics designer to make Dia diagrams prettier. If you have a Mac you are probably not in as bad a [...]]]></description>
			<content:encoded><![CDATA[<p>After multiple attempts to find a good free diagraming application I think I have found a decent solution. I&#039;m not creating enough diagrams to justify buying something expensive and I don&#039;t feel like finding a graphics designer to make <a href="http://www.gnome.org/projects/dia/">Dia</a> diagrams prettier. If you have a Mac you are probably not in as bad a situation since you can buy <a href="http://www.omnigroup.com/applications/omnigraffle/">OmniGraffle</a> for $79. But for those of us without a Mac or who are just very cheap I think the best solution starts with <a href="http://www.inkscape.org/">Inkscape</a>. I&#039;ve put together a list of 10 tips that will help make better looking diagrams with Inkscape.</p>
<p><span id="more-123"></span></p>
<p>You will want to <a href="http://www.inkscape.org/download/">download Inkscape</a> first. They have binaries for Linux, Windows and Mac OS X so it should be easy enough to get it installed. After installing Inkscape it is a good idea to browse their tutorials via the help->tutorials menu.</p>
<p><strong>1. Find a good color scheme</strong></p>
<p>
This is one of the most important things you need to do. You don&#039;t want the boring black and white diagrams, you want something that has a little color to it. You can use a <a href="http://wellstyled.com/tools/colorscheme2/index-en.html">color picker</a> or you can check out <a href="http://www.colourlovers.com/">colourlovers.com</a> where people vote on different schemes. I like colourlovers.com because they take items like <a href="http://www.colourlovers.com/blog/2007/07/05/fruit-basket-colors/">fruit baskets</a> and convert those into schemes.</p>
<p>I&#039;m using the following color scheme for the examples here:</p>
<p><center><img src="http://d28nuaxr58rcpu.cloudfront.net/inkscape-examples/bowl_of_oranges.png"/></center><br/><br/>
</p>
<p><strong>2. Use all of the space</strong></p>
<p>
Don&#039;t be afraid to use the sides of the screen as a scratch pad. This comes in handy when you want to create smaller images to use in the main drawing area. When you are ready to export you can export just the &#034;page&#034; and you won&#039;t see the outside area in the final result.</p>
<p><img src="http://d28nuaxr58rcpu.cloudfront.net/inkscape-examples/scratch.jpg"/><br/><br/>
</p>
<p><strong>3. Learn the hot keys</strong></p>
<p>
Learning the hot keys will speed up your drawing. The following hot keys are the ones I use the most:</p>
<ul>
<li>group &#8211; Ctrl-G</li>
<li>un-group &#8211; Ctrl-Shift-G</li>
<li>create square &#8211; F4</li>
<li>create circle &#8211; F5</li>
<li>create polygons &#8211; *</li>
<li>transform &#8211; F1</li>
</ul>
<p><strong>4. Use zoom to work close in then zoom out and scale</strong></p>
<p>
I use the zoom function to find a blank area in the &#034;scratch pad&#034; when I want to assemble a shape that may require fine tuning. Since this is a vector drawing it is easy to resize the item later and place it in the correct place after returning to the normal zoom.
</p>
<p><strong>5. Learn how to using masking to make simple shapes</strong></p>
<p>
You can build complex shapes using different simple shapes with path set operations (see the path menu and the advanced tutorial). Here is an example of what a difference operation can create:</p>
<p>First draw a square:</p>
<p><img src="http://d28nuaxr58rcpu.cloudfront.net/inkscape-examples/shape1.jpg"/><br/><br/></p>
<p>Then draw a circle:</p>
<p><img src="http://d28nuaxr58rcpu.cloudfront.net/inkscape-examples/shape2.jpg"/><br/><br/></p>
<p>Then put the circle over the square:</p>
<p><img src="http://d28nuaxr58rcpu.cloudfront.net/inkscape-examples/shape3.jpg"/><br/><br/></p>
<p>Now highlight both the circle and the square:</p>
<p><img src="http://d28nuaxr58rcpu.cloudfront.net/inkscape-examples/shape4.jpg"/><br/><br/></p>
<p>And finally hit Ctrl&#8211;:</p>
<p><img src="http://d28nuaxr58rcpu.cloudfront.net/inkscape-examples/shape5.jpg"/><br/><br/>
</p>
<p><strong>6. Don&#039;t use the connectors tool</strong><br/></p>
<p>
I started out trying to use the connectors tool to connect the objects. I found that the tool didn&#039;t work very well because the connections don&#039;t lay themselves out. If you really want any type of bend you are out of luck. They do bend when you click the layout button but they are almost always too close to the objects.</p>
<p>I found that it wasn&#039;t that hard to just use the polygon tool to draw the lines after I finished laying out the objects. When using the polygon tool don&#039;t add the end markers to the lines however because changing the color of the lines doesn&#039;t change the color of the markers (see step #7). I&#039;ve also found that adjusting the transparency of the lines makes for a better look.
</p>
<p><strong>7. Create your own markers</strong></p>
<p>
As I said in step 6 you will want to create your own markers. For one the <a href="http://tavmjong.free.fr/INKSCAPE/MANUAL/html/Attributes-Stroke.html#Attributes-Stroke-Markers">attributes of a line don&#039;t carry over to the marker</a> so you need them to be separate objects. After you create your marker zoom to the end of the line to do the alignment. I found that it isn&#039;t<br />
that hard to align the markers once you have them created. Then use the group function to group the markers with the lines.
</p>
<p><strong>8. Overlay text on a color to go over lines.</strong></p>
<p>
The easiest way I have found to overlay the text on the lines is to first create a box the same color as the background of the drawing. After you create the box you will need to force it down using the <img src="http://d28nuaxr58rcpu.cloudfront.net/inkscape-examples/forcedown.jpg"/> button. Now that you have a box create your text and lay it over the box. Adjust the size of the box so the entire text is inside of it and then group the box and the text together as one unit. Now you can just place the resulting unit over the line.</p>
<p><center><img src="http://d28nuaxr58rcpu.cloudfront.net/inkscape-examples/textoverlay.jpg"/></center><br/><br/>
</p>
<p><strong>9. Outline your objects</strong></p>
<p>
Outlining your objects seems to make them pop a little more. I also reduce the transparency a little to allow any text on top of the object to stand out. You will want to consult your color scheme to figure out what two colors to use for the fill and outline. </p>
<p><center><img src="http://d28nuaxr58rcpu.cloudfront.net/inkscape-examples/outlined.jpg"/></center><br/><br/>
</p>
<p><strong>10. Import SVG graphics</strong></p>
<p>
I think if I had a pen tablet I could probably draw some more complicated objects but there is no way I could draw everything I might need. Luckily there are a number of sources you can use to get SVG graphics. A number of places sell their art in SVG format and there are a few open source or free sources of clip art/icons. The source I have been using is <a href="http://openclipart.org">openclipart.org</a> (one note on this site is that they are moving to new equipment and I had to use archive.org to <a href="">download the latest open source clipart archive</a>). Another option is to convert a raster image into SVG and then import it that way. You can then use free icons like the <a href="http://www.famfamfam.com/">famfamfam icons</a> in your diagrams. Although converting to SVG this way works it is best to find images that are sourced directly to SVG from their drawing.</p>
<p><img src="http://d28nuaxr58rcpu.cloudfront.net/inkscape-examples/import.jpg"/><br/><br/>
</p>
<p><strong>Bonus Tip &#8211; How to add drop shadows</strong></p>
<p>
Someone asked if you could do drop shadows and it looks like you can by using the <a href="http://wiki.inkscape.org/wiki/index.php/ReleaseNotes045#SVG_filters:_Gaussian_blur">Gaussian Blur</a>. This can make things look better too but you can&#039;t use transparent objects when you do this. After redoing the example I decided I liked the drop shadows better so I&#039;ve included it here.</p>
<p>The first thing is to copy the object you want to have the drop shadow for:</p>
<p><img src="http://d28nuaxr58rcpu.cloudfront.net/inkscape-examples/drop1.jpg"/><br/><br/></p>
<p>Next you want to change the color of the copy to black and set the blur to 10 or so:</p>
<p><img src="http://d28nuaxr58rcpu.cloudfront.net/inkscape-examples/drop2.jpg"/><br/><br/></p>
<p>Now you send the object to the background:</p>
<p><img src="http://d28nuaxr58rcpu.cloudfront.net/inkscape-examples/drop3.jpg"/><br/><br/></p>
<p>And last you align the object a little bit offset from the original:</p>
<p><img src="http://d28nuaxr58rcpu.cloudfront.net/inkscape-examples/drop4.jpg"/><br/><br/></p>
<p>Here is the final result:</p>
<p><img src="http://d28nuaxr58rcpu.cloudfront.net/inkscape-examples/example-dropshadow.png"/><br/><br/></p>
<p>And another copy of the SVG: <a href="http://d28nuaxr58rcpu.cloudfront.net/inkscape-examples/example-dropshadow.svg">dropshadow example</a>
</p>
<p>I wanted to see if I could use these tips to create a diagram that looks similar to what is on the OmniGraffle page. Here is the result of that:</p>
<p><img src="http://d28nuaxr58rcpu.cloudfront.net/inkscape-examples/example.png"/><br/><br/></p>
<p>Good luck and I hope this keeps your next diagram from <a href="http://www.presentationzen.com/presentationzen/2005/10/fema_chart_beco.html">becoming a joke</a>.</p>
<p>Here are a couple links so you can download the <a href="http://d28nuaxr58rcpu.cloudfront.net/inkscape-examples/example.svg">example SVG</a> and the <a href="http://d28nuaxr58rcpu.cloudfront.net/inkscape-examples/cloud.svg">cloud SVG</a> if you want.</p>
<p>Tags: <a href="http://technorati.com/tag/inkscape" rel="tag">inkscape</a>, <a href="http://technorati.com/tag/diagram" rel="tag"> diagram</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.ioncannon.net/utilities/123/10-tips-for-creating-good-looking-diagrams-using-inkscape/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>Acrobat Reader 7 and FC6</title>
		<link>http://www.ioncannon.net/system-administration/121/acrobat-reader-7-and-fc6/</link>
		<comments>http://www.ioncannon.net/system-administration/121/acrobat-reader-7-and-fc6/#comments</comments>
		<pubDate>Wed, 14 Feb 2007 13:41:54 +0000</pubDate>
		<dc:creator>carson</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[system administration]]></category>
		<category><![CDATA[utilities]]></category>

		<guid isPermaLink="false">http://www.ioncannon.net/system-administration/121/acrobat-reader-7-and-fc6/</guid>
		<description><![CDATA[I broke down and wanted to install Adobe Acrobat Reader 7 on my FC6 box to replace xpdf. After installing it from the tar.gz version the acroread startup script bombed out with the error: expr substr 2400000000000 1 After a little searching I didn&#039;t find much help so I started looking at the script myself [...]]]></description>
			<content:encoded><![CDATA[<p>I broke down and wanted to install Adobe Acrobat Reader 7 on my FC6 box to replace xpdf. After installing it from the tar.gz version the acroread startup script bombed out with the error: expr substr 2400000000000 1</p>
<p>After a little searching I didn&#039;t find much help so I started looking at the script myself to see if I could track down the problem. It turns out that it wasn&#039;t that hard to fix. First off the script file was located at: /usr/bin/acroread</p>
<p>Open the script file and find the function named &#034;check_gtk_ver_and_set_lib_path&#034;. This is the location of the first error you will hit. To fix the error you will need to change:</p>
<div class="codesnip-container" >
<div class="text codesnip" style="font-family:monospace;">base_version=`expr substr &quot;${base_version}0000000000&quot; 1 $len_version`</div>
</div>
<p>to</p>
<div class="codesnip-container" >
<div class="text codesnip" style="font-family:monospace;">blah1=&quot;${base_version}0000000000&quot;<br />
base_version=${blah1:1:$len_version}</div>
</div>
<p>You will find this two places and it needs to be changed in both. If you don&#039;t notice the 2nd place it is right after the first in a loop:</p>
<div class="codesnip-container" >
<div class="text codesnip" style="font-family:monospace;">while [ $len_version -gt $len_base_version ]; do</div>
</div>
<p>The second problem you will have is located in the function &#034;get_gtk_file_ver&#034;. Find this function and change the following line:</p>
<div class="codesnip-container" >
<div class="text codesnip" style="font-family:monospace;">echo $mfile| sed &#039;s/libgtk-x11-\([0-9]*\).0.so.0.\([0-9]\)00.\([0-9]*\)\|\(.*\)/\1\2\3/g&#039;</div>
</div>
<p>to</p>
<div class="codesnip-container" >
<div class="text codesnip" style="font-family:monospace;">echo $mfile| sed &#039;s/libgtk-x11-\([0-9]*\).0.so.0.\([0-9]\)000.\([0-9]*\)\|\(.*\)/\1\2\3/g&#039;</div>
</div>
<p>Now you should be able to run acroread without errors.</p>
<p>Tags: <a href="http://technorati.com/tag/acroread" rel="tag">acroread</a>, <a href="http://technorati.com/tag/fedora" rel="tag"> fedora</a>, <a href="http://technorati.com/tag/script" rel="tag"> script</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.ioncannon.net/system-administration/121/acrobat-reader-7-and-fc6/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Akismet spam graphs with PHP RRD</title>
		<link>http://www.ioncannon.net/php/113/akismet-spam-graphs-with-php-rrd/</link>
		<comments>http://www.ioncannon.net/php/113/akismet-spam-graphs-with-php-rrd/#comments</comments>
		<pubDate>Mon, 01 Jan 2007 17:37:33 +0000</pubDate>
		<dc:creator>carson</dc:creator>
				<category><![CDATA[php]]></category>
		<category><![CDATA[utilities]]></category>

		<guid isPermaLink="false">http://www.ioncannon.net/php/113/akismet-spam-graphs-with-php-rrd/</guid>
		<description><![CDATA[After reading a post on hacking Akismet to add graphs I decided I liked the idea but I didn&#039;t want to store the data in a database. It seemed like it would be better to store it using a RRD and then use the PHP RRD library. So after a little hacking I&#039;ve created a [...]]]></description>
			<content:encoded><![CDATA[<p>After reading a post on <a href="http://blog.joshuaeichorn.com/archives/2006/12/21/more-spam-fun/">hacking Akismet to add graphs</a> I decided I liked the idea but I didn&#039;t want to store the data in a database. It seemed like it would be better to store it using a RRD and then use the PHP RRD library. So after a little hacking I&#039;ve created a version that does basically the same thing except uses a RRD.</p>
<p><span id="more-113"></span></p>
<p>A good place to start is the <a href="http://www.ioncannon.net/system-administration/59/php-rrdtool-tutorial/">PHP RRDTool tutorial</a>. It will make it easier to read the following code if you have an idea of how to use the RRDTool extension.</p>
<p>All of the following changes should be made in the plugins/akismet directory.</p>
<p>The first part of the code is akismet_rrd.php that adds a utility function for updating the RRD file. It will create the file if it doesn&#039;t already exist. To gather the stats on incoming spam it uses a timestamp of the last time it ran and then queries WordPress&#039;s comment table for anything marked as spam in increments that match the step used to set up the RRD. The update function can be called in a number of locations but the most efficient seems to be right before any deletes happen.</p>
<div class="codesnip-container" >
<div class="php codesnip" style="font-family:monospace;"><span class="kw2">&lt;?php</span><br />
<a href="http://www.php.net/define"><span class="kw3">define</span></a><span class="br0">&#40;</span><span class="st_h">&#039;AKISMET_RRD_FILE&#039;</span><span class="sy0">,</span> ABSPATH <span class="sy0">.</span> <span class="st_h">&#039;wp-content/plugins/&#039;</span> <span class="sy0">.</span> <a href="http://www.php.net/dirname"><span class="kw3">dirname</span></a><span class="br0">&#40;</span>plugin_basename<span class="br0">&#40;</span><span class="kw4">__FILE__</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="sy0">.</span> <span class="st_h">&#039;/akismet.rrd&#039;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<a href="http://www.php.net/define"><span class="kw3">define</span></a><span class="br0">&#40;</span><span class="st_h">&#039;AKISMET_RRD_TS&#039;</span><span class="sy0">,</span> 300<span class="br0">&#41;</span><span class="sy0">;</span></p>
<p><span class="kw2">function</span> akismet_update_rrd<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; <span class="re0">$last_update</span> <span class="sy0">=</span> get_option<span class="br0">&#40;</span> <span class="st_h">&#039;akismet_stat_last_update&#039;</span> <span class="br0">&#41;</span><span class="sy0">;</span></p>
<p>&nbsp; <span class="re0">$current_time</span> <span class="sy0">=</span> <a href="http://www.php.net/strtotime"><span class="kw3">strtotime</span></a><span class="br0">&#40;</span>current_time<span class="br0">&#40;</span><span class="st_h">&#039;mysql&#039;</span><span class="sy0">,</span> 1<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; <span class="kw1">if</span><span class="br0">&#40;</span><span class="re0">$last_update</span> <span class="sy0">==</span> 0<span class="br0">&#41;</span><br />
&nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="re0">$last_update</span> <span class="sy0">=</span> <span class="re0">$current_time</span> <span class="sy0">-</span> <span class="br0">&#40;</span>AKISMET_RRD_TS <span class="sy0">*</span> 200<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; <span class="re0">$time_diff</span> <span class="sy0">=</span> <span class="re0">$current_time</span> <span class="sy0">-</span> <span class="re0">$last_update</span><span class="sy0">;</span><br />
&nbsp; <span class="kw1">if</span><span class="br0">&#40;</span> <span class="re0">$time_diff</span> <span class="sy0">&gt;</span> AKISMET_RRD_TS <span class="br0">&#41;</span><br />
&nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; update_option<span class="br0">&#40;</span> <span class="st_h">&#039;akismet_stat_last_update&#039;</span><span class="sy0">,</span> <span class="br0">&#40;</span><span class="re0">$current_time</span> <span class="sy0">-</span> <span class="br0">&#40;</span><span class="br0">&#40;</span><span class="re0">$time_diff</span> <span class="sy0">-</span> AKISMET_RRD_TS<span class="br0">&#41;</span> <span class="sy0">%</span> AKISMET_RRD_TS<span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#41;</span><span class="sy0">;</span></p>
<p>&nbsp; &nbsp; akismet_create_rrd<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></p>
<p>&nbsp; &nbsp; <span class="kw2">global</span> <span class="re0">$wpdb</span><span class="sy0">;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">while</span><span class="br0">&#40;</span> <span class="re0">$last_update</span> <span class="sy0">&lt;</span> <span class="re0">$current_time</span> <span class="sy0">-</span> AKISMET_RRD_TS <span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span class="re0">$data</span> <span class="sy0">=</span> <span class="re0">$wpdb</span><span class="sy0">-&gt;</span><span class="me1">get_row</span><span class="br0">&#40;</span><span class="st0">&quot;SELECT COUNT(1) as spam_count FROM <span class="es4">$wpdb-&gt;comments</span> WHERE comment_date_gmt BETWEEN FROM_UNIXTIME(&quot;</span> <span class="sy0">.</span> <span class="re0">$last_update</span> <span class="sy0">.</span> <span class="st0">&quot;) AND FROM_UNIXTIME(&quot;</span> <span class="sy0">.</span> <span class="br0">&#40;</span><span class="re0">$last_update</span> <span class="sy0">+</span> AKISMET_RRD_TS<span class="br0">&#41;</span> <span class="sy0">.</span> <span class="st0">&quot;) AND comment_approved = &#039;spam&#039;&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; <span class="re0">$spam_count</span> <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span><span class="re0">$data</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$spam_count</span> <span class="sy0">=</span> <span class="re0">$data</span><span class="sy0">-&gt;</span><span class="me1">spam_count</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; rrd_update<span class="br0">&#40;</span>AKISMET_RRD_FILE<span class="sy0">,</span> <span class="br0">&#40;</span><span class="re0">$last_update</span> <span class="sy0">+</span> <span class="br0">&#40;</span>get_settings<span class="br0">&#40;</span><span class="st_h">&#039;gmt_offset&#039;</span><span class="br0">&#41;</span> <span class="sy0">*</span> <span class="nu0">3600</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="sy0">.</span> <span class="st0">&quot;:<span class="es4">$spam_count</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span></p>
<p>&nbsp; &nbsp; &nbsp; <span class="re0">$last_update</span> <span class="sy0">+=</span> AKISMET_RRD_TS<span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></p>
<p><span class="kw2">function</span> akismet_create_rrd<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; <span class="kw1">if</span><span class="br0">&#40;</span> <span class="sy0">!</span><a href="http://www.php.net/file_exists"><span class="kw3">file_exists</span></a><span class="br0">&#40;</span>AKISMET_RRD_FILE<span class="br0">&#41;</span> <span class="br0">&#41;</span><br />
&nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="re0">$opts</span> <span class="sy0">=</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span> <span class="st0">&quot;&#8211;step&quot;</span><span class="sy0">,</span> AKISMET_RRD_TS<span class="sy0">,</span> <span class="st0">&quot;&#8211;start&quot;</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;DS:input:ABSOLUTE:600:0:100000&quot;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;RRA:AVERAGE:0.5:1:600&quot;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;RRA:AVERAGE:0.5:6:700&quot;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;RRA:AVERAGE:0.5:24:775&quot;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;RRA:AVERAGE:0.5:288:797&quot;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;RRA:MAX:0.5:1:600&quot;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;RRA:MAX:0.5:6:700&quot;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;RRA:MAX:0.5:24:775&quot;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;RRA:MAX:0.5:288:797&quot;</span><br />
&nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">;</span></p>
<p>&nbsp; &nbsp; rrd_create<span class="br0">&#40;</span>AKISMET_RRD_FILE<span class="sy0">,</span> <span class="re0">$opts</span><span class="sy0">,</span> <a href="http://www.php.net/count"><span class="kw3">count</span></a><span class="br0">&#40;</span><span class="re0">$opts</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></p>
<p><span class="sy1">?&gt;</span></div>
</div>
<p>The next step is the code to create graphs from the RRD in the file akismet_graph.php. This code registers the menu for WordPress in the Dashboard area and when displayed will generate the graphs for a day, month and year.</p>
<div class="codesnip-container" >
<div class="php codesnip" style="font-family:monospace;"><span class="kw2">&lt;?php</span><br />
<span class="kw1">include_once</span> <span class="br0">&#40;</span><span class="st0">&quot;akismet_rrd.php&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span></p>
<p><a href="http://www.php.net/define"><span class="kw3">define</span></a><span class="br0">&#40;</span><span class="st_h">&#039;AKISMET_GRAPH_DIR&#039;</span><span class="sy0">,</span> ABSPATH <span class="sy0">.</span> <span class="st_h">&#039;wp-content/plugins/&#039;</span> <span class="sy0">.</span> <a href="http://www.php.net/dirname"><span class="kw3">dirname</span></a><span class="br0">&#40;</span>plugin_basename<span class="br0">&#40;</span><span class="kw4">__FILE__</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="sy0">.</span> <span class="st_h">&#039;/&#039;</span><span class="br0">&#41;</span><span class="sy0">;</span></p>
<p>add_action<span class="br0">&#40;</span><span class="st_h">&#039;activity_box_end&#039;</span><span class="sy0">,</span> <span class="st_h">&#039;akismet_stats&#039;</span><span class="br0">&#41;</span><span class="sy0">;</span></p>
<p><span class="kw2">function</span> wp_akstat_add_pages<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><a href="http://www.php.net/function_exists"><span class="kw3">function_exists</span></a><span class="br0">&#40;</span><span class="st_h">&#039;add_submenu_page&#039;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; add_submenu_page<span class="br0">&#40;</span><span class="st_h">&#039;index.php&#039;</span><span class="sy0">,</span> <span class="st_h">&#039;Akismet Graphs&#039;</span><span class="sy0">,</span> <span class="st_h">&#039;Akismet Graphs&#039;</span><span class="sy0">,</span> 1<span class="sy0">,</span> <span class="kw4">__FILE__</span><span class="sy0">,</span> displayit<span class="br0">&#41;</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
add_action<span class="br0">&#40;</span><span class="st_h">&#039;admin_menu&#039;</span><span class="sy0">,</span> <span class="st_h">&#039;wp_akstat_add_pages&#039;</span><span class="br0">&#41;</span><span class="sy0">;</span></p>
<p><span class="kw2">function</span> displayit<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
akismet_update_rrd<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></p>
<p><span class="re0">$opts</span> <span class="sy0">=</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span> <span class="st0">&quot;&#8211;start&quot;</span><span class="sy0">,</span> <span class="st0">&quot;-1d&quot;</span><span class="sy0">,</span> <span class="st0">&quot;&#8211;title=Hourly Spam Graph&quot;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;DEF:inspams=&quot;</span> <span class="sy0">.</span> AKISMET_RRD_FILE <span class="sy0">.</span><span class="st0">&quot;:input:AVERAGE&quot;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;CDEF:hr=inspams,720,*&quot;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;LINE2:hr#00FF00:Spams/Hour&quot;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;COMMENT:<span class="es1">\\</span>n&quot;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;GPRINT:hr:AVERAGE:Avg Spams/Hour\: %6.2lf&quot;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;COMMENT: &nbsp;&quot;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;GPRINT:hr:MAX:Max Spams/Hour\: %6.2lf<span class="es1">\\</span>r&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="br0">&#41;</span><span class="sy0">;</span></p>
<p>rrd_graph<span class="br0">&#40;</span>AKISMET_GRAPH_DIR <span class="sy0">.</span> <span class="st0">&quot;akismet_1d.gif&quot;</span><span class="sy0">,</span> <span class="re0">$opts</span><span class="sy0">,</span> <a href="http://www.php.net/count"><span class="kw3">count</span></a><span class="br0">&#40;</span><span class="re0">$opts</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></p>
<p><span class="re0">$opts</span> <span class="sy0">=</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span> <span class="st0">&quot;&#8211;start&quot;</span><span class="sy0">,</span> <span class="st0">&quot;-1m&quot;</span><span class="sy0">,</span> <span class="st0">&quot;&#8211;title=Daily Spam Graph&quot;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;DEF:inspams=&quot;</span> <span class="sy0">.</span> AKISMET_RRD_FILE <span class="sy0">.</span><span class="st0">&quot;:input:AVERAGE&quot;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;CDEF:dy=inspams,8640,*&quot;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;LINE2:dy#00FF00:Spams/Day&quot;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;COMMENT:<span class="es1">\\</span>n&quot;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;GPRINT:dy:AVERAGE:Avg Spams/Day\: %6.2lf&quot;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;COMMENT: &nbsp;&quot;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;GPRINT:dy:MAX:Max Spams/Day\: %6.2lf<span class="es1">\\</span>r&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="br0">&#41;</span><span class="sy0">;</span></p>
<p>rrd_graph<span class="br0">&#40;</span>AKISMET_GRAPH_DIR <span class="sy0">.</span> <span class="st0">&quot;akismet_1m.gif&quot;</span><span class="sy0">,</span> <span class="re0">$opts</span><span class="sy0">,</span> <a href="http://www.php.net/count"><span class="kw3">count</span></a><span class="br0">&#40;</span><span class="re0">$opts</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></p>
<p><span class="re0">$opts</span> <span class="sy0">=</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span> <span class="st0">&quot;&#8211;start&quot;</span><span class="sy0">,</span> <span class="st0">&quot;-1y&quot;</span><span class="sy0">,</span> <span class="st0">&quot;&#8211;title=Monthly Spam Graph&quot;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;DEF:inspams=&quot;</span> <span class="sy0">.</span> AKISMET_RRD_FILE <span class="sy0">.</span><span class="st0">&quot;:input:AVERAGE&quot;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;CDEF:dy=inspams,8640,*&quot;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;LINE2:dy#00FF00:Spams/Day&quot;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;COMMENT:<span class="es1">\\</span>n&quot;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;GPRINT:dy:AVERAGE:Avg Spams/Day\: %6.2lf&quot;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;COMMENT: &nbsp;&quot;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;GPRINT:dy:MAX:Max Spams/Day\: %6.2lf<span class="es1">\\</span>r&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="br0">&#41;</span><span class="sy0">;</span></p>
<p>rrd_graph<span class="br0">&#40;</span>AKISMET_GRAPH_DIR <span class="sy0">.</span> <span class="st0">&quot;akismet_1y.gif&quot;</span><span class="sy0">,</span> <span class="re0">$opts</span><span class="sy0">,</span> <a href="http://www.php.net/count"><span class="kw3">count</span></a><span class="br0">&#40;</span><span class="re0">$opts</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></p>
<p><span class="re0">$img_loc</span> <span class="sy0">=</span> <span class="st0">&quot;/wp-content/plugins/&quot;</span> <span class="sy0">.</span> <a href="http://www.php.net/dirname"><span class="kw3">dirname</span></a><span class="br0">&#40;</span>plugin_basename<span class="br0">&#40;</span><span class="kw4">__FILE__</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="sy0">.</span> <span class="st0">&quot;/&quot;</span><span class="sy0">;</span><br />
<span class="sy1">?&gt;</span></p>
<p>&lt;div style=&quot;text-align:center; padding: 5px;&quot;&gt;<br />
&lt;img src=&quot;<span class="kw2">&lt;?php</span> <span class="kw1">echo</span> <span class="re0">$img_loc</span> <span class="sy1">?&gt;</span>akismet_1d.gif&quot;/&gt; &lt;br/&gt;<br />
&lt;img src=&quot;<span class="kw2">&lt;?php</span> <span class="kw1">echo</span> <span class="re0">$img_loc</span> <span class="sy1">?&gt;</span>akismet_1m.gif&quot;/&gt; &lt;br/&gt;<br />
&lt;img src=&quot;<span class="kw2">&lt;?php</span> <span class="kw1">echo</span> <span class="re0">$img_loc</span> <span class="sy1">?&gt;</span>akismet_1y.gif&quot;/&gt; &lt;br/&gt;<br />
&lt;/div&gt;</p>
<p><span class="kw2">&lt;?php</span><br />
<span class="br0">&#125;</span><br />
<span class="sy1">?&gt;</span></div>
</div>
<p>The final step is to make some changes to akismet.php to add the update functionality.</p>
<p>Put this at the top:</p>
<p>include_once (&#034;akismet_rrd.php&#034;);<br />
include(&#039;akismet_graph.php&#039;);</p>
<p>Every place you find &#034;DELETE FROM&#034; add the following before it:</p>
<p>akismet_update_rrd();</p>
<p>And finally here is what you will end up with after a few days:</p>
<p><img src="/examples/akismet-graph/akismet_1d.gif"/> <br/><br />
<img src="/examples/akismet-graph/akismet_1m.gif"/> <br/><br />
<img src="/examples/akismet-graph/akismet_1y.gif"/> <br/></p>
<p>One downside to the way this setup works is that you can miss some data if you delete quicker than the step time. I figured that was ok since the graphs are averages, the step is only 5 minutes and most people probably don&#039;t purge their spam that quickly.</p>
<p>Tags: <a href="http://technorati.com/tag/php" rel="tag">php</a>, <a href="http://technorati.com/tag/akismet" rel="tag"> akismet</a>, <a href="http://technorati.com/tag/rrd" rel="tag"> rrd</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.ioncannon.net/php/113/akismet-spam-graphs-with-php-rrd/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic page generated in 1.148 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2012-02-07 21:13:16 -->

