<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Proud to Use Perl</title>
    <link rel="alternate" type="text/html" href="http://proudtouseperl.com/" />
    <link rel="self" type="application/atom+xml" href="http://proudtouseperl.com/atom.xml" />
    <id>tag:proudtouseperl.com,2008-08-16://2</id>
    <updated>2009-05-15T14:49:45Z</updated>
    <subtitle>We love Perl and we don&apos;t care who knows it</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type Pro 4.25</generator>

<entry>
    <title>5 Things I Love/Hate About Krang</title>
    <link rel="alternate" type="text/html" href="http://proudtouseperl.com/2009/05/5-things-i-lovehate-about-krang.html" />
    <id>tag:proudtouseperl.com,2009://2.21</id>

    <published>2009-05-15T14:21:40Z</published>
    <updated>2009-05-15T14:49:45Z</updated>

    <summary> Krang is an OSS Perl CMS that doesn&apos;t get a lot of attention (in the Perl world is mostly Moveable Type and sometimes Bricolage). We use it at work and for the most part I&apos;m pretty happy with it....</summary>
    <author>
        <name>Michael Peters</name>
        
    </author>
    
        <category term="tech" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="web" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://proudtouseperl.com/">
        <![CDATA[<p><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="krang_body.jpg" src="http://proudtouseperl.com/krang_body.jpg" width="220" class="mt-image-left" style="float: left; margin: 0 20px 20px 0;" /></span>
<a href="http://krangcms.com">Krang</a> is an OSS Perl CMS that doesn't get
a lot of attention (in the Perl world is mostly <a href="http://www.movabletype.org/">Moveable Type</a>
and sometimes <a href="http://bricolagecms.org/">Bricolage</a>). We use it at work and for the most
part I'm pretty happy with it. So after being inspired by <a href="http://www.webquills.net/scroll/2009/05/10-things-i-lovehate-about-mov.html">this post</a>
I thought I'd write a similar post about Krang just to get the word out
there.
<br><br></p>

<h2>1 - Flexible</h2>

<h3>Love</h3>

<p>Krang was initially developed for a large magazine company that had lots
of magazines that they needed to bring online. Each magazine had their own
look and feel, their own editors, their own workflow and their own style
of composing articles. Krang needed to support all of these magazines
in a single install.</p>

<p>Everything about a story in Krang is defined by an "element
library". These element libraries can be created for each site you run
or they can be shared between multiple sites. You can also inherit from
other libraries to have some sites become even more specialized.</p>

<p>Krang also has the concept of different story types, so in your element
library you could define blog posts, petitions, image galleries, surveys,
etc. Every industry can be different in the kinds of things they want
on their site. With the right element library you can easily turn Krang
from a generic CMS into an industry specific one. That's why I like to
think of Krang as a CMS platform rather than just a CMS.</p>

<p>Krang also divorces the creation and editting of content from the
serving of that content. By default Krang publishes out static HTML
documents and media files which can then be served by any old webserver.
But for the more power hungry among us, we use Krang to publish out more
interesting things. XML, PHP, generated Perl scripts, HTML::Template
templates, .htaccess files, you name it. We then customize our front-end
web servers to take those generated files and turn them into the tasty
goodness that our clients see.</p>

<p><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="edit_story-thumb.png" src="http://proudtouseperl.com/find_story_adv-thumb.png" width="240" height="140" class="mt-image-right" style="float: right; margin: 0 0 20px 20px;" /></span></p>

<p>Krang also has an extensive addon system that allows any addon to override
and extend any internal Krang class, template or media file. This means
we can easily add extra screens, extra reports or even add fields to
existing screens. All of these enhancements can exist with very little
worry about upgrades breaking our addons (if we're careful).</p>

<p>At my job we manage over 70 distinct sites using just a handful of element
libraries. Each one is very distinct in it's layout and different in what
they do. Some are basically, static HTML sites. Others have complicated
forms tied together and still others are flash apps that consume XML
data files.</p>

<h3>Hate</h3>

<p>This flexibility comes at a cost. Setting up Krang is not a simple
task. It does come with a very basic Default element library, but I see
that more as an example of how to write your own element library rather
than something that's useful for basic sites.</p>

<p>You also need to write you own templates, stylesheets, etc. Nothing like
the nice pre-packaged skins you can get for Wordpress or Moveable Type.</p>

<p>We've talked about making this easier with a better default element
library and even writing other more specific element libraries for common
types of sites. We also talked about creating a kind of Krang-Forge
where people could share and collaborate on addons.  Unfortunately no
one has found the time to do any of these ideas.</p>

<p>Krang's documentation is pretty good and thorough, but to get started
you need to have skills as a sys-admin, Perl developer and front-end
web designer. So it's hard to justify for smaller projects if you don't
already have all that talent on hand.</p>

<h2>2 - Everything is an Element</h2>

<h3>Love</h3>

<p>Story elements (and even elements on media objects, and categories) are
defined by the story's type and element library being used. When you
create a story you add the elements you need and ignore the ones you
don't. For an article this could be headings, subheadings, paragraphs,
quotes, images, tags, etc. Elements can even be nested so that you can
add things like images where you put in an alignment value, a caption,
an attribution, etc and have it all be treated like a single entity
when publishing.</p>

<p><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="find_story_adv-thumb.png" src="http://proudtouseperl.com/edit_story-thumb.png" width="240" height="140" class="mt-image-left" style="float: left; margin: 0 20px 20px 0;" /></span></p>

<p>Each element can have it's own template and publishing works by cascading
upward: first publish the image's caption with it's template (if it has
one) then the image with it's optional template and then the article the
image is in. This gives a lot of power in deciding how similar things
can look on different parts of the site.</p>

<p>The element library defines not only how the element is published, but
also how it looks when the editor enters the data. An Event story's date
element could be a fancy pop up calendar.  A paragraph could be a little
WYSIWYG editor and a section-heading could be simple text input.</p>

<h3>Hate</h3>

<p>Because everything is an element, they aren't just simple text
items. Elements are complex Perl objects that are serialized and stored
in the database. This makes it hard to examine them on the outside. You
almost always have to write Perl code to manipulate the data in story. And
because things can be nested to arbitary levels it's not always easy to
find what you want in a flat database table.</p>

<p>Debugging serialized story data can sometimes be a royal pain. Dumping
out a story's elements using Data::Dumper for more complicated stories
can fill up many terminal screens.</p>

<p>Having our Stories in structured data has lots of benefits, but simplicity
isn't one of them. Sometimes users just want a simple large WYSIWYG
editor on the page so they can pretend they are using Microsoft Word
and not have to think about composition or consistency. "I want this
sentence to be red and blinking!".</p>

<h2>3 - Small Community</h2>

<h3>Love</h3>

<p><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="krang_grafitti.jpg" src="http://proudtouseperl.com/krang_grafitti.jpg" width="229" height="221" class="mt-image-right" style="float: right; margin: 0 0 20px 20px;" /></span></p>

<p>Since we have a lot clients who want lots of different things, often
we've found ourselves wanting to make Krang do something different than
what it does by default.  It already has lots of customization hooks,
but sometimes we've wanted just a few more.</p>

<p>Since it's OSS community is small it's pretty easy to get SVN access and
commit the changes we've needed. Also, when we need to have something
rolled out into production we can influence (and sometimes even outright
control) the release schedule so that we have a version with the features
and bug fixes we need for our clients. And it's not just our company that
has this weight. All of the other companies that contribute heavily to
Krang take advantage of this too.</p>

<h3>Hate</h3>

<p>A smaller community means less diversity and less structure. We don't
have a project leader or even a project roadmap. We've done in-person
meetings a couple of times that have always given blasts of energy to
Krang development, but it's hard to sustain when the few core people
have other things they need to do.</p>

<p>A smaller community also means there's less of a Krang eco-system. On
larger projects beginners can get help from intermediate users who in
turn can get help from experts.  When you need to hire someone, you can
put Wordpress, or Drupal experience on the job requirements because you
know there's a large user base out there. There are even books written
about using and developing for some of these Content Management Systems.
While I hope this post brings more users into the Krang community,
I'm realistic and know that I'm using a pretty obscure technology. I do
sometimes ask myself whether it will come back to bite me down the road.</p>

<h2>4 - All-in-One Installation</h2>

<h3>Love</h3>

<p>Perl doesn't have a standard packaging system for deployment. Krang
came into the OSS world in 2004 when projects like PAR were just getting
started, so the developers at that time created their own custom way of
packaging it.  Krang comes bundled with it's own Apache, mod_perl, mod_ssl
and a copy of every CPAN module it uses. This means deploying Krang is not
a hunting expedition trying to round up all the dependencies nor digging
through your Apache config to squeeze Krang in. Everything is built and
installed together and doesn't affect anything else on your system.</p>

<p>This means we always have control over which versions of which Perl
libraries a given install is using. We have complete control over the
Apache/mod_perl configuration so we know that someone's custom setup
isn't going to cause us problems. Every install of Krang is identical
to every other install of that same version (minus any addons they
have installed). This makes troubleshooting much easier than it would be
otherwise. It also makes it easy for non sys-admins to install because you
don't have to teach them about rpm or their OS's package manager, you just
give them a simple <code>./bin/krang_install</code> command to run and that's it.</p>

<h3>Hate</h3>

<p>A custom packaging system by definition means it's non-standard. You
can't release Krang to CPAN, you can't turn it into an .rpm or .deb
package (at least no easily). Any real sys-admin is going to give you
the stink-eye when you tell them to install this application in a way
that ignores all the other tools they use for managing their systems.</p>

<p>It also means that you have to learn and work around all of the platform
specific problems that comes with building software. Krang does a pretty
good job of this, but if we didn't have to worry about it we could definitely
save developer time.</p>

<p>Another problem with a custom packaging system is that it's one more step
for a new contributor to overcome. One more quirk to learn about our system
before they can start submitting useful, tested patches.</p>

<h2>5 - Simple Templating</h2>

<h3>Love</h3>

<p>By default Krang uses <a href="http://search.cpan.org/perldoc?HTML::Template">HTML::Template</a> (<a href="http://search.cpan.org/perldoc?HTML::Template::Expr">HTML::Template::Expr</a> actually)
both internally and for the publishing of stories. Users can control and
edit these story templates for their sites and HTML::Template is pretty
easy for them to learn. One of our addons provides some extra template
functions to make things like number and date formatting easier.</p>

<p>Most people who can understand HTML can understand HTML::Template's
syntax so we don't need too much training to get them up to speed. And
most of the built-in operators and functions are simple enough to not
cause the non-technical brain too much damage. Plus it's really fast.</p>

<h3>Hate</h3>

<p>Because of it's simplicity, HTML::Template lacks some constructs that
would make life much easier. There's no C<elsif>, no way to set/override
variables, and no way to pass in container objects without making them
into a loop. None of these are too painful, but they can make your
templates more verbose and messier than you'd like.</p>

<p>Addon's are free to override the templating system and use their own
if they'd like, but I'm not sure anyone really does this.</p>

<h2>Conclusion</h2>

<p>Even given it's warts, I really do like Krang. It lets my small team
manage some really complicated sites and give a lot of power to our
users that they couldn't get in another system. It also let's us split
up the responsibilities nicely. Non-technical people can create and
edit dynamic forms on their web sites, view reports on the activities on
those forms and make adjustments. And the most important thing is that when they are doing it, they don't have to bother me to do it for them :)</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Dealing with Duplicate Person Data</title>
    <link rel="alternate" type="text/html" href="http://proudtouseperl.com/2009/04/dealing-with-duplicate-person-data.html" />
    <id>tag:proudtouseperl.com,2009://2.20</id>

    <published>2009-04-21T16:06:45Z</published>
    <updated>2009-04-21T17:53:05Z</updated>

    <summary>I&apos;ve recently been working on a fairly large project that that has contact information for almost 2 million people. These records contain details for both online and offline actions. Since the data can come from multiple sources there exist many...</summary>
    <author>
        <name>Michael Peters</name>
        
    </author>
    
    <category term="cpanduplicateforkparallel" label="cpan duplicate fork parallel" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://proudtouseperl.com/">
        <![CDATA[<p><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="clones.jpg" src="http://proudtouseperl.com/2009/04/21/clones.jpg" width="240" height="160" class="mt-image-left" style="float: left; margin: 0 20px 20px 0;" /></span>I've recently been working on a fairly large project that that has
contact information for almost 2 million people. These records contain
details for both online and offline actions. Since the data can come from
multiple sources there exist many duplicate records. Duplicate records
mean more processing for our code, more storage space and more hassle
for our clients who have to deal with these duplicates. All in all,
bad things to leave lying around.</p>

<p>In this article we'll look at some strategies that I used to identify
and remove these duplicates. All code in this article are samples, and
we'll leave the task of assembling them into a final working program up
to the reader.</p>

<h2>CPAN is your Friend</h2>

<p>Like all good Perl projects, we will make heavy use of the CPAN. It makes
our lives so much easier and every day I'm more in awe at the quality
and bredth of solutions I find there. For this project we'll be using
<a href="http://search.cpan.org/perldoc?Text::LevenshteinXS">Text::LevenshteinXS</a>, 
<a href="http://search.cpan.org/perldoc?Lingua::EN::Nickname">Lingua::EN::Nickname</a> and 
<a href="http://search.cpan.org/perldoc?Parallel::ForkManager">Parallel::ForkManager</a>.</p>

<h2>What is a Duplicate?</h2>

<p>For our project we didn't want to automatically merge duplicates but
rather flag them as being potential duplicates and then let our client
choose to do the actual merge. Not only does this force a human to make
the final decision but it also allows the client to determine which values
for which conflicting fields are chosen for the final merged record.</p>

<p>To mark a pair of records as being potential duplicates we want to
give them a score and then remember any pair that scored over a certain
threshold. In our case the scores go from 0 to 100 and our threshold is
75. Each organization is different in what fields it has and what they
consider to be a duplicate. Since some fields are more important than
others (having the same state is not as important as having the same
last name) we need to give our fields some weight. For this project
we'll use the following fields and weights:</p>

<pre><code>    my %field_weight = (
        last_name  =&gt; 25,
        first_name =&gt; 25,
        address1   =&gt; 20,
        address2   =&gt; 10,
        city       =&gt; 20,
    );
</code></pre>

<p><br>
If the fields from 2 different records don't match (we ignore case for
all matches because "peters" is the same thing as "PETERS") for a given
field we subtract the given weight. You will of course have to play with
these numbers for your own data.</p>

<h2>Catching Typos</h2>

<p>What if 2 people who are living at the same address have first names
of "Michael" and "Michal"?  They are most likely the same person and
someone somewhere made a typo. One of the easiest ways to catch typos
or strings that are almost identical is with an algorithm called a
"Levenshtein Distance". You can read more about it if you want the
specifics, but basically this algorithm calculates the number of changes
needed to transform one string into another. In the case of "Michael" vs
"Michal" the Levenshtein Distance is 1. The distance between "Michael"
and "Michelle" is 3 and the distance between "Michael" and "Peters"
is a whopping 7.</p>

<pre><code>    use Text::LevenshteinXS qw(distance);
    my $distance = distance("Michael", "Michelle");
</code></pre>

<p><br>
We're using <a href="http://search.cpan.org/perldoc?Text::LevenshteinXS">Text::LevenshteinXS</a> because it's simple and written in C
(the "XS" part of the name means it's written in Perl's C API which is
called XS).</p>

<h3>More Weights</h3>

<p>Since typos are usually 1 or 2 characters we don't really want anything
with a distance of more than 3. But 1 is more likely to be a duplicate
than is 3. So once again we'll use weighted values. For this project
we'll use the following weights modifiers:</p>

<pre><code>    my @distance_modifiers = (.10, .30, .45, .60, .90);
</code></pre>

<p><br>
So if we're comparing our first_name fields and they have a Levenshtein
Distance of 2, then we'll subtract 7.5 points (25 x .30). If that's the
only difference between our two records then we'll have a total score
of 92.5 which is a pretty good score.</p>

<pre><code>    my $distance = distance($val1, $val2);
    $score -= $distance ? $field_weight{$field} * $distance_modifiers[$distance -1] : 0;
</code></pre>

<p><br></p>

<h2>Nicknames</h2>

<p>Nicknames are another problem we want to deal with. If we encounter
2 records that are similar but one has a first name of "Michael"
and the other is "Mike" that won't score very well because it has a
Levenshtein Distance of 4. It gets even worse when you look at examples
like "Charles" and "Chuck".  Our specific problem is made easier by the
fact that almost all our our data is in English. CPAN comes to the rescue
with <a href="http://search.cpan.org/perldoc?Lingua::EN::Nickname">Lingua::EN::Nickname</a>. 
You can give it 2 names and it will give
you a score that lets you know whether one is probably the nickname of
the other.</p>

<pre><code>    nickname_eq("Robert", "Bob"); # gives a score of 98
</code></pre>

<p><br>
Having played with our data set more, we find that if the score is above
90 we are almost certain that it's a nickname and we treat it as if the
names had matched exactly. If the score is between 80 and 90 we use the
score as another modifier to the weight.</p>

<pre><code>    my $nick_score = nickname_eq($val1, $val2);
    if( $nick_score &lt; 90 &amp;&amp; $nick_score &gt; 80 ) {
        $score -= $field_weight{$field} * (1 - ($nick_score / 100));
    }
</code></pre>

<p><br></p>

<h2>Abbreviations</h2>

<p>We love to use abbreviations to make things shorter and easier to type. I
can't remember the last time I entered my full street name in a web
form. But to better find duplicates in our data we need to be able to
consider "Drive" and "Dr." to be the same thing. You could use something
like <a href="http://search.cpan.org/perldoc?Geo::PostalAddress">Geo::PostalAddress</a> 
to <code>normalize()</code> the different addresses,
but that was a little more processing than I wanted for this project.</p>

<p>So I just used a simple lookup hash based on the data I pulled from the
US Postal Service (http://www.usps.com/ncsc/lookups/abbr_suffix.txt). I
just took the abbreviations that were most common and our resulting
address normalization looks something like this:</p>

<pre><code>    my %ADDR_ABBR = (
        avenue     =&gt; 'ave',
        avn        =&gt; 'ave',
        boulevard  =&gt; 'blvd',
        circle     =&gt; 'cir',
        circ       =&gt; 'cir',
        court      =&gt; 'ct',
        crt        =&gt; 'ct',
        drive      =&gt; 'dr',
        driv       =&gt; 'dr',
        drv        =&gt; 'dr',
        ...
    );

    my @parts = split(/\s+/, $address);
    for(my $i=0; $i&lt;=$#parts; $i++) {
        if( exists $ADDR_ABBR{$parts[$i]} ) {
            $parts[$i] = $ADDR_ABBR{$parts[$i]};
        }
    }

    $address = join(' ', @parts);
</code></pre>

<p><br>
And now we can compare 2 addresses to get the Levenshtein distance
without having to worry about common abbreviations throwing it off.</p>

<h2>Multiple Cores and Multiple CPUS</h2>

<p>Since this process will be running on a machine with multiple CPUs we
want to take advantage of that. We are comparing each record to every
other record so it's basically an N-squared algorithm. With millions
of records this means the number of record comparisons will be in the
trillions and would take way too long if we didn't take advantage of the
extra CPUs on this machine. To split the work up I decided to take all
of the data for a single US state and work on that as a group and then
move on to the next state one by one.</p>

<p>This approach is trivially parallelizable so we should simply be able
to fork off multiple processes and have them work on their own portion
of the data. Duplicate scores will be recorded in the database so we
don't even need any communication between the processes (in reality I
used <a href="http://search.cpan.org/perldoc?IPC::Shareable">IPC::Shareable</a> 
to communicate with the main process so that we
could show a progress indicator of sorts when used from the command line,
but this isn't necessary).</p>

<p>Using <code>fork()</code> under Unix isn't really that hard especially if you
follow the canonical example in the Camel Book. But that's no reason it
can't be made even simpler. I like <a href="http://search.cpan.org/perldoc?Parallel::ForkManager">Parallel::ForkManager</a>
 because it
makes it brain-dead simple to fork off a bunch of processes up to a some
limit (for me this seemed to be the number of CPUs + 1). Then every time
a child process finishes it takes care of forking another one to take
it's place to do more work.</p>

<pre><code>    my $fork_manager = Parallel::ForkManager-&gt;new($num_cpus + 1);
    while(my ($state) = get_next_state()) {
        # fork off and let a child handle this state
        my $pid = $fork_manager-&gt;start and next;

        process_state_records($state);
        $fork_manager-&gt;finish();
    }
    $fork_manager-&gt;wait_all_children;
</code></pre>

<p><br></p>

<h2>Conclusions</h2>

<p>While there are many ways to tackle this problem (and mine is far
from the most optimal) I hope that this helps you to see the power of
the CPAN when tackling big problems. It's hard to find a problem that
someone else hasn't already faced and with the size and generosity of
the Perl community, they've probably put at least some of the solution
on to the CPAN.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Amazon S3 and Query-based Authentication</title>
    <link rel="alternate" type="text/html" href="http://proudtouseperl.com/2009/03/amazon-s3-and-query-based-authentication.html" />
    <id>tag:proudtouseperl.com,2009://2.19</id>

    <published>2009-03-10T13:10:34Z</published>
    <updated>2009-03-10T20:08:12Z</updated>

    <summary>At work, one of our latest projects is to offer a PDF download of some of our printed content, but before we do that, we want to ask for some contact information and then after that, we want to email...</summary>
    <author>
        <name>Jason Purdy</name>
        <uri>http://www.qsrmagazine.com</uri>
    </author>
    
        <category term="tech" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="amazons3" label="amazon s3" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="aws" label="aws" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://proudtouseperl.com/">
        <![CDATA[At <a href="http://www.qsrmagazine.com/">work</a>, one of our latest projects is to offer a PDF download of some of our printed content, but before we do that, we want to ask for some contact information and then after that, we want to email the requesting user download information.<br /><br /><a href="http://aws.amazon.com/s3/">Amazon S3</a> offers a great way for us to offload the bandwidth consumption and at the same time, protect the content from (most) unauthorized downloads. There are a lot of steps I'm going to gloss over, in terms of how to set it up. The important (Perl) part I want to share with you is once you get a file up on Amazon S3, how can you generate one-off URL's to download the file?<br /><br />The first thing is you'll need these 3 modules: <a href="http://search.cpan.org/%7Egaas/Digest-HMAC-1.01/lib/Digest/HMAC_SHA1.pm">Digest::HMAC_SHA1</a>, <a href="http://search.cpan.org/%7Egaas/MIME-Base64-3.07/Base64.pm">MIME::Base64</a> and <a href="http://search.cpan.org/%7Egaas/URI-1.37/URI/Escape.pm">URI::Escape</a>.<br /><br />Then you'll also need your account identifiers, <a href="http://aws-portal.amazon.com/gp/aws/developer/account/index.html?action=access-key">which you can find here</a>. Grab your "Access Key ID" and your "Secret Access Key" ( it's the 40 character string you gotta slick on 'Show' to unhide). Let me strongly urge you or remind you that those account pieces are confidential and should not be shared. People can rack up some serious charges on your credit card or obtain illegal access to your data.<br /><br />Ok, back to code. You'll first create your Digest::HMAC_SHA1 instance with your Amazon S3 "Secret Access Key":<br /><br /><blockquote><tt>my $hmac = Digest::HMAC_SHA1-&gt;new( &lt;KEY&gt; );</tt></blockquote>Then you need to figure out how long you want the URL to be available for - you'll need to figure out an epoch from which any request for the URL afterwards will no longer be available. Unfortunately, the epoch depends on whichever Amazon server is handling the request, so there's no really good way to get granular on the expiration. Or there might be, but I wasn't realy all-that-concerned. I just created an epoch 86400 seconds (1 day) in the future:<br /><br /><blockquote><tt>my $time = time() + 86400;</tt></blockquote>Now the last piece is a string of data that you have to put together to pass into the Digest::HMAC_SHA1 object. The string looks something like this:<br /><br /><blockquote><tt>my $string_to_sign = "GET\n\n\n$time\n/$bucket/$key"</tt></blockquote>Where $bucket is the bucket name and $key is the object name within the bucket. If you don't know what buckets and keys/objects are, check out Amazon's documentation.<br /><br />Now you have everything you need ... add the $string_to_sign to the Digest::HMAC_SHA1 object, encode it, escape it:<br /><br /><blockquote><tt>$hmac-&gt;add( $string_to_sign );<br />my $digest = encode_base64( $hmac-&gt;digest, '' );<br />$digest = uri_escape_utf8( $digest, '^A-Za-z0-9_-' );</tt></blockquote>Then you just put together the URL:<br /><br /><blockquote><tt>my $url = "http://s3.amazonaws.com/$bucket/$key?AWSAccessKeyId=XXX&amp;Expires=$time&amp;Signature=$digest";</tt></blockquote>By the way, did you know that you can make your bucket name a domain name and then assign its CNAME to amazon so that the URL looks even more proprietary? Then the URL would look something like this:<br /><br /><blockquote><tt>my $url = "http://$bucket/$key?AWSAccessKeyId=XXX&amp;Expires=$time&amp;Signature=$digest";</tt></blockquote>There are some great-looking CPAN modules (<a href="http://search.cpan.org/%7Etima/Amazon-S3-0.441/lib/Amazon/S3.pm">Amazon::S3</a> and <a href="http://search.cpan.org/%7Elbrocard/Net-Amazon-S3-0.50/lib/Net/Amazon/S3.pm">Net::Amazon::S3</a>) that may already do this, but seeing how I didn't want to install Moose (for Net::Amazon::S3) for 10 lines of code, I opt'd to go my own route. There are many other way-more complicated things you can do w/ Amazon S3 and if you are doing more complex things, then the CPAN modules may be up your alley.<br /><br />Cheers,<br /><br />Jason<br /><br />PS: I will be speaking at <a href="http://webinale.de/">webinale</a> in Berlin this May, so if anyone's in the area, come and check it out.<br /> ]]>
        
    </content>
</entry>

<entry>
    <title>Obfuscating Email Addresses with JavaScript (and Prototype)</title>
    <link rel="alternate" type="text/html" href="http://proudtouseperl.com/2009/02/obfuscating-email-addresses-with-javascript-and-prototype.html" />
    <id>tag:proudtouseperl.com,2009://2.18</id>

    <published>2009-02-25T04:30:09Z</published>
    <updated>2009-02-25T04:33:53Z</updated>

    <summary> I know this is probably done a million times elsewhere, but I thought this approach was pretty neat. At work, we worry about spam harvesters collecting our addresses, so we want to hide them. So today at work, I...</summary>
    <author>
        <name>Jason Purdy</name>
        <uri>http://www.qsrmagazine.com</uri>
    </author>
    
        <category term="tech" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="antispam" label="antispam" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="javascript" label="javascript" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="prototype" label="prototype" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://proudtouseperl.com/">
        <![CDATA[ <div>I know this is probably done a million times elsewhere, but I thought this approach was pretty neat. At work, we worry about spam harvesters collecting our addresses, so we want to hide them.</div>

<div><br />So today at work, I whipped this up pretty quickly, using <a href="http://code.google.com/apis/ajaxlibs/">Google's AJAX API Library</a> + <a href="http://prototypejs.org/">Prototype</a>.</div>

<code>
<br /></code><blockquote><code>&lt;html&gt;</code><br /><code>
&lt;head&gt;&lt;title&gt;Dynamic/Obfuscated Email Link Example&lt;/title&gt;&lt;/head&gt;</code><br /><code>
&lt;body&gt;</code><br /><code>
&lt;div&gt;</code><br /><code>
&lt;span class="add_email_link" id="jason"&gt;This should become an email link to me!&lt;/span&gt;</code><br /><code>
&lt;/div&gt;</code><br /><code>
&lt;script type="text/javascript" src="http://www.google.com/jsapi"&gt;&lt;/script&gt;</code><br /><code>
&lt;script type="text/javascript"&gt;</code><br /><code>
&nbsp;&nbsp;&nbsp;&nbsp;google.load("prototype", "1.6.0.3");</code><br /><code>
&nbsp;&nbsp;&nbsp;&nbsp;google.setOnLoadCallback( function() {</code><br /><code>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// gather all .add_email_link's and add mailto links around their children</code><br /><code>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$$('span.add_email_link').each( function( span ) {</code><br /><code>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;span.update( '&lt;a href="mailto:' + span.id + '@example.com"&gt;' +</code><br /><code>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;span.innerHTML + '&lt;/a&gt;' );</code><br /><code>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} );</code><br /><code>
&nbsp;&nbsp;&nbsp;&nbsp;} );</code><br /><code>
&lt;/script&gt;</code><br /><code>
&lt;/body&gt;</code><br /><code>
&lt;/html&gt;</code><br /><code>
</code></blockquote>

<div><br />So ... guess this doesn't have anything to do w/ Perl, per se, but couldn't resist sharing. What about you? What technique do you use?</div>

<div><br />Peace,</div>

<div><br />Jason</div>]]>
        
    </content>
</entry>

<entry>
    <title>How Perl Helped the Genome Project</title>
    <link rel="alternate" type="text/html" href="http://proudtouseperl.com/2008/12/today-i-want-to-talk.html" />
    <id>tag:proudtouseperl.com,2008://2.17</id>

    <published>2008-12-07T18:56:42Z</published>
    <updated>2008-12-07T19:21:22Z</updated>

    <summary>Today I want to talk about how Perl helped the Human Genome Project. The legend tells that somewhere in early February 1996, in Cambridge, England, in the largest DNA Sequencing centre in Europe, a meeting between scientists from Cambridge and...</summary>
    <author>
        <name>Luis Motta Campos</name>
        <uri>http://search.cpan.org/~lmc/</uri>
    </author>
    
        <category term="tech" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="bioperlgenome" label="bioperl genome" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://proudtouseperl.com/">
        <![CDATA[<p>Today I want to talk about how <a href="http://www.perl.org">Perl</a> helped the <a href="http://en.wikipedia.org/wiki/Human_Genome_Project">Human Genome Project</a>.</p>

<p>The legend <a href="http://www.bioperl.org/wiki/How_Perl_saved_human_genome">tells</a> that somewhere in early February 1996, in <a href="http://en.wikipedia.org/wiki/Cambridge">Cambridge, England</a>, in the <a href="http://www.yourgenome.org/">largest DNA Sequencing centre in Europe</a>, a meeting between scientists from Cambridge and from the largest DNA sequencing centre in the United States of America tried to solve a disconcerting problem: despite both DNA sequencing centres being using mainly the most laboratory techniques, databases, and data analysis tools, it was not possible to interchange data or meaningfully compare results between them.</p>

<p>The dimension of the Genome Project is respectable and would make an average DBA run for cover: estimates go up to 10 terabytes of information at the project completion, divided in complex and not so intuitive parts that make a lot of sense for molecular biologists, but not as much for a computer scientist.</p>

<p>From the software engineering point of view, managing the laboratory activity is a complex, ever-changing problem that drove a lot of development teams out of the road at the initial, monolithic implementations attempted. After a while, groups learned that modular, loosely-coupled systems that specialize on parts of the process and can be swapped around as the laboratory protocols and techniques used improve and change were a better implementation solution for the problem.</p>

<p>The utilization of those modular systems to analyse the DNA data was similar to a pipeline, and unix pipes were largely utilized to pass data between small processing programs.</p>

<p>A data interchange format was developed by the <a href="http://www.genome.wi.mit.edu/">Whitehead Institute and the MIT Centre for Genome Research</a> in order to easy the communication between those small pipelined analytic utilities. It's named <a href="http://stein.cshl.org/software/boulder/">Boulder</a>. It eventually became the data interchange format used by all the DNA Sequencing Centres around the world.</p>

<p>The format itself is designed to be easily implemented using Perl strengths, and the implementation provided is, of course, Perl-based. Nowadays, implementations for other languages are also available.</p>

<p>The basic principle of the <a href="http://search.cpan.org/~lds/Boulder-1.30/Boulder.pod">Boulder</a> API is that all data is associated with tags. The API allows easy access to the tags the programmer is interested in from the standard input, and allows the programmer to add more tags to be passed along with all the data to the next program in the pipeline through the standard out.</p>

<p>The use of the <a href="http://search.cpan.org/~lds/Boulder-1.30/Boulder.pod">Boulder</a> library, the cooperation of many other <a href="http://www.bioperl.org/wiki/BioPerl_Users">Perl developers</a>, and <a href="http://www.bioperl.org/wiki/Run_package">many other tools</a>, the Genome Project succeeded. I am proud to say this would be all much difficult without Perl.</p>]]>
        
    </content>
</entry>

<entry>
    <title>Music, Brains... and Perl.</title>
    <link rel="alternate" type="text/html" href="http://proudtouseperl.com/2008/11/music-brains-and-perl.html" />
    <id>tag:proudtouseperl.com,2008://2.16</id>

    <published>2008-11-23T18:20:00Z</published>
    <updated>2008-11-23T17:26:23Z</updated>

    <summary>Today I will talk about music. Well, not exactly about music, but about all the hassle I used to go through whenever I wanted to tag the MPeg Layer 3 files I want to listen on my computer. I used...</summary>
    <author>
        <name>Luis Motta Campos</name>
        <uri>http://search.cpan.org/~lmc/</uri>
    </author>
    
        <category term="tech" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://proudtouseperl.com/">
        <![CDATA[<p>Today I will talk about <a href="http://en.wikipedia.org/wiki/Music">music</a>. Well, not exactly about music, but about all the <a href="http://search.cpan.org/~karasik/PHP-0.11/PHP.pm">hassle</a> I used to go through whenever I wanted to tag the <a href="http://en.wikipedia.org/wiki/Mp3">MPeg Layer 3</a> files I want to listen on my <A href="http://en.wikipedia.org/wiki/Abacus">computer</a>.

<p>I used to do this <a href="http://en.wikipedia.org/wiki/Java_(programming_language)">labour-intensive, time-consuming, manual, repetitive task</a> by hand, and commited a lot of mistakes in the past. I longed for a tool that would be able to automate this process and make my life simpler, being at the same time less time-consuming, fully automated, and leaving the repetitive stuff for my desktop computer do handle.

<p>Probably all the noble readers of this Blog at least once in their lives had a thought like this before.

<p>After some search and lots of talking with the <a href="http://en.wikipedia.org/wiki/Internet">Drunken Librarian</a>, the solution finally came to me. And, guess what? It was implemented as a <a href="">Perl</a>-based meta information database about music, named <a href="http://www.MusicBrainz.org">MusicBrainz</a>

<p>As I presume that not all my noble readers know about this useful tool.

<p>MusicBrainz describes himself as 

<blockquote>(...) a user-maintained community music metadatabase. Music metadata is information such as the artist name, the release title, and the list of tracks that appear on a release. MusicBrainz collects this information about recordings and makes it available to the public. The web site is the interface which allows the creation and maintenance of the data. All of the data in MusicBrainz is user contributed and user maintained.</blockquote>

<p>Well, definitions apart, MusicBrainz also have some impressive numbers associated with them: they hold information about 420,000 artists, and information about more than 630,000 releases of more than 250,000 albums. The community maintained by the service have thousands of active users, and hold a total of almost 7,000,000 editions since 2003 and answers to more than 500,000 queries a day from all over the world.

<p>I use the service for about one year, and it usually surprises me, knowing about all unexpected and rare music and authors that I would have a hard time identifying by myself. It's a great service, quite reliable, running for more or less 10 years, and one that I say proudly that <a href="http://musicbrainz.org/doc/Server">uses</a> <a href="http://www.perl.org/">Perl</a>.]]>
        
    </content>
</entry>

<entry>
    <title>About Steve Marvell</title>
    <link rel="alternate" type="text/html" href="http://proudtouseperl.com/2008/10/about-steve-marvell.html" />
    <id>tag:proudtouseperl.com,2008://2.14</id>

    <published>2008-10-28T15:57:00Z</published>
    <updated>2008-10-28T16:23:42Z</updated>

    <summary>My name&apos;s Steve Marvell and I&apos;m Proud to Use Perl.I remember a day in the final term of University, some 13 years ago, when I asked a good friend of mine what I should learn next. He said &quot;Learn Perl...</summary>
    <author>
        <name>Steve Marvell</name>
        
    </author>
    
        <category term="admin" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="about" label="about" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="colophon" label="colophon" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://proudtouseperl.com/">
        <![CDATA[My name's Steve Marvell and I'm Proud to Use Perl.<br /><br />I remember a day in the final term of University, some 13 years ago, when I asked a good friend of mine what I should learn next. He said "Learn Perl Steve" and so I did. This would have been around the time that Perl 5 came out. I learnt it with a pocket guide, at work and did some quite exciting things with next to no code. I was hooked.<br /><br />Since then, I've worked pretty much exclusively with Perl for all manner of projects including Information Retrieval, Fraud Detection and Statistical Genetics. I presently run a small software engineering company which works almost exclusively with Perl. <br /><br />I have been an on and off user of Perl Monks and started the Devon and Cornwall Perl Mongers user group which is pretty tiny, to say the least.<br /><br />I've done quite a bit of book reviewing for O'Reilly and Manning and have an extra special mention in O'Reilly's Perl Graphics Programming, which I'm very proud of. <br /><br /><br /> ]]>
        
    </content>
</entry>

<entry>
    <title>¡Hola!</title>
    <link rel="alternate" type="text/html" href="http://proudtouseperl.com/2008/10/hola.html" />
    <id>tag:proudtouseperl.com,2008://2.13</id>

    <published>2008-10-24T23:36:29Z</published>
    <updated>2008-10-28T16:49:34Z</updated>

    <summary><![CDATA[Let me introduce myself as Yet-Another-Author of PTUP. I'm Michael Peters (mpeters on irc and use.perl, wonko on CPAN). my $work == 'Plus Three'; my @interests = qw(&nbsp;&nbsp;&nbsp; qa-and-testing&nbsp;&nbsp;&nbsp; scaling-and-performance&nbsp;&nbsp;&nbsp; ui-design);my @tools = qw(&nbsp;&nbsp;&nbsp; CGI::Application&nbsp;&nbsp;&nbsp; mod_perl&nbsp;&nbsp;&nbsp; vim&nbsp;&nbsp;&nbsp; linux&nbsp;&nbsp;&nbsp; MySQL&nbsp;&nbsp;&nbsp; Prototype&nbsp;&nbsp;&nbsp;...]]></summary>
    <author>
        <name>Michael Peters</name>
        
    </author>
    
        <category term="tech" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="about" label="about" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="colophon" label="colophon" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://proudtouseperl.com/">
        <![CDATA[Let me introduce myself as Yet-Another-Author of PTUP. I'm Michael Peters (mpeters on irc and use.perl, <a href="http://search.cpan.org/%7Ewonko/">wonko</a> on CPAN). <br />

<code><br />my $work == '<a href="http://plusthree.com/">Plus Three'</a>; <br />my @interests = qw(<br />&nbsp;&nbsp;&nbsp; qa-and-testing<br />&nbsp;&nbsp;&nbsp; scaling-and-performance<br />&nbsp;&nbsp;&nbsp; ui-design<br />);<br />my @tools = qw(<br />&nbsp;&nbsp;&nbsp; CGI::Application<br />&nbsp;&nbsp;&nbsp; mod_perl<br />&nbsp;&nbsp;&nbsp; vim<br />&nbsp;&nbsp;&nbsp; linux<br />&nbsp;&nbsp;&nbsp; MySQL<br />&nbsp;&nbsp;&nbsp; Prototype<br />&nbsp;&nbsp;&nbsp; jQuery<br />&nbsp;&nbsp;&nbsp; swish-e<br />&nbsp;&nbsp;&nbsp; spread<br />);<br /><br />my @projects = qw(<br />&nbsp;&nbsp;&nbsp; <a href="http://sourceforge.net/projects/smolder">Smolder</a><br />&nbsp;&nbsp;&nbsp; <a href="http://krangcms.com/">Krang</a><br />);</code><br /><br />I've lived and worked in Tennesee, Maryland (DC suburbs) and am now living with my family in Raleigh, NC. I've spoken at lots of YAPC::NAs (2008, 2007, 2006, 2005), a couple of ApacheCon's (US 2006, EU 2006) an OSCON (2007) and a PPW (2006). At my current job I do a little bit of management, technical planning, programming and system design.<br /><br />The name of this blog gives the impression that it might be all about Perl evangelism. I'm not a good evangelist (even though I spent 2 years as a missionary) so I probably won't be providing a lot zingers to convince your coworkers to use Perl. I'm just planning on writing about how I'm using Perl: module reviews, Perl related tools and other things happening in the Perl community that make me excited.<br /><br />Perl's not the coolest language around right now, but I've always been more of a fan of the underdog. I'm also an optimist which means that I'm really excited about the potential of Perl 6 and Parrot, so I'll probably be talking about those too. <br />]]>
        
    </content>
</entry>

<entry>
    <title>Perl &amp; JavaScript</title>
    <link rel="alternate" type="text/html" href="http://proudtouseperl.com/2008/10/perl-javascript.html" />
    <id>tag:proudtouseperl.com,2008://2.12</id>

    <published>2008-10-21T20:55:20Z</published>
    <updated>2008-10-21T21:28:30Z</updated>

    <summary>While I didn&apos;t promise frequent posts, I want to keep the chatter alive on the site. Unfortunately, this post has very little to do w/ Perl, but it&apos;s not an anti-Perl post, either. I&apos;m furiously at work on a paper...</summary>
    <author>
        <name>Jason Purdy</name>
        <uri>http://www.qsrmagazine.com</uri>
    </author>
    
    <category term="ajax" label="ajax" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="conference" label="conference" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="javascript" label="javascript" 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" xml:base="http://proudtouseperl.com/">
        <![CDATA[While I didn't promise frequent posts, I want to keep the chatter alive on the site. Unfortunately, this post has very little to do w/ Perl, but it's not an anti-Perl post, either. I'm furiously at work on a paper for the <a href="http://createordie.de/ajaxinaction/">Ajax in Action conference</a> next week, where <a href="http://createordie.de/ajaxinaction/session-tracks/?tid=960#session-1">I'll be presenting</a> selection criteria for JavaScript frameworks/libraries.<br /><br />When you're a Perl Web developer, there comes a time when you have to start developing parts of your web application for the client. Unfortunately, <a href="http://en.wikipedia.org/wiki/PerlScript">PerlScript</a> never really took off and so we walk down the road to JavaScript. Thus, a dichotomy is formed for our development work. Libraries make that easy, safe and reliable ... and not to mention, save us a ton of work. This keeps the percentage of your head attuned to things Perl at a majority, too.<br /><br />When I return, I'll share slides and more thoughts. ;)<br /><br />Peace,<br /><br />Jason<br />]]>
        
    </content>
</entry>

<entry>
    <title>Proud to Use Movable Type</title>
    <link rel="alternate" type="text/html" href="http://proudtouseperl.com/2008/10/proud-to-use-movable-type.html" />
    <id>tag:proudtouseperl.com,2008://2.11</id>

    <published>2008-10-18T00:57:39Z</published>
    <updated>2008-11-05T17:41:02Z</updated>

    <summary><![CDATA[When Dave Cross asked me to write for the Proud to Use Perl, I was unsure if I&nbsp; would be able to. I'm not a native English speaker, and I couldn't think about what to write. The answer was right...]]></summary>
    <author>
        <name>Luis Motta Campos</name>
        <uri>http://search.cpan.org/~lmc/</uri>
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://proudtouseperl.com/">
        <![CDATA[When Dave Cross asked me to write for the Proud to Use Perl, I was unsure if I&nbsp; would be able to. I'm not a native English speaker, and I couldn't think about what to write. The answer was right in front of my eyes all the time: I could write about the Proud To Use Perl website itself. This website is Perl Powered, and I don't have words in any of the four languages I speak to express how proud I am for being part of it.<br /><br />Movable Type is an amazing piece of Open Source Software, licensed under the version 2 of the GPL. It's maintained by the nice people from Six Apart, with the help of a lot of Perl hackers with Perl skills and blog addiction.<br /><br />It fills in an important niche of Internet applications in the competitive and highly visible blogging software market. His good quality, easy-to-use, and flexibility makes it a good option for big and small bloggers. Least but bot last, it probably pays the bills for people from Six Apart, or they would have dropped it long ago.<br /><br />From the user perspective, it's easy to use, with a simple, intuitive and powerful interface. From the administrator point of view, it does The Right Thing(TM), supporting templates and static HTML generation (which scales <i>ad infinitum</i>) among other cool features.<br /><br />I am proud to say that <a href="http://proudtouseperl.org/">Proud To Use Perl</a> uses <a href="http://movabletype.org/">Movable Type</a>, a competitive, high-quality, useful, flexible, and economically viable Perl Application, and a great success among bloggers around the globe.<br /><br /> ]]>
        
    </content>
</entry>

<entry>
    <title>About Luis Motta Campos</title>
    <link rel="alternate" type="text/html" href="http://proudtouseperl.com/2008/10/about-luis-motta-campos.html" />
    <id>tag:proudtouseperl.com,2008://2.10</id>

    <published>2008-10-18T00:45:18Z</published>
    <updated>2008-10-28T16:45:48Z</updated>

    <summary> Following Dave Cross&apos; example, I suppose I should write something about who I am and what I know about Perl, the Mongers, and the other communities and tools associated with the language. I am a spanish software engineer born...</summary>
    <author>
        <name>Luis Motta Campos</name>
        <uri>http://search.cpan.org/~lmc/</uri>
    </author>
    
        <category term="admin" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="about" label="about" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="colophon" label="colophon" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://proudtouseperl.com/">
        <![CDATA[<p> Following <a href="http://proudtouseperl.com/2008/08/about-dave-cross.html">Dave Cross' example</a>, I suppose I should write something about who I am and what I know about Perl, the Mongers, and the other communities and tools associated with the language.</p>

<p>I am a spanish software engineer born in São Paulo, Brazil. I grew in the big city, where my first contact with the Internet and with Perl happened at the same time, around 1996, at the <a href="http://www.usp.br/">São Paulo State University</a>. I was fascinated by the regular expressions support Perl offered (much better than the clumsy <code>/usr/bin/awk</code> support, just to name an easy one), and learned fast. I've been working as a Perl programmer for a living since then, always combining it with my system administration skills.</p>

<p>I learned about the Perl Mongers and the Perl Mailing Lists in 2001, when I subscribed to the <a href="http://london.pm.org/">London Perl Mongers</a> and contacted Dave Cross, requesting him to help me out re-activating the <a href="http://sao-paulo.pm.org">São Paulo Perl Mongers</a> community (there was a website and a <a href="http://mail.pm.org/mailman/listinfo/saopaulo-pm">mailing list</a>, but no subscribers). </p>

<p>I moved to Lisbon after several years of leadership of the <a href="http://sao-paulo.pm.org">SPPMers</a> leaving a new leader and a group with almost a hundred subscribers there. In Lisbon, I joined the <a href="http://lisbon.pm.org">Lisbon Perl Mongers</a>. After a while, personal reasons drove me out to the Netherlands, where I joined the <a href="http://amsterdam.pm.org/">Amsterdam Perl Mongers</a>, a highly technical and skilled PM group.</p>

<p>Since the beginning I admired the work and effort of the London Perl Mongers, and made them my model. And I am proud of it, and became even more proud when Dave Cross invited me to write on this blog. I hope proving myself worthy of this honor and privilege. </p>]]>
        
    </content>
</entry>

<entry>
    <title>my $first_post = &apos;Hello World&apos;</title>
    <link rel="alternate" type="text/html" href="http://proudtouseperl.com/2008/10/my-first-post-hello-world.html" />
    <id>tag:proudtouseperl.com,2008://2.9</id>

    <published>2008-10-16T13:37:23Z</published>
    <updated>2008-10-16T15:35:48Z</updated>

    <summary>Hello! My name is Jason Purdy and I&apos;m Proud to Use Perl ...[chorus: Hello, Jason]Honestly, sometimes you feel like part of a support group or a 12-step program when you tell others that you program in Perl. Earlier in the...</summary>
    <author>
        <name>Jason Purdy</name>
        <uri>http://www.qsrmagazine.com</uri>
    </author>
    
        <category term="tech" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://proudtouseperl.com/">
        <![CDATA[Hello! My name is Jason Purdy and I'm <b>Proud to Use Perl</b> ...<br /><br /><i>[chorus: Hello, Jason]</i><br /><br />Honestly, sometimes you feel like part of a support group or a 12-step program when you tell others that you program in Perl. Earlier in the year, I went to a <a href="http://ruby.meetup.com/3/">local Ruby group meetup</a> because they had a great program where an evangelist from Amazon came to present on their <a href="http://aws.amazon.com/">AWS</a> and perhaps they had an abnormal turnout because of the program, but they easily had 3-4 times as many folks as our own <a href="http://raleigh.pm.org/">local PM group</a> meetings.<br /><br />Now I'm not going to dig up graphs or charts or jobs-wanted numbers to justify anything ... I'll save that for later or for others. Rather, I shove all that aside and proudly say I use Perl.<br /><br />Now part of the mission of this blog/site, as I understand it, is to provide a place for proud Perl voices to be heard and for writing about amazing things that Perl can be proud of.<br /><br />So over my next few posts, I'll highlight several projects that we've done at work, where Perl has made them happen. I'm proud to use Perl for them and I hope Perl is proud of the results.<br /><br />Peace,<br /><br />Jason<br /> ]]>
        
    </content>
</entry>

<entry>
    <title>Proud To Use Perl Talk at YAPC::Europe</title>
    <link rel="alternate" type="text/html" href="http://proudtouseperl.com/2008/08/proud-to-use-perl-talk-at-yapceurope.html" />
    <id>tag:proudtouseperl.com,2008://2.8</id>

    <published>2008-08-15T04:59:59Z</published>
    <updated>2008-08-16T09:31:41Z</updated>

    <summary>In about two and a half hours time, I&apos;ll be giving my Proud To Use Perl talk at YAPC::Europe. During that talk, I&apos;ll be announcing the existence of this web site. So it you&apos;re visiting the site because I&apos;ve just...</summary>
    <author>
        <name>Dave Cross</name>
        
    </author>
    
        <category term="admin" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="slides" label="slides" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="talk" label="talk" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="welcome" label="welcome" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="yapc" label="yapc" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://proudtouseperl.com/">
        <![CDATA[In about two and a half hours time, I'll be giving my <a href="http://www.yapceurope2008.org/ye2008/talk/1175">Proud To Use Perl</a> talk at YAPC::Europe. During that talk, I'll be announcing the existence of this web site. So it you're visiting the site because I've just mentioned it in my talk (which is, perhaps, unlikely given the quality of the wireless network at the conference!), then hello and thanks for visiting.<br /><br />The slides to my talk will be available on <a href="http://www.slideshare.net/davorg/slideshows">my Slideshare account</a> later today.<br />]]>
        
    </content>
</entry>

<entry>
    <title>perl.org</title>
    <link rel="alternate" type="text/html" href="http://proudtouseperl.com/2008/08/perlorg.html" />
    <id>tag:proudtouseperl.com,2008://2.7</id>

    <published>2008-08-10T14:09:39Z</published>
    <updated>2008-11-03T16:13:52Z</updated>

    <summary>The perl.org infrastructure is incredible. Ok, so not all of the subdomains of perl.org are hosted on the same servers, some of them are just DNS redirections, but they still run a large number of web sites there. It&apos;s not...</summary>
    <author>
        <name>Dave Cross</name>
        
    </author>
    
        <category term="tech" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="infrastructure" label="infrastructure" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="mail" label="mail" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perlorg" label="perl.org" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="tech" label="tech" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="web" label="web" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://proudtouseperl.com/">
        <![CDATA[The <a href="http://perl.org/">perl.org</a> infrastructure is incredible. Ok, so not all of the subdomains of perl.org are hosted on the same servers, some of them are just DNS redirections, but they still run a large number of web sites there. It's not just web sites either, a large (and I mean <i>large</i>) number of Perl mailing lists are run on their servers. And that means they handle a lot of spam. They also run many of the sites under <a href="http://pm.org/">pm.org</a> and <a href="http://cpan.org/">cpan.org</a>. You can get a good idea of what is involved from the <a href="http://noc.perl.org/">NOC page</a> on the site. It's an impressive list.<br /><br />But the most amazing thing about the perl.org team is that they are volunteers. Both Robert and Ask have real jobs in addition to keeping the Perl infrastructure servers running. They have a small team that help them out with some of the work, but no-one gets paid for it. The hardware is all donated by sponsors too. If you have any hardware that a large network operations centre might be interested in then please take a look at their <a href="http://www.perl.org/wishlist.html">wishlist</a>.<br /><br />So each time you visit a Perl web site or use a Perl mailing list, spare a thought for the volunteers who keep it all running.<br /><br />Yet another good reason to be proud to use Perl.<br /><br />You can keep up to date with what is going on with the perl.org by reading their <a href="http://log.perl.org/">NOC blog</a>.<br />]]>
        
    </content>
</entry>

<entry>
    <title>Perl Monks</title>
    <link rel="alternate" type="text/html" href="http://proudtouseperl.com/2008/08/perl-monks.html" />
    <id>tag:proudtouseperl.com,2008://2.6</id>

    <published>2008-08-07T12:36:44Z</published>
    <updated>2008-11-03T16:15:27Z</updated>

    <summary>My experience of web-based language support forums has been patchy to say the least. Often they seem to be a &quot;blind leading the blind&quot; kind of place with uninformed people helping each other to find sub-optimal solutions. I&apos;m not suggesting...</summary>
    <author>
        <name>Dave Cross</name>
        
    </author>
    
        <category term="tech" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="advice" label="advice" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="community" label="community" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="help" label="help" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perlmonks" label="perlmonks" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="tech" label="tech" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="web" label="web" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://proudtouseperl.com/">
        <![CDATA[My experience of web-based language support forums has been patchy to say the least. Often they seem to be a "blind leading the blind" kind of place with uninformed people helping each other to find sub-optimal solutions. I'm not suggesting for a second that Perl is immune to this phenomenon. I've seen many Perl sites that conform completely to this model.<br /><br />So what it is that makes <a href="http://perlmonks.org/">Perl Monks</a> so different? The big difference has to be the quality of the programmers who visit the site. At any time of the day or night you'll find expert Perl programmers there who will be happy to help you with your problem. You can be sure that most of the advice you get from Perl Monks will be of top quality.<br /><br />"Most of the advice"? Yes. Of course there will be times when you get advice that isn't quite as good as it could be. And that's where Perl Monks' other advantage comes into play. Perl Monks has good feedback in the form of its voting system. If you see a good question or answer on the site then you can give it a positive vote. If you see a bad question or answer then you can give it a negative vote. Voting for or against an entry also has a change of effecting the reputation of the author of that node. People who consistently give good answers will rise to the top of the <a href="http://perlmonks.org/?node=Saints%20in%20our%20Book">league table</a> so it becomes easy to know whose answers to trust.<br /><br />Perl Monks is also one of the friendliest forums that I know. There are occasional arguments in the chatterbox, but most of the time it's a pleasure to be there. I think this was an ethos which was imposed by <a href="http://perlmonks.org/?node=vroom">Tim Vroom</a> (the original creator of the site) and which is now so deeply ingrained into the site that anyone who disturbs this peaceful and friendly atmosphere won't last very long on the site.<br /><br />So you've got friendly experts who will happily answer your Perl questions in something like real time. I can't see any downsides there at all.<br /><br />It's a site that makes me proud to use Perl.<br />]]>
        
    </content>
</entry>

</feed>
