aboutsummaryrefslogtreecommitdiffstats
path: root/dist-tools
diff options
context:
space:
mode:
authorGraham Wilson <graham@mknod.org>2004-08-30 01:34:48 +0000
committerGraham Wilson <graham@mknod.org>2004-08-30 01:34:48 +0000
commitc3a80da98846c21a5d3f32a91669d78774a0aa6a (patch)
tree72bee6836c468c8527560821cd65618f2c7b115d /dist-tools
parentfd2543489b53fe34a18b7204d6803bf527c0d198 (diff)
downloadfetchmail-c3a80da98846c21a5d3f32a91669d78774a0aa6a.tar.gz
fetchmail-c3a80da98846c21a5d3f32a91669d78774a0aa6a.tar.bz2
fetchmail-c3a80da98846c21a5d3f32a91669d78774a0aa6a.zip
Move a handful of scripts (used for releases, testing, etc.) to dist-tools, so that they are not released in the tarball.
svn path=/trunk/; revision=3934
Diffstat (limited to 'dist-tools')
-rwxr-xr-xdist-tools/getstats.py18
-rwxr-xr-xdist-tools/growthplot114
-rwxr-xr-xdist-tools/indexgen.sh386
-rwxr-xr-xdist-tools/listsize36
-rwxr-xr-xdist-tools/makerelease176
-rw-r--r--dist-tools/test/test-request20
-rwxr-xr-xdist-tools/test/testmail10
-rwxr-xr-xdist-tools/test/testmda10
-rw-r--r--dist-tools/test/testrc14
-rwxr-xr-xdist-tools/test/testservers-gen.sh57
-rw-r--r--dist-tools/test/testservers.html64
-rw-r--r--dist-tools/test/torturetest.glade976
-rw-r--r--dist-tools/test/torturetest.gladep7
-rwxr-xr-xdist-tools/test/torturetest.py326
-rwxr-xr-xdist-tools/timeplot40
-rwxr-xr-xdist-tools/timeseries101
-rwxr-xr-xdist-tools/upload26
-rwxr-xr-xdist-tools/uploadfaq24
18 files changed, 2405 insertions, 0 deletions
diff --git a/dist-tools/getstats.py b/dist-tools/getstats.py
new file mode 100755
index 00000000..f957c7d3
--- /dev/null
+++ b/dist-tools/getstats.py
@@ -0,0 +1,18 @@
+#!/usr/bin/env python
+#
+# Collect statistics on current release.
+
+import commands, string, ftplib
+
+# Get version and date
+date = commands.getoutput("date")
+ln = commands.getoutput("co -p RCS/*.[chly],v 2>/dev/null | wc -l")
+vers = commands.getoutput("sed -n -e '/VERSION/s/VERSION *= *\\(.*\\)/\\1/p' <Makefile")
+print "fetchmail-" + vers + " (" + date + "), " + string.strip(ln) + " lines:"
+
+# Use local listsize command to grab list statistics
+friends = commands.getoutput("listsize friends").strip()
+announce = commands.getoutput("listsize announce").strip()
+print "There are %s people on fetchmail-friends and %s on fetchmail-announce."% (friends, announce)
+
+# getstats.py
diff --git a/dist-tools/growthplot b/dist-tools/growthplot
new file mode 100755
index 00000000..73f4f4e9
--- /dev/null
+++ b/dist-tools/growthplot
@@ -0,0 +1,114 @@
+#!/bin/sh
+#
+# growthplot -- plot the fetchmail project's growth as a function of time
+#
+
+PATH="$PATH:.:./dist-tools"; export PATH
+
+tmp=/tmp/fetchmail-growthplot.$$
+mkdir $tmp
+
+# Get data from the NEWS file
+timeseries >$tmp/growthplot$$
+grep "^[0-9]" $tmp/growthplot$$ >$tmp/growthnumbers$$
+grep "^[0-9.]*.[05].0 " $tmp/growthplot$$ >$tmp/growthmajors$$
+sed '/^4.2.9/,$d' <$tmp/growthnumbers$$ >$tmp/growthannounce$$
+
+# gnuplot line styles. These occasionally change (like beteween 3.5 and 3.7);
+# use "echo 'set terminal png; test' | gnuplot | display -" to check.
+blue_boxes=3
+green_crosses=2
+cyan_diamonds=37 # Once purple triangles, but we can't do that anymore
+brown_triangles=23
+
+cat >$tmp/growthimage$$ <<EOF
+set title "Fetchmail project growth history"
+set xlabel 'Days since baseline'
+set ylabel 'Participants'
+set y2label 'Lines of code'
+set ytics nomirror
+set y2tics
+set tics out
+set autoscale y
+set y2range [5000:50000]
+set key bottom right box
+set terminal png
+
+EOF
+
+# OK, now write the event labels
+(
+ count=0
+ lastday=0
+ breakheight=510
+ while read version legend
+ do
+ if [ "$version" = '%' ]
+ then
+ echo "# Associate $lastday to '$legend'"
+ count=$((count+1))
+ lastday=$(($lastday-5))
+ endy=$((breakheight+50+count*50))
+ if ((endy>lasttotal))
+ then
+ # Label over curve hanging right, arrow down
+ arrowhead=$((lasttotal+50))
+ echo "set label '$legend' at $lastday-10, $endy+15"
+ else
+ # Label under curve hanging left, arrow up
+ arrowhead=$((lasttotal-5))
+ strlen=`python -c "print len('$legend')"`
+ lablen=$((strlen*22))
+ echo "set label '$legend' at $lastday-$lablen+10, $endy-15"
+ fi
+ echo set arrow \
+ from $lastday, $endy \
+ to $lastday, $arrowhead \
+ head
+ else
+ set -- $legend
+ size=$1
+ friends=$2
+ announce=$3
+ total=$4
+ days=$5
+ date=$6
+ lastday=$days
+ lasttotal=$total
+ fi
+ done
+) <$tmp/growthplot$$ >>$tmp/growthimage$$
+
+# OK, now write the major-release labels
+(
+ while read version size friends announce total days date
+ do
+ echo "set arrow from $days, $total - 55 to $days, $total - 15 head"
+ echo "set label '$version' at $days - 5, $total - 65"
+ done
+) <$tmp/growthmajors$$ >>$tmp/growthimage$$
+
+cat >>$tmp/growthimage$$ <<EOF
+plot [] [0:] '$tmp/growthnumbers$$' using 6:5 \
+ title "Both lists" with points $blue_boxes, \
+ '$tmp/growthannounce$$' using 6:4 \
+ title "fetchmail-announce" with points $cyan_diamonds, \
+ '$tmp/growthannounce$$' using 6:3 \
+ title "fetchmail-friends" with points $green_crosses, \
+ '$tmp/growthnumbers$$' using 6:2 axes x1y2 \
+ title "Lines of code" with points $brown_triangles
+EOF
+
+gnuplot $tmp/growthimage$$ >growth.png
+
+rm -f $tmp/growth*
+rmdir $tmp
+
+# growthplot ends here
+
+
+
+
+
+
+
diff --git a/dist-tools/indexgen.sh b/dist-tools/indexgen.sh
new file mode 100755
index 00000000..0fac4259
--- /dev/null
+++ b/dist-tools/indexgen.sh
@@ -0,0 +1,386 @@
+#!/bin/sh
+#
+# indexgen.sh -- generate current version of fetchmail home page.
+#
+goldvers="6.2.0"
+goldname="6.2.0"
+version=`sed -n <Makefile.in "/VERSION *= */s/VERSION *= *\([^ ]*\)/\1/p"`
+date=`date "+%d %b %Y"`
+
+set -- `timeseries | grep -v "[%#]" | head -1`
+subscribers=$4
+make fetchmail
+set -- `ls -ks fetchmail`
+fetchmailsize=$1
+set -- `(cd /lib; ls libc-*)`
+glibc=`echo $1 | sed 's/libc-\(.*\)\.so/\1/'`
+glibc="glibc-$glibc"
+
+rm -f index.html
+
+# Compute MD5 checksums for security audit
+rm -f checksums
+for file in fetchmail-$version.tar.gz fetchmail-$version-1.*.rpm
+do
+ md5sum $file >>checksums
+done
+
+if [ $version != $goldvers ]
+then
+ for file in fetchmail-$goldvers.tar.gz fetchmail-$goldvers-1.*.rpm
+ do
+ md5sum $file | sed -e "s: .*/: :" >>checksums
+ done
+fi
+
+# Cryptographically sign checksums
+gpg --clearsign checksums
+mv checksums.asc checksums
+
+cat >index.html <<EOF
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<link rev="made" href="mailto:esr@snark.thyrsus.com" />
+<link rel="stylesheet" href="/~esr/sitestyle.css" type="text/css"/>
+<meta name="description" content="Home page of the fetchmail project" />
+<meta name="keywords" content="" />
+<meta name="MSSmartTagsPreventParsing" content="TRUE" />
+<title>The fetchmail home page</title>
+</head>
+<body>
+
+<div id="Header">
+<table width="100%" cellpadding="0" summary="Canned page header">
+<tr>
+<td>The fetchmail home page</td>
+<td align="right">$date</td>
+</tr>
+</table>
+</div>
+
+<div id="Menu">
+ <hr/>
+ <a href="/~esr" title="My home page">Home Page</a><br />
+ <a href="/~esr/sitemap.html" title="Map of the site">Site Map</a><br />
+ <a href="/~esr/software.html" title="Software I maintain">Software</a><br />
+ <a href="/~esr/projects.html" title="My projects">Projects</a><br />
+ <a href="/~esr/faqs/" title="My FAQ documents">HOWTOs</a><br />
+ <a href="/~esr/writings/" title="Essays and ruminations">Essays</a><br />
+ <a href="/~esr/personal.html" title="Portrait of the author">Personal</a><br />
+ <a href="http://www.ibiblio.org/esrblog/">Weblog</a><br/>
+ <a href="/~esr/netfreedom/">Freedom!</a><br />
+ <a href="/~esr/guns/">Firearms!</a><br />
+ <hr/>
+</div>
+
+<div id="Content">
+
+<h1>The fetchmail Home Page</h1>
+</center>
+
+<p><b>Note: if you are a stranded fetchmail.com user, we're sorry but
+we have nothing to do with that site and cannot help you. It's just an
+unfortunate coincidence of names.</b></p>
+
+<h1>What fetchmail does:</h1>
+
+<p>Fetchmail is a full-featured, robust, well-documented
+remote-mail retrieval and forwarding utility intended to be used over
+on-demand TCP/IP links (such as SLIP or PPP connections). It supports
+every remote-mail protocol now in use on the Internet: POP2, POP3,
+RPOP, APOP, KPOP, all flavors of <a
+href="http://www.imap.org">IMAP</a>, ETRN, and ODMR. It can even
+support IPv6 and IPSEC.</p>
+
+<p>Fetchmail retrieves mail from remote mail servers and forwards it via
+SMTP, so it can then be read by normal mail user agents such as <a
+href="http://www.mutt.org/">mutt</a>, elm(1) or BSD Mail.
+It allows all your system MTA's filtering, forwarding, and aliasing
+facilities to work just as they would on normal mail.</p>
+
+<p>Fetchmail offers better security than any other Unix remote-mail
+client. It supports APOP, KPOP, OTP, Compuserve RPA, Microsoft NTLM,
+and IMAP RFC1731 encrypted authentication methods including CRAM-MD5
+to avoid sending passwords en clair. It can be configured to support
+end-to-end encryption via tunneling with <a
+href="http://www.openssh.com/">ssh, the Secure Shell</a>.</p>
+
+<p>Fetchmail can be used as a POP/IMAP-to-SMTP gateway for an entire DNS
+domain, collecting mail from a single drop box on an ISP and
+SMTP-forwarding it based on header addresses. (We don't really
+recommend this, though, as it may lose important envelope-header
+information. ETRN or a UUCP connection is better.)</p>
+
+<p>Fetchmail can be started automatically and silently as a system daemon
+at boot time. When running in this mode with a short poll interval,
+it is pretty hard for anyone to tell that the incoming mail link is
+not a full-time "push" connection.</p>
+
+<p>Fetchmail is easy to configure. You can edit its dotfile directly, or
+use the interactive GUI configurator (fetchmailconf) supplied with the
+fetchmail distribution. It is also directly supported in linuxconf
+versions 1.16r8 and later.</p>
+
+<p>Fetchmail is fast and lightweight. It packs all its standard
+features (POP3, IMAP, and ETRN support) in ${fetchmailsize}K of core on a
+Pentium under Linux.</p>
+
+<p>Fetchmail is <a href="http://www.opensource.org">open-source</a>
+software. The openness of the sources is your strongest possible
+assurance of quality and reliability.</p>
+
+<h1>Where to find out more about fetchmail:</h1>
+
+<p>See the <a href="fetchmail-features.html">Fetchmail Feature List</a> for more
+about what fetchmail does.</p>
+
+<p>See the on-line <a href="fetchmail-man.html">manual page</a> for
+basics.</p>
+
+<p>See the <a href="fetchmail-FAQ.html">HTML Fetchmail FAQ</a> for
+troubleshooting help.</p>
+
+<p>See the <a href="design-notes.html">Fetchmail Design Notes</a>
+for discussion of some of the design choices in fetchmail.</p>
+
+<p>See the project's <a href="todo.html">To-Do list</a> for indications
+of known problems and requested features.</p>
+
+<h1>How to get fetchmail:</h1>
+
+<p>You can get any of the following leading-edge resources here:</p>
+<ul>
+<li> <a href="fetchmail-$version.tar.gz">
+ Gzipped source archive of fetchmail $version</a>
+<li> <a href="fetchmail-$version-1.i386.rpm">
+ Intel binary RPM of fetchmail $version (uses $glibc)</a>
+<li> <a href="fetchmail-$version-1.src.rpm">
+ Source RPM of fetchmail $version</a>
+</ul>
+
+<p>MD5 <a href="checksums">checksums</a> are available for these files; the
+checksum file is cryptographically signed and can be verified with the
+command:</p>
+
+<pre>
+gpg --verify checksums
+</pre>
+
+EOF
+
+if [ $version != $goldvers ]
+then
+ cat >>index.html <<EOF
+
+<p>Or you can get the last \`gold' version, $goldname:</p>
+<ul>
+<li> <a href="fetchmail-$goldvers.tar.gz">
+ Gzipped source archive of fetchmail $goldname</a>
+<li> <a href="fetchmail-$goldvers-1.i386.rpm">
+ Intel binary RPM of fetchmail $goldname (uses glibc)</a>
+<li> <a href="fetchmail-$goldvers-1.alpha.rpm">
+ Alpha binary RPM of fetchmail $goldname (uses glibc)</a>
+<li> <a href="fetchmail-$goldvers-1.src.rpm">
+ Source RPM of fetchmail $goldname</a>
+</ul>
+
+<p>The <a href="fetchmail-$goldvers.tar.gz.asc">detached GPG
+signature</a> for the binary tarball can be used to check it for
+correctness, with the command</p>
+
+<pre>
+gpg --verify fetchmail-$goldvers.tar.gz.asc fetchmail-$goldvers.tar.gz
+</pre>
+
+<p>For differences between the leading-edge $version and gold $goldname versions,
+see the distribution <a href="NEWS">NEWS</a> file.</p>
+EOF
+fi
+
+cat >>index.html <<EOF
+<p>(Note that the binary RPMs don't have the POP2, OTP, IPv6, Kerberos,
+GSSAPI, Compuserve RPA, Microsoft NTLM, or GNU gettext
+internationalization support compiled in. To get any of these you
+will have to build from sources.)</p>
+
+<p>The latest version of fetchmail is also carried in the
+<a href="http://metalab.unc.edu/pub/Linux/system/mail/pop/!INDEX.html">
+Metalab remote mail tools directory</a>.</p>
+
+<h1>Getting help with fetchmail:</h1>
+
+<p>There is a fetchmail-friends list for people who want to discuss
+fixes and improvements in fetchmail and help co-develop it. It's a
+MailMan list, which you can sign up for at <a
+href="http://lists.ccil.org/mailman/listinfo/fetchmail-friends">
+fetchmail-friends@ccil.org</a>. There is also an announcements-only
+list, <a
+href="http://lists.ccil.org/mailman/listinfo/fetchmail-announce">
+fetchmail-announce@lists.ccil.org</a>.</p>
+
+<p>Note: before submitting a question to the list, <strong>please read
+the <a href="fetchmail-FAQ.html">FAQ</a></strong> (especially item <a
+href="fetchmail-FAQ.html#G3">G3</a> on how to report bugs). We
+tend to get the same three newbie questions over and over again. The
+FAQ covers them like a blanket.</p>
+
+<p>Fetchmail was written and is maintained by <a
+href="../index.html">Eric S. Raymond</a>. There are some designated
+backup maintainers (<a href="mailto:rfunk@funknet.net">Rob Funk</a>, <a
+href="http://www.dallas.net/~fox/">David DeSimone aka Fuzzy Fox</a>,
+<a href="mailto:imdave@mcs.net">Dave Bodenstab</a> and <a
+href="mailto:shetye@bombay.retortsoft.com">Sunil Shetye</a>). Other backup
+maintainers may be added in the future, in order to ensure continued
+support should Eric S. Raymond drop permanently off the net for any
+reason.</p>
+
+<h1>You can help improve fetchmail:</h1>
+
+<p>I welcome your code contributions. But even if you don't write code,
+you can help fetchmail improve.</p>
+
+<p>If you administer a site that runs a post-office server, you may be
+able help improve fetchmail by lending me a test account on your site.
+Note that I do not need a shell account for this purpose, just a
+maildrop. Nor am I interested in collecting maildrops per se --
+what I'm collecting is different <em>kinds of servers</em>.</p>
+
+<p>Before each release, I run a test harness that sends date-stamped
+test mail to each site on my regression-test list, then tries to
+retrieve it. Please take a look at my <a href="testservers.html">
+list of test servers</a>. If you can lend me an account on a kind
+of server that is <em>not</em> already on this list, please do.</p>
+
+<h1>Who uses fetchmail:</h1>
+
+<p>Fetchmail entered full production status with the 2.0.0 version in
+November 1996 after about five months of evolution from the ancestral
+<code>popclient</code> utility. It has since come into extremely wide use
+in the Internet/Unix/Linux community. The Red Hat, Debian and
+Suse Linux distributions and their derivatives all include it. A
+customized version is used at Whole Earth 'Lectronic Link. Several
+large ISPs are known to recommend it to Unix-using SLIP and PPP
+customers.</p>
+
+<p>Somewhere around a thousand people have participated on the fetchmail
+beta lists (at time of current release there were $subscribers on the
+friends and announce lists). While it's hard to count the users of
+open-source software, we can estimate based on (a) population figures
+at the WELL and other known fetchmail sites, (b) the size of the
+Linux-using ISP customer base, and (c) the volume of fetchmail-related
+talk on USENET. These estimates suggest that daily fetchmail users
+number well into the hundreds of thousands, and possibly over a million.</p>
+
+<h1>The sociology of fetchmail:</h1>
+
+<p>The fetchmail development project was a sociological experiment as well
+as a technical effort. I ran it as a test of some theories about why the
+Linux development model works.</p>
+
+<p>I wrote a paper, <a
+href="http://www.catb.org/~esr/writings/cathedral-bazaar/">The
+Cathedral And The Bazaar</a>, about these theories and the project.
+I developed the line of analysis it suggested in two later essays.
+These papers became quite popular and (to my continuing astonishment) may
+have actually helped change the world. Chase the title link, above,
+for links to all three papers.</p>
+
+<p>I have done some analysis on the information in the project NEWS file.
+You can view a <a href="history.html">statistical history</a> showing
+levels of participation and release frequency over time.</p>
+
+<h1>Recent releases and where fetchmail is going:</h1>
+
+<p>Fetchmail is now sufficiently stable and effective that I'm getting
+very little pressure to fix things or add features. Development has
+slowed way down, release frequency has dropped off, and we're
+basically in maintainance mode.</p>
+
+<p>Major changes or additions therefore seem unlikely until there are
+significant changes in or additions to the related protocol RFCs.</p>
+
+<h1>Where you can use fetchmail:</h1>
+
+<p>The fetchmail code was developed under Linux, but has also been
+extensively tested under 4.4BSD, SunOS, Solaris, AIX, and NEXTSTEP. It
+should be readily portable to other Unix variants (it requires only
+POSIX plus BSD sockets, and uses GNU autoconf).</p>
+
+<p>Fetchmail is supported only for Unix by its official maintainers.
+However, it is reported to build and run correctly under BeOS,
+AmigaOS, Rhapsody, and QNX as well. There is a CygWin port.</p>
+
+<h1>Related resources:</h1>
+
+<p>Jochen Hayek is developing a set of
+<a href="http://www.ACM.org/~Jochen_Hayek/JHimap_utils/">
+IMAP tools in Python</a> that read your .fetchmailrc file and are
+designed to work with fetchmail. Jochen's tools can report selected
+header lines, or move incoming messages to named mailboxes based on
+the contents of headers.</p>
+
+<p>Donncha O Caoihm has written a Perl script called
+<a href="http://cork.linux.ie/projects/install-sendmail/">install-sendmail</a>
+that assists you in installing sendmail and fetchmail together.</p>
+
+<p>Peter Hawkins has written a script called <a
+href="http://linux.cudeso.be/linuxdoc/gotmail.php">gotmail</a> that
+can retrieve Hotmail. Another script, <a
+href="http://yosucker.sourceforge.net">yosucker</a>, can retrieve
+Yahoo webmail.</p>
+
+<p>There's a program called
+<http://mailfilter.sourceforge.net/'>mailfilter</a> which can be used
+to do span filtering, that works particularly well called from fetchmail's
+<code>preconnect</code> directive,</p>
+
+<p>A hacker identifying himself simply as \`Steines' has written a
+filter which rewrites the to-line with a line which only includes
+receipients for a given domain and renames the old to-line. It also
+rewrites the domain-part of addresses if the offical domain is
+different from the local domain. You can find it <a
+href="http://www.steines.com/mailf/">here</a>.</p>
+
+<h1>Fetchmail's funniest fan letter:</h1>
+
+<a href="funny.html">This letter</a> still cracks me up whenever I reread it.
+
+<h1>The fetchmail button:</h1>
+
+<p>If you use fetchmail and like it, here's a nifty fetchmail button you
+can put on your web page:</p>
+
+<center><img src="fetchmail.png" alt="fetchmail logo" /></center>
+
+<p>Thanks to <a href="http://www.gl.umbc.edu/~smatus1/">Steve
+Matuszek</a> for the graphic design. The hand in the button (and the
+larger top-of-page graphic) was actually derived from a color scan of
+the fetchmail author's hand.</p>
+
+<h1>Fetchmail mirror sites:</h1>
+
+<p>There is a FTP mirror of the current sources and RPMs in Japan at
+<a href="ftp://ftp.win.ne.jp/pub/network/mail/fetchmail">
+ftp://ftp.win.ne.jp/pub/network/mail/fetchmail</a>.
+
+<h1>Reviews and Awards</h1>
+
+<p>Fetchmail was DaveCentral's Best Of Linux winner for
+<a href="http://linux.davecentral.com/bol_19990630.html">June 30 1999</a>.</p>
+
+<p>Fetchmail was a five-star Editor's Pick at Softlandindia.</p>
+
+</div>
+
+</body>
+</html>
+EOF
+
+# The following sets edit modes for GNU EMACS
+# Local Variables:
+# mode:html
+# truncate-lines:t
+# End:
diff --git a/dist-tools/listsize b/dist-tools/listsize
new file mode 100755
index 00000000..73e25887
--- /dev/null
+++ b/dist-tools/listsize
@@ -0,0 +1,36 @@
+#!/bin/sh
+#
+# Mine list sizes from MailMan web interfaces
+#
+# * Must set environment variable FETCHMAIL_LIST_PASS to list admin password
+
+project="fetchmail"
+admin="http://lists.berlios.de/mailman/admin"
+adminpw=$FETCHMAIL_LIST_PASS
+
+list="$1"
+if [ ! "$list" ]; then
+ echo "Usage: $0 list" 1>&2
+ exit 1
+fi
+case "$list" in
+$project-*)
+ # already gave us the full name, e.g. fetchmail-announce
+ ;;
+*)
+ # only gave us the last part of the name, e.g. announce
+ list="$project-$list"
+ ;;
+esac
+
+hexpw=`echo "$adminpw" | od -t x1 -w64 | sed -e 's/^[0-9]*//' -e '/^ *$/d' -e 's/ /%/g'`
+umask 077
+tmp="/tmp/$project-$list.listsize.$$"
+# First get the login cookie...
+curl -s -D "$tmp" "$admin/${list}?adminpw=$hexpw" >/dev/null
+# Second gets the actual stat
+curl -s -b "$tmp" "$admin/${list}/members" \
+ | sed -n '/.*>(\([0-9][0-9]*\) members total.*/s//\1/p'
+rm -f "$tmp"
+# end
+
diff --git a/dist-tools/makerelease b/dist-tools/makerelease
new file mode 100755
index 00000000..41ddf038
--- /dev/null
+++ b/dist-tools/makerelease
@@ -0,0 +1,176 @@
+#!/usr/bin/env perl
+#
+# Make a fetchmail release. Must be run as root, to make RPMs.
+# Dumps a release notice and diffs as a MIME multipart message
+# in RELEASE_NOTES
+#
+use POSIX qw(strftime);
+$timezone = strftime('%z', localtime) || "-0500";
+$tmp = $ENV{TMPDIR} || $ENV{TMP} || $ENV{TEMP} || "/tmp";
+
+$project = "fetchmail";
+$svnrepos = "svn://svn.berlios.de/$project";
+$website = "http://developer.berlios.de/projects/$project";
+$mailfrom = "<$project-devel-owner\@lists.berlios.de> (Fetchmail Development Team)";
+
+# parse options
+$diffs = 0;
+$verbose = 0;
+$null = ">/dev/null";
+$errnull = "2>/dev/null";
+while ($i = shift @ARGV)
+{
+ if ($i =~ /^(--diffs|-d)$/i)
+ {
+ $diffs = 1;
+ next;
+ }
+
+ if ($i =~ /^(--verbose|-v)$/i)
+ {
+ $verbose = 1;
+ $null = "";
+ next;
+ }
+
+ die "Error: Unknown option: $i\n";
+}
+
+# extract version from source
+$version=`grep 'AC_INIT' configure.in`;
+$version =~ /AC_INIT\([^,]*,\[?([0-9.]+)\]?\)/;
+$version = $1;
+die "cannot determine version" unless defined $1;
+$tag = "RELEASE_$version";
+$tag =~ tr/./-/;
+
+# extract existing tags
+open(ID, "svn ls $svnrepos/tags|");
+while (<ID>) {
+ if (m{^(RELEASE_.*)/}) {
+ unshift(@versions, $1);
+ }
+}
+close(ID);
+
+if ($versions[0] eq $tag) {
+ $tag = $versions[0];
+ $oldtag = $versions[1];
+} else {
+ $tag = '<workfile>';
+ $oldtag = $versions[0];
+}
+
+$ENV{PATH} .= ":./dist-tools:./dist-tools/shipper:.";
+
+print "Building $version release, tag $tag, previous tag $oldtag\n";
+
+if (-d autom4te.cache) {
+ system("rm -rf autom4te.cache")
+ and die "Failure in removing autom4te.cache";
+}
+
+if (system("autoreconf -isv")) {
+ die("Failure in regenerating autoconf files\n");
+}
+
+if (system("./configure && make clean && make -C po update-po && make clean")) {
+ die("Failure in translation-file rebuild\n");
+}
+
+print "### Test-building the software...\n";
+if (system("./configure && make clean && make all check")) {
+ die("Compilation failure\n");
+}
+
+print "### Building the distribution...\n";
+if (system("make dist $null")) {
+ die("Distribution-build failure\n");
+}
+
+print "### Building the RPMs...\n";
+if (system("buildrpms $project-${version}.tar.gz $null")) {
+ die("RPM-build failure\n");
+}
+
+open(REPORT, ">$tmp/$project.PREAMBLE.$$");
+
+print REPORT <<EOF;
+From: $mailfrom
+Subject: The $version release of $project is available
+
+The $version release of $project is now available at the usual locations,
+including <URL:$website>.
+
+The source archive is available at:
+<URL:$website/$project-${version}.tar.gz>
+
+Here are the release notes:
+
+EOF
+
+# Extract the current notes
+open(NEWS, "NEWS");
+while (<NEWS>) {
+ if (/^$project/) {
+ print REPORT $_;
+ last;
+ }
+}
+while (<NEWS>) {
+ if (/^$project/) {
+ last;
+ }
+ print REPORT $_;
+}
+
+$oldver = $oldtag;
+$oldver =~ tr/-/./;
+$oldver =~ s/^RELEASE_//;
+
+if ($diffs) {
+ print REPORT "Diffs from the previous ($oldver) release follow as a MIME attachment."
+} else {
+ print REPORT "By popular demand, diffs from the previous release have been omitted."
+}
+
+close(NEWS);
+
+close(REPORT);
+
+if ($tag eq '<workfile>') {
+ system("svn diff -r$oldtag $errnull >$tmp/$project.DIFFS.$$");
+} else {
+ system("svn diff -r$oldtag -r$tag $errnull >$tmp/$project.DIFFS.$$");
+}
+print "Diff size:";
+system("wc <$tmp/$project.DIFFS.$$");
+
+if ($diffs) {
+ system "metasend -b"
+ ." -D '$project-$tag announcement' -m 'text/plain' -e 7bit -f $tmp/$project.PREAMBLE.$$"
+ ." -n -D 'diff between $oldver and $version' -m 'text/plain' -e 7bit -f $tmp/$project.DIFFS.$$"
+ ." -o ANNOUNCE.EMAIL";
+} else {
+ rename("$tmp/$project.PREAMBLE.$$", "ANNOUNCE.EMAIL");
+}
+#system("chown esr ANNOUNCE.EMAIL");
+#chmod(0700, "ANNOUNCE.EMAIL");
+
+#unlink("$tmp/$project.PREAMBLE.$$");
+unlink("$tmp/$project.DIFFS.$$");
+
+print "Building index page...\n";
+system("rm -f index.html; indexgen.sh");
+
+if (-r "testsites") {
+ print "Building test server list...\n";
+ system("rm -f testservers.html; testservers-gen.sh >testservers.html");
+}
+
+print "Making activity graph...";
+system "growthplot";
+
+print "Done\n";
+
+# makerelease ends here
diff --git a/dist-tools/test/test-request b/dist-tools/test/test-request
new file mode 100644
index 00000000..160c1885
--- /dev/null
+++ b/dist-tools/test/test-request
@@ -0,0 +1,20 @@
+I maintain an open-source POP and IMAP client called fetchmail. It is
+widely used in the Linux and open-source community, and is probably
+the single most popular remote-mail client in that world. You can
+find out more about this project at
+<http://www.catb.org/~esr/fetchmail>.
+
+In order to be able to do thorough regression testing before each release,
+I collect test accounts on as many different kinds of POP3, IMAP, and
+ODMR servers as possible. Because fetchmail is strictly conformant to the
+remote-mail RFCs, many server developers have found fetchmail a useful
+standards-conformance test.
+
+I'm writing to request test accounts on your server. I support all flavors
+of POP2, POP3, IMAP and ODMR with either plain-password, CRAM-MD5, NTLM,
+GSSAPI, or Kerberos authentication. I also support SSL/TLS.
+
+It would be very helpful if I could have a separate test account for
+each protocol you support (that is, separate POP3, IMAP, and ODMR
+accounts) so I can do automated regression testing without worrying
+about mailbox race conditions.
diff --git a/dist-tools/test/testmail b/dist-tools/test/testmail
new file mode 100755
index 00000000..7941892e
--- /dev/null
+++ b/dist-tools/test/testmail
@@ -0,0 +1,10 @@
+#!/bin/sh
+size=${1:-0}
+
+(
+echo "This mail was generated on "`date`"."
+
+) | mail -s "${size}k test mail from process $$" esr@ccil.org
+
+ <<EOF
+EOF
diff --git a/dist-tools/test/testmda b/dist-tools/test/testmda
new file mode 100755
index 00000000..98a7c760
--- /dev/null
+++ b/dist-tools/test/testmda
@@ -0,0 +1,10 @@
+#!/bin/sh
+# Test MDA for debugging fetchmail configurations.
+echo "[testmda called with the following arguments: $*]"
+
+# Display the input
+cat >/tmp/testmda$$
+echo "[text is "`wc -c </tmp/testmda$$`" bytes long]"
+cat /tmp/testmda$$
+rm /tmp/testmda$$
+
diff --git a/dist-tools/test/testrc b/dist-tools/test/testrc
new file mode 100644
index 00000000..7520f8d4
--- /dev/null
+++ b/dist-tools/test/testrc
@@ -0,0 +1,14 @@
+# Configuration created Thu Oct 23 20:13:55 2003 by fetchmailconf
+set syslog
+set postmaster "postmaster"
+set bouncemail
+set no spambounce
+set properties ""
+poll pop.whosey.net with proto POP3
+ user 'foo' there with password '*' is 'me' here
+ user 'bar' there with password '*' is 'her' here
+ user 'baz' there with password '*' is 'that' here
+
+poll mail.whatsey.ca with proto POP3 interval 60
+ user 'nimble' there with password '*' is 'her' here
+
diff --git a/dist-tools/test/testservers-gen.sh b/dist-tools/test/testservers-gen.sh
new file mode 100755
index 00000000..52a1e589
--- /dev/null
+++ b/dist-tools/test/testservers-gen.sh
@@ -0,0 +1,57 @@
+#!/bin/sh
+
+date=`date`
+cat <<EOF
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<link rev=made href="mailto:esr@snark.thyrsus.com"/>
+<meta name="description" content=""/>
+<meta name="keywords" content=""/>
+<title>Fetchmail's Test List</title>
+</head>
+<body>
+<table width="100%" cellpadding=0 summary="Canned page header"><tr>
+<td width="30%">Back to <a href="/~esr">Eric's Home Page</a>
+<td width="30%" align=center>Up to <a href="/~esr/sitemap.html">Site Map</a>
+<td width="30%" align=right>${date}
+</tr></table>
+<hr />
+<h1>Fetchmail's Test List</h1>
+
+<p>Here are the server types on my regression-test list:</p>
+
+<table border=1 width=80% align=center summary="Server list">
+<tr>
+<td><strong>Protocol &amp; Version:</strong></td>
+<td><strong>Special Options:</strong></td>
+</tr>
+EOF
+torturetest.py -t
+cat <<EOF
+</tr></table>
+
+<p>If you control a post-office server that is not one of the types listed
+here, please consider lending me a test account. Note that I do <em>not</em>
+need shell access, just the permissions to send mail to a mailbox the server
+looks at and to fetch mail off of it.</p>
+
+<p>I'd like to have weird things like a POP2 server on here. Also more
+closed-source servers because they tend to be broken in odd
+ways. These are the real robustness tests.</p>
+
+<hr />
+<table width="100%" cellpadding=0 summary="Canned page header"><tr>
+<td width="30%">Back to <a href="/~esr">Eric's Home Page</a>
+<td width="30%" align=center>Up to <a href="/~esr/sitemap.html">Site Map</a>
+<td width="30%" align=right>${date}
+</tr></table>
+
+<br clear="left" />
+<ADDRESS>Eric S. Raymond <A HREF="mailto:esr@thyrsus.com">&lt;esr@thyrsus.com&gt;</A></ADDRESS>
+</BODY>
+</HTML>
+EOF
+
diff --git a/dist-tools/test/testservers.html b/dist-tools/test/testservers.html
new file mode 100644
index 00000000..62dc9e7b
--- /dev/null
+++ b/dist-tools/test/testservers.html
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<link rev=made href="mailto:esr@snark.thyrsus.com"/>
+<meta name="description" content=""/>
+<meta name="keywords" content=""/>
+<title>Fetchmail's Test List</title>
+</head>
+<body>
+<table width="100%" cellpadding=0 summary="Canned page header"><tr>
+<td width="30%">Back to <a href="/~esr">Eric's Home Page</a>
+<td width="30%" align=center>Up to <a href="/~esr/sitemap.html">Site Map</a>
+<td width="30%" align=right>Mon Jan 12 15:52:14 EST 2004
+</tr></table>
+<hr />
+<h1>Fetchmail's Test List</h1>
+
+<p>Here are the server types on my regression-test list:</p>
+
+<table border=1 width=80% align=center summary="Server list">
+<tr>
+<td><strong>Protocol &amp; Version:</strong></td>
+<td><strong>Special Options:</strong></td>
+</tr>
+<tr><td>IMAP: CommuniGate IMAP server</td><td>IMAPrev1 STARTTLS AUTH=CRAM-MD5 AUTH=DIGEST-MD5</td>
+<tr><td>POP3: CommuniGate POP3 server</td><td>CAPA LAST APOP CRAM-MD5</td>
+<tr><td>POP3: IntraStore POP3 mail server</td><td>!CAPA LAST</td>
+<tr><td>APOP: IntraStore POP3 mail server</td><td>!CAPA LAST APOP</td>
+<tr><td>IMAP: IntraStore IMAP mail server</td><td>IMAPrev1 IDLE AUTH=CRAM-MD5 AUTH=SKEY AUTH=ANONYMOUS</td>
+<tr><td>POP3: Eudora EIMS</td><td>CAPA LAST APOP SASL CRAM-MD5 NTLM</td>
+<tr><td>POP3: gmx.de pop server</td><td>!CAPA UIDL</td>
+<tr><td>IMAP: IMail IMAP server</td><td>IMAP4rev1 AUTH=CRAM-MD5</td>
+<tr><td>IMAP: Microsoft Exchange</td><td>IDLE AUTH=NTLM</td>
+<tr><td>POP3: qpopper 3.1.2 (Eudora) patched with mysql</td><td>CAPA UIDL</td>
+<tr><td>IMAP: Courier IMAP</td><td>IMAP4rev1</td>
+<tr><td>POP3: Courier POP3</td><td>CAPA UIDL</td>
+<tr><td>APOP: Qpopper using APOP</td><td>!CAPA</td>
+<tr><td>IMAP: UW IMAP</td><td>IMAPrev1</td>
+<tr><td>IMAP: Courier IMAP</td><td>IMAP4rev1</td>
+<tr><td>POP3: Qpopper 4.0.5</td><td>CAPA UIDL</td>
+</tr></table>
+
+<p>If you control a post-office server that is not one of the types listed
+here, please consider lending me a test account. Note that I do <em>not</em>
+need shell access, just the permissions to send mail to a mailbox the server
+looks at and to fetch mail off of it.</p>
+
+<p>I'd like to have weird things like a POP2 server on here. Also more
+closed-source servers because they tend to be broken in odd
+ways. These are the real robustness tests.</p>
+
+<hr />
+<table width="100%" cellpadding=0 summary="Canned page header"><tr>
+<td width="30%">Back to <a href="/~esr">Eric's Home Page</a>
+<td width="30%" align=center>Up to <a href="/~esr/sitemap.html">Site Map</a>
+<td width="30%" align=right>Mon Jan 12 15:52:14 EST 2004
+</tr></table>
+
+<br clear="left" />
+<ADDRESS>Eric S. Raymond <A HREF="mailto:esr@thyrsus.com">&lt;esr@thyrsus.com&gt;</A></ADDRESS>
+</BODY>
+</HTML>
diff --git a/dist-tools/test/torturetest.glade b/dist-tools/test/torturetest.glade
new file mode 100644
index 00000000..d2cf07ee
--- /dev/null
+++ b/dist-tools/test/torturetest.glade
@@ -0,0 +1,976 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
+
+<glade-interface>
+
+<widget class="GtkWindow" id="torturetest">
+ <property name="visible">True</property>
+ <property name="title" translatable="yes">torturetest</property>
+ <property name="type">GTK_WINDOW_TOPLEVEL</property>
+ <property name="window_position">GTK_WIN_POS_NONE</property>
+ <property name="modal">False</property>
+ <property name="resizable">True</property>
+ <property name="destroy_with_parent">False</property>
+ <signal name="destroy" handler="on_torturetest_destroy" last_modification_time="Wed, 16 Jul 2003 18:21:37 GMT"/>
+
+ <child>
+ <widget class="GtkVBox" id="vbox1">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkHBox" id="hbox2">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkLabel" id="sitelabel">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Site select: </property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkCombo" id="combo1">
+ <property name="visible">True</property>
+ <property name="value_in_list">False</property>
+ <property name="allow_empty">True</property>
+ <property name="case_sensitive">False</property>
+ <property name="enable_arrow_keys">True</property>
+ <property name="enable_arrows_always">False</property>
+
+ <child internal-child="entry">
+ <widget class="GtkEntry" id="entry2">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="visibility">True</property>
+ <property name="max_length">0</property>
+ <property name="text" translatable="yes"></property>
+ <property name="has_frame">True</property>
+ <property name="invisible_char" translatable="yes">*</property>
+ <property name="activates_default">False</property>
+ <signal name="activate" handler="on_combo_entry1_activate" last_modification_time="Wed, 16 Jul 2003 18:48:10 GMT"/>
+ </widget>
+ </child>
+
+ <child internal-child="list">
+ <widget class="GtkList" id="list1">
+ <property name="visible">True</property>
+ <property name="selection_mode">GTK_SELECTION_BROWSE</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHSeparator" id="hseparator2">
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkTable" id="table1">
+ <property name="visible">True</property>
+ <property name="n_rows">9</property>
+ <property name="n_columns">2</property>
+ <property name="homogeneous">False</property>
+ <property name="row_spacing">0</property>
+ <property name="column_spacing">0</property>
+
+ <child>
+ <widget class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Sitename: </property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="bottom_attach">1</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Mail Address: </property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Username:</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Password: </property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkEntry" id="mailaddr_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="visibility">True</property>
+ <property name="max_length">0</property>
+ <property name="text" translatable="yes"></property>
+ <property name="has_frame">True</property>
+ <property name="invisible_char" translatable="yes">*</property>
+ <property name="activates_default">False</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkEntry" id="username_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="visibility">True</property>
+ <property name="max_length">0</property>
+ <property name="text" translatable="yes"></property>
+ <property name="has_frame">True</property>
+ <property name="invisible_char" translatable="yes">*</property>
+ <property name="activates_default">False</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkEntry" id="password_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="visibility">True</property>
+ <property name="max_length">0</property>
+ <property name="text" translatable="yes"></property>
+ <property name="has_frame">True</property>
+ <property name="invisible_char" translatable="yes">*</property>
+ <property name="activates_default">False</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkEntry" id="comment_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="visibility">True</property>
+ <property name="max_length">0</property>
+ <property name="text" translatable="yes"></property>
+ <property name="has_frame">True</property>
+ <property name="invisible_char" translatable="yes">*</property>
+ <property name="activates_default">False</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">8</property>
+ <property name="bottom_attach">9</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkEntry" id="recognition_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="visibility">True</property>
+ <property name="max_length">0</property>
+ <property name="text" translatable="yes"></property>
+ <property name="has_frame">True</property>
+ <property name="invisible_char" translatable="yes">*</property>
+ <property name="activates_default">False</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">7</property>
+ <property name="bottom_attach">8</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkEntry" id="capabilities_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="visibility">True</property>
+ <property name="max_length">0</property>
+ <property name="text" translatable="yes"></property>
+ <property name="has_frame">True</property>
+ <property name="invisible_char" translatable="yes">*</property>
+ <property name="activates_default">False</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">6</property>
+ <property name="bottom_attach">7</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkEntry" id="options_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="visibility">True</property>
+ <property name="max_length">0</property>
+ <property name="text" translatable="yes"></property>
+ <property name="has_frame">True</property>
+ <property name="invisible_char" translatable="yes">*</property>
+ <property name="activates_default">False</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">5</property>
+ <property name="bottom_attach">6</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label9">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Comment:</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">8</property>
+ <property name="bottom_attach">9</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label8">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Recognition: </property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">7</property>
+ <property name="bottom_attach">8</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label7">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Capabilities:</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">6</property>
+ <property name="bottom_attach">7</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label6">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Options: </property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">5</property>
+ <property name="bottom_attach">6</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label5">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Protocol:</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">4</property>
+ <property name="bottom_attach">5</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkEntry" id="host_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="visibility">True</property>
+ <property name="max_length">0</property>
+ <property name="text" translatable="yes"></property>
+ <property name="has_frame">True</property>
+ <property name="invisible_char" translatable="yes">*</property>
+ <property name="activates_default">False</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">0</property>
+ <property name="bottom_attach">1</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHBox" id="hbox8">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkHBox" id="hbox1">
+ <property name="visible">True</property>
+ <property name="homogeneous">True</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkRadioButton" id="POP3_radiobutton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">POP3</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="active">False</property>
+ <property name="inconsistent">False</property>
+ <property name="draw_indicator">True</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkRadioButton" id="APOP_radiobutton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">APOP</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="active">False</property>
+ <property name="inconsistent">False</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">POP3_radiobutton</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkRadioButton" id="IMAP_radiobutton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">IMAP</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="active">False</property>
+ <property name="inconsistent">False</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">POP3_radiobutton</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkVSeparator" id="vseparator1">
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkCheckButton" id="ssl_checkbox">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">SSL</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="active">False</property>
+ <property name="inconsistent">False</property>
+ <property name="draw_indicator">True</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">4</property>
+ <property name="bottom_attach">5</property>
+ <property name="x_options">fill</property>
+ <property name="y_options">fill</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHSeparator" id="hseparator1">
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHButtonBox" id="hbuttonbox1">
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_DEFAULT_STYLE</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkButton" id="updatebutton">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <signal name="clicked" handler="on_updatebutton_clicked" last_modification_time="Wed, 16 Jul 2003 23:17:30 GMT"/>
+
+ <child>
+ <widget class="GtkAlignment" id="alignment4">
+ <property name="visible">True</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xscale">0</property>
+ <property name="yscale">0</property>
+
+ <child>
+ <widget class="GtkHBox" id="hbox6">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">2</property>
+
+ <child>
+ <widget class="GtkImage" id="image4">
+ <property name="visible">True</property>
+ <property name="stock">gtk-apply</property>
+ <property name="icon_size">4</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label14">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Update</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="newbutton">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <signal name="clicked" handler="on_newbutton_clicked" last_modification_time="Wed, 16 Jul 2003 20:28:12 GMT"/>
+
+ <child>
+ <widget class="GtkAlignment" id="alignment1">
+ <property name="visible">True</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xscale">0</property>
+ <property name="yscale">0</property>
+
+ <child>
+ <widget class="GtkHBox" id="hbox3">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">2</property>
+
+ <child>
+ <widget class="GtkImage" id="image1">
+ <property name="visible">True</property>
+ <property name="stock">gtk-new</property>
+ <property name="icon_size">4</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label11">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">New</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="testbutton">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <signal name="clicked" handler="on_testbutton_clicked" last_modification_time="Wed, 16 Jul 2003 20:28:23 GMT"/>
+
+ <child>
+ <widget class="GtkAlignment" id="alignment3">
+ <property name="visible">True</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xscale">0</property>
+ <property name="yscale">0</property>
+
+ <child>
+ <widget class="GtkHBox" id="hbox5">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">2</property>
+
+ <child>
+ <widget class="GtkImage" id="image3">
+ <property name="visible">True</property>
+ <property name="stock">gtk-execute</property>
+ <property name="icon_size">4</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label13">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Test</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="quitbutton">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <signal name="clicked" handler="on_quitbutton_clicked" last_modification_time="Wed, 16 Jul 2003 20:08:46 GMT"/>
+
+ <child>
+ <widget class="GtkAlignment" id="alignment2">
+ <property name="visible">True</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xscale">0</property>
+ <property name="yscale">0</property>
+
+ <child>
+ <widget class="GtkHBox" id="hbox4">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">2</property>
+
+ <child>
+ <widget class="GtkImage" id="image2">
+ <property name="visible">True</property>
+ <property name="stock">gtk-quit</property>
+ <property name="icon_size">4</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label12">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Quit</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="dumpbutton">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <signal name="clicked" handler="on_dumpbutton_clicked" last_modification_time="Wed, 16 Jul 2003 23:34:47 GMT"/>
+
+ <child>
+ <widget class="GtkAlignment" id="alignment5">
+ <property name="visible">True</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xscale">0</property>
+ <property name="yscale">0</property>
+
+ <child>
+ <widget class="GtkHBox" id="hbox7">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">2</property>
+
+ <child>
+ <widget class="GtkImage" id="image5">
+ <property name="visible">True</property>
+ <property name="stock">gtk-print</property>
+ <property name="icon_size">4</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label15">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Dump</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+</widget>
+
+</glade-interface>
diff --git a/dist-tools/test/torturetest.gladep b/dist-tools/test/torturetest.gladep
new file mode 100644
index 00000000..d44797c3
--- /dev/null
+++ b/dist-tools/test/torturetest.gladep
@@ -0,0 +1,7 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<!DOCTYPE glade-project SYSTEM "http://glade.gnome.org/glade-project-2.0.dtd">
+
+<glade-project>
+ <name>torturetest</name>
+ <program_name>torturetest</program_name>
+</glade-project>
diff --git a/dist-tools/test/torturetest.py b/dist-tools/test/torturetest.py
new file mode 100755
index 00000000..f8a3535c
--- /dev/null
+++ b/dist-tools/test/torturetest.py
@@ -0,0 +1,326 @@
+#!/usr/bin/env python2
+
+import sys, getopt, os, smtplib, commands, time, gtk, gtk.glade
+
+protocols = ('POP3', 'APOP', 'IMAP',)
+
+class TestSite:
+ temp = "/usr/tmp/torturestest-%d" % os.getpid()
+
+ def __init__(self, line=None):
+ "Initialize site data from the external representation."
+ self.host = ""
+ self.mailaddr = ""
+ self.username = ""
+ self.password = ""
+ self.protocol = ""
+ self.ssl = ""
+ self.options = ""
+ self.capabilities = ""
+ self.recognition = ""
+ self.comment = ""
+ if line:
+ (self.host, self.mailaddr, self.username, self.password, \
+ self.protocol, self.ssl, self.options, self.capabilities, \
+ self.recognition, self.comment) = \
+ line.strip().split(":")
+ if not self.mailaddr:
+ self.mailaddr = self.username
+ # Test results
+ self.status = None
+ self.output = None
+
+ def allattrs(self):
+ "Return a tuple consisting of all this site's attributes."
+ return (self.host, self.mailaddr, self.username, self.password, \
+ self.protocol, self.ssl, self.options, self.capabilities, \
+ self.recognition, self.comment)
+
+ def __repr__(self):
+ "Return the external representation of this site's data."
+ return ":".join(self.allattrs())
+
+ def prettyprint(self):
+ "Prettyprint a site entry in human-readable form."
+ return "Host: %s\n" \
+ "Mail To: %s\n" \
+ "Username: %s\n" \
+ "Password: %s\n" \
+ "Protocol: %s\n" \
+ "SSL: %s\n" \
+ "Options: %s\n" \
+ "Capabilities: %s\n" \
+ "Recognition: %s\n" \
+ "Comment: %s\n" \
+ % self.allattrs()
+
+ def entryprint(self):
+ "Print a .fetchmailrc entry corresponding to a site entry."
+ rep = "poll %s-%s via %s with proto %s %s\n" \
+ " user %s there with password '%s' is esr here" \
+ % (self.host,self.protocol,self.host,self.protocol,self.options,self.username,self.password)
+ if self.ssl and self.ssl != 'False':
+ rep += " options ssl"
+ rep += "\n\n"
+ return rep
+
+ def tableprint(self):
+ "Print an HTML server-type table entry."
+ return "<tr><td>%s: %s</td><td>%s</td>\n" \
+ % (self.protocol, self.comment, self.capabilities)
+
+ def id(self):
+ "Identify this site."
+ rep = "%s %s at %s" % (self.protocol, self.recognition, self.host)
+ if self.capabilities:
+ rep += " (" + self.capabilities + ")"
+ if self.options:
+ rep += " using " + self.options
+ return rep
+
+ def testmail(self, n=None):
+ "Send test mail to the site."
+ server = smtplib.SMTP("localhost")
+ fromaddr = "esr@thyrsus.com"
+ if self.mailaddr.find("@") > -1:
+ toaddr = self.mailaddr
+ else:
+ toaddr = "%s@%s" % (self.mailaddr, self.host)
+ msg = ("From: %s\r\nTo: %s\r\n\r\n" % (fromaddr, toaddr))
+ if n != None:
+ msg += `n` + ": "
+ msg += "Test mail collected from %s.\n" % (self.id(),)
+ server.sendmail(fromaddr, toaddr, msg)
+ server.quit()
+
+ def fetch(self, logfile=False):
+ "Run a mail fetch on this site."
+ try:
+ ofp = open(TestSite.temp, "w")
+ if logfile:
+ mda = "(echo; echo \'From torturetest\' `date`;cat) >>TEST.LOG"
+ else:
+ mda = 'cat'
+ ofp.write('defaults mda "%s"\n' % mda)
+ ofp.write(self.entryprint())
+ ofp.close()
+ (self.status, self.output) = commands.getstatusoutput("fetchmail -d0 -v -f - <%s"%TestSite.temp)
+ if self.status:
+ os.system("cat " + TestSite.temp)
+ finally:
+ os.remove(TestSite.temp)
+
+ def failed(self):
+ "Did we have a test failure here?"
+ return os.WIFEXITED(self.status) and os.WEXITSTATUS(self.status) > 1
+
+ def explain(self):
+ "Explain the status of the last test."
+ if not os.WIFEXITED(self.status):
+ return self.id() + ": abnormal termination\n"
+ elif os.WEXITSTATUS(self.status) > 1:
+ return self.id() + ": %d\n" % os.WEXITSTATUS(self.status) + self.output
+ else:
+ return self.id() + ": succeeded\n"
+
+class TortureGUI:
+ "Torturetest editing GUI,"
+
+ # All site parameters except protocol
+ field_map = ('host', 'mailaddr', 'username', 'password', \
+ 'options', 'capabilities', 'recognition', 'comment')
+
+ def __init__(self):
+ # Build the widget tree from the glade XML file.
+ self.wtree = gtk.glade.XML("torturetest.glade")
+ # File in initial values
+ self.combo = self.wtree.get_widget("combo1")
+ self.combo.set_popdown_strings(map(lambda x: x.comment, sitelist))
+ self.sslcheck = self.wtree.get_widget("ssl_checkbox")
+ self.site = sitelist[0]
+ self.display(self.site)
+
+ # Provide handlers for the widget tree's events
+ mydict = {}
+ for key in ('on_torturetest_destroy',
+ 'on_updatebutton_clicked',
+ 'on_newbutton_clicked',
+ 'on_testbutton_clicked',
+ 'on_quitbutton_clicked',
+ 'on_dumpbutton_clicked',
+ 'on_combo_entry1_activate'):
+ mydict[key] = getattr(self, key)
+ self.wtree.signal_autoconnect(mydict)
+
+ gtk.mainloop()
+ print `self.site`
+
+ def get_widget(self, widget):
+ "Get the value of a widget's contents."
+ if type(widget) == type(""):
+ widget = self.wtree.get_widget(widget)
+ if type(widget) == gtk.Entry:
+ return widget.get_text()
+ #elif type(widget) == gtk.SpinButton:
+ # return widget.get_value()
+ #elif type(widget) == gtk.TextView:
+ # return widget.get_buffer().get_text()
+
+ def set_widget(self, name, exp):
+ "Set the value of a widget by name."
+ widget = self.wtree.get_widget(name)
+ if type(widget) == gtk.Entry:
+ widget.set_text(exp)
+ elif type(widget) == gtk.SpinButton:
+ widget.set_value(exp)
+ elif type(widget) == gtk.TextView:
+ if not widget.get_buffer():
+ widget.set_buffer(gtk.TextBuffer())
+ widget.get_buffer().set_text(exp)
+
+ def display(self, site):
+ for member in TortureGUI.field_map:
+ self.set_widget(member + "_entry", getattr(site, member))
+ for proto in protocols:
+ self.wtree.get_widget(proto + "_radiobutton").set_active(site.protocol == proto)
+ self.sslcheck.set_active(int(site.ssl != '' and site.ssl != 'False'))
+ self.combo.entry.set_text(site.comment)
+
+ def update(self, site):
+ for member in TortureGUI.field_map:
+ setattr(site, member, self.get_widget(member + "_entry"))
+ for proto in protocols:
+ if self.wtree.get_widget(proto + "_radiobutton").get_active():
+ site.protocol = proto
+ if self.wtree.get_widget("ssl_checkbox").get_active():
+ site.ssl = "True"
+ else:
+ site.ssl = "False"
+
+ # Housekeeping
+ def on_torturetest_destroy(self, obj):
+ gtk.mainquit()
+ def on_updatebutton_clicked(self, obj):
+ self.update(self.site)
+ print self.site
+ if self.site.comment:
+ self.combo.entry.set_text(self.site.comment)
+ else:
+ self.combo.entry.set_text(self.site.host)
+ def on_newbutton_clicked(self, obj):
+ global sitelist
+ sitelist = [TestSite()] + sitelist
+ self.site = sitelist[0]
+ self.display(self.site)
+ self.combo.entry.set_text("")
+ def on_testbutton_clicked(self, obj):
+ self.site.fetch(False)
+ print self.site.output
+ def on_quitbutton_clicked(self, obj):
+ gtk.mainquit()
+ def on_dumpbutton_clicked(self, obj):
+ print `self.site`
+
+ def on_combo_entry1_activate(self, obj):
+ key = self.combo.entry.get_text()
+ for site in sitelist:
+ if site.comment.find(key) > -1:
+ self.site = site
+ self.display(self.site)
+ break
+
+if __name__ == "__main__":
+ # Start by reading in the sitelist
+ ifp = open("testsites")
+ sitelist = []
+ linect = 0
+ while 1:
+ linect += 1
+ line = ifp.readline()
+ if not line:
+ break
+ elif line[0] in ("#", "\n"):
+ continue
+ else:
+ try:
+ sitelist.append(TestSite(line))
+ except:
+ print "Error on line %d" % linect
+ sys.exit(0)
+
+ (options, arguments) = getopt.getopt(sys.argv[1:], "dfp:tigvse")
+ verbose = 0
+ for (switch, value) in options:
+ if switch == "-d":
+ # Prettprint the sitelist
+ map(lambda x: sys.stdout.write(x.prettyprint() + "%%\n"), sitelist)
+ sys.exit(0)
+ elif switch == "-f":
+ # Dump the sitelist as a .fetchmailrc file
+ map(lambda x: sys.stdout.write(x.entryprint()), sitelist)
+ sys.exit(0)
+ elif switch == "-p":
+ # Probe a single site
+ selected = []
+ for site in sitelist:
+ if `site`.find(value) > -1:
+ selected.append(site)
+ sitelist = selected
+ # Fall through
+ elif switch == "-t":
+ # Dump the sitelist in HTML table form
+ map(lambda x: sys.stdout.write(x.tableprint()), sitelist)
+ sys.exit(0)
+ elif switch == "-i":
+ # Dump the ids of the sitelist
+ map(lambda x: sys.stdout.write(x.id() + "\n"), sitelist)
+ sys.exit(0)
+ elif switch == "-g":
+ i = 1
+ for site in sitelist:
+ print "Sending test mail to " + site.id()
+ site.testmail(i)
+ i+= 1
+ # Send test mail to each site
+ sys.stdout.write("Delaying to give the test mail time to land...")
+ time.sleep(5)
+ sys.stdout.write("here we go:\n")
+ # Fall through
+ elif switch == "-v":
+ # Display the test output
+ verbose = 1
+ elif switch == "-s":
+ # Dump recognition strings of all tested servers as a Python tuple
+ print "(" + ",\n".join(map(lambda x: repr(x.recognition), filter(lambda x: x.recognition, sitelist))) + ")"
+ sys.exit(0)
+ elif switch == "-e":
+ TortureGUI()
+ sys.exit(0)
+
+ # If no options, run the torture test
+ try:
+ failures = successes = 0
+ os.system("fetchmail -q")
+ for site in sitelist:
+ print "Testing " + site.id()
+ site.fetch(True)
+ if verbose:
+ print site.output
+ if site.failed():
+ failures += 1
+ else:
+ successes += 1
+
+ # OK, summarize results
+ print "\n%d successes and %d failures out of %d tests" \
+ % (successes, failures, len(sitelist))
+
+ if failures:
+ print "Bad status was returned on the following sites:"
+ for site in sitelist:
+ if site.failed():
+ sys.stdout.write(site.explain() + "\n")
+ except KeyboardInterrupt:
+ print "Interrupted."
+
+# end
diff --git a/dist-tools/timeplot b/dist-tools/timeplot
new file mode 100755
index 00000000..c8240d05
--- /dev/null
+++ b/dist-tools/timeplot
@@ -0,0 +1,40 @@
+#!/bin/sh
+#
+# timeplot -- plot data on fetchmail release intervals
+#
+#
+
+# Get data from the NEWS file
+timeseries | awk >/tmp/timeplot$$ '
+START {maxdiff = 0;}
+/^[#%]/ {next;}
+ {days[count++] = $6;}
+END {
+ for (i = 0; i < count-1; i++)
+ {
+ diffs[i] = days[i] - days[i + 1];
+ if (maxdiff < diffs[i])
+ maxdiff = diffs[i];
+ }
+ for (i = 0; i <= maxdiff; i++)
+ freq[i] = 0;
+ for (i = 0; i < count - 1; i++)
+ {
+ freq[diffs[i]]++;
+ }
+ for (i = 0; i <= maxdiff; i++)
+ printf("%d %d\n", i, freq[i]);
+ }
+'
+
+gnuplot >time.png - <<EOF
+set xlabel "Release interval (days)"
+set ylabel "Interval frequency"
+plot '/tmp/timeplot$$' using 1:2 \
+ title "Release interval frequency"
+pause 9999
+EOF
+
+rm -f /tmp/time*
+
+# timeplot ends here
diff --git a/dist-tools/timeseries b/dist-tools/timeseries
new file mode 100755
index 00000000..7a20c4c2
--- /dev/null
+++ b/dist-tools/timeseries
@@ -0,0 +1,101 @@
+#!/usr/bin/perl
+#
+# Extract information on the fetchmail project size from the NEWS file
+#
+# Note: this only works if you have a news file from 5.1.1 or later --
+# I didn't patch the code sizes into NEWS until then.
+#
+my($release, $date, $jdate);
+
+%month_offsets = (
+ "Jan", 0,
+ "Feb", 31,
+ "Mar", 59,
+ "Apr", 90,
+ "May", 120,
+ "Jun", 151,
+ "Jul", 181,
+ "Aug", 212,
+ "Sep", 243,
+ "Oct", 273,
+ "Nov", 304,
+ "Dec", 334,
+);
+
+
+sub day_offset
+{
+ my($datestring) = @_;
+ my($wday, $month, $day, $time, $zone, $year) = split(' ', $datestring);
+ my($jdate);
+
+ # We don't deal with leap years here because the baseline day is after
+ # the last leap year (1996) and there's a long time before the next
+ # one (2004).
+ $jdate = ($year - 1996) * 365;
+
+ $jdate += $month_offsets{$month};
+
+ $jdate += ($day - 1);
+
+ # Baseline day for the size data was Fri Oct 25 23:02:26 EDT 1996
+ $jdate -= 297;
+
+ return($jdate);
+}
+
+open(NEWS, "NEWS");
+$timestamp = `date`;
+chop $timestamp;
+$release = "unknown";
+$lines = "unknown";
+$date = "unknown";
+$jdate = "unknown";
+print <<EOF;
+# Population data from fetchmail NEWS file, as of $timestamp.
+#
+# Output other than pass-through % lines is tab-separated fields.
+# Field 1: release ID
+# Field 2: count of source lines under version control
+# Field 3: count of fetchmail-friends subscribers
+# Field 4: count of fetchmail-announce subscribers
+# Field 5: total subscribers to both lists
+# Field 6: date of release (days since first datum)
+# Field 7: date of release (RFC822 date format)
+#
+EOF
+while ($_ = <NEWS>)
+{
+ my($sum);
+
+ if (/^%/) {
+ print $_;
+ }
+ elsif (/^fetchmail-([^ ]*) \(([^)]+)\)(, [0-9]* lines)?:/) {
+ $release = $1;
+ $date = $2;
+ $jdate = &day_offset($date);
+ if ($3) {
+ $lines = substr($3, 2, length($3) - 8);
+ } else {
+ $lines = 'na'
+ }
+ }
+ elsif (/There are ([0-9]*) people on fetchmail-friends and ([0-9]*) on fetchmail-announce/) {
+ $sum = $1 + $2;
+ print "${release}\t${lines}\t$1\t$2\t${sum}\t${jdate}\t${date}\n";
+ $release = "unknown";
+ $date = "unknown";
+ }
+ elsif (/There are ([0-9]*) people on the fetchmail-friends list./) {
+ print "$release\t${lines}\t$1\t0\t$1\t$jdate\t$date\n";
+ $release = "unknown";
+ $date = "unknown";
+ }
+}
+
+# end
+
+
+
+
diff --git a/dist-tools/upload b/dist-tools/upload
new file mode 100755
index 00000000..3a76ee49
--- /dev/null
+++ b/dist-tools/upload
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+version=`sed -n '/VERSION *= *\(.*\)/s//\1/p' <Makefile`
+echo "Uploading fetchmail version ${version}"
+
+if [ $* ]
+then
+ ../upload $*
+else
+
+echo "Beginning web upload..."
+# First, copy to primary website
+dest=esr@${WWWHOST}:${WWWDIR}/fetchmail
+scp fetchmail-${version}.tar.gz.asc $dest
+#scp funny.html $dest
+#scp fetchmail.png $dest
+#scp bighand.png $dest
+scp growth.png $dest
+scp timeseries $dest
+scp growthplot $dest
+scp checksums $dest
+# shipper does the rest.
+rm -f ANNOUNCE.FRESHMEAT
+shipper
+
+
diff --git a/dist-tools/uploadfaq b/dist-tools/uploadfaq
new file mode 100755
index 00000000..73d29468
--- /dev/null
+++ b/dist-tools/uploadfaq
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+version=`sed -n '/VERSION *= *\(.*\)/s//\1/p' <Makefile`
+echo "Uploading fetchmail version ${version} FAQ"
+
+if [ $* ]
+then
+ ../upload $*
+else
+ lftp <<EOF
+# First, copy to primary website
+open ${WWWHOST}
+cd ${WWWDIR}/fetchmail
+put fetchmail-FAQ.html
+close
+
+# Next, upload to the ftp site
+open locke.ccil.org
+cd ~ftp/pub/esr/fetchmail
+put FAQ
+close
+EOF
+ echo "fetchmail FAQ uploaded"
+fi \ No newline at end of file