Index: inc/admin/class.dc.filter.php
===================================================================
--- inc/admin/class.dc.filter.php	(revision 453)
+++ 	(revision )
@@ -1,516 +1,0 @@
-<?php
-# ***** BEGIN LICENSE BLOCK *****
-# This file is part of DotClear "MyPostTypes" plugin.
-# Copyright (c) 2010 Bruno Hondelatte, and contributors. 
-# Many, many thanks to Olivier Meunier and the Dotclear Team.
-# All rights reserved.
-#
-# MyPostTypes plugin for DC2 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; either version 2 of the License, or
-# (at your option) any later version.
-# 
-# DotClear 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 DotClear; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-#
-# ***** END LICENSE BLOCK *****
-
-/**
-@ingroup DC_CORE
-@nosubgrouping
-@brief Dotclear FilterSet class.
-
-Dotclear FilterSet handles filters and columns when displaying items lists.
-*/
-class dcFilterSet {
-
-	protected $filters;			/// <b>array</b> lists of defined filters
-	protected $form_prefix;		/// <b>string</b> displayed form prefix
-	protected $action; 			/// <b>string</b> form action page
-	protected $hideform;		/// <b>boolean</b> start form display hidden by default or not
-	protected $columns_form;	/// <b>string</b> columns form
-	protected $name;			/// <b>string</b> fieldset name
-	/**
-	Inits dcFilterSet object
-	
-	@param	core		<b>dcCore</b>		Dotclear core reference
-	@param	form_prefix	<b>string</b>		form prefix to use for parameters
-	*/
-	public function __construct($name,$action,$form_prefix="f_") {
-		$this->name = $name;
-		$this->form_prefix=$form_prefix;
-		$this->filters = array();
-		$this->action = $action;
-	}
-
-	/**
-	Adds a new filter to list
-	
-	@param	filter		<b>dcFilter</b>		the filter to add
-	*/
-	public function addFilter (Filter $filter) {
-		$filter->setFormPrefix($this->form_prefix);
-		$this->filters[$filter->id] = $filter;
-		return $this;
-	}
-	
-	/**
-	Saves user filters to preferences
-	*/
-	protected function saveFilters() {
-		$ser = array();
-		$ws = $GLOBALS['core']->auth->user_prefs->addWorkspace('filters');
-		foreach($this->filters as $filter) {
-			$ser[$filter->id]=$filter->serialize();
-		}
-		$ws->put($this->name,serialize($ser),'string');
-	}
-	
-	/**
-	Loads user filters from preferences
-	*/
-	protected function loadFilters() {
-		$ws = $GLOBALS['core']->auth->user_prefs->addWorkspace('filters');
-		
-		$settings = !is_null($ws->{$this->name}) ? unserialize($ws->{$this->name}) : array();
-		foreach($settings as $k => $v) {
-			$this->filters[$k]->unserialize($v);
-		}
-	}
-	
-	/**
-	Updates filters values according to form_data
-	To be called before any call to display() or getForm()
-	
-	@param	form_data	<b>array</b>	form values (usually $_GET or $_POST)
-	*/
-	public function setValues ($form_data) {
-		$this->hideform = true;
-		if (isset($form_data['clear_filters'])) {
-			$this->saveFilters();
-			return;
-		}
-		if (!isset($form_data['apply'])) {
-			$this->loadFilters();
-		}
-		foreach ($this->filters as $filter) {
-			$filter->setValues ($form_data);
-			if ($filter->isEnabled()) {
-				$this->hideform=false;
-			}
-		}
-		if (isset($form_data['apply'])) {
-			if (trim($form_data['apply']) == '+'
-				&& isset($form_data['add_filter']) 
-				&& isset($this->filters[$form_data['add_filter']])) {
-				$this->filters[$form_data['add_filter']]->add();
-				$this->hideform=false;
-			}
-		}
-		$this->saveFilters();
-	}
-	
-	/**
-	Defines additional form in layout (right column)
-	
-	@param	html	<b>string</b>		the code to add
-	*/
-	public function setColumnsForm($html)
-	{
-		$this->columns_form = $html;
-	}
-	
-	/**
-	Returns form fields as hidden fields
-	
-	@return	<b>string</b>	the corresponding html code
-	*/
-	public function getFormFieldsAsHidden() {
-		$ret='';
-		foreach ($this->filters as $filter) {
-			$ret.= $filter->getFormFieldAsHidden();
-		}
-		return $ret;
-	}
-
-	/**
-	Retrieves filterset generated form
-	
-	@param	method	<b>string</b>		form method to use (default: "get")
-	*/
-	public function getForm($method="get") {
-		$ret = '';
-		
-		if ($this->hideform) {
-			$formclass = ' class="hidden"';
-		} else {
-			$formclass='';
-		}
-		$ret .= '<p><img alt="" src="images/minus.png" /> <a href="#" id="toggle-filters">'.__('Toggle filters and display options').'</a></p>';
-		$ret .=
-			'<div class="two-cols">'.
-			'<form id="filters" action="'.$this->action.'" method="'.$method.'"'.$formclass.'>'.
-			'<div class="col70">'.
-			'<h3>'.__('Entries filters').'</h3>';
-			
-		$count=0;
-		$form_combo=array();
-		$form_combo['-']='';
-		if (count($this->filters)) {
-			$ret .= '<ul>';
-			foreach ($this->filters as $filter) {
-				if ($filter->isEnabled()) {
-					$ret .= $filter->getFormLine();
-				}
-				$form_combo[$filter->desc]=$filter->id;
-				$count++;
-			}
-			$ret .= '</ul>';
-		}
-		$ret .= 
-			'<p class="clear"><input class="delete" type="submit" value="'.__('Delete all filters').'" name="clear_filters" /></p>'.
-			'<h3 class="margintop">'.__('Add a filter').'</h3>'.
-			'<p id="available_filters">'.
-			form::combo("add_filter",$form_combo).
-			'<input type="submit" value=" + " title="'.__('Add this filter').'" name="apply" />'.
-			'</p>'.
-			'</div>'.
-			'<div class="col30">'.
-			$this->columns_form.
-			'</div>'.
-			'<p class="clear margintop"><input type="submit" value="'.__('Apply filters and display options').'" name="apply" /></p>'.
-
-			'</form></div>';
-		return $ret;
-	}
-	
-	/**
-	Displays required fieldset http header
-	To be called in page header, of course.
-	*/
-	public function header() {
-		return dcPage::jsLoad('js/filters.js');
-	}
-	
-	
-	/**
-	Displays the fieldset
-	*/
-	public function display() {
-		echo $this->getForm();
-	}
-
-	/**
-	Applies fieldset and return resulting parameters for request
-	
-	@param	method	<b>string</b>		form method to use (default: "get")
-	@param	method	<b>string</b>		form method to use (default: "get")
-	
-	*/
-	public function applyFilters($params) {
-		$filtered = false;
-		foreach ($this->filters as $filter) {
-			if ($filter->isEnabled()) {
-				$filter->applyFilter($params);
-				$filtered = true;
-			}
-		}
-		return $filtered;
-	}
-	
-}
-
-
-/**
-@ingroup DC_CORE
-@nosubgrouping
-@brief abstract filter class.
-
-Dotclear Filter handles administration filters for each list
-A filter fills in a parameter array, as defined in dcBlog class
-*/
-abstract class Filter {
-	public $id;					///< <b>string</b> field id (local to fieldset)
-	public $desc;				///< <b>string</b> field description
-	protected $request_param;	///< <b>string</b> resulting parameter array key
-	protected $enabled;			///< <b>string</b> true if filter is enabled
-	protected $values;			///< <b>array</b> possible filter values
-	public $field_id;			///< <b>string</b> field id (global to the page)
-	
-	/**
-	Inits Filter object
-	
-	@param	id		<b>string</b>	field id
-	@param	form_prefix	<b>string</b>		form prefix to use for parameters
-	*/
-	public function __construct ($id,$desc,$request_param) {
-		$this->id = $id;
-		$this->desc = $desc;
-		$this->request_param = $request_param;
-		$this->enabled=false;
-		$this->values = array();
-		$this->field_id = $this->id;
-	}
-	
-	/**
-	Get a field id
-	
-	@param	pos		<b>integer</b>	position of field, in case of multiple field (0 if only 1 field set, default value)
-	@return	<b>string</b> The field ID
-	*/
-	protected function getFieldId($pos=0) {
-		if ($pos == 0) {
-			return $this->field_id;
-		} else {
-			return $this->field_id.'_'.$pos;
-		}
-	}
-	
-	/**
-	Tells whether the filter is enabled or not
-	
-	@return	<b>boolean</b> true if enabled, false otherwise
-	*/
-	public function isEnabled() {
-		return $this->enabled;
-	}
-	
-	/**
-	Adds the current filter to the list
-	*/
-	public function add() {
-		// By default here, only 1 value allowed. Simply enable the filter
-		$this->enabled = true;
-	}
-	
-	/**
-	Defines form prefix for filter
-	
-	@param	prefix		<b>string</b>	the form prefix
-	*/
-	public function setFormPrefix($prefix) {
-		$this->field_id = $prefix.$this->id;
-	}
-	
-	
-	/**
-	Returns HTML code for form field
-	
-	@param	pos		<b>integer</b>	position of the field to display (in case of multiple values)
-	@return <b>string</b> the html code
-	*/
-	public function getFormFields($pos=0) {
-		return '';
-	}
-	
-	/**
-	Returns filter values il a serialized way (array)
-	
-	@return		<b>array</b>	serialized data
-	*/
-	public function serialize() {
-		return array(
-			'values' => $this->values,
-			'enabled' => $this->enabled
-		);
-	}
-	
-	/**
-	Defines filter values from serialized data (array)
-	To be used in conjunction with serialize method
-	
-	@param	$data	<b>array</b>	serialized data to retrieve
-	*/
-	public function unserialize ($data) {
-		$this->values = $data['values'];
-		$this->enabled = $data['enabled'];
-	}
-	
-	/**
-	Set filter values from form_data (usually $_GET)	
-	@param	$form_data	<b>array</b>	form data
-	*/
-	public function setValues($form_data) {
-		$count=0;
-		while (isset($form_data[$this->getFieldId($count)])) {
-			if (!isset($form_data['del_'.$this->getFieldId($count)])) {
-				$this->values[$count] = $form_data[$this->getFieldId($count)];
-			} elseif (isset($this->values[$count])) {
-				unset($this->values[$count]);
-			}
-			$count++;
-
-		}
-		$this->values = array_values($this->values);
-		$this->enabled = (count($this->values)!=0);
-	}
-	
-		/**
-	Returns form fields as hidden fields
-	
-	@return	<b>string</b>	the corresponding html code
-	*/	
-	public function getFormFieldAsHidden () {
-		$ret='';
-		for ($cur=0; $cur < count($this->values); $cur++) {
-			$ret .= form::hidden($this->getFieldId($cur), $this->values[$cur]);
-		}
-	}
-	/**
-	Returns HTML code for the hole filter lines
-	
-	@return <b>string</b> the html code
-	*/
-	
-	public function getFormLine() {
-		$ret="";
-		for ($cur=0; $cur < count($this->values); $cur++) {
-			$ret .= '<li id="'.$this->getFieldId($cur).'" class="line" title="'.$this->desc.'">'.
-				$this->getFormFields($cur).
-				'<input id="del_'.$this->getFieldId($cur).'" class="delete" '.
-				'type="submit" title="Delete the following filter : " value=" - " name="del_'.$this->getFieldId($cur).'"/>'.
-				'</li>';
-		}
-		return $ret;
-	}
-	
-	/**
-	Convert filter values into a $param filter, used for the upcoming SQL request
-	
-	@param <b>ArrayObject</b> the parameters array to enrich
-	*/
-	public function applyFilter($params) {
-	}
-	
-}
-
-/**
-@ingroup DC_CORE
-@nosubgrouping
-@brief abstract filter class.
-
-Handle combo filter on admin side. Can be single or multi-valued
-*/
-class comboFilter extends Filter {
-	protected $options;
-	protected $default;
-	protected $no_value;
-	protected $verb;
-	protected $extra;
-	
-	public function __construct($id,$desc,$request_param,$options,$extra=array()) {
-		parent::__construct($id,$desc,$request_param);
-		$this->options = $options;
-		$this->extra = $extra;
-		$this->desc = $desc;
-		$this->verb = "is";
-		$this->values=array();
-	}
-	
-	public function add() {
-		parent::add();
-		if (isset($this->extra['singleval']) && (count($this->values) > 0))
-			return;
-		$this->values[]=current($this->options);
-	}
-	
-	public function getType() {
-		return "combo";
-	}
-
-	public function serialize() {
-		$data = parent::serialize();
-		$data['verb'] = $this->verb;
-		return $data;
-	}
-	
-	public function unserialize ($data) {
-		parent::unserialize($data);
-		$this->verb = $data['verb'];
-	}
-	
-	public function setValues($form_data) {
-		parent::setValues($form_data);
-		if (isset($form_data[$this->field_id."_v"])) {
-			$this->verb = ($form_data[$this->field_id."_v"] == 'is') ? 'is' : 'isnot';
-		}
-	}
-
-	public function getFormFieldAsHidden () {
-		return parent::getFormFieldAsHidden().form::hidden($this->field_id."_v",$this->verb);
-	}
-
-	public function getFormFields($pos=0) {
-		
-		if ($pos == 0) {
-			$desc = $this->desc.' : ';
-			$labelclass="filter-title";
-		} else {
-			$desc = __('or');
-			$labelclass = 'or';
-		};
-		return '<span class="'.$labelclass.'">'.$desc.'</span>'.
-			(($pos == 0) 
-				?form::combo($this->field_id.'_v',
-					array(__('is')=>'is',__('is not')=>'isnot'),$this->verb,'','',
-					false,'title="'.sprintf(__('%s is or is not'),$this->desc).'"') 
-				:'').
-			form::combo($this->getFieldId($pos),$this->options,$this->values[$pos],
-				'','',false,'title="'.__('Choose an option').'"');
-	}
-	
-	public function applyFilter($params) {
-		$attr = $this->request_param;
-		if ($this->verb != "is") {
-			$params[$attr."_not"] = true;
-		}
-		if (isset($this->extra['singleval']))
-			$params[$attr]=$this->values[0];
-		else
-			$params[$attr]=$this->values;
-	}
-}
-
-/**
-@ingroup DC_CORE
-@nosubgrouping
-@brief abstract filter class.
-
-Handle boolean filter on admin side.
-*/
-class booleanFilter extends Filter {
-	protected $options;
-	
-	public function __construct($id,$desc,$request_param,$options,$extra=array()) {
-		parent::__construct($id,$desc,$request_param);
-		$this->options = $options;
-		$this->values=array();
-	}
-	
-	
-	public function getType() {
-		return "boolean";
-	}
-	public function add() {
-		parent::add();
-		$this->values[]=$options[0];
-	}
-
-	public function getFormFields($pos=0) {
-		return '<span class="'.$labelclass.'">'.$this->desc.'</span>'.
-			form::combo($this->getFieldId($pos),$this->options,$this->values[$pos],
-				'','',false,'title="'.__('Choose an option').'"');
-	}
-	
-	public function applyFilter($params) {
-		$params[$this->request_param]=$this->values[0];
-	}
-}
-
-?>
Index: inc/admin/class.dc.menu.php
===================================================================
--- inc/admin/class.dc.menu.php	(revision 3)
+++ inc/admin/class.dc.menu.php	(revision 270)
@@ -4,5 +4,5 @@
 # This file is part of Dotclear 2.
 #
-# Copyright (c) 2003-2010 Olivier Meunier & Association Dotclear
+# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
 # Licensed under the GPL version 2.0 license.
 # See LICENSE file or
Index: inc/admin/lib.dc.page.php
===================================================================
--- inc/admin/lib.dc.page.php	(revision 224)
+++ inc/admin/lib.dc.page.php	(revision 454)
@@ -4,5 +4,5 @@
 # This file is part of Dotclear 2.
 #
-# Copyright (c) 2003-2010 Olivier Meunier & Association Dotclear
+# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
 # Licensed under the GPL version 2.0 license.
 # See LICENSE file or
@@ -16,4 +16,6 @@
 class dcPage
 {
+	private static $loaded_js=array();
+
 	# Auth check
 	public static function check($permissions)
@@ -73,5 +75,5 @@
 			__('Blogs:').' '.
 			$core->formNonce().
-			form::combo('switchblog',$blogs,$core->blog->id,	'',1).
+			form::combo('switchblog',$blogs,$core->blog->id).
 			'</label>'.
 			'<noscript><div><input type="submit" value="'.__('ok').'" /></div></noscript>';
@@ -102,4 +104,10 @@
 			echo '  <style type="text/css">'."\n".'  @import "style/default-rtl.css";'."\n"."  </style>\n";
 		}
+
+		$core->auth->user_prefs->addWorkspace('interface');
+		$user_ui_hide_std_favicon = $core->auth->user_prefs->interface->hide_std_favicon;
+		if (!$user_ui_hide_std_favicon) {
+			echo '<link rel="icon" type="image/png" href="images/favicon.png" />';
+		}
 		
 		echo
@@ -116,4 +124,5 @@
 		'">'."\n".
 		
+		'<ul id="prelude"><li><a href="#content">Aller au contenu</a></li><li><a href="#main-menu">Aller au menu</a></li></ul>'."\n".
 		'<div id="top"><h1><a href="index.php">'.DC_VENDOR_NAME.'</a></h1></div>'."\n";
 		
@@ -264,7 +273,7 @@
 			} else {
 				$prof_url = http::getSelfURI();
-				$prof_url .= (strpos($prof_url,'?') === false) ? '?' : '&amp;';
+				$prof_url .= (strpos($prof_url,'?') === false) ? '?' : '&';
 				$prof_url .= 'XDEBUG_PROFILE';
-				$res .= '<p><a href="'.$prof_url.'">Trigger profiler</a></p>';
+				$res .= '<p><a href="'.html::escapeURL($prof_url).'">Trigger profiler</a></p>';
 			}
 			
@@ -343,5 +352,9 @@
 	public static function jsLoad($src)
 	{
-		return '<script type="text/javascript" src="'.html::escapeHTML($src).'"></script>'."\n";
+		$escaped_src = html::escapeHTML($src);
+		if (!isset(self::$loaded_js[$escaped_src])) {
+			self::$loaded_js[$escaped_src]=true;
+			return '<script type="text/javascript" src="'.$escaped_src.'"></script>'."\n";
+		}
 	}
 	
@@ -358,4 +371,5 @@
 		self::jsLoad('js/jquery/jquery.bgFade.js').
 		self::jsLoad('js/common.js').
+		self::jsLoad('js/prelude.js').
 		
 		'<script type="text/javascript">'."\n".
Index: inc/admin/lib.pager.php
===================================================================
--- inc/admin/lib.pager.php	(revision 463)
+++ inc/admin/lib.pager.php	(revision 270)
@@ -4,5 +4,5 @@
 # This file is part of Dotclear 2.
 #
-# Copyright (c) 2003-2010 Olivier Meunier & Association Dotclear
+# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
 # Licensed under the GPL version 2.0 license.
 # See LICENSE file or
@@ -12,232 +12,10 @@
 if (!defined('DC_RC_PATH')) { return; }
 
-/**
-@ingroup DC_CORE
-@nosubgrouping
-@brief Dotclear Pager class.
-
-Dotclear Pager handles pagination for every admin list.
-*/
-class dcPager extends pager
-{
-	public function getLinks()
-	{
-		$htmlText = '';
-		$htmlStart = '';
-		$htmlEnd = '';
-		$htmlPrev = '';
-		$htmlNext = '';
-		$htmlDirectAccess = '';
-		$htmlHidden = '';
-		
-		$this->setURL();
-		
-		# Page text
-		$htmlText = '<span>'.sprintf(__('Page %s over %s'),$this->env,$this->nb_pages).'</span>';
-		
-		# Previous page
-		if($this->env != 1) {
-			$htmlPrev = '<a href="'.sprintf($this->page_url,$this->env-1).'" class="prev">'.
-			$htmlPrev .= $this->html_prev.'</a>';
-		}
-		
-		# Next page
-		if($this->env != $this->nb_pages) {
-			$htmlNext = '<a href="'.sprintf($this->page_url,$this->env+1).'" class="next">';
-			$htmlNext .= $this->html_next.'</a>';
-		}
-		
-		# Start
-		if($this->env != 1) {
-			$htmlStart = '<a href="'.sprintf($this->page_url,1).'" class="start">'.
-			$htmlStart .= $this->html_start.'</a>';
-		}
-		
-		# End
-		if($this->env != $this->nb_pages) {
-			$htmlEnd = '<a href="'.sprintf($this->page_url,$this->nb_elements).'" class="end">'.
-			$htmlEnd .= $this->html_end.'</a>';
-		}
-		
-		# Direct acces
-		$htmlDirectAccess = 
-			'<span>'.__('Direct access to page').'&nbsp;'.
-			form::field(array('page'),3,3,$this->env).'&nbsp;'.
-			'<input type="submit" value="'.__('ok').'" />'.
-			'</span>';
-			
-		# Hidden fields
-		foreach ($_GET as $k => $v) {
-			if ($k != $this->var_page) {
-				$htmlHidden .= form::hidden(array($k),$v);
-			}
-		}
-		
-		$res =
-			'<form method="get" action="'.$this->base_url.'"><p>'.
-			$htmlStart.
-			$htmlPrev.
-			$htmlText.
-			$htmlNext.
-			$htmlEnd.
-			$htmlDirectAccess.
-			$htmlHidden.
-			'</p></form>';
-		
-		return $this->nb_elements > 0 ? $res : '';
-	}
-}
-
-/**
-@ingroup DC_CORE
-@nosubgrouping
-@brief Dotclear Generic column class.
-
-Dotclear Generic column handles each column object use in adminGenericList class.
-*/
-class adminGenericColumn
-{
-	protected $core;		/// <b>object</b> dcCore object
-	protected $id;			/// <b>string</b> ID of defined column
-	protected $title;		/// <b>string</b> Title of defined column
-	protected $callback;	/// <b>array</b> Callback calls to display defined column
-	protected $html;		/// <b>string</b> Extra HTML for defined column
-	protected $visibility;	/// <b>boolean</b> Visibility of defined column
-	
-	/**
-	Inits Generic column object
-	
-	@param	id		<b>string</b>		Column id
-	@param	title	<b>string</b>		Column title (for table headers)
-	@param	callback	<b>array</b>		Column callback (used for display)
-	@param	html		<b>string</b>		Extra html (used for table headers)
-	@param	can_hide	<b>boolean</b>		Defines if the column can be hidden or not
-	*/
-	public function __construct($id,$title,$callback,$html = null,$can_hide = true)
-	{
-		if (!is_string($id) || $id === '') {
-			throw new Exception(__('Invalid column ID'));
-		}
-		
-		if (!is_string($title)) {
-			throw new Exception(__('Invalid column title'));
-		}
-		
-		if (is_null($html) || !is_string($html)) {
-			$html = '';
-		}
-		if (!empty($html)) {
-			$html = ' '.$html;
-		}
-		
-		if (!is_bool($can_hide)) {
-			$can_hide = true;
-		}
-		
-		try {
-			if (!is_array($callback) || count($callback) < 2) {
-				throw new Exception(__('Callback parameter should be an array'));
-			}
-			$r = new ReflectionClass($callback[0]);
-			$f = $r->getMethod($callback[1]);
-			$p = $r->getParentClass();
-			$find_parent = false;
-			
-			while (!$p) {
-				if ($p->name == 'adminGenericList') {
-					$find_parent = true;
-				}
-				else {
-					$p->getParentClass();
-				}
-			}
-			
-			if (!$p || !$f) {
-				throw new Exception(__('Callback class should be inherited of adminGenericList class'));
-			}
-		}
-		catch (Exception $e) {
-			throw new Exception(sprintf(__('Invalid column callback: %s'),$e->getMessage()));
-		}
-		
-		$this->id = $id;
-		$this->title = $title;
-		$this->callback = $callback;
-		$this->html = $html;
-		$this->can_hide = $can_hide;
-		$this->visibility = true;
-	}
-	
-	/**
-	Gets information of defined column
-	
-	@param	info		<b>string</b>		Column info to retrive
-	
-	@return	<b>mixed</b>	The information requested, null otherwise
-	*/
-	public function getInfo($info)
-	{
-		return property_exists(get_class($this),$info) ? $this->{$info} : null;
-	}
-	
-	/**
-	Sets visibility of defined column
-	
-	@param	visibility	<b>boolean</b>		Column visibility
-	*/
-	public function setVisibility($visibility)
-	{
-		if (is_bool($visibility)) {
-			$this->visibility = $visibility;
-		}
-	}
-	
-	/**
-	Returns visibility status of defined column
-	
-	@return	<b>boolean</b>		true if column is visible, false otherwise
-	*/
-	public function isVisible()
-	{
-		return $this->visibility;
-	}
-	
-	/**
-	Returns if the defined column can be hidden
-	
-	@return	<b>boolean</b>	true if column can be hidden, false otherwise
-	*/
-	public function canHide()
-	{
-		return $this->can_hide;
-	}
-}
-
-/**
-@ingroup DC_CORE
-@nosubgrouping
-@brief abstract Generic list class.
-
-Dotclear Generic list handles administration lists
-*/
-abstract class adminGenericList
+class adminGenericList
 {
 	protected $core;
 	protected $rs;
 	protected $rs_count;
-	protected $columns;
 	
-	/*
-	Sets columns of defined list
-	*/
-	public function setColumns() {}
-	
-	/**
-	Inits List object
-	
-	@param	core		<b>dcCore</b>		dcCore object
-	@param	rs		<b>recordSet</b>	Items recordSet to display
-	@param	rs_count	<b>int</b>		Total items number
-	*/
 	public function __construct($core,$rs,$rs_count)
 	{
@@ -245,91 +23,34 @@
 		$this->rs =& $rs;
 		$this->rs_count = $rs_count;
-		$this->context = get_class($this);
-		$this->columns = array();
-		$this->form_prefix = 'col_%s';
-		$this->form_trigger = 'add_filter';
-		
-		$this->html_prev = __('prev');
-		$this->html_next = __('next');
-		$this->html_start = __('start');
-		$this->html_end = __('end');
-		
-		$this->setColumns();
-		
-		$core->callBehavior('adminListConstruct',$this);
-		
-		$this->setColumnsVisibility();
-	}
-	
-	/**
-	Returns HTML code form used to choose which column to display
-	
-	@return	<b>string</b>		HTML code form
-	*/
-	public function getColumnsForm()
-	{
-		$block = 
-		'<h3>'.__('Displayed information').'</h3>'.
-		'<ul>%s</ul>';
-		
-		$list = array();
-		
-		foreach ($this->columns as $k => $v) {
-			$col_id = sprintf($this->form_prefix,$k);
-			$col_label = sprintf('<label for="%s">%s</label>',$col_id,$v->getInfo('title'));
-			$col_html = sprintf('<li class="line">%s</li>',$col_label.form::checkbox($col_id,1,$v->isVisible(),null,null,!$v->canHide()));
-			
-			array_push($list,$col_html);
-		}
-		
-		$nb_per_page = isset($_GET['nb']) ? $_GET['nb'] : 10;
-		
-		return
-		sprintf($block,implode('',$list)).
-		'<p><label for="nb">'.__('Items per page:').
-		'</label>&nbsp;'.form::field('nb',3,3,$nb_per_page).
-		'</p>';
-	}
-	
-	/**
-	Returns HTML code list to display
-	
-	@param	page			<b>string|int</b>	Current page
-	@param	nb_per_page	<b>string|int</b>	Number of items to display in each page
-	@param	enclose_block	<b>string</b>		HTML wrapper of defined list
-	
-	@return	<b>string</b>		HTML code list
-	*/
-	public function display($page,$nb_per_page,$enclose_block = '')
+		$this->html_prev = __('&#171;prev.');
+		$this->html_next = __('next&#187;');
+	}
+}
+
+class adminPostList extends adminGenericList
+{
+	public function display($page,$nb_per_page,$enclose_block='')
 	{
 		if ($this->rs->isEmpty())
 		{
-			echo '<p><strong>'.__('No item').'</strong></p>';
+			echo '<p><strong>'.__('No entry').'</strong></p>';
 		}
 		else
 		{
-			$pager = new dcPager($page,$this->rs_count,$nb_per_page,10);
+			$pager = new pager($page,$this->rs_count,$nb_per_page,10);
 			$pager->html_prev = $this->html_prev;
 			$pager->html_next = $this->html_next;
-			$pager->html_start = $this->html_start;
-			$pager->html_end = $this->html_end;
 			$pager->var_page = 'page';
 			
 			$html_block =
-			'<table class="maximal clear">'.
-			$this->getCaption($page).
-			'<thead><tr>';
-			
-			foreach ($this->columns as $k => $v) {
-				if ($v->isVisible()) {
-					$html_extra = $v->getInfo('html') != '' ? ' '.$v->getInfo('html') : '';
-					$html_block .= sprintf('<th scope="col"%s>%s</th>',$html_extra,$v->getInfo('title'));
-				}
-			}
-			
-			$html_block .=
-			'</tr></thead>'.
-			'<tbody>%s</tbody>'.
-			'</table>';
+			'<table class="clear"><tr>'.
+			'<th colspan="2">'.__('Title').'</th>'.
+			'<th>'.__('Date').'</th>'.
+			'<th>'.__('Category').'</th>'.
+			'<th>'.__('Author').'</th>'.
+			'<th>'.__('Comments').'</th>'.
+			'<th>'.__('Trackbacks').'</th>'.
+			'<th>'.__('Status').'</th>'.
+			'</tr>%s</table>';
 			
 			if ($enclose_block) {
@@ -337,5 +58,5 @@
 			}
 			
-			echo '<div class="pagination">'.$pager->getLinks().'</div>';
+			echo '<p>'.__('Page(s)').' : '.$pager->getLinks().'</p>';
 			
 			$blocks = explode('%s',$html_block);
@@ -345,176 +66,14 @@
 			while ($this->rs->fetch())
 			{
-				echo $this->displayLine();
+				echo $this->postLine();
 			}
 			
 			echo $blocks[1];
 			
-			echo '<div class="pagination">'.$pager->getLinks().'</div>';
+			echo '<p>'.__('Page(s)').' : '.$pager->getLinks().'</p>';
 		}
 	}
 	
-	/**
-	Adds column to defined list
-	
-	@param	id		<b>string</b>		Column id
-	@param	title	<b>string</b>		Column title (for table headers)
-	@param	callback	<b>array</b>		Column callback (used for display)
-	@param	html		<b>string</b>		Extra html (used for table headers)
-	@param	can_hide	<b>boolean</b>		Defines if the column can be hidden or not
-	*/
-	protected function addColumn($id,$title,$callback,$html = null,$can_hide = true)
-	{
-		try {
-			$c = new adminGenericColumn($id,$title,$callback,$html,$can_hide);
-			$this->columns[$id] = $c;
-		}
-		catch (Exception $e) {
-			if (DC_DEBUG) {
-				$this->core->error->add($e->getMessage());
-			}
-		}
-	}
-	
-	/**
-	Returns default caption text
-	
-	@return	<b>string</b>		Default caption
-	*/
-	protected function getDefaultCaption()
-	{
-		return;
-	}
-	
-	/**
-	Returns default HTMl code line
-	
-	@return	<b>string</b>		Default HTMl code line
-	*/
-	protected function getDefaultLine()
-	{
-		return '<tr class="line">%s</tr>';
-	}
-	
-	/**
-	Sets columns visibility of defined list
-	*/
-	private function setColumnsVisibility()
-	{
-		$ws = $this->core->auth->user_prefs->addWorkspace('lists');
-		
-		$user_pref = !is_null($ws->{$this->context}) ? unserialize($ws->{$this->context}) : array();
-		
-		foreach ($this->columns as $k => $v) {
-			$visibility =  array_key_exists($k,$user_pref) ? $user_pref[$k] : true;
-			if (array_key_exists($this->form_trigger,$_REQUEST)) {
-				$key = sprintf($this->form_prefix,$k);
-				$visibility = !array_key_exists($key,$_REQUEST) ? false : true;
-			}
-			if (!$v->canHide()) {
-				$visibility = true;
-			}
-			$v->setVisibility($visibility);
-			$user_pref[$k] = $visibility;
-		}
-		
-		if (array_key_exists($this->form_trigger,$_REQUEST)) {
-			$this->core->auth->user_prefs->lists->put($this->context,serialize($user_pref),'string');
-		}
-	}
-	
-	/**
-	Returns HTML code for each line of defined list
-	
-	@return	<b>string</b>		HTML code line
-	*/
-	private function displayLine()
-	{
-		$res = '';
-		
-		foreach ($this->columns as $k => $v) {
-			if ($v->isVisible()) {
-				$c = $v->getInfo('callback');
-				$res .= $this->{$c[1]}();
-			}
-		}
-		
-		return sprintf($this->getDefaultLine(),$res);
-	}
-	
-	/**
-	Returns caption of defined list
-	
-	@param	page			<b>string|int</b>	Current page
-	
-	@return	<b>string</b>		HTML caption tag
-	*/
-	private function getCaption($page)
-	{
-		$caption = $this->getDefaultCaption();
-		
-		if (!empty($caption)) {
-			$caption = sprintf(
-				'<caption>%s - %s</caption>',
-				$caption,sprintf(__('Page %s'),$page)
-			);
-		}
-		
-		return $caption;
-	}
-}
-
-/**
-@ingroup DC_CORE
-@nosubgrouping
-@brief abstract posts list class.
-
-Handle posts list on admin side
-*/
-class adminPostList extends adminGenericList
-{
-	public function setColumns()
-	{
-		$this->addColumn('title',__('Title'),array('adminPostList','getTitle'),' class="maximal"',false);
-		$this->addColumn('date',__('Date'),array('adminPostList','getDate'));
-		$this->addColumn('datetime',__('Date and time'),array('adminPostList','getDateTime'));
-		$this->addColumn('category',__('Category'),array('adminPostList','getCategory'));
-		$this->addColumn('author',__('Author'),array('adminPostList','getAuthor'));
-		$this->addColumn('comment',__('Comments'),array('adminPostList','getComments'));
-		$this->addColumn('trackback',__('Trackbacks'),array('adminPostList','getTrackbacks'));
-		$this->addColumn('status',__('Status'),array('adminPostList','getStatus'));
-	}
-	
-	protected function getDefaultCaption()
-	{
-		return __('Entries list');
-	}
-	
-	protected function getDefaultLine()
-	{
-		return
-		'<tr class="line'.($this->rs->post_status != 1 ? ' offline' : '').'"'.
-		' id="p'.$this->rs->post_id.'">%s</tr>';
-	}
-	
-	protected function getTitle()
-	{
-		return
-		'<th scope="row" class="maximal">'.
-		form::checkbox(array('entries[]'),$this->rs->post_id,'','','',!$this->rs->isEditable()).'&nbsp;'.
-		'<a href="'.$this->core->getPostAdminURL($this->rs->post_type,$this->rs->post_id).'">'.
-		html::escapeHTML($this->rs->post_title).'</a></th>';
-	}
-	
-	protected function getDate()
-	{
-		return '<td class="nowrap">'.dt::dt2str(__('%Y-%m-%d'),$this->rs->post_dt).'</td>';
-	}
-	
-	protected function getDateTime()
-	{
-		return '<td class="nowrap">'.dt::dt2str(__('%Y-%m-%d %H:%M'),$this->rs->post_dt).'</td>';
-	}
-	
-	protected function getCategory()
+	private function postLine()
 	{
 		if ($this->core->auth->check('categories',$this->core->blog->id)) {
@@ -531,24 +90,4 @@
 		}
 		
-		return '<td class="nowrap">'.$cat_title.'</td>';
-	}
-	
-	protected function getAuthor()
-	{
-		return '<td class="nowrap">'.$this->rs->user_id.'</td>';
-	}
-	
-	protected function getComments()
-	{
-		return '<td class="nowrap">'.$this->rs->nb_comment.'</td>';
-	}
-	
-	protected function getTrackbacks()
-	{
-		return '<td class="nowrap">'.$this->rs->nb_trackback.'</td>';
-	}
-	
-	protected function getStatus()
-	{
 		$img = '<img alt="%1$s" title="%1$s" src="images/%2$s" />';
 		switch ($this->rs->post_status) {
@@ -584,85 +123,166 @@
 		}
 		
-		return '<td class="nowrap status">'.$img_status.' '.$selected.' '.$protected.' '.$attach.'</td>';
+		$res = '<tr class="line'.($this->rs->post_status != 1 ? ' offline' : '').'"'.
+		' id="p'.$this->rs->post_id.'">';
+		
+		$res .=
+		'<td class="nowrap">'.
+		form::checkbox(array('entries[]'),$this->rs->post_id,'','','',!$this->rs->isEditable()).'</td>'.
+		'<td class="maximal"><a href="'.$this->core->getPostAdminURL($this->rs->post_type,$this->rs->post_id).'">'.
+		html::escapeHTML($this->rs->post_title).'</a></td>'.
+		'<td class="nowrap">'.dt::dt2str(__('%Y-%m-%d %H:%M'),$this->rs->post_dt).'</td>'.
+		'<td class="nowrap">'.$cat_title.'</td>'.
+		'<td class="nowrap">'.$this->rs->user_id.'</td>'.
+		'<td class="nowrap">'.$this->rs->nb_comment.'</td>'.
+		'<td class="nowrap">'.$this->rs->nb_trackback.'</td>'.
+		'<td class="nowrap status">'.$img_status.' '.$selected.' '.$protected.' '.$attach.'</td>'.
+		'</tr>';
+		
+		return $res;
 	}
 }
 
-/**
-@ingroup DC_CORE
-@nosubgrouping
-@brief abstract mini posts list class.
-
-Handle mini posts list on admin side (used for link popup)
-*/
-class adminPostMiniList extends adminPostList
+class adminPostMiniList extends adminGenericList
 {
-	public function setColumns()
-	{
-		$this->addColumn('title',__('Title'),array('adminPostMiniList','getTitle'),' class="maximal"',false);
-		$this->addColumn('date',__('Date'),array('adminPostList','getDate'));
-		$this->addColumn('author',__('Author'),array('adminPostList','getAuthor'));
-		$this->addColumn('status',__('Status'),array('adminPostList','getStatus'));
+	public function display($page,$nb_per_page,$enclose_block='')
+	{
+		if ($this->rs->isEmpty())
+		{
+			echo '<p><strong>'.__('No entry').'</strong></p>';
+		}
+		else
+		{
+			$pager = new pager($page,$this->rs_count,$nb_per_page,10);
+			$pager->html_prev = $this->html_prev;
+			$pager->html_next = $this->html_next;
+			$pager->var_page = 'page';
+			
+			$html_block =
+			'<table class="clear"><tr>'.
+			'<th>'.__('Title').'</th>'.
+			'<th>'.__('Date').'</th>'.
+			'<th>'.__('Author').'</th>'.
+			'<th>'.__('Status').'</th>'.
+			'</tr>%s</table>';
+			
+			if ($enclose_block) {
+				$html_block = sprintf($enclose_block,$html_block);
+			}
+			
+			echo '<p>'.__('Page(s)').' : '.$pager->getLinks().'</p>';
+			
+			$blocks = explode('%s',$html_block);
+			
+			echo $blocks[0];
+			
+			while ($this->rs->fetch())
+			{
+				echo $this->postLine();
+			}
+			
+			echo $blocks[1];
+			
+			echo '<p>'.__('Page(s)').' : '.$pager->getLinks().'</p>';
+		}
 	}
 	
-	protected function getTitle() 
-	{
-		return
-		'<th scope="row" class="maximal">'.
-		form::checkbox(array('entries[]'),$this->rs->post_id,'','','',!$this->rs->isEditable()).'&nbsp;'.
-		'<a href="'.$this->core->getPostAdminURL($this->rs->post_type,$this->rs->post_id).'" '.
+	private function postLine()
+	{
+		$img = '<img alt="%1$s" title="%1$s" src="images/%2$s" />';
+		switch ($this->rs->post_status) {
+			case 1:
+				$img_status = sprintf($img,__('published'),'check-on.png');
+				break;
+			case 0:
+				$img_status = sprintf($img,__('unpublished'),'check-off.png');
+				break;
+			case -1:
+				$img_status = sprintf($img,__('scheduled'),'scheduled.png');
+				break;
+			case -2:
+				$img_status = sprintf($img,__('pending'),'check-wrn.png');
+				break;
+		}
+		
+		$protected = '';
+		if ($this->rs->post_password) {
+			$protected = sprintf($img,__('protected'),'locker.png');
+		}
+		
+		$selected = '';
+		if ($this->rs->post_selected) {
+			$selected = sprintf($img,__('selected'),'selected.png');
+		}
+		
+		$attach = '';
+		$nb_media = $this->rs->countMedia();
+		if ($nb_media > 0) {
+			$attach_str = $nb_media == 1 ? __('%d attachment') : __('%d attachments');
+			$attach = sprintf($img,sprintf($attach_str,$nb_media),'attach.png');
+		}
+		
+		$res = '<tr class="line'.($this->rs->post_status != 1 ? ' offline' : '').'"'.
+		' id="p'.$this->rs->post_id.'">';
+		
+		$res .=
+		'<td class="maximal"><a href="'.$this->core->getPostAdminURL($this->rs->post_type,$this->rs->post_id).'" '.
 		'title="'.html::escapeHTML($this->rs->getURL()).'">'.
-		html::escapeHTML($this->rs->post_title).'</a></td>';
+		html::escapeHTML($this->rs->post_title).'</a></td>'.
+		'<td class="nowrap">'.dt::dt2str(__('%Y-%m-%d %H:%M'),$this->rs->post_dt).'</td>'.
+		'<td class="nowrap">'.$this->rs->user_id.'</td>'.
+		'<td class="nowrap status">'.$img_status.' '.$selected.' '.$protected.' '.$attach.'</td>'.
+		'</tr>';
+		
+		return $res;
 	}
 }
 
-/**
-@ingroup DC_CORE
-@nosubgrouping
-@brief abstract comments list class.
-
-Handle comments list on admin side
-*/
 class adminCommentList extends adminGenericList
 {
-	public function setColumns()
-	{
-		$this->addColumn('title',__('Title'),array('adminCommentList','getTitle'),' class="maximal"',false);
-		$this->addColumn('date',__('Date'),array('adminCommentList','getDate'));
-		$this->addColumn('author',__('Author'),array('adminCommentList','getAuthor'));
-		$this->addColumn('type',__('Type'),array('adminCommentList','getType'));
-		$this->addColumn('status',__('Status'),array('adminCommentList','getStatus'));
-		$this->addColumn('edit','',array('adminCommentList','getEdit'));
+	public function display($page,$nb_per_page,$enclose_block='')
+	{
+		if ($this->rs->isEmpty())
+		{
+			echo '<p><strong>'.__('No comment').'</strong></p>';
+		}
+		else
+		{
+			$pager = new pager($page,$this->rs_count,$nb_per_page,10);
+			$pager->html_prev = $this->html_prev;
+			$pager->html_next = $this->html_next;
+			$pager->var_page = 'page';
+			
+			$html_block =
+			'<table><tr>'.
+			'<th colspan="2">'.__('Title').'</th>'.
+			'<th>'.__('Date').'</th>'.
+			'<th>'.__('Author').'</th>'.
+			'<th>'.__('Type').'</th>'.
+			'<th>'.__('Status').'</th>'.
+			'<th>&nbsp;</th>'.
+			'</tr>%s</table>';
+			
+			if ($enclose_block) {
+				$html_block = sprintf($enclose_block,$html_block);
+			}
+			
+			echo '<p>'.__('Page(s)').' : '.$pager->getLinks().'</p>';
+			
+			$blocks = explode('%s',$html_block);
+			
+			echo $blocks[0];
+			
+			while ($this->rs->fetch())
+			{
+				echo $this->commentLine();
+			}
+			
+			echo $blocks[1];
+			
+			echo '<p>'.__('Page(s)').' : '.$pager->getLinks().'</p>';
+		}
 	}
 	
-	protected function getDefaultCaption()
-	{
-		return __('Comments list');
-	}
-	
-	protected function getDefaultLine()
-	{
-		return
-		'<tr class="line'.($this->rs->comment_status != 1 ? ' offline' : '').'"'.
-		' id="c'.$this->rs->comment_id.'">%s</tr>';
-	}
-	
-	protected function getTitle()
-	{
-		$post_url = $this->core->getPostAdminURL($this->rs->post_type,$this->rs->post_id);
-		
-		return
-		'<th scope="row" class="maximal">'.
-		form::checkbox(array('comments[]'),$this->rs->comment_id,'','','',0).'&nbsp;'.
-		'<a href="'.$post_url.'">'.
-		html::escapeHTML($this->rs->post_title).'</a>'.
-		($this->rs->post_type != 'post' ? ' ('.html::escapeHTML($this->rs->post_type).')' : '').'</th>';
-	}
-	
-	protected function getDate()
-	{
-		return '<td class="nowrap">'.dt::dt2str(__('%Y-%m-%d %H:%M'),$this->rs->comment_dt).'</td>';
-	}
-	
-	protected function getAuthor()
+	private function commentLine()
 	{
 		global $author, $status, $sortby, $order, $nb_per_page;
@@ -675,19 +295,12 @@
 		'&amp;author='.rawurlencode($this->rs->comment_author);
 		
-		$comment_author = html::escapeHTML($this->rs->comment_author);
-		if (mb_strlen($comment_author) > 20) {
-			$comment_author = mb_strcut($comment_author,0,17).'...';
-		}
-		
-		return '<td class="nowrap"><a href="'.$author_url.'">'.$comment_author.'</a></td>';
-	}
-	
-	protected function getType()
-	{
-		return '<td class="nowrap">'.($this->rs->comment_trackback ? __('trackback') : __('comment')).'</td>';
-	}
-	
-	protected function getStatus()
-	{
+		$post_url = $this->core->getPostAdminURL($this->rs->post_type,$this->rs->post_id);
+		
+		$comment_url = 'comment.php?id='.$this->rs->comment_id;
+		
+		$comment_dt =
+		dt::dt2str($this->core->blog->settings->system->date_format.' - '.
+		$this->core->blog->settings->system->time_format,$this->rs->comment_dt);
+		
 		$img = '<img alt="%1$s" title="%1$s" src="images/%2$s" />';
 		switch ($this->rs->comment_status) {
@@ -706,41 +319,77 @@
 		}
 		
-		return '<td class="nowrap status">'.$img_status.'</td>';
-	}
-	
-	protected function getEdit()
-	{
-		$comment_url = 'comment.php?id='.$this->rs->comment_id;
-		
-		return
+		$comment_author = html::escapeHTML($this->rs->comment_author);
+		if (mb_strlen($comment_author) > 20) {
+			$comment_author = mb_strcut($comment_author,0,17).'...';
+		}
+		
+		$res = '<tr class="line'.($this->rs->comment_status != 1 ? ' offline' : '').'"'.
+		' id="c'.$this->rs->comment_id.'">';
+		
+		$res .=
+		'<td class="nowrap">'.
+		form::checkbox(array('comments[]'),$this->rs->comment_id,'','','',0).'</td>'.
+		'<td class="maximal"><a href="'.$post_url.'">'.
+		html::escapeHTML($this->rs->post_title).'</a>'.
+		($this->rs->post_type != 'post' ? ' ('.html::escapeHTML($this->rs->post_type).')' : '').'</td>'.
+		'<td class="nowrap">'.dt::dt2str(__('%Y-%m-%d %H:%M'),$this->rs->comment_dt).'</td>'.
+		'<td class="nowrap"><a href="'.$author_url.'">'.$comment_author.'</a></td>'.
+		'<td class="nowrap">'.($this->rs->comment_trackback ? __('trackback') : __('comment')).'</td>'.
+		'<td class="nowrap status">'.$img_status.'</td>'.
 		'<td class="nowrap status"><a href="'.$comment_url.'">'.
 		'<img src="images/edit-mini.png" alt="" title="'.__('Edit this comment').'" /></a></td>';
+		
+		$res .= '</tr>';
+		
+		return $res;
 	}
 }
 
-/**
-@ingroup DC_CORE
-@nosubgrouping
-@brief abstract users list class.
-
-Handle users list on admin side
-*/
 class adminUserList extends adminGenericList
 {
-	public function setColumns()
-	{
-		$this->addColumn('username',__('Username'),array('adminUserList','getUserName'),'class="maximal"',false);
-		$this->addColumn('firstname',__('First name'),array('adminUserList','getFirstName'),'class="nowrap"');
-		$this->addColumn('lastname',__('Last name'),array('adminUserList','getLastName'),'class="nowrap"');
-		$this->addColumn('displayname',__('Display name'),array('adminUserList','getDisplayName'),'class="nowrap"');
-		$this->addColumn('entries',__('Entries'),array('adminUserList','getEntries'),'class="nowrap"');
+	public function display($page,$nb_per_page,$enclose_block='')
+	{
+		if ($this->rs->isEmpty())
+		{
+			echo '<p><strong>'.__('No user').'</strong></p>';
+		}
+		else
+		{
+			$pager = new pager($page,$this->rs_count,$nb_per_page,10);
+			$pager->html_prev = $this->html_prev;
+			$pager->html_next = $this->html_next;
+			$pager->var_page = 'page';
+			
+			$html_block =
+			'<table class="clear"><tr>'.
+			'<th colspan="2">'.__('Username').'</th>'.
+			'<th>'.__('First Name').'</th>'.
+			'<th>'.__('Last Name').'</th>'.
+			'<th>'.__('Display name').'</th>'.
+			'<th class="nowrap">'.__('Entries').'</th>'.
+			'</tr>%s</table>';
+			
+			if ($enclose_block) {
+				$html_block = sprintf($enclose_block,$html_block);
+			}
+			
+			echo '<p>'.__('Page(s)').' : '.$pager->getLinks().'</p>';
+			
+			$blocks = explode('%s',$html_block);
+			
+			echo $blocks[0];
+			
+			while ($this->rs->fetch())
+			{
+				echo $this->userLine();
+			}
+			
+			echo $blocks[1];
+			
+			echo '<p>'.__('Page(s)').' : '.$pager->getLinks().'</p>';
+		}
 	}
 	
-	protected function getDefaultCaption()
-	{
-		return __('Users list');
-	}
-	
-	protected function getUserName()
+	private function userLine()
 	{
 		$img = '<img alt="%1$s" title="%1$s" src="images/%2$s" />';
@@ -755,140 +404,17 @@
 			$img_status = sprintf($img,__('superadmin'),'superadmin.png');
 		}
-		
 		return
-		'<th scope="row" class="maximal">'.form::hidden(array('nb_post[]'),(integer) $this->rs->nb_post).
-		form::checkbox(array('user_id[]'),$this->rs->user_id).'&nbsp;'.
-		'<a href="user.php?id='.$this->rs->user_id.'">'.
-		$this->rs->user_id.'</a>&nbsp;'.$img_status.'</th>';
-	}
-	
-	protected function getFirstName()
-	{
-		return '<td class="nowrap">'.$this->rs->user_firstname.'</td>';
-	}
-	
-	protected function getLastName()
-	{
-		return '<td class="nowrap">'.$this->rs->user_name.'</td>';
-	}
-	
-	protected function getDisplayName()
-	{
-		return '<td class="nowrap">'.$this->rs->user_displayname.'</td>';
-	}
-	
-	protected function getEntries()
-	{
-		return
+		'<tr class="line">'.
+		'<td class="nowrap">'.form::hidden(array('nb_post[]'),(integer) $this->rs->nb_post).
+		form::checkbox(array('user_id[]'),$this->rs->user_id).'</td>'.
+		'<td class="maximal"><a href="user.php?id='.$this->rs->user_id.'">'.
+		$this->rs->user_id.'</a>&nbsp;'.$img_status.'</td>'.
+		'<td class="nowrap">'.$this->rs->user_firstname.'</td>'.
+		'<td class="nowrap">'.$this->rs->user_name.'</td>'.
+		'<td class="nowrap">'.$this->rs->user_displayname.'</td>'.
 		'<td class="nowrap"><a href="posts.php?user_id='.$this->rs->user_id.'">'.
-		$this->rs->nb_post.'</a></td>';
+		$this->rs->nb_post.'</a></td>'.
+		'</tr>';
 	}
 }
-
-/**
-@ingroup DC_CORE
-@nosubgrouping
-@brief abstract blogs list class.
-
-Handle blogs list on admin side
-*/
-class adminBlogList extends adminGenericList
-{
-	public function setColumns()
-	{
-		$this->addColumn('blogname',__('Blog name'),array('adminBlogList','getBlogName'),'class="maximal"',false);
-		$this->addColumn('lastupdate',__('Last update'),array('adminBlogList','getLastUpdate'),'class="nowrap"');
-		$this->addColumn('entries',__('Entries'),array('adminBlogList','getEntries'),'class="nowrap"');
-		$this->addColumn('blogid',__('Blog ID'),array('adminBlogList','getBlogId'),'class="nowrap"');
-		$this->addColumn('action','',array('adminBlogList','getAction'),'class="nowrap"');
-		$this->addColumn('status',__('status'),array('adminBlogList','getStatus'),'class="nowrap"');
-	}
-	
-	protected function getDefaultCaption()
-	{
-		return __('Blogs list');
-	}
-	
-	protected function getBlogName()
-	{
-		return
-		'<th scope="row" class="maximal"><a href="index.php?switchblog='.$this->rs->blog_id.'" '.
-		'title="'.sprintf(__('Switch to blog %s'),$this->rs->blog_id).'">'.
-		html::escapeHTML($this->rs->blog_name).'</a></th>';
-	}
-	
-	protected function getLastUpdate()
-	{
-		$offset = dt::getTimeOffset($this->core->auth->getInfo('user_tz'));
-		$blog_upddt = dt::str(__('%Y-%m-%d %H:%M'),strtotime($this->rs->blog_upddt) + $offset);
-	
-		return '<td class="nowrap">'.$blog_upddt.'</td>';
-	}
-	
-	protected function getEntries()
-	{
-		return '<td class="nowrap">'.$this->core->countBlogPosts($this->rs->blog_id).'</td>';
-	}
-	
-	protected function getBlogId()
-	{
-		return '<td class="nowrap">'.html::escapeHTML($this->rs->blog_id).'</td>';
-	}
-	
-	protected function getAction()
-	{
-		$edit_link = '';
-		$blog_id = html::escapeHTML($this->rs->blog_id);
-	
-		if ($GLOBALS['core']->auth->isSuperAdmin()) {
-			$edit_link = 
-			'<a href="blog.php?id='.$blog_id.'" '.
-			'title="'.sprintf(__('Edit blog %s'),$blog_id).'">'.
-			__('edit').'</a>';
-		}
-		
-		return '<td class="nowrap">'.$edit_link.'</td>';
-	}
-	
-	protected function getStatus()
-	{
-		$img_status = $this->rs->blog_status == 1 ? 'check-on' : 'check-off';
-		$txt_status = $GLOBALS['core']->getBlogStatus($this->rs->blog_status);
-		$img_status = sprintf('<img src="images/%1$s.png" alt="%2$s" title="%2$s" />',$img_status,$txt_status);
-		
-		return '<td class="status">'.$img_status.'</td>';
-	}
-}
-
-/**
-@ingroup DC_CORE
-@nosubgrouping
-@brief abstract blogs permissions list class.
-
-Handle blogs permissions list on admin side
-*/
-class adminBlogPermissionsList extends adminBlogList
-{
-	public function setColumns()
-	{
-		$this->addColumn('blogid',__('Blog ID'),array('adminBlogPermissionsList','getBlogId'),'class="nowrap"',false);
-		$this->addColumn('blogname',__('Blog name'),array('adminBlogPermissionsList','getBlogName'),'class="maximal"');
-		$this->addColumn('entries',__('Entries'),array('adminBlogList','getEntries'),'class="nowrap"');
-		$this->addColumn('status',__('status'),array('adminBlogList','getStatus'),'class="nowrap"');
-	}
-	
-	protected function getBlogId()
-	{
-		return
-		'<th scope="row" class="nowrap">'.
-		form::checkbox(array('blog_id[]'),$this->rs->blog_id,'','','',false,'title="'.__('select').' '.$this->rs->blog_id.'"').
-		$this->rs->blog_id.'</th>';
-	}
-	
-	protected function getBlogName()
-	{
-		return '<td class="maximal">'.html::escapeHTML($this->rs->blog_name).'</td>';
-	}
-}
-
 ?>
Index: inc/admin/prepend.php
===================================================================
--- inc/admin/prepend.php	(revision 185)
+++ inc/admin/prepend.php	(revision 468)
@@ -4,5 +4,5 @@
 # This file is part of Dotclear 2.
 #
-# Copyright (c) 2003-2010 Olivier Meunier & Association Dotclear
+# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
 # Licensed under the GPL version 2.0 license.
 # See LICENSE file or
@@ -21,4 +21,24 @@
 
 define('DC_CONTEXT_ADMIN',true);
+
+function dc_valid_fav($url) {
+	global $core;
+	
+	$parts = parse_url($url);
+	if (isset($parts['path'])) {
+		if ($parts['path'] == 'plugin.php') {
+			if (isset($parts['query'])) {
+				$parts = explode('&', $parts['query']);
+				$param = explode('=', $parts[0]);
+				if (($param[0] == 'p') && (isset($param[1]))) {
+					if (!$core->plugins->moduleExists($param[1])) {
+						return false;
+					}
+				}
+			}
+		}
+	}
+	return true;
+}
 
 function dc_prepare_url($url) {
@@ -185,43 +205,43 @@
 	# NB : '*' in permissions means any, null means super admin only
 	
-	$_fav['prefs'] = new ArrayObject(array('prefs',__('My preferences'),'preferences.php',
+	$_fav['prefs'] = new ArrayObject(array('prefs','My preferences','preferences.php',
 		'images/menu/user-pref.png','images/menu/user-pref-b.png',
 		'*',null,null));
 
-	$_fav['new_post'] = new ArrayObject(array('new_post',__('New entry'),'post.php',
+	$_fav['new_post'] = new ArrayObject(array('new_post','New entry','post.php',
 		'images/menu/edit.png','images/menu/edit-b.png',
 		'usage,contentadmin',null,'menu-new-post'));
-	$_fav['posts'] = new ArrayObject(array('posts',__('Entries'),'posts.php',
+	$_fav['posts'] = new ArrayObject(array('posts','Entries','posts.php',
 		'images/menu/entries.png','images/menu/entries-b.png',
 		'usage,contentadmin',null,null));
-	$_fav['comments'] = new ArrayObject(array('comments',__('Comments'),'comments.php',
+	$_fav['comments'] = new ArrayObject(array('comments','Comments','comments.php',
 		'images/menu/comments.png','images/menu/comments-b.png',
 		'usage,contentadmin',null,null));
-	$_fav['search'] = new ArrayObject(array('search',__('Search'),'search.php',
+	$_fav['search'] = new ArrayObject(array('search','Search','search.php',
 		'images/menu/search.png','images/menu/search-b.png',
 		'usage,contentadmin',null,null));
-	$_fav['categories'] = new ArrayObject(array('categories',__('Categories'),'categories.php',
+	$_fav['categories'] = new ArrayObject(array('categories','Categories','categories.php',
 		'images/menu/categories.png','images/menu/categories-b.png',
 		'categories',null,null));
-	$_fav['media'] = new ArrayObject(array('media',__('Media manager'),'media.php',
+	$_fav['media'] = new ArrayObject(array('media','Media manager','media.php',
 		'images/menu/media.png','images/menu/media-b.png',
 		'media,media_admin',null,null));
-	$_fav['blog_pref'] = new ArrayObject(array('blog_pref',__('Blog settings'),'blog_pref.php',
+	$_fav['blog_pref'] = new ArrayObject(array('blog_pref','Blog settings','blog_pref.php',
 		'images/menu/blog-pref.png','images/menu/blog-pref-b.png',
 		'admin',null,null));
-	$_fav['blog_theme'] = new ArrayObject(array('blog_theme',__('Blog appearance'),'blog_theme.php',
+	$_fav['blog_theme'] = new ArrayObject(array('blog_theme','Blog appearance','blog_theme.php',
 		'images/menu/themes.png','images/menu/blog-theme-b.png',
 		'admin',null,null));
 
-	$_fav['blogs'] = new ArrayObject(array('blogs',__('Blogs'),'blogs.php',
+	$_fav['blogs'] = new ArrayObject(array('blogs','Blogs','blogs.php',
 		'images/menu/blogs.png','images/menu/blogs-b.png',
 		'usage,contentadmin',null,null));
-	$_fav['users'] = new ArrayObject(array('users',__('Users'),'users.php',
+	$_fav['users'] = new ArrayObject(array('users','Users','users.php',
 		'images/menu/users.png','images/menu/users-b.png',
 		null,null,null));
-	$_fav['plugins'] = new ArrayObject(array('plugins',__('Plugins'),'plugins.php',
+	$_fav['plugins'] = new ArrayObject(array('plugins','Plugins','plugins.php',
 		'images/menu/plugins.png','images/menu/plugins-b.png',
 		null,null,null));
-	$_fav['langs'] = new ArrayObject(array('langs',__('Languages'),'langs.php',
+	$_fav['langs'] = new ArrayObject(array('langs','Languages','langs.php',
 		'images/menu/langs.png','images/menu/langs-b.png',
 		null,null,null));
@@ -309,9 +329,11 @@
 		// User favorites only
 		if (!$v['global']) {
-			$count++;
 			$fav = unserialize($v['value']);
-			$_menu['Favorites']->addItem($fav['title'],$fav['url'],$fav['small-icon'],
-				preg_match(dc_prepare_url($fav['url']),$_SERVER['REQUEST_URI']),
-				(($fav['permissions'] == '*') || $core->auth->check($fav['permissions'],$core->blog->id)),$fav['id'],$fav['class']);
+			if (dc_valid_fav($fav['url'])) {
+				$count++;
+				$_menu['Favorites']->addItem(__($fav['title']),$fav['url'],$fav['small-icon'],
+					preg_match(dc_prepare_url($fav['url']),$_SERVER['REQUEST_URI']),
+					(($fav['permissions'] == '*') || $core->auth->check($fav['permissions'],$core->blog->id)),$fav['id'],$fav['class']);
+			}
 		}
 	}	
@@ -319,9 +341,11 @@
 		// Global favorites if any
 		foreach ($ws->dumpPrefs() as $k => $v) {
-			$count++;
 			$fav = unserialize($v['value']);
-			$_menu['Favorites']->addItem($fav['title'],$fav['url'],$fav['small-icon'],
-				preg_match(dc_prepare_url($fav['url']),$_SERVER['REQUEST_URI']),
-				(($fav['permissions'] == '*') || $core->auth->check($fav['permissions'],$core->blog->id)),$fav['id'],$fav['class']);
+			if (dc_valid_fav($fav[url])) {
+				$count++;
+				$_menu['Favorites']->addItem(__($fav['title']),$fav['url'],$fav['small-icon'],
+					preg_match(dc_prepare_url($fav['url']),$_SERVER['REQUEST_URI']),
+					(($fav['permissions'] == '*') || $core->auth->check($fav['permissions'],$core->blog->id)),$fav['id'],$fav['class']);
+			}
 		}
 	}
