Index: extensions/Comments_on_Albums/trunk/admin.php
===================================================================
--- extensions/Comments_on_Albums/trunk/admin.php	(revision 26089)
+++ extensions/Comments_on_Albums/trunk/admin.php	(revision 26089)
@@ -0,0 +1,219 @@
+<?php
+/* Code adapted from admin/comments.php */
+defined('COA_ID') or die('Hacking attempt!');
+
+$page['active_menu'] = get_active_menu('comments');
+
+include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
+
+if (isset($_GET['start']) and is_numeric($_GET['start']))
+{
+  $page['start'] = $_GET['start'];
+}
+else
+{
+  $page['start'] = 0;
+}
+
+// +-----------------------------------------------------------------------+
+// | Check Access and exit when user status is not ok                      |
+// +-----------------------------------------------------------------------+
+
+check_status(ACCESS_ADMINISTRATOR);
+
+// +-----------------------------------------------------------------------+
+// |                                actions                                |
+// +-----------------------------------------------------------------------+
+if (!empty($_POST))
+{
+  if (empty($_POST['comments']))
+  {
+    $page['errors'][] = l10n('Select at least one comment');
+  }
+  else
+  {
+    include_once(COA_PATH.'include/functions_comment.inc.php');
+    check_input_parameter('comments', $_POST, true, PATTERN_ID);
+
+    if (isset($_POST['validate']))
+    {
+      validate_user_comment_albums($_POST['comments']);
+
+      $page['infos'][] = l10n_dec(
+        '%d user comment validated', '%d user comments validated',
+        count($_POST['comments'])
+        );
+    }
+
+    if (isset($_POST['reject']))
+    {
+      delete_user_comment_albums($_POST['comments']);
+
+      $page['infos'][] = l10n_dec(
+        '%d user comment rejected', '%d user comments rejected',
+        count($_POST['comments'])
+        );
+    }
+  }
+}
+
+// +-----------------------------------------------------------------------+
+// |                             template init                             |
+// +-----------------------------------------------------------------------+
+
+$template->set_filename('comments', 'comments.tpl');
+$template->set_prefilter('comments', 'coa_admin_add_category_name');
+
+$template->assign('F_ACTION', COA_ADMIN);
+
+// +-----------------------------------------------------------------------+
+// | Tabs                                                                  |
+// +-----------------------------------------------------------------------+
+
+include_once(PHPWG_ROOT_PATH.'admin/include/tabsheet.class.php');
+
+$tabsheet = new tabsheet();
+$tabsheet->set_id('comments');
+$tabsheet->select('albums');
+$tabsheet->assign();
+
+// +-----------------------------------------------------------------------+
+// |                           comments display                            |
+// +-----------------------------------------------------------------------+
+
+$nb_total = 0;
+$nb_pending = 0;
+
+$query = '
+SELECT
+    COUNT(*) AS counter,
+    validated
+  FROM '.COA_TABLE.'
+  GROUP BY validated
+;';
+$result = pwg_query($query);
+while ($row = pwg_db_fetch_assoc($result))
+{
+  $nb_total+= $row['counter'];
+
+  if ('false' == $row['validated'])
+  {
+    $nb_pending = $row['counter'];
+  }
+}
+
+if (!isset($_GET['filter']) and $nb_pending > 0)
+{
+  $page['filter'] = 'pending';
+}
+else
+{
+  $page['filter'] = 'all';
+}
+
+if (isset($_GET['filter']) and 'pending' == $_GET['filter'])
+{
+  $page['filter'] = 'pending';
+}
+
+$template->assign(
+  array(
+    'nb_total' => $nb_total,
+    'nb_pending' => $nb_pending,
+    'filter' => $page['filter'],
+    )
+  );
+
+$where_clauses = array('1=1');
+
+if ('pending' == $page['filter'])
+{
+  $where_clauses[] = 'validated=\'false\'';
+}
+
+$query = '
+SELECT
+    com.id,
+    com.category_id,
+    com.date,
+    com.author,
+    u.'.$conf['user_fields']['username'].' AS username,
+    com.content,
+    cat.name,
+    img.id AS image_id,
+    img.path,
+    com.validated
+  FROM '.COA_TABLE.' AS com
+    LEFT JOIN '.CATEGORIES_TABLE.' AS cat
+      ON cat.id = com.category_id
+    LEFT JOIN '.USERS_TABLE.' AS u
+      ON u.'.$conf['user_fields']['id'].' = com.author_id
+    LEFT JOIN '.USER_CACHE_CATEGORIES_TABLE.' AS ucc
+      ON ucc.cat_id = com.category_id AND ucc.user_id = '.$user['id'].'
+    LEFT JOIN '.IMAGES_TABLE.' AS img
+      ON img.id = ucc.user_representative_picture_id
+  WHERE '.implode(' AND ', $where_clauses).'
+  ORDER BY com.date DESC
+  LIMIT '.$page['start'].', '.$conf['comments_page_nb_comments'].'
+;';
+$result = pwg_query($query);
+
+while ($row = pwg_db_fetch_assoc($result))
+{
+  $thumb = DerivativeImage::thumb_url(
+    array(
+      'id'=>$row['image_id'],
+      'path'=>$row['path'],
+      )
+   );
+
+  if (empty($row['author_id']))
+  {
+    $author_name = $row['author'];
+  }
+  else
+  {
+    $author_name = stripslashes($row['username']);
+  }
+
+  $template->append(
+    'comments',
+    array(
+      'ID' => $row['id'],
+      'U_PICTURE' => get_root_url().'admin.php?page=album-'.$row['category_id'],
+      'CATEGORY_NAME' => trigger_change('render_category_name', $row['name']),
+      'TN_SRC' => $thumb,
+      'AUTHOR' => trigger_change('render_comment_author', $author_name),
+      'DATE' => format_date($row['date'], true),
+      'CONTENT' => trigger_change('render_comment_content', $row['content'], 'album'),
+      'IS_PENDING' => ('false' == $row['validated']),
+      )
+    );
+}
+
+// +-----------------------------------------------------------------------+
+// |                            navigation bar                             |
+// +-----------------------------------------------------------------------+
+
+$navbar = create_navigation_bar(
+  get_root_url().'admin.php'.get_query_string_diff(array('start')),
+  ('pending' == $page['filter'] ? $nb_pending : $nb_total),
+  $page['start'],
+  $conf['comments_page_nb_comments']
+  );
+
+$template->assign('navbar', $navbar);
+
+// +-----------------------------------------------------------------------+
+// |                           sending html code                           |
+// +-----------------------------------------------------------------------+
+
+$template->assign_var_from_handle('ADMIN_CONTENT', 'comments');
+
+
+function coa_admin_add_category_name($content)
+{
+  $search = '<img src="{$comment.TN_SRC}">';
+  $add = '<br>{$comment.CATEGORY_NAME}';
+  return str_replace($search, $search.$add, $content);
+}
Index: extensions/Comments_on_Albums/trunk/include/coa_admin_comments.php
===================================================================
--- extensions/Comments_on_Albums/trunk/include/coa_admin_comments.php	(revision 25632)
+++ 	(revision )
@@ -1,173 +1,0 @@
-<?php
-/* Code adapted from admin/comments.php */
-if (!defined('PHPWG_ROOT_PATH')) die('Hacking attempt!');
-
-global $template, $conf, $user;
-load_language('plugin.lang', COA_PATH);
-
-// +-----------------------------------------------------------------------+
-// |                               tabsheet                                |
-// +-----------------------------------------------------------------------+
-include_once(PHPWG_ROOT_PATH.'admin/include/tabsheet.class.php');
-
-if (isset($_GET['section']) and $_GET['section'] == 'albums')
-{
-  $page['tab'] = 'albums';
-} 
-else 
-{
-  $page['tab'] = 'pictures';
-}
-
-$tabsheet = new tabsheet();
-$tabsheet->add('pictures', l10n('Comments on photos'), get_root_url().'admin.php?page=comments');
-$tabsheet->add('albums', l10n('Comments on albums'), get_root_url().'admin.php?page=comments&amp;section=albums');
-$tabsheet->select($page['tab']);
-$tabsheet->assign();
-
-
-if ($page['tab'] == 'albums') 
-{
-  // clear template sended by original page
-  $template->clear_assign(array('ADMIN_CONTENT', 'comments', 'LIST', 'F_ACTION'));
-
-  // +-----------------------------------------------------------------------+
-  // |                                actions                                |
-  // +-----------------------------------------------------------------------+
-  if (!empty($_POST)) 
-  {
-    if (empty($_POST['comments']))
-    {
-      array_push(
-        $page['errors'],
-        l10n('Select at least one comment')
-        );
-    }
-    else
-    {
-      include_once(COA_PATH.'include/functions_comment.inc.php'); // custom functions
-      check_input_parameter('comments', $_POST, true, PATTERN_ID);
-
-      if (isset($_POST['validate_albums'])) 
-      {
-        validate_user_comment_albums($_POST['comments']);
-
-        array_push(
-          $page['infos'], 
-          l10n_dec(
-            '%d user comment validated', '%d user comments validated',
-            count($_POST['comments'])
-            )
-          );
-      }
-
-      if (isset($_POST['reject_albums'])) 
-      {
-        delete_user_comment_albums($_POST['comments']);
-
-        array_push(
-          $page['infos'], 
-          l10n_dec(
-            '%d user comment rejected', '%d user comments rejected',
-            count($_POST['comments'])
-            )
-          );
-      }
-    }
-  }
-
-  // +-----------------------------------------------------------------------+
-  // |                             template init                             |
-  // +-----------------------------------------------------------------------+
-
-  $template->set_filename('comments', dirname(__FILE__) .'/../template/admin_comments.tpl');
-
-  $template->assign(
-    array(
-      'F_ACTION' => get_root_url().'admin.php?page=comments&amp;section=albums'
-      )
-    );
-    
-  if (count($page['infos']) != 0) 
-  {
-    $template->assign('infos', $page['infos']);
-  }
-
-  // +-----------------------------------------------------------------------+
-  // |                           comments display                            |
-  // +-----------------------------------------------------------------------+
-  $list = array();
-
-  $query = '
-SELECT 
-    com.id, 
-    com.category_id, 
-    com.date, 
-    com.author,
-    u.'.$conf['user_fields']['username'].' AS username, 
-    com.content, 
-    cat.name,
-    img.id AS image_id,
-    img.path
-  FROM '.COA_TABLE.' AS com
-    LEFT JOIN '.CATEGORIES_TABLE.' AS cat
-      ON cat.id = com.category_id
-    LEFT JOIN '.USERS_TABLE.' AS u
-      ON u.'.$conf['user_fields']['id'].' = com.author_id
-    LEFT JOIN '.USER_CACHE_CATEGORIES_TABLE.' AS ucc 
-      ON ucc.cat_id = com.category_id AND ucc.user_id = '.$user['id'].'
-    LEFT JOIN '.IMAGES_TABLE.' AS img
-      ON img.id = ucc.user_representative_picture_id
-  WHERE validated = \'false\'
-  ORDER BY com.date DESC
-;';
-  $result = pwg_query($query);
-
-  while ($row = pwg_db_fetch_assoc($result)) 
-  {
-    // author
-    if (empty($row['author_id'])) 
-    {
-      $author_name = $row['author'];
-    } 
-    else 
-    {
-      $author_name = stripslashes($row['username']);
-    }
-    
-    // thumbnail
-    $row['thumb'] = DerivativeImage::thumb_url(
-      array(
-        'id'=>$row['image_id'],
-        'path'=>$row['path'],
-        )
-     );
-
-    // comment content
-    $template->append(
-      'comments', 
-      array(
-        'ID' => $row['id'],
-        'CAT_URL' => PHPWG_ROOT_PATH.'admin.php?page=album-'.$row['category_id'],
-        'CAT_NAME' => trigger_event('render_category_name', $row['name']),
-        'TN_SRC' => $row['thumb'],
-        'AUTHOR' => trigger_event('render_comment_author', $author_name),
-        'DATE' => format_date($row['date'], true),
-        'CONTENT' => trigger_event('render_comment_content', $row['content'], 'album'),
-        )
-      );
-
-    array_push($list, $row['id']);
-  }
-
-  $template->assign('LIST', implode(',', $list));
-
-  // +-----------------------------------------------------------------------+
-  // |                           sending html code                           |
-  // +-----------------------------------------------------------------------+
-
-  $template->assign_var_from_handle('ADMIN_CONTENT', 'comments');
-
-}
-
-?>
Index: extensions/Comments_on_Albums/trunk/include/coa_admin_intro.php
===================================================================
--- extensions/Comments_on_Albums/trunk/include/coa_admin_intro.php	(revision 25632)
+++ 	(revision )
@@ -1,59 +1,0 @@
-<?php
-/* adds info about comments count on main admin page, uses javascript */
-if (!defined('PHPWG_ROOT_PATH')) die('Hacking attempt!');
-
-global $template;
-
-// comments count
-$query = '
-SELECT COUNT(*)
-  FROM '.COA_TABLE.'
-;';
-list($nb_comments) = pwg_db_fetch_row(pwg_query($query));
-
-$template->assign(
-  'DB_COMMENTS_ALBUMS', 
-  l10n_dec('%d comment', '%d comments', $nb_comments)
-  );
-
-// unvalidated comments
-$query = '
-SELECT COUNT(*)
-  FROM '.COA_TABLE.'
-  WHERE validated=\'false\'
-;';
-list($nb_comments) = pwg_db_fetch_row(pwg_query($query));
-
-if ($nb_comments > 0) 
-{
-  $template->assign(
-    'unvalidated_albums', 
-    array(
-      'URL' => PHPWG_ROOT_PATH.'admin.php?page=comments&amp;section=albums',
-      'INFO' => sprintf(l10n('%d waiting for validation'), $nb_comments)
-      )
-    );
-}
-
-$template->set_prefilter('intro', 'coa_admin_intro_prefilter');
-
-function coa_admin_intro_prefilter($content, &$smarty)
-{
-  $search = '(<a href="{$unvalidated.URL}">{$unvalidated.INFO}</a>)';
-        
-  $replace = $search.'
-        {/if}
-        [{\'Photos\'|@translate}]
-      </li>
-      <li>
-        {$DB_COMMENTS_ALBUMS}
-        {if isset($unvalidated_albums)}
-        (<a href="{$unvalidated_albums.URL}">{$unvalidated_albums.INFO}</a>)
-        {/if}
-        [{\'Albums\'|@translate}]
-      {if true}';
-
-  return str_replace($search, $replace, $content);
-}
-
-?>
Index: extensions/Comments_on_Albums/trunk/include/coa_albums.php
===================================================================
--- extensions/Comments_on_Albums/trunk/include/coa_albums.php	(revision 25632)
+++ extensions/Comments_on_Albums/trunk/include/coa_albums.php	(revision 26089)
@@ -1,7 +1,7 @@
 <?php
 /* Code adapted from include/picture_comment.inc.php and picture.php */
-if (!defined('PHPWG_ROOT_PATH')) die('Hacking attempt!');
-
-global $conf, $user;
+defined('COA_ID') or die('Hacking attempt!');
+
+global $template, $page, $conf, $pwg_loaded_plugins, $user;
 
 // +-----------------------------------------------------------------------+
@@ -12,8 +12,8 @@
 $url_self = duplicate_index_url(array(
   'category' => array(
-    'id' => $category['id'], 
-    'name' => $category['name'], 
+    'id' => $category['id'],
+    'name' => $category['name'],
     'permalink' => $category['permalink']
-    ), 
+    ),
   array('start')
   ));
@@ -23,17 +23,17 @@
 // |                                actions                                |
 // +-----------------------------------------------------------------------+
-if (isset($_GET['action'])) 
+if (isset($_GET['action']))
 {
-  switch ($_GET['action']) 
-  {
-    case 'edit_comment' : 
-    {
-      include_once(COA_PATH.'include/functions_comment.inc.php'); // custom fonctions
+  switch ($_GET['action'])
+  {
+    case 'edit_comment' :
+    {
+      include_once(COA_PATH.'include/functions_comment.inc.php');
       check_input_parameter('comment_to_edit', $_GET, false, PATTERN_ID);
       $author_id = get_comment_author_id_albums($_GET['comment_to_edit']);
 
-      if (can_manage_comment('edit', $author_id)) 
-      {
-        if (!empty($_POST['content'])) 
+      if (can_manage_comment('edit', $author_id))
+      {
+        if (!empty($_POST['content']))
         {
           check_pwg_token();
@@ -42,9 +42,10 @@
               'comment_id' => $_GET['comment_to_edit'],
               'category_id' => $category['id'],
-              'content' => $_POST['content']
+              'content' => $_POST['content'],
+              'website_url' => @$_POST['website_url'],
               ),
             $_POST['key']
             );
-          
+
           $perform_redirect = false;
           switch ($comment_action)
@@ -69,23 +70,25 @@
           }
           unset($_POST['content']);
-        } 
-        else 
+        }
+        else
         {
           $edit_comment = $_GET['comment_to_edit'];
         }
+
+        $template->assign('DISPLAY_COMMENTS_BLOCK', true);
         break;
       }
     }
-    case 'delete_comment' : 
+    case 'delete_comment' :
     {
       check_pwg_token();
-      
-      include_once(COA_PATH.'include/functions_comment.inc.php'); // custom fonctions
-      
+
+      include_once(COA_PATH.'include/functions_comment.inc.php');
+
       check_input_parameter('comment_to_delete', $_GET, false, PATTERN_ID);
-      
+
       $author_id = get_comment_author_id_albums($_GET['comment_to_delete']);
 
-      if (can_manage_comment('delete', $author_id)) 
+      if (can_manage_comment('delete', $author_id))
       {
         delete_user_comment_albums($_GET['comment_to_delete']);
@@ -94,15 +97,15 @@
       redirect($url_self);
     }
-    case 'validate_comment' : 
+    case 'validate_comment' :
     {
       check_pwg_token();
-      
-      include_once(COA_PATH.'include/functions_comment.inc.php'); // custom fonctions
-      
+
+      include_once(COA_PATH.'include/functions_comment.inc.php');
+
       check_input_parameter('comment_to_validate', $_GET, false, PATTERN_ID);
-      
+
       $author_id = get_comment_author_id_albums($_GET['comment_to_validate']);
 
-      if (can_manage_comment('validate', $author_id)) 
+      if (can_manage_comment('validate', $author_id))
       {
         validate_user_comment_albums($_GET['comment_to_validate']);
@@ -118,11 +121,11 @@
 // |                            insert comment                             |
 // +-----------------------------------------------------------------------+
-if ($category['commentable'] and isset($_POST['content'])) 
+if ($category['commentable'] and isset($_POST['content']))
 {
-  if (is_a_guest() and !$conf['comments_forall']) 
+  if (is_a_guest() and !$conf['comments_forall'])
   {
     die('Session expired');
   }
-  
+
   $comm = array(
     'author' => trim( @$_POST['author'] ),
@@ -133,31 +136,31 @@
    );
 
-  include_once(COA_PATH.'include/functions_comment.inc.php'); // custom fonctions
-  
+  include_once(COA_PATH.'include/functions_comment.inc.php');
+
   $comment_action = insert_user_comment_albums($comm, @$_POST['key'], $page['errors']);
 
-  switch ($comment_action) 
+  switch ($comment_action)
   {
     case 'moderate':
-      array_push($page['infos'], l10n('An administrator must authorize your comment before it is visible.'));
+      $page['infos'][] = l10n('An administrator must authorize your comment before it is visible.');
     case 'validate':
-      array_push($page['infos'], l10n('Your comment has been registered'));
+      $page['infos'][] = l10n('Your comment has been registered');
       break;
     case 'reject':
       set_status_header(403);
-      array_push($page['errors'], l10n('Your comment has NOT been registered because it did not pass the validation rules'));
+      $page['errors'][] = l10n('Your comment has NOT been registered because it did not pass the validation rules');
       break;
     default:
       trigger_error('Invalid comment action '.$comment_action, E_USER_WARNING);
   }
-    
+
   // allow plugins to notify what's going on
   trigger_action( 'user_comment_insertion',
       array_merge($comm, array('action'=>$comment_action) )
     );
-    
+
   $template->assign('DISPLAY_COMMENTS_BLOCK', true);
-} 
-else if (isset($_POST['content'])) 
+}
+else if (isset($_POST['content']))
 {
   set_status_header(403);
@@ -169,11 +172,16 @@
 // |                           display comments                            |
 // +-----------------------------------------------------------------------+
-if ($category['commentable']) 
+if ($category['commentable'])
 {
-  if (!is_admin()) 
+  if (isset($_GET['coa_open']))
+  {
+    $template->assign('DISPLAY_COMMENTS_BLOCK', true);
+  }
+
+  if (!is_admin())
   {
     $validated_clause = " AND validated = 'true'";
-  } 
-  else 
+  }
+  else
   {
     $validated_clause = null;
@@ -182,5 +190,5 @@
   // number of comments for this category
   $query = '
-SELECT 
+SELECT
     COUNT(*) AS nb_comments
   FROM '.COA_TABLE.'
@@ -190,20 +198,22 @@
   $row = pwg_db_fetch_assoc(pwg_query($query));
 
-  // navigation bar creation, can't use $_GET['start'] because used by thumbnails navigation bar
-  if (isset($_GET['start_comments'])) 
+  // navigation bar creation
+  // can't use $_GET['start'] because used by thumbnails navigation bar
+  if (isset($_GET['start_comments']))
   {
     $page['start_comments'] = $_GET['start_comments'];
-  } 
-  else 
+  }
+  else
   {
     $page['start_comments'] = 0;
   }
-  include_once(COA_PATH.'include/functions.inc.php'); // custom fonctions
-
-  $navigation_bar = create_comment_navigation_bar(
-    duplicate_index_url(array(), array('start')),
+
+  $navigation_bar = create_navigation_bar(
+    add_url_params(duplicate_index_url(array(), array('start_comments')), array('coa_open'=>null)),
     $row['nb_comments'],
     $page['start_comments'],
-    $conf['nb_comment_page']
+    $conf['nb_comment_page'],
+    false,
+    'start_comments'
     );
 
@@ -215,5 +225,5 @@
     );
 
-  if ($row['nb_comments'] > 0) 
+  if ($row['nb_comments'] > 0)
   {
     // comments order (get, session, conf)
@@ -225,8 +235,8 @@
 
     $template->assign(array(
-      'COMMENTS_ORDER_URL' => add_url_params( duplicate_index_url(), array('comments_order'=> ($comments_order == 'ASC' ? 'DESC' : 'ASC') ) ),
+      'COMMENTS_ORDER_URL' => add_url_params(duplicate_index_url(), array('comments_order'=> ($comments_order == 'ASC' ? 'DESC' : 'ASC'), 'coa_open'=>null ) ),
       'COMMENTS_ORDER_TITLE' => $comments_order == 'ASC' ? l10n('Show latest comments first') : l10n('Show oldest comments first'),
       ));
-      
+
     // get comments
     $query = '
@@ -235,10 +245,9 @@
     com.author,
     com.author_id,
-    u.'.$conf['user_fields']['username'].' AS username,
     u.'.$conf['user_fields']['email'].' AS user_email,
+    com.date,
+    com.category_id,
+    com.website_url,
     com.email,
-    com.date,
-    com.website_url,
-    com.category_id,
     com.content,
     com.validated
@@ -253,5 +262,5 @@
     $result = pwg_query($query);
 
-    while ($row = pwg_db_fetch_assoc($result)) 
+    while ($row = pwg_db_fetch_assoc($result))
     {
       if ($row['author'] == 'guest')
@@ -259,5 +268,5 @@
         $row['author'] = l10n('guest');
       }
-      
+
       $email = null;
       if (!empty($row['user_email']))
@@ -269,5 +278,5 @@
         $email = $row['email'];
       }
-      
+
       // comment content
       $tpl_comment = array(
@@ -275,13 +284,13 @@
         'AUTHOR' => trigger_event('render_comment_author', $row['author']),
         'DATE' => format_date($row['date'], true),
+        'CONTENT' => trigger_event('render_comment_content', $row['content'], 'album'),
         'WEBSITE_URL' => $row['website_url'],
-        'CONTENT' => trigger_event('render_comment_content', $row['content'], 'album'),
         );
-      
+
       // rights
-      if (can_manage_comment('delete', $row['author_id'])) 
+      if (can_manage_comment('delete', $row['author_id']))
       {
         $tpl_comment['U_DELETE'] = add_url_params(
-          $url_self, 
+          $url_self,
           array(
             'action' => 'delete_comment',
@@ -291,8 +300,8 @@
           );
       }
-      if (can_manage_comment('edit', $row['author_id'])) 
+      if (can_manage_comment('edit', $row['author_id']))
       {
         $tpl_comment['U_EDIT'] = add_url_params(
-          $url_self, 
+          $url_self,
           array(
             'action' => 'edit_comment',
@@ -300,5 +309,5 @@
             )
           );
-        if (isset($edit_comment) and ($row['id'] == $edit_comment)) 
+        if (isset($edit_comment) and ($row['id'] == $edit_comment))
         {
           $tpl_comment['IN_EDIT'] = true;
@@ -307,4 +316,5 @@
           $tpl_comment['CONTENT'] = $row['content'];
           $tpl_comment['PWG_TOKEN'] = get_pwg_token();
+          $tpl_comment['U_CANCEL'] = $url_self;
         }
       }
@@ -312,9 +322,9 @@
       {
         $tpl_comment['EMAIL'] = $email;
-        
-        if ($row['validated'] != 'true') 
+
+        if ($row['validated'] != 'true')
         {
           $tpl_comment['U_VALIDATE'] = add_url_params(
-            $url_self, 
+            $url_self,
             array(
               'action' => 'validate_comment',
@@ -325,5 +335,5 @@
         }
       }
-      
+
       $template->append('comments', $tpl_comment);
     }
@@ -332,41 +342,49 @@
   // comment form
   $show_add_comment_form = true;
-  if (isset($edit_comment)) 
+  if (isset($edit_comment))
   {
     $show_add_comment_form = false;
   }
-  if (is_a_guest() and !$conf['comments_forall']) 
+  if (is_a_guest() and !$conf['comments_forall'])
   {
     $show_add_comment_form = false;
   }
 
-  if ($show_add_comment_form) 
+  if ($show_add_comment_form)
   {
     $key = get_ephemeral_key(3, $category['id']);
-    
-    $template->assign('comment_add', 
-      array(
+
+    $tpl_var = array(
         'F_ACTION' =>         $url_self,
         'KEY' =>              $key,
-        'CONTENT' =>          stripslashes(@$_POST['content']),
+        'CONTENT' =>          '',
         'SHOW_AUTHOR' =>      !is_classic_user(),
         'AUTHOR_MANDATORY' => $conf['comments_author_mandatory'],
-        'AUTHOR' =>           stripslashes(@$_POST['author']),
-        'WEBSITE_URL' =>      stripslashes(@$_POST['website_url']),
+        'AUTHOR' =>           '',
+        'WEBSITE_URL' =>      '',
         'SHOW_EMAIL' =>       !is_classic_user() or empty($user['email']),
         'EMAIL_MANDATORY' =>  $conf['comments_email_mandatory'],
-        'EMAIL' =>            stripslashes(@$_POST['email']), 
-        )
-      );
-  }
-  
+        'EMAIL' =>            '',
+        );
+
+    if ('reject'==@$comment_action)
+    {
+      foreach (array('content', 'author', 'website_url', 'email') as $k)
+      {
+        $tpl_var[strtoupper($k)] = htmlspecialchars( stripslashes(@$_POST[$k]) );
+      }
+    }
+    $template->assign('comment_add', $tpl_var);
+  }
+
   // template
   $template->assign(array(
-    'COA_PATH' => COA_PATH, // for css
-    'COA_ABSOLUTE_PATH' => dirname(__FILE__) .'/../', // for template
+    'COA_PATH' => COA_PATH,
+    'COA_ABSOLUTE_PATH' => realpath(COA_PATH) . '/',
     ));
-  
-  $template->set_filename('comments_on_albums', dirname(__FILE__) .'/../template/albums.tpl');
-  if (isset($pwg_loaded_plugins['rv_tscroller']) AND count($page['navigation_bar']) != 0)
+
+  $template->set_filename('comments_on_albums', realpath(COA_PATH . 'template/albums.tpl'));
+
+  if (isset($pwg_loaded_plugins['rv_tscroller']) and count($page['navigation_bar']) != 0)
   {
     $template->assign('COMMENTS_ON_TOP', true);
@@ -378,4 +396,2 @@
   }
 }
-
-?>
Index: extensions/Comments_on_Albums/trunk/include/coa_comments_page.php
===================================================================
--- extensions/Comments_on_Albums/trunk/include/coa_comments_page.php	(revision 25632)
+++ extensions/Comments_on_Albums/trunk/include/coa_comments_page.php	(revision 26089)
@@ -1,6 +1,7 @@
-<?php 
+<?php
 /* inspired by comments.php */
-if (!defined('PHPWG_ROOT_PATH')) die('Hacking attempt!');
-load_language('plugin.lang', COA_PATH);
+defined('COA_ID') or die('Hacking attempt!');
+
+global $template, $page, $conf, $user;
 
 // +-----------------------------------------------------------------------+
@@ -10,17 +11,16 @@
 $template->set_prefilter('comments', 'coa_add_button');
 
-function coa_add_button($content, &$smarty) 
-{    
+function coa_add_button($content, &$smarty)
+{
   $search ='<form class="filter" action="{$F_ACTION}" method="get">';
-  $replacement = '
-<form class="filter">
+
+  $add = '
 <fieldset>
-<legend>{\'Display comments on\'|@translate}</legend>
-<span style="font-size:1.1em;"><a href="comments.php" {if $COA_MODE=="photos"}style="font-weight:bold;"{/if}>{\'Photos\'|@translate}</a> | 
-<a href="comments.php?display_mode=albums" {if $COA_MODE=="albums"}style="font-weight:bold;"{/if}>{\'Albums\'|@translate}</a></span>
-</fieldset>
-</form>';
-
-  return str_replace($search, $replacement.$search, $content);
+  <legend>{\'Display comments on\'|@translate}</legend>
+  <span style="font-size:1.1em;"><a href="comments.php" {if $COA_MODE=="photos"}style="font-weight:bold;"{/if}>{\'Photos\'|@translate}</a> |
+  <a href="comments.php?display_mode=albums" {if $COA_MODE=="albums"}style="font-weight:bold;"{/if}>{\'Albums\'|@translate}</a></span>
+</fieldset>';
+
+  return str_replace($search, $add.$search, $content);
 }
 
@@ -29,147 +29,172 @@
 //                        comments on albums page                          |
 // +-----------------------------------------------------------------------+
-if ( isset($_GET['display_mode']) and $_GET['display_mode'] == 'albums' ) 
-{
-  include_once(COA_PATH.'include/functions_comment.inc.php'); // custom functions
-  
-  // reset some template vars
-  $template->clear_assign(array('comments', 'navbar', 'sort_by_options'));
-  
-  // sort_by : database fields proposed for sorting comments list
-  $sort_by = array(
-    'date' => l10n('comment date'),
-    'category_id' => l10n('album')
-    );
-  $template->assign('sort_by_options', $sort_by);
-  
-  // clean where_clauses from unknown column
-  foreach ($page['where_clauses'] as &$cond)
-  {
-    if (strpos($cond, 'ic.image_id') !== false)
-    {
-      $cond = get_sql_condition_FandF(array(
+if (!isset($_GET['display_mode']) or $_GET['display_mode'] != 'albums')
+{
+  return;
+}
+
+$url_self = PHPWG_ROOT_PATH.'comments.php'
+  .get_query_string_diff(array('edit_albums','delete_albums','validate_albums','pwg_token'));
+
+// reset some template vars
+$template->clear_assign(array('F_ACTION', 'comments', 'navbar', 'sort_by_options'));
+
+// sort_by : database fields proposed for sorting comments list
+global $sort_by;
+$sort_by = array(
+  'date' => l10n('comment date'),
+  'category_id' => l10n('Album')
+  );
+$template->assign(array(
+  'F_ACTION' => PHPWG_ROOT_PATH.'comments.php?display_mode=albums',
+  'sort_by_options' => $sort_by,
+  ));
+
+// clean where_clauses from unknown column
+foreach ($page['where_clauses'] as &$cond)
+{
+  if (strpos($cond, 'ic.image_id') !== false)
+  {
+    $cond = get_sql_condition_FandF(
+      array(
         'forbidden_categories' => 'category_id',
         'visible_categories' => 'category_id'
         ),
-        '', true);
-    }
-  }
-  unset($cond);
-
-  // +-----------------------------------------------------------------------+
-  // |                         comments management                           |
-  // +-----------------------------------------------------------------------+
-  $comment_id = null;
-  $action = null;
-
-  $actions = array('delete_albums', 'validate_albums', 'edit_albums'); // different indexes to not interfer with the main process
-  foreach ($actions as $loop_action) 
-  {
-    if (isset($_GET[$loop_action])) 
-    {
-      $action = $loop_action;
-      check_input_parameter($action, $_GET, false, PATTERN_ID);
-      $comment_id = $_GET[$action];
-      break;
-    }
-  }
-
-  if (isset($action)) 
-  {
-    $comment_author_id = get_comment_author_id_albums($comment_id);
-    
-    if (can_manage_comment(str_replace('_albums', null, $action), $comment_author_id)) 
-    {
-      $perform_redirect = false;
-
-      if ('delete_albums' == $action) 
+      '', true
+      );
+  }
+}
+unset($cond);
+
+// +-----------------------------------------------------------------------+
+// |                         comments management                           |
+// +-----------------------------------------------------------------------+
+
+$comment_id = null;
+$action = null;
+
+$actions = array('delete_albums', 'validate_albums', 'edit_albums');
+foreach ($actions as $loop_action)
+{
+  if (isset($_GET[$loop_action]))
+  {
+    $action = $loop_action;
+    check_input_parameter($action, $_GET, false, PATTERN_ID);
+    $comment_id = $_GET[$action];
+    break;
+  }
+}
+
+if (isset($action))
+{
+  include_once(COA_PATH.'include/functions_comment.inc.php');
+
+  $comment_author_id = get_comment_author_id_albums($comment_id);
+
+  if (can_manage_comment(str_replace('_albums', null, $action), $comment_author_id))
+  {
+    $perform_redirect = false;
+
+    if ('delete_albums' == $action)
+    {
+      check_pwg_token();
+      delete_user_comment_albums($comment_id);
+      $perform_redirect = true;
+    }
+    if ('validate_albums' == $action)
+    {
+      check_pwg_token();
+      validate_user_comment_albums($comment_id);
+      $perform_redirect = true;
+    }
+    if ('edit_albums' == $action)
+    {
+      if (!empty($_POST['content']))
       {
         check_pwg_token();
-        delete_user_comment_albums($comment_id);
-        $perform_redirect = true;
-      }
-      if ('validate_albums' == $action) 
-      {
-        check_pwg_token();
-        validate_user_comment_albums($comment_id);
-        $perform_redirect = true;
-      }
-      if ('edit_albums' == $action) 
-      {
-        if (!empty($_POST['content'])) 
+        $comment_action = update_user_comment_albums(
+          array(
+            'comment_id' => $_GET['edit_albums'],
+            'category_id' => $_POST['image_id'],
+            'content' => $_POST['content'],
+            'website_url' => @$_POST['website_url'],
+            ),
+          $_POST['key']
+          );
+
+        switch ($comment_action)
         {
-          check_pwg_token();
-          update_user_comment_albums(
-            array(
-              'comment_id' => $_GET['edit_albums'],
-              'category_id' => $_POST['image_id'],
-              'content' => $_POST['content']
-              ), 
-            $_POST['key']
-            );
-          
-          $perform_redirect = true;
-        } 
-        else 
-        {
-          $edit_comment = $_GET['edit_albums'];
+          case 'moderate':
+            $_SESSION['page_infos'][] = l10n('An administrator must authorize your comment before it is visible.');
+          case 'validate':
+            $_SESSION['page_infos'][] = l10n('Your comment has been registered');
+            $perform_redirect = true;
+            break;
+          case 'reject':
+            $_SESSION['page_errors'][] = l10n('Your comment has NOT been registered because it did not pass the validation rules');
+            break;
+          default:
+            trigger_error('Invalid comment action '.$comment_action, E_USER_WARNING);
         }
       }
-      if ($perform_redirect) 
+      else
       {
-        $redirect_url = 
-          PHPWG_ROOT_PATH
-          .'comments.php'
-          .get_query_string_diff(array('delete_albums','validate_albums','edit_albums','pwg_token'));
-        
-        redirect($redirect_url);
+        $edit_comment = $_GET['edit_albums'];
       }
     }
-  }
-
-  // +-----------------------------------------------------------------------+
-  // |                            navigation bar                             |
-  // +-----------------------------------------------------------------------+
-  if (isset($_GET['start']) and is_numeric($_GET['start'])) 
-  {
-    $start = $_GET['start'];
-  } 
-  else 
-  {
-    $start = 0;
-  }
-
-  $query = '
+    if ($perform_redirect)
+    {
+      redirect($url_self);
+    }
+  }
+}
+
+// +-----------------------------------------------------------------------+
+// |                            navigation bar                             |
+// +-----------------------------------------------------------------------+
+
+if (isset($_GET['start']) and is_numeric($_GET['start']))
+{
+  $start = $_GET['start'];
+}
+else
+{
+  $start = 0;
+}
+
+$query = '
 SELECT COUNT(DISTINCT(com.id))
-  FROM '.COA_TABLE.' AS com
-  LEFT JOIN '.USERS_TABLE.' As u
+  FROM '.CATEGORIES_TABLE.' AS cat
+  INNER JOIN '.COA_TABLE.' AS com
+    ON cat.id = com.category_id
+  LEFT JOIN '.USERS_TABLE.' AS u
     ON u.'.$conf['user_fields']['id'].' = com.author_id
   WHERE '.implode('
     AND ', $page['where_clauses']).'
 ;';
-  list($counter) = pwg_db_fetch_row(pwg_query($query));
-
-  $url = PHPWG_ROOT_PATH
-      .'comments.php'
-    .get_query_string_diff(array('start','delete_albums','validate_albums','edit_albums','pwg_token'));
-    
-  $navbar = create_navigation_bar(
-    $url, 
-    $counter, 
-    $start, 
-    $page['items_number'], 
-    ''
-    );
-  
-  $template->assign('navbar', $navbar);
-
-  // +-----------------------------------------------------------------------+
-  // |                        last comments display                          |
-  // +-----------------------------------------------------------------------+
-  $comments = array();
-  $element_ids = array();
-  $category_ids = array();
-
-  $query = '
+list($counter) = pwg_db_fetch_row(pwg_query($query));
+
+$url = PHPWG_ROOT_PATH.'comments.php'
+  .get_query_string_diff(array('start','delete_albums','validate_albums','edit_albums','pwg_token'));
+
+$navbar = create_navigation_bar(
+  $url,
+  $counter,
+  $start,
+  $page['items_number'],
+  ''
+  );
+
+$template->assign('navbar', $navbar);
+
+// +-----------------------------------------------------------------------+
+// |                        last comments display                          |
+// +-----------------------------------------------------------------------+
+
+$comments = array();
+$element_ids = array();
+$category_ids = array();
+
+$query = '
 SELECT
     com.id AS comment_id,
@@ -184,5 +209,7 @@
     com.content,
     com.validated
-  FROM '.COA_TABLE.' AS com
+  FROM '.CATEGORIES_TABLE.' AS cat
+    INNER JOIN '.COA_TABLE.' AS com
+      ON cat.id = com.category_id
     LEFT JOIN '.USERS_TABLE.' As u
       ON u.'.$conf['user_fields']['id'].' = com.author_id
@@ -198,28 +225,28 @@
     com.validated
   ORDER BY '.$page['sort_by'].' '.$page['sort_order'];
-if ('all' != $page['items_number']) 
-{
-  $query.= '
-  LIMIT '.$page['items_number'].' OFFSET '.$start;
-}
+  if ('all' != $page['items_number'])
+  {
+    $query.= '
+    LIMIT '.$page['items_number'].' OFFSET '.$start;
+  }
 $query.= '
 ;';
-  $result = pwg_query($query);
-
-  while ($row = pwg_db_fetch_assoc($result)) 
-  {
-    array_push($comments, $row);
-    array_push($element_ids, $row['category_id']);
-  }
-
-  if (count($comments) > 0) 
-  {
-    // retrieving category informations
-    $query = '
-SELECT 
-    cat.id, 
-    cat.name, 
-    cat.permalink, 
-    cat.uppercats, 
+$result = pwg_query($query);
+
+while ($row = pwg_db_fetch_assoc($result))
+{
+  $comments[] = $row;
+  $element_ids[] = $row['category_id'];
+}
+
+if (count($comments) > 0)
+{
+  // retrieving category informations
+  $query = '
+SELECT
+    cat.id,
+    cat.name,
+    cat.permalink,
+    cat.uppercats,
     com.id as comment_id,
     img.id AS image_id,
@@ -228,5 +255,5 @@
     LEFT JOIN '.COA_TABLE.' AS com
       ON com.category_id = cat.id
-    LEFT JOIN '.USER_CACHE_CATEGORIES_TABLE.' AS ucc 
+    LEFT JOIN '.USER_CACHE_CATEGORIES_TABLE.' AS ucc
       ON ucc.cat_id = cat.id AND ucc.user_id = '.$user['id'].'
     LEFT JOIN '.IMAGES_TABLE.' AS img
@@ -236,117 +263,109 @@
       'forbidden_categories' => 'cat.id',
       'visible_categories' => 'cat.id'
-      ), 
+      ),
     'WHERE'
     ).'
     AND cat.id IN ('.implode(',', $element_ids).')
 ;';
-    $categories = hash_from_query($query, 'comment_id');
-
-    foreach ($comments as $comment) 
-    {
-      // source of the thumbnail picture
-      $comment['src_image'] = new SrcImage($categories[$comment['comment_id']]);
-    
-      // category url
-      $comment['cat_url'] = duplicate_index_url(
+  $categories = hash_from_query($query, 'comment_id');
+
+  foreach ($comments as $comment)
+  {
+    // source of the thumbnail picture
+    $comment['src_image'] = new SrcImage($categories[$comment['comment_id']]);
+
+    // category url
+    $comment['cat_url'] = make_index_url(
+      array(
+        'section' => 'categories',
+        'category' => $categories[$comment['comment_id']],
+        )
+      );
+
+    $email = null;
+    if (!empty($comment['user_email']))
+    {
+      $email = $comment['user_email'];
+    }
+    else if (!empty($comment['email']))
+    {
+      $email = $comment['email'];
+    }
+
+    // comment content
+    $tpl_comment = array(
+      'ID' => $comment['comment_id'],
+      'U_PICTURE' => $comment['cat_url'],
+      'src_image' => $comment['src_image'],
+      'ALT' => trigger_event('render_category_name', $categories[$comment['comment_id']]['name']),
+      'AUTHOR' => trigger_event('render_comment_author', $comment['author']),
+      'WEBSITE_URL' => $comment['website_url'],
+      'DATE' => format_date($comment['date'], true),
+      'CONTENT' => trigger_event('render_comment_content', $comment['content'], 'album'),
+      );
+
+    if (is_admin())
+    {
+      $tpl_comment['EMAIL'] = $email;
+    }
+
+    // rights
+    if (can_manage_comment('delete', $comment['author_id']))
+    {
+      $tpl_comment['U_DELETE'] = add_url_params(
+        $url_self,
         array(
-          'category' => array(
-            'id' => $categories[$comment['comment_id']]['id'], 
-            'name' => $categories[$comment['comment_id']]['name'], 
-            'permalink' => $categories[$comment['comment_id']]['permalink'],
-            ),
-          array('start')
+          'delete_albums' => $comment['comment_id'],
+          'pwg_token' => get_pwg_token(),
           )
         );
-        
-      $email = null;
-      if (!empty($comment['user_email']))
+    }
+    if (can_manage_comment('edit', $comment['author_id']))
+    {
+      $tpl_comment['U_EDIT'] = add_url_params(
+        $url_self,
+        array(
+          'edit_albums' => $comment['comment_id'],
+          )
+        );
+
+      if (isset($edit_comment) and ($comment['comment_id'] == $edit_comment))
       {
-        $email = $comment['user_email'];
+        $tpl_comment['IN_EDIT'] = true;
+        $key = get_ephemeral_key(2, $comment['category_id']);
+        $tpl_comment['KEY'] = $key;
+        $tpl_comment['IMAGE_ID'] = $comment['category_id'];
+        $tpl_comment['CONTENT'] = $comment['content'];
+        $tpl_comment['PWG_TOKEN'] = get_pwg_token();
+        $tpl_comment['U_CANCEL'] = $url_self;
       }
-      else if (!empty($comment['email']))
+    }
+    if (can_manage_comment('validate', $comment['author_id']))
+    {
+      if ('true' != $comment['validated'])
       {
-        $email = $comment['email'];
-      }
-      
-      // comment content
-      $tpl_comment = array(
-        'ID' => $comment['comment_id'],
-        'U_PICTURE' => $comment['cat_url'],
-        'ALT' => trigger_event('render_category_name', $categories[$comment['comment_id']]['name']),
-        'src_image' => $comment['src_image'],
-        'AUTHOR' => trigger_event('render_comment_author', $comment['author']),
-        'WEBSITE_URL' => $comment['website_url'],
-        'DATE' => format_date($comment['date'], true),
-        'CONTENT' => trigger_event('render_comment_content', $comment['content'], 'album'),
-        );
-        
-      if (is_admin())
-      {
-        $tpl_comment['EMAIL'] = $email;
-      }
-
-      // rights
-      if (can_manage_comment('delete', $comment['author_id'])) 
-      {
-        $tpl_comment['U_DELETE'] = add_url_params(
-          $url, 
+        $tpl_comment['U_VALIDATE'] = add_url_params(
+          $url_self,
           array(
-            'delete_albums' => $comment['comment_id'],
+            'validate_albums'=> $comment['comment_id'],
             'pwg_token' => get_pwg_token(),
             )
           );
       }
-      if (can_manage_comment('edit', $comment['author_id'])) 
-      {
-        $tpl_comment['U_EDIT'] = add_url_params(
-          $url, 
-          array(
-            'edit_albums' => $comment['comment_id'],
-            )
-          );
-
-        if (isset($edit_comment) and ($comment['comment_id'] == $edit_comment)) 
-        {
-          $tpl_comment['IN_EDIT'] = true;
-          $key = get_ephemeral_key(2, $comment['category_id']);
-          $tpl_comment['KEY'] = $key;
-          $tpl_comment['IMAGE_ID'] = $comment['category_id'];
-          $tpl_comment['CONTENT'] = $comment['content'];
-          $tpl_comment['PWG_TOKEN'] = get_pwg_token();
-        }
-      }
-      if (can_manage_comment('validate', $comment['author_id'])) 
-      {
-        if ('true' != $comment['validated']) 
-        {
-          $tpl_comment['U_VALIDATE'] = add_url_params(
-            $url, 
-            array(
-              'validate_albums'=> $comment['comment_id'],
-              'pwg_token' => get_pwg_token(),
-              )
-            );
-        }
-      }
-      
-      $template->append('comments', $tpl_comment);
-    }
-  }
-
-  // +-----------------------------------------------------------------------+
-  // |                            template                                   |
-  // +-----------------------------------------------------------------------+
-  // add a line to display category name
-  $template->set_prefilter('comments', 'coa_change_comments_list');
-  
-  function coa_change_comments_list($content, &$smarty) {
-    $search[0] = '<a href="{$comment.U_PICTURE}">';
-    $replacement[0] = $search[0].'{$comment.ALT}<br/>';
-    $search[1] = '<input type="submit"';
-    $replacement[1] = '<input type=hidden name=display_mode value=albums>'.$search[1];
-    return str_replace($search, $replacement, $content);
-  }
-}
-
-?>
+    }
+
+    $template->append('comments', $tpl_comment);
+  }
+}
+
+// +-----------------------------------------------------------------------+
+// |                            template                                   |
+// +-----------------------------------------------------------------------+
+// add a line to display category name
+$template->set_prefilter('comments', 'coa_change_comments_list');
+
+function coa_change_comments_list($content, &$smarty) {
+  $search = '<a href="{$comment.U_PICTURE}">';
+  $replacement = $search.'{$comment.ALT}<br>';
+  return str_replace($search, $replacement, $content);
+}
Index: extensions/Comments_on_Albums/trunk/include/events.inc.php
===================================================================
--- extensions/Comments_on_Albums/trunk/include/events.inc.php	(revision 26089)
+++ extensions/Comments_on_Albums/trunk/include/events.inc.php	(revision 26089)
@@ -0,0 +1,105 @@
+<?php
+defined('COA_ID') or die('Hacking attempt!');
+
+function coa_albums()
+{
+  global $page;
+
+  if (!empty($page['section']) and $page['section'] == 'categories' and
+      isset($page['category']) and $page['body_id'] == 'theCategoryPage'
+    )
+  {
+    trigger_notify('loc_begin_coa');
+    include(COA_PATH . 'include/coa_albums.php');
+  }
+}
+
+function coa_comments()
+{
+  include(COA_PATH . 'include/coa_comments_page.php');
+}
+
+function coa_admin_intro()
+{
+  global $page;
+
+  if ($page['page'] == 'intro')
+  {
+    global $template;
+
+    // comments count
+    $query = '
+SELECT COUNT(*)
+  FROM '.COA_TABLE.'
+;';
+    list($nb_comments) = pwg_db_fetch_row(pwg_query($query));
+
+    $template->assign(
+      'DB_COMMENTS_ALBUMS',
+      l10n_dec('%d comment on album', '%d comments on albums', $nb_comments)
+      );
+
+    if ($nb_comments)
+    {
+      // unvalidated comments
+      $query = '
+SELECT COUNT(*)
+  FROM '.COA_TABLE.'
+  WHERE validated=\'false\'
+;';
+      list($nb_comments) = pwg_db_fetch_row(pwg_query($query));
+
+      if ($nb_comments > 0)
+      {
+        $template->assign(array(
+          'U_COMMENTS_ALBUMS' => COA_ADMIN,
+          'NB_PENDING_COMMENTS_ALBUMS' => $nb_comments,
+          ));
+      }
+    }
+
+    $template->set_prefilter('intro', 'coa_admin_intro_prefilter');
+  }
+}
+
+function coa_admin_intro_prefilter($content)
+{
+  $search = '(<a href="{$U_COMMENTS}">{\'%d waiting for validation\'|translate:$NB_PENDING_COMMENTS}</a>){/if}';
+
+  $add = '
+      </li>
+    {/if}
+    {if isset($DB_COMMENTS_ALBUMS)}
+      <li>
+        {$DB_COMMENTS_ALBUMS}{if isset($NB_PENDING_COMMENTS_ALBUMS)} (<a href="{$U_COMMENTS_ALBUMS}">{\'%d waiting for validation\'|translate:$NB_PENDING_COMMENTS_ALBUMS}</a>){/if}';
+
+  return str_replace($search, $search.$add, $content);
+}
+
+
+function coa_tabsheet_before_select($sheets, $id)
+{
+  if ($id == 'comments')
+  {
+    $sheets['']['caption'] = l10n('Comments on photos');
+    $sheets['']['url'] = get_root_url().'admin.php?page=comments';
+
+    $sheets['albums'] = array(
+      'caption' => l10n('Comments on albums'),
+      'url' => COA_ADMIN,
+      );
+  }
+
+  return $sheets;
+}
+
+function coa_register_stuffs_module($modules)
+{
+  $modules[] = array(
+    'path' => COA_PATH . '/stuffs_module',
+    'name' => l10n('Last comments on albums'),
+    'description' => l10n('Display last posted comments on albums'),
+    );
+
+  return $modules;
+}
Index: extensions/Comments_on_Albums/trunk/include/functions.inc.php
===================================================================
--- extensions/Comments_on_Albums/trunk/include/functions.inc.php	(revision 25632)
+++ 	(revision )
@@ -1,59 +1,0 @@
-<?php
-/* This is from include/functions.inc.php but adapted for Comments On Albums */
-
-/**
- * return an array which will be sent to template to display navigation bar
- */
-function create_comment_navigation_bar($url, $nb_element, $start, $nb_element_page)
-{
-  global $conf;
-
-  $navbar = array();
-  $pages_around = $conf['paginate_pages_around'];
-  $start_str = (strpos($url, '?')===false ? '?':'&amp;').'start_comments=';
-
-  if (!isset($start) or !is_numeric($start) or (is_numeric($start) and $start < 0))
-  {
-    $start = 0;
-  }
-
-  // navigation bar useful only if more than one page to display !
-  if ($nb_element > $nb_element_page)
-  {
-    $cur_page = ceil($start / $nb_element_page) + 1;
-    $maximum = ceil($nb_element / $nb_element_page);
-    $previous = $start - $nb_element_page;
-    $next = $start + $nb_element_page;
-    $last = ($maximum - 1) * $nb_element_page;
-
-    $navbar['CURRENT_PAGE'] = $cur_page;
-
-    // link to first page and previous page?
-    if ($cur_page != 1)
-    {
-      $navbar['URL_FIRST'] = $url;
-      $navbar['URL_PREV'] = $url.($previous > 0 ? $start_str.$previous : '');
-    }
-    // link on next page and last page?
-    if ($cur_page != $maximum)
-    {
-      $navbar['URL_NEXT'] = $url.$start_str.$next;
-      $navbar['URL_LAST'] = $url.$start_str.$last;
-    }
-
-    // pages to display
-    $navbar['pages'] = array();
-    $navbar['pages'][1] = $url;
-    $navbar['pages'][$maximum] = $url.$start_str.$last;
-
-    for ($i = max($cur_page - $pages_around , 2), $stop = min($cur_page + $pages_around + 1, $maximum);
-         $i < $stop; $i++)
-    {
-      $navbar['pages'][$i] = $url.$start_str.(($i - 1) * $nb_element_page);
-    }
-    ksort($navbar['pages']);
-  }
-  return $navbar;
-}
-
-?>
Index: extensions/Comments_on_Albums/trunk/include/functions_comment.inc.php
===================================================================
--- extensions/Comments_on_Albums/trunk/include/functions_comment.inc.php	(revision 25632)
+++ extensions/Comments_on_Albums/trunk/include/functions_comment.inc.php	(revision 26089)
@@ -1,17 +1,17 @@
 <?php
 /* This is a copy of include/functions_comment.inc.php but adapted for Comments On Albums */
+defined('COA_ID') or die('Hacking attempt!');
 
 include_once(PHPWG_ROOT_PATH.'include/functions_comment.inc.php');
-add_event_handler('user_comment_check_albums', 'user_comment_check',
-  EVENT_HANDLER_PRIORITY_NEUTRAL, 2);
 
 /**
- * Tries to insert a user comment in the database and returns one of :
- * validate, moderate, reject
- * @param array comm contains author, content, category_id
- * @param string key secret key sent back to the browser
- * @param array infos out array of messages
+ * Tries to insert a user comment and returns action to perform.
+ *
+ * @param array &$comm
+ * @param string $key secret key sent back to the browser
+ * @param array &$infos output array of error messages
+ * @return string validate, moderate, reject
  */
-function insert_user_comment_albums( &$comm, $key, &$infos )
+function insert_user_comment_albums(&$comm, $key, &$infos)
 {
   global $conf, $user;
@@ -37,9 +37,9 @@
   if (!is_classic_user())
   {
-    if ( empty($comm['author']) )
+    if (empty($comm['author']))
     {
       if ($conf['comments_author_mandatory'])
       {
-        array_push($infos, l10n('Username is mandatory') );
+        $infos[] = l10n('Username is mandatory');
         $comment_action='reject';
       }
@@ -47,16 +47,17 @@
     }
     $comm['author_id'] = $conf['guest_id'];
-    // if a guest try to use the name of an already existing user, he must be
-    // rejected
-    if ( $comm['author'] != 'guest' )
+    // if a guest try to use the name of an already existing user,
+    // he must be rejected
+    if ($comm['author'] != 'guest')
     {
       $query = '
 SELECT COUNT(*) AS user_exists
   FROM '.USERS_TABLE.'
-  WHERE '.$conf['user_fields']['username']." = '".addslashes($comm['author'])."'";
+  WHERE '.$conf['user_fields']['username']." = '".addslashes($comm['author'])."'
+;";
       $row = pwg_db_fetch_assoc( pwg_query( $query ) );
-      if ( $row['user_exists'] == 1 )
+      if ($row['user_exists'] == 1)
       {
-        array_push($infos, l10n('This login is already used by another user') );
+        $infos[] = l10n('This login is already used by another user');
         $comment_action='reject';
       }
@@ -69,15 +70,17 @@
   }
 
-  if ( empty($comm['content']) )
-  { // empty comment content
+  // content
+  if (empty($comm['content']))
+  {
     $comment_action='reject';
   }
 
-  if ( !verify_ephemeral_key(@$key, $comm['category_id']) )
+  // key
+  if (!verify_ephemeral_key(@$key, $comm['category_id']))
   {
     $comment_action='reject';
     $_POST['cr'][] = 'key';
   }
-  
+
   // website
   if (!empty($comm['website_url']))
@@ -89,9 +92,9 @@
     if (!url_check_format($comm['website_url']))
     {
-      array_push($infos, l10n('Your website URL is invalid'));
+      $infos[] = l10n('Your website URL is invalid');
       $comment_action='reject';
     }
   }
-  
+
   // email
   if (empty($comm['email']))
@@ -103,5 +106,5 @@
     else if ($conf['comments_email_mandatory'])
     {
-      array_push($infos, l10n('Email address is missing. Please specify an email address.') );
+      $infos[] = l10n('Email address is missing. Please specify an email address.');
       $comment_action='reject';
     }
@@ -109,8 +112,8 @@
   else if (!email_check_format($comm['email']))
   {
-    array_push($infos, l10n('mail address must be like xxx@yyy.eee (example : jack@altern.org)'));
+    $infos[] = l10n('mail address must be like xxx@yyy.eee (example : jack@altern.org)');
     $comment_action='reject';
   }
-  
+
   // anonymous id = ip address
   $ip_components = explode('.', $comm['ip']);
@@ -138,7 +141,7 @@
 
     list($counter) = pwg_db_fetch_row(pwg_query($query));
-    if ( $counter > 0 )
-    {
-      array_push( $infos, l10n('Anti-flood system : please wait for a moment before trying to post another comment') );
+    if ($counter > 0)
+    {
+      $infos[] = l10n('Anti-flood system : please wait for a moment before trying to post another comment');
       $comment_action='reject';
     }
@@ -146,9 +149,9 @@
 
   // perform more spam check
-  $comment_action = trigger_event('user_comment_check_albums',
+  $comment_action = trigger_event('user_comment_check',
       $comment_action, $comm
     );
 
-  if ( $comment_action!='reject' )
+  if ($comment_action!='reject')
   {
     $query = '
@@ -168,7 +171,5 @@
   )
 ';
-
     pwg_query($query);
-
     $comm['id'] = pwg_db_insert_id(COA_TABLE);
 
@@ -191,10 +192,8 @@
       if ('moderate' == $comment_action)
       {
-        $keyargs_content[] = get_l10n_args('', '');
         $keyargs_content[] = get_l10n_args('(!) This comment requires validation', '');
       }
 
-      pwg_mail_notification_admins
-      (
+      pwg_mail_notification_admins(
         get_l10n_args('Comment by %s', stripslashes($comm['author']) ),
         $keyargs_content
@@ -202,16 +201,17 @@
     }
   }
+
   return $comment_action;
 }
 
 /**
- * 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
+ * Tries to delete a (or more) user comment.
+ *    only admin can delete all comments
+ *    other users can delete their own comments
  *
- * @param comment_id
+ * @param int|int[] $comment_id
+ * @return bool false if nothing deleted
  */
-function delete_user_comment_albums($comment_id) 
+function delete_user_comment_albums($comment_id)
 {
   $user_where_clause = '';
@@ -220,10 +220,14 @@
     $user_where_clause = '   AND author_id = \''.$GLOBALS['user']['id'].'\'';
   }
-  
+
   if (is_array($comment_id))
+  {
     $where_clause = 'id IN('.implode(',', $comment_id).')';
+  }
   else
+  {
     $where_clause = 'id = '.$comment_id;
-  
+  }
+
   $query = '
 DELETE FROM '.COA_TABLE.'
@@ -231,26 +235,27 @@
 $user_where_clause.'
 ;';
-  $result = pwg_query($query);
-  
-  if ($result) 
-  {
-    email_admin('delete', 
+
+  if (pwg_db_changes(pwg_query($query)))
+  {
+    email_admin('delete',
                 array('author' => $GLOBALS['user']['username'],
                       'comment_id' => $comment_id
                   ));
-  }
-  
-  trigger_action('user_comment_deletion', $comment_id, 'category');
+    trigger_action('user_comment_deletion', $comment_id, 'category');
+
+    return true;
+  }
+
+  return false;
 }
 
 /**
- * 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
+ * Tries to update a user comment
+ *    only admin can update all comments
+ *    users can edit their own comments if admin allow them
  *
- * @param comment_id
- * @param post_key
- * @param content
+ * @param array $comment
+ * @param string $post_key secret key sent back to the browser
+ * @return string validate, moderate, reject
  */
 function update_user_comment_albums($comment, $post_key)
@@ -260,5 +265,5 @@
   $comment_action = 'validate';
 
-  if ( !verify_ephemeral_key($post_key, $comment['category_id']) )
+  if (!verify_ephemeral_key($post_key, $comment['category_id']))
   {
     $comment_action='reject';
@@ -275,5 +280,5 @@
   // perform more spam check
   $comment_action =
-    trigger_event('user_comment_check_albums',
+    trigger_event('user_comment_check',
       $comment_action,
       array_merge($comment,
@@ -282,4 +287,18 @@
       );
 
+  // website
+  if (!empty($comment['website_url']))
+  {
+    if (!preg_match('/^https?/i', $comment['website_url']))
+    {
+      $comment['website_url'] = 'http://'.$comment['website_url'];
+    }
+    if (!url_check_format($comment['website_url']))
+    {
+      $page['errors'][] = l10n('Your website URL is invalid');
+      $comment_action='reject';
+    }
+  }
+
   if ( $comment_action!='reject' )
   {
@@ -294,4 +313,5 @@
 UPDATE '.COA_TABLE.'
   SET content = \''.$comment['content'].'\',
+      website_url = '.(!empty($comment['website_url']) ? '\''.$comment['website_url'].'\'' : 'NULL').',
       validated = \''.($comment_action=='validate' ? 'true':'false').'\',
       validation_date = '.($comment_action=='validate' ? 'NOW()':'NULL').'
@@ -300,7 +320,7 @@
 ;';
     $result = pwg_query($query);
-    
+
     // mail admin and ask to validate the comment
-    if ($result and $conf['email_admin_on_comment_validation'] and 'moderate' == $comment_action) 
+    if ($result and $conf['email_admin_on_comment_validation'] and 'moderate' == $comment_action)
     {
       include_once(PHPWG_ROOT_PATH.'include/functions_mail.inc.php');
@@ -314,10 +334,8 @@
         get_l10n_args('', ''),
         get_l10n_args('Manage this user comment: %s', $comment_url),
-        get_l10n_args('', ''),
         get_l10n_args('(!) This comment requires validation', ''),
       );
 
-      pwg_mail_notification_admins
-      (
+      pwg_mail_notification_admins(
         get_l10n_args('Comment by %s', stripslashes($GLOBALS['user']['username']) ),
         $keyargs_content
@@ -331,8 +349,15 @@
     }
   }
-  
+
   return $comment_action;
 }
 
+/**
+ * Returns the author id of a comment
+ *
+ * @param int $comment_id
+ * @param bool $die_on_error
+ * @return int
+ */
 function get_comment_author_id_albums($comment_id, $die_on_error=true)
 {
@@ -355,5 +380,5 @@
     }
   }
-  
+
   list($author_id) = pwg_db_fetch_row($result);
 
@@ -362,14 +387,19 @@
 
 /**
- * Tries to validate a user comment in the database
- * @param int or array of int comment_id
+ * Tries to validate a user comment.
+ *
+ * @param int|int[] $comment_id
  */
 function validate_user_comment_albums($comment_id)
 {
   if (is_array($comment_id))
+  {
     $where_clause = 'id IN('.implode(',', $comment_id).')';
+  }
   else
+  {
     $where_clause = 'id = '.$comment_id;
-    
+  }
+
   $query = '
 UPDATE '.COA_TABLE.'
@@ -379,6 +409,5 @@
 ;';
   pwg_query($query);
-  
+
   trigger_action('user_comment_validation', $comment_id, 'category');
 }
-?>
Index: extensions/Comments_on_Albums/trunk/include/install.inc.php
===================================================================
--- extensions/Comments_on_Albums/trunk/include/install.inc.php	(revision 25632)
+++ 	(revision )
@@ -1,44 +1,0 @@
-<?php
-defined('PHPWG_ROOT_PATH') or die('Hacking attempt!');
-
-function coa_install() 
-{
-  global $prefixeTable;
-  
-  pwg_query('
-CREATE TABLE IF NOT EXISTS `' . $prefixeTable . 'comments_categories` (
-  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
-  `category_id` mediumint(8) unsigned NOT NULL DEFAULT 0,
-  `date` datetime NOT NULL DEFAULT "0000-00-00 00:00:00",
-  `author` varchar(255) DEFAULT NULL,
-  `email` varchar(255) DEFAULT NULL,
-  `author_id` smallint(5) DEFAULT NULL,
-  `anonymous_id` varchar(45) NOT NULL,
-  `website_url` varchar(255) DEFAULT NULL,
-  `content` longtext,
-  `validated` enum("true","false") NOT NULL DEFAULT "false",
-  `validation_date` datetime DEFAULT NULL,
-  PRIMARY KEY (`id`),
-  KEY `comments_i2` (`validation_date`),
-  KEY `comments_i1` (`category_id`)
-) ENGINE=MyISAM DEFAULT CHARSET=utf8');
-  
-  $result = pwg_query('SHOW COLUMNS FROM `' . $prefixeTable . 'comments_categories` LIKE "anonymous_id";');
-  if (!pwg_db_num_rows($result))
-  {      
-    pwg_query('ALTER TABLE `' . $prefixeTable . 'comments_categories` ADD `anonymous_id` VARCHAR( 45 ) DEFAULT NULL;');
-  }
-  
-  $result = pwg_query('SHOW COLUMNS FROM `' . $prefixeTable . 'comments_categories` LIKE "email";');
-  if (!pwg_db_num_rows($result))
-  {      
-    pwg_query('ALTER TABLE `' . $prefixeTable . 'comments_categories` 
-      ADD `email` varchar(255) DEFAULT NULL,
-      ADD `website_url` varchar(255) DEFAULT NULL,
-      ADD KEY `comments_i2` (`validation_date`),
-      ADD KEY `comments_i1` (`category_id`)
-      ;');
-  }
-}
-
-?>
Index: extensions/Comments_on_Albums/trunk/language/en_UK/plugin.lang.php
===================================================================
--- extensions/Comments_on_Albums/trunk/language/en_UK/plugin.lang.php	(revision 25632)
+++ extensions/Comments_on_Albums/trunk/language/en_UK/plugin.lang.php	(revision 26089)
@@ -6,4 +6,7 @@
 $lang['Last comments on albums'] = 'Last comments on albums';
 $lang['Display last posted comments on albums'] = 'Display last posted comments on albums';
+$lang['%d comment on album'] = '%d comment on album';
+$lang['%d comments on albums'] = '%d comments on albums';
+$lang['Photos'] = 'Photos';
 
 ?>
Index: extensions/Comments_on_Albums/trunk/language/fr_FR/plugin.lang.php
===================================================================
--- extensions/Comments_on_Albums/trunk/language/fr_FR/plugin.lang.php	(revision 25632)
+++ extensions/Comments_on_Albums/trunk/language/fr_FR/plugin.lang.php	(revision 26089)
@@ -6,3 +6,7 @@
 $lang['Last comments on albums'] = 'Derniers commentaires sur les albums';
 $lang['Display last posted comments on albums'] = 'Affiche les derniers commentaires postés sur les albums';
+$lang['%d comment on album'] = '%d commentaire sur un album';
+$lang['%d comments on albums'] = '%d commentaires sur albums';
+$lang['Photos'] = 'Photos';
+
 ?>
Index: extensions/Comments_on_Albums/trunk/main.inc.php
===================================================================
--- extensions/Comments_on_Albums/trunk/main.inc.php	(revision 25632)
+++ extensions/Comments_on_Albums/trunk/main.inc.php	(revision 26089)
@@ -9,5 +9,5 @@
 */
 
-if (!defined('PHPWG_ROOT_PATH')) die('Hacking attempt!');
+defined('PHPWG_ROOT_PATH') or die('Hacking attempt!');
 
 if (mobile_theme())
@@ -18,8 +18,6 @@
 global $prefixeTable;
 
-// +-----------------------------------------------------------------------+
-//          Global variables
-// +-----------------------------------------------------------------------+
-defined('COA_ID') or define('COA_ID', basename(dirname(__FILE__)));
+
+define('COA_ID',      basename(dirname(__FILE__)));
 define('COA_PATH' ,   PHPWG_PLUGINS_PATH . COA_ID . '/');
 define('COA_TABLE' ,  $prefixeTable . 'comments_categories');
@@ -28,117 +26,33 @@
 
 
-// +-----------------------------------------------------------------------+
-//          Triggers
-// +-----------------------------------------------------------------------+
 add_event_handler('init', 'coa_init');
+
 function coa_init()
 {
   global $user, $conf, $pwg_loaded_plugins;
-  
+
+  include_once(COA_PATH . 'maintain.inc.php');
+  $maintain = new Comments_on_Albums_maintain(COA_ID);
+  $maintain->autoUpdate(COA_VERSION, 'install');
+
   // luciano doesn't use comments
   // incompatible with dynamic display of Stripped & Collumns
   if ($user['theme'] == 'luciano' or $user['theme'] == 'stripped_black_bloc') return;
-  
-  // apply upgrade if needed
-  if (
-    COA_VERSION == 'auto' or
-    $pwg_loaded_plugins[COA_ID]['version'] == 'auto' or
-    version_compare($pwg_loaded_plugins[COA_ID]['version'], COA_VERSION, '<')
-  )
-  {
-    // call install function
-    include_once(COA_PATH . 'include/install.inc.php');
-    coa_install();
-    
-    // update plugin version in database
-    if ( $pwg_loaded_plugins[COA_ID]['version'] != 'auto' and COA_VERSION != 'auto' )
-    {
-      $query = '
-UPDATE '. PLUGINS_TABLE .'
-SET version = "'. COA_VERSION .'"
-WHERE id = "'. COA_ID .'"';
-      pwg_query($query);
-      
-      $pwg_loaded_plugins[COA_ID]['version'] = COA_VERSION;
-      
-      if (defined('IN_ADMIN'))
-      {
-        $_SESSION['page_infos'][] = 'Comments on Albums updated to version '. COA_VERSION;
-      }
-    }
-  }
-  
-  // add events handlers
+
+  include_once(COA_PATH . 'include/events.inc.php');
+
   if (defined('IN_ADMIN'))
   {
+    add_event_handler('tabsheet_before_select', 'coa_tabsheet_before_select', EVENT_HANDLER_PRIORITY_NEUTRAL, 2);
     add_event_handler('loc_begin_admin_page', 'coa_admin_intro');
-    add_event_handler('loc_end_admin', 'coa_admin_comments');
   }
   else
   {
     add_event_handler('loc_after_page_header', 'coa_albums');
-    add_event_handler('loc_after_page_header', 'coa_comments_page');
-  }  
+    add_event_handler('loc_end_comments', 'coa_comments');
+  }
+
   add_event_handler('get_stuffs_modules', 'coa_register_stuffs_module');
+
+  load_language('plugin.lang', COA_PATH);
 }
-
-
-// +-----------------------------------------------------------------------+
-//          Functions
-// +-----------------------------------------------------------------------+
-
-function coa_albums() 
-{
-  global $template, $page, $conf, $pwg_loaded_plugins;
-  
-  if ( !empty($page['section']) AND $page['section'] == 'categories' AND isset($page['category']) AND $page['body_id'] == 'theCategoryPage' )
-  {    
-    trigger_action('loc_begin_coa');
-    include(COA_PATH . 'include/coa_albums.php');
-  }
-}
-
-function coa_comments_page() 
-{
-  global $template, $page, $conf, $user;
-  
-  if (isset($page['body_id']) AND $page['body_id'] == 'theCommentsPage') 
-  {
-    include(COA_PATH . 'include/coa_comments_page.php');
-  }
-}
-
-function coa_admin_intro() 
-{
-  global $page;
-  
-  if ($page['page'] == 'intro') 
-  {  
-    include(COA_PATH . 'include/coa_admin_intro.php');
-  } 
-}
-
-function coa_admin_comments() 
-{
-  global $page;
-  
-  if ($page['page'] == 'comments') 
-  {  
-    include(COA_PATH . 'include/coa_admin_comments.php');
-  }
-}
-
-function coa_register_stuffs_module($modules) 
-{
-  load_language('plugin.lang', COA_PATH);
-  
-  array_push($modules, array(
-    'path' => COA_PATH . '/stuffs_module',
-    'name' => l10n('Last comments on albums'),
-    'description' => l10n('Display last posted comments on albums'),
-  ));
-
-  return $modules;
-}
-
-?>
Index: extensions/Comments_on_Albums/trunk/maintain.inc.php
===================================================================
--- extensions/Comments_on_Albums/trunk/maintain.inc.php	(revision 25632)
+++ extensions/Comments_on_Albums/trunk/maintain.inc.php	(revision 26089)
@@ -1,28 +1,69 @@
 <?php
-if (!defined('PHPWG_ROOT_PATH')) die('Hacking attempt!');
+defined('PHPWG_ROOT_PATH') or die('Hacking attempt!');
 
-defined('COA_ID') or define('COA_ID', basename(dirname(__FILE__)));
-include_once(PHPWG_PLUGINS_PATH . COA_ID . '/include/install.inc.php');
+class Comments_on_Albums_maintain extends PluginMaintain
+{
+  private $installed = false;
 
-function plugin_install() 
-{
-  coa_install();
-  define('coa_installed', true);
-}
+  function install($plugin_version, &$errors=array())
+  {
+    global $prefixeTable;
 
-function plugin_activate()
-{
-  if (!defined('coa_installed'))
+    pwg_query('
+CREATE TABLE IF NOT EXISTS `' . $prefixeTable . 'comments_categories` (
+  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+  `category_id` mediumint(8) unsigned NOT NULL DEFAULT 0,
+  `date` datetime NOT NULL DEFAULT "0000-00-00 00:00:00",
+  `author` varchar(255) DEFAULT NULL,
+  `email` varchar(255) DEFAULT NULL,
+  `author_id` smallint(5) DEFAULT NULL,
+  `anonymous_id` varchar(45) NOT NULL,
+  `website_url` varchar(255) DEFAULT NULL,
+  `content` longtext,
+  `validated` enum("true","false") NOT NULL DEFAULT "false",
+  `validation_date` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `comments_i2` (`validation_date`),
+  KEY `comments_i1` (`category_id`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8');
+
+    $result = pwg_query('SHOW COLUMNS FROM `' . $prefixeTable . 'comments_categories` LIKE "anonymous_id";');
+    if (!pwg_db_num_rows($result))
+    {
+      pwg_query('ALTER TABLE `' . $prefixeTable . 'comments_categories` ADD `anonymous_id` VARCHAR(45) DEFAULT NULL;');
+    }
+
+    $result = pwg_query('SHOW COLUMNS FROM `' . $prefixeTable . 'comments_categories` LIKE "email";');
+    if (!pwg_db_num_rows($result))
+    {
+      pwg_query('
+ALTER TABLE `' . $prefixeTable . 'comments_categories`
+  ADD `email` varchar(255) DEFAULT NULL,
+  ADD `website_url` varchar(255) DEFAULT NULL,
+  ADD KEY `comments_i2` (`validation_date`),
+  ADD KEY `comments_i1` (`category_id`)
+      ;');
+    }
+
+    $this->installed = true;
+  }
+
+  function activate($plugin_version, &$errors=array())
   {
-    coa_install();
+    if (!$this->installed)
+    {
+      $this->install($plugin_version, $errors);
+    }
+  }
+
+  function deactivate()
+  {
+  }
+
+  function uninstall()
+  {
+    global $prefixeTable;
+
+    pwg_query('DROP TABLE `' . $prefixeTable . 'comments_categories`;');
   }
 }
-
-function plugin_uninstall() 
-{
-  global $prefixeTable;
-
-  pwg_query('DROP TABLE `' . $prefixeTable . 'comments_categories`;');
-}
-
-?>
Index: extensions/Comments_on_Albums/trunk/template/admin_comments.tpl
===================================================================
--- extensions/Comments_on_Albums/trunk/template/admin_comments.tpl	(revision 25632)
+++ 	(revision )
@@ -1,87 +1,0 @@
-{* this is a copy of admin/theme/defaults/template/comments.tpl a bit modified *}
-  
-{footer_script}{literal}
-jQuery(document).ready(function(){
-  function highlighComments() {
-    jQuery(".checkComment").each(function() {
-      var parent = jQuery(this).parent('tr');
-      if (jQuery(this).children("input[type=checkbox]").is(':checked')) {
-        jQuery(parent).addClass('selectedComment'); 
-      }
-      else {
-        jQuery(parent).removeClass('selectedComment'); 
-      }
-    });
-  }
-
-  jQuery(".checkComment").click(function(event) {
-    var checkbox = jQuery(this).children("input[type=checkbox]");
-    if (event.target.type !== 'checkbox') {
-      jQuery(checkbox).attr('checked', !jQuery(checkbox).is(':checked'));
-    }
-    highlighComments();
-  });
-
-  jQuery("#commentSelectAll").click(function () {
-    jQuery(".checkComment input[type=checkbox]").attr('checked', true);
-    highlighComments();
-    return false;
-  });
-
-  jQuery("#commentSelectNone").click(function () {
-    jQuery(".checkComment input[type=checkbox]").attr('checked', false);
-    highlighComments();
-    return false;
-  });
-
-  jQuery("#commentSelectInvert").click(function () {
-    jQuery(".checkComment input[type=checkbox]").each(function() {
-      jQuery(this).attr('checked', !$(this).is(':checked'));
-    });
-    highlighComments();
-    return false;
-  });
-
-});
-{/literal}{/footer_script}
-
-<div class="titrePage">
-  <h2>{'Pending Comments'|@translate} [{'Albums'|@translate}]</h2>
-</div>
-
-{if !empty($comments) }
-<form method="post" action="{$F_ACTION}" id="pendingComments">
-
-<table>
-  {foreach from=$comments item=comment name=comment}
-    <tr valign="top" class="{if $smarty.foreach.comment.index is odd}row2{else}row1{/if}">
-      <td style="width:50px;" class="checkComment">
-        <input type="checkbox" name="comments[]" value="{$comment.ID}">
-      </td>
-      <td>
-        <div class="comment">
-          <a class="illustration" href="{$comment.CAT_URL}"><img src="{$comment.TN_SRC}"><br/>{$comment.CAT_NAME}</a>
-          <p class="commentHeader"><strong>{$comment.AUTHOR}</strong> - <em>{$comment.DATE}</em></p>
-          <blockquote>{$comment.CONTENT}</blockquote>
-        </div>
-      </td>
-    </tr>
-  {/foreach}
-</table>
-
-  <p class="checkActions">
-    {'Select:'|@translate}
-    <a href="#" id="commentSelectAll">{'All'|@translate}</a>,
-    <a href="#" id="commentSelectNone">{'None'|@translate}</a>,
-    <a href="#" id="commentSelectInvert">{'Invert'|@translate}</a>
-  </p>
-
-  <p class="bottomButtons">
-    <input class="submit" type="submit" name="validate_albums" value="{'Validate'|@translate}">
-    <input class="submit" type="submit" name="reject_albums" value="{'Reject'|@translate}">
-  </p>
-
-</form>
-{else}
-{'No pending comment'|@translate}
-{/if}
Index: extensions/Comments_on_Albums/trunk/template/albums.tpl
===================================================================
--- extensions/Comments_on_Albums/trunk/template/albums.tpl	(revision 25632)
+++ extensions/Comments_on_Albums/trunk/template/albums.tpl	(revision 26089)
@@ -1,103 +1,71 @@
-{* this is inspired by theme/defaults/template/picture.tpl *}
- 
-{* <!-- need some css modifications, specific to each theme --> *}
-{html_head}
-<style type="text/css">
-#comments .commentElement {ldelim} width:98%;}
+{*<!-- this is inspired by theme/defaults/template/picture.tpl -->*}
+
+{combine_script id='coa.script' load='footer' require='jquery' path=$COA_PATH|cat:'template/script.js'}
+
+{html_style}{strip}
+#comments { margin:10px 0 0 0; padding: 2px 5px !important; position:relative; }
+#comments .commentElement { width:98%; }
+
 {if $COMMENTS_ON_TOP}
-#commentAdd, #pictureCommentList {ldelim} float:none; display:inline-block; width:47.5%; vertical-align:top;}
-#commentsSwitcher {ldelim} float:none; display:inline-block; margin: 2px 0; cursor:pointer;}
-.noCommentContent #commentsSwitcher  {ldelim} display: none;}
-.switchArrow{ldelim} width: 16px; height: 16px; margin: 5px;}
-.commentshidden #pictureComments {ldelim} display: none;}
-.commentContent .comments_toggle   {ldelim} cursor: pointer;}
-{/if}
-{if $themeconf.name == 'Sylvia'}
-#comments .description {ldelim} padding: 15px 2px 6px 12px;}
-#comments .commentElement {ldelim} border: 1px solid #666;}
-{/if}
-{if $themeconf.name|strstr:"stripped"}
-#comments {ldelim} text-align: left;}
-#comments .description {ldelim} height:auto;}
-#thumbnails_block2 {ldelim} min-height:0;}
+#comments { margin:0 0 10px 0; }
 {/if}
 
-</style>
-{/html_head}
-
-{* <!-- if RV Thumb Scroller is installed comments block is displayed on top with a drop-down --> *}
-{if $COMMENTS_ON_TOP}
-{footer_script}{literal}
-  // comments show/hide
-  var commentsswicther=jQuery("#commentsSwitcher");
-  var comments=jQuery("#theCategoryPage #comments");
-  
-  commentsswicther.html('<div class="switchArrow">&nbsp;</div>');
-  {/literal}{if $themeconf.name != 'elegant'}switcharrow = commentsswicther.children(".switchArrow");{else}switcharrow = $('<div></div>');{/if}{literal}
-  
-  if (comments.length == 1) {
-    var comments_button=jQuery("#comments h3");
-
-    if (comments_button.length == 0) {
-      jQuery("#addComment").before('<h3>Comments</h3>');
-      comments_button=jQuery("#comments h3");
-    }
-  
-    {/literal}{if $DISPLAY_COMMENTS_BLOCK}
-    comments.addClass("commentsshown");
-    comments_button.addClass("comments_toggle").addClass("comments_toggle_on");
-    switcharrow.html("&uarr;");
-    {else}
-    comments.addClass("commentshidden");
-    comments_button.addClass("comments_toggle").addClass("comments_toggle_off");
-    switcharrow.html("&darr;");
-    {/if}{literal}
-    
-    comments_button.click(function() { commentsToggle() });
-    commentsswicther.click(function() { commentsToggle() });
-  
-  }
-  
-  function commentsToggle() {
-    var comments=jQuery("#theCategoryPage #comments");
-    var comments_button=jQuery("#comments h3");
-
-    if (comments.hasClass("commentshidden")) {
-        comments.removeClass("commentshidden").addClass("commentsshown");
-        comments_button.addClass("comments_toggle_off").removeClass("comments_toggle_off");
-        switcharrow.html("&uarr;");
-      } else {
-        comments.addClass("commentshidden").removeClass("commentsshown");
-        comments_button.addClass("comments_toggle_on").removeClass("comments_toggle_on");
-        switcharrow.html("&darr;");
-      }
-
-  }
-{/literal}{/footer_script}
+{if $themeconf.name == 'elegant'}
+#content { padding-bottom:0; }
+#comments { background-color:#333333; }
+#comments h3 { margin: 10px 0px; }
 {/if}
 
+{if $themeconf.name == 'Sylvia'}
+#comments .description { padding: 15px 2px 6px 12px; }
+#comments .commentElement { border: 1px solid #666; }
+{/if}
+
+{if $themeconf.name|strstr:"stripped"}
+#comments { text-align: left; }
+#comments .description { height:auto; }
+#thumbnails_block2 { min-height:0; }
+{/if}
+
+{if $themeconf.name != 'elegant'}
+#comments { background:rgba(127,127,127,0.1); }
+#comments.commentshidden #pictureComments { display:none; }
+#comments .comments_toggle { cursor:pointer; }
+#commentsSwitcher { float:left; margin:2px 0; cursor:pointer; }
+#comments .switchArrow { width:16px; height:16px; margin:8px 5px 8px 4px; }
+#comments .switchArrow:before { content:"\BB"; display:inline-block; font-size:22px; }
+#comments.commentshidden .switchArrow:before { -webkit-transform:rotate(90deg); transform:rotate(90deg); }
+#comments.commentsshown .switchArrow:before { -webkit-transform:rotate(-90deg); transform:rotate(-90deg); }
+{/if}
+{/strip}{/html_style}
+
+{footer_script}
+var coa_on_top = {intval(isset($COMMENTS_ON_TOP))}, coa_force_open = {intval(isset($DISPLAY_COMMENTS_BLOCK))};
+{/footer_script}
+
+
 {if isset($COMMENT_COUNT)}
-<div id="comments" style="margin:10px 0 10px 0;" {if (!isset($comment_add) && ($COMMENT_COUNT == 0))}class="noCommentContent"{else}class="commentContent"{/if}>
-  <h3 style="margin:0 0 0 5px;"><div id="commentsSwitcher"></div>{$pwg->l10n_dec('%d comment', '%d comments',$COMMENT_COUNT)}</h3>
+<div id="comments" {if (!isset($comment_add) && ($COMMENT_COUNT == 0))}class="noCommentContent"{else}class="commentContent"{/if}><div id="commentsSwitcher"></div>
+  <h3>{$COMMENT_COUNT|translate_dec:'%d comment':'%d comments'}</h3>
 
-  <div id="pictureComments"><fieldset>
+  <div id="pictureComments">
     {if isset($comment_add)}
     <div id="commentAdd">
-      <h4>{'Add a comment'|@translate}</h4>
+      <h4>{'Add a comment'|translate}</h4>
       <form method="post" action="{$comment_add.F_ACTION}" id="addComment">
         {if $comment_add.SHOW_AUTHOR}
-          <p><label for="author">{'Author'|@translate}{if $comment_add.AUTHOR_MANDATORY} ({'mandatory'|@translate}){/if} :</label></p>
+          <p><label for="author">{'Author'|translate}{if $comment_add.AUTHOR_MANDATORY} ({'mandatory'|translate}){/if} :</label></p>
           <p><input type="text" name="author" id="author" value="{$comment_add.AUTHOR}"></p>
         {/if}
         {if $comment_add.SHOW_EMAIL}
-          <p><label for="email">{'Email'|@translate}{if $comment_add.EMAIL_MANDATORY} ({'mandatory'|@translate}){/if} :</label></p>
+          <p><label for="email">{'Email address'|translate}{if $comment_add.EMAIL_MANDATORY} ({'mandatory'|translate}){/if} :</label></p>
           <p><input type="text" name="email" id="email" value="{$comment_add.EMAIL}"></p>
         {/if}
-        <p><label for="website_url">{'Website'|@translate} :</label></p>
+        <p><label for="website_url">{'Website'|translate} :</label></p>
         <p><input type="text" name="website_url" id="website_url" value="{$comment_add.WEBSITE_URL}"></p>
-        <p><label for="contentid">{'Comment'|@translate} ({'mandatory'|@translate}) :</label></p>
+        <p><label for="contentid">{'Comment'|translate} ({'mandatory'|translate}) :</label></p>
         <p><textarea name="content" id="contentid" rows="5" cols="50">{$comment_add.CONTENT}</textarea></p>
         <p><input type="hidden" name="key" value="{$comment_add.KEY}">
-          <input type="submit" value="{'Submit'|@translate}"></p>
+          <input type="submit" value="{'Submit'|translate}"></p>
       </form>
     </div>
@@ -110,5 +78,7 @@
             <a href="{$COMMENTS_ORDER_URL}#comments" rel="nofollow" class="commentsOrder">{$COMMENTS_ORDER_TITLE}</a>
           {/if}
-          {if !empty($comment_navbar) }{include file=$COA_ABSOLUTE_PATH|@cat:'template/navigation_bar.tpl'|@get_extent:'navbar'}{/if}
+          {if !empty($comment_navbar)}
+            {include file='navigation_bar.tpl'|get_extent:'navbar' navbar=$comment_navbar}
+          {/if}
         </div>
       {/if}
@@ -116,6 +86,6 @@
     </div>
     {/if}
-    {if not $COMMENTS_ON_TOP}<div style="clear:both"></div>{/if}
-  </fieldset></div>
+    <div style="clear:both"></div>
+  </div>
 
 </div>
Index: extensions/Comments_on_Albums/trunk/template/navigation_bar.tpl
===================================================================
--- extensions/Comments_on_Albums/trunk/template/navigation_bar.tpl	(revision 25632)
+++ 	(revision )
@@ -1,31 +1,0 @@
-{* this is a copy of theme/defaults/template/navigation_bar.tpl 
-  but with other variables to not interfer with the thumbnails' navigation bar *}
-  
-<div class="navigationBar">
-  {if isset($comment_navbar.URL_FIRST)}
-    <a href="{$comment_navbar.URL_FIRST}#comments" rel="first">{'First'|@translate}</a> |
-    <a href="{$comment_navbar.URL_PREV}#comments" rel="prev">{'Previous'|@translate}</a> |
-  {else}
-    {'First'|@translate} |
-    {'Previous'|@translate} |
-  {/if}
-
-  {assign var='prev_page' value=0}
-  {foreach from=$comment_navbar.pages key=page item=url}
-    {if $page > $prev_page+1}...{/if}
-    {if $page == $comment_navbar.CURRENT_PAGE}
-      <span class="pageNumberSelected">{$page}</span>
-    {else}
-      <a href="{$url}#comments">{$page}</a>
-    {/if}
-    {assign var='prev_page' value=$page}
-  {/foreach}
-
-  {if isset($comment_navbar.URL_NEXT)}
-    | <a href="{$comment_navbar.URL_NEXT}#comments" rel="next">{'Next'|@translate}</a>
-    | <a href="{$comment_navbar.URL_LAST}#comments" rel="last">{'Last'|@translate}</a>
-  {else}
-    | {'Next'|@translate}
-    | {'Last'|@translate}
-  {/if}
-</div>
Index: extensions/Comments_on_Albums/trunk/template/script.js
===================================================================
--- extensions/Comments_on_Albums/trunk/template/script.js	(revision 26089)
+++ extensions/Comments_on_Albums/trunk/template/script.js	(revision 26089)
@@ -0,0 +1,75 @@
+(function(){
+  var session_storage = window.sessionStorage || {};
+
+  var comments=jQuery("#theCategoryPage #comments"),
+      comments_button,
+      commentsswitcher,
+      comments_add,
+      comments_top_offset = 0;
+
+  function commentsToggle() {
+    if (comments.hasClass("commentshidden")) {
+      comments.removeClass("commentshidden").addClass("commentsshown");
+      comments_button.addClass("comments_toggle_off").removeClass("comments_toggle_on");;
+      session_storage['comments'] = 'visible';
+      comments_top_offset = comments_add.offset().top - parseFloat(comments_add.css('marginTop').replace(/auto/, 0));
+    }
+    else {
+      comments.addClass("commentshidden").removeClass("commentsshown");
+      comments_button.addClass("comments_toggle_on").removeClass("comments_toggle_off");;
+      session_storage['comments'] = 'hidden';
+      comments_top_offset = 0;
+    }
+  }
+
+  jQuery(function(){
+    // comments show/hide
+    if (comments.length == 1) {
+      commentsswitcher=jQuery("#commentsSwitcher");
+      comments_button=jQuery("#comments h3");
+      comments_add=jQuery('#commentAdd');
+
+      commentsswitcher.html('<div class="switchArrow">&nbsp;</div>');
+
+      if (comments_button.length == 0) {
+        jQuery("#addComment").before("<h3>Comments</h3>");
+        comments_button=jQuery("#comments h3");
+      }
+
+      if ((session_storage['comments'] == 'hidden' || coa_on_top) && !coa_force_open) {
+        comments.addClass("commentshidden");
+        comments_button.addClass("comments_toggle comments_toggle_on");
+      }
+      else {
+        comments.addClass("commentsshown");
+        comments_button.addClass("comments_toggle comments_toggle_off");
+      }
+
+      comments_button.click(commentsToggle);
+      commentsswitcher.click(commentsToggle);
+
+      jQuery(window).scroll(function (event) {
+        if (comments_top_offset==0) return;
+
+        var y = jQuery(this).scrollTop();
+
+        if (y >= comments_top_offset) {
+          comments_add.css({
+            'position': 'absolute',
+            'top': Math.min(y-comments.offset().top+10, comments.height()-comments_add.height())
+          });
+        }
+        else {
+          comments_add.css({
+            'position': 'static',
+            'top': 0
+          });
+        }
+      });
+
+      if (comments_add.is(":visible")) {
+        comments_top_offset = comments_add.offset().top - parseFloat(comments_add.css('marginTop').replace(/auto/, 0));
+      }
+    }
+  });
+}());
