[Fusionforge-commits] r9283 - in trunk/plugins: . coclico coclico/mailman coclico/mailman/bin coclico/mailman/common coclico/mailman/cronjobs coclico/mailman/db coclico/mailman/debian coclico/mailman/debian/po coclico/mailman/debian/source coclico/mailman/etc coclico/mailman/etc/plugins coclico/mailman/etc/plugins/mailman coclico/mailman/include coclico/mailman/include/events coclico/mailman/packaging coclico/mailman/packaging/control coclico/mailman/packaging/cron.d coclico/mailman/packaging/dirs coclico/mailman/packaging/docs coclico/mailman/packaging/install coclico/mailman/packaging/links coclico/mailman/translations coclico/mailman/usr coclico/mailman/usr/lib coclico/mailman/usr/lib/mailman coclico/mailman/usr/lib/mailman/Mailman coclico/mailman/utils coclico/mailman/var coclico/mailman/var/lib coclico/mailman/var/lib/mailman coclico/mailman/var/lib/mailman/lists coclico/mailman/www coclico/mailman/www/admin

Christian Bayle cbayle at libremir.placard.fr.eu.org
Mon Mar 29 17:47:51 CEST 2010


Author: cbayle
Date: 2010-03-29 17:47:50 +0200 (Mon, 29 Mar 2010)
New Revision: 9283

Added:
   trunk/plugins/coclico/
   trunk/plugins/coclico/mailman/
   trunk/plugins/coclico/mailman/README.txt
   trunk/plugins/coclico/mailman/bin/
   trunk/plugins/coclico/mailman/bin/db-delete.pl
   trunk/plugins/coclico/mailman/bin/db-upgrade.pl
   trunk/plugins/coclico/mailman/common/
   trunk/plugins/coclico/mailman/common/mailman-init.php
   trunk/plugins/coclico/mailman/cronjobs/
   trunk/plugins/coclico/mailman/cronjobs/manage_mailmanlists.php
   trunk/plugins/coclico/mailman/db/
   trunk/plugins/coclico/mailman/db/install.sql
   trunk/plugins/coclico/mailman/db/mailman-init.sql
   trunk/plugins/coclico/mailman/db/uninstall.sql
   trunk/plugins/coclico/mailman/debian/
   trunk/plugins/coclico/mailman/debian/README.Debian
   trunk/plugins/coclico/mailman/debian/README.source
   trunk/plugins/coclico/mailman/debian/changelog
   trunk/plugins/coclico/mailman/debian/compat
   trunk/plugins/coclico/mailman/debian/control
   trunk/plugins/coclico/mailman/debian/copyright
   trunk/plugins/coclico/mailman/debian/docs
   trunk/plugins/coclico/mailman/debian/dsf-po/
   trunk/plugins/coclico/mailman/debian/po/
   trunk/plugins/coclico/mailman/debian/po/templates.pot
   trunk/plugins/coclico/mailman/debian/rules
   trunk/plugins/coclico/mailman/debian/source/
   trunk/plugins/coclico/mailman/debian/source/format
   trunk/plugins/coclico/mailman/etc/
   trunk/plugins/coclico/mailman/etc/plugins/
   trunk/plugins/coclico/mailman/etc/plugins/mailman/
   trunk/plugins/coclico/mailman/etc/plugins/mailman/config.php
   trunk/plugins/coclico/mailman/include/
   trunk/plugins/coclico/mailman/include/BackendMailmanList.class.php
   trunk/plugins/coclico/mailman/include/MailmanList.class.php
   trunk/plugins/coclico/mailman/include/MailmanListDao.class.php
   trunk/plugins/coclico/mailman/include/MailmanListFactory.class.php
   trunk/plugins/coclico/mailman/include/MailmanPluginDescriptor.class.php
   trunk/plugins/coclico/mailman/include/MailmanPluginInfo.class.php
   trunk/plugins/coclico/mailman/include/MailsForUser.class.php
   trunk/plugins/coclico/mailman/include/events/
   trunk/plugins/coclico/mailman/include/events/SystemEvent_MAILMAN_LIST_CREATE.class.php
   trunk/plugins/coclico/mailman/include/events/SystemEvent_MAILMAN_LIST_DELETE.class.php
   trunk/plugins/coclico/mailman/include/mailman-init.php
   trunk/plugins/coclico/mailman/include/mailmanPlugin.class.php
   trunk/plugins/coclico/mailman/packaging/
   trunk/plugins/coclico/mailman/packaging/control/
   trunk/plugins/coclico/mailman/packaging/control/000source
   trunk/plugins/coclico/mailman/packaging/control/222plugin-mailman
   trunk/plugins/coclico/mailman/packaging/control/222plugin-mailman.shortdesc
   trunk/plugins/coclico/mailman/packaging/cron.d/
   trunk/plugins/coclico/mailman/packaging/cron.d/plugin-mailman
   trunk/plugins/coclico/mailman/packaging/dirs/
   trunk/plugins/coclico/mailman/packaging/dirs/plugin-mailman
   trunk/plugins/coclico/mailman/packaging/docs/
   trunk/plugins/coclico/mailman/packaging/docs/plugin-mailman
   trunk/plugins/coclico/mailman/packaging/install/
   trunk/plugins/coclico/mailman/packaging/install/plugin-mailman
   trunk/plugins/coclico/mailman/packaging/links/
   trunk/plugins/coclico/mailman/packaging/links/plugin-mailman
   trunk/plugins/coclico/mailman/tests/
   trunk/plugins/coclico/mailman/translations/
   trunk/plugins/coclico/mailman/translations/en.po
   trunk/plugins/coclico/mailman/translations/gforge.pot
   trunk/plugins/coclico/mailman/usr/
   trunk/plugins/coclico/mailman/usr/lib/
   trunk/plugins/coclico/mailman/usr/lib/mailman/
   trunk/plugins/coclico/mailman/usr/lib/mailman/Mailman/
   trunk/plugins/coclico/mailman/usr/lib/mailman/Mailman/ExternalConnector.py
   trunk/plugins/coclico/mailman/usr/lib/mailman/Mailman/ForgeSecurityManager.py
   trunk/plugins/coclico/mailman/usr/lib/mailman/Mailman/MySQLConnector.py
   trunk/plugins/coclico/mailman/usr/lib/mailman/Mailman/PsycopgConnector.py
   trunk/plugins/coclico/mailman/utils/
   trunk/plugins/coclico/mailman/utils/manage-translations.sh
   trunk/plugins/coclico/mailman/var/
   trunk/plugins/coclico/mailman/var/lib/
   trunk/plugins/coclico/mailman/var/lib/mailman/
   trunk/plugins/coclico/mailman/var/lib/mailman/lists/
   trunk/plugins/coclico/mailman/var/lib/mailman/lists/extend.py
   trunk/plugins/coclico/mailman/www/
   trunk/plugins/coclico/mailman/www/admin/
   trunk/plugins/coclico/mailman/www/admin/deletelist.php
   trunk/plugins/coclico/mailman/www/admin/index.php
   trunk/plugins/coclico/mailman/www/index.html
   trunk/plugins/coclico/mailman/www/index.php
   trunk/plugins/coclico/mailman/www/mailman_utils.php
Log:
Add mailman plugin


Added: trunk/plugins/coclico/mailman/README.txt
===================================================================
--- trunk/plugins/coclico/mailman/README.txt	                        (rev 0)
+++ trunk/plugins/coclico/mailman/README.txt	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,4 @@
+This is the readme of the plugin.
+You should put here any useful information about 
+the plugin : install, configuration, ...
+

Added: trunk/plugins/coclico/mailman/bin/db-delete.pl
===================================================================
--- trunk/plugins/coclico/mailman/bin/db-delete.pl	                        (rev 0)
+++ trunk/plugins/coclico/mailman/bin/db-delete.pl	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,187 @@
+#!/usr/bin/perl -w
+#
+# Debian-specific script to delete plugin-specific tables
+# Roland Mas <lolando at debian.org>
+
+use strict ;
+use diagnostics ;
+
+use DBI ;
+use MIME::Base64 ;
+use HTML::Entities ;
+
+use vars qw/$dbh @reqlist $query/ ;
+use vars qw/$sys_default_domain $sys_cvs_host $sys_download_host
+    $sys_shell_host $sys_users_host $sys_docs_host $sys_lists_host
+    $sys_dns1_host $sys_dns2_host $FTPINCOMING_DIR $FTPFILES_DIR
+    $sys_urlroot $sf_cache_dir $sys_name $sys_themeroot
+    $sys_news_group $sys_dbhost $sys_dbname $sys_dbuser $sys_dbpasswd
+    $sys_ldap_base_dn $sys_ldap_host $admin_login $admin_password
+    $server_admin $domain_name $newsadmin_groupid $statsadmin_groupid
+    $skill_list/ ;
+use vars qw/$pluginname/ ;
+
+sub is_lesser ( $$ ) ;
+sub is_greater ( $$ ) ;
+sub debug ( $ ) ;
+sub parse_sql_file ( $ ) ;
+
+require ("/usr/share/gforge/lib/include.pl") ; # Include a few predefined functions 
+require ("/usr/share/gforge/lib/sqlparser.pm") ; # Our magic SQL parser
+
+debug "You'll see some debugging info during this installation." ;
+debug "Do not worry unless told otherwise." ;
+
+&db_connect ;
+
+# debug "Connected to the database OK." ;
+
+$pluginname = "mailman" ;
+
+$dbh->{AutoCommit} = 0;
+$dbh->{RaiseError} = 1;
+eval {
+    my ($sth, @array, $version, $action, $path, $target, $rname) ;
+
+    my $pattern = "plugin_" . $pluginname . '_%' ;
+
+    $query = "SELECT relname FROM pg_class WHERE relname LIKE '$pattern' AND relkind='v'" ;
+    $sth = $dbh->prepare ($query) ;
+    $sth->execute () ;
+    while (@array = $sth->fetchrow_array ()) {
+	$rname = $array [0] ;
+	&drop_view_if_exists ($rname) ;
+    }
+    $sth->finish () ;
+
+    $query = "SELECT relname FROM pg_class WHERE relname LIKE '$pattern' AND relkind='r'" ;
+    $sth = $dbh->prepare ($query) ;
+    $sth->execute () ;
+    while (@array = $sth->fetchrow_array ()) {
+	$rname = $array [0] ;
+	&drop_table_if_exists ($rname) ;
+    }
+    $sth->finish () ;
+
+    $query = "SELECT relname FROM pg_class WHERE relname LIKE '$pattern' AND relkind='i'" ;
+    $sth = $dbh->prepare ($query) ;
+    $sth->execute () ;
+    while (@array = $sth->fetchrow_array ()) {
+	$rname = $array [0] ;
+	&drop_index_if_exists ($rname) ;
+    }
+    $sth->finish () ;
+
+    $query = "SELECT relname FROM pg_class WHERE relname LIKE '$pattern' AND relkind='s'" ;
+    $sth = $dbh->prepare ($query) ;
+    $sth->execute () ;
+    while (@array = $sth->fetchrow_array ()) {
+	$rname = $array [0] ;
+	&drop_sequence_if_exists ($rname) ;
+    }
+    $sth->finish () ;
+
+    $dbh->commit ();
+
+
+    debug "It seems your database deletion went well and smoothly.  That's cool." ;
+    debug "Please enjoy using Debian GForge." ;
+
+    # There should be a commit at the end of every block above.
+    # If there is not, then it might be symptomatic of a problem.
+    # For safety, we roll back.
+    $dbh->rollback ();
+};
+
+if ($@) {
+    warn "Transaction aborted because $@" ;
+    debug "Transaction aborted because $@" ;
+    debug "Last SQL query was:\n$query\n(end of query)" ;
+    $dbh->rollback ;
+    debug "Please report this bug on the Debian bug-tracking system." ;
+    debug "Please include the previous messages as well to help debugging." ;
+    debug "You should not worry too much about this," ;
+    debug "your DB is still in a consistent state and should be usable." ;
+    exit 1 ;
+}
+
+$dbh->rollback ;
+$dbh->disconnect ;
+
+sub debug ( $ ) {
+    my $v = shift ;
+    chomp $v ;
+    print STDERR "$v\n" ;
+}
+
+sub drop_table_if_exists ( $ ) {
+    my $tname = shift or die  "Not enough arguments" ;
+    $query = "SELECT count(*) FROM pg_class WHERE relname='$tname' AND relkind='r'" ;
+    my $sth = $dbh->prepare ($query) ;
+    $sth->execute () ;
+    my @array = $sth->fetchrow_array () ;
+    $sth->finish () ;
+
+    if ($array [0] != 0) {
+	# debug "Dropping table $tname" ;
+	$query = "DROP TABLE $tname" ;
+	# debug $query ;
+	$sth = $dbh->prepare ($query) ;
+	$sth->execute () ;
+	$sth->finish () ;
+    }
+}
+
+sub drop_sequence_if_exists ( $ ) {
+    my $sname = shift or die  "Not enough arguments" ;
+    $query = "SELECT count(*) FROM pg_class WHERE relname='$sname' AND relkind='S'" ;
+    my $sth = $dbh->prepare ($query) ;
+    $sth->execute () ;
+    my @array = $sth->fetchrow_array () ;
+    $sth->finish () ;
+
+    if ($array [0] != 0) {
+	# debug "Dropping sequence $sname" ;
+	$query = "DROP SEQUENCE $sname" ;
+	# debug $query ;
+	$sth = $dbh->prepare ($query) ;
+	$sth->execute () ;
+	$sth->finish () ;
+    }
+}
+
+sub drop_index_if_exists ( $ ) {
+    my $iname = shift or die  "Not enough arguments" ;
+    $query = "SELECT count(*) FROM pg_class WHERE relname='$iname' AND relkind='i'" ;
+    my $sth = $dbh->prepare ($query) ;
+    $sth->execute () ;
+    my @array = $sth->fetchrow_array () ;
+    $sth->finish () ;
+
+    if ($array [0] != 0) {
+	# debug "Dropping index $iname" ;
+	$query = "DROP INDEX $iname" ;
+	# debug $query ;
+	$sth = $dbh->prepare ($query) ;
+	$sth->execute () ;
+	$sth->finish () ;
+    }
+}
+
+sub drop_view_if_exists ( $ ) {
+    my $iname = shift or die  "Not enough arguments" ;
+    $query = "SELECT count(*) FROM pg_class WHERE relname='$iname' AND relkind='v'" ;
+    my $sth = $dbh->prepare ($query) ;
+    $sth->execute () ;
+    my @array = $sth->fetchrow_array () ;
+    $sth->finish () ;
+
+    if ($array [0] != 0) {
+	# debug "Dropping view $iname" ;
+	$query = "DROP VIEW $iname" ;
+	# debug $query ;
+	$sth = $dbh->prepare ($query) ;
+	$sth->execute () ;
+	$sth->finish () ;
+    }
+}

Added: trunk/plugins/coclico/mailman/bin/db-upgrade.pl
===================================================================
--- trunk/plugins/coclico/mailman/bin/db-upgrade.pl	                        (rev 0)
+++ trunk/plugins/coclico/mailman/bin/db-upgrade.pl	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,301 @@
+#!/usr/bin/perl -w
+#
+# Debian-specific script to upgrade the database between releases
+# Roland Mas <lolando at debian.org>
+
+use strict ;
+use diagnostics ;
+
+use DBI ;
+use MIME::Base64 ;
+use HTML::Entities ;
+
+use vars qw/$dbh @reqlist $query/ ;
+use vars qw/$sys_default_domain $sys_cvs_host $sys_download_host
+    $sys_shell_host $sys_users_host $sys_docs_host $sys_lists_host
+    $sys_dns1_host $sys_dns2_host $FTPINCOMING_DIR $FTPFILES_DIR
+    $sys_urlroot $sf_cache_dir $sys_name $sys_themeroot
+    $sys_news_group $sys_dbhost $sys_dbname $sys_dbuser $sys_dbpasswd
+    $sys_ldap_base_dn $sys_ldap_host $admin_login $admin_password
+    $server_admin $domain_name $newsadmin_groupid $statsadmin_groupid
+    $skill_list/ ;
+use vars qw/$pluginname/ ;
+
+sub is_lesser ( $$ ) ;
+sub is_greater ( $$ ) ;
+sub debug ( $ ) ;
+sub parse_sql_file ( $ ) ;
+
+require ("/usr/share/gforge/lib/include.pl") ; # Include a few predefined functions 
+require ("/usr/share/gforge/lib/sqlparser.pm") ; # Our magic SQL parser
+
+debug "You'll see some debugging info during this installation." ;
+debug "Do not worry unless told otherwise." ;
+
+&db_connect ;
+
+# debug "Connected to the database OK." ;
+
+$pluginname = "mailman" ;
+
+$dbh->{AutoCommit} = 0;
+$dbh->{RaiseError} = 1;
+eval {
+    my ($sth, @array, $version, $path, $target) ;
+
+    &create_metadata_table ("0") ;
+    
+    $version = &get_db_version ;
+    $target = "0.1" ;
+    if (is_lesser $version, $target) {
+	my @filelist = ( "/usr/share/gforge/plugins/$pluginname/lib/$pluginname-init.sql" ) ;
+	
+	foreach my $file (@filelist) {
+	    debug "Processing $file" ;
+	    @reqlist = @{ &parse_sql_file ($file) } ;
+	    
+	    foreach my $s (@reqlist) {
+		$query = $s ;
+		# debug $query ;
+		$sth = $dbh->prepare ($query) ;
+		$sth->execute () ;
+		$sth->finish () ;
+	    }
+	}
+	@reqlist = () ;
+	
+	&update_db_version ($target) ;
+	debug "Committing." ;
+	$dbh->commit () ;
+    }
+    
+    $version = &get_db_version ;
+    $target = "0.2" ;
+    if (is_lesser $version, $target) {
+	debug "Adding local data." ;
+	
+	do "/etc/gforge/local.pl" or die "Cannot read /etc/gforge/local.pl" ;
+	
+	my $ip_address = qx/host $domain_name | awk '{print \}'/ ;
+	
+	@reqlist = (
+		    "INSERT INTO plugin_".$pluginname."_sample_data (domain, ip_address) VALUES ('$domain_name', '$ip_address')",
+		    ) ;
+	
+	foreach my $s (@reqlist) {
+	    $query = $s ;
+	    # debug $query ;
+	    $sth = $dbh->prepare ($query) ;
+	    $sth->execute () ;
+	    $sth->finish () ;
+	}
+	@reqlist = () ;
+	
+	&update_db_version ($target) ;
+	debug "Committing." ;
+	$dbh->commit () ;
+    }
+
+    debug "It seems your database install/upgrade went well and smoothly.  That's cool." ;
+    debug "Please enjoy using Debian GForge." ;
+
+    # There should be a commit at the end of every block above.
+    # If there is not, then it might be symptomatic of a problem.
+    # For safety, we roll back.
+    $dbh->rollback ();
+};
+
+if ($@) {
+    warn "Transaction aborted because $@" ;
+    debug "Transaction aborted because $@" ;
+    debug "Last SQL query was:\n$query\n(end of query)" ;
+    $dbh->rollback ;
+    debug "Please report this bug on the Debian bug-tracking system." ;
+    debug "Please include the previous messages as well to help debugging." ;
+    debug "You should not worry too much about this," ;
+    debug "your DB is still in a consistent state and should be usable." ;
+    exit 1 ;
+}
+
+$dbh->rollback ;
+$dbh->disconnect ;
+
+sub is_lesser ( $$ ) {
+    my $v1 = shift || 0 ;
+    my $v2 = shift || 0 ;
+
+    my $rc = system "dpkg --compare-versions $v1 lt $v2" ;
+
+    return (! $rc) ;
+}
+
+sub is_greater ( $$ ) {
+    my $v1 = shift || 0 ;
+    my $v2 = shift || 0 ;
+
+    my $rc = system "dpkg --compare-versions $v1 gt $v2" ;
+
+    return (! $rc) ;
+}
+
+sub debug ( $ ) {
+    my $v = shift ;
+    chomp $v ;
+    print STDERR "$v\n" ;
+}
+
+sub create_metadata_table ( $ ) {
+    my $v = shift || "0" ;
+    my $tablename = "plugin_" .$pluginname . "_meta_data" ;
+    # Do we have the metadata table?
+
+    $query = "SELECT count(*) FROM pg_class WHERE relname = '$tablename' and relkind = 'r'";
+    # debug $query ;
+    my $sth = $dbh->prepare ($query) ;
+    $sth->execute () ;
+    my @array = $sth->fetchrow_array () ;
+    $sth->finish () ;
+
+    # Let's create this table if we have it not
+
+    if ($array [0] == 0) {
+	debug "Creating $tablename table." ;
+	$query = "CREATE TABLE $tablename (key varchar primary key, value text not null)" ;
+	# debug $query ;
+	$sth = $dbh->prepare ($query) ;
+	$sth->execute () ;
+	$sth->finish () ;
+    }
+
+    $query = "SELECT count(*) FROM $tablename WHERE key = 'db-version'";
+    # debug $query ;
+    $sth = $dbh->prepare ($query) ;
+    $sth->execute () ;
+    @array = $sth->fetchrow_array () ;
+    $sth->finish () ;
+
+    # Empty table?  We'll have to fill it up a bit
+
+    if ($array [0] == 0) {
+	debug "Inserting first data into $tablename table." ;
+	$query = "INSERT INTO $tablename (key, value) VALUES ('db-version', '$v')" ;
+	# debug $query ;
+	$sth = $dbh->prepare ($query) ;
+	$sth->execute () ;
+	$sth->finish () ;
+    }
+}
+
+sub update_db_version ( $ ) {
+    my $v = shift or die "Not enough arguments" ;
+    my $tablename = "plugin_" .$pluginname . "_meta_data" ;
+
+    debug "Updating $tablename table." ;
+    $query = "UPDATE $tablename SET value = '$v' WHERE key = 'db-version'" ;
+    # debug $query ;
+    my $sth = $dbh->prepare ($query) ;
+    $sth->execute () ;
+    $sth->finish () ;
+}
+
+sub get_db_version () {
+    my $tablename = "plugin_" .$pluginname . "_meta_data" ;
+
+    $query = "SELECT value FROM $tablename WHERE key = 'db-version'" ;
+    # debug $query ;
+    my $sth = $dbh->prepare ($query) ;
+    $sth->execute () ;
+    my @array = $sth->fetchrow_array () ;
+    $sth->finish () ;
+
+    my $version = $array [0] ;
+
+    return $version ;
+}
+
+sub drop_table_if_exists ( $ ) {
+    my $tname = shift or die  "Not enough arguments" ;
+    $query = "SELECT count(*) FROM pg_class WHERE relname='$tname' AND relkind='r'" ;
+    my $sth = $dbh->prepare ($query) ;
+    $sth->execute () ;
+    my @array = $sth->fetchrow_array () ;
+    $sth->finish () ;
+
+    if ($array [0] != 0) {
+	# debug "Dropping table $tname" ;
+	$query = "DROP TABLE $tname" ;
+	# debug $query ;
+	$sth = $dbh->prepare ($query) ;
+	$sth->execute () ;
+	$sth->finish () ;
+    }
+}
+
+sub drop_sequence_if_exists ( $ ) {
+    my $sname = shift or die  "Not enough arguments" ;
+    $query = "SELECT count(*) FROM pg_class WHERE relname='$sname' AND relkind='S'" ;
+    my $sth = $dbh->prepare ($query) ;
+    $sth->execute () ;
+    my @array = $sth->fetchrow_array () ;
+    $sth->finish () ;
+
+    if ($array [0] != 0) {
+	# debug "Dropping sequence $sname" ;
+	$query = "DROP SEQUENCE $sname" ;
+	# debug $query ;
+	$sth = $dbh->prepare ($query) ;
+	$sth->execute () ;
+	$sth->finish () ;
+    }
+}
+
+sub drop_index_if_exists ( $ ) {
+    my $iname = shift or die  "Not enough arguments" ;
+    $query = "SELECT count(*) FROM pg_class WHERE relname='$iname' AND relkind='i'" ;
+    my $sth = $dbh->prepare ($query) ;
+    $sth->execute () ;
+    my @array = $sth->fetchrow_array () ;
+    $sth->finish () ;
+
+    if ($array [0] != 0) {
+	# debug "Dropping index $iname" ;
+	$query = "DROP INDEX $iname" ;
+	# debug $query ;
+	$sth = $dbh->prepare ($query) ;
+	$sth->execute () ;
+	$sth->finish () ;
+    }
+}
+
+sub drop_view_if_exists ( $ ) {
+    my $iname = shift or die  "Not enough arguments" ;
+    $query = "SELECT count(*) FROM pg_class WHERE relname='$iname' AND relkind='v'" ;
+    my $sth = $dbh->prepare ($query) ;
+    $sth->execute () ;
+    my @array = $sth->fetchrow_array () ;
+    $sth->finish () ;
+
+    if ($array [0] != 0) {
+	# debug "Dropping view $iname" ;
+	$query = "DROP VIEW $iname" ;
+	# debug $query ;
+	$sth = $dbh->prepare ($query) ;
+	$sth->execute () ;
+	$sth->finish () ;
+    }
+}
+
+sub bump_sequence_to ( $$ ) {
+    my ($sth, @array, $seqname, $targetvalue) ;
+
+    $seqname = shift ;
+    $targetvalue = shift ;
+
+    do {
+	$query = "select nextval ('$seqname')" ;
+	$sth = $dbh->prepare ($query) ;
+	$sth->execute () ;
+	@array = $sth->fetchrow_array () ;
+	$sth->finish () ;
+    } until $array[0] >= $targetvalue ;
+}

Added: trunk/plugins/coclico/mailman/common/mailman-init.php
===================================================================
--- trunk/plugins/coclico/mailman/common/mailman-init.php	                        (rev 0)
+++ trunk/plugins/coclico/mailman/common/mailman-init.php	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,36 @@
+<?php
+
+/**
+ *
+ * This file is part of GForge.
+ *
+ * GForge 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.
+ *
+ * GForge 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 GForge; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ * 
+ * Portions Copyright 2010 (c) Mélanie Le Bail
+ */
+
+global $gfplugins;
+require_once $gfplugins.'mailman/include/mailmanPlugin.class.php' ;
+
+$mailmanPluginObject = new mailmanPlugin() ;
+
+register_plugin ($mailmanPluginObject) ;
+
+// Local Variables:
+// mode: php
+// c-file-style: "bsd"
+// End:
+
+?>

Added: trunk/plugins/coclico/mailman/cronjobs/manage_mailmanlists.php
===================================================================
--- trunk/plugins/coclico/mailman/cronjobs/manage_mailmanlists.php	                        (rev 0)
+++ trunk/plugins/coclico/mailman/cronjobs/manage_mailmanlists.php	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,73 @@
+#! /usr/bin/php5 -f
+<?php
+/**
+ * FusionForge source control management
+ *
+ * Copyright 2009, Roland Mas
+ *
+ * This file is part of FusionForge.
+ *
+ * FusionForge 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.
+ * 
+ * FusionForge 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 FusionForge; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+require 'env.inc.php';
+require_once $gfwww.'include/squal_pre.php';
+require_once $gfcommon.'include/cron_utils.php';
+
+// MailingList backend class
+require_once $gfplugins.'mailman/include/BackendMailmanList.class.php' ;
+			 
+
+$res = db_query_params ('SELECT id,type, parameters FROM system_event WHERE status=$1 ORDER BY id DESC',
+			array ('1')); 
+if (!$res) {
+	printf('Unable to get list of events: '.db_error());
+	return false;
+}
+
+while ($data = db_fetch_array ($res)) {
+	if($data['type'] == 'MAILMAN_LIST_CREATE') {
+		BackendMailmanList::instance()->createList($data['parameters']);
+	} elseif ($data['type'] == 'MAILMAN_LIST_DELETE') {
+		BackendMailmanList::instance()->deleteList($data['parameters']);
+	}
+	$events[$data['id']]=$data['parameters'];
+	echo "events[".$data['id']."]=".$data['parameters'];
+}
+if(isset($events)) {
+	foreach($events as $event_id => $list_id) {
+		$sql = "UPDATE system_event SET end_date='".time()."', log='DONE', status='3' WHERE id='".$event_id."';"; 
+		$result = db_query($sql);
+		if (!$result) {
+			printf('Unable to update the list of events: '.db_error());
+			return false;
+		}
+		$sql = "UPDATE mail_group_list SET status='3' WHERE group_list_id='".$list_id."';"; 
+		$result = db_query($sql);
+		if (!$result) {
+			printf('Unable to update the list of events: '.db_error());
+			return false;
+		}
+	}
+
+}
+
+
+// Local Variables:
+// mode: php
+// c-file-style: "bsd"
+// End:
+
+?>

Added: trunk/plugins/coclico/mailman/db/install.sql
===================================================================
--- trunk/plugins/coclico/mailman/db/install.sql	                        (rev 0)
+++ trunk/plugins/coclico/mailman/db/install.sql	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,29 @@
+## 
+## Sql Install Script
+##
+ CREATE TABLE IF NOT EXISTS `plugin_mailman` (
+listname varchar( 100 ) NOT NULL ,
+address varchar( 255 ) NOT NULL ,
+hide enum( 'Y', 'N' ) NOT NULL default 'N',
+nomail enum( 'Y', 'N' ) NOT NULL default 'N',
+ack enum( 'Y', 'N' ) NOT NULL default 'Y',
+not_metoo enum( 'Y', 'N' ) NOT NULL default 'Y',
+digest enum( 'Y', 'N' ) NOT NULL default 'N',
+plain enum( 'Y', 'N' ) NOT NULL default 'N',
+PASSWORD varchar( 255 ) NOT NULL default '!',
+lang varchar( 255 ) NOT NULL default 'en',
+name varchar( 255 ) default NULL ,
+one_last_digest enum( 'Y', 'N' ) NOT NULL default 'N',
+user_options bigint( 20 ) NOT NULL default 0,
+delivery_status INT( 10 ) NOT NULL default 0,
+topics_userinterest varchar( 255 ) default NULL ,
+delivery_status_timestamp datetime default '0000-00-00 00:00:00',
+bi_cookie varchar( 255 ) default NULL ,
+bi_score double NOT NULL default '0',
+bi_noticesleft double NOT NULL default '0',
+bi_lastnotice date NOT NULL default '0000-00-00',
+bi_date date NOT NULL default '0000-00-00'
+); 
+INSERT INTO service(group_id, label, description, short_name, link, is_active, is_used, scope, rank) VALUES ( 100 , 'Mailman' , 'Manage mailing lists' , 'mailman', '/plugins/mailman/index.php?group_id=$group_id', 1 , 0 , 'system',  230 );
+
+        

Added: trunk/plugins/coclico/mailman/db/mailman-init.sql
===================================================================
--- trunk/plugins/coclico/mailman/db/mailman-init.sql	                        (rev 0)
+++ trunk/plugins/coclico/mailman/db/mailman-init.sql	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,24 @@
+CREATE TABLE plugin_mailman (
+	  listname character varying(100) NOT NULL,
+	  address character varying(255) NOT NULL,
+	  hide character varying(255) NOT NULL default 'N',
+	  nomail character varying(255) NOT NULL default 'N',
+	  ack character varying(255) NOT NULL default 'Y',
+	  not_metoo character varying(255) NOT NULL default 'Y',
+	  digest character varying(255) NOT NULL default 'N',
+	  plain character varying(255) NOT NULL default 'N',
+	  password character varying(255) NOT NULL default '!',
+	  lang character varying(255) NOT NULL default 'en',
+	  name character varying(255) default NULL,
+	  one_last_digest character varying(255) NOT NULL default 'N',
+	  user_options bigint NOT NULL default 0,
+	  delivery_status integer NOT NULL default 0,
+	  topics_userinterest character varying(255) default NULL,
+	  delivery_status_timestamp timestamp without time zone default '1901-01-01 01:01:01',
+	  bi_cookie character varying(255) default NULL,
+	  bi_score double precision NOT NULL default '0',
+	  bi_noticesleft double precision NOT NULL default '0',
+	  bi_lastnotice date NOT NULL default '1901-01-01',
+	  bi_date date NOT NULL default '1901-01-01',
+	  PRIMARY KEY  (listname, address)
+);

Added: trunk/plugins/coclico/mailman/db/uninstall.sql
===================================================================
--- trunk/plugins/coclico/mailman/db/uninstall.sql	                        (rev 0)
+++ trunk/plugins/coclico/mailman/db/uninstall.sql	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,6 @@
+##
+## Sql Uninstall Script
+##
+
+DELETE FROM service WHERE short_name='mailman';
+

Added: trunk/plugins/coclico/mailman/debian/README.Debian
===================================================================
--- trunk/plugins/coclico/mailman/debian/README.Debian	                        (rev 0)
+++ trunk/plugins/coclico/mailman/debian/README.Debian	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,6 @@
+fusionforge-plugin-mailman for Debian
+---------------------
+
+See README.Debian in fusionforge-common package
+
+ -- Christian Bayle <bayle at debian.org>  Mon, 08 Mar 2010 16:37:51 +0100

Added: trunk/plugins/coclico/mailman/debian/README.source
===================================================================
--- trunk/plugins/coclico/mailman/debian/README.source	                        (rev 0)
+++ trunk/plugins/coclico/mailman/debian/README.source	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,9 @@
+mailman for Debian
+---------------------
+
+<this file describes information about the source package, see Debian policy
+manual section 4.14. You WILL either need to modify or delete this file>
+
+
+
+

Added: trunk/plugins/coclico/mailman/debian/changelog
===================================================================
--- trunk/plugins/coclico/mailman/debian/changelog	                        (rev 0)
+++ trunk/plugins/coclico/mailman/debian/changelog	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,5 @@
+fusionforge-plugin-mailman (1.0-1) unstable; urgency=low
+
+  * Initial release (Closes: #nnnn)  <nnnn is the bug number of your ITP>
+
+ -- Christian Bayle <bayle at debian.org>  Mon, 08 Mar 2010 16:37:51 +0100

Added: trunk/plugins/coclico/mailman/debian/compat
===================================================================
--- trunk/plugins/coclico/mailman/debian/compat	                        (rev 0)
+++ trunk/plugins/coclico/mailman/debian/compat	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1 @@
+7

Added: trunk/plugins/coclico/mailman/debian/control
===================================================================
--- trunk/plugins/coclico/mailman/debian/control	                        (rev 0)
+++ trunk/plugins/coclico/mailman/debian/control	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,20 @@
+Source: fusionforge-plugin-mailman
+Section: devel
+Priority: optional
+Maintainer: Christian Bayle <bayle at debian.org>
+Uploaders: Roland Mas <lolando at debian.org>
+Build-Depends-Indep: devscripts
+Build-Depends: debhelper (>= 7), perl, gettext
+Standards-Version: 3.8.4
+Homepage: http://fusionforge.org/
+Vcs-Bzr: http://scm.fusionforge.org/bzr/fusionforge/svn-trunk-ro/
+
+Package: fusionforge-plugin-mailman
+Architecture: all
+Depends: gforge-common, gforge-db-postgresql | gforge-db, gforge-web-apache2 | gforge-web, gforge-shell-postgresql | gforge-shell, php5-cli, ${misc:Depends}
+Description: collaborative development tool - Helloworld plugin
+ .
+ This plugin contains the Helloworld subsystem of FusionForge. It allows each
+ FusionForge project to have its own Helloworld, and gives some
+ control over it to the project's administrator.
+

Added: trunk/plugins/coclico/mailman/debian/copyright
===================================================================
--- trunk/plugins/coclico/mailman/debian/copyright	                        (rev 0)
+++ trunk/plugins/coclico/mailman/debian/copyright	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,63 @@
+The "sourceforge" package was first debianised on Wed, 22 Nov 2000
+22:06:35 +0100 by Roland Mas <lolando at debian.org>.  Work has been
+constant since then, and the package evolved a great deal.  It began
+to work, for a start, and then it evolved into GForge, what with the
+more recent versions of the Sourceforge software having been made
+proprietary.  And then in early 2009 it evolved into FusionForge, what
+with the more recent versions of GForge having been rewritten as
+proprietary software without a name change.
+
+FusionForge is Copyright © 2009-2010 by several people, including:
+Alain Peyrat            <aljeux at free.fr>
+Alexandre Neymann       <alexandre.neymann at dgfip.finances.gouv.fr>
+Christian Bayle         <bayle at debian.org>
+Roland Mas              <lolando at debian.org>
+Gonéri Le Bouder        <goneri.lebouder at atosorigin.com>
+Julien Heyman 		<julien.heyman at atosorigin.com>
+Olivier Meunier 	<olivier.meunier at centraliens.net>
+
+GForge itself is Copyright © 2000-2008 by a fair number of people,
+including:
+Tim Perdue              <tim at gforge.org>
+Roland Mas              <99.roland.mas at aist.enst.fr>
+Christian Bayle         <gforge at free.fr>
+Tom Copeland            <tom at infoether.com>
+Guillaume Smet          <guillaume-gforge at smet.org>
+Francisco Gimeno        <kikov at kikov.org>
+Sung Kim                <hunkims at gmail.com>
+Alain Peyrat            <aljeux at free.fr>
+
+Past Members of the development team include:
+Reinhard Spisser
+Ryan T. Sammartino
+Edward Ritter
+Michael Jennings
+
+Since FusionForge, and GForge before it, was initially a fork of
+Sourceforge, here's the copyright info for the Sourceforge software:
+,----
+| The original sources were downloaded from http://www.sourceforge.net/
+| 
+| Authors: The Sourceforge crew at VA Linux.  They are many, they
+| change as time goes by, and they are listed on the Sourceforge
+| website.  Let them be thanked for their work.
+| 
+| Copyright:
+| 
+| This software is Copyright © 1999-2000 by VA Linux.
+| 
+| You are free to distribute this software under the terms of the GNU
+| General Public License.
+`----
+
+The packaging and installing scripts (in the debian/ and deb-specific/
+directories amongst others) are Copyright © 2000-2010 by Christian
+Bayle <bayle at aist.enst.fr> and Roland Mas <lolando at debian.org>.  You
+are free to use and redistribute them under the terms of the GNU
+General Public License, version 2 or (at your option) any later
+version published by the Free Software Foundation.
+
+See Also Copyright file in fusionforge package
+
+On Debian systems, the complete text of the GNU General Public License
+can be found in the /usr/share/common-licenses directory.

Added: trunk/plugins/coclico/mailman/debian/rules
===================================================================
--- trunk/plugins/coclico/mailman/debian/rules	                        (rev 0)
+++ trunk/plugins/coclico/mailman/debian/rules	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,78 @@
+#!/usr/bin/make -f
+# -*- makefile -*-
+# Sample debian/rules that uses debhelper.
+# This file was originally written by Joey Hess and Craig Small.
+# As a special exception, when this file is copied by dh-make into a
+# dh-make output file, you may use that output file without restriction.
+# This special exception was added by Craig Small in version 0.37 of dh-make.
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+SRCPACKAGE=$(shell head -1 $(CURDIR)/debian/changelog | sed 's/\(.[^ ]*\) .*/\1/')
+MAJOR=$(shell head -1 $(CURDIR)/debian/changelog | sed 's/.*(\(.*\)-[^-]*).*/\1/')
+ORIGFILE=$(SRCPACKAGE)_$(MAJOR).orig.tar.gz
+OLDPACKAGE=gforge
+PACKAGE=fusionforge
+FORGENAME=FusionForge
+
+SED_REPLACE=sed -e 's/@PACKAGE@/$(PACKAGE)/g' -e 's/@SRCPACKAGE@/$(SRCPACKAGE)/g' -e 's/@FORGENAME@/$(FORGENAME)/g' -e 's/@OLDPACKAGE@/$(OLDPACKAGE)/g'
+
+CRONDFILES=$(patsubst packaging/cron.d/%,debian/$(PACKAGE)-%.cron.d,$(wildcard packaging/cron.d/[a-z]*))
+DIRSFILES=$(patsubst packaging/dirs/%,debian/$(PACKAGE)-%.dirs,$(wildcard packaging/dirs/[a-z]*))
+LINKSFILES=$(patsubst packaging/links/%,debian/$(PACKAGE)-%.links,$(wildcard packaging/links/[a-z]*))
+INSTALLFILES=$(patsubst packaging/install/%,debian/$(PACKAGE)-%.install,$(wildcard packaging/install/[a-z]*))
+DOCSFILES=$(patsubst packaging/docs/%,debian/$(PACKAGE)-%.docs,$(wildcard packaging/docs/[a-z]*))
+POFILES=$(patsubst debian/dsf-po/%,debian/po/%,$(wildcard debian/dsf-po/*) debian/po/POTFILES.in)
+
+.PHONY: conffiles
+conffiles: $(CRONDFILES) $(DIRSFILES) $(LINKSFILES) $(INSTALLFILES) $(DOCSFILES) debian/control
+
+debian/$(PACKAGE)-%.cron.d:
+	(cat $(CURDIR)/packaging/cron.d/00phpcron ; sed -e 's/\$$FFUSER/$(PACKAGE)/g' $(CURDIR)/packaging/cron.d/$*) > $@
+
+debian/$(PACKAGE)-%.dirs:
+	cp $(CURDIR)/packaging/dirs/$* $@ 
+
+debian/$(PACKAGE)-%.links:
+	cp $(CURDIR)/packaging/links/$* $@ 
+
+debian/$(PACKAGE)-%.install:
+	cp $(CURDIR)/packaging/install/$* $@ 
+
+debian/$(PACKAGE)-%.docs:
+	cp $(CURDIR)/packaging/docs/$* $@
+
+debian/control: $(wildcard packaging/control/*)
+	ls $(CURDIR)/packaging/control/[0-9][0-9][0-9]* | grep -v shortdesc | grep -v scmcpold | while read file ; do cat $${file}; if [ -f $${file}.shortdesc ] ; then cat $(CURDIR)/packaging/control/AAAdesc; echo ' .'; cat $${file}.shortdesc; fi; echo '';  done | $(SED_REPLACE) > $@
+
+debian/po/templates.pot: $(wildcard debian/dsf-in/*.templates.dsfh-in) $(wildcard debian/dsf-helper/*.templates)
+        @debconf-updatepo --podir=debian/dsf-po
+
+debian/po/%:
+	cat $(patsubst debian/po/%,debian/dsf-po/%,$@) | $(SED_REPLACE) > $@
+
+build: debian/po/templates.pot conffiles
+	dh $@
+	# Build gettext *.mo files
+	utils/manage-translations.sh build
+
+clean:
+	dh $@
+	rm -f $(CURDIR)/debian/*.cron.d
+	rm -f $(CURDIR)/debian/*.dirs
+	rm -f $(CURDIR)/debian/*.links
+	rm -f $(CURDIR)/debian/*.install
+	rm -f $(CURDIR)/debian/*.docs
+	rm -rf locales
+	rm -f $(POFILES)
+
+makeorig: 
+	find $(PKGDIR) -type f -or -type l | grep -v '/CVS/' | \
+	grep -v '/.svn/' | grep -v '/.testbox/' | \
+	grep -v rpm-specific | grep -v docs/phpdoc/docs | \
+	grep -v ^./debian/ | grep -v \\.jar$$ | \
+	grep -v \\.pdf$$ | grep -v plugins/fckeditor/www/_samples | \
+	cpio -o -H ustar | gzip > ../$(ORIGFILE)
+
+%:
+	dh  $@


Property changes on: trunk/plugins/coclico/mailman/debian/rules
___________________________________________________________________
Added: svn:executable
   + *

Added: trunk/plugins/coclico/mailman/debian/source/format
===================================================================
--- trunk/plugins/coclico/mailman/debian/source/format	                        (rev 0)
+++ trunk/plugins/coclico/mailman/debian/source/format	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1 @@
+1.0

Added: trunk/plugins/coclico/mailman/etc/plugins/mailman/config.php
===================================================================
--- trunk/plugins/coclico/mailman/etc/plugins/mailman/config.php	                        (rev 0)
+++ trunk/plugins/coclico/mailman/etc/plugins/mailman/config.php	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,4 @@
+<?php 
+$GLOBALS['mailman_bin_dir'] =  $GLOBALS['sys_path_to_mailman'].'/bin';
+$GLOBALS['mailman_list_dir'] = '/var/lib/mailman/lists';
+?>

Added: trunk/plugins/coclico/mailman/include/BackendMailmanList.class.php
===================================================================
--- trunk/plugins/coclico/mailman/include/BackendMailmanList.class.php	                        (rev 0)
+++ trunk/plugins/coclico/mailman/include/BackendMailmanList.class.php	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,174 @@
+<?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/>.
+ *
+ * Portions Copyright 2010 (c) Mélanie Le Bail
+ */
+
+require_once('common/event/Event.class.php');
+require_once 'mailman/include/MailmanListDao.class.php';
+require_once 'common/dao/CodendiDataAccess.class.php';
+require_once 'mailman/include/MailmanList.class.php';
+require_once 'plugins_utils.php';
+
+class BackendMailmanList {
+
+    protected $_mailinglistdao = null;
+
+    /**
+     * Hold an instance of the class
+     */
+    protected static $_instance;
+    
+    /**
+     * Backends are singletons
+     */
+    public static function instance() {
+    
+        if (!isset(self::$_instance)) {
+            $c = __CLASS__;
+            self::$_instance = new $c;
+        }
+        return self::$_instance;
+    }
+
+    /**
+     * @return MailingListDao
+     */
+    protected function _getMailingListDao() {
+        if (!$this->_mailinglistdao) {
+          $this->_mailinglistdao = new MailmanListDao(CodendiDataAccess::instance());
+        }
+        return $this->_mailinglistdao;
+    }
+
+
+    /** 
+     * Update mailman configuration for the given list
+     * Write configuration in temporary file, and load it with mailman config_list tool
+     * @return true on success, false otherwise
+     */
+    protected function updateListConfig($list) {
+        // write configuration in temporary file
+        $config_file=$GLOBALS['tmp_dir']."/mailman_config_".$list->getID().".in";
+        
+        if ($fp = fopen($config_file, 'w')) {
+            // Define encoding of this file for Python. See SR #764 
+            // Please note that this allows config_list to run with UTF-8 strings, but if the 	 
+            // description contains non-ascii chars, they will be displayed badly in mailman config web page.
+            fwrite($fp, "# coding=UTF-8\n\n");
+            // Deactivate monthly reminders by default
+            fwrite($fp, "send_reminders = 0\n");
+            // Setup the description
+            fwrite($fp, "description = '".addslashes($list->getDescription())."'\n");
+            // Allow up to 200 kB messages
+            fwrite($fp, "max_message_size = 200\n");
+        
+            if ($list->isPublic() == 0) { // Private lists
+                // Don't advertise this list when people ask what lists are on this machine
+                fwrite($fp, "advertised = False\n");
+                // Private archives
+                fwrite($fp, "archive_private = 1\n");
+                // Subscribe requires approval
+                fwrite($fp, "subscribe_policy = 2\n");
+            }
+            fclose($fp);
+            
+            if (system($GLOBALS['mailman_bin_dir']."/config_list -i $config_file ".$list->getName()) !== false) {
+                if (unlink($config_file)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+
+    /**
+     * Create new mailing list with mailman 'newlist' tool
+     * then update the list configuration according to list settings
+     * @return true on success, false otherwise
+     */
+    public function createList($group_list_id) {
+
+        $dar = $this->_getMailingListDao()->searchByGroupListId($group_list_id);
+
+        if ($row = $dar->getRow()) {
+        	echo "j'ai une row";
+            $list = new MailmanList($row['group_id'],$row['group_list_id']);
+            $user=UserManager::instance()->getUserByID($list->getListAdminId());
+			$list_admin_email= $user->getEmail();
+            $list_dir = $GLOBALS['mailman_list_dir']."/".$list->getName();
+
+            if ((! is_dir($list_dir))&&($list->isPublic() != 9)) {
+                // Create list
+                echo "execution system";
+               system($GLOBALS['mailman_bin_dir']."/newlist -q ".$list->getName()." ".$list_admin_email." ".$list->getPassword()." >/dev/null");
+				echo "ok pour system";
+				//$list->update($list->getDescription(),$list->isPublic(),'1');
+				echo "update done";
+                // Then update configuraion
+                return $this->updateListConfig($list);
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Delete mailing list 
+     * - list and archives are deleted
+     * - backup first in temp directory
+     * @return true on success, false otherwise
+     */
+    public function deleteList($group_list_id) {
+        $dar = $this->_getMailingListDao()->searchByGroupListId($group_list_id);
+
+        if ($row = $dar->getRow()) {
+            $list=new MailmanList($row['group_id'],$group_list_id);
+            $list_dir = $GLOBALS['mailman_list_dir']."/".$list->getName();
+            if ((is_dir($list_dir))&&($list->isPublic() == 9)) {
+
+                // Archive first
+                $list_archive_dir = $GLOBALS['mailman_list_dir']."/../archives/private/".$list->getName(); // Does it work? TODO
+                $backupfile=$GLOBALS['tmp_dir']."/".$list->getName()."-mailman.tgz";
+                system("tar cfz $backupfile $list_dir $list_archive_dir");
+                chmod($backupfile,0600);
+
+                // Delete the mailing list if asked to and the mailing exists (archive deleted as well)
+                system($GLOBALS['mailman_bin_dir']. '/rmlist -a '. $list->getName() .' >/dev/null');
+                
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Check if the list exists on the file system
+     * @return true if list exists, false otherwise
+     */
+    public function listExists($list) {
+        // Is this the best test?
+        $list_dir = $GLOBALS['mailman_list_dir']."/".$list->getName();
+        if (! is_dir($list_dir)) return false;
+        return true;
+    }
+
+}
+
+?>

Added: trunk/plugins/coclico/mailman/include/MailmanList.class.php
===================================================================
--- trunk/plugins/coclico/mailman/include/MailmanList.class.php	                        (rev 0)
+++ trunk/plugins/coclico/mailman/include/MailmanList.class.php	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,440 @@
+<?php
+/**
+ * GForge Mailing Lists Facility
+ *
+ * Copyright 2003 Guillaume Smet
+ * http://gforge.org/
+ *
+ * @version   $Id$
+ *
+ * This file is part of GForge.
+ *
+ * GForge 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.
+ *
+ * GForge 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 GForge; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * Portions Copyright 2010 (c) Mélanie Le Bail
+ */
+
+
+/*
+
+   This work is based on Tim Perdue's work on the forum stuff
+
+ */
+
+require_once 'MailmanListDao.class.php';
+require_once 'common/dao/CodendiDataAccess.class.php';
+require_once 'common/system_event/SystemEventManager.class.php';
+require_once 'common/system_event/SystemEvent.class.php';
+
+class MailmanList extends Error {
+	/**
+	 * DAO 
+	 *
+	 * @var	 MailingListDao   $mailingDAO.
+	 */
+	var $_mailingDAO;
+
+	/**
+	 * Associative array of data from db.
+	 *
+	 * @var	 array   $dataArray.
+	 */
+	var $dataArray;
+
+	/**
+	 * The Group object.
+	 *
+	 * @var	 object  $Group.
+	 */
+	var $Group;
+
+	/**
+	 * The mailing list id
+	 *
+	 * @var int $groupMailmanListId
+	 */
+	var $groupMailmanListId;
+
+	/**
+	 *  Constructor.
+	 *
+	 * @param	object	The Group object to which this mailing list is associated.
+	 * @param	int		The group_list_id.
+	 * @param	array		The associative array of data.
+	 * @return	boolean	success.
+	 */
+	function MailmanList($group_id, $groupListId = false, $dataArray = false) {
+		$pm = ProjectManager::instance();
+		$Group = $pm->getProject($group_id);
+		$this->_mailingDAO =& new MailmanListDao(CodendiDataAccess::instance());	
+		$this->Error();
+		if (!$Group || !is_object($Group)) {
+			$this->setError(sprintf(_('%1$s:: No Valid Group Object'), 'MailmanList'));
+			return false;
+		}
+		if ($Group->isError()) {
+			$this->setError('MailmanList:: '.$Group->getErrorMessage());
+			return false;
+		}
+		$this->Group =& $Group;
+
+		if ($groupListId) {
+			$this->groupMailmanListId = $groupListId;
+			if (!$dataArray || !is_array($dataArray)) {
+				if (!$this->fetchData($groupListId)) {
+					return false;
+				}
+			} else {
+				$this->dataArray =& $dataArray;
+				if ($this->dataArray['group_id'] != $this->Group->getID()) {
+					$this->setError(_('Group_id in db result does not match Group Object'));
+					$this->dataArray = null;
+					return false;
+				}
+			}
+			if (!$this->isPublic()) {
+				if (!isLogged()) {
+					$this->dataArray = null;
+					return false;
+				}
+			}
+		}
+
+		return true;
+	}
+
+	/**
+	 *	create - use this function to create a new entry in the database.
+	 *
+	 *	@param	string	The name of the mailing list
+	 *	@param	string	The description of the mailing list
+	 *	@param	int	Pass (1) if it should be public (0) for private.
+	 *
+	 *	@return	boolean	success.
+	 **/
+
+	function create($listName, $description, $isPublic = '1',$creator_id=false) {
+		$current_user=UserManager::instance()->getCurrentUser();
+		//
+		//	During the group creation, the current user_id will not match the admin's id
+		//
+		if (!$creator_id) {
+			$creator_id=$current_user->getID();
+			if(!$current_user->isMember($this->Group->getID(),'A')) {
+				exit_permission_denied();
+				return false;
+			}
+		}
+
+		if(!$listName || strlen($listName) < 4) {
+			$this->setError(_('Must Provide List Name That Is 4 or More Characters Long'));
+			return false;
+		}
+
+		$realListName = strtolower($this->Group->getUnixName().'-'.$listName);
+
+		if(!validate_email($realListName.'@'.$GLOBALS['sys_lists_host'])) {
+			$this->setError(_('Invalid List Name') . ': ' .
+					$realListName.'@'.$GLOBALS['sys_lists_host']);
+			return false;
+		}
+		$result=&$this->_mailingDAO->searchByName($realListName);
+
+		if ($result->valid()) {
+			$this->setError(_('List Already Exists'));
+			return false;
+		}
+
+
+		$listPassword = substr(md5($GLOBALS['session_hash'] . time() . rand(0,40000)), 0, 16);
+		$result = $this->_mailingDAO->insertNewList($this->Group->getID(), $realListName,$isPublic,$listPassword,$creator_id,'1',$description);
+		if (!$result) {
+			$this->setError(sprintf(_('Error Creating %1$s'), _('Error Creating %1$s')).db_error());
+			return false;
+		}
+
+		$this->groupMailmanListId = $result;
+		// Raise an event
+		require_once('mailman/include/events/SystemEvent_MAILMAN_LIST_CREATE.class.php');
+		$systemevent =	SystemEventManager::instance();
+		$systemevent->createEvent('MAILMAN_LIST_CREATE', array('group_list_id' => $this->groupMailmanListId,),SystemEvent::PRIORITY_MEDIUM);
+		$this->fetchData($this->groupMailmanListId);
+		$user=UserManager::instance()->getUserByID($creator_id);
+	
+		$userEmail = $user->getEmail();
+		if(empty($userEmail) || !validate_email($userEmail)) {
+			$this->setInvalidEmailError();
+			return false;
+		} else {
+			sendCreationMail($userEmail,$realListName,$listPassword);
+		}
+
+		return true;
+	}
+
+	/**
+	 *  fetchData - re-fetch the data for this mailing list from the database.
+	 *
+	 *  @param  int	 The list_id.
+	 *	@return	boolean	success.
+	 */
+	function fetchData($groupListId) {
+		$res =& $this->_mailingDAO->searchListFromGroup($groupListId, $this->Group->getID());
+
+		if (!$res) {
+			$this->setError(sprintf(_('Error Getting %1$s'), _('Error Getting %1$s')));
+			return false;
+		}
+		$this->dataArray =& $res->getRow();
+		return true;
+	}
+
+	/**
+	 *	update - use this function to update an entry in the database.
+	 *
+	 *	@param	string	The description of the mailing list
+	 *	@param	int	Pass (1) if it should be public (0) for private
+	 *	@return	boolean	success.
+	 */
+	function update($description, $isPublic ='1',$status='1') {
+		$current_user=UserManager::instance()->getCurrentUser();
+		if(!$current_user->isMember($this->Group->getID(),'A')) {
+			exit_permission_denied();
+			return false;
+		}
+		$res = $this->_mailingDAO->updateList($this->groupMailmanListId, $this->Group->getID(),$description , $isPublic,$status);
+		if (!$res) {
+			$this->setError(_('Error On Update:').db_error());
+			return false;
+		}
+		return true;
+	}
+
+	/**
+	 *	getGroup - get the Group object this mailing list is associated with.
+	 *
+	 *	@return	object	The Group object.
+	 */
+	function &getGroup() {
+		return $this->Group;
+	}
+
+	/**
+	 *	getID - The id of this mailing list
+	 *
+	 *	@return	int	The group_list_id #.
+	 */
+	function getID() {
+		return $this->dataArray['group_list_id'];
+	}
+
+
+	/**
+	 *	isPublic - Is this mailing list open to the general public.
+	 *
+	 *	@return boolean	is_public.
+	 */
+	function isPublic() {
+		return $this->dataArray['is_public'];
+	}
+
+	/**
+	 *	getName - get the name of this mailing list
+	 *
+	 *	@return string	The name of this mailing list
+	 */
+	function getName() {
+		return $this->dataArray['list_name'];
+	}
+
+
+	/**
+	 *	getDescription - get the description of this mailing list
+	 *
+	 *	@return string	The description.
+	 */
+	function getDescription() {
+		return $this->dataArray['description'];
+	}
+
+	/**
+	 * getPassword - get the password to administrate the mailing list
+	 *
+	 * @return string The password
+	 */
+	function getPassword() {
+		return $this->dataArray['password'];
+	}
+
+	/**
+	 * getListAdminID - get the user id who is the admin of this mailing list
+	 *
+	 * @return id The admin user
+	 */
+	function getListAdminID() {
+		return $this->dataArray['list_admin'];
+	}
+
+	/**
+	 * getStatus - get the status of this mailing list
+	 *
+	 * @return int The status
+	 */
+	function getStatus() {
+		return $this->dataArray['status'];
+	}
+
+	/**
+	 * getArchivesUrl - get the url to see the archives of the list
+	 *
+	 * @return string url of the archives
+	 */
+	function getArchivesUrl() {
+		if ($this->isPublic()) {
+			$iframe_url = 'http://'.$GLOBALS['sys_lists_host'].'/pipermail/'.$this->getName().'/';
+		} else {
+			$iframe_url = 'http://'.$GLOBALS['sys_lists_host'].'/mailman/private/'.$this->getName().'/';
+		}
+		htmlIframe($iframe_url, array('class' => 'iframe_service'));
+	}
+
+	/**
+	 * getExternalInfoUrl - get the url to subscribe/unsubscribe
+	 *
+	 * @return string url of the info page
+	 */
+	function getExternalInfoUrl() {
+		return 'http://'.$GLOBALS['sys_lists_host'].'/mailman/listinfo/'.$this->getName();
+	}
+	/**
+	 * getOptionsUrl - get the url to manage options for user
+	 *
+	 * @return string url of the info page
+	 */
+	function getOptionsUrl() {
+		$current_user=UserManager::instance()->getCurrentUser();
+		$user=$current_user->getEmail();
+		$iframe_url = 'http://'.$GLOBALS['sys_lists_host'].'/mailman/options/'.$this->getName().'/'.$user;
+		htmlIframe($iframe_url, array('class' => 'iframe_service'));
+	}
+	/**
+	 * subscribeUrl - add the user to the mailinglist
+	 *
+	 * @return string url of the info page
+	 */
+	function subscribe() {
+		if(isLogged() && $this->isPublic() && !$this->isMonitoring())
+		{
+			$current_user=UserManager::instance()->getCurrentUser();
+			$user=$current_user->getEmail();
+			$passwd= $current_user->getUserPw();
+			$name= $current_user->getRealName();
+			$res = $this->_mailingDAO->newSubscriber($user,$name,$passwd,$this->getName());
+			if (!$res) {
+				$this->setError(_('Error On Update:').db_error());
+				return false;
+			}
+			htmlRedirect('index.php?group_id='.$this->Group->getId());
+		}
+
+	}
+	/**
+	 * unsubscribeUrl - delete the user from the mailing list
+	 * 
+	 * @return string url of the info page
+	 */
+	function unsubscribe() {
+		$current_user=UserManager::instance()->getCurrentUser();
+		$user=$current_user->getEmail();
+		$res = $this->_mailingDAO->deleteSubscriber($user,$this->getName());
+		if (!$res) {
+			$this->setError(_('Error On Update:').db_error());
+			return false;
+		}
+		htmlRedirect('index.php?group_id='.$this->Group->getId());
+	}
+	/**
+	 *	isMonitoring - See if the current user is in the list of people monitoring the forum.
+	 *
+	 *	@return	boolean	is_monitoring.
+	 */
+	function isMonitoring() {
+		if (!isLogged()) {
+			return false;
+		}
+		$current_user=UserManager::instance()->getCurrentUser();
+		$user=$current_user->getEmail();
+		$res = $this->_mailingDAO->userIsMonitoring($user,$this->getName());
+		if (!$res) {
+			$this->setError(_('Error On Query:').db_error());
+			return false;
+		}
+		$row_count = $res->getRow();
+		return $row_count['count'] > 0;
+	}
+
+
+
+	/**
+	 * getExternalAdminUrl - get the url to admin the list with the external tools used
+	 *
+	 * @return string url of the admin
+	 */
+
+	function getExternalAdminUrl() {
+		$iframe_url = 'http://'.$GLOBALS['sys_lists_host'].'/mailman/admin/'.$this->getName();
+		htmlIframe($iframe_url, array('class' => 'iframe_service'));
+	}
+
+	/**
+	 *	delete - permanently delete this mailing list
+	 *
+	 *	@param	boolean	I'm Sure.
+	 *	@param	boolean	I'm Really Sure.
+	 *	@return	boolean success;
+	 */
+	function deleteList($sure,$really_sure) {
+		$current_user=UserManager::instance()->getCurrentUser();
+		if (!$sure || !$really_sure) {
+			$this->setError('Missing params');
+			return false;
+		}
+		
+		if (!$current_user->isMember($this->Group->getID(),'A')) {
+			exit_permission_denied();
+			return false;
+		}
+		$res = $this->_mailingDAO->deleteList($this->Group->getID(),$this->getID());
+		if (!$res) {
+			$this->setError('Could Not Delete List: '.db_error());
+			return false;
+		}
+		require_once('mailman/include/events/SystemEvent_MAILMAN_LIST_DELETE.class.php');
+		$systemevent =	SystemEventManager::instance();
+		$systemevent->createEvent('MAILMAN_LIST_DELETE', array('group_list_id' => $this->groupMailmanListId,),SystemEvent::PRIORITY_MEDIUM);
+		
+
+		return true;
+
+	}
+
+}
+
+// Local Variables:
+// mode: php
+// c-file-style: "bsd"
+// End:
+
+?>

Added: trunk/plugins/coclico/mailman/include/MailmanListDao.class.php
===================================================================
--- trunk/plugins/coclico/mailman/include/MailmanListDao.class.php	                        (rev 0)
+++ trunk/plugins/coclico/mailman/include/MailmanListDao.class.php	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,163 @@
+<?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/>.
+ * 
+ * Portions Copyright 2010 (c) Mélanie Le Bail
+ */
+
+require_once 'common/dao/include/DataAccessObject.class.php';
+
+/**
+ *  Data Access Object for mailing lists 
+ */
+class MailmanListDao extends DataAccessObject {
+
+	public function __construct($da) {
+		parent::__construct($da);
+	}
+
+	
+	/**
+	 * Search active (=not deteted) mailing lists 
+	 * return all active lists
+	 * @return DataAccessResult
+	 */
+	function & searchAllActiveML() {
+		$sql = "SELECT * 
+			FROM mail_group_list 
+			WHERE is_public IN (0,1)";
+		return $this->retrieve($sql,array());
+	}
+
+	/**
+	 * Searches by group_list_id
+	 * @return DataAccessResult
+	 */
+	function & searchByGroupListId($group_list_id) {
+		$group_list_id = $this->da->quoteSmart($group_list_id);
+		$sql = "SELECT * FROM mail_group_list 
+			WHERE group_list_id = $1";
+		return $this->retrieve($sql,array($group_list_id));
+	}
+	/**
+	 * Searches by list_name
+	 * @return DataAccessResult
+	 */
+	function & searchByName($realListName) {
+		$realListName = $this->da->quoteSmart($realListName);
+		$sql = 'SELECT 1 FROM mail_group_list WHERE lower(list_name)=$1';
+		return $this->retrieve($sql,array($realListName));
+	}
+	/**
+	 * Searches by group_id
+	 * @return DataAccessResult
+	 */
+	function & searchByGroupId($group_id) {
+		$group_id = $this->da->quoteSmart($group_id);
+		$sql = "SELECT * FROM mail_group_list 
+			WHERE group_id = $1";
+		return $this->retrieve($sql,array($group_id));
+	}
+	/**
+	 * Searches data with group_list_id and group_id
+	 * @return DataAccessResult
+	 */
+	function & searchListFromGroup($group_list_id,$group_id) {
+		$group_id = $this->da->quoteSmart($group_id);
+		$group_list_id = $this->da->quoteSmart($group_list_id);
+		$sql = "SELECT * FROM mail_group_list 
+			WHERE group_id = $1 AND group_list_id=$2";
+		return $this->retrieve($sql,array($group_id,$group_list_id));
+	}
+
+	function & insertNewList($group_id, $realListName,$isPublic,$listPassword,$creator_id,$requested,$description) {
+		$group_id = $this->da->quoteSmart($group_id);
+		$group_list_id = $this->da->quoteSmart($group_list_id);
+		$realListName = $this->da->quoteSmart($realListName);
+		$isPublic = $this->da->quoteSmart($isPublic);
+		$creator_id = $this->da->quoteSmart($creator_id);
+		$requested = $this->da->quoteSmart($requested);
+		$description = $this->da->quoteSmart($description);
+		$sql = "INSERT INTO mail_group_list (group_id, list_name, is_public, password, list_admin, status, description) VALUES ($1,$2,$3,$4,$5,$6,$7);";
+		return db_insertid($this->update($sql,array($group_id, $realListName,$isPublic,$listPassword,$creator_id,$requested,$description)),'mail_group_list','group_list_id');
+	}
+	function  deleteList($group_id, $list_id) {
+		return $this->updateList($list_id,$group_id,"deleted",9,1);
+	}
+
+	function  updateList($group_list_id,$group_id, $description, $isPublic,$status) {
+		$group_id = $this->da->quoteSmart($group_id);
+		$group_list_id = $this->da->quoteSmart($group_list_id);
+		$isPublic = $this->da->quoteSmart($isPublic);
+		$status = $this->da->quoteSmart($status);
+		$description = $this->da->quoteSmart($description);
+		$sql = "UPDATE mail_group_list SET is_public=$1, description=$2," .
+			"status=$3 WHERE group_list_id=$4 AND group_id=$5;";
+		return $this->update($sql,array($isPublic,$description,$status,$group_list_id,$group_id));
+
+	}
+
+	function & newSubscriber($usermail, $username, $userpasswd, $listname) {
+		$usermail = $this->da->quoteSmart($usermail);
+		$username = $this->da->quoteSmart($username);
+		$userpasswd = $this->da->quoteSmart($userpasswd);
+		$listname = $this->da->quoteSmart($listname);
+		$sql="INSERT INTO plugin_mailman (address,password,name,listname) VALUES ($1,$2,$3,$4);";
+		return $this->update($sql,array($usermail,$userpasswd,$username,$listname));
+	}
+
+	function & deleteSubscriber($usermail, $listname) {
+		$usermail = $this->da->quoteSmart($usermail);
+		$listname = $this->da->quoteSmart($listname);
+		$sql="DELETE FROM  plugin_mailman WHERE listname=$1 AND address=$2;";
+		return $this->update($sql,array($listname,$usermail));
+	}
+	function & userIsMonitoring($usermail,$listname) {
+		$usermail = $this->da->quoteSmart($usermail);
+		$listname = $this->da->quoteSmart($listname);
+		$sql="SELECT count(*) AS count FROM plugin_mailman WHERE address=$1 AND listname=$2;";
+		return $this->retrieve($sql,array($usermail,$listname));
+	}
+	
+	function & listsMonitoredByUser($usermail) {
+		$usermail = $this->da->quoteSmart($usermail);
+		$sql="SELECT groups.group_name,groups.group_id,mail_group_list.group_list_id,mail_group_list.list_name ".
+		     "FROM groups,mail_group_list,plugin_mailman ".
+		     "WHERE groups.group_id=mail_group_list.group_id AND groups.status ='A' ".
+		     "AND mail_group_list.list_name=plugin_mailman.listname ".
+		     "AND plugin_mailman.address=$1 ORDER BY group_name DESC";
+		
+		return $this->retrieve($sql,array($usermail));
+	}
+
+	function & compareInfos($mail) {
+		$mail = $this->da->quoteSmart($mail);
+		$sql="SELECT password, name FROM  plugin_mailman WHERE address=$1;";
+		return $this->retrieve($sql,array($mail));
+
+	}
+	function & updateInfos($mail,$passwd,$name) {
+		$mail = $this->da->quoteSmart($mail);
+		$passwd = $this->da->quoteSmart($passwd);
+		$name = $this->da->quoteSmart($name);
+		$sql="UPDATE plugin_mailman SET password=$1, name=$2 WHERE address=$3;";
+		return $this->update($sql,array($passwd,$name,$mail));
+
+	}
+}
+?>

Added: trunk/plugins/coclico/mailman/include/MailmanListFactory.class.php
===================================================================
--- trunk/plugins/coclico/mailman/include/MailmanListFactory.class.php	                        (rev 0)
+++ trunk/plugins/coclico/mailman/include/MailmanListFactory.class.php	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,182 @@
+<?php
+/**
+ * GForge Mailing Lists Facility
+ *
+ * Copyright 2003 Guillaume Smet
+ * http://gforge.org/
+ *
+ * @version   $Id$
+ *
+ * This file is part of GForge.
+ *
+ * GForge 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.
+ *
+ * GForge 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 GForge; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+ 
+ /*
+ 
+ This work is based on Tim Perdue's work on the forum stuff
+ 
+ */
+
+
+require_once 'MailmanList.class.php';
+require_once 'MailmanListDao.class.php';
+require_once 'common/dao/CodendiDataAccess.class.php';
+
+class MailmanListFactory extends Error {
+
+	/**
+	 * The Group object.
+	 *
+	 * @var	 object  $Group.
+	 */
+	var $Group;
+
+	/**
+	 * The mailing lists array.
+	 *
+	 * @var	 array	$mailingLists.
+	 */
+	var $mailingLists;
+	/**
+	 * DAO 
+	 *
+	 * @var	 MailingListDao   $mailingDAO.
+	 */
+	var $_mailingDAO;
+
+
+	/**
+	 *  Constructor.
+	 *
+	 *	@param	object	The Group object to which these mailing lists are associated.
+	 */
+	function MailmanListFactory(& $Group) {
+		$this->_mailingDAO =& new MailmanListDao(CodendiDataAccess::instance());	
+		$this->Error();
+		
+		if (!$Group || !is_object($Group)) {
+			$this->setError(sprintf(_('%1$s:: No Valid Group Object'), 'MailmanListFactory'));
+			return false;
+		}
+		if ($Group->isError()) {
+			$this->setError('MailmanListFactory:: '.$Group->getErrorMessage());
+			return false;
+		}
+		$this->Group =& $Group;
+
+		return true;
+	}
+
+	/**
+	 *	getGroup - get the Group object this MailmanListFactory is associated with.
+	 *
+	 *	@return object	The Group object.
+	 */
+	function &getGroup() {
+		return $this->Group;
+	}
+
+	/**
+	 *	getMailmanLists - get an array of MailmanList objects for this Group.
+	 *
+	 * @param boolean $admin if we are in admin mode (we want to see deleted lists)
+	 *	@return	array	The array of MailmanList objects.
+	 */
+	function &getMailmanLists() {
+		$current_user=UserManager::instance()->getCurrentUser();
+		if (isset($this->mailingLists) && is_array($this->mailingLists)) {
+			return $this->mailingLists;
+		}
+		
+		if (islogged() && $current_user->isMember($this->Group->getID())) {
+			$public_flag='0,1';
+		} else {
+			$public_flag='1';
+		}
+		$result =& $this->_mailingDAO->searchByGroupId($this->Group->getID());
+	
+		
+		if (!$result) {
+			$this->setError(sprintf(_('Error Getting %1$s'), _('Error Getting %1$s')).db_error());
+			return false;
+		} else {
+			$this->mailingLists = array();
+			while ($arr =& $result->getRow()) {
+				$this->mailingLists[] = new MailmanList($this->Group->getID(), $arr['group_list_id'], $arr);
+			}
+		}
+		return $this->mailingLists;
+	}
+
+	/**
+	 * compareInfos - replace mailman user info by forge user info
+	 *
+	 * @return string url of the info page
+	 */
+	function compareInfos()
+	{
+		$current_user=UserManager::instance()->getCurrentUser();
+		$mail=$current_user->getEmail();
+		
+		$passwd= $current_user->getUserPw();
+		$name= $current_user->getRealName();
+		$result =& $this->_mailingDAO->compareInfos($mail);
+		if (!$result) {
+			return false;
+		}
+		else 
+		{
+			while( $arr =& $result->getRow())
+			{
+				if($arr['password']!=$passwd || $arr['name']!=$name)
+				{
+					return true;
+				}
+			}
+		}
+		return false;
+
+	}
+	/**
+	 * updateInfos - replace mailman user info by forge user info
+	 *
+	 * @return string url of the info page
+	 */
+	function updateInfos()
+	{
+		$current_user=UserManager::instance()->getCurrentUser();
+		$mail=$current_user->getEmail();
+		
+		$passwd= $current_user->getUserPw();
+		$name= $current_user->getRealName();
+		
+		$result =& $this->_mailingDAO->updateInfos($mail,$passwd,$name);
+		if (!$result) {
+			return false;
+		}
+		htmlRedirect('index.php?group_id='.$this->Group->getId());
+		return $result;	
+	}
+
+
+}
+
+// Local Variables:
+// mode: php
+// c-file-style: "bsd"
+// End:
+
+?>

Added: trunk/plugins/coclico/mailman/include/MailmanPluginDescriptor.class.php
===================================================================
--- trunk/plugins/coclico/mailman/include/MailmanPluginDescriptor.class.php	                        (rev 0)
+++ trunk/plugins/coclico/mailman/include/MailmanPluginDescriptor.class.php	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,32 @@
+<?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/>.
+ * 
+ * Portions Copyright 2010 (c) Mélanie Le Bail
+ */
+
+require_once('common/plugin/PluginDescriptor.class.php');
+
+
+class MailmanPluginDescriptor extends PluginDescriptor {
+    
+    function MailmanPluginDescriptor() {
+        $this->PluginDescriptor(_('Mailman'), 'v1.0', _('Offers a better integration of Mailman in the forge'));
+    }
+}
+?>

Added: trunk/plugins/coclico/mailman/include/MailmanPluginInfo.class.php
===================================================================
--- trunk/plugins/coclico/mailman/include/MailmanPluginInfo.class.php	                        (rev 0)
+++ trunk/plugins/coclico/mailman/include/MailmanPluginInfo.class.php	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,33 @@
+<?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/>.
+ * 
+ * Portions Copyright 2010 (c) Mélanie Le Bail
+ */
+require_once('common/plugin/PluginInfo.class.php');
+require_once('MailmanPluginDescriptor.class.php');
+
+class MailmanPluginInfo extends PluginInfo {
+    
+    function MailmanPluginInfo(&$plugin) {
+        $this->PluginInfo($plugin);
+        $this->setPluginDescriptor(new MailmanPluginDescriptor());
+    }
+    
+}
+?>

Added: trunk/plugins/coclico/mailman/include/MailsForUser.class.php
===================================================================
--- trunk/plugins/coclico/mailman/include/MailsForUser.class.php	                        (rev 0)
+++ trunk/plugins/coclico/mailman/include/MailsForUser.class.php	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,87 @@
+<?php
+/**
+ * GForge Mails Facility
+ *
+ * Copyright 2002 GForge, LLC
+ * http://gforge.org/
+ *
+ * @version   $Id$
+ *
+ * This file is part of GForge.
+ *
+ * GForge 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.
+ *
+ * GForge 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 GForge; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+require_once 'MailmanList.class.php';
+
+class MailsForUser extends Error {
+
+	/**
+	 * The User object.
+	 *
+	 * @var	 object  $User.
+	 */
+	var $User;
+
+	/**
+	 *  Constructor.
+	 *
+	 *	@param	object	The Group object to which this  list associated.
+	 */
+	function MailsForUser(&$user) {
+		$this->User =& $user;
+
+		return true;
+	}
+
+
+	/**
+	*       getMonitoredForums
+	*
+	*       @return Forum[] The array of Forums
+	*
+	*/
+	function getMonitoredMails() {
+		$lists = array();
+		$sql="SELECT groups.group_name,groups.group_id,mail_group_list.group_list_id,mail_group_list.list_name ".
+		     "FROM groups,mail_group_list,mailman_sql ".
+		     "WHERE groups.group_id=mail_group_list.group_id AND groups.status ='A' ".
+		     "AND mail_group_list.list_name=mailman_sql.listname ".
+		     "AND mailman_sql.address='".$this->User->getEmail()."' ORDER BY group_name DESC";
+
+		$result=db_query($sql);
+		$rows=db_numrows($result);
+		if ($rows < 1) {
+		        return $lists;
+		}
+		$last_group='';
+		for ($i=0; $i<$rows; $i++) {
+			$group_id = db_result($result,$i,'group_id');
+			$list_id = db_result($result,$i,'group_list_id');
+			$group =& group_get_object($group_id);
+			$list =& new MailmanList($group,$list_id);
+			if ($list->isError()) {
+				$this->setError($list->getErrorMessage());
+			} else {
+				$lists[] =& $list;
+			}
+		}
+		return $lists;
+	}
+
+}
+
+?>

Added: trunk/plugins/coclico/mailman/include/events/SystemEvent_MAILMAN_LIST_CREATE.class.php
===================================================================
--- trunk/plugins/coclico/mailman/include/events/SystemEvent_MAILMAN_LIST_CREATE.class.php	                        (rev 0)
+++ trunk/plugins/coclico/mailman/include/events/SystemEvent_MAILMAN_LIST_CREATE.class.php	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,69 @@
+<?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/>.
+ *
+ * Portions Copyright 2010 (c) Mélanie Le Bail
+ */
+require_once 'mailman/include/BackendMailmanList.class.php';
+/**
+* System Event classes
+*
+*/
+class SystemEvent_MAILMAN_LIST_CREATE extends SystemEvent {
+    
+    /**
+     * Verbalize the parameters so they are readable and much user friendly in 
+     * notifications
+     * 
+     * @param bool $with_link true if you want links to entities. The returned 
+     * string will be html instead of plain/text
+     *
+     * @return string
+     */
+    public function verbalizeParameters($with_link) {
+        $txt = '';
+        $txt .= 'mailing list: #'. $this->getIdFromParam($this->parameters);
+        return $txt;
+    }
+
+    /** 
+     * Process stored event
+     */
+    function process() {
+        // Check parameters
+        $group_list_id=$this->getIdFromParam($this->parameters);
+
+        if ($group_list_id == 0) {
+            return $this->setErrorBadParam();
+        }
+
+        if (!BackendMailmanList::instance()->createList($group_list_id)) {
+            $this->error("Could not create mailing list $group_list_id");
+            return false;
+        }
+            
+        // Need to add list aliases
+        Backend::instance('Aliases')->setNeedUpdateMailAliases();
+
+        $this->done();
+        return true;
+    }
+
+}
+
+?>

Added: trunk/plugins/coclico/mailman/include/events/SystemEvent_MAILMAN_LIST_DELETE.class.php
===================================================================
--- trunk/plugins/coclico/mailman/include/events/SystemEvent_MAILMAN_LIST_DELETE.class.php	                        (rev 0)
+++ trunk/plugins/coclico/mailman/include/events/SystemEvent_MAILMAN_LIST_DELETE.class.php	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,70 @@
+<?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/>.
+ *
+ * Portions Copyright 2010 (c) Mélanie Le Bail
+ */
+require_once 'mailman/include/BackendMailmanList.class.php';
+
+/**
+* System Event classes
+*
+*/
+class SystemEvent_MAILMAN_LIST_DELETE extends SystemEvent {
+    
+    /**
+     * Verbalize the parameters so they are readable and much user friendly in 
+     * notifications
+     * 
+     * @param bool $with_link true if you want links to entities. The returned 
+     * string will be html instead of plain/text
+     *
+     * @return string
+     */
+    public function verbalizeParameters($with_link) {
+        $txt = '';
+        $txt .= 'mailing list: #'. $this->getIdFromParam($this->parameters);
+        return $txt;
+    }
+    
+    /** 
+     * Process stored event
+     */
+    function process() {
+        // Check parameters
+        $group_list_id=$this->getIdFromParam($this->parameters);
+
+        if ($group_list_id == 0) {
+            return $this->setErrorBadParam();
+        }
+
+        if (!BackendMailmanList::instance()->deleteList($group_list_id)) {
+            $this->error("Could not delete mailing list $group_list_id");
+            return false;
+        }
+            
+        // Need to add list aliases
+        Backend::instance('Aliases')->setNeedUpdateMailAliases();
+            
+        $this->done();
+        return true;
+    }
+
+}
+
+?>

Added: trunk/plugins/coclico/mailman/include/mailman-init.php
===================================================================
--- trunk/plugins/coclico/mailman/include/mailman-init.php	                        (rev 0)
+++ trunk/plugins/coclico/mailman/include/mailman-init.php	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,34 @@
+<?php
+
+/**
+ *
+ * This file is part of GForge.
+ *
+ * GForge 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.
+ *
+ * GForge 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 GForge; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+global $gfplugins;
+require_once $gfplugins.'mailman/include/mailmanPlugin.class.php' ;
+
+$mailmanPluginObject = new mailmanPlugin ;
+
+register_plugin ($mailmanPluginObject) ;
+
+// Local Variables:
+// mode: php
+// c-file-style: "bsd"
+// End:
+
+?>

Added: trunk/plugins/coclico/mailman/include/mailmanPlugin.class.php
===================================================================
--- trunk/plugins/coclico/mailman/include/mailmanPlugin.class.php	                        (rev 0)
+++ trunk/plugins/coclico/mailman/include/mailmanPlugin.class.php	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,285 @@
+<?php
+
+/**
+ * mailmanPlugin class 
+ *
+ * This file is part of FusionForge.
+ *
+ * FusionForge 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.
+ *
+ * FusionForge 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 GForge; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ * 
+ * Portions Copyright (c) Xerox Corporation, Codendi Team, 2001-2009. All rights reserved
+ * Portions Copyright 2010 (c) Mélanie Le Bail
+ */
+ 
+require_once 'plugins_utils.php';
+require_once('common/system_event/SystemEvent.class.php');
+require_once('common/event/Event.class.php');
+require_once 'MailmanList.class.php';
+require_once 'MailmanListFactory.class.php';
+require_once 'MailmanListDao.class.php';
+require_once 'common/dao/CodendiDataAccess.class.php';
+
+
+
+class mailmanPlugin extends Plugin {
+	public function __construct($id=0) {
+		$this->Plugin($id);
+		//$this->setScope(Plugin::SCOPE_PROJECT);
+		$this->name = "mailman" ;
+		$this->text = "Mailman" ; // To show in the tabs, use...
+		$this->_addHook("user_personal_links");//to make a link to the user�s personal part of the plugin
+		$this->_addHook("usermenu") ;
+		$this->_addHook("groupmenu");	// To put into the project tabs
+		$this->_addHook("groupisactivecheckbox") ; // The "use ..." checkbox in editgroupinfo
+		$this->_addHook("groupisactivecheckboxpost") ; //
+		$this->_addHook("userisactivecheckbox") ; // The "use ..." checkbox in user account
+		$this->_addHook("userisactivecheckboxpost") ; //
+		$this->_addHook("project_admin_plugins"); // to show up in the admin page fro group
+		$this->_addHook("monitored_element"); // to show monitored items in my page
+		$this->_addHook("group_delete"); // to delete mailing list associated when deleting a group
+		$this->_addHook("group_approve"); // to create mailing list 'Commit' when creating a group
+		$this->_addHook('site_admin_option_hook');
+		$this->_addHook(Event::GET_SYSTEM_EVENT_CLASS,'getSystemEventClass', false);//to make SystemEvent manager knows about mailman plugin
+		
+	}
+	
+	function process() {
+		echo '<h1>Mailman</h1>';
+		echo $this->getPluginInfo()->getpropVal('answer');
+	}
+	
+	function getPluginInfo() {
+		if (!is_a($this->pluginInfo, 'MailmanPluginInfo')) {
+			require_once('MailmanPluginInfo.class.php');
+			$this->pluginInfo =& new MailmanPluginInfo($this);
+		}
+		return $this->pluginInfo;
+	}
+	
+	function CallHook ($hookname, $params) {
+		global $use_mailmanplugin,$G_SESSION,$HTML,$gfcommon,$gfwww,$gfplugins;
+		if ($hookname == "usermenu") {
+			$text = $this->text; // this is what shows in the tab
+			if ($G_SESSION->usesPlugin("mailman")) {
+				$param = '?type=user&id=' . $G_SESSION->getId() . "&pluginname=" . $this->name; // we indicate the part we�re calling is the user one
+				echo ' | ' . $HTML->PrintSubMenu (array ($text),
+					array ('/plugins/mailman/index.php' . $param ));				
+			}
+		} elseif ($hookname == "groupmenu") {
+			$group_id=$params['group'];
+			$project = &group_get_object($group_id);
+			if (!$project || !is_object($project)) {
+				return;
+			}
+			if ($project->isError()) {
+				return;
+			}
+			if (!$project->isProject()) {
+				return;
+			}
+			if ( $project->usesPlugin ( $this->name ) ) {
+				$params['TITLES'][]=$this->text;
+				$params['DIRS'][]='/plugins/mailman/index.php?group_id=' . $group_id . "&pluginname=" . $this->name; // we indicate the part we�re calling is the project one
+			} 
+			(($params['toptab'] == $this->name) ? $params['selected']=(count($params['TITLES'])-1) : '' );
+		} elseif ($hookname == "groupisactivecheckbox") {
+			//Check if the group is active
+			// this code creates the checkbox in the project edit public info page to activate/deactivate the plugin
+			$group_id=$params['group'];
+			$group = &group_get_object($group_id);
+			echo "<tr>";
+			echo "<td>";
+			echo ' <input type="CHECKBOX" name="use_mailmanplugin" value="1" ';
+			// CHECKED OR UNCHECKED?
+			if ( $group->usesPlugin ( $this->name ) ) {
+				echo "CHECKED";
+			}
+			echo "><br/>";
+			echo "</td>";
+			echo "<td>";
+			echo "<strong>Use ".$this->text." Plugin</strong>";
+			echo "</td>";
+			echo "</tr>";
+			
+		} elseif ($hookname == "groupisactivecheckboxpost") {
+			// this code actually activates/deactivates the plugin after the form was submitted in the project edit public info page
+			$group_id=$params['group'];
+			$group = &group_get_object($group_id);
+			$use_mailmanplugin = getStringFromRequest('use_mailmanplugin');
+			if ( $use_mailmanplugin == 1 ) {
+				$group->setPluginUse ( $this->name );
+			} else {
+				$group->setPluginUse ( $this->name, false );
+			}
+		} elseif ($hookname == "userisactivecheckbox") {
+			//check if user is active
+			// this code creates the checkbox in the user account manteinance page to activate/deactivate the plugin
+			$user = $params['user'];
+			echo "<tr>";
+			echo "<td>";
+			echo ' <input type="CHECKBOX" name="use_mailmanplugin" value="1" ';
+			// CHECKED OR UNCHECKED?
+			if ( $user->usesPlugin ( $this->name ) ) {
+				echo "CHECKED";
+			}
+			echo ">    Use ".$this->text." Plugin";
+			echo "</td>";
+			echo "</tr>";
+		} elseif ($hookname == "userisactivecheckboxpost") {
+			// this code actually activates/deactivates the plugin after the form was submitted in the user account manteinance page
+			$user = $params['user'];
+			$use_mailmanplugin = getStringFromRequest('use_mailmanplugin');
+			if ( $use_mailmanplugin == 1 ) {
+				$user->setPluginUse ( $this->name );
+			} else {
+				$user->setPluginUse ( $this->name, false );
+			}
+			echo "<tr>";
+			echo "<td>";
+			echo ' <input type="CHECKBOX" name="use_mailmanplugin" value="1" ';
+			// CHECKED OR UNCHECKED?
+			if ( $user->usesPlugin ( $this->name ) ) {
+				echo "CHECKED";
+			}
+			echo ">    Use ".$this->text." Plugin";
+			echo "</td>";
+			echo "</tr>";
+		} elseif ($hookname == "user_personal_links") {
+			// this displays the link in the user�s profile page to it�s personal mailman (if you want other sto access it, youll have to change the permissions in the index.php
+			$userid = $params['user_id'];
+			$user = user_get_object($userid);
+			$text = $params['text'];
+			//check if the user has the plugin activated
+			if ($user->usesPlugin($this->name)) {
+				echo '	<p>' ;
+				echo util_make_link ("/plugins/mailman/index.php?id=$userid&type=user&pluginname=".$this->name,
+									 _('View Personal mailman')
+				);
+				echo '</p>';
+			}
+		} elseif ($hookname == "project_admin_plugins") {
+			// this displays the link in the project admin options page to it�s  mailman administration
+			$group_id = $params['group_id'];
+			$group = &group_get_object($group_id);
+			if ( $group->usesPlugin ( $this->name ) ) {
+				echo util_make_link ("/plugins/projects_hierarchy/index.php?id=".$group->getID().'&type=admin&pluginname='.$this->name,
+									 _('View the mailman Administration')) ;
+				echo '</p>';
+			}
+		}												    
+		elseif ($hookname == "monitored_element") {
+			$current_user=UserManager::instance()->getCurrentUser();
+			$last_group=0;
+			$order_name_arr=array();
+			$order_name_arr[]=_('Remove');
+			$order_name_arr[]=_('Monitored Lists');
+			echo $HTML->listTableTop($order_name_arr);
+			$dao = & new MailmanListDao(CodendiDataAccess::instance());	
+			$result = $dao->listsMonitoredByUser($current_user->getEmail());
+			for ($i=0; $i<$result->rowCount(); $i++) {
+				$listResult = $result->getRow();
+				$list =& new MailmanList($listResult['group_id'],$listResult['group_list_id']);
+				if ($list->isError()) {
+						$this->setError($list->getErrorMessage());
+				} else {
+						$lists[] =& $list;
+				}
+			}
+			if (count($lists) < 1) {
+				echo '<tr><td colspan="2"><strong>'._('You are not monitoring any lists.').'</strong></td></tr>';
+			} else {
+				echo '<tr><td colspan="2"><strong>'.util_make_link ('/plugins/mailman',_('My Monitored Lists')).'</strong></td></tr>';
+				foreach ($lists as $l) {
+					$group = $l->getGroup();
+					if ($group->getID() != $last_group) {
+						echo ' <tr '. $HTML->boxGetAltRowStyle(1) .'><td colspan="2">'.util_make_link ('/plugins/mailman/index.php?group_id='.$group->getID(),$group->getPublicName()).'</td></tr>';
+					}
+					echo '
+						<tr '.$HTML->boxGetAltRowStyle(0).'><td class="align-center"><a href="/plugins/mailman/index.php?group_id='.$group->getID().
+						'&action=unsubscribe&id='.$l->getID().'">' .
+						'<img src="'.$HTML->imgroot.'/ic/trash.png" height="16" width="16" '.'border="0" alt="" /></a>' .
+						'</td><td width="99%"><a href="/plugins/mailman/index.php?group_id='.$group->getID().'&action=options&id='.$l->getID().'">'.
+						$l->getName().'"</a></td></tr>';
+					$last_group= $group->getID();
+				}
+			}
+			echo $HTML->listTableBottom();
+	
+		}
+		elseif ($hookname == "group_delete") {
+			$group_id = $params['group_id'];
+			$group = &group_get_object($group_id);
+			$mlf = new MailmanListFactory($group);
+			$ml_arr =& $mlf->getMailmanLists();
+			for ($i=0; $i<count($ml_arr); $i++) {
+				if (!is_object($ml_arr[$i])) {
+					printf (_("Not Object: MailmanList: %d"),$i);
+					continue;
+				}
+				if (!$ml_arr[$i]->deleteList(1,1)) {
+					$this->setError(_('Could not properly delete the mailing list'));
+				}
+				//echo 'MailmanListFactory'.db_error();
+			}	
+		}  
+		elseif ($hookname == "group_approve") {
+			$idadmin_group =$params[0];
+			$group_id=$params[1];
+			$group = &group_get_object($group_id);
+			$mlist = new MailmanList($group);
+			if (!$mlist->create('commits','Commits',1,$idadmin_group)) {
+				$this->setError(sprintf(_('ML: %s'),$mlist->getErrorMessage()));
+				db_rollback();
+				return false;
+			}
+		}
+		elseif ($hookname=='site_admin_option_hook') {
+			echo '<li><a href="'.$this->getPluginPath().'/">Template</a></li>';
+		}
+		
+		
+		
+	}
+	function getSystemEventClass($params) {
+		
+		switch($params['type']) {
+			case 'MAILMAN_LIST_CREATE' :
+				
+				require_once(dirname(__FILE__).'/events/SystemEvent_MAILMAN_LIST_CREATE.class.php');
+				
+				$params['class'] = 'SystemEvent_MAILMAN_LIST_CREATE';
+				break;
+			case 'MAILMAN_LIST_DELETE' :
+				require_once(dirname(__FILE__).'/events/SystemEvent_MAILMAN_LIST_DELETE.class.php');
+				$params['class'] = 'SystemEvent_MAILMAN_LIST_DELETE';
+				break;
+			default:
+				break;
+		}
+
+	}
+	
+	
+	
+	
+	
+}
+
+// Local Variables:
+// mode: php
+// c-file-style: "bsd"
+// End:
+
+?>

Added: trunk/plugins/coclico/mailman/packaging/control/000source
===================================================================
--- trunk/plugins/coclico/mailman/packaging/control/000source	                        (rev 0)
+++ trunk/plugins/coclico/mailman/packaging/control/000source	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,10 @@
+Source: @SRCPACKAGE@
+Section: devel
+Priority: optional
+Maintainer: Christian Bayle <bayle at debian.org>
+Uploaders: Roland Mas <lolando at debian.org>
+Build-Depends-Indep: devscripts
+Build-Depends: debhelper (>= 7), perl, gettext
+Standards-Version: 3.8.4
+Homepage: http://fusionforge.org/
+Vcs-Bzr: http://scm.fusionforge.org/bzr/fusionforge/svn-trunk-ro/

Added: trunk/plugins/coclico/mailman/packaging/control/222plugin-mailman
===================================================================
--- trunk/plugins/coclico/mailman/packaging/control/222plugin-mailman	                        (rev 0)
+++ trunk/plugins/coclico/mailman/packaging/control/222plugin-mailman	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,4 @@
+Package: @SRCPACKAGE@
+Architecture: all
+Depends: @OLDPACKAGE at -common, @OLDPACKAGE at -db-postgresql | @OLDPACKAGE at -db, @OLDPACKAGE at -web-apache2 | @OLDPACKAGE at -web, @OLDPACKAGE at -shell-postgresql | @OLDPACKAGE at -shell, php5-cli, ${misc:Depends}
+Description: collaborative development tool - Helloworld plugin

Added: trunk/plugins/coclico/mailman/packaging/control/222plugin-mailman.shortdesc
===================================================================
--- trunk/plugins/coclico/mailman/packaging/control/222plugin-mailman.shortdesc	                        (rev 0)
+++ trunk/plugins/coclico/mailman/packaging/control/222plugin-mailman.shortdesc	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,3 @@
+ This plugin contains the Helloworld subsystem of FusionForge. It allows each
+ FusionForge project to have its own Helloworld, and gives some
+ control over it to the project's administrator.

Added: trunk/plugins/coclico/mailman/packaging/cron.d/plugin-mailman
===================================================================
--- trunk/plugins/coclico/mailman/packaging/cron.d/plugin-mailman	                        (rev 0)
+++ trunk/plugins/coclico/mailman/packaging/cron.d/plugin-mailman	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,16 @@
+FFCRON="/usr/share/gforge/cronjobs"
+FFUSER=gforge
+
+# You may need to change the pathname to php CLI (command line interface)
+PHP="/usr/bin/php -q -d include_path=.:/etc/gforge:/usr/share/gforge:/usr/share/gforge/www/include:/usr/share/gforge/plugins"
+
+# Don't mail command output to anyone.
+MAILTO=""
+
+#
+# Regular cron jobs for the lists-mailman package
+#
+
+# Mailman-list creation
+* * * * * root $PHP $FFCRON/manage_mailmanlists.php 
+

Added: trunk/plugins/coclico/mailman/packaging/dirs/plugin-mailman
===================================================================
--- trunk/plugins/coclico/mailman/packaging/dirs/plugin-mailman	                        (rev 0)
+++ trunk/plugins/coclico/mailman/packaging/dirs/plugin-mailman	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,5 @@
+etc/gforge/httpd.d
+etc/gforge/plugins/mailman
+usr/share/gforge/plugins/mailman/cgi-bin
+usr/share/gforge/plugins/mailman/common
+usr/share/gforge/plugins/mailman/www

Added: trunk/plugins/coclico/mailman/packaging/docs/plugin-mailman
===================================================================
--- trunk/plugins/coclico/mailman/packaging/docs/plugin-mailman	                        (rev 0)
+++ trunk/plugins/coclico/mailman/packaging/docs/plugin-mailman	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1 @@
+debian/README.Debian

Added: trunk/plugins/coclico/mailman/packaging/install/plugin-mailman
===================================================================
--- trunk/plugins/coclico/mailman/packaging/install/plugin-mailman	                        (rev 0)
+++ trunk/plugins/coclico/mailman/packaging/install/plugin-mailman	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,6 @@
+common/*                  usr/share/gforge/plugins/mailman/common/
+www/*                     usr/share/gforge/plugins/mailman/www/
+cronjobs/*                usr/share/gforge/cronjobs
+etc/plugins/mailman/*     etc/gforge/plugins/mailman/
+usr/lib/mailman/Mailman/* usr/lib/mailman/Mailman/
+var/lib/mailman/lists/*   var/lib/mailman/lists/

Added: trunk/plugins/coclico/mailman/packaging/links/plugin-mailman
===================================================================
--- trunk/plugins/coclico/mailman/packaging/links/plugin-mailman	                        (rev 0)
+++ trunk/plugins/coclico/mailman/packaging/links/plugin-mailman	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1 @@
+/usr/share/gforge/plugins/mailman/www /usr/share/gforge/www/plugins/mailman

Added: trunk/plugins/coclico/mailman/usr/lib/mailman/Mailman/ExternalConnector.py
===================================================================
--- trunk/plugins/coclico/mailman/usr/lib/mailman/Mailman/ExternalConnector.py	                        (rev 0)
+++ trunk/plugins/coclico/mailman/usr/lib/mailman/Mailman/ExternalConnector.py	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,649 @@
+# Copyright (C) 1998-2008 by the Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program 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 this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+# USA.
+
+
+import os
+import sys
+import re
+import time
+from types import StringType, TupleType
+
+from Errors import *
+from Mailman import Errors
+from Mailman import MemberAdaptor
+from Mailman import mm_cfg
+from Mailman import Utils
+from Mailman.Logging.Syslog import syslog
+from Mailman.Bouncer import _BounceInfo
+try:
+     from Mailman.Utils import md5_new
+except ImportError:
+     import md5
+     md5_new=md5.new
+ISREGULAR = 1
+ISDIGEST = 2
+tm_min = 4
+
+mm_cfg.connection = 0
+mm_cfg.cursor = 0
+
+try:
+    mm_cfg.MYSQL_MEMBER_CREATE_TABLE    
+    mm_cfg.MYSQL_MEMBER_DB_VERBOSE
+except AttributeError:
+    mm_cfg.MYSQL_MEMBER_DB_VERBOSE = False  # default value
+    mm_cfg.MYSQL_MEMBER_CREATE_TABLE = True
+    pass
+
+class ExternalConnector(MemberAdaptor.MemberAdaptor):
+	def __init__(self,mlist,param):
+		self._param=param
+		self.__mlist=mlist
+		self._members=None
+		self._member_passwd={}
+		self._member_names={}
+		self._updatetime = 0
+		# define the table and standard condition reflecting listname
+               	self._table = param['mailman_table'] 
+            	self._where = "listname = '%s'" %(self.__mlist.internal_name())
+
+		#define query for session management
+		self._cookiename=param['cookiename']	
+		self._queryCookieMail=param['queryCookieMail']
+		self._queryCookieId=param['queryCookieId']
+		self._queryIsAdmin=param['queryIsAdmin']
+		self._queryIsSiteAdmin=param['queryIsSiteAdmin']
+		self._queryIsMonitoring=param['queryIsMonitoring']
+		
+		self.__db_connect__()
+        	if mm_cfg.MYSQL_MEMBER_DB_VERBOSE:
+            	# Message to indicate successful init.
+            		message = "DBMemberships " \
+                		+ "$Revision: 1.69 $ initialized with host: %s (%s)" % (
+                		mm_cfg.connection.get_host_info(),
+                		mm_cfg.connection.get_server_info() )
+            		syslog('error', message)
+            		syslog('mysql', message)
+
+        	# add a cache memory
+        	self._cache = {}
+        	self._cachedate = 0
+
+	def __db_connect__(self):
+		return mm_cfg.cursor
+	def __del__(self):
+        # Cleaning up
+        	try:
+            		mm_cfg.cursor.close()
+       		except:
+            		pass
+        	try:
+            		mm_cfg.connection.close()
+        	except:
+            		pass
+        	if mm_cfg.MYSQL_MEMBER_DB_VERBOSE:
+            	# Message to indicate successful close.
+            		syslog("error", "MysqlMemberships $Revision: 1.69 $ unloaded" )
+            		syslog("mysql", "MysqlMemberships $Revision: 1.69 $ unloaded" )
+
+	
+
+	# empty the cache (when we touch a value)
+    	def uncache(self):
+        	self._cache = {}
+        	self._cachedate = time.localtime()[tm_min]
+
+    	# Apply query on list (manages both 'flat' and 'wide' modes)
+    	def query(self, query):
+        	if mm_cfg.MYSQL_MEMBER_DB_VERBOSE:
+            		syslog('mysql', query)
+        	mm_cfg.cursor.execute(query)
+		mm_cfg.connection.commit()
+		return
+
+	 # return all members according to a certain condition
+    	def queryall(self, query, cache=False):
+        	self.query(query)
+        	# get the number of rows in the resultset
+        	numrows = int(mm_cfg.cursor.rowcount)
+        	# save one at a time
+        	results = []
+        	for x in range(0,numrows):
+            		row = mm_cfg.cursor.fetchone()
+            		results.append(row[0])
+            		# we don't want to cache the whole list for global requests
+            		if cache and numrows < 1000:
+                		self._cache[row[1]] = row[2:]
+        	return results
+
+    	# select *, cache it, then return only the field that's asked for
+    	def select(self, what, where=''):
+        	query = "SELECT " + what \
+            		+ ",address,name,user_options,delivery_status,lang,digest " \
+            		+ "FROM %s WHERE %s" %(self._table, self._where)
+        	if where:
+            		query += " AND %s" %(where)
+        	return self.queryall(query + ' ORDER BY address', True)
+
+        def select_on(self, what, address):
+            if self._cachedate != time.localtime()[tm_min]:
+                self.uncache()
+            try:
+                a = self._cache[address]
+                if what == 'name':
+                    num = 0
+                elif what == 'user_options':
+                    num = 1
+                elif what == 'delivery_status':
+                    num = 2
+                elif what == 'lang':
+                    num = 3
+                elif what == 'digest':
+                    num = 4
+                a = [ a[num] ]
+            except:
+                a = self.select(what,
+                    "address='%s'" %(self.escape(address)))
+            return a
+
+        def update_on(self, what, value, address):
+            if what == 'delivery_status':
+                dst = ", delivery_status_timestamp=NOW() "
+            else:
+                dst = ""
+            self.query("UPDATE %s " %(self._table)
+                    + ("SET %s = '%s' " %(what, self.escape(value))
+                    + dst
+                    + ("WHERE %s " %(self._where))
+                    + ("AND address = '%s'" %(self.escape(address)))))
+            # remove the cache
+            self.uncache()
+    
+        def escape(self, value):
+            # transforms accents into html entities (&#233;)
+            # TODO: find out which language is current (here: assumes iso-8859-1)
+            value = Utils.uncanonstr(value)
+    
+            return value
+	def db_cookie_to_mail(self,c):
+		if cookiname and c.has_key(self._cookiename):
+			hash=c[self._cookiename]
+			query = self._queryCookieMail %hash
+			mm_cfg.cursor.execute(query)
+			attrs = mm_cfg.cursor.fetchone()
+			if attrs!= None :
+				usernames = attrs[0]
+				return usernames
+		return False
+
+	def db_cookie_to_id(self,c):
+		if self._cookiename and c.has_key(self._cookiename):
+			users=[]
+			hash=c[self._cookiename]
+			query=self._queryCookieId % hash
+			mm_cfg.cursor.execute(query)
+			attrs = mm_cfg.cursor.fetchone()
+			if attrs!= None :
+				users = attrs[0]
+				return users
+		return False
+
+	def db_id_to_monitored(self,user_id):
+		query=self._queryIsMonitoring %(str(user_id),self.__mlist.internal_name())
+		mm_cfg.cursor.execute(query)
+		result = mm_cfg.cursor.fetchone()
+		if result[0] == 0:
+			return False
+		if result[0] >= 1:
+			return True
+	
+	def db_isAdmin(self,user_id):
+		query = self._queryIsAdmin  %(str(user_id),self.__mlist.internal_name())
+		mm_cfg.cursor.execute(query)
+		result = mm_cfg.cursor.fetchone()
+		if result[0] == 0:
+			return False
+		if result[0] >= 1:
+			return True
+	def db_isSiteAdmin(self,user_id):
+		query = self._queryIsSiteAdmin  %(str(user_id))
+		mm_cfg.cursor.execute(query)
+		result = mm_cfg.cursor.fetchone()
+		if result[0] == 0:
+			return False
+		if result[0] >= 1:
+			return True
+
+    ############################### Now the active codes #######
+        #
+        # Read interface
+        #
+    
+        # All members
+        def getMembers(self):
+            return self.select('address')
+    
+        # regular members
+        def getRegularMemberKeys(self):
+            return self.select('address', "digest = 'N'")
+    
+        # digest members
+        def getDigestMemberKeys(self):
+            return self.select('address', "digest = 'Y'")
+    
+        # status (regular/digest) of a member (returns a key - lowercase)
+        def __get_cp_member(self, member):
+            lcmember = member.lower()
+            digest = self.select_on('digest', lcmember)
+            if len(digest):
+                if digest is 'Y':
+                    return lcmember, ISDIGEST
+                else:
+                    return lcmember, ISREGULAR
+            return None, None
+    
+        # is she a member?
+        def isMember(self, member):
+            member = self.select_on('name', member)
+            if len(member):
+                return 1
+            return 0
+    
+        # Covered by SQL __get_cp_member()
+        def getMemberKey(self, member):
+            cpaddr, where = self.__get_cp_member(member)
+            if cpaddr is None:
+                raise Errors.NotAMemberError, member
+            return member.lower()
+    
+        # Covered by SQL __get_cp_member()
+        def getMemberCPAddress(self, member):
+            cpaddr, where = self.__get_cp_member(member)
+            if cpaddr is None:
+                raise Errors.NotAMemberError, member
+            return cpaddr
+    
+        # Covered by SQL __get_cp_member()
+        def getMemberCPAddresses(self, members):
+            return [self.__get_cp_member(member)[0] for member in members]
+    
+        # SELECT password FROM <listname> WHERE address = member.lower()
+        def getMemberPassword(self, member):
+            password = self.select_on('password', member)
+            if len(password):
+                return password[0]
+            else:
+                raise Errors.NotAMemberError, member
+    
+        # Covered by SQL getMemberPassword()
+        def authenticateMember(self, member, response):
+            secret = self.getMemberPassword(member)
+            if secret == md5_new(response).hexdigest():
+                return secret
+            return 0
+    
+        # Covered by SQL isMember()
+        def __assertIsMember(self, member):
+            if not self.isMember(member):
+                raise Errors.NotAMemberError, member
+    
+        def getMemberLanguage(self, member):
+            lang = self.select_on('lang',member)
+            if len(lang) and lang[0] in self.__mlist.GetAvailableLanguages():
+                return lang[0]
+            else:
+                return self.__mlist.preferred_language
+    
+        # getOptions: different methods for digest and other (bitfield) options
+        def getMemberOption(self, member, flag):
+            self.__assertIsMember(member)
+            if flag == mm_cfg.Digests:
+                cpaddr, where = self.__get_cp_member(member)
+                return where == ISDIGEST
+            options = self.select_on('user_options', member)
+            if len(options):
+                return not not (options[0] & flag)
+    
+    
+        # new method to gest faster results when searching a user in the admin Gui
+        def getMembersMatching(self, regexp):
+            return self.select('address',
+                "(address REGEXP '%s' OR name REGEXP '%s')"
+                %( self.escape(regexp), self.escape(regexp) ) )
+    
+        # new method to get faster results when querying the number of subscribers
+        def getMembersCount(self, reason=None):
+            if reason:
+                where = " AND digest='%s'" %reason
+            else:
+                where = ""
+            self.query("SELECT COUNT(*) FROM %s WHERE %s%s" %(
+              self._table, self._where, where))
+            count = mm_cfg.cursor.fetchone()
+            return int(count[0])
+    
+        # get member's name (slow method if you need many)
+        # due to the way escape() is built, names are stored in html
+        # format in the DB, hence the canonstr() to put them back to
+        # normal (TODO)
+        def getMemberName(self, member):
+            name = self.select_on('name', member)
+            if len(name):
+              try:
+                return Utils.canonstr(name[0])
+              except:
+                return name[0]
+            self.__assertIsMember(member)
+    
+        # topics
+        def getMemberTopics(self, member):
+            topics = self.select_on('topics_userinterest',member)
+            if len(topics) and isinstance(topics[0], str):
+                return topics[0].split(',')
+            return []
+            self.__assertIsMember(member)
+    
+        # delivery status
+        def getDeliveryStatus(self, member):
+            status = self.select_on('delivery_status',member)
+            if len(status):
+                if status[0] in (MemberAdaptor.ENABLED, MemberAdaptor.UNKNOWN,
+                              MemberAdaptor.BYUSER, MemberAdaptor.BYADMIN,
+                              MemberAdaptor.BYBOUNCE):
+                    return status[0]
+                else:
+                    return MemberAdaptor.ENABLED
+            self.__assertIsMember(member)
+    
+    
+        # delivery status change time
+        def getDeliveryStatusChangeTime(self, member):
+            time = self.select_on('delivery_status_timestamp',member)
+            if len(time):
+                time = time[0]
+                if time is '0':
+                    return MemberAdaptor.ENABLED
+                else:
+                    return time
+            self.__assertIsMember(member)
+    
+        # Covered by SQL getMembers(), and getDeliveryStatus().
+        def getDeliveryStatusMembers(self, status=(MemberAdaptor.UNKNOWN,
+                                                   MemberAdaptor.BYUSER,
+                                                   MemberAdaptor.BYADMIN,
+                                                   MemberAdaptor.BYBOUNCE)):
+            return [member for member in self.getMembers()
+                    if self.getDeliveryStatus(member) in status]
+    
+        # show bouncing members
+        def getBouncingMembers(self):
+	    mm_cfg.cursor = self.__db_connect__()
+            self.query("""SELECT bi_cookie,bi_score,bi_noticesleft,
+                UNIX_TIMESTAMP(bi_lastnotice),UNIX_TIMESTAMP(bi_date),address
+                FROM %s WHERE %s""" %(self._table, self._where))
+            # get the number of rows in the resultset
+            numrows = int(mm_cfg.cursor.rowcount)
+            # save one address at a time
+            bounce_info_list = []
+            for x in range(0,numrows):
+                row = mm_cfg.cursor.fetchone()
+                # We must not return anything if there is
+                # no bounce info for that member to start with.
+                if row[4] > 0:
+                    # Append the member name to the bounce info list.
+                    bounce_info_list.append(row[5])
+            return [member.lower() for member in bounce_info_list]
+    
+        def getBounceInfo(self, member):
+	    mm_cfg.cursor = self.__db_connect__()
+            self.query("""SELECT
+                bi_score,
+                bi_noticesleft,
+                EXTRACT(YEAR FROM bi_lastnotice),
+                EXTRACT(MONTH FROM bi_lastnotice),
+                EXTRACT(DAY FROM bi_lastnotice),
+                EXTRACT(YEAR FROM bi_date),
+                EXTRACT(MONTH FROM bi_date),
+                EXTRACT(DAY FROM bi_date),
+                bi_cookie
+                FROM %s WHERE %s AND """ %(self._table, self._where)
+                + ("address = '%s'" %( self.escape(member) ) ))
+            numrows = int(mm_cfg.cursor.rowcount)
+            if numrows is 0:
+                self.__assertIsMember(member)
+            row = mm_cfg.cursor.fetchone()
+            # We must not return a _BounceInfo instance if there is no bounce info
+            # to start with.
+            if row[3] <= 0:
+                return None;
+            # Otherwise, populate a bounce_info structure.
+            bounce_info = _BounceInfo(member, row[0],
+                (row[5],row[6],row[7]), row[1])
+            bounce_info.lastnotice = (row[2],row[3],row[4])
+            bounce_info.cookie = row[8]
+            return bounce_info
+    
+    
+        #
+        # Write interface
+        #
+        def addNewMember(self, member, **kws):
+    #        assert self.__mlist.Locked()
+            # Make sure this address isn't already a member
+            if self.isMember(member):
+                raise Errors.MMAlreadyAMember, member
+            # Parse the keywords
+            digest = 0
+            password = Utils.MakeRandomPassword()
+            language = self.__mlist.preferred_language
+            realname = None
+            if kws.has_key('digest'):
+                digest = kws['digest']
+                del kws['digest']
+            if kws.has_key('password'):
+                password = kws['password']
+                del kws['password']
+            if kws.has_key('language'):
+                language = kws['language']
+                del kws['language']
+            if kws.has_key('realname'):
+                realname = kws['realname']
+                del kws['realname']
+            # Assert that no other keywords are present
+            if kws:
+                raise ValueError, kws.keys()
+            # If the localpart has uppercase letters in it, then the value in the
+            # members (or digest_members) dict is the case preserved address.
+            # Otherwise the value is 0.  Note that the case of the domain part is
+            # of course ignored.
+            if Utils.LCDomain(member) == member.lower():
+                value = 0
+            else:
+                value = member
+                member = member.lower()
+            if digest:
+                digest = 'Y'
+            else:
+                digest = 'N'
+            # All we need to do here is add the address.
+            # and Set the member's default set of options
+            if self.__mlist.new_member_options:
+                options = self.__mlist.new_member_options
+            else:
+                options = 0
+            query = "INSERT INTO %s " \
+                + "(address, user_options, password, lang, " \
+                + "digest, delivery_status,listname) values " \
+                + "('%s',%s,'%s','%s','%s','%s','%s')"
+            query = query %( self._table,
+                self.escape(member), options, md5_new(password).hexdigest(),
+                language, digest, MemberAdaptor.ENABLED,self.__mlist.internal_name())
+            if mm_cfg.MYSQL_MEMBER_DB_VERBOSE:
+                syslog('mysql',query)
+	    mm_cfg.cursor.execute(query)
+	    mm_cfg.connection.commit()
+            if realname:
+                self.setMemberName(member, realname)
+    
+        def removeMember(self, member):
+    #        assert self.__mlist.Locked()
+            self.__assertIsMember(member)
+            self.query("DELETE FROM %s WHERE %s " %(self._table, self._where)
+                + ("AND address = '%s'" %( self.escape(member.lower()) ) ))
+            self.uncache()
+    
+        def changeMemberAddress(self, member, newaddress, nodelete=0):
+    #        assert self.__mlist.Locked()
+            # Make sure this address isn't already a member
+            if self.isMember(newaddress):
+                raise Errors.MMAlreadyAMember, newaddress
+            self.update_on('address', newaddress, member)
+    
+        def setMemberPassword(self, member, password):
+    #        assert self.__mlist.Locked()
+            self.update_on('password', md5_new(password).hexdigest(), member)
+    
+        def setMemberLanguage(self, member, lang):
+    #        assert self.__mlist.Locked()
+            self.update_on('lang', lang, member)
+    
+        def setMemberOption(self, member, flag, value):
+    #        assert self.__mlist.Locked()
+            if flag == mm_cfg.Digests:
+                if value:
+                    # Be sure the list supports digest delivery
+                    if not self.__mlist.digestable:
+                        raise Errors.CantDigestError
+                    # The user is turning on digest mode
+                    # If they are already receiving digests, report an error.
+                    if self.getMemberOption(member, mm_cfg.Digests) is 'Y':
+                        raise Errors.AlreadyReceivingDigests, member
+                    # If we've got past all this, actually turn on digest mode.
+                    self.update_on('digest', 'Y', member)
+                else:
+                    # Be sure the list supports regular delivery
+                    if not self.__mlist.nondigestable:
+                        raise Errors.MustDigestError
+                    # The user is turning off digest mode
+                    # If they are already receiving regular, report an error.
+                    if self.getMemberOption(member, mm_cfg.Digests) is 'N':
+                        raise Errors.AlreadyReceivingRegularDeliveries, member
+                    # If we've got past all this, actually turn off digest mode.
+                    self.update_on('digest', 'N', member)
+                return
+    
+            # Apparently, mysql supports the & and | operators, so this should
+            # work, maybe. Will have to suck it and see for the moment.
+            # If the value is non-zero, set the bitfield indicated by 'flag'.
+            if value:
+                self.query("UPDATE %s " %(self._table)
+                    + ("SET user_options = user_options | %s " %(flag))
+                    + "WHERE %s " %(self._where)
+                    + ("AND address = '%s'" %( self.escape(member) ) ))
+            else:
+                self.query("UPDATE %s " %(self._table)
+                    + ("SET user_options = user_options & ~%s " %(flag))
+                    + "WHERE %s " %(self._where)
+                    + ("AND address = '%s'" %( self.escape(member) ) ))
+            # remove the cache
+            self.uncache()
+    
+        def setMemberName(self, member, name):
+    #        assert self.__mlist.Locked()
+            self.update_on('name', name, member)
+    
+        def setMemberTopics(self, member, topics):
+    #        assert self.__mlist.Locked()
+            if isinstance(topics,list):
+              topics=",".join(topics)
+            else:
+              topics=""
+            self.query("UPDATE %s " %(self._table)
+                + ("SET topics_userinterest = '%s' " %(
+                  self.escape(topics) ))
+                + "WHERE %s " %(self._where)
+                + ("AND address = '%s'" %( self.escape(member) )))
+    
+        def setDeliveryStatus(self, member, status):
+            assert status in (MemberAdaptor.ENABLED,  MemberAdaptor.UNKNOWN,
+                              MemberAdaptor.BYUSER,   MemberAdaptor.BYADMIN,
+                              MemberAdaptor.BYBOUNCE)
+    #        assert self.__mlist.Locked()
+            member = member.lower()
+            if status == MemberAdaptor.ENABLED:
+                # Enable by resetting their bounce info.
+                self.setBounceInfo(member, None)
+            else:
+                self.query("UPDATE %s " %(self._table)
+                    + ("SET delivery_status = '%s', " %(status))
+                    + "delivery_status_timestamp=NOW() WHERE %s " %(self._where)
+                    + ("AND address = '%s'" %( self.escape(member) )))
+            # remove the cache
+            self.uncache()                                                
+    
+        def setBounceInfo(self, member, info):
+    #        assert self.__mlist.Locked()
+            member = member.lower()
+            if info is None:
+                self.query("UPDATE %s " %(self._table)
+                    + ("SET delivery_status = '%s', " %(MemberAdaptor.ENABLED))
+                    + "bi_cookie = NULL, "
+                    + "bi_score = 0, "
+                    + "bi_noticesleft = 0, "
+		    + "bi_lastnotice = '1901-01-01'::date, "
+		    + "bi_date = '1901-01-01'::date "
+                    + "WHERE %s " %(self._where)
+                    + ("AND address = '%s'" %( self.escape(member) )))
+            else:
+                # Hack the dates to work with MySQL.
+                lnsql = time.strftime("%Y-%m-%d", time.strptime('-'.join(map(str,info.lastnotice)),'%Y-%m-%d'))
+                datesql = time.strftime("%Y-%m-%d", time.strptime('-'.join(map(str,info.date)),'%Y-%m-%d'))
+                self.query("UPDATE %s " %(self._table)
+                    + (("SET bi_cookie = '%s', "
+                        + "bi_score = %s, "
+                        + "bi_noticesleft = %s, "
+                        + "bi_lastnotice = '%s', "
+                        + "bi_date = '%s' ") %(
+                            info.cookie, info.score,
+                            info.noticesleft, lnsql, datesql
+                        ))
+                    + ("WHERE %s " %(self._where))
+                    + ("AND address = '%s'" %( self.escape(member) )))
+    
+    
+    
+    # this function can be plugged into Mailman.MailList.Save
+    # it saves a copy of a few list's attributes into a database
+        def SaveToDb(self,dict):
+            query = 'REPLACE lists (listname,moderation,advertised,new_member_options,subscribe_policy,host_name,description,info,count) ' \
+                " VALUES ('%s','%s','%s','%s','%s','%s','%s','%s','%s')" % (\
+                self.internal_name(), \
+                self.default_member_moderation, \
+                self.advertised, \
+                self.new_member_options, \
+                self.subscribe_policy, \
+                self.host_name, \
+                self.escape(self.description), \
+                self.escape(self.info), \
+                self.getMembersCount() \
+                )
+            syslog('mysql', query)
+            try:
+                self.query(query)
+            except Exception,e:
+                syslog('mysql', 'error %s'%e)
+            pass

Added: trunk/plugins/coclico/mailman/usr/lib/mailman/Mailman/ForgeSecurityManager.py
===================================================================
--- trunk/plugins/coclico/mailman/usr/lib/mailman/Mailman/ForgeSecurityManager.py	                        (rev 0)
+++ trunk/plugins/coclico/mailman/usr/lib/mailman/Mailman/ForgeSecurityManager.py	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,382 @@
+
+# Copyright (C) 1998-2008 by the Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program 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 this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+# USA.
+
+
+"""Handle passwords and sanitize approved messages."""
+
+# There are current 5 roles defined in Mailman, as codified in Defaults.py:
+# user, list-creator, list-moderator, list-admin, site-admin.
+#
+# Here's how we do cookie based authentication.
+#
+# Each role (see above) has an associated password, which is currently the
+# only way to authenticate a role (in the future, we'll authenticate a
+# user and assign users to roles).
+#
+# Each cookie has the following ingredients: the authorization context's
+# secret (i.e. the password, and a timestamp.  We generate an SHA1 hex
+# digest of these ingredients, which we call the `mac'.  We then marshal
+# up a tuple of the timestamp and the mac, hexlify that and return that as
+# a cookie keyed off the authcontext.  Note that authenticating the user
+# also requires the user's email address to be included in the cookie.
+#
+# The verification process is done in CheckCookie() below.  It extracts
+# the cookie, unhexlifies and unmarshals the tuple, extracting the
+# timestamp.  Using this, and the shared secret, the mac is calculated,
+# and it must match the mac passed in the cookie.  If so, they're golden,
+# otherwise, access is denied.
+#
+# It is still possible for an adversary to attempt to brute force crack
+# the password if they obtain the cookie, since they can extract the
+# timestamp and create macs based on password guesses.  They never get a
+# cleartext version of the password though, so security rests on the
+# difficulty and expense of retrying the cgi dialog for each attempt.  It
+# also relies on the security of SHA1.
+
+import os
+import re
+import time
+import sys
+import Cookie
+import marshal
+import binascii
+import urllib
+from types import StringType, TupleType
+from urlparse import urlparse
+
+try:
+    import crypt
+except ImportError:
+    crypt = None
+
+from Mailman import mm_cfg
+from Mailman import Utils
+from Mailman import Errors
+from Mailman.Logging.Syslog import syslog
+try:
+     from Mailman.Utils import md5_new, sha_new
+except ImportError:
+     import md5
+     import sha
+     md5_new=md5.new
+     sha_new=sha.new
+from Mailman import SecurityManager
+
+try:
+    True, False
+except NameError:
+    True = 1
+    False = 0
+
+
+
+class ForgeSecurityManager(SecurityManager.SecurityManager):
+    def __init__(self,mlist):
+	self.__mlist = mlist	
+        # We used to set self.password here, from a crypted_password argument,
+        # but that's been removed when we generalized the mixin architecture.
+        # self.password is really a SecurityManager attribute, but it's set in
+        # MailList.InitVars().
+        self.mod_password = None
+        # Non configurable
+        self.__mlist.passwords = {}
+
+    def AuthContextInfo(self, authcontext, user=None):
+        # authcontext may be one of AuthUser, AuthListModerator,
+        # AuthListAdmin, AuthSiteAdmin.  Not supported is the AuthCreator
+        # context.
+        #
+        # user is ignored unless authcontext is AuthUser
+        #
+        # Return the authcontext's secret and cookie key.  If the authcontext
+        # doesn't exist, return the tuple (None, None).  If authcontext is
+        # AuthUser, but the user isn't a member of this mailing list, a
+        # NotAMemberError will be raised.  If the user's secret is None, raise
+        # a MMBadUserError.
+        key = self.__mlist.internal_name() + '+'
+        if authcontext == mm_cfg.AuthUser:
+            if user is None:
+                # A bad system error
+                raise TypeError, 'No user supplied for AuthUser context'
+            secret = self.__mlist.getMemberPassword(user)
+            userdata = urllib.quote(Utils.ObscureEmail(user), safe='')
+            key += 'user+%s' % userdata
+        elif authcontext == mm_cfg.AuthListModerator:
+            secret = self.mod_password
+            key += 'moderator'
+        elif authcontext == mm_cfg.AuthListAdmin:
+            secret = self.__mlist.password
+            key += 'admin'
+        # BAW: AuthCreator
+        elif authcontext == mm_cfg.AuthSiteAdmin:
+            sitepass = Utils.get_global_password()
+            if mm_cfg.ALLOW_SITE_ADMIN_COOKIES and sitepass:
+                secret = sitepass
+                key = 'site'
+            else:
+                # BAW: this should probably hand out a site password based
+                # cookie, but that makes me a bit nervous, so just treat site
+                # admin as a list admin since there is currently no site
+                # admin-only functionality.
+                secret = self.__mlist.password
+                key += 'admin'
+        else:
+            return None, None
+        return key, secret
+
+    def Authenticate(self, authcontexts, response, user=None):
+        # Given a list of authentication contexts, check to see if the
+        # response matches one of the passwords.  authcontexts must be a
+        # sequence, and if it contains the context AuthUser, then the user
+        # argument must not be None.
+        #
+        # Return the authcontext from the argument sequence that matches the
+        # response, or UnAuthorized.
+        for ac in authcontexts:
+            if ac == mm_cfg.AuthCreator:
+                ok = Utils.check_global_password(response, siteadmin=0)
+                if ok:
+                    return mm_cfg.AuthCreator
+            elif ac == mm_cfg.AuthSiteAdmin:
+                ok = Utils.check_global_password(response)
+                if ok:
+                    return mm_cfg.AuthSiteAdmin
+            elif ac == mm_cfg.AuthListAdmin:
+                def cryptmatchp(response, secret):
+                    try:
+                        salt = secret[:2]
+                        if crypt and crypt.crypt(response, salt) == secret:
+                            return True
+                        return False
+                    except TypeError:
+                        # BAW: Hard to say why we can get a TypeError here.
+                        # SF bug report #585776 says crypt.crypt() can raise
+                        # this if salt contains null bytes, although I don't
+                        # know how that can happen (perhaps if a MM2.0 list
+                        # with USE_CRYPT = 0 has been updated?  Doubtful.
+                        return False
+                # The password for the list admin and list moderator are not
+                # kept as plain text, but instead as an sha hexdigest.  The
+                # response being passed in is plain text, so we need to
+                # digestify it first.  Note however, that for backwards
+                # compatibility reasons, we'll also check the admin response
+                # against the crypted and md5'd passwords, and if they match,
+                # we'll auto-migrate the passwords to sha.
+                key, secret = self.AuthContextInfo(ac)
+                if secret is None:
+                    continue
+                sharesponse = sha_new(response).hexdigest()
+                upgrade = ok = False
+                if sharesponse == secret:
+                    ok = True
+                elif md5_new(response).digest() == secret:
+                    ok = upgrade = True
+                elif cryptmatchp(response, secret):
+                    ok = upgrade = True
+                if upgrade:
+                    save_and_unlock = False
+                    if not self.__mlist.Locked():
+                        self.__mlist.Lock()
+                        save_and_unlock = True
+                    try:
+                        self.__mlist.password = sharesponse
+                        if save_and_unlock:
+                            self.__mlist.Save()
+                    finally:
+                        if save_and_unlock:
+                            self.__mlist.Unlock()
+                if ok:
+                    return ac
+            elif ac == mm_cfg.AuthListModerator:
+                # The list moderator password must be sha'd
+                key, secret = self.AuthContextInfo(ac)
+                if secret and sha_new(response).hexdigest() == secret:
+                    return ac
+            elif ac == mm_cfg.AuthUser:
+                if user is not None:
+                    try:
+                        if self.__mlist.authenticateMember(user, response):
+                            return ac
+                    except Errors.NotAMemberError:
+                        pass
+            else:
+                # What is this context???
+                syslog('error', 'Bad authcontext: %s', ac)
+                raise ValueError, 'Bad authcontext: %s' % ac
+        return mm_cfg.UnAuthorized
+
+    def WebAuthenticate(self, authcontexts, response, user=None):
+        # Given a list of authentication contexts, check to see if the cookie
+        # contains a matching authorization, falling back to checking whether
+        # the response matches one of the passwords.  authcontexts must be a
+        # sequence, and if it contains the context AuthUser, then the user
+        # argument should not be None.
+        #
+        # Returns a flag indicating whether authentication succeeded or not.
+        for ac in authcontexts:
+            ok = self.CheckCookie(ac,user)
+            if ok:
+                return True
+        # Check passwords
+        ac = self.Authenticate(authcontexts, response, user)
+        if ac:
+            print self.MakeCookie(ac, user)
+            return True
+        return False
+
+    def MakeCookie(self, authcontext, user=None):
+        key, secret = self.AuthContextInfo(authcontext, user)
+        if key is None or secret is None or not isinstance(secret, StringType):
+            raise ValueError
+        # Timestamp
+        issued = int(time.time())
+        # Get a digest of the secret, plus other information.
+        mac = sha_new(secret + `issued`).hexdigest()
+        # Create the cookie object.
+        c = Cookie.SimpleCookie()
+        c[key] = binascii.hexlify(marshal.dumps((issued, mac)))
+        # The path to all Mailman stuff, minus the scheme and host,
+        # i.e. usually the string `/mailman'
+        path = urlparse(self.__mlist.web_page_url)[2]
+        c[key]['path'] = path
+        # We use session cookies, so don't set `expires' or `max-age' keys.
+        # Set the RFC 2109 required header.
+        c[key]['version'] = 1
+        return c
+
+    def ZapCookie(self, authcontext, user=None):
+        # We can throw away the secret.
+        key, secret = self.AuthContextInfo(authcontext, user)
+        # Logout of the session by zapping the cookie.  For safety both set
+        # max-age=0 (as per RFC2109) and set the cookie data to the empty
+        # string.
+        c = Cookie.SimpleCookie()
+        c[key] = ''
+        # The path to all Mailman stuff, minus the scheme and host,
+        # i.e. usually the string `/mailman'
+        path = urlparse(self.__mlist.web_page_url)[2]
+        c[key]['path'] = path
+        c[key]['max-age'] = 0
+        # Don't set expires=0 here otherwise it'll force a persistent cookie
+        c[key]['version'] = 1
+        return c
+    
+    def CheckCookie(self, authcontext, user):
+	cookiedata = os.environ.get('HTTP_COOKIE')
+	if not cookiedata:
+		return False
+	c = parsecookie(cookiedata)
+	if authcontext == mm_cfg.AuthUser:
+		if user:
+                	usernames = [user]
+		else:
+			usernames = []
+			usernames = self.__mlist.db_cookie_to_mail(c)	
+		if usernames :
+			for user in usernames:
+				ok =  self.__checkone(c, authcontext, user)
+				if ok:
+					return True
+               	usernames = []
+               	prefix = self.__mlist.internal_name() + '+user+'
+               	for k in c.keys():
+                 	if k.startswith(prefix):
+                        	usernames.append(k[len(prefix):])
+            	# If any check out, we're golden.  Note: `@'s are no longer legal
+            	# values in cookie keys.
+            	for user in [Utils.UnobscureEmail(urllib.unquote(u))
+                         for u in usernames]:
+                	ok = self.__checkone(c, authcontext, user)
+                	if ok:
+                    		return True
+            	return False
+	else:
+		return self.__checkone(c,authcontext, user)
+
+    def __checkone(self, c, authcontext, user):
+        try:
+            key, secret = self.AuthContextInfo(authcontext, user)
+        except Errors.NotAMemberError:
+            return False
+	user_id = self.__mlist.db_cookie_to_id(c)
+	if user_id :
+		monitored = self.__mlist.db_id_to_monitored(user_id)
+		isAdmin = self.__mlist.db_isAdmin(user_id)
+		isSiteAdmin = self.__mlist.db_isSiteAdmin(user_id)
+		if authcontext == mm_cfg.AuthUser:    
+			if not monitored:
+				return False
+			else :
+				return True
+		elif authcontext == mm_cfg.AuthListAdmin:
+			if not isAdmin: 
+				return False
+			else :
+				return True
+		elif authcontext == mm_cfg.AuthListModerator:
+			if not isAdmin :
+				return False
+			else :
+				return True
+		elif authcontext == mm_cfg.AuthSiteAdmin:
+			if not isSiteAdmin :
+				return False
+			else :
+				return True
+	if not c.has_key(key) or not isinstance(secret, StringType):
+            return False
+        # Undo the encoding we performed in MakeCookie() above.  BAW: I
+        # believe this is safe from exploit because marshal can't be forced to
+        # load recursive data structures, and it can't be forced to execute
+        # any unexpected code.  The worst that can happen is that either the
+        # client will have provided us bogus data, in which case we'll get one
+        # of the caught exceptions, or marshal format will have changed, in
+        # which case, the cookie decoding will fail.  In either case, we'll
+        # simply request reauthorization, resulting in a new cookie being
+        # returned to the client.
+        try:
+            data = marshal.loads(binascii.unhexlify(c[key]))
+            issued, received_mac = data
+        except (EOFError, ValueError, TypeError, KeyError):
+            return False
+        # Make sure the issued timestamp makes sense
+        now = time.time()
+        if now < issued:
+            return False
+        # Calculate what the mac ought to be based on the cookie's timestamp
+        # and the shared secret.
+        mac = sha_new(secret + `issued`).hexdigest()
+        if mac <> received_mac:
+            return False
+        # Authenticated!
+        return True
+
+
+splitter = re.compile(';\s*')
+
+def parsecookie(s):
+    c = {}
+    for line in s.splitlines():
+        for p in splitter.split(line):
+            try:
+                k, v = p.split('=', 1)
+            except ValueError:
+                pass
+            else:
+                c[k] = v
+    return c

Added: trunk/plugins/coclico/mailman/usr/lib/mailman/Mailman/MySQLConnector.py
===================================================================
--- trunk/plugins/coclico/mailman/usr/lib/mailman/Mailman/MySQLConnector.py	                        (rev 0)
+++ trunk/plugins/coclico/mailman/usr/lib/mailman/Mailman/MySQLConnector.py	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,42 @@
+
+# Copyright (C) 1998-2008 by the Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program 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 this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+# USA.
+
+
+import os
+import sys
+import re
+import time
+from types import StringType, TupleType
+
+
+from Mailman import ExternalConnector 
+from Mailman import mm_cfg
+from Mailman import Utils
+from Mailman.Logging.Syslog import syslog
+import MySQLdb
+class MySQLConnector(ExternalConnector.ExternalConnector):
+	def __init__(self,mlist,param):
+		ExternalConnector.ExternalConnector.__init__(self,mlist,param)
+	def __db_connect__(self):
+		if mm_cfg.connection ==0: 
+			connection = MySQLdb.connect (host = self._param['dbhost'], user = self._param['dbuser'], passwd = self._param['dbpassword'],db = self._param['database'])
+			mm_cfg.connection = connection
+			mm_cfg.cursor = connection.cursor()
+			connection.commit()
+		return mm_cfg.cursor
+

Added: trunk/plugins/coclico/mailman/usr/lib/mailman/Mailman/PsycopgConnector.py
===================================================================
--- trunk/plugins/coclico/mailman/usr/lib/mailman/Mailman/PsycopgConnector.py	                        (rev 0)
+++ trunk/plugins/coclico/mailman/usr/lib/mailman/Mailman/PsycopgConnector.py	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,45 @@
+# Copyright (C) 1998-2008 by the Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program 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 this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+# USA.
+
+
+import os
+import sys
+import re
+import time
+from types import StringType, TupleType
+
+from Mailman import ExternalConnector 
+
+from Mailman import mm_cfg
+from Mailman import Utils
+from Mailman.Logging.Syslog import syslog
+import psycopg2
+
+class PsycopgConnector(ExternalConnector.ExternalConnector):
+	def __init__(self,mlist,param):
+		ExternalConnector.ExternalConnector.__init__(self,mlist,param)
+	def __db_connect__(self):
+		if mm_cfg.connection == 0:
+			if self._param['dbhost']:
+				connection = psycopg2.connect (host = self._param['dbhost'], user = self._param['dbuser'], password = self._param['dbpassword'], database = self._param['database'])
+			else :
+				connection = psycopg2.connect (user = self._param['dbuser'], password = self._param['dbpassword'], database = self._param['database'])
+			mm_cfg.connection = connection
+			mm_cfg.cursor=connection.cursor()
+			connection.commit()
+		return mm_cfg.cursor
+

Added: trunk/plugins/coclico/mailman/utils/manage-translations.sh
===================================================================
--- trunk/plugins/coclico/mailman/utils/manage-translations.sh	                        (rev 0)
+++ trunk/plugins/coclico/mailman/utils/manage-translations.sh	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,56 @@
+#! /bin/sh -e
+
+if [ -e gforge/translations/gforge.pot ] ; then        # We're in the parent dir
+    cd gforge
+elif [ -e translations/gforge.pot ] ; then             # probably in gforge/ (or a renamed gforge/)
+    cd . # do nothing, but shell syntax requires an instruction in a then-block
+elif [ -e ../gforge/translations/gforge.pot ] ; then   # in tools/ or tests/ or something
+    cd ../gforge
+elif [ -e ../translations/gforge.pot ] ; then          # In a subdir of gforge/
+    cd ..
+else
+    echo "Couldn't find translations directory..."
+    exit 1
+fi
+
+locales=$(ls translations/*.po \
+    | xargs -n1 -iFILE basename FILE .po \
+    | egrep '^[a-z][a-z](_[A-Z][A-Z]$)?' \
+    | sort)
+
+print_stats () {
+    for l in $(echo $locales | xargs -n 1 | sort) ; do
+	printf "* %5s: " $l
+	msgfmt --statistics -o /dev/null translations/$l.po
+    done
+}
+
+case $1 in
+    stats)
+	print_stats
+	;;
+    refresh)
+	rm translations/gforge.pot
+	
+	find -type f -\( -name \*.php -or -name users -or -name projects -\) \
+	    | grep -v -e {arch} -e svn-base \
+	    | grep -v ^./plugins/wiki \
+	    | LANG=C sort \
+	    | xargs xgettext -d gforge -o translations/gforge.pot -L PHP --from-code=iso-8859-1
+	    
+	for l in $locales ; do
+	    echo "Processing $l..."
+	    msgmerge -U translations/$l.po translations/gforge.pot
+	done
+	;;
+    build)
+	for l in $locales ; do
+	    mkdir -p locales/$l/LC_MESSAGES
+	    msgfmt -o locales/$l/LC_MESSAGES/gforge.mo translations/$l.po
+	done
+	;;
+    *)
+	echo "Unknown operation"
+	exit 1
+	;;
+esac


Property changes on: trunk/plugins/coclico/mailman/utils/manage-translations.sh
___________________________________________________________________
Added: svn:executable
   + *

Added: trunk/plugins/coclico/mailman/var/lib/mailman/lists/extend.py
===================================================================
--- trunk/plugins/coclico/mailman/var/lib/mailman/lists/extend.py	                        (rev 0)
+++ trunk/plugins/coclico/mailman/var/lib/mailman/lists/extend.py	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,45 @@
+from Mailman.PsycopgConnector import PsycopgConnector
+from Mailman.ForgeSecurityManager import ForgeSecurityManager
+import sys
+
+def extendMemberAdaptor(list):
+    sys.path.append('/etc/gforge')
+    import database 
+    dbparam={}
+    #Config to connect to database
+    dbparam['dbhost'] = database.sys_dbhost 
+    dbparam['dbuser']=  database.sys_dbuser
+    dbparam['dbpassword'] = database.sys_dbpasswd 
+    dbparam['database'] =  database.sys_dbname
+    dbparam['refresh'] = 360
+
+    dbparam['mailman_table']= 'plugin_mailman'#table where mailman stores memeberships info
+
+    ######################	
+    # Session Management #
+    ######################
+    #Forge default session
+    dbparam['cookiename']='session_ser'
+    dbparam['queryCookieMail']="SELECT email FROM plugin_defaultsession,users WHERE users.user_id=plugin_defaultsession.user_id AND session_hash = substring('%s','.*-%%2A-(.*)');"
+    dbparam['queryCookieId']="SELECT user_id FROM plugin_defaultsession WHERE session_hash = substring('%s','.*-%%2A-(.*)');"
+
+    dbparam['queryIsAdmin'] = "SELECT COUNT(*) FROM mail_group_list WHERE list_admin=%s AND list_name='%s';" 
+    dbparam['queryIsMonitoring'] = "SELECT COUNT(*) FROM "+dbparam['mailman_table']+", users "+" WHERE users.email = "+dbparam['mailman_table']+".address"+" AND users.user_id=%s AND listname='%s';" 
+    dbparam['queryIsSiteAdmin'] = "SELECT count(*) AS count FROM user_group WHERE user_id=%s AND group_id=1 AND admin_flags='A';"
+    
+    #Forge ZendSession
+    #dbparam['cookiename']='zend_cookie_session'
+    #dbparam['queryCookieMail']="""select substring(session_data,'email";s:[0-9]*?:"(.*)";s') from plugin_zendsession where session_hash='%s';"""
+    #dbparam['queryCookieId']="""SELECT substring(session_data,'user_id";i:([0-9]{1,})') FROM plugin_zendsession WHERE session_hash='%s';"""
+    
+    ######################
+    # Type of connection #
+    ######################
+    db = PsycopgConnector(list,dbparam)
+    list._memberadaptor = db
+
+def extendSecurityManager(list):
+    sm = ForgeSecurityManager(list)
+    list._securitymanager = sm
+
+

Added: trunk/plugins/coclico/mailman/www/admin/deletelist.php
===================================================================
--- trunk/plugins/coclico/mailman/www/admin/deletelist.php	                        (rev 0)
+++ trunk/plugins/coclico/mailman/www/admin/deletelist.php	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,67 @@
+<?php
+
+/**
+ * GForge Mailing Lists Facility
+ *
+ * Portions Copyright 1999-2001 (c) VA Linux Systems
+ * The rest Copyright 2003-2004 (c) Guillaume Smet - Open Wide
+ *
+ * @version $Id$
+ * 
+ * Portions Copyright 2010 (c) Mélanie Le Bail
+ */
+require_once ('env.inc.php');
+require_once 'pre.php';
+require_once('plugins_utils.php');
+require_once '../mailman_utils.php';
+
+$request =& HTTPRequest::instance();
+$group_id = $request->get('group_id');
+
+$feedback = '';
+
+if (!$group_id) {
+	exit_no_group();
+}
+$pm = ProjectManager::instance();
+$Group = $pm->getProject($group_id);
+if (!$Group || !is_object($Group) || $Group->isError()) {
+	exit_no_group();
+}
+if(isLogged()) {
+	if (!$current_user->isMember($group_id,'A')) {
+		exit_permission_denied();
+	}
+}
+
+
+$ml = new MailmanList($group_id,$request->get('id'));
+
+if ($request->exist('submit')) {
+	$sure = $request->get('sure');
+	$really_sure = $request->get('really_sure');
+	if (!$ml->deleteList($sure,$really_sure)) {
+		exit_error('Error',$ml->getErrorMessage());
+	} else {
+		htmlRedirect('index.php?group_id='.$group_id.'&feedback=DELETED');
+	}
+}
+
+mailman_header(array(
+	'title' => _('Permanently Delete List')
+));
+
+?>
+<h3><?php echo $ml->getName(); ?></h3>
+<p>
+<form method="post" action="<?php echo $request->get('PHP_SELF'); ?>?group_id=<?php echo $group_id; ?>&amp;id=<?php echo $ml->getID(); ?>">
+<input type="checkbox" name="sure" value="1"><?php echo _('Confirm Delete'); ?><br />
+<input type="checkbox" name="really_sure" value="1"><?php echo _('Confirm Delete'); ?><br />
+<input type="submit" name="submit" value="<?php echo _('Permanently Delete'); ?>">
+</form>
+</p>
+<?php
+
+mail_footer(array());
+
+?>

Added: trunk/plugins/coclico/mailman/www/admin/index.php
===================================================================
--- trunk/plugins/coclico/mailman/www/admin/index.php	                        (rev 0)
+++ trunk/plugins/coclico/mailman/www/admin/index.php	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,220 @@
+<?php
+
+/**
+ * GForge Mailing Lists Facility
+ *
+ * Portions Copyright 1999-2001 (c) VA Linux Systems
+ * The rest Copyright 2003-2004 (c) Guillaume Smet - Open Wide
+ *
+ * @version $Id$
+ * 
+ * Portions Copyright 2010 (c) Mélanie Le Bail
+ */
+require_once 'env.inc.php';
+require_once 'pre.php';
+require_once 'plugins_utils.php';
+require_once '../mailman_utils.php';
+
+$request =& HTTPRequest::instance();
+$group_id=$request->get('group_id');
+$group_list_id=$request->get('group_list_id');
+$pm = ProjectManager::instance();
+$Group = $pm->getProject($group_id);
+$post_changes= $request->get('post_changes');
+$add_list=$request->get('add_list');
+$change_status=$request->get('change_status');
+$list_name=$request->get('list_name');
+$is_public=$request->get('is_public');
+$description=$request->get('description');
+$PHP_SELF = $request->get('PHP_SELF');
+$feedback = '';
+
+
+if ($group_id) {
+	if (!$Group || !is_object($Group) || $Group->isError()) {
+		
+		exit_no_group();
+	}
+
+	if (!$current_user->isMember($group_id,'A')) {
+		exit_permission_denied();
+	}
+
+	//
+	//	Post Changes to database
+	//
+	if ($post_changes == 'y') {
+		//
+		//	Add list
+		//
+		if ($add_list == 'y') {
+			$mailingList = new MailmanList($group_id);
+
+			if(!$mailingList || !is_object($mailingList)) {
+				exit_error(_('Error'), _('Error getting the list'));
+			} elseif($mailingList->isError()) {
+				exit_error(_('Error'), $mailingList->getErrorMessage());
+			}
+
+			if(!$mailingList->create(
+						$list_name,
+						$description,
+						$is_public
+						)) {
+				exit_error(_('Error'), $mailingList->getErrorMessage());
+			} else {
+				$feedback .= _('List Added');
+			}
+			//
+			//	Change status
+			//
+		} elseif ($change_status == 'y') {
+			$mailingList = new MailmanList($group_id, $group_list_id);
+
+			if(!$mailingList || !is_object($mailingList)) {
+				exit_error(_('Error'), _('Error getting the list'));
+			} elseif($mailingList->isError()) {
+				exit_error(_('Error'), $mailingList->getErrorMessage());
+			}
+
+			if(!$mailingList->update(
+						$description,
+						$is_public
+						)) {
+				
+				exit_error(_('Error'), $mailingList->getErrorMessage());
+			} else {
+				$feedback .= _('List updated');
+			}
+		}
+
+	}
+
+	//
+	//	Form to add list
+	//
+	if($add_list) {
+		mailman_header(array(
+					'title' => _('Add a Mailing List'),
+					'help'=>'CommunicationServices.html#MailingLists',
+					'admin' => '1'));
+		printf(_('<p>Lists are named in this manner:<br /><strong>projectname-listname@%1$s</strong></p><p>It will take <span class="important">6-24 Hours</span> for your list to be created.</p>'), $GLOBALS['sys_lists_host']);
+
+		$mlFactory = new MailmanListFactory($Group);
+		if (!$mlFactory || !is_object($mlFactory) || $mlFactory->isError()) {
+			exit_error(_('Error'), $mlFactory->getErrorMessage());
+		}
+
+		$mlArray =& $mlFactory->getMailmanLists();
+
+		if ($mlFactory->isError()) {
+			echo '<h1>'._('Error').' '._('Unable to get the lists') .'</h1>';
+			echo $mlFactory->getErrorMessage();
+			mail_footer(array());
+			exit;
+		}
+
+		//
+		//	Form to add list
+		//
+		?>
+			<form method="post" action="<?php echo $PHP_SELF; ?>?group_id=<?php echo $group_id ?>">
+			<input type="hidden" name="post_changes" value="y" />
+			<input type="hidden" name="add_list" value="y" />
+			<p><strong><?php echo _('Mailing List Name:'); ?></strong><br />
+			<strong><?php echo $Group->getUnixName(); ?>-<input type="text" name="list_name" value="" size="10" maxlength="12" />@<?php echo $GLOBALS['sys_lists_host']; ?></strong><br /></p>
+			<p>
+			<strong><?php echo _('Is Public?'); ?></strong><br />
+			<input type="radio" name="is_public" value="1" checked="checked" /> <?php echo _('Yes'); ?><br />
+			<input type="radio" name="is_public" value="0" /> <?php echo _('No'); ?></p><p>
+			<strong><?php echo _('Description:'); ?></strong><br />
+			<input type="text" name="description" value="" size="40" maxlength="80" /><br /></p>
+			<p>
+			<input type="submit" name="submit" value="<?php echo _('Add This List'); ?>" /></p>
+			</form>
+			<?php
+			mail_footer(array());
+
+		//
+		//	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',
+					'admin' => 1));
+		echo "PHPSELF=".$PHP_SELF;
+		?>
+		
+			<h3><?php echo $mailingList->getName(); ?></h3>
+			<form method="post" action="<?php echo $PHP_SELF; ?>?group_id=<?php echo $group_id; ?>&amp;group_list_id=<?php echo $mailingList->getID(); ?>">
+			<input type="hidden" name="post_changes" value="y" />
+			<input type="hidden" name="change_status" value="y" />
+			<p>
+			<strong><?php echo _('Is Public?'); ?></strong><br />
+			<input type="radio" name="is_public" value="1"<?php echo ($mailingList->isPublic() == 1 ? ' checked="checked"' : ''); ?> /> <?php echo _('Yes'); ?><br />
+			<input type="radio" name="is_public" value="0"<?php echo ($mailingList->isPublic() == 0 ? ' checked="checked"' : ''); ?> /> <?php echo _('No'); ?><br />
+			</p>
+			<p><strong><?php echo _('Description:'); ?></strong><br />
+			<input type="text" name="description" value="<?php echo $mailingList->getDescription(); ?>" size="40" maxlength="80" /><br /></p>
+			<p>
+			<input type="submit" name="submit" value="<?php echo _('Update'); ?>" /></p>
+			</form>
+					<?php
+			mail_footer(array());
+	} else {
+		//
+		//	Show lists
+		//
+		$mlFactory = new MailmanListFactory($Group);
+		if (!$mlFactory || !is_object($mlFactory) || $mlFactory->isError()) {
+			exit_error(_('Error'), $mlFactory->getErrorMessage());
+		}
+
+		mailman_header(array(
+					'title' => _('Mailing List Administration'),
+					'help'=>'CommunicationServices.html#MailingLists',
+					'admin'=>1)
+			      );
+
+		$mlArray =& $mlFactory->getMailmanLists();
+
+		if ($mlFactory->isError()) {
+			echo '<p>'._('Error').' '.sprintf(_('Unable to get the list %s'), $Group->getPublicName()) .'</p>';
+			echo $mlFactory->getErrorMessage();
+			mail_footer(array());
+			exit;
+		}
+		echo '<p>'.sprintf(_('You can administrate lists from here. Please note that private lists can still be viewed by members of your project, but are not listed on %1$s.'), $GLOBALS['sys_name']).'</p>';
+		echo '<ul>
+			<li>
+			<a href="'.$PHP_SELF.'?group_id='.$group_id.'&amp;add_list=1">'._('Add Mailing List').'</a>
+			</li>
+			</ul>';
+		$mlCount = count($mlArray);
+
+		if($mlCount > 0) {
+				table_begin();
+				for ($j = 0; $j < $mlCount; $j++) {
+					$currentList =& $mlArray[$j];
+					display_list_admin($currentList);
+				}
+
+				table_end();
+		}
+		mail_footer(array());
+	}
+} else {
+	exit_no_group();
+}
+?>

Added: trunk/plugins/coclico/mailman/www/index.html
===================================================================
--- trunk/plugins/coclico/mailman/www/index.html	                        (rev 0)
+++ trunk/plugins/coclico/mailman/www/index.html	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,5 @@
+<html>
+<body>
+<h1>Plugin Template</h1>
+</body>
+</html>

Added: trunk/plugins/coclico/mailman/www/index.php
===================================================================
--- trunk/plugins/coclico/mailman/www/index.php	                        (rev 0)
+++ trunk/plugins/coclico/mailman/www/index.php	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,118 @@
+<?php
+
+
+/*
+ * mailman plugin
+ *
+ * Daniel Perez <danielperez.arg at gmail.com>
+ *
+ * This is an example to watch things in action. You can obviously modify things and logic as you see fit
+ * 
+ * Portions Copyright 2010 (c) Mélanie Le Bail
+ */
+require_once ('env.inc.php');
+require_once 'pre.php';
+require_once 'plugins_utils.php';
+require_once 'mailman_utils.php';
+$request =& HTTPRequest::instance();
+	
+$group_id = $request->get('group_id');
+$pm = ProjectManager::instance();
+$Group = $pm->getProject($group_id);
+if (isset ($group_id)) {
+	
+	if (!$Group || !is_object($Group)) {
+		
+		exit_error(_('Error'), 'Could Not Get Group');
+	}
+	elseif ($Group->isError()) {
+		
+		exit_no_group();
+	}
+
+	
+	$mlFactory = new MailmanListFactory($Group);
+	if (!$mlFactory || !is_object($mlFactory)) {
+		exit_error(_('Error'), 'Could Not Get MailmanListFactory');
+	}
+	elseif ($mlFactory->isError()) {
+		exit_error(_('Error'), $mlFactory->getErrorMessage());
+	}
+
+	mailman_header(array (
+		'title' => _('Mailing Lists for') . $Group->getPublicName(),
+		'help' => 'CommunicationServices.html#MailingLists',
+		'pv' => isset ($pv) ? $pv : false
+	));
+
+	$mlArray = & $mlFactory->getMailmanLists();
+
+	if ($mlFactory->isError()) {
+		echo '<h1>' . _('Error') . ' ' . sprintf(_('Unable to get the list %s'), $Group->getPublicName()) . '</h1>';
+		echo $mlFactory->getErrorMessage();
+		mail_footer(array ());
+		exit;
+	}
+
+	$mlCount = count($mlArray);
+	if ($mlCount == 0) {
+		echo '<p>' . sprintf(_('No Lists found for %1$s'), $Group->getPublicName()) . '</p>';
+		echo '<p>' . _('Project administrators use the admin link to request mailing lists.') . '</p>';
+		mail_footer(array ());
+		exit;
+	}
+	personalized_message();
+
+
+	if (isLogged()){
+		if ($mlFactory->compareInfos()) {
+		echo _('<p>You seem to have mailman account with a different name or password. If you want to update mailman information, click on ');
+		echo '<a href="index.php?group_id=' . $group_id . '&action=update">' . _('Update</p>') . '</a>';
+	}
+	}
+	
+	echo _('<p>Choose a list to browse, search, and post messages.</p>');
+
+	table_begin();
+	for ($j = 0; $j < $mlCount; $j++) {
+		$currentList = & $mlArray[$j];
+		display_list($currentList);
+	}
+
+	table_end();
+	if ($request->exist('action')) {
+		if ($request->exist('id')) {
+			$list = new MailmanList($group_id, $request->get('id'));
+			switch ($request->get('action')) {
+				case 'options' :
+					$list->getOptionsURL();
+					break;
+				case 'subscribe' :
+					$list->subscribe();
+					break;
+				case 'unsubscribe' :
+					$list->unsubscribe();
+					break;
+				case 'pipermail' :
+					$list->getArchivesUrl();
+					break;
+				case 'admin' :
+					$list->getExternalAdminUrl();
+					break;
+				default :
+					break;
+			}
+		}
+		if ($request->get('action') == 'update') {
+			$mlFactory->updateInfos();
+		}
+
+	}
+	mail_footer(array ());
+
+} else {
+
+	exit_no_group();
+
+}
+?>

Added: trunk/plugins/coclico/mailman/www/mailman_utils.php
===================================================================
--- trunk/plugins/coclico/mailman/www/mailman_utils.php	                        (rev 0)
+++ trunk/plugins/coclico/mailman/www/mailman_utils.php	2010-03-29 15:47:50 UTC (rev 9283)
@@ -0,0 +1,148 @@
+<?php
+/**
+ * FusionForge Mailing Lists Facility
+ *
+ * Portions Copyright 1999-2001 (c) VA Linux Systems
+ * The rest Copyright 2003 (c) Guillaume Smet
+ * Portions Copyright 2010 (c) Mélanie Le Bail
+ *
+ * @version   $Id$
+ *
+ */
+
+
+require_once 'mailman/include/MailmanList.class.php';
+require_once 'mailman/include/MailmanListFactory.class.php';
+
+$current_user=UserManager::instance()->getCurrentUser();
+
+
+function sendCreationMail($userEmail,$listname,$listpassword) {
+
+	//$message = $Language->getText('mail_admin_index','list_create_explain',array($GLOBALS['sys_name'], $listname.'@' .$GLOBALS['sys_lists_host'],$list_server."/mailman/listinfo/$listname",$list_server."/mailman/admin/$list_name",$listpassword));
+
+	$hdrs = "From: ".$GLOBALS['sys_email_admin'].$GLOBALS['sys_lf'];
+	$hdrs .='Content-type: text/plain; charset=utf-8'.$GLOBALS['sys_lf'];
+
+	//mail ($userEmail,$GLOBALS['sys_name']." ".$Language->getText('mail_admin_index','new_mail_list'),$message,$hdrs);
+
+
+}
+function table_begin()
+{
+
+	echo "<table WIDTH=\"100%\" border=0>\n"."<TR><TD VALIGN=\"TOP\">\n"; 
+}
+function table_end()
+{
+	echo '</TD></TR></TABLE>';
+
+}
+function personalized_message()
+{
+
+	echo _('<p>Mailing lists provided via a GForge version of <a href="http://www.list.org/">GNU Mailman</a>. Thanks to the Mailman and <a href="http://www.python.org/">Python</a> crews for excellent software.</p>');
+}
+function display_list($currentList)
+{
+	$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($currentList->getStatus() == '3') {
+				echo	_('Not activated yet');
+			} else {
+				echo ' <A HREF="index.php?group_id='.$request->get('group_id').'&action=pipermail&id='.$currentList->getID().'">'._('Archives').'</A>';
+				if(isLogged())
+				{ 
+					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>';
+					} else {
+						echo 	' | <a href="index.php?group_id='.$request->get('group_id').'&action=subscribe&id='.$currentList->getID().'">'._('Subscribe').'</a>';
+					}
+					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 ' ] <br>&nbsp;';
+			echo htmlspecialchars($currentList->getDescription()).'<p>';
+
+		}
+	}
+
+}
+function display_list_admin($currentList)
+{
+	$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($currentList->getStatus() == '3') {
+			echo	_('Not activated yet');
+		} 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>';
+
+			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 ' ] <br>&nbsp;';
+		echo htmlspecialchars($currentList->getDescription()).'<p>';
+	}
+}
+
+
+function mailman_header($params) {
+	global $group_id;
+	$current_user=UserManager::instance()->getCurrentUser();
+	$request =& HTTPRequest::instance();
+
+	//required for site_project_header
+	$params['group'] = $request->get('group_id');
+	$params['toptab'] = 'mailman';
+
+	site_project_header($params);
+	echo '<P><B>';
+	// admin link is only displayed if the user is a project administrator
+	if ($current_user->isMember($request->get('group_id'),'A')) {
+		if (isset($params['admin'])){
+			echo '<A HREF="index.php?group_id='.$request->get('group_id').'">'._('Administration').'</A>';
+		}
+		else{
+			echo '<A HREF="admin/index.php?group_id='.$request->get('group_id').'">'._('Administration').'</A>';
+		}
+
+	}
+	if ($params['help']) {
+		helpButton($params['help']);
+	}
+
+}
+
+function mail_footer($params) {
+	site_project_footer($params);
+}
+
+
+// Local Variables:
+// mode: php
+// c-file-style: "bsd"
+// End:
+
+?>




More information about the Fusionforge-commits mailing list