Back In Print

My article on Ruby/Amazon has finally made it into print in the February issue of Dr Dobb’s Journal.

This is my first published work for a computer magazine in just under ten years. It’s hard to imagine it was that long ago that I wrote a monthly column about the Internet for the now defunct PCW Plus, a magazine devoted to users of the dearly beloved Amstrad PCW.

I’d still like to write a book at some point, if I can ever manage to summon the energy. I used to think I’d one day write a book about LDAP or Bourne shell scripting, but there are good books available on those subjects these days.

No, it’s more likely I’ll turn my hand to newspaper journalism at some point in the future, once I have more free time available.

ruby-ldap controls patch

I’ve put out a series of patches to ruby-ldap 0.8.3 to allow the easy use of controls. Controls take advantage of the extensible nature of LDAPv3 to provide functionality not part of the original protocol specification.



Specifically, I had a need at work to use the Paged Results control, described in RFC2696. ruby-ldap 0.8.3 allows the client to set controls at the search level via LDAP::Conn#search_ext and LDAP::Conn#search_ext2, but it has no way to return controls sent by the server to the client as a side-effect of the search. Furthermore, I wanted to be able to set controls at the session level and have those be effective during

LDAP::Conn#search and LDAP::Conn#search2, which are methods I use much more frequently.

Anyway, if you need to use LDAP controls from Ruby (and let’s face it, who doesn’t?), this if for you.

On The Money

Ruby/Finance is finally available for public consumption. I released version 0.1.0 yesterday evening to a deafening roar of silence.

Currently, it handles basic Yahoo Finance stuff, such as currency conversions and stock data retrieval from the American, Australian, Asian and European markets. As such, it replicates some of the functionality of Perl‘s Finance::Quote and is somewhat based on its design. In fact, whilst running unit tests, I was amused to find that I had even managed to faithfully port one of Finance::Quote‘s bugs.

For the foreseeable future, I’ll be adding more of Finance::Quote‘s functionality to provide Ruby users with the same range of features that the Perl crowd enjoy. After that, who knows?

The next module I’ll be implementing is one to retrieve stock data from Amsterdam’s AEX exchange.

The Bug Returns

I’ve been farting around, looking for another programming project to sink some time into. I haven’t felt like doing any programming for a couple of months now, and I needed something to get my teeth into enough that it would draw me back in and make me excited to play with my computer once more.

More and more, I find myself losing interest in computers, not just professionally, but to a lesser degree, personally, too. I hope that’s just a symptom of feeling jaded and burnt out. I’d hate to permanently lose interest in a hobby I’ve had for most of my life, but we all get older and some of us even get a little wiser in the process, so maybe that’s the direction I’m heading in. I don’t think so, though; I think this is just a temporary malaise.

Anyway, I released version 0.8.3 of Ruby/Amazon a few days ago, but that was hardly a major event. It’s already the most complete high-level language interface to Amazon’s Web Services, so this release was just to add support for HTTP proxy servers. Some poor unfortunates still have to use those, I suppose.

Now back to my story. With Sarah’s company (well, her employer’s company, to be precise) having gone public last week, I fished around on RAA for a library to help me write a stock price grabber. To my surprise, there wasn’t yet anything available.

Well, it didn’t take me long to hack up a few lines of code to grab the current price and plonk it in the sidebar on our front page, as well as e-mail a copy to Sarah at work when the integer dollar price changes.

That set me thinking, though. E-mail is all well and good, but I wanted some kind of scrolling applet on my desktop. Unfortunately, ruby-gnome2 doesn’t seem to support the GNOME panel yet, so that was out as a possibility. Oh well, I thought, there must be a GKrellM plug-in out there and, sure enough, I quickly found what I was looking for: GkrellStock.

Upon untarring the archive, it quickly became apparent that this software would need Perl’s Finance::Quote., which I vaguely remembered once having read a little about. Anyway, once I’d acquired that, I was up and running with GkrellStock.

Finally, I’m getting to the point of the story. With Sarah’s company already floated on the stock market and mine destined to do the same at some point in the coming months, the need for a Ruby library to handle one’s financial networking is greater than ever. And thus was begun the effort to port Finance::Quote to Ruby.

After a few hours of hacking, I have implemented about 15% of what Finance::Quote can do, but even this is enough to have GkrellStock now work via Ruby/Finance or whatever it ends up being called.

I don’t normally port things, as it’s too much like reinventing the wheel and thus usually strikes me as a poor investment of my time. However, since the Ruby world is so lacking in this area, it seemed appropriate to put some time into the project. Depending on how much time I can spend on it this week, I should have something I feel comfortable having the hoi polloi gawk at pretty soon.

It really is quite nice to be hacking again.

Accounting for spam

Since I wrote about my new anti-spam measures, the spam has been furiously banging up against my virtual front door.

Talking to a colleague on IRC tonight, I was inspired to write a quick Ruby script to report the progress since last Sunday:

#!/usr/bin/ruby -w
reject = 0 )
while line = ARGF.gets
  case line
  when /un(verified|deliverable) address/
  when /554 Service unavailable.* (blocked using .+?);/
    reject[$1] +=1
  when /NOQUEUE: reject:(?:.+?:.+?: )(.+?)[;:] from/
    reject[$1] +=1
  when /reject: header .+helo=.+?: (.+)$/
    reject[$1] +=1
total = 0
reject = reject.to_a.sort { |a,b| a[1] &lt;=&gt; b[1] }
reject.each do |x|
  printf( "%-74s%5d\n", x[0], x[1] )
  total += x[1]
printf( "\n%-74s%5d\n", "Total blocked:", total )

Here are the results:

Bad attachment with file name extension: bat 1
Bad attachment with file name extension: cpl 1
Sender address rejected: need fully-qualified address 2
Sender address rejected: Improper use of SMTP command pipelining 3
Bad attachment with file name extension: exe 5
Bad attachment with file name extension: com 8
Relay access denied 9
Bad attachment with file name extension: scr 12
Bad attachment with file name extension: pif 25
Helo command rejected: Improper use of SMTP command pipelining 27
blocked using 30
Helo command rejected: Host not found 58
Helo command rejected: need fully-qualified hostname 124
blocked using 155
blocked using 290
Sender address rejected: Domain not found 1619
Recipient address rejected: User unknown in local recipient table 6659
Total blocked 9028

All in all, I’m very pleased. Very little spam is making it through now. For the spam that does make it into the system, I also upgraded to a recent CVS snapshot of SpamAssassin this afternoon, so most of it still gets zapped before making it to the in-box of any of my users.