From f9ba1fdb262bbe8235d1766f2a5f481e08196a8f Mon Sep 17 00:00:00 2001 From: lars Date: Mon, 2 Jan 2006 23:00:48 +0000 Subject: [PATCH] added tags for 0.06 and 0.07 --- .../{Ezmlm-0.0.5.1 => Ezmlm-0.05.1}/Changes | 0 .../{Ezmlm-0.0.5.1 => Ezmlm-0.05.1}/Ezmlm.pm | 0 .../{Ezmlm-0.0.5.1 => Ezmlm-0.05.1}/MANIFEST | 0 .../{Ezmlm-0.0.5.1 => Ezmlm-0.05.1}/META.yml | 0 .../Makefile.PL | 0 .../{Ezmlm-0.0.5.1 => Ezmlm-0.05.1}/README | 0 .../{Ezmlm-0.0.5.1 => Ezmlm-0.05.1}/test.pl | 0 Ezmlm/tags/Ezmlm-0.06/Changes | 35 + Ezmlm/tags/Ezmlm-0.06/Ezmlm.pm | 870 ++++++++++++++++++ Ezmlm/tags/Ezmlm-0.06/MANIFEST | 7 + Ezmlm/tags/Ezmlm-0.06/META.yml | 10 + Ezmlm/tags/Ezmlm-0.06/Makefile.PL | 119 +++ Ezmlm/tags/Ezmlm-0.06/README | 22 + Ezmlm/tags/Ezmlm-0.06/test.pl | 140 +++ Ezmlm/tags/make-tar.sh | 15 + Ezmlm/tags/packages/Ezmlm-0.06.tar.gz | Bin 0 -> 12381 bytes Ezmlm/tags/packages/Ezmlm-0.07.tar.gz | Bin 0 -> 14411 bytes 17 files changed, 1218 insertions(+) rename Ezmlm/tags/{Ezmlm-0.0.5.1 => Ezmlm-0.05.1}/Changes (100%) rename Ezmlm/tags/{Ezmlm-0.0.5.1 => Ezmlm-0.05.1}/Ezmlm.pm (100%) rename Ezmlm/tags/{Ezmlm-0.0.5.1 => Ezmlm-0.05.1}/MANIFEST (100%) rename Ezmlm/tags/{Ezmlm-0.0.5.1 => Ezmlm-0.05.1}/META.yml (100%) rename Ezmlm/tags/{Ezmlm-0.0.5.1 => Ezmlm-0.05.1}/Makefile.PL (100%) rename Ezmlm/tags/{Ezmlm-0.0.5.1 => Ezmlm-0.05.1}/README (100%) rename Ezmlm/tags/{Ezmlm-0.0.5.1 => Ezmlm-0.05.1}/test.pl (100%) create mode 100644 Ezmlm/tags/Ezmlm-0.06/Changes create mode 100644 Ezmlm/tags/Ezmlm-0.06/Ezmlm.pm create mode 100644 Ezmlm/tags/Ezmlm-0.06/MANIFEST create mode 100644 Ezmlm/tags/Ezmlm-0.06/META.yml create mode 100644 Ezmlm/tags/Ezmlm-0.06/Makefile.PL create mode 100644 Ezmlm/tags/Ezmlm-0.06/README create mode 100644 Ezmlm/tags/Ezmlm-0.06/test.pl create mode 100755 Ezmlm/tags/make-tar.sh create mode 100644 Ezmlm/tags/packages/Ezmlm-0.06.tar.gz create mode 100644 Ezmlm/tags/packages/Ezmlm-0.07.tar.gz diff --git a/Ezmlm/tags/Ezmlm-0.0.5.1/Changes b/Ezmlm/tags/Ezmlm-0.05.1/Changes similarity index 100% rename from Ezmlm/tags/Ezmlm-0.0.5.1/Changes rename to Ezmlm/tags/Ezmlm-0.05.1/Changes diff --git a/Ezmlm/tags/Ezmlm-0.0.5.1/Ezmlm.pm b/Ezmlm/tags/Ezmlm-0.05.1/Ezmlm.pm similarity index 100% rename from Ezmlm/tags/Ezmlm-0.0.5.1/Ezmlm.pm rename to Ezmlm/tags/Ezmlm-0.05.1/Ezmlm.pm diff --git a/Ezmlm/tags/Ezmlm-0.0.5.1/MANIFEST b/Ezmlm/tags/Ezmlm-0.05.1/MANIFEST similarity index 100% rename from Ezmlm/tags/Ezmlm-0.0.5.1/MANIFEST rename to Ezmlm/tags/Ezmlm-0.05.1/MANIFEST diff --git a/Ezmlm/tags/Ezmlm-0.0.5.1/META.yml b/Ezmlm/tags/Ezmlm-0.05.1/META.yml similarity index 100% rename from Ezmlm/tags/Ezmlm-0.0.5.1/META.yml rename to Ezmlm/tags/Ezmlm-0.05.1/META.yml diff --git a/Ezmlm/tags/Ezmlm-0.0.5.1/Makefile.PL b/Ezmlm/tags/Ezmlm-0.05.1/Makefile.PL similarity index 100% rename from Ezmlm/tags/Ezmlm-0.0.5.1/Makefile.PL rename to Ezmlm/tags/Ezmlm-0.05.1/Makefile.PL diff --git a/Ezmlm/tags/Ezmlm-0.0.5.1/README b/Ezmlm/tags/Ezmlm-0.05.1/README similarity index 100% rename from Ezmlm/tags/Ezmlm-0.0.5.1/README rename to Ezmlm/tags/Ezmlm-0.05.1/README diff --git a/Ezmlm/tags/Ezmlm-0.0.5.1/test.pl b/Ezmlm/tags/Ezmlm-0.05.1/test.pl similarity index 100% rename from Ezmlm/tags/Ezmlm-0.0.5.1/test.pl rename to Ezmlm/tags/Ezmlm-0.05.1/test.pl diff --git a/Ezmlm/tags/Ezmlm-0.06/Changes b/Ezmlm/tags/Ezmlm-0.06/Changes new file mode 100644 index 0000000..3dbb064 --- /dev/null +++ b/Ezmlm/tags/Ezmlm-0.06/Changes @@ -0,0 +1,35 @@ +$Id: Changes,v 1.5 2005/03/05 14:14:27 guy Exp $ + +Revision history for Perl extension Mail::Ezmlm. + +0.01 Sun Oct 31 12:58:16 1999 + - original version; created by h2xs 1.1.1.1.2.1 + +0.02 Wed Jan 26 07:59:10 SAST 2000 + - Added functions to check various options + (ismodsub, ismodpost, isremote, isdeny, isallow, isdigest) + - Allowed sub, unsub, list, subscribers, issub to work with list subparts + (ie, the allow, deny, mod, digest sub directories) + - Changed system() calls to safer ones (ie command, switches) + - Made error handling better (errmsg() and errno()) + - Added support for creating MySQL tables via ezmlm-mktab + +0.03 Mon Sep 25 11:49:26 SAST 2000 + - fixed the issub() function + - fixed the problem with dashes in hostnames. + - hopefully got rid of some of the warnings from sub() and unsub() + +0.04 Mon May 26 18:15:38 SAST 2003 + - fixed return value of Makefile.PL (Andrew Pam ) + - fixed issub() (again) to handle parts properly (bug 602; moguo@servism.com) + - converted module global variables to instance variables + +0.05 Sat Mar 5 12:47:10 SAST 2005 + - fixed forced scalar return in subscribers() (Jon Coulter ) + - fixed handling of dashes in hostnames (bug 5571; Lars Braeuer ) + - fixed some tainting problems (Scott Beck and Matt Simerson ) + - fixed order of control/defaulthost and control/me (bug 1515) + - fixed a bug in Makefile.PL (bug 11771). does not affect most users, so released as 0.05.1 + +0.06 Mon Dec 26 18:55:12 CET 2005 + - support for ezmlm-idx-5.0.0 added diff --git a/Ezmlm/tags/Ezmlm-0.06/Ezmlm.pm b/Ezmlm/tags/Ezmlm-0.06/Ezmlm.pm new file mode 100644 index 0000000..fe55e08 --- /dev/null +++ b/Ezmlm/tags/Ezmlm-0.06/Ezmlm.pm @@ -0,0 +1,870 @@ +# =========================================================================== +# Ezmlm.pm - version 0.04 - 26/05/2003 +# $Id: Ezmlm.pm,v 1.10 2005/03/05 14:11:11 guy Exp $ +# +# Object methods for ezmlm mailing lists +# +# Copyright (C) 1999-2005, Guy Antony Halse, All Rights Reserved. +# Please send bug reports and comments to guy@rucus.ru.ac.za +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# Neither name Guy Antony Halse nor the names of any contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS +# IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +# ========================================================================== +# POD is at the end of this file. Search for '=head' to find it +package Mail::Ezmlm; + +use strict; +use vars qw($QMAIL_BASE $EZMLM_BASE $MYSQL_BASE $VERSION @ISA @EXPORT @EXPORT_OK); +use Carp; + +require Exporter; + +@ISA = qw(Exporter); +# Items to export into callers namespace by default. Note: do not export +# names by default without a very good reason. Use EXPORT_OK instead. +# Do not simply export all your public functions/methods/constants. +@EXPORT = qw( + +); +$VERSION = '0.06'; + +require 5.005; + +# == Begin site dependant variables == +$EZMLM_BASE = '/usr/local/bin'; #Autoinserted by Makefile.PL +$QMAIL_BASE = '/var/qmail'; #Autoinserted by Makefile.PL +$MYSQL_BASE = ''; #Autoinserted by Makefile.PL +# == End site dependant variables == + +use Carp; + +# == clean up the path for taint checking == +local $ENV{'PATH'} = $EZMLM_BASE; + +# == Initialiser - Returns a reference to the object == +sub new { + my($class, $list) = @_; + my $self = {}; + bless $self, ref $class || $class || 'Mail::Ezmlm'; + $self->setlist($list) if(defined($list) && $list); + return $self; +} + +# == Make a new mailing list and set it to current == +sub make { + my($self, %list) = @_; + my($VHOST, $comandline, $hostname); + + # Do we want to use command line switches + my $commandline = ''; + $commandline = '-' . $list{'-switches'} if(defined($list{'-switches'})); + my @commandline; + # UGLY! + foreach (split(/["'](.+?)["']|(\s-\w+)/, $commandline)) { + next if (!defined($_) or !$_ or $_ eq ' '); + push @commandline, $_; + } + + # These three variables are essential + ($self->_seterror(-1, 'must define -dir in a make()') && return 0) unless(defined($list{'-dir'})); + ($self->_seterror(-1, 'must define -qmail in a make()') && return 0) unless(defined($list{'-qmail'})); + ($self->_seterror(-1, 'must define -name in a make()') && return 0) unless(defined($list{'-name'})); + + # Determine hostname if it is not supplied + $hostname = $self->_getdefaultdomain; + if(defined($list{'-host'})) { + $VHOST = 1 unless ($list{'-host'} eq $hostname); + } else { + $list{'-host'} = $hostname; + } + + # Attempt to make the list if we can. + unless(-e $list{'-dir'}) { + system("$EZMLM_BASE/ezmlm-make", @commandline, $list{'-dir'}, $list{'-qmail'}, $list{'-name'}, $list{'-host'}) == 0 + || ($self->_seterror($?) && return undef); + } else { + ($self->_seterror(-1, '-dir must be defined in make()') && return 0); + } + + # Sort out the DIR/inlocal problem if necessary + if(defined($VHOST)) { + unless(defined($list{'-user'})) { + ($self->_seterror(-1, '-user must match virtual host user in make()') && return 0) unless($list{'-user'} = $self->_getvhostuser($list{'-host'})); + } + + open(INLOCAL, ">$list{'-dir'}/inlocal") || ($self->_seterror(-1, 'unable to read inlocal in make()') && return 0); + print INLOCAL $list{'-user'} . '-' . $list{'-name'} . "\n"; + close INLOCAL; + } + + $self->_seterror(undef); + return $self->setlist($list{'-dir'}); +} + +# == Update the current list == +sub update { + my($self, $switches) = @_; + my($outhost, $inlocal); + + # Do we have the command line switches + ($self->_seterror(-1, 'nothing to update()') && return 0) unless(defined($switches)); + $switches = '-e' . $switches; + my @switches; + + # UGLY! + foreach (split(/["'](.+?)["']|(-\w+)/, $switches)) { + next if (!defined($_) or !$_ or $_ eq ' '); + # untaint input + $_ =~ m/^([\w _\/,\.@:'"-]*)$/; + push @switches, $1; + } + + # can we actually alter this list; + ($self->_seterror(-1, 'must setlist() before you update()') && return 0) unless(defined($self->{'LIST_NAME'})); + # check for important files: 'config' (idx < v5.0) or 'flags' (idx >= 5.0) + ($self->_seterror(-1, "$self->{'LIST_NAME'} does not appear to be a valid list in update()") && return 0) unless((-e "$self->{'LIST_NAME'}/config") || (-e "$self->{'LIST_NAME'}/flags")); + + # Work out if this is a vhost. + open(OUTHOST, "<$self->{'LIST_NAME'}/outhost") || ($self->_seterror(-1, 'unable to read outhost in update()') && return 0); + chomp($outhost = ); + close(OUTHOST); + + # Save the contents of inlocal if it is a vhost + unless($outhost eq $self->_getdefaultdomain) { + open(INLOCAL, "<$self->{'LIST_NAME'}/inlocal") || ($self->_seterror(-1, 'unable to read inlocal in update()') && return 0); + chomp($inlocal = ); + close(INLOCAL); + } + + # Attempt to update the list if we can. + system("$EZMLM_BASE/ezmlm-make", @switches, $self->{'LIST_NAME'}) == 0 + || ($self->_seterror($?) && return undef); + + # Sort out the DIR/inlocal problem if necessary + if(defined($inlocal)) { + open(INLOCAL, ">$self->{'LIST_NAME'}/inlocal") || ($self->_seterror(-1, 'unable to write inlocal in update()') && return 0); + print INLOCAL "$inlocal\n"; + close INLOCAL; + } + + $self->_seterror(undef); + return $self->{'LIST_NAME'}; +} + +# == Get a list of options for the current list == +sub getconfig { + my($self) = @_; + my($options); + + # Read the config file + if(-e "$self->{'LIST_NAME'}/flags") { + # this file exists since ezmlm-idx-5.0.0 + # 'config' is not authorative anymore since that version + $options = $self->_getconfig_idx5(); + } elsif(open(CONFIG, "<$self->{'LIST_NAME'}/config")) { + # 'config' contains the authorative information + while() { + if (/^F:-(\w+)/) { + $options = $1; + } elsif (/^(\d):(.+)$/) { + $options .= " -$1 '$2'"; + } + } + close CONFIG; + } else { + # Try manually - this will ignore all string settings, that can only be found + # in the config file + $options = $self->_getconfigmanual(); + } + + ($self->_seterror(-1, 'unable to read configuration in getconfig()') && return undef) unless (defined($options)); + + $self->_seterror(undef); + return $options; +} + +# == Return the name of the current list == +sub thislist { + my($self) = shift; + $self->_seterror(undef); + return $self->{'LIST_NAME'}; +} + +# == Set the current mailing list == +sub setlist { + my($self, $list) = @_; + if ($list =~ m/^([\w\d\_\-\.\/]+)$/) { + $list = $1; + if (-e "$list/lock") { + $self->_seterror(undef); + return $self->{'LIST_NAME'} = $list; + } else { + $self->_seterror(-1, "$list does not appear to be a valid list in setlist()"); + return undef; + } + } else { + $self->_seterror(-1, "$list contains tainted data in setlist()"); + return undef; + } +} + +# == Output the subscribers to $stream == +sub list { + my($self, $stream, $part) = @_; + $stream = *STDOUT unless (defined($stream)); + if(defined($part)) { + print $stream $self->subscribers($part); + } else { + print $stream $self->subscribers; + } +} + +# == Return an array of subscribers == +sub subscribers { + my($self, $part) = @_; + my(@subscribers); + ($self->_seterror(-1, 'must setlist() before returning subscribers()') && return undef) unless(defined($self->{'LIST_NAME'})); + if(defined($part) && $part) { + ($self->_seterror(-1, "$part part of $self->{'LIST_NAME'} does not appear to exist in subscribers()") && return undef) unless(-e "$self->{'LIST_NAME'}/$part"); + @subscribers = map { s/[\r\n]// && $_ } sort `$EZMLM_BASE/ezmlm-list $self->{'LIST_NAME'}/$part`; + } else { + @subscribers = map { s/[\r\n]// && $_ } sort `$EZMLM_BASE/ezmlm-list $self->{'LIST_NAME'}`; + } + + if($?) { + $self->_seterror($?, 'error during ezmlm-list in subscribers()'); + return (scalar @subscribers ? @subscribers : undef); + } else { + $self->_seterror(undef); + return @subscribers; + } +} + +# == Subscribe users to the current list == +sub sub { + my($self, @addresses) = @_; + ($self->_seterror(-1, 'sub() must be called with at least one address') && return 0) unless @addresses; + my($part) = pop @addresses unless ($#addresses < 1 or $addresses[$#addresses] =~ /\@/); + my($address); + ($self->_seterror(-1, 'must setlist() before sub()') && return 0) unless(defined($self->{'LIST_NAME'})); + + if(defined($part) && $part) { + ($self->_seterror(-1, "$part of $self->{'LIST_NAME'} does not appear to exist in sub()") && return 0) unless(-e "$self->{'LIST_NAME'}/$part"); + foreach $address (@addresses) { + next unless $self->_checkaddress($address); + system("$EZMLM_BASE/ezmlm-sub", "$self->{'LIST_NAME'}/$part", $address) == 0 || + ($self->_seterror($?) && return undef); + } + } else { + foreach $address (@addresses) { + next unless $self->_checkaddress($address); + system("$EZMLM_BASE/ezmlm-sub", $self->{'LIST_NAME'}, $address) == 0 || + ($self->_seterror($?) && return undef); + } + } + $self->_seterror(undef); + return 1; +} + +# == Unsubscribe users from a list == +sub unsub { + my($self, @addresses) = @_; + ($self->_seterror(-1, 'unsub() must be called with at least one address') && return 0) unless @addresses; + my($part) = pop @addresses unless ($#addresses < 1 or $addresses[$#addresses] =~ /\@/); + my($address); + ($self->_seterror(-1, 'must setlist() before unsub()') && return 0) unless(defined($self->{'LIST_NAME'})); + + if(defined($part) && $part) { + ($self->_seterror(-1, "$part of $self->{'LIST_NAME'} does not appear to exist in unsub()") && return 0) unless(-e "$self->{'LIST_NAME'}/$part"); + foreach $address (@addresses) { + next unless $self->_checkaddress($address); + system("$EZMLM_BASE/ezmlm-unsub", "$self->{'LIST_NAME'}/$part", $address) == 0 || + ($self->_seterror($?) && return undef); + } + } else { + foreach $address (@addresses) { + next unless $self->_checkaddress($address); + system("$EZMLM_BASE/ezmlm-unsub", $self->{'LIST_NAME'}, $address) == 0 || + ($self->_seterror($?) && return undef); + } + } + $self->_seterror(undef); + return 1; +} + +# == Test whether people are subscribed to the list == +sub issub { + my($self, @addresses) = @_; + my($part) = pop @addresses unless ($#addresses < 1 or $addresses[$#addresses] =~ /\@/); + my($address, $issub); $issub = 1; + ($self->_seterror(-1, 'must setlist() before issub()') && return 0) unless(defined($self->{'LIST_NAME'})); + + local $ENV{'SENDER'}; + + if(defined($part) && $part) { + ($self->_seterror(-1, "$part of $self->{'LIST_NAME'} does not appear to exist in issub()") && return 0) unless(-e "$self->{'LIST_NAME'}/$part"); + foreach $address (@addresses) { + $ENV{'SENDER'} = $address; + undef($issub) if ((system("$EZMLM_BASE/ezmlm-issubn", "$self->{'LIST_NAME'}/$part") / 256) != 0) + } + } else { + foreach $address (@addresses) { + $ENV{'SENDER'} = $address; + undef($issub) if ((system("$EZMLM_BASE/ezmlm-issubn", $self->{'LIST_NAME'}) / 256) != 0) + } + } + + $self->_seterror(undef); + return $issub; +} + +# == Is the list posting moderated == +sub ismodpost { + my($self) = @_; + ($self->_seterror(-1, 'must setlist() before ismodpost()') && return 0) unless(defined($self->{'LIST_NAME'})); + $self->_seterror(undef); + return -e "$self->{'LIST_NAME'}/modpost"; +} + +# == Is the list subscriber moderated == +sub ismodsub { + my($self) = @_; + ($self->_seterror(-1, 'must setlist() before ismodsub()') && return 0) unless(defined($self->{'LIST_NAME'})); + $self->_seterror(undef); + return -e "$self->{'LIST_NAME'}/modsub"; +} + +# == Is the list remote adminable == +sub isremote { + my($self) = @_; + ($self->_seterror(-1, 'must setlist() before isremote()') && return 0) unless(defined($self->{'LIST_NAME'})); + $self->_seterror(undef); + return -e "$self->{'LIST_NAME'}/remote"; +} + +# == Does the list have a kill list == +sub isdeny { + my($self) = @_; + ($self->_seterror(-1, 'must setlist() before isdeny()') && return 0) unless(defined($self->{'LIST_NAME'})); + $self->_seterror(undef); + return -e "$self->{'LIST_NAME'}/deny"; +} + +# == Does the list have an allow list == +sub isallow { + my($self) = @_; + ($self->_seterror(-1, 'must setlist() before isallow()') && return 0) unless(defined($self->{'LIST_NAME'})); + $self->_seterror(undef); + return -e "$self->{'LIST_NAME'}/allow"; +} + +# == Is this a digested list == +sub isdigest { + my($self) = @_; + ($self->_seterror(-1, 'must setlist() before isdigest()') && return 0) unless(defined($self->{'LIST_NAME'})); + $self->_seterror(undef); + return -e "$self->{'LIST_NAME'}/digest"; +} + +# == retrieve file contents == +sub getpart { + my($self, $part) = @_; + my(@contents, $content); + if(open(PART, "<$self->{'LIST_NAME'}/$part")) { + while() { + chomp($contents[$#contents++] = $_); + $content .= $_; + } + close PART; + if(wantarray) { + return @contents; + } else { + return $content; + } + } ($self->_seterror($?) && return undef); +} + +# == set files contents == +sub setpart { + my($self, $part, @content) = @_; + my($line); + if(open(PART, ">$self->{'LIST_NAME'}/$part")) { + foreach $line (@content) { + $line =~ s/[\r]//g; $line =~ s/\n$//; + print PART "$line\n"; + } + close PART; + return 1; + } ($self->_seterror($?) && return undef); +} + +# == return an error message if appropriate == +sub errmsg { + my($self) = @_; + return $self->{'ERRMSG'}; +} + +sub errno { + my($self) = @_; + return $self->{'ERRNO'}; +} + +# == Test the compatiblity of the module == +sub check_version { + my($self) = @_; + my $version = `$EZMLM_BASE/ezmlm-make -V 2>&1`; + $self->_seterror(undef); + + my ($ezmlm, $idx) = $version =~ m/^ezmlm-make\s+version:\s+ezmlm-([\d\.]+)(?:\+ezmlm-idx-([\d\.]+))?/; + if($ezmlm >= 0.53) { + if (defined($idx)) { + if ($idx >= 0.40) { + return 0; + } elsif ($idx =~ m/^(\d)/) { + if ($1 >= 5) { + return 1; + } else { + return 0; + } + } else { + return $version; + } + } + return 0; + } + return $version; +} + +# == Create SQL Database tables if defined for a list == +sub createsql { + my($self) = @_; + + ($self->_seterror(-1, 'MySQL must be compiled into Ezmlm for createsql() to work') && return 0) unless(defined($MYSQL_BASE) && $MYSQL_BASE); + ($self->_seterror(-1, 'must setlist() before isdigest()') && return 0) unless(defined($self->{'LIST_NAME'})); + my($config) = $self->getconfig(); + + if($config =~ m/-6\s+'(.+?)'\s*/){ + my($sqlsettings) = $1; + my($host, $port, $user, $password, $database, $table) = split(':', $sqlsettings, 6); + + ($self->_seterror(-1, 'error in list configuration while trying createsql()') && return 0) + unless (defined($host) && defined($port) && defined($user) + && defined($password) && defined($database) && defined($table)); + + system("$EZMLM_BASE/ezmlm-mktab -d $table | $MYSQL_BASE/mysql -h$host -P$port -u$user -p$password -f $database") == 0 || + ($self->_seterror($?) && return undef); + + } else { + $self->_seterror(-1, 'config for thislist() must include SQL options'); + return 0; + } + + ($self->_seterror(undef) && return 1); + +} + + +# == Internal function to set the error to return == +sub _seterror { + my($self, $no, $mesg) = @_; + + if(defined($no) && $no) { + if($no < 0) { + $self->{'ERRNO'} = -1; + $self->{'ERRMSG'} = $mesg || 'An undefined error occoured'; + } else { + $self->{'ERRNO'} = $no / 256; + $self->{'ERRMSG'} = $! || $mesg || 'An undefined error occoured in a system() call'; + } + } else { + $self->{'ERRNO'} = 0; + $self->{'ERRMSG'} = undef; + } + return 1; +} + +# == Internal function to test for valid email addresses == +sub _checkaddress { + my($self, $address) = @_; + return 1 unless defined($address); + return 0 unless ($address =~ m/^(\S+\@\S+\.\S+)$/); + $_[1] = $1; + return 1; +} + +# == Internal function to work out a list configuration (idx >= v5.0) == +sub _getconfig_idx5 { + my($self) = @_; + my ($options, %optionfiles); + my ($file, $opt_num, $temp); + + # read flag file (available since ezmlm-idx 5.0.0) + chomp($options = $self->getpart('flags')); + # remove prefixed '-' + $options =~ s/^-//; + + # since ezmlm-idx v5, we have to read the config + # values from different files + # first: preset a array with "filename" and "option_number" + %optionfiles = ( + 'sublist', '0', + 'fromheader', '3', + 'tstdigopts', '4', + 'owner', '5', + 'sql', '6', + 'modpost', '7', + 'modsub', '8'); + # "-9" seems to be ignored - this is a good change (tm) + while (($file, $opt_num) = each(%optionfiles)) { + if (-e "$self->{'LIST_NAME'}/$file") { + chomp($temp = $self->getpart($file)); + $options .= " -$opt_num '$temp'" if ($temp ne ''); + } + } + + return $options; +} + +# == Internal function to work out a list configuration manually (idx < v5.0.0 ) == +sub _getconfigmanual { + # use this function for strange lists without + # 'config' (idx < v5.0) and 'flags' (idx >= v5.0) + my($self) = @_; + my ($savedollarslash, $options, $manager, $editor, $i); + + # Read the whole of DIR/editor and DIR/manager in + $savedollarslash = $/; + undef $/; + # $/ = \0777; + + open (EDITOR, "<$self->{'LIST_NAME'}/editor") || ($self->_seterror($?) && return undef); + open (MANAGER, "<$self->{'LIST_NAME'}/manager") || ($self->_seterror($?) && return undef); + $editor = ; $manager = ; + close(EDITOR), close(MANAGER); + + $/ = $savedollarslash; + + $options = ''; + $options .= 'a' if (-e "$self->{'LIST_NAME'}/archived"); + $options .= 'd' if (-e "$self->{'LIST_NAME'}/digest"); + $options .= 'f' if (-e "$self->{'LIST_NAME'}/prefix"); + $options .= 'g' if ($manager =~ /ezmlm-get -\w*s/ ); + $options .= 'i' if (-e "$self->{'LIST_NAME'}/indexed"); + $options .= 'k' if (-e "$self->{'LIST_NAME'}/blacklist" || -e "$self->{'LIST_NAME'}/deny"); + $options .= 'l' if ($manager =~ /ezmlm-manage -\w*l/ ); + $options .= 'm' if (-e "$self->{'LIST_NAME'}/modpost"); + $options .= 'n' if ($manager =~ /ezmlm-manage -\w*e/ ); + $options .= 'p' if (-e "$self->{'LIST_NAME'}/public"); + $options .= 'q' if ($manager =~ /ezmlm-request/ ); + $options .= 'r' if (-e "$self->{'LIST_NAME'}/remote"); + $options .= 's' if (-e "$self->{'LIST_NAME'}/modsub"); + $options .= 't' if (-e "$self->{'LIST_NAME'}/text/trailer"); + $options .= 'u' if (($options !~ /m/ && $editor =~ /ezmlm-issubn \'/ ) + || $editor =~ /ezmlm-gate/ ); + $options .= 'x' if (-e "$self->{'LIST_NAME'}/extra" || -e "$self->{'LIST_NAME'}/allow"); + + # Add the unselected options too + # but we will skip invalid options (any of 'cevz') + foreach $i ('a' .. 'z') { + $options .= uc($i) unless (('cevz' =~ /$i/) || ($options =~ /$i/i)) + } + + # there is no way to get the other string settings, that are only + # defined in 'config' - sorry ... + + return $options; +} + +# == Internal Function to try to determine the vhost user == +sub _getvhostuser { + my($self, $hostname) = @_; + my($username); + + open(VD, "<$QMAIL_BASE/control/virtualdomains") || ($self->_seterror($?) && return undef); + while() { + last if(($username) = /^\s*$hostname:(\w+)$/); + } + close VD; + + return $username; +} + +# == Internal function to work out default host name == +sub _getdefaultdomain { + my($self) = @_; + my($hostname); + + open (GETHOST, "<$QMAIL_BASE/control/defaultdomain") + || open (GETHOST, "<$QMAIL_BASE/control/me") + || ($self->_seterror($?) && return undef); + chomp($hostname = ); + close GETHOST; + + return $hostname; +} + +1; +__END__ + +=head1 NAME + +Ezmlm - Object Methods for Ezmlm Mailing Lists + +=head1 SYNOPSIS + + use Mail::Ezmlm; + $list = new Mail::Ezmlm; + +The rest is a bit complicated for a Synopsis, see the description. + +=head1 ABSTRACT + +Ezmlm is a Perl module that is designed to provide an object interface to +the ezmlm mailing list manager software. See the ezmlm web page +(http://www.ezmlm.org/) for a complete description of the software. + +This version of the module is designed to work with ezmlm version 0.53. +It is fully compatible with ezmlm's IDX extensions (version 0.40). Both +of these can be obtained via anon ftp from ftp://ftp.ezmlm.org/pub/patches/ + +=head1 DESCRIPTION + +=head2 Setting up a new Ezmlm object: + + use Mail::Ezmlm; + $list = new Mail::Ezmlm; + $list = new Mail::Ezmlm('/home/user/lists/moolist'); + +=head2 Changing which list the Ezmlm object points at: + + + $list->setlist('/home/user/lists/moolist'); + +=head2 Getting a list of current subscribers: + +=item Two methods of listing subscribers is provided. The first prints a list +of subscribers, one per line, to the supplied FILEHANDLE. If no filehandle is +given, this defaults to STDOUT. An optional second argument specifies the +part of the list to display (mod, digest, allow, deny). If the part is +specified, then the FILEHANDLE must be specified. + + $list->list; + $list->list(\*STDERR); + $list->list(\*STDERR, 'deny'); + +=item The second method returns an array containing the subscribers. The +optional argument specifies which part of the list to display (mod, digest, +allow, deny). + + @subscribers = $list->subscribers; + @subscribers = $list->subscribers('allow'); + +=head2 Testing for subscription: + + $list->issub('nobody@on.web.za'); + $list->issub(@addresses); + $list->issub(@addresses, 'mod'); + +issub() returns 1 if all the addresses supplied are found as subscribers +of the current mailing list, otherwise it returns undefined. The optional +argument specifies which part of the list to check (mod, digest, allow, +deny). + +=head2 Subscribing to a list: + + $list->sub('nobody@on.web.za'); + $list->sub(@addresses); + $list->sub(@addresses, 'digest'); + +sub() takes a LIST of addresses and subscribes them to the current mailing list. +The optional argument specifies which part of the list to subscribe to (mod, +digest, allow, deny). + + +=head2 Unsubscribing from a list: + + $list->unsub('nobody@on.web.za'); + $list->unsub(@addresses); + $list->unsub(@addresses, 'mod'); + +unsub() takes a LIST of addresses and unsubscribes them (if they exist) from the +current mailing list. The optional argument specifies which part of the list +to unsubscribe from (mod, digest, allow, deny). + + +=head2 Creating a new list: + + $list->make(-dir=>'/home/user/list/moo', + -qmail=>'/home/user/.qmail-moo', + -name=>'user-moo', + -host=>'on.web.za', + -user=>'onwebza', + -switches=>'mPz'); + +make() creates the list as defined and sets it to the current list. There are +three variables which must be defined in order for this to occur; -dir, -qmail and -name. + +=over 6 + +=item -dir is the full path of the directory in which the mailing list is to +be created. + +=item -qmail is the full path and name of the .qmail file to create. + +=item -name is the local part of the mailing list address (eg if your list +was user-moo@on.web.za, -name is 'user-moo'). + +=item -host is the name of the host that this list is being created on. If +this item is omitted, make() will try to determine your hostname. If -host is +not the same as your hostname, then make() will attempt to fix DIR/inlocal for +a virtual host. + +=item -user is the name of the user who owns this list. This item only needs to +be defined for virtual domains. If it exists, it is prepended to -name in DIR/inlocal. +If it is not defined, the make() will attempt to work out what it should be from +the qmail control files. + +=item -switches is a list of command line switches to pass to ezmlm-make(1). +Note that the leading dash ('-') should be ommitted from the string. + +=back + +make() returns the value of thislist() for success, undefined if there was a +problem with the ezmlm-make system call and 0 if there was some other problem. + +See the ezmlm-make(1) man page for more details + +=head2 Determining which list we are currently altering: + + $whichlist = $list->thislist; + print $list->thislist; + +=head2 Getting the current configuration of the current list: + + $list->getconfig; + +getconfig() returns a string that contains the command line switches that +would be necessary to re-create the current list. It does this by reading the +DIR/config file (idx < v5.0) or DIR/flags (idx >= v5.0) if one of them exists. +If it can't find these files it attempts to work things out for itself (with +varying degrees of success). If both these methods fail, then getconfig() +returns undefined. + + $list->ismodpost; + $list->ismodsub; + $list->isremote; + $list->isdeny; + $list->isallow; + +The above five functions test various features of the list, and return a 1 +if the list has that feature, or a 0 if it doesn't. + +=head2 Updating the configuration of the current list: + + $list->update('msPd'); + +update() can be used to rebuild the current mailing list with new command line +options. These options can be supplied as a string argument to the procedure. +Note that you do not need to supply the '-' or the 'e' command line switch. + + @part = $list->getpart('headeradd'); + $part = $list->getpart('headeradd'); + $list->setpart('headerremove', @part); + +getpart() and setpart() can be used to retrieve and set the contents of +various text files such as headeradd, headerremove, mimeremove, etc. + +=head2 Creating MySQL tables: + + $list->createsql(); + +Currently only works for MySQL. + +createsql() will attempt to create the table specified in the SQL connect +options of the current mailing list. It will return an error if the current +mailing list was not configured to use SQL, or is Ezmlm was not compiled +with MySQL support. See the MySQL info pages for more information. + +=head2 Checking the Mail::Ezmlm and ezmlm version numbers + +The version number of the Mail::Ezmlm module is stored in the variable +$Mail::Ezmlm::VERSION. The compatibility of this version of Mail::Ezmlm +with your system installed version of ezmlm can be checked with + + $list->check_version(); + +This returns 0 for compatible, or the version string of ezmlm-make(2) if +the module is incompatible with your set up. + +=head1 RETURN VALUES + +All of the routines described above have return values. 0 or undefined are +used to indicate that an error of some form has occoured, while anything +>0 (including strings, etc) are used to indicate success. + +If an error is encountered, the functions + + $list->errno(); + $list->errmsg(); + +can be used to determine what the error was. + +errno() returns; 0 or undef if there was no error. + -1 for an error relating to this module. + >0 exit value of the last system() call. + +errmsg() returns a string containing a description of the error ($! if it +was from a system() call). If there is no error, it returns undef. + +For those who are interested, in those sub routines that have to make system +calls to perform their function, an undefined value indicates that the +system call failed, while 0 indicates some other error. Things that you would +expect to return a string (such as thislist()) return undefined to indicate +that they haven't a clue ... as opposed to the empty string which would mean +that they know about nothing :) + +=head1 AUTHOR + + Guy Antony Halse + +=head1 BUGS + + May have problems with newer versions of Perl. + + Please report bugs to the author. + +=head1 SEE ALSO + + ezmlm(5), ezmlm-make(2), ezmlm-sub(1), + ezmlm-unsub(1), ezmlm-list(1), ezmlm-issub(1) + + http://rucus.ru.ac.za/~guy/ezmlm/ + http://www.ezmlm.org/ + http://www.qmail.org/ + +=cut diff --git a/Ezmlm/tags/Ezmlm-0.06/MANIFEST b/Ezmlm/tags/Ezmlm-0.06/MANIFEST new file mode 100644 index 0000000..8bcd77d --- /dev/null +++ b/Ezmlm/tags/Ezmlm-0.06/MANIFEST @@ -0,0 +1,7 @@ +Changes +Ezmlm.pm +MANIFEST +README +Makefile.PL +test.pl +META.yml diff --git a/Ezmlm/tags/Ezmlm-0.06/META.yml b/Ezmlm/tags/Ezmlm-0.06/META.yml new file mode 100644 index 0000000..f050e61 --- /dev/null +++ b/Ezmlm/tags/Ezmlm-0.06/META.yml @@ -0,0 +1,10 @@ +# http://module-build.sourceforge.net/META-spec.html +#XXXXXXX This is a prototype!!! It will change in the future!!! XXXXX# +name: Ezmlm +version: 0.05 +version_from: Ezmlm.pm +installdirs: site +requires: + +distribution_type: module +generated_by: ExtUtils::MakeMaker version 6.17 diff --git a/Ezmlm/tags/Ezmlm-0.06/Makefile.PL b/Ezmlm/tags/Ezmlm-0.06/Makefile.PL new file mode 100644 index 0000000..7e6f918 --- /dev/null +++ b/Ezmlm/tags/Ezmlm-0.06/Makefile.PL @@ -0,0 +1,119 @@ +# $Id: Makefile.PL,v 1.3 2005/03/05 14:15:20 guy Exp $ + +use ExtUtils::MakeMaker; +# See lib/ExtUtils/MakeMaker.pm for details of how to influence +# the contents of the Makefile that is written. +WriteMakefile( + 'CONFIGURE' => \&set_paths, + 'NAME' => 'Mail::Ezmlm', + 'VERSION_FROM' => 'Ezmlm.pm', # finds $VERSION + 'DISTNAME' => 'Ezmlm', + 'dist' => { COMPRESS => 'gzip', SUFFIX => 'gz' }, + 'clean' => { FILES => 'ezmlmtmp' } +); + +sub set_paths { + my($qmail_path, $ezmlm_path); + + # special case to handle the FreeBSD ports system + if ($ENV{BSD_BATCH_INSTALL}) { + print STDERR "\$BSD_BATCH_INSTALL is set in your environment, assuming port defaults\n"; + return {}; + } + + print << 'EOM'; + +We now need to know where some things live on your system. I'll try and make +some intelligent guesses - if I get it right, please just press enter at the +prompt. If I get them wrong, please type in the correct path for me and then +press enter. + +First I need to know where the Ezmlm binaries live (ie where I can find +ezmlm-make, ezmlm-sub, etc). + +EOM + + *prompt = \&ExtUtils::MakeMaker::prompt; + + foreach (1..10) { + $ezmlm_path = prompt('Ezmlm binary directory?', '/usr/local/bin'); + last if (-e "$ezmlm_path/ezmlm-make"); + print "I can't find $ezmlm_path/ezmlm-make. Please try again\n"; + if (! -e "$ezmlm_path/ezmlm-make") { + print STDERR "No correct input after $_ attempts. Exiting Makefile.PL.\n"; + exit (2); + } + } + + print << 'EOM'; + +Now I need to know where Qmail resides on your system. The Qmail base +directory is the one in which the Qmail bin, control, etc directories +live in. + +EOM + + foreach (1..10) { + $qmail_path = prompt('Qmail base directory?', '/var/qmail'); + last if (-d "$qmail_path/control"); + print "I can't find $qmail_path/control. Please try again\n"; + if (! -e "$qmail_path/control") { + print STDERR "No correct input after $_ attempts. Exiting Makefile.PL.\n"; + exit (2); + } + } + + if(`strings $ezmlm_path/ezmlm-sub | grep -i 'MySQL'`) { + + print << 'EOM'; + +It appears you have compiled MySQL support into your version of Ezmlm. If +this is correct, I now need to know where the MySQL client (mysql) lives on +your machine. + +Please leave this blank if you do not want to enable MySQL support in the +Mail::Ezmlm module. + +EOM + + foreach (1..10) { + $mysql_path = prompt('MySQL binary directory?', ''); + last if (-e "$mysql_path/mysql" || $mysql_path eq ''); + print "I can't find $mysql_path/mysql. Please enter the full path\n"; + print "or leave this option blank if you don't want to use MySQL\n"; + if ((! -e "$mysql_path/mysql") && ($mysql_path ne '')) { + print STDERR "No correct input after $_ attempts. Exiting Makefile.PL.\n"; + exit (2); + } + } + + } + + print << 'EOM'; + +Thank you. I will use this information to configure Mail::Ezmlm for you + +EOM + + # Back up file + open(EZMLM, 'Ezmlm.pm.tmp.$$") or die "Unable to create temp file: $!"; + while() { print TMP; } + close TMP; close EZMLM; + + # Do variable substitution + open(EZMLM, '>Ezmlm.pm') or die "Unable to open Ezmlm.pm for write: $!"; + open(TMP, ") { + s{^\$EZMLM_BASE\s*=\s*['"].+?['"]\s*;}{\$EZMLM_BASE = '$ezmlm_path'; #Autoinserted by Makefile.PL}; + s{^\$QMAIL_BASE\s*=\s*['"].+?['"]\s*;}{\$QMAIL_BASE = '$qmail_path'; #Autoinserted by Makefile.PL}; + s{^\$MYSQL_BASE\s*=\s*['"].*?['"]\s*;}{\$MYSQL_BASE = '$mysql_path'; #Autoinserted by Makefile.PL}; + print EZMLM; + } + close TMP; close EZMLM; + + unlink "Ezmlm.pm.tmp.$$"; + + return {}; + +} diff --git a/Ezmlm/tags/Ezmlm-0.06/README b/Ezmlm/tags/Ezmlm-0.06/README new file mode 100644 index 0000000..3b2046a --- /dev/null +++ b/Ezmlm/tags/Ezmlm-0.06/README @@ -0,0 +1,22 @@ +$Id: README,v 1.3 2005/03/05 14:14:06 guy Exp $ + +Ezmlm.pm + +Object methods for ezmlm mailing lists. + +Install by doing the following ... +# perl Makefile.PL +# make test +# make install + +One thing. For some reason MakeMaker doesn't like symlinks. Please make sure +you use the full cantonical path for the qmail and ezmlm binaries. + +Documentation is in pod format. Please run perldoc Mail::Ezmlm after you have +installed it. + +Much as I'd like to, I don't have the time to regularly maintain this. New +releases are infrequent at best. Check http://guy.rucus.net/ezmlm/contrib/ +for patches, etc that may be useful. + +- Guy Antony Halse diff --git a/Ezmlm/tags/Ezmlm-0.06/test.pl b/Ezmlm/tags/Ezmlm-0.06/test.pl new file mode 100644 index 0000000..e8de0ff --- /dev/null +++ b/Ezmlm/tags/Ezmlm-0.06/test.pl @@ -0,0 +1,140 @@ +# =========================================================================== +# test.pl - version 0.02 - 25/09/2000 +# $Id: test.pl,v 1.5 2005/03/05 14:08:30 guy Exp $ +# Test suite for Mail::Ezmlm +# +# Copyright (C) 1999, Guy Antony Halse, All Rights Reserved. +# Please send bug reports and comments to guy-ezmlm@rucus.ru.ac.za +# +# This program is subject to the restrictions set out in the copyright +# agreement that can be found in the Ezmlm.pm file in this distribution +# +# ========================================================================== +# Before `make install' is performed this script should be runnable with +# `make test'. After `make install' it should work as `perl test.pl' + +######################### We start with some black magic to print on failure. + +$failed = 0; + +BEGIN { $| = 1; print "1..9\n"; } +END {($failed++ && print "not ok 1\n") unless $loaded;} +use Mail::Ezmlm; +$loaded = 1; +print "Loading: ok 1\n"; + +######################### End of black magic. + +# Insert your test code below (better if it prints "ok 13" +# (correspondingly "not ok 13") depending on the success of chunk 13 +# of the test code): + +use Cwd; +use File::Find; +$list = new Mail::Ezmlm; + +# create a temp directory if necessary +$TMP = cwd() . '/ezmlmtmp'; +mkdir $TMP, 0755 unless (-d $TMP); + +print 'Checking list creation: '; +$test1 = $list->make(-name=>"ezmlm-test1-$$", + -qmail=>"$TMP/.qmail-ezmlm-test1-$$", + -dir=>"$TMP/ezmlm-test1-$$"); +if($test1 eq "$TMP/ezmlm-test1-$$") { + print "ok 2\n"; +} else { + print 'not ok 2 [', $list->errmsg(), "]\n"; + $failed++; +} + +print 'Checking vhost list creation: '; +$test2 = $list->make(-name=>"ezmlm-test2-$$", + -qmail=>"$TMP/.qmail-ezmlm-test2-$$", + -dir=>"$TMP/ezmlm-test2-$$", + -host=>'on.web.za', + -user=>'onwebza'); +if($test2 eq "$TMP/ezmlm-test2-$$") { + open(INLOCAL, "<$TMP/ezmlm-test2-$$/inlocal"); + chomp($test2 = ); + close INLOCAL; + if($test2 eq "onwebza-ezmlm-test2-$$") { + print "ok 3\n"; + } else { + print 'not ok 3 [', $list->errmsg(), "]\n"; + $failed++; + } +} else { + print 'not ok 3 [', $list->errmsg(), "]\n"; + $failed++; +} + +print 'Testing list update: '; +if($list->update('ms')) { + print "ok 4\n"; +} else { + print 'not ok 4 [', $list->errmsg(), "]\n"; + $failed++; +} + +print 'Testing setlist() and thislist(): '; +$list->setlist("$TMP/ezmlm-test1-$$"); +if($list->thislist eq "$TMP/ezmlm-test1-$$") { + print "ok 5\n"; +} else { + print 'not ok 5 [', $list->errmsg(), "]\n"; + $failed++; +} + +print 'Testing list subscription and subscription listing: '; +$list->sub('nobody@on.web.za'); +$list->sub('anonymous@on.web.za', 'test@on.web.za'); +@subscribers = $list->subscribers; +if($subscribers[1] =~ /nobody\@on.web.za/) { + print "ok 6\n"; +} else { + print 'not ok 6 [', $list->errmsg(), "]\n"; + $failed++; +} + +print 'Testing issub(): '; +if(defined($list->issub('nobody@on.web.za'))) { + if(defined($list->issub('some@non.existant.address'))) { + print 'not ok 7 [', $list->errmsg(), "]\n"; + $failed++; + } else { + print "ok 7\n"; + } +} else { + print 'not ok 7 [', $list->errmsg(), "]\n"; + $failed++; +} + +print 'Testing list unsubscription: '; +$list->unsub('nobody@on.web.za'); +$list->unsub('anonymous@on.web.za', 'test@on.web.za'); +@subscribers = $list->subscribers; +unless(@subscribers) { + print "ok 8\n"; +} else { + print 'not ok 8 [', $list->errmsg(), "]\n"; + $failed++; +} + +print 'Testing installed version of ezmlm: '; +my($version) = $list->check_version(); +if ($version) { + $version =~ s/\n//; + print 'not ok 9 [Ezmlm.pm is designed to work with ezmlm-idx > 0.40. Your version reports as: ', $version, "]\n"; +} else { + print "ok 9\n"; +} + +if($failed > 0) { + print "\n$failed tests were failed\n"; + exit $failed; +} else { + print "\nSuccessful :-)\n"; + finddepth(sub { (-d $File::Find::name) ? rmdir ($File::Find::name) : unlink ($File::Find::name) }, cwd() . "/ezmlmtmp"); + exit; +} diff --git a/Ezmlm/tags/make-tar.sh b/Ezmlm/tags/make-tar.sh new file mode 100755 index 0000000..5d1022b --- /dev/null +++ b/Ezmlm/tags/make-tar.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +set -eu + +PREFIX=Ezmlm + +[ $# -ne 1 ] && echo "Syntax: `basename $0` VERSION" && echo && exit 1 +[ ! -d "${PREFIX}-${1}" ] && echo "the directory '${PREFIX}-${1}' does not exist!" && exit 2 + +TMP_DIR=/tmp/${PREFIX}-${1} +[ -e "$TMP_DIR" ] && rm -rf "$TMP_DIR" + +svn export "${PREFIX}-${1}" "$TMP_DIR" +tar czf "packages/${PREFIX}-${1}.tar.gz" -C "$(dirname $TMP_DIR)" --owner=0 --group=0 "$(basename $TMP_DIR)" +rm -rf "$TMP_DIR" diff --git a/Ezmlm/tags/packages/Ezmlm-0.06.tar.gz b/Ezmlm/tags/packages/Ezmlm-0.06.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..6020ebc04df139ace37b66c6d29c960230df5695 GIT binary patch literal 12381 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 Pe&h2$=8Z@00LTCUY_J-M literal 0 HcmV?d00001 diff --git a/Ezmlm/tags/packages/Ezmlm-0.07.tar.gz b/Ezmlm/tags/packages/Ezmlm-0.07.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..830ec5cf5c229f075f479197a289db537f7dbc18 GIT binary patch literal 14411 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 Ro982+{{zQM7_R{E001K317QFF literal 0 HcmV?d00001