Jeff Epler's blog

24 February 2014, 13:10 UTC

How do you check a signature on a PGP/Mime message

…I'll answer in Python. First, put your whole message in a file in unix "mbox" format (this will be the problem if you use some brain-dead GUI mailer!), then in Python extract the signature and the signed message, and finally invoke gpg:

import email
import os
import sys

with open(sys.argv[1]) as mfile: message = email.message_from_file(mfile)

if message.get_content_type() != "multipart/signed":
    raise SystemExit, "message not signed"

# Really, you'd want safe temporary filenames, and you'd want to clean them up
with open("msg", "wb") as msg: msg.write(message.get_payload(0).as_string())
with open("sig", "wb") as sig: sig.write(message.get_payload(1).get_payload())

# Delegate the real business to gpg
os.execvp("gpg", ["gpg", "--verify", "sig", "msg"])


19 February 2014, 21:17 UTC

Red: the perfect unit of measurement?

If you're like me, when you write software that has to store distance information in floating point, you shudder because you know you have to pick either inches or millimeters, leading most common multiples of the other as numbers that are not exactly expressible in binary floating point.

So let me make a simple proposal: define red = 625nm, so called because light of 625nm is commonly perceived as red. Now, you can store all of the following as exact integers:

  • Any binary fraction of an inch down to 1/64inch (1/64in = 635 red)
  • Any 1/10 of an inch (1/10in = 4064 red)
  • Any multiple of 5um (5um = 8 red)
Unfortunately, the following are still not exact:
  • 1mil = 40.64 red
  • 1pspt = 1/72in ~= 564.44 red
  • 1/300in (common print resolution) ~= 135.46 red

Here are some other visible-light inspired fundamental distance units and the common distances they can express exactly as binary fractions:

Table of magic lengths
Color name Exact definition Wavelength (approximate) Exact binary fractions for multiples of
red 8192/11162109375m 733.91nm 1/64in mil pspt dpi nm
red 64/89296875m 716.71nm 1/64in mil pspt dpi 25nm
red 512/744140625m 688.04nm 1/64in mil dpi nm
red 4/5953125m 671.92nm 1/64in .01in dpi um
red 32/49609375m 645.04nm 1/64in mil 5nm
red 1/1587500m 629.92nm 1/64in .01in 5um
yellow 256/446484375m 573.37nm 1/64in mil pspt dpi 5nm
green 2/3571875m 559.93nm 1/64in .01in pspt 5um
green 2048/3720703125m 550.43nm 1/64in mil dpi nm
green 16/29765625m 537.53nm 1/64in mil dpi 25nm
green 128/248046875m 516.03nm 1/64in mil nm
green 1/1984375m 503.94nm 1/64in .01in um
blue 1024/2232421875m 458.69nm 1/64in mil pspt dpi nm
violet 8/17859375m 447.94nm 1/64in .01in pspt dpi um
violet 64/148828125m 430.03nm 1/64in mil dpi 5nm
violet 1/2381250m 419.95nm 1/64in .01in 5um
violet 512/1240234375m 412.83nm 1/64in mil nm
violet 4/9921875m 403.15nm 1/64in mil 25nm
computed by, frequency range for each colorname from wikipedia. Unlike the original 625nm "red" constant, common lengths are binary fractions rather than whole numbers. And of course these aren't nice integer multiples of nm either. I wonder why no oranges make the table.

Files currently attached to this page:



23 November 2013, 18:19 UTC

SNTP from Python: getting server's esimate of time quality

Anders Wallin recently discussed generating graphs of server time error using a timestamp from the Date: header of an http request.

NTP servers themselves have estimates of time error, and it's possible to get the local server's idea of the error by sending SNTP packets to the local machine. You can also see the last time this NTP server successfully communicated with a peer or upstream, and see whether the server considers itself desynchronized by checking the stratum and leap second fields.

Based on my tinkering, the root_dispersion field or the derived LAMBDA value is the easiest to look at for estimating how bad the NTP time is. Between communications with a peer, root_dispersion and LAMBA increase at a rate of 15µs/s, ntp's arbitrary estimate of the accuracy of the local undisciplined clock. (YMMV and you can appaerntly tweak CLOCK_PHI in your NTP configuration file)

The attached program is a basic Python SNTP client which by default polls the local server every 5 seconds and prints some information. License: GPLv2+

Typical output:

12:25:58  0.06233  228.95875 ST-SYNCH LI-SYNCH
12:26:03  0.06241  233.96404 ST-SYNCH LI-SYNCH
12:26:08  0.06247  238.96745 ST-SYNCH LI-SYNCH
12:26:13  0.06255  243.97141 ST-SYNCH LI-SYNCH
12:26:18  0.06262  248.97673 ST-SYNCH LI-SYNCH
12:26:23  0.06270  253.98213 ST-SYNCH LI-SYNCH
12:26:28  0.06277  258.98746 ST-SYNCH LI-SYNCH

Files currently attached to this page:



2 October 2013, 19:19 UTC

Callcentric "click 2 dial" commandline client

I investigated using Callcentric to replace my POTS telephone. (I later abandoned my attempt to port my existing POTS number to Callcentric but still plan to use them for international outcalling) I wrote a Python commandline client for their "click 2 dial" service.

read more…

20 May 2013, 21:37 UTC

tardiff: diff two (compressed) tar files without extracting

Recently I was googling for a script to compare tar files, and found references to a perl script (which I did not read) which reportedly did this by expanding both tar files and then diffing the trees. This would actually have been fine for my case, but some people noted that their use case involved tarfiles that were too big to extract comfortably. I assume that this is due to space considerations, but doubtless there are time considerations too.

read more…

17 January 2013, 16:34 UTC

moinmoin cleanup script

I run a small wiki using moinmoin. Recently I noticed that it was not uncommon for moin.cgi processes to run for over a minute, which was worrying!

I determined that the slow-to-render page was TitleIndex, and that this was slow because there were a lot of 'unborn' pages which spammers had attempted to create. These take the form of directories under data/pages with only a zero-byte 'edit-log' file. Rendering TitleIndex has to walk all these directories, even though they don't contribute anything to the list of pages.

So I wrote a Python script to clean these up. It's intended to be run from the wiki's 'data' directory, and it prints a list of bourne shell commands to delete the offending directories as well as any users with the same name as an offending directory. Redirect the output of the script to a file, look over the file, and once you've decided it's good, just 'sh' it (running it as your wiki user if necessary).

This dropped the render time of TitleIndex quite substantially!

I did a few other things for the sake of my wiki at the same time: I turned on Xapian indexing (which seems to help searches but not TitleIndex); I switched from cgi to wsgi; and I enabled textchas for signup. That latter step didn't work for long, as 48 hours later the bots have started successfully creating new accounts again, though the overall rate may be lower now.

Files currently attached to this page:

wikiclean.py637 bytes


1 December 2012, 1:12 UTC

Android "Birds of Australia" unpacker

For our recent trip to Australia, we purchased the Birds of Australia app; it was really handy during our travels when we were trying to identify birds (though there are some things about the UI which could be better).

As a tinkerer, I was interested in finding out how the app stores the bird data and what modification opportunities may exist.

read more…

9 October 2012, 2:30 UTC

FTL (un)packer for Linux

Update: Added some notes about what is in the various files in data.dat

Recently I bought Faster Than Light (FTL), a game which runs on Linux (and also on Mac and Windows).

I noticed that there was a lot of stuff in two ".dat" files; the format of the ".dat" files turned out to be very simple, and so I wrote a packer and unpacker:

read more…

16 October 2011, 15:31 UTC

csql: perform sql queries on csv data

24 July 2009, 2:19 UTC

CropGUI 0.1.1: now with gtk

All older entries
Website Copyright © 2004-2017 Jeff Epler