aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatěj Cepl <mcepl@cepl.eu>2002-06-04 17:02:00 +0200
committerMatěj Cepl <mcepl@cepl.eu>2015-01-03 10:31:58 +0100
commit59eda1d0150e4b517a071c1e04ded96ff8f0f314 (patch)
tree47db347f3ff74e3a7fb23cef1cba2ed4a452aeaa
parenta9d49c6a0fd9dbad859659d7f49901bc9101d790 (diff)
downloadpyg-0.9.6.tar.gz
pyg 0.9.6 from archive.debian.org0.9.6
-rw-r--r--HOWTO14
-rw-r--r--INSTALL29
-rw-r--r--Makefile17
-rw-r--r--README31
-rw-r--r--TODO12
-rw-r--r--debian/README.debian12
-rw-r--r--debian/changelog172
-rw-r--r--debian/control29
-rw-r--r--debian/copyright10
-rw-r--r--debian/dirs2
-rw-r--r--debian/docs2
-rw-r--r--debian/examples2
-rw-r--r--debian/notused/crontab.ex1
-rw-r--r--debian/notused/diversions.ex1
-rw-r--r--debian/notused/inetd.conf.ex2
-rw-r--r--debian/notused/info.ex15
-rw-r--r--debian/notused/init.d.ex51
-rw-r--r--debian/notused/manpage.1.ex41
-rw-r--r--debian/notused/menu.ex2
-rw-r--r--debian/notused/watch.ex5
-rw-r--r--debian/pygm2n.1 (renamed from pygm2n.1)0
-rw-r--r--debian/pygn2m.1 (renamed from pygn2m.1)0
-rwxr-xr-xdebian/rules78
-rw-r--r--debian/whitelist.575
-rw-r--r--docs/01-leafnode-list-pygn-as-mail2news.html148
-rw-r--r--docs/02-leafnode-list-pygn-as-mail2news.html85
-rw-r--r--docs/joerg01.eml145
-rw-r--r--docs/mail2news-gateway.eml268
-rw-r--r--examples/drhyde-news2mail-and-mail2news/LICENCE3
-rw-r--r--examples/drhyde-news2mail-and-mail2news/mail2news58
-rw-r--r--examples/drhyde-news2mail-and-mail2news/news2mail177
-rw-r--r--examples/drhyde-news2mail-and-mail2news/yapc-europe-2007-paper.pdfbin82566 -> 0 bytes
-rw-r--r--examples/drhyde-news2mail-and-mail2news/yapc-europe-2007-paper.pod177
-rw-r--r--mail2news.py374
-rw-r--r--mail2news.py.withtab319
-rw-r--r--news2mail.py412
-rw-r--r--pyginfo.py26
-rwxr-xr-xpygm2n248
-rwxr-xr-xpygn2m272
-rw-r--r--setup.py69
-rw-r--r--tarballs/pyg_0.9.6-2.tar.gzbin32360 -> 0 bytes
-rw-r--r--tarballs/pyg_0.9.6-4.1.tar.gzbin33066 -> 0 bytes
-rw-r--r--tarballs/pyg_0.9.6-4.tar.gzbin32980 -> 0 bytes
-rw-r--r--test/__init__.py0
-rwxr-xr-xtest/test_wlp.py115
-rw-r--r--whitelist-pygn2m3
-rw-r--r--whitelist.py194
-rw-r--r--wlp/C/Makefile43
-rw-r--r--wlp/C/commands.l (renamed from wlp/commands.l)1
-rw-r--r--wlp/C/commands.y (renamed from wlp/commands.y)1
-rw-r--r--wlp/C/macro.h (renamed from wlp/macro.h)0
-rw-r--r--wlp/C/structs.c (renamed from wlp/structs.c)0
-rw-r--r--wlp/C/structs.h (renamed from wlp/structs.h)0
-rw-r--r--wlp/C/test.c (renamed from wlp/test.c)0
-rw-r--r--wlp/C/wlp.c (renamed from wlp/wlp.c)31
-rw-r--r--wlp/C/yytest.c (renamed from wlp/yytest.c)0
-rw-r--r--wlp/Makefile14
-rw-r--r--wlp/Makefile.C61
-rw-r--r--wlp/README2
-rw-r--r--wlp/module/Makefile.pre.in305
-rw-r--r--wlp/module/Setup.in88
-rwxr-xr-xwlp/module/makesetup261
-rwxr-xr-xwlp_test31
63 files changed, 2677 insertions, 1857 deletions
diff --git a/HOWTO b/HOWTO
index e39c123..12f1a6b 100644
--- a/HOWTO
+++ b/HOWTO
@@ -5,27 +5,17 @@ It is a (very) small HOWTO to make pyg working properly.
pygm2n:
-Pre: a fully working MTA (ie postfix) where you can run procmail or any other MDA.
-A news server (local or remote) where you can create groups (admin
-privileges).
+Pre: a fully working MTA (ie postfix) where you can run procmail. A
+new server (local or remote) where you can create groups.
Create a user, ie mailgate, set its procmail as:
:0 bhc:
| pygm2n -n local.test
-or its maildrop (thanks to Joy):
-
-dotlock pygm2n.`echo $$`.lock {
- `pygm2n -n local.test`
-}
-
you can use -a your@address and -s nntphost if local.test is moderated,
or nntphost isn't localhost
-[NOTE: if you've configuration for any other MDA, please file a wishlist
-bug against pyg]
-
Create local.test (if it doen't exist).
Now any mail you will write to mailgate user, will be sent to the
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..599a64d
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,29 @@
+For debian user:
+
+Make package as usual:
+
+$ dpkg-buildpackage -uc -us -rfakeroot
+and install .deb file made.
+
+
+
+
+For non debian user only:
+
+Simply run make:
+
+$ make
+
+and install file where you want:
+Something like:
+
+$ install -m 0755 -d /usr/local/lib/pyg
+to create /usr/local/lib/pyg with right permissions
+
+$ make install DESTDIR=/usr/local
+to install file in /usr/local as basedir
+/usr/local/sbin pygs (pyg frontend)
+/usr/local/lib/pyg *.py *.so (module classes)
+
+You may install manually documentation and examples in examples/ dir in
+/usr/local/share/doc or where you wish.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..e37e417
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,17 @@
+WLPDIR=wlp
+
+CSRCDIR=$(WLPDIR)/C
+MODULEDIR=$(WLPDIR)/module
+BINDIR=$(WLPDIR)
+
+bin:
+ $(MAKE) -C $(WLPDIR)
+
+install:
+ install pygm2n pygn2m $(DESTDIR)/usr/bin
+ install *.py $(DESTDIR)/usr/lib/pyg
+ install *.so $(DESTDIR)/usr/lib/pyg
+
+clean:
+ -$(MAKE) -C $(WLPDIR) clean
+ -rm *.pyc *.so
diff --git a/README b/README
index 8d690fe..4eed9d9 100644
--- a/README
+++ b/README
@@ -1,37 +1,14 @@
-Python Gateway Script from news to mail and vice versa.
-
-Copyright:
-Copyright (C) 2000-2001,2012 Cosimo Alfarano <kalfa@debian.org>
-Copyright (C) 2014 Matěj Cepl <mcepl@cepl.eu>
-
-A copy of the GNU General Public License, version 3, can be found in
-http://www.gnu.org/licenses/gpl-3.0.txt
-
-It is intended to be a full SMTP/NNTP rfc compliant gateway
-with whitelist manager.
-
-You will probably have to install a mail-transport-agent and/or
-news-transport-system package to manage SMTP/NNTP traffic.
-
-MTA is needed for mail2news service, since mail have to be
-processed on a box where pyg is installed. You can use a remote
-smtpserver for news2mail.
-
-News system is useful but not needed, since you can send articles to a
-remote SMTP server (ie: moderated NG) where is installed pyg, otherwise you
-will need it.
-
-It refers to rfc 822 (mail) and 850 (news).
-
-----------------
+Pyg is a news to mail and mail to news gateway.
+It is under devel.
List of file:
mail2news.py mail to news python class module
news2mail.py news to mail python class module
-setup.py setup script
+pyginfo.py info about pygs python class module
pygm2n mail to news gateway frontend
pygn2m news to mail gateway frontend
whitelist.py whitelist managing python class module
+wlp_test test script to test yout whitelist file
wlp C backend for whitelist parser (wlp) directory
examples documentation and exaples directory
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..469ee36
--- /dev/null
+++ b/TODO
@@ -0,0 +1,12 @@
+pygm2n:
+
+Handle better socket errors (try: in sendemail)
+Let choose if remove (let server generate it), regenerete or leave Message-ID
+Post to many server (server list)? maybe.
+reads NNTPHOST environ var to set default host.
+
+
+both:
+
+try: for open() in readfile()
+finish to write HOWTO
diff --git a/debian/README.debian b/debian/README.debian
new file mode 100644
index 0000000..c9d90ed
--- /dev/null
+++ b/debian/README.debian
@@ -0,0 +1,12 @@
+pyg for Debian
+--------------
+
+pyg is a package to manage gateway from usenet to email and vice versa.
+
+It is written in python and is (hopefully) rfc compliant.
+My intent is to write a fully standardized gateway.
+
+Any help, advice or patch is accepted :)
+If you try pyg, send me your opinion, please.
+
+Cosimo Alfarano <alfarano@students.cs.unibo.it>, Sun, 25 Jun 2000 17:52:35 +0200
diff --git a/debian/changelog b/debian/changelog
new file mode 100644
index 0000000..bf818b4
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,172 @@
+pyg (0.9.6-2) unstable; urgency=low
+
+ * typos in debian/control fixed (closes: #125276)
+
+ -- Cosimo Alfarano <kalfa@debian.org> Sat, 6 Apr 2002 18:52:57 +0200
+
+pyg (0.9.6-1) unstable; urgency=low
+
+ * minor changes to mail2news.py sendemail() method
+ now does str(msg) on exception
+ * addedd support for void header ('Cc: \n\r') even if it is not fully rfc
+ conform.
+ * addedd support for multiline header of the form
+ "Received: \n\r<text>" (closes: #124396)
+ * fixed helo hostname sent, now it's the box name
+ (closes: #122851)
+ * sorry for the long fixing time, to everyone was waiting for them.
+
+ -- Cosimo Alfarano <kalfa@debian.org> Wed, 3 Apr 2002 22:39:47 +0200
+
+pyg (0.9.5-1) unstable; urgency=low
+
+ * compiled against python2.1 (wlp.c)
+ * debian/control updated for dependancies
+ python (>= 2.1), I want it to be usable on any 2.X
+ the same for python-dev (closes: #119202)
+
+ -- Cosimo Alfarano <kalfa@debian.org> Mon, 12 Nov 2001 22:17:28 +0100
+
+pyg (0.9.4-7) unstable; urgency=low
+
+ * fixed some typos
+ * fixed import of getopt module (thanks to zack@debian.org)
+ * inverted 'if' and 'else' in line 78 of mail2news.py
+ that's not a bug, but I do it for readability closes: #105922
+
+ -- Cosimo Alfarano <kalfa@debian.org> Fri, 20 Jul 2001 00:49:26 +0200
+
+pyg (0.9.4-6) unstable; urgency=low
+
+ * added -P port option to pygm2n
+
+ -- Cosimo Alfarano <kalfa@debian.org> Sun, 11 Feb 2001 22:09:03 +0100
+
+pyg (0.9.4-5) unstable; urgency=low
+
+ * added suport for NNTP auth (thanks to Marc Sherman for his patch) closes: #84809
+
+ -- Cosimo Alfarano <kalfa@debian.org> Sun, 11 Feb 2001 16:43:09 +0100
+
+pyg (0.9.4-4) unstable; urgency=low
+
+ * moved files from /usr/sbin to /usr/bin closes: #84806
+ * changed Maintainer: filed to kalfa@debian.org addr
+
+ -- Cosimo Alfarano <alfarano@students.cs.unibo.it> Sun, 04 Feb 2000 18:50:00 +0100
+
+pyg (0.9.4-3) unstable; urgency=low
+
+ * Sponsored upload.
+ * fixed getopt problem with -M
+
+ -- Davide Puricelli (evo) <evo@debian.org> Sun, 30 Sep 2000 21:50:00 +0200
+
+pyg (0.9.4-2) unstable; urgency=low
+
+ * added Approved: header (pygm2n)
+ * added selection of smtpserver for relay (pygn2m)
+ * added conversion from In-Reply-To: to References: (pygm2n)
+ * added Suggests: news-transport-system , mail-transport-agent
+ * removed NNTP-Posting-Host, X-Trace
+ * added TODO file
+ * mail to news is working fine.
+
+ -- Cosimo Alfarano <alfarano@students.cs.unibo.it> Sun, 30 Sep 2000 21:50:00 +0200
+
+pyg (0.9.4-1) unstable; urgency=low
+
+ * Sponsored upload.
+ * New upstream version.
+ * mail to news gateway is working. Anyway testing it is adviced before use.
+
+ -- Davide Puricelli (evo) <evo@debian.org> Mon, 18 Sep 2000 19:45:19 +0200
+
+pyg (0.9.3-1) unstable; urgency=low
+
+ * started to write mail to news gateway module
+
+ -- Cosimo Alfarano <alfarano@students.cs.unibo.it> Sat, 16 Sep 2000 17:30:00 +0200
+
+pyg (0.9.2-3) unstable; urgency=low
+
+ * Sponsored upload.
+ * Swapped binary-{indep,arch} in debian/rules, closes: #71446.
+ * Added flex and bison to Build-Depends.
+
+ -- Davide Puricelli (evo) <evo@debian.org> Thu, 14 Sep 2000 16:34:10 +0200
+
+pyg (0.9.2-2) unstable; urgency=low
+
+ * debian/rules rewritten to a more readble dh_make style.
+ * moved example files from debian/ to exaples/
+ * dh_stripped *.so
+ * dh_undocumented *.py
+ * Sponsored upload for Cosimo Alfarano <alfarano@students.cs.unibo.it>
+ * Initial Debian release.
+
+ -- Davide Puricelli (evo) <evo@debian.org> Sat, 2 Sep 2000 22:35:25 +0200
+
+pyg (0.9.2-1) unstable; urgency=low
+
+ * written the whitelist parser (wlp) in yacc+flex
+ * written C funtions as python built-in module for wlp
+ * fixed parsecommandline() return object
+ * added -T opt for test mode and -V for verbose output
+
+ -- Cosimo Alfarano <alfarano@students.cs.unibo.it> Sun, 23 Jul 2000 19:30:00 +0200
+
+pyg (0.9.1-5) unstable; urgency=low
+
+ * added file locking on log
+ * modified default location of whitelist and log file to homedir.
+ log file will moved to /var/log as soon as possible
+
+ -- Cosimo Alfarano <alfarano@students.cs.unibo.it> Sun, 03 Jul 2000 18:00:00 +0200
+
+pyg (0.9.1-4) unstable; urgency=low
+
+ * Added Message-Id: logging in whitelist
+
+ -- Cosimo Alfarano <alfarano@students.cs.unibo.it> Sun, 02 Jul 2000 18:30:00 +0200
+
+pyg (0.9.1-3) unstable; urgency=low
+
+ * removed Sender: header from nntp article. It is usually set to news@news.domain
+
+ -- Cosimo Alfarano <alfarano@students.cs.unibo.it> Thu, 29 Jun 2000 16:30:00 +0200
+
+pyg (0.9.1-2) unstable; urgency=low
+
+ * modified copyright note in sources
+ * moved parse_cmdline() from news2mail.py to pygs
+
+ -- Cosimo Alfarano <alfarano@students.cs.unibo.it> Thu, 29 Jun 2000 02:30:00 +0200
+
+pyg (0.9.1-1) unstable; urgency=low
+
+ * enriched whitelist log system
+
+ -- Cosimo Alfarano <alfarano@students.cs.unibo.it> Thu, 29 Jun 2000 01:30:00 +0200
+
+pyg (0.9-3) unstable; urgency=low
+
+ * corrected load path for modules in pygs. now points to /usr/lib/pyg
+
+ -- Cosimo Alfarano <alfarano@students.cs.unibo.it> Wed, 28 Jun 2000 00:45:00 +0200
+
+pyg (0.9-2) unstable; urgency=low
+
+ * added basic (and rudimental) whitelist functionality (whitelist.py)
+
+ -- Cosimo Alfarano <alfarano@students.cs.unibo.it> Wed, 28 Jun 2000 00:05:00 +0200
+
+pyg (0.9-1) unstable; urgency=low
+
+ * Initial release.
+
+ -- Cosimo Alfarano <alfarano@students.cs.unibo.it> Sun, 25 Jun 2000 17:52:35 +0200
+
+Local variables:
+mode: debian-changelog
+End:
diff --git a/debian/control b/debian/control
new file mode 100644
index 0000000..55cb948
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,29 @@
+Source: pyg
+Section: news
+Priority: optional
+Maintainer: Cosimo Alfarano <kalfa@debian.org>
+Standards-Version: 3.5.6.0
+Build-Depends: debhelper, python-dev (>= 2.1), flex, bison
+
+Package: pyg
+Architecture: any
+Depends: python (>= 2.1)
+Suggests: news-transport-system , mail-transport-agent, procmail
+Description: Python Mail <-> News Gateway
+ Python Gateway Script from news to mail and vice versa.
+ .
+ It is intended to be a full SMTP/NNTP rfc compliant gateway
+ with whitelist manager.
+ .
+ You will probably have to install a mail-transport-agent and/or
+ news-transport-system package to manage SMTP/NNTP traffic.
+ .
+ MTA is needed for mail2news service, since mail have to be
+ processed on a box where pyg is installed. You can use a remote
+ smtpserver for news2mail.
+ .
+ News system is useful but not needed, since you can send articles to a
+ remote SMTP server (ie: moderated NG) where is installed pyg, otherwise you
+ will need it.
+ .
+ It refers to rfc 822 (mail) and 850 (news).
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 0000000..d31508f
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,10 @@
+This package was debianized by Cosimo Alfarano <alfarano@students.cs.unibo.it> on Sun, 25 Jun 2000 17:52:35 +0200.
+
+Current maintainer and author is Cosimo Alfarano.
+You can find this package at URL HTTP://www.students.cs.unibo.it/~alfarano
+
+Copyright:
+Copyright (C) 2000,2001 Cosimo Alfarano <alfarano@students.cs.unibo.it>
+
+A copy of the GNU General Public License, version 2, can be found in
+/usr/share/common-licenses/GPL.
diff --git a/debian/dirs b/debian/dirs
new file mode 100644
index 0000000..7bdd9cc
--- /dev/null
+++ b/debian/dirs
@@ -0,0 +1,2 @@
+usr/bin
+usr/lib/pyg
diff --git a/debian/docs b/debian/docs
new file mode 100644
index 0000000..e882956
--- /dev/null
+++ b/debian/docs
@@ -0,0 +1,2 @@
+HOWTO
+TODO
diff --git a/debian/examples b/debian/examples
new file mode 100644
index 0000000..7a0a00b
--- /dev/null
+++ b/debian/examples
@@ -0,0 +1,2 @@
+examples/*
+wlp_test
diff --git a/debian/notused/crontab.ex b/debian/notused/crontab.ex
new file mode 100644
index 0000000..99b6819
--- /dev/null
+++ b/debian/notused/crontab.ex
@@ -0,0 +1 @@
+0 4 * * * root pyg_maintenance
diff --git a/debian/notused/diversions.ex b/debian/notused/diversions.ex
new file mode 100644
index 0000000..aebbbe5
--- /dev/null
+++ b/debian/notused/diversions.ex
@@ -0,0 +1 @@
+<FILE> <Diverted to> <Packagename>
diff --git a/debian/notused/inetd.conf.ex b/debian/notused/inetd.conf.ex
new file mode 100644
index 0000000..1dcaa61
--- /dev/null
+++ b/debian/notused/inetd.conf.ex
@@ -0,0 +1,2 @@
+#:OTHER:
+pyg stream tcp nowait root /usr/sbin/tcpd /usr/sbin/pyg
diff --git a/debian/notused/info.ex b/debian/notused/info.ex
new file mode 100644
index 0000000..31365f9
--- /dev/null
+++ b/debian/notused/info.ex
@@ -0,0 +1,15 @@
+# This is a configuration files for installing a .info menu
+# The Description to be placed into the directory
+DESCR="Description"
+
+# The section this info file should be placed in (Regexp) followed by
+# the new section name to be created if the Regexp does not match
+# (Optional. If not given the .info will be appended to the directory)
+#SECTION_MATCH="Regexp"
+#SECTION_NAME="New Section Name"
+
+# The file referred to from the Info directory
+FILE=pyg.info
+
+# Optional. The files to be copied to /usr/share/info
+#FILES=*.info
diff --git a/debian/notused/init.d.ex b/debian/notused/init.d.ex
new file mode 100644
index 0000000..c2302bb
--- /dev/null
+++ b/debian/notused/init.d.ex
@@ -0,0 +1,51 @@
+#!/bin/sh
+#
+# This file was automatically customized by debmake on Sun, 25 Jun 2000 17:52:35 +0200
+#
+# Written by Miquel van Smoorenburg <miquels@cistron.nl>.
+# Modified for Debian GNU/Linux by Ian Murdock <imurdock@gnu.org>.
+# Modified for Debian by Christoph Lameter <clameter@debian.org>
+
+PATH=/bin:/usr/bin:/sbin:/usr/sbin
+DAEMON=/usr/sbin/pyg
+# The following value is extracted by debstd to figure out how to generate
+# the postinst script. Edit the field to change the way the script is
+# registered through update-rc.d (see the manpage for update-rc.d!)
+FLAGS="defaults 50"
+
+test -f $DAEMON || exit 0
+
+case "$1" in
+ start)
+ start-stop-daemon --start --verbose --exec $DAEMON
+ ;;
+ stop)
+ start-stop-daemon --stop --verbose --exec $DAEMON
+ ;;
+ #reload)
+ #
+ # If the daemon can reload its config files on the fly
+ # for example by sending it SIGHUP, do it here.
+ #
+ # If the daemon responds to changes in its config file
+ # directly anyway, make this a do-nothing entry.
+ #
+ # start-stop-daemon --stop --signal 1 --verbose --exec $DAEMON
+ # ;;
+ restart|force-reload)
+ #
+ # If the "reload" option is implemented, move the "force-reload"
+ # option to the "reload" entry above. If not, "force-reload" is
+ # just the same as "restart".
+ #
+ start-stop-daemon --stop --verbose --exec $DAEMON
+ sleep 1
+ start-stop-daemon --start --verbose --exec $DAEMON
+ ;;
+ *)
+ echo "Usage: /etc/init.d/pyg {start|stop|restart|force-reload}"
+ exit 1
+ ;;
+esac
+
+exit 0
diff --git a/debian/notused/manpage.1.ex b/debian/notused/manpage.1.ex
new file mode 100644
index 0000000..4ce8b61
--- /dev/null
+++ b/debian/notused/manpage.1.ex
@@ -0,0 +1,41 @@
+.TH NAME SECTION
+.\" NAME should be all caps, SECTION should be 1-8, maybe w/ subsection
+.\" other parms are allowed: see man(7), man(1)
+.SH NAME
+pyg \- programs to do something
+.SH SYNOPSIS
+.B pyg
+.I "[options] files ..."
+.br
+.B bar
+.I "[options] files ..."
+.SH "DESCRIPTION"
+This manual page documents briefly the
+.BR pyg ,
+and
+.B bar
+commands.
+This manual page was written for the Debian GNU/Linux distribution
+because the original program does not have a manual page.
+Instead, it has documentation in the GNU Info format; see below.
+.PP
+.B pyg
+is a program that...
+.SH OPTIONS
+The programs follow the usual GNU command line syntax, with long
+options starting with two dashes (`-').
+A summary of options are included below.
+For a complete description, see the Info files.
+.TP
+.B \-h, \-\-help
+Show summary of options.
+.TP
+.B \-v, \-\-version
+Show version of program.
+.SH "SEE ALSO"
+The programs are documented fully by
+.IR "The Rise and Fall of a Fooish Bar" ,
+available via the Info system.
+.SH AUTHOR
+This manual page was written by Kame Alfa III <kame@aragorn.lorien.org>,
+for the Debian GNU/Linux system (but may be used by others).
diff --git a/debian/notused/menu.ex b/debian/notused/menu.ex
new file mode 100644
index 0000000..b608ca8
--- /dev/null
+++ b/debian/notused/menu.ex
@@ -0,0 +1,2 @@
+?package(pyg):needs=X11|text|vc|wm section=Apps/see-menu-manual\
+ title="pygs" command="/usr/sbin/pygs"
diff --git a/debian/notused/watch.ex b/debian/notused/watch.ex
new file mode 100644
index 0000000..5aba8f5
--- /dev/null
+++ b/debian/notused/watch.ex
@@ -0,0 +1,5 @@
+# Example watch control file for uscan
+# Rename this file to "watch" and then you can run the "uscan" command
+# to check for upstream updates and more.
+# Site Directory Pattern Version Script
+sunsite.unc.edu /pub/Linux/Incomingu pyg-*.tar.gz debian uupdate
diff --git a/pygm2n.1 b/debian/pygm2n.1
index 63f2e09..63f2e09 100644
--- a/pygm2n.1
+++ b/debian/pygm2n.1
diff --git a/pygn2m.1 b/debian/pygn2m.1
index 5b2750e..5b2750e 100644
--- a/pygn2m.1
+++ b/debian/pygn2m.1
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 0000000..23bee10
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,78 @@
+#!/usr/bin/make -f
+
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+# This is the debhelper compatability version to use.
+export DH_COMPAT=3
+
+export package=pyg
+export debdestdir=$(CURDIR)/debian/$(package)
+
+build: build-stamp
+
+build-stamp:
+ dh_testdir
+
+ $(MAKE) bin #CFLAGS="-O2 -g -Wall"
+ touch build-stamp
+
+clean:
+ dh_testdir
+
+ -rm -f build-stamp
+ -$(MAKE) clean
+
+ -dh_clean
+
+install: build
+ dh_testdir
+ dh_testroot
+ dh_clean -k
+ dh_installdirs
+
+ $(MAKE) install DESTDIR=$(debdestdir)
+
+
+binary-arch: build install
+ dh_testdir
+ dh_testroot
+
+ dh_installdirs
+ dh_installchangelogs
+ dh_installdocs
+ dh_installmanpages
+# dh_installinfo
+
+ # these are class modules, they don't need manpages,
+ # undocumented link means I'm planning to document them.
+ #dh_undocumented whitelist.py.3 news2mail.py.3 mail2news.py.3 pyginfo.py.3
+ dh_installexamples
+
+ dh_fixperms
+ # dh_fixperms doesn't fix perms in /usr/lib subdirs
+ chmod 0644 $(debdestdir)/usr/lib/$(package)/*.py
+ # make sure pyg executables have right permission
+ chmod 0755 $(debdestdir)/usr/bin/pygn2m
+ chmod 0755 $(debdestdir)/usr/bin/pygm2n
+
+ # dh_fixperms doesn't fix perms in /usr/share/doc subdirs
+ find $(debdestdir)/usr/share/doc/$(package) -type d -exec chmod 0755 {} \;
+
+ dh_strip
+ dh_compress
+ dh_installdeb
+ dh_shlibdeps
+ dh_gencontrol
+ dh_builddeb
+
+
+# no binary arch-indep is present
+binary-indep: build install
+ dh_testdir
+ dh_testroot
+
+binary: binary-indep binary-arch
+
+.PHONY: build binary binary-arch binary-indep clean install
diff --git a/debian/whitelist.5 b/debian/whitelist.5
new file mode 100644
index 0000000..d129243
--- /dev/null
+++ b/debian/whitelist.5
@@ -0,0 +1,75 @@
+.\" wing requests are required for all man pages.
+.Dd July 23, 2000
+.Os Debian GNU/Linux
+.Dt whitelist 5
+.Sh NAME
+.Nm pygs
+.Nd the PYthon Gateway Script
+.Sh SYNOPSIS
+pygs
+-t recipient@domain1
+-s sender@domain2
+[-e envelope@domain3]
+[-d]
+[-T]
+[-V]
+[-l logfile]
+[-w whitelist]
+[-h]
+.Sh DESCRIPTION
+NOTE: this man page is to be continued :)
+
+pygs read from stdin a nntp article, sending it to recipient@domain1 a rfc822 compliant email setting Resent-Sender: sender@domain2 and envelope envelope@domain3 if exists, else sender@domain2.
+.Sh OPTIONS
+.Tp 0.5i
+.B \-t
+
+\" The following requests should be uncommented and
+.\" used where appropriate. This next request is
+.\" for sections 2 and 3 function return values only.
+.\" .Sh RETURN VALUES
+.\" This next request is for sections 1, 6, 7 & 8 only
+.\" .Sh ENVIRONMENT
+.\" .Sh FILES
+.Sh EXAMPLES
+There is some documetation in /urs/share/doc/pyg
+
+I created mailgate user (moderator of local.moderated ng).
+Every article posted in local.moderated is sent to mailgate,
+in its .procmailrc I've put:
+
+.Bd
+.Li :0 bhc
+.Li \ * ^To: *local-moderated
+.Li | $HOME/pygs -t kalfa@localhost -e mailgate@students.cs.unibo.it -s 'cosimo@students.cs.unibo.it'
+.Ed
+
+where kalfa@localhost is the recipient (it usually is a mailing list)
+
+an header extract from kalfa@localhost mbox:
+
+From mailgate@students.cs.unibo.it
+From: whosentnntparticle@domain4
+To: kalfa@localhost
+Resent-Sender: cosimo@students.cs.unibo.it
+
+note that sender and envelope are different. rfc822 says that Sender: have to be a human user (not a program or similia). envelope can mailgate user.
+
+.
+
+.\" This next request is for sections 1, 6, 7 & 8 only
+.\" (command return values (to shell) and
+.\" fprintf/stderr type diagnostics)
+.\" .Sh DIAGNOSTICS
+.\" The next request is for sections 2 and 3 error
+.\" and signal handling only.
+.\" .Sh ERRORS
+.\" .Sh SEE ALSO
+.\" .Sh STANDARDS
+.\" .Sh HISTORY
+.Sh AUTHORS
+Cosimo Alfarano <alfarano@students.cs.unibo.it>
+.Sh BUGS
+Boh. send any bug to the author
+.An , please.
+
diff --git a/docs/01-leafnode-list-pygn-as-mail2news.html b/docs/01-leafnode-list-pygn-as-mail2news.html
deleted file mode 100644
index a582b0d..0000000
--- a/docs/01-leafnode-list-pygn-as-mail2news.html
+++ /dev/null
@@ -1,148 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
-<HTML>
- <HEAD>
- <TITLE> [leafnode-list] pygn as a mail2news gateway
- </TITLE>
- <LINK REL="Index" HREF="index.html" >
- <LINK REL="made" HREF="mailto:leafnode-list%40dt.e-technik.uni-dortmund.de?Subject=%5Bleafnode-list%5D%20%20pygn%20as%20a%20mail2news%20gateway&In-Reply-To=">
- <META NAME="robots" CONTENT="index,nofollow">
- <META http-equiv="Content-Type" content="text/html; charset=us-ascii">
- <LINK REL="Previous" HREF="001361.html">
- <LINK REL="Next" HREF="001368.html">
- </HEAD>
- <BODY BGCOLOR="#ffffff">
- <H1>[leafnode-list] pygn as a mail2news gateway</H1>
- <B>Matej Cepl</B>
- <A HREF="mailto:leafnode-list%40dt.e-technik.uni-dortmund.de?Subject=%5Bleafnode-list%5D%20%20pygn%20as%20a%20mail2news%20gateway&In-Reply-To="
- TITLE="[leafnode-list] pygn as a mail2news gateway">ceplm at seznam.cz
- </A><BR>
- <I>Fri Sep 1 05:26:49 CEST 2006</I>
- <P><UL>
- <LI>Previous message: <A HREF="001361.html">[leafnode-list] leafnode-2.0.0.alpha20060831a snapshot available
-</A></li>
- <LI>Next message: <A HREF="001368.html">[leafnode-list] Re: pygn as a mail2news gateway
-</A></li>
- <LI> <B>Messages sorted by:</B>
- <a href="date.html#1364">[ date ]</a>
- <a href="thread.html#1364">[ thread ]</a>
- <a href="subject.html#1364">[ subject ]</a>
- <a href="author.html#1364">[ author ]</a>
- </LI>
- </UL>
- <HR>
-<!--beginarticle-->
-<PRE>Hi,
-
-so now the real problem I am dealing with -- mail2news bidirectional
-gateway.
-
-On leafnode 1.* I used mail2news patch by Nikita Youschenko
-(<A HREF="http://zigzag.lvk.cs.msu.su/leafnode/">http://zigzag.lvk.cs.msu.su/leafnode/</A> -- I wonder something like that has
-not been included in leafnode 2.*, it would make great fit IMHO, but I know
-I am not a programmer, and I won't do it, so I shut up on this), so I have
-to install some mail2news gateway. I tried pygn (just because it is
-packaged for Debian; any other suggestions?), but I haven't managed to
-configured it yet. This is what I did (with expected workflow):
-
-1) mail is read by my kmail (user matej) and if it is list message which
-should be gatewayed to news, it is bounced to <A HREF="https://www.dt.e-technik.uni-dortmund.de/mailman/listinfo/leafnode-list">news at localhost</A> -- this step
-has been working perfectly for couple of years and it has not been changed.
-
-2) news' .procmailrc contains a lot of rules like this (for news2mail):
-
-ARG = $1
-
-:<i>0 bh:
-</I>* ARG ?? local-mail-comp-boston
-|<i> pygn2m -l $HOME/log-pygn2m -d -t <A HREF="https://www.dt.e-technik.uni-dortmund.de/mailman/listinfo/leafnode-list">discuss at blu.org</A> -s <A HREF="https://www.dt.e-technik.uni-dortmund.de/mailman/listinfo/leafnode-list">ceplm at seznam.cz</A>
-</I>
-and like this (for mail2news):
-
-:<i>0 bh:
-</I>* ^List-Id:.*pkg-lyx-devel.lists.alioth.debian.org
-|<i> pygm2n -l $HOME/log-pygm2n -d -n local.mail.comp.lyx-debian
-</I>
-/etc/news/local.groups is this:
-
-local.mail.comp.cambridge m Cambridge (UK) LUG
-local.mail.comp.boston m Boston LUG
-local.mail.comp.surrey m Surrey LUG
-local.mail.comp.bosto-admin m Boston admins
-local.mail.comp.oxford m Oxford LUG
-local.mail.comp.lyx-debian m Maintainer of LyX on Debian
-local.mail.comp.scottish m Scottish LUG
-local.mail.comp.northwales m NWales LUG
-local.mail.comp.southwales m SWales LUG
-local.mail.comp.czdebian m Diskuse &#269;esk&#253;ch u&#382;ivatel Debianu
-local.mail.vcfc.random m Random list z VCFC
-local.mail.vcfc.branik m Diskuse &#268;CE Bran&#237;k
-local.mail.soc.oakeshott m Conversation -- discussion about Oakeshott
-local.mail.soc.read-only m r&#367;zn&#225; RO sociologie
-local.mail.zpravy m NG pro r&#367;zn&#233; zpravodajstv&#237;
-local.test m testing group
-
-and this is /etc/news/moderators (w/o comments):
-
-## Public hierarchies with exceptions.
-fido7.*:%<A HREF="https://www.dt.e-technik.uni-dortmund.de/mailman/listinfo/leafnode-list">s at fido7.ru</A>
-ffm.*:%<A HREF="https://www.dt.e-technik.uni-dortmund.de/mailman/listinfo/leafnode-list">s at moderators.arcornews.de</A>
-fj.*:%<A HREF="https://www.dt.e-technik.uni-dortmund.de/mailman/listinfo/leafnode-list">s at moderators.fj-news.org</A>
-medlux.*:%<A HREF="https://www.dt.e-technik.uni-dortmund.de/mailman/listinfo/leafnode-list">s at news.medlux.ru</A>
-nl.*:%<A HREF="https://www.dt.e-technik.uni-dortmund.de/mailman/listinfo/leafnode-list">s at nl.net</A>
-relcom.*:%<A HREF="https://www.dt.e-technik.uni-dortmund.de/mailman/listinfo/leafnode-list">s at moderators.relcom.ru</A>
-ukr.*:%<A HREF="https://www.dt.e-technik.uni-dortmund.de/mailman/listinfo/leafnode-list">s at sita.kiev.ua</A>
-
-# local groups are moderated by <A HREF="https://www.dt.e-technik.uni-dortmund.de/mailman/listinfo/leafnode-list">news at localhost</A>
-local.*:news+%<A HREF="https://www.dt.e-technik.uni-dortmund.de/mailman/listinfo/leafnode-list">s at localhost</A>
-
-# and all gmane stuff should be posted directly
-# gmane does its own thing on it
-gmane.*:
-
-## Direct all other public hierarchies to the master moderator database.
-*:%<A HREF="https://www.dt.e-technik.uni-dortmund.de/mailman/listinfo/leafnode-list">s at moderators.isc.org</A>
-
-Even though (according to ~news/log-procmail) all messages seem to be
-running correctly, I don't get a message with moderated newsgroups.
-However, without moderating newsgroups, I don't know how to make work
-sending emails from leafnode to email.
-
-Any thoughts or help, please?
-
-Best,
-
-Mat&#283;j
-
---
-GPG Finger: 89EF 4BC6 288A BF43 1BAB 25C3 E09F EF25 D964 84AC
-<A HREF="http://www.ceplovi.cz/matej/blog/,">http://www.ceplovi.cz/matej/blog/,</A> Jabber: <A HREF="https://www.dt.e-technik.uni-dortmund.de/mailman/listinfo/leafnode-list">ceplma at jabber.cz</A>
-23 Marion St. #3, (617) 876-1259, ICQ 132822213
-
-Home is where ~/.bashrc is.
- -- from Usenet
--------------- next part --------------
-An embedded and charset-unspecified text was scrubbed...
-Name: .procmailrc
-Url: <A HREF="http://www.dt.e-technik.uni-dortmund.de/pipermail/leafnode-list/attachments/20060831/47d485c1/attachment.txt">http://www.dt.e-technik.uni-dortmund.de/pipermail/leafnode-list/attachments/20060831/47d485c1/attachment.txt</A>
-</PRE>
-
-<!--endarticle-->
- <HR>
- <P><UL>
- <!--threads-->
- <LI>Previous message: <A HREF="001361.html">[leafnode-list] leafnode-2.0.0.alpha20060831a snapshot available
-</A></li>
- <LI>Next message: <A HREF="001368.html">[leafnode-list] Re: pygn as a mail2news gateway
-</A></li>
- <LI> <B>Messages sorted by:</B>
- <a href="date.html#1364">[ date ]</a>
- <a href="thread.html#1364">[ thread ]</a>
- <a href="subject.html#1364">[ subject ]</a>
- <a href="author.html#1364">[ author ]</a>
- </LI>
- </UL>
-
-<hr>
-<a href="https://www.dt.e-technik.uni-dortmund.de/mailman/listinfo/leafnode-list">More information about the leafnode-list
-mailing list</a><br>
-</body></html>
diff --git a/docs/02-leafnode-list-pygn-as-mail2news.html b/docs/02-leafnode-list-pygn-as-mail2news.html
deleted file mode 100644
index 886d064..0000000
--- a/docs/02-leafnode-list-pygn-as-mail2news.html
+++ /dev/null
@@ -1,85 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
-<HTML>
- <HEAD>
- <TITLE> [leafnode-list] Re: pygn as a mail2news gateway
- </TITLE>
- <LINK REL="Index" HREF="index.html" >
- <LINK REL="made" HREF="mailto:leafnode-list%40dt.e-technik.uni-dortmund.de?Subject=%5Bleafnode-list%5D%20Re%3A%20pygn%20as%20a%20mail2news%20gateway&In-Reply-To=">
- <META NAME="robots" CONTENT="index,nofollow">
- <META http-equiv="Content-Type" content="text/html; charset=us-ascii">
- <LINK REL="Previous" HREF="001364.html">
- <LINK REL="Next" HREF="001379.html">
- </HEAD>
- <BODY BGCOLOR="#ffffff">
- <H1>[leafnode-list] Re: pygn as a mail2news gateway</H1>
- <B>Matej Cepl</B>
- <A HREF="mailto:leafnode-list%40dt.e-technik.uni-dortmund.de?Subject=%5Bleafnode-list%5D%20Re%3A%20pygn%20as%20a%20mail2news%20gateway&In-Reply-To="
- TITLE="[leafnode-list] Re: pygn as a mail2news gateway">ceplm at seznam.cz
- </A><BR>
- <I>Fri Sep 1 19:35:16 CEST 2006</I>
- <P><UL>
- <LI>Previous message: <A HREF="001364.html">[leafnode-list] pygn as a mail2news gateway
-</A></li>
- <LI>Next message: <A HREF="001379.html">[leafnode-list] Re: pygn as a mail2news gateway
-</A></li>
- <LI> <B>Messages sorted by:</B>
- <a href="date.html#1368">[ date ]</a>
- <a href="thread.html#1368">[ thread ]</a>
- <a href="subject.html#1368">[ subject ]</a>
- <a href="author.html#1368">[ author ]</a>
- </LI>
- </UL>
- <HR>
-<!--beginarticle-->
-<PRE>Matej Cepl wrote:
-&gt;<i> so now the real problem I am dealing with -- mail2news bidirectional
-</I>&gt;<i> gateway.
-</I>
-I tried everything, but I am just not able to make it working. So I have to
-ask again: is there any leafnode-style (aka &quot;for dummies&quot;) HOWTO for
-mail2news bi-directional gateway? The most far I got is that I have all my
-local newsgroups unmoderated, so I at least get messages to them. When I
-switch them to moderated, a) I don't get any messages to read, b) no
-messages are posted anyway. Details of how I tried (see above in this
-thread).
-
-Can anybody help me please?
-
-Thanks a lot,
-
-Mat&#283;j
-
---
-GPG Finger: 89EF 4BC6 288A BF43 1BAB 25C3 E09F EF25 D964 84AC
-<A HREF="http://www.ceplovi.cz/matej/blog/,">http://www.ceplovi.cz/matej/blog/,</A> Jabber: <A HREF="https://www.dt.e-technik.uni-dortmund.de/mailman/listinfo/leafnode-list">ceplma at jabber.cz</A>
-23 Marion St. #3, (617) 876-1259, ICQ 132822213
-
-See, when the GOVERNMENT spends money, it creates jobs; whereas
-when the money is left in the hands of TAXPAYERS, God only knows
-what they do with it. Bake it into pies, probably. Anything to
-avoid creating jobs.
- -- Dave Barry
-
-
-</PRE>
-
-<!--endarticle-->
- <HR>
- <P><UL>
- <!--threads-->
- <LI>Previous message: <A HREF="001364.html">[leafnode-list] pygn as a mail2news gateway
-</A></li>
- <LI>Next message: <A HREF="001379.html">[leafnode-list] Re: pygn as a mail2news gateway
-</A></li>
- <LI> <B>Messages sorted by:</B>
- <a href="date.html#1368">[ date ]</a>
- <a href="thread.html#1368">[ thread ]</a>
- <a href="subject.html#1368">[ subject ]</a>
- <a href="author.html#1368">[ author ]</a>
- </LI>
- </UL>
-
-<hr>
-<a href="https://www.dt.e-technik.uni-dortmund.de/mailman/listinfo/leafnode-list">More information about the leafnode-list
-mailing list</a><br>
-</body></html>
diff --git a/docs/joerg01.eml b/docs/joerg01.eml
deleted file mode 100644
index 3b13030..0000000
--- a/docs/joerg01.eml
+++ /dev/null
@@ -1,145 +0,0 @@
-Path: news.gmane.org!not-for-mail
-From: Joerg Dietrich <joerg-FR+SGtcfUjXk1uMJSBkQmQ@public.gmane.org>
-Newsgroups: gmane.network.leafnode
-Subject: Re: status of leafnode 2 and how to upgrade from
- leafnode 1
-Date: Wed, 16 Aug 2006 16:15:54 +0200
-Lines: 60
-Approved: news@gmane.org
-Message-ID: <20060816141554.GA30999@leviathan.homedns.org>
-References: <hq35r3-igk.ln1@chelcicky.vysocina>
- <m3irkvr86e.fsf@merlin.emma.line.org>
-NNTP-Posting-Host: main.gmane.org
-Mime-Version: 1.0
-Content-Type: text/plain; charset="iso-8859-1"
-Content-Transfer-Encoding: quoted-printable
-X-Trace: sea.gmane.org 1155748787 14017 80.91.229.2 (16 Aug 2006 17:19:47 GMT)
-X-Complaints-To: usenet@sea.gmane.org
-NNTP-Posting-Date: Wed, 16 Aug 2006 17:19:47 +0000 (UTC)
-Original-X-From: leafnode-list-bounces+gnl-leafnode-list=m.gmane.org-DcxqERLcJkQeCZckdHr3IYGCWcDMi6xaD8jGkxKTr40@public.gmane.org Wed Aug 16 19:19:42 2006
-Return-path: <leafnode-list-bounces+gnl-leafnode-list=m.gmane.org-DcxqERLcJkQeCZckdHr3IYGCWcDMi6xaD8jGkxKTr40@public.gmane.org>
-Envelope-to: gnl-leafnode-list@m.gmane.org
-Original-Received: from krusty.dt.e-technik.uni-dortmund.de ([129.217.163.1])
- by ciao.gmane.org with esmtp (Exim 4.43)
- id 1GDP3I-0004At-B1
- for gnl-leafnode-list@m.gmane.org; Wed, 16 Aug 2006 19:19:36 +0200
-Original-Received: from krusty.dt.e-technik.uni-dortmund.de (localhost [127.0.0.1])
- by mail.dt.e-technik.uni-dortmund.de (Postfix) with ESMTP id E257285FB49
- for <gnl-leafnode-list@m.gmane.org>; Wed, 16 Aug 2006 19:19:35 +0200 (CEST)
-X-Original-To: leafnode-list-DcxqERLcJkQeCZckdHr3IYGCWcDMi6xaD8jGkxKTr40@public.gmane.org
-Delivered-To: leafnode-list-DcxqERLcJkQeCZckdHr3IYGCWcDMi6xaD8jGkxKTr40@public.gmane.org
-Original-Received: from localhost (localhost [127.0.0.1])
- by mail.dt.e-technik.uni-dortmund.de (Postfix) with ESMTP id
- 692D185FB46 for <leafnode-list-DcxqERLcJkQeCZckdHr3IYGCWcDMi6xaD8jGkxKTr40@public.gmane.org>;
- Wed, 16 Aug 2006 19:19:32 +0200 (CEST)
-Original-Received: from krusty.dt.e-technik.uni-dortmund.de ([127.0.0.1])
- by localhost (krusty [127.0.0.1]) (amavisd-new, port 10024) with ESMTP
- id 09436-03 for <leafnode-list-DcxqERLcJkQeCZckdHr3IYGCWcDMi6xaD8jGkxKTr40@public.gmane.org>;
- Wed, 16 Aug 2006 19:19:29 +0200 (CEST)
-Original-Received: from nx5.hrz.uni-dortmund.de (nx5.HRZ.Uni-Dortmund.DE
- [129.217.131.21])
- by mail.dt.e-technik.uni-dortmund.de (Postfix) with ESMTP id
- 9450585FE4E for <leafnode-list-DcxqERLcJkQeCZckdHr3IYGCWcDMi6xaD8jGkxKTr40@public.gmane.org>;
- Wed, 16 Aug 2006 19:19:27 +0200 (CEST)
-Original-Received: from ws6-3.us4.outblaze.com (ws6-3.us4.outblaze.com [205.158.62.199])
- by nx5.hrz.uni-dortmund.de (Postfix) with SMTP id 6E9BA4AA5F7
- for <leafnode-list-DcxqERLcJkQeCZckdHr3IYGCWcDMi6xaD8jGkxKTr40@public.gmane.org>;
- Wed, 16 Aug 2006 18:54:36 +0200 (MET DST)
-Original-Received: (qmail 12849 invoked from network); 16 Aug 2006 14:16:00 -0000
-Original-Received: from unknown (HELO leviathan.homedns.org)
- (joerg-FR+SGtcfUjXk1uMJSBkQmQ@public.gmane.org@80.136.237.253)
- by ws6-3.us4.outblaze.com with SMTP; 16 Aug 2006 14:15:58 -0000
-Original-Received: from leviathan.homedns.org (nobody@localhost [127.0.0.1])
- by leviathan.homedns.org (8.13.7/8.13.7) with ESMTP id k7GEFs5l031057
- for <leafnode-list-DcxqERLcJkQeCZckdHr3IYGCWcDMi6xaD8jGkxKTr40@public.gmane.org>;
- Wed, 16 Aug 2006 16:15:55 +0200
-Original-Received: (from joerg@localhost)
- by leviathan.homedns.org (8.13.7/8.12.11/Submit) id k7GEFsZg031053
- for leafnode-list-DcxqERLcJkQeCZckdHr3IYGCWcDMi6xaD8jGkxKTr40@public.gmane.org;
- Wed, 16 Aug 2006 16:15:54 +0200
-Original-To: leafnode-list-DcxqERLcJkQeCZckdHr3IYGCWcDMi6xaD8jGkxKTr40@public.gmane.org
-Mail-Followup-To: leafnode-list-DcxqERLcJkQeCZckdHr3IYGCWcDMi6xaD8jGkxKTr40@public.gmane.org
-Content-Disposition: inline
-In-Reply-To: <m3irkvr86e.fsf-SvAj7qPd1zteOLZSG9Hm2mD2FQJk+8+b@public.gmane.org>
-User-Agent: Mutt/1.5.11
-X-Virus-Scanned: amavisd-new at dt.e-technik.uni-dortmund.de
-X-Spam-Status: No, hits=0.001 tagged_above=0 required=7
- tests=[UNPARSEABLE_RELAY=0.001]
-X-Spam-Level:
-X-BeenThere: leafnode-list-DcxqERLcJkQeCZckdHr3IYGCWcDMi6xaD8jGkxKTr40@public.gmane.org
-X-Mailman-Version: 2.1.8
-Precedence: list
-List-Id: Discussions on the Leafnode Usenet software package
- <leafnode-list.dt.e-technik.uni-dortmund.de>
-List-Unsubscribe: <https://www.dt.e-technik.uni-dortmund.de/mailman/listinfo/leafnode-list>,
- <mailto:leafnode-list-request-DcxqERLcJkQeCZckdHr3IYGCWcDMi6xaD8jGkxKTr40@public.gmane.org?subject=unsubscribe>
-List-Archive: <http://www.dt.e-technik.uni-dortmund.de/pipermail/leafnode-list>
-List-Post: <mailto:leafnode-list-DcxqERLcJkQeCZckdHr3IYGCWcDMi6xaD8jGkxKTr40@public.gmane.org>
-List-Help: <mailto:leafnode-list-request-DcxqERLcJkQeCZckdHr3IYGCWcDMi6xaD8jGkxKTr40@public.gmane.org?subject=help>
-List-Subscribe: <https://www.dt.e-technik.uni-dortmund.de/mailman/listinfo/leafnode-list>,
- <mailto:leafnode-list-request-DcxqERLcJkQeCZckdHr3IYGCWcDMi6xaD8jGkxKTr40@public.gmane.org?subject=subscribe>
-Original-Sender: leafnode-list-bounces+gnl-leafnode-list=m.gmane.org-DcxqERLcJkQeCZckdHr3IYGCWcDMi6xaD8jGkxKTr40@public.gmane.org
-Errors-To: leafnode-list-bounces+gnl-leafnode-list=m.gmane.org-DcxqERLcJkQeCZckdHr3IYGCWcDMi6xaD8jGkxKTr40@public.gmane.org
-Xref: news.gmane.org gmane.network.leafnode:3524
-Archived-At: <http://permalink.gmane.org/gmane.network.leafnode/3524>
-
-On Mon, Aug 14, 2006 at 11:14:01AM +0200, Matthias Andree wrote:
-> fetches group articles faster (thanks to pipelining ARTICLE or
-> HEAD/BODY commands).
-
-Which was a big issue when Cornelius and I worked on this in
-1999/2000 when many people still had expensive dial-up
-connections that were not fully utilized by fetchnews.
-
-> Official mail2news gatewaying isn't integrated and probably suffers from
-> the usual "Message-ID are unique per server" problem that impairs messages
-> sent to several lists at the same time. I don't know the state of J=F6rg
-> Dietrich's prior works or views on this either.
-
-I run a mail2news gateway for three or four mailing lists on my
-computer. I wrote a python programme for this. It is available
-from <http://www.astro.uni-bonn.de/~dietrich/mail2news/>. The
-program lacks documentation and testing by a wider audience,
-which is the reason for its "alpha status". However, the program
-has been working for me for the last 2 years without any need of
-intervention. But I have very little feedback from others.
-
-Mail2news.py tries to circumvent the problem of unique
-Message-IDs by cross-posting to newsgroups corresponding to the
-mailing lists the original mail was sent to. Because
-cross-mailing does not happen with the few mailing list I am
-subscribed to this feature is anything but well tested.
-
-> It is alpha because I don't care too much for compatibility between
-> leafnode-2 versions until I'm happy with it (not much work has been done
-> to leafnode-2 in the past weeks since I've been busy with difficult
-> fetchmail bug fixes). Else, I know of few bugs that hinder daily
-> personal use and am usually quick to fix bugs given the report is
-> substantiated (for instance, with a stack backtrace).
-
-As someone who contributed a substantial amount of code in the
-past, I find this a very frustrating status. Since 2000 leafnode-2
-provides significant improved features over leafnode-1. I have
-been using leafnode-2 in production mode for four or five years
-now. I really do not understand what keeps you from releasing it
-instead of keeping it in alpha stage for 5 years and still
-supporting leafnode-1, which has been technically obsoleted by
-many improvements in leafnode-2.
-
-Cheers,
- Jo:rg
-
--- =
-
- ---=3D=3D=3D Encrypted mail preferred. Key-ID: 1024D/2B693EBF =3D=
-=3D=3D---
-Fortune cookie of the day:
-A clash of doctrine is not a disaster -- it is an opportunity.
--- =
-
-_______________________________________________
-leafnode-list mailing list
-leafnode-list-DcxqERLcJkQeCZckdHr3IYGCWcDMi6xaD8jGkxKTr40@public.gmane.org
-https://www.dt.e-technik.uni-dortmund.de/mailman/listinfo/leafnode-list
-http://leafnode.sourceforge.net/
-
diff --git a/docs/mail2news-gateway.eml b/docs/mail2news-gateway.eml
deleted file mode 100644
index 1c57406..0000000
--- a/docs/mail2news-gateway.eml
+++ /dev/null
@@ -1,268 +0,0 @@
-From ceplm@seznam.cz Fri Sep 1 13:51:25 2006
-Message-Id: <pslks3xh02.ln2@chelcicky.vysocina>
-From: Matej Cepl <ceplm@seznam.cz>
-Subject: pygn as a mail2news gateway
-Newsgroups: gmane.network.leafnode
-Date: Thu, 31 Aug 2006 23:26:49 -0400
-User-Agent: KNode/0.10.2
-MIME-Version: 1.0
-Content-Type: multipart/mixed; boundary="nextPart1312693.60ImoN5RI4"
-Content-Transfer-Encoding: 7Bit
-Status: RO
-Content-Length: 7709
-Lines: 247
-
---nextPart1312693.60ImoN5RI4
-Content-Type: text/plain; charset=utf-8
-Content-Transfer-Encoding: 8Bit
-
-Hi,
-
-so now the real problem I am dealing with -- mail2news bidirectional
-gateway.
-
-On leafnode 1.* I used mail2news patch by Nikita Youschenko
-(http://zigzag.lvk.cs.msu.su/leafnode/ -- I wonder something like that has
-not been included in leafnode 2.*, it would make great fit IMHO, but I know
-I am not a programmer, and I won't do it, so I shut up on this), so I have
-to install some mail2news gateway. I tried pygn (just because it is
-packaged for Debian; any other suggestions?), but I haven't managed to
-configured it yet. This is what I did (with expected workflow):
-
-1) mail is read by my kmail (user matej) and if it is list message which
-should be gatewayed to news, it is bounced to news@localhost -- this step
-has been working perfectly for couple of years and it has not been changed.
-
-2) news' .procmailrc contains a lot of rules like this (for news2mail):
-
-ARG = $1
-
-:0 bh:
-* ARG ?? local-mail-comp-boston
-| pygn2m -l $HOME/log-pygn2m -d -t discuss@blu.org -s ceplm@seznam.cz
-
-and like this (for mail2news):
-
-:0 bh:
-* ^List-Id:.*pkg-lyx-devel.lists.alioth.debian.org
-| pygm2n -l $HOME/log-pygm2n -d -n local.mail.comp.lyx-debian
-
-/etc/news/local.groups is this:
-
-local.mail.comp.cambridge m Cambridge (UK) LUG
-local.mail.comp.boston m Boston LUG
-local.mail.comp.surrey m Surrey LUG
-local.mail.comp.bosto-admin m Boston admins
-local.mail.comp.oxford m Oxford LUG
-local.mail.comp.lyx-debian m Maintainer of LyX on Debian
-local.mail.comp.scottish m Scottish LUG
-local.mail.comp.northwales m NWales LUG
-local.mail.comp.southwales m SWales LUG
-local.mail.comp.czdebian m Diskuse českých uživatel Debianu
-local.mail.vcfc.random m Random list z VCFC
-local.mail.vcfc.branik m Diskuse ČCE Braník
-local.mail.soc.oakeshott m Conversation -- discussion about Oakeshott
-local.mail.soc.read-only m různá RO sociologie
-local.mail.zpravy m NG pro různé zpravodajství
-local.test m testing group
-
-and this is /etc/news/moderators (w/o comments):
-
-## Public hierarchies with exceptions.
-fido7.*:%s@fido7.ru
-ffm.*:%s@moderators.arcornews.de
-fj.*:%s@moderators.fj-news.org
-medlux.*:%s@news.medlux.ru
-nl.*:%s@nl.net
-relcom.*:%s@moderators.relcom.ru
-ukr.*:%s@sita.kiev.ua
-
-# local groups are moderated by news@localhost
-local.*:news+%s@localhost
-
-# and all gmane stuff should be posted directly
-# gmane does its own thing on it
-gmane.*:
-
-## Direct all other public hierarchies to the master moderator database.
-*:%s@moderators.isc.org
-
-Even though (according to ~news/log-procmail) all messages seem to be
-running correctly, I don't get a message with moderated newsgroups.
-However, without moderating newsgroups, I don't know how to make work
-sending emails from leafnode to email.
-
-Any thoughts or help, please?
-
-Best,
-
-Matěj
-
---
-GPG Finger: 89EF 4BC6 288A BF43 1BAB 25C3 E09F EF25 D964 84AC
-http://www.ceplovi.cz/matej/blog/, Jabber: ceplma@jabber.cz
-23 Marion St. #3, (617) 876-1259, ICQ 132822213
-
-Home is where ~/.bashrc is.
- -- from Usenet
-
---nextPart1312693.60ImoN5RI4
-Content-Type: text/plain; name=".procmailrc"
-Content-Transfer-Encoding: 8Bit
-Content-Disposition: attachment; filename=".procmailrc"
-
-PATH=/bin:/usr/bin:/usr/bin
-LOGFILE=$HOME/log-procmail
-VERBOSE=yes
-
-# Note: The $1 contains value only _IF_ procmail
-# is invoked with option -m or -a (with an argument).
-# Be sure procmail is invoked with that oprion either as from
-# LDA or ~/.forward.
-#
-# $1 is pseudo variable and it can't be used in condition line,
-# so we copy the value to ARG.
-
-ARG = $1
-
-#:0 fwh
-#* ! ^List-Post:
-#* ^Mailing-List:
-#| sed -e '/^-\{6,\}\s*Yahoo\!\s*Groups\s*Sponsor/,$d' yahoo-groups-message.txt \
-#| sed -e :a -e '/^\n*$/{$d;N;};/\n$/ba'
-
-:0 bh:
-* ARG ?? local-mail-comp-boston
-| pygn2m -l $HOME/log-pygn2m -d -t discuss@blu.org -s ceplm@seznam.cz
-
-:0 bh:
-* ARG ?? local-mail-comp-lyx-debian
-| pygn2m -l $HOME/log-pygn2m -d -t pkg-lyx-devel@lists.alioth.debian.org -s ceplm@seznam.cz
-
-:0 bh:
-* ARG ?? local-mail-comp-boston
-| pygn2m -l $HOME/log-pygn2m -d -t discuss@blu.org -s ceplm@seznam.cz
-
-:0 bh:
-* ARG ?? local-mail-comp-bosto-admin
-| pygn2m -l $HOME/log-pygn2m -d -t bblisa@bblisa.org -s ceplm@seznam.cz
-
-:0 bh:
-* ARG ?? local-mail-comp-surrey
-| pygn2m -l $HOME/log-pygn2m -d -t surrey@mailman.lug.org.uk -s ceplm@seznam.cz
-
-:0 bh:
-* ARG ?? local-mail-comp-scottish
-| pygn2m -l $HOME/log-pygn2m -d -t scottish@mailman.lug.org.uk -s ceplm@seznam.cz
-
-:0 bh:
-* ARG ?? local-mail-comp-northwales
-| pygn2m -l $HOME/log-pygn2m -d -t northwales@mailman.lug.org.uk -s ceplm@seznam.cz
-
-:0 bh:
-* ARG ?? local-mail-comp-southwales
-| pygn2m -l $HOME/log-pygn2m -d -t discuss@swlug.org -s ceplm@seznam.cz
-
-:0 bh:
-* ARG ?? local-mail-comp-oxford
-| pygn2m -l $HOME/log-pygn2m -d -t oxlug@lists.oxlug.org -s ceplm@seznam.cz
-
-:0 bh:
-* ARG ?? local-mail-comp-cambridge
-| pygn2m -l $HOME/log-pygn2m -d -t clug@cambridge-lug.org -s ceplm@seznam.cz
-
-:0 bh:
-* ARG ?? local-mail-comp-czdebian
-| pygn2m -l $HOME/log-pygn2m -d -t czdebian-l@debian.cz -s ceplm@seznam.cz
-
-:0 bh:
-* ARG ?? local-mail-vcfc-random
-| pygn2m -l $HOME/log-pygn2m -d -t vcfgb-random@yahoogroups.com -s ceplm@seznam.cz
-
-:0 bh:
-* ARG ?? local-mail-vcfc-branik
-| pygn2m -l $HOME/log-pygn2m -d -t cebranik@pandora.cz -s ceplm@seznam.cz
-
-:0 bh:
-* ARG ?? local-mail-soc-goffman
-| pygn2m -l $HOME/log-pygn2m -d -t goffman@mail.lsit.ucsb.edu -s ceplm@seznam.cz
-
-:0 bh:
-* ARG ?? local-mail-soc-oakeshott
-| pygn2m -l $HOME/log-pygn2m -d -t conversation@jiscmail.ac.uk -s ceplm@seznam.cz
-
-:0 bh:
-* ARG ?? local-test
-| pygn2m -l $HOME/log-pygn2m -d -t matej@localhost -s ceplm@seznam.cz
-
-:0 bh:
-* ^Subject: *test
-| pygm2n -l $HOME/log-pygm2n -d -n local.test
-
-:0 bh:
-* ^List-Id:.*pkg-lyx-devel.lists.alioth.debian.org
-| pygm2n -l $HOME/log-pygm2n -d -n local.mail.comp.lyx-debian
-
-:0 bh:
-* ^List-Id:.*discuss.blu.org
-| pygm2n -l $HOME/log-pygm2n -d -n local.mail.comp.boston
-
-:0 bh:
-* ^List-Id:.*bblisa.bblisa.org
-| pygm2n -l $HOME/log-pygm2n -d -n local.mail.comp.bosto-admin
-
-:0 bh:
-* ^List-Id:.*surrey.mailman.lug.org.uk
-| pygm2n -l $HOME/log-pygm2n -d -n local.mail.comp.surrey
-
-:0 bh:
-* ^List-Id:.*scottish.mailman.lug.org.uk
-| pygm2n -l $HOME/log-pygm2n -d -n local.mail.comp.scottish
-
-:0 bh:
-* ^List-Id:.*northwales.mailman.lug.org.uk
-| pygm2n -l $HOME/log-pygm2n -d -n local.mail.comp.northwales
-
-:0 bh:
-* ^List-Id:.*discuss.swlug.org
-| pygm2n -l $HOME/log-pygm2n -d -n local.mail.comp.southwales
-
-:0 bh:
-* ^List-Id:.*oxlug.lists.oxlug.org
-| pygm2n -l $HOME/log-pygm2n -d -n local.mail.comp.oxford
-
-:0 bh:
-* ^List-Id:.*clug.cambridge-lug.org
-| pygm2n -l $HOME/log-pygm2n -d -n local.mail.comp.cambridge
-
-:0 bh:
-* ^List-Id:.*czdebian-l.debian.cz
-| pygm2n -l $HOME/log-pygm2n -d -n local.mail.comp.czdebian
-
-:0 bh:
-* ^Mailing-List:.*(vcfgb|vcfc)-(announce|random)@yahoogroups.com
-| pygm2n -l $HOME/log-pygm2n -d -n local.mail.vcfc.random
-
-:0 bh:
-* ^List-Post:.*cebranik@pandora.cz
-| pygm2n -l $HOME/log-pygm2n -d -n local.mail.vcfc.branik
-
-:0 bh:
-* ^List-Post:.*goffman.mail.lsit.ucsb.edu
-| pygm2n -l $HOME/log-pygm2n -d -n local.mail.soc.goffman
-
-:0 bh:
-* ^To:.*CONVERSATION@JISCMAIL.AC.UK
-| pygm2n -l $HOME/log-pygm2n -d -n local.mail.soc.oakeshott
-
-:0 bh:
-* ^To:.*(@JISCMAIL.AC.UK|PILN@COLUMBIA.EDU|UMD-LPBR-FULL@LISTSERV.UMD.EDU)
-| pygm2n -l $HOME/log-pygm2n -d -n local.mail.soc.read-only
-
-:0 bh:
-* ^From:.*(googlealerts-noreply@google.com|alerts@yahoo-inc.com|robot@radio.cz)
-| pygm2n -l $HOME/log-pygm2n -d -n local.mail.zpravy
-
---nextPart1312693.60ImoN5RI4--
-
-
diff --git a/examples/drhyde-news2mail-and-mail2news/LICENCE b/examples/drhyde-news2mail-and-mail2news/LICENCE
deleted file mode 100644
index 46961de..0000000
--- a/examples/drhyde-news2mail-and-mail2news/LICENCE
+++ /dev/null
@@ -1,3 +0,0 @@
-The news2mail and mail2news scripts are licenced under the same terms as perl itself.
-
-All other files in this directory may be used and distributed by anyone but may not be modified.
diff --git a/examples/drhyde-news2mail-and-mail2news/mail2news b/examples/drhyde-news2mail-and-mail2news/mail2news
deleted file mode 100644
index 1f026a0..0000000
--- a/examples/drhyde-news2mail-and-mail2news/mail2news
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/usr/local/bin/perl
-
-use warnings;
-use strict;
-
-use Data::Dumper;
-use Net::NNTP;
-use News::Article;
-
-use constant DEBUG => 0;
-
-select(STDERR); $| = 1; select(STDOUT);
-
-die("mail2news hasn't been configured.\n") unless(-r '/etc/mail2newsrc');
-
-my $subs = { do '/etc/mail2newsrc' };
-
-my $group = shift;
-die("mail2news must be told what group to post to\n") unless($group);
-
-my $article = News::Article->new();
-$article->read(\*STDIN);
-$article->set_headers(Newsgroups => $group);
-$article->drop_headers(qw(date to received));
-$article->add_date();
-
-my $posted_ok = 0;
-foreach my $server (grep { $subs->{$_}->{$group} } keys %{$subs}) {
- my($auth, $host) = split('@', $server);
- ($auth, $host) = (':', $auth) if(!$host);
- my($user, $pass) = split(':', $auth);
- ($host, my $port) = split(':', $host);
- $port ||= 119;
-
- my $client = Net::NNTP->new($host, Port => $port);
- $client->authinfo($user => $pass) if($user);
-
- unless($client->postok()) {
- print STDERR "mail2news configured to post to $group via\n".
- "$server, but it didn't say we can post. Bother and damnation!\n";
- next;
- }
-
- eval { $article->post($client); };
- die("Error in posting to $server: $@\n") if($@);
- $posted_ok++;
-}
-
-if(!$posted_ok) {
- die "mail2news couldn't post to $group on any configured server.\n\n".
- "Your message read:\n\n".
- join("\n\n",
- join("\n", $article->headers()),
- join("\n", $article->body())
- )."\n\n".
- "And the environment was:\n\n".
- join("\n", map { join(":\t", $_, $ENV{$_}) } sort keys %ENV);
-}
diff --git a/examples/drhyde-news2mail-and-mail2news/news2mail b/examples/drhyde-news2mail-and-mail2news/news2mail
deleted file mode 100644
index e91bea6..0000000
--- a/examples/drhyde-news2mail-and-mail2news/news2mail
+++ /dev/null
@@ -1,177 +0,0 @@
-#!/usr/local/bin/perl
-
-use strict;
-use warnings;
-
-use Net::NNTP::Client;
-use GDBM_File;
-use Email::Send;
-use Data::Dumper;
-
-use constant DEBUG => 0;
-
-select(STDERR); $| = 1; select(STDOUT);
-
-my $confdir = "$ENV{HOME}/.news2mail";
-unless(-d $confdir && -f $confdir.'/config.pl') {
- mkdir $confdir || die("Couldn't create $confdir\n");
- open(FILE, ">$confdir/config.pl") || die("Couldn't create $confdir/config.pl\n");
- print FILE join("\n",
- "smtphost => 'localhost',",
- "address => 'myaddress\@example.com',",
- "'user:pass\@news.example.com:119' => {",
- " 'misc.test' => { post => 1 },",
- " 'alt.config' => { post => 1 },",
- "},",
- "'privateserver.localdomain' => {",
- " 'my.secret.newsgroup' => { post => 1 },",
- "}"
- );
- close(FILE);
-
- print "You need to configure me! Take a look in $confdir\n";
- exit;
-}
-
-tie my %seen, 'GDBM_File', "$confdir/seen.dbm", GDBM_WRCREAT, 0640;
-
-my $subscriptions = { do $confdir.'/config.pl' };
-
-my $smtphost = $subscriptions->{smtphost};
-my $address = $subscriptions->{address};
-delete $subscriptions->{smtphost};
-delete $subscriptions->{address};
-
-SERVERS: foreach my $server (keys %{$subscriptions}) {
- unless(-d "$confdir/$server") {
- mkdir("$confdir/$server") || die("Can't create $confdir/$server\n");
- }
- my($auth, $host) = split('@', $server);
- ($auth, $host) = (':', $auth) if(!$host);
- my($user, $pass) = split(':', $auth);
- ($host, my $port) = split(':', $host);
- $port ||= 119;
- print "Connecting to $host:$port with credentials [$user,$pass]\n" if(DEBUG);
- my $client = Net::NNTP::Client->new(
- "$host:$port",
- server => $host,
- port => $port,
- (($user) ? (user => $user, pass => $pass) : ()),
- debug => 0, # set to 1 by default - hate!
- );
- # refresh groups list if this is a new server or the list is more
- # than 7 days old
- if(!-f "$confdir/groups.$server" || -M "$confdir/groups.$server" > 7) {
- my $list = eval { $client->list() };
- if($@) {
- print STDERR "$@\n";
- next SERVERS;
- }
- open(FILE, ">$confdir/groups.$server") || die("Can't write $confdir/groups.$server\n");
- print FILE "$_\n" foreach(sort keys %{$list});
- close(FILE);
- print "Updated groups list, see $confdir/groups.$server\n";
- }
-
- GROUPS: foreach my $group (keys %{$subscriptions->{$server}}) {
- my($articles, $firstarticle) = eval { $client->group($group); };
- if($@) {
- print STDERR "$@\n";
- next SERVERS;
- }
- if(!-e "$confdir/$server/$group.lastretrieved") {
- # new subscription, so set lastretrieved to current
- open(FOO, ">$confdir/$server/$group.lastretrieved") ||
- die("Can't write $confdir/$server/$group.lastretrieved\n");
- print FOO $firstarticle + $articles - 1;
- close(FOO);
- print "New subscription: $server/$group\n first: $firstarticle\n articles: $articles\n" if(DEBUG);
- next GROUPS;
- }
- open(FOO, "$confdir/$server/$group.lastretrieved") ||
- die("Can't read $confdir/$server/$group.lastretrieved\n");
- chomp(my $lastretrieved = <FOO>);
- $client->nntpstat($lastretrieved);
- close(FOO);
- FETCHNEWS: while(my $msgid = $client->next()) {
- if(exists($seen{$msgid})) { # already got this article
- print "$group: $msgid already seen\n" if(DEBUG);
- $seen{$msgid} = time(); # update timestamp
- $lastretrieved++;
- open(FOO, ">$confdir/$server/$group.lastretrieved") ||
- die("Can't write $confdir/$server/$group.lastretrieved\n");
- print FOO $lastretrieved;
- close(FOO);
- next FETCHNEWS;
- }
- my $article = [map { chomp; $_; } @{$client->head($msgid)}];
- # filter based on headers here
- push @{$article}, '', map { chomp; $_; } @{$client->body($msgid)};
-
- print "$group: fetched $msgid\n" if(DEBUG);
-
- my @newsheaders;
- my @headers = (
- "To: $address",
- "Reply-To: ".
- ($subscriptions->{$server}->{$group}->{post} || 'dave.null'),
- "X-Newsgroup: $group"
- );
- while((my $line = shift(@{$article})) ne '') {
- if($line =~ /^\s+/) { $newsheaders[-1] .= $line; }
- else { push @newsheaders, $line; }
- }
- foreach my $line (@newsheaders) {
- if($line =~ /^(Message-Id|Date|Subject|From)/i) {
- # headers common to mail and news
- push @headers, $line;
- } elsif($line =~ /^Path: (.*)$/i) {
- push @headers, "Received: from $host with NNTP path $1";
- } elsif($line =~ /^References: (.*)$/i) {
- my @refs = split(/\s+/, $1);
- push @headers, $line, "In-Reply-To: $refs[-1]";
- } else {
- push @headers, "X-NNTP-Header-$line";
- }
- }
-
- my $body = $article;
-
- my $sender = Email::Send->new({mail => 'SMTP'});
- $sender->mailer_args([Host => $smtphost]);
- $sender->send(
- join("\n\n",
- join("\n", sort { $a cmp $b } @headers),
- join("\n", @{$body})
- )
- );
-
- $seen{$msgid} = time(); # so we never fetch this one again
- $lastretrieved++;
- open(FOO, ">$confdir/$server/$group.lastretrieved") ||
- die("Can't write $confdir/$server/$group.lastretrieved\n");
- print FOO $lastretrieved;
- close(FOO);
- }
- }
-}
-
-# while(my($msgid, $time) = each(%seen)) {
-# if(time() - $time > 2 * 86400) {
-# delete $seen{$msgid};
-# }
-# }
-
-# now optimise seendb
-# delete anything from 'seen' more than a year old. This is partially for
-# dropping cross-posts, (we use lastretrieved to avoid going back in time)
-# but also for when a server shits its pants
-my %newseen;
-$newseen{$_} = $seen{$_} foreach(
- grep { time() - $seen{$_} < 365 * 86400 } keys %seen
-);
-untie %seen;
-unlink "$confdir/seen.dbm";
-tie %seen, 'GDBM_File', "$confdir/seen.dbm", GDBM_WRCREAT, 0640;
-$seen{$_} = $newseen{$_} foreach(keys %newseen);
-untie %seen;
diff --git a/examples/drhyde-news2mail-and-mail2news/yapc-europe-2007-paper.pdf b/examples/drhyde-news2mail-and-mail2news/yapc-europe-2007-paper.pdf
deleted file mode 100644
index f3bee99..0000000
--- a/examples/drhyde-news2mail-and-mail2news/yapc-europe-2007-paper.pdf
+++ /dev/null
Binary files differ
diff --git a/examples/drhyde-news2mail-and-mail2news/yapc-europe-2007-paper.pod b/examples/drhyde-news2mail-and-mail2news/yapc-europe-2007-paper.pod
deleted file mode 100644
index fb65679..0000000
--- a/examples/drhyde-news2mail-and-mail2news/yapc-europe-2007-paper.pod
+++ /dev/null
@@ -1,177 +0,0 @@
-=head1 news2mail and mail2news - a Usenet/Email gateway
-
-=head2 Abstract
-
-Usenet has a bad reputation for being full of spam and idiots, but this is no longer really justified. Most of the spam is dealt with by automatic cancelbots before normal people ever get to see it, and the current crop of idiots don't know about Usenet anyway because as far as they're concerned, if it isn't Teh Web then it doesn't exist. So the only thing that sucks about Usenet these days is the dreadful client software.
-
-With a good client, Usenet becomes a great place to discuss any topic and make friends. That's why I wrote news2mail and its companion mail2news. They are perl scripts which speak sufficient subsets of NNTP and SMTP to make Usenet available in your mail client and enable posting to Usenet as if it were a mailing list.
-
-=head2 Where to get the software
-
-L<http://drhyde.cvs.sourceforge.net/drhyde/perlscripts/news2mail-and-mail2news/>
-
-=head2 Other implementations
-
-There are *lots* of other implementations of this idea. However, all the ones I looked at when I needed it had one big flaw - they assumed that you were running your own local news server and so could read and write messages directly from and to the news spool. Worse, many of them assumed that you were running INN. I not only don't run my own news server, but if I did, INN would be a serious case of overkill for my own personal use.
-
-So I did what any hacker would do, and wrote my own version.
-
-=head2 Message formats
-
-These two scripts are, effectively, a bit of glue sticking two different protocols together. Both SMTP and NNTP are concerned with transferring text messages from one place to another, and the message formats are nigh-on identical. Here's a typical email, which I received from a mailing list:
-
- Return-path: <cctech-bounces@classiccmp.org>
- Envelope-to: david@cantrell.org.uk
- Delivery-date: Fri, 17 Aug 2007 14:15:32 +0100
- Received: from dewey.classiccmp.org ([209.145.140.57])
- by bytemark.barnyard.co.uk with esmtp (Exim 3.35 #1)
- id 1IM1fo-0006tf-00
- for david@cantrell.org.uk; Fri, 17 Aug 2007 14:15:32 +0100
- [ several other Received headers cut out ]
- Date: Fri, 17 Aug 2007 11:23:04 +0100
- From: David Cantrell <david@cantrell.org.uk>
- To: "General Discussion: On-Topic Posts Only" <cctech@classiccmp.org>
- Message-ID: <20070817102303.GA31679@bytemark.barnyard.co.uk>
- X-Sepdate: Fri Sep 5099 10:27:25 BST 1993
- References: <200708140955.50011.mark@wickensonline.co.uk>
- Mime-Version: 1.0
- Content-Type: text/plain; charset=us-ascii
- Content-Disposition: inline
- In-Reply-To: <200708140955.50011.mark@wickensonline.co.uk>
- User-Agent: Mutt/1.5.9i
- Subject: Re: UK retro show evening
- Precedence: list
- Reply-To: "General Discussion: On-Topic Posts Only" <cctech@classiccmp.org>
- Sender: cctech-bounces@classiccmp.org
-
- On Tue, Aug 14, 2007 at 09:55:49AM +0100, Mark Wickens wrote:
-
- > I'm thinking 'start small' here. Maybe an event with 30 or so
- > participants? Primarily to 'chew-the-cud'?
-
- How about "come to the pub and natter".
- I propose the evening of Thursday the 6th of September, at whatever
- venue the London Perl Mongers choose for their social ...
-
-and here's a typical Usenet posting:
-
- Path: g2news2.google.com!postnews.google.com!...
- From: roberthar...@my-deja.com
- Newsgroups: alt.2eggs.sausage.beans.tomatoes.2toast.largetea.cheerslove
- Subject: Re: black Pudding
- Date: Wed, 22 Aug 2007 17:15:13 -0700
- Organization: http://groups.google.com
- Lines: 20
- Message-ID: <1187828113.562214.100540@m37g2000prh.googlegroups.com>
- References: <46CC4CFA.2A57EE2B@yahoo.com>
- NNTP-Posting-Host: 195.137.63.170
- Mime-Version: 1.0
- Content-Type: text/plain; charset="us-ascii"
- X-Complaints-To: groups-abuse@google.com
- NNTP-Posting-Date: Thu, 23 Aug 2007 00:15:14 +0000 (UTC)
- In-Reply-To: <46CC4CFA.2A57EE2B@yahoo.com>
- User-Agent: G2/1.0
- X-HTTP-UserAgent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.6) Gecko/20061201 Firefox/2.0.0.6 (Ubuntu-feisty),gzip(gfe),gzip(gfe)
-
- On 22 Aug, 15:49, Reverend Hoovie <reverendhoo...@yahoo.com> wrote:
-
- > Did a google on black pudding and must admit it sounds quite tasty.
-
- I love black pudding, except as served in hotel help-yersel buffets.
- ...
-
-Both are basically the same format with just a few very minor changes. Both have From, Date, Subject and Message-ID headers, for example. The email's To header is replaced with usenet's Newsgroups header, and email uses multiple Received headers to show how a message got to you where Usenet instead uses a single Path header.
-
-This makes the task of translating between the two systems very easy.
-
-=head2 From Usenet to email
-
-The news2mail script is designed to be run periodically from a cron job, and to store all its configuration and state information under your home directory. It uses Net::NNTP::Client to talk to any number of news servers, retrieving different newsgroups from each one - this means that you can use it to retrieve public postings from public servers, as well as private groups run by your university or company.
-
-For each message that it retrieves it does a few simple edits to the headers before using Email::Send to forward it to whatever address you choose using SMTP. Those edits are:
-
-=over
-
-=item Insert a To header
-
-=item Insert a Reply-To header
-
-This will be either the address that you have configured for the mail2news script to use for posting, or if you've not configured posting to the group that this message came from it will be 'dave.null'.
-
-=item Insert an X-Newsgroup header
-
-So that you can see where it came from, and more importantly so that procmail can see it as well and filter your mail into folders.
-
-=item Path is translated to Received
-
-The Path header is turned into "Received: from [hostname] with NNTP path ..." which is not strictly legal, but it works. Google do something similarly illegal with Received headers emited by gmail, so I reckon I'm in good company.
-
-=item References header is turned into In-Reply-To
-
-Although you do see emails with References headers, In-Reply-To seems to be more widely implemented.
-
-=back
-
-Date, Message-Id, Subject and From are passed through unchanged, and anything else is turned into an X-NNTP-Header-$foo header.
-
-The message is then passed to Email::Send, and ends up in your mailbox. It then updates a cache of message-ids that it has seen, in case a server burps and re-sends stuff (which happens occasionally, and also eliminates cross-posts) and goes on to the next message.
-
-Finally, anything that's been in the cache for more than a year is deleted.
-
-=head2 From Email to Usenet
-
-Going in the opposite direction, from email to Usenet, is just as simple. The mail2news script is meant to be invoked by the mail server, and is handed an email on STDIN, with the newsgroup name on the command line. Again, a few headers are edited - we add a Newsgroups header so that the news server will know which group we're posting to, drop the Date, To and Received headers, and then insert a Date header again. The shenanigans with dropping and then adding a date header are to work around a problem with some mail clients setting incorrectly formatted dates, which then confuse the news server.
-
-It reads a configuration file which tells it which servers to use for posting to which groups, and logs in to each appropriate server in turn, using a username and password if necessary. Provided that the server confirms that yes, you can post to it, the article is sent on its way.
-
-=head2 Configuration
-
-=head3 news2mail
-
-news2mail looks in $HOME/.news2mail for several items. The most important of those is config.pl, which looks like this:
-
- 'username:password@server.example.com:portnumber' => {
- 'comp.lang.perl.misc' =>
- { post => 'clpm-post@example.com' },
- 'alt.2eggs.sausage.beans.tomatoes.2toast.largetea.cheerslove' =>
- { post => '2eggs-post@example.com' }
- },
- 'news.somewhereelse.wherever' => {
- 'local.fart-jokes' => { post => 0 }
- }
-
-which is a simple hash where keys are servers to query. Their associated values are hashes whose keys are group names. *Their* values are again hashes, which currently have a single key 'post' whose value is either 0, meaning that you can't post, or the email address for sending articles to the group.
-
-The other items in that directory will be created by news2mail, and are the cache of previously seen message-ids, and the number of the last message we saw in each group, which makes startup next time quicker. If that number doesn't exist (ie we've just subscribed to a group) then it is set to the last message in the group, to avoid downloading *everything* the first time. You really don't want to do that, as some servers store several hundred days worth of messages and your mail server wouldn't like that.
-
-=head3 mail2news
-
-Configuring mail2news is a bit more complicated. First, you'll need to create a /etc/mail2newsrc file like this:
-
- 'username:password@server.example.com:portnumber' => {
- 'comp.lang.perl.misc' => 1,
- 'alt.2eggs.sausage.beans.tomatoes.2toast.largetea.cheerslove' => 1
- }
-
-which lists all the servers that we can post to, and for each of them the groups that we can post to. Note that this applies to all mail2news users on this system.
-
-Then you will need to configure your mail server to accept mail for the appropriate addresses, and tell it what to do with 'em. The easiest way is to drop some entries in the /etc/aliases file:
-
- clpm-post: "|/usr/local/bin/mail2news comp.lang.perl.misc"
- 2eggs-post: "|/usr/local/bin/mail2news alt.2eggs.sausage.beans.tomatoes.2toast.largetea.cheerslove"
-
-This is too complicated and has a couple of nasty little security holes on a multi-user system, but I wrote the software for my own use where they're not an issue.
-
-=head2 How to contribute
-
-I have created a mailing list to which I invite anyone interested in using or hacking on the scripts to subscribe. It is E<lt>drhyde-news2mail@lists.sourceforge.netE<gt> and is managed using mailman. You can subscribe at L<https://lists.sourceforge.net/lists/listinfo/dhyde-news2mail>.
-
-=head1 AUTHOR, COPYRIGHT and LICENCE
-
-Copyright 2007 David Cantrell E<lt>david@cantrell.org.ukE<gt>
-
-The news2mail and mail2news scripts are licenced under the same terms as perl itself.
-
-This documentation may be used and distributed by anyone but may not be modified without permission from the author.
-
-=cut
diff --git a/mail2news.py b/mail2news.py
index 38ae507..f15ca4e 100644
--- a/mail2news.py
+++ b/mail2news.py
@@ -3,7 +3,7 @@
Author: Cosimo Alfarano
Date: September 16 2000
-mail2news.py - (C) 2000 by Cosimo Alfarano <Alfarano@Students.CS.UniBo.It>
+mail2news.py - Copyright 2000 by Cosimo Alfarano <Alfarano@Students.CS.UniBo.It>
You can use this software under the terms of the GPL. If we meet some day,
and you think this stuff is worth it, you can buy me a beer in return.
@@ -14,70 +14,163 @@ Gets news email and sends it via SMTP.
class mail2news is hopefully conform to rfc850.
"""
-from StringIO import StringIO
-from collections import OrderedDict
-import email
-import logging
-import nntplib
-import os
-from re import findall
-from socket import gethostbyaddr, gethostname
+
import sys
+from os import unlink, getpid
+from socket import gethostbyaddr, gethostname
+import string
+from re import findall
+import time
+import nntplib
+import pyginfo
+import tempfile
+class mail2news:
+ """news to mail gateway class"""
-#logging.basicConfig(level=logging.DEBUG)
-# This is the single source of Truth
-# Yes, it is awkward to have it assymetrically here
-# and not in news2mail as well.
-VERSION = '0.9.12'
-DESC = "The Python Gateway Script: news2mail mail2news gateway"
+
+ reader = None # mode reader
+# newsgroups = None # Newsgroups: local.test,local.moderated...
+# approved = None # Approved: kame@aragorn.lorien.org
+ newsserver = 'localhost' # no comment :)
+ port = 119
+ user = None
+ password = None
+ hostname = gethostbyaddr(gethostname())[0]
-class mail2news(object):
- """news to mail gateway class"""
+ heads_dict, smtpheads, nntpheads = {}, {}, {}
+ email, headers, body = [], [], []
- def __init__(self, options):
- # newsgroups = None # Newsgroups: local.test,local.moderated...
- # approved = None # Approved: kame@aragorn.lorien.org
- if 'NNTPHOST' in os.environ:
- self.newsserver = os.environ['NNTPHOST']
- else:
- self.newsserver = 'localhost'
- self.port = 119
- self.user = None
- self.password = None
- self.verbose = options.verbose
- logging.debug('self.verbose = %s', self.verbose)
+ def readfile(self):
- self.hostname = gethostbyaddr(gethostname())[0]
+ for line in sys.stdin.readlines():
+ self.email.append(line)
+
+ if(len(self.email) == 1 and self.email[0][0] == '/'):
+ file = self.email[0][:-1]
+ del self.email[0]
+ for line in open(file,'r').readlines():
+ self.email.append(line)
+
+ return 1
- self.heads_dict, self.smtpheads, self.nntpheads = {}, {}, {}
- self.message = self.__readfile(options)
- self.message['X-Gateway'] = 'pyg {0} {1}'.format(VERSION, DESC)
+ def parseemail(self):
+ """get news email from file or stdin and separate heads from body
- def __add_header(self, header, value, msg=None):
- if msg is None:
- msg = self.message
- if value:
- msg[header] = value.strip()
+ REMEBER: headers value has '\n' as last char.
+ Use string[:-1] to ignore newline.
+ """
- def __readfile(self, opt):
- message = email.message_from_file(sys.stdin)
+ try:
+ body = 0 # are we in body or in headers?
+
+ for line in self.email:
+ if not body and len(line) == 1:
+ body = 1 # starts email body section
+
+ if not body:
+ try:
+ # if it is a multi-line header like Received:
+ if not line[0] in [' ','\t']:
+ try:
+ head, value = string.split(line, ' ', 1)
+ except string.index_error:
+ value = ''
+ self.smtpheads[head] = value
+ else:
+ self.smtpheads[head] = '%s%s' % \
+ (self.smtpheads[head], line)
+ except (string.index_error), message:
+ print 'line: %s' % line
+ print '(probably missing couple "Header: value" in %s)' % line
+ sys.exit(1)
+
+ elif len(line) > 0 and body:
+ self.body.append(line)
+
+ except (string.index_error), message:
+ print message
+ sys.exit(1)
+
+ return self.smtpheads, self.body
+
+ def puthead(self, dict, list, key):
+ """private, transform dict entries in list entries
+ Appends key of dict to list, deleting it from dict.
+ """
- if (len(message) == 0) \
- and message.get_payload().startswith('/'):
- msg_file_name = message.get_payload().strip()
- del message
- with open(msg_file_name, 'r') as msg_file:
- message = email.message_from_file(msg_file)
+ if dict.has_key(key):
+ list.append(key + ' ' + dict.get(key))
+ del dict[key]
+ else:
+ return 0
+ return 1
- # introduce nntpheads
- self.__add_header('Newsgroups', opt.newsgroup, message)
- self.__add_header('Approved', opt.approver, message)
+ def sortheads(self):
+ """make list sorted by heads: From: To: Subject: first, others, X-*, X-Resent-* last"""
+
+ set = ('Newsgroups:','From:','To:','X-To:','Cc:','Subject:','Date:','Approved:','References:','Message-Id:') # put at top
+
+ for k in set:
+ self.puthead(self.heads_dict,self.headers,k)
+
+ for k in self.heads_dict.keys():
+ if k[:2] != 'X-' and k[:9] != 'X-Resent-' and k not in set:
+ self.puthead(self.heads_dict,self.headers,k)
+
+ for k in self.heads_dict.keys():
+ if k[:2] == 'X-':
+ self.puthead(self.heads_dict,self.headers,k)
+
+ for k in self.heads_dict.keys():
+ if k[:9] == 'X-Resent-':
+ self.puthead(self.heads_dict,self.headers,k)
+
+ return self.headers
+
+
+ def mergeheads(self):
+ """make a unique headers dictionary from NNTP and SMTP
+ single headers dictionaries."""
+
+ self.heads_dict = {}
- return message
+ try:
+ for header in self.smtpheads.keys(): # fill it w/ smtp old heads
+ self.heads_dict[header] = self.smtpheads[header]
+
+ for header in self.nntpheads.keys(): # and replace them w/ nntp new heads
+ self.heads_dict[header] = self.nntpheads[header]
+
+ except KeyError, message:
+ print message
+
+ return self.heads_dict
+
+ def addheads(self):
+ """add new header like X-Gateway:
+ """
+
+ info = pyginfo.pygsinfo()
+
+ try:
+ self.heads_dict['X-Gateway:'] = info.PROGNAME + ' ' + \
+ info.PROGDESC + ' - Mail to News\n'
+
+# it is nntpheads stuff
+# if(self.newsgroups):
+# self.heads_dict['Newsgroups:'] = self.newsgroups
+
+# if(self.approved):
+# self.heads_dict['Approved:'] = self.approved
+
+ except KeyError, message:
+ print message
+
+ return self.heads_dict
def renameheads(self):
"""rename headers such as Resent-*: to X-Resent-*:
@@ -87,99 +180,140 @@ class mail2news(object):
"""
try:
- for key in self.message.keys():
- if key.startswith('Resent-'):
- if ('X-' + key) in self.message:
- self.message['X-Original-' + key] = \
- self.message['X-' + key]
- self.message['X-' + key] = self.message[key]
- del self.message[key]
-
+### test
+# if(post):
+# if(self.heads_dict.has_key(post)):
+# self.heads_dict['X-Original-' + post] = self.heads_dict[post]
+#
+# self.heads_dict[post] = self.heads_dict[pre]
+# del(self.heads_dict[pre])
+#
+# else:
+# if(pre[0:2] == 'X-' and self.heads_dict.has_key(pre)):
+# self.heads_dict['X-Original-' + pre] = self.heads_dict[pre]
+# elif(not pre[0:2] == 'X-' and self.heads_dict.has_key('X-' + pre)):
+# self.heads_dict['X-' + pre] = self.heads_dict[pre]
+# del(self.heads_dict[pre])
+### end test
+
+ for key in self.heads_dict.keys():
+ if(key[:7] in ['Resent-']):
+ if(self.heads_dict.has_key('X-' + key)):
+ self.heads_dict[ 'X-Original-' + key ] = self.heads_dict['X-' + key]
+ self.heads_dict[ 'X-' + key ] = self.heads_dict[key]
+ del self.heads_dict[key]
+
+
# In rfc822 References: is considered, but many MUA doen't put it.
- if ('References' not in self.message) and \
- ('In-Reply-To' in self.message):
- print self.message['In-Reply-To']
+ if(not self.heads_dict.has_key('References:') and self.heads_dict.has_key('In-Reply-To:')):
+ print self.heads_dict['In-Reply-To:']
# some MUA uses msgid without '<' '>'
# ref = findall('([^\s<>\']+@[^\s<>;:\']+)', \
# but I prefer use RFC standards
- ref = findall('(<[^<>]+@[^<>]+>)',
- self.message['In-Reply-To'])
+ ref = findall('(<[^<>]+@[^<>]+>)', \
+ self.heads_dict['In-Reply-To:'])
# if found, keep first element that seems a Msg-ID.
if(ref and len(ref)):
- self.message['References'] = '%s\n' % ref[0]
+ self.heads_dict['References:'] = '%s\n' % ref[0]
+
+# if(self.heads_dict.has_key('To:')):
+# self.heads_dict['X-To:'] = self.heads_dict['To:']
+# del self.heads_dict['To:']
except KeyError, message:
print message
- def removeheads(self, heads=None):
+ return self.heads_dict
+
+
+ def removeheads(self, heads = None):
"""remove headers like Xref: Path: Lines:
"""
try:
# removing some others useless headers .... (From is not From:)
- rmheads = ['Received', 'From ', 'NNTP-Posting-Host',
- 'X-Trace', 'X-Compliants-To', 'NNTP-Posting-Date']
- if heads:
+ rmheads = ['Received:','From','NNTP-Posting-Host:','X-Trace']
+ if(heads):
rmheads.append(heads)
-
+
for head in rmheads:
- if head in self.message:
- del self.message[head]
-
- if 'Message-Id' in self.message:
- msgid = self.message['Message-Id']
- del self.message['Message-Id']
- self.message['Message-Id'] = msgid
- else:
- msgid = '<pyg.%d@tuchailepuppapera.org>\n' % (os.getpid())
- self.message['Message-Id'] = msgid
+ if self.heads_dict.has_key(head):
+ del self.heads_dict[head]
+
+# if self.heads_dict.has_key('From'): # neither 'From ' nor 'From:'
+# del self.heads_dict['From']
+
+# if self.heads_dict.has_key('NNTP-Posting-Host:'): # neither 'From ' nor 'From:'
+# del self.heads_dict['']
+
+
+# if self.heads_dict.has_key('Lines:'):
+# del self.heads_dict['Lines:']
+
+ # it is usually set by INN, if ng is moderated...
+# if self.heads_dict.has_key('Sender:'):
+# del self.heads_dict['Sender:']
+
+
+ if self.heads_dict.has_key('Message-id:'):
+ self.heads_dict['Message-Id:'] = self.heads_dict['Message-id:']
+ del(self.heads_dict['Message-id:'])
+
+ if self.heads_dict.has_key('Message-ID:'):
+ self.heads_dict['Message-Id:'] = self.heads_dict['Message-ID:']
+ del(self.heads_dict['Message-ID:'])
+
+ # If message-id is not present, I generate it
+ if not self.heads_dict.has_key('Message-Id:'):
+ msgid = '<pyg.%d@tuchailepuppapera.org>\n' % (getpid())
+ self.heads_dict['Message-Id:'] = msgid
except KeyError, message:
print message
- def sortheads(self):
- """make list sorted by heads: From: To: Subject: first,
- others, X-*, X-Resent-* last"""
-
- heads_dict = OrderedDict(self.message)
- for hdr in self.message.keys():
- del self.message[hdr]
-
- # put at top
- head_set = ('Newsgroups', 'From', 'To', 'X-To', 'Cc', 'Subject',
- 'Date', 'Approved', 'References', 'Message-Id')
-
- logging.debug('heads_dict = %s', heads_dict)
- for k in head_set:
- if k in heads_dict:
- self.__add_header(k, heads_dict[k])
-
- for k in heads_dict:
- if not k.startswith('X-') and not k.startswith('X-Resent-') \
- and k not in head_set:
- self.__add_header(k, heads_dict[k])
-
- for k in heads_dict:
- if k.startswith('X-'):
- self.__add_header(k, heads_dict[k])
-
- for k in heads_dict:
- if k.startswith('X-Resent-'):
- self.__add_header(k, heads_dict[k])
+ return self.heads_dict
def sendemail(self):
- "Talk to NNTP server and try to send email."
- # readermode must be True, otherwise we don't have POST command.
- server = nntplib.NNTP(self.newsserver, self.port, self.user,
- self.password, readermode=True)
-
- logging.debug('self.verbose = %s', self.verbose)
- if self.verbose:
- server.set_debuglevel(2)
-
- server.post(StringIO(self.message.as_string()))
-
- server.quit()
+ """Talk to NNTP server and try to send email."""
+ try:
+ msglist = []
+
+ n = nntplib.NNTP(self.newsserver, self.port, self.user, self.password)
+
+ if(self.reader):
+ n.putline('mode reader')
+ resp = n.getline()
+ print resp
+
+ resp = n.shortcmd('POST')
+
+ # sett RFC977 2.4.2
+ if resp[0] <> '3':
+ raise n.error_reply, str(resp)
+
+ for line in self.headers:
+ if not line:
+ break
+ if line[-1] == '\n':
+ line = line[:-1]
+ if line[:1] == '.':
+ line = '.' + line
+ n.putline(line)
+
+ for line in self.body:
+ if not line:
+ break
+ if line[-1] == '\n':
+ line = line[:-1]
+ if line[:1] == '.':
+ line = '.' + line
+ n.putline(line)
+
+ n.putline('.')
+ n.quit()
+ return None
+ except (nntplib.error_reply, nntplib.error_temp, nntplib.error_perm, nntplib.error_proto, nntplib.error_data), message:
+ return 'NNTP: ' + str(message)
diff --git a/mail2news.py.withtab b/mail2news.py.withtab
new file mode 100644
index 0000000..8b80e0c
--- /dev/null
+++ b/mail2news.py.withtab
@@ -0,0 +1,319 @@
+"""Mail to news gateway script. Copyright 2000 Cosimo Alfarano
+
+Author: Cosimo Alfarano
+Date: September 16 2000
+
+mail2news.py - Copyright 2000 by Cosimo Alfarano <Alfarano@Students.CS.UniBo.It>
+You can use this software under the terms of the GPL. If we meet some day,
+and you think this stuff is worth it, you can buy me a beer in return.
+
+Thanks to md for this useful formula. Beer is beer.
+
+Gets news email and sends it via SMTP.
+
+class mail2news is hopefully conform to rfc850.
+
+"""
+
+import sys
+from os import unlink, getpid
+from socket import gethostbyaddr, gethostname
+import string
+from re import findall
+import time
+import nntplib
+import pyginfo
+import tempfile
+
+class mail2news:
+ """news to mail gateway class"""
+
+
+ reader = None # mode reader
+# newsgroups = None # Newsgroups: local.test,local.moderated...
+# approved = None # Approved: kame@aragorn.lorien.org
+ newsserver = 'localhost' # no comment :)
+ port = 119
+ user = None
+ password = None
+
+ hostname = gethostbyaddr(gethostname())[0]
+
+ heads_dict, smtpheads, nntpheads = {}, {}, {}
+ email, headers, body = [], [], []
+
+
+ def readfile(self):
+
+ for line in sys.stdin.readlines():
+ self.email.append(line)
+
+ if(len(self.email) == 1 and self.email[0][0] == '/'):
+ file = self.email[0][:-1]
+ del self.email[0]
+ for line in open(file,'r').readlines():
+ self.email.append(line)
+
+ return 1
+
+
+ def parseemail(self):
+ """get news email from file or stdin and separate heads from body
+
+ REMEBER: headers value has '\n' as last char.
+ Use string[:-1] to ignore newline.
+ """
+
+ try:
+ body = 0 # are we in body or in headers?
+
+ for line in self.email:
+ if not body and len(line) == 1:
+ body = 1 # starts email body section
+
+ if not body:
+ try:
+ # if it is a multi-line header like Received:
+ if not line[0] in [' ','\t']:
+ try:
+ head, value = string.split(line, ' ', 1)
+ except string.index_error:
+ value = ''
+ self.smtpheads[head] = value
+ else:
+ self.smtpheads[head] = '%s%s' % \
+ (self.smtpheads[head], line)
+ except (string.index_error), message:
+ print 'line: %s' % line
+ print '(probably missing couple "Header: value" in %s)' % line
+ sys.exit(1)
+
+ elif len(line) > 0 and body:
+ self.body.append(line)
+
+ except (string.index_error), message:
+ print message
+ sys.exit(1)
+
+ return self.smtpheads, self.body
+
+ def puthead(self, dict, list, key):
+ """private, transform dict entries in list entries
+ Appends key of dict to list, deleting it from dict.
+ """
+
+ if dict.has_key(key):
+ list.append(key + ' ' + dict.get(key))
+ del dict[key]
+ else:
+ return 0
+ return 1
+
+ def sortheads(self):
+ """make list sorted by heads: From: To: Subject: first, others, X-*, X-Resent-* last"""
+
+ set = ('Newsgroups:','From:','To:','X-To:','Cc:','Subject:','Date:','Approved:','References:','Message-Id:') # put at top
+
+ for k in set:
+ self.puthead(self.heads_dict,self.headers,k)
+
+ for k in self.heads_dict.keys():
+ if k[:2] != 'X-' and k[:9] != 'X-Resent-' and k not in set:
+ self.puthead(self.heads_dict,self.headers,k)
+
+ for k in self.heads_dict.keys():
+ if k[:2] == 'X-':
+ self.puthead(self.heads_dict,self.headers,k)
+
+ for k in self.heads_dict.keys():
+ if k[:9] == 'X-Resent-':
+ self.puthead(self.heads_dict,self.headers,k)
+
+ return self.headers
+
+
+ def mergeheads(self):
+ """make a unique headers dictionary from NNTP and SMTP
+ single headers dictionaries."""
+
+ self.heads_dict = {}
+
+ try:
+ for header in self.smtpheads.keys(): # fill it w/ smtp old heads
+ self.heads_dict[header] = self.smtpheads[header]
+
+ for header in self.nntpheads.keys(): # and replace them w/ nntp new heads
+ self.heads_dict[header] = self.nntpheads[header]
+
+ except KeyError, message:
+ print message
+
+ return self.heads_dict
+
+ def addheads(self):
+ """add new header like X-Gateway:
+ """
+
+ info = pyginfo.pygsinfo()
+
+ try:
+ self.heads_dict['X-Gateway:'] = info.PROGNAME + ' ' + \
+ info.PROGDESC + ' - Mail to News\n'
+
+# it is nntpheads stuff
+# if(self.newsgroups):
+# self.heads_dict['Newsgroups:'] = self.newsgroups
+
+# if(self.approved):
+# self.heads_dict['Approved:'] = self.approved
+
+ except KeyError, message:
+ print message
+
+ return self.heads_dict
+
+ def renameheads(self):
+ """rename headers such as Resent-*: to X-Resent-*:
+
+ headers renamed are useless or not rfc 977/850 copliant
+ handles References/In-Reply-To headers
+ """
+ try:
+
+### test
+# if(post):
+# if(self.heads_dict.has_key(post)):
+# self.heads_dict['X-Original-' + post] = self.heads_dict[post]
+#
+# self.heads_dict[post] = self.heads_dict[pre]
+# del(self.heads_dict[pre])
+#
+# else:
+# if(pre[0:2] == 'X-' and self.heads_dict.has_key(pre)):
+# self.heads_dict['X-Original-' + pre] = self.heads_dict[pre]
+# elif(not pre[0:2] == 'X-' and self.heads_dict.has_key('X-' + pre)):
+# self.heads_dict['X-' + pre] = self.heads_dict[pre]
+# del(self.heads_dict[pre])
+### end test
+
+ for key in self.heads_dict.keys():
+ if(key[:7] in ['Resent-']):
+ if(self.heads_dict.has_key('X-' + key)):
+ self.heads_dict[ 'X-Original-' + key ] = self.heads_dict['X-' + key]
+ self.heads_dict[ 'X-' + key ] = self.heads_dict[key]
+ del self.heads_dict[key]
+
+
+ # In rfc822 References: is considered, but many MUA doen't put it.
+ if(not self.heads_dict.has_key('References:') and self.heads_dict.has_key('In-Reply-To:')):
+ print self.heads_dict['In-Reply-To:']
+
+ # some MUA uses msgid without '<' '>'
+# ref = findall('([^\s<>\']+@[^\s<>;:\']+)', \
+ # but I prefer use RFC standards
+ ref = findall('(<[^<>]+@[^<>]+>)', \
+ self.heads_dict['In-Reply-To:'])
+
+ # if found, keep first element that seems a Msg-ID.
+ if(ref and len(ref)):
+ self.heads_dict['References:'] = '%s\n' % ref[0]
+
+# if(self.heads_dict.has_key('To:')):
+# self.heads_dict['X-To:'] = self.heads_dict['To:']
+# del self.heads_dict['To:']
+
+ except KeyError, message:
+ print message
+
+ return self.heads_dict
+
+
+ def removeheads(self, heads = None):
+ """remove headers like Xref: Path: Lines:
+ """
+
+ try:
+ # removing some others useless headers .... (From is not From:)
+
+ rmheads = ['Received:','From','NNTP-Posting-Host:','X-Trace']
+ if(heads):
+ rmheads.append(heads)
+
+ for head in rmheads:
+ if self.heads_dict.has_key(head):
+ del self.heads_dict[head]
+
+# if self.heads_dict.has_key('From'): # neither 'From ' nor 'From:'
+# del self.heads_dict['From']
+
+# if self.heads_dict.has_key('NNTP-Posting-Host:'): # neither 'From ' nor 'From:'
+# del self.heads_dict['']
+
+
+# if self.heads_dict.has_key('Lines:'):
+# del self.heads_dict['Lines:']
+
+ # it is usually set by INN, if ng is moderated...
+# if self.heads_dict.has_key('Sender:'):
+# del self.heads_dict['Sender:']
+
+
+ if self.heads_dict.has_key('Message-id:'):
+ self.heads_dict['Message-Id:'] = self.heads_dict['Message-id:']
+ del(self.heads_dict['Message-id:'])
+
+ if self.heads_dict.has_key('Message-ID:'):
+ self.heads_dict['Message-Id:'] = self.heads_dict['Message-ID:']
+ del(self.heads_dict['Message-ID:'])
+
+ # If message-id is not present, I generate it
+ if not self.heads_dict.has_key('Message-Id:'):
+ msgid = '<pyg.%d@tuchailepuppapera.org>\n' % (getpid())
+ self.heads_dict['Message-Id:'] = msgid
+
+ except KeyError, message:
+ print message
+
+ return self.heads_dict
+
+ def sendemail(self):
+ """Talk to NNTP server and try to send email."""
+ try:
+ msglist = []
+
+ n = nntplib.NNTP(self.newsserver, self.port, self.user, self.password)
+
+ if(self.reader):
+ n.putline('mode reader')
+ resp = n.getline()
+ print resp
+
+ resp = n.shortcmd('POST')
+
+ # sett RFC977 2.4.2
+ if resp[0] <> '3':
+ raise n.error_reply, str(resp)
+
+ for line in self.headers:
+ if not line:
+ break
+ if line[-1] == '\n':
+ line = line[:-1]
+ if line[:1] == '.':
+ line = '.' + line
+ n.putline(line)
+
+ for line in self.body:
+ if not line:
+ break
+ if line[-1] == '\n':
+ line = line[:-1]
+ if line[:1] == '.':
+ line = '.' + line
+ n.putline(line)
+
+ n.putline('.')
+ n.quit()
+ return None
+ except (nntplib.error_reply, nntplib.error_temp, nntplib.error_perm, nntplib.error_proto, nntplib.error_data), message:
+ return 'NNTP: ' + str(message)
diff --git a/news2mail.py b/news2mail.py
index 78d0ae4..73808b3 100644
--- a/news2mail.py
+++ b/news2mail.py
@@ -3,12 +3,13 @@
Author: Cosimo Alfarano
Date: June 11 2000
-news2mail.py - (C) 2000 by Cosimo Alfarano <Alfarano@Students.CS.UniBo.It>
+news2mail.py - Copyright 2000 by Cosimo Alfarano <Alfarano@Students.CS.UniBo.It>
You can use this software under the terms of the GPL. If we meet some day,
and you think this stuff is worth it, you can buy me a beer in return.
Thanks to md for this useful formula. Beer is beer.
+
Gets news article and sends it via SMTP.
class news2mail is hopefully conform to rfc822.
@@ -19,151 +20,280 @@ normal (what pygs does) operations flow is:
3) merges NNTP and SMTP heads into a unique heads
4) adds, renames and removes some heads
5) sorts remaining headers starting at top with Received: From: To: Subject:
- Date:, normal headers ending with X-* and Resent-* headers.
+ Date:, normal headers ending with X-* and Resent-* headers.
"""
-from collections import OrderedDict
-import email
-from mail2news import VERSION, DESC
-import smtplib
-from socket import gethostbyaddr, gethostname
+
import sys
+import smtplib
+import string
+from re import compile
+#import getopt
import time
+#import rfc822
+from socket import gethostbyaddr, gethostname
+import tempfile
+import pyginfo
+
+class news2mail:
+ """news to mail gateway class"""
+
+ TMPFILE = tempfile.mktemp()
+ wlfile = None
+ logfile = None
+
+ sender = ''
+ rcpt = ''
+ envelope = ''
+
+ smtpserver = 'localhost'
+
+ hostname = gethostbyaddr(gethostname())[0]
+
+ heads_dict, smtpheads, nntpheads = {}, {}, {}
+ article, headers, body = [], [], []
+
+ debug = 1
+
+ def readfile(self):
+
+ for line in sys.stdin.readlines():
+ self.article.append(line)
+
+ if (len(self.article) == 1 and self.article[0][0] == '/'):
+ file = self.article[0][:-1]
+ del self.article[0]
+ for line in open(file,'r').readlines():
+ self.article.append(line)
+
+
+ def parsearticle(self):
+ """get news article from file or stdin and separate heads from body
+
+ REMEBER: headers value has '\n' as last char.
+ Use string[:-1] to ignore newline.
+ """
+
+ try:
+ body = 0 # are we in body or in headers?
+
+# voidline = compile('^$') # I need '\n', ^$ matches anything
+# spaceending = compile('\s*\n$')
+
+ for line in self.article:
+ if not body and len(line) == 1:
+ body = 1 # starts article body section
+
+ if not body:
+ try:
+ head, value = string.split(line, ' ', 1)
+ self.nntpheads[head] = value
+ except (string.index_error), message:
+ print 'string error: %s' % message
+ print '(probably missing couple "Header: value" in %s)' % line
+ sys.exit(1)
+
+ elif len(line) > 0 and body:
+ self.body.append(line)
+
+ return self.nntpheads, self.body
+
+# except (re.error, string.index_error), message:
+ except (string.index_error), message:
+ print message
+ sys.exit(1)
+
+
+ def puthead(self, dict, list, key):
+ """private, x-form dict entries in list entries"""
+
+ if dict.has_key(key):
+ list.append(key + ' ' + dict.get(key))
+ else:
+ return 0
+ return 1
+
+ def sortheads(self):
+ """make list sorting heads, Received: From: To: Subject: first, others, X-*, Resent-* last"""
+
+ set = ('Received:','From:','To:','Subject:','Date:') # put at top
+
+ for k in set:
+ self.puthead(self.heads_dict,self.headers,k)
+
+ for k in self.heads_dict.keys():
+ if k[:2] != 'X-' and k[:7] != 'Resent-' and k not in set:
+ self.puthead(self.heads_dict,self.headers,k)
+
+ for k in self.heads_dict.keys():
+ if k[:2] == 'X-':
+ self.puthead(self.heads_dict,self.headers,k)
+
+ for k in self.heads_dict.keys():
+ if k[:7] == 'Resent-':
+ self.puthead(self.heads_dict,self.headers,k)
+
+ return self.headers
+
+
+ def mergeheads(self):
+ """make a unique headers dictionary from NNTP and SMTP
+ single headers dictionaries."""
+
+ self.heads_dict = {}
+
+
+ try:
+ for header in self.nntpheads.keys(): # fill it w/ nntp old heads
+ self.heads_dict[header] = self.nntpheads[header]
+
+ for header in self.smtpheads.keys(): # and replace them w/ smtp new heads
+ self.heads_dict[header] = self.smtpheads[header]
+
+ except KeyError, message:
+ print message
+
+ return self.heads_dict
+
+ def addheads(self):
+ """add new header like X-Gateway: Received:
+ """
+
+ info = pyginfo.pygsinfo()
+
+ try:
+ self.heads_dict['X-Gateway:'] = info.PROGNAME + ' ' + \
+ info.__doc__ + '\n'
+
+ ##self.heads_dict['X-Gateway:'] = '%s %s\n' % (info.PROGNAME, info.__doc__)
+
+ # to make Received: header
+ t = time.ctime(time.time())
+
+ if time.daylight:
+ tzone = time.tzname[1]
+ else:
+ tzone = time.tzname[0]
+
+ # An exemple from debian-italian:
+ # Received: from murphy.debian.org (murphy.debian.org [216.234.231.6])
+ # by smv04.iname.net (8.9.3/8.9.1SMV2) with SMTP id JAA26407
+ # for <kame.primo@innocent.com> sent by
+ # <debian-italian-request@lists.debian.org
+
+ tmp = 'from GATEWAY by ' + self.hostname + \
+ ' with ' + info.PROGNAME + \
+ '\n\tfor <' + self.rcpt + '> ; ' + \
+ t + ' (' + tzone +')\n'
+
+ self.heads_dict['Received:'] = tmp
+ except KeyError, message:
+ print message
+
+ return self.heads_dict
+
+ def renameheads(self):
+ """rename headers such as Newsgroups: to X-Newsgroups:
+
+ headers renamed are useless or not rfc 822 copliant
+ """
+ try:
+ if self.heads_dict.has_key('Newsgroups:'):
+ self.heads_dict['X-Newsgroups:'] = self.heads_dict['Newsgroups:']
+ del self.heads_dict['Newsgroups:']
+
+ if self.heads_dict.has_key('NNTP-Posting-Host:'):
+ self.heads_dict['X-NNTP-Posting-Host:'] = self.heads_dict['NNTP-Posting-Host:']
+ del self.heads_dict['NNTP-Posting-Host:']
+ except KeyError, message:
+ print message
+
+ return self.heads_dict
+
+
+ def removeheads(self):
+ """remove headers like Xref: Path: Lines:
+ """
+
+ try:
+ # removing some others useless headers ....
+
+ if self.heads_dict.has_key('Approved:'):
+ del self.heads_dict['Approved:']
+
+ if self.heads_dict.has_key('From'): # neither 'From ' nor 'From:'
+ del self.heads_dict['From']
+
+ if self.heads_dict.has_key('Xref:'):
+ del self.heads_dict['Xref:']
+
+ if self.heads_dict.has_key('Path:'):
+ del self.heads_dict['Path:']
+
+ if self.heads_dict.has_key('Lines:'):
+ del self.heads_dict['Lines:']
+
+ # it is usually set by INN, if ng is moderated...
+ if self.heads_dict.has_key('Sender:'):
+ del self.heads_dict['Sender:']
+
+
+ if self.heads_dict.has_key('Message-id:'):
+ self.heads_dict['Message-Id:'] = self.heads_dict['Message-id']
+ del(self.heads_dict['Message-id'])
+
+ if self.heads_dict.has_key('Message-ID:'):
+ self.heads_dict['Message-Id:'] = self.heads_dict['Message-ID']
+ del(self.heads_dict['Message-ID'])
+
+ # If message-id is not present, I generate it
+ if not self.heads_dict.has_key('Message-Id:'):
+ # It should put a real user@domain
+ msgid = 'pyg@puppapera.org'
+
+ except KeyError, message:
+ print message
+
+ return self.heads_dict
+
+ def sendarticle(self):
+ """Talk to SMTP server and try to send email."""
+ try:
+ msglist = []
+
+ s = smtplib.SMTP(self.smtpserver)
+
+ # put real locahost domain name.
+ s.helo(self.hostname)
+ if s.helo_resp is None and s.ehlo_resp is None:
+ print 'No helo resp'
+ sys.exit(1)
+
+ resp = s.mail(self.envelope)
+ if resp[0] != 250:
+ print 'SMTP error during MAIL cmd: %s %s' % (resp[0], resp[1])
+ print 'envelope %s gave problem?' % self.envelope
+ sys.exit(1)
+ resp = s.rcpt(self.rcpt)
+ if resp[0] != 250:
+ print 'SMTP error during MAIL cmd: %s %s' % (resp[0], resp[1])
+ sys.exit(1)
+
+
+ msglist.append(string.join(self.headers,''))
+
+ msglist.append(string.join(self.body,''))
+ msg = string.join(msglist,'')
+
+ s.data(msg)
+ s.quit()
+
+ return 1
+
+ except (smtplib.SMTPException), messaggio:
+ print messaggio
+ sys.exit(1)
-# logging.basicConfig(level=logging.DEBUG)
-class news2mail(object):
- """news to mail gateway class"""
-
- def __init__(self, verbose=False):
- self.wlfile = None
- self.logfile = None
- self.verbose = verbose
-
- self.sender = ''
- self.rcpt = ''
- self.envelope = ''
-
- self.smtpserver = 'localhost'
-
- self.hostname = gethostbyaddr(gethostname())[0]
- self.heads_dict = {}
- self.article, self.headers, self.body = [], [], []
- self.message = self.__addheads(email.message_from_file(sys.stdin))
- def __addheads(self, msg):
- """add new header like X-Gateway: Received:
- """
-
- msg['X-Gateway'] = 'pyg {0} {1}'.format(VERSION, DESC)
-
- # to make Received: header
- t = time.ctime(time.time())
-
- if time.daylight:
- tzone = time.tzname[1]
- else:
- tzone = time.tzname[0]
-
- # An example from debian-italian:
- # Received: from murphy.debian.org (murphy.debian.org [216.234.231.6])
- # by smv04.iname.net (8.9.3/8.9.1SMV2) with SMTP id JAA26407
- # for <kame.primo@innocent.com> sent by
- # <debian-italian-request@lists.debian.org
-
- tmp = 'from GATEWAY by ' + self.hostname + \
- ' with pyg' + \
- '\n\tfor <' + self.rcpt + '> ; ' + \
- t + ' (' + tzone + ')\n'
-
- msg['Received'] = tmp
-
- return msg
-
- def __renameheads(self):
- """remove headers like Xref: Path: Lines:
- rename headers such as Newsgroups: to X-Newsgroups:
-
- headers renamed are useless or not rfc 822 copliant
- """
- try:
- if 'Newsgroups' in self.message:
- self.message['X-Newsgroups'] = \
- self.message['Newsgroups']
- del self.message['Newsgroups']
-
- if 'NNTP-Posting-Host' in self.message:
- self.message['X-NNTP-Posting-Host'] = \
- self.message['NNTP-Posting-Host']
- del self.message['NNTP-Posting-Host']
- except KeyError as ex:
- print(ex)
-
- try:
- # removing some others useless headers ....
- # that includes BOTH 'From ' and 'From'
- # 'Sender is usually set by INN, if ng is moderated...
- for key in ('Approved', 'From', 'Xref', 'Path', 'Lines', 'Sender'):
- if key in self.message:
- del self.message[key]
-
- if 'Message-id' in self.message:
- msgid = self.message['Message-id']
- del self.message['Message-id']
- self.message['Message-Id'] = msgid
- else:
- # It should put a real user@domain
- self.heads_dict['Message-Id'] = 'pyg@puppapera.org'
-
- if 'References' in self.message and \
- 'In-Reply-To' not in self.message:
- refs = self.message['References'].split()
- self.message['In-Reply-To'] = refs[-1]
-
- except KeyError, message:
- print message
-
- def __sortheads(self):
- """make list sorting heads, Received: From: To: Subject: first,
- others, X-*, Resent-* last"""
-
- # put at top
- header_set = ('Received', 'From', 'To', 'Subject', 'Date')
-
- heads_dict = OrderedDict(self.message)
- for hdr in self.message.keys():
- del self.message[hdr]
-
- for k in header_set:
- if k in heads_dict:
- self.message[k] = heads_dict[k]
-
- for k in heads_dict:
- if not k.startswith('X-') and not k.startswith('Resent-') \
- and k not in header_set:
- self.message[k] = heads_dict[k]
-
- for k in heads_dict:
- if k.startswith('X-'):
- self.message[k] = heads_dict[k]
-
- for k in heads_dict:
- if k.startswith('Resent-'):
- self.message[k] = heads_dict[k]
-
- def process_message(self):
- """phase 3:
- format rfc 822 headers from input article
- """
- self.__renameheads() # remove other heads
- self.__sortheads()
-
- def sendarticle(self):
- """Talk to SMTP server and try to send email."""
- s = smtplib.SMTP(self.smtpserver)
- s.set_debuglevel(self.verbose)
-
- s.sendmail(self.envelope, self.rcpt, self.message.as_string())
-
- s.quit()
diff --git a/pyginfo.py b/pyginfo.py
new file mode 100644
index 0000000..a9a0bfa
--- /dev/null
+++ b/pyginfo.py
@@ -0,0 +1,26 @@
+"""News to mail gateway script. Copyright 2000 Cosimo Alfarano
+
+Author: Cosimo Alfarano
+Date: June 11 2000
+
+pyginfo.py - Copyright 2000 by Cosimo Alfarano <Alfarano@Students.CS.UniBo.It>
+You can use this software under the terms of the GPL. If we meet some day,
+and you think this stuff is worth it, you can buy me a beer in return.
+
+Thanks to md for this useful formula. Beer is beer.
+
+
+Gets news article and sends it via SMTP.
+"""
+
+
+class pygsinfo:
+ """The Python Gateway Script: news2mail mail2news gateway"""
+
+ PROGNAME = 'pyg'
+ PROGDESC= 'The Python Gateway'
+
+ MAJOR = '0'
+ MINOR = '7b'
+ VERSION = MAJOR + '.' + MINOR
+
diff --git a/pygm2n b/pygm2n
index 3629857..428ca5b 100755
--- a/pygm2n
+++ b/pygm2n
@@ -1,5 +1,5 @@
#!/usr/bin/env python
-# -*- coding: utf-8 -*-
+
"""News to mail gateway script. Copyright 2000 Cosimo Alfarano
Author: Cosimo Alfarano
@@ -13,87 +13,211 @@ Thanks to md for this useful formula. Beer is beer.
Gets news article and sends it via SMTP.
"""
-from __future__ import print_function
-import argparse
-import logging
-import mail2news
-import nntplib
-import sys
+import sys, os
+import getopt
+from string import split
+
+sys.path.append('/usr/lib/pyg')
+
+import pyginfo
+import mail2news
+
+
+def parse_cmdline(gw):
+ """Parses cmdline with getopt. and returns a dictionary with
+ smtp new header
+ """
+
+ opt, arg = None, None
+ test, verbose = 0, 0
+# retnull = (None, None)
+ retnull = None
+
+ retval = { 'test': 0,
+ 'verbose': 0 }
+
+ try:
+ opt, arg = getopt.getopt(sys.argv[1:],"a:s:n:u:p:P:hvVTM")
+ except (getopt.error), message:
+ print '%s: %s\n' % (sys.argv[0], message)
+ sys.exit(1)
+
+ if len(sys.argv) == 1 or opt == []:
+ gw.smtpheads = None
+ return retnull
+
+ for i in range(len(opt)):
+ if opt[i][0] == '-h':
+ gw.nntpheads = None
+ return retnull
+ elif opt[i][0] == '-v':
+ gw.nntpheads = None
+ return retnull
+ elif opt[i][0] == '-n':
+ gw.nntpheads['Newsgroups:'] = opt[i][1] + '\n'
+ elif opt[i][0] == '-a':
+ gw.nntpheads['Approved:'] = opt[i][1] + '\n'
+ elif opt[i][0] == '-s':
+ gw.newsserver = opt[i][1]
+ elif opt[i][0] == '-P':
+ gw.port = int(opt[i][1])
+# elif opt[i][0] == '-d':
+# gw.debug = 1
+ elif opt[i][0] == '-u':
+ gw.user = opt[i][1]
+ elif opt[i][0] == '-p':
+ gw.password = opt[i][1]
+ elif opt[i][0] == '-T':
+ retval['test'] = 1
+ elif opt[i][0] == '-V':
+ retval['verbose'] = 1
+ elif opt[i][0] == '-M':
+ gw.reader = 1
+
+ if not gw.nntpheads.has_key('Newsgroups:'):
+ print 'Error: Missing Newsgroups\n'
+ return retnull
+
+
+# By rfc822 [Resent-]Sender: should be ever set, unless == From:
+# (not this case). Should be a human, while [Resent-]From: may be a program.
+
+# if gw.rcpt == '' or gw.sender == '':
+# print 'missing command line option'
+# gw.smtpheads = None
+# return retnull
+
+# if gw.envelope == '' and gw.sender != '':
+# gw.smtpheads['Resent-From:'] = gw.sender + '\n'
+# gw.envelope = gw.sender
+# elif gw.envelope == -1:
+# gw.smtpheads = None
+# return retnull
+
+ sys.argv[1:] = arg
+
+# return (test, verbose)
+ return retval
+
+
+def usage():
+ i = pyginfo.pygsinfo()
+
+ print '%s version %s - Copyright 2000 Cosimo Alfarano' % (i.PROGNAME, i.VERSION)
+ print i.PROGDESC + ' - Mail to News'
+ print
+ print 'usage: %s -n newsgroup [-h] [-a approver] [-n newsgroup] [-T] [-V]' % split(sys.argv[0],'/')[-1]
+ print '-n newsgroup[s] (specified as comma separated without spaces list)'
+ print '-u user | -p passwword (for auth to newsserver)'
+ print '-a address of moderator/approver'
+ print '-s servername'
+# print '-d for debug'
+ print '-h or -v for this info'
+ print '-T for test mode (not send article via NNTP)'
+ print '-V for verbose output (usefull with -T option for debugging)'
+
+
+
-# logging.basicConfig(level=logging.DEBUG)
-def parse_cmdline():
- parser = argparse.ArgumentParser(
- description='%s version %s - Copyright 2000 Cosimo Alfarano\n%s' %
- ('pyg', mail2news.VERSION, mail2news.DESC))
- parser.add_argument('-s', '--newsserver', default='')
- parser.add_argument('-a', '--approver', default='',
- help="address of moderator/approver")
- parser.add_argument('-n', '--newsgroup', default='',
- help='newsgroup[s] (specified as comma separated ' +
- 'without spaces list)', required=True)
- parser.add_argument('-u', '--user', default='',
- help='NNTP server user (for authentication)')
- parser.add_argument('-p', '--password', default='',
- help='NNTP server password (for authentication)')
- parser.add_argument('-P', '--port', default='')
- parser.add_argument('-e', '--envellope', default='')
- parser.add_argument('-l', '--logfile')
- parser.add_argument('-T', '--test', action='store_true',
- help='test mode (not send article via NNTP)')
- parser.add_argument('-v', '--verbose', action='store_true',
- help='verbose output ' +
- '(usefull with -T option for debugging)')
- args = parser.parse_args()
- if not args.newsgroup:
- raise argparse.ArgumentError('Error: Missing Newsgroups\n')
- return args
"""main is structured in 4 phases:
- 1) check and set pyg's internal variables
- 2) check whitelist for users' permission
- 3) format rfc 822 headers from input article
- 4) open smtp connection and send e-mail
+ 1) check and set pyg's internal variables
+ 2) check whitelist for users' permission
+ 3) format rfc 822 headers from input article
+ 4) open smtp connection and send e-mail
"""
try:
- """phase 1:
- check and set pyg's internal variables
- """
- opt = parse_cmdline()
+ """phase 1:
+ check and set pyg's internal variables
+ """
- m2n = mail2news.mail2news(opt)
- owner = None
+ m2n = mail2news.mail2news()
+ owner = None
- """phase 3:
- format rfc 822 headers from input article
- """
- m2n.renameheads() # rename useless heads
- m2n.removeheads() # remove other heads
+ opt = parse_cmdline(m2n)
+ if(opt == None):
+ usage()
+ sys.exit(0)
+
+
+ # check if m2n has some file prefercences set on commandline
+# if(m2n.wlfile == None):
+# wl = os.environ['HOME'] + '/pyg.whitelist'
+# else:
+# wl = m2n.wlfile
+#
+# if(m2n.logfile == None):
+# log = os.environ['HOME'] + '/pyg.log'
+# else:
+# log = m2n.logfile
+
+
+# wl = whitelist.whitelist(wl,log)
+
+ # reads stdin and parses article separating head from body
+ m2n.readfile()
+ m2n.parseemail()
+
+
+
+# for line in m2n.email:
+# print line[:-1]
+
+# for line in m2n.smtpheads.keys():
+# print line
+# print m2n.smtpheads[line][:-1]
+
+ """phase 2:
+ check whitelist for user's permission
+ """
+
+ # make a first check of From: address
+# owner = wl.checkfrom(m2n.nntpheads['From:'])
+# if(owner == None):
+# if(sys.stdin.isatty()==1 or test or verbose):
+# print ('"%s" is not in whitelist!' % (m2n.nntpheads['From:'][:-1]))
+# else:
+# wl.logmsg(m2n.nntpheads,wl.DENY)
+# sys.exit(1)
+
+ """phase 3:
+ format rfc 822 headers from input article
+ """
+
+ m2n.mergeheads() # make unique dict from NNTP and SMTP dicts
+
+ m2n.addheads() # add some important heads
+ m2n.renameheads() # rename useless heads
+ m2n.removeheads() # remove other heads
+
+ m2n.sortheads() # sort remaining heads :)
- m2n.sortheads() # sort remaining heads :)
+ if(opt['verbose']):
+ for line in m2n.headers:
+ print line[:-1]
- if opt.verbose:
- print(m2n.message.as_string())
+ """phase 4:
+ open smtp connection and send e-mail
+ """
- logging.debug('m2n.payload = len %d', len(m2n.message.get_payload()))
- if len(m2n.message.get_payload()) > 0:
-# wl.logmsg(m2n.heads_dict,wl.ACCEPT,owner)
- if not opt.test:
- try:
- resp = m2n.sendemail()
- except nntplib.NNTPError as ex:
- print(ex)
+ if(len(m2n.headers) > 0 and len(m2n.body) > 0):
+# wl.logmsg(m2n.heads_dict,wl.ACCEPT,owner)
+ if(not opt['test']):
+ resp = m2n.sendemail()
+ if resp:
+ print resp
except KeyboardInterrupt:
- print('Keyboard Interrupt')
- sys.exit(0)
+ print 'Keyboard Interrupt'
+ sys.exit(0)
diff --git a/pygn2m b/pygn2m
index a2c07cb..d093756 100755
--- a/pygn2m
+++ b/pygn2m
@@ -1,5 +1,5 @@
#!/usr/bin/env python
-# -*- coding: utf-8 -*-
+
"""News to mail gateway script. Copyright 2000 Cosimo Alfarano
Author: Cosimo Alfarano
@@ -13,114 +13,202 @@ Thanks to md for this useful formula. Beer is beer.
Gets news article from stdin and sends it via SMTP.
"""
-from __future__ import print_function
-
-import argparse
-from mail2news import VERSION, DESC
-import news2mail
-import os
-import sys
-import whitelist
-
-def parse_cmdline():
- """
- set a dictionary with smtp new header in gw parameter (gw.smtpheads)
- return (test,verbose) boolean tuple
- """
- parser = argparse.ArgumentParser(
- description='pyg version %s - Copyright 2000 Cosimo Alfarano\n%s' %
- (VERSION, DESC))
+import sys, os
+import getopt
+from string import split
- parser.add_argument('-H', '--smtpserver', default='')
- parser.add_argument('-s', '--sender', required=True, default='')
- parser.add_argument('-e', '--envelope', default='')
- parser.add_argument('-t', '--to', dest='rcpt', required=True)
- parser.add_argument('-w', '--wlfile')
- parser.add_argument('-l', '--logfile')
+sys.path.append('/usr/lib/pyg')
- parser.add_argument('-T', '--test',
- help='test mode (not send article via SMTP)',
- action='store_true')
- parser.add_argument('-v', '--verbose', help='verbose output',
- action='store_true')
-
- opts = parser.parse_args()
-
-# By rfc822 [Resent-]Sender: should be ever set, unless == From:
+import pyginfo
+import whitelist
+import news2mail
+#import mail2news
+
+
+def parse_cmdline(gw):
+ """Parses cmdline with getopt.
+ set a dictionary with smtp new header in gw parameter (gw.smtpheads)
+ return (test,verbose) boolean tuple
+ """
+
+ opt, arg = None, None
+ test, verbose = 0, 0
+ retnull = (None, None)
+
+ try:
+ opt, arg = getopt.getopt(sys.argv[1:],"H:t:s:e:w:l:hdvVT")
+ except (getopt.error), message:
+ print '%s: %s\n' % (sys.argv[0], message)
+ sys.exit(1)
+
+ if len(sys.argv) == 1 or opt == []:
+ gw.smtpheads = None
+ return retnull
+
+ for i in range(len(opt)):
+ if opt[i][0] == '-h':
+ gw.smtpheads = None
+ return retnull
+ elif opt[i][0] == '-v':
+ gw.smtpheads = None
+ return retnull
+ elif opt[i][0] == '-H':
+ gw.smtpserver = opt[i][1]
+ elif opt[i][0] == '-s':
+ gw.smtpheads['Resent-Sender:'] = opt[i][1] + '\n'
+ gw.sender = opt[i][1]
+ elif opt[i][0] == '-t' or opt[i][0] == '-r':
+ gw.smtpheads['To:'] = opt[i][1] + '\n'
+ gw.rcpt = opt[i][1]
+ elif opt[i][0] == '-e':
+ gw.smtpheads['Resent-From:'] = opt[i][1] + '\n' #envelope
+ gw.envelope = opt[i][1]
+ elif opt[i][0] == '-w':
+ gw.wlfile = opt[i][1]
+ elif opt[i][0] == '-l':
+ gw.logfile = opt[i][1]
+ elif opt[i][0] == '-d':
+ gw.debug = 1
+ elif opt[i][0] == '-T':
+ test = 1
+ elif opt[i][0] == '-V':
+ verbose = 1
+
+# By rfc822 [Resent-]Sender: should be ever set, unless == From:
# (not this case). Should be a human, while [Resent-]From: may be a program.
- if opts.rcpt == '' or opts.sender == '':
- raise argparse.ArgumentError('missing command line option')
+ if gw.rcpt == '' or gw.sender == '':
+ print 'missing command line option'
+ gw.smtpheads = None
+ return retnull
- if opts.envelope == '' and opts.sender != '':
- opts.envelope = opts.sender
+ if gw.envelope == '' and gw.sender != '':
+ gw.smtpheads['Resent-From:'] = gw.sender + '\n'
+ gw.envelope = gw.sender
+ elif gw.envelope == -1:
+ gw.smtpheads = None
+ return retnull
- return opts
+ sys.argv[1:] = arg
+ return (test, verbose)
-"""main is structured in 4 phases:
- 1) check and set pyg's internal variables
- 2) check whitelist for users' permission
- 3) format rfc 822 headers from input article
- 4) open smtp connection and send e-mail
-"""
-
-"""phase 1:
-check and set pyg's internal variables
-"""
-# it returns only test, other parms are set directly in the actual
-# parameter
-args = parse_cmdline()
+def usage():
+ i = pyginfo.pygsinfo()
-n2m = news2mail.news2mail(verbose=args.verbose)
-owner = None
+ print '%s version %s - Copyright 2000 Cosimo Alfarano' % (i.PROGNAME, i.VERSION)
+ print i.__doc__
+ print
+ print 'usage: %s [-h] [-d] [-T] [-V] [-H smtphost] [-l logfile] [-w whitelist] -t recipient@... -s sender@... [-e envelope@...]' % split(sys.argv[0],'/')[-1]
+ print '-t -s recipient, sender are necessary'
+ print '-e envelope [default: same of sender]'
+ print '-T for test mode (not send article via SMTP)'
+ print '-V for verbose output'
+ print '-d for debug'
+ print '-h or -v for this info'
+
-# check if n2m has some file prefercences set on commandline
-if args.wlfile is None:
- wl = os.path.expanduser(os.path.join(os.path.dirname(__file__), 'pyg.whitelist'))
-else:
- wl = args.wlfile
-if args.logfile is None:
- log = os.path.expanduser(os.path.join(os.path.dirname(__file__), 'pyg.log'))
-else:
- log = args.logfile
-wl = whitelist.whitelist(wl, log)
-
-"""phase 2:
-check whitelist for user's permission
-"""
-# make a first check of From: address
-owner = wl.checkfrom(n2m.message['From'])
-if owner is None:
- if sys.stdin.isatty() == 1 or args.test:
- print ('"%s" is not in whitelist!' % (n2m.message['From'][:-1]))
- else:
- wl.logmsg(n2m.nntpheads, wl.DENY)
- # if verbose, I want to print out headers, so I can't
- # exit now.
- if not args.verbose:
- sys.exit(1)
-# Reformat the message
-n2m.process_message()
-# prints formatted email message only (without send) if user wants
-if args.verbose:
- print(n2m.message.as_string())
-
-if owner is None:
- sys.exit(1)
-
-"""phase 4:
-open smtp connection and send e-mail
+"""main is structured in 4 phases:
+ 1) check and set pyg's internal variables
+ 2) check whitelist for users' permission
+ 3) format rfc 822 headers from input article
+ 4) open smtp connection and send e-mail
"""
-wl.logmsg(n2m.heads_dict, wl.ACCEPT, owner)
-if not args.test:
- n2m.sendarticle()
+
+try:
+
+ """phase 1:
+ check and set pyg's internal variables
+ """
+
+ n2m = news2mail.news2mail()
+ owner = None
+
+ # it returns only test, other parms are set directly in the actual parameter
+ (test, verbose) = parse_cmdline(n2m)
+ if (test, verbose) == (None, None):
+ usage()
+ sys.exit(0)
+
+
+ # check if n2m has some file prefercences set on commandline
+ if(n2m.wlfile == None):
+ wl = os.environ['HOME'] + '/pyg.whitelist'
+ else:
+ wl = n2m.wlfile
+
+ if(n2m.logfile == None):
+ log = os.environ['HOME'] + '/pyg.log'
+ else:
+ log = n2m.logfile
+
+# print 'using %s %s\n' % (wl,log)
+
+ wl = whitelist.whitelist(wl,log)
+
+ # reads stdin and parses article separating head from body
+ n2m.readfile()
+ n2m.parsearticle()
+
+
+ """phase 2:
+ check whitelist for user's permission
+ """
+
+ # make a first check of From: address
+ owner = wl.checkfrom(n2m.nntpheads['From:'])
+ if(owner == None):
+ if(sys.stdin.isatty()==1 or test):
+ print ('"%s" is not in whitelist!' % (n2m.nntpheads['From:'][:-1]))
+ else:
+ wl.logmsg(n2m.nntpheads,wl.DENY)
+
+ # if verbose, I want to print out headers, so I can't
+ # exit now.
+ if(not verbose):
+ sys.exit(1)
+
+ """phase 3:
+ format rfc 822 headers from input article
+ """
+
+ n2m.mergeheads() # make unique dict from NNTP and SMTP dicts
+
+ n2m.addheads() # add some important heads
+ n2m.renameheads() # rename useless heads
+ n2m.removeheads() # remove other heads
+
+ n2m.sortheads() # sort remaining heads :)
+
+ # prints formatted email message only (without send) if user wants
+ if(verbose):
+ for line in n2m.headers:
+ print line[:-1]
+
+ if(owner == None):
+ sys.exit(1)
+
+
+ """phase 4:
+ open smtp connection and send e-mail
+ """
+
+ if len(n2m.headers) > 0:
+ wl.logmsg(n2m.heads_dict,wl.ACCEPT,owner)
+ if(not test):
+ n2m.sendarticle()
+ else:
+ print 'Error: No Headers!!!'
+
+except KeyboardInterrupt:
+ print 'Keyboard Interrupt'
+ sys.exit(1)
diff --git a/setup.py b/setup.py
deleted file mode 100644
index 9fdad76..0000000
--- a/setup.py
+++ /dev/null
@@ -1,69 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-from __future__ import print_function
-import os.path
-from setuptools import setup
-from distutils.core import Extension
-from distutils.command.build_ext import build_ext
-from subprocess import check_call
-from mail2news import VERSION, DESC
-
-
-class Build_WLP_ext(build_ext):
- def run(self):
- self.make_file(
- 'wlp/commands.y', 'wlp/commands.tab.c', check_call,
- # Yes, the following line contains list-in-list-in-tuple, and
- # that's how it should be.
- # otherwise, subsequent calls down the stack unwind the list and
- # check_call won't get it.
- ([['yacc', '-d', '-o', 'wlp/commands.tab.c', 'wlp/commands.y']]),
- 'Generating lexer')
- self.make_file(
- 'wlp/commands.l', 'wlp/lex.yy.c', check_call,
- ([['lex', '-o', 'wlp/lex.yy.c', 'wlp/commands.l']]),
- 'Generating parser')
- build_ext.run(self)
-
-
-def read(fname):
- return open(os.path.join(os.path.dirname(__file__), fname)).read()
-
-# see https://github.com/Turbo87/py-xcsoar/blob/master/setup.py
-wlp_module = Extension('wlp',
- sources=['wlp/wlp.c',
- 'wlp/structs.c',
- 'wlp/commands.tab.c',
- 'wlp/lex.yy.c'])
-
-
-setup(name='pygn',
- version=VERSION, # the current Debian version is 0.9.8
- author="Cosimo Alfarano, Matej Cepl",
- author_email="kalfa@debian.org, mcepl@cepl.eu",
- description=DESC,
- long_description=read('README'),
- url='https://gitlab.com/mcepl/pyg',
- py_modules=['mail2news', 'news2mail', 'setup', 'whitelist'],
- ext_modules=[wlp_module],
- test_suite="test",
- scripts=['pygm2n', 'pygn2m'],
- cmdclass={
- 'build_ext': Build_WLP_ext
- },
- # TODO package actually requires lex and yacc port, but not sure
- # how to say it here
- requires=[],
- license="GPLv3",
- keywords=["nntp", "email", "gateway"],
- classifiers=[
- 'Development Status :: 3 - Alpha',
- 'Programming Language :: Python :: 2.7',
- 'Intended Audience :: System Administrators',
- 'Topic :: Utilities',
- 'Topic :: Communications :: Usenet News',
- 'Environment :: Console',
- 'Operating System :: OS Independent',
- 'License :: OSI Approved :: GNU General Public License v3 (GPLv3)'
- ]
- )
diff --git a/tarballs/pyg_0.9.6-2.tar.gz b/tarballs/pyg_0.9.6-2.tar.gz
deleted file mode 100644
index 138eeba..0000000
--- a/tarballs/pyg_0.9.6-2.tar.gz
+++ /dev/null
Binary files differ
diff --git a/tarballs/pyg_0.9.6-4.1.tar.gz b/tarballs/pyg_0.9.6-4.1.tar.gz
deleted file mode 100644
index 8a658fa..0000000
--- a/tarballs/pyg_0.9.6-4.1.tar.gz
+++ /dev/null
Binary files differ
diff --git a/tarballs/pyg_0.9.6-4.tar.gz b/tarballs/pyg_0.9.6-4.tar.gz
deleted file mode 100644
index d1fabbb..0000000
--- a/tarballs/pyg_0.9.6-4.tar.gz
+++ /dev/null
Binary files differ
diff --git a/test/__init__.py b/test/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/test/__init__.py
+++ /dev/null
diff --git a/test/test_wlp.py b/test/test_wlp.py
deleted file mode 100755
index 4dd1516..0000000
--- a/test/test_wlp.py
+++ /dev/null
@@ -1,115 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-import mail2news
-import os
-import os.path
-import re
-import subprocess
-import sys
-import sysconfig
-import unittest
-import wlp
-
-
-def distutils_dir_name(dname):
- """Returns the name of a distutils build directory"""
- f = "{dirname}.{platform}-{version[0]}.{version[1]}"
- return f.format(dirname=dname,
- platform=sysconfig.get_platform(),
- version=sys.version_info)
-wlp_lib_path = os.path.join('build', distutils_dir_name('lib'))
-sys.path.insert(0, wlp_lib_path)
-
-
-
-
-class TestWLP(unittest.TestCase):
- def test_wlp_parser(self):
- wlp.setfilebyname('examples/whitelist.example')
- wl_dict = wlp.mkdict()
- expected_dict = {'alfarano@students.cs.unibo.it': {
- 'From:': 'Cosimo Alfarano',
- 'X-Firstname:': 'Cosimo'
- },
- 'kame@innocent.com': {
- 'From:': 'kame@inwind.it',
- 'Reply-to': 'me',
- 'Reply-to:': 'KA',
- 'Sender:': 'Kalfa'}
- }
- self.assertEqual(wl_dict, expected_dict)
-
-
-class TestM2N(unittest.TestCase):
- expected_output = """Newsgroups: pyg.test
-From: Pyg <pyg@localhost.com>
-To: User <user@localhost.com>
-Subject: test
-Date: Sun, 1 Feb 2002 16:40:40 +0200
-Message-Id: <20001001164040.Aa8326@localhost>
-Return-Path: <pyg@localhost>
-Mime-Version: 1.0
-Content-Type: text/plain; charset=us-ascii
-User-Agent: Mutt/1.2.5i
-X-Multiline: this header probably broke RFC, but is frequent.
-X-Gateway: pyg %s %s
-
-one line test
-
-""" % (mail2news.VERSION, mail2news.DESC)
-
- def test_m2n(self):
- with open('examples/mail') as in_mail:
- pid = subprocess.Popen(['./pygm2n', '-Tv', '-n', 'pyg.test'],
- stdin=subprocess.PIPE,
- stdout=subprocess.PIPE)
- out, _ = pid.communicate(in_mail.read())
- self.assertEqual(out, self.expected_output)
-
-
-class TestN2M(unittest.TestCase):
- expected_output = """Received: from GATEWAY by mitmanek.ceplovi.cz with pyg
- for <test@example.com> ; Mon Dec 15 17:13:30 2014 (CEST)
-From: kame@inwind.it (PYG)
-To: test@example.com
-Subject: pyg's article test
-Date: 10 Jun 2000 23:20:47 +0200
-Organization: Debian GNU/Linux
-Reply-To: pyg@localhost
-Content-Type: text/plain; charset=US-ASCII
-Mime-Version: 1.0
-Content-Transfer-Encoding: 7bit
-X-Trace: pyg.server.tld 960672047 927 192.168.1.2 (10 Jun 2000 21:20:47 GMT)
-X-Newsgroups: local.moderated
-X-Gateway: pyg %s %s
-X-NNTP-Posting-Host: pyg.server.tld
-Resent-From: sender@example.com
-Resent-Sender: sender@example.com
-""" % (mail2news.VERSION, mail2news.DESC)
-
- def test_n2m(self):
- env = os.environ
- env['PYTHONPATH'] = wlp_lib_path
-
- with open('examples/articletest.accepted') as in_mail:
- pid = subprocess.Popen(['./pygn2m', '-Tvt', 'test@example.com',
- '-s', 'sender@example.com',
- '-w', 'examples/whitelist.example'],
- stdin=subprocess.PIPE,
- stdout=subprocess.PIPE, env=env)
- in_message = in_mail.read().replace('pyg@pyg.server.tld',
- 'kame@inwind.it')
- out, err = pid.communicate(in_message)
- out = re.sub(r'^Message-Id:.*$', '', out)
- # Not sure how to compare two email mesages (with different
- # times, etc.) so for now just to make sure the script doesn’t
- # blow up and gives some output
- # otherwise it would be
- # self.assertEqual(out, expected_output)
- self.assertEqual(pid.returncode, 0)
- self.assertGreater(len(out), 0)
-
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/whitelist-pygn2m b/whitelist-pygn2m
deleted file mode 100644
index 33044bc..0000000
--- a/whitelist-pygn2m
+++ /dev/null
@@ -1,3 +0,0 @@
-<ceplm@seznam.cz> {
- From: = 'ceplm@seznam.cz'
-}
diff --git a/whitelist.py b/whitelist.py
index cd0906c..7eb88cd 100644
--- a/whitelist.py
+++ b/whitelist.py
@@ -3,7 +3,7 @@
Author: Cosimo Alfarano
Date: June 11 2000
-whitelist.py - (C) 2000 by Cosimo Alfarano <Alfarano@Students.CS.UniBo.It>
+whitelist.py - Copyright 2000 by Cosimo Alfarano <Alfarano@Students.CS.UniBo.It>
You can use this software under the terms of the GPL. If we meet some day,
and you think this stuff is worth it, you can buy me a beer in return.
@@ -12,90 +12,118 @@ Thanks to md for this useful formula. Beer is beer.
whitelist manage a list of trusted user.
"""
-import logging
import sys
+import string
import time
+import fcntl
+
+import pyginfo
import wlp
-class whitelist(object):
- """whitelist handling class
-
- Do you really want anyone can post? Ah ah ah.
- """
- wl = {}
-
- # constants
- DENY = 0
- ACCEPT = 1
-
- def __init__(self, wlfile='wl.pyg', logfile='pyg.log'):
- self.logger = logging.getLogger(__name__)
- self.logger.setLevel(logging.INFO)
- log_fh = logging.FileHandler(logfile)
- log_fmt = logging.Formatter(
- '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
- log_fh.setFormatter(log_fmt)
- self.logger.addHandler(log_fh)
-
- try:
- wlp.setfilebyname(wlfile)
- except Exception as ex:
- self.logger.exception('Opening %s: %s', wlfile, ex)
- sys.exit(1)
-
- # dict is a { ownername : {variable: value}} dictionary of dictionaries
- self.wl = wlp.mkdict()
-
- def checkfrom(self, fromhead):
- """have you permission to be here, sir?"""
- for owner in self.wl.keys():
- # here colon after 'From' IS required, because binary module wl
- # expects it.
- # TODO: when switching to the python lexxing, remove this
- # limitation.
- if fromhead[:-1].find(self.wl[owner]['From:']) >= 0:
- return owner
- else:
- return None
-
- def logmsg(self, heads, ok=DENY, owner=None):
- """who are walking through my gate?
- """
-
- ltime = time.ctime(time.time())
-
- if time.daylight:
- tzone = time.tzname[1]
- else:
- tzone = time.tzname[0]
-
- if ok == self.ACCEPT:
- self.logger.info('Permission Accorded ')
- else:
- self.logger.info('Permission Denied ')
-
- self.logger.info('at %s (%s)', ltime, tzone)
- if owner is not None:
- self.logger.info('\tWLOwner: ' + owner + '')
- self.logger.info('\tFrom: ' + heads.get('From', 'NOT PRESENT'))
- self.logger.info('\tSubject: ' + heads.get('Subject', 'NOT PRESENT'))
- self.logger.info('\tSender: ' + heads.get('Sender', 'NOT PRESENT'))
- self.logger.info('\tDate: ' + heads.get('Date', 'NOT PRESENT'))
-
- # some client create Message-Id other Message-ID.
- if 'Message-ID' in heads:
- self.logger.info('\tMessage-ID: ' + heads.get('Message-ID'))
- else:
- self.logger.info('\tMessage-Id: ' + heads.get('Message-Id',
- 'NOT PRESENT'))
-
- # X-Newsgroups: and To: are present if user is trusted, else
- # Newsgroup: exists since no changes on nntp headers are done.
- if 'X-Newsgroups' in heads:
- self.logger.info('\tTo: ' + heads.get('To', 'NOT PRESENT'))
- self.logger.info('\tX-Newsgroups: ' + heads.get('X-Newsgroups',
- 'NOT PRESENT'))
- else:
- self.logger.info('\tNewsgroups: ' +
- heads.get('Newsgroups', 'NOT PRESENT'))
+class whitelist:
+ """whitelist handling class
+
+ Do you really want anyone can post? Ah ah ah.
+ """
+
+ wl = {}
+ debug = None
+ log = None # filedescriptor
+
+ # constants
+ DENY = 0
+ ACCEPT = 1
+
+ def __init__(self, wlfile='wl.pyg', logfile='pyg.log', debug=0):
+
+ self.debug = debug
+
+ try:
+ wlp.setfilebyname(wlfile)
+ except (Exception), (errno,message):
+ print 'Opening %s: %s (errno %d)' % (wlfile,message,errno)
+ sys.exit(0)
+
+ # dict is a { ownername : {variable: value}} dictionary of dictionaries
+ self.wl = wlp.mkdict()
+
+# print 'owner: option = value'
+# for owner in self.wl.keys():
+# for option in self.wl[owner].keys():
+# print '%s: %s = %s' % (owner,option,self.wl[owner][option])
+
+ try:
+ self.log = open(logfile, 'a')
+ self.lock()
+ except (Exception), message:
+ print '%s\nAre you authorized to use this program? ' % message
+ sys.exit(1)
+
+ def lock(self):
+ fcntl.flock(self.log.fileno(),fcntl.LOCK_EX)
+
+ # to unlock fd locked, usually fd are unlocked after process exit()
+ def unlock(self):
+ fcntl.flock(self.log.fileno(),fcntl.LOCK_UN)
+
+ def checkfrom(self, fromhead):
+ """have you permission to be here, sir?"""
+
+ for owner in self.wl.keys():
+# if(self.wl[owner]['From:'] == fromhead[:-1]): # remove '\n'
+ if(string.find(fromhead[:-1],self.wl[owner]['From:']) >= 0):
+ return owner
+ else:
+ return None
+
+
+ def log(self, string):
+ """Captain Diary, Astral Date 962555394 from epoch.
+ it rawly write a line in logfile. Remeber to indent it, if you
+ like.
+ """
+
+ self.log.write(string + '\n')
+
+ def logmsg(self, heads, ok=DENY,owner=None):
+ """who are walking through my gate?
+ log
+ """
+
+ ltime = time.ctime(time.time())
+
+ if time.daylight:
+ tzone = time.tzname[1]
+ else:
+ tzone = time.tzname[0]
+
+ if(ok == self.ACCEPT):
+ self.log.write('Permission Accorded ')
+ else:
+ self.log.write('Permission Denied ')
+
+ self.log.write('at %s (%s)\n' % (ltime,tzone))
+ if(owner != None):
+ self.log.write('\tWLOwner: ' + owner + '\n')
+ self.log.write('\tFrom: ' + heads.get('From:','NOT PRESENT\n'))
+ self.log.write('\tSubject: ' + heads.get('Subject:','NOT PRESENT\n'))
+ self.log.write('\tSender: ' + heads.get('Sender:','NOT PRESENT\n'))
+ self.log.write('\tDate: ' + heads.get('Date:','NOT PRESENT\n'))
+
+ # some client create Message-Id other Message-ID.
+ if(heads.has_key('Message-ID:')):
+ self.log.write('\tMessage-ID: ' + heads.get('Message-ID:'))
+ else:
+ self.log.write('\tMessage-Id: ' + heads.get('Message-Id:','NOT PRESENT\n'))
+
+ # X-Newsgroups: and To: are present if user is trusted, else
+ # Newsgroup: exists since no changes on nntp headers are done.
+ if(heads.has_key('X-Newsgroups:')):
+ self.log.write('\tTo: ' + heads.get('To:','NOT PRESENT\n'))
+ self.log.write('\tX-Newsgroups: ' + heads.get('X-Newsgroups:','NOT PRESENT\n'))
+ else:
+ self.log.write('\tNewsgroups: ' + heads.get('Newsgroups:','NOT PRESENT\n'))
+
+
+ self.log.write('\n')
diff --git a/wlp/C/Makefile b/wlp/C/Makefile
new file mode 100644
index 0000000..6bc8fc3
--- /dev/null
+++ b/wlp/C/Makefile
@@ -0,0 +1,43 @@
+CC=gcc
+AR=ar
+FLEX=flex
+YACC=bison
+
+CCOPTS=-Wall -ansi
+CCSHARED=-fPIC
+AROPTS=-rs
+FLEXOPTS=
+YACCOPTS=-d
+
+SRCDIR=.
+BINDIR=.
+
+OBJFILE=structs.o commands.tab.o lex.yy.o
+
+all: archive bin
+
+# archive file for python module
+archive: structs bison flex /usr/lib/libfl.a macro.h structs.h commands.tab.h
+ $(AR) $(AROPTS) $(BINDIR)/wlp.a $(OBJFILE) \
+ /usr/lib/libfl.a
+
+# binary (executable) file for testing
+executable: bin
+
+bin: structs bison flex /usr/lib/libfl.a macro.h structs.h commands.tab.h
+ $(CC) $(CCSHARED) $(CCOPTS) $(OBJFILE) \
+ yytest.c /usr/lib/libfl.a -o ./yytest
+
+flex:
+ $(FLEX) $(FLEXOPTS) commands.l
+ $(CC) $(CCSHARED) -c lex.yy.c -o lex.yy.o
+
+bison:
+ $(YACC) $(YACCOPTS) -d commands.y -b commands
+ $(CC) $(CCSHARED) -c commands.tab.c -o commands.tab.o
+
+structs:
+ $(CC) $(CCSHARED) $(CCOPTS) -c structs.c -o structs.o
+
+clean:
+ -rm $(OBJFILE) lex.yy.c commands.tab.h commands.tab.c wlp.a yytest
diff --git a/wlp/commands.l b/wlp/C/commands.l
index ab954cf..8f0f28e 100644
--- a/wlp/commands.l
+++ b/wlp/C/commands.l
@@ -4,7 +4,6 @@
#include "commands.tab.h"
/*#define DEBUG*/
#include "macro.h"
-#include <string.h>
%}
OWNER "<"[a-zA-Z0-9_.+-]+@[a-zA-Z0-9._-]+">"
diff --git a/wlp/commands.y b/wlp/C/commands.y
index e6cfb18..8b720d7 100644
--- a/wlp/commands.y
+++ b/wlp/C/commands.y
@@ -3,7 +3,6 @@
/*#define YYSTYPE char**/
/*#define DEBUG*/
#include "macro.h"
-#include "string.h"
%}
%union {
diff --git a/wlp/macro.h b/wlp/C/macro.h
index 303b3c6..303b3c6 100644
--- a/wlp/macro.h
+++ b/wlp/C/macro.h
diff --git a/wlp/structs.c b/wlp/C/structs.c
index 8c33443..8c33443 100644
--- a/wlp/structs.c
+++ b/wlp/C/structs.c
diff --git a/wlp/structs.h b/wlp/C/structs.h
index 92036a7..92036a7 100644
--- a/wlp/structs.h
+++ b/wlp/C/structs.h
diff --git a/wlp/test.c b/wlp/C/test.c
index 47717b5..47717b5 100644
--- a/wlp/test.c
+++ b/wlp/C/test.c
diff --git a/wlp/wlp.c b/wlp/C/wlp.c
index 6a36617..8c0779d 100644
--- a/wlp/wlp.c
+++ b/wlp/C/wlp.c
@@ -6,6 +6,7 @@
* Thanks to md for this useful formula. Beer is beer.
*/
+//#include <python/Python.h>
#include <Python.h>
#include <stdio.h>
#include <unistd.h>
@@ -19,6 +20,8 @@ static FILE *fd = NULL;
struct wlp_list_t *list;
static PyObject *node2dict(struct wlp_node_t *node);
+static PyObject *node2dict2(struct wlp_node_t *node);
+
@@ -34,7 +37,7 @@ static PyObject *wlp_setfilebyname(PyObject *self, PyObject *args) {
if (!PyArg_ParseTuple(args, "s", &file))
return NULL;
- if((fd = fopen(file,"r"))) {
+ if(fd = fopen(file,"r")) {
return Py_None;
} else {
PyErr_SetFromErrno(PyExc_Exception);
@@ -141,6 +144,32 @@ static PyObject *node2dict(struct wlp_node_t *node) {
}
+
+/*
+ * node2dict2(): transoform a wlp_node_t node in a python dictionary of the form
+ * { 'owner': ownername, var: val}
+ * it's currently unused (obsoleted)
+ */
+
+static PyObject *node2dict2(struct wlp_node_t *node) {
+ PyObject *dict = PyDict_New();
+
+ if(!dict)
+ dict = Py_None;
+ else {
+ PyDict_SetItem(dict,
+ Py_BuildValue("s","owner"),
+ Py_BuildValue("s",node->owner));
+
+ PyDict_SetItem(dict,
+ Py_BuildValue("s",node->left),
+ Py_BuildValue("s",node->right));
+ }
+
+ return dict;
+
+}
+
static PyMethodDef wlp_methods[] = {
{"mkdict", wlp_mkdict, METH_VARARGS},
{"setfilebyname", wlp_setfilebyname, METH_VARARGS},
diff --git a/wlp/yytest.c b/wlp/C/yytest.c
index 74c6fe7..74c6fe7 100644
--- a/wlp/yytest.c
+++ b/wlp/C/yytest.c
diff --git a/wlp/Makefile b/wlp/Makefile
index 7480b47..4e180d1 100644
--- a/wlp/Makefile
+++ b/wlp/Makefile
@@ -28,15 +28,15 @@ makemodule:
clean: cleanmodule cleansrc
- rm -f $(BINDIR)/*.so
+ -rm $(BINDIR)/*.so
cleansrc:
- $(MAKE) -C $(CSRCDIR) clean
+ -$(MAKE) -C $(CSRCDIR) clean
cleanmodule:
- @if test -f $(MODULEDIR)/Makefile; then $(MAKE) -C $(MODULEDIR) clean ;fi
- rm -f $(MODULEDIR)/Makefile.pre $(MODULEDIR)/Makefile
- rm -f $(MODULEDIR)/config.c
- rm -f $(MODULEDIR)/sedscript
- rm -f $(MODULEDIR)/Setup
+ -$(MAKE) -C $(MODULEDIR) clean
+ -rm $(MODULEDIR)/Makefile.pre $(MODULEDIR)/Makefile
+ -rm $(MODULEDIR)/config.c
+ -rm $(MODULEDIR)/sedscript
+ -rm $(MODULEDIR)/Setup
diff --git a/wlp/Makefile.C b/wlp/Makefile.C
deleted file mode 100644
index 0c962e6..0000000
--- a/wlp/Makefile.C
+++ /dev/null
@@ -1,61 +0,0 @@
-DESTDIR=
-LIBDIR=/usr/lib64
-BINDIR=/usr/bin
-PYGLIBDIR=$(DESTDIR)/$(LIBDIR)/pyg
-PYGBINDIR=$(DESTDIR)/$(BINDIR)
-
-CC=gcc
-AR=ar
-FLEX=flex
-YACC=bison
-
-CCOPTS=-Wall -ansi
-CCSHARED=-fPIC
-AROPTS=-rs
-FLEXOPTS=
-YACCOPTS=-d
-
-#CPPFLAGS:=$(shell dpkg-buildflags --get CPPFLAGS)
-CPPFLAGS:=
-# Add more -I and -D options here
-## CFLAGS=$(OPT) -I$(INCLUDEPY) -I$(EXECINCLUDEPY) $(DEFS) $(shell dpkg-buildflags --get CFLAGS)
-OPTFLAGS=-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4
-OPTFLAGS+=-grecord-gcc-switches -m64 -mtune=generic
-CFLAGS=$(OPTFLAGS)
-CXXFLAGS:=$(OPTFLAGS)
-OPTLDFLAGS=-Wl,-z,relro
-#LDFLAGS:=$(shell dpkg-buildflags --get LDFLAGS)
-LDFLAGS:=$(OPTLDFLAGS)
-
-SRCDIR=.
-BINDIR=.
-
-OBJFILE=structs.o commands.tab.o lex.yy.o
-
-all: archive bin
-
-# archive file for python module
-archive: structs bison flex macro.h structs.h commands.tab.h
- mkdir -p $(PYGLIBDIR)
- $(AR) $(AROPTS) $(PYGLIBDIR)/wlp.a $(OBJFILE)
-
-# binary (executable) file for testing
-executable: bin
-
-bin: structs bison flex macro.h structs.h commands.tab.h
- $(CC) $(CCSHARED) $(CCOPTS) $(OBJFILE) \
- yytest.c $(PYGLIBDIR)/libfl.a -o ./yytest
-
-flex:
- $(FLEX) $(FLEXOPTS) commands.l
- $(CC) $(CCSHARED) -c lex.yy.c -o lex.yy.o
-
-bison:
- $(YACC) $(YACCOPTS) -d commands.y -b commands
- $(CC) $(CCSHARED) -c commands.tab.c -o commands.tab.o
-
-structs:
- $(CC) $(CCSHARED) $(CCOPTS) -c structs.c -o structs.o
-
-clean:
- rm -f $(OBJFILE) lex.yy.c commands.tab.h commands.tab.c wlp.a yytest
diff --git a/wlp/README b/wlp/README
index 9c4d9b7..a2f97a0 100644
--- a/wlp/README
+++ b/wlp/README
@@ -9,4 +9,4 @@ make -C module # to really make .so python module
Please, remeber to report full output.
-Cosimo Alfarano <kalfa@debian.org>
+Cosimo Alfarano <alfarano@cs.unibo.it>
diff --git a/wlp/module/Makefile.pre.in b/wlp/module/Makefile.pre.in
new file mode 100644
index 0000000..8279573
--- /dev/null
+++ b/wlp/module/Makefile.pre.in
@@ -0,0 +1,305 @@
+# Universal Unix Makefile for Python extensions
+# =============================================
+
+# Short Instructions
+# ------------------
+
+# 1. Build and install Python (1.5 or newer).
+# 2. "make -f Makefile.pre.in boot"
+# 3. "make"
+# You should now have a shared library.
+
+# Long Instructions
+# -----------------
+
+# Build *and install* the basic Python 1.5 distribution. See the
+# Python README for instructions. (This version of Makefile.pre.in
+# only withs with Python 1.5, alpha 3 or newer.)
+
+# Create a file Setup.in for your extension. This file follows the
+# format of the Modules/Setup.in file; see the instructions there.
+# For a simple module called "spam" on file "spammodule.c", it can
+# contain a single line:
+# spam spammodule.c
+# You can build as many modules as you want in the same directory --
+# just have a separate line for each of them in the Setup.in file.
+
+# If you want to build your extension as a shared library, insert a
+# line containing just the string
+# *shared*
+# at the top of your Setup.in file.
+
+# Note that the build process copies Setup.in to Setup, and then works
+# with Setup. It doesn't overwrite Setup when Setup.in is changed, so
+# while you're in the process of debugging your Setup.in file, you may
+# want to edit Setup instead, and copy it back to Setup.in later.
+# (All this is done so you can distribute your extension easily and
+# someone else can select the modules they actually want to build by
+# commenting out lines in the Setup file, without editing the
+# original. Editing Setup is also used to specify nonstandard
+# locations for include or library files.)
+
+# Copy this file (Misc/Makefile.pre.in) to the directory containing
+# your extension.
+
+# Run "make -f Makefile.pre.in boot". This creates Makefile
+# (producing Makefile.pre and sedscript as intermediate files) and
+# config.c, incorporating the values for sys.prefix, sys.exec_prefix
+# and sys.version from the installed Python binary. For this to work,
+# the python binary must be on your path. If this fails, try
+# make -f Makefile.pre.in Makefile VERSION=1.5 installdir=<prefix>
+# where <prefix> is the prefix used to install Python for installdir
+# (and possibly similar for exec_installdir=<exec_prefix>).
+
+# Note: "make boot" implies "make clobber" -- it assumes that when you
+# bootstrap you may have changed platforms so it removes all previous
+# output files.
+
+# If you are building your extension as a shared library (your
+# Setup.in file starts with *shared*), run "make" or "make sharedmods"
+# to build the shared library files. If you are building a statically
+# linked Python binary (the only solution of your platform doesn't
+# support shared libraries, and sometimes handy if you want to
+# distribute or install the resulting Python binary), run "make
+# python".
+
+# Note: Each time you edit Makefile.pre.in or Setup, you must run
+# "make Makefile" before running "make".
+
+# Hint: if you want to use VPATH, you can start in an empty
+# subdirectory and say (e.g.):
+# make -f ../Makefile.pre.in boot srcdir=.. VPATH=..
+
+
+# === Bootstrap variables (edited through "make boot") ===
+
+# The prefix used by "make inclinstall libainstall" of core python
+installdir= /usr/local
+
+# The exec_prefix used by the same
+exec_installdir=$(installdir)
+
+# Source directory and VPATH in case you want to use VPATH.
+# (You will have to edit these two lines yourself -- there is no
+# automatic support as the Makefile is not generated by
+# config.status.)
+srcdir= .
+VPATH= .
+
+# === Variables that you may want to customize (rarely) ===
+
+# (Static) build target
+TARGET= python
+
+# Installed python binary (used only by boot target)
+PYTHON= python
+
+# Add more -I and -D options here
+CFLAGS= $(OPT) -I$(INCLUDEPY) -I$(EXECINCLUDEPY) $(DEFS)
+
+# These two variables can be set in Setup to merge extensions.
+# See example[23].
+BASELIB=
+BASESETUP=
+
+# === Variables set by makesetup ===
+
+MODOBJS= _MODOBJS_
+MODLIBS= _MODLIBS_
+
+# === Definitions added by makesetup ===
+
+# === Variables from configure (through sedscript) ===
+
+VERSION= @VERSION@
+CC= @CC@
+LINKCC= @LINKCC@
+SGI_ABI= @SGI_ABI@
+OPT= @OPT@
+LDFLAGS= @LDFLAGS@
+LDLAST= @LDLAST@
+DEFS= @DEFS@
+LIBS= @LIBS@
+LIBM= @LIBM@
+LIBC= @LIBC@
+RANLIB= @RANLIB@
+MACHDEP= @MACHDEP@
+SO= @SO@
+LDSHARED= @LDSHARED@
+CCSHARED= @CCSHARED@
+LINKFORSHARED= @LINKFORSHARED@
+#@SET_CCC@
+
+# Install prefix for architecture-independent files
+prefix= /usr/local
+
+# Install prefix for architecture-dependent files
+exec_prefix= $(prefix)
+
+# Uncomment the following two lines for AIX
+#LINKCC= $(LIBPL)/makexp_aix $(LIBPL)/python.exp "" $(LIBRARY); $(PURIFY) $(CC)
+#LDSHARED= $(LIBPL)/ld_so_aix $(CC) -bI:$(LIBPL)/python.exp
+
+# === Fixed definitions ===
+
+# Shell used by make (some versions default to the login shell, which is bad)
+SHELL= /bin/sh
+
+# Expanded directories
+BINDIR= $(exec_installdir)/bin
+LIBDIR= $(exec_prefix)/lib
+MANDIR= $(installdir)/man
+INCLUDEDIR= $(installdir)/include
+SCRIPTDIR= $(prefix)/lib
+
+# Detailed destination directories
+BINLIBDEST= $(LIBDIR)/python$(VERSION)
+LIBDEST= $(SCRIPTDIR)/python$(VERSION)
+INCLUDEPY= $(INCLUDEDIR)/python$(VERSION)
+EXECINCLUDEPY= $(exec_installdir)/include/python$(VERSION)
+LIBP= $(exec_installdir)/lib/python$(VERSION)
+DESTSHARED= $(BINLIBDEST)/site-packages
+
+LIBPL= $(LIBP)/config
+
+PYTHONLIBS= $(LIBPL)/libpython$(VERSION).a
+
+MAKESETUP= ./makesetup
+MAKEFILE= $(LIBPL)/Makefile
+CONFIGC= $(LIBPL)/config.c
+CONFIGCIN= $(LIBPL)/config.c.in
+SETUP= $(LIBPL)/Setup.thread $(LIBPL)/Setup.local $(LIBPL)/Setup
+
+SYSLIBS= $(LIBM) $(LIBC)
+
+ADDOBJS= $(LIBPL)/python.o config.o
+
+# Portable install script (configure doesn't always guess right)
+INSTALL= $(LIBPL)/install-sh -c
+# Shared libraries must be installed with executable mode on some systems;
+# rather than figuring out exactly which, we always give them executable mode.
+# Also, making them read-only seems to be a good idea...
+INSTALL_SHARED= ${INSTALL} -m 555
+
+# === Fixed rules ===
+
+# Default target. This builds shared libraries only
+default: sharedmods
+
+# Build everything
+all: static sharedmods
+
+# Build shared libraries from our extension modules
+sharedmods: $(SHAREDMODS)
+
+# Build a static Python binary containing our extension modules
+static: $(TARGET)
+$(TARGET): $(ADDOBJS) lib.a $(PYTHONLIBS) Makefile $(BASELIB)
+ $(LINKCC) $(LDFLAGS) $(LINKFORSHARED) \
+ $(ADDOBJS) lib.a $(PYTHONLIBS) \
+ $(LINKPATH) $(BASELIB) $(MODLIBS) $(LIBS) $(SYSLIBS) \
+ -o $(TARGET) $(LDLAST)
+
+install: sharedmods
+ if test ! -d $(DESTSHARED) ; then \
+ mkdir $(DESTSHARED) ; else true ; fi
+ -for i in X $(SHAREDMODS); do \
+ if test $$i != X; \
+ then $(INSTALL_SHARED) $$i $(DESTSHARED)/$$i; \
+ fi; \
+ done
+
+# Build the library containing our extension modules
+lib.a: $(MODOBJS)
+ -rm -f lib.a
+ ar cr lib.a $(MODOBJS)
+ -$(RANLIB) lib.a
+
+# This runs makesetup *twice* to use the BASESETUP definition from Setup
+config.c Makefile: Makefile.pre Setup $(BASESETUP) $(MAKESETUP)
+ $(MAKESETUP) \
+ -m Makefile.pre -c $(CONFIGCIN) Setup -n $(BASESETUP) $(SETUP)
+ $(MAKE) -f Makefile do-it-again
+
+# Internal target to run makesetup for the second time
+do-it-again:
+ $(MAKESETUP) \
+ -m Makefile.pre -c $(CONFIGCIN) Setup -n $(BASESETUP) $(SETUP)
+
+# Make config.o from the config.c created by makesetup
+config.o: config.c
+ $(CC) $(CFLAGS) -c config.c
+
+# Setup is copied from Setup.in *only* if it doesn't yet exist
+Setup:
+ cp $(srcdir)/Setup.in Setup
+
+# Make the intermediate Makefile.pre from Makefile.pre.in
+Makefile.pre: Makefile.pre.in sedscript
+ sed -f sedscript $(srcdir)/Makefile.pre.in >Makefile.pre
+
+# Shortcuts to make the sed arguments on one line
+P=prefix
+E=exec_prefix
+H=Generated automatically from Makefile.pre.in by sedscript.
+L=LINKFORSHARED
+
+# Make the sed script used to create Makefile.pre from Makefile.pre.in
+sedscript: $(MAKEFILE)
+ sed -n \
+ -e '1s/.*/1i\\/p' \
+ -e '2s%.*%# $H%p' \
+ -e '/^VERSION=/s/^VERSION=[ ]*\(.*\)/s%@VERSION[@]%\1%/p' \
+ -e '/^CC=/s/^CC=[ ]*\(.*\)/s%@CC[@]%\1%/p' \
+ -e '/^CCC=/s/^CCC=[ ]*\(.*\)/s%#@SET_CCC[@]%CCC=\1%/p' \
+ -e '/^LINKCC=/s/^LINKCC=[ ]*\(.*\)/s%@LINKCC[@]%\1%/p' \
+ -e '/^OPT=/s/^OPT=[ ]*\(.*\)/s%@OPT[@]%\1%/p' \
+ -e '/^LDFLAGS=/s/^LDFLAGS=[ ]*\(.*\)/s%@LDFLAGS[@]%\1%/p' \
+ -e '/^LDLAST=/s/^LDLAST=[ ]*\(.*\)/s%@LDLAST[@]%\1%/p' \
+ -e '/^DEFS=/s/^DEFS=[ ]*\(.*\)/s%@DEFS[@]%\1%/p' \
+ -e '/^LIBS=/s/^LIBS=[ ]*\(.*\)/s%@LIBS[@]%\1%/p' \
+ -e '/^LIBM=/s/^LIBM=[ ]*\(.*\)/s%@LIBM[@]%\1%/p' \
+ -e '/^LIBC=/s/^LIBC=[ ]*\(.*\)/s%@LIBC[@]%\1%/p' \
+ -e '/^RANLIB=/s/^RANLIB=[ ]*\(.*\)/s%@RANLIB[@]%\1%/p' \
+ -e '/^MACHDEP=/s/^MACHDEP=[ ]*\(.*\)/s%@MACHDEP[@]%\1%/p' \
+ -e '/^SO=/s/^SO=[ ]*\(.*\)/s%@SO[@]%\1%/p' \
+ -e '/^LDSHARED=/s/^LDSHARED=[ ]*\(.*\)/s%@LDSHARED[@]%\1%/p' \
+ -e '/^CCSHARED=/s/^CCSHARED=[ ]*\(.*\)/s%@CCSHARED[@]%\1%/p' \
+ -e '/^SGI_ABI=/s/^SGI_ABI=[ ]*\(.*\)/s%@SGI_ABI[@]%\1%/p' \
+ -e '/^$L=/s/^$L=[ ]*\(.*\)/s%@$L[@]%\1%/p' \
+ -e '/^$P=/s/^$P=\(.*\)/s%^$P=.*%$P=\1%/p' \
+ -e '/^$E=/s/^$E=\(.*\)/s%^$E=.*%$E=\1%/p' \
+ $(MAKEFILE) >sedscript
+ echo "/^#@SET_CCC@/d" >>sedscript
+ echo "/^installdir=/s%=.*%= $(installdir)%" >>sedscript
+ echo "/^exec_installdir=/s%=.*%=$(exec_installdir)%" >>sedscript
+ echo "/^srcdir=/s%=.*%= $(srcdir)%" >>sedscript
+ echo "/^VPATH=/s%=.*%= $(VPATH)%" >>sedscript
+ echo "/^LINKPATH=/s%=.*%= $(LINKPATH)%" >>sedscript
+ echo "/^BASELIB=/s%=.*%= $(BASELIB)%" >>sedscript
+ echo "/^BASESETUP=/s%=.*%= $(BASESETUP)%" >>sedscript
+
+# Bootstrap target
+boot: clobber
+ VERSION=`$(PYTHON) -c "import sys; print sys.version[:3]"`; \
+ installdir=`$(PYTHON) -c "import sys; print sys.prefix"`; \
+ exec_installdir=`$(PYTHON) -c "import sys; print sys.exec_prefix"`; \
+ $(MAKE) -f $(srcdir)/Makefile.pre.in VPATH=$(VPATH) srcdir=$(srcdir) \
+ VERSION=$$VERSION \
+ installdir=$$installdir \
+ exec_installdir=$$exec_installdir \
+ Makefile
+
+# Handy target to remove intermediate files and backups
+clean:
+ -rm -f *.o *~
+
+# Handy target to remove everything that is easily regenerated
+clobber: clean
+ -rm -f *.a tags TAGS config.c Makefile.pre $(TARGET) sedscript
+ -rm -f *.so *.sl so_locations
+
+
+# Handy target to remove everything you don't want to distribute
+distclean: clobber
+ -rm -f Makefile Setup
diff --git a/wlp/module/Setup.in b/wlp/module/Setup.in
new file mode 100644
index 0000000..18cce4d
--- /dev/null
+++ b/wlp/module/Setup.in
@@ -0,0 +1,88 @@
+# -*- makefile -*-
+# The file Setup is used by the makesetup script to construct the files
+# Makefile and config.c, from Makefile.pre and config.c.in,
+# respectively. The file Setup itself is initially copied from
+# Setup.in; once it exists it will not be overwritten, so you can edit
+# Setup to your heart's content. Note that Makefile.pre is created
+# from Makefile.pre.in by the toplevel configure script.
+
+# (VPATH notes: Setup and Makefile.pre are in the build directory, as
+# are Makefile and config.c; the *.in files are in the source
+# directory.)
+
+# Each line in this file describes one or more optional modules.
+# Comment out lines to suppress modules.
+# Lines have the following structure:
+#
+# <module> ... [<sourcefile> ...] [<cpparg> ...] [<library> ...]
+
+# <sourcefile> is anything ending in .c (.C, .cc, .c++ are C++ files)
+# <cpparg> is anything starting with -I, -D, -U or -C
+# <library> is anything ending in .a or beginning with -l or -L
+# <module> is anything else but should be a valid Python
+# identifier (letters, digits, underscores, beginning with non-digit)
+#
+# (As the makesetup script changes, it may recognize some other
+# arguments as well, e.g. *.so and *.sl as libraries. See the big
+# case statement in the makesetup script.)
+#
+# Lines can also have the form
+#
+# <name> = <value>
+#
+# which defines a Make variable definition inserted into Makefile.in
+#
+# Finally, if a line contains just the word "*shared*" (without the
+# quotes but with the stars), then the following modules will not be
+# included in the config.c file, nor in the list of objects to be
+# added to the library archive, and their linker options won't be
+# added to the linker options, but rules to create their .o files and
+# their shared libraries will still be added to the Makefile, and
+# their names will be collected in the Make variable SHAREDMODS. This
+# is used to build modules as shared libraries. (They can be
+# installed using "make sharedinstall", which is implied by the
+# toplevel "make install" target.) (For compatibility,
+# *noconfig* has the same effect as *shared*.)
+#
+# In addition, *static* reverses this effect (negating a previous
+# *shared* line).
+
+# NOTE: As a standard policy, as many modules as can be supported by a
+# platform should be present. The distribution comes with all modules
+# enabled that are supported by most platforms and don't require you
+# to ftp sources from elsewhere.
+
+*static*
+# Some special rules to define PYTHONPATH.
+# Edit the definitions below to indicate which options you are using.
+# Don't add any whitespace or comments!
+
+# Directories where library files get installed.
+# DESTLIB is for Python modules; MACHDESTLIB for shared libraries.
+DESTLIB=$(LIBDEST)
+MACHDESTLIB=$(BINLIBDEST)
+
+# NOTE: all the paths are now relative to the prefix that is computed
+# at run time!
+
+# Standard path -- don't edit.
+# No leading colon since this is the first entry.
+# Empty since this is now just the runtime prefix.
+DESTPATH=
+
+# Site specific path components -- should begin with : if non-empty
+SITEPATH=
+
+# Standard path components for test modules
+TESTPATH=
+
+# Path components for machine- or system-dependent modules and shared libraries
+MACHDEPPATH=:plat-$(MACHDEP)
+
+COREPYTHONPATH=$(DESTPATH)$(SITEPATH)$(MACHDEPPATH)$(STDWINPATH)$(TKPATH)
+PYTHONPATH=$(COREPYTHONPATH)
+
+*shared*
+
+WLPSRCDIR=../C
+wlp $(WLPSRCDIR)/wlp.c $(WLPSRCDIR)/wlp.a
diff --git a/wlp/module/makesetup b/wlp/module/makesetup
new file mode 100755
index 0000000..0fefcff
--- /dev/null
+++ b/wlp/module/makesetup
@@ -0,0 +1,261 @@
+#! /bin/sh
+
+# Convert templates into Makefile and config.c, based on the module
+# definitions found in the file Setup.
+#
+# Usage: makesetup [-s dir] [-c file] [-m file] [Setup] ... [-n [Setup] ...]
+#
+# Options:
+# -s directory: alternative source directory (default derived from $0)
+# -c file: alternative config.c template (default $srcdir/config.c.in)
+# -c -: don't write config.c
+# -m file: alternative Makefile template (default ./Makefile.pre)
+# -m -: don't write Makefile
+#
+# Remaining arguments are one or more Setup files (default ./Setup).
+# Setup files after a -n option are used for their variables, modules
+# and libraries but not for their .o files.
+#
+# See Setup.in for a description of the format of the Setup file.
+#
+# The following edits are made:
+#
+# Copying config.c.in to config.c:
+# - insert an identifying comment at the start
+# - for each <module> mentioned in Setup before *noconfig*:
+# + insert 'extern void init<module>();' before MARKER 1
+# + insert '{"<module>", initmodule},' before MARKER 2
+#
+# Copying Makefile.pre to Makefile:
+# - insert an identifying comment at the start
+# - replace _MODOBJS_ by the list of objects from Setup (except for
+# Setup files after a -n option)
+# - replace _MODLIBS_ by the list of libraries from Setup
+# - for each object file mentioned in Setup, append a rule
+# '<file>.o: <file>.c; <build commands>' to the end of the Makefile
+# - for each module mentioned in Setup, append a rule
+# which creates a shared library version to the end of the Makefile
+# - for each variable definition found in Setup, insert the definition
+# before the comment 'Definitions added by makesetup'
+
+# Loop over command line options
+usage='
+usage: makesetup [-s srcdir] [-c config.c.in] [-m Makefile.pre]
+ [Setup] ... [-n [Setup] ...]'
+srcdir=''
+config=''
+makepre=''
+noobjects=''
+doconfig=yes
+while :
+do
+ case $1 in
+ -s) shift; srcdir=$1; shift;;
+ -c) shift; config=$1; shift;;
+ -m) shift; makepre=$1; shift;;
+ --) shift; break;;
+ -n) noobjects=yes;;
+ -*) echo "$usage" 1>&2; exit 2;;
+ *) break;;
+ esac
+done
+
+# Set default srcdir and config if not set by command line
+# (Not all systems have dirname)
+case $srcdir in
+'') case $0 in
+ */*) srcdir=`echo $0 | sed 's,/[^/]*$,,'`;;
+ *) srcdir=.;;
+ esac;;
+esac
+case $config in
+'') config=$srcdir/config.c.in;;
+esac
+case $makepre in
+'') makepre=Makefile.pre;;
+esac
+
+# Newline for sed i and a commands
+NL='\
+'
+
+# Main loop
+for i in ${*-Setup}
+do
+ case $i in
+ -n) echo '*noobjects*';;
+ *) echo '*doconfig*'; cat "$i";;
+ esac
+done |
+sed -e 's/[ ]*#.*//' -e '/^[ ]*$/d' |
+(
+ rulesf="@rules.$$"
+ trap 'rm -f $rulesf' 0 1 2 3
+ echo "
+# Rules appended by makedepend
+" >$rulesf
+ DEFS=
+ MODS=
+ SHAREDMODS=
+ OBJS=
+ LIBS=
+ LOCALLIBS=
+ BASELIBS=
+ while read line
+ do
+ # Output DEFS in reverse order so first definition overrides
+ case $line in
+ *=*) DEFS="$line$NL$DEFS"; continue;;
+ 'include '*) DEFS="$line$NL$DEFS"; continue;;
+ '*noobjects*')
+ case $noobjects in
+ yes) ;;
+ *) LOCALLIBS=$LIBS; LIBS=;;
+ esac
+ noobjects=yes;
+ continue;;
+ '*doconfig*') doconfig=yes; continue;;
+ '*static*') doconfig=yes; continue;;
+ '*noconfig*') doconfig=no; continue;;
+ '*shared*') doconfig=no; continue;;
+ esac
+ srcs=
+ cpps=
+ libs=
+ mods=
+ skip=
+ for arg in $line
+ do
+ case $skip in
+ libs) libs="$libs $arg"; skip=; continue;;
+ cpps) cpps="$cpps $arg"; skip=; continue;;
+ srcs) srcs="$srcs $arg"; skip=; continue;;
+ esac
+ case $arg in
+ -[IDUC]*) cpps="$cpps $arg";;
+ -Xlinker) libs="$libs $arg"; skip=libs;;
+ -[A-Zl]*) libs="$libs $arg";;
+ *.a) libs="$libs $arg";;
+ *.so) libs="$libs $arg";;
+ *.sl) libs="$libs $arg";;
+ /*.o) libs="$libs $arg";;
+ *.o) srcs="$srcs `basename $arg .o`.c";;
+ *.[cC]) srcs="$srcs $arg";;
+ *.cc) srcs="$srcs $arg";;
+ *.c++) srcs="$srcs $arg";;
+ *.cxx) srcs="$srcs $arg";;
+ *.cpp) srcs="$srcs $arg";;
+ \$*) libs="$libs $arg"
+ cpps="$cpps $arg";;
+ *.*) echo 1>&2 "bad word $arg in $line"
+ exit 1;;
+ -u) skip=libs; libs="$libs -u";;
+ [a-zA-Z_]*) mods="$mods $arg";;
+ *) echo 1>&2 "bad word $arg in $line"
+ exit 1;;
+ esac
+ done
+ case $doconfig in
+ yes)
+ LIBS="$LIBS $libs"
+ MODS="$MODS $mods"
+ ;;
+ esac
+ case $noobjects in
+ yes) continue;;
+ esac
+ objs=''
+ for src in $srcs
+ do
+ case $src in
+ *.c) obj=`basename $src .c`.o; cc='$(CC)';;
+ *.cc) obj=`basename $src .cc`.o; cc='$(CCC)';;
+ *.c++) obj=`basename $src .c++`.o; cc='$(CCC)';;
+ *.C) obj=`basename $src .C`.o; cc='$(CCC)';;
+ *.cxx) obj=`basename $src .cxx`.o; cc='$(CCC)';;
+ *.cpp) obj=`basename $src .cpp`.o; cc='$(CCC)';;
+ *) continue;;
+ esac
+ objs="$objs $obj"
+ case $src in
+ glmodule.c) ;;
+ /*) ;;
+ *) src='$(srcdir)/'$src;;
+ esac
+ case $doconfig in
+ no) cc="$cc \$(CCSHARED)";;
+ esac
+ rule="$obj: $src; $cc $cpps \$(CFLAGS) -c $src"
+ echo "$rule" >>$rulesf
+ done
+ case $doconfig in
+ yes) OBJS="$OBJS $objs";;
+ esac
+ for mod in $mods
+ do
+ case $objs in
+ *$mod.o*) base=$mod;;
+ *) base=${mod}module;;
+ esac
+ file="$base\$(SO)"
+ case $doconfig in
+ no) SHAREDMODS="$SHAREDMODS $file";;
+ esac
+ rule="$file: $objs"
+ rule="$rule; \$(LDSHARED) $objs $libs -o $file"
+ echo "$rule" >>$rulesf
+ done
+ done
+
+ case $SHAREDMODS in
+ '') ;;
+ *) DEFS="SHAREDMODS=$SHAREDMODS$NL$DEFS";;
+ esac
+
+ case $noobjects in
+ yes) BASELIBS=$LIBS;;
+ *) LOCALLIBS=$LIBS;;
+ esac
+ LIBS='$(LOCALMODLIBS) $(BASEMODLIBS)'
+ DEFS="BASEMODLIBS=$BASELIBS$NL$DEFS"
+ DEFS="LOCALMODLIBS=$LOCALLIBS$NL$DEFS"
+
+ EXTDECLS=
+ INITBITS=
+ for mod in $MODS
+ do
+ EXTDECLS="${EXTDECLS}extern void init$mod();$NL"
+ INITBITS="${INITBITS} {\"$mod\", init$mod},$NL"
+ done
+
+
+ case $config in
+ -) ;;
+ *) sed -e "
+ 1i$NL/* Generated automatically from $config by makesetup. */
+ /MARKER 1/i$NL$EXTDECLS
+
+ /MARKER 2/i$NL$INITBITS
+
+ " $config >config.c
+ ;;
+ esac
+
+ case $makepre in
+ -) ;;
+ *) sedf="@sed.in.$$"
+ trap 'rm -f $sedf' 0 1 2 3
+ echo "1i\\" >$sedf
+ str="# Generated automatically from $makepre by makesetup."
+ echo "$str" >>$sedf
+ echo "s%_MODOBJS_%$OBJS%" >>$sedf
+ echo "s%_MODLIBS_%$LIBS%" >>$sedf
+ echo "/Definitions added by makesetup/a$NL$NL$DEFS" >>$sedf
+ sed -f $sedf $makepre >Makefile
+ cat $rulesf >>Makefile
+ rm -f $sedf
+ ;;
+ esac
+
+ rm -f $rulesf
+)
diff --git a/wlp_test b/wlp_test
new file mode 100755
index 0000000..5ccea1c
--- /dev/null
+++ b/wlp_test
@@ -0,0 +1,31 @@
+#!/usr/bin/python
+
+# Script to test if wlp.so works. It should parse confile without errors.
+
+import sys
+import wlp
+
+if(len(sys.argv) == 1):
+ wlp.setfilebyname('./pyg.wl')
+else:
+ wlp.setfilebyname(sys.argv[1])
+
+# dict is a { ownername : {variable: value}} dictionary of dictionaries
+dict = wlp.mkdict()
+
+try:
+ print 'owner: option = value'
+
+ for owner in dict.keys():
+ options = dict[owner]
+ for option in options.keys():
+ print '%s: %s = %s' % (owner,option,options[option])
+except (Exception), message:
+ print message
+
+
+for k in dict.keys():
+ if(dict[k]['From:'] == 'Cosimo Alfarano'):
+ print '%s has %s' % (k,dict[k]['From:'])
+
+sys.exit(0)