changeset 697:9d5846a45086

Added contrib/web/php-moderation (Thomas Goirand)
author mortenp
date Thu, 05 Mar 2009 07:08:29 +1100
parents 9b32890a008e
children 8427a73e12b7
files ChangeLog contrib/web/php-moderation/build-translations.sh contrib/web/php-moderation/mlmmj-moderation.php contrib/web/php-moderation/mlmmj.css contrib/web/php-moderation/translations/dot.htaccess contrib/web/php-moderation/translations/fr_FR.po
diffstat 6 files changed, 463 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Thu Mar 05 07:05:19 2009 +1100
+++ b/ChangeLog	Thu Mar 05 07:08:29 2009 +1100
@@ -1,3 +1,4 @@
+ o Added contrib/web/php-moderation (Thomas Goirand)
 1.2.16
  o Fixed injection in contrib/web/perl-user (Gerd von Egidy)
 1.2.16-RC1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/web/php-moderation/build-translations.sh	Thu Mar 05 07:08:29 2009 +1100
@@ -0,0 +1,37 @@
+#!/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	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/web/php-moderation/mlmmj-moderation.php	Thu Mar 05 07:08:29 2009 +1100
@@ -0,0 +1,277 @@
+<?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) {
+				$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>";
+		$out .= "<td $cls>" . htmlspecialchars($all_msg[$i]["headers"]["date"]) . "</td>";
+		if( 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>";
+		$out .= "<td $cls>" . htmlspecialchars($all_msg[$i]["headers"]["from"]) . "</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]);
+			}
+		}
+	}
+}
+
+// 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>';
+
+?>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/web/php-moderation/mlmmj.css	Thu Mar 05 07:08:29 2009 +1100
@@ -0,0 +1,46 @@
+.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	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/web/php-moderation/translations/dot.htaccess	Thu Mar 05 07:08:29 2009 +1100
@@ -0,0 +1,2 @@
+Order Deny,Allow
+Deny from all
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/web/php-moderation/translations/fr_FR.po	Thu Mar 05 07:08:29 2009 +1100
@@ -0,0 +1,100 @@
+# 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-02-08 11:46+0000\n"
+"PO-Revision-Date: 2009-02-08 11:15+0000\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:249
+msgid "Back to messages list"
+msgstr "Retour a la liste des messages"
+
+#: mlmmj-moderation.php:144
+msgid "Date"
+msgstr "Date"
+
+#: mlmmj-moderation.php:251
+msgid "Date:"
+msgstr "Date :"
+
+#: mlmmj-moderation.php:167
+msgid "Delete"
+msgstr "Effacer"
+
+#: mlmmj-moderation.php:246
+msgid "Error: could not read"
+msgstr "Erreur: impossible de lire"
+
+#: mlmmj-moderation.php:165
+msgid "For the selection:"
+msgstr "Pour la selection :"
+
+#: mlmmj-moderation.php:144
+msgid "From"
+msgstr "De"
+
+#: mlmmj-moderation.php:250
+msgid "From:"
+msgstr "De:"
+
+#: mlmmj-moderation.php:144
+msgid "Inverse selection"
+msgstr "Inverser la selection"
+
+#: mlmmj-moderation.php:239
+msgid "Message ID format is wrong: can't display!"
+msgstr "Le format de l'ID du message est faux: affichage impossible !"
+
+#: mlmmj-moderation.php:254
+msgid "Message body:"
+msgstr "Corp du message :"
+
+#: mlmmj-moderation.php:184
+msgid "Moderation ID not found in the moderation folder!"
+msgstr "ID de moderation non trouve dans le dossier de moderation!"
+
+#: mlmmj-moderation.php:174
+msgid "No message selected!"
+msgstr "Pas de message selectionne !"
+
+#: mlmmj-moderation.php:156
+msgid "No subject"
+msgstr "Pas de sujet"
+
+#: mlmmj-moderation.php:235
+msgid "Refresh page"
+msgstr "Rafraichir la page"
+
+#: mlmmj-moderation.php:144
+msgid "Subject"
+msgstr "Sujet"
+
+#: mlmmj-moderation.php:253
+msgid "Subject:"
+msgstr "Sujet :"
+
+#: mlmmj-moderation.php:252
+msgid "To:"
+msgstr "Pour :"
+
+#: mlmmj-moderation.php:166
+msgid "Validate"
+msgstr "Valider"
+
+#: mlmmj-moderation.php:122
+msgid "Warning: could not read"
+msgstr "Warning : impossible de lire"
+
+#: mlmmj-moderation.php:234
+msgid "moderation web interface"
+msgstr "interface web de moderation"