Slash Boxes
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

wickline (135)

  (email not shown publicly)

Journal of wickline (135)

Tuesday September 17, 2002
01:02 PM

How to get spam without even trying.

Sometimes folks ask why I don't want to be forwarded jokes unless I'm on BCC. ...or they ask why I use such funny email addresses. I end up explaining this frequently, so I thought I would put it in the journal.

This was prompted by Matt's observation that many hotmail users complain about getting spam even though they never give out their email address.

If you truely never give the email addie out (ie: never use the account to send mail or give it to anyone any other way), then you probalby won't get spam unless your username can be guessed. (Brute force username guesses against SMTP hosts are on the rise.)

However, if you phone your girlfriend and give her the address the day it was assigned to you, then you might never log in to the account at all and find out when you do so for the first time a year later that it is full of spam.

Suppose your girlfriend sent you only one message once she had your address.

She sent this hillarious story about a kitten which she knew you would appreicate. She also include her co-worker in the recipient list.

That co-worker had a great laugh, and forwarded it to five friends who like to share 'funny stuff' via email. One of those friends is on a mailing list where folks exchange 'funny stuff'. That friend forwards the message to the list.

Now, if these folks all just hit the forward button, then all of the original recpients' addresses are included in this post to the mailing list.

That list may have an address harvester subscribed.

That list may be accessible via NNTP where havesters lurk in abundance.

That list may be archived on the web, where harvesters are probably more common than on usenet these days.

Subscribers to the list may re-foward, further increasing chances of exposure.

It is possible that by telling your girlfriend your email address, you allowed that address to be exposed to spammers. ...and once exposed, it's probably doomed. Spammers are an incestuous lot who constantly buy one anothers' lists, combine them and try to sell the new larger list for more money. I'm sure you've had plenty of spam trying to sell you email addresses, right? Once you get on one list, you have decent odds of being on oodles of lists.

If you use an address, it may get spam through no fault of your own. You can try to educate folks to use BCC when sending that kind of content (and don't send it yourself). ...but the problem is that you just don't have control.

The only certain solution is to never use or advertise your email address.

A decent second-best is to use an infinite number of addresses. Try to use addresses specific to each contact/occasion/date/etc so that if the address ever gets spam, you can route it to the big bit bucket.

An interesting example: I once sent mail to Simon Cozens which he forwarded to a perl list. That address started getting spam, and in addition related addresses started getting spam, revealing a bug in some common spam address-processing software I suppose:

This series came from part of a Message-ID header:


None of the above addresses will get to me... they all get auto-trashed because they've been tainted and now receive spam. I could claim that I never used that simon_cozens address but the truth is that I did use it. One time. Now it gets spam. (and so do some releated addresses!)

When hotmail users say they never give out their address, I bet that they've at least used it once.


Wednesday August 14, 2002
02:59 PM

horray for vacation!

Checking work email from home tomorrow, but not doing any real work... just kicking back and relaxing.

Friday will be some house cleaning so we can come back to a tidy nest (and so our friends won't see how we really live when they drop by to care for our cats ;) and packing.

Saturday we're flying to PDX, meeting up with friends who are also flying in, then driving up to spend some time with my mom, then further up to the Olympic National Forest.

Peace and friends and green and trees and sensible temperatures and no appreciable humidity and no work.



Sunday August 11, 2002
07:35 PM

my second-least favorite experience on the 'net long as I'm thinking about icky things...

Within a year of the sig-changing incident, some spammer used one of my addresses in the From header of their mail. The address was one of those 'free for life' ones and forwarded to my less-permanent school-provided address.

I won't mention the provider of that address, as they may have cleaned up their act since then.

I discovered a gazillion bounce messages in my inbox one day, some of which included the bounced message... which was spam. My address was in the From header. I also discovered a large volume of venomous hate mail from folks who had received the spam. While I felt bad for them, I was feeling worse for myself.

A few days later, I got a message directly to my school account from someone who had been unable to reach me at my 'permanent' address. It turns out that my account was closed. When I contacted support, they said that sending spam was in violation of the terms of use, and that they couldn't re-open the account. I provided them with instructions for the trivial From header forgery and they admitted that they hadn't done any investigation beyond looking at the From header... but they still wouldn't re-open the account.

At that point, I was happy to leave them. Sucky service sucks.

This was years ago. Hopefully they've invested in clues since then.


07:08 PM

my least favorite experience on the 'net

Until 1995 or 1996 (I forget the date, but I remember where I was living at the time) I had all sorts of information in my .sig file. The more useful info was name/phone/address.

I thought phone number and address (mailing address, that is) were useful because folks would have a convenient way to find my phone number if they needed to call me, or my address if they needed to mail me something. This was before everyone was carrying PDAs in their pockets, and the sig info had come in handy for folks in the past. ...and I didn't think it could do any harm.

I was wrong. :(

One afternoon I got a phone call from some woman about some conversation she thought we had had in a white supremacist irc channel the evening prior.

If there's a group for which I have a prejudiced and unreasoned hatred, it's bigots. That may well make me a bigot myself, but I am not a white supremacist.

I was too upset to remember the details of our brief conversation, but the gist was she was sure she had the right person because she had the right combination of name, phone number and address. I was just as sure she had the wrong person.

Minutes after our phone conversation, my .sig was void of any 'useful' information.

The Internet lost some of its charm for me on that day. I don't suppose it actually was any different, but I sure learned to look at it through less-rosy glasses. :/


Thursday August 08, 2002
09:46 PM

So what's this button do, I wonder?

Everyone loves mysterious switches, right?

If you scroll down to the bottom of this page, there's a Misc link. Click the link and you'll arrive at a Miscellaneous Options screen. That screen has a Save button.

Click the button and you'll be informed that "Option(s) Changed."

So, if you don't like the options life hands you, visit, eh?

Acutally, I didn't notice my options changing. Maybe I changed someone else's options? "Sorry" or "Your welcome", as appropriate.


Wednesday August 07, 2002
07:09 PM

Holy vanity, Batman!

Every several months or so, I type my name in a couple of variations
into google.

Why? Well, the first time I did it was after my natural father had found
me via the internet. I wanted to see just how easy it was to find me. I
wasn't trying to be hidden, or to be visible... I was just curious. So,
I typed in a handful of variations of my name in a few search engines.
This was in the pre-google days, and the altavista advanced search was
my favored search engine (back when altavista wasn't just another web

Every several months it occurs to me to repeat the excersize. I don't
really have any good reason for it. I'm not looking to see if I've been
keeping a low enough profile to be unobserved and I'm not looking to see
if I'm famous. I'm just wasting time basically. People do that at times,
ya know? I don't try all the search engines anymore, just google. ...but
I still try a few variations of my name. I've found that there are a few
folks with my first and last name who are somewhat famous. I'm not one
of them. There are also a few less famous folks with my name. I've had
email from three strangers asking if I was their long lost relative or
high school classmate. I'm not.

Today I googled for 'wickline'. It's my last name, and I'd expected to
see oodles of strangers and an occasional relative. I did *not* expect
to see something of mine in the #3 spot! ...but that's what I found!

As I type this,
has as the third hit

Given the way google's page-rank system works, I'm interpreting that
result to indicate that this year's YAPC was more important than just
about anything wickline-related. YAPC beats out every wickline in the
world but two!

Bravo! Way to go YAPC! :)

On google images, there's a couple of nude women. I think you can
search for just about anything and find porn.

On google groups, strangers and relatives.

On google directory we find that is more important than
any wickline entry in (source data for google directory). My
name just happened to be on (because of that yapc post)
on the day it was last indexed by google, so as I type this, the u.p.o
page comes up on a search for wickline... and because u.p.o is better
ranked than any wickline-related page, it comes up first.

And if wasting time at google wasn't enough, I'm now wasting time here
talking about my waste of time.

What a waste of time. :) I think I need to get some sleep...

Tuesday August 06, 2002
10:19 AM

mozilla custom keyword queries on steriods

Do you use mozilla?

Do you use keywords?

Do you use custom keyword queries?

Do you want your custom keyword queries to
    - relace *all* instances of the token in your URI template?
    - allow multiple arguments to be place in multiple places?
    - allow some args to be url-encoded, but not others?

Then you want to take this perl code as a starting point for your own
CGI script or Apache module. Then set up a custom keyword to call that
script or module and you're home free (modulus one HTTP transaction per

See also

This code predates the above, but miyagawa's posting reminded me
that other folks might find use for it...

I'm m_mozilla, so feel free to copy/adapt/whatever this code to
your heart's desire.

    Slash wraped the long URLs.
    The tests won't work until you unwrap them.


#!/usr/bin/perl -w
$::verbose = 0; # turn on to enable verbose testing (to STDOUT)
use strict;
print "testing...\n";
print "testing complete.\n";
sub build_uri ($$) { # Q=plain, q=encode
    my( $uri_t, $query ) = @_;
    return undef unless defined $uri_t;
    return $uri_t unless $uri_t =~ m/%[qQ]\d*;/;
    return &empty_tokens( $uri_t )
        unless ( defined $query and $query =~ /\S/ );
    $uri_t =~ s/%([qQ])0*(\d+);/%$1$2;/g;
    $query =~ s/^\s+|\s+$//g;
    my @terms = split( /\s+/, $query);
    my @numeric_tokens = sort { $a <=> $b } (  keys %{{
        map  { $_ => 1 }  ( $uri_t =~ m/%[qQ](\d+);/g )
    }}); # <=> sorted uniq numbers from %[qQ](\d+); tokens
    while ( @terms and @numeric_tokens ) {
        my $term = shift @terms;
        my $token = shift @numeric_tokens;
        $uri_t =~ s{%([qQ])$token;}{  $1 eq 'Q'
            ?  $term  :  &uri_encode( $term )
    } # now we're out of @terms and/or @numeric_tokens
    return &empty_tokens( $uri_t ) unless @terms;
    return $uri_t unless $uri_t =~ m/%[qQ]\d*;/;
    $uri_t =~ s{%([qQ]);}{  $1 eq 'Q'
        ?               join( '+', @terms )
        :  uri_encode(  join( ' ', @terms )  )
    return $uri_t;
sub empty_tokens ($) {
    local $_ = shift; s/%[qQ]\d*;//g; return $_;
sub uri_encode {
    return undef unless $_[0];
    my $txt = shift;
    # use a real look-up table in mozilla; faster than this:
    $txt =~ s/([^a-zA-Z0-9~._\-])/$1 eq' '?'+':sprintf("%%%02X",ord($1))/ge;
    return $txt;
sub test_uri_template_code {
    # keywords containing '_x_' have malformed URI templates, and
    # the test results will need to not treat bad tokens as tokens
    %::keywords2templates = qw{
        a_x_4             ;
        a_x_7             ;
        a_x_8             ;
        a_x_9             $q
        a_x_10            ^%1$q
        isbninfo          ;
        isbnbuy           ;
        isbnbuy_1         ;
        isbnbuy_2         ;
        isbnbuy_3         ;
        isbnbuy_4         ;
        isbnbuy_5         ;
        isbnbuy_6         ;
        isbnbuy_7         ;
        chart             ;&symbols=%q2;
        chart_1           ;&symbols=%q025;
        chart_2           ;&symbols=%q;
        chart_x_1         ;&symbols=%q;
        chart_x_2         ;&symbols=%0q;
        chart_reverse     ;&symbols=%q1;
        chart_reverse_1   ;&symbols=%q000;
        chart_reverse_2   ;&symbols=%q0;
        bughunt            ug_status=ASSIGNED&bug_status=REOPENED&field0-0-0=product&type0-0-0=substring&va lue0-0-0=%q;&field0-0-1=component&type0-0-1=substring&value0-0-1=%q;&field0-0-2= short_desc&type0-0-2=substring&value0-0-2=%q;&field0-0-3=status_whiteboard&type0 -0-3=substring&value0-0-3=%q;
        bughunt_first_term_only ug_status=ASSIGNED&bug_status=REOPENED&field0-0-0=product&type0-0-0=substring&va lue0-0-0=%q0;&field0-0-1=component&type0-0-1=substring&value0-0-1=%q0;&field0-0- 2=short_desc&type0-0-2=substring&value0-0-2=%q0;&field0-0-3=status_whiteboard&ty pe0-0-3=substring&value0-0-3=%q0;
        bughunt_ordered_terms ug_status=ASSIGNED&bug_status=REOPENED&field0-0-0=product&type0-0-0=substring&va lue0-0-0=%q0;&field0-0-1=component&type0-0-1=substring&value0-0-1=%q1;&field0-0- 2=short_desc&type0-0-2=substring&value0-0-2=%q2;&field0-0-3=status_whiteboard&ty pe0-0-3=substring&value0-0-3=%q3;
        owner_a_bughunt_queryb g_status=ASSIGNED&bug_status=REOPENED&field0-0-0=product&type0-0-0=substring&val ue0-0-0=%q;&field0-0-1=component&type0-0-1=substring&value0-0-1=%q;&field0-0-2=s hort_desc&type0-0-2=substring&value0-0-2=%q;&field0-0-3=status_whiteboard&type0- 0-3=substring&value0-0-3=%q;&email1=%q0;&emailtype1=exact&emailassigned_to1=1
        reporter_a_bughunt_queryb ug_status=ASSIGNED&bug_status=REOPENED&field0-0-0=product&type0-0-0=substring&va lue0-0-0=%q;&field0-0-1=component&type0-0-1=substring&value0-0-1=%q;&field0-0-2= short_desc&type0-0-2=substring&value0-0-2=%q;&field0-0-3=status_whiteboard&type0 -0-3=substring&value0-0-3=%q;&email1=%q0;&emailtype1=exact&emailreporter1=1
        anyemail_a_bughunt_queryb ug_status=ASSIGNED&bug_status=REOPENED&field0-0-0=product&type0-0-0=substring&va lue0-0-0=%q;&field0-0-1=component&type0-0-1=substring&value0-0-1=%q;&field0-0-2= short_desc&type0-0-2=substring&value0-0-2=%q;&field0-0-3=status_whiteboard&type0 -0-3=substring&value0-0-3=%q;&email1=%q0;&emailtype1=exact&emailassigned_to1=1&e mailreporter1=1&emailqa_contact1=1&emailcc1=1&emaillongdesc1=1
        val_mozilla_page  ;
        drivefromhome_to_a %Q1;&tarcsz=%q2;
        drivefrom_a_to_b  ;&newcsz=%q2;&taraddr=%Q3;&tarc sz=%q4;
        trans_parturl_a_from_b_2c;%2F%q3;&Url=%q1;&Sequence=c ore
        trans_parturl_a_from_b_2c_1;%2F%q33;&Url=%q11;&Sequence =core
        trans_parturl_a_from_b_2c_2;%2F%q033;&Url=%q000011;& Sequence=core
        trans_parturl_a_from_b_2c_3;%2F%q;&Url=%q0;&Sequence =core
        trans_from_a_2b_parturl_c;%2F%q2;&Url=%q3;&Sequence=c ore
    my %canonical_testcases = (
        # for each testcase, [q{query string}, q{expected resuting URI}]
        'a' => [
              [ q{doesn't matter what args you put here, they should all be ignored},
        'isbninfo' => [
              [ q{0596000529},
            ],[ q{0596000529 additional args ignored. Book title is Creating Applications with Mozilla},
            ],[ q{    0596000529 initial whitespace also ignored},
        'isbnbuy' => [
              [ q{0764545884},
            ],[ q{0764545884 additional args ignored. Book title is Mozilla Source Code Guide with CDROM},
        'chart' => [
              [ q{1mo aapl},
            ],[ q{3mo aapl},
            ],[ q{ytd aapl},
            ],[ q{2yr aapl},
            ],[ q{all aapl},
            ],[ q{ytd msft},
            ],[ q{    1mo    aapl    whitespace and extra args ignored},
        'chart_reverse' => [
              [ q{ aapl  1mo         like above, but for those who prefer reversed syntax},
        'bughunt' => [ # bonus: bug 98749 gets fixed too!
              [ q{custom keywords},
                q{ bug_status=ASSIGNED&bug_status=REOPENED&field0-0-0=product&type0-0-0=substring&v alue0-0-0=custom+keywords&field0-0-1=component&type0-0-1=substring&value0-0-1=cu stom+keywords&field0-0-2=short_desc&type0-0-2=substring&value0-0-2=custom+keywor ds&field0-0-3=status_whiteboard&type0-0-3=substring&value0-0-3=custom+keywords},
            ],[ q{not suck},
                q{ bug_status=ASSIGNED&bug_status=REOPENED&field0-0-0=product&type0-0-0=substring&v alue0-0-0=not+suck&field0-0-1=component&type0-0-1=substring&value0-0-1=not+suck& field0-0-2=short_desc&type0-0-2=substring&value0-0-2=not+suck&field0-0-3=status_ whiteboard&type0-0-3=substring&value0-0-3=not+suck},
        'bughunt_first_term_only' => [
              [ q{tabs     and additional args are ignored},
                q{ bug_status=ASSIGNED&bug_status=REOPENED&field0-0-0=product&type0-0-0=substring&v alue0-0-0=tabs&field0-0-1=component&type0-0-1=substring&value0-0-1=tabs&field0-0 -2=short_desc&type0-0-2=substring&value0-0-2=tabs&field0-0-3=status_whiteboard&t ype0-0-3=substring&value0-0-3=tabs},
        'owner_a_bughunt_queryb' => [
              [ q{  custom keywords},
                q{ bug_status=ASSIGNED&bug_status=REOPENED&field0-0-0=product&type0-0-0=substring&v alue0-0-0=custom+keywords&field0-0-1=component&type0-0-1=substring&value0-0-1=cu stom+keywords&field0-0-2=short_desc&type0-0-2=substring&value0-0-2=custom+keywor ds&field0-0-3=status_whiteboard&type0-0-3=substring&value0-0-3=custom+keywords&e},
            ],[ q{  white-space: pre},
                q{ bug_status=ASSIGNED&bug_status=REOPENED&field0-0-0=product&type0-0-0=substring&v alue0-0-0=white-space%3A+pre&field0-0-1=component&type0-0-1=substring&value0-0-1 =white-space%3A+pre&field0-0-2=short_desc&type0-0-2=substring&value0-0-2=white-s pace%3A+pre&field0-0-3=status_whiteboard&type0-0-3=substring&value0-0-3=white-sp ace%3A+pre&},
        'reporter_a_bughunt_queryb' => [
              [ q{  crash causes},
                q{ bug_status=ASSIGNED&bug_status=REOPENED&field0-0-0=product&type0-0-0=substring&v alue0-0-0=crash+causes&field0-0-1=component&type0-0-1=substring&value0-0-1=crash +causes&field0-0-2=short_desc&type0-0-2=substring&value0-0-2=crash+causes&field0 -0-3=status_whiteboard&type0-0-3=substring&value0-0-3=crash+causes&email1=asa%40},
        'anyemail_a_bughunt_queryb' => [
              [ q{  tooltip},
                q{ bug_status=ASSIGNED&bug_status=REOPENED&field0-0-0=product&type0-0-0=substring&v alue0-0-0=tooltip&field0-0-1=component&type0-0-1=substring&value0-0-1=tooltip&fi eld0-0-2=short_desc&type0-0-2=substring&value0-0-2=tooltip&field0-0-3=status_whi teboard&type0-0-3=substring&value0-0-3=tooltip& ltype1=exact&emailassigned_to1=1&emailreporter1=1&emailqa_contact1=1&emailcc1=1& emaillongdesc1=1},
            ],[ q{}, # leaves normal query part empty, makes bugzilla work for very long time :/
                q{ bug_status=ASSIGNED&bug_status=REOPENED&field0-0-0=product&type0-0-0=substring&v alue0-0-0=&field0-0-1=component&type0-0-1=substring&value0-0-1=&field0-0-2=short _desc&type0-0-2=substring&value0-0-2=&field0-0-3=status_whiteboard&type0-0-3=sub string&value0-0-3=& o1=1&emailreporter1=1&emailqa_contact1=1&emailcc1=1&emaillongdesc1=1},
        'val_mozilla_page' => [
              [ q{mozorg.html},
            ],[ q{ports/fizzilla/Cocoazilla.html},
                q{ 2FCocoazilla.html},
        'val_mozilla_page_to_html_v' => [
              [ q{ports/fizzilla/Cocoazilla.html HTML 4.01 Strict},
                q{ 2FCocoazilla.html&doctype=HTML+4.01+Strict},
            ],[ q{ports/fizzilla/Cocoazilla.html XHTML 1.0 Transitional},
                q{ 2FCocoazilla.html&doctype=XHTML+1.0+Transitional},
        'drivefromhome_to_a' => [
              [ q{999+EndHere+Ave 56789},
                q{ r=999+EndHere+Ave&tarcsz=56789},
            ],[ q{666+Brimstone+Ave 00666},
                q{ r=666+Brimstone+Ave&tarcsz=00666},
        'drivefrom_a_to_b' => [
              [ q{111+StartHere+Blvd 12345  999+EndHere+Ave 56789},
                q{ taraddr=999+EndHere+Ave&tarcsz=56789},
            ],[ q{111+StartHere+Blvd 12345  999+EndHere+Ave 56789    all other args ignored},
                q{ taraddr=999+EndHere+Ave&tarcsz=56789},
        'trans_parturl_a_from_b_2c' => [
              [ q{ English Spanish},
                q{ org&Sequence=core},
            ],[ q{ English French},
                q{ rg&Sequence=core},
            ],[ q{ English German},
                q{ rg&Sequence=core},
            ],[ q{ English Italian},
                q{ org&Sequence=core},
            ],[ q{ English Norwegian},
            ],[ q{ English Portuguese},
            ],[ q{ Spanish English},
                q{ .com&Sequence=core},
            ],[ q{ German English},
                q{ com&Sequence=core},
        'trans_from_a_2b_parturl_c' => [
              [ q{German English},
                q{ com&Sequence=core},
            ],[ q{Spanish English},
                q{ .com&Sequence=core},
            ],[ q{English Italian},
                q{ org&Sequence=core},
            ],[ q{English French},
                q{ rg&Sequence=core},
    for my $keyword ( keys %canonical_testcases ) {
        for my $pair ( @{$canonical_testcases{$keyword}} ) {
            &report_on_keyword_with_input( $keyword, @$pair );
    my %additional_testcases = (
        # like above, but for catching bizarre bugs. As bugs come up,
        # fix them and add a relevant test case or two in here.
    for my $keyword ( keys %additional_testcases ) {
        for my $pair ( @{$additional_testcases{$keyword}} ) {
            &report_on_keyword_with_input( $keyword, @$pair );
sub report_on_keyword_with_input {
    my( $keyword, $query, $expected ) = @_;
    my $uri_t = $::keywords2templates{ $keyword };
    my $result = &build_uri( $uri_t, $query );
    if ( defined $result ) {
        my $ok = $result eq $expected;
        if ( $ok and $::verbose ) {
            print "... Correct URI when expanding:  $keyword $query\n";
        } elsif ( !$ok ) {
            print "!!! Unexpected URI when expanding:  $keyword $query\n";
            print "        looking for:  $expected\n";
            print "        but I found:  $result\n";
    } else {
        print "!!! Undefined URI when expanding:  $keyword $query\n";

Saturday August 03, 2002
12:21 PM

Editor holy war spills into unfamiliar terrain

Sure, we're all sick of editor wars. We've got our favorite tools, and
we're so much more familiar with them that we're more efficient using
those tools than any others.

If you've recently purchased a T?iBook (and it sounds like a great many
of you have), then you may be finding that your favorite editor doesn't
work quite as handily in MacOS X as you'd like. It just doesn't fit in
with your newly-raised user-interface expectations and doesn't use the
strengths of the operating system to your advantage.

If you're feeling a wee bit dissatisfied, try BBEdit. It is IMHO (and
in many other folks' HOs) the best editor available on any platform,
and is only available for the Mac. It not only uses the MacOS to your
advantage (applescriptable, recordable, and attachable, quicktime
integration, services), but also integrates well with perl, python,
assorted shell scripting (and lets you set your default shell).

I don't get any kickback for convincing folks to use BBEdit. I just
think that it's so much better than the alternatives that those of
you who haven't tried it are really doing yourselves a disservice.

I had my employer buy me a mac so that I could use BBEdit. I told them
that they'd get more than their money back in my increased productivity
and I wasn't kidding.

A brief laundry list of some of the features:

    World-class support. You contact them, and you get answers
        back from the folks who actually write the program.
        They also have very high quality mailing lists with
        very active particpation from the developers.

    best perl syntax coloring I've ever seen
        (yes, I've seen vim and emacs)
        also does a zillion other languages, but I don't care
        so much about those

    perl scripts and filters handily integrated
    as well as pod-reading, perldoc lookup, syntax checking,
    running the current file

    PCRE find/replace including multi-file search/replace
    with file filters to indicate which files to process

    menu of your perl subs (menu does headers and named
        anchors in HTML documents, similar handy things
        in other languages)

    user-configurable key bindings

    convenient edit via ftp
        also integrates well with other ftp clients

    worksheets (hybrid of text document and unix shell)

    find-differences and selectively apply changes in
    either direction

    handy DTD- and context-sensitive HTML markup tools

    integration with ToolServer, SourceServer, CodeWarrior,
    Dreamweaver Absoft Fortran, Mac OS X Developer Help,
    your favorite shell, your favorite AppleScript editor,
    your favorite everything.

    So many useful features that every time I re-read the
    manual, I find a new one which will benefit me.

If the above doesn't at least pique your curiosity, then maybe BBEdit isn't
for you. If you're interested, you can get a free 'crippleware' version of
the editor (BBEdit Lite) to get a little taste. The real thing is *so* much
better though.

Wednesday July 10, 2002
09:03 AM

dump of module version information

mako132 was looking for a way to get version info for
each module use'd by his script.

I replied with a ~20 line END block which should do the
trick. I thought I might find the code handy myself one
day, so I thought I'd stash it in my journal as well for
ease of finding. ((code at end of journal entry))

Maybe that's a use for this journal... post odd bits of
code that don't have any associated project, invite any
readers to critique/improve/ridicule said code, look at
code years in the future when I can better do the same
to it.

(still deciding what to do with this journal thing)

END { no strict 'refs';
    for my $k ( sort keys %INC ) {
        ( my $module = $k ) =~ s{[:/\\]}{::}g;
        $module =~ s{\.pm$}{};
        my $version = ${"${module}::VERSION"};
        if ( defined $version ) {
            $version = "\$${module}::VERSION = $version\n";
        } else { # maybe they didn't use ALLCAPS
            my @found = (
                map { defined ${"${module}::$_"}
                     ? qq(\$${module}::$_ = ${"${module}::$_"}) : ()
                grep { m/^version$/i }
                keys %{"${module}::"}
            $version = !@found
                ? "($module  version number not found)\n"
                : join( "\n", @found );
        # if you want, print this to a log file instead:
        print "$version $module  loaded from  $INC{$k}\n\n";
Monday July 01, 2002
04:57 PM

Wheeee! YAPC was fun!

(and so is this journal thing, or maybe it's just 'cause I'm a wee
bit punchy from lack of sleep... we'll find out in future days)

Highlights (Letterman style)

    #10 the weather could have been substantially worse (really!)
     #9 being paid to have nothing but fun for three days
     #8 finding little ways to pitch in with assistance
     #7 seeing more women (I think) than at YAPC::NA 2001
     #6 laughing my ass off (especially allison's & gnat's l.Talks)
     #5 being local so I didn't have to miss Laura for a week
     #4 seeing some interesting ideas in code (YAML, abigail's OO)
     #3 seeing the perl community *qua* community
     #2 catching up with folks from far places
     #1 meeting neat new people (Riley would have to be the most new)
     #0 great company every day and evening, Wed though Sat!


    #4 gnat's 'something something' eleventh-hour slot-filler
       turned out to be something else at the last minute. I
       have yet to see him speak, and was looking forward to
       whatever 'something something' might have been. Next time.
       Silver lining: even though I still didn't get to see him
       speak for his l.Talk, the movie was fucking hillarious.

    #3 MJD wasn't quite his usual animated and focused self
       when giving his red flags talk on Friday morning.
       Silver lining: in reading the slides (half of the YAPC
       proceedings!) I found a flag I need to watch myself.
       I can think of a few scripts where I do the icky
           if (...) {
               if (...) {
                   if (...) {
                       # ...
                   } else { ... } # tertiary error
               } else { ... }    # secondary error
           } else { ... }       # my initial error
       insted of using breaks or carting it all off into a
       sub where I can use 'condition or return' statements.

    #2 I'd hoped for more perl code in T::S::C
       but it's all hidden to avoid spoiling the effect.
       Silver lining: maybe I'll start playing with source
       filtering to figure it out myself.

    #1 I could only be in one room at a time. Silver lining:
       I'm looking forward to seeing more recorded sessions
       show up on the web as folks get settled in and have
       time to process their recordings.

Of course not every cloud has a silver lining...

    #0 YAPC was over far too quickly :(

Biggest Bummer of them all:
    I think I might have to miss YAPC next year. We'll be
    moving to Portland, OR around YAPC season, and so not
    only will the budget be leaner, but time will be more
    precious (and likely spent job-hunting). Sigh...