<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Shepherding Computers</title>
    <link rel="alternate" type="text/html" href="http://blog.lib.umn.edu/kerzn002/blog/" />
    <link rel="self" type="application/atom+xml" href="http://blog.lib.umn.edu/kerzn002/blog/atom.xml" />
    <id>tag:blog.lib.umn.edu,2009-09-10:/kerzn002/blog//10841</id>
    <updated>2012-10-18T22:39:01Z</updated>
    <subtitle>They&apos;re EVERYWHERE!</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type Enterprise 4.31-en</generator>

<entry>
    <title>Syntax Highlighting</title>
    <link rel="alternate" type="text/html" href="http://blog.lib.umn.edu/kerzn002/blog/2012/10/syntax-highlighting.html" />
    <id>tag:blog.lib.umn.edu,2012:/kerzn002/blog//10841.372085</id>

    <published>2012-10-18T21:03:43Z</published>
    <updated>2012-10-18T22:39:01Z</updated>

    <summary> #!/usr/bin/perl use warnings; use strict; print &quot;Hello World\n&quot;; SyntaxHighlighter.all()...</summary>
    <author>
        <name>Jeff Kerzner</name>
        
    </author>
    
    
    <content type="html" xml:lang="en-us" xml:base="http://blog.lib.umn.edu/kerzn002/blog/">
        <![CDATA[<pre class="brush: perl">
#!/usr/bin/perl
use warnings;
use strict;

print "Hello World\n";
</pre>

<script type="text/javascript">
     SyntaxHighlighter.all()
</script>]]>
        
    </content>
</entry>

<entry>
    <title>Capistrano and svn prompts</title>
    <link rel="alternate" type="text/html" href="http://blog.lib.umn.edu/kerzn002/blog/2011/07/capistrano-and-svn-prompts-1.html" />
    <id>tag:blog.lib.umn.edu,2011:/kerzn002/blog//10841.300395</id>

    <published>2011-07-29T16:16:20Z</published>
    <updated>2011-07-29T16:31:10Z</updated>

    <summary>I&apos;ve been configuring rails 2 apps for automation with Capistrano 2.6 lately and I encountered a pretty irritating bug with svn.  When you run the deploy:update command, Capistrano prompts you for your svn password and your machine password - like it should - and then it hangs forever on the actual deploy step.</summary>
    <author>
        <name>Jeff Kerzner</name>
        
    </author>
    
        <category term="Work" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="computers" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="capistrano" label="Capistrano" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="rails" label="rails" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="software" label="software" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="svn" label="svn" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-us" xml:base="http://blog.lib.umn.edu/kerzn002/blog/">
        <![CDATA[I've been configuring rails 2 apps for automation with Capistrano 2.6 lately and I encountered a pretty irritating bug with svn.  When you run the deploy:update command, Capistrano prompts you for your svn password and your machine password - like it should - and then it hangs forever on the actual deploy step.

The problem occurs only when svn continually asks if you want to save your password with one of these dialogs:

<pre>
-----------------------------------------------------------------------
ATTENTION!  Your password for authentication realm:
   <https://svn.example.com:443> Subversion Repository
can only be stored to disk unencrypted!  
...
-----------------------------------------------------------------------
</pre>

Solution: make svn stop asking you if you want to save your password.  To do this, modify your ~/.subversion/config so that it has (at least) this section:
<pre>
[auth]
store-passwords = no
store-auth-creds = no
</pre>

If you're interested, read more to view the error messages from Capistrano.]]>
        <![CDATA[Here's a ascii screenshot of what svn was doing with capistrano:

<pre>
kerzn002@ike:/web/railsapps/FAKE/config/deploy$ cap demo deploy
  * executing `demo'
    triggering start callbacks for `deploy'
  * executing `multistage:ensure'
  * executing `deploy'
  * executing `deploy:update'
 ** transaction: start
  * executing `deploy:update_code'
    executing locally: "svn info https://svn.example.com/repos/example/webapp/trunk  -rHEAD"
Authentication realm: <https://svn.example.com:443> Subversion Repository
Password for 'kerzn002':

-----------------------------------------------------------------------
ATTENTION!  Your password for authentication realm:

   <https://svn.example.com:443> Subversion Repository

can only be stored to disk unencrypted!  You are advised to configure
your system so that Subversion can store passwords encrypted, if
possible.  See the documentation for details.   

You can avoid future appearances of this warning by setting the value
of the 'store-plaintext-passwords' option to either 'yes' or 'no' in
'/home/kerzn002/.subversion/servers'.
-----------------------------------------------------------------------
Store password unencrypted (yes/no)? no
    command finished in 5237ms
  * executing "svn checkout -q  -r38770 https://svn.example.com/repos/example/webapp/trunk /web/railsapps/rails/istads/releases/20110629035332 && (echo 38770 > /web/railsapps/rails/istads/releases/20110629035332/REV
ISION)"
    servers: ["myhost.example.com"]
Password:
    [myhost.example.com] executing command
 ** [myhost.example.com :: out] Authentication realm: <https://svn.example.com:443> Subversion Repository
 ** Password for 'kerzn002':
 ** [myhost.example.com :: out]
 ** [myhost.example.com :: out] Authentication realm: <https://svn.example.com:443> Subversion Repository
 ** Username:
</pre>

Here's the part where I interrupt the deployment since it's hanging forever 

<pre>
^C
*** [deploy:update_code] rolling back
  * executing "rm -rf /web/railsapps/rails/istads/releases/20110629035332; true"
    servers: ["myhost.example.com"]
    [myhost.example.com] executing command
    command finished in 48ms
</pre>]]>
    </content>
</entry>

<entry>
    <title>Uploading Files with Drupal 6</title>
    <link rel="alternate" type="text/html" href="http://blog.lib.umn.edu/kerzn002/blog/2011/01/uploading-files-with-drupal-6.html" />
    <id>tag:blog.lib.umn.edu,2011:/kerzn002/blog//10841.265843</id>

    <published>2011-01-04T22:47:54Z</published>
    <updated>2011-01-05T18:25:53Z</updated>

    <summary>Here&apos;s a relatively painless example for file uploads in Drupal 6. This code is in a module file called usertab.module: #create the form function usertab_admin($form_state) { #prepare the file upload form $form = array(&apos;#attributes&apos; =&gt; array(&apos;enctype&apos; =&gt; &apos;multipart/form-data&apos;)); #file selector...</summary>
    <author>
        <name>Jeff Kerzner</name>
        
    </author>
    
    <category term="drupal" label="drupal" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="php" label="php" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="software" label="software" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-us" xml:base="http://blog.lib.umn.edu/kerzn002/blog/">
        <![CDATA[<p>Here's a relatively painless example for file uploads in Drupal 6.</p>

<p>This code is in a module file called usertab.module:</p>

<pre>
#create the form
function usertab_admin($form_state) {
    
  #prepare the file upload form
  $form = array('#attributes' => array('enctype' => 'multipart/form-data'));

  #file selector element
  $form['csv'] = array(
      '#type' => 'file',
      '#title' => 'Upload users',
      '#description' => t('Pick a csv file to upload')
  );

  #submit button
  $form['submit'] = array('#type' => 'submit', '#value' => 'Upload');
   return $form;
}

#handle the form submission
function usertab_admin_submit($form, &$form_state) {

  #this leads us to sites/mysite.example.com/files/
  $dir = file_directory_path();
 
  # unlike form submissions, multipart form submissions are not in 
  # $form_state, but rather in $FILES, which requires more checking
  if(isset($_FILES) && !empty($_FILES) && $_FILES['files']['size']['csv'] != 0)){
    
    #this structure is kind of wacky
    $name = $_FILES['files']['name']['csv'];
    $size = $_FILES['files']['size']['csv'];
    $type = $_FILES['files']['type']['csv'];

    #this is the actual place where we store the file
    $file = file_save_upload('csv', array() , $dir);
    if($file){
      drupal_set_message("You uploaded $name!");
    }
    else{
        drupal_set_message("Something went wrong saving your file.");
    }
  }
  else {
    drupal_set_message("Your file doesn't appear to be here.");
  }
}
</pre>

Here are some of the strange things going on here:

<p>First, the structure of the $_FILES array in php is kind of strange.  There's a good diagram of it here: <a href="http://www.php.net/manual/en/features.file-upload.post-method.php#91479">http://www.php.net/manual/en/features.file-upload.post-method.php#91479</a>.  Notice that it's the <u>second</u> one in the example.</p>

<p>Next, Drupal's (6) file_save_upload() method.  The API documentation is here: <a href="http://api.drupal.org/api/drupal/includes--file.inc/function/file_save_upload/6">http://api.drupal.org/api/drupal/includes--file.inc/function/file_save_upload/6</a>, but the parameters can be kind of confusing so here are some details:
<ol>
	<li>$source is the name of the file in the $_FILES array (also the name of the file field on form.</li>
	<li>$validators are outside the scope of this example.</li>
	<li>$dest is relative to the drupal root directory.</li>
	<li>$replace is actually self-explanatory </li>
</ol>
</p>

<p>P.S.  At some point, I will figure out how to get some syntax highlighting going here.</p>]]>
        
    </content>
</entry>

<entry>
    <title>Debian/Shorewall routing issues</title>
    <link rel="alternate" type="text/html" href="http://blog.lib.umn.edu/kerzn002/blog/2010/12/debianshorewall-routing-issues.html" />
    <id>tag:blog.lib.umn.edu,2010:/kerzn002/blog//10841.262677</id>

    <published>2010-12-04T08:05:40Z</published>
    <updated>2010-12-04T08:21:54Z</updated>

    <summary>I&apos;ve recently deployed a new router running Debian Squeeze and Shorewall. The problem started like this: I have my network configured with five vlans for different areas (servers, workstations, sandboxing, guests, and DMZ) and a /28 subnet assigned for each...</summary>
    <author>
        <name>Jeff Kerzner</name>
        
    </author>
    
        <category term="computers" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="linux" label="linux" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="networks" label="networks" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="software" label="software" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-us" xml:base="http://blog.lib.umn.edu/kerzn002/blog/">
        <![CDATA[<p>I've recently deployed a new router running Debian Squeeze and Shorewall.  The problem started like this:</p>

<p>I have my network configured with five vlans for different areas (servers, workstations, sandboxing, guests, and DMZ) and a /28 subnet assigned for each zone all the fancy network math done.  </p>

<p>Everything worked fine until I had to get machines to talk to the outside world.</p>

<p>Shorewall has configurations for 5 zones (corresponding neatly to the vlans) and a few filtering rules for each one.  One is behind NAT and the others all have public addresses for which shorewall handles proxyarp.</p>

<p>With and without shorewall running, the router could ping machines both inside and outside the perimeter.  In both cases, machines on the inside of the perimeter couldn't ping machines on the outside, but could ping each other.</p>

<p>Something, clearly, was wrong.</p>

<p>I'm pretty sure I spent at least 6 hours trying everything from verifying the upstream switch configuration to checking sysctl variables (mental note: make sure to enable the .forwarding keys!) to checking arp caches everywhere to even swapping out cables and hardware.</p>

<p>As it turns out, the problem was with shorewall.  Since shorewall ultimately ends up making a lot of the routing decisions, a badly configured value will ultimately foobar everything else you work so hard to configure.  Just remember that even though every other almost value in shorewall.conf is {Yes|No}, IP_FORWARDING takes {On|Off|Keep}.</p>

<p>This was a most extreme case of not RTFMing closely enough.</p>]]>
        
    </content>
</entry>

<entry>
    <title>Passenger on Solaris</title>
    <link rel="alternate" type="text/html" href="http://blog.lib.umn.edu/kerzn002/blog/2010/11/passenger-on-solaris.html" />
    <id>tag:blog.lib.umn.edu,2010:/kerzn002/blog//10841.261885</id>

    <published>2010-11-30T00:15:21Z</published>
    <updated>2010-11-30T00:22:12Z</updated>

    <summary>So today I set about installing passenger on a Solaris 10 machine. This turned out to be way harder than it seemed. I went down the &quot;install via gem&quot; road, so it wasn&apos;t too painful to being with. When I...</summary>
    <author>
        <name>Jeff Kerzner</name>
        
    </author>
    
        <category term="Work" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="computers" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="apache" label="Apache" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="software" label="software" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="solaris" label="Solaris" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-us" xml:base="http://blog.lib.umn.edu/kerzn002/blog/">
        <![CDATA[<p>So today I set about installing passenger on a Solaris 10 machine.  This turned out to be way harder than it seemed.</p>

<p>I went down the "install via gem" road, so it wasn't too painful to being with.  When I reached the phase of actually installing passenger to apache, I discovered that the configuration tool is a bit confused by Solaris, especially the apache APU component.</p>

<p>Here's the problem:<br />
<code><br />
 * GNU C++ compiler... found at /opt/csw/gcc4/bin/g++<br />
 * Ruby development headers... found<br />
 * OpenSSL support for Ruby... found<br />
 * RubyGems... found<br />
 * Rake... found at /opt/csw/bin/rake<br />
 * rack... found<br />
 * Apache 2... found at /opt/csw/apache/bin/httpd<br />
 * Apache 2 development headers... found at /opt/csw/apache/bin/apxs<br />
 * Apache Portable Runtime (APR) development headers... not found<br />
 * Apache Portable Runtime Utility (APU) development headers... not found<br />
</code></p>

<p>No big deal - we'll just pass it some options, right?  Wrong.  The CLI only accepts arguments for apxs2 and apr, but not apu.</p>

<p>Running with --apr-config-path /opt/csw/apache2/bin gets us slightly further:</p>

<p><code><br />
 * GNU C++ compiler... found at /opt/csw/gcc4/bin/g++<br />
 * Ruby development headers... found<br />
 * OpenSSL support for Ruby... found<br />
 * RubyGems... found<br />
 * Rake... found at /opt/csw/bin/rake<br />
 * rack... found<br />
 * Apache 2... found at /opt/csw/apache/bin/httpd<br />
 * Apache 2 development headers... found at /opt/csw/apache/bin/apxs<br />
 * Apache Portable Runtime (APR) development headers... found at /opt/csw/apache2/bin/<br />
 * Apache Portable Runtime Utility (APU) development headers... not found<br />
</code></p>

<p>Finally the APU.  This is a bit tricky to track down.</p>

<p>This was my process:</p>

<p>passenger-install-apache2-module secretly runs this file:</p>

<p>/opt/csw/lib/ruby/gems/1.8/gems/passenger-2.2.9/bin/passenger-install-apache2-module</p>

<p>Right away we see the following lines:<br />
<code><br />
37  require 'phusion_passenger/dependencies'<br />
52  Dependencies::Apache2,<br />
53  Dependencies::Apache2_DevHeaders<br />
</code><br />
So we follow them:</p>

<p>lib/phusion_passenger/dependencies.rb reveals that it secrely calls PlatformInfo to look for the APU:<br />
<code><br />
304 if PlatformInfo.apu_config.nil?<br />
</code><br />
So we jump into lib/phusion_passenger/platform_info.rb and discover (with some casual grepping):<br />
<code><br />
284         if env_defined?('APU_CONFIG')<br />
285             return ENV['APU_CONFIG']<br />
</code><br />
This means that if we do the following, we can convince the installer that we do, in fact, have the necessary files:<br />
<code><br />
setenv APU_CONFIG /opt/csw/apache2/bin/apu-1-config<br />
passenger-install-apache2-module --apr-config-path /opt/csw/apache2/bin/<br />
</code><br />
Hopefully this will make your life easier.<br />
</p>]]>
        
    </content>
</entry>

<entry>
    <title>Drupal GCal Events module and time zones</title>
    <link rel="alternate" type="text/html" href="http://blog.lib.umn.edu/kerzn002/blog/2010/11/drupal-gcal-events-module-and-time-zones.html" />
    <id>tag:blog.lib.umn.edu,2010:/kerzn002/blog//10841.257953</id>

    <published>2010-11-01T21:14:16Z</published>
    <updated>2010-11-01T21:34:27Z</updated>

    <summary>If you&apos;ve been using the GCal Events module, you might have noticed a problem where the timezone causes event times to be displayed incorrectly. In my situation, the time is correct in Drupal, but incorrect in the corresponding GCal link....</summary>
    <author>
        <name>Jeff Kerzner</name>
        
    </author>
    
        <category term="Work" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="computers" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="calendar" label="calendar" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="drupal" label="drupal" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="googleapps" label="Google Apps" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="software" label="software" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="timezones" label="time zones" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-us" xml:base="http://blog.lib.umn.edu/kerzn002/blog/">
        <![CDATA[<p>If you've been using the GCal Events module, you might have noticed a problem where the timezone causes event times to be displayed incorrectly.</p>

<p>In my situation, the time is correct in Drupal, but incorrect in the corresponding GCal link.  To force the calendar to interpret the timezone correctly, you can pass the current timezone argument as a GET parameter with the link.</p>

<p>In your GCal Events block,  configure the Event Template like this:</p>

<pre>
<code>
&lt;P&gt;&lt;A HREF="#URL#&ctz=America/Chicago"&gt;#TITLE#&lt;/A&gt;&lt;br&gt;#LOC##DATE##TIME#
</code>
</pre>

<p>This should force GCal to interpret the times as specific to Central Time.  </p>

<p>See the <a href="http://code.google.com/apis/calendar/data/2.0/reference.html#Calendar_feeds">Google API Atom Reference</a> for more information about the ctz option.  An example of the link in practice is visible on the Minnesota Population Center (shameless department promotion!) website (http://www.pop.umn.edu) on the right-hand events sidebar.</p>]]>
        
    </content>
</entry>

<entry>
    <title>Monitors and displays</title>
    <link rel="alternate" type="text/html" href="http://blog.lib.umn.edu/kerzn002/blog/2010/09/monitors-and-displays.html" />
    <id>tag:blog.lib.umn.edu,2010:/kerzn002/blog//10841.247570</id>

    <published>2010-09-11T04:59:43Z</published>
    <updated>2010-09-11T05:05:29Z</updated>

    <summary>If anyone has an elegant solution to extending gnome panels over multiple monitors, please let me know! I other news, if you have two monitors and stack them with the panel on the top of the bottommost monitor, you&apos;ll discover...</summary>
    <author>
        <name>Jeff Kerzner</name>
        
    </author>
    
        <category term="Amusement" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="gnome" label="gnome" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="monitors" label="monitors" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-us" xml:base="http://blog.lib.umn.edu/kerzn002/blog/">
        <![CDATA[<p>If anyone has an <em>elegant</em> solution to extending gnome panels over multiple monitors, please let me know!</p>

<p>I other news, if you have two monitors and stack them with the panel on the top of the bottommost monitor, you'll discover how gnome handles hiding panels.  Set the panel to auto-hide and it'll just slide up to the bottom of the top monitor!  That's not <em>hiding</em> my panel anymore, that's just making it really hard to control the screen layout.  </p>

<p>More and more I find myself just using a whole pile of screen sessions and putting jobs in the background...this makes for quite a mess when I need to reboot.</p>

<p>Also, if you have one of those convenient USB hubs on your monitor, make sure that you know which one your keyboard and mouse are plugged into before you go shutting off monitors!</p>]]>
        
    </content>
</entry>

<entry>
    <title>Drupal and Shibboleth</title>
    <link rel="alternate" type="text/html" href="http://blog.lib.umn.edu/kerzn002/blog/2010/09/drupal-and-shibboleth.html" />
    <id>tag:blog.lib.umn.edu,2010:/kerzn002/blog//10841.246933</id>

    <published>2010-09-04T00:10:45Z</published>
    <updated>2010-09-04T02:40:36Z</updated>

    <summary>With the imminent switch to Shibboleth, I&apos;ve decided to try out hooking up a Drupal instance...to...Shibboleth. Exactly as the title implies. I&apos;m using Ubuntu Server 10.04 for my server and rather then authentication against a real IdP, I&apos;m using the...</summary>
    <author>
        <name>Jeff Kerzner</name>
        
    </author>
    
        <category term="computers" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="drupal" label="drupal" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="shibboleth" label="Shibboleth" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="software" label="software" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="webprogramming" label="web programming" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-us" xml:base="http://blog.lib.umn.edu/kerzn002/blog/">
        <![CDATA[<p>With the imminent switch to Shibboleth, I've decided to try out hooking up a Drupal instance...to...Shibboleth.  Exactly as the title implies.</p>

<p>I'm using Ubuntu Server 10.04 for my server and rather then authentication against a real IdP, I'm using the public <a href="www.testshib.org">TestShib Two</a> service as an IdP and configuring the SP myself.</p>

<p>Here's how I did it:</p>

<p>0) Register with OpenIdP and get a machine ready for testing.</p>

<p>1) Install the necessary packages:<br />
apache mpm-prefork<br />
php5<br />
libapache2-mod-shib2<br />
mysql (for drupal)!<br />
...and all their friends.</p>

<p>2) Get drupal and install that properly.  There are plenty of tutorials out there on how to do this.</p>

<p>3) Configure your apache server so that it looks something like this:<br />
<code><br />
<IfModule mod_ssl.c><br />
<VirtualHost *:443><br />
        ServerAdmin webmaster@localhost<br />
        ServerName x-128-101-79-21.pop.umn.edu<br />
        UseCanonicalName On</p>

<p>        DocumentRoot /var/www<br />
        <Directory /><br />
                Options FollowSymLinks<br />
                AllowOverride None<br />
        </Directory></p>

<p>        Alias /secure /var/www/drupal<br />
        <Directory /var/www/drupal><br />
                Options Indexes FollowSymLinks Multiviews</p>

<p>                Order allow,deny<br />
                Allow from all</p>

<p>                AuthType Shibboleth<br />
                ShibRequireSession On<br />
                require shibboleth<br />
        </Directory><br />
</code><br />
...and a whole bunch more as needed.  You can actually base it off the default-ssl site (...like I did.)</p>

<p>4.  Somewhere in your shibboleth2.xml (probably in /etc/shibboleth), you have something that looks like this:<br />
<code><br />
    <RequestMapper type="Native"><br />
        <RequestMap applicationId="default" requireSession="1"><br />
            <Host name="x-128-101-79-21.pop.umn.edu"><br />
                <Path name="secure" authType="shibboleth" requireSession="true"/><br />
            </Host><br />
        </RequestMap><br />
    </RequestMapper><br />
</code><br />
This is the really important part.  It's telling you exactly which paths on the server are going to be secured by </p>]]>
        
    </content>
</entry>

<entry>
    <title>Dynamic Layer 2 filtering (and a concert)</title>
    <link rel="alternate" type="text/html" href="http://blog.lib.umn.edu/kerzn002/blog/2010/04/dynamic-layer-2-filtering-and-a-concert.html" />
    <id>tag:blog.lib.umn.edu,2010:/kerzn002/blog//10841.227173</id>

    <published>2010-04-02T07:17:25Z</published>
    <updated>2010-08-21T03:00:37Z</updated>

    <summary>Last week I saw Celtic Woman in concert - they put on an excellent performance, though the audience around me left a lot to be desired. Onto more relevant topics. It turns out that building a MAC address + IP...</summary>
    <author>
        <name>Jeff Kerzner</name>
        
    </author>
    
    <category term="concert" label="concert" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="linux" label="linux" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="networks" label="networks" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="Perl" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-us" xml:base="http://blog.lib.umn.edu/kerzn002/blog/">
        <![CDATA[<p>Last week I saw Celtic Woman in concert - they put on an excellent performance, though the audience around me left a lot to be desired.</p>

<p>Onto more relevant topics.  It turns out that building a MAC address + IP address + authentication application is actually easier than it sounds.  The challenge is hovering near the network stack, specifically with the firewalls.</p>

<p>Here's the deal:</p>

<p>Ubuntu - Everyone's favorite Linux is several versions behind on both iptables and shorewall, not to mention that ipset isn't even in the kernel/package tree.  If you want to, you can hack at it and compile in support.</p>

<p>FreeBSD - While it has the benefit of pick-your favorite firewall (pf, ipfw, firewall, etc...) it lacks layer2 filtering in a pretty big way.  <a href="http://blogs.freebsdish.org/gleb/">Gleb Kurtsou</a> wrote a kernel patch as part of the Summer of Code '08 but sadly, <a href="http://www.freebsd.org/projects/summerofcode-2008.html">it's not ready yet</a> (and doesn't seem to work seamlessly with 8.0 Stable).</p>

<p>Debian - Well, according to the debian package repository it has ipset, iptables, and shorewall all at reasonably high version numbers.  I'm going down this road now and I'll let you know how it turns out when I'm finished.</p>

<p>The big challenge at this stage is figuring out how to track valid IPs leased to DHCP to permitted MAC addresses.  Simply adding the IPs to an allowed list doesn't work since someone could steal an active lease once the original client left the network (window between disconnect and lease return-to-pool).  A MAC-IP pair helps track who has the lease at a given time (good for auditing), but a database tracking MAC-IP pairs + username at captive portal/proxy login is the best.</p>

<p>Basically, not until a user logs in with a valid mac address and a valid username and gets logged can they access the network.  By default all IP addresses are in a blocked ACL and then moved over to a pass ACL when the login process is finished.  Storing these MAC-IP pass-OK ACLs is the challenge.  While we could statefully [keep-state] reload the firewall ruleset each time we wanted to add a new pass or remove an expired one, that seems pretty expensive.  Instead, I'm going to try using in-memory tables.</p>

<p>Maybe next week I'll post more about the entire system (written mostly in perl).</p>]]>
        
    </content>
</entry>

<entry>
    <title>vhosts with modperl</title>
    <link rel="alternate" type="text/html" href="http://blog.lib.umn.edu/kerzn002/blog/2010/03/vhosts-with-modperl.html" />
    <id>tag:blog.lib.umn.edu,2010:/kerzn002/blog//10841.224232</id>

    <published>2010-03-12T23:44:25Z</published>
    <updated>2010-03-13T00:09:13Z</updated>

    <summary>This post deals with configuring mod_perl environments with vhosts. Our objects for the post are to configure an Apache2 prefork server with mod_perl 2.0 with the following specifications: 1) Each vhost should have its own interpretter pool with its own...</summary>
    <author>
        <name>Jeff Kerzner</name>
        
    </author>
    
        <category term="computers" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="apache" label="Apache" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="modperl" label="modperl" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="Perl" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="software" label="software" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-us" xml:base="http://blog.lib.umn.edu/kerzn002/blog/">
        <![CDATA[<p>This post deals with configuring mod_perl environments with vhosts.  Our objects for the post are to configure an Apache2 prefork server with mod_perl 2.0 with the following specifications:</p>

<p>1) Each vhost should have its own interpretter pool with its own paths.<br />
2) vhosts do not need to use custom directives during startup.<br />
3) Custom liraries in each vhost should not be shared with the others.<br />
4) Users should be able to execute mod_perl scripts only from docs/bin.</p>

<p>Here's a snip from my apache2ctl status: &quot;Server Version: Apache/2.2.11 (Ubuntu) mod_apreq2-20051231/2.6.0 mod_perl/2.0.4 Perl/v5.10.0&quot;</p>

<p>Let's get started!</p>

<p>I have three vhosts {a, b, c} each listening on ports 5050, 8080, and 9090 respectively.</p>

<p>Here's my initial /etc/apache2/sites-available/vhosts.conf file:<br />
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><br />
&lt;VirtualHost *:5050&gt;<br />
    DocumentRoot /var/www/a<br />
    #PerlPostConfigHandler MyApache2::Test-&gt;post_config<br />
&lt;/VirtualHost&gt;</p>

<p>&lt;VirtualHost *:8080&gt;<br />
    DocumentRoot /var/www/b<br />
    #PerlPostConfigHandler MyApache2::Test-&gt;post_config<br />
&lt;/VirtualHost&gt;</p>

<p>&lt;VirtualHost *:9090&gt;<br />
    DocumentRoot /var/www/c<br />
    #PerlPostConfigHandler MyApache2::Test-&gt;post_config<br />
&lt;/VirtualHost&gt;<br />
</pre><br />
Here's my initial /etc/apache2/httpd.conf file:</p>

<p>ServerName localhost<br />
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><br />
PerlSwitches -I/var/myperl/dep_lib<br />
PerlPostConfigHandler MyApache2::Test-&gt;post_config<br />
</pre></p>

<p>/var/myperl/dep_lib/MyApache2::Test.pm looks like this:<br />
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><br />
package MyApache2::Test;<br />
use Apache2::ServerRec;<br />
use Apache2::Const -compile =&gt; OK<br />
use strict;<br />
use warnings;</p>

<p>sub post_config {<br />
  my ($self, $conf_pool, $log_pool, $temp_pool, $s) = @_;<br />
  warn &quot;HELLO &quot; . $s-&gt;port . &quot;\n&quot;;<br />
}</p>

<p>1;<br />
</pre></p>

<p>When we start the server, this is the output we get:</p>

<p>root@larx:~# tail -fn 0 /var/log/apache2/error.log<br />
HELLO 0<br />
HELLO 0<br />
[Tue Mar 09 19:09:00 2010] [notice] Apache/2.2.11 (Ubuntu) mod_apreq2-20051231/2.6.0 mod_perl/2.0.4 Perl/v5.10.0 configured -- resuming normal operations<br />
[Tue Mar 09 19:09:00 2010] [info] Server built: Nov 13 2009 21:59:28<br />
[Tue Mar 09 19:09:00 2010] [debug] prefork.c(1032): AcceptMutex: sysvsem (default: sysvsem)</p>

<p>This shows that the global configuration (*:0) is saying hello when it calls the PostConfigHandler.  After the first call to PerlPostConfigHandler, Apache restarts itself to test its graceful restart ability. [1]</p>

<p>Now what happens when we try to implement a PostConfigHandler in a VirtualHost?  According to the documentation, since PerlPostConfigHandler is valid in the SRV scope, we should be able to do this:</p>

<p>/etc/apache2/httpd.conf:<br />
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><br />
ServerName localhost<br />
PerlSwitches -I/var/myperl/dep_lib<br />
#PerlPostConfigHandler MyApache2::Test-&gt;post_config<br />
</pre></p>

<p>/etc/apache2/site-available/vhosts.conf:<br />
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><br />
&lt;VirtualHost *:5050&gt;<br />
        DocumentRoot /var/www/a<br />
        PerlSwitches -I/var/myperl/dep_lib<br />
        PerlPostConfigHandler MyApache2::Test-&gt;post_config<br />
&lt;/VirtualHost&gt;</p>

<p>&lt;VirtualHost *:8080&gt;<br />
        DocumentRoot /var/www/b<br />
&lt;/VirtualHost&gt;</p>

<p>&lt;VirtualHost *:9090&gt;<br />
        DocumentRoot /var/www/c<br />
&lt;/VirtualHost&gt;<br />
</pre><br />
and the startup:</p>

<p>root@larx:~# tail -fn 0 /var/log/apache2/error.log<br />
[Tue Mar 09 19:19:23 2010] [notice] Apache/2.2.11 (Ubuntu) mod_apreq2-20051231/2.6.0 mod_perl/2.0.4 Perl/v5.10.0 configured -- resuming normal operations<br />
[Tue Mar 09 19:19:23 2010] [info] Server built: Nov 13 2009 21:59:28<br />
[Tue Mar 09 19:19:23 2010] [debug] prefork.c(1032): AcceptMutex: sysvsem (default: sysvsem)</p>

<p>Notice that the PerlPostConfigHandler hasn't said anything.  This is actually by design, contrary to what the documentation might say.  In reality, PerlPostConfigHandler is only valid in the server-wide configuration context, NOT in vhosts.  There are two ways to get around this.</p>

<p>1) Patch your mod_perl installation using a patch (possibly outdated) available on the mod-perl mailing lists here [2].<br />
2) Use startup.pl files in a per-host configuration scheme.</p>

<p></p>

<p>Since I have less than no desire to go hacking around inside the monster, I've opted for choice 2.</p>

<p>To achieve this, we need to provide each vhost with a way to load some file at server startup.  In /var/www/(a&#124;b&#124;c) we place a file called startup.pl that looks remarkably like this:  (just make sure to s/a/(b&#124;c) when and where appropriate)</p>

<p>/var/www/a/startup.pl:<br />
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><br />
#!/usr/bin/perl</p>

<p>use lib qw( /var/www/a/lib /var/www/a/lib/dep_lib );</p>

<p>use Data::Dumper;</p>

<p>use warnings;<br />
use strict;</p>

<p>warn &quot;Dumping the A startup.pl:\n&quot;;<br />
print STDERR Dumper(\@INC);<br />
warn &quot;Finished processing A startup!\n&quot;;</p>

<p>1;<br />
</pre></p>

<p>Notice that &quot;1;&quot;.  That's pretty important since the script is effectively being require()'d by mod_perl and therefore must return true.</p>

<p>Next we need to configure the vhost:</p>

<p>/etc/apache2/sites-available/vhosts.conf:<br />
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><br />
&lt;VirtualHost *:5050&gt;<br />
        DocumentRoot /var/www/a<br />
        PerlPostConfigRequire /var/www/a/startup.pl<br />
&lt;/VirtualHost&gt;</p>

<p>&lt;VirtualHost *:8080&gt;<br />
        DocumentRoot /var/www/b<br />
&lt;/VirtualHost&gt;</p>

<p>&lt;VirtualHost *:9090&gt;<br />
        DocumentRoot /var/www/c<br />
&lt;/VirtualHost&gt;<br />
</pre><br />
This is the outcome from a startup run:</p>

<p>root@larx:~# tail -fn 0 /var/log/apache2/error.log<br />
[Thu Mar 11 16:54:12 2010] [info] removed PID file /var/run/apache2.pid (pid=4057)<br />
[Thu Mar 11 16:54:12 2010] [notice] caught SIGTERM, shutting down<br />
Dumping the A startup.pl:<br />
$VAR1 = [<br />
          '/var/www/a/lib',<br />
          '/var/www/a/lib/dep_lib',<br />
      '/var/myperl/dep_lib',<br />
          '/etc/perl',<br />
          '/usr/local/lib/perl/5.10.0',<br />
          '/usr/local/share/perl/5.10.0',<br />
          '/usr/lib/perl5',<br />
          '/usr/share/perl5',<br />
          '/usr/lib/perl/5.10',<br />
          '/usr/share/perl/5.10',<br />
          '/usr/local/lib/site_perl',<br />
          '.',<br />
          '/etc/apache2'<br />
        ];<br />
Finished processing A startup!<br />
Dumping the A startup.pl:<br />
$VAR1 = [<br />
          '/var/www/a/lib',<br />
          '/var/www/a/lib/dep_lib',<br />
          '/var/myperl/dep_lib',<br />
          '/etc/perl',<br />
          '/usr/local/lib/perl/5.10.0',<br />
          '/usr/local/share/perl/5.10.0',<br />
          '/usr/lib/perl5',<br />
          '/usr/share/perl5',<br />
          '/usr/lib/perl/5.10',<br />
          '/usr/share/perl/5.10',<br />
          '/usr/local/lib/site_perl',<br />
          '.',<br />
          '/etc/apache2'<br />
        ];<br />
Finished processing A startup!<br />
[Thu Mar 11 16:54:15 2010] [notice] Apache/2.2.11 (Ubuntu) mod_apreq2-20051231/2.6.0 mod_perl/2.0.4 Perl/v5.10.0 configured -- resuming normal operations<br />
[Thu Mar 11 16:54:15 2010] [info] Server built: Mar  9 2010 21:04:15<br />
[Thu Mar 11 16:54:15 2010] [debug] prefork.c(1032): AcceptMutex: sysvsem (default: sysvsem)</p>

<p><br />
Notice that we see the Dumper being called twice.  This is, again, because immediately after starting up for the first time Apache starts once, and then restarts to test its graceful restart ability. [1]  </p>

<p>Really interesting side note:  when you reload (aka &quot;graceful restart,&quot; &quot;-k graceful,&quot; SIGUSR1) the apache server will start new children with the new configuration settings.  On the other hand, restarting (aka &quot;restart now, &quot;-k restart&quot;, SIGHUP) stops all children, reloads the parent, and then loads all children with the new configuration.  This means that when you send &quot;reload&quot; you get one startup pass from modperl instead of two (since the server is already running it doesn't test it's ability to restart) whereas with restart, the server (for all intents and purposes) stops and starts again meaning that you see the output from modperl twice.  [3]</p>

<p>Now that we know what's going on with the modperl startup, let's finish our setup.  The remaining adjustments are fairly straightforward:</p>

<p>/etc/apache2/httpd.conf:<br />
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><br />
ServerName localhost<br />
PerlSwitches -I/var/myperl/dep_lib<br />
#This option allows us to say things like print &quot;Content-Type: text/plain\n\n&quot;<br />
PerlOptions +ParseHeaders<br />
#We still might want to do something server-wide<br />
PerlPostConfigHandler MyApache2::Test-&gt;post_config<br />
</pre></p>

<p>/etc/apache2/sites-available/vhosts.conf:<br />
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><br />
#I've actually ignored one of the criteria I set earlier (because I can, and partially to show a point):<br />
#vhost a allows scripts to run under modperl from docs/bin even though the documentroot is under ExecCGI.<br />
#The PerlOptions +Parent gives vhost a it's own perl interpreter pool complete with its own @INC.<br />
&lt;VirtualHost *:5050&gt;<br />
        DocumentRoot /var/www/a/docs<br />
        Options ExecCGI +Includes FollowSymLinks +MultiViews Indexes<br />
        DirectoryIndex index.html</p>

<p>        PerlPostConfigRequire /var/www/a/startup.pl<br />
        PerlOptions +Parent</p>

<p>        &lt;Directory /var/www/a&gt;<br />
                AllowOverride All<br />
        &lt;/Directory&gt;</p>

<p>        &lt;Directory /var/www/a/docs/bin&gt;<br />
                SetHandler perl-script<br />
                PerlResponseHandler ModPerl::Registry<br />
        &lt;/Directory&gt;<br />
&lt;/VirtualHost&gt;</p>

<p>#vhost b is configred identically to vhost a.<br />
&lt;VirtualHost *:8080&gt;<br />
        DocumentRoot /var/www/b/docs<br />
        Options ExecCGI +Includes FollowSymLinks +MultiViews Indexes<br />
        DirectoryIndex index.html</p>

<p>        PerlPostConfigRequire /var/www/b/startup.pl<br />
        PerlOptions +Parent</p>

<p>        &lt;Directory /var/www/b&gt;<br />
                AllowOverride All<br />
        &lt;/Directory&gt;</p>

<p>        &lt;Directory /var/www/b/docs/bin&gt;<br />
                SetHandler perl-script<br />
                PerlResponseHandler ModPerl::Registry<br />
        &lt;/Directory&gt;<br />
&lt;/VirtualHost&gt;</p>

<p>#vhost c is a little different.  This vhost allows scripts to be run under modperl from anywhere it its document root.<br />
&lt;VirtualHost *:9090&gt;<br />
        DocumentRoot /var/www/c/docs<br />
        Options ExecCGI +Includes FollowSymLinks +MultiViews Indexes<br />
        DirectoryIndex index.html</p>

<p>        PerlPostConfigRequire /var/www/c/startup.pl<br />
        PerlOptions +Parent<br />
    SetHandler perl-script<br />
        PerlResponseHandler ModPerl::Registry</p>

<p>        &lt;Directory /var/www/c&gt;<br />
                AllowOverride All<br />
        &lt;/Directory&gt;</p>

<p>&lt;/VirtualHost&gt;<br />
</pre></p>

<p>There are two things that should be explained:</p>

<p>PerlOptions +Parent <br />
...creates a separate interpreter pool for each of the vhosts.  These pools do not inherit any settings from other pools.</p>

<p>SetHandler perl-script <br />
...tells Apache to parse all files in that Directory (also valid for Locations) as perl-scripts.  (&quot;SetHandler modperl&quot; also works just as well here).  More on this in a week or two.</p>

<p>PerlResponseHandler ModPerl::Registry <br />
...tells modperl that everytime it needs to process something, use ModPerl::Registry to generate the response by compiling/parsing/executing your code when it needs to.</p>

<p>Finally, to prove that this actually works (in addition to having the error log), here's a script that you can actually run under modperl in each of the vhosts.  Notice the lack of a #! line and a 1;.  They're not necessary [in this particular instance]!</p>

<p>test.pl:<br />
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><br />
use Data::Dumper;</p>

<p>print &quot;Content-type: text/plain\n\n&quot;;<br />
for(sort keys %ENV) {<br />
        print &quot;$_ =&gt; $ENV{$_}\n&quot;;<br />
}</p>

<p>print Dumper(\@INC);<br />
</pre></p>

<p>Finally, my directory structure looks like this:</p>

<p>root@larx:/var/www# tree<br />
.<br />
&#124;-- a<br />
&#124;   &#124;-- docs<br />
&#124;   &#124;   &#124;-- bin<br />
&#124;   &#124;   &#124;   `-- test.pl<br />
&#124;   &#124;   `-- index.html<br />
&#124;   &#124;-- lib<br />
&#124;   &#124;   `-- dep_lib<br />
&#124;   `-- startup.pl<br />
&#124;-- b<br />
&#124;   &#124;-- docs<br />
&#124;   &#124;   &#124;-- bin<br />
&#124;   &#124;   &#124;   `-- test.pl<br />
&#124;   &#124;   `-- lib<br />
&#124;   &#124;       `-- dep_lib<br />
&#124;   &#124;-- lib<br />
&#124;   &#124;   `-- dep_lib<br />
&#124;   `-- startup.pl<br />
`-- c<br />
    &#124;-- docs<br />
    &#124;   &#124;-- bin<br />
    &#124;   &#124;   `-- test.pl<br />
    &#124;   &#124;-- lib<br />
    &#124;   &#124;   `-- dep_lib<br />
    &#124;   `-- test.pl<br />
    &#124;-- lib<br />
    &#124;   `-- dep_lib<br />
    `-- startup.pl</p>

<p>19 directories, 8 files</p>

<p>Try visiting http://localhost:8080/bin/test.pl and http://localhost:9090/test.pl .  Now you have mod_perl working with isolated vhosts!</p>

<p>Join me next week as I delve further into mod_perl.  Possible topics include authentication and authorization, ModPerl::Registry and/or ModPerl::PerlRun, custom environment variables, and further per-vhost configuration options.</p>

<p><br />
References: </p>

<p>[1] http://perl.apache.org/docs/2.0/user/handlers/server.html#Server_Life_Cycle</p>

<p>[2] http://www.gossamer-threads.com/lists/modperl/modperl/60796#60796</p>

<p>[3] http://httpd.apache.org/docs/2.2/en/stopping.html#graceful</p>]]>
        
    </content>
</entry>

<entry>
    <title>A mystery!</title>
    <link rel="alternate" type="text/html" href="http://blog.lib.umn.edu/kerzn002/blog/2010/02/a-mystery.html" />
    <id>tag:blog.lib.umn.edu,2010:/kerzn002/blog//10841.220246</id>

    <published>2010-02-20T11:06:08Z</published>
    <updated>2010-02-20T11:21:42Z</updated>

    <summary>So I have a machine called Walrus and it has some problems. I leave work around 7 pm and when I get back, sometimes the machine is on, sometimes it isn&apos;t. I shut down the machine (shutdown -h now) each...</summary>
    <author>
        <name>Jeff Kerzner</name>
        
    </author>
    
    <category term="ubuntu" label="Ubuntu" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-us" xml:base="http://blog.lib.umn.edu/kerzn002/blog/">
        <![CDATA[<p>So I have a machine called Walrus and it has some problems.  I leave work around 7 pm and when I get back, sometimes the machine is on, sometimes it isn't.  I shut down the machine (shutdown -h now) each night, so it's not sleeping.  Anyway, here are some logs.</p>

<p>kerzn002@walrus% last -daix<code><br />
kerzn002 tty7         Thu Feb 18 16:14   still logged in    0.0.0.0<br />
runlevel (to lvl 2)   Tue Feb 16 23:00 - 20:04 (1+21:04)    0.0.0.0<br />
reboot   system boot  Tue Feb 16 23:00 - 20:04 (1+21:04)    0.0.0.0<br />
runlevel (to lvl 0)   Tue Feb 16 21:08 - 23:00  (01:52)     0.0.0.0<br />
kerzn002 tty7         Tue Feb 16 16:12 - down   (04:55)     0.0.0.0<br />
runlevel (to lvl 2)   Sun Feb 14 23:03 - 21:08 (1+22:04)    0.0.0.0<br />
reboot   system boot  Sun Feb 14 23:03 - 21:08 (1+22:04)    0.0.0.0<br />
runlevel (to lvl 0)   Fri Feb 12 19:05 - 23:03 (2+03:58)    0.0.0.0<br />
kerzn002 tty7         Fri Feb 12 15:22 - down   (03:42)     0.0.0.0<br />
runlevel (to lvl 2)   Thu Feb 11 23:00 - 19:05  (20:04)     0.0.0.0<br />
reboot   system boot  Thu Feb 11 23:00 - 19:05  (20:04)     0.0.0.0<br />
runlevel (to lvl 0)   Thu Feb 11 19:08 - 23:00  (03:51)     0.0.0.0<br />
kerzn002 tty7         Thu Feb 11 16:04 - down   (03:04)     0.0.0.0<br />
</code></p>

<p>kerzn002@walrus% cat /var/log/kern.log<code><br />
Feb 14 23:03:34 walrus kernel: Loaded 52777 symbols from 39 modules.<br />
Feb 14 23:03:34 walrus kernel: [    0.000000] BIOS EBDA/lowmem at: 0009fc00/0009fc00<br />
Feb 14 23:03:34 walrus kernel: [    0.000000] Initializing cgroup subsys cpuset<br />
Feb 14 23:03:34 walrus kernel: [    0.000000] Initializing cgroup subsys cpu<br />
---<br />
Feb 16 21:08:05 walrus kernel: [166077.525990] [drm] Num pipes: 1<br />
Feb 16 21:08:05 walrus kernel: [166077.932482] mtrr: no MTRR for c0000000,10000000 found<br />
Feb 16 23:00:24 walrus kernel: Inspecting /boot/System.map-2.6.28-18-generic<br />
Feb 16 23:00:24 walrus kernel: Cannot find map file.<br />
Feb 16 23:00:24 walrus kernel: Loaded 52777 symbols from 39 modules.<br />
Feb 16 23:00:24 walrus kernel: [    0.000000] BIOS EBDA/lowmem at: 0009fc00/0009fc00<br />
Feb 16 23:00:24 walrus kernel: [    0.000000] Initializing cgroup subsys cpuset<br />
---<br />
Feb 16 23:00:37 walrus kernel: [   27.471617] tg3: eth0: Flow control is off for TX and off for RX.<br />
Feb 16 23:00:37 walrus kernel: [   27.471766] ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready<br />
Feb 16 23:00:49 walrus kernel: [   37.508025] eth0: no IPv6 routers present<br />
Feb 18 16:14:55 walrus kernel: [148484.128595] tun: Universal TUN/TAP device driver, 1.6<br />
</code><br />
Those huge numbers are me showing up to work (not every day) and those small numbers are the machine starting up.  I'm not sure how, or why, but I'll figure it out at some point...maybe.  Anyway, if anyone knows anything about Ubuntu (9.04) powering up at will (it's a Dell Optiplex something-or-other), you should comment on it...</p>]]>
        
    </content>
</entry>

<entry>
    <title>Another Concert</title>
    <link rel="alternate" type="text/html" href="http://blog.lib.umn.edu/kerzn002/blog/2010/02/another-concert.html" />
    <id>tag:blog.lib.umn.edu,2010:/kerzn002/blog//10841.218857</id>

    <published>2010-02-13T08:12:32Z</published>
    <updated>2010-02-13T08:14:25Z</updated>

    <summary>So I bought tickets to another concert. This time it&apos;s a lot closer and a lot larger: Celtic Woman at the Xcel Energy Center on March 24th (coincidentally, that&apos;s the same day as the Database Architecture midterm and the Theory...</summary>
    <author>
        <name>Jeff Kerzner</name>
        
    </author>
    
        <category term="Amusement" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="concert" label="concert" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-us" xml:base="http://blog.lib.umn.edu/kerzn002/blog/">
        <![CDATA[<p>So I bought tickets to another concert.  This time it's a lot closer and a lot larger: Celtic Woman at the Xcel Energy Center on March 24th (coincidentally, that's the same day as the Database Architecture midterm and the Theory and Methods in Religious Studies paper).  As always, I have two tickets.</p>]]>
        
    </content>
</entry>

<entry>
    <title>CGI::Application and POST forms</title>
    <link rel="alternate" type="text/html" href="http://blog.lib.umn.edu/kerzn002/blog/2010/01/cgiapplication-and-post-forms.html" />
    <id>tag:blog.lib.umn.edu,2010:/kerzn002/blog//10841.212078</id>

    <published>2010-01-07T01:12:03Z</published>
    <updated>2010-01-07T02:06:40Z</updated>

    <summary>So you&apos;re writing a webapp using CGI::Application, you add a form to the application and set its submission method to POST and all of a sudden you can&apos;t seem to get a runmode to handle it. Instead of mixing GET...</summary>
    <author>
        <name>Jeff Kerzner</name>
        
    </author>
    
        <category term="computers" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="cgi" label="CGI" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="cgiapplication" label="CGI::Application" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="Perl" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="webprogramming" label="web programming" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-us" xml:base="http://blog.lib.umn.edu/kerzn002/blog/">
        <![CDATA[<p>So you're writing a webapp using CGI::Application, you add a form to the application and set its submission method to POST and all of a sudden you can't seem to get a runmode to handle it.  Instead of mixing GET and POST parameters, here's a way to convince C::A to work with POST data.</p>

<p>I usually use CGI::Application::Plugin::TT and CGI::Application::Plugin::AutoRunmode in my applications.</p>

<p>Suppose your application has two screens: statistics and administration.</p>

<p>In the administration screen a user can add or remove other users.<br />
In the statistics screen a user can generate reports based on a type and some parameters.</p>

<p>Each of these screens corresponds to a run mode.  Here's the general logic behind the runmodes:</p>

<p>Enter the mode and create useful objects (esp. $self = shift;)<br />
Test to see if the form has been submitted.<br />
If it has, process the associated information and return something useful.<br />
If it hasn't, return the information to display.<br />
Return</p>

<p>Both methods use POST for form submission, but can be accessed by GET URL parameters by default.</p>

<p>When your clients visit the website http://example.com/cgi-bin/myapp?rm=stats they get sent to the statistics page and visiting http://example.com/cgi-bin/myapp?rm=admin they get sent to the administration page.</p>

<p>Here's the problem: When the user clicks on the "submit" button on either page, the runmode parameter (rm=stats) becomes part of the CGI environment variable QUERY_STRING (which, by definition, contains URL parameters).  </p>

<p>Suppose your instance script (cgi-bin/myapp) looks like this:</p>

<p><code><pre><br />
my $app = MyApp::Admin->new();<br />
$app->run();<br />
</pre></code></p>

<p>It may not appear obvious, but without any fancy processing, passing rm?=stats will cause the value of rm to be the runmode.  Read more about that here: http://search.cpan.org/~markstos/CGI-Application-4.31/lib/CGI/Application.pm .</p>

<p>Anyway, if you try that with a POST request, it will blow up in your face (I suggest using use CGI::Carp qw(fatalsToBrowser) to have it explode cleanly).</p>]]>
        <![CDATA[<p>Here's the solution:</p>

<p>Before you jump into a runmode, any runmode, CGI::Application calls cgiapp_prerun().  If here you can check to figure out if you have a runmode set or not!</p>

<p>With a GET request, $q->param('rm') will give you the rm parameter that you expect to be your runmode.   With a POST submission, however, you'll notice that you have form data there instead and your rm is now in the CGI environment variable.  You can get at these with $q->url_param().<br />
<code><pre><br />
sub cgiapp_prerun {<br />
        my $self = shift;<br />
        my $q = $self->query();<br />
        my $v = undef;<br />
        $v = $q->param('rm');<br />
        if(!defined($v)) {<br />
                my $arm = $q->url_param('rm');<br />
                $self->prerun_mode($arm);<br />
        }<br />
}<br />
</pre></code><br />
The logic works like this:</p>

<ul>
	<li>Try to get the parameter rm from the CGI parameters ($v = $q->param('rm')).  When this fails $v will be undefined.</li>
	<li>If $v is undefined then get the rm parameter from the URL encoded parameters list and pass it to prerun_mode() which will set the runmode.</li>
	<li>Fall off the end of control and your runmode will either be the rm passed via GET, or the one you set from url_params().
</ul>

<p>It's just that easy!</p>

<p>Checkout these sites for more information:</p>

<p>http://search.cpan.org/~markstos/CGI-Application-4.31/lib/CGI/Application.pm<br />
http://search.cpan.org/dist/CGI.pm/lib/CGI.pm#MIXING_POST_AND_URL_PARAMETERS<br />
</p>]]>
    </content>
</entry>

<entry>
    <title>The Spice Must Flow</title>
    <link rel="alternate" type="text/html" href="http://blog.lib.umn.edu/kerzn002/blog/2009/10/the-spice-must-flow.html" />
    <id>tag:blog.lib.umn.edu,2009:/kerzn002/blog//10841.199251</id>

    <published>2009-10-22T03:41:24Z</published>
    <updated>2009-10-29T09:00:03Z</updated>

    <summary>For this week&apos;s seminar, I read Paul Freedman&apos;s book &quot;Out of the East: Spices and the Medieval Imagination.&quot; In a similar vein to Phillips in &quot;The Medieval Expansion of Europe,&quot; Freedman explores Europe as part of the greater world order,...</summary>
    <author>
        <name>Jeff Kerzner</name>
        
    </author>
    
        <category term="History" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="history" label="History" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="middleages" label="Middle Ages" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="reading" label="Reading" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-us" xml:base="http://blog.lib.umn.edu/kerzn002/blog/">
        <![CDATA[<p>For this week's seminar, I read Paul Freedman's book "Out of the East: Spices and the Medieval Imagination."  In a similar vein to Phillips in "The Medieval Expansion of Europe," Freedman explores Europe as part of the greater world order, yet places it in the comparative economic perspective it deserves in relationship to the Mongols, Chinese, Arabs.  His theory, that the pusuit of luxury goods - specifically that demand for spice fueled exploration by Europeans in the Eastern (and eventually Western) hemisphere.</p>]]>
        <![CDATA[<p>Possibly the most important thread in the book (aside from the spice) was the notion that exploration from Western Europe was driven out of economic necessity rather than out of a latent ambition or cultural force.  </p>

<p>Most of the book was spent discussing the role of spice in European culture ranging from cooking to medicine to spirituality.  Especially interesting are his discussion about the notion of hot-cold and wet-dry spectra for spices and humours as well as a brief reflection on the development of European cuisine as an effect of the commoditization of the spice trade.  It's well worth reading if you have an interest in tracing the roots of European culture in the middle ages.</p>]]>
    </content>
</entry>

<entry>
    <title>Readings</title>
    <link rel="alternate" type="text/html" href="http://blog.lib.umn.edu/kerzn002/blog/2009/10/readings.html" />
    <id>tag:blog.lib.umn.edu,2009:/kerzn002/blog//10841.198131</id>

    <published>2009-10-17T07:56:39Z</published>
    <updated>2009-11-10T04:36:00Z</updated>

    <summary>This week I read J. R. S. Phillips&apos; &quot;The Medieval Expansion of Europe&quot; which was a fairly painless read. The author&apos;s prose is relatively easy and doesn&apos;t presuppose an extensive knowledge of medieval history - I think it&apos;s good as...</summary>
    <author>
        <name>Jeff Kerzner</name>
        
    </author>
    
    
    <content type="html" xml:lang="en-us" xml:base="http://blog.lib.umn.edu/kerzn002/blog/">
        <![CDATA[<p>This week I read J. R. S. Phillips' "The Medieval Expansion of Europe" which was a fairly painless read.  The author's prose is relatively easy and doesn't presuppose an extensive knowledge of medieval history - I think it's good as a point-counterpoint text for general reading.</p>

<p>Even though the reading was quite general, Phillips' hypothesis raises several concerns and questions about situating Europe on the periphery of the world.</p>]]>
        <![CDATA[<p>On the one hand, Philips clearly and successfully sets out to illustrate that travel is not dead in the Middle Ages and rather that there are glimmers of an exploratory spirit afoot.  His magnification of foreign travel, however, leaves the reader in a frame of mind with Europe as part of an interconnected global framework.  </p>

<p>Although it is apparently quite possible to trace the threads of global travel from Europe in the Middle Ages, to remove completely the idea of a disconnected, backwater Western Europe detracts from the importance of the extraordinary travelers.</p>

<p>I'm particularly interested in his treatment of 'collective actors' as agents of long-distance diplomacy.  On page 68 Philips writes that Bela IV of Hungary and Innocent IV in the 13th century sought "...a more reasoned response to the mongol onslaught in the form of a desire to discover more about the invaders, and if possible to persuade them to call off their attack."  Unfortunately, a dearth of citations makes it impossible to follow the claims of coherent, European foreign policy.</p>]]>
    </content>
</entry>

</feed>
