Index: /trunk/admin/configuration.php
===================================================================
--- /trunk/admin/configuration.php	(revision 3444)
+++ /trunk/admin/configuration.php	(revision 3445)
@@ -70,4 +70,8 @@
     'email_admin_on_comment',
     'email_admin_on_comment_validation',
+    'user_can_delete_comment',
+    'user_can_edit_comment',
+    'email_admin_on_comment_edition',
+    'email_admin_on_comment_deletion'
   );
 
Index: /trunk/admin/template/goto/configuration.tpl
===================================================================
--- /trunk/admin/template/goto/configuration.tpl	(revision 3444)
+++ /trunk/admin/template/goto/configuration.tpl	(revision 3445)
@@ -144,4 +144,30 @@
       </label>
     </li>
+
+    <li>
+      <label>
+        <span class="property">{'Allow users to edit theirs owns comments'|@translate}</span>
+        <input type="checkbox" name="user_can_edit_comment" {if ($comments.user_can_edit_comment)}checked="checked"{/if}>
+      </label>
+    </li>
+    <li>
+      <label>
+        <span class="property">{'Allow users to delete theirs owns comments'|@translate}</span>
+        <input type="checkbox" name="user_can_delete_comment" {if ($comments.user_can_delete_comment)}checked="checked"{/if}>
+      </label>
+    </li>
+    <li>
+      <label>
+        <span class="property">{'Email administrators when a comment is modified'|@translate}</span>
+        <input type="checkbox" name="email_admin_on_comment_edition" {if ($comments.email_admin_on_comment_edition)}checked="checked"{/if}>
+      </label>
+    </li>
+    <li>
+      <label>
+        <span class="property">{'Email administrators when a comment is deleted'|@translate}</span>
+        <input type="checkbox" name="email_admin_on_comment_deletion" {if ($comments.email_admin_on_comment_deletion)}checked="checked"{/if}>
+      </label>
+    </li>
+
   </ul>
 </fieldset>
Index: /trunk/comments.php
===================================================================
--- /trunk/comments.php	(revision 3444)
+++ /trunk/comments.php	(revision 3445)
@@ -27,4 +27,5 @@
 define('PHPWG_ROOT_PATH','./');
 include_once(PHPWG_ROOT_PATH.'include/common.inc.php');
+include_once(PHPWG_ROOT_PATH.'include/functions_comment.inc.php');
 
 // +-----------------------------------------------------------------------+
@@ -143,12 +144,7 @@
 // +-----------------------------------------------------------------------+
 if (isset($_GET['delete']) and is_numeric($_GET['delete'])
-      and !is_adviser() )
+    and (is_admin() || $conf['user_can_delete_comment']))
 {// comments deletion
-  check_status(ACCESS_ADMINISTRATOR);
-  $query = '
-DELETE FROM '.COMMENTS_TABLE.'
-  WHERE id='.$_GET['delete'].'
-;';
-  pwg_query($query);
+  delete_user_comment($_GET['delete']);
 }
 
@@ -164,4 +160,23 @@
 ;';
   pwg_query($query);
+}
+
+if (isset($_GET['edit']) and is_numeric($_GET['edit'])
+    and (is_admin() || $conf['user_can_edit_comment']))
+{
+  if (!empty($_POST['content'])) 
+  {
+    update_user_comment(array('comment_id' => $_GET['edit'], 
+			      'image_id' => $_POST['image_id'],
+			      'content' => $_POST['content']),
+			$_POST['key']
+			); 
+
+    $edit_comment = null;
+  }
+  else 
+  {
+    $edit_comment = $_GET['edit'];
+  }
 }
 
@@ -368,17 +383,37 @@
         );
 
-    if ( is_admin() )
-    {
-      $url = get_root_url().'comments.php'.get_query_string_diff(array('delete','validate'));
-      $tpl_comment['U_DELETE'] = add_url_params($url,
-                          array('delete'=>$comment['comment_id'])
-                         );
-
-      if ($comment['validated'] != 'true')
+    if (can_manage_comment('delete', $comment['author'])) 
+    {
+      $url = get_root_url().'comments.php'
+	.get_query_string_diff(array('delete','validate','edit'));
+      $tpl_comment['U_DELETE'] = 
+	add_url_params($url,
+		       array('delete'=>$comment['comment_id'])
+		       );
+    }
+    if (can_manage_comment('edit', $comment['author']))
+    {
+      $url = get_root_url().'comments.php'
+	.get_query_string_diff(array('edit', 'delete','validate'));
+      $tpl_comment['U_EDIT'] = 
+	add_url_params($url,
+		       array('edit'=>$comment['comment_id'])
+		       );
+      if (isset($edit_comment) and ($comment['comment_id'] == $edit_comment)) 
       {
-        $tpl_comment['U_VALIDATE'] = add_url_params($url,
-                            array('validate'=>$comment['comment_id'])
-                           );
+	$tpl_comment['IN_EDIT'] = true;
+	$key = get_comment_post_key($comment['image_id']);
+	$tpl_comment['KEY'] = $key;
+	$tpl_comment['IMAGE_ID'] = $comment['image_id'];
+	$tpl_comment['CONTENT'] = $comment['content'];
       }
+    }
+
+    if ( is_admin() && $comment['validated'] != 'true')
+    {
+      $tpl_comment['U_VALIDATE'] = 
+	add_url_params($url,
+		       array('validate'=>$comment['comment_id'])
+		       );
     }
     $template->append('comments', $tpl_comment);
Index: /trunk/include/functions_comment.inc.php
===================================================================
--- /trunk/include/functions_comment.inc.php	(revision 3444)
+++ /trunk/include/functions_comment.inc.php	(revision 3445)
@@ -206,3 +206,133 @@
 }
 
+/**
+ * Tries to delete a user comment in the database
+ * only admin can delete all comments
+ * other users can delete their own comments 
+ * so to avoid a new sql request we add author in where clause
+ *
+ * @param comment_id 
+ */
+
+function delete_user_comment($comment_id) {
+  $user_where_clause = '';
+  if (!is_admin())
+  {
+    $user_where_clause = '   AND author = \''.$GLOBALS['user']['username'].'\'';
+  }
+  $query = '
+DELETE FROM '.COMMENTS_TABLE.'
+  WHERE id = '.$comment_id.
+$user_where_clause.'
+;';
+  $result = pwg_query($query);
+  if ($result) {
+    email_admin('delete', array('author' => $GLOBALS['user']['username']));
+  }
+}
+
+/**
+ * Tries to update a user comment in the database
+ * only admin can update all comments
+ * users can edit their own comments if admin allow them
+ * so to avoid a new sql request we add author in where clause
+ *
+ * @param comment_id 
+ * @param post_key
+ * @param content
+ */
+
+function update_user_comment($comment, $post_key) {
+  global $conf;
+
+  $comment_action = 'validate';
+
+  $key = explode( ':', $post_key );
+  if ( count($key)!=2
+       or $key[0]>time()-2 // page must have been retrieved more than 2 sec ago
+       or $key[0]<time()-3600 // 60 minutes expiration
+       or hash_hmac('md5', $key[0].':'.$comment['image_id'], $conf['secret_key']
+		    ) != $key[1]
+       )
+  {
+    $comment_action='reject';
+  }
+
+  if ($comment_action!='reject' and $conf['anti-flood_time']>0 )
+  { // anti-flood system
+    $reference_date = time() - $conf['anti-flood_time'];
+    $query = '
+SELECT id FROM '.COMMENTS_TABLE.'
+  WHERE date > FROM_UNIXTIME('.$reference_date.')
+    AND author = "'.$GLOBALS['user']['username'].'"';
+    if ( mysql_num_rows( pwg_query( $query ) ) > 0 )
+    {
+      array_push( $infos, l10n('comment_anti-flood') );
+      $comment_action='reject';
+    }
+  }
+
+  // perform more spam check
+  $comment_action = 
+    trigger_event('user_comment_check',
+		  $comment_action, 
+		  array_merge($comment, 
+			      array('author' => $GLOBALS['user']['username'])
+			      )
+		  );
+
+  if ( $comment_action!='reject' )
+  {
+    $user_where_clause = '';
+    if (!is_admin())
+    {
+      $user_where_clause = '   AND author = \''.
+	$GLOBALS['user']['username'].'\'';
+    }
+    $query = '
+UPDATE '.COMMENTS_TABLE.'
+  SET content = \''.$comment['content'].'\',
+      validation_date = now()
+  WHERE id = '.$comment['comment_id'].
+$user_where_clause.'
+;';
+    $result = pwg_query($query);
+    if ($result) {
+      email_admin('edit', array('author' => $GLOBALS['user']['username'],
+				'content' => $comment['content']));
+    }
+  }
+}
+
+function email_admin($action, $comment) {
+  global $conf;
+
+  if (!in_array($action, array('edit', 'delete'))
+      or (($action=='edit') and !$conf['email_admin_on_comment_edition'])
+      or (($action=='delete') and !$conf['email_admin_on_comment_deletion']))
+  {
+    return;
+  }
+
+  include_once(PHPWG_ROOT_PATH.'include/functions_mail.inc.php');
+  
+  $keyargs_content = array();
+  $keyargs_content[] = get_l10n_args('Author: %s', $comment['author']);
+  if ($action=='delete') 
+  {
+    $keyargs_content[] = get_l10n_args('This author remove comment with id %d',
+				       $comment['comment_id']
+				       );
+  }
+  else
+  {
+    $keyargs_content[] = get_l10n_args('This author modified following comment:', '');
+    $keyargs_content[] = get_l10n_args('Comment: %s', $comment['content']);
+  }
+  
+  pwg_mail_notification_admins(get_l10n_args('Comment by %s', 
+					     $comment['author']),
+			       $keyargs_content
+			       );
+}
 ?>
Index: /trunk/include/functions_user.inc.php
===================================================================
--- /trunk/include/functions_user.inc.php	(revision 3444)
+++ /trunk/include/functions_user.inc.php	(revision 3445)
@@ -1196,4 +1196,19 @@
 
   return ($user['adviser'] == 'true');
+}
+
+/*
+ * Return if current user can edit/delete a comment
+ * @param action edit/delete
+ * @return bool
+ */
+function can_manage_comment($action, $comment_author) 
+{
+  if (!in_array($action, array('delete','edit'))) {
+    return false;
+  }
+  return (is_admin() || 
+	  (($GLOBALS['user']['username'] == $comment_author) 
+	   && $GLOBALS['conf'][sprintf('user_can_%s_comment', $action)]));
 }
 
Index: /trunk/include/picture_comment.inc.php
===================================================================
--- /trunk/include/picture_comment.inc.php	(revision 3444)
+++ /trunk/include/picture_comment.inc.php	(revision 3445)
@@ -152,14 +152,33 @@
         );
 
+      if (can_manage_comment('delete', $row['author']))
+      {
+        $tpl_comment['U_DELETE'] =
+	  add_url_params($url_self,
+			 array(
+			   'action'=>'delete_comment',
+			   'comment_to_delete'=>$row['id']
+			       )
+			 );
+      }
+      if (can_manage_comment('edit', $row['author']))
+      {
+	$tpl_comment['U_EDIT'] =
+	  add_url_params($url_self,
+			 array(
+			   'action'=>'edit_comment',
+			   'comment_to_edit'=>$row['id']
+			       )
+			 );
+	if (isset($edit_comment) and ($row['id'] == $edit_comment))
+	{
+	  $tpl_comment['IN_EDIT'] = true;
+	  $key = get_comment_post_key($page['image_id']);
+	  $tpl_comment['KEY'] = $key;
+	  $tpl_comment['CONTENT'] = $row['content'];
+	}
+      }
       if (is_admin())
       {
-        $tpl_comment['U_DELETE'] =
-            add_url_params(
-                  $url_self,
-                  array(
-                    'action'=>'delete_comment',
-                    'comment_to_delete'=>$row['id']
-                  )
-              );
 	if ($row['validated'] != 'true')
 	{
@@ -177,5 +196,6 @@
 
   if (!is_a_guest()
-      or (is_a_guest() and $conf['comments_forall']))
+      or (is_a_guest() and $conf['comments_forall'])
+      and (isset($edit_comment) and ($edit_comment != null)))
   {
     $key = get_comment_post_key($page['image_id']);
Index: /trunk/install/config.sql
===================================================================
--- /trunk/install/config.sql	(revision 3444)
+++ /trunk/install/config.sql	(revision 3445)
@@ -5,4 +5,8 @@
 INSERT INTO piwigo_config (param,value,comment) VALUES ('comments_validation','false','administrators validate users comments before becoming visible');
 INSERT INTO piwigo_config (param,value,comment) VALUES ('comments_forall','false','even guest not registered can post comments');
+INSERT INTO piwigo_config (param,value,comment) VALUES ('user_can_delete_comment','false','administrators can allow user delete their own comments');
+INSERT INTO piwigo_config (param,value,comment) VALUES ('user_can_edit_comment','false','administrators can allow user edit their own comments');
+INSERT INTO piwigo_config (param,value,comment) VALUES ('email_admin_on_comment_edition','false','Send an email to the administrators when a comment is modified');
+INSERT INTO piwigo_config (param,value,comment) VALUES ('email_admin_on_comment_deletion','false','Send an email to the administrators when a comment is deleted');
 INSERT INTO piwigo_config (param,value,comment) VALUES ('gallery_locked','false','Lock your gallery temporary for non admin users');
 INSERT INTO piwigo_config (param,value,comment) VALUES ('gallery_title','Piwigo demonstration site','Title at top of each page and for RSS feed');
Index: /trunk/install/db/81-database.php
===================================================================
--- /trunk/install/db/81-database.php	(revision 3445)
+++ /trunk/install/db/81-database.php	(revision 3445)
@@ -0,0 +1,50 @@
+<?php
+// +-----------------------------------------------------------------------+
+// | Piwigo - a PHP based picture gallery                                  |
+// +-----------------------------------------------------------------------+
+// | Copyright(C) 2008-2009 Piwigo Team                  http://piwigo.org |
+// | Copyright(C) 2003-2008 PhpWebGallery Team    http://phpwebgallery.net |
+// | Copyright(C) 2002-2003 Pierrick LE GALL   http://le-gall.net/pierrick |
+// +-----------------------------------------------------------------------+
+// | 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                                          |
+// |                                                                       |
+// | 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
+// | USA.                                                                  |
+// +-----------------------------------------------------------------------+
+
+if (!defined('PHPWG_ROOT_PATH'))
+{
+  die('Hacking attempt!');
+}
+
+$upgrade_description = 'add new email features : 
+users can modify/delete their owns comments';
+
+$query = '
+INSERT INTO '.PREFIX_TABLE.'config (param,value,comment)
+  VALUES (\'user_can_delete_comment\',\'false\',
+    \'administrators can allow user delete their own comments\'),
+  (\'user_can_edit_comment\',\'false\',
+    \'administrators can allow user edit their own comments\'),
+  (\'email_admin_on_comment_edition\',\'false\',
+    \'Send an email to the administrators when a comment is modified\'),
+  (\'email_admin_on_comment_deletion\',\'false\',
+    \'Send an email to the administrators when a comment is deleted\')
+;';
+pwg_query($query);
+
+echo
+"\n"
+. $upgrade_description
+."\n"
+;
+?>
Index: /trunk/language/fr_FR/admin.lang.php
===================================================================
--- /trunk/language/fr_FR/admin.lang.php	(revision 3444)
+++ /trunk/language/fr_FR/admin.lang.php	(revision 3445)
@@ -72,4 +72,8 @@
 $lang['Check for upgrade'] = 'Dernière version ?';
 $lang['Comments for all'] = 'Commentaires pour tous';
+$lang['Allow users to edit theirs owns comments'] = 'Autoriser les utilisateurs à modifier leurs propres commentaires';
+$lang['Allow users to delete theirs owns comments'] = 'Autoriser les utilisateurs à supprimer leurs propres commentaires';
+$lang['Email administrators when a comment is modified'] = 'Notifier les administrateurs quand un commentaire est modifié';
+$lang['Email administrators when a comment is deleted'] = 'Notifier les administrateurs quand un commentaire est supprimé';
 $lang['Controversy'] = 'Controverse';
 $lang['Current name'] = 'Nom courant';
Index: /trunk/language/fr_FR/common.lang.php
===================================================================
--- /trunk/language/fr_FR/common.lang.php	(revision 3444)
+++ /trunk/language/fr_FR/common.lang.php	(revision 3445)
@@ -161,4 +161,5 @@
 $lang['comments'] = 'Commentaires';
 $lang['comments_add'] = 'Ajouter un commentaire';
+$lang['Edit a comment'] = 'Editer un commentaire';
 $lang['created after %s (%s)'] = 'créée après le %s (%s)';
 $lang['created before %s (%s)'] = 'créée avant le %s (%s)';
Index: /trunk/picture.php
===================================================================
--- /trunk/picture.php	(revision 3444)
+++ /trunk/picture.php	(revision 3445)
@@ -26,4 +26,5 @@
 include(PHPWG_ROOT_PATH.'include/section_init.inc.php');
 include_once(PHPWG_ROOT_PATH.'include/functions_picture.inc.php');
+include_once(PHPWG_ROOT_PATH.'include/functions_comment.inc.php');
 
 // Check Access and exit when user status is not ok
@@ -308,17 +309,32 @@
       redirect($url_self);
     }
+    case 'edit_comment' :
+    {
+      if (isset($_GET['comment_to_edit'])
+          and is_numeric($_GET['comment_to_edit'])
+	  and (is_admin() || $conf['user_can_edit_comment']))
+      {
+	if (!empty($_POST['content'])) 
+	{
+	  update_user_comment(array('comment_id' => $_GET['comment_to_edit'], 
+				    'image_id' => $page['image_id'],
+				    'content' => $_POST['content']),
+			      $_POST['key']
+			      ); 
+	  redirect($url_self);
+	} else {
+	  $edit_comment = $_GET['comment_to_edit'];
+	  break;
+	}
+      }
+    }
     case 'delete_comment' :
     {
       if (isset($_GET['comment_to_delete'])
           and is_numeric($_GET['comment_to_delete'])
-          and is_admin() and !is_adviser() )
+	  and (is_admin() || $conf['user_can_delete_comment']))
       {
-        $query = '
-DELETE FROM '.COMMENTS_TABLE.'
-  WHERE id = '.$_GET['comment_to_delete'].'
-;';
-        pwg_query( $query );
+	delete_user_comment($_GET['comment_to_delete']);
       }
-
       redirect($url_self);
     }
@@ -593,5 +609,4 @@
 
 
-
 $page['body_id'] = 'thePicturePage';
 
@@ -948,5 +963,4 @@
 $template->assign( 'ELEMENT_CONTENT', $element_content );
 
-
 // +-----------------------------------------------------------------------+
 // |                               sub pages                               |
Index: /trunk/template/yoga/comment_list.tpl
===================================================================
--- /trunk/template/yoga/comment_list.tpl	(revision 3444)
+++ /trunk/template/yoga/comment_list.tpl	(revision 3445)
@@ -3,5 +3,5 @@
 {foreach from=$comments item=comment name=comment_loop}
 <li>
-	<div class="thumbnailCategory {if $smarty.foreach.comment_loop.index is odd}odd{else}even{/if}">
+  <div class="thumbnailCategory {if $smarty.foreach.comment_loop.index is odd}odd{else}even{/if}">
     {if isset($comment.TN_SRC)}
     <div class="illustration">
@@ -11,11 +11,18 @@
     </div>
     {/if}
-    <div class="description">
-      {if isset($comment.U_DELETE) or isset($comment.U_VALIDATE) }
+    <div class="description" style="height:{if ($comment.IN_EDIT==1)}200{/if}px">
+      {if isset($comment.U_DELETE) or isset($comment.U_VALIDATE) or isset($comment.U_EDIT) }
       <ul class="actions" style="float:right">
         {if isset($comment.U_DELETE)}
         <li>
-          <a href="{$comment.U_DELETE}" title="{'delete this comment'|@translate}">
+          <a href="{$comment.U_DELETE}" title="{'delete this comment'|@translate}" onclick="return confirm('{'Are you sure?'|@translate|@escape:javascript}');">
             <img src="{$ROOT_URL}{$themeconf.icon_dir}/delete.png" class="button" alt="[delete]">
+          </a>
+        </li>
+        {/if}
+        {if isset($comment.U_EDIT) and ($comment.IN_EDIT!=1)}
+        <li>
+          <a class="editComment" href="{$comment.U_EDIT}#edit_comment" title="{'edit this comment'|@translate}">
+            <img src="{$ROOT_URL}{$themeconf.icon_dir}/edit.png" class="button" alt="[edit]">
           </a>
         </li>
@@ -31,11 +38,21 @@
       {/if}
       <span class="author">{$comment.AUTHOR}</span> - <span class="date">{$comment.DATE}</span>
+      {if ($comment.IN_EDIT==1)}
+      <a name="edit_comment"></a>
+      <form  method="post" action="{$comment.U_EDIT}" class="filter" id="editComment">
+	<fieldset>
+	  <legend>{'Edit a comment'|@translate}</legend>
+	  <label>{'comment'|@translate}<textarea name="content" id="contenteditid" rows="5" cols="80">{$comment.CONTENT}</textarea></label>
+	  <input type="hidden" name="key" value="{$comment.KEY}">
+	  <input type="hidden" name="image_id" value="{$comment.IMAGE_ID|default:$current.id}">
+	  <input class="submit" type="submit" value="{'Submit'|@translate}">
+	</fieldset>
+      </form>
+      {else}      
       <blockquote>{$comment.CONTENT}</blockquote>
+      {/if}
     </div>
   </div>
-</li>
-{if isset($comment_separator)}
-<hr>
-{/if}
+<li>
 {/foreach}
 </ul>
Index: /trunk/template/yoga/picture.tpl
===================================================================
--- /trunk/template/yoga/picture.tpl	(revision 3444)
+++ /trunk/template/yoga/picture.tpl	(revision 3445)
@@ -258,5 +258,5 @@
 
 	{if isset($comments)}
-		{include file='comment_list.tpl' comment_separator=true}
+		{include file='comment_list.tpl'}
 	{/if}
 
Index: /trunk/template/yoga/theme/Sylvia/theme.css
===================================================================
--- /trunk/template/yoga/theme/Sylvia/theme.css	(revision 3444)
+++ /trunk/template/yoga/theme/Sylvia/theme.css	(revision 3445)
@@ -1,10 +1,4 @@
 .content div.thumbnailCategory div.illustration { 
 	width:165px !important; /* Usable range 162px-360px , optimal : Thumbnail width + 40px */ 
-}
-.content div.thumbnailCategory { 
-	height: 180px !important; /* Usable range 172px-250px , optimal : Thumbnail height + 30px */ 
-}
-.content div.thumbnailCategory div.description .text { 
-	height: 130px !important; /* -42px than previous one */ 
 }
 #comments div.thumbnailCategory div.illustration { 
@@ -222,5 +216,5 @@
 	margin: 0; 
 	padding:15px 10px 3px 0; 
-	overflow: hidden !important; 
+	overflow-x: hidden !important; 
 }
 .content .thumbnailCategory div.description .text { 
