Index: branches/branch-1_6/include/config_default.inc.php
===================================================================
--- branches/branch-1_6/include/config_default.inc.php	(revision 1173)
+++ branches/branch-1_6/include/config_default.inc.php	(revision 1174)
@@ -334,4 +334,7 @@
 $conf['debug_l10n'] = false;
 
+// die_on_sql_error: if an SQL query fails, should everything stop?
+$conf['die_on_sql_error'] = true;
+
 // +-----------------------------------------------------------------------+
 // |                            authentication                             |
Index: branches/branch-1_6/include/functions.inc.php
===================================================================
--- branches/branch-1_6/include/functions.inc.php	(revision 1173)
+++ branches/branch-1_6/include/functions.inc.php	(revision 1174)
@@ -652,4 +652,6 @@
 function my_error($header)
 {
+  global $conf;
+  
   $error = '<pre>';
   $error.= $header;
@@ -657,5 +659,13 @@
   $error.= mysql_error();
   $error.= '</pre>';
-  die ($error);
+
+  if ($conf['die_on_sql_error'])
+  {
+    die($error);
+  }
+  else
+  {
+    echo $error;
+  }
 }
 
Index: branches/branch-1_6/install/upgrade_1.5.0.php
===================================================================
--- branches/branch-1_6/install/upgrade_1.5.0.php	(revision 1174)
+++ branches/branch-1_6/install/upgrade_1.5.0.php	(revision 1174)
@@ -0,0 +1,300 @@
+<?php
+// +-----------------------------------------------------------------------+
+// | PhpWebGallery - a PHP based picture gallery                           |
+// | Copyright (C) 2002-2003 Pierrick LE GALL - pierrick@phpwebgallery.net |
+// | Copyright (C) 2003-2005 PhpWebGallery Team - http://phpwebgallery.net |
+// +-----------------------------------------------------------------------+
+// | branch        : BSF (Best So Far)
+// | file          : $RCSfile$
+// | last update   : $Date: 2005-10-23 23:02:21 +0200 (dim, 23 oct 2005) $
+// | last modifier : $Author: plg $
+// | revision      : $Revision: 911 $
+// +-----------------------------------------------------------------------+
+// | This program is free software; you can redistribute it and/or modify  |
+// | it under the terms of the GNU General Public License as published by  |
+// | the Free Software Foundation                                          |
+// |                                                                       |
+// | This program is distributed in the hope that it will be useful, but   |
+// | WITHOUT ANY WARRANTY; without even the implied warranty of            |
+// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      |
+// | General Public License for more details.                              |
+// |                                                                       |
+// | You should have received a copy of the GNU General Public License     |
+// | along with this program; if not, write to the Free Software           |
+// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
+// | USA.                                                                  |
+// +-----------------------------------------------------------------------+
+
+if (!defined('PHPWG_ROOT_PATH'))
+{
+  die ('This page cannot be loaded directly, load upgrade.php');
+}
+else
+{
+  if (!defined('PHPWG_IN_UPGRADE') or !PHPWG_IN_UPGRADE)
+  {
+    die ('Hacking attempt!');
+  }
+}
+
+tag_replace_keywords();
+
+$queries = array(
+  "
+CREATE TABLE ".PREFIX_TABLE."search (
+  id int UNSIGNED NOT NULL AUTO_INCREMENT,
+  last_seen date DEFAULT NULL,
+  rules text,
+  PRIMARY KEY  (id)
+);",
+
+  "
+CREATE TABLE ".PREFIX_TABLE."user_mail_notification (
+  user_id smallint(5) NOT NULL default '0',
+  check_key varchar(16) binary NOT NULL default '',
+  enabled enum('true','false') NOT NULL default 'false',
+  last_send datetime default NULL,
+  PRIMARY KEY  (user_id),
+  UNIQUE KEY uidx_check_key (check_key)
+);",
+
+  "
+CREATE TABLE ".PREFIX_TABLE."upgrade (
+  id varchar(20) NOT NULL default '',
+  applied datetime NOT NULL default '0000-00-00 00:00:00',
+  description varchar(255) default NULL,
+  PRIMARY KEY  (`id`)
+);",
+
+  "
+ALTER TABLE ".PREFIX_TABLE."config
+  MODIFY COLUMN value TEXT
+;",
+
+  "
+ALTER TABLE ".PREFIX_TABLE."images
+  ADD COLUMN has_high enum('true') default NULL
+;",
+
+  "
+ALTER TABLE ".PREFIX_TABLE."rate
+  ADD COLUMN anonymous_id varchar(45) NOT NULL default ''
+;",
+  "
+ALTER TABLE ".PREFIX_TABLE."rate
+  ADD COLUMN date date NOT NULL default '0000-00-00'
+;",
+  "
+ALTER TABLE ".PREFIX_TABLE."rate
+  DROP PRIMARY KEY
+;",
+  "
+ALTER TABLE ".PREFIX_TABLE."rate
+  ADD PRIMARY KEY (element_id,user_id,anonymous_id)
+;",
+  "
+UPDATE ".PREFIX_TABLE."rate
+  SET date = CURDATE()
+;",
+  
+  "
+DELETE
+  FROM ".PREFIX_TABLE."sessions
+;",
+  "
+ALTER TABLE ".PREFIX_TABLE."sessions
+  DROP COLUMN user_id
+;",
+  "
+ALTER TABLE ".PREFIX_TABLE."sessions
+  ADD COLUMN data text NOT NULL
+;",
+  
+  "
+ALTER TABLE ".PREFIX_TABLE."user_cache
+  ADD COLUMN nb_total_images mediumint(8) unsigned default NULL
+;",
+  
+  "
+ALTER TABLE ".PREFIX_TABLE."user_infos
+  CHANGE COLUMN status
+     status enum('webmaster','admin','normal','generic','guest')
+     NOT NULL default 'guest'
+;",
+  "
+UPDATE ".PREFIX_TABLE."user_infos
+  SET status = 'normal'
+  WHERE status = 'guest'
+;",
+  "
+UPDATE ".PREFIX_TABLE."user_infos
+  SET status = 'guest'
+  WHERE user_id = ".$conf['guest_id']."
+;",
+  "
+UPDATE ".PREFIX_TABLE."user_infos
+  SET status = 'webmaster'
+  WHERE user_id = ".$conf['webmaster_id']."
+;",
+
+  "
+ALTER TABLE ".PREFIX_TABLE."user_infos
+   CHANGE COLUMN template template varchar(255) NOT NULL default 'yoga/clear'
+;",
+
+  "
+UPDATE ".PREFIX_TABLE."user_infos
+  SET template = 'yoga/dark'
+  WHERE template = 'yoga-dark'
+;",
+  "
+UPDATE ".PREFIX_TABLE."user_infos
+  SET template = 'yoga/clear'
+  WHERE template != 'yoga/dark'
+;",
+  "
+ALTER TABLE ".PREFIX_TABLE."user_infos
+  ADD COLUMN adviser enum('true','false') NOT NULL default 'false'
+;",
+  "
+ALTER TABLE ".PREFIX_TABLE."user_infos
+  ADD COLUMN enabled_high enum('true','false') NOT NULL default 'true'
+;",
+
+  // configuration table
+  "
+UPDATE ".PREFIX_TABLE."config
+  SET value = 'yoga/clear'
+  WHERE param = 'default_template'
+;"
+  );
+
+foreach ($queries as $query)
+{
+  pwg_query($query);
+}
+
+//
+// Move rate, rate_anonymous and gallery_url from config file to database
+//
+$params = array(
+  'gallery_url' => array(
+    'http://demo.phpwebgallery.net',
+    'URL given in RSS feed'
+    ),
+  'rate' => array(
+    'true',
+    'Rating pictures feature is enabled'
+    ),
+  'rate_anonymous' => array(
+    'true',
+    'Rating pictures feature is also enabled for visitors'
+    )
+  );
+// Get real values from config file
+$conf_save = $conf;
+unset($conf);
+@include(PHPWG_ROOT_PATH. 'include/config_local.inc.php');
+if ( isset($conf['gallery_url']) )
+{
+  $params['gallery_url'][0] = $conf['gallery_url'];
+}
+if ( isset($conf['rate']) and is_bool($conf['rate']) )
+{
+  $params['rate'][0] = $conf['rate'] ? 'true' : 'false';
+}
+if ( isset($conf['rate_anonymous']) and is_bool($conf['rate_anonymous']) )
+{
+  $params['rate_anonymous'][0] = $conf['rate_anonymous'] ? 'true' : 'false';
+}
+$conf = $conf_save;
+
+// Do I already have them in DB ?
+$query = 'SELECT param FROM '.PREFIX_TABLE.'config';
+$result = pwg_query($query);
+while ($row = mysql_fetch_array($result))
+{
+  unset( $params[ $row['param'] ] );
+}
+
+// Perform the insert query
+foreach ($params as $param_key => $param_values)
+{
+  $query = '
+INSERT INTO '.PREFIX_TABLE.'config
+  (param,value,comment)
+  VALUES
+ ('."'$param_key','$param_values[0]','$param_values[1]')
+;";
+  pwg_query($query);
+}
+
+$query = "
+ALTER TABLE ".PREFIX_TABLE."config MODIFY COLUMN `value` TEXT;";
+pwg_query($query);
+
+
+//
+// replace gallery_description by page_banner
+//
+$query = '
+SELECT value
+  FROM '.PREFIX_TABLE.'config
+  WHERE param=\'gallery_title\'
+;';
+list($t) = array_from_query($query, 'value');
+
+$query = '
+SELECT value
+  FROM '.PREFIX_TABLE.'config
+  WHERE param=\'gallery_description\'
+;';
+list($d) = array_from_query($query, 'value');
+
+$page_banner='<div id="theHeader"><h1>'.$t.'</h1><p>'.$d.'</p></div>';
+$page_banner=addslashes($page_banner);
+$query = '
+INSERT INTO '.PREFIX_TABLE.'config
+  (param,value,comment)
+  VALUES
+  (
+    \'page_banner\',
+    \''.$page_banner.'\',
+    \'html displayed on the top each page of your gallery\'
+  )
+;';
+pwg_query($query);
+
+$query = '
+DELETE FROM '.PREFIX_TABLE.'config
+  WHERE param=\'gallery_description\'
+;';
+pwg_query($query);
+
+//
+// configuration for notification by mail
+//
+$query = "
+INSERT INTO ".CONFIG_TABLE."
+  (param,value,comment)
+  VALUES
+  (
+    'nbm_send_mail_as',
+    '',
+    'Send mail as param value for notification by mail'
+  ),
+  (
+    'nbm_send_detailed_content',
+    'true',
+    'Send detailed content for notification by mail'
+  ),
+  (
+    'nbm_complementary_mail_content',
+    '',
+    'Complementary mail content for notification by mail'
+  )
+;
+";
+pwg_query($query);
+
+?>
Index: branches/branch-1_6/template/yoga/upgrade.tpl
===================================================================
--- branches/branch-1_6/template/yoga/upgrade.tpl	(revision 1173)
+++ branches/branch-1_6/template/yoga/upgrade.tpl	(revision 1174)
@@ -8,16 +8,15 @@
 
   <body>
-    <!-- BEGIN choices -->
+    <!-- BEGIN introduction -->
     <h1>Welcome to PhpWebGallery upgrade page.</h1>
-    <p>This page proposes to upgrade your database corresponding to your old version
-      of PhpWebGallery to the current version. Select the version you wish to upgrade
-      :</p>
 
-    <ul>
-      <!-- BEGIN choice -->
-      <li><a href="{choices.choice.URL}">{choices.choice.VERSION}</a></li>
-      <!-- END choice -->
-    </ul>
-    <!-- END choices -->
+    <p>This page proposes to upgrade your database corresponding to your old
+version of PhpWebGallery to the current version. The upgrade assistant
+thinks you are currently running a
+<strong>release {introduction.CURRENT_RELEASE}</strong> (or equivalent).</p>
+
+    <p><a href="{introduction.RUN_UPGRADE_URL}">Upgrade from release
+{introduction.CURRENT_RELEASE} to {RELEASE}</a></p>
+    <!-- END introduction -->
 
     <!-- BEGIN upgrade -->
Index: branches/branch-1_6/upgrade.php
===================================================================
--- branches/branch-1_6/upgrade.php	(revision 1173)
+++ branches/branch-1_6/upgrade.php	(revision 1174)
@@ -30,11 +30,11 @@
 include_once(PHPWG_ROOT_PATH.'include/functions.inc.php');
 include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
+include_once(PHPWG_ROOT_PATH.'admin/include/functions_upgrade.php');
 include(PHPWG_ROOT_PATH.'include/template.php');
 
 include(PHPWG_ROOT_PATH.'include/mysql.inc.php');
-
-// +-----------------------------------------------------------------------+
-// | Check Access and exit when it is not ok                               |
-// +-----------------------------------------------------------------------+
+include(PHPWG_ROOT_PATH . 'include/config_default.inc.php');
+@include(PHPWG_ROOT_PATH. 'include/config_local.inc.php');
+
 check_upgrade();
 
@@ -44,6 +44,4 @@
 include_once(PHPWG_ROOT_PATH.'include/constants.php');
 define('PREFIX_TABLE', $prefixeTable);
-
-$conf['show_queries'] = false;
 
 // Database connection
@@ -69,42 +67,216 @@
 
 /**
- * loads an sql file and executes all queries
+ * list all tables in an array
  *
- * Before executing a query, $replaced is... replaced by $replacing. This is
- * useful when the SQL file contains generic words. Drop table queries are
- * not executed.
+ * @return array
+ */
+function get_tables()
+{
+  $tables = array();
+  
+  $query = '
+SHOW TABLES
+;';
+  $result = mysql_query($query);
+
+  while ($row = mysql_fetch_row($result))
+  {
+    array_push(
+      $tables,
+      preg_replace('/^'.PREFIX_TABLE.'/', '', $row[0])
+      );
+  }
+
+  return $tables;
+}
+
+/**
+ * list all columns of each given table
  *
- * @param string filepath
- * @param string replaced
- * @param string replacing
+ * @return array of array
+ */
+function get_columns_of($tables)
+{
+  $columns_of = array();
+
+  foreach ($tables as $table)
+  {
+    $query = '
+DESC '.PREFIX_TABLE.$table.'
+;';
+    $result = mysql_query($query);
+
+    $columns_of[$table] = array();
+
+    while ($row = mysql_fetch_row($result))
+    {
+      array_push($columns_of[$table], $row[0]);
+    }
+  }
+
+  return $columns_of;
+}
+
+/**
+ */
+function print_time($message)
+{
+  global $last_time;
+  
+  $new_time = get_moment();
+  echo '<pre>['.get_elapsed_time($last_time, $new_time).']';
+  echo ' '.$message;
+  echo '</pre>';
+  flush();
+  $last_time = $new_time;
+}
+
+/**
+ * replace old style #images.keywords by #tags. Requires a big data
+ * migration.
+ *
  * @return void
  */
-function execute_sqlfile($filepath, $replaced, $replacing)
-{
-  $sql_lines = file($filepath);
-  $query = '';
-  foreach ($sql_lines as $sql_line)
-  {
-    $sql_line = trim($sql_line);
-    if (preg_match('/(^--|^$)/', $sql_line))
-    {
-      continue;
-    }
-    $query.= ' '.$sql_line;
-    // if we reached the end of query, we execute it and reinitialize the
-    // variable "query"
-    if (preg_match('/;$/', $sql_line))
-    {
-      $query = trim($query);
-      $query = str_replace($replaced, $replacing, $query);
-      // we don't execute "DROP TABLE" queries
-      if (!preg_match('/^DROP TABLE/i', $query))
+function tag_replace_keywords()
+{
+  // code taken from upgrades 19 and 22
+  
+  $query = '
+CREATE TABLE '.PREFIX_TABLE.'tags (
+  id smallint(5) UNSIGNED NOT NULL auto_increment,
+  name varchar(255) BINARY NOT NULL,
+  url_name varchar(255) BINARY NOT NULL,
+  PRIMARY KEY (id)
+)
+;';
+  pwg_query($query);
+  
+  $query = '
+CREATE TABLE '.PREFIX_TABLE.'image_tag (
+  image_id mediumint(8) UNSIGNED NOT NULL,
+  tag_id smallint(5) UNSIGNED NOT NULL,
+  PRIMARY KEY (image_id,tag_id)
+)
+;';
+  pwg_query($query);
+  
+  //
+  // Move keywords to tags
+  //
+
+  // each tag label is associated to a numeric identifier
+  $tag_id = array();
+  // to each tag id (key) a list of image ids (value) is associated
+  $tag_images = array();
+
+  $current_id = 1;
+
+  $query = '
+SELECT id, keywords
+  FROM '.PREFIX_TABLE.'images
+  WHERE keywords IS NOT NULL
+;';
+  $result = pwg_query($query);
+  while ($row = mysql_fetch_array($result))
+  {
+    foreach(preg_split('/[,]+/', $row['keywords']) as $keyword)
+    {
+      if (!isset($tag_id[$keyword]))
       {
-        mysql_query($query);
+        $tag_id[$keyword] = $current_id++;
       }
-      $query = '';
-    }
-  }
-}
+
+      if (!isset($tag_images[ $tag_id[$keyword] ]))
+      {
+        $tag_images[ $tag_id[$keyword] ] = array();
+      }
+
+      array_push(
+        $tag_images[ $tag_id[$keyword] ],
+        $row['id']
+        );
+    }
+  }
+
+  $datas = array();
+  foreach ($tag_id as $tag_name => $tag_id)
+  {
+    array_push(
+      $datas,
+      array(
+        'id'       => $tag_id,
+        'name'     => $tag_name,
+        'url_name' => str2url($tag_name),
+        )
+      );
+  }
+  
+  if (!empty($datas))
+  {
+    mass_inserts(
+      PREFIX_TABLE.'tags',
+      array_keys($datas[0]),
+      $datas
+      );
+  }
+
+  $datas = array();
+  foreach ($tag_images as $tag_id => $images)
+  {
+    foreach (array_unique($images) as $image_id)
+    {
+      array_push(
+        $datas,
+        array(
+          'tag_id'   => $tag_id,
+          'image_id' => $image_id,
+          )
+        );
+    }
+  }
+  
+  if (!empty($datas))
+  {
+    mass_inserts(
+      PREFIX_TABLE.'image_tag',
+      array_keys($datas[0]),
+      $datas
+      );
+  }
+
+  //
+  // Delete images.keywords
+  //
+  $query = '
+ALTER TABLE '.PREFIX_TABLE.'images DROP COLUMN keywords
+;';
+  pwg_query($query);
+
+  //
+  // Add useful indexes
+  //
+  $query = '
+ALTER TABLE '.PREFIX_TABLE.'tags
+  ADD INDEX tags_i1(url_name)
+;';
+  pwg_query($query);
+
+
+  $query = '
+ALTER TABLE '.PREFIX_TABLE.'image_tag
+  ADD INDEX image_tag_i1(tag_id)
+;';
+  pwg_query($query);
+
+  print_time('tags have replaced keywords');
+}
+
+// +-----------------------------------------------------------------------+
+// |                             playing zone                              |
+// +-----------------------------------------------------------------------+
+
+// echo implode('<br>', get_tables());
+// echo '<pre>'; print_r(get_columns_of(get_tables())); echo '</pre>';
+
 // +-----------------------------------------------------------------------+
 // |                        template initialization                        |
@@ -116,45 +288,59 @@
 
 // +-----------------------------------------------------------------------+
-// |                          versions upgradable                          |
-// +-----------------------------------------------------------------------+
-$versions = array();
-$path = PHPWG_ROOT_PATH.'install';
-if ($contents = opendir($path))
-{
-  while (($node = readdir($contents)) !== false)
-  {
-    if (is_file($path.'/'.$node)
-        and preg_match('/^upgrade_(.*?)\.php$/', $node, $match))
-    {
-      array_push($versions, $match[1]);
-    }
-  }
-}
-natcasesort($versions);
-// +-----------------------------------------------------------------------+
 // |                            upgrade choice                             |
 // +-----------------------------------------------------------------------+
+
 if (!isset($_GET['version']))
 {
-  $template->assign_block_vars('choices', array());
-  foreach ($versions as $version)
-  {
-    $template->assign_block_vars(
-      'choices.choice',
-      array(
-        'URL' => PHPWG_ROOT_PATH.'upgrade.php?version='.$version,
-        'VERSION' => $version
-        ));
-  }
-}
+  // find the current release
+  $tables = get_tables();
+  $columns_of = get_columns_of($tables);
+
+  if (!in_array('param', $columns_of['config']))
+  {
+    // we're in branch 1.3, important upgrade, isn't it?
+    if (in_array('user_category', $tables))
+    {
+      $current_release = '1.3.1';
+    }
+    else
+    {
+      $current_release = '1.3.0';
+    }
+  }
+  else if (!in_array('user_cache', $tables))
+  {
+    $current_release = '1.4.0';
+  }
+  else if (!in_array('tags', $tables))
+  {
+    $current_release = '1.5.0';
+  }
+  else
+  {
+    die('You are already on branch 1.6, no upgrade required');
+  }
+  
+  $template->assign_block_vars(
+    'introduction',
+    array(
+      'CURRENT_RELEASE' => $current_release,
+      'RUN_UPGRADE_URL' =>
+        PHPWG_ROOT_PATH.'upgrade.php?version='.$current_release,
+      )
+    );
+}
+
 // +-----------------------------------------------------------------------+
 // |                            upgrade launch                             |
 // +-----------------------------------------------------------------------+
+
 else
 {
-  $upgrade_file = $path.'/upgrade_'.$_GET['version'].'.php';
+  $upgrade_file = PHPWG_ROOT_PATH.'install/upgrade_'.$_GET['version'].'.php';
   if (is_file($upgrade_file))
   {
     $page['upgrade_start'] = get_moment();
+    $conf['die_on_sql_error'] = false;
     include($upgrade_file);
     $page['upgrade_end'] = get_moment();
@@ -164,9 +350,17 @@
       array(
         'VERSION' => $_GET['version'],
-        'TOTAL_TIME' => get_elapsed_time($page['upgrade_start'],
-                                         $page['upgrade_end']),
-        'SQL_TIME' => number_format($page['queries_time'], 3, '.', ' ').' s',
+        'TOTAL_TIME' => get_elapsed_time(
+          $page['upgrade_start'],
+          $page['upgrade_end']
+          ),
+        'SQL_TIME' => number_format(
+          $page['queries_time'],
+          3,
+          '.',
+          ' '
+          ).' s',
         'NB_QUERIES' => $page['count_queries']
-        ));
+        )
+      );
 
     if (!isset($infos))
@@ -198,6 +392,10 @@
     foreach ($infos as $info)
     {
-      $template->assign_block_vars('upgrade.infos.info',
-                                   array('CONTENT' => $info));
+      $template->assign_block_vars(
+        'upgrade.infos.info',
+        array(
+          'CONTENT' => $info,
+          )
+        );
     }
   }
@@ -207,7 +405,15 @@
   }
 }
+
+$query = '
+UPDATE '.USER_CACHE_TABLE.'
+  SET need_update = \'true\'
+;';
+pwg_query($query);
+
 // +-----------------------------------------------------------------------+
 // |                          sending html code                            |
 // +-----------------------------------------------------------------------+
+
 $template->pparse('upgrade');
 ?>
