Index: /extensions/UserCollections/admin.php
===================================================================
--- /extensions/UserCollections/admin.php	(revision 20090)
+++ /extensions/UserCollections/admin.php	(revision 20090)
@@ -0,0 +1,39 @@
+<?php
+if (!defined('USER_COLLEC_PATH')) die('Hacking attempt!');
+
+global $template, $page, $conf;
+
+
+// tabsheet
+include_once(PHPWG_ROOT_PATH.'admin/include/tabsheet.class.php');
+$page['tab'] = (isset($_GET['tab'])) ? $_GET['tab'] : 'sets';
+  
+$tabsheet = new tabsheet();
+$tabsheet->add('sets', l10n('Collections'), USER_COLLEC_ADMIN . '-sets');
+if ($page['tab'] == 'export')
+{
+  if (isset($_GET['col_id']))
+  {
+    $tabsheet->add('export', l10n('Export'), USER_COLLEC_ADMIN . '-export&amp;col_id='.$_GET['col_id']);
+  }
+  else
+  {
+    $page['tab'] = 'sets';
+  }
+}
+$tabsheet->add('config', l10n('Configuration'), USER_COLLEC_ADMIN . '-config');
+$tabsheet->select($page['tab']);
+$tabsheet->assign();
+
+// include page
+include(USER_COLLEC_PATH . 'admin/' . $page['tab'] . '.php');
+
+// template
+$template->assign(array(
+  'USER_COLLEC_PATH' => USER_COLLEC_PATH,
+  'USER_COLLEC_ADMIN' => USER_COLLEC_ADMIN,
+  ));
+  
+$template->assign_var_from_handle('ADMIN_CONTENT', 'user_collections');
+
+?>
Index: /extensions/UserCollections/admin/config.php
===================================================================
--- /extensions/UserCollections/admin/config.php	(revision 20090)
+++ /extensions/UserCollections/admin/config.php	(revision 20090)
@@ -0,0 +1,21 @@
+<?php
+if (!defined('USER_COLLEC_PATH')) die('Hacking attempt!');
+
+if (isset($_POST['save_config']))
+{
+  $conf['user_collections'] = array(
+    'allow_mails'     => isset($_POST['allow_mails']),
+    'allow_public'    => isset($_POST['allow_public']),
+    );
+  
+  conf_update_param('user_collections', serialize($conf['user_collections']));
+}
+
+$template->assign(array(
+  'user_collections' => $conf['user_collections'],
+  ));
+
+
+$template->set_filename('user_collections', dirname(__FILE__) . '/template/config.tpl');
+
+?>
Index: /extensions/UserCollections/admin/export.php
===================================================================
--- /extensions/UserCollections/admin/export.php	(revision 20090)
+++ /extensions/UserCollections/admin/export.php	(revision 20090)
@@ -0,0 +1,36 @@
+<?php
+if (!defined('USER_COLLEC_PATH')) die('Hacking attempt!');
+
+try {
+  $UserCollection = new UserCollection($_GET['col_id']);
+  
+  $template->assign('COL_ID', $_GET['col_id']);
+}
+catch (Exception $e)
+{
+  array_push($page['errors'], $e->getMessage());
+}
+
+
+if (isset($_POST['download']))
+{
+  $content = $UserCollection->serialize($_POST['content']);
+  $filename = 'collection_'.$_GET['col_id'].'_'.date('Ymd-Hi').'.csv';
+  
+  header('Content-Type: application/force-download; name="'.$filename.'"');
+  header('Content-Disposition: attachment; filename="'.$filename.'"');
+  header('Content-Description: File Transfer');
+  header('Content-Transfer-Encoding: binary');
+  header('Content-Length: '.strlen($content).'');
+
+  header('Cache-Control: no-cache, must-revalidate');
+  header('Pragma: no-cache');
+  header('Expires: 0');
+  
+  echo $content;
+  exit;
+}
+
+$template->set_filename('user_collections', dirname(__FILE__) . '/template/export.tpl');
+
+?>
Index: /extensions/UserCollections/admin/index.php
===================================================================
--- /extensions/UserCollections/admin/index.php	(revision 20090)
+++ /extensions/UserCollections/admin/index.php	(revision 20090)
@@ -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/UserCollections/admin/sets.php
===================================================================
--- /extensions/UserCollections/admin/sets.php	(revision 20090)
+++ /extensions/UserCollections/admin/sets.php	(revision 20090)
@@ -0,0 +1,90 @@
+<?php
+if (!defined('USER_COLLEC_PATH')) die('Hacking attempt!');
+
+// actions
+if (isset($_GET['delete']))
+{
+  pwg_query('DELETE FROM '.COLLECTIONS_TABLE.' WHERE id = '.$_GET['delete'].';');
+  pwg_query('DELETE FROM '.COLLECTION_IMAGES_TABLE.' WHERE col_id = '.$_GET['delete'].';');
+}
+
+// filter
+$where_clauses = array('1=1');
+$order_by = 'date_creation DESC, name ASC';
+
+if (isset($_POST['filter']))
+{
+  if (!empty($_POST['username']))
+  {
+    array_push($where_clauses, 'username LIKE "%'.$_POST['username'].'%"');
+  }
+  
+  if (!empty($_POST['name']))
+  {
+    array_push($where_clauses, 'name LIKE "%'.$_POST['name'].'%"');
+  }
+  
+  $order_by = $_POST['order_by'].' '.$_POST['direction'];
+}
+
+
+// get sets
+$query = '
+SELECT 
+    c.*,
+    u.'.$conf['user_fields']['username'].' AS username
+  FROM '.COLLECTIONS_TABLE.' AS c
+    INNER JOIN '.USERS_TABLE.' AS u
+    ON c.user_id = u.'.$conf['user_fields']['id'].'
+  WHERE
+    '.implode("\n    AND ", $where_clauses).'
+  ORDER BY '.$order_by.'
+;';
+$sets = hash_from_query($query, 'id');
+
+foreach ($sets as $row)
+{
+  $template->append('sets', array(
+    'NAME' => $row['name'],
+    'NB_IMAGES' => $row['nb_images'],
+    'DATE_CREATION' => format_date($row['date_creation'], true),
+    'USERNAME' => $row['username'],
+    'IS_PUBLIC' => (bool)$row['public'],
+    'U_PUBLIC' => USER_COLLEC_PUBLIC . 'view/'.$row['public_id'],
+    'U_EDIT' => USER_COLLEC_PUBLIC . 'edit/'.$row['id'],
+    'U_EXPORT' => USER_COLLEC_ADMIN . '-export&amp;col_id='.$row['id'],
+    'U_DELETE' => USER_COLLEC_ADMIN . '-sets&amp;delete='.$row['id'],
+    ));
+}
+
+
+// filter options
+$page['order_by_items'] = array(
+  'date_creation' => l10n('Creation date'),
+  'nb_images' => l10n('Number of images'),
+  );
+
+$page['direction_items'] = array(
+  'DESC' => l10n('descending'),
+  'ASC' => l10n('ascending'),
+  );
+
+$template->assign('order_options', $page['order_by_items']);
+$template->assign('order_selected',
+    isset($_POST['order_by']) ? $_POST['order_by'] : '');
+
+$template->assign('direction_options', $page['direction_items']);
+$template->assign('direction_selected',
+    isset($_POST['direction']) ? $_POST['direction'] : '');
+
+
+$template->assign(array(
+  'F_USERNAME' => @htmlentities($_POST['username'], ENT_COMPAT, 'UTF-8'),
+  'F_NAME' => @htmlentities($_POST['name'], ENT_COMPAT, 'UTF-8'),
+  'F_FILTER_ACTION' => USER_COLLEC_ADMIN . '-sets',
+  ));
+
+
+$template->set_filename('user_collections', dirname(__FILE__) . '/template/sets.tpl');
+
+?>
Index: /extensions/UserCollections/admin/template/config.tpl
===================================================================
--- /extensions/UserCollections/admin/template/config.tpl	(revision 20090)
+++ /extensions/UserCollections/admin/template/config.tpl	(revision 20090)
@@ -0,0 +1,26 @@
+{combine_css path=$USER_COLLEC_PATH|@cat:"admin/template/style.css"}
+
+<div class="titrePage">
+	<h2>User Collections</h2>
+</div>
+
+<form method="post" action="" class="properties">
+<fieldset id="commentsConf">
+  <ul>
+    <li>
+      <label>
+        <input type="checkbox" name="allow_public" {if $user_collections.allow_public}checked="checked"{/if}>
+        <b>{'Allow users to set their collections as public'|@translate}</b>
+      </label>
+    </li>
+    <li>
+      <label>
+        <input type="checkbox" name="allow_mails" {if $user_collections.allow_mails}checked="checked"{/if}>
+        <b>{'Allow users to send their public collections by mail'|@translate}</b>
+      </label>
+    </li>
+  </ul>
+</fieldset>
+
+  <p class="formButtons"><input type="submit" name="save_config" value="{'Save Settings'|@translate}"></p>    
+</form>
Index: /extensions/UserCollections/admin/template/export.tpl
===================================================================
--- /extensions/UserCollections/admin/template/export.tpl	(revision 20090)
+++ /extensions/UserCollections/admin/template/export.tpl	(revision 20090)
@@ -0,0 +1,60 @@
+{combine_css path=$USER_COLLEC_PATH|@cat:"admin/template/style.css"}
+
+{footer_script require='jquery.ui.sortable'}{literal}
+$( "#fields_active, #fields_inactive" ).sortable({
+  connectWith: ".connectedSortable",
+  items: "> li",
+  placeholder: "sortable-moving"
+}).disableSelection();
+
+$("input[name='generate']").click(function() {
+  query = "ws.php?format=rest&method=pwg.collections.getSerialized&col_id={/literal}{$COL_ID}{literal}";
+  $("#fields_active li").each(function() {
+    query+= '&content[]='+ $(this).data('name');
+  });
+  
+  $("#iframeWrapper").show();
+  $("#invokeFrame").attr('src', query);
+  
+  return false;
+});
+
+$("input[name='download']").click(function() {
+  $("#fields_active li").each(function() {
+    $("#export_form").append('<input type="hidden" name="content[]" value="'+ $(this).data('name') +'"/>');
+  });
+});
+{/literal}{/footer_script}
+
+<div class="titrePage">
+	<h2>User Collections</h2>
+</div>
+
+{if $COL_ID}
+<form method="post" action="" class="properties" id="export_form">
+<fieldset>
+  <legend>{'Fields'|@translate}</legend>
+  <ul id="fields_active" class="connectedSortable">
+    <h4>{'Active'|@translate}</h4>
+    <li data-name="id"><img src="{$themeconf.admin_icon_dir}/cat_move.png"> id</li>
+    <li data-name="name"><img src="{$themeconf.admin_icon_dir}/cat_move.png"> name</li>
+    <li data-name="path"><img src="{$themeconf.admin_icon_dir}/cat_move.png"> path</li>
+  </ul>
+  <ul id="fields_inactive" class="connectedSortable">
+    <h4>{'Inactive'|@translate}</h4>
+    <li data-name="file"><img src="{$themeconf.admin_icon_dir}/cat_move.png"> file</li>
+    <li data-name="url"><img src="{$themeconf.admin_icon_dir}/cat_move.png"> url</li>
+  </ul>
+  
+  <p class="formButtons">
+    <input type="submit" name="generate" value="{'Generate'|@translate}">
+    <input type="submit" name="download" value="{'Download CSV file'|@translate}">
+  </p>    
+</fieldset>
+
+<fieldset id="iframeWrapper" style="display:none;">
+  <legend>{'Output'|@translate}</legend>
+  <iframe src="" id="invokeFrame" name="invokeFrame"></iframe>
+</fieldset>
+</form>
+{/if}
Index: /extensions/UserCollections/admin/template/index.php
===================================================================
--- /extensions/UserCollections/admin/template/index.php	(revision 20090)
+++ /extensions/UserCollections/admin/template/index.php	(revision 20090)
@@ -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/UserCollections/admin/template/sets.tpl
===================================================================
--- /extensions/UserCollections/admin/template/sets.tpl	(revision 20090)
+++ /extensions/UserCollections/admin/template/sets.tpl	(revision 20090)
@@ -0,0 +1,69 @@
+{combine_css path=$USER_COLLEC_PATH|@cat:"admin/template/style.css"}
+
+<div class="titrePage">
+	<h2>User Collections</h2>
+</div>
+
+<form class="filter" method="post" name="filter" action="{$F_FILTER_ACTION}">
+<fieldset>
+  <legend>{'Filter'|@translate}</legend>
+  <input type="hidden" name="page" value="user_list">
+
+  <label>{'Name'|@translate} <input type="text" name="name" value="{$F_NAME}"></label>
+  
+  <label>{'Username'|@translate} <input type="text" name="username" value="{$F_USERNAME}"></label>
+
+  <label>
+  {'Sort by'|@translate}
+  {html_options name=order_by options=$order_options selected=$order_selected}
+  </label>
+
+  <label>
+  {'Sort order'|@translate}
+  {html_options name=direction options=$direction_options selected=$direction_selected}
+  </label>
+
+  <label>
+  &nbsp;
+  <span><input class="submit" type="submit" name="filter" value="{'Submit'|@translate}"> <a href="{$F_FILTER_ACTION}">{'Reset'|@translate}</a></span>
+  </label>
+
+</fieldset>
+
+</form>
+
+<table class="table2" width="97%">
+  <thead>
+    <tr class="throw">
+      <td class="name">{'Name'|@translate}</td>
+      <td class="user">{'Username'|@translate}</td>
+      <td class="status">{'Public'|@translate}</td>
+      <td class="date">{'Creation date'|@translate}</td>
+      <td class="images">{'Number of images'|@translate}</td>
+      <td class="action">{'Actions'|@translate}</td>
+    </tr>
+  </thead>
+
+  {foreach from=$sets item=set name=sets_loop}
+  <tr class="{if $smarty.foreach.sets_loop.index is odd}row1{else}row2{/if}">
+    <td>
+      <a href="{$set.U_PUBLIC}">{$set.NAME}</a>
+    </td>
+    <td>{$set.USERNAME}</td>
+    <td style="text-align:center;">{if $set.IS_PUBLIC}{'Yes'|@translate}{else}{'No'|@translate}{/if}</td>
+    <td style="text-align:center;">{$set.DATE_CREATION}</td>
+    <td>{$set.NB_IMAGES}</td>
+    <td style="padding-left:25px;">
+      <a href="{$set.U_EDIT}" title="{'Edit this collection'|@translate}"><img src="{$themeconf.admin_icon_dir}/edit_s.png"></a>
+      <a href="{$set.U_EXPORT}" title="{'Export image list'|@translate}"><img src="{$themeconf.admin_icon_dir}/plug_install.png"></a>
+      <a href="{$set.U_DELETE}" title="{'Delete this collection'|@translate}" onClick="return confirm('{'Are your sure?'|@translate}');"><img src="{$themeconf.admin_icon_dir}/delete.png"></a>
+    </td>
+  </tr>
+  {/foreach}
+  
+  {if not $sets}
+  <tr class="row2">
+    <td colspan="8" style="text-align:center;font-style:italic;">{'No result'|@translate}</td>
+  </tr>
+  {/if}
+</table>
Index: /extensions/UserCollections/admin/template/style.css
===================================================================
--- /extensions/UserCollections/admin/template/style.css	(revision 20090)
+++ /extensions/UserCollections/admin/template/style.css	(revision 20090)
@@ -0,0 +1,99 @@
+.chzn-choices li {
+  clear:none !important;
+}
+
+.property {
+  width:auto !important;
+}
+
+input[name='max_size'], input[name='max_elements'] {
+  border:none;
+  background:none;
+  font-weight:bold;
+  margin-left:5px;
+}
+
+#max_size, #max_elements {
+  display:inline-block;
+  width:300px;
+}
+
+.table2 {
+  width:auto;
+}
+.table2 .throw {
+  font-size:100%;
+  line-height: 1em;
+}
+TABLE.table2 THEAD TD {
+  padding: 3px 5px !important;
+}
+.table2 .action {
+  width:90px;
+}
+.table2 .user, .table2 .name {
+  width:150px;
+}
+.table2 .date {
+  width:230px;
+}
+.table2 .images {
+  width:100px;
+}
+
+.connectedSortable {
+  display:inline-block;
+  width:150px;
+  vertical-align:top;
+  border:1px dashed #7a7a7a;
+  border-radius:5px;
+  padding:0 5px 5px 5px !important;
+  margin:5px !important;
+}
+  .connectedSortable h4 {
+    font-size:13px;
+    text-align:center;
+  }
+  .connectedSortable li, .sortable-moving  {
+    margin:2px;
+    padding:0 5xp !important;
+    border:1px solid #ffffff;
+    box-shadow:0 0 2px rgba(0, 0, 0, 0.5);
+    border-radius:3px;
+    cursor:move;
+    font-family:monospace;
+    font-size:12px;
+    color:#222;
+  }
+  .connectedSortable li img {
+    vertical-align:middle;
+  }
+  #fields_inactive li {
+    background: #fff4ed;
+    background: -moz-linear-gradient(-45deg,  #fff4ed 0%, #ffd8d8 100%);
+    background: -webkit-gradient(linear, left top, right bottom, color-stop(0%,#fff4ed), color-stop(100%,#ffd8d8));
+    background: -webkit-linear-gradient(-45deg,  #fff4ed 0%,#ffd8d8 100%);
+    background: -o-linear-gradient(-45deg,  #fff4ed 0%,#ffd8d8 100%);
+    background: -ms-linear-gradient(-45deg,  #fff4ed 0%,#ffd8d8 100%);
+    background: linear-gradient(135deg,  #fff4ed 0%,#ffd8d8 100%);
+    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#fff4ed', endColorstr='#ffd8d8',GradientType=1 );
+  }
+  #fields_active li {
+    background: #e9f6fd;
+    background: -moz-linear-gradient(-45deg,  #e9f6fd 0%, #d3eefb 100%);
+    background: -webkit-gradient(linear, left top, right bottom, color-stop(0%,#e9f6fd), color-stop(100%,#d3eefb));
+    background: -webkit-linear-gradient(-45deg,  #e9f6fd 0%,#d3eefb 100%);
+    background: -o-linear-gradient(-45deg,  #e9f6fd 0%,#d3eefb 100%);
+    background: -ms-linear-gradient(-45deg,  #e9f6fd 0%,#d3eefb 100%);
+    background: linear-gradient(135deg,  #e9f6fd 0%,#d3eefb 100%);
+    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#e9f6fd', endColorstr='#d3eefb',GradientType=1 );
+  }
+  .sortable-moving  {
+    height:1.8em;
+    opacity:0.5;
+  }
+  
+#invokeFrame {
+  width:100%;
+  height:500px;
+}
Index: /extensions/UserCollections/include/UserCollection.class.php
===================================================================
--- /extensions/UserCollections/include/UserCollection.class.php	(revision 20089)
+++ /extensions/UserCollections/include/UserCollection.class.php	(revision 20090)
@@ -12,11 +12,15 @@
    * @param: array images
    */
-  function __construct($col_id, $images=array(), $name=null, $active=false, $public=false)
+  function __construct($col_id, $images=array(), $name=null, $active=false, $public=false, $user_id=null)
   {
     global $user;
+    
+    if (empty($user_id)) {
+      $user_id = $user['id'];
+    }
     
     $this->data = array(
       'id' => 0,
-      'user_id' => $user['id'],
+      'user_id' => $user_id,
       'name' => null,
       'date_creation' => '0000-00-00 00:00:00',
@@ -28,5 +32,5 @@
     $this->images = array();
     
-    // access from public id
+    // access from public id (access permission is checked line 66)
     if ( strlen($col_id) == 10 and strpos($col_id, 'uc') === 0 )
     {
@@ -84,4 +88,5 @@
         pwg_query($query);
       
+        // select images of the collection
         $query = '
 SELECT image_id
@@ -91,8 +96,5 @@
         $this->images = array_from_query($query, 'image_id');
         
-        if ($this->data['nb_images'] != count($this->images))
-        {
-          $this->updateParam('nb_images', count($this->images));
-        }
+        $this->updateParam('nb_images', count($this->images));
       }
       else
@@ -130,5 +132,5 @@
       $this->data['id'] = pwg_db_insert_id();
       
-      $date = pwg_query('SELECT FROM_UNIXTIME(NOW());');
+      $date = pwg_query('SELECT NOW();');
       list($this->data['date_creation']) = pwg_db_fetch_row($date);
       
@@ -164,6 +166,9 @@
   function updateParam($name, $value)
   {
-    $this->data[$name] = $value;
-    pwg_query('UPDATE '.COLLECTIONS_TABLE.' SET '.$name.' = "'.$value.'" WHERE id = '.$this->data['id'].';');
+    if ($value != $this->data[$name])
+    {
+      $this->data[$name] = $value;
+      pwg_query('UPDATE '.COLLECTIONS_TABLE.' SET '.$name.' = "'.pwg_db_real_escape_string($value).'" WHERE id = '.$this->data['id'].';');
+    }
   }
   
@@ -246,4 +251,14 @@
       );
       
+    $query = '
+UPDATE '.COLLECTION_IMAGES_TABLE.'
+  SET add_date = NOW()
+  WHERE
+    col_id = '.$this->data['id'].'
+    AND image_id IN ('.implode(',', $image_ids).')
+    AND add_date IS NULL
+';
+    pwg_query($query);
+      
     $this->updateParam('nb_images', count($this->images));
   }
@@ -291,5 +306,5 @@
       'ACTIVE' => (bool)$this->data['active'],
       'PUBLIC' => (bool)$this->data['public'],
-      'DATE_CREATION' => format_date($this->data['date_creation'], true),
+      'DATE_CREATION' => $this->data['date_creation'],
       'U_PUBLIC' => USER_COLLEC_PUBLIC . 'view/'.$this->data['public_id'],
       'IS_TEMP' =>  $this->data['name'] == 'temp',
@@ -298,4 +313,257 @@
     return $set;
   }
+  
+  /**
+   * Send the collection by email
+   * @param: array
+   *          - sender_name
+   *          - sender_email
+   *          - recipient_email
+   *          - recipient_name
+   *          - nb_images
+   *          - message
+   * @return: array errors
+   */
+  function sendEmail($comm, $key)
+  {
+    global $conf, $page, $template;
+    
+    $errors = array();
+    
+    $comm = array_map('stripslashes', $comm);
+
+    $comment_action='validate';
+    
+    // check key
+    if (!verify_ephemeral_key(@$key))
+    {
+      array_push($errors, l10n('Invalid or expired security key'));
+      $comment_action='reject';
+    }
+
+    // check author
+    if (empty($comm['sender_name']))
+    {
+      array_push($errors, l10n('Please enter your name'));
+      $comment_action='reject';
+    }      
+    if (empty($comm['recipient_name']))
+    {
+      array_push($errors, l10n('Please enter the recipient name'));
+      $comment_action='reject';
+    }
+    
+    // check email
+    if (empty($comm['sender_email']))
+    {
+      array_push($errors, l10n('Please enter your e-mail'));
+      $comment_action='reject';
+    }
+    else if ( !empty($comm['sender_email']) and !uc_check_email_validity($comm['sender_email']) )
+    {
+      array_push($errors, l10n('mail address must be like xxx@yyy.eee (example : jack@altern.org)'));
+      $comment_action='reject';
+    }
+    if (empty($comm['recipient_email']))
+    {
+      array_push($errors, l10n('Please enter the recipient e-mail'));
+      $comment_action='reject';
+    }
+    else if ( !empty($comm['recipient_email']) and !uc_check_email_validity($comm['recipient_email']) )
+    {
+      array_push($errors, l10n('mail address must be like xxx@yyy.eee (example : jack@altern.org)'));
+      $comment_action='reject';
+    }
+     
+    // check content
+    if (!empty($comm['message']))
+    {
+      $comm['message'] = nl2br($comm['message']);
+    }
+    
+    include_once(PHPWG_ROOT_PATH.'include/functions_mail.inc.php');
+    
+    if ($comment_action == 'validate')
+    {
+      // format subject
+      $subject = '['.$conf['gallery_title'].'] '.sprintf(l10n('A photo collection by %s'), $comm['sender_name']);
+      $subject = encode_mime_header($subject);
+            
+      // format expeditor
+      $args['from'] = format_email($comm['sender_name'], $comm['sender_email']);
+      $args['to'] = format_email($comm['recipient_name'], $comm['recipient_email']);
+      
+      // hearders
+      $headers = 'From: '.$args['from']."\n";  
+      $headers.= 'MIME-Version: 1.0'."\n";
+      $headers.= 'X-Mailer: Piwigo Mailer'."\n";
+      $headers.= 'Content-Transfer-Encoding: 8bit'."\n";
+      $headers.= 'Content-Type: text/html; charset="'.get_pwg_charset().'";'."\n";
+            
+      // mail content
+      $content = $this->getMailContent($comm);
+      $content = wordwrap($content, 70, "\n", true);
+      
+      // send mail
+      $result =
+        trigger_event('send_mail',
+          false, /* Result */
+          trigger_event('send_mail_to', $args['to']),
+          trigger_event('send_mail_subject', $subject),
+          trigger_event('send_mail_content', $content),
+          trigger_event('send_mail_headers', $headers),
+          $args
+        );
+      
+      if ($result == false)
+      {
+        $_SESSION['page_errors'][] = l10n('Error while sending e-mail');
+      }
+      else
+      {
+        $_SESSION['page_infos'][] = l10n('E-mail sent successfully');
+      }
+      
+      redirect();
+    }
+    
+    return $errors;
+  }
+  
+  /**
+   * get mail content for sendMail()
+   */
+  function getMailContent($params)
+  {
+    global $user, $conf, $template;
+    
+    // switch to guest user
+    $user_save = $user;
+    $user = build_user($conf['guest_id'], true);
+    
+    // get pictures
+    $query = '
+SELECT
+    id,
+    file,
+    name,
+    path
+  FROM '.IMAGES_TABLE.' AS i
+    JOIN '.IMAGE_CATEGORY_TABLE.' AS ci ON ci.image_id = i.id
+  WHERE id IN ('.implode(',', $this->images).')
+    '.get_sql_condition_FandF(array(
+                'forbidden_categories' => 'category_id',
+                'forbidden_images' => 'id'
+                ),
+              'AND'
+              ).'
+  GROUP BY i.id
+  ORDER BY '.DB_RANDOM_FUNCTION.'()
+  LIMIT '.$params['nb_images'].'
+;';
+    $pictures = hash_from_query($query, 'id');
+    
+    // switch back to current user
+    $user = $user_save;
+    unset($user_save);
+  
+    // picture sinfos
+    set_make_full_url();
+    $tpl_vars = array();
+    foreach ($pictures as $row)
+    {
+      $name = render_element_name($row);
+      
+      $tpl_vars[] = array(
+        'TN_ALT' => htmlspecialchars(strip_tags($name)),
+        'NAME' => $name,
+        'URL' => make_picture_url(array('image_id' => $row['id'])),
+        'THUMB' => DerivativeImage::url(IMG_SQUARE, $row),
+        );
+    }
+    
+    // template
+    $mail_css = file_get_contents(dirname(__FILE__).'/../template/mail.css');
+    
+    $template->assign(array(
+      'GALLERY_URL' => get_gallery_home_url(),
+      'PHPWG_URL' => PHPWG_URL,
+      'UC_MAIL_CSS' => str_replace("\n", null, $mail_css),
+      'MAIL_TITLE' => $this->getParam('name').' ('.sprintf(l10n('by %s'), $params['sender_name']).')',
+      'COL_URL' => USER_COLLEC_PUBLIC . 'view/'.$this->data['public_id'],
+      'PARAMS' => $params,
+      'derivative_params' => ImageStdParams::get_by_type(IMG_SQUARE),
+      'thumbnails' => $tpl_vars,
+      ));
+      
+    $template->set_filename('uc_mail', dirname(__FILE__).'/../template/mail.tpl');
+    $content = $template->parse('uc_mail', true);
+  
+    unset_make_full_url();
+    
+    return $content;
+  }
+
+  /**
+   * generate a listing of the collection
+   */
+  function serialize($params)
+  {      
+    $content = null;
+     
+    // get images infos
+    $query = '
+SELECT
+    id,
+    file,
+    name,
+    path
+  FROM '.IMAGES_TABLE.'
+  WHERE id IN('.implode(',', $this->images).')
+  ORDER BY id
+;';
+    $pictures = hash_from_query($query, 'id');
+    
+    if (count($pictures))
+    {
+      // generate csv
+      set_make_full_url();
+      $root_url = get_root_url();
+      
+      $fp = fopen('php://temp', 'r+');
+      foreach ($pictures as $row)
+      {
+        $element = array();
+        foreach ($params as $field)
+        {
+          switch ($field)
+          {
+          case 'id':
+            $element[] = $row['id']; break;
+          case 'file':
+            $element[] = $row['file']; break;
+          case 'name':
+            $element[] = render_element_name($row); break;
+          case 'url':
+            $element[] = make_picture_url(array('image_id'=>$row['id'], 'image_file'=>$row['file'])); break;
+          case 'path':
+            $element[] = $root_url.ltrim($row['path'], './'); break;
+          }
+        }
+        if (!empty($element))
+        {
+          fputcsv($fp, $element);
+        }
+      }
+      
+      rewind($fp);
+      $content = stream_get_contents($fp);
+      fclose($fp);
+      
+      unset_make_full_url();
+    }
+    
+    return $content;
+  }
 }
 
Index: /extensions/UserCollections/include/collections.inc.php
===================================================================
--- /extensions/UserCollections/include/collections.inc.php	(revision 20089)
+++ /extensions/UserCollections/include/collections.inc.php	(revision 20090)
@@ -159,4 +159,5 @@
     $self_url = USER_COLLEC_PUBLIC . 'edit/'.$page['col_id'];
     $template->assign(array(
+      'user_collections' => $conf['user_collections'],
       'USER_COLLEC_PATH' => USER_COLLEC_PATH,
       'F_ACTION' => $self_url,
@@ -184,7 +185,45 @@
         else
         {
-          $UserCollection->updateParam('name', $_POST['name']);
+          $UserCollection->updateParam('name', stripslashes($_POST['name']));
+        }
+        if (!$conf['user_collections']['allow_public'])
+        {
+          $_POST['public'] = '0';
         }
         $UserCollection->updateParam('public', $_POST['public']);
+      }
+      
+      // send mail
+      if ( $conf['user_collections']['allow_public'] and $conf['user_collections']['allow_mails'] )
+      {
+        $contact = array(
+            'sender_name' => $user['username'],
+            'sender_email' => $user['email'],
+            'recipient_name' => null,
+            'recipient_email' => null,
+            'nb_images' => 4,
+            'message' => null,
+            );
+            
+        if ( isset($_POST['send_mail']) and (bool)$UserCollection->getParam('public') )
+        {
+          $contact = array(
+            'sender_email' => trim($_POST['sender_email']),
+            'sender_name' => trim($_POST['sender_name']),
+            'recipient_email' => trim($_POST['recipient_email']),
+            'recipient_name' => trim($_POST['recipient_name']),
+            'nb_images' => $_POST['nb_images'],
+            'message' => $_POST['message'],
+            );
+            
+          $errors = $UserCollection->sendEmail($contact, @$_POST['key']);
+          if (count($errors))
+          {
+            $template->assign('uc_mail_errors', $errors);
+          }
+        }
+        
+        $contact['KEY'] = get_ephemeral_key(3);
+        $template->assign('contact', $contact);
       }
       
@@ -202,32 +241,38 @@
       }
       
-      // special template
-      add_event_handler('loc_end_index_thumbnails', 'user_collections_thumbnails_in_collection', EVENT_HANDLER_PRIORITY_NEUTRAL+10, 2); // +10 to overload GThumb+
+      // add links for colorbox
+      add_event_handler('loc_end_index_thumbnails', 'user_collections_thumbnails_in_collection', EVENT_HANDLER_PRIORITY_NEUTRAL, 2);
+      
+      // add remove item links
       $template->set_prefilter('index_thumbnails', 'user_collections_thumbnails_list_prefilter');
       
       // collection content
       $col = $UserCollection->getCollectionInfo();
+      $col['DATE_CREATION'] = format_date($col['DATE_CREATION'], true);
       $col['U_CLEAR'] = $self_url.'&amp;action=clear';
       $col['U_DELETE'] = add_url_params(USER_COLLEC_PUBLIC, array('action'=>'delete','col_id'=>$page['col_id']));
       $template->assign('collection', $col);
-      
       $page['items'] = $UserCollection->getImages();
       
-      // navigation bar
-      $page['start'] = isset($_GET['start']) ? $_GET['start'] : 0;
-      if (count($page['items']) > $page['nb_image_page'])
-      {
-        $page['navigation_bar'] = create_navigation_bar(
-          $self_url,
-          count($page['items']),
-          $page['start'],
-          $page['nb_image_page'],
-          false
-          );
-        $template->assign('navbar', $page['navigation_bar']);
-      }
-      
-      // display
-      include(PHPWG_ROOT_PATH . 'include/category_default.inc.php');
+      // toolbar buttons
+      $buttons = null;
+      if ($conf['user_collections']['allow_public'] and $conf['user_collections']['allow_mails'])
+      {
+        $buttons.= '<li><a class="mail_colorbox_open" href="#mail_form" title="'.l10n('Send this collection my mail').'" class="pwg-state-default pwg-button" rel="nofollow" '.(!$col['PUBLIC']?'onClick="alert(\''.l10n('The collection must be public in order to send it').'\');return false;"':null).'>
+          <span class="pwg-icon user-collections-delete-icon" style="background:url(\'' . get_root_url().USER_COLLEC_PATH . 'template/resources/mail.png\') center center no-repeat;">&nbsp;</span><span class="pwg-button-text">'.l10n('Send').'</span>
+        </a></li>';
+      }
+      $buttons.= '
+        <li><a href="'. $col['U_CLEAR'] .'" title="'.l10n('Clear this collection').'" class="pwg-state-default pwg-button" rel="nofollow" onClick="return confirm(\''.l10n('Are you sure?').'\');">
+          <span class="pwg-icon user-collections-delete-icon" style="background:url(\'' . get_root_url().USER_COLLEC_PATH . 'template/resources/bin.png\') center center no-repeat;">&nbsp;</span><span class="pwg-button-text">'.l10n('Clear').'</span>
+        </a></li>
+        <li><a href="'. $col['U_DELETE'] .'" title="'.l10n('Delete this collection').'" class="pwg-state-default pwg-button" rel="nofollow" onClick="return confirm(\''.l10n('Are you sure?').'\');">
+          <span class="pwg-icon user-collections-delete-icon" style="background:url(\'' . get_root_url().USER_COLLEC_PATH . 'template/resources/delete.png\') center center no-repeat;">&nbsp;</span><span class="pwg-button-text">'.l10n('Delete').'</span>
+        </a></li>';
+      $template->concat('COLLECTION_ACTIONS', $buttons);
+      
+      // thumbnails
+      define('USER_COLLEC_REMOVE_GTHUMB', true);
+      include(USER_COLLEC_PATH . '/include/display_thumbnails.inc.php');
       
       $template->concat('TITLE', $conf['level_separator'].$UserCollection->getParam('name'));
@@ -245,5 +290,5 @@
   {
     // security
-    if ( empty($page['col_id']) or strlen($page['col_id']) != 10 or strpos($page['col_id'], 'uc') === false )
+    if ( empty($page['col_id']) or strlen($page['col_id']) != 10 or strpos($page['col_id'], 'uc') === false or !$conf['user_collections']['allow_public'] )
     {
       $_SESSION['page_errors'][] = l10n('Invalid collection');
@@ -257,28 +302,10 @@
     try {
       $UserCollection = new UserCollection($page['col_id']);
-      
-      // special template
-      add_event_handler('loc_end_index_thumbnails', 'user_collections_thumbnails_in_collection', EVENT_HANDLER_PRIORITY_NEUTRAL+10, 2); // +10 to overload GThumb+
-      
-      // collection content
       $page['items'] = $UserCollection->getImages();
       
-      // navigation bar
-      $page['start'] = isset($_GET['start']) ? $_GET['start'] : 0;
-      if (count($page['items']) > $page['nb_image_page'])
-      {
-        $page['navigation_bar'] = create_navigation_bar(
-          $self_url,
-          count($page['items']),
-          $page['start'],
-          $page['nb_image_page'],
-          false
-          );
-        $template->assign('navbar', $page['navigation_bar']);
-      }
-      
-      // display
-      include(PHPWG_ROOT_PATH . 'include/category_default.inc.php');
-      
+      // thumbnails
+      include(USER_COLLEC_PATH . '/include/display_thumbnails.inc.php');
+      
+      // add username in title
       include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
       $template->concat('TITLE', 
@@ -295,4 +322,5 @@
   }
 }
+
 
 $template->assign(array(
Index: /extensions/UserCollections/include/display_thumbnails.inc.php
===================================================================
--- /extensions/UserCollections/include/display_thumbnails.inc.php	(revision 20090)
+++ /extensions/UserCollections/include/display_thumbnails.inc.php	(revision 20090)
@@ -0,0 +1,54 @@
+<?php
+defined('USER_COLLEC_PATH') or die('Hacking attempt!');
+
+if (defined('USER_COLLEC_REMOVE_GTHUMB'))
+{
+  global $uc_nb_image_page_save;
+
+  $user['nb_image_page'] = $uc_nb_image_page_save['user'];
+  $page['nb_image_page'] = $uc_nb_image_page_save['page'];
+  remove_event_handler('loc_end_index_thumbnails', 'process_GThumb', 50);
+  remove_event_handler('loc_end_index', 'GThumb_remove_thumb_size');
+}
+
+// navigation bar
+$page['start'] = isset($_GET['start']) ? $_GET['start'] : 0;
+if (count($page['items']) > $page['nb_image_page'])
+{
+  $page['navigation_bar'] = create_navigation_bar(
+    $self_url,
+    count($page['items']),
+    $page['start'],
+    $page['nb_image_page'],
+    false
+    );
+  $template->assign('navbar', $page['navigation_bar']);
+}
+
+// display
+include(PHPWG_ROOT_PATH . 'include/category_default.inc.php');
+
+// multisize link
+$url = add_url_params(
+    $self_url,
+    array('display' => '')
+  );
+  
+$selected_type = $template->get_template_vars('derivative_params')->type;
+$template->clear_assign( 'derivative_params' );
+$type_map = ImageStdParams::get_defined_type_map();
+unset($type_map[IMG_XXLARGE], $type_map[IMG_XLARGE]);
+
+foreach($type_map as $params)
+{
+  $template->append(
+    'image_derivatives',
+    array(
+      'DISPLAY' => l10n($params->type),
+      'URL' => $url.$params->type,
+      'SELECTED' => ($params->type == $selected_type ? true:false),
+      )
+    );
+}
+  
+?>
Index: /extensions/UserCollections/include/events.inc.php
===================================================================
--- /extensions/UserCollections/include/events.inc.php	(revision 20089)
+++ /extensions/UserCollections/include/events.inc.php	(revision 20090)
@@ -3,4 +3,13 @@
 
 # this file contains all functions directly called by the triggers #
+
+/* compatibility fix with Gthumb+ */
+function user_collections_save_pagination()
+{
+  global $user, $page, $uc_nb_image_page_save;
+   
+  $uc_nb_image_page_save['user'] = $user['nb_image_page'];
+  $uc_nb_image_page_save['page'] = $page['nb_image_page'];
+}
 
 
@@ -122,7 +131,7 @@
 {strip}<a class="addCollection" href="{$collection_toggle_url}{$thumbnail.id}" data-id="{$thumbnail.id}" rel="nofollow">
 {if $COL_ID or $thumbnail.COLLECTION_SELECTED}
-{\'Remove from collection\'|@translate}&nbsp;<img src="{$ROOT_URL}{$USER_COLLEC_PATH}template/image_delete.png" title="{\'Remove from collection\'|@translate}">
+{\'Remove from collection\'|@translate}&nbsp;<img src="{$ROOT_URL}{$USER_COLLEC_PATH}template/resources/image_delete.png" title="{\'Remove from collection\'|@translate}">
 {else}
-{\'Add to collection\'|@translate}&nbsp;<img src="{$ROOT_URL}{$USER_COLLEC_PATH}template/image_add.png" title="{\'Add to collection\'|@translate}">
+{\'Add to collection\'|@translate}&nbsp;<img src="{$ROOT_URL}{$USER_COLLEC_PATH}template/resources/image_add.png" title="{\'Add to collection\'|@translate}">
 {/if}
 </a>{/strip}';
Index: /extensions/UserCollections/include/functions.inc.php
===================================================================
--- /extensions/UserCollections/include/functions.inc.php	(revision 20089)
+++ /extensions/UserCollections/include/functions.inc.php	(revision 20090)
@@ -32,3 +32,23 @@
 }
 
+function uc_check_email_validity($mail_address)
+{
+  if (function_exists('email_check_format'))
+  {
+    return email_check_format($mail_address); // Piwigo 2.5
+  }
+  else 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';
+
+    return (bool)preg_match($regex, $mail_address);
+  }
+}
+
 ?>
Index: /extensions/UserCollections/include/install.inc.php
===================================================================
--- /extensions/UserCollections/include/install.inc.php	(revision 20089)
+++ /extensions/UserCollections/include/install.inc.php	(revision 20090)
@@ -5,4 +5,15 @@
 {
   global $conf, $prefixeTable;
+  
+  if (empty($conf['user_collections']))
+  {
+    $default_config = serialize(array(
+      'allow_mails' => true,
+      'allow_public' => true,
+      ));
+      
+    conf_update_param('user_collections', $default_config);
+    $conf['user_collections'] = $default_config;
+  }
   
   // create tables
@@ -26,8 +37,15 @@
   `col_id` mediumint(8) NOT NULL,
   `image_id` mediumint(8) NOT NULL,
+  `add_date` DATETIME NULL,
   UNIQUE KEY `UNIQUE` (`col_id`,`image_id`)
 ) DEFAULT CHARSET=utf8
 ;';
   pwg_query($query);
+  
+  $result = pwg_query('SHOW COLUMNS FROM `'.$prefixeTable.'collection_images` LIKE "add_date";');
+  if (!pwg_db_num_rows($result))
+  {
+    pwg_query('ALTER TABLE `'.$prefixeTable.'collection_images` ADD `add_date` DATETIME NULL;');
+  }
 }
 
Index: /extensions/UserCollections/include/plain_encoder.php
===================================================================
--- /extensions/UserCollections/include/plain_encoder.php	(revision 20090)
+++ /extensions/UserCollections/include/plain_encoder.php	(revision 20090)
@@ -0,0 +1,43 @@
+<?php
+// +-----------------------------------------------------------------------+
+// | Piwigo - a PHP based photo gallery                                    |
+// +-----------------------------------------------------------------------+
+// | Copyright(C) 2008-2013 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.                                                                  |
+// +-----------------------------------------------------------------------+
+
+class PwgPlainEncoder extends PwgResponseEncoder
+{
+  function encodeResponse($response)
+  {
+    $respClass = strtolower( @get_class($response) );
+    if ($respClass=='pwgerror')
+    {
+      return 'Error ['.$response->code().'] '.$response->message();
+    }
+    parent::flattenResponse($response);
+    return $response;
+  }
+
+  function getContentType()
+  {
+    return 'text/plain';
+  }
+}
+
+?>
Index: /extensions/UserCollections/include/ws_functions.inc.php
===================================================================
--- /extensions/UserCollections/include/ws_functions.inc.php	(revision 20090)
+++ /extensions/UserCollections/include/ws_functions.inc.php	(revision 20090)
@@ -0,0 +1,489 @@
+<?php
+defined('USER_COLLEC_PATH') or die('Hacking attempt!');
+
+function user_collections_ws_add_methods($arr)
+{
+  $service = &$arr[0];
+  global $conf;
+  
+  $service->addMethod(
+    'pwg.collections.create',
+    'ws_collections_create',
+    array(
+      'name' => array(),
+      'user_id' => array('default' => null),
+      'active' => array('default' => 0),
+      'public' => array('default' => 0),
+      ),
+    'Create a new User Collection. If "user_id" is empty, the collection is created for the current user.'
+    );
+    
+  $service->addMethod(
+    'pwg.collections.delete',
+    'ws_collections_delete',
+    array(
+      'col_id' => array(),
+      ),
+    'Delete a User Collection. The current user must be admin or owner of the collection.'
+    );
+    
+  $service->addMethod(
+    'pwg.collections.getList',
+    'ws_collections_getList',
+    array(
+      'col_id' => array('default' => null),
+      'user_id' => array('default' => null),
+      'name' => array('default' => null),
+      'public' => array('default' => null),
+      'active' => array('default' => null),
+      ),
+    'Retrive a list of collections.'
+    );
+    
+  $service->addMethod(
+    'pwg.collections.addImages',
+    'ws_collections_addImages',
+    array(
+      'col_id' => array(),
+      'image_ids' => array('flags'=>WS_PARAM_FORCE_ARRAY),
+      ),
+    'Add images to a collection. The current user must be admin or owner of the collection.'
+    );
+    
+  $service->addMethod(
+    'pwg.collections.removeImages',
+    'ws_collections_removeImages',
+    array(
+      'col_id' => array(),
+      'image_ids' => array('flags'=>WS_PARAM_FORCE_ARRAY),
+      ),
+    'Remove images from a collection. The current user must be admin or owner of the collection.'
+    );
+    
+  $service->addMethod(
+    'pwg.collections.getImages',
+    'ws_collections_getImages',
+    array(
+      'col_id' => array(),
+      'per_page' => array('default'=>100, 'maxValue'=>$conf['ws_max_images_per_page']),
+      'page' => array('default'=>0),
+      'order' => array('default'=>null),
+      ),
+    'Returns elements for the corresponding  collection.'
+    );
+    
+  $service->addMethod(
+    'pwg.collections.getSerialized',
+    'ws_collections_getSerialized',
+    array(
+      'col_id' => array(),
+      'content' => array('default'=>array('id','name','url','path'), 'flags'=>WS_PARAM_FORCE_ARRAY),
+      ),
+    'Returns a serialized version of the collection in CSV.<br>Available options for "content" are : id, file, name, url, path.<br>The return type is plain/text whatever you select as response format.'
+    );
+}
+
+/**
+ * create a new collection
+ */
+function ws_collections_create($params, &$service)
+{
+  global $conf, $user;
+  
+  // check status
+  if (is_a_guest())
+  {
+    return new PwgError(403, 'Forbidden');
+  }
+  
+  // check name
+  if (empty($params['name']))
+  {
+    return new PwgError(WS_ERR_MISSING_PARAM, 'Empty collection name');
+  }
+  
+  // check user id
+  if (!empty($params['user_id']))
+  {
+    if (!is_admin() and $params['user_id'] != $user['id'])
+    {
+      return new PwgError(403, 'Forbidden');
+    }
+    include_once(PHPWG_ROOT_PATH . 'admin/include/functions.php');
+    if (get_username($params['user_id']) === false)
+    {
+      return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid user id');
+    }
+  }
+  else
+  {
+    $params['user_id'] = $user['id'];
+  }
+  
+  // check public
+  if ($params['public'] != 0 and $params['public'] != 1)
+  {
+    return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid "public" value, 0 or 1.');
+  }
+  if (!$conf['user_collections']['allow_public'])
+  {
+    $params['public'] = 0;
+  }
+  
+  // check active
+  if ($params['active'] != 0 and $params['active'] != 1)
+  {
+    return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid "active" value, 0 or 1.');
+  }
+  
+  $UserCollection = new UserCollection('new', array(), $params['name'], $params['active'], $params['public'], $params['user_id']);
+  
+  $infos = array_change_key_case($UserCollection->getCollectionInfo(), CASE_LOWER);
+  
+  return $infos;
+}
+
+/**
+ * delete a collection
+ */
+function ws_collections_delete($params, &$service)
+{
+  global $user;
+  
+  // check status
+  if (is_a_guest())
+  {
+    return new PwgError(403, 'Forbidden');
+  }
+  
+  // check collection id
+  if (!preg_match('#^[0-9]+$#', $params['col_id']))
+  {
+    return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid collection id');
+  }
+  
+  $query = '
+SELECT user_id
+  FROM '.COLLECTIONS_TABLE.'
+  WHERE id = '.$params['col_id'].'
+;';
+  $result = pwg_query($query);
+  
+  if (!pwg_db_num_rows($result))
+  {
+    return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid collection id');
+  }
+  else
+  {
+    // check owner
+    list($user_id) = pwg_db_fetch_row($result);
+    
+    if (!is_admin() and $user_id != $user['id'])
+    {
+      return new PwgError(403, 'Forbidden');
+    }
+    
+    // delete
+    $query = '
+DELETE ci, c
+  FROM '.COLLECTION_IMAGES_TABLE.' AS ci
+    RIGHT JOIN '.COLLECTIONS_TABLE.' AS c 
+    ON ci.col_id = c.id
+  WHERE
+    c.user_id = '.$user_id.'
+    AND c.id = '.$params['col_id'].'
+;';
+    pwg_query($query);
+  }
+}
+
+/**
+ * get a list of collections
+ */
+function ws_collections_getList($params, &$service)
+{
+  global $user, $conf;
+  
+  // check status
+  if (is_a_guest())
+  {
+    return new PwgError(403, 'Forbidden');
+  }
+  
+  // check user_id
+  if (!empty($params['user_id']))
+  {
+    if (!is_admin() and $params['user_id'] != $user['id'])
+    {
+      return new PwgError(403, 'Forbidden');
+    }
+    include_once(PHPWG_ROOT_PATH . 'admin/include/functions.php');
+    if (get_username($params['user_id']) === false)
+    {
+      return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid user id');
+    }
+  }
+  else if (!is_admin())
+  {
+    $params['user_id'] = $user['id'];
+  }
+  
+  // check collection id
+  if ( !empty($params['col_id']) and !preg_match('#^[0-9]+$#', $params['col_id']) )
+  {
+    return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid collection id');
+  }
+  
+  // check public
+  if ( !empty($params['public']) and $params['public'] != 0 and $params['public'] != 1 )
+  {
+    return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid "public" value, 0 or 1.');
+  }
+  
+  // check active
+  if ( !empty($params['active']) and $params['active'] != 0 and $params['active'] != 1 )
+  {
+    return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid "active" value, 0 or 1.');
+  }
+  
+  // search
+  $where_clauses = array('1=1');
+  if (!empty($params['col_id']))
+  {
+    $where_clauses[] = 'c.id = '.$params['col_id'];
+  }
+  if (!empty($params['user_id']))
+  {
+    $where_clauses[] = 'user_id = '.$params['user_id'];
+  }
+  if (!empty($params['public']))
+  {
+    $where_clauses[] = 'public = '.$params['public'];
+  }
+  if (!empty($params['active']))
+  {
+    $where_clauses[] = 'active = '.$params['active'];
+  }
+  if (!empty($params['name']))
+  {
+    $where_clauses[] = 'name LIKE("%'.pwg_db_real_escape_string($params['name']).'%")';
+  }
+  
+  $query = '
+SELECT 
+    c.*,
+    u.'.$conf['user_fields']['username'].' AS username
+  FROM '.COLLECTIONS_TABLE.' AS c
+    INNER JOIN '.USERS_TABLE.' AS u
+    ON c.user_id = u.'.$conf['user_fields']['id'].'
+  WHERE
+    '.implode("\n    AND ", $where_clauses).'
+  ORDER BY username ASC, name ASC
+;';
+  $sets = hash_from_query($query, 'id');
+  
+  $ret = array();
+  foreach ($sets as $row)
+  {
+    $ret[] = array(
+      'id' => $row['id'],
+      'name' => $row['name'],
+      'nb_images' => $row['nb_images'],
+      'active' => (bool)$row['active'],
+      'public' => (bool)$row['public'],
+      'date_creation' => $row['date_creation'],
+      'is_temp' => $row['name'] == 'temp',
+      'u_public' => USER_COLLEC_PUBLIC . 'view/'.$row['public_id'],
+      'user_id' => $row['user_id'],
+      'username' => $row['username'],
+      );
+  }
+  
+  return $ret;
+}
+
+/**
+ * add images to a collection
+ */
+function ws_collections_addImages($params, &$service)
+{
+  global $conf, $user;
+  
+  // check status
+  if (is_a_guest())
+  {
+    return new PwgError(403, 'Forbidden');
+  }
+  
+  // check collection id
+  if (!preg_match('#^[0-9]+$#', $params['col_id']))
+  {
+    return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid collection id');
+  }
+
+  try {
+    $UserCollection = new UserCollection($params['col_id']);
+    
+    $UserCollection->addImages($params['image_ids']);
+    
+    return array('nb_images' => $UserCollection->getParam('nb_images'));
+  }
+  catch (Exception $e)
+  {
+    return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid collection id');
+  }
+}
+
+/**
+ * remove images from a collection
+ */
+function ws_collections_removeImages($params, &$service)
+{
+  global $conf, $user;
+  
+  // check status
+  if (is_a_guest())
+  {
+    return new PwgError(403, 'Forbidden');
+  }
+  
+  // check collection id
+  if (!preg_match('#^[0-9]+$#', $params['col_id']))
+  {
+    return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid collection id');
+  }
+
+  try {
+    $UserCollection = new UserCollection($params['col_id']);
+    
+    $UserCollection->removeImages($params['image_ids']);
+    
+    return array('nb_images' => $UserCollection->getParam('nb_images'));
+  }
+  catch (Exception $e)
+  {
+    return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid collection id');
+  }
+}
+
+/**
+ * get images from a collection
+ */
+function ws_collections_getImages($params, &$service)
+{
+  global $conf, $user;
+  
+  // check status
+  if (is_a_guest())
+  {
+    return new PwgError(403, 'Forbidden');
+  }
+  
+  // check collection id
+  if (!preg_match('#^[0-9]+$#', $params['col_id']))
+  {
+    return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid collection id');
+  }
+
+  try {
+    $UserCollection = new UserCollection($params['col_id']);
+    
+    $image_ids = $UserCollection->getImages();
+    $images = array();
+    
+    if (!empty($image_ids))
+    {
+      $where_clauses = array();
+      $where_clauses[] = 'i.id IN ('.implode(',', $image_ids ).')';
+      $where_clauses[] = get_sql_condition_FandF( array(
+            'visible_images' => 'i.id'
+          ), null, true
+        );
+
+      $order_by = ws_std_image_sql_order($params, 'i.');
+      $order_by = empty($order_by) ? $conf['order_by'] : 'ORDER BY '.$order_by;
+
+      $query = '
+SELECT i.*
+  FROM '.IMAGES_TABLE.' i
+  WHERE 
+    '. implode("\n AND ", $where_clauses).'
+GROUP BY i.id
+'.$order_by.'
+LIMIT '.(int)$params['per_page'].' OFFSET '.(int)($params['per_page']*$params['page']);
+
+    $result = pwg_query($query);
+    while ($row = pwg_db_fetch_assoc($result))
+    {
+      $image = array();
+      foreach (array('id', 'width', 'height', 'hit') as $k)
+      {
+        if (isset($row[$k]))
+        {
+          $image[$k] = (int)$row[$k];
+        }
+      }
+      foreach (array('file', 'name', 'comment', 'date_creation', 'date_available') as $k)
+      {
+        $image[$k] = $row[$k];
+      }
+      $image = array_merge($image, ws_std_get_urls($row));
+      
+      array_push($images, $image);
+    }
+  }
+
+  return array('images' => array(
+    WS_XML_ATTRIBUTES => array(
+      'page' => $params['page'],
+      'per_page' => $params['per_page'],
+      'count' => count($images)
+      ),
+    WS_XML_CONTENT => new PwgNamedArray(
+      $images, 
+      'image', 
+      ws_std_get_image_xml_attributes()
+      ),
+    ));
+  }
+  catch (Exception $e)
+  {
+    return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid collection id');
+  }
+}
+
+/**
+ * get serialised collection
+ */
+function ws_collections_getSerialized($params, &$service)
+{
+  global $conf, $user;
+  
+  // check status
+  if (is_a_guest())
+  {
+    return new PwgError(403, 'Forbidden');
+  }
+  
+  // check collection id
+  if (!preg_match('#^[0-9]+$#', $params['col_id']))
+  {
+    return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid collection id');
+  }
+
+  try {
+    $UserCollection = new UserCollection($params['col_id']);
+    
+    // change encoder to plain text
+    include_once(USER_COLLEC_PATH.'include/plain_encoder.php');
+    $encoder = new PwgPlainEncoder();
+    $service->setEncoder('plain', $encoder);
+  
+    return $UserCollection->serialize($params['content']);
+  }
+  catch (Exception $e)
+  {
+    return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid collection id');
+  }
+}
+?>
Index: /extensions/UserCollections/language/ca_ES/plugin.lang.php
===================================================================
--- /extensions/UserCollections/language/ca_ES/plugin.lang.php	(revision 20089)
+++ /extensions/UserCollections/language/ca_ES/plugin.lang.php	(revision 20090)
@@ -29,5 +29,5 @@
 $lang['%d more...'] = '%d més...';
 $lang['Add to collection'] = 'Afegeix a la col·lecció';
-$lang['Clear collection'] = 'Esborra';
+$lang['Clear'] = 'Esborra';
 $lang['Collection'] = 'Col·lecció';
 $lang['Collection name:'] = 'Nom de la col·lecció';
Index: /extensions/UserCollections/language/cs_CZ/plugin.lang.php
===================================================================
--- /extensions/UserCollections/language/cs_CZ/plugin.lang.php	(revision 20089)
+++ /extensions/UserCollections/language/cs_CZ/plugin.lang.php	(revision 20090)
@@ -23,5 +23,5 @@
 $lang['%d more...'] = '%d více...';
 $lang['Add to collection'] = 'Přidat do sbírky';
-$lang['Clear collection'] = 'Vyčistit';
+$lang['Clear'] = 'Vyčistit';
 $lang['Collection name:'] = 'Jméno sbírky';
 $lang['Collection'] = 'Sbírka';
Index: /extensions/UserCollections/language/da_DK/plugin.lang.php
===================================================================
--- /extensions/UserCollections/language/da_DK/plugin.lang.php	(revision 20089)
+++ /extensions/UserCollections/language/da_DK/plugin.lang.php	(revision 20090)
@@ -30,5 +30,5 @@
 $lang['%d more...'] = '%d mere ...';
 $lang['Add to collection'] = 'Tilføj til samling';
-$lang['Clear collection'] = 'Ryd';
+$lang['Clear'] = 'Ryd';
 $lang['Collection'] = 'Samling';
 $lang['Collection name:'] = 'Navn på samling:';
Index: /extensions/UserCollections/language/de_DE/plugin.lang.php
===================================================================
--- /extensions/UserCollections/language/de_DE/plugin.lang.php	(revision 20089)
+++ /extensions/UserCollections/language/de_DE/plugin.lang.php	(revision 20090)
@@ -22,5 +22,5 @@
 // +-----------------------------------------------------------------------+
 $lang['Add to collection'] = 'Sammlung hinzufügen';
-$lang['Clear collection'] = 'Löschen';
+$lang['Clear'] = 'Löschen';
 $lang['Collection name:'] = 'Name der Sammlung:';
 $lang['Collection'] = 'Sammlung';
Index: /extensions/UserCollections/language/el_GR/plugin.lang.php
===================================================================
--- /extensions/UserCollections/language/el_GR/plugin.lang.php	(revision 20089)
+++ /extensions/UserCollections/language/el_GR/plugin.lang.php	(revision 20090)
@@ -22,5 +22,5 @@
 // +-----------------------------------------------------------------------+
 $lang['Add to collection'] = 'Προσθήκη στη συλλογή';
-$lang['Clear collection'] = 'Καθαρίζω';
+$lang['Clear'] = 'Καθαρίζω';
 $lang['Collection name:'] = 'Όνομα Συλλογής';
 $lang['Collection'] = 'Συλλογή';
Index: /extensions/UserCollections/language/en_UK/plugin.lang.php
===================================================================
--- /extensions/UserCollections/language/en_UK/plugin.lang.php	(revision 20089)
+++ /extensions/UserCollections/language/en_UK/plugin.lang.php	(revision 20090)
@@ -20,5 +20,5 @@
 $lang['Remove from collection'] = 'Remove from collection';
 $lang['Add to collection'] = 'Add to collection';
-$lang['Clear collection'] = 'Clear';
+$lang['Clear'] = 'Clear';
 $lang['You have %d collection'] = 'You have %d collection';
 $lang['You have no collection'] = 'You have no collection';
@@ -28,3 +28,33 @@
 $lang['%d more...'] = '%d more...';
 
+$lang['Allow users to set their collections as public'] = 'Allow users to set their collections as public';
+$lang['Allow users to send their public collections by mail'] = 'Allow users to send their public collections by mail';
+$lang['Fields'] = 'Fields';
+$lang['Active'] = 'Active';
+$lang['Inactive'] = 'Inactive';
+$lang['Generate'] = 'Generate';
+$lang['Download CSV file'] = 'Download CSV file';
+$lang['Output'] = 'Output';
+$lang['Number of images'] = 'Number of images';
+$lang['Edit this collection'] = 'Edit this collection';
+$lang['Export image list'] = 'Export image list';
+$lang['Delete this collection'] = 'Delete this collection';
+$lang['Send this collection my mail'] = 'Send this collection my mail';
+$lang['Clear this collection'] = 'Clear this collection';
+$lang['Please enter your name'] = 'Please enter your name';
+$lang['Please enter the recipient name'] = 'Please enter the recipient name';
+$lang['Please enter your e-mail'] = 'Please enter your e-mail';
+$lang['Please enter the recipient e-mail'] = 'Please enter the recipient e-mail';
+$lang['A photo collection by %s'] = 'A photo collection by %s';
+$lang['Error while sending e-mail'] = 'Error while sending e-mail';
+$lang['E-mail sent successfully'] = 'E-mail sent successfully';
+$lang['The collection must be public in order to send it'] = 'The collection must be public in order to send it';
+$lang['Your name'] = 'Your name';
+$lang['Your e-mail'] = 'Your e-mail';
+$lang['Recipient name'] = 'Recipient name';
+$lang['Recipient e-mail'] = 'Recipient e-mail';
+$lang['Message (optional)'] = 'Message (optional)';
+$lang['Hello <b>%s</b>, %s sent you a photos collection from <a href="%s">%s</a>'] = 'Hello <b>%s</b>, %s sent you a photos collection from <a href="%s">%s</a>';
+$lang['Click here to view the complete collection'] = 'Click here to view the complete collection';
+
 ?>
Index: /extensions/UserCollections/language/es_ES/plugin.lang.php
===================================================================
--- /extensions/UserCollections/language/es_ES/plugin.lang.php	(revision 20089)
+++ /extensions/UserCollections/language/es_ES/plugin.lang.php	(revision 20090)
@@ -23,5 +23,5 @@
 $lang['%d more...'] = '%d más...';
 $lang['Add to collection'] = 'Añadir a la colección';
-$lang['Clear collection'] = 'Limpiar';
+$lang['Clear'] = 'Limpiar';
 $lang['Collection name:'] = 'Nombre de la colección';
 $lang['Collection'] = 'Colección';
Index: /extensions/UserCollections/language/fa_IR/plugin.lang.php
===================================================================
--- /extensions/UserCollections/language/fa_IR/plugin.lang.php	(revision 20089)
+++ /extensions/UserCollections/language/fa_IR/plugin.lang.php	(revision 20090)
@@ -23,5 +23,5 @@
 $lang['%d more...'] = '%d بیشتر ...';
 $lang['Add to collection'] = 'افزودن به مجموعه';
-$lang['Clear collection'] = 'پاک کردن';
+$lang['Clear'] = 'پاک کردن';
 $lang['Collection'] = 'مجموعه';
 $lang['Collection name:'] = 'نام مجموعه:';
Index: /extensions/UserCollections/language/fr_FR/plugin.lang.php
===================================================================
--- /extensions/UserCollections/language/fr_FR/plugin.lang.php	(revision 20089)
+++ /extensions/UserCollections/language/fr_FR/plugin.lang.php	(revision 20090)
@@ -20,5 +20,5 @@
 $lang['Remove from collection'] = 'Supprimer de la collection';
 $lang['Add to collection'] = 'Ajouter à la collection';
-$lang['Clear collection'] = 'Vider';
+$lang['Clear'] = 'Vider';
 $lang['You have %d collection'] = 'Vous avez %d collection';
 $lang['You have no collection'] = 'Vous n\'avez aucune collection';
@@ -28,3 +28,33 @@
 $lang['%d more...'] = 'et %d autres...';
 
+$lang['Allow users to set their collections as public'] = 'Les utilisateurs peuvent rendre leurs collections publiques';
+$lang['Allow users to send their public collections by mail'] = 'Les utilisateurs peuvent envoyer leurs collections publiques par mail';
+$lang['Fields'] = 'Champs';
+$lang['Active'] = 'Actifs';
+$lang['Inactive'] = 'Inactifs';
+$lang['Generate'] = 'Générer';
+$lang['Download CSV file'] = 'Télécharger le fichier CSV';
+$lang['Output'] = 'Aperçu';
+$lang['Number of images'] = 'Nombre d\'images';
+$lang['Edit this collection'] = 'Editer celle collection';
+$lang['Export image list'] = 'Exporter la liste d\'images';
+$lang['Delete this collection'] = 'Supprimer la collection';
+$lang['Send this collection my mail'] = 'Envoyer cette collection par mail';
+$lang['Clear this collection'] = 'Vider cette collection';
+$lang['Please enter your name'] = 'Veuillez entrer votre nom';
+$lang['Please enter the recipient name'] = 'Veuillez entrer le nom du destinataire';
+$lang['Please enter your e-mail'] = 'Veuillez entrer votre e-mail';
+$lang['Please enter the recipient e-mail'] = 'Veuillez entrer l\'e-mail du destinataire';
+$lang['A photo collection by %s'] = 'Une collection photo de %s';
+$lang['Error while sending e-mail'] = 'Erreur lors de l\'envoi de l\'e-mail';
+$lang['E-mail sent successfully'] = 'E-mail envoyé avec succès';
+$lang['The collection must be public in order to send it'] = 'La collection doit être publique pour l\'envoyer';
+$lang['Your name'] = 'Votre nom';
+$lang['Your e-mail'] = 'Votre e-mail';
+$lang['Recipient name'] = 'Nom du destinataire';
+$lang['Recipient e-mail'] = 'E-mail du destinataire';
+$lang['Message (optional)'] = 'Message (optionel)';
+$lang['Hello <b>%s</b>, %s sent you a photos collection from <a href="%s">%s</a>'] = 'Bonjour <b>%s</b>, %s vous a envoyé une collection de photos depuis <a href="%s">%s</a>';
+$lang['Click here to view the complete collection'] = 'Cliquez ici pour voir la collection complète';
+
 ?>
Index: /extensions/UserCollections/language/hu_HU/plugin.lang.php
===================================================================
--- /extensions/UserCollections/language/hu_HU/plugin.lang.php	(revision 20089)
+++ /extensions/UserCollections/language/hu_HU/plugin.lang.php	(revision 20090)
@@ -22,5 +22,5 @@
 // +-----------------------------------------------------------------------+
 $lang['Add to collection'] = 'Gyűjteménybe';
-$lang['Clear collection'] = 'Kiürítés';
+$lang['Clear'] = 'Kiürítés';
 $lang['Collection name:'] = 'Gyűjtemény neve:';
 $lang['Collection'] = 'Gyűjtemény';
Index: /extensions/UserCollections/language/it_IT/plugin.lang.php
===================================================================
--- /extensions/UserCollections/language/it_IT/plugin.lang.php	(revision 20089)
+++ /extensions/UserCollections/language/it_IT/plugin.lang.php	(revision 20090)
@@ -23,5 +23,5 @@
 $lang['%d more...'] = '%d di più...';
 $lang['Add to collection'] = 'Aggiungi ad una raccolta';
-$lang['Clear collection'] = 'Cancella';
+$lang['Clear'] = 'Cancella';
 $lang['Collection name:'] = 'Nome della collezione:';
 $lang['Collection'] = 'Collezione';
Index: /extensions/UserCollections/language/lv_LV/plugin.lang.php
===================================================================
--- /extensions/UserCollections/language/lv_LV/plugin.lang.php	(revision 20089)
+++ /extensions/UserCollections/language/lv_LV/plugin.lang.php	(revision 20090)
@@ -22,5 +22,5 @@
 // +-----------------------------------------------------------------------+
 $lang['Add to collection'] = 'Pievienot kolekcijai';
-$lang['Clear collection'] = 'Tīrs';
+$lang['Clear'] = 'Tīrs';
 $lang['Collection name:'] = 'Kolekcijas nosaukums:';
 $lang['Collection'] = 'Kolekcija';
Index: /extensions/UserCollections/language/nl_NL/plugin.lang.php
===================================================================
--- /extensions/UserCollections/language/nl_NL/plugin.lang.php	(revision 20089)
+++ /extensions/UserCollections/language/nl_NL/plugin.lang.php	(revision 20090)
@@ -22,5 +22,5 @@
 // +-----------------------------------------------------------------------+
 $lang['Add to collection'] = 'Aan verzameling toevoegen';
-$lang['Clear collection'] = 'Leegmaken';
+$lang['Clear'] = 'Leegmaken';
 $lang['Collection name:'] = 'Naam van verzameling';
 $lang['Collection'] = 'Verzameling';
Index: /extensions/UserCollections/language/pl_PL/plugin.lang.php
===================================================================
--- /extensions/UserCollections/language/pl_PL/plugin.lang.php	(revision 20089)
+++ /extensions/UserCollections/language/pl_PL/plugin.lang.php	(revision 20090)
@@ -23,5 +23,5 @@
 $lang['%d more...'] = '%d więcej...';
 $lang['Add to collection'] = 'Dodaj do kolekcji';
-$lang['Clear collection'] = 'Wyczyść';
+$lang['Clear'] = 'Wyczyść';
 $lang['Collection name:'] = 'Nazwa kolekcji';
 $lang['Collection'] = 'Kolekcja';
Index: /extensions/UserCollections/language/pt_BR/index.php
===================================================================
--- /extensions/UserCollections/language/pt_BR/index.php	(revision 20090)
+++ /extensions/UserCollections/language/pt_BR/index.php	(revision 20090)
@@ -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/UserCollections/language/pt_BR/plugin.lang.php
===================================================================
--- /extensions/UserCollections/language/pt_BR/plugin.lang.php	(revision 20089)
+++ /extensions/UserCollections/language/pt_BR/plugin.lang.php	(revision 20090)
@@ -30,5 +30,5 @@
 mais %d...';
 $lang['Add to collection'] = 'Adicione a coleção';
-$lang['Clear collection'] = 'Limpar';
+$lang['Clear'] = 'Limpar';
 $lang['Collection'] = 'Coleção';
 $lang['Collection name:'] = 'Nome da coleção:';
Index: /extensions/UserCollections/language/pt_PT/plugin.lang.php
===================================================================
--- /extensions/UserCollections/language/pt_PT/plugin.lang.php	(revision 20089)
+++ /extensions/UserCollections/language/pt_PT/plugin.lang.php	(revision 20090)
@@ -29,5 +29,5 @@
 $lang['%d more...'] = '%d mais';
 $lang['Add to collection'] = 'acrescentar à colecção';
-$lang['Clear collection'] = 'Limpar';
+$lang['Clear'] = 'Limpar';
 $lang['Collection'] = 'Colecção';
 $lang['Collection name:'] = 'Nome da colecção';
Index: /extensions/UserCollections/language/ru_RU/plugin.lang.php
===================================================================
--- /extensions/UserCollections/language/ru_RU/plugin.lang.php	(revision 20089)
+++ /extensions/UserCollections/language/ru_RU/plugin.lang.php	(revision 20090)
@@ -22,5 +22,5 @@
 // +-----------------------------------------------------------------------+
 $lang['Add to collection'] = 'Добавить в коллекцию';
-$lang['Clear collection'] = 'Очистить';
+$lang['Clear'] = 'Очистить';
 $lang['Collection name:'] = 'Название коллекции:';
 $lang['Collection'] = 'Коллекция';
Index: /extensions/UserCollections/language/sk_SK/plugin.lang.php
===================================================================
--- /extensions/UserCollections/language/sk_SK/plugin.lang.php	(revision 20089)
+++ /extensions/UserCollections/language/sk_SK/plugin.lang.php	(revision 20090)
@@ -22,5 +22,5 @@
 // +-----------------------------------------------------------------------+
 $lang['Add to collection'] = 'Pridať do kolekcie';
-$lang['Clear collection'] = 'Vyčistiť';
+$lang['Clear'] = 'Vyčistiť';
 $lang['Collection name:'] = 'Názov kolekcie:';
 $lang['Collection'] = 'Kolekcia';
Index: /extensions/UserCollections/language/th_TH/plugin.lang.php
===================================================================
--- /extensions/UserCollections/language/th_TH/plugin.lang.php	(revision 20089)
+++ /extensions/UserCollections/language/th_TH/plugin.lang.php	(revision 20090)
@@ -22,5 +22,5 @@
 // +-----------------------------------------------------------------------+
 $lang['%d more...'] = '%d เพิ่มเติม...';
-$lang['Clear collection'] = 'ล้าง';
+$lang['Clear'] = 'ล้าง';
 $lang['Copied'] = 'คัดลอก';
 $lang['Public collection'] = 'สาธารณะ';
Index: /extensions/UserCollections/language/tr_TR/plugin.lang.php
===================================================================
--- /extensions/UserCollections/language/tr_TR/plugin.lang.php	(revision 20089)
+++ /extensions/UserCollections/language/tr_TR/plugin.lang.php	(revision 20090)
@@ -22,5 +22,5 @@
 // +-----------------------------------------------------------------------+
 $lang['Add to collection'] = 'Koleksiyona ekle';
-$lang['Clear collection'] = 'Temizle';
+$lang['Clear'] = 'Temizle';
 $lang['Collection name:'] = 'Koleksiyon adı:';
 $lang['Collections'] = 'Koleksiyon';
Index: /extensions/UserCollections/language/uk_UA/plugin.lang.php
===================================================================
--- /extensions/UserCollections/language/uk_UA/plugin.lang.php	(revision 20089)
+++ /extensions/UserCollections/language/uk_UA/plugin.lang.php	(revision 20090)
@@ -30,5 +30,5 @@
 $lang['set active'] = 'встановити активним';
 $lang['Add to collection'] = 'Додати до колекції';
-$lang['Clear collection'] = 'Очистити';
+$lang['Clear'] = 'Очистити';
 $lang['Collection'] = 'Колекція';
 $lang['Collection name:'] = 'Ім\'я колекції:';
Index: /extensions/UserCollections/language/zh_CN/plugin.lang.php
===================================================================
--- /extensions/UserCollections/language/zh_CN/plugin.lang.php	(revision 20089)
+++ /extensions/UserCollections/language/zh_CN/plugin.lang.php	(revision 20090)
@@ -44,5 +44,5 @@
 $lang['Collection name:'] = '精选集名称：';
 $lang['Collection'] = '精选集';
-$lang['Clear collection'] = '清除';
+$lang['Clear'] = '清除';
 $lang['Add to collection'] = '添加到精选集';
 $lang['%d more...'] = '%d 更多...';
Index: /extensions/UserCollections/main.inc.php
===================================================================
--- /extensions/UserCollections/main.inc.php	(revision 20089)
+++ /extensions/UserCollections/main.inc.php	(revision 20090)
@@ -13,25 +13,40 @@
 global $conf, $prefixeTable;
 
-define('USER_COLLEC_PATH',       PHPWG_PLUGINS_PATH . 'UserCollections/');
+defined('USER_COLLEC_ID') or define('USER_COLLEC_ID', basename(dirname(__FILE__)));
+define('USER_COLLEC_PATH',       PHPWG_PLUGINS_PATH . USER_COLLEC_ID . '/');
 define('COLLECTIONS_TABLE',      $prefixeTable.'collections');
 define('COLLECTION_IMAGES_TABLE',$prefixeTable.'collection_images');
-define('USER_COLLEC_ADMIN',      get_root_url() . 'admin.php?page=plugin-UserCollections');
+define('USER_COLLEC_ADMIN',      get_root_url() . 'admin.php?page=plugin-' . USER_COLLEC_ID);
 define('USER_COLLEC_PUBLIC',     get_absolute_root_url() . make_index_url(array('section' => 'collections')) . '/');
 define('USER_COLLEC_VERSION',    'auto');
 
-
 add_event_handler('init', 'user_collections_init');
 
-add_event_handler('loc_end_section_init', 'user_collections_section_init');
-add_event_handler('loc_end_index', 'user_collections_page', EVENT_HANDLER_PRIORITY_NEUTRAL-10);
+add_event_handler('ws_add_methods', 'user_collections_ws_add_methods');
 
-add_event_handler('loc_end_index', 'user_collections_index_actions');
-add_event_handler('loc_end_index_thumbnails', 'user_collections_thumbnails_list', EVENT_HANDLER_PRIORITY_NEUTRAL, 2);
+if (defined('IN_ADMIN'))
+{
+  add_event_handler('get_admin_plugin_menu_links', 'user_collections_admin_menu');
+}
+else
+{
+  // collections page
+  add_event_handler('loc_begin_index', 'user_collections_save_pagination', EVENT_HANDLER_PRIORITY_NEUTRAL-10);
+  add_event_handler('loc_end_section_init', 'user_collections_section_init');
+  add_event_handler('loc_end_index', 'user_collections_page', EVENT_HANDLER_PRIORITY_NEUTRAL-10);
 
-add_event_handler('loc_end_picture', 'user_collections_picture_page');
+  // thumbnails actions
+  add_event_handler('loc_end_index', 'user_collections_index_actions');
+  add_event_handler('loc_end_index_thumbnails', 'user_collections_thumbnails_list', EVENT_HANDLER_PRIORITY_NEUTRAL, 2);
 
-add_event_handler('blockmanager_register_blocks', 'user_collections_add_menublock');
-add_event_handler('blockmanager_apply', 'user_collections_applymenu');
+  // picture action
+  add_event_handler('loc_end_picture', 'user_collections_picture_page');
 
+  // menu
+  add_event_handler('blockmanager_register_blocks', 'user_collections_add_menublock');
+  add_event_handler('blockmanager_apply', 'user_collections_applymenu');
+}
+
+require(USER_COLLEC_PATH . 'include/ws_functions.inc.php');
 require(USER_COLLEC_PATH . 'include/functions.inc.php');
 require(USER_COLLEC_PATH . 'include/UserCollection.class.php');
@@ -44,10 +59,10 @@
 function user_collections_init()
 {
-  global $pwg_loaded_plugins;
+  global $pwg_loaded_plugins, $conf;
   
   if (
     USER_COLLEC_VERSION == 'auto' or
-    $pwg_loaded_plugins['UserCollections']['version'] == 'auto' or
-    version_compare($pwg_loaded_plugins['UserCollections']['version'], USER_COLLEC_VERSION, '<')
+    $pwg_loaded_plugins[USER_COLLEC_ID]['version'] == 'auto' or
+    version_compare($pwg_loaded_plugins[USER_COLLEC_ID]['version'], USER_COLLEC_VERSION, '<')
   )
   {
@@ -55,13 +70,13 @@
     user_collections_install();
     
-    if ( $pwg_loaded_plugins['UserCollections']['version'] != 'auto' and USER_COLLEC_VERSION != 'auto' )
+    if ( $pwg_loaded_plugins[USER_COLLEC_ID]['version'] != 'auto' and USER_COLLEC_VERSION != 'auto' )
     {
       $query = '
 UPDATE '. PLUGINS_TABLE .'
 SET version = "'. USER_COLLEC_VERSION .'"
-WHERE id = "UserCollections"';
+WHERE id = "'. USER_COLLEC_ID .'"';
       pwg_query($query);
       
-      $pwg_loaded_plugins['UserCollections']['version'] = USER_COLLEC_VERSION;
+      $pwg_loaded_plugins[USER_COLLEC_ID]['version'] = USER_COLLEC_VERSION;
       
       if (defined('IN_ADMIN'))
@@ -73,4 +88,18 @@
   
   load_language('plugin.lang', USER_COLLEC_PATH);
+  
+  $conf['user_collections'] = unserialize($conf['user_collections']);
+}
+
+/**
+ * admin plugins menu
+ */
+function user_collections_admin_menu($menu) 
+{
+  array_push($menu, array(
+    'NAME' => 'User Collections',
+    'URL' => USER_COLLEC_ADMIN,
+  ));
+  return $menu;
 }
 
Index: /extensions/UserCollections/maintain.inc.php
===================================================================
--- /extensions/UserCollections/maintain.inc.php	(revision 20089)
+++ /extensions/UserCollections/maintain.inc.php	(revision 20090)
@@ -2,5 +2,6 @@
 if (!defined('PHPWG_ROOT_PATH')) die('Hacking attempt!');
 
-include_once(PHPWG_PLUGINS_PATH . 'UserCollections/include/install.inc.php');
+defined('USER_COLLEC_ID') or define('USER_COLLEC_ID', basename(dirname(__FILE__)));
+include_once(PHPWG_PLUGINS_PATH . USER_COLLEC_ID . '/include/install.inc.php');
 
 function plugin_install() 
Index: /extensions/UserCollections/template/edit.tpl
===================================================================
--- /extensions/UserCollections/template/edit.tpl	(revision 20089)
+++ /extensions/UserCollections/template/edit.tpl	(revision 20090)
@@ -1,39 +1,51 @@
 {combine_css path=$USER_COLLEC_PATH|@cat:"template/style.css"}
-{combine_script id='jquery.zclip' path=$USER_COLLEC_PATH|@cat:"template/jquery.zclip.min.js"}
+{combine_script id='jquery.zclip' path=$USER_COLLEC_PATH|@cat:"template/resources/jquery.zclip.min.js"}
 {combine_script id='jquery.tipTip' path='themes/default/js/plugins/jquery.tipTip.minified.js'}
 
+{combine_script id='jquery.colorbox' load='footer' require='jquery' path='themes/default/js/plugins/jquery.colorbox.min.js'}
+{combine_css path="themes/default/js/plugins/colorbox/style2/colorbox.css"}
+
 {footer_script require='jquery'}
-function bindZclip() {ldelim}
-  jQuery("#publicURL .button").zclip({ldelim}
-    path:'{$ROOT_URL}{$USER_COLLEC_PATH}template/ZeroClipboard.swf',
-    copy:$("#publicURL .url").html(),
-    afterCopy: function() {ldelim}
-      $('.confirm').remove();
-      $("#publicURL .url").select();
-      $('<span class="confirm" style="display:none;">{'Copied'|@translate}</span>').appendTo("#publicURL")
-        .fadeIn(400).delay(1000).fadeOut(400, function(){ldelim} $(this).remove(); });
-    }
+{if $user_collections.allow_public}
+  function bindZclip() {ldelim}
+    jQuery("#publicURL .button").zclip({ldelim}
+      path:'{$ROOT_URL}{$USER_COLLEC_PATH}template/resources/ZeroClipboard.swf',
+      copy:$("#publicURL .url").html(),
+      afterCopy: function() {ldelim}
+        $('.confirm').remove();
+        $("#publicURL .url").select();
+        $('<span class="confirm" style="display:none;">{'Copied'|@translate}</span>').appendTo("#publicURL")
+          .fadeIn(400).delay(1000).fadeOut(400, function(){ldelim} $(this).remove(); });
+      }
+    });
+    $("#publicURL .url").click(function() {ldelim}
+      $(this).select();
+    });
+  }
+
+  jQuery("input[name='public']").change(function() {ldelim}
+    jQuery("#publicURL").fadeToggle("fast");
+    bindZclip();
   });
-  $("#publicURL .url").click(function() {ldelim}
-    $(this).select();
+  jQuery("#publicURL .button").tipTip({ldelim}
+    delay: 0,
+    defaultPosition: 'right'
   });
-}
+  {if $collection.PUBLIC}bindZclip();{/if}
+{/if}
 
-jQuery("input[name='public']").change(function() {ldelim}
-  jQuery("#publicURL").fadeToggle("fast");
-  bindZclip();
-});
-jQuery("#publicURL .button").tipTip({ldelim}
-  delay: 0,
-  defaultPosition: 'right'
-});
-
-jQuery("#actions input").click(function() {ldelim}
-  if (confirm("{'Are you sure?'|@translate}")) {ldelim}
-    document.location.href = jQuery(this).data("href");
-  }
-  return false;
-});
-{if $collection.PUBLIC}bindZclip();{/if}
+{if $collection.PUBLIC && $user_collections.allow_mails}
+  $(window).load(function(){ldelim}
+    $(".mail_colorbox_open").colorbox({ldelim}
+      {if isset($uc_mail_errors)}open: true, transition:"none",{/if}
+      inline:true
+    });
+    $(".mail_colorbox_close").click(function() {ldelim}
+      $(".mail_colorbox_open").colorbox.close();
+      return false;
+    })
+  });
+  $("#mail_form").css('background-color', $("#the_page #content").css('background-color'));
+{/if}
 {/footer_script}
 
@@ -56,4 +68,5 @@
 
 {if $collection}
+{* <!-- edit collection -->*}
 <form action="{$F_ACTION}" method="post">
 <fieldset id="colProperties">
@@ -61,5 +74,6 @@
   
   <p class="title"><label for="name">{'Name'|@translate}</label></p>
-  <p><input type="text" name="name" id="name" value="{$collection.NAME}" size="60"></p>
+  <p><input type="text" name="name" id="name" value="{$collection.NAME|escape:html}" size="60"></p>
+{if $user_collections.allow_public}
   <p class="title">{'Public collection'|@translate}</p>
   <p>
@@ -68,4 +82,5 @@
     <span id="publicURL" {if not $collection.PUBLIC}style="display:none;"{/if}><span class="button" title="{'Copy to clipboard'|@translate}">&nbsp;</span><input type="text" class="url" value="{$collection.U_PUBLIC}" size="{$collection.U_PUBLIC|strlen}"></span>
   </p>
+{/if}
   <p>
     <input type="submit" name="save_col" value="{'Save'|@translate}">
@@ -75,11 +90,66 @@
 </form>
 
+{* <!-- send collection by mail -->*}
+{if $user_collections.allow_public && $user_collections.allow_mails}
+<div style="display:none;">
+  <form id="mail_form" action="{$F_ACTION}" method="post">
+  {if isset($uc_mail_errors)}
+    {assign var=errors value=$uc_mail_errors}
+    {include file='infos_errors.tpl'}
+  {/if}
 
-<form id="actions" style="text-align:center;">
-<input type="submit" data-href="{$collection.U_CLEAR}" value="{'Clear collection'|@translate}">
-<input type="submit" data-href="{$collection.U_DELETE}" value="{'Delete'|@translate}">
-</form>
+    <table>
+      <tr>
+        <td class="title"><label for="sender_name">{'Your name'|@translate}</label></td>
+        <td>
+          <input type="text" name="sender_name" id="sender_name" size="40" value="{$contact.sender_name}">
+        </td>
+      </tr>
+      <tr>
+        <td class="title"><label for="sender_email">{'Your e-mail'|@translate}</label></td>
+        <td>
+          <input type="text" name="sender_email" id="sender_email" size="40" value="{$contact.sender_email}">
+        </td>
+      </tr>
+      <tr>
+        <td class="title"><label for="recipient_name">{'Recipient name'|@translate}</label></td>
+        <td>
+          <input type="text" name="recipient_name" id="recipient_name" size="40" value="{$contact.recipient_name}">
+        </td>
+      </tr>
+      <tr>
+        <td class="title"><label for="recipient_email">{'Recipient e-mail'|@translate}</label></td>
+        <td>
+          <input type="text" name="recipient_email" id="recipient_email" size="40" value="{$contact.recipient_email}">
+        </td>
+      </tr>
+      <tr>
+        <td class="title"><label for="nb_images">{'Number of images'|@translate}</label></td>
+        <td>
+          <select name="nb_images">
+            <option value="2" {if $contact.nb_images==2}selected="selected"{/if}>2</option>
+            <option value="4" {if $contact.nb_images==4}selected="selected"{/if}>4</option>
+            <option value="8" {if $contact.nb_images==8}selected="selected"{/if}>8</option>
+          </select>
+        </td>
+      </tr>
+      <tr>
+        <td class="title"><label for="message">{'Message (optional)'|@translate}</label></td>
+        <td><textarea name="message" id="message" rows="6" style="width:350px;">{$contact.message}</textarea></td>
+      </tr>
+      <tr>
+        <td class="title">&nbsp;</td>
+        <td>
+          <input class="submit" type="submit" name="send_mail" value="{'Send'|@translate}">
+          <a class="mail_colorbox_close" href="#">{'Cancel'|@translate}</a>
+          <input type="hidden" name="key" value="{$contact.KEY}" />
+        </td>
+      </tr>
+    </table>
+  </form>
+</div>
+{/if}
 
-
+{* <!-- collection content -->*}
 {if $collection.NB_IMAGES > 0}
 <ul class="thumbnails" id="thumbnails">
Index: /extensions/UserCollections/template/index.php
===================================================================
--- /extensions/UserCollections/template/index.php	(revision 20090)
+++ /extensions/UserCollections/template/index.php	(revision 20090)
@@ -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: tensions/UserCollections/template/jquery.zclip.min.js
===================================================================
--- /extensions/UserCollections/template/jquery.zclip.min.js	(revision 20089)
+++ 	(revision )
@@ -1,12 +1,0 @@
-/*
- * zClip :: jQuery ZeroClipboard v1.1.1
- * http://steamdev.com/zclip
- *
- * Copyright 2011, SteamDev
- * Released under the MIT license.
- * http://www.opensource.org/licenses/mit-license.php
- *
- * Date: Wed Jun 01, 2011
- */
-
-(function(a){a.fn.zclip=function(c){if(typeof c=="object"&&!c.length){var b=a.extend({path:"ZeroClipboard.swf",copy:null,beforeCopy:null,afterCopy:null,clickAfter:true,setHandCursor:true,setCSSEffects:true},c);return this.each(function(){var e=a(this);if(e.is(":visible")&&(typeof b.copy=="string"||a.isFunction(b.copy))){ZeroClipboard.setMoviePath(b.path);var d=new ZeroClipboard.Client();if(a.isFunction(b.copy)){e.bind("zClip_copy",b.copy)}if(a.isFunction(b.beforeCopy)){e.bind("zClip_beforeCopy",b.beforeCopy)}if(a.isFunction(b.afterCopy)){e.bind("zClip_afterCopy",b.afterCopy)}d.setHandCursor(b.setHandCursor);d.setCSSEffects(b.setCSSEffects);d.addEventListener("mouseOver",function(f){e.trigger("mouseenter")});d.addEventListener("mouseOut",function(f){e.trigger("mouseleave")});d.addEventListener("mouseDown",function(f){e.trigger("mousedown");if(!a.isFunction(b.copy)){d.setText(b.copy)}else{d.setText(e.triggerHandler("zClip_copy"))}if(a.isFunction(b.beforeCopy)){e.trigger("zClip_beforeCopy")}});d.addEventListener("complete",function(f,g){if(a.isFunction(b.afterCopy)){e.trigger("zClip_afterCopy")}else{if(g.length>500){g=g.substr(0,500)+"...\n\n("+(g.length-500)+" characters not shown)"}e.removeClass("hover");/*alert("Copied text to clipboard:\n\n "+g)*/}if(b.clickAfter){e.trigger("click")}});d.glue(e[0],e.parent()[0]);a(window).bind("load resize",function(){d.reposition()})}})}else{if(typeof c=="string"){return this.each(function(){var f=a(this);c=c.toLowerCase();var e=f.data("zclipId");var d=a("#"+e+".zclip");if(c=="remove"){d.remove();f.removeClass("active hover")}else{if(c=="hide"){d.hide();f.removeClass("active hover")}else{if(c=="show"){d.show()}}}})}}}})(jQuery);var ZeroClipboard={version:"1.0.7",clients:{},moviePath:"ZeroClipboard.swf",nextId:1,$:function(a){if(typeof(a)=="string"){a=document.getElementById(a)}if(!a.addClass){a.hide=function(){this.style.display="none"};a.show=function(){this.style.display=""};a.addClass=function(b){this.removeClass(b);this.className+=" "+b};a.removeClass=function(d){var e=this.className.split(/\s+/);var b=-1;for(var c=0;c<e.length;c++){if(e[c]==d){b=c;c=e.length}}if(b>-1){e.splice(b,1);this.className=e.join(" ")}return this};a.hasClass=function(b){return !!this.className.match(new RegExp("\\s*"+b+"\\s*"))}}return a},setMoviePath:function(a){this.moviePath=a},dispatch:function(d,b,c){var a=this.clients[d];if(a){a.receiveEvent(b,c)}},register:function(b,a){this.clients[b]=a},getDOMObjectPosition:function(c,a){var b={left:0,top:0,width:c.width?c.width:c.offsetWidth,height:c.height?c.height:c.offsetHeight};if(c&&(c!=a)){b.left+=c.offsetLeft;b.top+=c.offsetTop}return b},Client:function(a){this.handlers={};this.id=ZeroClipboard.nextId++;this.movieId="ZeroClipboardMovie_"+this.id;ZeroClipboard.register(this.id,this);if(a){this.glue(a)}}};ZeroClipboard.Client.prototype={id:0,ready:false,movie:null,clipText:"",handCursorEnabled:true,cssEffects:true,handlers:null,glue:function(d,b,e){this.domElement=ZeroClipboard.$(d);var f=99;if(this.domElement.style.zIndex){f=parseInt(this.domElement.style.zIndex,10)+1}if(typeof(b)=="string"){b=ZeroClipboard.$(b)}else{if(typeof(b)=="undefined"){b=document.getElementsByTagName("body")[0]}}var c=ZeroClipboard.getDOMObjectPosition(this.domElement,b);this.div=document.createElement("div");this.div.className="zclip";this.div.id="zclip-"+this.movieId;$(this.domElement).data("zclipId","zclip-"+this.movieId);var a=this.div.style;a.position="absolute";a.left=""+c.left+"px";a.top=""+c.top+"px";a.width=""+c.width+"px";a.height=""+c.height+"px";a.zIndex=f;if(typeof(e)=="object"){for(addedStyle in e){a[addedStyle]=e[addedStyle]}}b.appendChild(this.div);this.div.innerHTML=this.getHTML(c.width,c.height)},getHTML:function(d,a){var c="";var b="id="+this.id+"&width="+d+"&height="+a;if(navigator.userAgent.match(/MSIE/)){var e=location.href.match(/^https/i)?"https://":"http://";c+='<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="'+e+'download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" width="'+d+'" height="'+a+'" id="'+this.movieId+'" align="middle"><param name="allowScriptAccess" value="always" /><param name="allowFullScreen" value="false" /><param name="movie" value="'+ZeroClipboard.moviePath+'" /><param name="loop" value="false" /><param name="menu" value="false" /><param name="quality" value="best" /><param name="bgcolor" value="#ffffff" /><param name="flashvars" value="'+b+'"/><param name="wmode" value="transparent"/></object>'}else{c+='<embed id="'+this.movieId+'" src="'+ZeroClipboard.moviePath+'" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="'+d+'" height="'+a+'" name="'+this.movieId+'" align="middle" allowScriptAccess="always" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="'+b+'" wmode="transparent" />'}return c},hide:function(){if(this.div){this.div.style.left="-2000px"}},show:function(){this.reposition()},destroy:function(){if(this.domElement&&this.div){this.hide();this.div.innerHTML="";var a=document.getElementsByTagName("body")[0];try{a.removeChild(this.div)}catch(b){}this.domElement=null;this.div=null}},reposition:function(c){if(c){this.domElement=ZeroClipboard.$(c);if(!this.domElement){this.hide()}}if(this.domElement&&this.div){var b=ZeroClipboard.getDOMObjectPosition(this.domElement);var a=this.div.style;a.left=""+b.left+"px";a.top=""+b.top+"px"}},setText:function(a){this.clipText=a;if(this.ready){this.movie.setText(a)}},addEventListener:function(a,b){a=a.toString().toLowerCase().replace(/^on/,"");if(!this.handlers[a]){this.handlers[a]=[]}this.handlers[a].push(b)},setHandCursor:function(a){this.handCursorEnabled=a;if(this.ready){this.movie.setHandCursor(a)}},setCSSEffects:function(a){this.cssEffects=!!a},receiveEvent:function(d,f){d=d.toString().toLowerCase().replace(/^on/,"");switch(d){case"load":this.movie=document.getElementById(this.movieId);if(!this.movie){var c=this;setTimeout(function(){c.receiveEvent("load",null)},1);return}if(!this.ready&&navigator.userAgent.match(/Firefox/)&&navigator.userAgent.match(/Windows/)){var c=this;setTimeout(function(){c.receiveEvent("load",null)},100);this.ready=true;return}this.ready=true;try{this.movie.setText(this.clipText)}catch(h){}try{this.movie.setHandCursor(this.handCursorEnabled)}catch(h){}break;case"mouseover":if(this.domElement&&this.cssEffects){this.domElement.addClass("hover");if(this.recoverActive){this.domElement.addClass("active")}}break;case"mouseout":if(this.domElement&&this.cssEffects){this.recoverActive=false;if(this.domElement.hasClass("active")){this.domElement.removeClass("active");this.recoverActive=true}this.domElement.removeClass("hover")}break;case"mousedown":if(this.domElement&&this.cssEffects){this.domElement.addClass("active")}break;case"mouseup":if(this.domElement&&this.cssEffects){this.domElement.removeClass("active");this.recoverActive=false}break}if(this.handlers[d]){for(var b=0,a=this.handlers[d].length;b<a;b++){var g=this.handlers[d][b];if(typeof(g)=="function"){g(this,f)}else{if((typeof(g)=="object")&&(g.length==2)){g[0][g[1]](this,f)}else{if(typeof(g)=="string"){window[g](this,f)}}}}}}};
Index: /extensions/UserCollections/template/mail.css
===================================================================
--- /extensions/UserCollections/template/mail.css	(revision 20090)
+++ /extensions/UserCollections/template/mail.css	(revision 20090)
@@ -0,0 +1,80 @@
+body {
+  margin:0px; 
+  padding:0px;
+  font-family: Univers, Helvetica, Optima; 
+  font-size:12px;
+  text-align:left;
+  background:#111;
+  color:#aaa;
+}
+
+a {
+  color:#CE2E5A;
+}
+ 
+#the_page {
+  min-width:600px;
+  max-width:800px;
+  margin:10px auto; 
+  padding:0px; 
+}
+
+#the_header {
+  background:#222;
+  border-top:5px solid #CE2E5A;
+  border-bottom:1px solid #111;
+  font-size:16px;
+  padding:10px;
+}
+
+#the_content {
+  background:#333;
+  border-top:1px solid #555;
+  border-bottom:1px solid #111;
+  padding:10px;
+}
+
+#the_footer {
+  background:#222;
+  border-top:1px solid #555;
+  border-bottom:2px solid #CE2E5A;
+  font-size:10px;
+  padding:5px;
+}
+
+#the_image {
+  text-align:center;
+}
+  #the_image a {
+    position:relative;
+    display:inline-block;
+    border:10px solid #444;
+  }
+  #the_image span {
+    display:block;
+    width:100%;
+    position:absolute;
+    bottom:-10px;
+    left:0;
+    text-align:center;
+    background:#444;
+  }
+  #the_image img {
+    max-width:150px;
+    border:none;
+  }
+
+.button {
+  margin-top:25px;
+  text-align:center;
+}
+
+.button  a {
+  padding:8px 15px;
+  background:#A80D24;
+  color:#bbb;
+  border:1px solid #CE2E5A;
+  text-decoration:none;
+  font-size:14px;
+  font-weight:bold;
+}
Index: /extensions/UserCollections/template/mail.tpl
===================================================================
--- /extensions/UserCollections/template/mail.tpl	(revision 20090)
+++ /extensions/UserCollections/template/mail.tpl	(revision 20090)
@@ -0,0 +1,62 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+  <title>Piwigo Mail</title>
+  <meta http-equiv="Content-Type" content="text/html; charset={$CONTENT_ENCODING}">
+  
+  {math assign=tn_width equation="min(x,150)"  x=$derivative_params->max_width()}
+  <style type="text/css">{strip}<!--
+  {$UC_MAIL_CSS}
+  #the_image a {ldelim}
+    width:{$tn_width}px;
+    height:{$tn_width}px;
+  }
+  #the_page {ldelim}
+    width:{math equation="x*4+120" x=$tn_width}px;
+  }
+  -->{/strip}</style>
+</head>
+
+<body>
+<div id="the_page">
+
+<div id="the_header">
+<b>{$MAIL_TITLE}</b>
+</div>
+
+<div id="the_content">
+
+<p>
+  {'Hello <b>%s</b>, %s sent you a photos collection from <a href="%s">%s</a>'|@translate|sprintf:$PARAMS.recipient_name:$PARAMS.sender_name:$GALLERY_URL:$GALLERY_TITLE}
+</p>
+
+<p id="the_image">
+{foreach from=$thumbnails item=element}
+  <a href="{$element.URL}">
+    <span>{$element.NAME|truncate:25:"..."}</span>
+    <img src="{$element.THUMB}" alt="{$element.TN_ALT}">
+  </a>
+{/foreach}
+</p>
+
+{if $PARAMS.message}
+<p>
+  <blockquote>{$PARAMS.message}</blockquote>
+</p>
+{/if}
+
+<p class="button">
+  <a href="{$COL_URL}">{'Click here to view the complete collection'|@translate}</a>
+</p>
+
+</div>
+
+<div id="the_footer">
+  {'Sent by'|@translate} <a href="{$GALLERY_URL}">{$GALLERY_TITLE}</a>
+  - {'Powered by'|@translate} <a href="{$PHPWG_URL}" class="Piwigo">Piwigo</a> {$VERSION}
+  - User Collections
+</div>
+
+</div>
+</body>
+</html>
Index: /extensions/UserCollections/template/resources/index.php
===================================================================
--- /extensions/UserCollections/template/resources/index.php	(revision 20090)
+++ /extensions/UserCollections/template/resources/index.php	(revision 20090)
@@ -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/UserCollections/template/resources/jquery.zclip.min.js
===================================================================
--- /extensions/UserCollections/template/resources/jquery.zclip.min.js	(revision 20090)
+++ /extensions/UserCollections/template/resources/jquery.zclip.min.js	(revision 20090)
@@ -0,0 +1,12 @@
+/*
+ * zClip :: jQuery ZeroClipboard v1.1.1
+ * http://steamdev.com/zclip
+ *
+ * Copyright 2011, SteamDev
+ * Released under the MIT license.
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ * Date: Wed Jun 01, 2011
+ */
+
+(function(a){a.fn.zclip=function(c){if(typeof c=="object"&&!c.length){var b=a.extend({path:"ZeroClipboard.swf",copy:null,beforeCopy:null,afterCopy:null,clickAfter:true,setHandCursor:true,setCSSEffects:true},c);return this.each(function(){var e=a(this);if(e.is(":visible")&&(typeof b.copy=="string"||a.isFunction(b.copy))){ZeroClipboard.setMoviePath(b.path);var d=new ZeroClipboard.Client();if(a.isFunction(b.copy)){e.bind("zClip_copy",b.copy)}if(a.isFunction(b.beforeCopy)){e.bind("zClip_beforeCopy",b.beforeCopy)}if(a.isFunction(b.afterCopy)){e.bind("zClip_afterCopy",b.afterCopy)}d.setHandCursor(b.setHandCursor);d.setCSSEffects(b.setCSSEffects);d.addEventListener("mouseOver",function(f){e.trigger("mouseenter")});d.addEventListener("mouseOut",function(f){e.trigger("mouseleave")});d.addEventListener("mouseDown",function(f){e.trigger("mousedown");if(!a.isFunction(b.copy)){d.setText(b.copy)}else{d.setText(e.triggerHandler("zClip_copy"))}if(a.isFunction(b.beforeCopy)){e.trigger("zClip_beforeCopy")}});d.addEventListener("complete",function(f,g){if(a.isFunction(b.afterCopy)){e.trigger("zClip_afterCopy")}else{if(g.length>500){g=g.substr(0,500)+"...\n\n("+(g.length-500)+" characters not shown)"}e.removeClass("hover");/*alert("Copied text to clipboard:\n\n "+g)*/}if(b.clickAfter){e.trigger("click")}});d.glue(e[0],e.parent()[0]);a(window).bind("load resize",function(){d.reposition()})}})}else{if(typeof c=="string"){return this.each(function(){var f=a(this);c=c.toLowerCase();var e=f.data("zclipId");var d=a("#"+e+".zclip");if(c=="remove"){d.remove();f.removeClass("active hover")}else{if(c=="hide"){d.hide();f.removeClass("active hover")}else{if(c=="show"){d.show()}}}})}}}})(jQuery);var ZeroClipboard={version:"1.0.7",clients:{},moviePath:"ZeroClipboard.swf",nextId:1,$:function(a){if(typeof(a)=="string"){a=document.getElementById(a)}if(!a.addClass){a.hide=function(){this.style.display="none"};a.show=function(){this.style.display=""};a.addClass=function(b){this.removeClass(b);this.className+=" "+b};a.removeClass=function(d){var e=this.className.split(/\s+/);var b=-1;for(var c=0;c<e.length;c++){if(e[c]==d){b=c;c=e.length}}if(b>-1){e.splice(b,1);this.className=e.join(" ")}return this};a.hasClass=function(b){return !!this.className.match(new RegExp("\\s*"+b+"\\s*"))}}return a},setMoviePath:function(a){this.moviePath=a},dispatch:function(d,b,c){var a=this.clients[d];if(a){a.receiveEvent(b,c)}},register:function(b,a){this.clients[b]=a},getDOMObjectPosition:function(c,a){var b={left:0,top:0,width:c.width?c.width:c.offsetWidth,height:c.height?c.height:c.offsetHeight};if(c&&(c!=a)){b.left+=c.offsetLeft;b.top+=c.offsetTop}return b},Client:function(a){this.handlers={};this.id=ZeroClipboard.nextId++;this.movieId="ZeroClipboardMovie_"+this.id;ZeroClipboard.register(this.id,this);if(a){this.glue(a)}}};ZeroClipboard.Client.prototype={id:0,ready:false,movie:null,clipText:"",handCursorEnabled:true,cssEffects:true,handlers:null,glue:function(d,b,e){this.domElement=ZeroClipboard.$(d);var f=99;if(this.domElement.style.zIndex){f=parseInt(this.domElement.style.zIndex,10)+1}if(typeof(b)=="string"){b=ZeroClipboard.$(b)}else{if(typeof(b)=="undefined"){b=document.getElementsByTagName("body")[0]}}var c=ZeroClipboard.getDOMObjectPosition(this.domElement,b);this.div=document.createElement("div");this.div.className="zclip";this.div.id="zclip-"+this.movieId;$(this.domElement).data("zclipId","zclip-"+this.movieId);var a=this.div.style;a.position="absolute";a.left=""+c.left+"px";a.top=""+c.top+"px";a.width=""+c.width+"px";a.height=""+c.height+"px";a.zIndex=f;if(typeof(e)=="object"){for(addedStyle in e){a[addedStyle]=e[addedStyle]}}b.appendChild(this.div);this.div.innerHTML=this.getHTML(c.width,c.height)},getHTML:function(d,a){var c="";var b="id="+this.id+"&width="+d+"&height="+a;if(navigator.userAgent.match(/MSIE/)){var e=location.href.match(/^https/i)?"https://":"http://";c+='<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="'+e+'download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" width="'+d+'" height="'+a+'" id="'+this.movieId+'" align="middle"><param name="allowScriptAccess" value="always" /><param name="allowFullScreen" value="false" /><param name="movie" value="'+ZeroClipboard.moviePath+'" /><param name="loop" value="false" /><param name="menu" value="false" /><param name="quality" value="best" /><param name="bgcolor" value="#ffffff" /><param name="flashvars" value="'+b+'"/><param name="wmode" value="transparent"/></object>'}else{c+='<embed id="'+this.movieId+'" src="'+ZeroClipboard.moviePath+'" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="'+d+'" height="'+a+'" name="'+this.movieId+'" align="middle" allowScriptAccess="always" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="'+b+'" wmode="transparent" />'}return c},hide:function(){if(this.div){this.div.style.left="-2000px"}},show:function(){this.reposition()},destroy:function(){if(this.domElement&&this.div){this.hide();this.div.innerHTML="";var a=document.getElementsByTagName("body")[0];try{a.removeChild(this.div)}catch(b){}this.domElement=null;this.div=null}},reposition:function(c){if(c){this.domElement=ZeroClipboard.$(c);if(!this.domElement){this.hide()}}if(this.domElement&&this.div){var b=ZeroClipboard.getDOMObjectPosition(this.domElement);var a=this.div.style;a.left=""+b.left+"px";a.top=""+b.top+"px"}},setText:function(a){this.clipText=a;if(this.ready){this.movie.setText(a)}},addEventListener:function(a,b){a=a.toString().toLowerCase().replace(/^on/,"");if(!this.handlers[a]){this.handlers[a]=[]}this.handlers[a].push(b)},setHandCursor:function(a){this.handCursorEnabled=a;if(this.ready){this.movie.setHandCursor(a)}},setCSSEffects:function(a){this.cssEffects=!!a},receiveEvent:function(d,f){d=d.toString().toLowerCase().replace(/^on/,"");switch(d){case"load":this.movie=document.getElementById(this.movieId);if(!this.movie){var c=this;setTimeout(function(){c.receiveEvent("load",null)},1);return}if(!this.ready&&navigator.userAgent.match(/Firefox/)&&navigator.userAgent.match(/Windows/)){var c=this;setTimeout(function(){c.receiveEvent("load",null)},100);this.ready=true;return}this.ready=true;try{this.movie.setText(this.clipText)}catch(h){}try{this.movie.setHandCursor(this.handCursorEnabled)}catch(h){}break;case"mouseover":if(this.domElement&&this.cssEffects){this.domElement.addClass("hover");if(this.recoverActive){this.domElement.addClass("active")}}break;case"mouseout":if(this.domElement&&this.cssEffects){this.recoverActive=false;if(this.domElement.hasClass("active")){this.domElement.removeClass("active");this.recoverActive=true}this.domElement.removeClass("hover")}break;case"mousedown":if(this.domElement&&this.cssEffects){this.domElement.addClass("active")}break;case"mouseup":if(this.domElement&&this.cssEffects){this.domElement.removeClass("active");this.recoverActive=false}break}if(this.handlers[d]){for(var b=0,a=this.handlers[d].length;b<a;b++){var g=this.handlers[d][b];if(typeof(g)=="function"){g(this,f)}else{if((typeof(g)=="object")&&(g.length==2)){g[0][g[1]](this,f)}else{if(typeof(g)=="string"){window[g](this,f)}}}}}}};
Index: /extensions/UserCollections/template/style.css
===================================================================
--- /extensions/UserCollections/template/style.css	(revision 20089)
+++ /extensions/UserCollections/template/style.css	(revision 20090)
@@ -29,5 +29,5 @@
   #publicURL .button {
     display:inline-block;
-    background:#e7e7e7 url('link.png') center center no-repeat;
+    background:#e7e7e7 url('resources/link.png') center center no-repeat;
     width:25px;
     height:20px;
@@ -73,4 +73,24 @@
     }
   
+/* SEND BY MAIL */
+#mail_form {
+  width:540px;
+  padding:10px;
+}
+  #mail_form table td {
+    padding-bottom:5px;
+    text-align:left;
+  }
+  #mail_form table td.title {
+    font-weight:bold;
+    text-align:right !important;
+    padding-top:3px;
+    vertical-align:top;
+    width:120px;
+  }
+  #mail_form input[type="text"], #mail_form textarea, #mail_form select {
+    border-radius:2px;
+    padding:3px;
+  }
   
 /* TipTip CSS - Version 1.2 */
Index: /extensions/UserCollections/template/themes/default.tpl
===================================================================
--- /extensions/UserCollections/template/themes/default.tpl	(revision 20089)
+++ /extensions/UserCollections/template/themes/default.tpl	(revision 20090)
@@ -4,9 +4,37 @@
 
 <div class="titrePage">
+	<ul class="categoryActions">
+  {if !empty($image_derivatives)}
+		<li>{strip}<a id="derivativeSwitchLink" title="{'Photo sizes'|@translate}" class="pwg-state-default pwg-button" rel="nofollow">
+			<span class="pwg-icon pwg-icon-sizes">&nbsp;</span><span class="pwg-button-text">{'Photo sizes'|@translate}</span>
+		</a>
+		<div id="derivativeSwitchBox" class="switchBox">
+			<div class="switchBoxTitle">{'Photo sizes'|@translate}</div>
+			{foreach from=$image_derivatives item=image_derivative name=loop}{if !$smarty.foreach.loop.first}<br>{/if}
+			{if $image_derivative.SELECTED}
+			<span>&#x2714; </span>{$image_derivative.DISPLAY}
+			{else}
+			<span style="visibility:hidden">&#x2714; </span><a href="{$image_derivative.URL}" rel="nofollow">{$image_derivative.DISPLAY}</a>
+			{/if}
+			{/foreach}
+		</div>
+		{footer_script require='jquery'}{literal}
+    jQuery("#derivativeSwitchLink").click(function() {
+      var elt = jQuery("#derivativeSwitchBox");
+      elt.css("left", Math.min( jQuery(this).offset().left, jQuery(window).width() - elt.outerWidth(true) - 5))
+        .css("top", jQuery(this).offset().top + jQuery(this).outerHeight(true))
+        .toggle();
+    });
+    jQuery("#derivativeSwitchBox").on("mouseleave", function() {
+      jQuery(this).hide();
+    });
+		{/literal}{/footer_script}
+		{/strip}</li>
+  {/if}
+
   {if !empty($COLLECTION_ACTIONS)}
-	<ul class="categoryActions">
     {$COLLECTION_ACTIONS}
+  {/if}
 	</ul>
-  {/if}
 
   <h2>{$TITLE}</h2>
Index: /extensions/UserCollections/template/thumbnails.tpl
===================================================================
--- /extensions/UserCollections/template/thumbnails.tpl	(revision 20089)
+++ /extensions/UserCollections/template/thumbnails.tpl	(revision 20090)
@@ -1,4 +1,5 @@
 {combine_script id='jquery.colorbox' load='footer' require='jquery' path='themes/default/js/plugins/jquery.colorbox.min.js'}
 {combine_css path="themes/default/js/plugins/colorbox/style2/colorbox.css"}
+
 {footer_script}
 jQuery("a.preview-box").colorbox({ldelim}
Index: /extensions/UserCollections/template/thumbnails_css_js.tpl
===================================================================
--- /extensions/UserCollections/template/thumbnails_css_js.tpl	(revision 20089)
+++ /extensions/UserCollections/template/thumbnails_css_js.tpl	(revision 20090)
@@ -17,5 +17,5 @@
   }).done(function(msg) {ldelim}
     if (msg == "true") {ldelim}
-      $trigger.html('{'Remove from collection'|@translate}&nbsp;<img src="{$ROOT_URL}{$USER_COLLEC_PATH}template/image_delete.png" title="{'Remove from collection'|@translate}">');
+      $trigger.html('{'Remove from collection'|@translate}&nbsp;<img src="{$ROOT_URL}{$USER_COLLEC_PATH}template/resources/image_delete.png" title="{'Remove from collection'|@translate}">');
       jQuery(".nbImagesCollec").html(parseInt(jQuery(".nbImagesCollec").html()) +1);
     } else if (msg == "false") {ldelim}
@@ -24,5 +24,5 @@
       if (typeof batchdown_count != 'undefined') batchdown_count-=1;
     {else}
-      $trigger.html('{'Add to collection'|@translate}&nbsp;<img src="{$ROOT_URL}{$USER_COLLEC_PATH}template/image_add.png" title="{'Add to collection'|@translate}">');
+      $trigger.html('{'Add to collection'|@translate}&nbsp;<img src="{$ROOT_URL}{$USER_COLLEC_PATH}template/resources/image_add.png" title="{'Add to collection'|@translate}">');
     {/if}
       jQuery(".nbImagesCollec").html(parseInt(jQuery(".nbImagesCollec").html()) -1);
