Index: /extensions/whois_online/config.php
===================================================================
--- /extensions/whois_online/config.php	(revision 3319)
+++ /extensions/whois_online/config.php	(revision 3319)
@@ -0,0 +1,240 @@
+<?php
+
+/* Whois online Configuration, Radar and cleaning */
+
+/*
+ TODO list:
+- User comments
+ (Delete all comments or partial delete)
+- Bots identification (for exclusion maybe a sharing feature with antiaspi to lock user/IP)
+- hits level (to suggest a new bot)
+- IPV6 Support
+- Map
+*/
+
+if (!defined('PHPWG_ROOT_PATH')) die('Hacking attempt!');
+if (!defined('IN_ADMIN') or !IN_ADMIN) die('Hacking attempt!');
+global $conf, $lang;
+load_language('plugin.lang', WHOIS_ONLINE_PATH);
+
+pwg_debug('*********** Whois configuration ***********');
+
+$conf_whois = whois_online_conf();
+$errors = array();
+$infos = array();
+
+// Get Current data
+$conf['Whois Online Update'] = false;
+whois_online_management();
+
+$template->set_filenames(array(
+    'plugin_admin_content' => dirname(__FILE__) . '/config.tpl',
+		'double_select' => 'double_select.tpl'
+		));
+
+// Tabsheets 
+include_once(PHPWG_ROOT_PATH.'admin/include/tabsheet.class.php');
+$_url = get_admin_plugin_menu_link(__FILE__);
+if (!isset($_GET['tab'])) $page['tab'] = 'config';
+else $page['tab'] = $_GET['tab'];  
+
+$tabsheet = new tabsheet();
+$tabsheet->add('config', l10n('config'), $_url.'&amp;tab=config');
+$tabsheet->add('monitor', l10n('Monitor'), $_url.'&amp;tab=monitor');
+$tabsheet->add('report', l10n('Report'), $_url.'&amp;tab=report');
+$tabsheet->select($page['tab']);
+$tabsheet->assign();
+$template->assign('page', $page['tab']);
+
+$sub = ( isset($_POST['submit']) ) ? true : false;
+
+// Check input on config
+if ($sub and isset($_POST['from']) and $_POST['from']=='config') {
+  if (!is_numeric($_POST['Level']) or $_POST['Level'] < 10 or $_POST['Level'] > 200) 
+		array_push($errors, l10n('Error range: '). l10n('Delete level [10-200] (ratio between obsolete and active)'));
+  if (!is_numeric($_POST['Limit']) or $_POST['Limit'] < 10 or $_POST['Limit'] > 200) 
+		array_push($errors, l10n('Error range: '). l10n('Obsolete limit [20-100] (obsolete data count)'));
+	if (!is_numeric($_POST['Radar_limit']) or $_POST['Radar_limit'] < 10 or $_POST['Radar_limit'] > 200) 
+		array_push($errors, l10n('Error range: '). l10n('Radar_limit [10-200] (Users with image cluetips on radar page)'));
+	if (!is_numeric($_POST['Webmaster_management']) or $_POST['Webmaster_management'] > 2) 
+		array_push($errors, l10n('User follow up error'));
+	if (!is_numeric($_POST['Administrator_management']) or $_POST['Administrator_management'] > 2) 
+		array_push($errors, l10n('User follow up error'));
+	$conf_whois = array_merge($conf_whois, Array(
+		'Active' => ($_POST['Active']==1) ? true:false,
+		'Delete level' => $_POST['Level'],
+		'Obsolete limit' => $_POST['Limit'],
+		'Radar limit' => $_POST['Radar_limit'],
+		'Webmasters' => (int) $_POST['Webmaster_management'],
+		'Administrators' => (int) $_POST['Administrator_management'],
+		'Add to Plugins menu' => ($_POST['Plugins_menu']==1) ? true:false,
+		'Add icon to History' => ($_POST['History_icon']==1) ? true:false,
+		'Keep data' => ($_POST['Keep_data']==1) ? true:false,
+		'Default display' => ($_POST['Display']==1) ? true:false,
+		'Version' => WHOIS_ONLINE_VER,
+	));
+}
+
+// Submit and Advisor => Thanks
+if ( $sub and is_adviser() )
+	array_push($infos, l10n('You are Adviser and you are not authorized to change this configuration.'));
+
+	// Submit and not Advisor => Update Config table
+if ( $sub and count($errors) == 0 and $_POST['from']=='config' and !is_adviser()) {
+	if ( $conf['Whois Online'] != serialize($conf_whois) ) {
+		pwg_query('REPLACE INTO ' . CONFIG_TABLE . " (param,value,comment)
+    VALUES ('Whois Online','". serialize($conf_whois) ."','Whois Online configuration');");
+		array_push($infos, l10n('Configuration has been saved.'));
+	}
+}
+
+// Switch users on right side (=> Temporary)
+if ( isset($_POST['falsify']) and !is_adviser() 
+    and count($errors) == 0 and $_POST['from']=='monitor'
+    and isset($_POST['cat_true']) and count($_POST['cat_true']) > 0) {
+      pwg_query('UPDATE '.WHOIS_ONLINE_TABLE.'
+  SET `permanent` = \'false\'
+  WHERE `session_id` IN ("'.implode('","', $_POST['cat_true']).'");');
+}
+// Switch users on left side (Permanent <=)
+if ( isset($_POST['trueify']) and !is_adviser() 
+    and count($errors) == 0 and $_POST['from']=='monitor'
+    and isset($_POST['cat_false']) and count($_POST['cat_false']) > 0) {
+      pwg_query('UPDATE '.WHOIS_ONLINE_TABLE.'
+  SET `permanent` = \'true\'
+  WHERE `session_id` IN ("'.implode('","', $_POST['cat_false']).'");');
+}
+// Delete users from > 24 h temporary list
+if ( isset($_POST['prs_delete']) and !is_adviser() 
+    and count($errors) == 0 and $_POST['from']=='monitor'
+    and isset($_POST['prs_remove']) and count($_POST['prs_remove']) > 0) {
+     pwg_query('DELETE FROM '.WHOIS_ONLINE_TABLE.'
+  WHERE `permanent` = \'false\'
+    AND `session_id` IN ("'.implode('","', $_POST['prs_remove']).'");');
+}
+// Compress it!
+if ( isset($_GET['check']) and !is_adviser() ) {
+  pwg_query('DELETE FROM ' . WHOIS_ONLINE_TABLE . ' WHERE `last_access` < ' . (time() - (3*24*60*60)) . '
+    AND `permanent` = \'false\' AND `IP` <> \'global\';');
+  pwg_query('CHECK TABLE '.WHOIS_ONLINE_TABLE);
+  pwg_query('OPTIMIZE TABLE '.WHOIS_ONLINE_TABLE);
+}
+// The whois_online table summary
+if (isset($_GET['tab']) and $_GET['tab']=='monitor') {
+  $whois_status = mysql_fetch_assoc(pwg_query('SHOW TABLE STATUS LIKE "' . WHOIS_ONLINE_TABLE .'%" ;'));
+  $whois_status['table'] = WHOIS_ONLINE_TABLE;
+  $whois_status['size'] = ($whois_status['Data_length'] + $whois_status['Index_length']) . ' bytes';
+  if ($whois_status['size'] > 1024) $whois_status['size'] = round($whois_status['size'] / 1024, 1) . ' Kb';
+  if ($whois_status['size'] > 1024) $whois_status['size'] = round($whois_status['size'] / 1024, 1) . ' Mb';
+  $whois_status['spacef'] = $whois_status['Data_free'] . ' bytes';
+  if ($whois_status['spacef'] > 1024) $whois_status['spacef'] = round($whois_status['spacef'] / 1024, 1) . ' Kb';
+  if ($whois_status['spacef'] > 1024) $whois_status['spacef'] = round($whois_status['spacef'] / 1024, 1) . ' Mb';
+	$whois_status['Rows']--;
+	$whois_status['url'] = get_admin_plugin_menu_link(WHOIS_ONLINE_PATH.'config.php');
+  $template->assign( array( 'WO_status' => $whois_status, ));
+}
+
+// The Radar page
+if (isset($_GET['tab']) and $_GET['tab']=='monitor') {
+	$query_true = 'SELECT `session_id`, `username`
+	  FROM '.WHOIS_ONLINE_TABLE.'
+	  WHERE `permanent` = \'true\' 
+	    AND `user_id`<> ' . $conf['guest_id'] . ' AND `IP` <> \'global\';';
+	$result = pwg_query($query_true);
+	$tpl = array();
+	if (!empty($result))
+	{
+		while ($row = mysql_fetch_assoc($result))
+		{
+			$tpl[$row['session_id']] = $row['username'];
+		}
+	}
+	$template->assign( 'category_option_true', $tpl);
+	$template->assign( 'category_option_true_selected', array());
+
+	$query_false = 'SELECT `session_id`, `username`, `last_access`
+	  FROM '.WHOIS_ONLINE_TABLE.'
+	  WHERE `permanent` = \'false\' 
+	    AND `user_id`<> ' . $conf['guest_id'] . ' AND `IP` <> \'global\';';
+	$result = pwg_query($query_false);
+	$tpl = array();
+	$del = array();
+	$six_ago = time()-360; 			// 6 minutes ago
+	if (!empty($result))
+	{
+		while ($row = mysql_fetch_assoc($result))
+		{
+			$tpl[$row['session_id']] = $row['username'];
+			if ($row['last_access'] < $six_ago) $del[$row['session_id']] = $row['username'];
+		}
+	}
+	$template->assign( 'category_option_false', $tpl);
+	$template->assign( 'category_option_false_selected', array());
+	$template->assign( 'present_remove', $del);
+	$template->assign( 'present_remove_selected', array());
+}
+
+// Send data
+$template->assign(Array(
+	'Whois_version' => WHOIS_ONLINE_VER,
+	'Whois_path' => WHOIS_ONLINE_PATH,
+	'F_ACTION' => '',
+	'L_CAT_OPTIONS_TRUE' => l10n('Permanent users (3 months min)'),
+	'L_CAT_OPTIONS_FALSE' => l10n('Temporary users (around 72 hours)'),
+));
+$template->assign_var_from_handle('DOUBLE_SELECT', 'double_select');
+
+if (count($errors) != 0) $template->assign('errors', $errors);
+if (count($infos) != 0) $template->assign('infos', $infos);
+if (isset($_GET['tab']) and $_GET['tab']=='report') {
+  // Once for all, prepare the stupid History search ... (even if History search will recreate it)
+	if (!isset($conf_whois['Search id']) or $conf_whois['Search id'] == 0) {
+	  pwg_query('INSERT INTO '.SEARCH_TABLE.'  (rules)
+	  VALUES (\''. 
+	  'a:1:{s:6:"fields";a:5:{s:10:"date-after";s:10:"2009-09-09";s:11:"date-before";s:10:"2009-09-09";s:5:"types";a:4:{i:0;s:4:"none";i:1;s:7:"picture";i:2;s:4:"high";i:3;s:5:"other";}s:4:"user";s:2:"-1";s:17:"display_thumbnail";s:26:"display_thumbnail_hoverbox";}}'
+	  .'\');');
+	  $conf_whois['Search id'] = mysql_insert_id();
+		$conf['Whois Online'] = serialize($conf_whois);
+		pwg_query('REPLACE INTO ' . CONFIG_TABLE . " (param,value,comment)
+	  VALUES ('Whois Online','". $conf['Whois Online'] ."','Whois Online configuration');");
+	}
+	// Get and Set to current date the stupid History search.
+	list($serialized_rules) = mysql_fetch_row(pwg_query('SELECT rules FROM '.SEARCH_TABLE.'
+	  WHERE id = '.$conf_whois['Search id'].';'));
+	$page['search'] = unserialize($serialized_rules);
+	$today = date('Y-m-d');
+	$page['search']['fields']['date-after'] = $today;
+	$page['search']['fields']['date-before'] = $today;
+	pwg_query('REPLACE INTO '.SEARCH_TABLE.'  (id, rules)
+	  VALUES (' . $conf_whois['Search id'] . ', \''. serialize($page['search']) .'\');');
+	// Most members ever online was
+	if (!isset($conf_whois['Users']['count']) or $conf_whois['Users']['count'] == 0) {
+		$count = mysql_fetch_assoc(pwg_query('SELECT MAX(`id`) AS `ctr` FROM ' . USERS_TABLE));
+		$conf_whois['Users']['count'] = $count['ctr'];
+	}
+	//$conf_whois['Users']['Date'] = date('Y-m-d H:i',$conf_whois['Users']['When']);
+	$template->assign(array(
+		'Members' => $conf_whois['Users'],
+		'Whois_url' => WHOIS_ONLINE_PATH,
+	));
+  // Include reload.php for first request (Filtering is an intrusive jQuery)
+  include_once(WHOIS_ONLINE_PATH.'reload.php');
+}
+
+pwg_debug('*********** Whois configuration ended ***********');
+
+$template->assign('Option', array(
+		'Active' => ($conf_whois['Active']) ? 1 : 0,
+		'Level' => $conf_whois['Delete level'],
+		'Limit' => $conf_whois['Obsolete limit'],
+		'Radar_limit' => $conf_whois['Radar limit'],
+		'Webmasters' => $conf_whois['Webmasters'],
+		'Administrators' => $conf_whois['Administrators'],
+		'Plugins_menu' => ($conf_whois['Add to Plugins menu']) ? 1 : 0,
+		'History_icon' => ($conf_whois['Add icon to History']) ? 1 : 0,
+		'Keep_data' => ($conf_whois['Keep data']) ? 1 : 0,
+		'Display' => ($conf_whois['Default display']) ? 1 : 0,
+	) );
+$template->assign_var_from_handle('ADMIN_CONTENT', 'plugin_admin_content');
+
+?>
Index: /extensions/whois_online/config.tpl
===================================================================
--- /extensions/whois_online/config.tpl	(revision 3319)
+++ /extensions/whois_online/config.tpl	(revision 3319)
@@ -0,0 +1,175 @@
+<div class="titrePage">
+	<h2>Whois Online [{$Whois_version}]</h2>
+</div>
+
+<form method="post" action="{$F_ACTION}" class="Whois_Online properties">
+
+{if $page == 'config'}
+<fieldset>
+	<legend>{'Options'|@translate}</legend>
+
+	<ul>
+		<li>
+			<span class="property">{'Active capture'|@translate}</span>
+			<input type="radio" value="1" name="Active" {if ($Option.Active==1)} checked="checked" {/if}/>{'Yes'|@translate}
+			<input type="radio" value="0" name="Active" {if ($Option.Active==0)} checked="checked" {/if}/>{'No'|@translate}
+		</li>
+		<li>
+			<span class="property">{'Delete level [10-200] (ratio between obsolete and active)'|@translate}</span>
+			<input type="text" id="Level" maxlength="3" size="8" name="Level" value="{$Option.Level}" />
+		</li>
+		<li>
+			<span class="property">{'Obsolete limit [20-100] (obsolete data count)'|@translate}</span>
+			<input type="text" id="Limit" maxlength="3" size="8" name="Limit" value="{$Option.Limit}" />
+		</li>
+		<li>
+			<span class="property">{'Add link to Plugins menu'|@translate}</span>
+			<input type="radio" value="1" name="Plugins_menu" {if ($Option.Plugins_menu==1)} checked="checked" {/if}/>{'Yes'|@translate}
+			<input type="radio" value="0" name="Plugins_menu" {if ($Option.Plugins_menu==0)} checked="checked" {/if}/>{'No'|@translate}
+		</li>
+		<li>
+			<span class="property">{'Add icon to History'|@translate}</span>
+			<input type="radio" value="1" name="History_icon" {if ($Option.History_icon==1)} checked="checked" {/if}/>{'Yes'|@translate}
+			<input type="radio" value="0" name="History_icon" {if ($Option.History_icon==0)} checked="checked" {/if}/>{'No'|@translate}
+		</li>
+		<li>
+			<span class="property">{'Keep data even if plugin is deactivated/uninstall'|@translate}</span>
+			<input type="radio" value="1" name="Keep_data" {if ($Option.Keep_data==1)} checked="checked" {/if}/>{'Yes'|@translate}
+			<input type="radio" value="0" name="Keep_data" {if ($Option.Keep_data==0)} checked="checked" {/if}/>{'No'|@translate}
+		</li>
+		<li>
+			<span class="property" title="{'Advanced users: template vars are available in all cases and might be included in your extensions'|@translate}" >{'Default display'|@translate}</span>
+			<input type="radio" value="1" name="Display" {if ($Option.Display==1)} checked="checked" {/if}/>{'Yes'|@translate}
+			<input type="radio" value="0" name="Display" {if ($Option.Display==0)} checked="checked" {/if}/>{'No'|@translate}
+		</li>
+		<li>
+			<span class="property" title="{'Users with image cluetips [10-200]'|@translate}" >{'Radar limit'|@translate}</span>
+			<input type="text" maxlength="2" size="8" id="Radar_limit" name="Radar_limit" value="{$Option.Radar_limit}"  title="{'Default %s'|@translate|@sprintf:'25'}"/>
+		</li>
+		<li>
+			<span class="property" title="{'Default as anybody'|@translate}" >{'Webmasters management:'|@translate}</span>
+			<input type="radio" value="0" name="Webmaster_management" {if ($Option.Webmasters==0)} checked="checked" {/if}/>{'Exclude'|@translate}
+			<input type="radio" value="1" name="Webmaster_management" {if ($Option.Webmasters==1)} checked="checked" {/if}/>{'Hidden'|@translate}
+			<input type="radio" value="2" name="Webmaster_management" {if ($Option.Webmasters==2)} checked="checked" {/if}/>{'As anybody'|@translate}
+		</li>
+		<li>
+			<span class="property" title="{'Default as anybody'|@translate}" >{'Administrators management:'|@translate}</span>
+			<input type="radio" value="0" name="Administrator_management" {if ($Option.Administrators==0)} checked="checked" {/if}/>{'Exclude'|@translate}
+			<input type="radio" value="1" name="Administrator_management" {if ($Option.Administrators==1)} checked="checked" {/if}/>{'Hidden'|@translate}
+			<input type="radio" value="2" name="Administrator_management" {if ($Option.Administrators==2)} checked="checked" {/if}/>{'As anybody'|@translate}
+		</li>
+
+	</ul>
+	<input type="submit" value="{'Submit'|@translate}" name="submit" class="submit"/>
+	<div><input type="hidden" name="from" value="config" /></div>
+</fieldset>
+{/if}
+
+{if $page == 'monitor'}
+
+<fieldset>
+	<legend>{'Your `%s` table summary'|@translate|@sprintf:$WO_status.table}</legend>
+	<p>
+		{if ($WO_status.spacef > 0)}<a href="{$WO_status.url}&amp;tab=monitor&amp;check">{'Compress it!'|@translate}</a>
+		{' => Delete old guests access (over 3 days), and optimize table and index.'|@translate}<br />{/if}
+      <table class="table1">
+				<tr class="row2"><td style="padding:7px; width: 45%">{'Space used: %s'|@translate|@sprintf:$WO_status.size}</td>
+				<td style="padding:7px; width: 45%">{'Unused allocated space: <strong>%s</strong>'|@translate|@sprintf:$WO_status.spacef}</td></tr>
+				<tr class="row2"><td>{'Traced sessions: %s'|@translate|@sprintf:$WO_status.Rows}</td>
+				<td>{'Altered/created since: %s'|@translate|@sprintf:$WO_status.Create_time}</td></tr>
+			</table>
+		</p>
+</fieldset>
+
+
+<fieldset>
+	<legend>{'Permanence/Durability of user monitoring'|@translate}</legend>
+    {$DOUBLE_SELECT}
+		<div><input type="hidden" name="from" value="monitor" /></div>
+</fieldset>
+<fieldset>
+	<legend>{'Clearing'|@translate}</legend>
+	<p>{'Clear temporary users (minimal delay is 6 minutes). To clean any permanent users, switch them before in the right list above.'|@translate}</p>
+      <select class="CleaningList" name="prs_remove[]" multiple="multiple">
+        {html_options options=$present_remove selected=$present_remove_selected}
+      </select>
+      <p><input class="submit" type="submit" value="{'Delete'|@translate}" name="prs_delete" style="font-size:15px;" {$TAG_INPUT_ENABLED}/></p>
+		<div><input type="hidden" name="from" value="monitor" /></div>
+</fieldset>
+{literal}
+<script type="text/javascript">// <![CDATA[
+  jQuery().ready(function(){
+    // Resize possible for double select list
+    jQuery("select.CleaningList").resizable({
+      handles: "n",
+      animate: true,
+      animateDuration: "slow",
+      animateEasing: "swing",
+      preventDefault: true,
+      preserveCursor: true,
+      autoHide: true,
+      ghost: true
+    });
+  });
+// ]]>
+</script>
+{/literal}
+{/if}
+
+
+{if $page == 'report'}
+<fieldset>
+	<legend>{'Members summary'|@translate}</legend>
+<p>{'Registration counter: %s'|@translate|sprintf:$Members.count} - {'Most members ever online was %s on %s'|@Whois_most:$Members.max:$Members.When:'Y-m-d H:i'}</p> 
+</fieldset>
+{if !empty($search_results) }
+<fieldset>
+	<legend>{'Available filters'|@translate}</legend>
+	<p>
+		<a href="{$Whois_url}reload.php?req=members"		class="load"	id="members" title="{'Monitored members'|@translate}">{'Members'|@translate}</a> - 
+		<a href="{$Whois_url}reload.php?req=guest"			class="load"	id="guest" title="{'Captured guests'|@translate}">{'Guests'|@translate}</a> - 
+		<a href="{$Whois_url}reload.php?req=less_24"		class="load"	id="less_24" title="{'Last 24h accesses'|@translate}">{'Recents (less 24h)'|@translate}</a> - 
+		<a href="{$Whois_url}reload.php?req=over_24"		class="load"	id="over_24" title="{'More than 24h accesses'|@translate}">{'More than 24h'|@translate}</a> - 
+		<a href="{$Whois_url}reload.php?req=pics"				class="load"	id="pics" title="{'Pictures accesses'|@translate}">{'On pictures'|@translate}</a> - 
+		<a href="{$Whois_url}reload.php?req=no_pic"			class="load"	id="no_pic" title="{'No picture accesses'|@translate}">{'Categories only'|@translate}</a> - 
+		<a href="{$Whois_url}reload.php?req=no_country"	class="load"	id="no_country" title="{'Unidentifed countries'|@translate}">{'No country'|@translate}</a> - 
+		<a href="{$Whois_url}reload.php?req=single"			class="load"	id="single" title="{'Only one day accesses'|@translate}">{'One day'|@translate}</a> - 
+		<a href="{$Whois_url}reload.php?req=multi"			class="load"	id="multi" title="{'Several days accesses or over midnight'|@translate}">{'Several days'|@translate}</a> - 
+		<a href="{$Whois_url}reload.php?req=IPs"				class="load"	id="IPs" title="{'Several identified IPs (Only the first one is kept)'|@translate}">{'Several IPs'|@translate}</a> 
+	</p>
+</fieldset>
+
+<fieldset>
+	<legend>{'User access details'|@translate}</legend>
+<div id="reloadable">
+{include file="../../.`$Whois_url`report.tpl"}
+</div>
+</fieldset>
+{else}
+{'No data available'|@translate}
+{/if}
+
+{html_head}
+{literal}
+<script type="text/javascript">// <![CDATA[
+$(document).ready(function () {  
+  $("a.load")
+  .click(function() {
+  $("#reloadable").load(this.href);
+    return false;
+  });
+});
+// ]]>
+</script>
+{/literal}
+{/html_head}
+
+{/if}
+</form>
+
+{html_head}
+<link rel="stylesheet" type="text/css" href="{$Whois_path|@cat:'online.css'}"> 
+{/html_head}
+{known_script id="jquery.ui" src=$ROOT_URL|@cat:"template-common/lib/ui/ui.core.packed.js"}
+{known_script id="jquery.cluetip" src=$ROOT_URL|@cat:"template-common/lib/plugins/jquery.cluetip.packed.js"}
+{known_script id="jquery.tablesorter" src=$Whois_path|@cat:"jquery/tablesorter/jquery.tablesorter.min.js"}
Index: /extensions/whois_online/default.tpl
===================================================================
--- /extensions/whois_online/default.tpl	(revision 3319)
+++ /extensions/whois_online/default.tpl	(revision 3319)
@@ -0,0 +1,44 @@
+<div class="Online" style="float:right;text-align:center;margin-right:25px; margin-bottom:35px;">
+{if $Whois.Total > 0 and !$Whois.Slideshow}
+	{'Total hits:'|@translate} {if (is_admin())}<a href="./admin.php?page=plugin&amp;section=whois_online%2Fconfig.php&amp;tab=report" class="other">{$Whois.Total}</a>{else}{$Whois.Total}{/if}
+
+	{if $Whois.Current_10mins > 0}
+	<br />{if $Whois.Seen_url>''}<a href="{$Whois.Seen_url}" title="{'Your recently viewed pictures'|@translate}">{/if}
+	{'Most recent 10 minutes hits:'|@translate}
+	{if $Whois.Seen_url>''}</a>{/if}
+	 {$Whois.Current_10mins}
+	{/if}
+
+	<br />
+	{if $Whois.Review_url>''}<a href="{$Whois.Review_url}" title="{'Some of recently viewed pictures by other users'|@translate}">{/if}
+	{'Current hour hits:'|@translate}
+	{if $Whois.Review_url>''}</a>{/if}
+	 {$Whois.Current_hour}
+
+	{if $Whois.Yesterday > 0}
+	<br />
+	{'Yesterday hits:'|@translate} {$Whois.Yesterday}
+	{/if}
+
+	{if $Whois.Users_Last_day > 0}
+	<br />
+	{'Last 24h users:'|@translate} {$Whois.Users_Last_day}
+	{/if}
+
+	{if $Whois.Users_Last_hour > 0}
+	<br />
+	{'Last hour online users:'|@translate} {$Whois.Users_Last_hour}
+	{/if}
+
+	{if $Whois.Guests > 0}
+	<br />
+	{'Recent guest(s):'|@translate} {$Whois.Guests}
+	{/if}
+
+	{if count($Whois.Online) > 0}
+	<br />
+	{'Recent member(s):'|@translate} {','|@implode:$Whois.Online|@substr:0:70}{if (strlen(implode(',',$Whois.Online))>70)}...{/if}
+	{/if}
+	
+{/if}
+</div>
Index: /extensions/whois_online/flags/index.php
===================================================================
--- /extensions/whois_online/flags/index.php	(revision 3319)
+++ /extensions/whois_online/flags/index.php	(revision 3319)
@@ -0,0 +1,30 @@
+<?php
+// +-----------------------------------------------------------------------+
+// | Piwigo - a PHP based picture gallery                                  |
+// +-----------------------------------------------------------------------+
+// | Copyright(C) 2008-2009 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/whois_online/icons/index.php
===================================================================
--- /extensions/whois_online/icons/index.php	(revision 3319)
+++ /extensions/whois_online/icons/index.php	(revision 3319)
@@ -0,0 +1,30 @@
+<?php
+// +-----------------------------------------------------------------------+
+// | Piwigo - a PHP based picture gallery                                  |
+// +-----------------------------------------------------------------------+
+// | Copyright(C) 2008-2009 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/whois_online/jquery/index.php
===================================================================
--- /extensions/whois_online/jquery/index.php	(revision 3319)
+++ /extensions/whois_online/jquery/index.php	(revision 3319)
@@ -0,0 +1,30 @@
+<?php
+// +-----------------------------------------------------------------------+
+// | Piwigo - a PHP based picture gallery                                  |
+// +-----------------------------------------------------------------------+
+// | Copyright(C) 2008-2009 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/whois_online/jquery/tablesorter/index.php
===================================================================
--- /extensions/whois_online/jquery/tablesorter/index.php	(revision 3319)
+++ /extensions/whois_online/jquery/tablesorter/index.php	(revision 3319)
@@ -0,0 +1,30 @@
+<?php
+// +-----------------------------------------------------------------------+
+// | Piwigo - a PHP based picture gallery                                  |
+// +-----------------------------------------------------------------------+
+// | Copyright(C) 2008-2009 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/whois_online/jquery/tablesorter/jquery.tablesorter.min.js
===================================================================
--- /extensions/whois_online/jquery/tablesorter/jquery.tablesorter.min.js	(revision 3319)
+++ /extensions/whois_online/jquery/tablesorter/jquery.tablesorter.min.js	(revision 3319)
@@ -0,0 +1,2 @@
+
+(function($){$.extend({tablesorter:new function(){var parsers=[],widgets=[];this.defaults={cssHeader:"header",cssAsc:"headerSortUp",cssDesc:"headerSortDown",sortInitialOrder:"asc",sortMultiSortKey:"shiftKey",sortForce:null,sortAppend:null,textExtraction:"simple",parsers:{},widgets:[],widgetZebra:{css:["even","odd"]},headers:{},widthFixed:false,cancelSelection:true,sortList:[],headerList:[],dateFormat:"us",decimal:'.',debug:false};function benchmark(s,d){log(s+","+(new Date().getTime()-d.getTime())+"ms");}this.benchmark=benchmark;function log(s){if(typeof console!="undefined"&&typeof console.debug!="undefined"){console.log(s);}else{alert(s);}}function buildParserCache(table,$headers){if(table.config.debug){var parsersDebug="";}var rows=table.tBodies[0].rows;if(table.tBodies[0].rows[0]){var list=[],cells=rows[0].cells,l=cells.length;for(var i=0;i<l;i++){var p=false;if($.metadata&&($($headers[i]).metadata()&&$($headers[i]).metadata().sorter)){p=getParserById($($headers[i]).metadata().sorter);}else if((table.config.headers[i]&&table.config.headers[i].sorter)){p=getParserById(table.config.headers[i].sorter);}if(!p){p=detectParserForColumn(table,cells[i]);}if(table.config.debug){parsersDebug+="column:"+i+" parser:"+p.id+"\n";}list.push(p);}}if(table.config.debug){log(parsersDebug);}return list;};function detectParserForColumn(table,node){var l=parsers.length;for(var i=1;i<l;i++){if(parsers[i].is($.trim(getElementText(table.config,node)),table,node)){return parsers[i];}}return parsers[0];}function getParserById(name){var l=parsers.length;for(var i=0;i<l;i++){if(parsers[i].id.toLowerCase()==name.toLowerCase()){return parsers[i];}}return false;}function buildCache(table){if(table.config.debug){var cacheTime=new Date();}var totalRows=(table.tBodies[0]&&table.tBodies[0].rows.length)||0,totalCells=(table.tBodies[0].rows[0]&&table.tBodies[0].rows[0].cells.length)||0,parsers=table.config.parsers,cache={row:[],normalized:[]};for(var i=0;i<totalRows;++i){var c=table.tBodies[0].rows[i],cols=[];cache.row.push($(c));for(var j=0;j<totalCells;++j){cols.push(parsers[j].format(getElementText(table.config,c.cells[j]),table,c.cells[j]));}cols.push(i);cache.normalized.push(cols);cols=null;};if(table.config.debug){benchmark("Building cache for "+totalRows+" rows:",cacheTime);}return cache;};function getElementText(config,node){if(!node)return"";var t="";if(config.textExtraction=="simple"){if(node.childNodes[0]&&node.childNodes[0].hasChildNodes()){t=node.childNodes[0].innerHTML;}else{t=node.innerHTML;}}else{if(typeof(config.textExtraction)=="function"){t=config.textExtraction(node);}else{t=$(node).text();}}return t;}function appendToTable(table,cache){if(table.config.debug){var appendTime=new Date()}var c=cache,r=c.row,n=c.normalized,totalRows=n.length,checkCell=(n[0].length-1),tableBody=$(table.tBodies[0]),rows=[];for(var i=0;i<totalRows;i++){rows.push(r[n[i][checkCell]]);if(!table.config.appender){var o=r[n[i][checkCell]];var l=o.length;for(var j=0;j<l;j++){tableBody[0].appendChild(o[j]);}}}if(table.config.appender){table.config.appender(table,rows);}rows=null;if(table.config.debug){benchmark("Rebuilt table:",appendTime);}applyWidget(table);setTimeout(function(){$(table).trigger("sortEnd");},0);};function buildHeaders(table){if(table.config.debug){var time=new Date();}var meta=($.metadata)?true:false,tableHeadersRows=[];for(var i=0;i<table.tHead.rows.length;i++){tableHeadersRows[i]=0;};$tableHeaders=$("thead th",table);$tableHeaders.each(function(index){this.count=0;this.column=index;this.order=formatSortingOrder(table.config.sortInitialOrder);if(checkHeaderMetadata(this)||checkHeaderOptions(table,index))this.sortDisabled=true;if(!this.sortDisabled){$(this).addClass(table.config.cssHeader);}table.config.headerList[index]=this;});if(table.config.debug){benchmark("Built headers:",time);log($tableHeaders);}return $tableHeaders;};function checkCellColSpan(table,rows,row){var arr=[],r=table.tHead.rows,c=r[row].cells;for(var i=0;i<c.length;i++){var cell=c[i];if(cell.colSpan>1){arr=arr.concat(checkCellColSpan(table,headerArr,row++));}else{if(table.tHead.length==1||(cell.rowSpan>1||!r[row+1])){arr.push(cell);}}}return arr;};function checkHeaderMetadata(cell){if(($.metadata)&&($(cell).metadata().sorter===false)){return true;};return false;}function checkHeaderOptions(table,i){if((table.config.headers[i])&&(table.config.headers[i].sorter===false)){return true;};return false;}function applyWidget(table){var c=table.config.widgets;var l=c.length;for(var i=0;i<l;i++){getWidgetById(c[i]).format(table);}}function getWidgetById(name){var l=widgets.length;for(var i=0;i<l;i++){if(widgets[i].id.toLowerCase()==name.toLowerCase()){return widgets[i];}}};function formatSortingOrder(v){if(typeof(v)!="Number"){i=(v.toLowerCase()=="desc")?1:0;}else{i=(v==(0||1))?v:0;}return i;}function isValueInArray(v,a){var l=a.length;for(var i=0;i<l;i++){if(a[i][0]==v){return true;}}return false;}function setHeadersCss(table,$headers,list,css){$headers.removeClass(css[0]).removeClass(css[1]);var h=[];$headers.each(function(offset){if(!this.sortDisabled){h[this.column]=$(this);}});var l=list.length;for(var i=0;i<l;i++){h[list[i][0]].addClass(css[list[i][1]]);}}function fixColumnWidth(table,$headers){var c=table.config;if(c.widthFixed){var colgroup=$('<colgroup>');$("tr:first td",table.tBodies[0]).each(function(){colgroup.append($('<col>').css('width',$(this).width()));});$(table).prepend(colgroup);};}function updateHeaderSortCount(table,sortList){var c=table.config,l=sortList.length;for(var i=0;i<l;i++){var s=sortList[i],o=c.headerList[s[0]];o.count=s[1];o.count++;}}function multisort(table,sortList,cache){if(table.config.debug){var sortTime=new Date();}var dynamicExp="var sortWrapper = function(a,b) {",l=sortList.length;for(var i=0;i<l;i++){var c=sortList[i][0];var order=sortList[i][1];var s=(getCachedSortType(table.config.parsers,c)=="text")?((order==0)?"sortText":"sortTextDesc"):((order==0)?"sortNumeric":"sortNumericDesc");var e="e"+i;dynamicExp+="var "+e+" = "+s+"(a["+c+"],b["+c+"]); ";dynamicExp+="if("+e+") { return "+e+"; } ";dynamicExp+="else { ";}var orgOrderCol=cache.normalized[0].length-1;dynamicExp+="return a["+orgOrderCol+"]-b["+orgOrderCol+"];";for(var i=0;i<l;i++){dynamicExp+="}; ";}dynamicExp+="return 0; ";dynamicExp+="}; ";eval(dynamicExp);cache.normalized.sort(sortWrapper);if(table.config.debug){benchmark("Sorting on "+sortList.toString()+" and dir "+order+" time:",sortTime);}return cache;};function sortText(a,b){return((a<b)?-1:((a>b)?1:0));};function sortTextDesc(a,b){return((b<a)?-1:((b>a)?1:0));};function sortNumeric(a,b){return a-b;};function sortNumericDesc(a,b){return b-a;};function getCachedSortType(parsers,i){return parsers[i].type;};this.construct=function(settings){return this.each(function(){if(!this.tHead||!this.tBodies)return;var $this,$document,$headers,cache,config,shiftDown=0,sortOrder;this.config={};config=$.extend(this.config,$.tablesorter.defaults,settings);$this=$(this);$headers=buildHeaders(this);this.config.parsers=buildParserCache(this,$headers);cache=buildCache(this);var sortCSS=[config.cssDesc,config.cssAsc];fixColumnWidth(this);$headers.click(function(e){$this.trigger("sortStart");var totalRows=($this[0].tBodies[0]&&$this[0].tBodies[0].rows.length)||0;if(!this.sortDisabled&&totalRows>0){var $cell=$(this);var i=this.column;this.order=this.count++%2;if(!e[config.sortMultiSortKey]){config.sortList=[];if(config.sortForce!=null){var a=config.sortForce;for(var j=0;j<a.length;j++){if(a[j][0]!=i){config.sortList.push(a[j]);}}}config.sortList.push([i,this.order]);}else{if(isValueInArray(i,config.sortList)){for(var j=0;j<config.sortList.length;j++){var s=config.sortList[j],o=config.headerList[s[0]];if(s[0]==i){o.count=s[1];o.count++;s[1]=o.count%2;}}}else{config.sortList.push([i,this.order]);}};setTimeout(function(){setHeadersCss($this[0],$headers,config.sortList,sortCSS);appendToTable($this[0],multisort($this[0],config.sortList,cache));},1);return false;}}).mousedown(function(){if(config.cancelSelection){this.onselectstart=function(){return false};return false;}});$this.bind("update",function(){this.config.parsers=buildParserCache(this,$headers);cache=buildCache(this);}).bind("sorton",function(e,list){$(this).trigger("sortStart");config.sortList=list;var sortList=config.sortList;updateHeaderSortCount(this,sortList);setHeadersCss(this,$headers,sortList,sortCSS);appendToTable(this,multisort(this,sortList,cache));}).bind("appendCache",function(){appendToTable(this,cache);}).bind("applyWidgetId",function(e,id){getWidgetById(id).format(this);}).bind("applyWidgets",function(){applyWidget(this);});if($.metadata&&($(this).metadata()&&$(this).metadata().sortlist)){config.sortList=$(this).metadata().sortlist;}if(config.sortList.length>0){$this.trigger("sorton",[config.sortList]);}applyWidget(this);});};this.addParser=function(parser){var l=parsers.length,a=true;for(var i=0;i<l;i++){if(parsers[i].id.toLowerCase()==parser.id.toLowerCase()){a=false;}}if(a){parsers.push(parser);};};this.addWidget=function(widget){widgets.push(widget);};this.formatFloat=function(s){var i=parseFloat(s);return(isNaN(i))?0:i;};this.formatInt=function(s){var i=parseInt(s);return(isNaN(i))?0:i;};this.isDigit=function(s,config){var DECIMAL='\\'+config.decimal;var exp='/(^[+]?0('+DECIMAL+'0+)?$)|(^([-+]?[1-9][0-9]*)$)|(^([-+]?((0?|[1-9][0-9]*)'+DECIMAL+'(0*[1-9][0-9]*)))$)|(^[-+]?[1-9]+[0-9]*'+DECIMAL+'0+$)/';return RegExp(exp).test($.trim(s));};this.clearTableBody=function(table){if($.browser.msie){function empty(){while(this.firstChild)this.removeChild(this.firstChild);}empty.apply(table.tBodies[0]);}else{table.tBodies[0].innerHTML="";}};}});$.fn.extend({tablesorter:$.tablesorter.construct});var ts=$.tablesorter;ts.addParser({id:"text",is:function(s){return true;},format:function(s){return $.trim(s.toLowerCase());},type:"text"});ts.addParser({id:"digit",is:function(s,table){var c=table.config;return $.tablesorter.isDigit(s,c);},format:function(s){return $.tablesorter.formatFloat(s);},type:"numeric"});ts.addParser({id:"currency",is:function(s){return/^[£$€?.]/.test(s);},format:function(s){return $.tablesorter.formatFloat(s.replace(new RegExp(/[^0-9.]/g),""));},type:"numeric"});ts.addParser({id:"ipAddress",is:function(s){return/^\d{2,3}[\.]\d{2,3}[\.]\d{2,3}[\.]\d{2,3}$/.test(s);},format:function(s){var a=s.split("."),r="",l=a.length;for(var i=0;i<l;i++){var item=a[i];if(item.length==2){r+="0"+item;}else{r+=item;}}return $.tablesorter.formatFloat(r);},type:"numeric"});ts.addParser({id:"url",is:function(s){return/^(https?|ftp|file):\/\/$/.test(s);},format:function(s){return jQuery.trim(s.replace(new RegExp(/(https?|ftp|file):\/\//),''));},type:"text"});ts.addParser({id:"isoDate",is:function(s){return/^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(s);},format:function(s){return $.tablesorter.formatFloat((s!="")?new Date(s.replace(new RegExp(/-/g),"/")).getTime():"0");},type:"numeric"});ts.addParser({id:"percent",is:function(s){return/\%$/.test($.trim(s));},format:function(s){return $.tablesorter.formatFloat(s.replace(new RegExp(/%/g),""));},type:"numeric"});ts.addParser({id:"usLongDate",is:function(s){return s.match(new RegExp(/^[A-Za-z]{3,10}\.? [0-9]{1,2}, ([0-9]{4}|'?[0-9]{2}) (([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(AM|PM)))$/));},format:function(s){return $.tablesorter.formatFloat(new Date(s).getTime());},type:"numeric"});ts.addParser({id:"shortDate",is:function(s){return/\d{1,2}[\/\-]\d{1,2}[\/\-]\d{2,4}/.test(s);},format:function(s,table){var c=table.config;s=s.replace(/\-/g,"/");if(c.dateFormat=="us"){s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/,"$3/$1/$2");}else if(c.dateFormat=="uk"){s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/,"$3/$2/$1");}else if(c.dateFormat=="dd/mm/yy"||c.dateFormat=="dd-mm-yy"){s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{2})/,"$1/$2/$3");}return $.tablesorter.formatFloat(new Date(s).getTime());},type:"numeric"});ts.addParser({id:"time",is:function(s){return/^(([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(am|pm)))$/.test(s);},format:function(s){return $.tablesorter.formatFloat(new Date("2000/01/01 "+s).getTime());},type:"numeric"});ts.addParser({id:"metadata",is:function(s){return false;},format:function(s,table,cell){var c=table.config,p=(!c.parserMetadataName)?'sortValue':c.parserMetadataName;return $(cell).metadata()[p];},type:"numeric"});ts.addWidget({id:"zebra",format:function(table){if(table.config.debug){var time=new Date();}$("tr:visible",table.tBodies[0]).filter(':even').removeClass(table.config.widgetZebra.css[1]).addClass(table.config.widgetZebra.css[0]).end().filter(':odd').removeClass(table.config.widgetZebra.css[0]).addClass(table.config.widgetZebra.css[1]);if(table.config.debug){$.tablesorter.benchmark("Applying Zebra widget",time);}}});})(jQuery);
Index: /extensions/whois_online/language/en_UK/index.php
===================================================================
--- /extensions/whois_online/language/en_UK/index.php	(revision 3319)
+++ /extensions/whois_online/language/en_UK/index.php	(revision 3319)
@@ -0,0 +1,30 @@
+<?php
+// +-----------------------------------------------------------------------+
+// | Piwigo - a PHP based picture gallery                                  |
+// +-----------------------------------------------------------------------+
+// | Copyright(C) 2008-2009 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/whois_online/language/en_UK/plugin.lang.php
===================================================================
--- /extensions/whois_online/language/en_UK/plugin.lang.php	(revision 3319)
+++ /extensions/whois_online/language/en_UK/plugin.lang.php	(revision 3319)
@@ -0,0 +1,117 @@
+<?php
+$lang['Monitor'] = 'Monitor';
+$lang['Active capture'] = 'Active capture';
+$lang['Delete level [10-200] (ratio between obsolete and active)'] = 
+	'Delete level [10-200] (ratio between obsolete and active)';
+$lang['Obsolete limit [20-100] (obsolete data count)'] = 
+	'Obsolete limit [20-100] (obsolete data count)';
+$lang['Add link to Plugins menu'] = 'Add link to Plugins menu';
+$lang['Keep data even if plugin is deactivated/uninstall'] = 
+	'Keep data even if plugin is deactivated/uninstall';
+$lang['Advanced users: template vars are available in all cases and might be included in your extensions'] = 
+	'Advanced users: template vars are available in all cases and might be included in your extensions';
+$lang['Default display'] = 'Default display';
+$lang['Total hits:'] = 'Total hits:';
+//$lang['Image hits:'] = 'Image hits:';
+//$lang['other hits:'] = 'other hits:';
+$lang['Your recently viewed pictures'] = 'Your recently viewed pictures';
+$lang['Most recent 10 minutes hits:'] = 'Most recent 10 minutes hits:';
+$lang['Some of recently viewed pictures by other users'] = 
+	'Some of recently viewed pictures by other users';
+$lang['Current hour hits:'] = 'Current hour hits:';
+$lang['Yesterday hits:'] = 'Yesterday hits:';
+$lang['Last 24h users:'] = 'Last 24 hours visitors:';
+$lang['Last hour online users:'] = 'Current hour visitors:';
+$lang['Recent guest(s):'] = 'Recent guest(s):';
+$lang['Recent member(s):'] = 'Recent member(s):';
+$lang['Permanence/Durability of user monitoring'] = 'Permanence/Durability of user monitoring';
+//$lang['Next version enhancements: Set/Unset of permanence, Cleaning, and detail reporting'] = 
+//	'Next version enhancements: Set/Unset of permanence, Cleaning, and detail reporting';
+$lang['Whois_review'] = 'Recently viewed by you';
+$lang['Whois_others'] = 'Recently viewed by others'; /* or you a long time ago */
+$lang['Add icon to History'] = 'Add icon to History';
+
+// Added 2.0.e
+$lang['Radar limit'] = 'Radar limit';
+$lang['Users with image cluetips [10-200]'] = 'Users with image cluetips [10-200]';
+$lang['Default %s'] = 'Default %s';
+$lang['Default as anybody'] = 'Default as anybody';
+$lang['Webmasters management:'] = 'Webmasters management:';
+$lang['Exclude'] = 'Exclude';
+$lang['Hidden'] = 'Hidden';
+$lang['As anybody'] = 'As anybody';
+$lang['Administrators management:'] = 'Administrators management:';
+$lang['Your `%s` table summary'] = 'Your `%s` table summary';
+$lang['Compress it!'] = 'Compress it!';
+$lang[' => Delete old guests access (over 3 days), and optimize table and index.'] = 
+	' => Delete old guests access (over 3 days), and optimize table and index.';
+$lang['Space used: %s'] = 'Space used: %s';
+$lang['Unused allocated space: <strong>%s</strong>'] = 'Unused allocated space: <strong>%s</strong>';
+$lang['Traced sessions: %s'] = 'Traced sessions: %s';
+$lang['Altered/created since: %s'] = 'Altered/created since: %s';
+$lang['Clearing'] = 'Clearing';
+$lang['Clear temporary users (minimal delay is 6 minutes). To clean any permanent users, switch them before in the right list above.'] = 
+	'Clear temporary users (minimal delay is 6 minutes). To clean any permanent users, switch them before in the right list above.';
+$lang['Delete'] = 'Delete';
+$lang['Members summary'] = 'Members summary';
+$lang['Registration counter: %s'] = 'Registration counter: %s';
+$lang['Most members ever online was %s on %s'] = 'Most members ever online was %s on %s';
+$lang['Y-m-d H:i'] = 'F dS, Y g:i A';
+$lang['Available filters'] = 'Available filters';
+$lang['Monitored members'] = 'Monitored members';
+$lang['Captured guests'] = 'Captured guests';
+$lang['Last 24h accesses'] = 'Last 24h accesses';
+$lang['More than 24h accesses'] = 'More than 24h accesses';
+$lang['Pictures accesses'] = 'Pictures accesses';
+$lang['No picture accesses'] = 'No picture accesses';
+$lang['Unidentifed countries'] = 'Unidentifed countries';
+$lang['Only one day accesses'] = 'Only one day accesses';
+$lang['Several days accesses or over midnight'] = 'Several days accesses or over midnight';
+$lang['Several identified IPs (Only the first one is kept)'] = 'Several identified IPs (Only the first one is kept)';
+$lang['User access details'] = 'User access details';
+$lang['No data available'] = 'No data available';
+$lang['users'] = 'Users';
+$lang['First access'] = 'First access';
+$lang['Level'] = 'Level';
+$lang['Images (Modify)'] = 'Images (Modify)';
+$lang['Last access'] = 'Last access';
+$lang['User:'] = 'User:';
+$lang['(Multiple IP)'] = '(Multiple IP)';
+$lang['Registered since'] = 'Registered since';
+$lang['Hits since'] = 'Hits since';
+$lang['on pictures'] = 'on pictures';
+$lang['on pages'] = 'on pages';
+$lang['Level %d'] = 'Level %d';
+$lang['Image privacy level is higher than the user privacy level (Any change of one of them?)'] = 
+	'Image privacy level is higher than the user privacy level (Any change of one of them?)';
+$lang[' - Over the radar limit => No level control'] = ' - Over the radar limit => No level control';
+$lang['Previous connection dates'] = 'Previous connection dates';
+$lang[': provides newcomers\' localization and possibly new country flags, thanks to them.'] = 
+	': provides newcomers\' localization and possibly new country flags, thanks to them.';
+$lang[': provides IP geolocalization on request (link on flag). Useful for unknown countries.'] =
+	': provides IP geolocalization on request (link on flag). Useful for unknown countries.';
+$lang['Report'] = 'Radar Report';
+$lang['Error range: '] = 'Error range: ';
+$lang['Radar_limit [10-200] (Users with image cluetips on radar page)'] = 
+	'Radar_limit [10-200] (Users with image cluetips on radar page)';
+$lang['User follow up error'] = 'User follow up error';
+$lang['You are Adviser and you are not authorized to change this configuration.'] = 
+	'You are Adviser and you are not authorized to change this configuration.';
+$lang['Configuration has been saved.'] = 'Configuration has been saved.';
+$lang['Permanent users (3 months min)'] = 'Permanent users (3 months min)';
+$lang['Temporary users (around 72 hours)'] = 'Temporary users (around 72 hours)';
+$lang['Unknown country'] = 'Unknown country';
+$lang['Deleted language'] = 'Deleted language';
+$lang['Recents (less 24h)'] = 'Recents (less 24h)';
+$lang['More than 24h'] = 'More than 24h';
+$lang['On pictures'] = 'On pictures';
+$lang['Categories only'] = 'Categories only';
+$lang['No country'] = 'No country';
+$lang['One day'] = 'One day';
+$lang['Several days'] = 'Several days';
+$lang['Several IPs'] = 'Several IPs';
+$lang['http:geoiptool'] = 'http://www.geoiptool.com/en/?IP=';
+$lang[':geoiptool:title']= 'My IP Address Lookup and GeoTargeting information';
+$lang['http:hostip'] = 'http://www.hostip.info';
+$lang[':hostip:title'] = 'My IP Address Lookup and GeoTargeting Community Geotarget IP Project - what country, city IP addresses map to';
+?>
Index: /extensions/whois_online/language/fr_FR/index.php
===================================================================
--- /extensions/whois_online/language/fr_FR/index.php	(revision 3319)
+++ /extensions/whois_online/language/fr_FR/index.php	(revision 3319)
@@ -0,0 +1,30 @@
+<?php
+// +-----------------------------------------------------------------------+
+// | Piwigo - a PHP based picture gallery                                  |
+// +-----------------------------------------------------------------------+
+// | Copyright(C) 2008-2009 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/whois_online/language/fr_FR/plugin.lang.php
===================================================================
--- /extensions/whois_online/language/fr_FR/plugin.lang.php	(revision 3319)
+++ /extensions/whois_online/language/fr_FR/plugin.lang.php	(revision 3319)
@@ -0,0 +1,117 @@
+<?php 
+$lang['Monitor'] = "Suivi et nettoyage";
+$lang['Active capture'] = "Activer la capture des accès";
+$lang['Delete level [10-200] (ratio between obsolete and active)'] = 
+	"Seuil de nettoyage [10-200] (rapport entre données obsolètes et actives)";
+$lang['Obsolete limit [20-100] (obsolete data count)'] = 
+	"Limite d'inactifs [20-100] (nombre maximum d'anciens enregistrements)";
+$lang['Add link to Plugins menu'] = "Ajouter le lien dans le menu des Plugins";
+$lang['Keep data even if plugin is deactivated/uninstall'] = 
+	"Conserver les données même si le plugin est désactivé/désinstallé";
+$lang['Advanced users: template vars are available in all cases and might be included in your extensions'] = 
+	"Utilisateurs avancés: les variables de templates sont disponibles dans tous les cas et peuvent être incluses dans vos extensions";
+$lang['Default display'] = "Utiliser l'affichage par défaut";
+$lang['Total hits:'] = "Nombre de pages vues (miniatures ou images) :";
+//$lang['Image hits:'] = "Pages d'images vues :";
+//$lang['other hits:'] = "Autres pages :";
+$lang['Your recently viewed pictures'] = "Vos dernières consultations";
+$lang['Most recent 10 minutes hits:'] = "Consultations des 10 dernières minutes :";
+$lang['Some of recently viewed pictures by other users'] = 
+	"Dernières consultations des autres visiteurs";
+$lang['Current hour hits:'] = "Nombre de pages vues des 60 dernières minutes :";
+$lang['Yesterday hits:'] = "Nombre de consultations d'hier:";
+$lang['Last 24h users:'] = "Nombre de visiteurs des dernières 24h :";
+$lang['Last hour online users:'] = "Visiteurs des 60 dernières minutes:";
+$lang['Recent guest(s):'] = "Visiteur(s) récents:";
+$lang['Recent member(s):'] = "Membre(s) récemment connectés :";
+$lang['Permanence/Durability of user monitoring'] = "Suivi des utilisateurs (Permanence et Présence)";
+//$lang['Next version enhancements: Set/Unset of permanence, Cleaning, and detail reporting'] = 
+//	"Améliorations de la prochaine version: Activation de la permanence du suivi, Nettoyage, et liste détaillée des accès.";
+$lang['Whois_review'] = "Récemment vues par vous";
+$lang['Whois_others'] = "Récemment vues par d'autres";
+$lang['Add icon to History'] = "Ajouter l'icone après le lien Historique";
+
+// Added 2.0.e
+$lang['Radar limit'] = 'Profondeur du radar';
+$lang['Users with image cluetips [10-200]'] = 'Nombre de visiteurs avec des infobulles sur les images [10-200]';
+$lang['Default %s'] = 'Valeur par défaut : %s';
+$lang['Default as anybody'] = 'Valeur par défaut: Normal';
+$lang['Webmasters management:'] = 'Gestion du/des Webmestres :';
+$lang['Exclude'] = 'Exclue';
+$lang['Hidden'] = 'Cachée';
+$lang['As anybody'] = 'Normale';
+$lang['Administrators management:'] = 'Gestion des Administrateurs :';
+$lang['Your `%s` table summary'] = 'Résumé de votre table `%s` ';
+$lang['Compress it!'] = 'Compressez la table!';
+$lang[' => Delete old guests access (over 3 days), and optimize table and index.'] = 
+	' => Supprimer les accès des anciens visiteurs (de plus de 3 jours), et optimiser la table et l\'index.';
+$lang['Space used: %s'] = 'Espace utilisé : %s';
+$lang['Unused allocated space: <strong>%s</strong>'] = 'Espace inutilisé et même perdu : <strong>%s</strong>';
+$lang['Traced sessions: %s'] = 'Sessions suivies : %s';
+$lang['Altered/created since: %s'] = 'Modifiée/Créée le : %s';
+$lang['Clearing'] = 'Nettoyage';
+$lang['Clear temporary users (minimal delay is 6 minutes). To clean any permanent users, switch them before in the right list above.'] = 
+	'Retrait des membres temporaires (minimum de 6 minutes sans activité). Pour retirer un membre permanent, le déplacer avant dans la boite de droite ci-dessus.';
+$lang['Delete'] = 'Supprimer';
+$lang['Members summary'] = 'Suivi des Membres';
+$lang['Registration counter: %s'] = 'Nombre d\'enregistrements: %s';
+$lang['Most members ever online was %s on %s'] = 'En date du %2$s, le record du nombre de membres connectés simultanément est de %1$s !';
+$lang['Y-m-d H:i'] = 'd-m-Y à H\hi';
+$lang['Available filters'] = 'Filtres disponibles';
+$lang['Monitored members'] = 'Members suivis';
+$lang['Captured guests'] = 'Visiteurs capturés';
+$lang['Last 24h accesses'] = 'Accès de dernières 24h';
+$lang['More than 24h accesses'] = 'Accès + 24h';
+$lang['Pictures accesses'] = 'Accès aux images';
+$lang['No picture accesses'] = 'Accès sans image';
+$lang['Unidentifed countries'] = 'Pays inconnu';
+$lang['Only one day accesses'] = 'Un jour seulement';
+$lang['Several days accesses or over midnight'] = 'Accès sur plusieurs jours';
+$lang['Several identified IPs (Only the first one is kept)'] = 'Plusieurs adresses IP relevées (Uniquement la première est conservée)';
+$lang['User access details'] = 'Détails des accès de l\'utilisateur';
+$lang['No data available'] = 'Donnée indisponible';
+$lang['users'] = 'Utilisateurs';
+$lang['First access'] = '1er accès';
+$lang['Level'] = 'Niveau';
+$lang['Images (Modify)'] = 'Images (Modification)';
+$lang['Last access'] = 'Dernier accès';
+$lang['User:'] = 'Utilisateur :';
+$lang['(Multiple IP)'] = '(Plusieurs IP (société ?))';
+$lang['Registered since'] = 'Enregistré le';
+$lang['Hits since'] = 'Suivi depuis le';
+$lang['on pictures'] = 'Visites aux images';
+$lang['on pages'] = 'aux pages';
+$lang['Level %d'] = 'Niveau %d';
+$lang['Image privacy level is higher than the user privacy level (Any change of one of them?)'] = 
+	'Le niveau de confidentialité de l\'image est plus élevé que celui de l\'utilisateur (Un changement a été opéré?)';
+$lang[' - Over the radar limit => No level control'] = ' - Dépasse la profondeur du Radar => plus de contrôle de la confidentialité';
+$lang['Previous connection dates'] = 'Dates des connexions précédentes';
+$lang[': provides newcomers\' localization and possibly new country flags, thanks to them.'] = 
+	': identifie la provenance des nouveaux venus et au besoin fourni le drapeau du pays, merci à eux.';
+$lang[': provides IP geolocalization on request (link on flag). Useful for unknown countries.'] =
+	': propose à la demande une localisation géographique basée sur l\'adresse IP (lien sur le drapeau). Pratique pour tout pays inconnu.';
+$lang['Report'] = 'Le radar';
+$lang['Error range: '] = 'Erreur de valeurs: ';
+$lang['Radar_limit [10-200] (Users with image cluetips on radar page)'] = 
+	'La profondeur du radar [10-200] (Images avec des infobulles pour les accès des n premiers utilisateurs sur la page du radar)';
+$lang['User follow up error'] = 'Erreur de suivi de l\'utilisateur';
+$lang['You are Adviser and you are not authorized to change this configuration.'] = 
+	'Vous êtes en mode Conseillé et vous n\'êtes pas autorisé à changer la configuration.';
+$lang['Configuration has been saved.'] = 'Configuration sauvegardée.';
+$lang['Permanent users (3 months min)'] = 'Membres permanents (3 mois min)';
+$lang['Temporary users (around 72 hours)'] = 'Membres temporaires (72 heures et +)';
+$lang['Unknown country'] = 'Pays inconnu (ou société)';
+$lang['Deleted language'] = 'Langue retirée';
+$lang['Recents (less 24h)'] = 'Récents (<24h)';
+$lang['More than 24h'] = 'Plus de 24h';
+$lang['On pictures'] = 'Avec images';
+$lang['Categories only'] = 'Catégories seules';
+$lang['No country'] = 'Sans pays';
+$lang['One day'] = 'Un jour';
+$lang['Several days'] = 'Plusieurs jours';
+$lang['Several IPs'] = 'Plusieurs IP';
+$lang['http:geoiptool'] = 'http://www.geoiptool.com/fr/?IP=';
+$lang[':geoiptool:title']= 'My IP Address Lookup and GeoTargeting information';
+$lang['http:hostip'] = 'http://www.hostip.info';
+$lang[':hostip:title'] = 'My IP Address Lookup and GeoTargeting Community Geotarget IP Project - what country, city IP addresses map to';
+?>
Index: /extensions/whois_online/language/index.php
===================================================================
--- /extensions/whois_online/language/index.php	(revision 3319)
+++ /extensions/whois_online/language/index.php	(revision 3319)
@@ -0,0 +1,30 @@
+<?php
+// +-----------------------------------------------------------------------+
+// | Piwigo - a PHP based picture gallery                                  |
+// +-----------------------------------------------------------------------+
+// | Copyright(C) 2008-2009 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/whois_online/main.inc.php
===================================================================
--- /extensions/whois_online/main.inc.php	(revision 3319)
+++ /extensions/whois_online/main.inc.php	(revision 3319)
@@ -0,0 +1,75 @@
+<?php
+// +-----------------------------------------------------------------------+
+// | Piwigo - a PHP based picture gallery                                  |
+// +-----------------------------------------------------------------------+
+// | Copyright(C) 2008-2009 Piwigo Team                  http://piwigo.org |
+// | Copyright(C) 2003-2008 Piwigo 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.                                                                  |
+// +-----------------------------------------------------------------------+
+
+/*
+Plugin Name: Whois online
+Version: 2.0.i
+Description: Who is online?
+Plugin URI: http://fr.piwigo.org/ext/extension_view.php?eid=279
+Author: Piwigo team
+Author URI: http://www.vdigital.org
+*/
+/*
+
+/** History **
+  2009-05-xx 2.0.j
+						 Additionnal flags (Turkey)
+  2009-05-20 2.0.i
+						 Bug resolution.
+						 Icons removed due to tablesorter constraints.
+						 Active link style on active filter.
+						 Additionnal flags (Luxemburg, Austria, Malta, and some other revised)
+  2009-05-19 2.0.h
+						 Additional links to profile and permissions corrective path with filtering.
+						 Minor optimizations.
+						 Additionnal flags (Egypt, Indonesia, Malaysia)
+  2009-05-17 2.0.g
+						 htmlspecialchars for Countries (Some City have quoted names)
+						 Keep Previous config.
+						 Additional links to profile and permissions
+						 Additionnal flags
+  2009-05-12 2.0.e and 2.0.f
+						 IPV4 Localisation
+						 Monitoring Permanence/Temporary user lists 
+						 Reporting of User accesses
+						 Most connected
+						 And more...
+  2009-04-14 2.0.d 
+						 Icon on History can be removed
+						 Appropriate titles for both links
+  2009-04-14 2.0.c 
+	           Default display on admin pages even if not displayed on other pages
+						 Bug on History Search page
+						 Appropriate titles for both links on each first access (later "Random picture")
+  2009-04-13 2.0.b 
+	           Corrective of &review and &others
+						 Automatic upgrade
+*/
+define('WHOIS_ONLINE_VER', '2.0.i'); 
+global $prefixeTable, $conf;
+// $conf['debug_l10n'] = true;
+if (!defined('WHOIS_ONLINE_TABLE')) define('WHOIS_ONLINE_TABLE', $prefixeTable.'whois_online');
+define('WHOIS_ONLINE_DIR' , basename(dirname(__FILE__)));
+define('WHOIS_ONLINE_PATH' , PHPWG_PLUGINS_PATH . WHOIS_ONLINE_DIR . '/');
+include_once(WHOIS_ONLINE_PATH.'online.php');
+?>
Index: /extensions/whois_online/maintain.inc.php
===================================================================
--- /extensions/whois_online/maintain.inc.php	(revision 3319)
+++ /extensions/whois_online/maintain.inc.php	(revision 3319)
@@ -0,0 +1,106 @@
+<?php
+
+global $prefixeTable, $conf;
+if (!defined('PHPWG_ROOT_PATH')) die('Hacking attempt!');
+if (!defined('IN_ADMIN') or !IN_ADMIN) die('Hacking attempt!');
+if (!defined('WHOIS_ONLINE_TABLE')) define('WHOIS_ONLINE_TABLE', $prefixeTable.'whois_online');
+
+function plugin_activate()
+{
+	global $user;
+	$query = "CREATE TABLE IF NOT EXISTS ". WHOIS_ONLINE_TABLE ." (
+  `IP` varchar(39) NOT NULL default '',
+  `hidden_IP` enum('true','false') NOT NULL default 'false',
+  `session_id` varchar(40) NOT NULL,
+  `user_id` smallint(5) NOT NULL default '0',
+  `username` varchar(100) character set utf8 collate utf8_bin NOT NULL default '',
+  `lang` char(2) character set utf8 collate utf8_bin NOT NULL default 'en',
+  `country` VARCHAR( 256 ) NOT NULL default '',
+  `permanent` enum('true','false') NOT NULL default 'false',
+  `last_access` varchar(12) NOT NULL default '',
+  `last_elm_ids` varchar(75) NOT NULL default '',
+  `last_cat_ids` varchar(75) NOT NULL default '',
+  `last_tag_ids` varchar(75) NOT NULL default '',
+  `last_sch_ids` varchar(75) NOT NULL default '',
+  `first_access_date` varchar(45) NOT NULL default '',
+  `last_dates` varchar(110) character set utf8 collate utf8_bin NOT NULL default '',
+  `elm_hits` int(10) unsigned NOT NULL default '0',
+  `pag_hits` int(10) unsigned NOT NULL default '0',
+  `db_timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
+  PRIMARY KEY  (`session_id`)
+) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
+";
+	$result = pwg_query($query);
+	if (isset($conf['Whois Online'])) {
+		$conf_whois = unserialize($conf['Whois Online']);
+		if (!isset($conf_whois['Active'])) $conf_whois['Active'] = true;
+		if (!isset($conf_whois['Delete level'])) $conf_whois['Delete level'] = 20;
+		if (!isset($conf_whois['Radar limit'])) $conf_whois['Radar limit'] = 25;
+		if (!isset($conf_whois['Webmasters'])) $conf_whois['Webmasters'] = 2;
+		if (!isset($conf_whois['Administrators'])) $conf_whois['Administrators'] = 2;
+		if (!isset($conf_whois['Obsolete limit'])) $conf_whois['Obsolete limit'] = 20;
+		if (!isset($conf_whois['Add to Plugins menu'])) $conf_whois['Add to Plugins menu'] = false;
+		if (!isset($conf_whois['Add icon to History'])) $conf_whois['Add icon to History'] = true;
+		if (!isset($conf_whois['Keep data'])) $conf_whois['Keep data'] = true;
+		if (!isset($conf_whois['Default display'])) $conf_whois['Default display'] = true;
+		if (!isset($conf_whois['Search id'])) $conf_whois['Search id'] = 0;
+		if (!isset($conf_whois['Users'])) 
+			$conf_whois['Users'] = Array('max' => 0, 'When' => date('Y-m-d'), 'count' => 0);
+		$conf['Whois Online'] = serialize($conf_whois);
+	}
+	else {
+		$conf['Whois Online'] = serialize(Array(
+			'Active' => true,
+			'Delete level' => 20,
+			'Radar limit' => 25,
+			'Obsolete limit' => 20,
+			'Webmasters' => 2,
+			'Administrators' => 2,
+			'Search id' => 0,
+			'Users' => Array('max' => 0, 'When' => date('Y-m-d'), 'count' => 0),
+			'Add to Plugins menu' => false,
+			'Add icon to History' => true,
+			'Keep data' => true,
+			'Default display' => true,
+		));
+	}
+	pwg_query('REPLACE INTO ' . CONFIG_TABLE . " (param,value,comment)
+	VALUES ('Whois Online','". $conf['Whois Online'] ."','Whois Online configuration');");
+	$conf_whois = unserialize($conf['Whois Online']);
+	if (isset($conf_whois['Keep data']) and !$conf_whois['Keep data']) {
+		pwg_query('DELETE FROM ' . WHOIS_ONLINE_TABLE);
+	}
+	list($hits) = mysql_fetch_row(pwg_query('SELECT SUM(hit) FROM '.IMAGES_TABLE.';'));
+	$pags = floor($hits * 1.69); /* estimate : 1.69 is a frequent ratio between images hits and pages hits */
+	pwg_query('REPLACE INTO ' . WHOIS_ONLINE_TABLE . ' (`IP`, `hidden_IP`, `session_id`, `user_id`,`username`,`lang`,`permanent`,`last_access`,
+	`last_elm_ids`, `last_cat_ids`, `last_tag_ids`, `last_sch_ids`,
+	`first_access_date`, `last_dates`, `elm_hits`, `pag_hits`)
+		VALUES (\'global\', \'true\',\'global\', 0, \'Administrator\', \'--\', \'true\', \''
+		. time() .'\', \''. implode(' ',array_fill(0, 12, 0))
+		. '\', \''. implode(' ',array_fill(0, 14, 0))
+		. '\', \''. implode(' ',array_fill(0, 14, 0))
+		. '\', \''. implode(' ',array_fill(0, 14, 0))
+		. '\', \'' 
+		. date('Y-m-d') . '\', \'\', \'' 
+		. $hits . '\', \'' . $pags . '\');');
+}
+
+function plugin_deactivate()
+{
+	global $conf;
+	if (isset($conf['Whois Online'])) $conf_whois = unserialize($conf['Whois Online']);
+	if (isset($conf_whois['Keep data']) and !$conf_whois['Keep data']) 
+		pwg_query('DROP TABLE IF EXISTS ' . WHOIS_ONLINE_TABLE);
+}
+
+function plugin_uninstall()
+{
+	global $conf;
+	if (isset($conf['Whois Online'])) $conf_whois = unserialize($conf['Whois Online']);
+	if (isset($conf_whois['Keep data']) and !$conf_whois['Keep data']) {
+		pwg_query('DELETE FROM ' . CONFIG_TABLE . ' WHERE param = ' . "'Whois Online'");
+		pwg_query('DROP TABLE IF EXISTS ' . WHOIS_ONLINE_TABLE);
+		unset($conf['Whois Online']);
+	}
+}
+?>
Index: /extensions/whois_online/online.css
===================================================================
--- /extensions/whois_online/online.css	(revision 3319)
+++ /extensions/whois_online/online.css	(revision 3319)
@@ -0,0 +1,20 @@
+select.CleaningList { width: 100%; height:90px; }
+select.categoryList { height:90px; }
+td.right { text-align: right; }
+a .thumbbar {display: inline-block; color:#f70; background-color:#f70; width: 16px; }
+a:hover .thumbbar {display: inline-block; color:#f33; background-color:#f33; width: 16px; border: 1px solid #ff3363; }
+a.other { color: #666; text-decoration: none; 	border-bottom: none; }
+a.other:hover { text-decoration: none; border-bottom: none; }
+/* tables */
+.table2 thead tr .header {
+	background-image: url(icons/bg.gif); background-repeat: no-repeat;
+	background-position: center right; cursor: pointer;
+}
+.table2 thead tr .headerSortUp { background-image: url(icons/asc.gif); }
+.table2 thead tr .headerSortDown { background-image: url(icons/desc.gif); }
+.table2 thead tr .ns { background-image: none !important; }
+a.ws2 { display: inline-block; text-align: center; padding: 0px 1px; min-width: 21px; overflow: hidden; margin-left: 0px; margin-right: 1px; color: #666; background-color: #111; }
+a.ws2:hover { color: #f33; background-color: #f33; border-bottom: 1px solid #ff3363;}
+a.ws1 { display: inline-block; text-align: center; padding: 0px 1px; min-width: 21px; overflow: hidden; margin-left: 0px; margin-right: 1px; color: #666; background-color: #222; }
+a.ws1:hover { color: #f33; background-color: #f33; border-bottom: 1px solid #ff3363;}
+a.ws { color: #111; background-color: #f33 !important; }
Index: /extensions/whois_online/online.php
===================================================================
--- /extensions/whois_online/online.php	(revision 3319)
+++ /extensions/whois_online/online.php	(revision 3319)
@@ -0,0 +1,485 @@
+<?php
+
+if (!defined('PHPWG_ROOT_PATH')) die('Hacking attempt!');
+global $conf;
+
+/* Secure Config */
+
+$conf_whois = whois_online_conf();
+
+function whois_online_conf()
+{
+	global $conf;
+	$conf_whois = unserialize($conf['Whois Online']);
+	if (!isset($conf_whois['Active'])) $conf_whois['Active'] = true;
+	if (!isset($conf_whois['Delete level'])) $conf_whois['Delete level'] = 20;
+	if (!isset($conf_whois['Radar limit'])) $conf_whois['Radar limit'] = 25;
+	if (!isset($conf_whois['Webmasters'])) $conf_whois['Webmasters'] = 2;
+	if (!isset($conf_whois['Administrators'])) $conf_whois['Administrators'] = 2;
+	if (!isset($conf_whois['Obsolete limit'])) $conf_whois['Obsolete limit'] = 20;
+	if (!isset($conf_whois['Add to Plugins menu'])) $conf_whois['Add to Plugins menu'] = false;
+	if (!isset($conf_whois['Add icon to History'])) $conf_whois['Add icon to History'] = true;
+	if (!isset($conf_whois['Keep data'])) $conf_whois['Keep data'] = true;
+	if (!isset($conf_whois['Default display'])) $conf_whois['Default display'] = true;
+	if (!isset($conf_whois['Search id'])) $conf_whois['Search id'] = 0;
+	if (!isset($conf_whois['Users'])) 
+		$conf_whois['Users'] = Array('max' => 0, 'When' => date('Y-m-d'), 'count' => 0);
+	if (!isset($conf_whois['Version']) or $conf_whois['Version'] != WHOIS_ONLINE_VER
+		or $conf['Whois Online'] != serialize($conf_whois)) {
+		$conf_whois['Version'] = WHOIS_ONLINE_VER;
+		$conf['Whois Online'] = serialize($conf_whois);
+		pwg_query('REPLACE INTO ' . CONFIG_TABLE . " (param,value,comment)
+	  VALUES ('Whois Online','". $conf['Whois Online'] ."','Whois Online configuration');");
+	}
+	return $conf_whois;
+}
+
+define('ONLINE_LEVEL', (100+$conf_whois['Delete level'])/100);
+define('ONLINE_LIMIT', $conf_whois['Obsolete limit']);
+
+/* Admin menus are always available */
+$conf['Add to Plugins menu'] = $conf_whois['Add to Plugins menu'];
+$conf['Add icon to History'] = $conf_whois['Add icon to History'];
+add_event_handler('get_admin_plugin_menu_links', 'whois_add_icon' );
+/* On Active */
+if ($conf_whois['Active']) {
+	$conf['Whois Online Update'] = true;
+	add_event_handler('loc_begin_picture', 'whois_online_management');
+	add_event_handler('loc_begin_index', 'whois_online_management');
+	add_event_handler('register_user', 'whois_online_register');
+	if ($conf_whois['Default display'] or (defined('IN_ADMIN') and IN_ADMIN)) add_event_handler('loc_begin_page_tail', 'whois_default_display' );
+}
+
+/* --------------- Functions ----------------- */
+
+// pparse whois_online/default.tpl
+function whois_default_display() {
+	global $template;
+	$template->set_filenames(array( 'Whois_display' => dirname(__FILE__).'/default.tpl'));
+	$template->pparse('Whois_display');
+	// Based on get_enums(USER_INFOS_TABLE, 'status') ???
+}
+
+// Add admin links
+function whois_add_icon($menu) {
+	global $conf, $lang;
+	if ($conf['Add icon to History'])
+		$lang['History'] .= '</a> <a class="external" href="' . get_admin_plugin_menu_link(WHOIS_ONLINE_PATH.'config.php') . '">
+			<img class="button" src="' . WHOIS_ONLINE_PATH . 'icons/Whois_tuner.gif" alt="Whois Online configuration" title="Whois Online configuration" /></a>';
+	if ($conf['Add to Plugins menu']) array_push($menu, array(
+				'NAME' => 'Whois Online',
+				'URL' => get_admin_plugin_menu_link(WHOIS_ONLINE_PATH.'config.php'),
+			));
+	return $menu;
+}
+
+// Template function
+function Whois_most($text, $count, $when, $format) {
+ return sprintf(l10n($text),$count,date(l10n($format),$when));
+}
+
+// New member
+function whois_online_register($who) {
+	global $conf, $conf_whois;
+	$conf_whois['Users']['count'] = $who['id'];
+	$conf['Whois Online'] = serialize($conf_whois);
+	pwg_query('REPLACE INTO ' . CONFIG_TABLE . " (param,value,comment)
+  VALUES ('Whois Online','". $conf['Whois Online'] ."','Whois Online configuration');");
+	return;
+}
+
+function whois_country($trace, $bypass = false) {
+  if (!isset($trace['country'])) {
+			pwg_query('ALTER TABLE ' . WHOIS_ONLINE_TABLE . ' ADD `country` VARCHAR( 256 ) NOT NULL AFTER `lang` ;');
+			$trace['country']='';
+	}
+	$c = array();
+	if ($trace['country']!='') $c = @unserialize(htmlspecialchars_decode($trace['country']));
+	if (isset($c['Code']) and $c['Code']!='' and $c['Code']!='__') return $c; 
+	if ($bypass and isset($c['Code']) and $c['Code']=='__') return $c;
+  $f = @fopen ('http://api.hostip.info/get_html.php?ip=' . $trace['IP'], 'r');
+	if ($f === FALSE) return Array('Code' => '__', 'Name' => l10n('Unknown country'), 'City' => 'N/A',);
+	$result='';
+	while ($l = fgets ($f, 1024)) $result .= $l;
+	fclose ($f);
+	$tokens = split ("[:\n]", $result);
+	$c = array ('Name' => $tokens[1], 'City' => $tokens[3]);
+	if (strpos ($c['Name'], '?') === FALSE) {
+		$tokens = split ("[\(\)]", $c['Name']);
+		$c['Code'] = isset($tokens[1]) ? $tokens[1]:'__';
+		$c['Name'] = ucwords ( strtolower( ereg_replace
+			(' \([^\)]+)', '', $c['Name'])));
+	}
+	else $c = Array('Code' => '__', 'Name' => l10n('Unknown country'), 'City' => 'N/A',);
+	if ($c['Code'] == 'Private Address') {
+		$c['Name'] = l10n('Private Address');
+		$c['City'] = l10n('N/A');
+		$c['Code'] = '__';
+	}
+	pwg_query('UPDATE ' . WHOIS_ONLINE_TABLE . ' 
+      SET `country` = \'' . htmlspecialchars(serialize($c),ENT_QUOTES,'UTF-8') . '\'
+    WHERE `session_id` = \'' . $trace['session_id'] . '\';');
+  return $c;
+}
+
+function whois_flag($trace, &$step, $limit = 10) {
+  $flag = WHOIS_ONLINE_PATH . 'flags/' . $trace['Country']['Code'] . '.jpg';
+	if (file_exists($flag)) return $flag;
+	if ( $step > $limit ) return WHOIS_ONLINE_PATH . 'flags/__.jpg';
+	$f = fopen ('http://api.hostip.info/flag.php?ip=' . $trace['IP'], 'r');
+	$result='';
+	while ($l = fgets ($f, 1024)) $result .= $l;
+	fclose ($f);
+	$f = fopen($flag,"w+");
+	fputs($f,$result);
+	fclose($f);
+  return $flag;
+}
+
+// Read all data
+function whois_online_get_data($order='') {
+	$remove = "''"; // Nothing to remove ( = an empty session_id)
+	$ctr = 0; $Online[0] = '';
+	$result = pwg_query('SELECT * FROM ' . WHOIS_ONLINE_TABLE . $order . ';');
+	while($row=mysql_fetch_array($result)) {
+		$row['delay'] = (int) time() - $row['last_access'];
+		$row['elm_ids'] = explode(' ', $row['last_elm_ids']);
+		$row['cat_ids'] = explode(' ', $row['last_cat_ids']);
+		$row['tag_ids'] = explode(' ', $row['last_tag_ids']);
+		$row['sch_ids'] = explode(' ', $row['last_sch_ids']);
+		$row['dates'] = explode(' ', $row['last_dates']);
+		$ctr++;
+		if ( $row['IP'] != 'global' and $row['permanent'] == 'false'
+			and $row['delay'] > (float)( 60 * 60 * 24 * 3 )) $remove .= ", '" . $row['session_id'] . "'";
+		elseif ($row['IP'] == 'global') $Online[0] = $row;
+		else $Online[] = $row;
+	}
+	// Out of 7 visits: Reduce registered visits for 3 days without access
+	if ($remove != "''" and $ctr > (count($Online) * ONLINE_LEVEL)
+		and ($ctr-count($Online)) > ONLINE_LIMIT and ($Online[0]['pag_hits']%7)==0) {
+		pwg_query('DELETE FROM ' . WHOIS_ONLINE_TABLE . ' WHERE `session_id` IN ('. $remove .')
+				AND `permanent` = \'false\' AND `IP` <> \'global\';');
+		if (($Online[0]['pag_hits']%13)==0) @pwg_query('OPTIMIZE TABLE ' . WHOIS_ONLINE_TABLE . ';');
+	}
+	return $Online;
+}
+
+// Update global and update/create current session_id
+function whois_online_update(&$global, &$dedicated, &$gtrace)
+{
+	global $lang_info;
+	// Rewrite the global record
+	if ( $gtrace == 2 ) {
+		$query = 'REPLACE INTO ' . WHOIS_ONLINE_TABLE . ' (`IP`, `hidden_IP`, `session_id`,`user_id`,`username`,`lang`,
+		`permanent`,`last_access`,`last_elm_ids`, `last_cat_ids`, `last_tag_ids`, `last_sch_ids`,
+		`first_access_date`, `last_dates`, `elm_hits`, `pag_hits`)
+			VALUES (\'global\', \'true\',\'global\', 0, \''. $global['username'] .'\', \'--\', \'true\', \''
+			. time()  .'\',  \''
+			. implode(' ',$global['elm_ids']) . '\', \''
+			. implode(' ',$global['cat_ids']) . '\', \''
+			. implode(' ',$global['tag_ids']) . '\', \''
+			. implode(' ',$global['sch_ids']) . '\', \''
+			. $global['first_access_date'] . '\', \'\', \''
+			. $global['elm_hits'] . '\', \'' . $global['pag_hits'] . '\');';
+		pwg_query($query);
+	}
+	// Write or Rewrite the dedicated record
+	$query = 'REPLACE INTO ' . WHOIS_ONLINE_TABLE . ' (`IP`, `hidden_IP`, `session_id`,`user_id`,`username`,`lang`,
+	`permanent`,`last_access`,`last_elm_ids`, `last_cat_ids`, `last_tag_ids`, `last_sch_ids`,
+	`first_access_date`, `last_dates`, `elm_hits`, `pag_hits`)
+		VALUES (\''. $dedicated['IP'] .'\', \''
+		. $dedicated['hidden_IP'] .'\', \''. $dedicated['session_id'] .'\', \''
+		. $dedicated['user_id'] .'\', \''. $dedicated['username'] .'\', \''
+		. substr($lang_info['code'],0,2) .'\', \''
+		. $dedicated['permanent'] . '\', \''. time() .'\',  \''
+		. implode(' ',$dedicated['elm_ids']) . '\', \''
+		. implode(' ',$dedicated['cat_ids']) . '\', \''
+		. implode(' ',$dedicated['tag_ids']) . '\', \''
+		. implode(' ',$dedicated['sch_ids']) . '\', \''
+		. $dedicated['first_access_date'] . '\', \''
+		. implode(' ',$dedicated['dates']) . '\', \''
+		. $dedicated['elm_hits'] . '\', \''
+		. $dedicated['pag_hits'] . '\');';
+	pwg_query($query);
+}
+
+// Data tracking 
+// Parameters:
+//  - Array of Ids
+//  - New ID
+//  - Array of dates
+// => Add the ID if needed, Add Today if needed
+function whois_online_track(&$key, $id, &$date) {
+	if ($id != '') array_unshift($key, $id);
+	$key = array_unique($key);
+	if (count($key)>10) array_pop($key);
+	array_unshift($date, date('Y-m-d'));
+	$date = array_unique($date);
+	if (count($date)>5) array_pop($date);
+	return;
+}
+
+/*
+		Main process: Analyze, set new values and prepare displayed values.
+		
+		Update on parameter...
+*/
+function whois_online_management()
+{
+	global $user, $conf, $conf_whois, $template, $page, $lang, $lang_info;
+	load_language('plugin.lang', WHOIS_ONLINE_PATH);
+	srand((float)time());
+
+  pwg_debug('*********** start Online_management ***********');
+	if (!isset($conf_whois['Active'])) $conf_whois = whois_online_conf();
+
+	$online = whois_online_get_data();
+
+	$global = $online[0];
+	unset($online[0]);
+	$sid = session_id();
+
+	// Step 1 - Find the User and/or IP/session_id
+	foreach ($online as $key => $record) {
+		// 1st case: Same IP and same member (Proxy guests are viewed as one)
+		if ($record['IP'] == $_SERVER['REMOTE_ADDR']
+			and $record['username'] == $user['username'] ) {
+				$visit = $record;
+				$v = $key;
+				break;
+		}
+		// 2nd case: Same session and user (No doubt)
+		if ($record['session_id'] == $sid
+			and $record['username'] == $user['username'] ) {
+				$visit = $record; // Maybe a guest
+				if (!is_a_guest()) $visit['hidden_IP'] = 'true'; // Maybe Proxy or hidden IP
+				//$visit['IP'] = $_SERVER['REMOTE_ADDR']; 
+				$v = $key;
+				break;
+		}
+		// 3rd and last case: Same user_id
+		if ($record['user_id'] == $user['id'] and !is_a_guest()) { // new IP and new session
+				$visit = $record;
+				$visit['hidden_IP'] = 'true'; /* Or Generic user or the user is using several connections */
+				//$visit['IP'] = $_SERVER['REMOTE_ADDR']; 
+				$v = $key;
+				break;
+		}
+	}
+
+	// Step 2 - Assume a new comer
+	if ( !isset($visit) ) {
+		$visit = Array( 
+			'IP' => $_SERVER['REMOTE_ADDR'], // First known IP (Is that one true?)
+			'hidden_IP' => 'false', // supposed a fixed IP
+			'session_id' => $sid,
+			'user_id' => $user['id'],
+			'username' => $user['username'],
+			'delay' => 0,
+			'lang' => substr($lang_info['code'],0,2),
+			'permanent' => 'false', // False: delete after 72 Hours / True: delete after 90 days
+			'last_access' => time(), // Last access by this user
+			'elm_ids' => array_fill(0, 10, 0), // 10 last minutes + Last reference minute
+			'cat_ids' => array_fill(0, 12, 0), // 12 ranges (of 5 minutes) + ref
+			'tag_ids' => array_fill(0, 24, 0), // 24 hours + ref
+			'sch_ids' => array_fill(0, 14, 0), // 14 days + ref
+			'date' => date('Y-m-d'), // Futur usage
+			'elm_hits' => 0, 'pag_hits' => 0, // elements hits and pages hits by this user
+			'first_access_date' => date('Y-m-d'), // First access by this user
+			'dates' => Array(), // 5 last access dates
+		);
+		$online[] = $visit;
+		$v = count($online);
+	}
+
+	// Step 3 - Monitor this access
+	$base = script_basename();
+	// Picture page
+	if (isset($page['image_id']) and $base == 'picture') {
+		whois_online_track($visit['elm_ids'], $page['image_id'],$visit['dates']);
+		if (isset($page['tags']))
+		whois_online_track($visit['tag_ids'], $page['image_id'],$visit['dates']);
+		if (isset($page['search']))
+		whois_online_track($visit['sch_ids'], $page['image_id'],$visit['dates']);
+		$visit['elm_hits']++;
+		$global['elm_hits']++;
+	}
+	// Category page
+	if (isset($page['category']['id']) and $base == 'index')
+		whois_online_track($visit['cat_ids'], $page['category']['id'],$visit['dates']);
+	// Page index
+	if (!isset($page['category']['id']) and !isset($page['image_id']))
+		whois_online_track($visit['cat_ids'], '' ,$visit['dates']);
+	$visit['pag_hits']++;
+	$global['pag_hits']++;
+
+	// Step 4 - Identify current range
+	$current = floor(time() / 60); 			// minutes for Unix time origin
+	$minute = $current % 10; 						// (0-9) current minute
+	$five = floor($current / 5); 	// (0-11) last 5 minutes range
+	$hour = floor($current / 60); 	// (0-11) last hours
+	$day = floor($current / 1440); // (0-13) last days
+	if (isset($global['elm_ids'][10])) $old = $global['elm_ids'][10]; // previous minute (last one, or maybe 60 minutes ago or more).
+	else $old = $current; /* Only the first time or prevent wrong changes */
+
+	// Step 5 - Hits by range
+	if ($current != $old) {
+		$global['elm_ids'][11] = $global['elm_ids'][$minute];
+		$raz = min($current-$old, 10);
+	// 5.1 - $global['elm_ids'] ( hits by minute range )
+		for ($i=0;$i<$raz;$i++) {
+			$global['elm_ids'][($minute+10-$i)%10] = 0;
+		}
+	// 5.2 - $global['cat_ids'] ( hits by 5 minutes range )
+		if (isset($global['cat_ids'][12])) $oldfive = $global['cat_ids'][12];
+		else $oldfive = floor($old / 5);
+		$raz = min($five - $oldfive, 12);
+		for ($i=0;$i<$raz;$i++) {
+			$global['cat_ids'][($five+12-$i)%12] = 0; // Reset in backside
+		}
+	// 5.3 - $global['tag_ids'] (hits by hours )
+		if (count($global['tag_ids'])<25) $global['tag_ids'] = array_fill(0, 24, 0);
+		if (isset($global['tag_ids'][24])) $oldhour = $global['tag_ids'][24];
+		else $oldhour = floor($old / 60);
+		$raz = min($hour - $oldhour, 24);
+		for ($i=0;$i<$raz;$i++) {
+			$global['tag_ids'][($hour+24-$i)%24] = 0; // Reset in backside
+		}
+	// 5.4 - $global['sch_ids'] ( hits by days )
+		if (isset($global['sch_ids'][14])) $oldday = $global['sch_ids'][14];
+		else $oldday = floor($old / 1440);
+		$raz = min($day - $oldday, 14);
+		for ($i=0;$i<$raz;$i++) {
+			$global['sch_ids'][($day+14-$i)%14] = 0; // Reset in backside
+		}
+	}
+	$global['elm_ids'][$minute]++;
+	$global['cat_ids'][$five%12]++;
+	$global['tag_ids'][$hour%12]++;
+	$global['sch_ids'][$day%14]++;
+  // !!! WARNING  !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!!
+	$global['elm_ids'][10] = $current; // reference minute has changed
+	$global['cat_ids'][12] = $five;
+	$global['tag_ids'][24] = $hour;
+	$global['sch_ids'][14] = $day;
+  // !!! WARNING  !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!!
+
+	// Step 6 - Update (on Conf_Update and trace) and send trace to determine global tracing or not
+	$dtrace = 0;
+	if ($user['status'] == 'admin') $dtrace += $conf_whois['Administrators'];
+	elseif ($user['status'] == 'webmaster') $dtrace += $conf_whois['Webmasters'];
+	else $dtrace = 2;
+	if ($conf['Whois Online Update'] and $dtrace > 0) whois_online_update($global, $visit, $dtrace);
+
+	// Step 7 - Find your recent visits (These image_ids are presumely authorized)
+	$my_ids = $visit['elm_ids'];
+	sort($my_ids);
+	unset($my_ids[0]);
+	$url_visited = (count($my_ids)>0) ? make_index_url(array('list' => $my_ids)).'&amp;review':'';
+
+	// Step 8 - Guest count and Member list
+	$h24 = 0; $h1 = 0; $guest = 0;
+	$list = array();
+	$elm = array(); $excl = array(); // Get images_ids from all and from the current visitor
+	foreach ($online as $k => $monit)
+	{
+		if ($user['id']==$monit['user_id']) $excl = $monit['elm_ids'];
+		else $elm = array_merge($elm, $monit['elm_ids']);
+		if ($monit['delay'] <= (24*3600)) $h24++;
+		if ($monit['delay'] <= 3600) $h1++;
+		// Less than 5 minutes: users are considered as still online...
+		if ($monit['delay'] <= 300) {
+			if ($monit['user_id'] == $conf['guest_id']) $guest++;
+			else $list[] = $monit['username'];
+		}
+	}
+	// The first (and current) access are not recorded in $online
+	// As visitor you are not expecting your access to be already counted: Ok that the case
+	// but you are expecting to see you as a member in the member list if you are: and there it is
+	if ($visit['user_id'] != $conf['guest_id'] ) $list[] = $visit['username'];
+	$list = array_unique($list);
+	
+	if (count($list) > $conf_whois['Users']['max']) {
+		$conf_whois['Users']['max'] = count($list);
+		$conf_whois['Users']['When'] = time();
+		$conf['Whois Online'] = serialize($conf_whois);
+		pwg_query('REPLACE INTO ' . CONFIG_TABLE . " (param,value,comment)
+    VALUES ('Whois Online','". $conf['Whois Online'] ."','Whois Online configuration');");
+	}
+
+	// Step 9 - Review pictures viewed by others (all images except yours)
+	$elm = array_diff( array_unique($elm), $excl );
+	shuffle($elm);
+	$elm = array_slice($elm,0,($conf['top_number']+50));
+	sort($elm);
+	array_shift($elm);
+	$elm[] = 0; // Check if authorized pictures
+	$query = 'SELECT DISTINCT(image_id)
+  FROM '.IMAGE_CATEGORY_TABLE.'
+    INNER JOIN '.IMAGES_TABLE.' ON id = image_id
+  WHERE image_id IN ('.implode(',', $elm ).')
+    '.get_sql_condition_FandF(
+      array(
+          'forbidden_categories' => 'category_id',
+          'visible_categories' => 'category_id',
+          'visible_images' => 'id'
+        ), "\n  AND") . ';';
+	$ids = array_from_query($query, 'image_id');
+	shuffle($ids);
+	$ids = array_slice($ids, 0, $conf['top_number']); // Keep some
+	$url_someothers = (isset($ids[0])) ? make_index_url(array('list' => $ids)).'&amp;others':'';
+
+	// Random page title change
+	$url_type = pwg_get_session_var('whois_url_type', ''); /* previous review or others */
+	$list_ids = pwg_get_session_var('whois_list_ids', ''); /* previous list/xx,yy,zz, ... */
+	$list_section = (isset($page['section']) and $page['section'] == 'list') ? true:false;
+	$same_ids = (isset($page['list']) and $page['list'] == $list_ids) ? true:false;
+	if ($list_section and isset($_GET['review'])) {
+		$url_type = 'Whois_review';
+		$same_ids = true;
+	}
+	if ($list_section and isset($_GET['others'])) {
+		$url_type = 'Whois_others';
+		$same_ids = true;
+	}
+	if ($list_section and $same_ids and isset($page['list'])) $list_ids = $page['list'];
+	else $url_type = ''; // Not the same list
+	pwg_set_session_var('whois_list_ids', $list_ids);
+	pwg_set_session_var('whois_url_type', $url_type);
+	if ($url_type != '' and $list_section)
+  $page['title'] = '<a href="'.duplicate_index_url(array('start'=>0)).'">'
+                    .l10n($url_type).'</a>';
+
+	
+	// Step 10 - Prepare data to display
+	$yesterday = ($day+13) % 14;
+	$template->assign('Whois', array(
+		'Total' => $global['pag_hits'],
+		'Image' => $global['elm_hits'],
+		'Other' => ($global['pag_hits']-$global['elm_hits']),
+		'Current_minute' => $global['elm_ids'][$minute],
+		'Previous_minute' => $global['elm_ids'][($minute+9) % 10],
+		'Current_5mins' => $global['elm_ids'][$minute]
+									+ $global['elm_ids'][($minute+9) % 10]
+									+ $global['elm_ids'][($minute+8) % 10]
+									+ $global['elm_ids'][($minute+7) % 10]
+									+ $global['elm_ids'][($minute+6) % 10],
+		'Current_10mins' => array_sum(array_slice($global['elm_ids'],0,10)),
+		'Current_hour' => array_sum(array_slice($global['cat_ids'],0,12)),
+		'Current_24h' => array_sum(array_slice($global['tag_ids'],0,24)),
+		'Yesterday' => $global['sch_ids'][$yesterday],
+		'Users_Last_day' => $h24,
+		'Users_Last_hour' => $h1,
+		'Guests' => $guest,
+		'Online' => $list,
+		'Review_url' => $url_someothers,
+		'Their_ids' => $ids,
+		'Seen_url' => $url_visited,
+		'My_ids' => $my_ids,
+		'Slideshow' => isset($_GET['slideshow']) ? true:false,
+	));
+	$template->assign('Online', $global );
+
+	pwg_debug('end Online_management');
+}
+?>
Index: /extensions/whois_online/reload.php
===================================================================
--- /extensions/whois_online/reload.php	(revision 3319)
+++ /extensions/whois_online/reload.php	(revision 3319)
@@ -0,0 +1,133 @@
+<?php
+// Reload might be :
+// - accessed thru a direct link from admin.php?page=plugin&section=whois_online%2Fconfig.php&tab=report
+// - or included directly by admin.php (include_one in reporting part)
+// Reload won't work if Whois_Online is deactivated
+$included = true;
+if (!isset($_url)) {
+		define('PHPWG_ROOT_PATH','../../');
+		define('IN_ADMIN', true);
+		include_once(PHPWG_ROOT_PATH.'include/common.inc.php');
+		$included = false;
+		load_language('plugin.lang', WHOIS_ONLINE_PATH);
+}
+
+// This is MANDATORY to secure your website !
+check_status(ACCESS_ADMINISTRATOR);
+
+pwg_debug('*********** Radar reload ***********');
+$conf_whois = whois_online_conf();
+
+$sort = ' WHERE `IP` = "global" or ( 1=1 ';
+
+// Filtering on direct link parameters
+$case = '';
+if (isset($_GET['req'])) {
+	$case = $_GET['req'];
+	switch($_GET['req']) { 
+		case 'members': 
+			$sort.= ' AND `user_id` <> "' . $conf['guest_id'] . '"';
+			break;
+		case 'guest': 
+			$sort.= ' AND `user_id` = "' . $conf['guest_id'] . '"';
+			break;
+		case 'less_24': 
+			$sort.= ' AND `last_access` > "' . (time()-(24*3600)) . '"';
+			break;
+		case 'over_24': 
+			$sort.= ' AND `last_access` < "' . (time()-(24*3600)) . '"';
+			break;
+		case 'pics': 
+			$sort.= ' AND `last_elm_ids` > "0 0 0 0 0 0 0 0 0 0"';
+			break;
+		case 'no_pic': 
+			$sort.= ' AND `last_elm_ids` = "0 0 0 0 0 0 0 0 0 0"';
+			break;
+		case 'country': 
+			$sort.= ' AND `country` <> \'' . htmlspecialchars(serialize(Array('Code' => '__', 'Name' => l10n('Unknown country'), 'City' => 'N/A',))) . '\'';
+			break;
+		case 'no_country': 
+			$sort.= ' AND `country` = \'' . htmlspecialchars(serialize(Array('Code' => '__', 'Name' => l10n('Unknown country'), 'City' => 'N/A',))) . '\'';
+			break;
+		case 'single': 
+			$sort.= ' AND LENGTH(`last_dates`) < 12';
+			break;
+		case 'multi': 
+			$sort.= ' AND LENGTH(`last_dates`) > 12';
+			break;
+		case 'IPs': 
+			$sort.= ' AND `hidden_IP` = "true"';
+			break;
+	} 
+}
+$sort .= ')
+ORDER BY `db_timestamp` DESC;';
+$online = whois_online_get_data($sort);
+$global = $online[0]; unset($online[0]);
+$sid = session_id();
+
+$iflag = 0; // Get the 10 first new flags on included requests ONLY (Duration reasons)
+
+// prefetch to optimize
+$local_guest = mysql_fetch_assoc(pwg_query('SELECT * FROM ' . USER_INFOS_TABLE .
+	' WHERE user_id = ' . $conf['guest_id'] .';'));
+	
+$lang_tab = get_languages();
+foreach ($lang_tab as $k => $v) $lang_code[substr($k,0,2)] = substr($v,0,strrpos($v,'[')-1);
+
+$bypass = false;
+$limit = 20;
+$ql = 0; 
+foreach ($online as $k => $v) {
+  // The stupid History search will be reused instead of created... (even if History search will recreate it)
+	if ($conf['log']) $online[$k]['url_user'] = 
+		PHPWG_ROOT_PATH .'admin.php?page=history&amp;user_id='.$online[$k]['user_id'].'&amp;search_id='.$conf_whois['Search id'];
+	
+	$online[$k]['Language'] = (isset($lang_code[$v['lang']])) ? $lang_code[$v['lang']]:l10n('Deleted language');
+	$online[$k]['Country'] = whois_country($v, $bypass);
+	$iflag++;
+	$online[$k]['Flag'] = ($included) ? whois_flag($online[$k], $iflag) : whois_flag($online[$k], $iflag, $limit);
+	if (!$included) $online[$k]['Flag'] = substr($online[$k]['Flag'],4);
+	if ($iflag > 5) $bypass = true; // Don't search already unknown countries over 5 countries
+	if ($v['user_id'] == $conf['guest_id']) { 
+		$online[$k]['username'] =  ucwords(l10n('guest'));
+		$online[$k]['guest'] =  true;
+		$online[$k]['user'] = $local_guest; // Prefetched guest data
+	}
+	else {
+		$online[$k]['user'] = mysql_fetch_assoc(pwg_query('SELECT * FROM ' . USER_INFOS_TABLE .
+		 ' WHERE user_id = ' . $v['user_id'] .';'));
+		$online[$k]['guest'] =  false;
+	}
+	$ql++;
+	// Images queries are limited (no cluetip over $conf_whois['Radar limit'])
+	// For performance reasons
+	if ($ql <= $conf_whois['Radar limit']) {
+		$result = pwg_query('SELECT * FROM ' . IMAGES_TABLE .
+			' WHERE id IN (' . implode(', ',explode(' ',$online[$k]['last_elm_ids'])) .');');
+		while ($row = mysql_fetch_assoc($result)) {
+			$online[$k]['images'][$row['id']] = $row;
+			$online[$k]['images'][$row['id']]['ws_level'] = ($row['level']>$online[$k]['user']['level']) ? 'ws':'';
+			$online[$k]['images'][$row['id']]['tn_url'] = get_thumbnail_url($row);
+			$online[$k]['images'][$row['id']]['url_modify'] = PHPWG_ROOT_PATH . 'admin.php?page=picture_modify&image_id='.$row['id'];
+		}
+	} else {
+	// Only the id is available for links (NO LEVEL CONTROL)
+		foreach (explode(' ',$online[$k]['last_elm_ids']) as $id) {
+			if ($id > 0) {
+			$online[$k]['images'][$id]['id'] = $id;
+			$online[$k]['images'][$row['id']]['url_modify'] = PHPWG_ROOT_PATH . 'admin.php?page=picture_modify&image_id='.$id;
+			}
+		}
+	}
+}
+pwg_debug('*********** Radar reloaded ***********');
+$template->assign('search_results', $online);
+$template->assign('Case', $case);
+// Send reloadable HTML
+if ( !$included ) {
+	$template->set_filenames(array('reload'=> dirname(__FILE__) . '/report.tpl'));
+	$template->pparse('reload');
+}
+
+?>
Index: /extensions/whois_online/report.tpl
===================================================================
--- /extensions/whois_online/report.tpl	(revision 3319)
+++ /extensions/whois_online/report.tpl	(revision 3319)
@@ -0,0 +1,106 @@
+<table class="table2" id="detailedStats">
+<thead> 
+<tr class="throw">
+  <th>{'users'|@translate} &nbsp; &nbsp;</th>
+  <th class="ns">&nbsp;</th>
+  <th>{'First access'|@translate} &nbsp; &nbsp;</th>
+  <th>{'Level'|@translate} &nbsp;</th>
+  <th class="ns">{'Images (Modify)'|@translate}</th>
+  <th>{'Last access'|@translate} &nbsp;</th>
+</tr>
+</thead> 
+<tbody> 
+{foreach from=$search_results item=detail name=res_loop}
+<tr class="{if $smarty.foreach.res_loop.index is odd}row1{else}row2{/if}">
+  <td><a href={if isset($detail.url_user)}"{$detail.url_user}" onclick="window.open(this.href); return false;"{else}"#"{/if} class="cluetip{if ($detail.guest)} other{/if}" 
+		title="{'User:'|@translate} {$detail.username}|
+			<table>
+				<tr><td class=&#34;right&#34;><b><i>IP:</i></b></td><td colspan=&#34;3&#34;>{$detail.IP} 
+				{if ($detail.hidden_IP== 'true')}{'(Multiple IP)'|@translate}{/if}</td></tr>
+				{if (substr($detail.user.registration_date,0,4)!='0000')}
+				<tr><td class=&#34;right&#34;><b><i>{'Registered since'|@translate}</i></b></td><td colspan=&#34;3&#34;>{$detail.user.registration_date|@substr:0:10}</td></tr>
+				{/if}
+				<tr><td class=&#34;right&#34;><b><i>User_id</i></b></td><td>{$detail.user_id}</td>
+				<td class=&#34;right&#34;><b><i>{'Status'|@translate}</i></b></td><td>{$detail.user.status|@translate|ucfirst} ({$detail.user.status})</td></tr>
+				<tr><td class=&#34;right&#34;><b><i>{'language'|@translate}</i></b></td><td>{$detail.Language}</td></tr>
+				<tr><td class=&#34;right&#34; colspan=&#34;2&#34;>{$detail.Country.Name}</td><td colspan=&#34;2&#34;> / {$detail.Country.City}</td></tr>
+				<tr><td colspan=&#34;4&#34;>&nbsp;</td></tr>
+				<tr><td class=&#34;right&#34;><b><i>{'Hits since'|@translate}</i></b></td><td colspan=&#34;3&#34;>{$detail.first_access_date}</td></tr>
+				<tr><td class=&#34;right&#34;><b><i>{'on pictures'|@translate}</i></b></td><td>{$detail.elm_hits}</td>
+				<td class=&#34;right&#34;><b><i>{'on pages'|@translate}</i></b></td><td>{$detail.pag_hits}</td></tr>
+			</table>">{$detail.username}</a> 
+				<a href="./admin.php?page=profile&amp;user_id={$detail.user_id}" title="{'Profile'|@translate}" alt="{'Profile'|@translate}" 
+				onclick="window.open(this.href); return false;">[{$detail.lang}]</a>
+	</td>
+	<td>
+		{if ($detail.user_id == '1')}<a class="external" href="{'http:hostip'|@translate}" title="{':hostip:title'|@translate}">
+			<img src="{$detail.Flag}" border="0" alt="{$detail.IP} - {'language'|@translate}: {$detail.Language}" width="24" height="16">
+		</a>
+		{else}<a class="external" href="{'http:geoiptool'|@translate}{$detail.IP}" title="{':geoiptool:title'|@translate}">
+			<img src="{$detail.Flag}" border="0" alt="{$detail.IP} - {'language'|@translate}: {$detail.Language}" width="24" height="16">
+		</a>
+		{/if}
+	</td>
+  <td>{$detail.first_access_date}</td>
+  <td>
+		<a href="./admin.php?page=user_perm&amp;user_id={$detail.user_id}" onclick="window.open(this.href); return false;" title="{'permissions'|@translate}">
+		{'Level %d'|@sprintf:$detail.user.level|@translate}</a> ({$detail.user.level})
+	</td>
+  <td>
+	{foreach from=$detail.images key=id item=image name=elm_loop}
+		{if ($id > 0)}&nbsp;
+			{if (isset($image.path))}
+				<a class="cluetip {if $smarty.foreach.res_loop.index is odd}ws1{else}ws2{/if} {$image.ws_level}" 
+				  href="{$image.url_modify}" title="<div style=&#34;text-align:center;&#34;>
+				<img src=&#34;{$image.tn_url}&#34;></div>|
+					Image ID: {$id} <br />
+					{'Privacy level'|@translate}: {'Level %d'|@sprintf:$image.level|@translate} ({$image.level}) <br />
+					{if ($image.ws_level=='ws')}{'Image privacy level is higher than the user privacy level (Any change of one of them?)'|@translate} {/if}
+					Path: {$image.path}<br />
+					<hr>
+					Filesize: {$image.filesize} Kb <br />
+					Width x Height: {$image.width} x {$image.height} px<br />
+					<hr>
+					{if (is_null($image.high_filesize))}High Resolution: {if ($image.has_high == 'true')}Yes{else}No{/if}<br />{/if}
+					{if (!is_null($image.high_filesize))}High Filesize: {$image.high_filesize} Kb <br />{/if}
+					{if (!is_null($image.md5sum))}pLoader (Dynamic upload): Yes <br />{/if}
+					Posted on: {$image.date_available} <br />
+					{if (!is_null($image.date_creation))}Created on: {$image.date_creation} <br />{/if}
+					<hr>
+					Hits on: {$image.hit}<br />">{$id}</a>
+				{else}<a class="{if $smarty.foreach.res_loop.index is odd}ws1{else}ws2{/if}" 
+				  href="{$image.url_modify}" title="{$id}{' - Over the radar limit => No level control'|@translate}">{$id}</a>
+			{/if}
+		{/if}
+	{/foreach}
+	</td>
+  <td>{if (strlen($detail.last_dates) > 10)}<a href="#" class="cluetip"
+		title="{'Previous connection dates'|@translate}|
+			{$detail.last_dates|@substr:11|@explode:' '|@implode:'<br />'}">{$detail.db_timestamp}</a>{else}{$detail.db_timestamp}{/if}</td>
+</tr>
+{/foreach}
+<tbody> 
+</table>
+<p><a class="external" href="{'http:hostip'|@translate}" title="{':hostip:title'|@translate}"
+ alt="">hostip.info</a>{': provides newcomers\' localization and possibly new country flags, thanks to them.'|@translate}</p>
+<p><a class="external" href="{'http:geoiptool'|@translate}" title="{':geoiptool:title'|@translate}"
+ alt="">geoiptool.com</a>{': provides IP geolocalization on request (link on flag). Useful for unknown countries.'|@translate}</p>
+{literal}
+<script type="text/javascript">// <![CDATA[
+$(document).ready(function(){
+  $("#detailedStats").tablesorter( {sortList: [[5,1]]} );}
+);
+jQuery().ready(function(){
+  jQuery('.cluetip').cluetip({
+    width: 300,
+    splitTitle: '|'
+  });
+});
+// ]]>
+</script>
+{/literal}
+{if (isset($Case) and $Case > '')}
+<style type="text/css">
+a#{$Case} {ldelim}  color: #ff3333;  border-bottom: 1px solid #ff3363; outline: 0; }
+</style>
+{/if}
