## Process this file with automake to produce Makefile.in
-EXTRA_DIST = web amime-receive foot_filter pymime
+EXTRA_DIST = amime-receive foot_filter pymime
SUBDIRS = receivestrip
+++ /dev/null
-mlmmj-1.0.0 August 20th 2004
-
-To use this web-interface you have to:
-
-0) Make sure you have the CGI::FastTemplate perl module installed. If not, then
- install it. It has no dependencies to other perl modules.
-
-1) Copy the files from the perl-admin directory of the mlmmj distribution to a
- suitable location and point your webroot to the htdocs directory. If you
- don't want the webinterface in the root of your website it is recommended to
- make an alias in your web server configuration in order to keep the conf
- directory at the same level as the htdocs directory and still outside
- webscope.
-
-2) You need to enable cgi in your apache configuration like this
-
- Options ExecCGI
- DirectoryIndex index.cgi
- AddHandler cgi-script .cgi
-
-3) Change the permissions of the listdir/control directories of any list you
- want to control using the web-interface, so the web server can write in it:
-
- # chown -R wwwrun /var/spool/mlmmj/mlmmj-test/control/
-
-4) If the web server does not run as the same user the mailserver writes as
- you need to create a group (eg. mlmmj) and add both users to it. The
- subscribers.d directory then needs to be writable by that group:
-
- # chgrp -R mlmmj /var/spool/mlmmj/mlmmj-test/subscribers.d
- # chmod -R g+w /var/spool/mlmmj/mlmmj-test/subscribers.d
- # chgrp -R mlmmj /var/spool/mlmmj/mlmmj-test/digesters.d
- # chmod -R g+w /var/spool/mlmmj/mlmmj-test/digesters.d
- # chgrp -R mlmmj /var/spool/mlmmj/mlmmj-test/nomailsubs.d
- # chmod -R g+w /var/spool/mlmmj/mlmmj-test/nomailsubs.d
- # chgrp -R mlmmj /var/spool/mlmmj/mlmmj-test/text
- # chmod -R g+w /var/spool/mlmmj/mlmmj-test/text
-
-To enable access control on Apache you have to:
-
-5) Rename dot.htaccess to .htaccess and edit the path inside the file to point
- to a htpasswd file somewhere outside the webscope.
-
- If you don't have one already, you can create one like this
-
- htpasswd -c /home/mlmmj/htpasswd USER
-
- It will then ask you for a password for the given username.
-
-6) That is it, you are ready to use the interface.
-
-Further customization:
-
-You can set two environment variables in your apache config to control the
-configuration of the mlmmj webinterface. Remember to have mod_env loaded if
-you do this.
-
- SetEnv CONFIG_PATH /home/mlmmj/conf/config.pl
- SetEnv TUNABLES_PATH /home/mlmmj/conf/tunables.pl
-
-This allows you to run several instances of the webinterface with e.g. different
-topdirs, translated to another language or with another layout.
+++ /dev/null
-$topdir = "/var/spool/mlmmj";
-$templatedir = "/home/mlmmj/templates";
+++ /dev/null
-mlmmj_list("listaddress",
- "List address",
- "This option contains all addresses which mlmmj sees as listaddresses (see ".
- "tocc below). The first one is the one used as the primary one, when mlmmj ".
- "sends out mail.");
-
-mlmmj_boolean("closedlist",
- "Closed list",
- "If the list is open or closed. If it's closed subscription ".
- "and unsubscription via mail is disabled.");
-
-mlmmj_boolean("closedlistsub",
- "Closed for subscription",
- "Closed for subscription. Unsubscription is possible.");
-
-mlmmj_boolean("nosubconfirm",
- "No subscribe confirmation",
- "If this option is set, the user is not required to confirm when subscribing or unsubscribing.");
-
-mlmmj_boolean("moderated",
- "Moderated",
- "If this option is set, the emailaddresses in the file listdir/control/moderators will act as moderators for the list.");
-
-mlmmj_list("moderators",
- "Moderators",
- "If the list is moderated, this is the list of moderators.");
-
-mlmmj_list("submod",
- "Subscription moderators",
- "This is the list of moderators that will approve subscriptions.");
-
-mlmmj_boolean("tocc",
- "To: Cc:",
- "If this option is set, the list address does not have to be in the To: or Cc: header of the email to the list.");
-
-mlmmj_boolean("addtohdr",
- "Add To: header",
- "If this option is set, a To: header including the recipients emailaddress will be added to outgoing mail. ".
- "Recommended usage is to remove existing To: headers with delheaders (see below) first.");
-
-mlmmj_boolean("subonlypost",
- "Subscribers only post",
- "If this option is set, only people who are subscribed to the list, are allowed to post to it. ".
- "The check is made against the \"From:\" header.");
-
-mlmmj_boolean("modonlypost",
- "Moderators only post",
- "When this file is present, only people listed in listdir/control/moderators ".
- "are allowed to post to it. The check is made against the "From:" header.");
-
-mlmmj_boolean("modnonsubposts",
- "Moderate non-allowed posts",
- "If this option is set, postings from people who are not allowed to post ".
- "to the list will be moderated instead of denied.");
-
-mlmmj_string("modreqlife",
- "Moderation request lifetime",
- "This specifies how long in seconds a mail awaits moderation before it's ".
- "discarded. Defaults to 604800 seconds, which is 7 days.");
-
-mlmmj_string("prefix",
- "Prefix",
- "The prefix for the Subject: line of mails to the list. This will alter the Subject: line, ".
- "and add a prefix if it's not present elsewhere.");
-
-mlmmj_list("owner",
- "Owner",
- "The emailaddresses in this list will get mails to ".encode_entities($list)."+owner");
-
-mlmmj_list("customheaders",
- "Custom headers",
- "These headers are added to every mail coming through. This is ".
- "the place you want to add Reply-To: header in case you want ".
- "such. ".
- "If a header should not occur twice in the mail it should be listed in the 'Delete headers' box too.");
-
-mlmmj_list("delheaders",
- "Delete headers",
- "In this file is specified *ONE* headertoken to match pr. line. ".
- "If the file consists of: Received: Message-ID: Then all occurences of these headers in incoming list mail will be deleted. ".
- "\"From \" and \"Return-Path:\" are deleted no matter what.");
-
-mlmmj_list("access",
- "Access",
- "If this option is set, all headers of a post to the list is matched against the rules. The first rule to match wins. ".
- "See README.access for syntax and examples. NOTE: If this field is empty access control is *disabled*, ".
- "unlike having an empty control/access file.");
-
-mlmmj_string("memorymailsize",
- "Memory mail size",
- "Here is specified in bytes how big a mail can be and still be prepared for sending in memory. ".
- "It's greatly reducing the amount of write system calls to prepare it in memory before sending it, ".
- "but can also lead to denial of service attacks. Default is 16k (16384 bytes).");
-
-mlmmj_string("relayhost",
- "Relay host",
- "The host specified (IP address or domainname, both works) in this file will be used for relaying the mail sent to the list. ".
- "Defaults to 127.0.0.1.");
-
-mlmmj_string("smtpport",
- "SMTP port",
- "In this file a port other than port 25 for connecting to the relayhost can be specified.");
-
-mlmmj_string("delimiter",
- "Delimiter",
- "This specifies what to use as recipient delimiter for the list.".
- "Default is \"+\".");
-
-mlmmj_boolean("notifysub",
- "Notify subscribers",
- "If this option is set, the owner(s) will get a mail with the address of someone sub/unsubscribing to a mailinglist.");
-
-mlmmj_boolean("notifymod",
- "Notify moderation",
- "If this option is set, the poster (based on the envelope from) will ".
- "get a mail when their post is being moderation.");
-
-mlmmj_string("digestinterval",
- "Digest interval",
- "This option specifies how many seconds will pass before the ".
- "next digest is sent. Defaults to 604800 seconds, which is 7 ".
- "days.");
-
-mlmmj_string("digestmaxmails",
- "Max. digest mails",
- "This option specifies how many mails can accumulate before ".
- "digest sending is triggered. Defaults to 50 mails, meaning ".
- "that if 50 mails arrive to the list before digestinterval have ".
- "passed, the digest is delivered.");
-
-mlmmj_string("bouncelife",
- "Bouncing lifetime",
- "This specifies how long in seconds an address can bounce before it's ".
- "unsubscribed. Defaults to 432000 seconds, which is 5 days.");
-
-mlmmj_boolean("noarchive",
- "No archive",
- "If this option is set, the mails won't be saved in the ".
- "archive but simply deleted");
-
-mlmmj_boolean("noget",
- "No get",
- "If this option is set, listname+get-INDEX is turned off.");
-
-mlmmj_boolean("subonlyget",
- "Subscribers only get",
- "If this option is set, retrieving old posts with +get-N is only possible for subscribers.");
-
-mlmmj_string("verp",
- "VERP",
- "Enable VERP support. Anything added in this variable will be appended the ".
- "MAIL FROM: line. If \"postfix\" is put in the file, it'll make postfix use ".
- "VERP by adding XVERP=-= to the MAIL FROM: line.");
-
-mlmmj_string("maxverprecips",
- "Maximum VERP recipients",
- "How many recipients pr. mail delivered to the smtp server. Defaults to 100.");
-
-mlmmj_boolean("notoccdenymails",
- "No To: Cc: deny mails",
- "This switch turns off whether mlmmj sends out notification about postings ".
- "being denied due to the listaddress not being in To: or Cc: (see 'tocc').");
-
-mlmmj_boolean("noaccessdenymails",
- "No access deny mails",
- "This switch turns off whether mlmmj sends out notification about postings ".
- "being rejected due to an access rule (see 'access').");
-
-mlmmj_boolean("nosubonlydenymails",
- "No subscribers only deny mails",
- "This switch turns off whether mlmmj sends out notification about postings ".
- "being rejected due to a subscribers only posting list (see 'subonlypost').");
-
-mlmmj_boolean("nomodonlydenymails",
- "No moderators only deny mails",
- "This switch turns off whether mlmmj sends out notification about postings ".
- "being rejected due to a moderators only posting list (see 'modonlypost').");
-
-mlmmj_boolean("nosubmodmails",
- "No subscription moderated mails",
- "This switch turns off whether mlmmj sends out notification about ".
- "subscription being moderated to the person requesting subscription".
- "(see 'submod').");
-
-mlmmj_boolean("nodigesttext",
- "No digest text summary",
- "This switch turns off whether digest mails will have a text part with a thread ".
- "summary.");
-
-mlmmj_boolean("nodigestsub",
- "No digest subscribers",
- "If this option is set, subscription to the digest version of the mailinglist ".
- "will be denied. (Useful if you don't want to allow digests and notify users ".
- "about it).");
-
-mlmmj_boolean("nonomailsub",
- "No nomail subscribers",
- "If this option is set, subscription to the nomail version of the mailinglist ".
- "will be denied. (Useful if you don't want to allow nomail and notify users ".
- "about it).");
-
-mlmmj_string("maxmailsize",
- "Max. mail size",
- "With this option the maximal allowed size of incoming mails can be specified.");
-
-mlmmj_boolean("nomaxmailsizedenymails",
- "No max. mail size deny mails",
- "If this is set, no reject notifications caused by violation of maxmailsize ".
- "will be sent.");
-
-mlmmj_boolean("nolistsubsemail",
- "No list subscribers email",
- "If this is set, the LISTNAME+list\@ functionality for requesting an ".
- "email with the subscribers for owner is disabled.");
-
-mlmmj_string("staticbounceaddr",
- "Static bounce address",
- "If this is set to something\@example.org, the bounce address (Return-Path:) ".
- "will be fixed to something+listname-bounces-and-so-on\@example.org ".
- "in case you need to disable automatic bounce handling.");
-
-mlmmj_boolean("ifmodsendonlymodmoderate",
- "If moderator send only moderator moderate",
- "If this is set, then mlmmj in case of moderation checks the ".
- "envelope from, to see if the sender is a moderator, and in that case ".
- "only send the moderation mails to that address. In practice this means that ".
- "a moderator sending mail to the list won't bother all the other moderators ".
- "with his mail.");
-
-mlmmj_list("footer",
- "Footer",
- "The content of this option is appended to mail sent to the list.");
-
-mlmmj_boolean("notmetoo",
- "Not me too",
- "If this is set, mlmmj attempts to exclude the sender of a post ".
- "from the distribution list for that post so people don't receive copies ".
- "of their own posts.");
-
-mlmmj_string("smtphelo",
- "SMTP Helo Name",
- "When this file is present, it contains the hostname to send in the SMTP ".
- "EHLO or HELO command. Otherwise the machine hostname is used.");
+++ /dev/null
-Require valid-user
-AuthType Basic
-AuthName "mlmmj web-interface"
-AuthUserFile /home/mlmmj/htpasswd
+++ /dev/null
-#!/usr/bin/perl -w
-
-# Copyright (C) 2004 Morten K. Poulsen <morten at afdelingp.dk>
-# Copyright (C) 2004 Christian Laursen <christian@pil.dk>
-#
-# $Id$
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to
-# deal in the Software without restriction, including without limitation the
-# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-# sell copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-# IN THE SOFTWARE.
-
-use strict;
-use CGI;
-use CGI::FastTemplate;
-use HTML::Entities;
-
-use vars qw($topdir $templatedir $list);
-
-if (exists $ENV{CONFIG_PATH}) {
- require $ENV{CONFIG_PATH};
-} else {
- require "../conf/config.pl";
-}
-
-my $tpl = new CGI::FastTemplate($templatedir);
-
-my $q = new CGI;
-$list = $q->param("list");
-
-die "no list specified" unless $list;
-die "non-existent list" unless -d("$topdir/$list");
-
-$tpl->define(main => "edit.html",
- boolean => "edit_boolean.html",
- string => "edit_string.html",
- list => "edit_list.html");
-
-$tpl->assign(LIST => encode_entities($list));
-
-my $tunables_file = "../conf/tunables.pl";
-if (exists $ENV{TUNABLES_PATH}) {
- $tunables_file = $ENV{TUNABLES_PATH};
-}
-
-do $tunables_file;
-
-print "Content-type: text/html\n\n";
-$tpl->parse(CONTENT => "main");
-$tpl->print;
-
-sub mlmmj_boolean {
- my ($name, $nicename, $text) = @_;
- my $checked = -f "$topdir/$list/control/$name";
-
- $tpl->assign(NAME => encode_entities($name));
- $tpl->assign(NICENAME => encode_entities($nicename));
- $tpl->assign(TEXT => encode_entities($text));
- $tpl->assign(CHECKED => $checked ? ' checked' : '');
-
- $tpl->parse(ROWS => ".boolean");
-}
-
-sub mlmmj_string {
- my ($name, $nicename, $text) = @_;
- my $file = "$topdir/$list/control/$name";
- my $value;
-
- if (! -f $file) {
- $value = "";
- } else {
- open(F, $file) or die("can't open $file");
- $value = <F>;
- close(F);
- chomp($value);
- }
-
- $tpl->assign(NAME => encode_entities($name));
- $tpl->assign(NICENAME => encode_entities($nicename));
- $tpl->assign(TEXT => encode_entities($text));
- $tpl->assign(VALUE => encode_entities($value));
-
- $tpl->parse(ROWS => ".string");
-}
-
-sub mlmmj_list {
- my ($name, $nicename, $text) = @_;
- my $file = "$topdir/$list/control/$name";
- my $value;
-
- if (! -f $file) {
- $value = "";
- } else {
- open(F, $file) or die("can't open $file");
- while (<F>) {
- $value .= $_;
- }
- close(F);
- chomp($value);
- }
-
- $tpl->assign(NAME => encode_entities($name));
- $tpl->assign(NICENAME => encode_entities($nicename));
- $tpl->assign(TEXT => encode_entities($text));
- $tpl->assign(VALUE => encode_entities($value));
-
- $tpl->parse(ROWS => ".list");
-}
-
+++ /dev/null
-#!/usr/bin/perl -w
-
-# Copyright (C) 2007 Franky Van Liedekerke <liedekef@telenet.be>
-#
-# $Id$
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to
-# deal in the Software without restriction, including without limitation the
-# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-# sell copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-# IN THE SOFTWARE.
-
-use strict;
-use CGI;
-use CGI::FastTemplate;
-use HTML::Entities;
-
-use vars qw($topdir $templatedir $list);
-
-if (exists $ENV{CONFIG_PATH}) {
- require $ENV{CONFIG_PATH};
-} else {
- require "../conf/config.pl";
-}
-
-my $tpl = new CGI::FastTemplate($templatedir);
-
-my $q = new CGI;
-$list = $q->param("list");
-
-die "no list specified" unless $list;
-die "non-existent list" unless -d("$topdir/$list");
-
-$tpl->define(main => "edit_text.html",
- list => "edit_textstring.html");
-
-$tpl->assign(LIST => encode_entities($list));
-
-my $textdir = "$topdir/$list/text";
-my @files;
-opendir(DIR, $textdir ) || die "can't opendir $textdir: $!";
-@files = grep { !/^\./ && -f "$textdir/$_" } readdir(DIR);
-closedir DIR;
-
-for my $textfile (sort @files) {
- mlmmj_text($textfile);
-}
-
-print "Content-type: text/html\n\n";
-$tpl->parse(CONTENT => "main");
-$tpl->print;
-
-sub mlmmj_text {
- my ($name) = @_;
- my $file = "$textdir/$name";
- my $value;
-
- if (! -f $file) {
- $value = "";
- } else {
- open(F, $file) or die("can't open $file");
- while (<F>) {
- $value .= $_;
- }
- close(F);
- chomp($value);
- }
-
- $tpl->assign(NAME => encode_entities($name));
- $tpl->assign(VALUE => encode_entities($value));
-
- $tpl->parse(ROWS => ".list");
-}
+++ /dev/null
-#!/usr/bin/perl -w
-
-# Copyright (C) 2004 Morten K. Poulsen <morten at afdelingp.dk>
-# Copyright (C) 2004 Christian Laursen <christian@pil.dk>
-#
-# $Id$
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to
-# deal in the Software without restriction, including without limitation the
-# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-# sell copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-# IN THE SOFTWARE.
-
-use strict;
-use URI::Escape;
-use HTML::Entities;
-use CGI::FastTemplate;
-
-use vars qw($topdir $templatedir);
-
-if (exists $ENV{CONFIG_PATH}) {
- require $ENV{CONFIG_PATH};
-} else {
- require "../conf/config.pl";
-}
-
-my $tpl = new CGI::FastTemplate($templatedir);
-
-$tpl->define(main => "index.html",
- row => "index_row.html");
-
-my $lists = "";
-opendir(DIR, $topdir) or die "Couldn't open $topdir for reading: $!";
-while (my $list = readdir(DIR)) {
- next if $list =~ /^\./;
- $tpl->assign(LIST => encode_entities($list));
- $tpl->assign(ULIST => uri_escape($list));
- $tpl->parse(LISTS => '.row');
-}
-closedir(DIR);
-
-print "Content-type: text/html\n\n";
-
-$tpl->parse(CONTENT => "main");
-$tpl->print;
+++ /dev/null
-#!/usr/bin/perl -w
-
-# Copyright (C) 2004 Morten K. Poulsen <morten at afdelingp.dk>
-# Copyright (C) 2004, 2005 Christian Laursen <christian@pil.dk>
-#
-# $Id$
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to
-# deal in the Software without restriction, including without limitation the
-# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-# sell copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-# IN THE SOFTWARE.
-
-# We might want some kind of validation of the values we are about to save,
-# but that would require save.cgi to know about all kind of options that mlmmj
-# accepts. I am not sure we want that. -- mortenp 20040709
-
-use strict;
-use CGI;
-use CGI::FastTemplate;
-use HTML::Entities;
-
-use vars qw($topdir $templatedir $list);
-
-if (exists $ENV{CONFIG_PATH}) {
- require $ENV{CONFIG_PATH};
-} else {
- require "../conf/config.pl";
-}
-
-my $tpl = new CGI::FastTemplate($templatedir);
-
-my $q = new CGI;
-$list = $q->param("list");
-
-die "no list specified" unless $list;
-die "non-existent list" unless -d("$topdir/$list");
-
-$tpl->define(main => "save.html");
-$tpl->assign(LIST => encode_entities($list));
-
-my $tunables_file = "../conf/tunables.pl";
-if (exists $ENV{TUNABLES_PATH}) {
- $tunables_file = $ENV{TUNABLES_PATH};
-}
-
-do $tunables_file;
-
-print "Content-type: text/html\n\n";
-$tpl->parse(CONTENT => "main");
-$tpl->print;
-
-sub mlmmj_boolean {
- my ($name, $nicename, $text) = @_;
-
- my $file = "$topdir/$list/control/$name";
-
- my $value = $q->param($name);
- if ($value) {
- open (FILE, ">$file") or die "Couldn't open $file for writing: $!";
- close FILE;
- } else {
- unlink $file;
- }
-}
-
-sub mlmmj_string {
- mlmmj_list(@_);
-}
-
-sub mlmmj_list {
- my ($name, $nicename, $text) = @_;
-
- my $file = "$topdir/$list/control/$name";
-
- my $value = $q->param($name);
-
- if (defined $value && $value !~ /^\s*$/) {
- $value .= "\n" if $value !~ /\n$/;
- $value =~ s/\s*\r?\n/\n/g;
- open (FILE, ">$file") or die "Couldn't open $file for writing: $!";
- print FILE $value;
- close FILE;
- } else {
- unlink $file;
- }
-}
+++ /dev/null
-#!/usr/bin/perl -w
-
-# Copyright (C) 2007 Franky Van Liedekerke <liedekef@telenet.be>
-#
-# $Id$
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to
-# deal in the Software without restriction, including without limitation the
-# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-# sell copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-# IN THE SOFTWARE.
-
-# We might want some kind of validation of the values we are about to save,
-# but that would require save.cgi to know about all kind of options that mlmmj
-# accepts. I am not sure we want that. -- mortenp 20040709
-
-use strict;
-use CGI;
-use CGI::FastTemplate;
-use HTML::Entities;
-
-use vars qw($topdir $templatedir $list);
-
-if (exists $ENV{CONFIG_PATH}) {
- require $ENV{CONFIG_PATH};
-} else {
- require "../conf/config.pl";
-}
-
-my $tpl = new CGI::FastTemplate($templatedir);
-
-my $q = new CGI;
-$list = $q->param("list");
-
-die "no list specified" unless $list;
-die "non-existent list" unless -d("$topdir/$list");
-
-$tpl->define(main => "save_text.html");
-$tpl->assign(LIST => encode_entities($list));
-
-my $textdir = "$topdir/$list/text";
-my @files;
-opendir(DIR, $textdir ) || die "can't opendir $textdir: $!";
-@files = grep { !/^\./ && -f "$textdir/$_" } readdir(DIR);
-closedir DIR;
-
-for my $textfile (sort @files) {
- mlmmj_text($textfile);
-}
-
-print "Content-type: text/html\n\n";
-$tpl->parse(CONTENT => "main");
-$tpl->print;
-
-sub mlmmj_text {
- my ($name, $nicename, $text) = @_;
-
- my $file = "$textdir/$name";
-
- my $value = $q->param($name);
-
- open (FILE, ">$file") or die "Couldn't open $file for writing: $!";
- print FILE $value;
- close FILE;
-}
+++ /dev/null
-#!/usr/bin/perl -w
-
-# Copyright (C) 2004, 2005, 2006, 2007 Christian Laursen <christian@pil.dk>
-# Copyright (C) 2007 Franky Van Liedekerke <liedekef@telenet.be>
-#
-# $Id$
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to
-# deal in the Software without restriction, including without limitation the
-# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-# sell copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-# IN THE SOFTWARE.
-
-use strict;
-use URI::Escape;
-use HTML::Entities;
-use CGI;
-use CGI::FastTemplate;
-use Digest::MD5;
-
-use vars qw($topdir $templatedir $list);
-
-if (exists $ENV{CONFIG_PATH}) {
- require $ENV{CONFIG_PATH};
-} else {
- require "../conf/config.pl";
-}
-
-my $mlmmjsub = "/usr/local/bin/mlmmj-sub";
-my $mlmmjunsub = "/usr/local/bin/mlmmj-unsub";
-
-my $tpl = new CGI::FastTemplate($templatedir);
-
-my $q = new CGI;
-$list = $q->param("list");
-my $update = $q->param("update");
-my $search = $q->param("search");
-my $email = $q->param("email");
-my $file = $q->param("file");
-my $removeall = $q->param("removeall");
-
-# Everything is submitted from the same form so a little hackery is needed
-# to pick the right action to perform. When doing subscribe and search we
-# don't depend on the submit buttons since hitting enter in either of the
-# text fields will pick the "Subscribe" button.
-#
-# If an email has been entered for subscription, clear the search field.
-
-if (defined $email && $email !~ /^$/) {
- $search = undef;
-} else {
- $email = undef;
-}
-
-die "no list specified" unless $list;
-die "non-existent list" unless -d("$topdir/$list");
-
-$tpl->define(main => "subscribers.html",
- row => "subscribers_row.html");
-
-my $action = '';
-
-my $subscribers;
-my $subcount;
-
-if (defined $removeall) {
- my $removeall_check = $q->param("removeall_check");
- if ($removeall_check) {
- unlink <$topdir/$list/subscribers.d/*>;
- unlink <$topdir/$list/nomailsubs.d/*>;
- unlink <$topdir/$list/digesters.d/*>;
- $action = "All subscribers have been removed.";
- } else {
- $action = "Safety check not clicked, nothing done.";
- }
-} elsif (defined $file) {
- my $subscriber = $q->param("subscriber");
- my $digester = $q->param("digester");
- my $nomailsub = $q->param("nomailsub");
- my $upload_handle = $q->upload("file");
- binmode $upload_handle;
- while (<$upload_handle>) {
- s/\r?\n$//;
- my $email=$_;
- if ($email =~ /^[a-z0-9\.\-_\@]+$/i) {
- if ($subscriber) {
- system "$mlmmjsub -L $topdir/$list -a $email -U -s";
- }
- if ($digester) {
- system "$mlmmjsub -L $topdir/$list -a $email -Ud -s";
- }
- if ($nomailsub) {
- system "$mlmmjsub -L $topdir/$list -a $email -Un -s";
- }
- if ($? == 0) {
- $action .= "$email has been subscribed.<br>\n";
- } else {
- $action .= "error subscribing $email (code $?)<br>\n";
- }
- } else {
- $action .= '"'.encode_entities($email).'" is not a valid email address.<br>';
- }
- }
-} elsif (defined $email) {
- my $subscriber = $q->param("subscriber");
- my $digester = $q->param("digester");
- my $nomailsub = $q->param("nomailsub");
- if ($email =~ /^[a-z0-9\.\-_\@]+$/i) {
- if ($subscriber) {
- system "$mlmmjsub -L $topdir/$list -a $email -U -s";
- }
- if ($digester) {
- system "$mlmmjsub -L $topdir/$list -a $email -Ud -s";
- }
- if ($nomailsub) {
- system "$mlmmjsub -L $topdir/$list -a $email -Un -s";
- }
- if ($? == 0) {
- $action = "$email has been added";
- } else {
- $action = "error adding $email (code $?)";
- }
- } else {
- $action = '"'.encode_entities($email).'" is not a valid email address.';
- }
-} elsif (defined $update) {
- my $maxid = $q->param("maxid");
- $subscribers = get_subscribers();
- for (my $i = 0; $i < $maxid; ++$i) {
- my $email = $q->param("email$i");
- if (defined $email) {
- if ($email =~ /^[a-z0-9\.\-_\@]+$/i) {
- my $updated = 0;
-
- my @actions = ();
-
- push @actions, {oldstatus => exists $subscribers->{$email}->{subscriber},
- newstatus => defined $q->param("subscriber$i"),
- action => ''};
- push @actions, {oldstatus => exists $subscribers->{$email}->{digester},
- newstatus => defined $q->param("digester$i"),
- action => '-d'};
- push @actions, {oldstatus => exists $subscribers->{$email}->{nomailsub},
- newstatus => defined $q->param("nomailsub$i"),
- action => '-n'};
-
- for my $action (@actions) {
- if ($action->{oldstatus} && !$action->{newstatus}) {
- system "$mlmmjunsub -L $topdir/$list -a $email $action->{action}";
- $updated = 1;
- } elsif (!$action->{oldstatus} && $action->{newstatus}) {
- system "$mlmmjsub -L $topdir/$list -a $email $action->{action}";
- $updated = 1;
- }
- }
-
- if ($updated) {
- $action .= "Subscription for $email has been updated.<br>\n";
- }
- } else {
- $action .= '"'.encode_entities($email).'" is not a valid email address.'."<br>\n";
- }
- }
- }
-}
-
-$tpl->assign(ACTION => $action);
-
-$subscribers = get_subscribers();
-
-my $paginator = '';
-my $page = $q->param('page');
-$page = 0 unless defined $page && $page =~ /^\d+$/;
-if (keys %$subscribers > 50) {
- $paginator = 'Pages: ';
- my $pages = (keys %$subscribers) / 50;
- $page = 0 unless ($page >= 0 && $page < $pages);
- my $searchstr = (defined $search && $search ne '') ? '&search='.uri_escape($search) : '';
-
- for (my $i = 0; $ i < $pages; ++$i) {
- if ($page == $i) {
- $paginator .= ($i + 1)." ";
- } else {
- $paginator .= "<a href=\"?list=".uri_escape($list)."&page=$i$searchstr\">".($i + 1)."</a> ";
- }
- }
-}
-
-my $i = 0;
-my @addresses = sort {lc $a cmp lc $b} keys %$subscribers;
-if ($paginator ne '') {
- @addresses = @addresses[$page * 50 .. ($page + 1) * 50 - 1];
- pop @addresses until defined $addresses[@addresses - 1];
-}
-
-for my $address (@addresses) {
- $tpl->assign(EMAIL => $address,
- ID => $i++,
- SCHECKED => $subscribers->{$address}->{subscriber} ? 'checked' : '',
- DCHECKED => $subscribers->{$address}->{digester} ? 'checked' : '',
- NCHECKED => $subscribers->{$address}->{nomailsub} ? 'checked' : '');
- $tpl->parse(ROWS => '.row');
-}
-if (keys %$subscribers == 0) {
- $tpl->assign(ROWS => '');
-}
-
-$tpl->assign(LIST => encode_entities($list),
- MAXID => scalar(@addresses),
- SEARCH => defined $search ? $search : '',
- PAGINATOR => $paginator,
- PAGE => $page,
- SUBCOUNT => $subcount);
-
-print "Content-type: text/html\n\n";
-
-$tpl->parse(CONTENT => "main");
-$tpl->print;
-
-sub get_subscribers {
- my %subscribers = ();
-
- my @subscribers = `/usr/local/bin/mlmmj-list -L $topdir/$list`;
- my @digesters = `/usr/local/bin/mlmmj-list -L $topdir/$list -d`;
- my @nomailsubs = `/usr/local/bin/mlmmj-list -L $topdir/$list -n`;
-
- chomp @subscribers;
- chomp @digesters;
- chomp @nomailsubs;
-
- if (defined $search) {
- $search = lc $search;
- @subscribers = grep {index(lc $_, $search) != -1} @subscribers;
- @digesters = grep {index(lc $_, $search) != -1} @digesters;
- @nomailsubs = grep {index(lc $_, $search) != -1} @nomailsubs;
- }
-
- for my $address (@subscribers) {
- $subscribers{$address}->{subscriber} = 1;
- }
-
- for my $address (@digesters) {
- $subscribers{$address}->{digester} = 1;
- }
-
- for my $address (@nomailsubs) {
- $subscribers{$address}->{nomailsub} = 1;
- }
-
- $subcount = scalar(keys %subscribers);
-
- return \%subscribers;
-}
+++ /dev/null
-<html><head><title>mlmmj config</title></head><body>
-<h1>mlmmj config</h1>
-<p>
-<a href="index.cgi">Index</a> | <a href="subscribers.cgi?list=$LIST">Subscribers</a> | <a href="edit_text.cgi?list=$LIST">Edit texts</a></td>
-</p>
-<p>
-List: $LIST
-</p>
-<form method="post" action="save.cgi">
-<input type="hidden" name="list" value="$LIST">
-<table border="1">
-$ROWS
-</table>
-<input type="submit" name="submit" value="Update configuration" />
-</form>
-</body></html>
+++ /dev/null
-<tr><td>$NICENAME</td><td><input type="checkbox" name="$NAME" value="1"$CHECKED></td><td>$TEXT</td></tr>
+++ /dev/null
-<tr><td>$NICENAME</td><td><textarea name="$NAME" cols="40">$VALUE</textarea></td><td>$TEXT</td></tr>
+++ /dev/null
-<tr><td>$NICENAME</td><td><input type="text" name="$NAME" value="$VALUE"></td><td>$TEXT</td></tr>
+++ /dev/null
-<html><head><title>mlmmj config</title></head><body>
-<h1>mlmmj config</h1>
-<p>
-<a href="index.cgi">Index</a> | <a href="edit.cgi?list=$LIST">Configuration</a> | <a href="subscribers.cgi?list=$LIST">Subscribers</a>
-</p>
-<p>
-List: $LIST
-</p>
-<form method="post" action="save_text.cgi">
-<input type="hidden" name="list" value="$LIST">
-<table border="1">
-$ROWS
-</table>
-<input type="submit" name="submit" value="Update texts" />
-</form>
-</body></html>
+++ /dev/null
-<tr><td>$NAME</td><td><textarea name="$NAME" rows="10" cols="70">$VALUE</textarea></td></tr>
+++ /dev/null
-<html><head><title>mlmmj config</title></head><body>
-<h1>mlmmj config</h1>
-<table border="1">
-$LISTS
-</table>
-</body></html>
+++ /dev/null
-<tr><td>$LIST</td><td><a href="edit.cgi?list=$ULIST">Configure</a></td><td><a href="subscribers.cgi?list=$ULIST">Subscribers</a></td><td><a href="edit_text.cgi?list=$ULIST">Edit texts</a></td></tr>
+++ /dev/null
-<html><head><title>mlmmj config</title></head><body>
-<h1>mlmmj config</h1>
-<p>
-$LIST control values saved!
-</p>
-<p>
-<a href="index.cgi">Index</a> | <a href="edit.cgi?list=$LIST">Configuration</a> | <a href="edit_text.cgi?list=$LIST">Edit texts</a></td>
-</p>
-</body></html>
+++ /dev/null
-<html><head><title>mlmmj config</title></head><body>
-<h1>mlmmj config</h1>
-<p>
-$LIST text values saved!
-</p>
-<p>
-<a href="index.cgi">Index</a> | <a href="edit.cgi?list=$LIST">Configuration</a> | <a href="edit_text.cgi?list=$LIST">Edit texts</a></td>
-</p>
-</body></html>
+++ /dev/null
-<html><head><title>mlmmj subscribers</title></head><body>
-<h1>mlmmj subscribers</h1>
-<p>
-<a href="index.cgi">Index</a> | <a href="subscribers.cgi?list=$LIST">Reload subscriber list</a> | <a href="edit.cgi?list=$LIST">Configuration</a> | <a href="edit_text.cgi?list=$LIST">Edit texts</a></td>
-</p>
-<p>
-$ACTION
-</p>
-<hr>
-<form action="subscribers.cgi" method="post" onSubmit="if (window.confirm('Are you sure you want to do this?')) this.submit(); else return false;">
-<input type="hidden" name="list" value="$LIST">
-<input type="hidden" name="maxid" value="$MAXID">
-<input type="hidden" name="removeall" value="1">
-<table><tr><td rowspan="5" valign="top">Remove all subscribers: </td>
-<td><input type="submit" name="remove" value="Remove all"></td></tr>
-<tr><td>Click this as extra safety check: <input type="checkbox" name="removeall_check" value="1" unchecked></td></tr>
-</table>
-</form>
-<hr>
-<form action="subscribers.cgi" method="post" enctype="multipart/form-data">
-<input type="hidden" name="list" value="$LIST">
-<input type="hidden" name="maxid" value="$MAXID">
-<input type="hidden" name="page" value="$PAGE">
-<table><tr><td rowspan="5" valign="top">Bulk add subscribers: </td>
-<td>File: <input type="FILE" name="file"></td></tr>
-<tr><td>Normal subscribers: <input type="checkbox" name="subscriber" value="1" checked></td></tr>
-<tr><td>Digest subscribers: <input type="checkbox" name="digester" value="1"></td></tr>
-<tr><td>No-mail subscribers: <input type="checkbox" name="nomailsub" value="1"></td></tr>
-<tr><td><input type="submit" name="subscribe" value="Subscribe"></td></tr>
-</table>
-</form>
-
-<form action="subscribers.cgi" method="post">
-<input type="hidden" name="list" value="$LIST">
-<input type="hidden" name="maxid" value="$MAXID">
-<input type="hidden" name="page" value="$PAGE">
-<table><tr><td rowspan="5" valign="top">Add subscriber: </td>
-<td>Email address: <input type="text" name="email"></td></tr>
-<tr><td>Normal subscriber: <input type="checkbox" name="subscriber" value="1" checked></td></tr>
-<tr><td>Digest subscriber: <input type="checkbox" name="digester" value="1"></td></tr>
-<tr><td>No-mail subscriber: <input type="checkbox" name="nomailsub" value="1"></td></tr>
-<tr><td><input type="submit" name="subscribe" value="Subscribe"></td></tr>
-
-<tr><td rowspan="2" valign="top">Search for subscriber:</td>
-<td>Email address: <input type="text" name="search" value="$SEARCH"></td></tr>
-<tr><td><input type="submit" name="searchsubmit" value="Search"></td></tr>
-</table>
-<hr>
-<p>
-List: $LIST<br>
-Subscribers: $SUBCOUNT
-</p>
-<hr>
-$PAGINATOR
-<table border="1">
-<tr><th>Email address</th><th>Normal subscriber</th><th>Digest subscriber</th><th>No-mail subscriber</th></tr>
-$ROWS
-</table>
-$PAGINATOR
-<p><input type="submit" name="update" value="Update subscriptions"></p>
-</form>
-</body></html>
+++ /dev/null
-<tr>
- <td>$EMAIL<input type="hidden" name="email$ID" value="$EMAIL"></td>
- <td><input type="checkbox" name="subscriber$ID" value="1" $SCHECKED></td>
- <td><input type="checkbox" name="digester$ID" value="1" $DCHECKED></td>
- <td><input type="checkbox" name="nomailsub$ID" value="1" $NCHECKED></td>
-</tr>
+++ /dev/null
-$topdir = "/var/spool/mlmmj";
-$sendmail = "/usr/lib/sendmail";
-$delimiter = "+";
+++ /dev/null
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
-<html>
-<head>
-<title>mlmmj-webinterface</title>
-</head>
-<body>
-
-<p>
-<h1>subscribe</h1>
-<form action="mlmmj.cgi" method="post">
-<!--input name="mailinglist" type="hidden" value="mlmmj-test@domain.tld"-->
-<input name="mailinglist" type="hidden" value="mlmmj-test@ms.webdmz.tv2.dk">
-<input name="job" type="hidden" value="subscribe">
-<input name="redirect_failure" type="hidden" value="http://www.failure.com/">
-<input name="redirect_success" type="hidden" value="http://www.success.com/">
-<input name="email" type="text" size="30" maxlength="254"><br>
-<input type="submit" value="Subscribe">
-</form>
-</p>
-
-<p>
-<h1>unsubscribe</h1>
-<form action="mlmmj.cgi" method="post">
-<input name="mailinglist" type="hidden" value="mlmmj-test@domain.tld">
-<input name="job" type="hidden" value="unsubscribe">
-<input name="redirect_failure" type="hidden" value="http://www.failure.com/">
-<input name="redirect_success" type="hidden" value="http://www.success.com/">
-<input name="email" type="text" size="30" maxlength="254"><br>
-<input type="submit" value="Unsubscribe">
-</form>
-</p>
-
-</body>
-</html>
+++ /dev/null
-#!/usr/bin/perl
-
-# Copyright (C) 2004 Morten K. Poulsen <morten at afdelingp.dk>
-#
-# $Id$
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to
-# deal in the Software without restriction, including without limitation the
-# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-# sell copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-# IN THE SOFTWARE.
-
-use CGI qw(:standard);
-
-require "config.pl";
-
-
-# You might want to customize this function if you are not running the web
-# server on the same host as the mail server running the lists, or if your
-# lists are not in $topdir/list-name.
-sub mlmmj_check_list {
- my $list = shift;
-
- if ($list !~ /^([a-z0-9-.]+)\@/) {
- return false;
- }
-
- if (!-f "$topdir/$1/control/listaddress") {
- return false;
- }
-
- open(FILE, "$topdir/$1/control/listaddress") or die('unable to open control/listaddress');
- $listaddr = readline(FILE);
- chomp($listaddr);
- if ($list ne $listaddr) {
- return false;
- }
-
- return true;
-}
-
-
-sub mlmmj_mail {
- my $from = shift;
- my $to = shift;
- my $subject = shift;
- my $body = shift;
- my $date = `/bin/date -R`;
-
- $mail = "Received: from " . $query->remote_addr()
- . " by " . $query->server_name() . " with HTTP;\n"
- . "\t$date"
- . "X-Originating-IP: " . $query->remote_addr() . "\n"
- . "X-Mailer: mlmmj-webinterface powered by Perl\n"
- . "Date: $date"
- . "From: $from\n"
- . "To: $to\n"
- . "Subject: $subject\n"
- . "\n"
- . "$body\n";
- open(P, "|$sendmail -i -t") or die('unable to send mail');
- print(P $mail);
- close(P);
-}
-
-
-sub mlmmj_gen_to {
- my $list = shift;
- my $job = shift;
-
- if (($job ne 'subscribe') && ($job ne 'unsubscribe')) {
- return false;
- }
- ($user, $domain) = split(/@/, $list);
-
- return sprintf("%s%s%s@%s", $user, $delimiter, $job, $domain);
-}
-
-sub check_email {
- my $addr = shift;
-
- if ($addr !~ /^[-!#$%&\'*+\.\/0-9=?A-Z^_a-z{|}~]+@[-0-9A-Za-z]+\.[-\.0-9A-Za-z]+$/) {
- return false;
- } else {
- return true;
- }
-}
-
-$query = new CGI;
-
-$list = $query->param('mailinglist');
-$job = $query->param('job');
-$redirect_failure = $query->param('redirect_failure');
-$redirect_success = $query->param('redirect_success');
-$email = $query->param('email');
-
-if (mlmmj_check_list($list) ne false && check_email($email) ne false)) {
- $to = mlmmj_gen_to($list, $job);
- if ($to ne false) {
- mlmmj_mail($email, $to, "$job to $list", $job);
-
- print $query->redirect($redirect_success);
- exit(0);
- }
-}
-
-print $query->redirect($redirect_failure);
+++ /dev/null
-mlmmj-1.0.0 August 31th 2004
-
-To use this web-interface you have to:
-
-1) Copy the files from the php-admin directory of the mlmmj distribution to a
- suitable location and point your webroot to the htdocs directory. If you
- don't want the webinterface in the root of your website it is recommended to
- make an alias in your web server configuration in order to keep the conf
- directory at the same level as the htdocs directory and still outside
- webscope. If you want to keep it somewhere else, you will need to modify
- the first line of code in index.php, edit.php and save.php.
-
-2) If your lists are stored somewhere other than /var/spool/mlmmj, edit
- conf/config.php to reflect this.
-
-3) Change the permissions of the listdir/control directories of any list you
- want to control using the web-interface, so the web server can write in it:
-
- # chown -R wwwrun /var/spool/mlmmj/mlmmj-test/control/
-
-4) If the web server does not run as the same user the mailserver writes as
- you need to create a group (eg. mlmmj) and add both users to it. The
- subscribers.d directory then needs to be writable by that group:
-
- # addgroup mlmmj
- # adduser wwwrun mlmmj
- # adduser mailuser mlmmj
- # chgrp -R mlmmj /var/spool/mlmmj/mlmmj-test/subscribers.d/
- # chmod -R g+w /var/spool/mlmmj/mlmmj-test/subscribers.d/
- # chmod g+s /var/spool/mlmmj/mlmmj-test/subscribers.d/
-
- setgid flag is needed when the webserver calls mlmmj-sub and creates a file
- under subscribers.d, to keep the mlmmj group.
-
- If using the Exim mailserver, you should add initgroups = true in your
- mlmmj_transport, otherwise it won't be able to write files having write
- permission to mlmmj group.
-
-5) To enable access control on Apache you have to rename dot.htaccess to
- .htaccess and edit the path inside the file to point to a htpasswd file
- somewhere outside the webscope.
-
- If you don't have one already, you can create one like this
-
- htpasswd -c /home/mlmmj/htpasswd USER
-
- It will then ask you for a password for the given username.
-
-6) That is it, you are ready to use the interface.
+++ /dev/null
-<?php
-
-$topdir = "/var/spool/mlmmj";
-$confdir = dirname(__FILE__);
-$templatedir = dirname(dirname(__FILE__))."/templates";
-
-?>
+++ /dev/null
-mlmmj_list("listaddress",
- "List address",
- "This option contains all addresses which mlmmj sees as listaddresses (see ".
- "tocc below). The first one is the one used as the primary one, when mlmmj ".
- "sends out mail.");
-
-mlmmj_boolean("closedlist",
- "Closed list",
- "If the list is open or closed. If it's closed subscription ".
- "and unsubscription via mail is disabled.");
-
-mlmmj_boolean("closedlistsub",
- "Closed for subscription",
- "Closed for subscription. Unsubscription is possible.");
-
-mlmmj_boolean("nosubconfirm",
- "No subscribe confirmation",
- "If this option is set, the user is not required to confirm when subscribing or unsubscribing.");
-
-mlmmj_boolean("moderated",
- "Moderated",
- "If this option is set, the emailaddresses in the file listdir/control/moderators will act as moderators for the list.");
-
-mlmmj_list("moderators",
- "Moderators",
- "If the list is moderated, this is the list of moderators.");
-
-mlmmj_list("submod",
- "Subscription moderators",
- "This is the list of moderators that will approve subscriptions.");
-
-mlmmj_boolean("tocc",
- "To: Cc:",
- "If this option is set, the list address does not have to be in the To: or Cc: header of the email to the list.");
-
-mlmmj_boolean("addtohdr",
- "Add To: header",
- "If this option is set, a To: header including the recipients emailaddress will be added to outgoing mail. ".
- "Recommended usage is to remove existing To: headers with delheaders (see below) first.");
-
-mlmmj_boolean("subonlypost",
- "Subscribers only post",
- "If this option is set, only people who are subscribed to the list, are allowed to post to it. ".
- "The check is made against the \"From:\" header.");
-
-mlmmj_boolean("modonlypost",
- "Moderators only post",
- "When this file is present, only people listed in listdir/control/moderators ".
- "are allowed to post to it. The check is made against the "From:" header.");
-
-mlmmj_boolean("modnonsubposts",
- "Moderate non-allowed posts",
- "If this option is set, postings from people who are not allowed to post ".
- "to the list will be moderated instead of denied.");
-
-mlmmj_string("modreqlife",
- "Moderation request lifetime",
- "This specifies how long in seconds a mail awaits moderation before it's ".
- "discarded. Defaults to 604800 seconds, which is 7 days.");
-
-mlmmj_string("prefix",
- "Prefix",
- "The prefix for the Subject: line of mails to the list. This will alter the Subject: line, ".
- "and add a prefix if it's not present elsewhere.");
-
-mlmmj_list("owner",
- "Owner",
- "The emailaddresses in this list will get mails to ".encode_entities($list)."+owner");
-
-mlmmj_list("customheaders",
- "Custom headers",
- "These headers are added to every mail coming through. This is ".
- "the place you want to add Reply-To: header in case you want ".
- "such. ".
- "If a header should not occur twice in the mail it should be listed in the 'Delete headers' box too.");
-
-mlmmj_list("delheaders",
- "Delete headers",
- "In this file is specified *ONE* headertoken to match pr. line. ".
- "If the file consists of: Received: Message-ID: Then all occurences of these headers in incoming list mail will be deleted. ".
- "\"From \" and \"Return-Path:\" are deleted no matter what.");
-
-mlmmj_list("access",
- "Access",
- "If this option is set, all headers of a post to the list is matched against the rules. The first rule to match wins. ".
- "See README.access for syntax and examples. NOTE: If this field is empty access control is *disabled*, ".
- "unlike having an empty control/access file.");
-
-mlmmj_string("memorymailsize",
- "Memory mail size",
- "Here is specified in bytes how big a mail can be and still be prepared for sending in memory. ".
- "It's greatly reducing the amount of write system calls to prepare it in memory before sending it, ".
- "but can also lead to denial of service attacks. Default is 16k (16384 bytes).");
-
-mlmmj_string("relayhost",
- "Relay host",
- "The host specified (IP address or domainname, both works) in this file will be used for relaying the mail sent to the list. ".
- "Defaults to 127.0.0.1.");
-
-mlmmj_string("smtpport",
- "SMTP port",
- "In this file a port other than port 25 for connecting to the relayhost can be specified.");
-
-mlmmj_string("delimiter",
- "Delimiter",
- "This specifies what to use as recipient delimiter for the list.".
- "Default is '+'.");
-
-mlmmj_boolean("notifysub",
- "Notify subscribers",
- "If this option is set, the owner(s) will get a mail with the address of someone sub/unsubscribing to a mailinglist.");
-
-mlmmj_boolean("notifymod",
- "Notify moderation",
- "If this option is set, the poster (based on the envelope from) will ".
- "get a mail when their post is being moderation.");
-
-mlmmj_string("digestinterval",
- "Digest interval",
- "This option specifies how many seconds will pass before the ".
- "next digest is sent. Defaults to 604800 seconds, which is 7 ".
- "days.");
-
-mlmmj_string("digestmaxmails",
- "Max. digest mails",
- "This option specifies how many mails can accumulate before ".
- "digest sending is triggered. Defaults to 50 mails, meaning ".
- "that if 50 mails arrive to the list before digestinterval have ".
- "passed, the digest is delivered.");
-
-mlmmj_string("bouncelife",
- "Bouncing lifetime",
- "This specifies how long in seconds an address can bounce before it's ".
- "unsubscribed. Defaults to 432000 seconds, which is 5 days.");
-
-mlmmj_boolean("noarchive",
- "No archive",
- "If this option is set, the mails won't be saved in the ".
- "archive but simply deleted");
-
-mlmmj_boolean("noget",
- "No get",
- "If this option is set, listname+get-INDEX is turned off.");
-
-mlmmj_boolean("subonlyget",
- "Subscribers only get",
- "If this option is set, retrieving old posts with +get-N is only possible for subscribers.");
-
-mlmmj_string("verp",
- "VERP",
- "Enable VERP support. Anything added in this variable will be appended the ".
- "MAIL FROM: line. If 'postfix' is put in the file, it'll make postfix use ".
- "VERP by adding XVERP=-= to the MAIL FROM: line.");
-
-mlmmj_string("maxverprecips",
- "Maximum VERP recipients",
- "How many recipients pr. mail delivered to the smtp server. Defaults to 100.");
-
-mlmmj_boolean("notoccdenymails",
- "No To: Cc: deny mails",
- "This switch turns off whether mlmmj sends out notification about postings ".
- "being denied due to the listaddress not being in To: or Cc: (see 'tocc').");
-
-mlmmj_boolean("noaccessdenymails",
- "No access deny mails",
- "This switch turns off whether mlmmj sends out notification about postings ".
- "being rejected due to an access rule (see 'access').");
-
-mlmmj_boolean("nosubonlydenymails",
- "No subscribers only deny mails",
- "This switch turns off whether mlmmj sends out notification about postings ".
- "being rejected due to a subscribers only posting list (see 'subonlypost').");
-
-mlmmj_boolean("nomodonlydenymails",
- "No moderators only deny mails",
- "This switch turns off whether mlmmj sends out notification about postings ".
- "being rejected due to a moderators only posting list (see 'modonlypost').");
-
-mlmmj_boolean("nosubmodmails",
- "No subscription moderated mails",
- "This switch turns off whether mlmmj sends out notification about ".
- "subscription being moderated to the person requesting subscription".
- "(see 'submod').");
-
-mlmmj_boolean("nodigesttext",
- "No digest text summary",
- "This switch turns off whether digest mails will have a text part with a thread ".
- "summary.");
-
-mlmmj_boolean("nodigestsub",
- "No digest subscribers",
- "If this option is set, subscription to the digest version of the mailinglist ".
- "will be denied. (Useful if you don't want to allow digests and notify users ".
- "about it).");
-
-mlmmj_boolean("nonomailsub",
- "No nomail subscribers",
- "If this option is set, subscription to the nomail version of the mailinglist ".
- "will be denied. (Useful if you don't want to allow nomail and notify users ".
- "about it).");
-
-mlmmj_string("maxmailsize",
- "Max. mail size",
- "With this option the maximal allowed size of incoming mails can be specified.");
-
-mlmmj_boolean("nomaxmailsizedenymails",
- "No max. mail size deny mails",
- "If this is set, no reject notifications caused by violation of maxmailsize ".
- "will be sent.");
-
-mlmmj_boolean("nolistsubsemail",
- "No list subscribers email",
- "If this is set, the LISTNAME+list\@ functionality for requesting an ".
- "email with the subscribers for owner is disabled.");
-
-mlmmj_string("staticbounceaddr",
- "Static bounce address",
- "If this is set to something\@example.org, the bounce address (Return-Path:) ".
- "will be fixed to something+listname-bounces-and-so-on\@example.org ".
- "in case you need to disable automatic bounce handling.");
-
-mlmmj_boolean("ifmodsendonlymodmoderate",
- "If moderator send only moderator moderate",
- "If this is set, then mlmmj in case of moderation checks the ".
- "envelope from, to see if the sender is a moderator, and in that case ".
- "only send the moderation mails to that address. In practice this means that ".
- "a moderator sending mail to the list won't bother all the other moderators ".
- "with his mail.");
-
-mlmmj_list("footer",
- "Footer",
- "The content of this option is appended to mail sent to the list.");
-
-mlmmj_boolean("notmetoo",
- "Not me too",
- "If this is set, mlmmj attempts to exclude the sender of a post ".
- "from the distribution list for that post so people don't receive copies ".
- "of their own posts.");
-
-mlmmj_string("smtphelo",
- "SMTP Helo Name",
- "When this file is present, it contains the hostname to send in the SMTP ".
- "EHLO or HELO command. Otherwise the machine hostname is used.");
+++ /dev/null
-<?php
-//
-// Copyright © 2000-2001, Roland Roberts <roland@astrofoto.org>
-// 2001 Alister Bulman <alister@minotaur.nu> Re-Port multi template-roots + more
-// PHP3 Port: Copyright © 1999 CDI <cdi@thewebmasters.net>, All Rights Reserved.
-// Perl Version: Copyright © 1998 Jason Moore <jmoore@sober.com>, All Rights Reserved.
-//
-// RCS Revision
-// @(#) $Id$
-// $Source$
-//
-// Copyright Notice
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2, or (at your option)
-// any later version.
-//
-// class.rFastTemplate.php is distributed in the hope that it will be
-// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// General Public License for more details.
-//
-// Comments
-//
-// I would like to thank CDI <cdi@thewebmasters.net> for pointing out the
-// copyright notice attached to his PHP3 port which I had blindly missed
-// in my first release of this code.
-//
-// This work is derived from class.FastTemplate.php3 version 1.1.0 as
-// available from http://www.thewebmasters.net/. That work makes
-// reference to the "GNU General Artistic License". In correspondence
-// with the author, the intent was to use the GNU General Public License;
-// this work does the same.
-//
-// Authors
-//
-// Roland Roberts <roland@astrofoto.org>
-// Alister Bulman <alister@minotaur.nu> (multi template-roots)
-// Michal Rybarik <michal@rybarik.sk> (define_raw())
-// CDI <cdi@thewebmasters.net>, PHP3 port
-// Jason Moore <jmoore@sober.com>, original Perl version
-//
-// Synopsis
-//
-// require ("PATH-TO-TEMPLATE-CODE/class.Template.php");
-// $t = new Template("PATH-TO-TEMPLATE-DIRECTORY");
-// $t->define (array(MAIN => "diary.html"));
-// $t->setkey (VAR1, "some text");
-// $t->subst (INNER, "inner")
-// $t->setkey (VAR1, "some more text");
-// $t->subst (INNER, ".inner")
-// $t->setkey (VAR2, "var2 text");
-// $t->subst (CONTENT, "main");
-// $t->print (CONTENT);
-//
-// Description
-//
-// This is a class.FastTemplate.php3 replacement that provides most of the
-// same interface but has the ability to do nested dynamic templates. The
-// default is to do dynamic template expansion and no special action is
-// required for this to happen.
-//
-// class.FastTemplate.php3 Methods Not Implemented
-//
-// clear_parse
-// Same as clear. In fact, it was the same as clear in FastTemplate.
-// clear_all
-// If you really think you need this, try
-// unset $t;
-// $t = new Template ($path);
-// which gives the same effect.
-// clear_tpl
-// Use unload instead. This has the side effect of unloading all parent
-// and sibling templates which may be more drastic than you expect and
-// is different from class.FastTemplate.php3. This difference is
-// necessary since the only way we can force the reload of an embedded
-// template is to force the reload of the parent and sibling templates.
-//
-// class.FastTemplate.php3 Methods by Another Name
-//
-// The existence of these functions is a historical artifact. I
-// originally had in mind to write a functional equivalent from scratch.
-// Then I came my senses and just grabbed class.FastTemplate.php3 and
-// started hacking it. So, you can use the names on the right, but the
-// ones on the left are equivalent and are the names used in the original
-// class.FastTemplate.php3.
-//
-// parse --> subst
-// get_assiged --> getkey
-// assign --> setkey
-// clear_href --> unsetkey
-// clear_assign --> unsetkey
-// FastPrint --> xprint
-//
-
-class rFastTemplate {
-
- // File name to be used for debugging output. Needs to be set prior to
- // calling anything other than option setting commands (debug, debugall,
- // strict, dynamic) because once the file has been opened, this is ignored.
- var $DEBUGFILE = '/tmp/class.rFastTemplate.php.dbg';
-
- // File descriptor for debugging output.
- var $DEBUGFD = -1;
-
- // Array for individual member functions. You can turn on debugging for a
- // particular member function by calling $this->debug(FUNCTION_NAME)
- var $DEBUG = array ();
-
- // Turn this on to turn on debugging in all member functions via
- // $this->debugall(). Turn if off via $this->debugall(false);
- var $DEBUGALL = false;
-
- // Names of actual templates. Each element will be an array with template
- // information including is originating file, file load status, parent
- // template, variable list, and actual template contents.
- var $TEMPLATE = array();
-
- // Holds paths-to-templates (See: set_root and FindTemplate)
- var $ROOT = array();
-
- // Holds the HANDLE to the last template parsed by parse()
- var $LAST = '';
-
-
- // Strict template checking. Unresolved variables in templates will generate a
- // warning.
- var $STRICT = true;
-
- // If true, this suppresses the warning generated by $STRICT=true.
- var $QUIET = false;
-
- // If true, throw an error if the template file is empty. This was previously the default
- // behavior. I'm not sure how this compares to the original FastTemplate().
- var $NOEMPTY = false;
-
- // If true, a non-existent directory in the template path will not
- // generate an error. This was added to allow a directory to be
- // prepended to the template path array based on where in the directory
- // tree we are. If the template path is non-existent, it is skipped.
- var $MISSING_DIR_OKAY = false;
-
- // Holds handles assigned by a call to parse().
- var $HANDLE = array();
-
- // Holds all assigned variable names and values.
- var $VAR = array();
-
- // Set to true is this is a WIN32 server. This was part of the
- // class.FastTemplate.php3 implementation and the only real place it kicks
- // in is in setting the terminating character on the value of $ROOT, the
- // path where all the templates live.
- var $WIN32 = false;
-
- // Automatically scan template for dynamic templates and assign new values
- // to TEMPLATE based on whatever names the HTML comments use. This can be
- // changed up until the time the first parse() is called. Well, you can
- // change it anytime, but it will have no effect on already loaded
- // templates. Also, if you have dynamic templates, the first call to parse
- // will load ALL of your templates, so changing it after that point will
- // have no effect on any defined templates.
- var $DYNAMIC = true;
-
- // Grrr. Don't try to break these extra long regular expressions into
- // multiple lines for readability. PHP 4.03pl1 chokes on them if you do.
- // I'm guessing the reason is something obscure with the parenthesis
- // matching, the same sort of thing Tcl might have, but I'm not sure.
-
- // Regular expression which matches the beginning of a dynamic/inferior
- // template. The critical bit is that we need two parts: (1) the entire
- // match, and (2) the name of the dynamic template. The first part is
- // required because will do a strstr() to split the buffer into two
- // pieces: everything before the dynamic template declaration and
- // everything after. The second is needed because after finding a BEGIN
- // we will search for an END and they both have to have the same name of
- // we consider the template malformed and throw and error.
-
- // Both of these are written with PCRE (Perl-Compatible Regular
- // Expressions) because we need the non-greedy operators to insure that
- // we don't read past the end of the HTML comment marker in the case that
- // the BEGIN/END block have trailing comments after the tag name.
- var $REGEX_DYNBEG = '/(<!--\s*BEGIN\s+DYNAMIC\s+BLOCK:\s*([A-Za-z][-_A-Za-z0-9.]+)\n?(\s*|\s+.*?)-->)/s';
-
- // Regular expression which matches the end of a dynamic/inferior
- // template; see the comment about on the BEGIN match.
- var $REGEX_DYNEND = '/(<!--\s*END\s+DYNAMIC\s+BLOCK:\s*([A-Za-z][-_A-Za-z0-9.]+)(\s*|\s+.*?)-->)/s';
- // Regular expression which matches a variable in the template.
-
- var $REGEX_VAR = '/\{[A-Za-z][-_A-Za-z0-9]*\}/';
- //
- // Description
- // Constructor.
- //
- function rFastTemplate ($pathToTemplates = '') {
-
- // $pathToTemplates can also be an array of template roots, handled in set_root
- global $php_errormsg;
- if (!empty($pathToTemplates)) {
- $this->set_root ($pathToTemplates);
- }
- $this->DEBUG = array ('subst' => false,
- 'parse_internal' => false,
- 'parse_internal_1' => false,
- 'parsed' => false,
- 'clear' => false,
- 'clear_dynamic' => false,
- 'load' => false);
-
- return $this;
- }
-
- //
- // Description
- // Set the name to be used for debugging output. If another file has
- // already been opened, close it so the next call to logwrite will
- // reopen under this name.
- //
- function debugfile ($name) {
- $this->DEBUGFILE = $name;
- }
-
- //
- // Description
- // Turn on/off debugging output of an individual member function.
- //
- function debug ($what, $on = true) {
- $this->DEBUG[$what] = $on;
- }
-
- //
- // Description
- // Turn on/off debugging output of all member functions.
- //
- function debugall ($on = true) {
- $this->DEBUGALL = $on;
- }
-
- //
- // Description
- // Turn on/off automatic dynamic template expansion. Note that a
- // template with an inferior dynamic template embedded will still
- // parse but only as if it were part of the main template. When this
- // is turned on, it will be parsed out as as if it were a full-blown
- // template and can thus be both parsed and appended to as a separate
- // entity.
- //
- function dynamic ($on = true) {
- $this->DYNAMIC = $on;
- }
-
- //
- // Description
- // Turn on/off strict template checking. When on, all template tags
- // must be assigned or we throw an error (but stilll parse the
- // template).
- //
- function strict ($on = true) {
- $this->STRICT = $on;
- }
-
- function quiet ($on = true) {
- $this->QUIET = $on;
- }
-
- //
- // Description
- // For compatibility with class.FastTemplate.php3.
- //
- function no_strict () {
- $this->STRICT = false;
- }
-
- //
- // Description
- // Turn off errors for missing template directories. This allows you
- // to specify a template path that may not yet exist.
- //
- function missing_dir_okay ($on = true) {
- $this->MISSING_DIR_OKAY = $on;
- }
-
- //
- // Description
- // Utility function for debugging.
- //
- function logwrite ($msg) {
- if ($this->DEBUGFD < 0) {
- $this->DEBUGFD = fopen ($this->DEBUGFILE, 'a');
- }
- fputs ($this->DEBUGFD,
- strftime ('%Y/%m/%d %H:%M:%S ') . $msg . "\n");
- }
-
- //
- // Description
- // This was lifted as-is from class.FastTemplate.php3. Based on what
- // platform is in use, it makes sure the path specification ends with
- // the proper path separator; i.e., a slash on unix systems and a
- // back-slash on WIN32 systems. When we can run on Mac or VMS I guess
- // we'll worry about other characters....
- //
- // $root can now be an array of template roots which will be searched to
- // find the first matching name.
- function set_root ($root) {
-
- if (!is_array($root)) {
- $trailer = substr ($root, -1);
- if ($trailer != ($this->WIN32 ? '\\' : '/'))
- $root .= ($this->WIN32 ? '\\' : '/');
-
- if (!is_dir($root)) {
- if (!$this->MISSING_DIR_OKAY)
- $this->error ("Specified ROOT dir [$root] is not a directory", true);
- return false;
- }
- $this->ROOT[] = $root;
- } else {
- reset($root);
- while(list($k, $v) = each($root)) {
- if (is_dir($v)) {
- $trailer = substr ($v,-1);
- if ($trailer != ($this->WIN32 ? '\\' : '/'))
- $v .= ($this->WIN32 ? '\\' : '/');
- $this->ROOT[] = $v;
- } else if (!$this->MISSING_DIR_OKAY) {
- $this->error ("Specified ROOT dir [$v] is not a directory", true);
- }
- }
- }
- // FIXME: should add something here to make sure there is at least one
- // entry in ROOT[].
- }
-
- //
- // Description
- // Associate files with a template names.
- //
- // Sigh. At least with the CVS version of PHP, $dynamic = false sets it
- // to true.
- //
- function define ($fileList, $dynamic = 0) {
- reset ($fileList);
- while (list ($tpl, $file) = each ($fileList)) {
- $this->TEMPLATE[$tpl] = array ('file' => $file, 'dynamic' => $dynamic);
- }
- return true;
- }
-
- function define_dynamic ($tplList, $parent='') {
- if (is_array($tplList)) {
- reset ($tplList);
- while (list ($tpl, $parent) = each ($tplList)) {
- $this->TEMPLATE[$tpl]['parent'] = $parent;
- $this->TEMPLATE[$tpl]['dynamic'] = true;
- }
- } else {
- // $tplList is not an array, but a single child/parent pair.
- $this->TEMPLATE[$tplList]['parent'] = $parent;
- $this->TEMPLATE[$tplList]['dynamic'] = true;
- }
- }
-
- //
- // Description
- // Defines a template from a string (not a file). This function has
- // not been ported from original PERL module to CDI's
- // class.FastTemplate.php3, and it comebacks in rFastTemplate
- // class. You can find it useful if you want to use templates, stored
- // in database or shared memory.
- //
- function define_raw ($stringList, $dynamic = 0) {
- reset ($stringList);
- while (list ($tpl, $string) = each ($stringList)) {
- $this->TEMPLATE[$tpl] = array ('string' => $string, 'dynamic' => $dynamic, 'loaded' => 1);
- }
- return true;
- }
-
- //
- // Description
- // Try each directory in our list of possible roots in turn until we
- // find a matching template
- //
- function FindTemplate ($file) {
- // first try for a template in the current directory short path for
- // absolute filenames
- if (substr($file, 0, 1) == '/') {
- if (file_exists($file)) {
- return $file;
- }
- }
-
- // search path for a matching file
- reset($this->ROOT);
- while(list($k, $v) = each($this->ROOT)) {
- $f = $v . $file;
- if (file_exists($f)) {
- return $f;
- }
- }
-
- $this->error ("FindTemplate: file $file does not exist anywhere in " . implode(' ', $this->ROOT), true);
- return false;
- }
-
-
- //
- // Description
- // Load a template into memory from the underlying file.
- //
- function &load ($file) {
- $debug = $this->DEBUGALL || $this->DEBUG['load'];
- if (! count($this->ROOT)) {
- if ($debug)
- $this->logwrite ("load: cannot open template $file, template base directory not set");
- $this->error ("cannot open template $file, template base directory not set", true);
- return false;
- } else {
- $contents = '';
- unset ($contents);
-
- $filename = $this->FindTemplate ($file);
-
- if ($filename)
- @ $contents = implode ('', (@file($filename)));
- // This is inconsistent and depends on the setting of track_errors. First, with no
- // @-directive above, the error will be reported immediately. Second, if the template
- // is empty, it may be that no error occurred and we still end up here. To get around
- // this, we explicitly unset $contents and then check to see if it isset(). If so,
- // the template was empty and we treat that as a non-error.
- if (isset($contents) && ($this->NOEMPTY && empty($contents)) ) {
- if ($debug)
- $this->logwrite ("load($file): empty template file");
- $this->error ("load($file): empty template file", true);
- } else if (!isset($contents)) {
- if ($debug)
- $this->logwrite ("load($file) failure: $php_errormsg");
- $this->error ("load($file): failure: $php_errormsg", true);
- } else {
- if ($debug)
- $this->logwrite ("load: found $filename");
- return $contents;
- }
- }
- }
-
- //
- // Description
- // Recursive internal parse routine. This will recursively parse a
- // template containing dynamic inferior templates. Each of these
- // inferior templates gets their own entry in the TEMPLATE array.
- //
- function &parse_internal_1 ($tag, $rest = '') {
- $debug = $this->DEBUGALL || $this->DEBUG['parse_internal_1'];
- if (empty($tag)) {
- $this->error ("parse_internal_1: empty tag invalid", true);
- }
- if ($debug)
- $this->logwrite ("parse_internal_1 (tag=$tag, rest=$rest)");
- while (!empty($rest)) {
- if ($debug)
- $this->logwrite ('parse_internal_1: REGEX_DYNBEG search: rest => ' . $rest);
- if (preg_match ($this->REGEX_DYNBEG, $rest, $dynbeg)) {
- // Found match, now split into two pieces and search the second
- // half for the matching END. The string which goes into the
- // next element includes the HTML comment which forms the BEGIN
- // block.
- if ($debug)
- $this->logwrite ('parse_internal_1: match beg => ' . $dynbeg[1]);
- $pos = strpos ($rest, $dynbeg[1]);
-
- // See if the text on either side of the BEGIN comment is only
- // whitespace. If so, we delete the entire line.
- $okay = false;
- for ($offbeg = $pos - 1; $offbeg >= 0; $offbeg--) {
- $c = $rest{$offbeg};
- if ($c == "\n") {
- $okay = true;
- $offbeg++;
- break;
- }
- if (($c != ' ') && ($c != "\t")) {
- $offbeg = $pos;
- break;
- }
- }
- if (! $okay) {
- $offend = $pos + strlen($dynbeg[1]);
- } else {
- $l = strlen ($rest);
- for ($offend = $pos + strlen($dynbeg[1]); $offend < $l; $offend++) {
- $c = $rest{$offend};
- if ($c == "\n") {
- $offend++;
- break;
- }
- if (($c != ' ') && ($c != "\t")) {
- $offend = $pos + strlen($dynbeg[1]);
- break;
- }
- }
- }
-
- // This includes the contents of the REGEX_DYNBEG in the output
- // $part[] = substr ($rest, 0, $pos);
- // This preserves whitespace on the END block line(s).
- // $part[] = substr ($rest, 0, $pos+strlen($dynbeg[1]));
- // $rest = substr ($rest, $pos+strlen($dynbeg[1]));
- // Catch case where BEGIN block is at position 0.
- if ($offbeg > 0)
- $part[] = substr ($rest, 0, $offbeg);
- $rest = substr ($rest, $offend);
- $sub = '';
- if ($debug)
- $this->logwrite ("parse_internal_1: found at pos = $pos");
- // Okay, here we are actually NOT interested in just the next
- // END block. We are only interested in the next END block that
- // matches this BEGIN block. This is not the most efficient
- // because we really could do this in one pass through the
- // string just marking BEGIN and END blocks. But the recursion
- // makes for a simple algorithm (if there was a reverse
- // preg...).
- $found = false;
- while (preg_match ($this->REGEX_DYNEND, $rest, $dynend)) {
- if ($debug)
- $this->logwrite ('parse_internal_1: REGEX_DYNEND search: rest => ' . $rest);
- if ($debug)
- $this->logwrite ('parse_internal_1: match beg => ' . $dynend[1]);
- $pos = strpos ($rest, $dynend[1]);
- if ($dynbeg[2] == $dynend[2]) {
- $found = true;
- // See if the text on either side of the END comment is
- // only whitespace. If so, we delete the entire line.
- $okay = false;
- for ($offbeg = $pos - 1; $offbeg >= 0; $offbeg--) {
- $c = $rest{$offbeg};
- if ($c == "\n") {
- $offbeg++;
- $okay = true;
- break;
- }
- if (($c != ' ') && ($c != "\t")) {
- $offbeg = $pos;
- break;
- }
- }
- if (! $okay) {
- $offend = $pos + strlen($dynend[1]);
- } else {
- $l = strlen ($rest);
- for ($offend = $pos + strlen($dynend[1]); $offend < $l; $offend++) {
- $c = $rest{$offend};
- if ($c == "\n") {
- $offend++;
- break;
- }
- if (($c != ' ') && ($c != "\t")) {
- $offend = $pos + strlen($dynend[1]);
- break;
- }
- }
- }
- // if ($debug)
- // $this->logwrite ("parse_internal_1: DYNAMIC BEGIN: (pos,len,beg,end) => ($pos, " . strlen($dynbeg[1]) . ", $offbeg, $offend)
- // This includes the contents of the REGEX_DYNEND in the output
- // $rest = substr ($rest, $pos);
- // This preserves whitespace on the END block line(s).
- // $rest = substr ($rest, $pos+strlen($dynend[1]));
- // $sub .= substr ($rest, 0, $pos);
- $sub .= substr ($rest, 0, $offbeg);
- $rest = substr ($rest, $offend);
- // Already loaded templates will not be reloaded. The
- // 'clear' test was actually hiding a bug in the clear()
- // logic....
- if (false && isset($this->TEMPLATE[$dynend[2]]['clear'])
- && $this->TEMPLATE[$dynend[2]]['clear']) {
- $this->TEMPLATE[$dynend[2]]['string'] = '';
- $this->TEMPLATE[$dynend[2]]['result'] = '';
- $this->TEMPLATE[$dynend[2]]['part'] =
- $this->parse_internal_1 ($dynend[2], ' ');
- } else if (!isset($this->TEMPLATE[$dynend[2]]['loaded'])
- || !$this->TEMPLATE[$dynend[2]]['loaded']) {
- // Omit pathological case of empty dynamic template.
- if (strlen($sub) > 0) {
- $this->TEMPLATE[$dynend[2]]['string'] = $sub;
- $this->TEMPLATE[$dynend[2]]['part'] =
- $this->parse_internal_1 ($dynend[2], $sub);
- $this->TEMPLATE[$dynend[2]]['part']['parent'] = $tag;
- }
- }
- $this->TEMPLATE[$dynend[2]]['loaded'] = true;
- $part[] = &$this->TEMPLATE[$dynend[2]];
- $this->TEMPLATE[$dynend[2]]['tag'] = $dynend[2];
- break;
- } else {
- $sub .= substr ($rest, 0, $pos+strlen($dynend[1]));
- $rest = substr ($rest, $pos+strlen($dynend[1]));
- if ($debug)
- $this->logwrite ("parse_internal_1: $dynbeg[2] != $dynend[2]");
- }
- }
- if (!$found) {
- $this->error ("malformed dynamic template, missing END<BR />\n" .
- "$dynbeg[1]<BR />\n", true);
- }
- } else {
- // Although it would appear to make sense to check that we don't
- // have a dangling END block, we will, in fact, ALWAYS appear to
- // have a dangling END block. We stuff the BEGIN string in the
- // part before the inferior template and the END string in the
- // part after the inferior template. So for this test to work,
- // we would need to look just past the final match.
- if (preg_match ($this->REGEX_DYNEND, $rest, $dynend)) {
- // $this->error ("malformed dynamic template, dangling END<BR />\n" .
- // "$dynend[1]<BR />\n", 1);
- }
- $part[] = $rest;
- $rest = '';
- }
- }
- return $part;
- }
-
- //
- // Description
- // Parse the template. If $tag is actually an array, we iterate over
- // the array elements. If it is a simple string tag, we may still
- // recursively parse the template if it contains dynamic templates and
- // we are configured to automatically load those as well.
- //
- function parse_internal ($tag) {
- $debug = $this->DEBUGALL || $this->DEBUG['parse_internal'];
- $append = false;
- if ($debug)
- $this->logwrite ("parse_internal (tag=$tag)");
-
- // If we are handed an array of tags, iterate over all of them. This
- // is really a holdover from the way class.FastTemplate.php3 worked;
- // I think subst() already pulls that array apart for us, so this
- // should not be necessary unless someone calls the internal member
- // function directly.
- if (gettype($tag) == 'array') {
- reset ($tag);
- foreach ($tag as $t) {
- $this->parse_internal ($t);
- }
- } else {
- // Load the file if it hasn't already been loaded. It might be
- // nice to put in some logic that reloads the file if it has
- // changed since we last loaded it, but that probably gets way too
- // complicated and only makes sense if we start keeping it floating
- // around between page loads as a persistent variable.
- if (!isset($this->TEMPLATE[$tag]['loaded'])) {
- if ($this->TEMPLATE[$tag]['dynamic']) {
- // Template was declared via define_dynamic().
- if ($this->TEMPLATE[$tag]['parent'])
- $tag = $this->TEMPLATE[$tag]['parent'];
- else {
- // Try to find a non-dynamic template with the same file.
- // This would have been defined via define(array(), true)
- reset ($this->TEMPLATE);
- foreach (array_keys($this->TEMPLATE) as $ptag) {
- if ($debug)
- $this->logwrite ("parse_internal: looking for non-dynamic parent, $ptag");
- if (!$this->TEMPLATE[$ptag]['dynamic']
- && ($this->TEMPLATE[$ptag]['file'] == $this->TEMPLATE[$tag]['file'])) {
- $tag = $ptag;
- break;
- }
- }
- }
- }
- $this->TEMPLATE[$tag]['string'] = &$this->load($this->TEMPLATE[$tag]['file']);
- $this->TEMPLATE[$tag]['loaded'] = 1;
- }
-
- // If we are supposed to automatically detect dynamic templates and the dynamic
- // flag is not set, scan the template for dynamic sections. Dynamic sections
- // markers have a very rigid syntax as HTML comments....
- if ($this->DYNAMIC) {
- $this->TEMPLATE[$tag]['tag'] = $tag;
- if (!isset($this->TEMPLATE[$tag]['parsed'])
- || !$this->TEMPLATE[$tag]['parsed']) {
- $this->TEMPLATE[$tag]['part'] = $this->parse_internal_1 ($tag, $this->TEMPLATE[$tag]['string']);
- $this->TEMPLATE[$tag]['parsed'] = true;
- }
- }
- }
- }
-
- //
- // Description
- // class.FastTemplate.php3 compatible interface.
- //
- // Notes
- // I prefer the name `subst' to `parse' since during this phase we are
- // really doing variable substitution into the template. However, at
- // some point we have to load and parse the template and `subst' will
- // do that as well...
- //
- function parse ($handle, $tag, $autoload = true) {
- return $this->subst ($handle, $tag, $autoload);
- }
-
- //
- // Description
- // Perform substitution on the template. We do not really recurse
- // downward in the sense that we do not do subsitutions on inferior
- // templates. For each inferior template which is a part of this
- // template, we insert the current value of their results.
- //
- // Notes
- // Do I want to make this return a reference?
- function subst ($handle, $tag, $autoload = true) {
- $append = false;
- $debug = $this->DEBUGALL || $this->DEBUG['subst'];
- $this->LAST = $handle;
-
- if ($debug)
- $this->logwrite ("subst (handle=$handle, tag=$tag, autoload=$autoload)");
-
- // For compatibility with FastTemplate, the results need to overwrite
- // for an array. This really only seems to be useful in the case of
- // something like
- // $t->parse ('MAIN', array ('array', 'main'));
- // Where the 'main' template has a variable named MAIN which will be
- // set on the first pass (i.e., when parasing 'array') and used on the
- // second pass (i.e., when parsing 'main').
- if (gettype($tag) == 'array') {
- foreach (array_values($tag) as $t) {
- if ($debug)
- $this->logwrite ("subst: calling subst($handle,$t,$autoload)");
- $this->subst ($handle, $t, $autoload);
- }
- return $this->HANDLE[$handle];
- }
-
- // Period prefix means append result to pre-existing value.
- if (substr($tag,0,1) == '.') {
- $append = true;
- $tag = substr ($tag, 1);
- if ($debug)
- $this->logwrite ("subst (handle=$handle, tag=$tag, autoload=$autoload) in append mode");
- }
- // $this->TEMPLATE[$tag] will only be set if it was explicitly
- // declared via define(); i.e., inferior templates will not have an
- // entry.
- if (isset($this->TEMPLATE[$tag])) {
- if (!isset($this->TEMPLATE[$tag]['parsed'])
- || !$this->TEMPLATE[$tag]['parsed'])
- $this->parse_internal ($tag);
- } else {
- if (!$this->DYNAMIC) {
- $this->error ("subst (handle=$handle, tag=$tag, autoload=$autoload): " .
- 'no such tag and dynamic templates are turned off', true);
- }
- if ($autoload) {
- if ($debug)
- $this->logwrite ("subst: TEMPLATE[tag=$tag] not found, trying autoload");
- foreach (array_keys($this->TEMPLATE) as $t) {
- if ($debug)
- $this->logwrite ("subst: calling parse_internal (tag=$t)");
- if (!isset($this->TEMPLATE[$tag]['parsed'])
- || !$this->TEMPLATE[$tag]['parsed'])
- $this->parse_internal ($t);
- }
- if ($debug)
- $this->logwrite ('subst: retrying with autoload = false');
- $this->subst ($handle, $tag, false);
- if ($debug)
- $this->logwrite ('subst: completed with autoload = false');
- return;
- } else {
- $this->error ("subst (handle=$handle, tag=$tag, autoload=$autoload): no such tag", true);
- }
- }
- if (!$append) {
- $this->TEMPLATE[$tag]['result'] = '';
- if ($debug)
- $this->logwrite ("subst (handle=$handle, tag=$tag, autoload=$autoload) in overwrite mode");
- }
- if ($debug)
- $this->logwrite ('subst: type(this->TEMPLATE[$tag][\'part\']) => ' .
- gettype($this->TEMPLATE[$tag]['part']));
- // Hmmm, clear() called before subst() seems to result in this not
- // being defined which leaves me a bit confused....
- $result = '';
- if (isset($this->TEMPLATE[$tag]['part'])) {
- reset ($this->TEMPLATE[$tag]['part']);
- foreach (array_keys($this->TEMPLATE[$tag]['part']) as $p) {
- if ($debug)
- $this->logwrite ("subst: looking at TEMPLATE[$tag]['part'][$p]");
- $tmp = $this->TEMPLATE[$tag]['part'][$p];
- // Don't try if ($p == 'parent')....
- if (strcmp ($p, 'parent') == 0) {
- if ($debug)
- $this->logwrite ("subst: skipping part $p");
- $tmp = '';
- } else if (gettype($this->TEMPLATE[$tag]['part'][$p]) == 'string') {
- if ($debug)
- $this->logwrite ("subst: using part $p");
- reset ($this->VAR);
- // Because we treat VAR and HANDLE separately (unlike
- // class.FastTemplate.php3), we have to iterate over both or we
- // miss some substitutions and are not 100% compatible.
- while (list($key,$val) = each ($this->VAR)) {
- if ($debug)
- $this->logwrite ("subst: substituting VAR $key = $val in $tag");
- $key = '{'.$key.'}';
- $tmp = str_replace ($key, $val, $tmp);
- }
- reset ($this->HANDLE);
- while (list($key,$val) = each ($this->HANDLE)) {
- if ($debug)
- $this->logwrite ("subst: substituting HANDLE $key = $val in $tag");
- $key = '{'.$key.'}';
- $tmp = str_replace ($key, $val, $tmp);
- }
- $result .= $tmp;
- } else {
- $xtag = $this->TEMPLATE[$tag]['part'][$p]['tag'];
- if ($debug) {
- $this->logwrite ("subst: substituting other tag $xtag result in $tag");
- }
- // The assignment is a no-op if the result is not set, but when
- // E_ALL is in effect, a warning is generated without the
- // isset() test.
- if (isset ($this->TEMPLATE[$xtag]['result']))
- $result .= $this->TEMPLATE[$xtag]['result'];
- }
- }
- }
- if ($this->STRICT) {
- // If quiet-mode is turned on, skip the check since we're not going
- // to do anything anyway.
- if (!$this->QUIET) {
- if (preg_match ($this->REGEX_VAR, $result)) {
- $this->error ("<B>unmatched tags still present in $tag</B><BR />");
- }
- }
- } else {
- $result = preg_replace ($this->REGEX_VAR, '', $result);
- }
- if ($append) {
- if ($debug) {
- $this->logwrite ("subst: appending TEMPLATE[$tag]['result'] = $result");
- $this->logwrite ("subst: old HANDLE[$handle] = {$this->HANDLE[$handle]}");
- $this->logwrite ("subst: old TEMPLATE[$tag]['result'] = {$this->TEMPLATE[$tag]['result']}");
- }
- // The isset() tests are to suppresss warning when E_ALL is in effect
- // and the variables have not actually been set yet (even though the
- // user specified append-mode).
- if (isset ($this->HANDLE[$handle]))
- $this->HANDLE[$handle] .= $result;
- else
- $this->HANDLE[$handle] = $result;
- if (isset ($this->TEMPLATE[$tag]['result']))
- $this->TEMPLATE[$tag]['result'] .= $result;
- else
- $this->TEMPLATE[$tag]['result'] = $result;
- if ($debug) {
- $this->logwrite ("subst: new HANDLE[$handle] = {$this->HANDLE[$handle]}");
- $this->logwrite ("subst: new TEMPLATE[$tag]['result'] = {$this->TEMPLATE[$tag]['result']}");
- }
-
- } else {
- if ($debug)
- $this->logwrite ("subst: setting TEMPLATE[$tag]['result'] = $result");
- $this->HANDLE[$handle] = $result;
- $this->TEMPLATE[$tag]['result'] = $result;
- }
- return $this->HANDLE[$handle];
- }
-
- //
- // Description
- // Clear a block from a template. The intent is to remove an inferior
- // template from a parent. This works even if the template has already
- // been parsed since we go straight to the specified template and clear
- // the results element. If the given template has not yet been
- // loaded, the load is forced by calling parse_internal().
- //
- function clear_dynamic ($tag = NULL) {
- $debug = $this->DEBUGALL || $this->DEBUG['clear_dynamic'];
- if (is_null ($tag)) {
- // Clear all result elements. Uhm, needs to be tested.
- if ($debug)
- $this->logwrite ("clear_dynamic (NULL)");
- foreach (array_values ($this->TEMPLATE) as $t) {
- $this->clear_dynamic ($t);
- }
- return;
- } else if (gettype($tag) == 'array') {
- if ($debug)
- $this->logwrite ("clear_dynamic ($tag)");
- foreach (array_values($tag) as $t) {
- $this->clear_dynamic ($t);
- }
- return;
- }
- else if (!isset($this->TEMPLATE[$tag])) {
- if ($debug)
- $this->logwrite ("clear_dynamic ($tag) --> $tag not set, calling parse_internal");
- $this->parse_internal ($tag);
- // $this->TEMPLATE[$tag] = array ();
- }
- if ($debug)
- $this->logwrite ("clear_dynamic ($tag)");
- // $this->TEMPLATE[$tag]['loaded'] = true;
- // $this->TEMPLATE[$tag]['string'] = '';
- $this->TEMPLATE[$tag]['result'] = '';
- // $this->TEMPLATE[$tag]['clear'] = true;
- }
-
- //
- // Description
- // Clear the results of a handle set by parse(). The input handle can
- // be a single value, an array, or the PHP constant NULL. For the
- // last case, all handles cleared.
- //
- function clear ($handle = NULL) {
- $debug = $this->DEBUGALL || $this->DEBUG['clear'];
- if (is_null ($handle)) {
- // Don't bother unsetting them, just set the whole thing to a new,
- // empty array.
- if ($debug)
- $this->logwrite ("clear (NULL)");
- $this->HANDLE = array ();
- } else if (gettype ($handle) == 'array') {
- if ($debug)
- $this->logwrite ("clear ($handle)");
- foreach (array_values ($handle) as $h) {
- $this->clear ($h);
- }
- } else if (isset ($this->HANDLE[$handle])) {
- if ($debug)
- $this->logwrite ("clear ($handle)");
- unset ($this->HANDLE[$handle]);
- }
- }
-
- //
- // Description
- // Clears all information associated with the specified tag as well as
- // any information associated with embedded templates. This will force
- // the templates to be reloaded on the next call to subst().
- // Additionally, any results of previous calls to subst() will also be
- // cleared.
- //
- // Notes
- // This leaves dangling references in $this->HANDLE. Or does PHP do
- // reference counting so they are still valid?
- //
- function unload ($tag) {
- if (!isset($this->TEMPLATE[$tag]))
- return;
- if (isset ($this->TEMPLATE[$tag]['parent'])) {
- $ptag = $this->TEMPLATE[$tag]['parent'];
- foreach (array_keys($this->TEMPLATE) as $t) {
- if ($this->TEMPLATE[$t]['parent'] == $ptag) {
- unset ($this->TEMPLATE[$t]);
- }
- }
- }
- unset ($this->TEMPLATE[$tag]);
- return;
- }
-
- //
- // Description
- // class.FastTemplate.php3 compatible interface.
- //
- function assign ($tplkey, $rest = '') {
- $this->setkey ($tplkey, $rest);
- }
-
- //
- // Description
- // Set a (key,value) in our internal variable array. These will be
- // used during the substitution phase to replace template variables.
- //
- function setkey ($tplkey, $rest = '') {
- if (gettype ($tplkey) == 'array') {
- reset ($tplkey);
- while (list($key,$val) = each ($tplkey)) {
- if (!empty($key)) {
- $this->VAR[$key] = $val;
- }
- }
- } else {
- if (!empty($tplkey)) {
- $this->VAR[$tplkey] = $rest;
- }
- }
- }
-
- function append ($tplkey, $rest = '') {
- if (gettype ($tplkey) == 'array') {
- reset ($tplkey);
- while (list($key,$val) = each ($tplkey)) {
- if (!empty($key)) {
- $this->VAR[$key] .= $val;
- }
- }
- } else {
- if (!empty($tplkey)) {
- $this->VAR[$tplkey] .= $rest;
- }
- }
- }
-
- //
- // Description
- // class.FastTemplate.php3 compatible interface
- //
- function get_assigned ($key = '') {
- return $this->getkey ($key);
- }
-
- //
- // Description
- // Retrieve a value from our internal variable array given the key name.
- //
- function getkey ($key = '') {
- if (empty($key)) {
- return false;
- } else if (isset ($this->VAR[$key])) {
- return $this->VAR[$key];
- } else {
- return false;
- }
- }
-
- function fetch ($handle = '') {
- if (empty($handle)) {
- $handle = $this->LAST;
- }
- return $this->HANDLE[$handle];
- }
-
- function xprint ($handle = '') {
- if (empty($handle)) {
- $handle = $this->LAST;
- }
- print ($this->HANDLE[$handle]);
- }
-
- function FastPrint ($handle = '') {
- $this->xprint ($handle);
- }
-
- function clear_href ($key = '') {
- $this->unsetkey ($key);
- }
-
- function unsetkey ($key = '') {
- if (empty($key)) {
- unset ($this->VAR);
- $this->VAR = array ();
- } else if (gettype($key) == 'array') {
- reset ($key);
- foreach (array_values($key) as $k) {
- unset ($this->VAR[$k]);
- }
- } else {
- unset ($this->VAR[$key]);
- }
- }
-
- function define_nofile ($stringList, $dynamic = 0) {
- $this->define_raw ($stringList, $dynamic);
- }
- //
- // Description
- // Member function to control explicit error messages. We don't do
- // real PHP error handling.
- //
- function error ($errorMsg, $die = 0) {
- $this->ERROR = $errorMsg;
- echo "ERROR: {$this->ERROR} <br /> \n";
- if ($die) {
- exit;
- }
- return;
- }
-}
+++ /dev/null
-Require valid-user
-AuthType Basic
-AuthName "mlmmj web-interface"
-AuthUserFile /home/mlmmj/htpasswd
+++ /dev/null
-<?php
-
-/* mlmmj/php-admin:
- * Copyright (C) 2004 Christoph Thiel <ct at kki dot org>
- *
- * mlmmj/php-perl:
- * Copyright (C) 2004 Morten K. Poulsen <morten at afdelingp.dk>
- * Copyright (C) 2004 Christian Laursen <christian@pil.dk>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-require(dirname(dirname(__FILE__))."/conf/config.php");
-require(dirname(__FILE__)."/class.rFastTemplate.php");
-
-function mlmmj_boolean($name, $nicename, $text)
-{
- global $tpl, $topdir, $list;
-
- if(is_file($topdir."/".$list."/control/".$name))
- $checked = TRUE;
- else
- $checked = FALSE;
-
- $tpl->assign(array("NAME" => htmlentities($name),
- "NICENAME" => htmlentities($nicename),
- "TEXT" => htmlentities($text)));
- $tpl->assign(array("CHECKED" => $checked ? " checked" : ""));
-
- $tpl->parse("ROWS",".boolean");
-}
-
-function mlmmj_string($name, $nicename, $text)
-{
- global $tpl, $topdir, $list;
-
- $file = $topdir."/".$list."/control/".$name;
- $value = "";
-
- if(is_file($file)) {
- $lines = file($file);
- $value = $lines[0];
- }
-
- // remove trailing \n if any, just to be sure
- $value = preg_replace('/\n$/',"",$value);
-
- $tpl->assign(array("NAME" => htmlentities($name),
- "NICENAME" => htmlentities($nicename),
- "TEXT" => htmlentities($text),
- "VALUE" => htmlentities($value)));
-
- $tpl->parse("ROWS",".string");
-}
-
-function mlmmj_list($name, $nicename, $text)
-{
- global $tpl, $topdir, $list;
-
- $file = "$topdir/$list/control/$name";
- $value = "";
-
- if(is_file($file))
- $value = file_get_contents($file);
-
- // the last \n would result in an extra empty line in the list box,
- // so we remove it
- $value = preg_replace('/\n$/',"",$value);
-
- $tpl->assign(array("NAME" => htmlentities($name),
- "NICENAME" => htmlentities($nicename),
- "TEXT" => htmlentities($text),
- "VALUE" => htmlentities($value)));
-
- $tpl->parse("ROWS",".list");
-}
-
-// Perl's encode_entities (to be able to use tunables.pl)
-function encode_entities($str) { return htmlentities($str); }
-
-
-$tpl = new rFastTemplate($templatedir);
-
-$list = $_GET["list"];
-
-if(!isset($list))
-die("no list specified");
-
-if (dirname(realpath($topdir."/".$list)) != realpath($topdir))
-die("list outside topdir");
-
-if(!is_dir($topdir."/".$list))
-die("non-existent list");
-
-$tpl->define(array("main" => "edit.html",
- "boolean" => "edit_boolean.html",
- "string" => "edit_string.html",
- "list" => "edit_list.html"));
-
-$tpl->assign(array("LIST" =>htmlentities($list)));
-
-$tunables = file_get_contents($confdir.'/tunables.pl');
-eval($tunables);
-
-$tpl->parse("MAIN","main");
-$tpl->FastPrint("MAIN");
-
-?>
+++ /dev/null
-<?php
-
-/* mlmmj/php-admin:
- * Copyright (C) 2004 Christoph Thiel <ct at kki dot org>
- *
- * mlmmj/php-perl:
- * Copyright (C) 2004 Morten K. Poulsen <morten at afdelingp.dk>
- * Copyright (C) 2004 Christian Laursen <christian@pil.dk>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-require(dirname(dirname(__FILE__))."/conf/config.php");
-require(dirname(__FILE__)."/class.rFastTemplate.php");
-
-$tpl = new rFastTemplate($templatedir);
-
-$tpl->define(array("main" => "index.html"));
-
-$lists = "";
-
-# use scandir to have alphabetical order
-foreach (scandir($topdir) as $file) {
- if (!ereg("^\.",$file))
- {
- $lists .= "<p>".htmlentities($file)."<br/>\n";
- $lists .= "<a href=\"edit.php?list=".urlencode($file)."\">Config</a> - <a href=\"subscribers.php?list=".urlencode($file)."\">Subscribers</a>\n";
- $lists .= "</p>\n";
- }
-}
-
-$tpl->assign(array("LISTS" => $lists));
-
-
-$tpl->parse("MAIN","main");
-$tpl->FastPrint("MAIN");
-
-?>
+++ /dev/null
-<?php
-
-/* mlmmj/php-admin:
- * Copyright (C) 2004 Christoph Thiel <ct at kki dot org>
- *
- * mlmmj/php-perl:
- * Copyright (C) 2004 Morten K. Poulsen <morten at afdelingp.dk>
- * Copyright (C) 2004 Christian Laursen <christian@pil.dk>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-require(dirname(dirname(__FILE__))."/conf/config.php");
-require(dirname(__FILE__)."/class.rFastTemplate.php");
-
-function mlmmj_boolean($name, $nicename, $text)
-{
- global $tpl, $topdir, $list;
-
- $file = $topdir."/".$list."/control/".$name;
-
- if(isset($_POST[$name]) && !empty($_POST[$name]))
- {
- if(!touch($file))
- die("Couldn't open ".$file." for writing");
- if (!chmod($file, 0644))
- die("Couldn't chmod ".$file);
- }
- else {
- if (file_exists($file)) {
- if (!unlink($file))
- die("Couldn't unlink ".$file);
- }
- }
-}
-
-function mlmmj_string ($name, $nicename, $text)
-{
- mlmmj_list($name, $nicename, $text);
-}
-
-function mlmmj_list($name, $nicename, $text)
-{
- global $tpl, $topdir, $list;
-
- $file = $topdir."/".$list."/control/".$name;
-
- if(isset($_POST[$name]) && !empty($_POST[$name]) && !preg_match('/^\s*$/',$_POST[$name]))
- {
- // remove all \r
- $_POST[$name]=preg_replace('/\r/',"",$_POST[$name]);
-
- // no trailing \n?, then we add one
- if (!preg_match('/\n$/',$_POST[$name]))
- $_POST[$name].="\n";
-
- // we don't like whitespace before a \n
- $_POST[$name]=preg_replace('/\s*\n/',"\n",$_POST[$name]);
-
- if (!$fp = fopen($file, "w"))
- die("Couldn't open ".$file." for writing");
-
- // write the result in a file
- fwrite($fp, $_POST[$name]);
- fclose($fp);
-
- if (!chmod($file, 0644))
- die("Couldn't chmod ".$file);
- }
- else {
- if (file_exists($file)) {
- if (!unlink($file))
- die("Couldn't unlink ".$file);
- }
- }
-}
-
-// Perl's encode_entities (to be able to use tunables.pl)
-function encode_entities($str) { return htmlentities($str); }
-
-
-$tpl = new rFastTemplate($templatedir);
-
-$list = $_POST["list"];
-
-if(!isset($list))
-die("no list specified");
-
-if (dirname(realpath($topdir."/".$list)) != realpath($topdir))
-die("list outside topdir");
-
-if(!is_dir($topdir."/".$list))
-die("non-existent list");
-
-$tpl->define(array("main" => "save.html"));
-$tpl->assign(array("LIST" => htmlentities($list)));
-
-$tunables = file_get_contents($confdir.'/tunables.pl');
-eval($tunables);
-
-$tpl->parse("MAIN","main");
-$tpl->FastPrint("MAIN");
-
-?>
+++ /dev/null
-<?php
-
-/* Copyright (C) 2012 Marc MAURICE <marc-mlmmj at pub dot positon dot org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-require(dirname(dirname(__FILE__))."/conf/config.php");
-require(dirname(__FILE__)."/class.rFastTemplate.php");
-
-$tpl = new rFastTemplate($templatedir);
-
-# get the list parameter and check that list exists
-$list = $_GET["list"];
-
-if(!isset($list))
-die("no list specified");
-
-if (dirname(realpath($topdir."/".$list)) != realpath($topdir))
-die("list outside topdir");
-
-if(!is_dir($topdir."/".$list))
-die("non-existent list");
-
-# this will be displayed on the top of the page
-$message = "";
-
-# subscribe some people if tosubscribe is set
-if (isset($_POST["tosubscribe"])) {
-
- foreach (preg_split('/\r\n|\n|\r/', $_POST["tosubscribe"]) as $line) {
- $email = trim($line);
- if ($email != "") {
- if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
- $cmd = "/usr/bin/mlmmj-sub -L ".escapeshellarg("$topdir/$list")." -a ".escapeshellarg($email)." 2>&1";
- unset($out);
- exec($cmd, $out, $ret);
- if ($ret !== 0) {
- $message.= "* Subscribe error for $email\ncommand: $cmd\nreturn code: $ret\noutput: ".implode("\n", $out)."\n";
- }
- } else {
- $message.= "* Email address not valid: $email\n";
- }
- }
-
- }
-
-# delete some people if delete is set
-} else if (isset($_POST["delete"])) {
-
- $email = $_POST["email"];
- if (! filter_var($email, FILTER_VALIDATE_EMAIL)) die("Email address not valid");
-
- $cmd = "/usr/bin/mlmmj-unsub -L ".escapeshellarg("$topdir/$list")." -a ".escapeshellarg($email)." 2>&1";
- unset($out);
- exec($cmd, $out, $ret);
- if ($ret !== 0) {
- $message.= "* Unsubscribe error.\ncommand: $cmd\nreturn code: $ret\noutput: ".implode("\n", $out)."\n";
- }
-}
-
-$subscribers="";
-
-# get subscribers from mlmmj
-$cmd = "/usr/bin/mlmmj-list -L ".escapeshellarg("$topdir/$list")." 2>&1";
-unset($out);
-exec($cmd, $out, $ret);
-if ($ret !== 0) {
- $message.= "* Error: Could not get subscribers list.\n";
-} else {
-
- foreach ($out as $email) {
- $email = trim($email);
-
- $form = "<form action=\"subscribers.php?list=".htmlspecialchars($list)."\" method=\"post\" style=\"margin: 0; margin-left: 1em\">";
- $form.= "<input type=\"hidden\" name=\"email\" value=\"".htmlspecialchars($email)."\" />";
- $form.= "<input type=\"submit\" name=\"delete\" value=\"Remove\" />";
- $form.= "</form>";
-
- $subscribers.= "<tr><td>".htmlspecialchars($email)."</td><td>$form</td></tr>\n";
- }
-
- if ($subscribers === "") {
- $subscribers = "<tr><td>This list is empty.</td></tr>\n";
- }
-}
-
-# set template vars
-$tpl->define(array("main" => "subscribers.html"));
-
-$tpl->assign(array("LIST" => htmlspecialchars($list)));
-$tpl->assign(array("MESSAGE" => "<pre>".htmlspecialchars($message)."</pre>"));
-$tpl->assign(array("SUBS" => $subscribers));
-
-$tpl->parse("MAIN","main");
-$tpl->FastPrint("MAIN");
-
-?>
+++ /dev/null
-<html><head><title>mlmmj config</title></head><body>
-<h1>mlmmj config</h1>
-<form method="post" action="save.php">
-<input type="hidden" name="list" value="{LIST}">
-<table border="1">
-{ROWS}
-</table>
-<input type="submit" name="submit" />
-</form>
-<p>
-<a href="index.php">Index</a>
-</p>
-</body></html>
+++ /dev/null
-<tr><td>{NICENAME}</td><td><input type="checkbox" name="{NAME}" value="1"{CHECKED}></td><td>{TEXT}</td></tr>
+++ /dev/null
-<tr><td>{NICENAME}</td><td><textarea name="{NAME}" columns="40">{VALUE}</textarea></td><td>{TEXT}</td></tr>
+++ /dev/null
-<tr><td>{NICENAME}</td><td><input type="text" name="{NAME}" value="{VALUE}"></td><td>{TEXT}</td></tr>
+++ /dev/null
-<html><head><title>mlmmj config</title></head><body>
-<h1>mlmmj config</h1>
-{LISTS}
-</body></html>
+++ /dev/null
-<html><head><title>mlmmj config</title></head><body>
-<h1>mlmmj config</h1>
-<p>
-{LIST} control values saved!
-</p>
-<p>
-<a href="index.php">Index</a> | <a href="edit.php?list={LIST}">{LIST}</a>
-</p>
-</body></html>
+++ /dev/null
-<html>
-<head>
-<title>mlmmj - {LIST} subscribers</title>
-<style type="text/css">
-#subscribers {
- float: left;
-}
-
-#addsubscribers {
- float: left;
- margin-left: 2em;
-}
-#index {
- clear: both;
-}
-</style>
-</head>
-<body>
-<h1>{LIST} subscribers</h1>
-
-{MESSAGE}
-
-<table id="subscribers">
-{SUBS}
-</table>
-
-<form method="post" action="subscribers.php?list={LIST}" id="addsubscribers">
-Add subscribers:<br/>
-<textarea name="tosubscribe" rows="5" cols="30">
-</textarea><br/>
-<input type="submit" name="submit" value="Add" />
-</form>
-
-<p id="index">
-<a href="index.php">Index</a>
-</p>
-</body>
-</html>
+++ /dev/null
-MLMMJ PHP Moderation Web Interface by Thomas Goirand <thomas@goirand.fr>
-
-
-* dependencies *
-
-This app needs:
-- php with gettext() support (for translations). Nearly all (if not all)
-Unix distributions have php with gettext support.
-- The Mail_mime PEAR package (php-mail-mime in Debian)
-
-
-* setup *
-
-- Run "./build-translations.sh" to generate the gettext binaries out of the
-sources
-- Edit the 5 variables on top of mlmmj-moderation.php to set the
-moderation folder, list name, domain, delimiter and the address used to
-send the moderation validation messages. You will need gettext installed
-on your system...
-- Eventually rename mlmmj-moderation.php and edit mlmmj.css to your taste
-- Edit and rename the dot.htaccess files to .htaccess to protect the
-moderation folder from others
-- make it so this app have read/write access to the moderation folder.
-Write access is needed because the app does some unlink() calls to
-delete the messages.
-- If using debian, you might need to dpkg-reconfigure locales and add
-fr_FR.UTF-8, if you want to see my French translation (there might be
-some other distributions needing the same kind of thing, I don't know...).
-
-
-* known issues *
-
-- Because this web app is sending an email to validate messages to be
-moderated, once you have hit "validate", validated messages will still
-(most of the times) show in the interface, as the folder is (most of the
-times) read before MLMMJ has time to send the moderated messages and
-remove them from the moderation folder.
-
-A workaround would be to NOT display messages that are moderated on the
-URL bar, but it's not a good way to go, as if the server is very busy,
-the next refresh of the page (the one after the validation) can still
-show some messages already validated. We see here that the method to
-send emails doesn't seem to be very good... Would it be possible for me
-to rename the moderated messages???
-
-- Because it's the first version, I have not yet used POST, but some GET
-in order to see things on the URL bar. So, of course, we are here
-hitting the limitation of the URL size (if there are really a lot of
-messages to moderate). This can be changed later simply by adding
-method="POST" in the form, as I use $_REQUEST (and not the stupid $_POST
-/ $_GET that everybody uses...). I might do this on the next version,
-but for now, it's more easy for debug purposes to keep it this way.
+++ /dev/null
-#!/bin/bash
-#
-# Build script for generating the MLMMJ moderation web interface locales
-#
-
-set -e
-
-LOCALE_TRANS=fr_FR
-WEB_SCRIPT_FILES=mlmmj-moderation.php
-
-if [ ! -d translations ]; then
- echo "Wrong working directory." >&2
- exit 1
-fi
-
-echo "===> Managing internationalizations and localizations"
-
-echo "=> Extracting strings from sources"
-xgettext $WEB_SCRIPT_FILES -o translations/templates.pot
-
-echo "=> Merging in every language .po file:"
-for i in $LOCALE_TRANS; do
- echo -n "$i "
- msgmerge -s -U "translations/$i.po" translations/templates.pot
-done
-
-echo "=> Creating l10n folders"
-for i in $LOCALE_TRANS; do
- mkdir -p "translations/locale/$i/LC_MESSAGES"
-done
-
-echo "=> Creating binary formats of language files:"
-for i in $LOCALE_TRANS; do
- echo -n $i" "
- msgfmt -c -v -o "translations/locale/$i/LC_MESSAGES/messages.mo" \
- "translations/$i.po"
-done
+++ /dev/null
-Require valid-user
-AuthType Basic
-AuthName "mlmmj web-interface"
-AuthUserFile /home/mlmmj/htpasswd
+++ /dev/null
-<?php
-
-/*
-The MIT License
-
-Copyright (C) 2009, Thomas Goirand <thomas@goirand.fr>
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-of the Software, and to permit persons to whom the Software is furnished to do
-so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
-OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-*/
-
-// These are the configuration variables for your list
-$mod_dir = "/some/path/to/your/listname/moderation";
-$list_name = "listname";
-$list_domain = "example.com";
-$delimiter = "+";
-$from_addr = "user@example.com";
-
-// Manage accepted language and cookies
-$txt_default_lang = "en";
-session_register("lang");
-if(isset($_SESSION["lang"]) && !is_string($_SESSION["lang"])){
- unset($lang);
-}
-if(isset($_SESSION["lang"])){
- $lang = $_SESSION["lang"];
-}
-
-// TODO: Add some web stuffs to change the language manually on the web interface...
-// ...HERE...
-//
-
-// $lang = "fr_FR";
-
-// The following code keeps the lang in sessions, so it can be changed manually above with lang=XX
-// and if there's nothing in session yet, then it will parse the language set in the browser
-if(isset($lang)){
- $_SESSION["lang"] = $lang;
-}
-if (!isset($lang)){
- if (isset($_SERVER["HTTP_ACCEPT_LANGUAGE"]) && $_SERVER["HTTP_ACCEPT_LANGUAGE"]) {
- $all_languages = strtok($_SERVER["HTTP_ACCEPT_LANGUAGE"],";");
- $langaccept = explode(",", $all_languages);
- for ($i = 0; $i < sizeof($langaccept); $i++) {
- $tmplang = trim($langaccept[$i]);
- $tmplang2 = substr($tmplang,0,2);
- if (!isset($lang) && isset($txt_langname[$tmplang]) && $txt_langname[$tmplang]) {
- $lang = $tmplang;
- }elseif (!isset($lang) && isset($txt_langname[$tmplang2])) {
- $lang = $tmplang2;
- }
- }
- }
- if (!isset($lang)) {
- $lang = $txt_default_lang;
- }
- $_SESSION["lang"] = $lang;
-}
-header("Content-type: text/html; charset=UTF-8");
-switch($lang){
-case "fr_FR":
-case "fr":
- $gettext_lang = "fr_FR.UTF-8";
- break;
-default:
- $gettext_lang = "en_US.UTF-8";
- break;
-}
-if(FALSE === putenv("LC_ALL=$gettext_lang")){
- echo "Failed to putenv LC_ALL=$gettext_lang<br>";
-}
-if(FALSE === putenv("LANG=$gettext_lang")){
- echo "Failed to putenv LANG=$gettext_lang<br>";
-}
-if(FALSE === setlocale(LC_ALL, $gettext_lang)){
- echo "Failed to setlocale(LC_ALL,$gettext_lang)<br>";
-}
-$pathname = bindtextdomain("messages", dirname(__FILE__) ."/translations/locale");
-$message_domain = textdomain("messages");
-
-// This comes from the Mail_Mime PEAR package, under Debian, you need
-// the php-mail-mime package to have this script work.
-require_once 'Mail/mimeDecode.php';
-
-// Email header parsing
-function decodeEmail($input){
- $params['include_bodies'] = true;
- $params['decode_bodies'] = true;
- $params['decode_headers'] = true;
-
- $decoder = new Mail_mimeDecode($input);
- $structure = $decoder->decode($params);
- return $structure;
-}
-
-// Reading of all the messages from the moderation folder
-function getMessageList(){
- global $mod_dir;
- $all_msg = array();
- // Read all files from the directory.
- if (is_dir($mod_dir)) {
- if ($dh = opendir($mod_dir)) {
- while (($file = readdir($dh)) !== false) {
- if( !ereg("^([0-9a-f]+)\$",$file) ) continue;
- $full_path = $mod_dir . "/" . $file;
- if(filetype($full_path) == "file"){
- if(FALSE === ($input = file_get_contents($full_path))){
- echo "<span class=\"errorMessages\">"._("Warning: could not read")." $full_path</span><br>";
- }else{
- $struct = decodeEmail($input);
- $my_msg = array();
- $my_msg["headers"] = $struct->headers;
- $my_msg["body"] = $struct->body;
- $my_msg["filename"] = $file;
- $all_msg[] = $my_msg;
- }
- }
- }
- closedir($dh);
- }
- }
- return $all_msg;
-}
-
-// Printing of the list of messages to be displayed (the big table)
-function printAllMessages($all_msg){
- $n = sizeof($all_msg);
- $out = "<table cellspacing=\"4\" cellpadding=\"4\" border=\"0\">\n";
- $th = " class=\"tableTitle\" ";
- $out .= "<tr><th$th><input onClick=\"checkscript();\" type=\"submit\" value=\""._("Inverse selection")."\"></th><th$th>"._("Date")."</th><th$th>"._("Subject")."</th><th$th>"._("From")."</th></tr>\n";
- $out .= "<form id=\"zeForm\" name=\"zeForm\" action=\"". $_SERVER["PHP_SELF"] ."\">";
- for($i=0;$i<$n;$i++){
- if($i % 2){
- $cls = " class=\"alternatecolorline\" ";
- }else{
- $cls = " class=\"alternatecolorline2\" ";
- }
- $out .= "<tr>";
- $out .= "<td $cls>" . "<input type=\"checkbox\" name=\"msg_id[]\" value=\"". $all_msg[$i]["filename"] ."\">" . "</td>";
- if( isset($all_msg[$i]["headers"]["date"]) ){
- $mydate = htmlspecialchars($all_msg[$i]["headers"]["date"]);
- }else{
- $mydate = _("No date");
- }
- $out .= "<td $cls>" . $mydate . "</td>";
- if( !isset($all_msg[$i]["headers"]["subject"]) || strlen($all_msg[$i]["headers"]["subject"]) == 0){
- $subject = _("No subject");
- }else{
- $subject = $all_msg[$i]["headers"]["subject"];
- }
- $out .= "<td $cls><a href=\"". $_SERVER["PHP_SELF"] ."?action=show_message&msgid=". $all_msg[$i]["filename"] ."\">" . htmlspecialchars($subject) . "</a></td>";
- if( isset($all_msg[$i]["headers"]["from"]) ){
- $myfrom = htmlspecialchars($all_msg[$i]["headers"]["from"]);
- }else{
- $myfrom = _("No from in headers");
- }
- $out .= "<td $cls>" . $myfrom . "</td>";
- $out .= "</tr>\n";
- }
- $out .= "</table>\n";
- $out .= _("For the selection:")." ";
- $out .= "<input type=\"submit\" name=\"validate\" value=\""._("Validate")."\">";
- $out .= "<input type=\"submit\" name=\"delete\" value=\""._("Delete")."\">";
- return $out;
-}
-
-// Deletion and validation of messages
-if( isset($_REQUEST["validate"]) || isset($_REQUEST["delete"])){
- if( !isset($_REQUEST["msg_id"]) ){
- echo "<span class=\"errorMessages\">"._("No message selected!")."</span><br>";
- }else{
- $n = sizeof($_REQUEST["msg_id"]);
- for($i=0;$i<$n;$i++){
- if( !ereg("^([0-9a-f]+)\$",$_REQUEST["msg_id"][$i]) ){
- echo "<span class=\"errorMessages\">".("Moderation ID format is wrong: will ignore this one!")."</span>";
- continue;
- }
- $fullpath = $mod_dir . "/" . $_REQUEST["msg_id"][$i];
- if(!file_exists($fullpath)){
- echo "<span class=\"errorMessages\">"._("Moderation ID not found in the moderation folder!")."</span>";
- continue;
- }
- // TODO: Check if message is there!
- if( isset($_REQUEST["validate"]) ){
-// echo "Validating message ".$_REQUEST["msg_id"][$i]."<br>";
- $to_addr = $list_name . $delimiter . "moderate-" . $_REQUEST["msg_id"][$i] . "@" . $list_domain;
- $headers = "From: ".$from_addr;
- mail($to_addr,"MLMMJ Web interface moderation","MLMMJ Web interface moderation",$headers);
- }else{
-// echo "Deleting message ".$_REQUEST["msg_id"][$i]."<br>";
- unlink($mod_dir . "/" . $_REQUEST["msg_id"][$i]);
- if( file_exists($mod_dir . "/" . $_REQUEST["msg_id"][$i] . ".orig") ){
- unlink($mod_dir . "/" . $_REQUEST["msg_id"][$i] . ".orig");
- }
- }
- }
- }
-}
-
-// A bit of javascript to do the checkboxes inversion.
-echo "<html>
-<head>
-<link REL=\"stylesheet\" TYPE=\"text/css\" href=\"mlmmj.css\">
-<script language=\"JavaScript\" type=\"text/javascript\">
-function getObj(name){
- if (document.getElementById){
- this.obj = document.getElementById(name);
- this.style = document.getElementById(name).style;
- }else if (document.all){
- this.obj = document.all[name];
- this.style = document.all[name].style;
- }else if (document.layers){
- this.obj = document.layers[name];
- this.style = document.layers[name];
- }
-}
-function checkscript(){
- var frm = document.forms['zeForm'];
- var n = frm.elements.length;
- for(i=0;i<n;i++){
- if(frm.elements[i].type == 'checkbox'){
- if(frm.elements[i].checked == true){
- frm.elements[i].checked = false;
- }else{
- frm.elements[i].checked = true;
- }
- }
- }
-}
-</script>
-</head>
-<body>
-<h3>MLMMJ "._("moderation web interface")."</h3>
-<a href=\"".$_SERVER["PHP_SELF"]."\">"._("Refresh page")."</a>";
-
-if( isset($_REQUEST["action"]) && $_REQUEST["action"] == "show_message"){
- if( !ereg("^([0-9a-f]+)\$",$_REQUEST["msgid"]) ){
- echo "<span class=\"errorMessages\">"._("Message ID format is wrong: can't display!")."</span>";
- }else{
- $full_path = $mod_dir . "/" . $_REQUEST["msgid"];
- if( !file_exists($full_path) ){
- echo "<span class=\"errorMessages\">".("Message does not exists!")."</span>";
- }else{
- if(FALSE === ($input = file_get_contents($full_path))){
- echo "<span class=\"errorMessages\">"._("Error: could not read")." $full_path </span><br>";
- }else{
- $struct = decodeEmail($input);
- echo "<a href=\"". $_SERVER["PHP_SELF"] ."\">"._("Back to messages list")."</a><br><br>";
- echo "<b>"._("From:")." </b>" . htmlspecialchars($struct->headers["from"])."<br>";
- echo "<b>"._("Date:")." </b>" . htmlspecialchars($struct->headers["date"])."<br>";
- echo "<b>"._("To:")." </b>" . htmlspecialchars($struct->headers["to"])."<br>";
- echo "<b>"._("Subject:")." </b>" . htmlspecialchars($struct->headers["subject"])."<br>";
- echo "<b>"._("Message body:")."</b><br><br>" . nl2br(htmlspecialchars($struct->body));
- }
- }
- }
-}else{
- $all_msg = getMessageList();
- echo printAllMessages($all_msg);
-}
-
-echo '
-<div class="footer">
-<a href="http://www.mlmmj.org">MLMMJ</a>: Mailing List Manager Make it Joyfull<br />
-<span class="italics">
-MLMMJ PHP moderator code done by:
-<a target="_blank" href="http://thomas.goirand.fr">Thomas GOIRAND</a>, released under the therms of the
-MIT license. Please visit GPLHost\'s leading
-<a target="_blank" href="http://www.gplhost.com/hosting-vps.html">VPS hosting</a> service, and
-<a target="_blank" href="http://www.gplhost.com/software-dtc.html">DTC GPL control panel home</a>
-if you want hosting with MLMMJ support.
-</span>
-</div>
-</body></html>';
-
-?>
+++ /dev/null
-.alternatecolorline2 {
- background-color: #E3f9ff;
- font-size: 10px;
- }
-
-.alternatecolorline {
- background-color: #bcd0d6;
- font-size: 10px;
- }
-
-.tableTitle {
- text-align: center;
- color: #547074;
- font-size: 12px;
- background-color: #dbe9ed;
-}
-
-.errorMessages {
- color: #FF0000;
- font-size: 14px;
- font-weight: bold;
-}
-
-a:link{color:#105278;text-decoration: none;}
-a:visited{color:#105278;text-decoration: none;}
-a:hover{color:#000000;text-decoration: underline;}
-a:active{color:#000000;text-decoration: none;}
-
-html{height:100%; margin:4;}
-body{height:100%;margin:4; font: 12px Arial, Helvetica, sans-serif; color: #000000;}
-
-/* Forms fields definitions */
-input,select,textarea {
- font-family: arial;
- font-size: 12px;
- color: #000000;
- background-color: #F6F6F2;
- border-color: #ECEEE5 #F6F6F2 #F6F6F2 #ECEEE5;
-}
-
-h3 {
- text-align: center;
- font-size: 20px;
-}
-
-.footer{width:98%; text-align:center; position:absolute; bottom:0; padding:1%; }
+++ /dev/null
-Order Deny,Allow
-Deny from all
+++ /dev/null
-# MLMMJ moderation web interface templates.
-# Copyright (C) 2009 Thomas GOIRAND <thomas@goirand.fr>
-# This file is distributed under the same license as MLMMJ package.
-# Thomas Goirand <thomas@goirand.fr>, 2009.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: 0.1\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2009-03-05 07:25+0800\n"
-"PO-Revision-Date: 2009-03-05 07:29+0800\n"
-"Last-Translator: Thomas Goirand <thomas@goirand.fr>\n"
-"Language-Team: Thomas Goirand <thomas@goirand.fr>\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-
-#: mlmmj-moderation.php:259
-msgid "Back to messages list"
-msgstr "Retour a la liste des messages"
-
-#: mlmmj-moderation.php:144
-msgid "Date"
-msgstr "Date"
-
-#: mlmmj-moderation.php:261
-msgid "Date:"
-msgstr "Date :"
-
-#: mlmmj-moderation.php:177
-msgid "Delete"
-msgstr "Effacer"
-
-#: mlmmj-moderation.php:256
-msgid "Error: could not read"
-msgstr "Erreur: impossible de lire"
-
-#: mlmmj-moderation.php:175
-msgid "For the selection:"
-msgstr "Pour la sélection :"
-
-#: mlmmj-moderation.php:144
-msgid "From"
-msgstr "De"
-
-#: mlmmj-moderation.php:260
-msgid "From:"
-msgstr "De:"
-
-#: mlmmj-moderation.php:144
-msgid "Inverse selection"
-msgstr "Inverser la selection"
-
-#: mlmmj-moderation.php:249
-msgid "Message ID format is wrong: can't display!"
-msgstr "Le format de l'ID du message est faux: affichage impossible !"
-
-#: mlmmj-moderation.php:264
-msgid "Message body:"
-msgstr "Corp du message :"
-
-#: mlmmj-moderation.php:194
-msgid "Moderation ID not found in the moderation folder!"
-msgstr "ID de modération non trouve dans le dossier de modération!"
-
-#: mlmmj-moderation.php:157
-msgid "No date"
-msgstr "Pas de date"
-
-#: mlmmj-moderation.php:169
-msgid "No from in headers"
-msgstr "Pas de from dans les entêtes"
-
-#: mlmmj-moderation.php:184
-msgid "No message selected!"
-msgstr "Pas de message sélectionné !"
-
-#: mlmmj-moderation.php:161
-msgid "No subject"
-msgstr "Pas de sujet"
-
-#: mlmmj-moderation.php:245
-msgid "Refresh page"
-msgstr "Rafraichir la page"
-
-#: mlmmj-moderation.php:144
-msgid "Subject"
-msgstr "Sujet"
-
-#: mlmmj-moderation.php:263
-msgid "Subject:"
-msgstr "Sujet :"
-
-#: mlmmj-moderation.php:262
-msgid "To:"
-msgstr "Pour :"
-
-#: mlmmj-moderation.php:176
-msgid "Validate"
-msgstr "Valider"
-
-#: mlmmj-moderation.php:122
-msgid "Warning: could not read"
-msgstr "Alerte : impossible de lire"
-
-#: mlmmj-moderation.php:244
-msgid "moderation web interface"
-msgstr "interface web de moderation"
-
+++ /dev/null
-README webinterface Jun 27th 2004
-
-Ehh, what's that?
- The mlmmj-webinterface was created to give people the opportunity to
-{sub,unsub}scribe to a mailinglists via a webinterface (without having to
-write an initial {sub,unsub}scribe-mail).
-
-
-What are the requirements?
- You only need a webserver with PHP >= 3.0.8 support.
-
-
-How can I install/use the webinterface?
- - Upload mlmmj.php to your webserver.
- - Have a look at example.html and copy one or both forms
- into your website.
- - Adjust the options to satisfy your needs:
-
- The mailinglist your want to {sub,unsub}scribe to:
- <input name="mailinglist" type="hidden" value="mlmmj-test@example.org">
-
- Do you want to subscribe or unsubscribe?
- <input name="job" type="hidden" value="subscribe">
-
- Where do you want to redirect your user after a failure?
- <input name="redirect_failure" type="hidden" value="http://www.failure.com/">
-
- What should be the success redirect?
- <input name="redirect_success" type="hidden" value="http://www.success.com/">
-
-
-That's it - have a lot of fun!
-
- Christoph Thiel <ct at kki dot org>
+++ /dev/null
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
-<html>
-<head>
-<title>mlmmj-webinterface</title>
-</head>
-<body>
-
-<p>
-<h1>subscribe</h1>
-<form action="mlmmj.php" method="post">
-<input name="mailinglist" type="hidden" value="mlmmj-test@domain.tld">
-<input name="job" type="hidden" value="subscribe">
-<input name="redirect_failure" type="hidden" value="http://www.failure.com/">
-<input name="redirect_success" type="hidden" value="http://www.success.com/">
-<input name="email" type="text" size="30" maxlength="254"><br>
-<input type="submit" value="Subscribe">
-</form>
-</p>
-
-<p>
-<h1>unsubscribe</h1>
-<form action="mlmmj.php" method="post">
-<input name="mailinglist" type="hidden" value="mlmmj-test@domain.tld">
-<input name="job" type="hidden" value="unsubscribe">
-<input name="redirect_failure" type="hidden" value="http://www.failure.com/">
-<input name="redirect_success" type="hidden" value="http://www.success.com/">
-<input name="email" type="text" size="30" maxlength="254"><br>
-<input type="submit" value="Unsubscribe">
-</form>
-</p>
-
-</body>
-</html>
+++ /dev/null
-<?php
-
-/* Copyright (C) 2004 Christoph Thiel <ct at kki dot org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-
-// error_reporting(E_ALL);
-
-class mlmmj
-{
- var $email;
- var $mailinglist;
- var $job;
- var $redirect_success;
- var $redirect_failure;
-
- var $delimiter;
- var $errors;
-
- function is_email($string="")
- {
- if (eregi("^[a-z0-9\._-]+".chr(64)."+[a-z0-9\._-]+\.+[a-z]{2,4}$", $string))
- {
- return TRUE;
- }
- else
- {
- return FALSE;
- }
- }
-
- function error($string="")
- {
- $this->errors = TRUE;
-// die($string);
- }
-
- function mlmmj()
- {
- // set mandatory vars...
- $this->errors = FALSE;
- $this->delimiter = "+";
-
- if (!isset($_POST["email"]) &&
- !isset($_POST["mailinglist"]) &&
- !isset($_POST["job"]) &&
- !isset($_POST["redirect_success"]) &&
- !isset($_POST["redirect_failure"]))
- {
- $this->errors = TRUE;
- if(isset($_POST["redirect_failure"]))
- {
- header("Location: ".$_POST["redirect_failure"]);
- exit;
- }
- else
- die("An error occurred. Please check contrib/web/php-user/README for details.");
- }
- else
- {
- if($this->is_email($_POST["email"]))
- $this->email = $_POST["email"];
- else
- $this->error("ERROR: email is not a valid email address.");
-
- if($this->is_email($_POST["mailinglist"]))
- $this->mailinglist = $_POST["mailinglist"];
- else
- $this->error("ERROR: mailinglist is not a valid email address.");
-
- $this->job = $_POST["job"];
-
- if(!(($this->job == "subscribe") OR ($this->job == "unsubscribe")))
- {
- $this->error("ERROR: job unknown.");
- }
-
- $this->redirect_failure = $_POST["redirect_failure"];
- $this->redirect_success = $_POST["redirect_success"];
-
- }
-
- // now we should try to go ahead and {sub,unsub}scribe... ;)
-
- if(!$this->errors)
- {
- // @ ^= char(64)
-
- $to = str_replace(chr(64),$this->delimiter.$this->job.chr(64),$this->mailinglist);
- $subject = $this->job." to ".$this->mailinglist;
- $body = $this->job;
- $addheader = "";
- $addheader .= "Received: from ". $_SERVER["REMOTE_ADDR"]
- ." by ". $_SERVER["SERVER_NAME"]. " with HTTP;\r\n\t".date("r")."\n";
- $addheader .= "X-Originating-IP: ".$_SERVER["REMOTE_ADDR"]."\n";
- $addheader .= "X-Mailer: mlmmj-webinterface powered by PHP/". phpversion() ."\n";
- $addheader .= "From: ".$this->email."\n";
- $addheader .= "Cc: ".$this->email."\n";
-
- if(!mail($to, $subject, $body, $addheader))
- $this->error($this->job." failed.");
- }
-
- if($this->errors)
- {
- header("Location: ".$this->redirect_failure);
- exit;
- }
- else
- {
- header("Location: ".$this->redirect_success);
- exit;
- }
- }
-}
-
-
-$mailinglist = new mlmmj;
-
-?>