<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Software on WormBytes</title><link>https://www.wormbytes.ca/categories/software/</link><description>Recent content in Software on WormBytes</description><generator>Hugo -- gohugo.io</generator><language>en-ca</language><managingEditor>Robert James Kaes</managingEditor><copyright>Robert James Kaes. All Rights Reserved.</copyright><lastBuildDate>Fri, 02 Dec 2005 14:51:50 +0000</lastBuildDate><atom:link href="https://www.wormbytes.ca/categories/software/index.xml" rel="self" type="application/rss+xml"/><item><title>Wormbytes::CGI::Application</title><link>https://www.wormbytes.ca/software/cgiapp/</link><pubDate>Fri, 02 Dec 2005 14:51:50 +0000</pubDate><author>Robert James Kaes</author><guid>https://www.wormbytes.ca/software/cgiapp/</guid><description>&lt;p&gt;I&amp;rsquo;ve done a lot of CGI application programming. Over the years I&amp;rsquo;ve
developed a
&lt;a href="http://cgiapp.erlbaum.net/cgi-bin/cgi-app/index.cgi"&gt;CGI::Application&lt;/a&gt;
base class that I derive my applications from. I&amp;rsquo;ve called my Perl
module
&lt;a href="https://www.wormbytes.ca/software/cgiapp/Application.pm.txt"&gt;WormBytes::CGI::Application&lt;/a&gt;
since it derives from CGI::Application. It brings in all the modules
I normally use in my CGI programming.&lt;/p&gt;
&lt;p&gt;In addition to the required modules, I&amp;rsquo;ve extended the class to handle
session management. There is also rudimentary support for user
management in the base code. Nothing fancy, but enough to do simple
log-in style applications. It can be easily extended in sub-classes
if needed.&lt;/p&gt;
&lt;p&gt;The session management code uses a UUID numbering system. The idea is
that each session ID needs a unique ID, but the IDs do not need to be
random. Uniqueness is more important. To ensure that sessions can
not be hi-jacked, an additional HMAC cookie is included with the
session ID cookie. This HMAC includes a random number stored in the
session on the server plus a hash of information from the client. The
client information is not required, but it does help if the
information is present. Because of the random key that&amp;rsquo;s used in the
hash it is impossible to guess what the HMAC will be. It is checked
at the beginning of each request and modified at the end of each
request. Therefore, the HMAC is constantly changing and is constantly
validated. In this, the base class, an invalid session causes the
system to log the user out.&lt;/p&gt;
&lt;p&gt;There are also certain helper functions like &lt;tt&gt;tt_pre_process()&lt;/tt&gt;
that adds certain objects and variables to all templates.
&lt;tt&gt;cgi_untaint()&lt;/tt&gt; creates a CGI::Untaint object for later use.
Finally, &lt;tt&gt;redirect_url()&lt;/tt&gt; simply redirects the client to a new
location.&lt;/p&gt;
&lt;p&gt;I find this module to be a great base for all my CGI applications.&lt;/p&gt;</description></item><item><title>Emacs Lisp</title><link>https://www.wormbytes.ca/software/emacs-lisp/</link><pubDate>Fri, 02 Dec 2005 10:13:05 +0000</pubDate><author>Robert James Kaes</author><guid>https://www.wormbytes.ca/software/emacs-lisp/</guid><description>&lt;p&gt;&lt;a href="http://www.gnu.org/software/emacs/emacs.html"&gt;Emacs&lt;/a&gt;
is my editor of choice, and like most people who use Emacs I have
customized it to suite my personal taste. I have included copies of
my customizations so that others may build on what I&amp;rsquo;ve created, or
simply have a more pleasant working environment.&lt;/p&gt;
&lt;h2 id="lisp-source"&gt;Lisp Source&lt;/h2&gt;
&lt;h3 id="emacsel"&gt;&lt;a href="https://www.wormbytes.ca/software/emacs-lisp/emacs.el"&gt;emacs.el&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This is my main &lt;tt&gt;.emacs&lt;/tt&gt; file. It contains the bulk of the
customizations, but it does include a few other features and functions
that other people may find useful. Some of the code is written by me,
and other parts I&amp;rsquo;ve found on the net.&lt;/p&gt;
&lt;h3 id="planner-configel"&gt;&lt;a href="https://www.wormbytes.ca/software/emacs-lisp/planner-config.el"&gt;planner-config.el&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To help me manage my time and my projects I have turned to the
&lt;a href="http://sacha.free.net.ph/notebook/wiki/PlannerMode.php"&gt;plannel-el (PlannerMode)&lt;/a&gt;
major mode. Since I have worked as a independent IT consultant, I
often need to track the number of hours I work on projects for various
clients. I have customized and extended planner-el to allow me to
clock in and out of a task. Upon clock-out the system will
automatically prompt me for a description of what I did during the
clocked-in time, and then write a note on the task page for the
project detailing the amount of time I spent, and allowing me to
classify the work performed. I then have a separate Perl script that
takes the raw task pages and produces an invoice. I think it&amp;rsquo;s a very
slick setup.&lt;/p&gt;
&lt;/p&gt;
&lt;h3 id="pic-asm-modeel"&gt;&lt;a href="https://www.wormbytes.ca/software/emacs-lisp/pic-asm-mode.el"&gt;pic-asm-mode.el&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I have done a lot of firmware programming on various Microchip PIC
micro-controllers, and I found that the default &lt;tt&gt;asm-mode.el&lt;/tt&gt;
script did not handle the idiosyncrasies of the PIC assembly language
very well. Therefore, I created &lt;tt&gt;pic-asm-mode.el&lt;/tt&gt; as an
extension to &lt;tt&gt;asm-mode.el&lt;/tt&gt;. It syntax highlights PIC assembly
mnemonics and handles formatting correctly.&lt;/p&gt;</description></item><item><title>Combo Button Lock Quiz Problem</title><link>https://www.wormbytes.ca/software/combo_lock/</link><pubDate>Wed, 30 Nov 2005 01:04:59 +0000</pubDate><author>Robert James Kaes</author><guid>https://www.wormbytes.ca/software/combo_lock/</guid><description>&lt;h2 id="introduction"&gt;Introduction&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://www.sentex.net/~mwandel/"&gt;Matthias Wandel&lt;/a&gt;
of &lt;a href="http://www.rim.net/"&gt;Research in Motion&lt;/a&gt; (RIM)
has a
&lt;a href="http://www.sentex.net/~mwandel/careers/sample_problem.html"&gt;programming challenge&lt;/a&gt;
posted on his website. The challenge is to write a
program that generates all the possible combinations for an N button
combination lock. The twist is the multi-button possibilities as
well. Read on to see how I solved the problem.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Updated on November 29, 2005:&lt;/em&gt; The version described below is
the second published version of the code. The
&lt;a href="https://www.wormbytes.ca/software/combo_lock/combos.v1.c"&gt;first program&lt;/a&gt;
was 160 lines of code and involved a more complicated way of producing
the combinations. It is, however, faster than the current version.&lt;/p&gt;
&lt;h2 id="constraints"&gt;Constraints&lt;/h2&gt;
&lt;p&gt;Matthias presents the programming challenge while describing the
position of an embedded developer. The original code traded memory
usage for more complicated code. The new version reverses this
decision since the amount of memory consumed is still much lower than
a typical 8-bit micro-controller. The other driving constraint is to
keep the source to less than 100 lines of code. The current version
is at 125, so there is still some room for improvement.&lt;/p&gt;
&lt;h2 id="theory-of-operation"&gt;Theory of Operation&lt;/h2&gt;
&lt;p&gt;The problem can be described as a simple
&lt;a href="http://en.wikipedia.org/wiki/Combinatorics"&gt;combinatoric&lt;/a&gt;
(&lt;var&gt;k&lt;/var&gt;-of-&lt;var&gt;n&lt;/var&gt;) where an increasing number of keys are drawn (starting
with one and increasing to a maximum of eight.) After
each choice the
&lt;a href="http://en.wikipedia.org/wiki/Permutation"&gt;permutations&lt;/a&gt;
of the set are generated. Pretty straight forward.&lt;/p&gt;
&lt;p&gt;The insight I had for the second version of the program is to
pre-compute all the button pair combinations. With only eight possible
keys, there are only:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
total_pairs = (total_keys * (total_keys - 1)) / 2
= (8 * (8 - 1)) / 2
= 28
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Therefore, there are 28 pair combinations plus eight single key
presses for a total of 36 possible button presses.
Now, I can consider the whole single
versus pair problem as a simple &lt;var&gt;k&lt;/var&gt;-of-36 with &lt;var&gt;k&lt;/var&gt;
increasing from 1 to 8. This simplifies a lot of the code.&lt;/p&gt;
&lt;p&gt;Pairs are stored in a single integer as the upper and lower nibbles of
a byte. Single buttons are also stored in an integer, but the upper
nibble is zero to differentiate them from the pairs. The display
routine uses this information to determine how the output should be
handled.&lt;/p&gt;
&lt;p&gt;In order to ensure that invalid combinations are not picked a simple
bitmask is used to track the keys already used in the current
combination. This decision does slow down the program a bit (with my
tests showing the current code calculates all the combinations and
permutations for eight keys in 4.6 seconds, while the older code could
do the same in 2.9 seconds.)&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m not happy about the slowdown in the execution, but the code is
easier to understand, and the change did eliminate 35 lines of source
code.&lt;/p&gt;
&lt;h2 id="source-code"&gt;Source Code&lt;/h2&gt;
&lt;p&gt;The complete source code for &lt;a href="https://www.wormbytes.ca/software/combo_lock/combos.c"&gt;combos.c&lt;/a&gt;
can be compiled into an
executable by doing: &lt;tt&gt;cc -o combos combos.c&lt;/tt&gt;&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;I found the process of writing this application to be fascinating.
I had never developed code requiring either permutations or
combinations. Even after I wrote a version that solved the problem I
still felt compelled to come up with a better version. At 125 lines,
this version is closer to meeting the requirements of the challenge,
but it&amp;rsquo;s still not enough. I&amp;rsquo;ll have to come back to this problem
again.&lt;/p&gt;</description></item><item><title>SpamAssassin Additions</title><link>https://www.wormbytes.ca/software/spamassassin/</link><pubDate>Mon, 20 Jun 2005 22:38:34 +0000</pubDate><author>Robert James Kaes</author><guid>https://www.wormbytes.ca/software/spamassassin/</guid><description>&lt;h2 id="delivery"&gt;Delivery Scripts&lt;/h2&gt;
&lt;p&gt;
I've written a &lt;a href="https://www.wormbytes.ca/software/spamassassin/spamassassin.sh.txt"&gt;shell script&lt;/a&gt; that handles
local delivery of email in a &lt;a href="http://www.qmail.org/"&gt;qmail&lt;/a&gt;
environment.
&lt;/p&gt;
&lt;p&gt;
To use the script you would place it in your &lt;tt&gt;.qmail&lt;/tt&gt; file
similar to this:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
.qmail:
|/usr/local/bin/spamassassin.sh
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
&lt;em&gt;Of course, use the correct path to the script on your system.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
I wrote this script (rather than using
&lt;a href="http://www.gbnet.net/~jrg/qmail/ifspamh/"&gt;&lt;tt&gt;ifspamh&lt;/tt&gt;&lt;/a&gt;)
because I needed a way to delete high scoring messages that could be
customized by the end user. In addition, I didn't want to store the
full message in memory like &lt;tt&gt;ifspamh&lt;/tt&gt; does.
&lt;/p&gt;
&lt;h3&gt;Required Software&lt;/h3&gt;
&lt;p&gt;
The following packages are required to be installed and working
correctly for the &lt;a href="https://www.wormbytes.ca/software/spamassassin/spamassassin.sh.txt"&gt;&lt;tt&gt;spamassassin.sh&lt;/tt&gt;&lt;/a&gt;
to work properly:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://spamassassin.org/"&gt;SpamAssassin&lt;/a&gt; (of
course)&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.qmail.org/"&gt;qmail&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;tt&gt;822field&lt;/tt&gt; from
DJB's &lt;a href="http://cr.yp.to/mess822.html"&gt;mess822&lt;/a&gt; package.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.courier-mta.org/reformail.html"&gt;&lt;tt&gt;reformail&lt;/tt&gt;&lt;/a&gt;
from &lt;a href="http://www.flounder.net/~mrsam/maildrop/"&gt;maildrop&lt;/a&gt; package.
&lt;/li&gt;
&lt;li&gt;&lt;a
href="http://budney.homeunix.net:8080/users/budney/linux/software/safecat.html"&gt;&lt;tt&gt;safecat&lt;/tt&gt;&lt;/a&gt;
for writing an email message safely to a Maildir mailbox. You will
then need the &lt;a href="https://www.wormbytes.ca/software/spamassassin/maildir"&gt;&lt;tt&gt;maildir&lt;/tt&gt;&lt;/a&gt; script to call
&lt;tt&gt;safecat&lt;/tt&gt; correctly.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;spam_bounce&lt;/h3&gt;
&lt;p&gt;
The above shell script does rely on one extra program called
&lt;tt&gt;spam_bounce&lt;/tt&gt;. This program takes an email address on standard
input and returns a numerical limit for that user on standard output.
If there is no numerical limit for the supplied email address, it &lt;b&gt;must&lt;/b&gt;
return 0. The score returned by &lt;tt&gt;spam_bounce&lt;/tt&gt; is used to
determine whether to deliver the message or to delete it. Any email
messages scored by SpamAssassin higher than the value returned by
&lt;tt&gt;spam_bounce&lt;/tt&gt; will be deleted from the user's mailbox. The
default bounce score is defined in
&lt;a href="https://www.wormbytes.ca/software/spamassassin/spamassassin.sh.txt"&gt;spamassassin.sh&lt;/a&gt; as 13.75.
&lt;/p&gt;
&lt;p&gt;
I separated the &lt;tt&gt;spam_bounce&lt;/tt&gt; functionality out of the main
delivery script because different people would have this spam score
limit information stored differently. The simplest method would be
to have a shell script that looked up the information is a flat text
file. On my system, I have a C program that retrieves the information
from a &lt;a href="http://www.mysql.org/"&gt;MySQL&lt;/a&gt; database where all
the SpamAssassin user preferences are stored.
&lt;/p&gt;
&lt;h2 id="rules"&gt;Custom Rules&lt;/h2&gt;
&lt;p&gt;
The local rules used by the Flarenet mail server are updated on a
daily basis. I'm using a new system where I annotate when each rule
was added or modified and why.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="https://www.wormbytes.ca/software/spamassassin/rules.cf"&gt;Local SpamAssassin Rules&lt;/a&gt;
&lt;/p&gt;</description></item><item><title>Additions for Qpsmtpd</title><link>https://www.wormbytes.ca/software/qpsmtpd/</link><pubDate>Sat, 12 Mar 2005 23:56:52 +0000</pubDate><author>Robert James Kaes</author><guid>https://www.wormbytes.ca/software/qpsmtpd/</guid><description>&lt;h2&gt;Plugins&lt;/h2&gt;
&lt;p&gt;
These plugins are used daily by the &lt;a href="http://www.flarenet.com/"&gt;Flarenet ISP&lt;/a&gt;
mail server, but I have not submitted them to the Qpsmtpd maintainers.
As always, use these plugins at your own risk. They work for me, but
as far as I know I'm the &lt;em&gt;only&lt;/em&gt; one using them.
&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;&lt;a href="https://www.wormbytes.ca/software/qpsmtpd/check_badpatterns"&gt;check_badpatterns&lt;/a&gt;&lt;/dt&gt;
&lt;dd&gt;Use the existing &lt;tt&gt;badmailpatterns&lt;/tt&gt; and &lt;tt&gt;badrcptpatterns&lt;/tt&gt;
control files from the
&lt;a href="http://www.fehcom.de/qmail/spamcontrol.html"&gt;SPAMCONTROL&lt;/a&gt;
patch.&lt;/dd&gt;
&lt;dt&gt;&lt;a href="https://www.wormbytes.ca/software/qpsmtpd/check_domain_regexp"&gt;check_domain_regexp&lt;/a&gt;&lt;/dt&gt;
&lt;dd&gt;Compares the reverse DNS (the host/domain name) against a
collection of regular expressions.&lt;/dd&gt;
&lt;dt&gt;&lt;a href="https://www.wormbytes.ca/software/qpsmtpd/check_goodrcptto"&gt;check_goodrcptto&lt;/a&gt;&lt;/dt&gt;
&lt;dd&gt;Allow (or white-list) certain email &lt;tt&gt;RCPT TO&lt;/tt&gt; email
addresses or users. This is useful for allowing &lt;tt&gt;postmaster&lt;/tt&gt;
and &lt;tt&gt;abuse&lt;/tt&gt; mail through.
&lt;/dd&gt;
&lt;dt&gt;&lt;a href="https://www.wormbytes.ca/software/qpsmtpd/rblsmtpd_env"&gt;rblsmtpd_env&lt;/a&gt;&lt;/dt&gt;
&lt;dd&gt;Mimics &lt;a href="http://cr.yp.to/ucspi-tcp/rblsmtpd.html"&gt;rblsmtpd&lt;/a&gt;
functionality with respect to the RBLSMTPD environment variable.&lt;/dd&gt;
&lt;/dl&gt;
&lt;h2&gt;Pending Patches&lt;/h2&gt;
&lt;p&gt;
The following patches have been sent to the Qpsmtpd
&lt;a href="http://nntp.x.perl.org/group/perl.qpsmtpd"&gt;mailing list&lt;/a&gt;,
but are not currently part of the Qpsmtpd distribution. &lt;em&gt;The date
in brackets is the day I submitted the patch.&lt;/em&gt;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;[2003-12-30] &lt;a href="https://www.wormbytes.ca/software/qpsmtpd/lib.qpsmtpd.smtp.reject-bare-crlf.patch"&gt;
Reject any mail with either a bare carriage-return or bare line-feed
in the header of the mail message.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[2003-12-22] &lt;a href="https://www.wormbytes.ca/software/qpsmtpd/lib.qpsmtpd.transaction.create-unlink.patch"&gt;
After creating the temporary file, unlink it right away. Also make
sure the temporary file doesn't exist before creation.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[2003-09-05] &lt;a href="https://www.wormbytes.ca/software/qpsmtpd/plugin.rhsbl.patch"&gt;Rewrote the
&lt;tt&gt;rhsbl&lt;/tt&gt; plugin to look up the DNS queries in the background.
Also added a configuration option to return soft errors.&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;[2003-09-04] &lt;a href="https://www.wormbytes.ca/software/qpsmtpd/lib.qpsmtpd.smtp.patch"&gt;Fix a problem with
bare linefeed messages being left in the spool directory&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[2003-08-28] &lt;a href="https://www.wormbytes.ca/software/qpsmtpd/lib.qpsmtpd.transaction.patch"&gt;Make the temporary files
mode 0600&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[2003-08-27] &lt;a href="https://www.wormbytes.ca/software/qpsmtpd/plugin.check_badrcptto.patch"&gt;Fixed a warning in
the &lt;tt&gt;check_badrcptto&lt;/tt&gt; plugin&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>