Index: /trunk/i.php
===================================================================
--- /trunk/i.php	(revision 31101)
+++ /trunk/i.php	(revision 31102)
@@ -31,4 +31,15 @@
 @include(PHPWG_ROOT_PATH.PWG_LOCAL_DIR .'config/database.inc.php');
 
+include(PHPWG_ROOT_PATH . 'include/Logger.class.php');
+
+$logger = new Logger(array(
+  'directory' => PHPWG_ROOT_PATH . $conf['data_location'] . $conf['log_dir'],
+  'severity' => $conf['log_level'],
+  // we use an hashed filename to prevent direct file access, and we salt with
+  // the db_password instead of secret_key because the log must be usable in i.php
+  // (secret_key is in the database)
+  'filename' => 'log_' . date('Y-m-d') . '_' . sha1(date('Y-m-d') . $conf['db_password']) . '.txt',
+  ));
+
 
 function trigger_notify() {}
@@ -67,31 +78,7 @@
 // end fast bootstrap
 
-function ilog()
-{
-  global $conf;
-  if (!$conf['enable_i_log']) return;
-
-  $line = date("c");
-  foreach( func_get_args() as $arg)
-  {
-    $line .= ' ';
-    if (is_array($arg))
-    {
-      $line .= implode(' ', $arg);
-    }
-    else
-    {
-      $line .= $arg;
-    }
-  }
-	$file=PHPWG_ROOT_PATH.$conf['data_location'].'tmp/i.log';
-  if (false == file_put_contents($file, $line."\n", FILE_APPEND))
-	{
-		mkgetdir(dirname($file));
-	}
-}
-
 function ierror($msg, $code)
 {
+  global $logger;
   if ($code==301 || $code==302)
   {
@@ -102,8 +89,10 @@
     // default url is on html format
     $url = html_entity_decode($msg);
+    $logger->warning($code . ' ' . $url, 'i.php', array(
+      'url' => $_SERVER['REQUEST_URI'],
+      ));
     header('Request-URI: '.$url);
     header('Content-Location: '.$url);
     header('Location: '.$url);
-    ilog('WARN', $code, $url, $_SERVER['REQUEST_URI']);
     exit;
   }
@@ -118,5 +107,7 @@
   //todo improve
   echo $msg;
-  ilog('ERROR', $code, $msg, $_SERVER['REQUEST_URI']);
+  $logger->error($code . ' ' . $msg, 'i.php', array(
+      'url' => $_SERVER['REQUEST_URI'],
+      ));
   exit;
 }
@@ -405,5 +396,5 @@
 catch (Exception $e)
 {
-  ilog("db error", $e->getMessage());
+  $logger->error($e->getMessage(), 'i.php');
 }
 pwg_db_check_charset();
@@ -502,5 +493,5 @@
   catch (Exception $e)
   {
-    ilog("db error", $e->getMessage());
+    $logger->error($e->getMessage(), 'i.php');
   }
 }
@@ -622,9 +613,15 @@
 $timing['send'] = time_step($step);
 
-ilog('perf',
-  basename($page['src_path']), $o_size, $o_size[0]*$o_size[1],
-  basename($page['derivative_path']), $d_size, $d_size[0]*$d_size[1],
-  function_exists('memory_get_peak_usage') ? round( memory_get_peak_usage()/(1024*1024), 1) : '',
-  time_step($begin),
-  '|', $timing);
-?>
+$timing['total'] = time_step($begin);
+
+if ($logger->severity() >= Logger::INFO)
+{
+  $logger->info('perf', 'i.php', array(
+    'src_path' => basename($page['src_path']),
+    'derivative_path' => basename($page['derivative_path']),
+    'o_size' => $o_size[0] . ' ' . $o_size[1] . ' ' . ($o_size[0]*$o_size[1]),
+    'd_size' => $d_size[0] . ' ' . $d_size[1] . ' ' . ($d_size[0]*$d_size[1]),
+    'mem_usage' => function_exists('memory_get_peak_usage') ? round( memory_get_peak_usage()/(1024*1024), 1) : '',
+    'timing' => $timing,
+    ));
+}
Index: /trunk/include/Logger.class.php
===================================================================
--- /trunk/include/Logger.class.php	(revision 31102)
+++ /trunk/include/Logger.class.php	(revision 31102)
@@ -0,0 +1,453 @@
+<?php
+// +-----------------------------------------------------------------------+
+// | Piwigo - a PHP based photo gallery                                    |
+// +-----------------------------------------------------------------------+
+// | Copyright(C) 2008-2015 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.                                                                  |
+// +-----------------------------------------------------------------------+
+
+/**
+ * Modified version of KLogger 0.2.0
+ *
+ * @author  Kenny Katzgrau <katzgrau@gmail.com>
+ *
+ * @package logger
+ */
+
+class Logger
+{
+  /**
+   * Error severity, from low to high. From BSD syslog RFC, section 4.1.1
+   * @link http://www.faqs.org/rfcs/rfc3164.html
+   */
+  const EMERGENCY = 0;  // Emergency: system is unusable
+  const ALERT     = 1;  // Alert: action must be taken immediately
+  const CRITICAL  = 2;  // Critical: critical conditions
+  const ERROR     = 3;  // Error: error conditions
+  const WARNING   = 4;  // Warning: warning conditions
+  const NOTICE    = 5;  // Notice: normal but significant condition
+  const INFO      = 6;  // Informational: informational messages
+  const DEBUG     = 7;  // Debug: debug messages
+
+  /**
+   * Custom "disable" level.
+   */
+  const OFF       = -1; // Log nothing at all
+
+  /**
+   * Internal status codes.
+   */
+  const STATUS_LOG_OPEN  = 1;
+  const STATUS_OPEN_FAILED = 2;
+  const STATUS_LOG_CLOSED  = 3;
+
+  /**
+   * Disable archive purge.
+   */
+  const ARCHIVE_NO_PURGE = -1;
+
+  /**
+   * Standard messages produced by the class.
+   * @var array
+   */
+  private static $_messages = array(
+    'writefail'   => 'The file could not be written to. Check that appropriate permissions have been set.',
+    'opensuccess' => 'The log file was opened successfully.',
+    'openfail'  => 'The file could not be opened. Check permissions.',
+  );
+
+  /**
+   * Instance options.
+   * @var array
+   */
+  private $options = array(
+    'directory' => null, // Log files directory
+    'filename' => null, // Path to the log file
+    'globPattern' => 'log_*.txt', // Pattern to select all log files with glob()
+    'severity' => self::DEBUG, // Current minimum logging threshold
+    'dateFormat' => 'Y-m-d G:i:s', // Date format
+    'archiveDays' => self::ARCHIVE_NO_PURGE, // Number of files to keep
+    );
+
+  /**
+   * Current status of the logger.
+   * @var integer
+   */
+  private $_logStatus = self::STATUS_LOG_CLOSED;
+  /**
+   * File handle for this instance's log file.
+   * @var resource
+   */
+  private $_fileHandle = null;
+
+  /**
+   * Class constructor.
+   *
+   * @param array $options
+   * @return void
+   */
+  public function __construct($options)
+  {
+    $this->options = array_merge($this->options, $options);
+    
+    if (is_string($this->options['severity'])) {
+      $this->options['severity'] = self::codeToLevel($this->options['severity']);
+    }
+
+    if ($this->options['severity'] === self::OFF) {
+      return;
+    }
+
+    $this->options['directory'] = rtrim($this->options['directory'], '\\/') . DIRECTORY_SEPARATOR;
+
+    if ($this->options['filename'] == null) {
+      $this->options['filename'] = 'log_' . date('Y-m-d') . '.txt';
+    }
+
+    $this->options['filePath'] = $this->options['directory'] . $this->options['filename'];
+
+    if (!file_exists($this->options['directory'])) {
+      mkgetdir($this->options['directory'], MKGETDIR_DEFAULT|MKGETDIR_PROTECT_HTACCESS);
+    }
+
+    if (file_exists($this->options['filePath']) && !is_writable($this->options['filePath'])) {
+      $this->_logStatus = self::STATUS_OPEN_FAILED;
+      throw new RuntimeException(self::$_messages['writefail']);
+      return;
+    }
+
+    if (($this->_fileHandle = fopen($this->options['filePath'], 'a'))) {
+      $this->_logStatus = self::STATUS_LOG_OPEN;
+    }
+    else {
+      $this->_logStatus = self::STATUS_OPEN_FAILED;
+      throw new RuntimeException(self::$_messages['openfail']);
+    }
+
+    if ($this->options['archiveDays'] != self::ARCHIVE_NO_PURGE && rand() % 97 == 0) {
+      $this->purge();
+    }
+  }
+
+  /**
+   * Class destructor.
+   */
+  public function __destruct()
+  {
+    if ($this->_fileHandle) {
+      fclose($this->_fileHandle);
+    }
+  }
+
+  /**
+   * Returns logger status.
+   *
+   * @return int
+   */
+  public function status()
+  {
+    return $this->_logStatus;
+  }
+
+  /**
+   * Returns logger severity threshold.
+   *
+   * @return int
+   */
+  public function severity()
+  {
+    return $this->options['severity'];
+  }
+
+  /**
+   * Writes a $line to the log with a severity level of DEBUG.
+   *
+   * @param string $line
+   * @param string $cat
+   * @param array $args
+   */
+  public function debug($line, $cat = null, $args = array())
+  {
+    $this->log(self::DEBUG, $line, $cat, $args);
+  }
+
+  /**
+   * Writes a $line to the log with a severity level of INFO.
+   *
+   * @param string $line
+   * @param string $cat
+   * @param array $args
+   */
+  public function info($line, $cat = null, $args = array())
+  {
+    $this->log(self::INFO, $line, $cat, $args);
+  }
+
+  /**
+   * Writes a $line to the log with a severity level of NOTICE.
+   *
+   * @param string $line
+   * @param string $cat
+   * @param array $args
+   */
+  public function notice($line, $cat = null, $args = array())
+  {
+    $this->log(self::NOTICE, $line, $cat, $args);
+  }
+
+  /**
+   * Writes a $line to the log with a severity level of WARNING.
+   *
+   * @param string $line
+   * @param string $cat
+   * @param array $args
+   */
+  public function warn($line, $cat = null, $args = array())
+  {
+    $this->log(self::WARNING, $line, $cat, $args);
+  }
+
+  /**
+   * Writes a $line to the log with a severity level of ERROR.
+   *
+   * @param string $line
+   * @param string $cat
+   * @param array $args
+   */
+  public function error($line, $cat = null, $args = array())
+  {
+    $this->log(self::ERROR, $line, $cat, $args);
+  }
+
+  /**
+   * Writes a $line to the log with a severity level of ALERT.
+   *
+   * @param string $line
+   * @param string $cat
+   * @param array $args
+   */
+  public function alert($line, $cat = null, $args = array())
+  {
+    $this->log(self::ALERT, $line, $cat, $args);
+  }
+
+  /**
+   * Writes a $line to the log with a severity level of CRITICAL.
+   *
+   * @param string $line
+   * @param string $cat
+   * @param array $args
+   */
+  public function critical($line, $cat = null, $args = array())
+  {
+    $this->log(self::CRITICAL, $line, $cat, $args);
+  }
+
+  /**
+   * Writes a $line to the log with a severity level of EMERGENCY.
+   *
+   * @param string $line
+   * @param string $cat
+   * @param array $args
+   */
+  public function emergency($line, $cat = null, $args = array())
+  {
+    $this->log(self::EMERGENCY, $line, $cat, $args);
+  }
+
+  /**
+   * Writes a $line to the log with the given severity.
+   *
+   * @param integer $severity
+   * @param string $line
+   * @param string $cat
+   * @param array $args
+   */
+  public function log($severity, $message, $cat = null, $args = array())
+  {
+    if ($this->severity() >= $severity) {
+      if (is_array($cat)) {
+        $args = $cat;
+        $cat = null;
+      }
+      $line = $this->formatMessage($severity, $message, $cat, $args);
+      $this->write($line);
+    }
+  }
+
+  /**
+   * Directly writes a line to the log without adding level and time.
+   *
+   * @param string $line
+   */
+  public function write($line)
+  {
+    if ($this->_logStatus == self::STATUS_LOG_OPEN) {
+      if (fwrite($this->_fileHandle, $line) === false) {
+        throw new RuntimeException(self::$_messages['writefail']);
+      }
+    }
+  }
+
+  /**
+   * Purges files matching 'globPattern' older than 'archiveDays'.
+   */
+  public function purge() {
+    $files = glob($this->options['directory'] . $this->options['globPattern']);
+    $limit = time() - $this->options['archiveDays'] * 86400;
+
+    foreach ($files as $file) {
+      if (@filemtime($file) < $limit) {
+        @unlink($file);
+      }
+    }
+  }
+
+  /**
+   * Formats the message for logging.
+   *
+   * @param  string $level
+   * @param  string $message
+   * @param  array  $context
+   * @return string
+   */
+  private function formatMessage($level, $message, $cat, $context)
+  {
+    if (!empty($context)) {
+      $message .= "\n" . $this->indent($this->contextToString($context));
+    }
+    $line = "[" . $this->getTimestamp() . "]\t[" . self::levelToCode($level) . "]\t";
+    if ($cat != null) {
+      $line .= "[" . $cat . "]\t";
+    }
+    return $line . $message . "\n";
+  }
+
+  /**
+   * Gets the formatted Date/Time for the log entry.
+   *
+   * PHP DateTime is dumb, and you have to resort to trickery to get microseconds
+   * to work correctly, so here it is.
+   *
+   * @return string
+   */
+  private function getTimestamp()
+  {
+    $originalTime = microtime(true);
+    $micro = sprintf("%06d", ($originalTime - floor($originalTime)) * 1000000);
+    $date = new DateTime(date('Y-m-d H:i:s.'.$micro, $originalTime));
+    return $date->format($this->options['dateFormat']);
+  }
+
+  /**
+   * Takes the given context and converts it to a string.
+   *
+   * @param  array $context
+   * @return string
+   */
+  private function contextToString($context)
+  {
+    $export = '';
+    foreach ($context as $key => $value) {
+      $export .= "{$key}: ";
+      $export .= preg_replace(array(
+        '/=>\s+([a-zA-Z])/im',
+        '/array\(\s+\)/im',
+        '/^  |\G  /m'
+      ), array(
+        '=> $1',
+        'array()',
+        '  '
+      ), str_replace('array (', 'array(', var_export($value, true)));
+      $export .= PHP_EOL;
+    }
+    return str_replace(array('\\\\', '\\\''), array('\\', '\''), rtrim($export));
+  }
+
+  /**
+   * Indents the given string with the given indent.
+   *
+   * @param  string $string The string to indent
+   * @param  string $indent What to use as the indent.
+   * @return string
+   */
+  private function indent($string, $indent = '  ')
+  {
+    return $indent.str_replace("\n", "\n".$indent, $string);
+  }
+
+  /**
+   * Converts level constants to string name.
+   *
+   * @param int $level
+   * @return string
+   */
+  static function levelToCode($level)
+  {
+    switch ($level) {
+      case self::EMERGENCY:
+        return 'EMERGENCY';
+      case self::ALERT:
+        return 'ALERT';
+      case self::CRITICAL:
+        return 'CRITICAL';
+      case self::NOTICE:
+        return 'NOTICE';
+      case self::INFO:
+        return 'INFO';
+      case self::WARNING:
+        return 'WARNING';
+      case self::DEBUG:
+        return 'DEBUG';
+      case self::ERROR:
+        return 'ERROR';
+      default:
+        throw new RuntimeException('Unknown severity level ' . $level);
+    }
+  }
+
+  /**
+   * Converts level names to constant.
+   *
+   * @param string $code
+   * @return int
+   */
+  static function codeToLevel($code)
+  {
+    switch (strtoupper($code)) {
+      case 'EMERGENCY':
+        return self::EMERGENCY;
+      case 'ALERT':
+        return self::ALERT;
+      case 'CRITICAL':
+        return self::CRITICAL;
+      case 'NOTICE':
+        return self::NOTICE;
+      case 'INFO':
+        return self::INFO;
+      case 'WARNING':
+        return self::WARNING;
+      case 'DEBUG':
+        return self::DEBUG;
+      case 'ERROR':
+        return self::ERROR;
+      default:
+        throw new RuntimeException('Unknown severity code ' . $code);
+    }
+  }
+}
Index: /trunk/include/common.inc.php
===================================================================
--- /trunk/include/common.inc.php	(revision 31101)
+++ /trunk/include/common.inc.php	(revision 31102)
@@ -105,4 +105,7 @@
 include(PHPWG_ROOT_PATH . 'include/constants.php');
 include(PHPWG_ROOT_PATH . 'include/functions.inc.php');
+include(PHPWG_ROOT_PATH . 'include/template.class.php');
+include(PHPWG_ROOT_PATH . 'include/cache.class.php');
+include(PHPWG_ROOT_PATH . 'include/Logger.class.php');
 
 $persistent_cache = new PersistentFileCache();
@@ -122,4 +125,15 @@
 
 load_conf_from_db();
+
+$logger = new Logger(array(
+  'directory' => PHPWG_ROOT_PATH . $conf['data_location'] . $conf['log_dir'],
+  'severity' => $conf['log_level'],
+  // we use an hashed filename to prevent direct file access, and we salt with
+  // the db_password instead of secret_key because the log must be usable in i.php
+  // (secret_key is in the database)
+  'filename' => 'log_' . date('Y-m-d') . '_' . sha1(date('Y-m-d') . $conf['db_password']) . '.txt',
+  'globPattern' => 'log_*.txt',
+  'archiveDays' => $conf['log_archive_days'],
+  ));
 
 if (!$conf['check_upgrade_feed'])
Index: /trunk/include/config_default.inc.php
===================================================================
--- /trunk/include/config_default.inc.php	(revision 31101)
+++ /trunk/include/config_default.inc.php	(revision 31102)
@@ -463,6 +463,4 @@
 $conf['show_php_errors'] = E_ALL;
 
-// enable log for i derivative script
-$conf['enable_i_log'] = false;
 
 // +-----------------------------------------------------------------------+
@@ -653,10 +651,4 @@
 // Web services are allowed (true) or completely forbidden (false)
 $conf['allow_web_services'] = true;
-
-// enable log for web services
-$conf['ws_enable_log'] = false;
-
-// web services log file path
-$conf['ws_log_filepath'] = '/tmp/piwigo_ws.log';
 
 // Maximum number of images to be returned foreach call to the web service
@@ -813,3 +805,15 @@
 // the directory where "ffmpeg" executable is.
 $conf['ffmpeg_dir'] = '';
-?>
+
+// +-----------------------------------------------------------------------+
+// |                                 log                                   |
+// +-----------------------------------------------------------------------+
+// Logs directory, relative to $conf['data_location']
+$conf['log_dir'] = '/logs';
+
+// Log level (OFF, CRITICAL, ERROR, WARNING, NOTICE, INFO, DEBUG)
+// development = DEBUG, production = ERROR
+$conf['log_level'] = 'DEBUG';
+
+// Keep logs file during X days
+$conf['log_archive_days'] = 30;
Index: /trunk/include/functions.inc.php
===================================================================
--- /trunk/include/functions.inc.php	(revision 31101)
+++ /trunk/include/functions.inc.php	(revision 31102)
@@ -37,6 +37,4 @@
 include_once( PHPWG_ROOT_PATH .'include/derivative_std_params.inc.php');
 include_once( PHPWG_ROOT_PATH .'include/derivative.inc.php');
-include_once( PHPWG_ROOT_PATH .'include/template.class.php');
-include_once( PHPWG_ROOT_PATH .'include/cache.class.php');
 
 
Index: /trunk/include/ws_functions.inc.php
===================================================================
--- /trunk/include/ws_functions.inc.php	(revision 31101)
+++ /trunk/include/ws_functions.inc.php	(revision 31102)
@@ -206,23 +206,4 @@
 
 /**
- * Writes info to the log file
- */
-function ws_logfile($string)
-{
-  global $conf;
-
-  if (!$conf['ws_enable_log'])
-  {
-    return true;
-  }
-
-  file_put_contents(
-    $conf['ws_log_filepath'],
-    '['.date('c').'] '.$string."\n",
-    FILE_APPEND
-    );
-}
-
-/**
  * create a tree from a flat list of categories, no recursivity for high speed
  */
Index: /trunk/include/ws_functions/pwg.images.php
===================================================================
--- /trunk/include/ws_functions/pwg.images.php	(revision 31101)
+++ /trunk/include/ws_functions/pwg.images.php	(revision 31102)
@@ -183,7 +183,7 @@
 function merge_chunks($output_filepath, $original_sum, $type)
 {
-  global $conf;
-
-  ws_logfile('[merge_chunks] input parameter $output_filepath : '.$output_filepath);
+  global $conf, $logger;
+
+  $logger->debug('[merge_chunks] input parameter $output_filepath : '.$output_filepath, 'WS');
 
   if (is_file($output_filepath))
@@ -207,5 +207,5 @@
       if (preg_match($pattern, $file))
       {
-        ws_logfile($file);
+        $logger->debug($file, 'WS');
         $chunks[] = $upload_dir.'/'.$file;
       }
@@ -217,5 +217,5 @@
 
   if (function_exists('memory_get_usage')) {
-    ws_logfile('[merge_chunks] memory_get_usage before loading chunks: '.memory_get_usage());
+    $logger->debug('[merge_chunks] memory_get_usage before loading chunks: '.memory_get_usage(), 'WS');
   }
 
@@ -227,5 +227,5 @@
 
     if (function_exists('memory_get_usage')) {
-      ws_logfile('[merge_chunks] memory_get_usage on chunk '.++$i.': '.memory_get_usage());
+      $logger->debug('[merge_chunks] memory_get_usage on chunk '.++$i.': '.memory_get_usage(), 'WS');
     }
 
@@ -239,5 +239,5 @@
 
   if (function_exists('memory_get_usage')) {
-    ws_logfile('[merge_chunks] memory_get_usage after loading chunks: '.memory_get_usage());
+    $logger->debug('[merge_chunks] memory_get_usage after loading chunks: '.memory_get_usage(), 'WS');
   }
 }
@@ -825,5 +825,5 @@
 function ws_images_add_chunk($params, $service)
 {
-  global $conf;
+  global $conf, $logger;
 
   foreach ($params as $param_key => $param_value)
@@ -833,11 +833,10 @@
       continue;
     }
-    ws_logfile(
-      sprintf(
-        '[ws_images_add_chunk] input param "%s" : "%s"',
-        $param_key,
-        is_null($param_value) ? 'NULL' : $param_value
-        )
-      );
+
+    $logger->debug(sprintf(
+      '[ws_images_add_chunk] input param "%s" : "%s"',
+      $param_key,
+      is_null($param_value) ? 'NULL' : $param_value
+      ), 'WS');
   }
 
@@ -857,5 +856,5 @@
     );
 
-  ws_logfile('[ws_images_add_chunk] data length : '.strlen($params['data']));
+  $logger->debug('[ws_images_add_chunk] data length : '.strlen($params['data']), 'WS');
 
   $bytes_written = file_put_contents(
@@ -882,7 +881,7 @@
 function ws_images_addFile($params, $service)
 {
-  ws_logfile(__FUNCTION__.', input :  '.var_export($params, true));
-
-  global $conf;
+  global $conf, $logger;
+
+  $logger->debug(__FUNCTION__, 'WS', $params);
 
   // what is the path and other infos about the photo?
@@ -975,15 +974,13 @@
 function ws_images_add($params, $service)
 {
-  global $conf, $user;
+  global $conf, $user, $logger;
 
   foreach ($params as $param_key => $param_value)
   {
-    ws_logfile(
-      sprintf(
-        '[pwg.images.add] input param "%s" : "%s"',
-        $param_key,
-        is_null($param_value) ? 'NULL' : $param_value
-        )
-      );
+    $logger->debug(sprintf(
+      '[pwg.images.add] input param "%s" : "%s"',
+      $param_key,
+      is_null($param_value) ? 'NULL' : $param_value
+      ), 'WS');
   }
 
@@ -1399,7 +1396,7 @@
 function ws_images_exist($params, $service)
 {
-  ws_logfile(__FUNCTION__.' '.var_export($params, true));
-
-  global $conf;
+  global $conf, $logger;
+
+  $logger->debug(__FUNCTION__, 'WS', $params);
 
   $split_pattern = '/[\s,;\|]/';
@@ -1472,5 +1469,7 @@
 function ws_images_checkFiles($params, $service)
 {
-  ws_logfile(__FUNCTION__.', input :  '.var_export($params, true));
+  global $logger;
+
+  $logger->debug(__FUNCTION__, 'WS', $params);
 
   $query = '
@@ -1510,5 +1509,5 @@
   if (isset($compare_type))
   {
-    ws_logfile(__FUNCTION__.', md5_file($path) = '.md5_file($path));
+    $logger->debug(__FUNCTION__.', md5_file($path) = '.md5_file($path), 'WS');
     if (md5_file($path) != $params[$compare_type.'_sum'])
     {
@@ -1521,5 +1520,5 @@
   }
 
-  ws_logfile(__FUNCTION__.', output :  '.var_export($ret, true));
+  $logger->debug(__FUNCTION__, 'WS', $ret);
 
   return $ret;
