<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Bill Ruppert</title>
    <link rel="alternate" type="text/html" href="http://www.billruppert.com/" />
    <link rel="self" type="application/atom+xml" href="http://www.billruppert.com/atom.xml" />
    <id>tag:www.billruppert.com,2009-04-17://4</id>
    <updated>2009-12-04T15:26:27Z</updated>
    <subtitle>Perl programming and whatever.</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type Pro 4.23-en</generator>

<entry>
    <title>Comparing DNS Servers in Perl</title>
    <link rel="alternate" type="text/html" href="http://www.billruppert.com/2009/12/comparing-dns-servers-in-perl.html" />
    <id>tag:www.billruppert.com,2009://4.55</id>

    <published>2009-12-04T15:10:55Z</published>
    <updated>2009-12-04T15:26:27Z</updated>

    <summary><![CDATA[I've been reading about Google's new DNS service with great interest.&nbsp; I had to switch to OpenDNS some time ago when my ISP began redirecting 404's to a search page.&nbsp; This wreaked havoc on my link verification tools.While reading, I...]]></summary>
    <author>
        <name>Bill Ruppert</name>
        <uri>http://www.billruppert.com</uri>
    </author>
    
        <category term="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Script" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en-us" xml:base="http://www.billruppert.com/">
        <![CDATA[I've been reading about Google's new DNS service with great interest.&nbsp; I had to switch to OpenDNS some time ago when my ISP began redirecting 404's to a search page.&nbsp; This wreaked havoc on my link verification tools.<br /><br />While reading, I came upon a shell script at <a href="http://www.manu-j.com/blog/opendns-alternative-google-dns-rocks/">http://www.manu-j.com/blog/opendns-alternative-google-dns-rocks/</a> that I wanted to try.&nbsp; Since I run WinXP, I translated it to Perl and spruced it up a bit.&nbsp; I installed the utility from <a href="http://members.shaw.ca/nicholas.fong/dig/">http://members.shaw.ca/nicholas.fong/dig/</a> and away we went...<br /> 
<pre><code>

# dnstimes.pl - test dns server times

use strict;
use warnings;

my @urls = qw(
	lifehacker.com
	facebook.com
	manu-j.com
	reddit.com
	tb4.fr
	bbc.co.uk
	cindyruppert.com
);

my %dns_servers = (
	Level_3	=&gt; '4.2.2.2',
	Google	=&gt; '8.8.8.8',
	OpenDNS	=&gt; '208.67.222.222',
);

for my $dns_firm (sort keys %dns_servers) {
	my $dns_ip = $dns_servers{$dns_firm};
	for my $url (@urls) {
		my $result = `dig \@$dns_ip $url`;
		my ($time) = $result =~ /Query time: (\d+)/s;
		print "$dns_firm\t$url\t$time\n";
	}
}

</code></pre>
<br /><br />]]>
        
    </content>
</entry>

<entry>
    <title>Removing HTML::FormFu elements from a form</title>
    <link rel="alternate" type="text/html" href="http://www.billruppert.com/2009/08/removing-htmlformfu-elements-from-a-form.html" />
    <id>tag:www.billruppert.com,2009://4.54</id>

    <published>2009-08-12T22:20:01Z</published>
    <updated>2009-08-12T22:30:00Z</updated>

    <summary>Figuring this out was somewhat painful, so I thought I would blog it.I want to use the same form yaml for several different actions (update, create, view) andI had a list of field names I wanted to remove that were...</summary>
    <author>
        <name>Bill Ruppert</name>
        <uri>http://www.billruppert.com</uri>
    </author>
    
        <category term="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Snippet" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Web Development" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en-us" xml:base="http://www.billruppert.com/">
        <![CDATA[Figuring this out was somewhat painful, so I thought I would blog it.<br /><br />I want to use the same form yaml for several different actions (update, create, view) andI had a list of field names I wanted to remove that were not relevant for create.<br /><br />The remove_element method only works on the immediate children of the invoking object (as does get element), so $form-&gt;remove_element does not usually work.&nbsp; I found <a href="http://www.mail-archive.com/html-formfu@lists.scsys.co.uk/msg01559.html">a posting</a> on the HTML::FormFu list where Carl Franks showed the idiom $element-&gt;parent-&gt;remove_element($element);<br /><br />So my code became:<br /><br />
<code></code><pre># remove fields not needed for this action
for (qw(created_by created_time changed_by changed_time version)) {
	my $element = $form-&gt;get_all_element({name =&gt; $_});
	if ($element) {
		$element-&gt;parent-&gt;remove_element($element);
	}
}

<br />Works great!<br /></pre>
]]>
        
    </content>
</entry>

<entry>
    <title>Check Google toolbar pagerank against multiple hosts</title>
    <link rel="alternate" type="text/html" href="http://www.billruppert.com/2009/08/check-google-toolbar-pagerank-against-multiple-hosts.html" />
    <id>tag:www.billruppert.com,2009://4.53</id>

    <published>2009-08-07T19:18:07Z</published>
    <updated>2009-08-07T19:23:11Z</updated>

    <summary><![CDATA[One of my sites was coming up with a graybar, so I wanted to check it against other hosts, besides the default.&nbsp; I tried a couple of the websites that I normally do this with, and they weren't working.&nbsp; So,...]]></summary>
    <author>
        <name>Bill Ruppert</name>
        <uri>http://www.billruppert.com</uri>
    </author>
    
        <category term="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Script" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en-us" xml:base="http://www.billruppert.com/">
        <![CDATA[One of my sites was coming up with a graybar, so I wanted to check it against other hosts, besides the default.&nbsp; I tried a couple of the websites that I normally do this with, and they weren't working.&nbsp; So, I wrote the following few lines.<br /><br /><pre><code>
use strict;
use warnings;
 
use WWW::Google::PageRank;

my @hosts = (
	"toolbarqueries.google.com",
	"209.85.227.147",
	"209.85.227.104",
);

for my $host (@hosts) {
	print "\n$host\n";
	my $pr = WWW::Google::PageRank-&gt;new(host =&gt; $host)
		or die $!;
	for my $domain (@ARGV) {
		$domain =~ s{http://}{};
		$domain =~ s{/$}{};
		my $pagerank = $pr-&gt;get("http://$domain/");
		print "    $pagerank  $domain\n";
	}
}
</code></pre>
]]>
        
    </content>
</entry>

<entry>
    <title>&quot;Everything&quot; at VoidTools.com</title>
    <link rel="alternate" type="text/html" href="http://www.billruppert.com/2009/06/everything-at-voidtoolscom.html" />
    <id>tag:www.billruppert.com,2009://4.41</id>

    <published>2009-06-05T14:44:29Z</published>
    <updated>2009-06-05T14:51:36Z</updated>

    <summary><![CDATA[I just used Everything to find all of the copies of Redemption.dll on my machine.&nbsp; As I did so, it I realized that I had to give it a shoutout and make a donation as well.&nbsp; This is really a...]]></summary>
    <author>
        <name>Bill Ruppert</name>
        <uri>http://www.billruppert.com</uri>
    </author>
    
        <category term="Tools" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en-us" xml:base="http://www.billruppert.com/">
        <![CDATA[I just used Everything to find all of the copies of Redemption.dll on my machine.&nbsp; As I did so, it I realized that I had to give it a shoutout and make a donation as well.&nbsp; <br /><br />This is really a great tool.&nbsp; It requires NTFS, and uses it to instantly index and find all of the file names on your computer.&nbsp; And I do mean instantly.&nbsp; I'm shocked at how often I use it.<br /><br /><a href="http://www.voidtools.com/">http://www.voidtools.com</a><br /><br />Thanks David!<br />]]>
        
    </content>
</entry>

<entry>
    <title>Deleting Old Files</title>
    <link rel="alternate" type="text/html" href="http://www.billruppert.com/2009/05/deleting-old-files.html" />
    <id>tag:www.billruppert.com,2009://4.38</id>

    <published>2009-05-24T14:51:19Z</published>
    <updated>2009-05-24T20:04:44Z</updated>

    <summary><![CDATA[Here is a script that deletes old files.&nbsp; In the Unix environment this is an easy job for a one line script using find.&nbsp; This Perl version has the -test option, to allow you to see what will happen, and...]]></summary>
    <author>
        <name>Bill Ruppert</name>
        <uri>http://www.billruppert.com</uri>
    </author>
    
        <category term="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Script" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en-us" xml:base="http://www.billruppert.com/">
        <![CDATA[Here is a script that deletes old files.&nbsp; In the Unix environment this is an easy job for a one line script using find.&nbsp; This Perl version has the -test option, to allow you to see what will happen, and prints some totals.<br /><pre><code><br />#!/usr/bin/perl

# delold.pl - delete old files

#-----------------------------------------------------------
# 05/24/2009  WR  Written
#-----------------------------------------------------------

use strict;
use warnings;
use Win32::Autoglob;
use Getopt::Long;

$| = 1;

sub print_usage;
sub abort_usage;

# option defaults
my $days_back    = 10;
my $test_flag    = 0;
my $verbose_flag = 0;
my $quiet_flag   = 0;

# get options
GetOptions (
    'days=i'  =&gt; \$days_back,
    'test'    =&gt; \$test_flag,
    'verbose' =&gt; \$verbose_flag,
    'quiet'   =&gt; \$quiet_flag,
    'usage'   =&gt; sub {print_usage; exit 1},
) or abort_usage "Invalid option";

my $time = time();

my $files_to_delete = 0;
my $files_total     = 0;
my $files_failed    = 0;

FILE:
for my $file (@ARGV) {

    # must exist, must be a plain old file
    next FILE if !-e $file;
    next FILE if !-f $file;

    $files_total++;

    # modified age in days
    my ($mtime) = (stat($file))[9];
    my $modified_age = ($time - $mtime) / (3600 * 24);

    # skip if too young
    next FILE if $modified_age &lt; $days_back;
    
    $files_to_delete++;

    if ($test_flag || $verbose_flag) {
        printf "Age: %-6.1f  File: %s\n",
            $modified_age,
            $file;
    }

    # skip if we are testing
    next FILE if $test_flag;

    # delete the file
    if (!unlink $file) {
        warn "Failed to delete file $file\n";
        $files_failed++;
    }

}

if ($test_flag) {
    print "\nTest Flag is set, no deletes done!\n";
}

my $files_remaining = $files_total - $files_to_delete + $files_failed;

if (!$quiet_flag || $test_flag) {
    print "\n";
    print "Total files:      $files_total\n";
    print "Files to delete:  $files_to_delete\n";
    print "Failed to delete: $files_failed\n";
    print "Files remaining:  $files_remaining\n";
}

exit 1;

sub abort_usage {
    print STDERR join("\n", @_), "\n" if @_;
    print_usage;
    exit 0;
}

sub print_usage {
    print STDERR &lt;&lt;END;
Usage: delold.pl [Options] files...
Options:
    --days n      - Set age of files to keep.
                    Files over "days" old will be deleted.
                    Default is 10 days.
    --test        - Print file names to be deleted with age,
                    but do not actually delete.
                    Default is false.
    --verbose     - Print file name and age while deleting.
                    Default is false.
    --quiet       - Suppress printing of totals after deleting.
                    Default is false.
    --usage       - print this message and exit
END
}

</code></pre>]]>
        
    </content>
</entry>

<entry>
    <title>Promoting Perl</title>
    <link rel="alternate" type="text/html" href="http://www.billruppert.com/2009/05/promoting-perl.html" />
    <id>tag:www.billruppert.com,2009://4.36</id>

    <published>2009-05-18T21:53:27Z</published>
    <updated>2009-05-18T21:54:43Z</updated>

    <summary><![CDATA[The Perl community is making an effort to improve visibility.&nbsp; I added "Perl programming" to the top of the blog in support of this effort....]]></summary>
    <author>
        <name>Bill Ruppert</name>
        <uri>http://www.billruppert.com</uri>
    </author>
    
        <category term="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en-us" xml:base="http://www.billruppert.com/">
        <![CDATA[The Perl community is making an effort to improve visibility.&nbsp; I added "Perl programming" to the top of the blog in support of this effort. ]]>
        
    </content>
</entry>

<entry>
    <title>Load SQLite Tables from .csv files</title>
    <link rel="alternate" type="text/html" href="http://www.billruppert.com/2009/04/load-sqlite-tables-from-csv-files.html" />
    <id>tag:www.billruppert.com,2009://4.35</id>

    <published>2009-04-28T21:28:01Z</published>
    <updated>2009-04-28T21:38:52Z</updated>

    <summary><![CDATA[Here is a quick script I wrote to load SQLite tables from CSV files.&nbsp; I exported the files from Microsoft Access.&nbsp; The first row has to have correct column names.Text::xSV is the best CSV file handler I could find on...]]></summary>
    <author>
        <name>Bill Ruppert</name>
        <uri>http://www.billruppert.com</uri>
    </author>
    
        <category term="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Snippet" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en-us" xml:base="http://www.billruppert.com/">
        <![CDATA[Here is a quick script I wrote to load SQLite tables from CSV files.&nbsp; I exported the files from Microsoft Access.&nbsp; The first row has to have correct column names.<br /><br />Text::xSV is the best CSV file handler I could find on CPAN.&nbsp; It correctly handles files with embedded newlines as well as very large files.&nbsp; SQL::Abstract makes it very easy to use straight DBI to speed up the load without going through an ORM.&nbsp; <br /><br />I prepare each row separately because I may have cases where there are trailing unused fields, and some Microsoft programs (Outlook comes to mind) do not attempt to output empty fields for them.&nbsp; If the speed difference is important, you may want to try to guarantee the exact number of fields in each row so you can prepare once.<br />

<pre><code>
#!/usr/bin/perl

# load_csv.pl - Load a db table from a csv file.
#               First row must be field names.
# 04/28/2009  W. Ruppert

use strict;
use warnings;
use Text::xSV;
use DBI;
use SQL::Abstract;

$| = 1;

sub usage {
    my ($msg) = @_;
    warn "$msg\n" if $msg;
    die "Usage: load_csv.pl db table csvfile\n";
}

# get parms
my $db        = shift || usage "No database name";
my $table     = shift || usage "No table name";
my $data_file = shift || usage "No csv data file";

usage "No such file: $db"        unless -e $db;
usage "No such file: $data_file" unless -e $data_file;

# setup csv file
my $csv = new Text::xSV;
$csv-&gt;open_file("$data_file");
$csv-&gt;read_header();

my $sql = SQL::Abstract-&gt;new;

# connect to db
my $dbh = DBI-&gt;connect("dbi:SQLite:$db", "","",
        { RaiseError =&gt; 1, PrintError =&gt; 0 }
) or die "can't connect\n";

$dbh-&gt;do('begin');

my $max_commit  = 1000;
my $inserted    = 0;

# process csv rows
while (my %fieldvals = $csv-&gt;fetchrow_hash) {

    # SQL::Abstract sets up the DBI variables
    my($stmt, @bind) = $sql-&gt;insert($table, \%fieldvals);

    # insert the row
    my $sth = $dbh-&gt;prepare($stmt);
    $inserted += $sth-&gt;execute(@bind);

    # progress bar
    print "*"            unless $inserted % 10;
    print " $inserted\n" unless $inserted % 500;

    # commit every once in a while
    unless ($inserted % $max_commit) {
        $dbh-&gt;do('commit');
        $dbh-&gt;do('begin');
    }
}

$dbh-&gt;do('commit');
$dbh-&gt;disconnect;

print "\nInserted $inserted records\n";
exit 1;
</code></pre>]]>
        
    </content>
</entry>

<entry>
    <title>Firefox FOUC fixed</title>
    <link rel="alternate" type="text/html" href="http://www.billruppert.com/2009/04/firefox-fouc-fixed.html" />
    <id>tag:www.billruppert.com,2009://4.34</id>

    <published>2009-04-27T15:25:20Z</published>
    <updated>2009-04-27T15:39:24Z</updated>

    <summary><![CDATA[Had a nasty FOUC (flash of unstyled content) on one of our websites.&nbsp; It was real bad in Firefox, didn't check it in IE.&nbsp; The page loads a fairly small amount of CSS (28k) in the head.&nbsp; No scripts though.&nbsp;...]]></summary>
    <author>
        <name>Bill Ruppert</name>
        <uri>http://www.billruppert.com</uri>
    </author>
    
        <category term="Web Development" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en-us" xml:base="http://www.billruppert.com/">
        <![CDATA[Had a nasty FOUC (flash of unstyled content) on one of our websites.&nbsp; It was real bad in Firefox, didn't check it in IE.&nbsp; <br /><br />The page loads a fairly small amount of CSS (28k) in the head.&nbsp; No scripts though.&nbsp; Our main site does not have this problem, and it has a small script in the head (to prevent external framing), so I added that but no difference.<br /><br />The main site also has a scipt at the top of the body to pre-load the "Cool DHTML Tooltip" from www.dynamicdrive.com.&nbsp; Adding that script fixed the FOUC:<br /><br />&lt;body&gt;<br />&lt;div id="dhtmltooltip"&gt;&lt;/div&gt;<br />&lt;script type="text/javascript" src="js/tooltip.js"&gt;&lt;/script&gt;<br /><br />Now there is a blank screen for a while, then the formatted page loads.&nbsp; I guess the script stops the rendering from starting too fast.&nbsp; I don't actually use the tooltip script on this site, but it is only 4k.<br />]]>
        
    </content>
</entry>

<entry>
    <title>Determine Image Size from URL</title>
    <link rel="alternate" type="text/html" href="http://www.billruppert.com/2009/04/new-blog.html" />
    <id>tag:www.billruppert.com,2009://4.31</id>

    <published>2009-04-17T16:47:15Z</published>
    <updated>2009-04-17T17:02:12Z</updated>

    <summary><![CDATA[Need to get the size of an image on the web without storing it.&nbsp; Done by pulling the image with LWP::Simple and giving the content buffer to Image::Size. #!/usr/bin/perl # Get dimensions of web image # 04/17/2009 WR use strict;...]]></summary>
    <author>
        <name>Bill Ruppert</name>
        <uri>http://www.billruppert.com</uri>
    </author>
    
        <category term="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Snippet" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en-us" xml:base="http://www.billruppert.com/">
        <![CDATA[Need to get the size of an image on the web without storing it.&nbsp; Done by pulling the image with LWP::Simple and giving the content buffer to Image::Size.<br /><br /><br />
<pre><code>
#!/usr/bin/perl
# Get dimensions of web image
# 04/17/2009  WR

use strict;
use warnings;
use LWP::Simple;
use Image::Size;

my @urls = (
	"http://www.google.com/intl/en_ALL/images/logo.gif",
	"http://l.yimg.com/a/i/ww/beta/y3.gif",
	"http://www.example.com/nothing.gif",
	"http://graphics8.nytimes.com/images/misc/nytlogo379x64.gif",
);

URL:
for my $url (@urls) {
	my $image = get $url;
	unless (defined $image) {
		warn "Couldn't get $url!\n";
		next URL;
	}
	my ($width, $height) = imgsize(\$image);
	printf "%4d %4d   %s\n", $width, $height, $url;
}

exit 1;
</code></pre>]]>
        
    </content>
</entry>

</feed>
