[Fusionforge-commits] r9470 - in trunk: gforge/common gforge/common/include gforge/common/mail gforge/common/valid gforge/www/include plugins/coclico/mailman/include plugins/coclico/mailman/usr/lib/mailman/Mailman plugins/coclico/mailman/www plugins/coclico/mailman/www/admin plugins/coclico/mailman/www/themes plugins/coclico/mailman/www/themes/default plugins/coclico/mailman/www/themes/default/images plugins/coclico/mailman/www/themes/default/images/ic

Mélanie Le Bail melanelebail at libremir.placard.fr.eu.org
Wed Apr 14 10:58:49 CEST 2010


Author: melanelebail
Date: 2010-04-14 10:58:49 +0200 (Wed, 14 Apr 2010)
New Revision: 9470

Added:
   trunk/gforge/common/include/Codendi_HTMLPurifier.class.php
   trunk/gforge/common/include/PluginInfo.class.php
   trunk/gforge/common/mail/Mail.class.php
   trunk/gforge/common/valid/
   trunk/gforge/common/valid/Rule.class.php
   trunk/gforge/common/valid/Valid.class.php
   trunk/gforge/common/valid/ValidFactory.class.php
   trunk/gforge/www/include/preplugins.php
   trunk/plugins/coclico/mailman/www/themes/
   trunk/plugins/coclico/mailman/www/themes/default/
   trunk/plugins/coclico/mailman/www/themes/default/images/
   trunk/plugins/coclico/mailman/www/themes/default/images/ic/
   trunk/plugins/coclico/mailman/www/themes/default/images/ic/add.png
   trunk/plugins/coclico/mailman/www/themes/default/images/ic/delete.png
   trunk/plugins/coclico/mailman/www/themes/default/images/ic/tick.png
Modified:
   trunk/gforge/common/include/Codendi_Request.class.php
   trunk/gforge/common/include/PluginManager.class.php
   trunk/gforge/common/include/UserManager.class.php
   trunk/gforge/www/include/plugins_utils.php
   trunk/gforge/www/include/pre.php
   trunk/plugins/coclico/mailman/include/MailmanList.class.php
   trunk/plugins/coclico/mailman/include/MailmanListDao.class.php
   trunk/plugins/coclico/mailman/usr/lib/mailman/Mailman/ExternalConnector.py
   trunk/plugins/coclico/mailman/www/admin/deletelist.php
   trunk/plugins/coclico/mailman/www/admin/index.php
   trunk/plugins/coclico/mailman/www/index.php
   trunk/plugins/coclico/mailman/www/mailman_utils.php
Log:
- Modif mailman plugin :
---- display : table with nice buttons
---- hook to prepare integration of forumml plugin
- Add Codendi classes that will be useful to forumML plugin
- Clean pre.php of codendi classes and creation of preplugins.php


Added: trunk/gforge/common/include/Codendi_HTMLPurifier.class.php
===================================================================
--- trunk/gforge/common/include/Codendi_HTMLPurifier.class.php	                        (rev 0)
+++ trunk/gforge/common/include/Codendi_HTMLPurifier.class.php	2010-04-14 08:58:49 UTC (rev 9470)
@@ -0,0 +1,236 @@
+<?php
+/**
+ * Copyright (c) STMicroelectronics, 2007. All Rights Reserved.
+ * 
+ * Originally written by Manuel VACELET, 2007.
+ * 
+ * This file is a part of Codendi.
+ *
+ * Codendi 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 of the License, or
+ * (at your option) any later version.
+ *
+ * Codendi 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Codendi. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Clean-up HTML code for user output.
+ *
+ * This class aims to purify the HTML code provided by a user for beeing
+ * displayed saftly (remove XSS and make the HTML std compliant).
+ * How to use it:
+ * <pre>
+ * require_once('pre.php');
+ * require_once('common/include/Codendi_HTMLPurifier.class.php');
+ * $crapy = '<a href="" onmouseover="alert(1);">testé</a>';
+ * $hp =& Codendi_HTMLPurifier::instance();
+ * $clean = $hp->purify($crapy);
+ * </pre>
+ */
+
+define('CODENDI_PURIFIER_CONVERT_HTML', 0);
+define('CODENDI_PURIFIER_STRIP_HTML', 1);
+define('CODENDI_PURIFIER_BASIC',      5);
+define('CODENDI_PURIFIER_BASIC_NOBR',      6);
+define('CODENDI_PURIFIER_LIGHT',     10);
+define('CODENDI_PURIFIER_FULL',      15);
+define('CODENDI_PURIFIER_JS_QUOTE', 20);
+define('CODENDI_PURIFIER_JS_DQUOTE', 25);
+define('CODENDI_PURIFIER_DISABLED', 100);
+
+class Codendi_HTMLPurifier {
+    /**
+     * Hold an instance of the class
+     */
+    private static $Codendi_HTMLPurifier_instance;
+    
+    /**
+     * Constructor
+     */
+    private function __construct() {
+    }
+
+    /**
+     * Singleton access.
+     *
+     * @access: static
+     */
+    public static function instance() {
+        if (!isset(self::$Codendi_HTMLPurifier_instance)) {
+            $c = __CLASS__;
+            self::$Codendi_HTMLPurifier_instance = new $c;
+        }
+        return self::$Codendi_HTMLPurifier_instance;
+    }
+
+    /**
+     * Base configuration of HTML Purifier for codendi.
+     */
+    protected function getCodendiConfig() {
+        $config = HTMLPurifier_Config::createDefault();
+        $config->set('Core', 'Encoding', 'UTF-8');
+        // $config->set('HTML', 'Doctype', 'XHTML 1.0 Strict');
+        $config->set('Cache', 'SerializerPath', $GLOBALS['codendi_cache_dir']);
+        return $config;
+    }
+
+    /**
+     * Allow basic formatting markups.
+     *
+     */
+    function getLightConfig() {
+        $config = $this->getCodendiConfig();
+        $config->set('HTML', 'Allowed', $this->getLightConfigMarkups());
+        return $config;
+    }
+    
+    /**
+     * Get allowed markups for light config
+     *
+     * This function defines the markups allowed for a light
+     * formatting. This includes markups for lists, for paragraphs, hypertext
+     * links, and content-based text.
+     * Allowed makups:
+     * - 'p', 'br'
+     * - 'a[href|title|class]'
+     * - 'ul', 'ol', 'li'
+     * - 'cite', 'code', 'blockquote', 'strong', 'em', 'pre', 'b', 'i'
+     */
+    function getLightConfigMarkups() {
+        $eParagraph       = array('p', 'br');
+        $eLinks           = array('a[href|title|class]');
+        $eList            = array('ul', 'ol', 'li');
+        $eContentBasedTxt = array('cite', 'code', 'blockquote', 'strong', 'em',
+                                  'pre', 'b', 'i');
+        
+        $aa = array_merge($eParagraph, $eLinks, $eList, $eContentBasedTxt);
+        $allowed = implode(',', $aa);
+        
+        return $allowed;
+    }
+
+    /**
+     *
+     */
+    function getStripConfig() {
+        $config = $this->getCodendiConfig();
+        $config->set('HTML', 'Allowed', '');
+        return $config;
+    }
+
+    /**
+     * HTML Purifier configuration factory
+     */
+    function getHPConfig($level) {
+        $config = null;
+        switch($level) {
+        case CODENDI_PURIFIER_LIGHT:
+            $config = $this->getLightConfig();
+            break;
+
+        case CODENDI_PURIFIER_FULL:
+            $config = $this->getCodendiConfig();
+            break;
+
+        case CODENDI_PURIFIER_STRIP_HTML:
+            $config = $this->getStripConfig();
+            break;
+        }
+        return $config;
+    }
+
+    /**
+     * Wrap call to util_make_links (for testing purpose).
+     */
+    function _makeLinks($str, $groupId) {
+        return util_make_links($str, $groupId);
+    }
+
+    /**
+     * Perform HTML purification depending of level purification required.
+     *
+     * There are 5 level of purification, from the most restrictive to most
+     * permissive:
+     * - CODENDI_PURIFIER_CONVERT_HTML (default)
+     *   Transform HTML markups it in entities.
+     *
+     * - CODENDI_PURIFIER_STRIP_HTML
+     *   Removes all HTML markups. Note: as we relly on HTML Purifier to
+     *   perform this operation this option is not considered as secure as
+     *   CONVERT_HTML. If you are looking for the most secure option please
+     *   consider CONVERT_HTML.
+     *
+     * - CODENDI_PURIFIER_BASIC (need $groupId to be set for automagic links)
+     *   Removes all user submitted HTML markups but: 
+     *    - transform typed URLs into clickable URLs.
+     *    - transform autmagic links.
+     *    - transform carrige return into HTML br markup.
+     *
+     * - CODENDI_PURIFIER_LIGHT
+     *   First set of HTML formatting (@see getLightConfig() for allowed
+     *   markups) plus all what is allowed by CODENDI_PURIFIER_BASIC.
+     *
+     * - CODENDI_PURIFIER_FULL
+     *   Clean-up plain HTML using HTML Purifier rules (remove forms,
+     *   javascript, ...). Warning: there is no longer codendi facilities
+     *   (neither automagic links nor carrige return to br transformation).
+     *
+     * - CODENDI_PURIFIER_DISABLED
+     *   No filter at all.
+     */
+    function purify($html, $level=0, $groupId=0) {
+        $clean = '';
+        switch($level) {
+        case CODENDI_PURIFIER_DISABLED:
+            $clean = $html;
+            break;
+
+        case CODENDI_PURIFIER_LIGHT:
+            $html = nl2br($this->_makeLinks($html, $groupId));
+        case CODENDI_PURIFIER_STRIP_HTML:
+        case CODENDI_PURIFIER_FULL:
+            require_once('HTMLPurifier.auto.php');
+            $hp =& HTMLPurifier::getInstance();
+            $config = $this->getHPConfig($level);
+            $clean = $hp->purify($html, $config);
+            // Quite big object, it's better to unset it (memory).
+            unset($config);
+            break;
+
+        case CODENDI_PURIFIER_BASIC:
+            $clean = nl2br($this->_makeLinks(htmlentities($html, ENT_QUOTES, 'UTF-8'), $groupId));
+            break;
+        case CODENDI_PURIFIER_BASIC_NOBR:
+            $clean = $this->_makeLinks(htmlentities($html, ENT_QUOTES, 'UTF-8'), $groupId);
+            break;
+
+        case CODENDI_PURIFIER_JS_QUOTE:
+            $clean = preg_replace('/\<\/script\>/umsi', "</'+'script>", addslashes(preg_replace('/\\\n/ums', "
+", $html)));
+            break;
+        case CODENDI_PURIFIER_JS_DQUOTE:
+            $clean = preg_replace('/\<\/script\>/umsi', '</"+"script>', addslashes(preg_replace('/\\\n/ums', '
+', $html)));
+            break;
+        case CODENDI_PURIFIER_CONVERT_HTML:
+        default:
+            $clean = htmlentities($html, ENT_QUOTES, 'UTF-8');
+            break;
+        }
+        return $clean;
+    }
+
+    function purifyMap($array, $level=0, $groupId=0) {
+        return array_map(array(&$this, "purify"), $array, array($level), array($groupId));
+    }
+
+}
+
+?>

Modified: trunk/gforge/common/include/Codendi_Request.class.php
===================================================================
--- trunk/gforge/common/include/Codendi_Request.class.php	2010-04-13 15:30:44 UTC (rev 9469)
+++ trunk/gforge/common/include/Codendi_Request.class.php	2010-04-14 08:58:49 UTC (rev 9470)
@@ -19,90 +19,144 @@
  */
 
 /* abstract */ class Codendi_Request {
-    /**
-     * @var array
-     * @access private
-     */
-    var $_validated_input;
-    
-    /**
-     * @var array
-     * @access private
-     */
-    var $_last_access_to_input;
-    
-    /**
-     * @var array
-     */
-    var $params;
-    
-    /**
-     * Constructor
-     */
-    function Codendi_Request($params) {
-        $this->params                = $params;
-        $this->_validated_input      = array();
-        $this->_last_access_to_input = array();
-    }
-    
-   
-    /**
-     * Get the value of $variable in $this->params (user submitted values).
-     *
-     * @param string $variable Name of the parameter to get.
-     * @return mixed If the variable exist, the value is returned (string)
-     * otherwise return false;
-     */
-    function get($variable) {
-      
-        return $this->_get($variable, $this->params);
-    }
+	/**
+	 * @var array
+	 * @access private
+	 */
+	var $_validated_input;
 
-    /**
-     * Add a param and/or set its value
-     *
-     */
-    function set($name, $value) {
-        $this->params[$name] = $value;
-    }
+	/**
+	 * @var array
+	 * @access private
+	 */
+	var $_last_access_to_input;
 
-    
-    /**
-     * Get the value of $variable in $array. 
-     *
-     * @access private
-     * @param string $variable Name of the parameter to get.
-     * @param array $array Name of the parameter to get.
-     */
-    function _get($variable, $array) {
-        if ($this->_exist($variable, $array)) {
-            return $array[$variable];
-        } else {
-            return false;
-        }
-    }
+	/**
+	 * @var array
+	 */
+	var $params;
 
-    /**
-     * Check if $variable exists in user submitted parameters.
-     *
-     * @param string $variable Name of the parameter.
-     * @return boolean
-     */
-    function exist($variable) {
-        return $this->_exist($variable, $this->params);
-    }
-    
-    /**
-     * Check if $variable exists in $array.
-     *
-     * @access private
-     * @param string $variable Name of the parameter.
-     * @return boolean
-     */
-    function _exist($variable, $array) {
-        return isset($array[$variable]);
-    }
-    
+	/**
+	 * Constructor
+	 */
+	function Codendi_Request($params) {
+		$this->params                = $params;
+		$this->_validated_input      = array();
+		$this->_last_access_to_input = array();
+	}
 
+
+	/**
+	 * Get the value of $variable in $this->params (user submitted values).
+	 *
+	 * @param string $variable Name of the parameter to get.
+	 * @return mixed If the variable exist, the value is returned (string)
+	 * otherwise return false;
+	 */
+	function get($variable) {
+
+		return $this->_get($variable, $this->params);
+	}
+
+	/**
+	 * Add a param and/or set its value
+	 *
+	 */
+	function set($name, $value) {
+		$this->params[$name] = $value;
+	}
+
+
+	/**
+	 * Get the value of $variable in $array. 
+	 *
+	 * @access private
+	 * @param string $variable Name of the parameter to get.
+	 * @param array $array Name of the parameter to get.
+	 */
+	function _get($variable, $array) {
+		if ($this->_exist($variable, $array)) {
+			return $array[$variable];
+		} else {
+			return false;
+		}
+	}
+
+	/**
+	 * Check if $variable exists in user submitted parameters.
+	 *
+	 * @param string $variable Name of the parameter.
+	 * @return boolean
+	 */
+	function exist($variable) {
+		return $this->_exist($variable, $this->params);
+	}
+
+	/**
+	 * Check if $variable exists in $array.
+	 *
+	 * @access private
+	 * @param string $variable Name of the parameter.
+	 * @return boolean
+	 */
+	function _exist($variable, $array) {
+		return isset($array[$variable]);
+	}
+	/**
+	 * Apply validator on submitted user value.
+	 *
+	 * @param Valid  Validator to apply
+	 * @return boolean
+	 */
+	function valid(&$validator) {
+		$this->_validated_input[$validator->getKey()] = true;
+		$attachmentId=5;
+		return $validator->validate($this->get($validator->getKey()));
+	} 
+
+	/**
+	 * Apply validator on all values of a submitted user array.
+	 *
+	 * @param Valid  Validator to apply
+	 * @return boolean
+	 */
+	function validArray(&$validator) {
+		$this->_validated_input[$validator->getKey()] = true;
+		$isValid = true;
+		$array = $this->get($validator->getKey());
+		if (is_array($array)) {
+			if (count($array)>0) {
+				foreach ($array as $key => $v) {
+					if (!$validator->validate($v)) {
+						$isValid = false;
+					}
+				}
+			} else {
+				$isValid = $validator->validate(null);
+			}
+		} else {
+			$isValid = false;
+		}
+		return $isValid;
+	}
+	/**
+	 * Apply validator on submitted user value and return the value if valid
+	 * Else return default value
+	 * @param string $variable Name of the parameter to get.
+	 * @param mixed $validator Name of the validator (string, uint, email) or an instance of a validator
+	 * @param mixed $default_value Value return if the validator is not valid. Optional, default is null.
+	 */
+	function getValidated($variable, $validator = 'string', $default_value = null) {
+		/*$is_valid = false;
+		  if ($v = ValidFactory::getInstance($validator, $variable)) {
+		  $is_valid = $this->valid($v);
+		  } else {
+		  trigger_error('Validator '. $validator .' is not found', E_USER_ERROR);
+		  }
+		  return $is_valid ? $this->get($variable) : $default_value;*/
+		return $this->get($variable);
+	}
+
+
 }
 ?>

Added: trunk/gforge/common/include/PluginInfo.class.php
===================================================================
--- trunk/gforge/common/include/PluginInfo.class.php	                        (rev 0)
+++ trunk/gforge/common/include/PluginInfo.class.php	2010-04-14 08:58:49 UTC (rev 9470)
@@ -0,0 +1,56 @@
+<?php
+/**
+ * Copyright (c) Xerox Corporation, Codendi Team, 2001-2009. All rights reserved
+ *
+ * This file is a part of Codendi.
+ *
+ * Codendi 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 of the License, or
+ * (at your option) any later version.
+ *
+ * Codendi 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Codendi. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * PluginInfo
+ */
+class PluginInfo {
+    
+    var $plugin;
+    var $pluginDescriptor;
+    var $propertyDescriptors;
+    
+    function PluginInfo($plugin) {
+        $this->plugin              = $plugin;
+    }
+    
+    function setPluginDescriptor($descriptor) {
+    }
+    
+    function getPluginDescriptor() {
+    }
+    function getPropertyDescriptors() {
+    }
+    
+    function _addPropertyDescriptor($descriptor) {
+    }
+    function _removePropertyDescriptor($descriptor) {
+    }
+    
+    function loadProperties() {
+    }
+    
+    function saveProperties() {
+    }
+    
+    function getPropertyDescriptorForName($name) {
+    }
+}
+?>

Modified: trunk/gforge/common/include/PluginManager.class.php
===================================================================
--- trunk/gforge/common/include/PluginManager.class.php	2010-04-13 15:30:44 UTC (rev 9469)
+++ trunk/gforge/common/include/PluginManager.class.php	2010-04-14 08:58:49 UTC (rev 9470)
@@ -18,7 +18,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with FusionForge; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 
  * USA
  */
 
@@ -38,7 +38,15 @@
 		$this->plugins_to_hooks = array () ;
 		$this->hooks_to_plugins = array () ;
 	}
+	//to work with Codendi files
+	function instance() {
+		global $PLUGINMANAGER_OBJ;
+		if (!isset($PLUGINMANAGER_OBJ) || !$PLUGINMANAGER_OBJ) {
+			$PLUGINMANAGER_OBJ = new PluginManager ;
+		}
+		return $PLUGINMANAGER_OBJ ;
 
+	}
 	/**
 	 * GetPlugins() - get a list of installed plugins
 	 *
@@ -48,7 +56,7 @@
 		if (!isset($this->plugins_data)) {
 			$this->plugins_data = array () ;
 			$res = db_query_params ('SELECT plugin_id, plugin_name FROM plugins',
-						array ());
+					array ());
 			$rows = db_numrows($res);
 			for ($i=0; $i<$rows; $i++) {
 				$plugin_id = db_result($res,$i,'plugin_id');
@@ -68,6 +76,10 @@
 		return @$this->plugins_objects [$pluginname] ;
 	}
 
+	//Added for Codendi compatibility
+	function getPluginByName ($pluginname) {
+		return @$this->plugins_objects [$pluginname] ;
+	}
 	/**
 	 * PluginIsInstalled() - is a plugin installed?
 	 *
@@ -83,13 +95,22 @@
 		}
 		return false ;
 	}
-
+	function isPluginAvailable ($plugin) {
+		$pluginname = $plugin->GetName();
+		$plugins_data = $this->getPlugins() ;
+		foreach ($plugins_data as $p_id => $p_name) {
+			if ($p_name == $pluginname) {
+				return true ;
+			}
+		}
+		return false ;
+	}
 	function activate($pluginname) {
 		$res = db_query_params('INSERT INTO plugins (plugin_name,plugin_desc) VALUES ($1,$2)',
-			array($pluginname, "This is the $pluginname plugin"));
+				array($pluginname, "This is the $pluginname plugin"));
 
 		$res = db_query_params ('SELECT plugin_id, plugin_name FROM plugins WHERE plugin_name=$1',
-			array ($pluginname));
+				array ($pluginname));
 		if (db_numrows($res) == 1) {
 			$plugin_id = db_result($res,0,'plugin_id');
 			$this->plugins_data[$plugin_id] = db_result($res,0,'plugin_name');
@@ -117,7 +138,7 @@
 	 */
 	function LoadPlugin ($p_name) {
 		global $gfplugins;
-		
+
 		$plugins_data = $this->GetPlugins() ;
 		$include_path = $GLOBALS['sys_plugins_path'] ;
 		$filename = $include_path . '/'. $p_name . "/common/".$p_name."-init.php" ;
@@ -227,7 +248,7 @@
 		} else {
 			return 0 ;
 		}
-		
+
 	}
 }
 

Modified: trunk/gforge/common/include/UserManager.class.php
===================================================================
--- trunk/gforge/common/include/UserManager.class.php	2010-04-13 15:30:44 UTC (rev 9469)
+++ trunk/gforge/common/include/UserManager.class.php	2010-04-14 08:58:49 UTC (rev 9470)
@@ -54,6 +54,9 @@
     	return user_get_object($user_id);
     }
    
+    function getUserByEmail($user_id) {
+	    return user_get_object_by_email($user_id);
+    }
 }
 
 ?>

Added: trunk/gforge/common/mail/Mail.class.php
===================================================================
--- trunk/gforge/common/mail/Mail.class.php	                        (rev 0)
+++ trunk/gforge/common/mail/Mail.class.php	2010-04-14 08:58:49 UTC (rev 9470)
@@ -0,0 +1,261 @@
+<?php
+/*
+ * 
+ */
+
+class Mail {
+    
+    function Mail() {
+        $this->setHeaderCharset('UTF-8');
+        $this->setBodyCharset('UTF-8');
+        $this->setMimeType('text/plain');
+        $this->setTo('', true);
+        $this->setBcc('', true);
+        $this->setCc('', true);
+        $this->setBody('', true);
+        $this->clearAdditionalHeaders();
+    }
+    
+    var $_headerCharset;
+    function setHeaderCharset($charset) { 
+        $this->_headerCharset = $charset; 
+    }
+    function getHeaderCharset() { 
+        return $this->_headerCharset; 
+    }
+    
+    var $_bodyCharset;
+    function setBodyCharset($charset) { 
+        $this->_bodyCharset = $charset; 
+    }
+    function getBodyCharset() { 
+        return $this->_bodyCharset; 
+    }
+    
+    var $_subject;
+    function setSubject($subject) {
+        $this->_subject = $subject;
+    }
+    function getSubject() {
+        return $this->_subject;
+    }
+    function getEncodedSubject() {
+        return $this->_encodeHeader($this->_subject, $this->getHeaderCharset());
+    }
+    
+    /**
+     * Function to encode a header if necessary
+     * according to RFC2047
+     * Filename.......: class.html.mime.mail.inc
+     * Project........: HTML Mime mail class
+     * Last Modified..: Date: 2002/07/24 13:14:10 
+     * CVS Revision...: Revision: 1.4 
+     * Copyright......: 2001, 2002 Richard Heyes
+     */
+    function _encodeHeader($input, $charset) {
+		preg_match_all('/(\s?\w*[\x80-\xFF]+\w*\s?)/', $input, $matches);
+		foreach ($matches[1] as $value) {
+			$replacement = preg_replace('/([\x80-\xFF])/e', '"=" . strtoupper(dechex(ord("\1")))', $value);
+			$input = str_replace($value, '=?' . $charset . '?Q?' . $replacement . '?=', $input);
+		}
+		
+		return $input;
+	}
+    
+    /**
+     * Given a header, this function will decode it
+     * according to RFC2047. Probably not *exactly*
+     * conformant, but it does pass all the given
+     * examples (in RFC2047).
+     *
+     * @param string Input header value to decode
+     * @return string Decoded header value
+     * @access private
+     */
+    function _decodeHeader($input)
+    {
+        // Remove white space between encoded-words
+        $input = preg_replace('/(=\?[^?]+\?(q|b)\?[^?]*\?=)(\s)+=\?/i', '\1=?', $input);
+
+        // For each encoded-word...
+        while (preg_match('/(=\?([^?]+)\?(q|b)\?([^?]*)\?=)/i', $input, $matches)) {
+
+            $encoded  = $matches[1];
+            $charset  = $matches[2];
+            $encoding = $matches[3];
+            $text     = $matches[4];
+
+            switch (strtolower($encoding)) {
+                case 'b':
+                    $text = base64_decode($text);
+                    break;
+
+                case 'q':
+                    $text = str_replace('_', ' ', $text);
+                    preg_match_all('/=([a-f0-9]{2})/i', $text, $matches);
+                    foreach($matches[1] as $value)
+                        $text = str_replace('='.$value, chr(hexdec($value)), $text);
+                    break;
+            }
+
+            $input = str_replace($encoded, $text, $input);
+        }
+
+        return $input;
+    }    
+    
+    var $_body;
+    function setBody($body) {
+        $this->_body = $body;
+    }
+    function getBody() {
+        return $this->_body;
+    }
+    
+    var $_from;
+    function setFrom($from) {
+        $this->_from = $this->_validateRecipient($from);
+    }
+    function getFrom() {
+        return $this->_from;
+    }
+
+    /**
+     * Check if given mail is a valid (Ie. Active or Restricted) user.
+     *
+     * The given mail can by both user_name or email. Return form is always the
+     * user email.
+     *
+     * @param $list (IN) list of email addresses separated by , or ;
+     * @return list of email separated by ,
+     */
+    function _validateRecipient($list) {
+        $recipArray = split('[;,]', $list);
+        $retArray = array();
+	foreach($recipArray as $email) {
+		$email = trim($email);
+		if(!empty($email)) {
+			$user = UserManager::instance()->getUserByEmail($email);
+			if ($user) {
+				$allowed_status = array('A', 'R', 'P', 'V', 'W');
+				$one_with_status_allowed_found = false;
+				while ( !$one_with_status_allowed_found) {
+					if (in_array($user->getStatus(), $allowed_status)) {
+						$retArray[] = '"'.$this->_encodeHeader($user->getRealName(), $this->getHeaderCharset()).'" <'.$user->getEmail().'>';
+						$one_with_status_allowed_found = true;
+					}
+				}
+			} else {
+				$retArray[] = $email;
+			}
+		}
+	}
+	return implode(', ', $retArray);
+    }
+
+    var $_to;
+    function setTo($to, $raw=false) {
+	    if($raw)
+		    $this->_to = $to;
+	    else
+		    $this->_to = $this->_validateRecipient($to);
+    }
+    function getTo()  {
+	    return $this->_to;
+    }
+
+    var $_bcc;
+    function setBcc($bcc, $raw=false) {
+	    if($raw)
+		    $this->_bcc = $bcc;
+	    else
+		    $this->_bcc = $this->_validateRecipient($bcc);
+    }
+    function getBcc()  {
+	    return $this->_bcc;
+    }
+
+    var $_cc;
+    function setCc($cc, $raw=false) {
+	    if($raw)
+		    $this->_cc = $cc;
+	    else
+		    $this->_cc = $this->_validateRecipient($cc);
+
+    }
+    function getCc()  {
+	    return $this->_cc;
+    }
+
+    var $_mimeType;
+    function setMimeType($mimeType) {
+	    $this->_mimeType = $mimeType;
+    }
+    function getMimeType() {
+	    return $this->_mimeType;
+    }
+
+    var $_additionalHeaders;
+    function clearAdditionalHeaders() {
+	    $this->_additionalHeaders = array();
+    }
+    function addAdditionalHeader($name, $value) {
+	    $this->_additionalHeaders[$name] = $value;
+    }
+    function removeAdditionalHeader($name) {
+	    if (isset($this->_additionalHeaders[$name])) {
+		    unset($this->_additionalHeaders[$name]);
+	    }
+    }
+
+    /**
+     * @returns TRUE if the mail was successfully accepted for delivery, FALSE otherwise.
+     *          It is important to note that just because the mail was accepted for delivery, 
+     *          it does NOT mean the mail will actually reach the intended destination. 
+     **/
+    function send() {
+	$sys_lf="\n";
+	    if($this->getTo() === ''
+			    && $this->getCc() === '' 
+			    && $this->getBcc() === '') {
+		    return false;
+	    }
+
+	    $header = "From: ".$this->getFrom().$sys_lf;
+	    $header .= "Content-type: ".$this->getMimeType()."; charset=".$this->getBodyCharset().$sys_lf;
+	    $cc = $this->getCc();
+	    if (strlen($cc) > 0) {
+		    $header .= "Cc: ".$cc.$sys_lf;
+	    }
+	    $bcc = $this->getBcc();
+	    if (strlen($bcc) > 0) {
+		    $header .= "Bcc: ".$bcc.$sys_lf;
+	    }
+	    foreach($this->_additionalHeaders as $name => $value) {
+		    $header .= $name.": ".$value.$sys_lf;
+	    }
+	    return $this->_sendmail($header);
+    }
+
+    /**
+     * Perform effective email send.
+     * @access protected
+     */
+    function _sendmail($header) {
+	    $params = array('mail' => $this,
+			    'header' => $header);
+	    //$em =& EventManager::instance();
+	    //$em->processEvent('mail_sendmail', $params);
+	    
+	    return mail($this->getTo(),
+			    $this->getEncodedSubject(),
+			    $this->getBody(),
+			    $header
+		       );
+    }
+
+
+
+}
+
+?>

Added: trunk/gforge/common/valid/Rule.class.php
===================================================================
--- trunk/gforge/common/valid/Rule.class.php	                        (rev 0)
+++ trunk/gforge/common/valid/Rule.class.php	2010-04-14 08:58:49 UTC (rev 9470)
@@ -0,0 +1,382 @@
+<?php
+/**
+ * Copyright (c) STMicroelectronics, 2007. All Rights Reserved.
+ *
+ * Originally written by Manuel VACELET, 2007.
+ *
+ * This file is a part of Codendi.
+ *
+ * Codendi 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 of the License, or
+ * (at your option) any later version.
+ *
+ * Codendi 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Codendi. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * @package Codendi
+ */
+class Rule {
+    /**
+     * @access private
+     */
+    var $error;
+
+    /**
+     * Check if $val is a valid not.
+     *
+     * @param String $val Value to check.
+     * @return Boolean
+     */
+    function isValid($val) {
+        trigger_error(get_class($this).'::isValid() => Not yet implemented', E_USER_ERROR);
+    }
+
+    /**
+     * Default error message if rule is not apply on value.
+     *
+     * @param String $val Value to check.
+     * @return Boolean
+     */
+    function getErrorMessage($key) {
+        return $this->error;
+    }
+}
+
+/**
+ * Validate date provided by Codendi calendar.
+ *
+ * Note: this date format is more restrictive than php check date because in
+ * this case, 2007-01-01 format (with zero in month or day) is not allowed.
+ */
+class Rule_Date
+extends Rule {
+    function isValid($val) {
+        if(preg_match('/^(\d{1,4})-(\d{1,2})-(\d{1,2}?)$/', $val, $m)) {
+            return checkdate($m[2], $m[3], $m[1]);
+        } else {
+            return false;
+        }
+    }
+}
+
+/**
+ * Abstract class that define left-hand operand for a comparison.
+ */
+class Rule_Comparator
+extends Rule {
+    /**
+     * @access private
+     */
+    var $ref;
+    function Rule_Comparator($ref) {
+        $this->ref = $ref;
+    }
+}
+
+/**
+ * Check that given value is strictly greater than the one defined in
+ * constructor.
+ */
+class Rule_GreaterThan
+extends Rule_Comparator {
+    function isValid($val) {
+        if(is_numeric($val) && $val > $this->ref) {
+            return true;
+        }
+        return false;
+    }
+}
+
+/**
+ * Check that given value is strictly less than the one defined in constructor.
+ */
+class Rule_LessThan
+extends Rule_Comparator {
+    function isValid($val) {
+        if(is_numeric($val) && $val < $this->ref) {
+            return true;
+        }
+        return false;
+    }
+}
+
+/**
+ * Check that given value is greater or equal to the one defined in
+ * constructor.
+ */
+class Rule_GreaterOrEqual
+extends Rule_Comparator {
+    function isValid($val) {
+        if(is_numeric($val) && $val >= $this->ref) {
+            return true;
+        }
+        return false;
+    }
+}
+
+/**
+ * Check that given value is strictly less or equal to the one defined in
+ * constructor.
+ */
+class Rule_lessOrEqual
+extends Rule_Comparator {
+    function isValid($val) {
+        if(is_numeric($val) && $val <= $this->ref) {
+            return true;
+        }
+        return false;
+    }
+}
+
+/**
+ * Check that given value belong to the array defined in constructor.
+ *
+ * There is no type check.
+ */
+class Rule_WhiteList
+extends Rule_Comparator {
+    function isValid($val) {
+        if(is_array($this->ref)
+           && count($this->ref) > 0
+           && in_array($val, $this->ref)) {
+            return true;
+        }
+        return false;
+    }
+}
+
+/**
+ * Check that given value is a valid signed 32 bits decimal integer.
+ */
+class Rule_Int
+extends Rule {
+    /**
+     * Check the format according to PHP definition of a decimal integer.
+     * @see http://php.net/int
+     * @access private
+     */
+    function checkFormat($val) {
+        if(preg_match('/^([+-]?[1-9][0-9]*|[+-]?0)$/', $val)) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    function isValid($val) {
+        // Need to check with the regexp because of octal form '0123' that is
+        // equal to '123' with string '==' comparison.
+        if($this->checkFormat($val)) {
+            // Check (-2^31;2^31-1) range
+            if(strval(intval($val)) == $val) {
+                return true;
+            } else {
+                return false;
+            }
+        } else {
+            return false;
+        }
+    }
+}
+
+/**
+ * Check that given value is a string.
+ */
+class Rule_String
+extends Rule {
+    function isValid($val) {
+        return is_string($val);
+    }
+}
+
+/**
+ * Check if given string contains neither a carrige return nor a null char.
+ */
+class Rule_NoCr
+extends Rule {
+    function isValid($val) {
+        if(is_string($val) && strpos($val, 0x0A) === false && strpos($val, 0x0D) === false
+           && strpos($val, 0x00) === false) {
+            return true;
+        }
+        return false;
+    }
+}
+
+/**
+ * Check if an email address is valid or not in Codendi context.
+ *
+ * This rule is influenced by a global variable 'sys_disable_subdomain'. If
+ * this variable is set (no subdomain for codendi) and only in this case, emails
+ * like 'user at codendi' are allowed.
+ *
+ * The faulty email address is available with $this->getErrorMessage();
+ */
+class Rule_Email
+extends Rule {
+    var $separator;
+
+    function Rule_Email($separator = null) {
+        $this->separator = $separator;
+    }
+
+    function isValid($val) {
+        if($this->separator !== null) {
+            // If separator is defined, split the string and check each email.
+            $emails = split($this->separator, $val);
+            $valid = true;
+            while((list($key,$email) = each($emails)) && $valid) {
+                $valid = $valid & $this->validEmail(trim(rtrim($email)));
+            }
+        } else {
+            // $val must contains only one email address
+            $valid = $this->validEmail($val);
+        }
+        return $valid;
+    }
+
+    /**
+     * Check email validity
+     *
+     * Important note: this is very important to keep the 'D' regexp modifier
+     * as this is the only way not to be bothered by injections of \n into the
+     * email address.
+     *
+     * Spaces are allowed at the beginning and the end of the address.
+     */
+    function validEmail($email) {
+        $valid_chars='-!#$%&\'*+0-9=?A-Z^_`a-z{|}~\.';
+        if (array_key_exists('sys_disable_subdomains', $GLOBALS)
+            && $GLOBALS['sys_disable_subdomains']) {
+            $valid_domain='['.$valid_chars.']+';
+        } else {
+            $valid_domain='['.$valid_chars.']+\.['.$valid_chars.']+';
+        }
+        $regexp = '/^['.$valid_chars.']+'.'@'.$valid_domain.'$/D';
+        return preg_match($regexp, $email);
+    }
+}
+
+/**
+ * Check if value match Codendi user names format.
+ *
+ * This rule doesn't check that user actually exists.
+ */
+class Rule_UserNameFormat
+extends Rule {
+
+    function containsIllegalChars($val) {
+        return (strspn($val,"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_") != strlen($val));
+    }
+
+    function isNotLegalName($val) {
+        return preg_match('/^((root)|(bin)|(daemon)|(adm)|(lp)|(sync)|(shutdown)|(halt)|(mail)|(news)'
+                          .'|(uucp)|(operator)|(games)|(mysql)|(httpd)|(nobody)|(dummy)'
+                          .'|(www)|(cvs)|(shell)|(ftp)|(irc)|(debian)|(ns)|(download))$/i', $val);
+    }
+
+    function isCvsAccount($val) {
+        return preg_match('/^anoncvs_/i', $val);
+    }
+
+    function lessThanMin($val) {
+        return (strlen($val) < 3);
+    }
+
+    function greaterThanMax($val) {
+        return (strlen($val) > 30);
+    }
+
+    function isValid($val) {
+        return !$this->isNotLegalName($val)
+            && !$this->isCvsAccount($val)
+            && !$this->lessThanMin($val)
+            && !$this->greaterThanMax($val)
+            && !$this->containsIllegalChars($val);
+    }
+}
+
+/**
+ * Check that file was correctly uploaded doesn't by pass Codendi limits.
+ *
+ * Tests mainly rely on PHP $_FILES error code but add a double check of file
+ * size because MAX_FILE_SIZE (used by PHP to check allowed size) is submitted
+ * by the client.
+ *
+ * By default the maxSize is defined by 'sys_max_size_upload' Codendi
+ * variable but may be customized with setMaxSize.
+ */
+//require_once("www/file/file_utils.php"); // Needed for 2 GB workaround
+class Rule_File
+extends Rule {
+    var $maxSize;
+    var $i18nPageName;
+
+    function Rule_File() {
+        $this->maxSize = $GLOBALS['sys_max_size_upload'];
+        $this->i18nPageName = 'rule_valid';
+    }
+
+    function setMaxSize($max) {
+        $this->maxSize = $max;
+    }
+
+    function geti18nError($key, $params="") {
+        return $GLOBALS['Language']->getText($this->i18nPageName, $key, $params);
+    }
+
+    /**
+     * Check file upload validity
+     *
+     * @param  Array   One entry in $_FILES superarray (e.g. $_FILES['test'])
+     * @return Boolean Is file upload valid or not.
+     */
+    function isValid($file) {
+        $ok = false;
+        if(is_array($file)) {
+            switch($file['error']) {
+            case UPLOAD_ERR_OK:
+                // all is OK
+                $ok = true;
+                break;
+            case UPLOAD_ERR_INI_SIZE:
+            case UPLOAD_ERR_FORM_SIZE:
+                $this->error = $this->geti18nError('error_upload_size', $file['error']);
+                break;
+            case UPLOAD_ERR_PARTIAL:
+                $this->error = $this->geti18nError('error_upload_partial', $file['error']);
+                break;
+            case UPLOAD_ERR_NO_FILE:
+                $this->error = $this->geti18nError('error_upload_nofile', $file['error']);
+                break;
+                //case UPLOAD_ERR_NO_TMP_DIR: PHP 5.0.3
+                //case UPLOAD_ERR_CANT_WRITE: PHP 5.1.0
+                //case UPLOAD_ERR_EXTENSION: PHP 5.2.0
+            default:
+                $this->error = $this->geti18nError('error_upload_unknown', $file['error']);
+            }
+            if($ok && $file['name'] == '') {
+                $ok = false;
+                $this->error = $this->geti18nError('error_upload');
+            }
+            if($ok) {
+                // Re-check filesize (do not trust uploaded MAX_FILE_SIZE)
+                if(file_utils_get_size($file['tmp_name']) > $this->maxSize) {
+                   $ok = false;
+                   $this->error = $this->geti18nError('error_upload_size', 1);
+                }
+            }
+        }
+        return $ok;
+    }
+}
+
+?>

Added: trunk/gforge/common/valid/Valid.class.php
===================================================================
--- trunk/gforge/common/valid/Valid.class.php	                        (rev 0)
+++ trunk/gforge/common/valid/Valid.class.php	2010-04-14 08:58:49 UTC (rev 9470)
@@ -0,0 +1,229 @@
+<?php
+/**
+ * Copyright (c) STMicroelectronics, 2007. All Rights Reserved.
+ *
+ * Originally written by Manuel VACELET, 2007.
+ *
+ * This file is a part of Codendi.
+ *
+ * Codendi 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 of the License, or
+ * (at your option) any later version.
+ *
+ * Codendi 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Codendi. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+require_once('common/valid/Rule.class.php');
+
+/**
+ * @package Codendi
+ */
+class Valid {
+    /**
+     * @access private
+     */
+    var $errors;
+
+    /**
+     * @access private
+     */
+    var $key;
+
+    /**
+     * @access private
+     */
+    var $rules;
+
+    /**
+     * @access private
+     */
+    var $isRequired;
+
+    /**
+     * @access private
+     */
+    var $useFeedback;
+
+    /**
+     * @access private
+     */
+    var $globalErrorMessage;
+
+    /**
+     * @access private
+     */
+    var $isValid;
+
+    /**
+     * Constructor
+     */
+    function Valid($key = null) {
+        $this->key = $key;
+        $this->errors = array();
+        $this->rules = array();
+        $this->isRequired = false;
+        $this->useFeedback = true;
+        $this->globalErrorMessage = null;
+        $this->isValid;
+    }
+
+    /**
+     * Return the variable name on which rules must applies.
+     *
+     * @access private
+     */
+    function getKey() {
+        return $this->key;
+    }
+
+    /**
+     * Add a new rule in this validation.
+     *
+     * ou can add a custom error message that will bypass the default one that
+     * comes with the rule.
+     * @param Rule   Reference on rule.
+     * @param String Error message.
+     */
+    function addRule(&$rule, $message=false) {
+        $this->rules[] =& $rule;
+        $this->errors[] = $message;
+    }
+
+    /**
+     * The value is required.
+     *
+     * All rules must succeed (as usual). Empty / null values are forbidden
+     * (raise an error). And all failure generate an error (instead of a
+     * warning).
+     */
+    function required() {
+        $this->isRequired = true;
+    }
+
+    /**
+     * Turn feedback off.
+     */
+    function disableFeedback() {
+        $this->useFeedback = false;
+    }
+
+    /**
+     * Set a global error message that will replace all other messages.
+     *
+     * Note: If no error, no message raised. The message is raised with either
+     * 'warning' or 'error' level according to required();
+     * @param String Error message
+     */
+    function setErrorMessage($msg) {
+        $this->globalErrorMessage = $msg;
+    }
+
+    /**
+     * Return true if given value is empty
+     *
+     * @access private
+     * @param mixed Value to test
+     * @return boolean
+     */
+    function isValueEmpty($value) {
+        return ($value === '' || $value === false || $value === null);
+    }
+
+    /**
+     * Append feebback in the global Response object.
+     * @access private
+     */
+    function addFeedback($level, $error) {
+        $GLOBALS['Response']->addFeedback($level, $error);
+    }
+
+    /**
+     * Generate error message according to settings.
+     *
+     * Takes in account user requirement 'required' and
+     * 'disableFeedback'. Empty error messages are disarded.
+     * @access private
+     */
+    function populateFeedback() {
+        if($this->useFeedback) {
+            $level = 'warning';
+            if($this->isRequired) {
+                $level = 'error';
+            }
+            if($this->globalErrorMessage !== null &&
+               !$this->isValid) {
+                $this->addFeedback($level, $this->globalErrorMessage);
+            } else {
+                foreach($this->errors as $error) {
+                    if($error != '') {
+                        $this->addFeedback($level, $error);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Prepare error message on Rule:isValid result.
+     *
+     * If the test succeeded, the error message is cleared (either custom or
+     * built-in messages).
+     * @access private
+     * @param Integer Index of the Rule that was applied.
+     * @param Boolean Result of the test.
+     */
+    function errorMessage($i, $result) {
+        if($result === true) {
+            $this->errors[$i] = '';
+        } else {
+            if($this->errors[$i] === false) {
+                $this->errors[$i] = $this->rules[$i]->getErrorMessage($this->key);
+            }
+        }
+    }
+
+    /**
+     * Apply each rule on the given value and prepare feedback.
+     *
+     * @access private
+     * @param mixed Value to test.
+     */
+    function checkEachRules($value) {
+        $isValid = true;
+        $rCtr = count($this->rules);
+        for($i = 0; $i < $rCtr; $i++) {
+            $valid = $this->rules[$i]->isValid($value);
+            $this->errorMessage($i, $valid);
+            $isValid = $isValid && $valid;
+        }
+        if($isValid && $this->isRequired && $this->isValueEmpty($value)) {
+            $this->isValid = false;
+        } else {
+            $this->isValid = $isValid;
+        }
+        $this->populateFeedback();
+    }
+
+    /**
+     * Run validation on given value.
+     *
+     * @param mixed Value to test.
+     */
+    function validate($value) {
+        if($this->isRequired
+           || (!$this->isRequired && !$this->isValueEmpty($value))) {
+            $this->checkEachRules($value);
+            return $this->isValid;
+        }
+        return true;
+    }
+}
+
+?>

Added: trunk/gforge/common/valid/ValidFactory.class.php
===================================================================
--- trunk/gforge/common/valid/ValidFactory.class.php	                        (rev 0)
+++ trunk/gforge/common/valid/ValidFactory.class.php	2010-04-14 08:58:49 UTC (rev 9470)
@@ -0,0 +1,199 @@
+<?php
+/**
+ * Copyright (c) STMicroelectronics, 2007. All Rights Reserved.
+ *
+ * Originally written by Manuel VACELET, 2007.
+ *
+ * This file is a part of Codendi.
+ *
+ * Codendi 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 of the License, or
+ * (at your option) any later version.
+ *
+ * Codendi 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Codendi. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+require_once('common/valid/Valid.class.php');
+
+/**
+ * Check that value is a decimal integer greater or equal to zero.
+ * @package Codendi
+ */
+class Valid_UInt
+extends Valid {
+    function validate($value) {
+        $this->addRule(new Rule_Int());
+        $this->addRule(new Rule_GreaterOrEqual(0));
+        return parent::validate($value);
+    }
+
+}
+
+/**
+ * Check that group_id variable is valid
+ */
+class Valid_GroupId
+extends Valid {
+    function Valid_GroupId() {
+        parent::Valid('group_id');
+        //$this->setErrorMessage($GLOBALS['Language']->getText('include_exit','no_gid_err'));
+    }
+
+    function validate($value) {
+        $this->addRule(new Rule_Int());
+        $this->addRule(new Rule_GreaterThan(0));
+        return parent::validate($value);
+    }
+}
+
+/**
+ * Check that 'pv' parameter is set to an acceptable value.
+ */
+class Valid_Pv
+extends Valid {
+    function Valid_Pv() {
+        parent::Valid('pv');
+    }
+
+    function validate($value) {
+        $this->addRule(new Rule_WhiteList(array(0,1,2)));
+        return parent::validate($value);
+    }
+}
+
+/**
+ * Check that value is a string (should always be true).
+ */
+class Valid_Text
+extends Valid {
+    function validate($value) {
+        $this->addRule(new Rule_String());
+        return parent::validate($value);
+    }
+}
+
+/**
+ * Check that value is a string with neither carrige return nor null char.
+ */
+class Valid_String
+extends Valid_Text {
+    function validate($value) {
+        $this->addRule(new Rule_NoCr());
+        return parent::validate($value);
+    }
+}
+
+/**
+ * Wrapprt for 'WhiteList' rule
+ */
+class Valid_WhiteList
+extends Valid {
+    function Valid_WhiteList($key, $whitelist) {
+        parent::Valid($key);
+        $this->addRule(new Rule_WhiteList($whitelist));
+    }
+}
+
+/**
+ * Check that value match Codendi user short name format.
+ *
+ * This rule doesn't check that user actually exists.
+ */
+class Valid_UserNameFormat
+extends Valid_String {
+    function validate($value) {
+        $this->addRule(new Rule_UserNameFormat());
+        return parent::validate($value);
+    }
+}
+
+
+/**
+ * Check that submitted value is a simple string and a valid Codendi email.
+ */
+class Valid_Email
+extends Valid_String {
+    var $separator;
+
+    function Valid_Email($key=null, $separator=null) {
+        if(is_string($separator)) {
+            $this->separator = $separator;
+        } else {
+            $this->separator = null;
+        }
+        parent::Valid_String($key);
+    }
+
+    function validate($value) {
+        $this->addRule(new Rule_Email($this->separator));
+        return parent::validate($value);
+    }
+}
+
+/**
+ * Check uploaded file validity.
+ */
+class Valid_File
+extends Valid {
+
+    /**
+     * Is uploaded file empty or not.
+     *
+     * @param Array One entry of $_FILES
+     */
+    function isEmptyValue($file) {
+        if(!is_array($file)) {
+            return false;
+        } elseif(parent::isEmptyValue($file['name'])) {
+            return false;
+        } else {
+            return true;
+        }
+    }
+
+    /**
+     * Check rules on given file.
+     *
+     * @param  Array  $_FILES superarray.
+     * @param  String Index of file to check in $_FILES array.
+     * @return Boolean
+     */
+    function validate($files, $index) {
+        if(is_array($files) && isset($files[$index])) {
+            $this->addRule(new Rule_File());
+            return parent::validate($files[$index]);
+        } elseif($this->isRequired) {
+            return false;
+        } else {
+            return true;
+        }
+    }
+}
+
+
+class ValidFactory {
+    /**
+     * If $validator is an instance of a Validator, do nothing and returns it
+     * If $validator is a string and a validator exists (Valid_String for 'string', Valid_UInt for 'uint', ...) then creates an instance and returns it
+     * Else returns null
+     */
+    /* public static */ function getInstance($validator, $key = null) {
+        if (is_a($validator, 'Valid')) {
+            return $validator;
+        } else if(is_string($validator) && class_exists('Valid_'.$validator)) {
+            $validator_classname = 'Valid_'.$validator;
+            $v = new $validator_classname($key);
+            return $v;
+        } else {
+            return null;
+        }
+    }
+}
+?>

Modified: trunk/gforge/www/include/plugins_utils.php
===================================================================
--- trunk/gforge/www/include/plugins_utils.php	2010-04-13 15:30:44 UTC (rev 9469)
+++ trunk/gforge/www/include/plugins_utils.php	2010-04-14 08:58:49 UTC (rev 9470)
@@ -1,6 +1,6 @@
 <?php
 /**
- * Portions Copyright 2010 (c) Mélanie Le Bail
+ * Copyright 2010 (c) Mélanie Le Bail
  */
 
 
@@ -8,26 +8,34 @@
  
 $GLOBALS['mailman_bin_dir'] =  $GLOBALS['sys_path_to_mailman'].'/bin';
 $GLOBALS['mailman_list_dir'] = '/var/lib/mailman/lists';
+$GLOBALS['forumml_arch'] = '/var/lib/mailman/archives';
+$GLOBALS['forumml_tmp'] = '/var/run/forumml';
+$GLOBALS['forumml_dir'] = '/var/lib/gforge/forumml';
+$GLOBALS['sys_lf'] = "\n"; 
 global $html;
-require_once 'common/include/Plugin.class.php';
 
 function isLogged(){
-	
-	return session_loggedin();
+        
+        return session_loggedin();
 }
 
 function htmlRedirect($url) {
-	session_redirect('plugins/mailman/'.$url);
+        session_redirect($url);
 }
 function htmlIframe($url,$poub) {
-	echo ('<iframe src= "'.$url.'" width=100% height=500px></iframe>');
+        echo ('<iframe src= "'.$url.'" width=100% height=500px></iframe>');
 }
 
 
 function helpButton($help) {
-	
+        
 }
-function getIcon() {
-	echo html_image("ic/mail16b.png","20","20",array("border"=>"0"));
+function getIcon($url,$w=16,$h=16,$args=array()) {
+        echo html_image($url,$w,$h,$args);
 }
+function getImage($img) {
+        echo util_make_url($html->imgroot.$img);
+
+}
 ?>
+

Modified: trunk/gforge/www/include/pre.php
===================================================================
--- trunk/gforge/www/include/pre.php	2010-04-13 15:30:44 UTC (rev 9469)
+++ trunk/gforge/www/include/pre.php	2010-04-14 08:58:49 UTC (rev 9470)
@@ -59,9 +59,6 @@
 //library to determine browser settings
 require_once $gfwww.'include/browser.php';
 
-//Codendi class for httpRequest
-require_once $gfcommon.'include/HTTPRequest.class.php';
-
 //base error library for new objects
 require_once $gfcommon.'include/Error.class.php';
 
@@ -88,14 +85,10 @@
 
 //user functions like get_name, logged_in, etc
 require_once $gfcommon.'include/User.class.php';
-require_once $gfcommon.'include/UserManager.class.php';
 
 //group functions like get_name, etc
 require_once $gfcommon.'include/Group.class.php';
 
-//ProjectManager from Codendi
-require_once $gfcommon.'include/ProjectManager.class.php';
-
 //permission functions
 require_once $gfcommon.'include/Permission.class.php';
 

Added: trunk/gforge/www/include/preplugins.php
===================================================================
--- trunk/gforge/www/include/preplugins.php	                        (rev 0)
+++ trunk/gforge/www/include/preplugins.php	2010-04-14 08:58:49 UTC (rev 9470)
@@ -0,0 +1,13 @@
+<?php
+//Codendi class for httpRequest
+require_once 'common/include/HTTPRequest.class.php';
+//Codendi class for hmlPurifier
+require_once 'common/include/Codendi_HTMLPurifier.class.php';
+//Codendi class for Validator 
+require_once 'common/valid/ValidFactory.class.php';
+
+//Manager from Codendi
+require_once 'common/include/ProjectManager.class.php';
+require_once 'common/include/UserManager.class.php';
+?>
+

Modified: trunk/plugins/coclico/mailman/include/MailmanList.class.php
===================================================================
--- trunk/plugins/coclico/mailman/include/MailmanList.class.php	2010-04-13 15:30:44 UTC (rev 9469)
+++ trunk/plugins/coclico/mailman/include/MailmanList.class.php	2010-04-14 08:58:49 UTC (rev 9470)
@@ -331,9 +331,9 @@
 	 */
 	function getArchivesUrl() {
 		if ($this->isPublic()) {
-			$iframe_url = 'http://'.$GLOBALS['sys_default_domain'].'/pipermail/'.$this->getName().'/';
+			$iframe_url = 'http://'.$GLOBALS['sys_lists_host'].'/pipermail/'.$this->getName().'/';
 		} else {
-			$iframe_url = 'http://'.$GLOBALS['sys_default_domain'].'/mailman/private/'.$this->getName().'/';
+			$iframe_url = 'http://'.$GLOBALS['sys_lists_host'].'/mailman/private/'.$this->getName().'/';
 		}
 		htmlIframe($iframe_url, array('class' => 'iframe_service'));
 	}
@@ -344,7 +344,7 @@
 	 * @return string url of the info page
 	 */
 	function getExternalInfoUrl() {
-		return 'http://'.$GLOBALS['sys_default_domain'].'/mailman/listinfo/'.$this->getName();
+		return 'http://'.$GLOBALS['sys_lists_host'].'/mailman/listinfo/'.$this->getName();
 	}
 	/**
 	 * getOptionsUrl - get the url to manage options for user
@@ -354,7 +354,7 @@
 	function getOptionsUrl() {
 		$current_user=UserManager::instance()->getCurrentUser();
 		$user=$current_user->getEmail();
-		$iframe_url = 'http://'.$GLOBALS['sys_default_domain'].'/mailman/options/'.$this->getName().'/'.$user;
+		$iframe_url = 'http://'.$GLOBALS['sys_lists_host'].'/mailman/options/'.$this->getName().'/'.$user;
 		htmlIframe($iframe_url, array('class' => 'iframe_service'));
 	}
 	/**
@@ -363,9 +363,9 @@
 	 * @return string url of the info page
 	 */
 	function subscribe() {
-		if(isLogged() && $this->isPublic() && !$this->isMonitoring())
+		$current_user=UserManager::instance()->getCurrentUser();
+		if(isLogged() && $current_user->isMember($this->Group->getID()) && !$this->isMonitoring())
 		{
-			$current_user=UserManager::instance()->getCurrentUser();
 			$user=$current_user->getEmail();
 			$passwd= $current_user->getUserPw();
 			$name= $current_user->getRealName();
@@ -374,7 +374,7 @@
 				$this->setError(_('Error On Update:').db_error());
 				return false;
 			}
-			htmlRedirect('index.php?group_id='.$this->Group->getId());
+			htmlRedirect('/plugins/mailman/index.php?group_id='.$this->Group->getId());
 		}
 
 	}
@@ -391,7 +391,7 @@
 			$this->setError(_('Error On Update:').db_error());
 			return false;
 		}
-		htmlRedirect('index.php?group_id='.$this->Group->getId());
+		htmlRedirect('/plugins/mailman/index.php?group_id='.$this->Group->getId());
 	}
 	/**
 	 *	isMonitoring - See if the current user is in the list of people monitoring the forum.
@@ -422,7 +422,7 @@
 	 */
 
 	function getExternalAdminUrl() {
-		$iframe_url = 'http://'.$GLOBALS['sys_default_domain'].'/mailman/admin/'.$this->getName();
+		$iframe_url = 'http://'.$GLOBALS['sys_lists_host'].'/mailman/admin/'.$this->getName();
 		htmlIframe($iframe_url, array('class' => 'iframe_service'));
 	}
 

Modified: trunk/plugins/coclico/mailman/include/MailmanListDao.class.php
===================================================================
--- trunk/plugins/coclico/mailman/include/MailmanListDao.class.php	2010-04-13 15:30:44 UTC (rev 9469)
+++ trunk/plugins/coclico/mailman/include/MailmanListDao.class.php	2010-04-14 08:58:49 UTC (rev 9470)
@@ -70,7 +70,7 @@
 	function & searchByGroupId($group_id) {
 		$group_id = $this->da->quoteSmart($group_id);
 		$sql = "SELECT * FROM mail_group_list 
-			WHERE group_id = $1";
+			WHERE group_id = $1 ORDER BY group_list_id";
 		return $this->retrieve($sql,array($group_id));
 	}
 	/**

Modified: trunk/plugins/coclico/mailman/usr/lib/mailman/Mailman/ExternalConnector.py
===================================================================
--- trunk/plugins/coclico/mailman/usr/lib/mailman/Mailman/ExternalConnector.py	2010-04-13 15:30:44 UTC (rev 9469)
+++ trunk/plugins/coclico/mailman/usr/lib/mailman/Mailman/ExternalConnector.py	2010-04-14 08:58:49 UTC (rev 9470)
@@ -180,7 +180,7 @@
     
             return value
 	def db_cookie_to_mail(self,c):
-		if cookiname and c.has_key(self._cookiename):
+		if c.has_key(self._cookiename):
 			hash=c[self._cookiename]
 			query = self._queryCookieMail %hash
 			mm_cfg.cursor.execute(query)

Modified: trunk/plugins/coclico/mailman/www/admin/deletelist.php
===================================================================
--- trunk/plugins/coclico/mailman/www/admin/deletelist.php	2010-04-13 15:30:44 UTC (rev 9469)
+++ trunk/plugins/coclico/mailman/www/admin/deletelist.php	2010-04-14 08:58:49 UTC (rev 9470)
@@ -12,6 +12,7 @@
  */
 require_once ('env.inc.php');
 require_once 'pre.php';
+require_once 'preplugins.php';
 require_once('plugins_utils.php');
 require_once '../mailman_utils.php';
 

Modified: trunk/plugins/coclico/mailman/www/admin/index.php
===================================================================
--- trunk/plugins/coclico/mailman/www/admin/index.php	2010-04-13 15:30:44 UTC (rev 9469)
+++ trunk/plugins/coclico/mailman/www/admin/index.php	2010-04-14 08:58:49 UTC (rev 9470)
@@ -1,7 +1,7 @@
 <?php
 
 /**
- * FusionForge Mailing Lists Facility
+ * Fusionforge Mailing Lists Facility
  *
  * Portions Copyright 1999-2001 (c) VA Linux Systems
  * The rest Copyright 2003-2004 (c) Guillaume Smet - Open Wide
@@ -12,6 +12,7 @@
  */
 require_once 'env.inc.php';
 require_once 'pre.php';
+require_once 'preplugins.php';
 require_once 'plugins_utils.php';
 require_once '../mailman_utils.php';
 
@@ -44,7 +45,6 @@
 	//	RE-CREATE List with problems
 	//
 	if($action=='recreate') {
-		echo 'Je recree';
 		$mailingList = new MailmanList($group_id, $group_list_id);
 		if(!$mailingList || !is_object($mailingList)) {
 			exit_error(_('Error'), _('Error getting the list'));
@@ -54,7 +54,6 @@
 			echo 'error';
 		}
 		$mailingList->recreate();
-			echo 'OKOKOK';
 		$feedback .=_('List re-created');
 		htmlRedirect('index.php?group_id='.$group_id);
 
@@ -158,16 +157,12 @@
 		//	Form to modify list
 		//
 	} elseif($change_status && $group_list_id) {
-		echo "je suis la group= et group_id=".$group_list_id;
 		$mailingList = new MailmanList($group_id, $group_list_id);
-		echo "coucou";
 		if(!$mailingList || !is_object($mailingList)) {
-			echo "mailinglist error";
 			exit_error(_('Error'), _('Error getting the list'));
 		} elseif($mailingList->isError()) {
 			exit_error(_('Error'), $mailingList->getErrorMessage());
 		}
-		echo "avant header";
 		mailman_header(array(
 					'title' => _('Mail admin'),
 					'help'=>'CommunicationServices.html#MailingLists',
@@ -223,17 +218,18 @@
 		$mlCount = count($mlArray);
 
 		if($mlCount > 0) {
-			table_begin();
+			table_begin_admin();
 			for ($j = 0; $j < $mlCount; $j++) {
-				$currentList =& $mlArray[$j];
-				display_list_admin($currentList);
-			}
 
-			table_end();
-		}
-		mail_footer(array());
-	}
+                                $currentList =& $mlArray[$j];
+                                display_list_admin($currentList);
+                        }
+
+                        table_end();
+                }
+                mail_footer(array());
+        }
 } else {
-	exit_no_group();
+        exit_no_group();
 }
 ?>

Modified: trunk/plugins/coclico/mailman/www/index.php
===================================================================
--- trunk/plugins/coclico/mailman/www/index.php	2010-04-13 15:30:44 UTC (rev 9469)
+++ trunk/plugins/coclico/mailman/www/index.php	2010-04-14 08:58:49 UTC (rev 9470)
@@ -12,6 +12,7 @@
  */
 require_once ('env.inc.php');
 require_once 'pre.php';
+require_once 'preplugins.php';
 require_once 'plugins_utils.php';
 require_once 'mailman_utils.php';
 $request =& HTTPRequest::instance();

Modified: trunk/plugins/coclico/mailman/www/mailman_utils.php
===================================================================
--- trunk/plugins/coclico/mailman/www/mailman_utils.php	2010-04-13 15:30:44 UTC (rev 9469)
+++ trunk/plugins/coclico/mailman/www/mailman_utils.php	2010-04-14 08:58:49 UTC (rev 9470)
@@ -13,10 +13,9 @@
 
 require_once 'mailman/include/MailmanList.class.php';
 require_once 'mailman/include/MailmanListFactory.class.php';
-
+global $class;
 $current_user=UserManager::instance()->getCurrentUser();
 
-
 function sendCreationMail($userEmail,&$list) {
  $message = sprintf(_('A mailing list will be created on %1$s in few minutes 
 and you are the list administrator.
@@ -51,24 +50,63 @@
 function table_begin()
 {
 
-	echo "<table WIDTH=\"100%\" border=0>\n"."<TR><TD VALIGN=\"TOP\">\n"; 
+//	echo "<table WIDTH=\"100%\" border=0>\n"."<TR><TD VALIGN=\"TOP\">\n"; 
+  echo "<table class='border' width='100%' border='0'>
+            <tr class='boxtable'>
+                <th class='forumml' width='15%'>"._('Mailing List')."</th>
+                <th class='forumml' width='30%'>"._('Description')."</th>
+                <th class='forumml' width='15%'>"._('Archives')."</th>";
+  if (isLogged()) {
+	  echo "<th class='forumml' width='10%'>"._('Subscription')."</th>";
+	  echo "<th class='forumml' width='10%'>"._('Preferences')."</th>";
+	  echo "<th class='forumml' width='10%'>"._('Administrate')."</th>";
+  }
+
 }
-function table_end()
+function table_begin_admin()
 {
-	echo '</TD></TR></TABLE>';
 
+//	echo "<table WIDTH=\"100%\" border=0>\n"."<TR><TD VALIGN=\"TOP\">\n"; 
+  echo "<table class='border' width='100%' border='0'>
+            <tr class='boxtable'>
+                <th class='forumml' width='15%'>"._('Mailing List')."</th>
+                <th class='forumml' width='20%'>"._('Description')."</th>
+                <th class='forumml' width='15%'>"._('Update')."</th>";
+	  echo "<th class='forumml' width='10%'>"._('Delete')."</th>";
+	  echo "<th class='forumml' width='10%'>"._('Administrate')."</th>";
+
 }
+
+function table_end()
+{
+	//	echo '</TD></TR></TABLE>';
+	echo '</table>';
+}
 function display_list($currentList)
 {
+global $class;
+$plugin_manager =& PluginManager::instance();
+$p =& $plugin_manager->getPluginByName('mailman');
 	$request =& HTTPRequest::instance();
 	$current_user=UserManager::instance()->getCurrentUser();
-	
+
 	if($currentList->isPublic()!='9'){
 		if ($currentList->isError()) {
 			echo $currentList->getErrorMessage();
 		} else {
-			getIcon();
-			echo '&nbsp;<b>'.$currentList->getName().'</b> [';
+			if ($class=="boxitem bgcolor-white") {
+				$class="boxitemalt bgcolor-grey";
+			}
+			else {
+				$class = "boxitem bgcolor-white";
+			}
+			echo "<tr class='".$class."'>";
+			echo '<td>';
+			if ($currentList->isMonitoring()) {
+				echo '<img src ="'.$p->getThemePath().'/images/ic/tick.png"'.' title="You are monitoring this list">';
+			}
+			echo $currentList->getName().'</td> ';
+			echo '<td>';
 			if($currentList->getStatus() == '1') {
 				if($currentList->activationRequested()){
 					echo	_('Not activated yet');
@@ -76,24 +114,31 @@
 				else{
 					echo _('Error during creation');
 				}
-
+				echo '</td>';
 			} else {
-				echo ' <A HREF="index.php?group_id='.$request->get('group_id').'&action=pipermail&id='.$currentList->getID().'">'._('Archives').'</A>';
+				echo htmlspecialchars($currentList->getDescription()).'</td>';
+				$archives =' <A HREF="index.php?group_id='.$request->get('group_id').'&action=pipermail&id='.$currentList->getID().'">'._('Archives').'</A>';
+				plugin_hook('browse_archives', array('html' => &$archives, 'group_list_id' => $currentList->getID()));
+				echo '<td>'.$archives.'</td>';
 				if(isLogged())
 				{ 
+					echo '<td>';
 					if ($currentList->isMonitoring()) {
-						echo 	' | <a href="index.php?group_id='.$request->get('group_id').'&action=unsubscribe&id='.$currentList->getID().'">'._('Unsubscribe').' </a>';
-						echo 	' | <a href="index.php?group_id='.$request->get('group_id').'&action=options&id='.$currentList->getID().'">'._('Preferences').'</a>';
+						echo ' <a href="index.php?group_id='.$request->get('group_id').'&action=unsubscribe&id='.$currentList->getID().'"><img src="'.$p->getThemePath().'/images/ic/delete.png" title='._('Unsubscribe').'>';
+						echo ' </a></td>';
+						echo 	' <td> <a href="index.php?group_id='.$request->get('group_id').'&action=options&id='.$currentList->getID().'">'._('Preferences').'</a></td>';
 					} else {
-						echo 	' | <a href="index.php?group_id='.$request->get('group_id').'&action=subscribe&id='.$currentList->getID().'">'._('Subscribe').'</a>';
+						echo 	'  <a href="index.php?group_id='.$request->get('group_id').'&action=subscribe&id='.$currentList->getID().'"><img src="'.$p->getThemePath().'/images/ic/add.png" title='._('Subscribe').'>';
+						;
+						echo  '</a></td> <td></td>';
 					}
 					if ($currentList->getListAdminID() == $current_user->getID()){
-						echo ' | <A HREF="index.php?group_id='. $request->get('group_id').'&action=admin&id='. $currentList->getID() .'">'._('Administrate').'</A> ';
+						echo ' <td> <A HREF="index.php?group_id='. $request->get('group_id').'&action=admin&id='. $currentList->getID() .'">'._('Administrate').'</A> ';
 					}
+					else { echo '<td>';}
 				}
 			}
-			echo ' ] <br>&nbsp;';
-			echo htmlspecialchars($currentList->getDescription()).'<p>';
+			echo '</td></tr>';
 
 		}
 	}
@@ -101,6 +146,7 @@
 }
 function display_list_admin($currentList)
 {
+global $class;
 	$request =& HTTPRequest::instance();
 	$current_user=UserManager::instance()->getCurrentUser();
 	if($currentList->isPublic()!='9'){
@@ -108,28 +154,35 @@
 			echo $currentList->getErrorMessage();
 		} else
 		{
-			getIcon();
-			echo '&nbsp;<b>'.$currentList->getName().'</b> [';
+			if ($class=="boxitem bgcolor-white") {
+				$class="boxitemalt bgcolor-grey";
+			}
+			else {
+				$class = "boxitem bgcolor-white";
+			}
+
+			echo "<tr class='".$class."'>";
+			echo '<td>'.$currentList->getName().'</td> ';
 		}
 		if($currentList->getStatus() == '1') {
 			if($currentList->activationRequested()){
-				echo	_('Not activated yet');
+				echo	'<td>'._('Not activated yet').'</td>';
 			}
 			else{
-				echo _('Error during creation').' | <A HREF="index.php?group_id='.$request->get('group_id').'&action=recreate&group_list_id='.$currentList->getID().'">'._('Re-create').'</A>';
+				echo '<td>'._('Error during creation').'  <A HREF="index.php?group_id='.$request->get('group_id').'&action=recreate&group_list_id='.$currentList->getID().'">'._('Re-create').'</A></td>';
 			}
 		} else {
 
-			echo ' <A HREF="index.php?group_id='.$request->get('group_id').'&change_status=1&group_list_id='.$currentList->getID().'">'._('Update').'</A>';
-			echo '	| <a href="deletelist.php?group_id='.$currentList->Group->getID().'&id='.$currentList->getID().'">'. _('Delete').'</a>';
+			echo '<td>'.htmlspecialchars($currentList->getDescription()).'</td>';
+			echo '<td> <A HREF="index.php?group_id='.$request->get('group_id').'&change_status=1&group_list_id='.$currentList->getID().'">'._('Update').'</A></td>';
+			echo '<td> <a href="deletelist.php?group_id='.$currentList->Group->getID().'&id='.$currentList->getID().'">'. _('Delete').'</td>';
 
 			if ($currentList->getListAdminID() == $current_user->getID()){
-				echo ' | <A HREF="../index.php?group_id='. $request->get('group_id').'&action=admin&id='. $currentList->getID() .'">'._('Administrate from Mailman').'</A> ';
+				echo ' <td> <A HREF="../index.php?group_id='. $request->get('group_id').'&action=admin&id='. $currentList->getID() .'">'._('Administrate from Mailman').'</td> ';
 			}
 		}
 
-		echo ' ] <br>&nbsp;';
-		echo htmlspecialchars($currentList->getDescription()).'<p>';
+		echo ' </tr>';
 	}
 }
 

Added: trunk/plugins/coclico/mailman/www/themes/default/images/ic/add.png
===================================================================
--- trunk/plugins/coclico/mailman/www/themes/default/images/ic/add.png	                        (rev 0)
+++ trunk/plugins/coclico/mailman/www/themes/default/images/ic/add.png	2010-04-14 08:58:49 UTC (rev 9470)
@@ -0,0 +1,9 @@
+‰PNG
+
+   
+IHDR         óÿa   gAMA  ¯È7Šé   tEXtSoftware Adobe ImageReadyqÉe<  oIDAT8Ë¥“ëK“a‡ý[¶/ƒ¤†Y(¨)%X(oÙlŠŠNÛ–skŠÎön.ºÍ-µ¡Ûh¤;8ÃfâÔÒEêëP¢"jï¿ÞMGˈø}yພ羹ï$ Iÿ“ß.tÓȕ„lu‰¨æ	AXþ¢:Ü𼂒ZËHÑh1óDnZJ´OJBÏÖ{±Z„ÿóÖ?­`2`‡ÒS¾‰â=¹N$ü„Å‘é=;¾íaöƒ&jw°ï›°ôqÚJGò#ÜÁ<"N ’2h8èÞµ`ïë6†·õx¸Ön_+~úüZto¶À}`é¢Ðx%XЛ͈	hXÑ¿¬Æ»/›ô‹}èÝÒBóJ‰_G½&ƒ|QÅr-œû6ÜÉAÞƒELÐ⬡\ýU3:WUh[‘C6+Š	6.fÊ *ÆÀôK͸ܝFÅŠqþ¡÷½ýou4Ü„?ñdó|XüÃÈÒ¥ÆMvÞáD`Ú
+*_ý‰Ò[
+«éì#A½­œ2ú´0liÐôRñ|xÖq`4w=\ôûÔèòÞÃuòQ	â±Åm+GÀÙ|%$ÞÒ5ˆœÔ¹‹áØ5ãRO*Ø÷YGMš‹UOƒ¤G€qj4Ö°(XëŒ&
+s1±cÂË­(LVžfÄ
+Rù£¢dèj¤ÑQ	'-1úÚAÎTA>U	ãj4,´pÀV±"4L$eÎ@.ArBù™èY a~m€yà ·Y])Q8tN¸L×ô™ÌÜžt2»ó"•¡I	§µŸ
+Ÿo=CS±Èdå)æ_·ñ_óAFË (ÓÁ    IEND®B`‚
\ No newline at end of file

Added: trunk/plugins/coclico/mailman/www/themes/default/images/ic/delete.png
===================================================================
--- trunk/plugins/coclico/mailman/www/themes/default/images/ic/delete.png	                        (rev 0)
+++ trunk/plugins/coclico/mailman/www/themes/default/images/ic/delete.png	2010-04-14 08:58:49 UTC (rev 9470)
@@ -0,0 +1,13 @@
+‰PNG
+
+   
+IHDR         óÿa   gAMA  ¯È7Šé   tEXtSoftware Adobe ImageReadyqÉe<  ]IDAT8Ë¥“ûKSaÇý[¶¢‰n„„QP˜ó2wÖÚܦγL[,biŽašAÅ\øC¨¥vÕÊ_2Ml”ZFjסå±òÒNMjmž³kÊ·¹`&.#záûËËûù¼<Ï“ å²æbV¯ÎPæ÷T3¥%¹I­†{Gª™qRiv•È…ë
+ætzâ#E±ß6„ˆ¼EddüÝÌJñª`Ÿ«ÅDRÁ2<]Nñ·;°4õѾ;ˆ¶Ûm>‡7›°8܏ɀQe6ÿLžI¬Ìèt‚ìæ®·c‰q!zñ|vü¶j„/Xi ¶ž@øÞ
+Ì%1|hŸû±l !ˆÁô|­‹®±ø!
+ïY#‚uºUáN’w]Á˼H3è„àu„	t]E´³>k%¾I“f¡’o«ÇR…‡D:“0åÚ`ä~¢|§
+øÓñ(rà¥
+áon„3oG0!˜$‹‚¡ÎV„ë
+ž*[W0_ª‚¿©ýâ-+‚‰ãµÖ d§ÁWÇ&2¾ZfMFô‰ÒVJpËiF&B°³
+>­ÞRɘ•gƒ- Ð~	CâmèÍÚ´ÒÄ×ERÁ
+áž«Ð p«5Þ°y•ø¨È+‹Á21ø¶ŒK—aw·h£`Õ ä#Šüôa×Zñ½ž†‡Tâ³ZoüåL¨óÑ“•ÊÇ`"é(?•ï'žÜËŽJváKµÞ†óñ|ª:†G9[—aöw8é2
+JwÄéf'±“y¿ëmæzsÓ˜žìTswæá_·ñ_óÒιIrþ    IEND®B`‚
\ No newline at end of file

Added: trunk/plugins/coclico/mailman/www/themes/default/images/ic/tick.png
===================================================================
--- trunk/plugins/coclico/mailman/www/themes/default/images/ic/tick.png	                        (rev 0)
+++ trunk/plugins/coclico/mailman/www/themes/default/images/ic/tick.png	2010-04-14 08:58:49 UTC (rev 9470)
@@ -0,0 +1,7 @@
+‰PNG
+
+   
+IHDR         óÿa   gAMA  ¯È7Šé   tEXtSoftware Adobe ImageReadyqÉe<  «IDAT8˽“Ù.Ca…{ç8ïbnÕSBª†T'êè)E)ª§­V«CJÇ¥jŽÄ” —ZÕ†g/¡ºü•hÂ…ÿÝ¿ÖÞûÛk þòÿn ^kâ[–ꝿ2P­6ò¦c=úXHø*îGÊ`?xÔ…Ù{7¼7Vè¶Ô¨ðÙ¾%V¬Hyã¡Óq¦âNtn·¢Ò[Œ‡J2^²5†3¦ç³X¾,åS-OÆœÄo•ËÝâDñX•ÁxÁ–õž2Oܵ	ì®rè]L`ñ}ûZîÆ࿳ƒÝT¡ÌU˜(²çSiˆýçÚÚÞPû£/Ìa:6Í–,A`
+É%S†=¾¨Þ[
+”Ž‹b[õa='šLýaÌW˜{ðÀ¶Âx¤ƒéD‰°î[˜u9JœÂ—BëGqzfGN“Ê0…ôosú£6¸"f¸ÂfhÖZR°’".—ú2H-[ {·îÈ(7ÃhÊ@`%E–ê[I”ÌWÓu3•¤eÔ+Í °’ÂÑlêGQ&û¥Ë'Ä °žÌÙ¿º‹ÎÉÊø—k|¾¢©<R
+H    IEND®B`‚
\ No newline at end of file




More information about the Fusionforge-commits mailing list