Index: /extensions/Ajax_Thumbnailer/ajaxThumbnailer.tpl
===================================================================
--- /extensions/Ajax_Thumbnailer/ajaxThumbnailer.tpl	(revision 10441)
+++ /extensions/Ajax_Thumbnailer/ajaxThumbnailer.tpl	(revision 10441)
@@ -0,0 +1,141 @@
+{combine_script id='jquery.ajaxmanager' load='footer' path='themes/default/js/plugins/jquery.ajaxmanager.js'}
+
+{footer_script}{literal}
+var queuedManager = $.manageAjax.create('queued', { 
+	queue: true,  
+	cacheResponse: false,
+	maxRequests: 3
+}); 
+
+function processThumbs(width,height,gd_version) {
+  var square=$('input[name="square"]').attr('checked');
+  var done=0;
+	$('tr.nothumb').each(function() {
+		var file=$(this).find('td.filepath').text();
+		$(this).find('td.thumbpic').html('<img src="plugins/Ajax_Thumbnailer/ajax-loader.gif">');
+		var td=this;
+		queuedManager.add({
+			type: 'GET', 
+			url: 'ws.php', 
+			data: {method: 'pwg.images.createThumbnail',picture:file,format:'json',width: width,height: height, gd_version: gd_version, square: square},
+			dataType: 'json',
+			success: (function(row) { return function(data) {
+					if (data.stat =='ok') {
+							$(row).find('td.thumbpic').html('<img src="'+data.result.tn_file+'"/>');
+							$(row).find('td.thumbdim').html(""+data.result.tn_width+"X"+data.result.tn_height);
+							$(row).find('td.thumbgentime').html(""+data.result.tn_time);
+							$(row).find('td.thumbsize').html(""+data.result.tn_size);
+							$(row).removeClass("nothumb");
+						} else {
+							$(row).find('td.thumbpic').html('#ERR#'+data.err+"# : "+data.message);
+							$(row).removeClass("nothumb");
+							$(row).addClass("error");
+						}
+          if (done++ == 20) {
+              $('tr.item:not(.nothumb)').remove();
+              done = 0;
+            }
+					};})(td)
+			});
+	});
+}
+
+$(document).ready(function(){
+  $('input#proceed').click (function () {
+    var width = $('#width')[0].value;
+    var height = $('#height')[0].value;
+    var gd_version=$("input[@name='gd']:checked").val();
+    $("input:not(.nodisable)").attr("disabled",true);
+
+    
+    processThumbs(width,height,gd_version);
+  });
+
+  $('input#cancel').click (function () {
+    queuedManager.clear();
+    queuedManager.abort();
+    $("input:not(.nodisable)").attr("disabled",false);
+    $('tr.nothumb td.thumbpic').html("&nbsp;");
+    
+  });
+
+  $('input#clear').click (function () {
+    $('tr.item:not(.nothumb)').remove();
+  });
+});
+{/literal}{/footer_script}
+
+<div class="titrePage">
+  <h2>{'Thumbnail creation'|@translate}</h2>
+</div>
+
+{if isset($params) }
+<form method="post" action="{$params.F_ACTION}" class="properties">
+
+  <fieldset>
+    <legend>{'Thumbnail creation'|@translate}</legend>
+
+    <ul>
+      <li>
+        <span class="property">{'GD version'|@translate}</span>
+	<label>
+          <input type="radio" name="gd" value="2" {if $params.GD_SELECTED==2}checked="checked"{/if}>2.x
+        </label>
+        <label>
+          <input type="radio" name="gd" value="1" {if $params.GD_SELECTED==1}checked="checked"{/if}>1.x
+        </label>
+      </li>
+
+      <li>
+        <span class="property">
+          <label for="width">{'maximum width'|@translate}</label>
+        </span>
+	<input type="text" id="width" name="width" value="{$params.WIDTH_TN}">
+      </li>
+
+      <li>
+        <span class="property">
+          <label for="height">{'maximum height'|@translate}</label>
+        </span>
+	<input type="text" id="height" name="height" value="{$params.HEIGHT_TN}">
+      </li>
+    </ul>
+  </fieldset>
+
+  <p><input type="button" name="submit" id="proceed" value="{'Submit'|@translate}" {$TAG_INPUT_ENABLED}>
+  <input type="button" class="nodisable" name="submit" id="cancel" value="{'Cancel'|@translate}" {$TAG_INPUT_ENABLED}>
+  <input type="button" class="nodisable" name="submit" id="clear" value="{'clear_success'|@translate}" {$TAG_INPUT_ENABLED}>
+  
+  </p>
+</form>
+{/if} {*isset params*}
+
+{if !empty($remainings) }
+<div class="admin">{$TOTAL_NB_REMAINING} {'Number of thumbnails to create'|@translate}</div>
+<table style="width:100%;">
+  <tr class="throw">
+    <td>&nbsp;</td>
+    <td style="width:60%;">{'Path'|@translate}</td>
+    <td>{'Filesize'|@translate}</td>
+    <td>{'Dimensions'|@translate}</td>
+    <td>{'Thumbnail'|@translate}</td>
+    <td>{'generated in'|@translate}</td>
+    <td>{'Filesize'|@translate}</td>
+    <td>{'Dimensions'|@translate}</td>
+  </tr>
+  {foreach from=$remainings item=elt name=remain_loop}
+  <tr class="{if $smarty.foreach.remain_loop.index is odd}row1{else}row2{/if} nothumb item" id="th_{$smarty.foreach.remain_loop.iteration}">
+    <td>{$smarty.foreach.remain_loop.iteration}</td>
+    <td class="filepath">{$elt.PATH}</div></td>
+    <td>{$elt.FILESIZE_IMG}</div></td>
+    <td>{$elt.WIDTH_IMG} x {$elt.HEIGHT_IMG}</td>
+	<td class="thumbpic">&nbsp;</td>
+	<td class="thumbgentime">&nbsp;</td>
+	<td class="thumbsize">&nbsp;</td>
+	<td class="thumbdim">&nbsp;</td>
+  </tr>
+  {/foreach}
+</table>
+{else}
+<div style="text-align:center;font-weight:bold;margin:10px;"> [ {'No missing thumbnail'|@translate} ]</div>
+{/if}
Index: /extensions/Ajax_Thumbnailer/main.inc.php
===================================================================
--- /extensions/Ajax_Thumbnailer/main.inc.php	(revision 10440)
+++ /extensions/Ajax_Thumbnailer/main.inc.php	(revision 10441)
@@ -9,152 +9,27 @@
 */
 
-ini_set('error_reporting', E_ALL);
-ini_set('display_errors', true);
-
 if (!defined('PHPWG_ROOT_PATH')) die('Hacking attempt!');
 
-class AjaxThumbnailer
+add_event_handler('ws_add_methods', 'add_thumbnail_create_method');
+
+function add_thumbnail_create_method($arr)
 {
-	/* This function is almost the same as the ont in admin/thumbnail.php , tuned
-		for web-service purposes */
-	function RatioResizeImg($path, $newWidth, $newHeight, $tn_ext,$gd_version=2) {
-		global $conf, $lang, $page;
-		
-		$starttime = get_moment();
+  include_once('ws_functions.inc.php');
+}
 
-		if (!function_exists('gd_info'))
-			return new PwgError(WS_ERR_INVALID_PARAM,  'no gd');
+add_event_handler('loc_begin_admin', 'ajaxThumbnailer_admin_modify');
 
-		if (!file_exists($path))
-			return new PwgError(WS_ERR_INVALID_PARAM,  'file not found');
+function ajaxThumbnailer_admin_modify()
+{
+  global $page, $template;
 
-		$filename = basename($path);
-		$dirname = dirname($path);
+  if (isset($_GET['page']) and $_GET['page'] == 'thumbnail')
+  {
+    load_language('plugin.lang', dirname(__FILE__).'/');
+    $template->set_extent(dirname(__FILE__).'/AjaxThumbnailer.tpl', 'thumbnail');
+  }
+}
 
-		// extension of the picture filename
-		$extension = get_extension($filename);
-
-		if (in_array($extension, array('jpg', 'JPG', 'jpeg', 'JPEG'))) {
-			$srcImage = @imagecreatefromjpeg($path);
-		}
-		elseif ($extension == 'png' or $extension == 'PNG') {
-			$srcImage = @imagecreatefrompng($path);
-		} else {
-			unset($extension);
-		}
-
-		if ( isset( $srcImage ) ) {
-			// width/height
-			$srcWidth    = imagesx( $srcImage ); 
-			$srcHeight   = imagesy( $srcImage ); 
-			$ratioWidth  = $srcWidth/$newWidth;
-			$ratioHeight = $srcHeight/$newHeight;
-
-			// maximal size exceeded ?
-			if ( ( $ratioWidth > 1 ) or ( $ratioHeight > 1 ) ) {
-				if ( $ratioWidth < $ratioHeight) { 
-					$destWidth = $srcWidth/$ratioHeight;
-					$destHeight = $newHeight; 
-				} else { 
-					$destWidth = $newWidth; 
-					$destHeight = $srcHeight/$ratioWidth;
-				}
-			} else {
-				$destWidth = $srcWidth;
-				$destHeight = $srcHeight;
-			}
-			// according to the GD version installed on the server
-			if ( $gd_version == 2 ) {
-				// GD 2.0 or more recent -> good results (but slower)
-				$destImage = imagecreatetruecolor( $destWidth, $destHeight); 
-				imagecopyresampled( $destImage, $srcImage, 0, 0, 0, 0,
-					$destWidth,$destHeight,$srcWidth,$srcHeight );
-			} else {
-				// GD prior to version  2 -> pretty bad results :-/ (but fast)
-				$destImage = imagecreate( $destWidth, $destHeight);
-				imagecopyresized( $destImage, $srcImage, 0, 0, 0, 0,
-					$destWidth,$destHeight,$srcWidth,$srcHeight );
-			}
-
-			if (($tndir = mkget_thumbnail_dir($dirname)) == false) {
-				return new PwgError(WS_ERR_INVALID_PARAM,  '['.$tndir.'] : '.l10n('no_write_access'));
-			}
-
-			$dest_file = $tndir.'/'.$conf['prefix_thumbnail'];
-			$dest_file.= get_filename_wo_extension($filename);
-			$dest_file.= '.'.$tn_ext;
-
-			// creation and backup of final picture
-			if (!is_writable($tndir))
-				return new PwgError(WS_ERR_INVALID_PARAM,  '['.$tndir.'] : '.l10n('no_write_access'));
-				
-			imagejpeg($destImage, $dest_file, $conf['tn_compression_level']);
-			// freeing memory ressources
-			imagedestroy( $srcImage );
-			imagedestroy( $destImage );
-
-			list($tn_width, $tn_height) = getimagesize($dest_file);
-			$tn_size = floor(filesize($dest_file) / 1024).' KB';
-
-			$endtime = get_moment();
-			
-			$info = array( 'path'      => $path,
-			'tn_file'   => $dest_file,
-			'tn_width'  => $tn_width,
-			'tn_height' => $tn_height,
-			'tn_size'   => $tn_size,
-			'tn_time'	=> number_format(($endtime - $starttime) * 1000, 2, '.', ' ').' ms');
-			return $info;
-		} else {
-			// error
-			$err=l10n('tn_no_support');
-			if ( isset( $extension ) )
-				$err .= l10n('tn_format').' '.$extension;
-			else
-				$err .= l10n('tn_thisformat');
-			return new PwgError(WS_ERR_INVALID_PARAM, $err);
-		}
-	}
-
-	function plugin_admin_menu($menu) {
-        array_push($menu,
-            array(
-                'NAME' => 'Ajax Thumbnailer',
-                'URL' => get_admin_plugin_menu_link(dirname(__FILE__).'/admin/thumbnailer_admin.php')
-            )
-        );
-        return $menu;
-    }
-
-	function ws_methods($arr) {
-		$service = &$arr[0];
-		$service->addMethod('pwg.thumbnail.create', array($this,'create_thumb'),
-		  array(
-			'picture'=>array(),
-			'width'=>array('default'=>"128"),
-			'height'=>array('default'=>"128"),
-			'ext'=>array('default'=>"jpg")
-		  ),
-		  'Creates a thumbnail for a given image,
-		<br><b>picture</b> is the name of the picture to create thumbnail from.'
-		);
-		
-	}
-	
-	function create_thumb($params, $service) {
-		$picture = $params['picture'];
-		$width = (integer)$params['width'];
-		$height = (integer)$params['height'];
-		$gd_version = (integer)$params['gd_version'];		
-		$ext =$params['ext'];
-		return $this->RatioResizeImg($picture,$width,$height,$ext,$gd_version);
-	}
-	
-}
-$obj = new AjaxThumbnailer();
-
-add_event_handler('ws_add_methods', array(&$obj, 'ws_methods'));
-add_event_handler('get_admin_plugin_menu_links', array(&$obj, 'plugin_admin_menu') );
-set_plugin_data($plugin['id'], $obj);
+//add_event_handler('get_admin_plugin_menu_links', 'ajaxThumbnailer_admin_menu');
 
 ?>
Index: /extensions/Ajax_Thumbnailer/ws_functions.inc.php
===================================================================
--- /extensions/Ajax_Thumbnailer/ws_functions.inc.php	(revision 10441)
+++ /extensions/Ajax_Thumbnailer/ws_functions.inc.php	(revision 10441)
@@ -0,0 +1,132 @@
+<?php
+
+if (!defined('PHPWG_ROOT_PATH')) die('Hacking attempt!');
+
+$service = &$arr[0];
+$service->addMethod('pwg.images.createThumbnail', 'ws_images_createThumbnail',
+  array(
+  'picture'=>array(),
+  'width'=>array('default'=>"128"),
+  'height'=>array('default'=>"128"),
+  'ext'=>array('default'=>"jpg")
+  ),
+  'Creates a thumbnail for a given image,
+<br><b>picture</b> is the name of the picture to create thumbnail from.'
+);
+
+function ws_images_createThumbnail($params, $service)
+{
+  $picture = $params['picture'];
+  $width = (integer)$params['width'];
+  $height = (integer)$params['height'];
+  $gd_version = (integer)$params['gd_version'];		
+  $ext =$params['ext'];
+  $square = (isset($params['square']) and $params['square'] == 'true' and function_exists('process_ratio'));
+  return RatioResizeImg($picture,$width,$height,$ext,$gd_version,$square);
+}
+
+function RatioResizeImg($path, $newWidth, $newHeight, $tn_ext, $gd_version=2, $square=false)
+{
+  global $conf, $lang, $page;
+  
+  $starttime = get_moment();
+
+  if (!function_exists('gd_info'))
+    return new PwgError(WS_ERR_INVALID_PARAM,  'no gd');
+
+  if (!file_exists($path))
+    return new PwgError(WS_ERR_INVALID_PARAM,  'file not found');
+
+  $filename = basename($path);
+  $dirname = dirname($path);
+
+  // extension of the picture filename
+  $extension = get_extension($filename);
+
+  if (in_array($extension, array('jpg', 'JPG', 'jpeg', 'JPEG'))) {
+    $srcImage = @imagecreatefromjpeg($path);
+  }
+  elseif ($extension == 'png' or $extension == 'PNG') {
+    $srcImage = @imagecreatefrompng($path);
+  } else {
+    unset($extension);
+  }
+
+  if ( isset( $srcImage ) ) {
+    // width/height
+    $srcWidth    = imagesx( $srcImage );
+    $srcHeight   = imagesy( $srcImage );
+
+    $coord = $square ? process_ratio($srcWidth, $srcHeight) : array('x'=>0, 'y'=>0);
+
+    $ratioWidth  = $srcWidth/$newWidth;
+    $ratioHeight = $srcHeight/$newHeight;
+
+    // maximal size exceeded ?
+    if ( ( $ratioWidth > 1 ) or ( $ratioHeight > 1 ) ) {
+      if ( $ratioWidth < $ratioHeight) { 
+        $destWidth = $srcWidth/$ratioHeight;
+        $destHeight = $newHeight; 
+      } else { 
+        $destWidth = $newWidth; 
+        $destHeight = $srcHeight/$ratioWidth;
+      }
+    } else {
+      $destWidth = $srcWidth;
+      $destHeight = $srcHeight;
+    }
+    // according to the GD version installed on the server
+    if ( $gd_version == 2 ) {
+      // GD 2.0 or more recent -> good results (but slower)
+      $destImage = imagecreatetruecolor( $destWidth, $destHeight); 
+      imagecopyresampled( $destImage, $srcImage, 0, 0, $coord['x'], $coord['y'],
+        $destWidth,$destHeight,$srcWidth,$srcHeight );
+    } else {
+      // GD prior to version  2 -> pretty bad results :-/ (but fast)
+      $destImage = imagecreate( $destWidth, $destHeight);
+      imagecopyresized( $destImage, $srcImage, 0, 0, $coord['x'], $coord['y'],
+        $destWidth,$destHeight,$srcWidth,$srcHeight );
+    }
+
+    $errors = array();
+    if (($tndir = mkget_thumbnail_dir($dirname, $errors)) == false) {
+      return new PwgError($errors[0]);
+    }
+
+    $dest_file = $tndir.'/'.$conf['prefix_thumbnail'];
+    $dest_file.= get_filename_wo_extension($filename);
+    $dest_file.= '.'.$tn_ext;
+
+    // creation and backup of final picture
+    if (!is_writable($tndir))
+      return new PwgError(WS_ERR_INVALID_PARAM,  '['.$tndir.'] : '.l10n('no_write_access'));
+      
+    imagejpeg($destImage, $dest_file, $conf['tn_compression_level']);
+    // freeing memory ressources
+    imagedestroy( $srcImage );
+    imagedestroy( $destImage );
+
+    list($tn_width, $tn_height) = getimagesize($dest_file);
+    $tn_size = floor(filesize($dest_file) / 1024).' KB';
+
+    $endtime = get_moment();
+    
+    $info = array( 'path'      => $path,
+    'tn_file'   => $dest_file,
+    'tn_width'  => $tn_width,
+    'tn_height' => $tn_height,
+    'tn_size'   => $tn_size,
+    'tn_time'	=> number_format(($endtime - $starttime) * 1000, 2, '.', ' ').' ms');
+    return $info;
+  } else {
+    // error
+    $err=l10n('tn_no_support');
+    if ( isset( $extension ) )
+      $err .= l10n('tn_format').' '.$extension;
+    else
+      $err .= l10n('tn_thisformat');
+    return new PwgError(WS_ERR_INVALID_PARAM, $err);
+  }
+}
+
+?>
