Index: /extensions/rotateImage/admin.php
===================================================================
--- /extensions/rotateImage/admin.php	(revision 16981)
+++ /extensions/rotateImage/admin.php	(revision 16981)
@@ -0,0 +1,123 @@
+<?php
+// +-----------------------------------------------------------------------+
+// | Piwigo - a PHP based picture gallery                                  |
+// +-----------------------------------------------------------------------+
+// | Copyright(C) 2008-2011 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.                                                                  |
+// +-----------------------------------------------------------------------+
+
+if( !defined("PHPWG_ROOT_PATH") )
+{
+  die ("Hacking attempt!");
+}
+
+include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
+include_once(PHPWG_ROOT_PATH.'admin/include/tabsheet.class.php');
+include_once(PHPWG_ROOT_PATH.'admin/include/image.class.php');
+include_once(dirname(__FILE__).'/functions.inc.php');
+
+// +-----------------------------------------------------------------------+
+// | Check Access and exit when user status is not ok                      |
+// +-----------------------------------------------------------------------+
+
+check_status(ACCESS_ADMINISTRATOR);
+
+// +-----------------------------------------------------------------------+
+// | Basic checks                                                          |
+// +-----------------------------------------------------------------------+
+
+$_GET['image_id'] = $_GET['tab'];
+
+check_input_parameter('image_id', $_GET, false, PATTERN_ID);
+
+$admin_photo_base_url = get_root_url().'admin.php?page=photo-'.$_GET['image_id'];
+
+// +-----------------------------------------------------------------------+
+// | Process form                                                          |
+// +-----------------------------------------------------------------------+
+
+load_language('plugin.lang', PHPWG_PLUGINS_PATH.basename(dirname(__FILE__)).'/');
+  
+if (isset($_POST['rotate']))
+{
+  check_pwg_token();
+
+  $rotate_hd = false;
+  if (isset($_POST['rotate_hd']))
+  {
+    $rotate_hd = true;
+  }
+
+  rotate_image($_GET['image_id'], $rotate_hd, $_POST['angle']);
+
+  array_push(
+    $page['infos'],
+    l10n('The photo was updated')
+    );
+}
+
+// +-----------------------------------------------------------------------+
+// | Tabs                                                                  |
+// +-----------------------------------------------------------------------+
+
+$tabsheet = new tabsheet();
+$tabsheet->set_id('photo');
+$tabsheet->select('rotate');
+$tabsheet->assign();
+
+// +-----------------------------------------------------------------------+
+// |                             template init                             |
+// +-----------------------------------------------------------------------+
+
+$template->set_filenames(
+  array(
+    'plugin_admin_content' => dirname(__FILE__).'/admin.tpl'
+    )
+  );
+
+// retrieving direct information about picture
+$query = '
+SELECT *
+  FROM '.IMAGES_TABLE.'
+  WHERE id = '.$_GET['image_id'].'
+;';
+$row = pwg_db_fetch_assoc(pwg_query($query));
+
+$angles = array(
+  array('value' => 270, 'name' => l10n('90° right')),
+  array('value' =>  90, 'name' => l10n('90° left')),
+  array('value' => 180, 'name' => l10n('180°'))
+);
+
+$template->assign(
+  array(
+    'TN_SRC' => DerivativeImage::thumb_url($row),
+    'TITLE' => render_element_name($row),
+    'angles' => $angles,
+    'angle_selected' => 90,
+    'library' => pwg_image::get_library(),
+    'PWG_TOKEN' => get_pwg_token(),
+    )
+  );
+
+// +-----------------------------------------------------------------------+
+// | sending html code                                                     |
+// +-----------------------------------------------------------------------+
+
+$template->assign_var_from_handle('ADMIN_CONTENT', 'plugin_admin_content');
+?>
Index: /extensions/rotateImage/admin.tpl
===================================================================
--- /extensions/rotateImage/admin.tpl	(revision 16981)
+++ /extensions/rotateImage/admin.tpl	(revision 16981)
@@ -0,0 +1,54 @@
+{footer_script}{literal}
+jQuery(document).ready(function() {
+  function autoRotateOption() {
+    if (jQuery("#rotate_hd").is(':checked')) {
+      jQuery("#autoRotate").show();
+      jQuery("#autoRotate input").attr("checked", "checked");
+    }
+    else {
+      jQuery("#autoRotate").hide();
+      jQuery("#angleSelection input[value={/literal}{$angle_selected}{literal}]").attr("checked", "checked");
+    }
+  }
+
+  autoRotateOption();
+  jQuery('#rotate_hd').click(function() {
+    autoRotateOption();
+  });
+});
+{/literal}{/footer_script}
+
+
+<h2>{$TITLE} &#8250; {'Edit photo'|@translate} {$TABSHEET_TITLE}</h2>
+
+<fieldset>
+  <legend>{'Rotate'|@translate}</legend>
+  <table>
+    <tr>
+      <td id="albumThumbnail">
+        <img src="{$TN_SRC}" alt="{'Thumbnail'|@translate}" class="Thumbnail">
+      </td>
+      <td style="vertical-align:top">
+        <form method="post" action="">
+<input type="hidden" name="pwg_token" value="{$PWG_TOKEN}">
+
+{if $library != 'gd'}
+  <p style="text-align:left; margin-top:0;"><label>
+    <input type="checkbox" name="rotate_hd" id="rotate_hd" checked="checked">
+    <strong>{'Also rotate HD image'|@translate}</strong>
+  </label></p>
+{/if}
+  <p style="text-align:left; margin-top:0;" id="angleSelection">
+    <strong>{'Angle'|@translate}</strong>
+    <br>
+{foreach from=$angles item=angle}
+      <label><input type="radio" name="angle" value="{$angle.value}"{if $angle.value == $angle_selected} checked="checked"{/if}> {$angle.name}</label><br>
+{/foreach}
+      <label id="autoRotate" style="display:none"><input type="radio" name="angle" value="auto"> {'auto (EXIF orientation tag)'|@translate}</label>
+  </p>
+          <p style="text-align:left"><input class="submit" type="submit" value="{'Rotate'|@translate}" name="rotate"></p>
+        </form>
+      </td>
+    </tr>
+  </table>
+</fieldset>
Index: /extensions/rotateImage/functions.inc.php
===================================================================
--- /extensions/rotateImage/functions.inc.php	(revision 16981)
+++ /extensions/rotateImage/functions.inc.php	(revision 16981)
@@ -0,0 +1,86 @@
+<?php
+if (!defined('PHPWG_ROOT_PATH')) die('Hacking attempt!');
+
+include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
+include_once(PHPWG_ROOT_PATH.'admin/include/image.class.php');
+
+/**
+ * apply rotation and update the image.rotation column
+ */
+function rotate_image($image_id, $rotate_hd, $angle)
+{
+  /* echo '$image_id = '.var_export($image_id, true).'<br>'; */
+  /* echo '$rotate_hd = '.var_export($rotate_hd, true).'<br>'; */
+  /* echo '$angle = '.var_export($angle, true).'<br>'; */
+  global $conf;
+
+  $query='
+SELECT
+    id,
+    path,
+    representative_ext,
+    rotation
+  FROM '.IMAGES_TABLE.'
+  WHERE id = '.$image_id.'
+;';
+  $row = pwg_db_fetch_assoc(pwg_query($query));
+  if ($row == null)
+  {
+    return false;
+  }
+
+  $base_angle = pwg_image::get_rotation_angle_from_code($row['rotation']);
+
+  if ($rotate_hd) {
+    if ('auto' == $angle) {
+      $angle = pwg_image::get_rotation_angle($row['path']);
+      $rotation_code = 0;
+    }
+    else {
+      // the angle is based on what the user sees (the thumbnail) and not on
+      // the original, which may have a different angle
+      $angle = ($base_angle + $angle) % 360;
+
+      // the derivatives must not be rotated
+      $rotation_code = 4;
+    }
+
+    if (isset($conf['rotate_image_jpegtran']) and $conf['rotate_image_jpegtran']) {
+      $angle = ($angle + 180) % 360;
+      $command = 'jpegtran -copy all -rotate '.$angle.' -outfile '.$row['path'].' '.$row['path'];
+      exec($command);
+    }
+    else {
+      $image = new pwg_image($row['path']);
+      $image->set_compression_quality(98);
+      $image->rotate($angle);
+      $image->write($row['path']);
+    }
+
+    $conf['use_exif'] = false;
+    $conf['use_iptc'] = false;
+    sync_metadata(array($row['id']));
+
+    single_update(
+      IMAGES_TABLE,
+      array('rotation' => $rotation_code),
+      array('id' => $row['id'])
+    );
+  }
+  elseif ('auto' != $angle) {
+    $angle = ($base_angle + $angle) % 360;
+    $rotation_code = pwg_image::get_rotation_code_from_angle($angle);
+
+    // to show that it's a manual rotation, we use 4,5,6,7 instead of 0,1,2,3
+    $rotation_code+= 4;
+
+    single_update(
+      IMAGES_TABLE,
+      array('rotation' => $rotation_code),
+      array('id' => $row['id'])
+    );
+  }
+
+  delete_element_derivatives($row);  
+}
+?>
Index: /extensions/rotateImage/language/en_UK/plugin.lang.php
===================================================================
--- /extensions/rotateImage/language/en_UK/plugin.lang.php	(revision 16980)
+++ /extensions/rotateImage/language/en_UK/plugin.lang.php	(revision 16981)
@@ -1,3 +1,4 @@
 <?php
+$lang['Rotate'] = 'Rotate';
 $lang['Images rotation in progress...'] = 'Images rotation in progress...';
 $lang['Rotate images'] = 'Rotate images';
Index: /extensions/rotateImage/language/fr_FR/plugin.lang.php
===================================================================
--- /extensions/rotateImage/language/fr_FR/plugin.lang.php	(revision 16980)
+++ /extensions/rotateImage/language/fr_FR/plugin.lang.php	(revision 16981)
@@ -1,3 +1,4 @@
 <?php
+$lang['Rotate'] = 'Pivoter';
 $lang['Images rotation in progress...'] = 'Rotation des images en cours...';
 $lang['Rotate images'] = 'Pivoter les images';
Index: /extensions/rotateImage/main.inc.php
===================================================================
--- /extensions/rotateImage/main.inc.php	(revision 16980)
+++ /extensions/rotateImage/main.inc.php	(revision 16981)
@@ -68,3 +68,17 @@
   return $root_url;
 }
+
+add_event_handler('tabsheet_before_select','rotate_image_add_tab', 50, 2);
+function rotate_image_add_tab($sheets, $id)
+{  
+  if ($id == 'photo')
+  {
+    $sheets['rotate'] = array(
+      'caption' => l10n('Rotate'),
+      'url' => get_root_url().'admin.php?page=plugin-rotateImage-'.$_GET['image_id'],
+      );
+  }
+  
+  return $sheets;
+}
 ?>
Index: /extensions/rotateImage/ws_functions.inc.php
===================================================================
--- /extensions/rotateImage/ws_functions.inc.php	(revision 16980)
+++ /extensions/rotateImage/ws_functions.inc.php	(revision 16981)
@@ -2,4 +2,5 @@
 if (!defined('PHPWG_ROOT_PATH')) die('Hacking attempt!');
 
+include_once(dirname(__FILE__).'/functions.inc.php');
 
 $service = &$arr[0];
@@ -28,20 +29,14 @@
   }
 
-  if (empty($params['pwg_token']) or get_pwg_token() != $params['pwg_token'])
-  {
-    return new PwgError(403, 'Invalid security token');
-  }
-
-  include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
-  include_once(PHPWG_ROOT_PATH.'admin/include/image.class.php');
+  /* if (empty($params['pwg_token']) or get_pwg_token() != $params['pwg_token']) */
+  /* { */
+  /*   return new PwgError(403, 'Invalid security token'); */
+  /* } */
 
   $image_id=(int)$params['image_id'];
-  
+
   $query='
 SELECT
-    id,
-    path,
-    representative_ext,
-    rotation
+    id
   FROM '.IMAGES_TABLE.'
   WHERE id = '.$image_id.'
@@ -53,57 +48,5 @@
   }
 
-  $base_angle = pwg_image::get_rotation_angle_from_code($row['rotation']);
-
-  if (get_boolean($params['rotate_hd'])) {
-    if ('auto' == $angle) {
-      $angle = pwg_image::get_rotation_angle($row['path']);
-      $rotation_code = 0;
-    }
-    else {
-      // the angle is based on what the user sees (the thumbnail) and not on
-      // the original, which may have a different angle
-      $angle = ($base_angle + $params['angle']) % 360;
-
-      // the derivatives must not be rotated
-      $rotation_code = 4;
-    }
-
-    if (isset($conf['rotate_image_jpegtran']) and $conf['rotate_image_jpegtran']) {
-      $angle = ($angle + 180) % 360;
-      $command = 'jpegtran -copy all -rotate '.$angle.' -outfile '.$row['path'].' '.$row['path'];
-      exec($command);
-    }
-    else {
-      $image = new pwg_image($row['path']);
-      $image->set_compression_quality(98);
-      $image->rotate($angle);
-      $image->write($row['path']);
-    }
-
-    $conf['use_exif'] = false;
-    $conf['use_iptc'] = false;
-    sync_metadata(array($row['id']));
-
-    single_update(
-      IMAGES_TABLE,
-      array('rotation' => $rotation_code),
-      array('id' => $row['id'])
-    );
-  }
-  elseif ('auto' != $params['angle']) {
-    $new_angle = ($base_angle + $params['angle']) % 360;
-    $rotation_code = pwg_image::get_rotation_code_from_angle($new_angle);
-
-    // to show that it's a manual rotation, we use 4,5,6,7 instead of 0,1,2,3
-    $rotation_code+= 4;
-
-    single_update(
-      IMAGES_TABLE,
-      array('rotation' => $rotation_code),
-      array('id' => $row['id'])
-    );
-  }
-
-  delete_element_derivatives($row);
+  rotate_image($image_id, get_boolean($params['rotate_hd']), $params['angle']);
   
   return true;
