Cookie Notice

As far as I know, and as far as I remember, nothing in this page does anything with Cookies.

2010/02/24

Good Ideas: Never Again File, or "When You Play It, Say It"

Saw this on Lifehacker: As a means to remember/look up past mistakes in order to avoid them, create a "Never Again" folder. If there's something you've done that you want to remember to avoid, or that someone warned you about, put it in there. And, of course, when you're going to do something, look up or remember it.

I like that. This blog is largely about that. When there's a yay, I post it. When there's a never-again, I post that too. Such as, if you have a data directory on a machine you're going to be reinstalling upon: 
  • back up everything of value 
  • make sure you have the format-this flag unset
  • back up everything of value
  • make sure you have the format-this flag unset
  • make sure you have the format-this flag unset
  • make sure you have the format-this flag unset
(Yeah, that one still burns a little.) Back in the day before radio and record stores had to be replaced by the Internet because they started to suck, you'd see used review copies of CDs, and they'd have a sticker that said if you play it, say it. This is something I try to do here. If I try something and it works, I tell everyone that it is a good thing. If I try something and it doesn't work, I tell everyone that it's a bad thing, or at least something you have to work to make good. The only way experience outlasts us, the only way that humanity makes progress, is if we allow ourselves to learn from the experiences of others.

2010/02/23

Let us not speak ill of the dead

Ms. Google in the server room with a candlestick. And frankly, it's about time.

Internet Explorer 6

2001-2010

2010/02/18

imap_filter.pl -- Mail Filtering via IMAP with Perl

Thunderbird is a big thing. It is an even bigger thing when you have several mailboxes. So, while I've not yet given up on Thunderbird, I have taken to not have it running unless I know I need it. That is where jBiff, my IMAP-to-XMPP thingee, comes in. I've even taken to using the web interfaces instead of Thunderbird on occasion. All is well in the world.

But there's a problem.

Lists. Lists and filters. Filtering lists. ( That makes it one problem again. )

I'm used to using slocal or procmail on Unix machines to filter as the mail comes in. I'm not nearly as happy with the interface to filtering in Gmail, but I do love the result, which is a cleaner inbox.

My work mail has filtering that's enabled when you use the web interface. I don't use the web interface often, and when I have all my filters in Thunderbird, nothing is filtered when I use the web. What I needed is a means to write my filters outside of a mail client and have them run regularly, so that the state of the inbox is always as it should be.

So, I wrote imap_filter.pl. It needs to be cleaned up a bit, and it is not feature-complete, but I'm able to move mail based on many good things, so I'm at a done point.

#!/usr/bin/perl
use 5.010 ;
use strict ;
use warnings ;
use lib '/home/jacoby/bin' ;
use Carp ;
use Data::Dumper ;
use Getopt::Long ;
use IO::Socket::SSL ;
use IO::Interactive qw{interactive} ;
use Mail::IMAPClient ;
use IdentConf ':all' ;
use subs qw{ imap_part xmpp_part } ;

$Data::Dumper::Indent = 1 ;
my $debug ;
my $imap_identity ;

#methods
my @from ;
my @to ;
my @cc ;
my @subject ;
my @to_or_cc ; # don't use or yet.
my $age = 0 ;

#actions
my $move ; #move to dir
my $forward ; #forward to this address
my $delete ; #delete this file
my $read ;
my $unread ;

GetOptions(
            'imap=s'    => \$imap_identity,
            'from=s'    => \@from,
            'to=s'      => \@to,
            'cc=s'      => \@cc,
            'or=s'      => \@to_or_cc,
            'subject=s' => \@subject,
            'age=i'     => \$age,

            'move=s'    => \$move ,
            'delete'    => \$delete ,
            'read'      => \$read ,
            ) or exit( 1 ) ;

exit if !defined $imap_identity ;
exit if length $imap_identity < 1 ;

for my $a ( @to_or_cc ) {
    push @to, $a ;
    push @cc, $a ;
    }

my $filter ;
$filter->{ from }    = \@from ;
$filter->{ subject } = \@subject ;
$filter->{ to }      = \@to ;
$filter->{ cc }      = \@cc ;
$filter->{ age }     = $age ;

$filter->{ move }    = $move ;
$filter->{ read }    = $read ;
$filter->{ delete }  = $delete ;

imap_part $filter ;
exit ;

# ====================================================================
#
# connect to and search your mail server via IMAP
#
# ====================================================================
sub imap_part {
    my ( $filter ) = @_ ;
    say { interactive } Dumper $filter ;

    my %creds = get_credentials( 'imap', $imap_identity ) ;

    my $socket = IO::Socket::SSL->new( PeerAddr => $creds{ server },
                                       PeerPort => $creds{ port },
                                       ) or die "socket(): $@" ;

    my $client = Mail::IMAPClient->new( Socket   => $socket,
                                        User     => $creds{ username },
                                        Password => $creds{ password },
                                        ) or die "new(): $@" ;

    if ( $client->IsAuthenticated() ) {
        $client->select( $creds{ directory } )
          or die "Select '$creds{directory}' error: ",
          $client->LastError, "\n" ;

        my $i = 1 ;
        for my $msg ( reverse $client->messages ) {
            my $flag    = 0 ;
            my $from    = $client->get_header( $msg, 'From' ) ;
            my $sender  = $client->get_header( $msg, 'Sender' ) ;
            my $date    = $client->date( $msg ) ;
            my $to      = $client->get_header( $msg, 'To' ) ;
            my $cc      = $client->get_header( $msg, 'Cc' ) ;
            my $subject = $client->subject( $msg ) ;
            my @flags   = $client->flags( $msg ) ;
            my $seen = 0 ; $seen = 1 if grep m{/Seen}mx , @flags ;
            next if grep m{\Deleted}mx , @flags ;

            # Subject
            if ( scalar @{ $filter->{ subject } } > 0 ) {
                for my $f ( $filter->{ subject } ) {
                    my $ff = $$f[ 0 ] ;
                    $subject =~ m{($ff)}mix ;
                    say $1 if defined $1 ;
                    $flag++ unless defined $1 ;
                    }
                }
            # From
            if ( scalar @{ $filter->{ from } } > 0 ) {
                for my $f ( $filter->{ from } ) {
                    my $ff = $$f[ 0 ] ;
                    $from =~ m{($ff)}mix ;
                    $flag++ unless defined $1 ;
                    }
                }
            # To
            if ( scalar @{ $filter->{ to } } > 0 && ! defined $to ) {
                $flag++ ;
                }
            if ( scalar @{ $filter->{ to } } > 0 && defined $to ) {
                for my $f ( $filter->{ to } ) {
                    my $ff = $$f[ 0 ] ;
                    $to =~ m{($ff)}mix ;
                    $flag++ unless defined $1 ;
                    }
                }
            # Cc
            if ( scalar @{ $filter->{ cc } } > 0 && ! defined $cc ) {
                $flag++ ;
                }
            if ( scalar @{ $filter->{ cc } } > 0 && defined $cc ) {
                for my $f ( $filter->{ cc } ) {
                    my $ff = $$f[ 0 ] ;
                    $cc =~ m{($ff)}mix ;
                    $flag++ unless defined $1 ;
                    }
                }
            # Age
                #GOT NADA

            next if $flag ;

            if ( 1 ) {
                my $title = 'New mail from ' . $from ;
                my $body  = $subject ;
                $body = join q{"}, '', $body, '' ;

                #say { interactive } "$title - $body" ;
                say { interactive } $i++ . "\t" . '=' x 40 ;
                say { interactive } $subject;
                say { interactive }   'From:     ' . $from ;
                say { interactive }   '  Sender: ' . $sender if $sender  ;
                say { interactive }   '      To: ' . $to if $to ;
                say { interactive }   '      Cc: ' . $cc if $cc ;
                say { interactive }   '    Date: ' . $date ;
                say { interactive }   join ' ' , ' ' , @flags ;
                if ( $filter->{ move } ) {
                    my $move = $filter->{ move } ;
                    say { interactive } '    Move: ' . $move ;
                    my $newUid = $client->move( $move , $msg )
                        or die "Could not move: $@\n";
                    }
                say { interactive } '' ;
                }
            }
        $client->logout() ;
        }
    else {
        say { interactive } 'FAIL ' . $! ;
        }
    }

# --------------------------------------------------------------------

There's Something To This

Ed Finkler (aka @funkatron and the developer of the AIR-based Twitter client Spaz) wrote on the subject of the user experience.
These people have better things to do with their days than tweaking out the spacing in their browser toolbars. A computer for them is a utility. One that is increasingly complex, and one that is used because it’s the only option for accomplishing certain things – not because it’s a good option.

It’s kind of like the Photoshop Problem: when people want to crop a picture, we give them Photoshop. Photoshop is a behemoth application with nearly every image editing and touchup function imaginable, and it is terribly complex. Now Photoshop is an impressive tool, but only a very tiny percentage people need the power it offers. The vast majority just want to crop their ex-husband from the photo and let their friends look at it. But even iPhoto, the poster child for Apps So Easy Your Grandparents Can Use Them, continues to pile on features and complexity.

When folks need an elevator, we should give them an elevator, not an airplane. We’ve been giving them airplanes for 30 years, and then laughing at them for being too stupid to fly them right.

I think we’re the stupid ones.
Forgive me if I am wrong, but I think there's crossover here with Jeff Atwood (@codinghorror) and his comments on netbooks.
They may be pieces of junk to Mr. Jobs, but to me, these modest little boxes are marvels -- inspiring evidence of the inexorable march of powerful, open computing technology to everyman and everywhere.

We have produced They may be pieces of junk to Mr. Jobs, but to me, these modest little boxes are marvels -- inspiring evidence of the inexorable march of powerful, open computing technology to everyman and everywhere.

We have produced a democracy of netbooks. And the geek in me can't wait to see what happens next.
There are a couple moves I can make from here. Don't know which is the best. So I will poke at it and try to find the right angle. Part of that angle is that the desktop PC is a dinosaur that's feeling the cold coming on. When I moved into my house, I ran CAT5 to the master bedroom. I crawled into the crawl space. I drilled holes through the floor and cut holes in the drywall. I bought a 2-foot long drill bit. I have not used that line in years. I have WiFi. I know the problems with WiFi, and how this means my neighbor can mess up my WiFi if his config is the same as mine (yeah, it happened) and I know that no wireless network will be as secure as a wire, but I don't care, because the win exceeds the lose.

My work is in a lab at a university. We have several instruments, tools to do science. Many of them are so complex and have computers to control them, and sometimes (not always) collect data from them. Dealing with these machines is a major part of my work day. One of the newer instruments came with a laptop. I groused, saying that this was small enough that someone could grab it, shove it in a bag and walk away, but it was put there. There's a lot to having a full-tower desktop PC that makes a whole lot of sense if you're going to push the full-power of the PC. If you expect to swap hard drives like a guitarist swaps strings, if you plan to add or shuffle PCI cards like a Vegas dealer, the full-tower case makes sense. If you're going to leave it sit, do it's business and whir, a laptop, or even a netbook, makes sense.

Similarly, if you're going to "compute", which in the modern sense means to browse the web, check mail, chat with friends and the like, wherever you might be, the end-all be-all of computer design circa 1999 on steroids is not going to be what you need. Weight, networking and power requirements lock you to one spot with desktop PCs, but are complete non-issues with netbooks. I have a reasonably smart phone. I have had an appreciably smarter phone. I don't walk around with the current best-of-class smartest phones (iPhone or Android). The one I have, a Samsung Instinct, is smart enough for much of what I do. It plays music. It plays video. It talks to my Google Calendar. It sends and receives mail. It isn't all the "computing" you will ever need, but it is a pretty useful subset. When my wife's netbook (and primary computer) went back to Asus for a repair, she relied on her phone and was able to do most of the stuff she needed to do.

I wouldn't want to develop on a netbook, and when I can, I use Synergy2 or the like to allow me to use a normal keyboard and mouse with mine. But I'm fine for tweeting and blogging and music and IM and such on it.

Years ago, I saw an article that compared and contrasted the workstation of 1990 and 2000. (I think. I can't find it.) You had a huge difference between the capabilities of the hardware ( 10baseT vs 100baseT, huge differences the amount of memory available, much larger drive sizes and processor speeds ) and stagnation in the
software ( X and a window manager holding a terminal window, into which you type via EMACS or VI and compile with gcc or the like ). If you do a similar comparison between the platforms of the common user vs a developer's setup, you'll get a big delta in both the hardware and the software. The computer the developer might be much faster than it was before, but it looks like a box with a mouse and a keyboard and a monitor, with a power cord and a network cord giving up to gigabit ethernet. The computer the end-user might look like that. It might have the HDTV as a monitor and a remote to serve as the mouse. It might be a netbook smaller than external CDROMs were five years ago. It might be a phone.

I flash back to the oil embargo of the early 1970s. This is where the definition of car that the US auto makers and the consumers diverged, leaving an opening for the Japanese car companies. I think it is clear that, hardware-wise, the industry is keeping up with demand, making smaller, lighter things with cupholders, but people used to having computers with two-tone paint and fins and big V8 engines (in this case, Steve Jobs and lots of programmers) are making the software like they used to. Like makes sense for them. Which is a great disconnect, which is where Ed's comment comes in. I think.

More later, when I can re-think this and force it to make more sense.

2010/02/10

Phoon Fail


We all love having our Bluetooh® Wireless Technology

2010/02/06

if you can't be a good example, you can at least be a horrible warning

I am not lost. No, far from it.

There's this blog. If I do anything interesting, I by and large tend to blog about it. so looking through old posts will tell me the packages and fixes I need to get my environment back.

Then there's Dropbox. Dropbox is a means to create a shared directory betweeen all your machines. Shawn Powers of Linux Journal suggested putting your config files into your Dropbox so that you can keep a consistent setup. I read that too late, and I don't have that. But what I do have is a set of nightly ZIP files of certain essential bits. And that's good. But I'm thinking that, once this is done, I'll go all out and keep much more in Dropbox.

Also, between Delicious and Google Bookmarks for bookmarks, Google Calendar for events and Thunderbird and IMAP for mail, much of that crucual stuff was never on my desktop. But it does remind me of something: I was just thinking about mail filtering, because all my work filtering occurred through Thunderbird, and my .mozilla-thunderbird directory is now dead.

Wondering now to what extent git might've helped. I have a GitHub account, but I hardly use it. I had git installed, but I hardly used it. If I'm not connecting to an external repository on each save, I've really done little. Must use that more.

What kills me the most is that that I was working on breaking apart a big ugly Perl module into lots of little modules. On Stack Overflow, I referred to it as Dumb and in keeping with that, I had created Dumb::Database, Dumb::Markup and Dumb::Table1Access, but it was all only on my desktop, while if it was on the server it was intended for, my wipe wouldn't have destroyed anything.

Such is life. Ubuntu is installing the 9.04->9.10 upgrades to get me to the full Koala, so soon I shall start the moving-in process.

Well, Crap

Crap Crap Crap Crap Crap.

Remember how I said that keeping /home on another partion keeps it safe?

You must be careful to keep sure that Ubuntu's installer (or whatever installer you prefer) doesn't format your partitions.

There was work I've lost.

Crap.

onward and backward

Five use cases:
  • I'm working remotely
  • I'm working remotely and I want to reboot but have everything come up again when done.
  • I want to connect to my machine via SMB from a Windows machine like my netbook
  • I want to have jobs going off at regular intervals
  • I want to print.
Simple stuff, right?
  • openssh-server
  • grub
  • samba
  • crom
  • cups
All of those packages don't work for me. Which is sick and bad and wrong. Did I mention the bad? So, I'm reinstalling.

At this second, really. I'm in the "try before you buy" part of the Ubuntu LiveCD, mounted on the office USB key.

One of the tricks I use, and this hardly rises to the level of trick, is to keep my /home on a separate partition from /, which means that everything I really value on a computer is safe while I wipe and pave over the operating system. I must admit that I didn't always do this, but I didn't always have 40GB (work) or 500GB (home) of drive to play with. Come to think of it, I have a 40GB drive for / at home as well as the big drive for /home.

But, while that's really helpful, there's more to remember.

Your crontab isn't saved in your home directory, so, when you wipe and reinstall, you lose your crontab, which, if you're like me, is as finely tuned a config as your .bashrc or your .vimrc or your .alias. So, the trick is to always save a copy of your crontab to a safe place. Schedule it. Put it in your crontab.

There's other considerations, too. I had an X11 problem that forced me to tweak my config to fix notify-osd, so I copied my xorg.conf to my home dir. I have a bunch of tools I use a lot that are not standard, so my apt sources.list has been changed. So I have that copied. I saved list of installed packages so I can start to reinstall the things I want without having to try to remember it all. Also, Ubuntu desktop defaults to DHCP, but my network address is hardcoded. I know that address, and if I forget it I can always nslookup myself to get it back.

Time to reboot.

2010/02/04

The Blog in Action

My boss has been working with Chart::Clicker. As you might know, I have blogged on the subject a bit. When he went searching for a solution for an issue he had, he went searching and guess what? He found the solution here on this blog. And I hadn't mentioned the blog to him before.

I'm sort of a big deal.

In fact, a Google Image Search shows (or at least showed on Feb 4, 2010) that my generated image is the #1 image.

Wow. That says something.

What it says is that anyone who would have given more than a little work with it would have gotten higher. I feel proud, but I've barely scratched the surface with this very powerful, very beautiful graphing tool. A very powerful and beautiful tool with near bupkis for documentation. The programmer has a site for the project, but while it has great pics, he has no sample code to show how that is generated. Which sucks.

Hey, go to a site called /var/log/rant, gotta expect a rant.

2010/02/02

I have a lot of problems with you bits!

I haven't yet removed the cut-tag style from this blog's default. It's a minor thing, but I nearly never write long enough to justify it, and there's no conditional.

My work machine doesn't start ssh, cups, cron or samba on startup, meaning I must do it manually, which sucks. Really considering a reinstall. Perhaps "planning" is a better word. Not having printing always is a bit annoying, and SMB networking is more a toy than a crucial item, but SSH is crucial to me, and cron is more so.

You see, I have a program called jBiff that tells me when important emails come, and that requires them to be scheduled via crontab. No cron, no messages, and I get people coming up to me saying "Did you get my email?" I hate being caught flat-footed in those situations. So, must reinstall to fix cron.

And my Samsung Instinct phone will not talk to Linux. That one's a bit beyond my ability to manipulate, I think.

2010/02/01

I Like Chrome

And I think I'm about to switch from Firefox as my go-to browser.

I apt-get installed it a while ago, and Chrome's insistence on looking like Chrome when I wanted it to look and act like Ubuntu was an early problem. If I can't move a window like any other window, I can't use that window, and thus that program.

This was a problem until I realized you could tell it to use the system's Title Bar, which means when I double-clicked, it rolled up like any other window, and a right-click on the bar meant I could kick it to whatever virtual desktop I wanted. That was enough for me to take away most of my dislike.

But not all. I had been using Delicious as my online bookmarks storage. I had used Google Bookmarks before, but something kicked me off that a while ago. For the life of me, I cannot remember what. But I went to Delicious. Chrome doesn't sync with Delicious, but it does sync with Google Bookmarks. ::SHOCK!::

Delicious exports RSS. Chrome imports a special type of HTML. You need to convert. For this purpose, I wrote rss2bookmarks.


#!/usr/bin/perl
use 5.010 ;
use strict ;
use warnings ;
use XML::RSS ;

# USAGE: rss2bookmarks.pl < input.rss > output.html

my %bookmarks ;

my $data ;
while (<STDIN>) { $data .= $_ }
my $rss = XML::RSS->new() ;
$rss->parse( $data ) ;

for my $item ( @{ $rss->{items} } ) {
my $title = $$item{title} ;
my $link = $$item{link} ;
$bookmarks{$title} = $link ;
}

say '#<DL><p>' ;
say ' <DT><H3>Bookmarks Bar</H3>' ;
say ' <DL><p>' ;
for my $bookmark ( sort keys %bookmarks ) {
my $link = $bookmarks{ $bookmark } ;
say qq{ <DT><A HREF="$link"> $bookmark </A>} ;
}
say ' </DL><p>' ;
say '</DL><p>' ;

Use it in good health.

Captain Picard on the Internet


I do Twitter. Otherwise, I'm pretty much with him.