Index: /extensions/GuestBook/admin.php
===================================================================
--- /extensions/GuestBook/admin.php	(revision 15940)
+++ /extensions/GuestBook/admin.php	(revision 15940)
@@ -0,0 +1,28 @@
+<?php
+if(!defined('GUESTBOOK_PATH')) die('Hacking attempt!');
+
+global $template, $page;
+
+// tabsheet
+include_once(PHPWG_ROOT_PATH.'admin/include/tabsheet.class.php');
+$page['tab'] = (isset($_GET['tab'])) ? $_GET['tab'] : $page['tab'] = 'pending';
+  
+$tabsheet = new tabsheet();
+$tabsheet->add('pending', l10n('Pending Comments'), GUESTBOOK_ADMIN . '-pending');
+$tabsheet->add('config', l10n('Configuration'), GUESTBOOK_ADMIN . '-config');
+$tabsheet->select($page['tab']);
+$tabsheet->assign();
+
+// include page
+include(GUESTBOOK_PATH . 'admin/' . $page['tab'] . '.php');
+
+// template
+$template->assign(array(
+  'GUESTBOOK_PATH' => GUESTBOOK_PATH,
+  'GUESTBOOK_ADMIN' => GUESTBOOK_ADMIN,
+));
+
+$template->assign_var_from_handle('ADMIN_CONTENT', 'guestbook');
+
+
+?>
Index: /extensions/GuestBook/admin/config.php
===================================================================
--- /extensions/GuestBook/admin/config.php	(revision 15940)
+++ /extensions/GuestBook/admin/config.php	(revision 15940)
@@ -0,0 +1,21 @@
+<?php
+if (!defined('PHPWG_ROOT_PATH')) die('Hacking attempt!');
+
+if (isset($_POST['submit']))
+{
+  $conf['guestbook'] = array(
+    'comments_validation' => isset($_POST['comments_validation']),
+    'email_admin_on_comment' => isset($_POST['email_admin_on_comment']),
+    'email_admin_on_comment_validation' => isset($_POST['email_admin_on_comment_validation']),
+    'nb_comment_page' => $_POST['nb_comment_page'],
+    );
+    
+  conf_update_param('guestbook', serialize($conf['guestbook']));
+  array_push($page['infos'], l10n('Information data registered in database'));
+}
+
+$template->assign($conf['guestbook']);
+
+$template->set_filename('guestbook', dirname(__FILE__).'/template/config.tpl');
+
+?>
Index: /extensions/GuestBook/admin/index.php
===================================================================
--- /extensions/GuestBook/admin/index.php	(revision 15940)
+++ /extensions/GuestBook/admin/index.php	(revision 15940)
@@ -0,0 +1,30 @@
+<?php
+// +-----------------------------------------------------------------------+
+// | Piwigo - a PHP based photo gallery                                    |
+// +-----------------------------------------------------------------------+
+// | Copyright(C) 2008-2012 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.                                                                  |
+// +-----------------------------------------------------------------------+
+
+// Recursive call
+$url = '../';
+header( 'Request-URI: '.$url );
+header( 'Content-Location: '.$url );
+header( 'Location: '.$url );
+exit();
+?>
Index: /extensions/GuestBook/admin/pending.php
===================================================================
--- /extensions/GuestBook/admin/pending.php	(revision 15940)
+++ /extensions/GuestBook/admin/pending.php	(revision 15940)
@@ -0,0 +1,113 @@
+<?php
+if (!defined('PHPWG_ROOT_PATH')) die('Hacking attempt!');
+
+include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
+
+// +-----------------------------------------------------------------------+
+// |                                actions                                |
+// +-----------------------------------------------------------------------+
+
+if (!empty($_POST))
+{
+  if (empty($_POST['comments']))
+  {
+    array_push(
+      $page['errors'],
+      l10n('Select at least one comment')
+      );
+  }
+  else
+  {
+    include_once( GUESTBOOK_PATH .'include/functions_comment.inc.php' );
+    check_input_parameter('comments', $_POST, true, PATTERN_ID);
+    
+    if (isset($_POST['validate']))
+    {
+      validate_user_comment_guestbook($_POST['comments']);
+
+      array_push(
+        $page['infos'],
+        l10n_dec(
+          '%d user comment validated', '%d user comments validated',
+          count($_POST['comments'])
+          )
+        );
+    }
+
+    if (isset($_POST['reject']))
+    {
+      delete_user_comment_guestbook($_POST['comments']);
+
+      array_push(
+        $page['infos'],
+        l10n_dec(
+          '%d user comment rejected', '%d user comments rejected',
+          count($_POST['comments'])
+          )
+        );
+    }
+  }
+}
+
+
+// +-----------------------------------------------------------------------+
+// |                           comments display                            |
+// +-----------------------------------------------------------------------+
+include(GUESTBOOK_PATH .'include/functions.inc.php');
+
+$list = array();
+
+$query = '
+SELECT 
+    c.id, 
+    c.date, 
+    c.author, 
+    '.$conf['user_fields']['username'].' AS username, 
+    c.content,
+    c.website,
+    c.email,
+    c.rate
+  FROM '.GUESTBOOK_TABLE.' AS c
+    LEFT JOIN '.USERS_TABLE.' AS u
+      ON u.'.$conf['user_fields']['id'].' = c.author_id
+  WHERE validated = \'false\'
+  ORDER BY c.date DESC
+;';
+$result = pwg_query($query);
+while ($row = pwg_db_fetch_assoc($result))
+{
+  if (empty($row['author_id'])) 
+  {
+    $author_name = $row['author'];
+  }
+  else
+  {
+    $author_name = stripslashes($row['username']);
+  }
+  
+  $template->append(
+    'comments',
+    array(
+      'ID' => $row['id'],
+      'AUTHOR' => trigger_event('render_comment_author', $author_name),
+      'DATE' => format_date($row['date'], true),
+      'CONTENT' => trigger_event('render_comment_content',$row['content']),
+      'EMAIL' => $row['email'],
+      'WEBSITE' => $row['website'],
+      'WEBSITE_NAME' => preg_replace('#^(https?:\/\/)#i', null, $row['website']),
+      'STARS' => get_stars($row['rate'], GUESTBOOK_PATH .'template/jquery.raty/'),
+      'RATE' => $row['rate'],
+      )
+    );
+
+  array_push($list, $row['id']);
+}
+
+$template->assign('LIST', implode(',', $list) );
+
+$template->assign('F_ACTION', GUESTBOOK_ADMIN . '-pending');
+
+
+$template->set_filename('guestbook', dirname(__FILE__).'/template/pending.tpl');
+
+?>
Index: /extensions/GuestBook/admin/template/config.tpl
===================================================================
--- /extensions/GuestBook/admin/template/config.tpl	(revision 15940)
+++ /extensions/GuestBook/admin/template/config.tpl	(revision 15940)
@@ -0,0 +1,42 @@
+{combine_css path=$GUESTBOOK_PATH|@cat:'template/style.css'}
+
+<div class="titrePage">
+  <h2>{'GuestBook'|@translate}</h2>
+</div>
+
+<form method="post" action="" class="properties">
+<fieldset id="commentsConf">
+  <legend></legend>
+  <ul>
+    <li>
+      <label>
+        <b>{'Number of comments per page'|@translate}</b>
+        <input type="text" size="3" maxlength="4" name="nb_comment_page" id="nb_comment_page" value="{$nb_comment_page}">
+      </label>
+    </li>
+
+    <li>
+      <label>
+        <input type="checkbox" name="comments_validation" {if ($comments_validation)}checked="checked"{/if}>
+        <b>{'Validation'|@translate}</b>
+      </label>
+    </li>
+
+    <li id="notifyAdmin">
+      <strong>{'Notify administrators when a comment is'|@translate}</strong>
+
+      <label id="email_admin_on_comment_validation">
+        <input type="checkbox" name="email_admin_on_comment_validation" {if ($email_admin_on_comment_validation)}checked="checked"{/if}> {'pending validation'|@translate}
+      </label>
+
+      <label>
+        <input type="checkbox" name="email_admin_on_comment" {if ($email_admin_on_comment)}checked="checked"{/if}> {'added'|@translate}
+      </label>
+    </li>
+  </ul>
+</fieldset>
+
+  <p class="formButtons">
+		<input type="submit" name="submit" value="{'Save Settings'|@translate}">
+	</p>
+</form>
Index: /extensions/GuestBook/admin/template/index.php
===================================================================
--- /extensions/GuestBook/admin/template/index.php	(revision 15940)
+++ /extensions/GuestBook/admin/template/index.php	(revision 15940)
@@ -0,0 +1,30 @@
+<?php
+// +-----------------------------------------------------------------------+
+// | Piwigo - a PHP based photo gallery                                    |
+// +-----------------------------------------------------------------------+
+// | Copyright(C) 2008-2012 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.                                                                  |
+// +-----------------------------------------------------------------------+
+
+// Recursive call
+$url = '../';
+header( 'Request-URI: '.$url );
+header( 'Content-Location: '.$url );
+header( 'Location: '.$url );
+exit();
+?>
Index: /extensions/GuestBook/admin/template/pending.tpl
===================================================================
--- /extensions/GuestBook/admin/template/pending.tpl	(revision 15940)
+++ /extensions/GuestBook/admin/template/pending.tpl	(revision 15940)
@@ -0,0 +1,90 @@
+{combine_css path=$GUESTBOOK_PATH|@cat:'admin/template/style.css'}
+
+<div class="titrePage">
+  <h2>{'GuestBook'|@translate}</h2>
+</div>
+
+{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}
+
+{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:20px;text-align:center;" valign="middle" class="checkComment">
+      <input type="checkbox" name="comments[]" value="{$comment.ID}">
+    </td>
+    <td>
+  <div class="comment">
+    <p class="commentHeader"><strong><a href="mailto:{$comment.EMAIL}">{$comment.AUTHOR}</a></strong> - <em>{$comment.DATE}</em><br>
+
+      {if $comment.WEBSITE}<a href="{$comment.WEBSITE}">{$comment.WEBSITE_NAME}</a>{/if}
+      {if $comment.RATE}{$comment.STARS}{/if}
+    </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" value="{'Validate'|@translate}">
+    <input class="submit" type="submit" name="reject" value="{'Reject'|@translate}">
+  </p>
+
+</form>
+{else}
+{'No pending comment'|@translate}
+{/if}
Index: /extensions/GuestBook/admin/template/style.css
===================================================================
--- /extensions/GuestBook/admin/template/style.css	(revision 15940)
+++ /extensions/GuestBook/admin/template/style.css	(revision 15940)
@@ -0,0 +1,9 @@
+DIV.comment blockquote {
+  padding-right:280px;
+  margin-top:18px;
+  min-height:0;
+}
+
+p.commentHeader {
+  float:right;
+}
Index: /extensions/GuestBook/include/functions.inc.php
===================================================================
--- /extensions/GuestBook/include/functions.inc.php	(revision 15940)
+++ /extensions/GuestBook/include/functions.inc.php	(revision 15940)
@@ -0,0 +1,79 @@
+<?php
+
+if (!defined('GUESTBOOK_PATH')) die('Hacking attempt!');
+
+if (!function_exists('is_valid_email'))
+{
+  function is_valid_email($mail_address)
+  {
+    if (version_compare(PHP_VERSION, '5.2.0') >= 0)
+    {
+      return filter_var($mail_address, FILTER_VALIDATE_EMAIL)!==false;
+    }
+    else
+    {
+      $atom   = '[-a-z0-9!#$%&\'*+\\/=?^_`{|}~]';   // before  arobase
+      $domain = '([a-z0-9]([-a-z0-9]*[a-z0-9]+)?)'; // domain name
+      $regex = '/^' . $atom . '+' . '(\.' . $atom . '+)*' . '@' . '(' . $domain . '{1,63}\.)+' . $domain . '{2,63}$/i';
+
+      if (!preg_match($regex, $mail_address)) return false;
+      return true;
+    }
+  }
+}
+
+function is_valid_url($url)
+{
+  if (version_compare(PHP_VERSION, '5.2.0') >= 0)
+  {
+    return filter_var($url, FILTER_VALIDATE_URL)!==false;
+  }
+  else
+  if (1)
+  {
+    $regex = '#^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$#i';
+
+    if (!preg_match($regex, $url)) return false;
+    return true;
+  }
+}
+
+function get_stars($score, $path)
+{
+  if ($score === null) return null;
+  
+  $max = 5;
+  $score = min(max($score, 0), $max);
+  $floor = floor($score);
+  
+  $html = null;
+  for ($i=1; $i<=$floor; $i++)
+  {
+    $html.= '<img alt="'.$i.'" src="'.$path.'star-on.png">';
+  }
+  
+  if ($score != $max)
+  {
+    if ($score-$floor <= .25)
+    {
+      $html.= '<img alt="'.($floor+1).'" src="'.$path.'star-off.png">';
+    }
+    else if ($score-$floor <= .75)
+    {
+      $html.= '<img alt="'.($floor+1).'" src="'.$path.'star-half.png">';
+    }
+    else
+    {
+      $html.= '<img alt="'.($floor+1).'" src="'.$path.'star-on.png">';
+    }
+  
+    for ($i=$floor+2; $i<=$max; $i++)
+    {
+      $html.= '<img alt="'.$i.'" src="'.$path.'star-off.png">';
+    }
+  }
+  
+  return $html;
+}
+
+?>
Index: /extensions/GuestBook/include/functions_comment.inc.php
===================================================================
--- /extensions/GuestBook/include/functions_comment.inc.php	(revision 15940)
+++ /extensions/GuestBook/include/functions_comment.inc.php	(revision 15940)
@@ -0,0 +1,320 @@
+<?php
+if (!defined('GUESTBOOK_PATH')) die('Hacking attempt!');
+
+function insert_user_comment_guestbook( &$comm, $key, &$infos )
+{
+  global $conf, $user, $page;
+
+  $comm = array_merge( $comm,
+    array(
+      'ip' => $_SERVER['REMOTE_ADDR'],
+      'agent' => $_SERVER['HTTP_USER_AGENT']
+    )
+   );
+
+  $infos = array();
+  if (!$conf['guestbook']['comments_validation'] or is_admin())
+  {
+    $comment_action='validate'; //one of validate, moderate, reject
+  }
+  else
+  {
+    $comment_action='moderate'; //one of validate, moderate, reject
+  }
+
+  // display author field if the user status is guest or generic
+  if (!is_classic_user())
+  {
+    if ( empty($comm['author']) )
+    {
+      array_push($page['errors'], l10n('Please enter your username'));
+      $comment_action='reject';
+    }
+    else
+    {
+      $comm['author_id'] = $conf['guest_id'];
+      // if a guest try to use the name of an already existing user, he must be
+      // rejected
+      $query = '
+SELECT COUNT(*) AS user_exists
+  FROM '.USERS_TABLE.'
+  WHERE '.$conf['user_fields']['username']." = '".addslashes($comm['author'])."'";
+      $row = pwg_db_fetch_assoc( pwg_query( $query ) );
+      
+      if ( $row['user_exists'] == 1 )
+      {
+        array_push($page['errors'], l10n('This login is already used by another user') );
+        $comment_action='reject';
+      }
+    }
+  }
+  else
+  {
+    $comm['author'] = addslashes($user['username']);
+    $comm['author_id'] = $user['id'];
+  }
+
+  if ( empty($comm['content']) )
+  { // empty comment content
+    $comment_action='reject';
+  }
+
+  if ( !verify_ephemeral_key(@$key) )
+  {
+    $comment_action='reject';
+    $_POST['cr'][] = 'key';
+  }
+  
+  // email
+  if ( empty($comm['email']) and is_classic_user() and !empty($user['email']) )
+  {
+    $comm['email'] = $user['email'];
+  }
+  else if ( !empty($comm['email']) and !is_valid_email($comm['email']) )
+  {
+    array_push($page['errors'], l10n('mail address must be like xxx@yyy.eee (example : jack@altern.org)'));
+    $comment_action='reject';
+  }
+  
+  // website
+  if ( !empty($comm['website']) and !preg_match('/^(https?:\/\/)/i', $comm['website']) )
+  {
+    $comm['website'] = 'http://'.$comm['website'];
+  }
+  if ( !empty($comm['website']) and !is_valid_url($comm['website']) )
+  {
+    array_push($page['errors'], l10n('invalid website address'));
+    $comment_action='reject';
+  }
+  
+  // anonymous id = ip address
+  $ip_components = explode('.', $_SERVER["REMOTE_ADDR"]);
+  if (count($ip_components) > 3)
+  {
+    array_pop($ip_components);
+  }
+  $comm['anonymous_id'] = implode('.', $ip_components);
+  
+  // comment validation and anti-spam
+  if ($comment_action!='reject' and $conf['anti-flood_time']>0 and !is_admin())
+  {
+    $reference_date = pwg_db_get_flood_period_expression($conf['anti-flood_time']);
+    
+    $query = '
+SELECT COUNT(1) FROM '.GUESTBOOK_TABLE.'
+  WHERE 
+    date > '.$reference_date.'
+    AND author_id = '.$comm['author_id'];
+    if (!is_classic_user())
+    {
+      $query.= '
+      AND anonymous_id = "'.$comm['anonymous_id'].'"';
+    }
+    $query.= '
+;';
+    
+    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') );
+      $comment_action='reject';
+    }
+  }
+  
+  include_once(PHPWG_ROOT_PATH.'include/functions_comment.inc.php');
+  $comment_action = user_comment_check($comment_action, $comm);
+
+  if ( $comment_action!='reject' )
+  {
+    $query = '
+INSERT INTO '.GUESTBOOK_TABLE.'(
+    author, 
+    author_id, 
+    anonymous_id,
+    content, 
+    date, 
+    validated, 
+    validation_date, 
+    website, 
+    rate, 
+    email
+  )
+  VALUES (
+    \''.$comm['author'].'\',
+    '.$comm['author_id'].',
+    \''.$comm['anonymous_id'].'\',
+    \''.$comm['content'].'\',
+    NOW(),
+    \''.($comment_action=='validate' ? 'true':'false').'\',
+    '.($comment_action=='validate' ? 'NOW()':'NULL').',
+    '.(!empty($comm['website']) ? '\''.$comm['website'].'\'' : 'NULL').',
+    '.(!empty($comm['rate']) ? $comm['rate'] : 'NULL').',
+    '.(!empty($comm['email']) ? '\''.$comm['email'].'\'' : 'NULL').'
+  )
+';
+
+    pwg_query($query);
+
+    $comm['id'] = pwg_db_insert_id(GUESTBOOK_TABLE);
+
+    if ( ($conf['guestbook']['email_admin_on_comment'] and 'validate' == $comment_action)
+        or ($conf['guestbook']['email_admin_on_comment_validation'] and 'moderate' == $comment_action))
+    {
+      include_once(PHPWG_ROOT_PATH.'include/functions_mail.inc.php');
+
+      $comment_url = get_absolute_root_url().add_url_params(GUESTBOOK_URL, array('comment_id'=>$comm['id']));
+
+      $keyargs_content = array
+      (
+        get_l10n_args('Author: %s', stripslashes($comm['author']) ),
+        get_l10n_args('Comment: %s', stripslashes($comm['content']) ),
+        get_l10n_args('', ''),
+        get_l10n_args('Manage this user comment: %s', $comment_url)
+      );
+
+      if ('moderate' == $comment_action)
+      {
+        $keyargs_content[] = get_l10n_args('', '');
+        $keyargs_content[] = get_l10n_args('(!) This comment requires validation', '');
+      }
+
+      pwg_mail_notification_admins
+      (
+        get_l10n_args('Comment by %s', stripslashes($comm['author']) ),
+        $keyargs_content
+      );
+    }
+  }
+  return $comment_action;
+}
+
+function update_user_comment_guestbook($comment, $post_key)
+{
+  global $conf;
+
+  $comment_action = 'validate';
+
+  if ( !verify_ephemeral_key($post_key) )
+  {
+    $comment_action='reject';
+  }
+  elseif (!$conf['guestbook']['comments_validation'] or is_admin()) // should the updated comment must be validated
+  {
+    $comment_action='validate'; //one of validate, moderate, reject
+  }
+  else
+  {
+    $comment_action='moderate'; //one of validate, moderate, reject
+  }
+
+  if ( $comment_action!='reject' )
+  {
+    $user_where_clause = '';
+    if (!is_admin())
+    {
+      $user_where_clause = '   AND author_id = \''.
+	$GLOBALS['user']['id'].'\'';
+    }
+
+    $query = '
+UPDATE '.GUESTBOOK_TABLE.'
+  SET content = \''.$comment['content'].'\',
+      validated = \''.($comment_action=='validate' ? 'true':'false').'\',
+      validation_date = '.($comment_action=='validate' ? 'NOW()':'NULL').'
+  WHERE id = '.$comment['comment_id'].
+$user_where_clause.'
+;';
+    $result = pwg_query($query);
+    
+    // mail admin and ask to validate the comment
+    if ($result and $conf['guestbook']['email_admin_on_comment_validation'] and 'moderate' == $comment_action) 
+    {
+      include_once(PHPWG_ROOT_PATH.'include/functions_mail.inc.php');
+      
+      $comment_url = get_absolute_root_url().add_url_params(GUESTBOOK_URL, array('comment_id'=>$comm['id']));
+
+      $keyargs_content = array
+      (
+        get_l10n_args('Author: %s', stripslashes($GLOBALS['user']['username']) ),
+        get_l10n_args('Comment: %s', stripslashes($comment['content']) ),
+        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
+      (
+        get_l10n_args('Comment by %s', stripslashes($GLOBALS['user']['username']) ),
+        $keyargs_content
+      );
+    }
+  }
+  
+  return $comment_action;
+}
+
+function get_comment_author_id_guestbook($comment_id, $die_on_error=true)
+{
+  $query = '
+SELECT
+    author_id
+  FROM '.GUESTBOOK_TABLE.'
+  WHERE id = '.$comment_id.'
+;';
+  $result = pwg_query($query);
+  if (pwg_db_num_rows($result) == 0)
+  {
+    if ($die_on_error)
+    {
+      fatal_error('Unknown comment identifier');
+    }
+    else
+    {
+      return false;
+    }
+  }
+  
+  list($author_id) = pwg_db_fetch_row($result);
+
+  return $author_id;
+}
+
+function delete_user_comment_guestbook($comment_id)
+{
+  $user_where_clause = '';
+  if (!is_admin())
+  {
+    $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 '.GUESTBOOK_TABLE.'
+  WHERE '.$where_clause.
+$user_where_clause.'
+;';
+  pwg_query($query);
+}
+
+function validate_user_comment_guestbook($comment_id)
+{
+  if (is_array($comment_id))
+    $where_clause = 'id IN('.implode(',', $comment_id).')';
+  else
+    $where_clause = 'id = '.$comment_id;
+    
+  $query = '
+UPDATE '.GUESTBOOK_TABLE.'
+  SET validated = \'true\'
+    , validation_date = NOW()
+  WHERE '.$where_clause.'
+;';
+  pwg_query($query);
+}
+
+?>
Index: /extensions/GuestBook/include/guestbook.inc.php
===================================================================
--- /extensions/GuestBook/include/guestbook.inc.php	(revision 15940)
+++ /extensions/GuestBook/include/guestbook.inc.php	(revision 15940)
@@ -0,0 +1,319 @@
+<?php
+if (!defined('GUESTBOOK_PATH')) die('Hacking attempt!');
+
+include(GUESTBOOK_PATH . '/include/functions.inc.php');
+
+$url_self = empty($page['start']) ? GUESTBOOK_URL : add_url_params(GUESTBOOK_URL, array('start' => $page['start']));
+
+// +-----------------------------------------------------------------------+
+// |                                actions                                |
+// +-----------------------------------------------------------------------+
+if (isset($_GET['action']))
+{
+  switch ($_GET['action'])
+  {
+    case 'edit_comment':
+    {
+      include_once(GUESTBOOK_PATH.'include/functions_comment.inc.php');
+      
+      check_input_parameter('comment_to_edit', $_GET, false, PATTERN_ID);
+      $author_id = get_comment_author_id_guestbook($_GET['comment_to_edit']);
+
+      if (can_manage_comment('edit', $author_id))
+      {
+        if (!empty($_POST['content']))
+        {
+          check_pwg_token();
+          $comment_action = update_user_comment_guestbook(
+            array(
+              'comment_id' => $_GET['comment_to_edit'],
+              'content' => $_POST['content']
+              ),
+            $_POST['key']
+            );
+
+          $perform_redirect = false;
+          switch ($comment_action)
+          {
+            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');
+              $perform_redirect = true;
+              break;
+            default:
+              trigger_error('Invalid comment action '.$comment_action, E_USER_WARNING);
+          }
+
+          if ($perform_redirect)
+          {
+            redirect($url_self);
+          }
+          unset($_POST['content']);
+        }
+        else
+        {
+          $edit_comment = $_GET['comment_to_edit'];
+        }
+      }
+      break;
+    }
+    case 'delete_comment' :
+    {
+      check_pwg_token();
+
+      include_once(GUESTBOOK_PATH.'include/functions_comment.inc.php');
+
+      check_input_parameter('comment_to_delete', $_GET, false, PATTERN_ID);
+
+      $author_id = get_comment_author_id_guestbook($_GET['comment_to_delete']);
+
+      if (can_manage_comment('delete', $author_id))
+      {
+        delete_user_comment_guestbook($_GET['comment_to_delete']);
+      }
+
+      redirect($url_self);
+    }
+    case 'validate_comment' :
+    {
+      check_pwg_token();
+
+      include_once(GUESTBOOK_PATH.'include/functions_comment.inc.php');
+
+      check_input_parameter('comment_to_validate', $_GET, false, PATTERN_ID);
+
+      $author_id = get_comment_author_id_guestbook($_GET['comment_to_validate']);
+
+      if (can_manage_comment('validate', $author_id))
+      {
+        validate_user_comment_guestbook($_GET['comment_to_validate']);
+      }
+
+      redirect($url_self);
+    }
+
+  }
+}
+
+// +-----------------------------------------------------------------------+
+// |                                add comment                            |
+// +-----------------------------------------------------------------------+
+if ( isset( $_POST['content'] ) )
+{
+  $comm = array(
+    'author' => trim( @$_POST['author'] ),
+    'email' => trim( @$_POST['email'] ),
+    'content' => trim( $_POST['content'] ),
+    'website' => trim( $_POST['website'] ),
+    'rate' => $_POST['score'],
+   );
+
+  include_once(GUESTBOOK_PATH.'include/functions_comment.inc.php');
+
+  $comment_action = insert_user_comment_guestbook($comm, @$_POST['key'], $page['infos']);
+
+  switch ($comment_action)
+  {
+    case 'moderate':
+      array_push($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'));
+      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') );
+      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) )
+    );
+}
+
+// +-----------------------------------------------------------------------+
+// |                                display comments                       |
+// +-----------------------------------------------------------------------+
+$where_clauses = array('1=1');
+if ( !is_admin() )
+{
+  array_push($where_clauses, 'validated = \'true\'');
+}
+if (isset($_GET['comment_id']))
+{
+  array_push($where_clauses, 'com.id = '.pwg_db_real_escape_string($_GET['comment_id']));
+}
+
+// number of comments for this picture
+$query = '
+SELECT
+    COUNT(*) AS nb_comments
+  FROM '.GUESTBOOK_TABLE.' as com
+  WHERE '.implode(' AND ', $where_clauses).'
+;';
+$row = pwg_db_fetch_assoc( pwg_query( $query ) );
+
+// navigation bar creation
+$page['start'] = 0;
+if (isset($_GET['start']))
+{
+  $page['start'] = $_GET['start'];
+}
+
+$navigation_bar = create_navigation_bar(
+  GUESTBOOK_URL,
+  $row['nb_comments'],
+  $page['start'],
+  $conf['guestbook']['nb_comment_page'],
+  false
+  );
+
+$template->assign(
+  array(
+    'COMMENT_COUNT' => $row['nb_comments'],
+    'navbar' => $navigation_bar,
+    )
+  );
+  
+if ($row['nb_comments'] > 0)
+{
+  $query = '
+SELECT
+    com.id,
+    author,
+    author_id,
+    '.$conf['user_fields']['username'].' AS username,
+    date,
+    content,
+    validated,
+    website,
+    rate,
+    email
+  FROM '.GUESTBOOK_TABLE.' AS com
+  LEFT JOIN '.USERS_TABLE.' AS u
+    ON u.'.$conf['user_fields']['id'].' = author_id
+  WHERE '.implode(' AND ', $where_clauses).'
+  ORDER BY date DESC
+  LIMIT '.$conf['guestbook']['nb_comment_page'].' OFFSET '.$page['start'].'
+;';
+  $result = pwg_query( $query );
+
+  while ($row = pwg_db_fetch_assoc($result))
+  {
+    if (!empty($row['author']))
+    {
+      $author = $row['author'];
+      if ($author == 'guest')
+      {
+        $author = l10n('guest');
+      }
+    }
+    else
+    {
+      $author = stripslashes($row['username']);
+    }
+
+    $tpl_comment =
+      array(
+        'ID' => $row['id'],
+        'AUTHOR' => trigger_event('render_comment_author', $author),
+        'DATE' => format_date($row['date'], true),
+        'CONTENT' => trigger_event('render_comment_content',$row['content']),
+        'WEBSITE' => $row['website'],
+        'WEBSITE_NAME' => preg_replace('#^(https?:\/\/)#i', null, $row['website']),
+        'STARS' => get_stars($row['rate'], GUESTBOOK_PATH .'template/jquery.raty/'),
+        'RATE' => $row['rate'],
+      );
+      
+    if (is_admin() and !empty($row['email']))
+    {
+      $tpl_comment['EMAIL'] = $row['email'];
+    }
+
+    if (can_manage_comment('delete', $row['author_id']))
+    {
+      $tpl_comment['U_DELETE'] = add_url_params(
+        $url_self,
+        array(
+          'action'=>'delete_comment',
+          'comment_to_delete'=>$row['id'],
+          'pwg_token' => get_pwg_token(),
+          )
+        );
+    }
+    if (can_manage_comment('edit', $row['author_id']))
+    {
+      $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;
+          $tpl_comment['KEY'] = get_ephemeral_key(2);
+          $tpl_comment['CONTENT'] = $row['content'];
+          $tpl_comment['PWG_TOKEN'] = get_pwg_token();
+          $tpl_comment['U_CANCEL'] = $url_self;
+        }
+    }
+    if (is_admin())
+    {
+      if ($row['validated'] != 'true')
+      {
+        $tpl_comment['U_VALIDATE'] = add_url_params(
+                $url_self,
+                array(
+                  'action' => 'validate_comment',
+                  'comment_to_validate' => $row['id'],
+                  'pwg_token' => get_pwg_token(),
+                  )
+                );
+      }
+    }
+    $template->append('comments', $tpl_comment);
+  }
+}
+
+$show_add_comment_form = true;
+if (isset($edit_comment))
+{
+  $show_add_comment_form = false;
+}
+
+if ($show_add_comment_form)
+{
+  foreach (array('content','author','website','email') as $el)
+  {
+    ${$el} = '';
+    if ('reject'===@$comment_action and !empty($comm[$el]))
+    {
+      ${$el} = htmlspecialchars( stripslashes($comm[$el]) );
+    }
+  }
+  $template->assign('comment_add',
+      array(
+        'F_ACTION' => $url_self,
+        'KEY' => get_ephemeral_key(3),
+        'CONTENT' => $content,
+        'SHOW_AUTHOR' => !is_classic_user(),
+        'AUTHOR' => $author ,
+        'WEBSITE' => $website ,
+        'EMAIL' => $email ,
+      ));
+}
+
+$template->assign('ABS_GUESTBOOK_PATH', dirname(__FILE__).'/../');
+$template->assign('GUESTBOOK_PATH', GUESTBOOK_PATH);
+$template->set_filename('index', dirname(__FILE__).'/../template/guestbook.tpl');
+
+?>
Index: /extensions/GuestBook/include/index.php
===================================================================
--- /extensions/GuestBook/include/index.php	(revision 15940)
+++ /extensions/GuestBook/include/index.php	(revision 15940)
@@ -0,0 +1,30 @@
+<?php
+// +-----------------------------------------------------------------------+
+// | Piwigo - a PHP based photo gallery                                    |
+// +-----------------------------------------------------------------------+
+// | Copyright(C) 2008-2012 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.                                                                  |
+// +-----------------------------------------------------------------------+
+
+// Recursive call
+$url = '../';
+header( 'Request-URI: '.$url );
+header( 'Content-Location: '.$url );
+header( 'Location: '.$url );
+exit();
+?>
Index: /extensions/GuestBook/index.php
===================================================================
--- /extensions/GuestBook/index.php	(revision 15940)
+++ /extensions/GuestBook/index.php	(revision 15940)
@@ -0,0 +1,30 @@
+<?php
+// +-----------------------------------------------------------------------+
+// | Piwigo - a PHP based photo gallery                                    |
+// +-----------------------------------------------------------------------+
+// | Copyright(C) 2008-2012 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.                                                                  |
+// +-----------------------------------------------------------------------+
+
+// Recursive call
+$url = '../';
+header( 'Request-URI: '.$url );
+header( 'Content-Location: '.$url );
+header( 'Location: '.$url );
+exit();
+?>
Index: /extensions/GuestBook/language/en_UK/description.txt
===================================================================
--- /extensions/GuestBook/language/en_UK/description.txt	(revision 15940)
+++ /extensions/GuestBook/language/en_UK/description.txt	(revision 15940)
@@ -0,0 +1,1 @@
+Add a guestbook to the gallery
Index: /extensions/GuestBook/language/en_UK/index.php
===================================================================
--- /extensions/GuestBook/language/en_UK/index.php	(revision 15940)
+++ /extensions/GuestBook/language/en_UK/index.php	(revision 15940)
@@ -0,0 +1,30 @@
+<?php
+// +-----------------------------------------------------------------------+
+// | Piwigo - a PHP based photo gallery                                    |
+// +-----------------------------------------------------------------------+
+// | Copyright(C) 2008-2012 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.                                                                  |
+// +-----------------------------------------------------------------------+
+
+// Recursive call
+$url = '../';
+header( 'Request-URI: '.$url );
+header( 'Content-Location: '.$url );
+header( 'Location: '.$url );
+exit();
+?>
Index: /extensions/GuestBook/language/en_UK/plugin.lang.php
===================================================================
--- /extensions/GuestBook/language/en_UK/plugin.lang.php	(revision 15940)
+++ /extensions/GuestBook/language/en_UK/plugin.lang.php	(revision 15940)
@@ -0,0 +1,12 @@
+<?php
+
+$lang['Please enter your username'] = 'Please enter your username';
+$lang['invalid website address'] = 'invalid website address';
+$lang['GuestBook'] = 'Guestbook';
+$lang['Sign the guestbook'] = 'Sign the guestbook';
+$lang['not publicly visible'] = 'not publicly visible';
+$lang['Website'] = 'Website';
+$lang['* : mandatory fields'] = '* : mandatory fields';
+$lang['There are %d messages'] = 'There are %d messages';
+
+?>
Index: /extensions/GuestBook/language/fr_FR/description.txt
===================================================================
--- /extensions/GuestBook/language/fr_FR/description.txt	(revision 15940)
+++ /extensions/GuestBook/language/fr_FR/description.txt	(revision 15940)
@@ -0,0 +1,1 @@
+Ajout un livre d'or à la gallerie
Index: /extensions/GuestBook/language/fr_FR/index.php
===================================================================
--- /extensions/GuestBook/language/fr_FR/index.php	(revision 15940)
+++ /extensions/GuestBook/language/fr_FR/index.php	(revision 15940)
@@ -0,0 +1,30 @@
+<?php
+// +-----------------------------------------------------------------------+
+// | Piwigo - a PHP based photo gallery                                    |
+// +-----------------------------------------------------------------------+
+// | Copyright(C) 2008-2012 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.                                                                  |
+// +-----------------------------------------------------------------------+
+
+// Recursive call
+$url = '../';
+header( 'Request-URI: '.$url );
+header( 'Content-Location: '.$url );
+header( 'Location: '.$url );
+exit();
+?>
Index: /extensions/GuestBook/language/fr_FR/plugin.lang.php
===================================================================
--- /extensions/GuestBook/language/fr_FR/plugin.lang.php	(revision 15940)
+++ /extensions/GuestBook/language/fr_FR/plugin.lang.php	(revision 15940)
@@ -0,0 +1,12 @@
+<?php
+
+$lang['Please enter your username'] = 'Veuillez renseigner votre nom';
+$lang['invalid website address'] = 'adresse du site web invalide';
+$lang['GuestBook'] = 'Livre d\'or';
+$lang['Sign the guestbook'] = 'Signer le livre d\'or';
+$lang['not publicly visible'] = 'not visible';
+$lang['Website'] = 'Site web';
+$lang['* : mandatory fields'] = '* : champs obligatoires';
+$lang['There are %d messages'] = 'Il y a %d messages';
+
+?>
Index: /extensions/GuestBook/language/index.php
===================================================================
--- /extensions/GuestBook/language/index.php	(revision 15940)
+++ /extensions/GuestBook/language/index.php	(revision 15940)
@@ -0,0 +1,30 @@
+<?php
+// +-----------------------------------------------------------------------+
+// | Piwigo - a PHP based photo gallery                                    |
+// +-----------------------------------------------------------------------+
+// | Copyright(C) 2008-2012 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.                                                                  |
+// +-----------------------------------------------------------------------+
+
+// Recursive call
+$url = '../';
+header( 'Request-URI: '.$url );
+header( 'Content-Location: '.$url );
+header( 'Location: '.$url );
+exit();
+?>
Index: /extensions/GuestBook/main.inc.php
===================================================================
--- /extensions/GuestBook/main.inc.php	(revision 15940)
+++ /extensions/GuestBook/main.inc.php	(revision 15940)
@@ -0,0 +1,103 @@
+<?php
+/*
+Plugin Name: GuestBook
+Version: auto
+Description: Add a guestbook to the gallery
+Plugin URI: http://piwigo.org/ext/extension_view.php?eid=609
+Author: Mistic
+Author URI: http://www.strangeplanet.fr
+*/
+
+if (!defined('PHPWG_ROOT_PATH')) die('Hacking attempt!');
+
+global $prefixeTable;
+
+
+define('GUESTBOOK_PATH' , PHPWG_PLUGINS_PATH . basename(dirname(__FILE__)) . '/');
+define('GUESTBOOK_TABLE' , $prefixeTable . 'guestbook');
+define('GUESTBOOK_URL', make_index_url(array('section' => 'guestbook')));
+define('GUESTBOOK_ADMIN', get_root_url().'admin.php?page=plugin-' . basename(dirname(__FILE__)));
+
+add_event_handler('init', 'gb_init');
+
+function gb_init()
+{
+  global $conf;
+  
+  load_language('plugin.lang', GUESTBOOK_PATH);
+  $conf['guestbook'] = unserialize($conf['guestbook']);
+  
+  // menubar
+  if (script_basename() != 'admin')
+  {
+    add_event_handler('blockmanager_apply', 'gb_menubar_apply');
+  }
+  else
+  {
+    add_event_handler('get_admin_plugin_menu_links', 'gb_admin_menu');
+  }
+  
+  // guestbook section
+  add_event_handler('loc_end_section_init', 'gb_section_init');
+  add_event_handler('loc_end_index', 'gb_index');
+  
+  // stuff
+  // add_event_handler('get_stuffs_modules', 'gb_register_stuffs_module')
+}
+
+function gb_menubar_apply($menu_ref_arr)
+{
+  $menu = &$menu_ref_arr[0];
+  
+  if ( ($block = $menu->get_block('mbMenu')) != null )
+  {
+    array_push($block->data, array(
+      'URL' => GUESTBOOK_URL,
+      'TITLE' => l10n('GuestBook'),
+      'NAME' => l10n('GuestBook')
+    ));
+  }
+}
+
+function gb_section_init()
+{
+  global $tokens, $page;
+
+  if ($tokens[0] == 'guestbook')
+  {
+    $page['section'] = 'guestbook';
+    $page['title'] = l10n('GuestBook');
+  }
+}
+
+function gb_index() 
+{
+  global $template, $page, $conf;
+
+  if (isset($page['section']) and $page['section'] == 'guestbook')
+  {
+    include(GUESTBOOK_PATH . '/include/guestbook.inc.php');
+  }
+}
+
+/*function gb_register_stuffs_module($modules)
+{
+  array_push($modules, array(
+    'path' => GUESTBOOK_PATH . '/stuffs_module',
+    'name' => GB_NAME,
+    'description' => l10n('gb_stuffs_desc'),
+  ));
+
+  return $modules;
+}*/
+
+function gb_admin_menu($menu) 
+{
+  array_push($menu, array(
+    'NAME' => 'GuestBook',
+    'URL' => GUESTBOOK_ADMIN,
+  ));
+  return $menu;
+}
+
+?>
Index: /extensions/GuestBook/maintain.inc.php
===================================================================
--- /extensions/GuestBook/maintain.inc.php	(revision 15940)
+++ /extensions/GuestBook/maintain.inc.php	(revision 15940)
@@ -0,0 +1,56 @@
+<?php
+if (!defined('PHPWG_ROOT_PATH')) die('Hacking attempt!');
+
+// Default config
+define('default_guestbook_config', serialize(array(
+  'comments_validation' => false,
+  'email_admin_on_comment' => false,
+  'email_admin_on_comment_validation' => false,
+  'nb_comment_page' => 15,
+)));
+
+// Installation
+function plugin_install()
+{
+  global $prefixeTable;
+
+  pwg_query("
+CREATE TABLE `" . $prefixeTable . "guestbook` (
+  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+  `date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
+  `author` varchar(255) NOT NULL,
+  `author_id` smallint(5) DEFAULT NULL,
+  `anonymous_id` varchar(45) NOT NULL,
+  `email` varchar(255) DEFAULT NULL,
+  `website` varchar(255) DEFAULT NULL,
+  `content` longtext NOT NULL,
+  `rate` float(5,2) unsigned DEFAULT NULL,
+  `validated` enum('true','false') NOT NULL DEFAULT 'false',
+  `validation_date` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`)
+) DEFAULT CHARSET=utf8
+;");
+  
+  conf_update_param('guestbook', default_guestbook_config);
+}
+
+// Activation
+function plugin_activate()
+{
+  global $conf;
+  
+  if (!isset($conf['guestbook']))
+  {
+    conf_update_param('guestbook', default_guestbook_config);
+  }
+}
+
+// Uninstallation
+function plugin_uninstall()
+{
+  global $prefixeTable;
+
+  pwg_query("DROP TABLE `" . $prefixeTable . "guestbook`;");
+  pwg_query("DELETE FROM " . CONFIG_TABLE . " WHERE `param` = 'guestbook';");
+}
+?>
Index: /extensions/GuestBook/template/comment_list.tpl
===================================================================
--- /extensions/GuestBook/template/comment_list.tpl	(revision 15940)
+++ /extensions/GuestBook/template/comment_list.tpl	(revision 15940)
@@ -0,0 +1,54 @@
+<ul class="commentsList">
+{foreach from=$comments item=comment name=comment_loop}
+<li class="commentElement {if $smarty.foreach.comment_loop.index is odd}odd{else}even{/if}">
+	<div class="description"{if isset($comment.IN_EDIT)} style="height:200px"{/if}>
+		{if isset($comment.U_DELETE) or isset($comment.U_VALIDATE) or isset($comment.U_EDIT)}
+		<div class="actions" style="float:right;font-size:90%">
+		{if isset($comment.U_DELETE)}
+			<a href="{$comment.U_DELETE}" onclick="return confirm('{'Are you sure?'|@translate|@escape:javascript}');">
+				{'Delete'|@translate}
+			</a>{if isset($comment.U_VALIDATE) or isset($comment.U_EDIT) or isset($comment.U_CANCEL)} | {/if}
+		{/if}
+		{if isset($comment.U_CANCEL)}
+			<a href="{$comment.U_CANCEL}">
+				{'Cancel'|@translate}
+			</a>{if isset($comment.U_VALIDATE) or isset($comment.U_EDIT)} | {/if}
+		{/if}
+		{if isset($comment.U_EDIT) and !isset($comment.IN_EDIT)}
+			<a class="editComment" href="{$comment.U_EDIT}#edit_comment">
+				{'Edit'|@translate}
+			</a>{if isset($comment.U_VALIDATE)} | {/if}
+		{/if}
+		{if isset($comment.U_VALIDATE)}
+			<a href="{$comment.U_VALIDATE}">
+				{'Validate'|@translate}
+			</a>
+		{/if}&nbsp;
+		</div>
+		{/if}
+
+    <div class="commentHeader">
+      <span class="commentAuthor">{$comment.AUTHOR}</span> 
+      {if $comment.WEBSITE} - <a href="{$comment.WEBSITE}">{$comment.WEBSITE_NAME}</a>{/if}
+      {if $comment.EMAIL} - <a href="mailto:{$comment.EMAIL}">{$comment.EMAIL}</a>{/if}<br>
+      <span class="commentDate">{$comment.DATE}</span>
+      {if $comment.RATE}{$comment.STARS}{/if}
+    </div>
+		{if isset($comment.IN_EDIT)}
+		<a name="edit_comment"></a>
+		<form method="post" action="{$comment.U_EDIT}" id="editComment">
+			<p><label>{'Edit a comment'|@translate} :</label></p>
+			<p><textarea name="content" id="contenteditid" rows="5" cols="80">{$comment.CONTENT|@escape}</textarea></p>
+			<p><input type="hidden" name="key" value="{$comment.KEY}">
+				<input type="hidden" name="pwg_token" value="{$comment.PWG_TOKEN}">
+				<input type="hidden" name="image_id" value="{$comment.IMAGE_ID|@default:$current.id}">
+				<input type="submit" value="{'Submit'|@translate}">
+			</p>
+		</form>
+		{else}
+		<blockquote><div>{$comment.CONTENT}</div></blockquote>
+		{/if}
+	</div>
+</li>
+{/foreach}
+</ul>
Index: /extensions/GuestBook/template/guestbook.tpl
===================================================================
--- /extensions/GuestBook/template/guestbook.tpl	(revision 15940)
+++ /extensions/GuestBook/template/guestbook.tpl	(revision 15940)
@@ -0,0 +1,83 @@
+{combine_css path=$GUESTBOOK_PATH|@cat:"template/style.css"}
+{combine_script id="jquery.raty" path=$GUESTBOOK_PATH|@cat:"template/jquery.raty/jquery.raty.min.js"}
+
+{$MENUBAR}
+
+{footer_script}
+$("#comment_rate").raty({ldelim}
+  path: "{$GUESTBOOK_PATH}template/jquery.raty/",
+  half: true
+});
+$("#expandForm").click(function() {ldelim}
+  $("#guestbookAdd").animate({ldelim}"width": "500px"}, function() {ldelim}
+    $("#addComment").slideDown("slow");
+  });
+});
+{/footer_script}
+
+<div id="content" class="content{if isset($MENUBAR)} contentWithMenu{/if}">
+
+<div class="titrePage">
+	<ul class="categoryActions">
+    {if !empty($PLUGIN_INDEX_ACTIONS)}{$PLUGIN_INDEX_ACTIONS}{/if}
+	</ul>
+
+  <h2>{'GuestBook'|@translate}</h2>
+</div>{* <!-- titrePage --> *}
+
+{if isset($errors) or not empty($infos)}
+{include file='infos_errors.tpl'}
+{/if}
+
+{if isset($comment_add)}
+<div id="guestbookAdd">
+<h4 id="expandForm">{'Sign the guestbook'|@translate}</h4>
+<form method="post" action="{$comment_add.F_ACTION}" id="addComment" style="display:none;">
+  <table>
+  {if $comment_add.SHOW_AUTHOR}
+    <tr>
+    <td>
+      <p><label for="author">{'Author'|@translate}* :</label></p>
+      <p><input type="text" name="author" id="author" value="{$comment_add.AUTHOR}"></p>
+    </td>
+    <td>
+      <p><label for="email">{'Email address'|@translate} ({'not publicly visible'|@translate}) :</label></p>
+      <p><input type="text" name="email" id="email" size="30" value="{$comment_add.EMAIL}"></p>
+    </td>
+    </tr>
+  {/if}
+    <tr>
+    <td>
+      <p>{'Rate'|@translate} :</p>
+      <p><span id="comment_rate"></span></p>
+    </td>
+    <td>
+      <p><label for="website">{'Website'|@translate} :</label></p>
+      <p><input type="text" name="website" id="website" size="30" value="{$comment_add.WEBSITE}"></p>
+    </td>
+    </tr>
+  </table>
+  
+  <p><label for="contentid">{'Comment'|@translate}* :</label></p>
+  <p><textarea name="content" id="contentid" rows="5" cols="60">{$comment_add.CONTENT}</textarea></p>
+  <p><input type="hidden" name="key" value="{$comment_add.KEY}">
+    <input type="submit" value="{'Submit'|@translate}"> {'* : mandatory fields'|@translate}</p>
+</form>
+</div>
+{/if}
+
+<p class="comment_count">{'There are %d messages'|@translate|@sprintf:$COMMENT_COUNT}</p>
+
+{if isset($comments)}
+<div id="guestbookCommentList">
+  {if !empty($navbar)}
+    <div id="pictureCommentNavBar">
+      {include file='navigation_bar.tpl'|@get_extent:'navbar'}
+    </div>
+  {/if}
+  {include file=$ABS_GUESTBOOK_PATH|@cat:'template/comment_list.tpl'}
+</div>
+{/if}
+
+
+</div>{* <!-- content --> *}
Index: /extensions/GuestBook/template/index.php
===================================================================
--- /extensions/GuestBook/template/index.php	(revision 15940)
+++ /extensions/GuestBook/template/index.php	(revision 15940)
@@ -0,0 +1,30 @@
+<?php
+// +-----------------------------------------------------------------------+
+// | Piwigo - a PHP based photo gallery                                    |
+// +-----------------------------------------------------------------------+
+// | Copyright(C) 2008-2012 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.                                                                  |
+// +-----------------------------------------------------------------------+
+
+// Recursive call
+$url = '../';
+header( 'Request-URI: '.$url );
+header( 'Content-Location: '.$url );
+header( 'Location: '.$url );
+exit();
+?>
Index: /extensions/GuestBook/template/jquery.raty/index.php
===================================================================
--- /extensions/GuestBook/template/jquery.raty/index.php	(revision 15940)
+++ /extensions/GuestBook/template/jquery.raty/index.php	(revision 15940)
@@ -0,0 +1,30 @@
+<?php
+// +-----------------------------------------------------------------------+
+// | Piwigo - a PHP based photo gallery                                    |
+// +-----------------------------------------------------------------------+
+// | Copyright(C) 2008-2012 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.                                                                  |
+// +-----------------------------------------------------------------------+
+
+// Recursive call
+$url = '../';
+header( 'Request-URI: '.$url );
+header( 'Content-Location: '.$url );
+header( 'Location: '.$url );
+exit();
+?>
Index: /extensions/GuestBook/template/jquery.raty/jquery.raty.min.js
===================================================================
--- /extensions/GuestBook/template/jquery.raty/jquery.raty.min.js	(revision 15940)
+++ /extensions/GuestBook/template/jquery.raty/jquery.raty.min.js	(revision 15940)
@@ -0,0 +1,12 @@
+/*!
+ * jQuery Raty - A Star Rating Plugin
+ *
+ * Licensed under The MIT License
+ *
+ * @version        2.1.0
+ * @author         Washington Botelho
+ * @documentation  wbotelhos.com/raty
+ * 
+ */
+
+;(function(b){var a={init:function(c){return this.each(function(){var g=b.extend({},b.fn.raty.defaults,c),n=b(this).data("options",g);if(g.number>20){g.number=20;}else{if(g.number<0){g.number=0;}}if(g.round.down===undefined){g.round.down=b.fn.raty.defaults.round.down;}if(g.round.full===undefined){g.round.full=b.fn.raty.defaults.round.full;}if(g.round.up===undefined){g.round.up=b.fn.raty.defaults.round.up;}if(g.path.substring(g.path.length-1,g.path.length)!="/"){g.path+="/";}if(typeof g.start=="function"){g.start=g.start.call(this);}var h=!isNaN(parseInt(g.start,10)),f="";if(h){f=(g.start>g.number)?g.number:g.start;}var o=g.starOn,d=(g.space)?4:0,k="";for(var l=1;l<=g.number;l++){o=(f<l)?g.starOff:g.starOn;k=(l<=g.hintList.length&&g.hintList[l-1]!==null)?g.hintList[l-1]:l;n.append('<img src="'+g.path+o+'" alt="'+l+'" title="'+k+'" />');if(g.space){n.append((l<g.number)?"&nbsp;":"");}}var j=b("<input/>",{type:"hidden",name:g.scoreName}).appendTo(n);if(h){if(g.start>0){j.val(f);}a.roundStar.call(n,f);}if(g.iconRange){a.fillStar.call(n,f);}a.setTarget.call(n,f,g.targetKeep);var e=g.width||(g.number*g.size+g.number*d);if(g.cancel){var m=b('<img src="'+g.path+g.cancelOff+'" alt="x" title="'+g.cancelHint+'" class="raty-cancel"/>');if(g.cancelPlace=="left"){n.prepend("&nbsp;").prepend(m);}else{n.append("&nbsp;").append(m);}e+=g.size+d;}if(g.readOnly){a.fixHint.call(n);n.children(".raty-cancel").hide();}else{n.css("cursor","pointer");a.bindAction.call(n);}n.css("width",e);});},bindAction:function(){var c=this,d=this.data("options"),e=this.children("input");c.mouseleave(function(){a.initialize.call(c,e.val());a.setTarget.call(c,e.val(),d.targetKeep);});var g=this.children("img").not(".raty-cancel"),f=(d.half)?"mousemove":"mouseover";if(d.cancel){c.children(".raty-cancel").mouseenter(function(){b(this).attr("src",d.path+d.cancelOn);g.attr("src",d.path+d.starOff);a.setTarget.call(c,null,true);}).mouseleave(function(){b(this).attr("src",d.path+d.cancelOff);c.mouseout();}).click(function(h){e.removeAttr("value");if(d.click){d.click.call(c[0],null,h);}});}g.bind(f,function(i){var j=parseInt(this.alt,10);if(d.half){var h=parseFloat((i.pageX-b(this).offset().left)/d.size),k=(h>0.5)?1:0.5;j=parseFloat(this.alt)-1+k;a.fillStar.call(c,j);if(d.precision){j=j-k+h;}a.showHalf.call(c,j);}else{a.fillStar.call(c,j);}c.data("score",j);a.setTarget.call(c,j,true);}).click(function(h){e.val((d.half||d.precision)?c.data("score"):this.alt);if(d.click){d.click.call(c[0],e.val(),h);}});},cancel:function(c){return this.each(function(){var d=b(this);if(d.data("readonly")=="readonly"){return false;}if(c){a.click.call(d,null);}else{a.start.call(d,null);}d.mouseleave().children("input").removeAttr("value");});},click:function(c){return this.each(function(){var e=b(this);if(e.data("readonly")=="readonly"){return false;}a.initialize.call(e,c);var d=e.data("options");if(d.click){d.click.call(e[0],c);}else{b.error('you must add the "click: function(score, evt) { }" callback.');}a.setTarget.call(e,c,true);});},fillStar:function(e){var d=this.data("options"),c=this.children("img").not(".raty-cancel"),f=c.length,k=0,g,j,l;for(var h=1;h<=f;h++){g=c.eq(h-1);if(d.iconRange&&d.iconRange.length>k){j=d.iconRange[k];if(d.single){l=(h==e)?(j.on||d.starOn):(j.off||d.starOff);}else{l=(h<=e)?(j.on||d.starOn):(j.off||d.starOff);}if(h<=j.range){g.attr("src",d.path+l);}if(h==j.range){k++;}}else{if(d.single){l=(h==e)?d.starOn:d.starOff;}else{l=(h<=e)?d.starOn:d.starOff;}g.attr("src",d.path+l);}}},fixHint:function(){var c=this.data("options"),d=this.children("input"),f=parseInt(d.val(),10),e=c.noRatedMsg;if(!isNaN(f)&&f>0){e=(f<=c.hintList.length&&c.hintList[f-1]!==null)?c.hintList[f-1]:f;}d.attr("readonly","readonly");this.css("cursor","default").data("readonly","readonly").attr("title",e).children("img").attr("title",e);},readOnly:function(c){return this.each(function(){var d=b(this),e=d.children(".raty-cancel");if(e.length){if(c){e.hide();}else{e.show();}}if(c){d.unbind();d.children("img").unbind();a.fixHint.call(d);}else{a.bindAction.call(d);a.unfixHint.call(d);}});},roundStar:function(f){var c=this.data("options"),e=(f-Math.floor(f)).toFixed(2);if(e>c.round.down){var d=c.starOn;if(e<c.round.up&&c.halfShow){d=c.starHalf;}else{if(e<c.round.full){d=c.starOff;}}this.children("img").not(".raty-cancel").eq(Math.ceil(f)-1).attr("src",c.path+d);}},score:function(){var d=[],c;this.each(function(){c=b(this).children("input").val();c=(c=="")?null:parseFloat(c);d.push(c);});return(d.length>1)?d:d[0];},setTarget:function(f,d){var e=this.data("options");if(e.target){var c=b(e.target);if(c.length==0){b.error("target selector invalid or missing!");}else{var g=f;if(g==null&&!e.cancel){b.error('you must enable the "cancel" option to set hint on target.');}else{if(!d||g==""){g=e.targetText;}else{if(e.targetType=="hint"){if(g===null&&e.cancel){g=e.cancelHint;}else{g=e.hintList[Math.ceil(g-1)];}}else{if(g!=""&&!e.precision){g=parseInt(g,10);}else{g=parseFloat(g).toFixed(1);}}}if(e.targetFormat.indexOf("{score}")<0){b.error('template "{score}" missing!');}else{if(f!==null){g=e.targetFormat.toString().replace("{score}",g);}}if(c.is(":input")){c.val(g);}else{c.html(g);}}}}},showHalf:function(e){var c=this.data("options"),d=(e-Math.floor(e)).toFixed(1);if(d>0&&d<0.6){this.children("img").not(".raty-cancel").eq(Math.ceil(e)-1).attr("src",c.path+c.starHalf);}},start:function(c){return this.each(function(){var e=b(this);if(e.data("readonly")=="readonly"){return false;}a.initialize.call(e,c);var d=e.data("options");a.setTarget.call(e,c,true);});},initialize:function(d){var c=this.data("options");if(d<0){d=0;}else{if(d>c.number){d=c.number;}}a.fillStar.call(this,d);if(d!=""){if(c.halfShow){a.roundStar.call(this,d);}this.children("input").val(d);}},unfixHint:function(){var d=this.data("options"),e=this.children("img").filter(":not(.raty-cancel)");for(var c=0;c<d.number;c++){e.eq(c).attr("title",(c<d.hintList.length&&d.hintList[c]!==null)?d.hintList[c]:c);}this.css("cursor","pointer").removeData("readonly").removeAttr("title").children("input").attr("readonly","readonly");}};b.fn.raty=function(c){if(a[c]){return a[c].apply(this,Array.prototype.slice.call(arguments,1));}else{if(typeof c==="object"||!c){return a.init.apply(this,arguments);}else{b.error("Method "+c+" does not exist!");}}};b.fn.raty.defaults={cancel:false,cancelHint:"cancel this rating!",cancelOff:"cancel-off.png",cancelOn:"cancel-on.png",cancelPlace:"left",click:undefined,half:false,halfShow:true,hintList:["bad","poor","regular","good","gorgeous"],iconRange:undefined,noRatedMsg:"not rated yet",number:5,path:"img/",precision:false,round:{down:0.25,full:0.6,up:0.76},readOnly:false,scoreName:"score",single:false,size:16,space:true,starHalf:"star-half.png",starOff:"star-off.png",starOn:"star-on.png",start:0,target:undefined,targetFormat:"{score}",targetKeep:false,targetText:"",targetType:"hint",width:undefined};})(jQuery);
Index: /extensions/GuestBook/template/style.css
===================================================================
--- /extensions/GuestBook/template/style.css	(revision 15940)
+++ /extensions/GuestBook/template/style.css	(revision 15940)
@@ -0,0 +1,70 @@
+#guestbookAdd {
+  padding:15px;
+  width:180px;
+  margin:10px auto 25px auto;
+  background: #333333;
+  background: -moz-linear-gradient(top,  #333333 0%, #252525 100%);
+  background: -webkit-linear-gradient(top,  #333333 0%,#252525 100%);
+  background: -o-linear-gradient(top,  #333333 0%,#252525 100%);
+  background: -ms-linear-gradient(top,  #333333 0%,#252525 100%);
+  background: linear-gradient(top,  #333333 0%,#252525 100%);
+  border-radius:5px;
+  border:1px solid #555;
+  box-shadow:5px 5px 5px rgba(0, 0, 0, 0.25);
+  color:#aaa;
+}
+
+#guestbookAdd h4 {
+  margin:0;
+  cursor:pointer;
+  border-bottom-width:1px;
+  border-bottom-style:dotted;
+  text-align:center;
+}
+  #guestbookAdd h4:hover {
+    color:#fff;
+  }
+
+#guestbookAdd table {
+  width:100%;
+  text-align:left;
+}
+
+#addComment {
+  margin-top:5px;
+}
+
+p.comment_count {
+  text-align:center;
+  font-style:italic;
+  font-weight:bold;
+  font-size:1.1em;
+}
+
+#guestbookAdd p, .commentElement p {
+  text-align:left;
+  margin-bottom:0.5em;
+  margin-top:0.5em;
+}
+
+.commentElement {
+  padding:0;
+  list-style:none;
+}
+
+.commentElement .description {
+  padding:7px !important;
+}
+
+.commentElement .commentHeader  {
+  background:#444;
+  margin:-7px;
+  margin-bottom:0;
+  padding:3px;
+  color:#ddd;
+  border-radius:5px 5px 0 0;
+}
+
+.commentElement .commentHeader a {
+  color:#FFE093;
+}
