Index: /extensions/write_metadata/element_set_global_action.tpl
===================================================================
--- /extensions/write_metadata/element_set_global_action.tpl	(revision 28872)
+++ /extensions/write_metadata/element_set_global_action.tpl	(revision 28872)
@@ -0,0 +1,90 @@
+{footer_script}
+var writeMetadataProgressMessage = "{'Write metadata in progress...'|translate}";
+var wm_pwg_token = '{$WM_PWG_TOKEN}';
+{literal}
+jQuery(document).ready(function() {
+  jQuery('#applyAction').click(function(e) {
+    if (typeof(elements) != "undefined") {
+      return true;
+    }
+
+    if (jQuery('[name="selectAction"]').val() == 'writeMetadata')
+    {
+      e.stopPropagation();
+    }
+    else
+    {
+      return true;
+    }
+
+    jQuery('.bulkAction').hide();
+    jQuery('#regenerationText').html(writeMetadataProgressMessage);
+    var maxRequests=1;
+
+    var queuedManager = jQuery.manageAjax.create('queued', { 
+      queue: true,  
+      cacheResponse: false,
+      maxRequests: maxRequests
+    });
+
+    elements = Array();
+
+    if (jQuery('input[name=setSelected]').is(':checked')) {
+      elements = all_elements;
+    }
+    else {
+      jQuery('input[name="selection[]"]').filter(':checked').each(function() {
+        elements.push(jQuery(this).val());
+      });
+    }
+
+    progressBar_max = elements.length;
+    todo = 0;
+
+    jQuery('#applyActionBlock').hide();
+    jQuery('select[name="selectAction"]').hide();
+    jQuery('#regenerationMsg').show();
+    jQuery('#progressBar').progressBar(0, {
+      max: progressBar_max,
+      textFormat: 'fraction',
+      boxImage: 'themes/default/images/progressbar.gif',
+      barImage: 'themes/default/images/progressbg_orange.gif'
+    });
+
+    for (i=0;i<elements.length;i++) {
+      queuedManager.add({
+        type: 'POST', 
+        url: 'ws.php?format=json', 
+        data: {
+          method: "pwg.images.writeMetadata",
+          pwg_token: wm_pwg_token,
+          image_id: elements[i]
+        },
+        dataType: 'json',
+        success: ( function(data) { progressWriteMetadata(++todo, progressBar_max, data['result']) }),
+        error: ( function(data) { progressWriteMetadata(++todo, progressBar_max, false) })
+      });
+    }
+    return false;
+  });
+
+  function progressWriteMetadata(val, max, success) {
+    jQuery('#progressBar').progressBar(val, {
+      max: max,
+      textFormat: 'fraction',
+      boxImage: 'themes/default/images/progressbar.gif',
+      barImage: 'themes/default/images/progressbg_orange.gif'
+    });
+    type = success ? 'regenerateSuccess': 'regenerateError'
+    s = jQuery('[name="'+type+'"]').val();
+    jQuery('[name="'+type+'"]').val(++s);
+
+    if (val == max)
+      jQuery('#applyAction').click();
+  }
+
+});
+{/literal}{/footer_script}
+
+<div id="write_metadata" class="bulkAction">
+</div>
Index: /extensions/write_metadata/index.php
===================================================================
--- /extensions/write_metadata/index.php	(revision 28872)
+++ /extensions/write_metadata/index.php	(revision 28872)
@@ -0,0 +1,30 @@
+<?php
+// +-----------------------------------------------------------------------+
+// | Piwigo - a PHP based picture gallery                                  |
+// +-----------------------------------------------------------------------+
+// | Copyright(C) 2008      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/write_metadata/language/en_UK/description.txt
===================================================================
--- /extensions/write_metadata/language/en_UK/description.txt	(revision 28872)
+++ /extensions/write_metadata/language/en_UK/description.txt	(revision 28872)
@@ -0,0 +1,1 @@
+Write Piwigo photo properties (title, description, author, tags) into IPTC fields
Index: /extensions/write_metadata/language/en_UK/index.php
===================================================================
--- /extensions/write_metadata/language/en_UK/index.php	(revision 28872)
+++ /extensions/write_metadata/language/en_UK/index.php	(revision 28872)
@@ -0,0 +1,30 @@
+<?php
+// +-----------------------------------------------------------------------+
+// | Piwigo - a PHP based picture gallery                                  |
+// +-----------------------------------------------------------------------+
+// | Copyright(C) 2008      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/write_metadata/language/en_UK/plugin.lang.php
===================================================================
--- /extensions/write_metadata/language/en_UK/plugin.lang.php	(revision 28872)
+++ /extensions/write_metadata/language/en_UK/plugin.lang.php	(revision 28872)
@@ -0,0 +1,5 @@
+<?php
+$lang['Write metadata'] = 'Write metadata';
+$lang['Write metadata in progress...'] = 'Write metadata in progress...';
+$lang['Metadata written into file'] = 'Metadata written into file(s)';
+?>
Index: /extensions/write_metadata/language/fr_FR/description.txt
===================================================================
--- /extensions/write_metadata/language/fr_FR/description.txt	(revision 28872)
+++ /extensions/write_metadata/language/fr_FR/description.txt	(revision 28872)
@@ -0,0 +1,1 @@
+Ecrire les propriétés Piwigo des photos (titre, description, auteur, tags) dans les métadonnées IPTC
Index: /extensions/write_metadata/language/fr_FR/index.php
===================================================================
--- /extensions/write_metadata/language/fr_FR/index.php	(revision 28872)
+++ /extensions/write_metadata/language/fr_FR/index.php	(revision 28872)
@@ -0,0 +1,30 @@
+<?php
+// +-----------------------------------------------------------------------+
+// | Piwigo - a PHP based picture gallery                                  |
+// +-----------------------------------------------------------------------+
+// | Copyright(C) 2008      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/write_metadata/language/fr_FR/plugin.lang.php
===================================================================
--- /extensions/write_metadata/language/fr_FR/plugin.lang.php	(revision 28872)
+++ /extensions/write_metadata/language/fr_FR/plugin.lang.php	(revision 28872)
@@ -0,0 +1,5 @@
+<?php
+$lang['Write metadata'] = 'Écrire les métadonnées';
+$lang['Write metadata in progress...'] = 'Écriture des métadonnées en cours...';
+$lang['Metadata written into file'] = 'Métadonnées écrites dans le(s) fichier(s)';
+?>
Index: /extensions/write_metadata/language/index.php
===================================================================
--- /extensions/write_metadata/language/index.php	(revision 28872)
+++ /extensions/write_metadata/language/index.php	(revision 28872)
@@ -0,0 +1,30 @@
+<?php
+// +-----------------------------------------------------------------------+
+// | Piwigo - a PHP based picture gallery                                  |
+// +-----------------------------------------------------------------------+
+// | Copyright(C) 2008      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/write_metadata/main.inc.php
===================================================================
--- /extensions/write_metadata/main.inc.php	(revision 28872)
+++ /extensions/write_metadata/main.inc.php	(revision 28872)
@@ -0,0 +1,231 @@
+<?php
+/*
+Plugin Name: Write Metadata
+Description: Write Piwigo photo properties (title, description, author, tags) into IPTC fields
+Author: plg
+Plugin URI: http://piwigo.org/ext/extension_view.php?eid=
+Version: auto
+*/
+
+// +-----------------------------------------------------------------------+
+// | Define plugin constants                                               |
+// +-----------------------------------------------------------------------+
+
+defined('WRITE_METADATA_ID') or define('WRITE_METADATA_ID', basename(dirname(__FILE__)));
+define('WRITE_METADATA_PATH' , PHPWG_PLUGINS_PATH.basename(dirname(__FILE__)).'/');
+
+// +-----------------------------------------------------------------------+
+// | Edit Photo                                                            |
+// +-----------------------------------------------------------------------+
+
+add_event_handler('loc_begin_admin_page', 'wm_add_link', 60);
+function wm_add_link()
+{
+	global $template, $page;
+
+	$template->set_prefilter('picture_modify', 'wm_add_link_prefilter');
+
+  if (isset($page['page']) and 'photo' == $page['page'])
+  {
+    $template->assign(
+      'U_WRITEMETADATA',
+      get_root_url().'admin.php?page=photo-'.$_GET['image_id'].'-properties&amp;write_metadata=1'
+      );
+  }
+}
+
+function wm_add_link_prefilter($content, &$smarty)
+{
+  $search = '{if !url_is_remote($PATH)}';
+  
+  $replacement = '{if !url_is_remote($PATH)}
+<li><a class="icon-arrows-cw" href="{$U_WRITEMETADATA}">{\'Write metadata\'|@translate}</a></li>';
+
+  return str_replace($search, $replacement, $content);
+}
+
+add_event_handler('loc_begin_admin_page', 'wm_picture_write_metadata');
+function wm_picture_write_metadata()
+{
+  global $page, $conf;
+
+  load_language('plugin.lang', dirname(__FILE__).'/');
+  
+  if (isset($page['page']) and 'photo' == $page['page'] and isset($_GET['write_metadata']))
+  {
+    check_input_parameter('image_id', $_GET, false, PATTERN_ID);
+    wm_write_metadata($_GET['image_id']);
+
+    $_SESSION['page_infos'][] = l10n('Metadata written into file');
+    redirect(get_root_url().'admin.php?page=photo-'.$_GET['image_id'].'-properties');
+  }
+}
+
+// +-----------------------------------------------------------------------+
+// | Batch Manager                                                         |
+// +-----------------------------------------------------------------------+
+
+add_event_handler('loc_begin_element_set_global', 'wm_element_set_global_add_action');
+function wm_element_set_global_add_action()
+{
+  global $template, $page;
+  
+  $template->set_filename('writeMetadata', realpath(WRITE_METADATA_PATH.'element_set_global_action.tpl'));
+
+  if (isset($_POST['submit']) and $_POST['selectAction'] == 'writeMetadata')
+  {
+    $page['infos'][] = l10n('Metadata written into file');
+  }
+
+  $template->assign(
+    array(
+      'WM_PWG_TOKEN' => get_pwg_token(),
+      )
+    );
+
+  $template->append(
+    'element_set_global_plugins_actions',
+    array(
+      'ID' => 'writeMetadata',
+      'NAME' => l10n('Write metadata'),
+      'CONTENT' => $template->parse('writeMetadata', true),
+      )
+    );
+}
+
+add_event_handler('ws_add_methods', 'wm_add_methods');
+function wm_add_methods($arr)
+{
+  include_once(WRITE_METADATA_PATH.'ws_functions.inc.php');
+}
+
+// +-----------------------------------------------------------------------+
+// | Common functions                                                      |
+// +-----------------------------------------------------------------------+
+
+/**
+ * inspired by convert_row_to_file_exiftool method in ExportImageMetadata
+ * class from plugin Tags2File. In plugin write_medata we just skip the
+ * batch command file, and execute directly on server (much more user
+ * friendly...).
+ */
+function wm_write_metadata($image_id)
+{
+  global $conf;
+  
+  $query = '
+SELECT
+    img.name,
+    img.comment,
+    img.author,
+    img.date_creation,
+    GROUP_CONCAT(tags.name) AS tags,
+    img.path
+  FROM '.IMAGES_TABLE.' AS img
+    LEFT OUTER JOIN '.IMAGE_TAG_TABLE.' AS img_tag ON img_tag.image_id = img.id
+    LEFT OUTER JOIN '.TAGS_TABLE.' AS tags ON tags.id = img_tag.tag_id
+  WHERE img.id = '.$image_id.'
+  GROUP BY img.id, img.name, img.comment, img.author, img.path
+;';
+  $result = pwg_query($query);
+  $row = pwg_db_fetch_assoc($result);
+
+  $name = wm_prepare_string($row['name'], 256);
+  $description = wm_prepare_string($row['comment'], 2000);
+  $author = wm_prepare_string($row['author'], 32);
+  $tags = wm_prepare_string($row['tags'], 64);
+
+  $command = isset($conf['exiftool_path']) ? $conf['exiftool_path'] : 'exiftool';
+
+  if (strlen($name) > 0)
+  {
+    # 2#105 in iptcparse($imginfo['APP13'])
+    $command.= ' -IPTC:Headline="'.$name.'"';
+
+    # 2#005 in iptcparse($imginfo['APP13'])
+    $command.= ' -IPTC:ObjectName="'.wm_cutString($name, 64).'"';
+  }
+
+  if (strlen($description) > 0)
+  {
+    # 2#120 in iptcparse($imginfo['APP13'])
+    $command.= ' -IPTC:Caption-Abstract="'.$description.'"';
+  }
+
+  if (strlen($author) > 0)
+  {
+    # 2#080 in iptcparse($imginfo['APP13'])
+    $iptc_field = 'By-line';
+
+    if (
+      $conf['use_iptc']
+      and isset($conf['use_iptc_mapping']['author'])
+      and '2#122' == $conf['use_iptc_mapping']['author']
+      )
+    {
+      # 2#122 in iptcparse($imginfo['APP13'])
+      $iptc_field = 'Writer-Editor';
+    }
+
+    $command.= ' -IPTC:'.$iptc_field.'="'.$author.'"';
+  }
+  
+  if (strlen($tags) > 0)
+  {
+    # 2#025 in iptcparse($imginfo['APP13'])
+    $command.= ' -IPTC:Keywords="'.$tags.'"';
+  }
+
+  $command.= ' "'.$row['path'].'"';
+  // echo $command;
+
+  $exec_return = exec($command, $output);
+  // echo '$exec_return = '.$exec_return.'<br>';
+  // echo '<pre>'; print_r($output); echo '</pre>';
+
+  return true;
+}
+
+function wm_prepare_string($string, $maxLen)
+{
+  return wm_cutString(
+    wm_explode_description(
+      wm_decode_html_string_to_unicode($string)
+      ),
+    $maxLen
+    );
+}
+
+function wm_cutString($description, $maxLen)
+{
+  if (strlen($description) > $maxLen)
+  {
+    $description = substr($description, 0, $maxLen);
+  }
+  return $description;
+}
+
+function wm_explode_description($description)
+{
+  return str_replace(
+    array('<br>', '<br />', "\n", "\r"),
+    array('', '', '', ''),
+    $description
+    );
+}
+
+function wm_decode_html_string_to_unicode($string)
+{
+  if (isset($string) and strlen($string) > 0)
+  {
+    $string = html_entity_decode(trim($string), ENT_QUOTES, 'UTF-8');
+    $string = stripslashes($string);
+  }
+  else
+  {
+    $string = '';
+  }
+  
+  return($string);
+}
+?>
Index: /extensions/write_metadata/ws_functions.inc.php
===================================================================
--- /extensions/write_metadata/ws_functions.inc.php	(revision 28872)
+++ /extensions/write_metadata/ws_functions.inc.php	(revision 28872)
@@ -0,0 +1,34 @@
+<?php
+if (!defined('PHPWG_ROOT_PATH')) die('Hacking attempt!');
+
+$service = &$arr[0];
+$service->addMethod(
+  'pwg.images.writeMetadata',
+  'ws_images_writeMetadata',
+  array(
+    'image_id' => array('type'=>WS_TYPE_ID),
+    'pwg_token' => array(),
+    ),
+  'Write metadata (IPTC) based on photo properties in Piwigo',
+  null,
+  array(
+    'admin_only' => true,
+    'post_only' => true
+    )
+);
+
+function ws_images_writeMetadata($params, &$service)
+{
+  global $conf;
+  
+  if (get_pwg_token() != $params['pwg_token'])
+  {
+    return new PwgError(403, 'Invalid security token');
+  }
+  
+  wm_write_metadata($params['image_id']);
+  
+  return true;
+}
+
+?>
