changeset 290:1180bcbc90d9

initial revision
author mortenp
date Sat, 10 Jul 2004 06:28:16 +1000
parents c0beaab3aa91
children 7da5c55b9330
files contrib/web/perl-admin/README contrib/web/perl-admin/config.pl contrib/web/perl-admin/dot.htaccess contrib/web/perl-admin/dot.htpasswd contrib/web/perl-admin/edit.cgi contrib/web/perl-admin/index.cgi contrib/web/perl-admin/save.cgi contrib/web/perl-user/config.pl contrib/web/perl-user/example.html contrib/web/perl-user/mlmmj.cgi contrib/web/php-user/README contrib/web/php-user/example.html contrib/web/php-user/mlmmj.php
diffstat 13 files changed, 606 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/web/perl-admin/README	Sat Jul 10 06:28:16 2004 +1000
@@ -0,0 +1,22 @@
+To use this web-interface you have to:
+
+1) Copy the files into your webroot, preferably in a sub-directory.
+
+2) 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/
+
+
+To enable access control on Apache you have to:
+
+3) Rename dot.htaccess to .htaccess.
+
+4) Rename dot.htpasswd to .htpasswd and remove the default login (admin:mlmmj)
+   from it. Then run
+
+     $ htpasswd .htpasswd USER
+
+   to add the login "USER" to the access file.
+
+5) That is it, you are ready to use the interface.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/web/perl-admin/config.pl	Sat Jul 10 06:28:16 2004 +1000
@@ -0,0 +1,1 @@
+$topdir = "/var/spool/mlmmj";
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/web/perl-admin/dot.htaccess	Sat Jul 10 06:28:16 2004 +1000
@@ -0,0 +1,7 @@
+Options +ExecCGI
+DirectoryIndex index.cgi
+
+Require valid-user
+AuthType Basic
+AuthName "mlmmj web-interface"
+AuthUserFile /srv/www/htdocs/.htpasswd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/web/perl-admin/dot.htpasswd	Sat Jul 10 06:28:16 2004 +1000
@@ -0,0 +1,1 @@
+admin:wQEi/IDlNVK82
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/web/perl-admin/edit.cgi	Sat Jul 10 06:28:16 2004 +1000
@@ -0,0 +1,107 @@
+#!/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";
+
+sub mlmmj_boolean {
+    my $name = shift;
+    my $text = shift;
+    my $checked = -f "$topdir/$list/control/$name";
+
+    print("<tr>");
+    print("<td>", $query->checkbox(-name=>$name,-checked=>$checked), "</td>\n");
+    print("<td>$text</td>\n");
+    print("</tr>");
+}
+
+sub mlmmj_string {
+    my $name = shift;
+    my $text = shift;
+    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);
+    }
+    print("<tr>");
+    print("<td>$name ", $query->textfield(-name=>$name,-default=>$value),"</td>\n");
+    print("<td>$text</td>\n");
+    print("</tr>");
+}
+
+sub mlmmj_list {
+    my $name = shift;
+    my $text = shift;
+    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);
+    }
+
+    print("<tr>");
+    print("<td>$name ", $query->textarea(-name=>$name,-default=>$value,-columns=>40), "</td>\n");
+    print("<td>$text</td>\n");
+    print("</tr>");
+}
+
+$query = new CGI;
+$list = $query->url(-relative=>1,-path=>1);
+$list =~ s/^[^\/]*\/([^\/]+)\/$/$1/ or die('no list parameter');
+#printf("list = '%s'<br/>\n", $list);
+
+print header;
+print start_html('mlmmj config');
+
+print($query->startform("POST","/save.cgi/$list/"));
+print("<table>");
+mlmmj_boolean("closedlist", "If this option is set, subscribtion and unsubscription via mail is disabled.");
+mlmmj_boolean("moderated", "If this option is set, the emailaddresses in the file listdir/control/moderators will act as moderators for the list.");
+mlmmj_boolean("tocc", "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", "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", "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_string("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", "The emailaddresses in this list will get mails to $list+owner");
+mlmmj_list("delheaders", "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", "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", "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).");
+print("</table>");
+print($query->submit());
+print($query->endform());
+
+print end_html;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/web/perl-admin/index.cgi	Sat Jul 10 06:28:16 2004 +1000
@@ -0,0 +1,39 @@
+#!/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";
+
+print header;
+print start_html('mlmmj config');
+
+opendir(DIR, $topdir);
+while ($list = readdir(DIR)) {
+    next if $list =~ /^\./;
+    printf("<a href=\"edit.cgi/%1\$s/\">%1\$s</a><br/>\n", $list);
+}
+closedir(DIR);
+
+print end_html;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/web/perl-admin/save.cgi	Sat Jul 10 06:28:16 2004 +1000
@@ -0,0 +1,70 @@
+#!/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.
+
+# 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 CGI qw(:standard);
+
+require "config.pl";
+
+$query = new CGI;
+$list = $query->url(-relative=>1,-path=>1);
+$list =~ s/^[^\/]*\/([^\/]+)\/$/$1/ or die('no list parameter');
+#printf("list = '%s'<br/>\n", $list);
+
+($query->request_method() eq 'POST') or die('wrong method');
+
+@controls = $query->all_parameters();
+
+foreach $param (keys %{$query->{'.fieldnames'}}) {
+	#printf("B params=[%s]<br/>\n", $name);
+	if (!defined $query->param($param)) {
+		push(@controls, $param);
+	}
+}
+
+
+foreach $control (@controls) {
+	($control !~ /^[a-z]\+$/) or die("illegal control name '$control'");
+        my $file = "$topdir/$list/control/$control";
+	my $value = $query->param($control);
+	#printf("A params=[%s -> '%s']<br/>\n", $control, $value);
+
+	if (length($value) > 0) {
+		open(FILE, ">$file") or die("unable to open '$file'");
+		printf(FILE "%s\n", $query->param($control));
+		close(FILE);
+	} else {
+		if (-f $file) {
+			unlink($file) or die("unable to unlin '$file'");
+		}
+	}
+}
+
+print header;
+print start_html('mlmmj config');
+print "$list control values saved!";
+print end_html;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/web/perl-user/config.pl	Sat Jul 10 06:28:16 2004 +1000
@@ -0,0 +1,3 @@
+$topdir = "/var/spool/mlmmj";
+$sendmail = "/usr/lib/sendmail";
+$delimiter = "+";
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/web/perl-user/example.html	Sat Jul 10 06:28:16 2004 +1000
@@ -0,0 +1,34 @@
+<!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	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/web/perl-user/mlmmj.cgi	Sat Jul 10 06:28:16 2004 +1000
@@ -0,0 +1,114 @@
+#!/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() . " witn 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"
+		. "Cc: $from\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);
+}
+
+
+$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');
+
+print header;
+print $list;
+
+if (mlmmj_check_list($list) 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	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/web/php-user/README	Sat Jul 10 06:28:16 2004 +1000
@@ -0,0 +1,35 @@
+README webinterface					Jun 27th 2004
+
+Ehh, what's that?
+   The mlmmj-webinterface was created to give people the opportunity to
+{sub,unsub}scribe to your mailinglists without having to write an initial
+{sub,unsub}scribe-mail, but only completing a form.
+
+
+What are the requirements?
+   Only a webserver, that has PHP >= 3.0.8 support.
+
+
+How can I install/use the webinterface?
+   - Upload webinterface/mlmmj.php to your webserver.
+   - Have a look at webinterface/example.html and copy one or both forms
+     and put them 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="test@ct.kki.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 fun!
+
+	Christoph Thiel <ct at kki dot org>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/web/php-user/example.html	Sat Jul 10 06:28:16 2004 +1000
@@ -0,0 +1,33 @@
+<!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	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/web/php-user/mlmmj.php	Sat Jul 10 06:28:16 2004 +1000
@@ -0,0 +1,140 @@
+<?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()
+	{
+	    global $HTTP_POST_VARS, $HTTP_SERVER_VARS;
+
+	    // set mandatory vars...
+	    $this->errors = FALSE;
+	    $this->delimiter = "+";
+
+	    if (!isset($HTTP_POST_VARS["email"]) &&
+		!isset($HTTP_POST_VARS["mailinglist"]) &&
+		!isset($HTTP_POST_VARS["job"]) &&
+		!isset($HTTP_POST_VARS["redirect_success"]) &&
+		!isset($HTTP_POST_VARS["redirect_failure"]))
+	    {
+		$this->errors = TRUE;
+		if(isset($HTTP_POST_VARS["redirect_failure"]))
+		{
+		    header("Location: ".$HTTP_POST_VARS["redirect_failure"]);
+		    exit;
+		}
+		else
+		    die("An error occurred. Please check contrib/web/php-user/README for details.");
+	    }
+	    else
+	    {
+		if($this->is_email($HTTP_POST_VARS["email"]))
+		    $this->email = $HTTP_POST_VARS["email"];
+		else
+		    $this->error("ERROR: email is not a valid email address.");
+
+		if($this->is_email($HTTP_POST_VARS["mailinglist"]))
+		    $this->mailinglist = $HTTP_POST_VARS["mailinglist"];
+		else
+		    $this->error("ERROR: mailinglist is not a valid email address.");
+		
+		$this->job = $HTTP_POST_VARS["job"];
+		
+		if(!(($this->job == "subscribe") OR ($this->job == "unsubscribe")))
+		{
+		    $this->error("ERROR: job unknown.");
+		}
+		
+		$this->redirect_failure = $HTTP_POST_VARS["redirect_failure"];
+		$this->redirect_success = $HTTP_POST_VARS["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 ". $HTTP_SERVER_VARS["REMOTE_ADDR"]
+		    ." by ". $HTTP_SERVER_VARS["SERVER_NAME"]. " with HTTP;\r\n\t".date("r")."\n";
+		$addheader .= "X-Originating-IP: ".$HTTP_SERVER_VARS["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;
+
+?>