Index: /extensions/AMetaData/JpegMetaData/Common/DateTime.class.php
===================================================================
--- /extensions/AMetaData/JpegMetaData/Common/DateTime.class.php	(revision 6731)
+++ /extensions/AMetaData/JpegMetaData/Common/DateTime.class.php	(revision 6731)
@@ -0,0 +1,146 @@
+<?php
+/*
+ * --:: JPEG MetaDatas ::-------------------------------------------------------
+ *
+ *  Author    : Grum
+ *   email    : grum at piwigo.org
+ *   website  : http://photos.grum.fr
+ *
+ *   << May the Little SpaceFrog be with you ! >>
+ *
+ * +-----------------------------------------------------------------------+
+ * | JpegMetaData - a PHP based Jpeg Metadata manager                      |
+ * +-----------------------------------------------------------------------+
+ * | Copyright(C) 2010  Grum - http://www.grum.fr                          |
+ * +-----------------------------------------------------------------------+
+ * | 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.                                                                  |
+ * +-----------------------------------------------------------------------+
+ *
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * This DateTime class is used if the PHP version don't have built-in DateTime
+ * class
+ *
+ * Only the needed methods are provided :
+ *  - public function __construct($time, $timeZone=null)
+ *  - public function format($fmt)
+ *
+ * -----------------------------------------------------------------------------
+ */
+
+  if(!class_exists('DateTime'))
+  {
+    Class DateTimeZone
+    {
+      private $timeZone='UTC';
+      private $pushedTZ='UTC';
+
+      public function __construct($value='UTC')
+      {
+        $this->set($value);
+      }
+
+      /**
+       * return the time zone
+       */
+      public function get()
+      {
+        return($this->timeZone);
+      }
+
+      /**
+       * set the time zone
+       */
+      public function set($timeZone)
+      {
+        if(is_string($timeZone))
+        {
+          $this->timeZone=$timeZone;
+        }
+      }
+
+      /**
+       * apply the time zone to the system
+       */
+      public function push()
+      {
+        if(function_exists('date_default_timezone_get'))
+        {
+          $this->pushed=date_default_timezone_get();
+          date_default_timezone_set($this->timeZone);
+        }
+      }
+
+      /**
+       * restore the previous system time zone
+       */
+      public function pop()
+      {
+        if(function_exists('date_default_timezone_set'))
+        {
+          $this->pushed=date_default_timezone_set($this->pushed);
+        }
+      }
+    }
+
+
+    class DateTime
+    {
+      private $time=0;
+      private $timeZone=null;
+
+      public function __construct($time=null, DateTimeZone $timeZone=null)
+      {
+        if(is_string($time))
+        {
+          /*
+           * try to parse the string ; assume the current date/time if provided
+           * string can't be interpreted
+           */
+          $this->time=strtotime($time);
+          if($this->time===false) $this->time=time();
+        }
+        elseif(is_numeric($time))
+        {
+          // a timestamp was given
+          $this->time=$time;
+        }
+        else
+        {
+          // in all other case, assume it's equal to the current date/time
+          $this->time=time();
+        }
+        $this->timeZone=$timeZone;
+      }
+
+      public function __destruct()
+      {
+      }
+
+      /**
+       * returns the date/time in the given time zone
+       */
+      public function format($fmt='c')
+      {
+        if(!is_null($this->timeZone)) $this->timeZone->push();
+        $returned=date($fmt, $this->time);
+        if(!is_null($this->timeZone)) $this->timeZone->pop();
+        return($returned);
+      }
+    }
+  }
+
+?>
Index: /extensions/AMetaData/JpegMetaData/index.php
===================================================================
--- /extensions/AMetaData/JpegMetaData/index.php	(revision 6731)
+++ /extensions/AMetaData/JpegMetaData/index.php	(revision 6731)
@@ -0,0 +1,33 @@
+<?php
+// +-----------------------------------------------------------------------+
+// | PhpWebGallery - a PHP based picture gallery                           |
+// | Copyright (C) 2002-2003 Pierrick LE GALL - pierrick@phpwebgallery.net |
+// | Copyright (C) 2003-2007 PhpWebGallery Team - http://phpwebgallery.net |
+// +-----------------------------------------------------------------------+
+// | file          : $Id: index.php 1912 2007-03-16 06:30:07Z rub $
+// | last update   : $Date: 2007-03-16 07:30:07 +0100 (ven, 16 mar 2007) $
+// | last modifier : $Author: rub $
+// | revision      : $Revision: 1912 $
+// +-----------------------------------------------------------------------+
+// | 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/AMetaData/admin/amd_metadata_database_database.tpl
===================================================================
--- /extensions/AMetaData/admin/amd_metadata_database_database.tpl	(revision 6731)
+++ /extensions/AMetaData/admin/amd_metadata_database_database.tpl	(revision 6731)
@@ -0,0 +1,323 @@
+{known_script id="jquery.ui" src=$ROOT_URL|@cat:"themes/default/js/ui/packed/ui.core.packed.js"}
+{known_script id="jquery.ui.dialog" src=$ROOT_URL|@cat:"themes/default/js/ui/packed/ui.dialog.packed.js"}
+
+{literal}
+<script type="text/javascript">
+var processAnalyze = {
+      step:0,
+      lists:new Array(),
+      timeStart:0,
+      timeEnd:0
+    }
+
+  function init()
+  {
+    formatNbItemPerRequest({/literal}{$datas.NumberOfItemsPerRequest}{literal});
+  }
+
+  function formatNbItemPerRequest(nbItems)
+  {
+    $("#iamd_NumberOfItemsPerRequest").val(nbItems);
+    $("#iamd_nb_item_per_request_display").html(nbItems);
+  }
+
+  function doAnalyze()
+  {
+    mode="all";
+    modeLabel="";
+
+    if($("#ianalyze_action0").get(0).checked)
+    {
+      mode="notAnalyzed";
+      modeLabel="{/literal}{'g003_analyze_not_analyzed_pictures'|@translate}{literal}";
+    }
+    else if($("#ianalyze_action1").get(0).checked)
+    {
+      mode="all";
+      modeLabel="{/literal}{'g003_analyze_all_pictures'|@translate}{literal}";
+    }
+    else if($("#ianalyze_action2").get(0).checked)
+    {
+      mode="caddieAdd";
+      modeLabel="{/literal}{'g003_analyze_caddie_add_pictures'|@translate}{literal}";
+    }
+    else if($("#ianalyze_action3").get(0).checked)
+    {
+      mode="caddieReplace";
+      modeLabel="{/literal}{'g003_analyze_caddie_replace_pictures'|@translate}{literal}";
+    }
+    else if($("#ianalyze_action4").get(0).checked)
+    {
+      mode="analyzed";
+      modeLabel="{/literal}{'g003_analyze_analyzed_pictures'|@translate}{literal}";
+    }
+
+    ignoreOptions=[];
+    if($('#iFillDataBaseIgnore_magic').get(0).checked)
+    {
+      ignoreOptions.push('magic');
+    }
+    if($('#iFillDataBaseIgnore_exif').get(0).checked)
+    {
+      ignoreOptions.push('exif');
+    }
+    if($('#iFillDataBaseIgnore_iptc').get(0).checked)
+    {
+      ignoreOptions.push('iptc');
+    }
+    if($('#iFillDataBaseIgnore_xmp').get(0).checked)
+    {
+      ignoreOptions.push('xmp');
+    }
+
+
+    doAnalyzeDialog="<br><form id='iDialogProgress' class='formtable'>"+
+      "<div id='iprogressbar_contener' class='gcBorderInput'>"+
+      "<span id='iprogressbar_bg' class='gcBgInput' style='width:0%;'>&nbsp;</span>"+
+      "<span id='iprogressbar_fg' class='gcLink'>0%</span>"+
+      "</div><p>{/literal}{'g003_analyze_in_progress'|@translate}{literal}"+
+      "<br><img src='./plugins/GrumPluginClasses/icons/processing.gif'>"
+      "</p></form>";
+
+    $("#dialog")
+    .html("")
+    .dialog(
+      {
+        resizable: false,
+        width:480,
+        height:120,
+        modal: true,
+        draggable:true,
+        dialogClass: 'gcBgTabSheet gcBorder',
+        title: '{/literal}{"g003_updating_metadata"|@translate}{literal}&nbsp;('+modeLabel+')',
+      }
+    ).html(doAnalyzeDialog);
+
+    NumberOfItemsPerRequest=$("#iamd_NumberOfItemsPerRequest").val();
+
+    $.ajax(
+      {
+        type: "POST",
+        url: "{/literal}{$datas.urlRequest}{literal}",
+        async: true,
+        data:
+          {
+            ajaxfct:"admin.makeStats.getList",
+            selectMode:mode,
+            numOfItems:NumberOfItemsPerRequest,
+            ignoreOptions:ignoreOptions,
+          },
+        success: function(msg)
+          {
+            processAnalyze.step=0;
+            processAnalyze.lists=msg.split(";");
+            processAnalyze.timeStart=new Date();
+            doStep_processList();
+          },
+        error: function()
+          {
+            alert('error');
+          }
+      }
+    );
+  }
+
+
+  function displayTime(eTime)
+  {
+    seconds=(eTime%60).toFixed(2);
+    minutes=((eTime-seconds)/60).toFixed(0);
+    returned=seconds+"s";
+    if(minutes>0) returned=minutes+"m"+returned;
+    return(returned);
+  }
+
+  function doStep_processList()
+  {
+    if(processAnalyze.step < processAnalyze.lists.length)
+    {
+      $.ajax({
+        type: "POST",
+        url: "{/literal}{$datas.urlRequest}{literal}",
+        async: true,
+        data: { ajaxfct:"admin.makeStats.doAnalyze", imagesList:processAnalyze.lists[processAnalyze.step] },
+        success: function(msg)
+          {
+            processAnalyze.step++;
+            doStep_processList();
+          },
+       });
+
+      pct=100*(processAnalyze.step+1)/processAnalyze.lists.length;
+      $("#iprogressbar_bg").css("width", pct+"%");
+      $("#iprogressbar_fg").html(Math.round(pct)+"%");
+    }
+    else
+    {
+      // list completely processed
+      tmp = $.ajax({
+        type: "POST",
+        url: "{/literal}{$datas.urlRequest}{literal}",
+        async: false,
+        data: { ajaxfct:"admin.makeStats.consolidate" }
+       }).responseText;
+
+      processAnalyze.timeEnd = new Date();
+      timeElapsed=processAnalyze.timeEnd.getTime()-processAnalyze.timeStart.getTime();
+
+      $("#dialog")
+      .dialog("destroy")
+      .html("")
+      .get(0).removeAttribute('style');
+
+      $("#dialog")
+      .dialog(
+        {
+          resizable: false,
+          width:480,
+          height:120,
+          modal: true,
+          draggable:true,
+          dialogClass: 'gcBgTabSheet gcBorder',
+          title: '{/literal}{"g003_updating_metadata"|@translate}{literal}',
+          dialogClass: 'gcBgTabSheet gcBorder',
+          open: function(event, ui)
+          {
+            bH=$("div.ui-dialog-buttonpane").get(0).clientHeight;
+            $("#dialog").css('height', (this.clientHeight-bH)+"px");
+          },
+          buttons:
+          {
+            '{/literal}{"g003_ok"|@translate}{literal}':
+              function()
+              {
+                $(this).dialog('destroy').html("").get(0).removeAttribute('style');
+              }
+          }
+        }
+      )
+      .html("<br>{/literal}{'g003_analyze_is_finished'|@translate}{literal}&nbsp;("+displayTime(timeElapsed/1000)+")");
+    }
+  }
+
+  function updateFillDatabaseOption()
+  {
+    $.ajax(
+      {
+        type: "POST",
+        url: "{/literal}{$datas.urlRequest}{literal}",
+        async: true,
+        data: { ajaxfct:"admin.config.setOption", id:'amd_FillDataBaseContinuously', value:$('#iamd_FillDataBaseContinuously').get(0).checked?'y':'n' },
+      }
+    );
+  }
+
+  function displayAnalyzedOption()
+  {
+    if($('#iAnalyzeAnalyzed').css('display')=='none')
+    {
+      $('#iAnalyzeAnalyzed').css('display', 'block');
+      $('#ianalyze_action4').get(0).checked=true;
+    }
+  }
+
+
+
+</script>
+{/literal}
+
+<h2>{'g003_updating_metadata'|@translate}</h2>
+
+<div id="dialog"></div>
+
+<div id='ianalyzearea'>
+  <form class="formtable">
+    <fieldset>
+      <legend>{'g003_options'|@translate}</legend>
+      <label><input onclick='updateFillDatabaseOption();' type="checkbox" id='iamd_FillDataBaseContinuously' {if $amdConfig.amd_FillDataBaseContinuously=='y'}checked{/if}>&nbsp;{'g003_fillDatabaseContinuously'|@translate}</label><br>
+
+      {if !(in_array('exif', $amdConfig.amd_FillDataBaseExcludeFilters) and
+            in_array('xmp', $amdConfig.amd_FillDataBaseExcludeFilters) and
+            in_array('iptc', $amdConfig.amd_FillDataBaseExcludeFilters) and
+            in_array('xmp', $amdConfig.amd_FillDataBaseExcludeFilters)) }
+        <br>
+        {'g003_ignoreMetadata'|@translate}<br>
+        <table style='margin-left:0px;'>
+          <tr style='vertical-align:top;text-align:left;'>
+            <td width='150px'>
+              {if !in_array('magic', $amdConfig.amd_FillDataBaseExcludeFilters)}
+              <label><input onclick='displayAnalyzedOption();' type="checkbox" id='iFillDataBaseIgnore_magic' {if in_array('magic', $amdConfig.amd_FillDataBaseIgnoreSchemas)}checked{/if}>&nbsp;Magic</label><br>
+              {/if}
+              {if !in_array('exif', $amdConfig.amd_FillDataBaseExcludeFilters)}
+              <label><input onclick='displayAnalyzedOption();' type="checkbox" id='iFillDataBaseIgnore_exif' {if in_array('exif', $amdConfig.amd_FillDataBaseIgnoreSchemas)}checked{/if}>&nbsp;EXIF</label><br>
+              {/if}
+              {if !in_array('iptc', $amdConfig.amd_FillDataBaseExcludeFilters)}
+              <label><input onclick='displayAnalyzedOption();' type="checkbox" id='iFillDataBaseIgnore_iptc' {if in_array('iptc', $amdConfig.amd_FillDataBaseIgnoreSchemas)}checked{/if}>&nbsp;IPTC</label><br>
+              {/if}
+              {if !in_array('xmp', $amdConfig.amd_FillDataBaseExcludeFilters)}
+              <label><input onclick='displayAnalyzedOption();' type="checkbox" id='iFillDataBaseIgnore_xmp' {if in_array('xmp', $amdConfig.amd_FillDataBaseIgnoreSchemas)}checked{/if}>&nbsp;XMP</label>
+              {/if}
+            </td>
+            <td style='border-left:1px dotted;'><br><span style='font-style:italic;margin-left:8px;'>{'g003_fillDatabaseIgnoreWarning'|@translate}</span></td>
+          </tr>
+        </table>
+      {/if}
+    </fieldset>
+
+    <fieldset>
+      <legend>{'g003_update_metadata'|@translate}</legend>
+        <label>
+          <input type="radio" value="caddieAdd" name="fAMD_analyze_action" id="ianalyze_action2" checked>&nbsp;
+          {'g003_analyze_caddie_add_pictures'|@translate}
+        </label><br>
+
+        <label>
+          <input type="radio" value="caddieReplace" name="fAMD_analyze_action" id="ianalyze_action3">&nbsp;
+          {'g003_analyze_caddie_replace_pictures'|@translate}
+        </label><br>
+
+
+        <label>
+          <input type="radio" value="notAnalayzed" name="fAMD_analyze_action" id="ianalyze_action0">&nbsp;
+          {'g003_analyze_not_analyzed_pictures'|@translate}
+        </label><br>
+
+        <label>
+          <input type="radio" value="all" name="fAMD_analyze_action" id="ianalyze_action1">&nbsp;
+          {'g003_analyze_all_pictures'|@translate}
+        </label><br>
+
+        <span id='iAnalyzeAnalyzed' style='display:none;'>
+          <label>
+            <input type="radio" value="analyzed" name="fAMD_analyze_action" id="ianalyze_action4">&nbsp;
+            {'g003_analyze_analyzed_pictures'|@translate}
+          </label><br>
+        </span>
+
+        {if $amdConfig.amd_DisplayWarningsMessageUpdate=='y'}
+          <div style="padding-left: 60px;" class="warnings">
+            <p style="font-size: 120%;">{'g003_warning_on_analyze_0'|@translate}</p>
+            <p>{'g003_warning_on_analyze_1'|@translate}</p>
+            <p>{'g003_warning_on_analyze_2'|@translate}</p>
+          </div>
+        {/if}
+
+        <br>
+        <input type="hidden" id="iamd_NumberOfItemsPerRequest" value="{$datas.NumberOfItemsPerRequest}">
+        <!--
+        {'g003_setting_nb_items_per_request'|@translate}&nbsp;
+        <div id="iamd_nb_item_per_request_slider"></div>
+        <div id="iamd_nb_item_per_request_display"></div>
+        <br><br>
+        -->
+        <input type="button" value="{'g003_analyze'|@translate}" onclick="doAnalyze();">
+    </fieldset>
+  </form>
+</div>
+
+
+
+
+<script type="text/javascript">
+  init();
+</script>
Index: /extensions/AMetaData/admin/amd_metadata_database_status.tpl
===================================================================
--- /extensions/AMetaData/admin/amd_metadata_database_status.tpl	(revision 6731)
+++ /extensions/AMetaData/admin/amd_metadata_database_status.tpl	(revision 6731)
@@ -0,0 +1,48 @@
+<h2>{'g003_status_of_database'|@translate}</h2>
+
+{if $amdConfig.amd_DisplayWarningsMessageStatus=='y'}
+<div style="padding-left: 60px;" class="warnings">
+<p style="font-size: 120%;">{'g003_databaseInformation'|@translate}</p>
+{$datas.warning1}
+</div>
+
+<fieldset>
+<legend>{'g003_informations'|@translate}</legend>
+<table class='mdInfo'>
+ <tbody><tr>
+
+   <td width="50%">
+    {$datas.nfoMetadata.nfoSizeAndRows}
+    <ul>
+     {if !in_array('magic', $amdConfig.amd_FillDataBaseExcludeFilters)}
+     <li><span class="mdInfo">Magic</span>{$datas.nfoMetadata.magic}</li>
+     {/if}
+     {if !(in_array('exif', $amdConfig.amd_FillDataBaseExcludeFilters) and
+           in_array('exif.maker', $amdConfig.amd_FillDataBaseExcludeFilters))}
+     <li><span class="mdInfo">Exif</span>{$datas.nfoMetadata.exif}</li>
+     {/if}
+     {if !in_array('iptc', $amdConfig.amd_FillDataBaseExcludeFilters)}
+     <li><span class="mdInfo">IPTC</span>{$datas.nfoMetadata.iptc}</li>
+     {/if}
+     {if !in_array('xmp', $amdConfig.amd_FillDataBaseExcludeFilters)}
+     <li><span class="mdInfo">XMP</span>{$datas.nfoMetadata.xmp}</li>
+     {/if}
+     <li><span class="mdInfo">{'g003_personnal'|@translate}</span>{$datas.nfoMetadata.userDefined}</li>
+    </ul>
+   </td>
+
+   <td>
+    <ul>
+     <li>{$datas.nfoMetadata.numOfPictures}</li>
+     <li>{$datas.nfoMetadata.numOfNotAnalyzedPictures}</li>
+     <li>{$datas.nfoMetadata.numOfPicturesWithoutTag}</li>
+    </ul>
+   </td>
+ </tr>
+</tbody></table>
+</fieldset>
+
+
+
+{/if}
+
Index: /extensions/AMetaData/admin/amd_metadata_personnal.tpl
===================================================================
--- /extensions/AMetaData/admin/amd_metadata_personnal.tpl	(revision 6731)
+++ /extensions/AMetaData/admin/amd_metadata_personnal.tpl	(revision 6731)
@@ -0,0 +1,775 @@
+{known_script id="jquery.ui" src=$ROOT_URL|@cat:"themes/default/js/ui/packed/ui.core.packed.js"}
+{known_script id="jquery.ui.dialog" src=$ROOT_URL|@cat:"themes/default/js/ui/packed/ui.dialog.packed.js"}
+
+{known_script id="gpc.external.interface" src=$ROOT_URL|@cat:"plugins/GrumPluginClasses/js/external/interface/interface.js"}
+{known_script id="gpc.external.inestedsortable" src=$ROOT_URL|@cat:"plugins/GrumPluginClasses/js/external/inestedsortable.pack.js"}
+
+{literal}
+<script type="text/javascript">
+
+  /**
+   * sorry, tagListSelector is coded like a pork, but I don't have the time to
+   * code something better... ^^;
+   */
+  function tagListSelector(itemId)
+  {
+    options = {
+      itemId:'',
+      selectorId:'',
+      width:'auto',
+      height:'auto',
+      maxHeight:250,
+      selectedClass:'gcText3',
+      selectorClass:'ruleTypeM gcTextInput gcBgInput gcBorderInput',
+      selectorItems:'ruleTypeM',
+    }
+
+    this.init = function (itemId)
+    {
+      options.itemId=itemId;
+      $('body').append("<div id='iTLSDiv' class='"+options.selectorClass+"' style='padding:0px;z-index:5000;overflow:auto;display:none;position:absolute;max-height:"+options.maxHeight+"px'></div>");
+      $('#iTLSDiv')
+        .prepend($('#'+itemId))
+        .bind('mouseleave', function ()
+          {
+            $('#iTLSDiv').css('display', 'none');
+          }
+        );
+      $('#'+itemId).css('display', 'block');
+      $('#iTLSDiv li').bind('click', function ()
+        {
+          $('#'+options.selectorId).attr('value', $(this).attr('value'));
+          $('#'+options.selectorId+' span.ruleContent').html($(this).html());
+          $('#iTLSDiv').css('display', 'none');
+        }
+      );
+    }
+
+    this.display = function (fromId)
+    {
+      selectedItem=$('#'+fromId).attr('value');
+
+      top=$('#'+fromId).offset().top+$('#'+fromId).outerHeight()-1;
+      left=$('#'+fromId).offset().left;
+      width=$('#'+fromId).innerWidth();
+      $('#iTLSDiv li').removeClass(options.selectedClass);
+      $('#iTagListItem'+selectedItem).addClass(options.selectedClass);
+      $('#iTLSDiv').css(
+        {
+          top:top+'px',
+          left:left+'px',
+          width:width+'px',
+          display:'block'
+        }
+      );
+      options.selectorId=fromId;
+    }
+
+    this.init(itemId);
+  }
+
+
+  function userDefManage ()
+  {
+    var options = {
+      numId:'',
+      newRuleId:1,
+    }
+
+    /**
+     * initialize the page
+     */
+    this.init = function ()
+    {
+      computedHeight=$(window).height()-100;
+      $('#iDialogEdit')
+        .dialog(
+          {
+            autoOpen:false,
+            width:900,
+            height:computedHeight,
+            modal: true,
+            dialogClass: 'gcBgTabSheet gcBorder',
+            title: '{/literal}{"g003_personnal_metadata"|@translate}{literal}',
+            buttons:
+              {
+                '{/literal}{"g003_ok"|@translate}{literal}':
+                  function()
+                  {
+                    if(checkValidity()) doUpdate();
+                  },
+                '{/literal}{"g003_cancel"|@translate}{literal}':
+                  function()
+                  {
+                    $('#iDialogEdit').dialog("close");
+                  }
+              }
+          }
+        );
+      $('#iBDTagId').bind('keyup focusout', function (event)
+        {
+          if(!checkTagIdValidity($(this).val()))
+          {
+            $(this).addClass('error');
+          }
+          else
+          {
+            $(this).removeClass('error');
+          }
+        }
+      );
+
+
+      loadList();
+    }
+
+    /**
+     * open the dialog box to edit the metadata properties
+     *
+     * @param String id : if set to '' => open dialogbox in 'add' mode
+     *                    otherwise edit the given metadata
+     */
+    this.editMetadata = function (id)
+    {
+      options.numId=id;
+      updateDialog('');
+
+      $('#iDialogEdit')
+        .bind('dialogopen', function ()
+          {
+            if(options.id!='')
+            {
+              displayProcessing(true);
+
+              $.ajax(
+                {
+                  type: "POST",
+                  url: "{/literal}{$datas.urlRequest}{literal}",
+                  async: true,
+                  data: { ajaxfct:"admin.userDefined.getTag", id:options.numId },
+                  success:
+                    function(msg)
+                    {
+                      updateDialog(msg);
+                      displayProcessing(false);
+                    }
+                }
+              );
+            }
+
+            $('#mdRulesArea').css('height', ($('#iDialogEdit').height()-$('#mdRulesArea').position().top)+'px' );
+          }
+        )
+        .dialog("open");
+    }
+
+    /**
+     * delete a metadata
+     *
+     * @param String id : id of the metadata to delete
+     */
+    this.deleteMetadata = function (id)
+    {
+      $('#iDialogDelete')
+        .html('<br>{/literal}{"g003_pleaseConfirmMetadataDelete"|@translate}{literal}')
+        .dialog(
+          {
+            autoOpen:true,
+            modal: true,
+            dialogClass: 'gcBgTabSheet gcBorder',
+            title: '{/literal}{"g003_deleteMetadata"|@translate}{literal}',
+            buttons:
+              {
+                '{/literal}{"g003_delete"|@translate}{literal}':
+                  function()
+                  {
+                    $(this).html("<br><img src='./plugins/GrumPluginClasses/icons/processing.gif'>");
+                    $.ajax(
+                      {
+                        type: "POST",
+                        url: "{/literal}{$datas.urlRequest}{literal}",
+                        async: true,
+                        data: { ajaxfct:"admin.userDefined.deleteTag", id:id },
+                        success:
+                          function(msg)
+                          {
+                            $('#iDialogDelete').dialog("destroy");
+                            loadList();
+                          }
+                      }
+                    );
+                  },
+                '{/literal}{"g003_cancel"|@translate}{literal}':
+                  function()
+                  {
+                    $('#iDialogDelete').dialog("destroy");
+                  }
+              }
+          }
+        );
+    }
+
+    /**
+     * update values of the dialog box
+     *
+     * @param String items : json string ; if empty assume to reset all fields
+     *                       with blank
+     */
+    var updateDialog = function (items)
+    {
+      if(items=='')
+      {
+        options.newRuleId=1;
+        $('#iBDNumId').val('');
+        $('#iBDTagId').val('');
+        $('#iBDLabel').val('');
+        $('#iBDRules').html('');
+      }
+      else
+      {
+        tmp=$.parseJSON(items);
+
+        options.newRuleId=tmp.lastDefId+1;
+        $('#iBDNumId').val(tmp.numId);
+        $('#iBDTagId').val(tmp.tagId);
+        $('#iBDLabel').val(tmp.label);
+        $('#iBDRules').html('');
+        for(i=0;i<tmp.rules.length;i++)
+        {
+          addRule(tmp.rules[i]);
+        }
+      }
+    }
+
+    /**
+     * reload the user defined metadata list
+     */
+    var loadList = function ()
+    {
+      $('#iListTags').html("<br>{/literal}{'g003_loading'|@translate}{literal}<br><img src='./plugins/GrumPluginClasses/icons/processing.gif'>");
+
+      $.ajax(
+        {
+          type: "POST",
+          url: "{/literal}{$datas.urlRequest}{literal}",
+          async: true,
+          data: { ajaxfct:"admin.userDefined.getList" },
+          success:
+            function(msg)
+            {
+              $("#iListTags").html(msg);
+            }
+        }
+      );
+    }
+
+    /**
+     * check the validity of a given tagId
+     *  a valid tagId only contains chars : A-Z0-9.
+     *  a valid tagId can't start or finish with a dot, and a dot can't repeat
+     *  "machin.truc.much" => ok
+     *  ".machin.truc"     => ko
+     *  "machin.truc."     => ko
+     *  "machin..truc"     => ko
+     *
+     * @param String tagId : the tagId
+     * @return Boolean : true if ok, otherwise false
+     */
+    var checkTagIdValidity = function (tagId)
+    {
+      re=/^(?:[a-z0-9]+\.)*[a-z0-9]+$/i;
+      if(re.exec(tagId)==null) return(false);
+      return(true);
+    }
+
+    /**
+     * this function make the groups&items ready to be sorted & grouped
+     */
+    var applyNested = function ()
+    {
+      $('#iBDRules').NestedSortableDestroy();
+      $('#iBDRules').NestedSortable(
+        {
+          accept: 'rmSortable',
+          noNestingClass: 'rmItem',
+          opacity: 0.8,
+          helperclass: 'helper',
+          serializeRegExp:/.*/i,
+          autoScroll: true,
+          handle: '.rmSortHandle',
+          ghosting:false,
+          nestingPxSpace:5,
+
+          onChange: function(serialized)
+            {
+              $('#mdRulesArea li.rmSortable').each(
+                function ()
+                {
+                  checkSubRules(this.id);
+                }
+              );
+            },
+          onHover: function (draggedItem)
+            {
+              $('#mdRulesArea').scrollTop($('#sortHelper').position().top);
+            }
+        }
+      );
+    }
+
+    /**
+     * create a rule item and add it to the rulesArea
+     *
+     * the given object properties have the structure of a user_tags_def record
+     *  - itemId
+     *  - parentId
+     *  - numId
+     *  - type
+     *  - value
+     *  - ifType
+     *  - ifValue
+     *  - elseId
+     *  - order
+     *
+     * @param Object properties : an object with rules properties
+     */
+    this.addRule = function (properties)
+    {
+      addRule(properties);
+    }
+    var addRule = function (properties)
+    {
+      if(properties.defId==null)
+      {
+        properties={
+          defId:options.newRuleId++,
+          parentId:0,
+          numId:options.numId,
+          type:'T',
+          value:'',
+          conditionType:'E',
+          conditionValue:'',
+          order:-1
+        }
+      }
+
+      if(properties.parentId==0)
+      {
+        $('#iBDRules').append($('#iBDModel').html().split('ZZZZZ').join(properties.defId));
+      }
+      else
+      {
+        $('#iBDSubRulesNum'+properties.parentId).append($('#iBDModel').html().split('ZZZZZ').join(properties.defId));
+      }
+
+      $('#iBDRuleType'+properties.defId).val(properties.type).change();
+      switch(properties.type)
+      {
+        case 'T':
+          $('#iBDRuleTypeT'+properties.defId).val(properties.value);
+          break;
+        case 'M':
+          $('#iBDRuleTypeM'+properties.defId).attr('value', properties.value);
+          $('#iBDRuleTypeM'+properties.defId+' span.ruleContent').html($('#iTagListItem'+properties.value).html());
+          break;
+        case 'C':
+          $('#iBDRuleTypeCM'+properties.defId).attr('value', properties.value);
+          $('#iBDRuleTypeCM'+properties.defId+' span.ruleContent').html($('#iTagListItem'+properties.value).html());
+          $('#iBDRuleTypeCIf'+properties.defId).val(properties.conditionType).change();
+          $('#iBDRuleTypeCIfValue'+properties.defId).val(properties.conditionValue);
+          break;
+      }
+      applyNested();
+    }
+
+    /**
+     *
+     */
+    this.deleteRule = function (id)
+    {
+      $('#iBDRuleNum'+id).remove();
+      $('#mdRulesArea li.rmSortable').each(
+        function ()
+        {
+          checkSubRules(this.id);
+        }
+      );
+    }
+
+    /**
+     *
+     */
+    this.changeRuleType = function (id)
+    {
+      if($('#iBDRuleType'+id).val()=='T')
+      {
+        $('#iBDRuleNum'+id).addClass('rmItem');
+        $('#iBDRuleTypeT'+id).css('display', 'inline');
+        $('#iBDRuleTypeM'+id).css('display', 'none');
+        $('#iBDRuleTypeC'+id).css('display', 'none');
+      }
+      else if($('#iBDRuleType'+id).val()=='M')
+      {
+        $('#iBDRuleNum'+id).addClass('rmItem');
+        $('#iBDRuleTypeT'+id).css('display', 'none');
+        $('#iBDRuleTypeM'+id).css('display', 'inline-block');
+        $('#iBDRuleTypeC'+id).css('display', 'none');
+      }
+      else if($('#iBDRuleType'+id).val()=='C')
+      {
+        $('#iBDRuleNum'+id).removeClass('rmItem');
+        $('#iBDRuleTypeT'+id).css('display', 'none');
+        $('#iBDRuleTypeM'+id).css('display', 'none');
+        $('#iBDRuleTypeC'+id).css('display', 'inline-block');
+      }
+    }
+
+    /**
+     * display/hide the 'ifValue' property
+     */
+    this.changeRuleTypeCIf = function (id)
+    {
+      value=$('#iBDRuleTypeCIf'+id).val();
+      if(value=='E' || value =='!E')
+      {
+        $('#iBDRuleTypeCIfValue'+id).css('display', 'none');
+      }
+      else
+      {
+        $('#iBDRuleTypeCIfValue'+id).css('display', 'inline');
+      }
+    }
+
+    /**
+     * check if there is subrules affected to the item (conditionned by the 'condition' type)
+     * if subrules are present, disable the selector
+     */
+    var checkSubRules = function (parentId)
+    {
+      value=$('#'+parentId).attr('value');
+
+      if($('#iBDRuleType'+value).val()=='C' && $('#iBDSubRulesNum'+value+' li').length>0)
+      {
+        $('#iBDRuleType'+value).get(0).disabled=true;
+      }
+      else
+      {
+        $('#iBDRuleType'+value).get(0).disabled=false;
+      }
+    }
+
+    /**
+     * check for the validity of the metadata settings
+     */
+    var checkValidity = function ()
+    {
+      $('.error').removeClass('error');
+
+      ok=true;
+
+      if(checkTagIdValidity($('#iBDTagId').val())==false)
+      {
+        $('#iBDTagId').addClass('error');
+        alert('{/literal}{"g003_invalidId"|@translate}{literal}');
+        ok=false;
+      }
+
+      if($('#iBDRules li').length==0)
+      {
+        $('#iBDRules').addClass('error');
+        alert('{/literal}{"g003_oneRuleIsNeeded"|@translate}{literal}');
+        ok=false;
+      }
+      else
+      {
+        $('#iBDRules li').each(
+          function ()
+          {
+            value=$(this).attr('value');
+            switch($('#iBDRuleType'+value).val())
+            {
+              case 'T':
+                if($('#iBDRuleTypeT'+value).val()=='')
+                {
+                  $('#iBDRuleTypeT'+value).addClass('error');
+                  alert('{/literal}{"g003_textRuleInvalid"|@translate}{literal}');
+                  ok=false;
+                }
+                break;
+              case 'M':
+                if($('#iBDRuleTypeM'+value).attr('value')=='-')
+                {
+                  $('#iBDRuleTypeM'+value).addClass('error');
+                  alert('{/literal}{"g003_metadataRuleInvalid"|@translate}{literal}');
+                  ok=false;
+                }
+                break;
+              case 'C':
+                if($('#iBDRuleTypeCM'+value).attr('value')=='-')
+                {
+                  $('#iBDRuleTypeCM'+value).addClass('error');
+                  alert('{/literal}{"g003_conditionMdRuleInvalid"|@translate}{literal}');
+                  ok=false;
+                }
+
+                if($('#iBDSubRulesNum'+value+' li').length==0)
+                {
+                  $('#iBDSubRulesNum'+value).addClass('error');
+                  alert('{/literal}{"g003_conditionRulesRuleInvalid"|@translate}{literal}');
+                  ok=false;
+                }
+                break;
+            }
+          }
+        );
+      }
+      return(ok);
+    }
+
+    /**
+     * send metadata update to the server, and close the dialog box if everything
+     * is ok
+     */
+    var doUpdate = function ()
+    {
+      displayProcessing(true);
+
+      // build datas
+      properties = {
+        tagId:$('#iBDTagId').val(),
+        name:$('#iBDLabel').val(),
+        rules: [ ]
+      }
+
+      order=1;
+      $('#iBDRules li').each(
+        function ()
+        {
+          defId=$(this).attr('value');
+          type=$('#iBDRuleType'+defId).val();
+          switch(type)
+          {
+            case 'T':
+              value=$('#iBDRuleTypeT'+defId).val();
+              conditionType='';
+              conditionValue='';
+              break;
+            case 'M':
+              value=$('#iBDRuleTypeM'+defId).attr('value');
+              conditionType='';
+              conditionValue='';
+              break;
+            case 'C':
+              value=$('#iBDRuleTypeCM'+defId).attr('value');
+              conditionType=$('#iBDRuleTypeCIf'+defId).val();
+              conditionValue=$('#iBDRuleTypeCIfValue'+defId).val();
+              break;
+          }
+
+          properties.rules.push(
+            {
+              defId:defId,
+              parentId:$(this).parent().parent().attr('value'),
+              type:type,
+              value:value,
+              conditionType:conditionType,
+              conditionValue:conditionValue,
+              order:order
+            }
+          );
+
+          order++;
+        }
+      );
+
+      $.ajax(
+        {
+          type: "POST",
+          url: "{/literal}{$datas.urlRequest}{literal}",
+          async: true,
+          data: { ajaxfct:"admin.userDefined.setTag", id:options.numId, properties:properties },
+          success:
+            function(msg)
+            {
+              displayProcessing(false);
+
+              re=/^\d+,\d+$/;
+              if(re.exec(msg)!=null)
+              {
+                // result Ok ! => close the dialog box and reload the list
+                $('#iDialogEdit').dialog("close");
+                loadList();
+              }
+              else
+              {
+                returned=msg.split('!');
+                $('#'+returned[0]).addClass('error');
+                alert(returned[1]);
+              }
+            }
+        }
+      );
+    }
+
+    /**
+     * display or hide the processing flower
+     */
+    var displayProcessing = function (visible)
+    {
+      if(visible)
+      {
+        $('#iBDProcessing').css("display", "block");
+      }
+      else
+      {
+        $('#iBDProcessing').css("display", "none");
+      }
+    }
+
+    this.init();
+  }
+
+
+</script>
+{/literal}
+
+
+<h2>{'g003_personnal_metadata'|@translate}</h2>
+
+<div class='addMetadata'>
+  <a onclick="udm.editMetadata('');">{'g003_add_a_new_md'|@translate}</a>
+</div>
+
+<table id='iHeaderListTags' class="littlefont">
+  <tr>
+    <th style="width:35%;min-width:340px;">{'g003_TagId'|@translate}</th>
+    <th>{'g003_TagLabel'|@translate}</th>
+    <th style="width:15%;">{'g003_fill_database'|@translate}</th>
+    <th style="width:15%;">{'g003_num_of_rules'|@translate}</th>
+    <th width="40px">&nbsp;</th>
+  </tr>
+</table>
+<div id='iListTags' class="{$themeconf.name}">
+</div>
+<div id="iListTagsNb"></div>
+
+<div id="iDialogDelete">
+</div>
+
+<div id="iDialogEdit">
+  <div id='iBDProcessing' style="display:none;position:absolute;width:100%;height:100%;background:#000000;opacity:0.75">
+      <img src="plugins/GrumPluginClasses/icons/processing.gif" style="margin-top:100px;">
+  </div>
+
+  <form>
+    <table class='formtable'>
+      <tr>
+        <td>{'g003_metadatId'|@translate}</td>
+        <td>
+          <input type='text' id='iBDTagId' maxlength=200 size=60 value=''>
+          <input type='hidden' id='iBDNumId' value=''>
+        </td>
+      </tr>
+      <tr>
+        <td>{'g003_TagLabel'|@translate}</td>
+        <td>
+          <input type='text' id='iBDLabel' maxlength=200 size=60 value=''>
+          <!--<select id='iBDLang' disabled>
+            <option value='fr_FR'>Français</option>
+          </select>-->
+        </td>
+      </tr>
+      <tr>
+        <td>{'g003_rules'|@translate}</td>
+        <td>
+          <a onclick='udm.addRule({ldelim}{rdelim});'>{'g003_add_a_rule'|@translate}</a>
+        </td>
+      </tr>
+    </table>
+
+    <div id='mdRulesArea' value='0'>
+      <ul id='iBDRules'>
+      </ul>
+    </div>
+
+  </form>
+</div>
+
+
+<ul style='display:none' id='iBDModel'>
+  <li id='iBDRuleNumZZZZZ' class='groupItems gcBgPage rmSortable rmItem' value='ZZZZZ'>
+    <img onclick='udm.deleteRule("ZZZZZ");' src='{$themeconf.admin_icon_dir}/delete.png' class='button pointer' alt='{"g003_delete"|@translate}' title='{"g003_delete"|@translate}' style='float:right;'/>
+    <div class='rmContent'>
+
+      <div class='ruleSelector'>
+        <img src='{$themeconf.admin_icon_dir}/cat_move.png' class='rmSortHandle button drag_button' alt='{"Drag to re-order"|@translate}' title='{"Drag to re-order"|@translate}'/>
+
+
+        <select id='iBDRuleTypeZZZZZ' onchange='udm.changeRuleType("ZZZZZ");'>
+          <option value='T'>{'g003_typeText'|@translate}</option>
+          <option value='M'>{'g003_typeMetadata'|@translate}</option>
+          <option value='C'>{'g003_typeCondition'|@translate}</option>
+        </select>
+      </div>
+
+      <div class='ruleProperties'>
+        <input type='text' id='iBDRuleTypeTZZZZZ' value='' maxlength=200 size=60>
+
+        <div id='iBDRuleTypeMZZZZZ'
+             style='display:none;'
+             value='-'
+             class='ruleTypeM gcTextInput gcBgInput gcBorderInput pointer'
+             onclick='tls.display("iBDRuleTypeMZZZZZ");'>
+          <span class='ruleContent'><span class='tagName'>&nbsp;</span></span>
+          <span style='float:right' class='gcText3'>&dArr;</span>
+        </div>
+
+        <div id='iBDRuleTypeCZZZZZ' style='display:none;'>
+          <table>
+            <tr>
+              <td style='vertical-align:top;'>{'g003_conditionIf'|@translate}</td>
+              <td>
+                <div id='iBDRuleTypeCMZZZZZ'
+                     value='-'
+                     style='display:inline-block'
+                     class='ruleTypeM2 gcTextInput gcBgInput gcBorderInput pointer'
+                     onclick='tls.display("iBDRuleTypeCMZZZZZ");'>
+                  <span class='ruleContent'>
+                    <span class='tagName'>&nbsp;</span>
+                  </span>
+                  <span style='float:right' class='gcText3'>&dArr;</span>
+                </div>
+                <br>
+                <div style='display:inline-block;margin-top:2px;'>
+                  <select id='iBDRuleTypeCIfZZZZZ' onchange='udm.changeRuleTypeCIf("ZZZZZ");'>
+                    <option value='E'>{'g003_typeCIfExist'|@translate}</option>
+                    <option value='!E'>{'g003_typeCIfNotExist'|@translate}</option>
+                    <option value='='>{'g003_typeCIfEqual'|@translate}</option>
+                    <option value='!='>{'g003_typeCIfNotEqual'|@translate}</option>
+                    <option value='%'>{'g003_typeCIfLike'|@translate}</option>
+                    <option value='!%'>{'g003_typeCIfNotLike'|@translate}</option>
+                  </select>
+                  <input type='text' id='iBDRuleTypeCIfValueZZZZZ' value='' maxlength=200 size=26 style='display:none;'>
+                </div>
+              </td>
+            </tr>
+          </table>
+        </div>
+
+      </div>
+    </div>
+
+    <ul class='subRules' id='iBDSubRulesNumZZZZZ'></ul>
+  </li>
+</ul>
+
+<ul style='display:none' id='iTagList' class="{$themeconf.name}">
+  {foreach from=$datas.tagList item=tag}
+    <li id='iTagListItem{$tag.numId}' value='{$tag.numId}'><span class='tagName'>{$tag.tagId}</span><span>{$tag.name}</span></li>
+  {/foreach}
+</ul>
+
+<script type="text/javascript">
+  var udm=new userDefManage();
+  var tls=new tagListSelector('iTagList');
+</script>
Index: /extensions/AMetaData/admin/amd_metadata_personnal_iListTags.tpl
===================================================================
--- /extensions/AMetaData/admin/amd_metadata_personnal_iListTags.tpl	(revision 6731)
+++ /extensions/AMetaData/admin/amd_metadata_personnal_iListTags.tpl	(revision 6731)
@@ -0,0 +1,21 @@
+<table class="littlefont">
+  {foreach from=$datas item=data}
+  <tr>
+    <td style="width:35%;min-width:340px;">{$data.tagId}</td>
+    <td>{$data.label}</td>
+    <th style="width:15%;">{$data.fillDatabase}</th>
+    <th style="width:15%;">{$data.numOfRules}</th>
+    <td width="40px">
+      <img src="{$themeconf.admin_icon_dir}/edit_s.png"
+           class="button" alt="{'g003_edit'|@translate}"
+           title="{'g003_edit'|@translate}"
+           onclick='udm.editMetadata({$data.numId});'/>
+      <img src="{$themeconf.admin_icon_dir}/delete.png"
+           class="button"
+           alt="{'g003_delete'|@translate}"
+           title="{'g003_delete'|@translate}"
+           onclick='udm.deleteMetadata({$data.numId});'/>
+    </td>
+  </tr>
+  {/foreach}
+</table>
Index: /extensions/AMetaData/templates/doAnalyze.tpl
===================================================================
--- /extensions/AMetaData/templates/doAnalyze.tpl	(revision 6731)
+++ /extensions/AMetaData/templates/doAnalyze.tpl	(revision 6731)
@@ -0,0 +1,12 @@
+{literal}
+<script type='text/javascript'>
+  $.ajax(
+    {
+      type: "POST",
+      url: "{/literal}{$datas.urlRequest}{literal}",
+      async: true,
+      data: { ajaxfct:"public.makeStats.doPictureAnalyze", id:{/literal}{$datas.id}{literal} }
+    }
+  );
+</script>
+{/literal}
Index: /extensions/AMetaData/templates/index.php
===================================================================
--- /extensions/AMetaData/templates/index.php	(revision 6731)
+++ /extensions/AMetaData/templates/index.php	(revision 6731)
@@ -0,0 +1,33 @@
+<?php
+// +-----------------------------------------------------------------------+
+// | PhpWebGallery - a PHP based picture gallery                           |
+// | Copyright (C) 2002-2003 Pierrick LE GALL - pierrick@phpwebgallery.net |
+// | Copyright (C) 2003-2007 PhpWebGallery Team - http://phpwebgallery.net |
+// +-----------------------------------------------------------------------+
+// | file          : $Id: index.php 1912 2007-03-16 06:30:07Z rub $
+// | last update   : $Date: 2007-03-16 07:30:07 +0100 (ven, 16 mar 2007) $
+// | last modifier : $Author: rub $
+// | revision      : $Revision: 1912 $
+// +-----------------------------------------------------------------------+
+// | 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();
+?>
