Index: inc/admin/class.dc.filter.php
===================================================================
--- inc/admin/class.dc.filter.php	(revision 242)
+++ inc/admin/class.dc.filter.php	(revision 242)
@@ -0,0 +1,273 @@
+<?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 *****
+
+class dcFilterSet {
+
+	protected $filters;
+	protected $form_prefix;
+	protected $action;
+	protected $hideform;
+	protected $columns_form;
+	
+	public function __construct($action,$form_prefix="f_") {
+		$this->form_prefix=$form_prefix;
+		$this->filters = array();
+		$this->action = $action;
+	}
+
+	public function addFilter (Filter $filter) {
+		$filter->setFormPrefix($this->form_prefix);
+		$this->filters[$filter->id] = $filter;
+		return $this;
+	}
+
+	// Retrieves filter values from context
+	public function setValues ($form_data) {
+		$this->hideform = true;
+		if (isset($form_data['clear_filters']))
+			return;
+		foreach ($this->filters as $filter) {
+			$filter->setValues ($form_data);
+			if ($filter->isEnabled())
+				$this->hideform=false;
+		}
+		if (isset($form_data['add_filter']) && isset($this->filters[$form_data['add_filter']])) {
+			$this->filters[$form_data['add_filter']]->add();
+		}
+	}
+	
+	public function setColumnsForm($html)
+	{
+		$this->columns_form = $html;
+	}
+	
+	public function getFormFieldsAsHidden() {
+		$ret='';
+		foreach ($this->filters as $filter) {
+			$ret.= $filter->getFormFieldAsHidden();
+		}
+		return $ret;
+	}
+
+	public function getForm($action,$extra_content,$method="get",$nb_cols=3) {
+		$ret = '';
+		/*if ($this->hideform) {
+			$ret .= '<p><a id="filter-control" class="form-control" href="#">'.
+			__('Filters').'</a></p>';
+		}*/
+		$ret .= '<p><img alt="" src="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="get" id="filters-form">'.
+			'<div class="col70">'.
+			'<h3>'.__('Entries filters').'</h3>';
+			
+		$count=0;
+		$form_combo=array();
+		$form_combo['-']='';
+		foreach ($this->filters as $filter) {
+			if ($filter->isEnabled()) {
+				$ret .= $filter->getFormLine();
+			}
+			$form_combo[$filter->desc]=$filter->id;
+			$count++;
+		}
+		$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;
+	}
+
+	public function header() {
+		return dcPage::jsLoad('js/filters.js');
+	}
+	public function display() {
+		echo $this->getForm("#","");
+	}
+
+	public function applyFilters($params) {
+		$filtered = false;
+		foreach ($this->filters as $filter) {
+			if ($filter->isEnabled()) {
+				$filter->applyFilter($params);
+				$filtered = true;
+			}
+		}
+		return $filtered;
+	}
+	
+}
+
+
+abstract class Filter {
+	public $id;
+	public $desc;
+	protected $request_param;
+	protected $enabled;
+	protected $values;
+	public $field_id;
+	
+	
+	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;
+	}
+	
+	protected function getFieldId($pos=0) {
+		if ($pos == 0) {
+			return $this->field_id;
+		} else {
+			return $this->field_id.'_'.$pos;
+		}
+	}
+	
+	public function isEnabled() {
+		return $this->enabled;
+	}
+	
+	public function add() {
+		$this->enabled = true;
+	}
+	
+	public function setFormPrefix($prefix) {
+		$this->field_id = $prefix.$this->id;
+	}
+	
+	public abstract function getType();
+	
+	public function getFormFields() {
+		return '';
+	}
+
+	public function setValues($form_data) {
+/*		if (isset($form_data['c_'.$this->field_id])) {
+			$this->enabled = true;
+		}*/
+		$count=0;
+		while (isset($form_data[$this->getFieldId($count)])) {
+			if (!isset($form_data['del_'.$this->getFieldId($count)])) {
+				$this->values[] = $form_data[$this->getFieldId($count)];
+				$this->enabled = true;
+			}
+			$count++;
+		}
+	}
+	
+	public function getFormFieldAsHidden () {
+		$ret='';
+		for ($cur=0; $cur < count($this->values); $cur++) {
+			$ret .= form::hidden($this->getFieldId($cur), $this->values[$cur]);
+		}
+	}
+	public function getFormLine() {
+		$ret="";
+		for ($cur=0; $cur < count($this->values); $cur++) {
+			$ret .= '<p id="'.$this->getFieldId($cur).'" class="line" title="'.$this->desc.'">'.
+				$this->getFormFields($cur).
+				'<input id="del_'.$this->getFieldId($cur).'" class="delete" '.
+				'type="submit" title="Delete this filter" value=" - " name="del_'.$this->getFieldId($cur).'"/>'.
+				'</p>';
+		}
+		return $ret;
+	}
+	
+	public function applyFilter($params) {
+	}
+	
+}
+
+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 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="";
+		} else {
+			$desc = __('or');
+			$labelclass = ' class="or"';
+		};
+		return '<label for="'.$this->getFieldId($pos).'"'.$labelclass.'>'.$desc.'</label>'.
+			(($pos == 0) ?form::combo($this->field_id.'_v',array(__('is')=>'is',__('is not')=>'isnot'),$this->verb) : '').
+			form::combo($this->getFieldId($pos),$this->options,$this->values[$pos]);
+	}
+	
+	public function applyFilter($params) {
+		if (isset($this->extra['singleval']))
+			$params[$this->request_param]=$this->values[0];
+		else
+			$params[$this->request_param]=$this->values;
+	}
+}
+?>
Index: inc/admin/class.dc.menu.php
===================================================================
--- inc/admin/class.dc.menu.php	(revision 270)
+++ inc/admin/class.dc.menu.php	(revision 3)
@@ -4,5 +4,5 @@
 # This file is part of Dotclear 2.
 #
-# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
+# Copyright (c) 2003-2010 Olivier Meunier & Association Dotclear
 # Licensed under the GPL version 2.0 license.
 # See LICENSE file or
Index: inc/admin/class.dc.toolbar.php
===================================================================
--- inc/admin/class.dc.toolbar.php	(revision 379)
+++ inc/admin/class.dc.toolbar.php	(revision 379)
@@ -0,0 +1,127 @@
+<?php
+
+class dcToolbar
+{
+	protected $core;
+	protected $toolbars;
+	
+	public function __construct($core)
+	{
+		$this->core = $core;
+		$this->toolbars = array();
+		$this->i18n = array();
+	}
+	
+	public function addFormatter($formatter)
+	{
+		if (!is_string($formatter) || empty($formatter)) {
+			return;
+		}
+		
+		$toolbar = array(
+			'settings' => array(),
+			'plugins' => array(),
+			'buttons' => array(
+				1 => array(),
+				2 => array(),
+				3 => array(),
+				4 => array()
+			)
+		);
+		
+		$this->toolbars[$formatter] = array_key_exists($formatter,$this->toolbars) ? $this->toolbars[$formatter] : $toolbar;
+	}
+	
+	public function addSettings($formatter,$settings)
+	{
+		
+		if (!array_key_exists($formatter,$this->toolbars)) {
+			return;
+		}
+		if (!is_array($settings)) {
+			return;
+		}
+		
+		$this->toolbars[$formatter]['settings'] = array_merge($this->toolbars[$formatter]['settings'],$settings);
+	}
+	
+	public function addPlugins($formatter,$plugins)
+	{
+		if (!array_key_exists($formatter,$this->toolbars)) {
+			return;
+		}
+		if (!is_array($plugins)) {
+			return;
+		}
+		
+		$this->toolbars[$formatter]['plugins'] = array_merge($this->toolbars[$formatter]['plugins'],$plugins);
+	}
+	
+	public function addButtons($formatter,$buttons)
+	{
+		if (!array_key_exists($formatter,$this->toolbars)) {
+			return;
+		}
+		if (!is_array($buttons)) {
+			return;
+		}
+		
+		foreach($buttons as $level => $ids) {
+			if (!is_array($ids)) {
+				continue;
+			}
+			$level = !preg_match('#^[1-4]$#',$level) ? 1 : $level;
+			$this->toolbars[$formatter]['buttons'][$level] = array_merge($this->toolbars[$formatter]['buttons'][$level],$ids);
+		}
+	}
+	
+	public function addI18n($component,$i18n)
+	{
+		if (!is_array($i18n)) {
+			return;
+		}
+		if (!array_key_exists($component,$this->i18n)) {
+			$this->i18n[$component] = array();
+		}
+		
+		$this->i18n[$component] = array_merge($this->i18n[$component],$i18n);
+	}
+	
+	public function getJS()
+	{
+		$res = "dcToolBar = new dcToolBar();\n";
+		
+		$this->core->callBehavior('adminToolbar',$this);
+		
+		foreach ($this->toolbars as $formatter => $options) {
+			$s = $options['settings'];
+			
+			// Add plugins
+			array_walk($options['plugins'],create_function('&$v,$k','$v=!$v ? "-".$k : $k;'));
+			$s['plugins'] = implode(',',$options['plugins']);
+			
+			// Add buttons
+			foreach ($options['buttons'] as $level => $buttons) {
+				$s[sprintf('theme_advanced_buttons%d',$level)] = implode(',',$buttons);
+			}
+			
+			// Add configuration
+			array_walk($s,create_function('&$v,$k','$v=sprintf("%s: %s",$k,(!preg_match("#^(true|false|{.*})$#",$v)?"\'".$v."\'":$v));'));
+			$res .= sprintf("dcToolBar.setConfig('%s',{%s});\n",$formatter,implode(",\n",$s));
+		}
+		
+		// Add translation
+		$i18n = array();
+		
+		foreach ($this->i18n as $component => $values) {
+			array_walk($this->i18n[$component],create_function('&$v,$k','$v=sprintf("\'%s\': \'%s\'",$k,html::escapeJS($v));'));
+			array_push($i18n,sprintf('%s: {%s}',$component,implode(',',$this->i18n[$component])));
+		}
+		
+		$res .= !empty($i18n) ? sprintf("dcToolBar.setI18n({%s: {%s}});\n",'en',implode(",\n",$i18n)) : '';
+		
+		return $res;
+	}
+}
+
+?>
Index: inc/admin/lib.dc.page.php
===================================================================
--- inc/admin/lib.dc.page.php	(revision 344)
+++ inc/admin/lib.dc.page.php	(revision 411)
@@ -4,5 +4,5 @@
 # This file is part of Dotclear 2.
 #
-# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
+# Copyright (c) 2003-2010 Olivier Meunier & Association Dotclear
 # Licensed under the GPL version 2.0 license.
 # See LICENSE file or
@@ -16,6 +16,4 @@
 class dcPage
 {
-	private static $loaded_js=array();
-
 	# Auth check
 	public static function check($permissions)
@@ -104,10 +102,4 @@
 			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
@@ -272,7 +264,7 @@
 			} else {
 				$prof_url = http::getSelfURI();
-				$prof_url .= (strpos($prof_url,'?') === false) ? '?' : '&';
+				$prof_url .= (strpos($prof_url,'?') === false) ? '?' : '&amp;';
 				$prof_url .= 'XDEBUG_PROFILE';
-				$res .= '<p><a href="'.html::escapeURL($prof_url).'">Trigger profiler</a></p>';
+				$res .= '<p><a href="'.$prof_url.'">Trigger profiler</a></p>';
 			}
 			
@@ -351,9 +343,5 @@
 	public static function jsLoad($src)
 	{
-		$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";
-		}
+		return '<script type="text/javascript" src="'.html::escapeHTML($src).'"></script>'."\n";
 	}
 	
@@ -561,80 +549,278 @@
 	public static function jsToolBar()
 	{
+		$tb = new dcToolBar($GLOBALS['core']);
+		
+		// Add xhtml toolbar
+		$tb->addFormatter('xhtml');
+		$tb->addSettings('xhtml',array(
+			'mode' => 'textareas',
+			'relative_urls' => 'false',
+			'theme' => 'advanced',
+			'skin' => 'dotclear',
+			'theme_advanced_toolbar_location' => 'top',
+			'theme_advanced_toolbar_align' => 'left',
+			'theme_advanced_statusbar_location' => 'bottom',
+			'theme_advanced_resizing' => 'true',
+			'theme_advanced_resize_horizontal' => 'false',
+			'theme_advanced_blockformats' => 'p,pre,h3,h4,h5,h6',
+			'paste_auto_cleanup_on_paste' => 'true',
+			'forced_root_block' => '',
+			'formats' => '{underline: {inline: "ins"},strikethrough: {inline: "del"},inlinecode: {inline: "code"},quote: {inline: "q"}}'
+		));
+		$tb->addPlugins('xhtml',array(
+			'fullscreen' => true,
+			'paste' => true,
+			'searchreplace' => true,
+			'dcControls' => true
+		));
+		$tb->addButtons('xhtml',array(
+			1 => array(
+				'justifyleft',
+				'justifycenter',
+				'justifyright',
+				'separator',
+				'bold',
+				'italic',
+				'underline',
+				'strikethrough',
+				'inlinecode',
+				'quote',
+				'sub',
+				'sup',
+				'separator',
+				'blockquote',
+				'bullist',
+				'numlist',
+				'outdent',
+				'indent',
+				'separator',
+				'undo',
+				'redo',
+				'separator',
+				'fullscreen',
+				'separator',
+				'code'
+			),
+			2 => array(
+				'formatselect',
+				'removeformat',
+				'cleanup',
+				'separator',
+				'pastetext',
+				'pasteword',
+				'separator',
+				'search',
+				'replace'
+			),
+			3 => array(
+				'link',
+				'unlink',
+				'anchor',
+				'separator',
+				'media',
+				'webmedia',
+				'separator',
+				'hr',
+				'charmap',
+				'visualchars'
+			)
+		));
+		
+		// Add wiki toolbar
+		$tb->addFormatter('wiki');
+		$tb->addSettings('wiki',array(
+			'mode' => 'none',
+			'relative_urls' => 'false',
+			'theme' => 'advanced',
+			'skin' => 'dotclear',
+			'theme_advanced_toolbar_location' => 'top',
+			'theme_advanced_toolbar_align' => 'left',
+			'theme_advanced_statusbar_location' => 'bottom',
+			'theme_advanced_resizing' => 'true',
+			'theme_advanced_resize_horizontal' => 'false',
+			'theme_advanced_path'  => 'false',
+			'theme_advanced_blockformats' => 'p,pre,h3,h4,h5,h6',
+			'entity_encoding' => 'raw',
+			'remove_linebreaks' => 'false',
+			'inline_styles' => 'false',
+			'convert_fonts_to_spans' => 'false',
+			'paste_auto_cleanup_on_paste' => 'true',
+			'force_br_newlines' => 'true',
+			'force_p_newlines' => 'false',
+			'forced_root_block' => '',
+			'formats' => '{underline: {inline: "ins"},strikethrough: {inline: "del"},inlinecode: {inline: "code"},quote: {inline: "q"}}'
+		));
+		$tb->addPlugins('wiki',array(
+			'fullscreen' => true,
+			'paste' => true,
+			'searchreplace' => true,
+			'dcControls' => true
+		));
+		$tb->addButtons('wiki',array(
+			1 => array(
+				'formatselect',
+				'bold',
+				'italic',
+				'underline',
+				'strikethrough',
+				'quote',
+				'inlinecode',
+				'separator',
+				'blockquote',
+				'bullist',
+				'numlist',
+				'separator',
+				'link',
+				'unlink',
+				'separator',
+				'search',
+				'replace',
+				'separator',
+				'undo',
+				'redo',
+				'separator',
+				'fullscreen',
+				'separator',
+				'code'
+			)
+		));
+		
+		$tb->addI18n('common',array(
+			'edit_confirm' => __('Do you want to use the WYSIWYG mode for this textarea?'),
+			'apply' => __('Apply'),
+			'insert' => __('Insert'),
+			'update' => __('Update'),
+			'cancel' => __('Cancel'),
+			'close' => __('Close'),
+			'browse' => __('Browse'),
+			'class_name' => __('Class'),
+			'not_set' => __('-- Not set --'),
+			'clipboard_msg' => __('Copy/Cut/Paste is not available in Mozilla and Firefox. Do you want more information about this issue?'),
+			'clipboard_no_support' => __('Currently not supported by your browser, use keyboard shortcuts instead.'),
+			'popup_blocked' => __('Sorry, but we have noticed that your popup-blocker has disabled a window that provides application functionality. You will need to disable popup blocking on this site in order to fully utilize this tool.'),
+			'invalid_data' => __('{#field} is invalid'),
+			'invalid_data_number' => __('{#field} must be a number'),
+			'invalid_data_min' => __('{#field} must be a number greater than {#min}'),
+			'invalid_data_size' => __('{#field} must be a number or percentage'),
+			'more_colors' => __('More colors')
+		));
+		$tb->addI18n('advanced',array(
+			'style_select' => __('Styles'),
+			'font_size' => __('Font size'),
+			'fontdefault' => __('Font family'),
+			'block' => __('Format'),
+			'paragraph' => __('Paragraph'),
+			'div' => __('Div'),
+			'address' => __('Address'),
+			'pre' => __('Preformatted'),
+			'h1' => __('Heading blog'),
+			'h2' => __('Heading entry'),
+			'h3' => __('Heading 1'),
+			'h4' => __('Heading 2'),
+			'h5' => __('Heading 3'),
+			'h6' => __('Heading 4'),
+			'blockquote' => __('Blockquote'),
+			'code' => __('Code'),
+			'samp' => __('Code sample'),
+			'dt' => __('Definition term '),
+			'dd' => __('Definition description'),
+			'bold_desc' => __('Bold (Ctrl+B)'),
+			'italic_desc' => __('Italic (Ctrl+I)'),
+			'underline_desc' => __('Underline (Ctrl+U)'),
+			'striketrough_desc' => __('Strikethrough'),
+			'justifyleft_desc' => __('Align left'),
+			'justifycenter_desc' => __('Align center'),
+			'justifyright_desc' => __('Align right'),
+			'justifyfull_desc' => __('Align full'),
+			'bullist_desc' => __('Unordered list'),
+			'numlist_desc' => __('Ordered list'),
+			'outdent_desc' => __('Outdent'),
+			'indent_desc' => __('Indent'),
+			'undo_desc' => __('Undo (Ctrl+Z)'),
+			'redo_desc' => __('Redo (Ctrl+Y)'),
+			'link_desc' => __('Insert/edit link'),
+			'unlink_desc' => __('Unlink'),
+			'image_desc' => __('Insert/edit image'),
+			'cleanup_desc' => __('Cleanup messy code'),
+			'code_desc' => __('Edit HTML Source'),
+			'sub_desc' => __('Subscript'),
+			'sup_desc' => __('Superscript'),
+			'hr_desc' => __('Insert horizontal ruler'),
+			'removeformat_desc' => __('Remove formatting'),
+			'custom1_desc' => __('Your custom description here'),
+			'forecolor_desc' => __('Select text color'),
+			'backcolor_desc' => __('Select background color'),
+			'charmap_desc' => __('Insert custom character'),
+			'visualaid_desc' => __('Toggle guidelines/invisible elements'),
+			'anchor_desc' => __('Insert/edit anchor'),
+			'cut_desc' => __('Cut'),
+			'copy_desc' => __('Copy'),
+			'paste_desc' => __('Paste'),
+			'image_props_desc' => __('Image properties'),
+			'newdocument_desc' => __('New document'),
+			'help_desc' => __('Help'),
+			'blockquote_desc' => __('Blockquote'),
+			'clipboard_msg' => __('Copy/Cut/Paste is not available in Mozilla and Firefox.\r\nDo you want more information about this issue?'),
+			'path' => __('Path'),
+			'newdocument' => __('Are you sure you want clear all contents?'),
+			'toolbar_focus' => __('Jump to tool buttons - Alt+Q, Jump to editor - Alt-Z, Jump to element path - Alt-X'),
+			'more_colors' => __('More colors'),
+			'shortcuts_desc' => __('Accessibility Help'),
+			'help_shortcut' => __('. Press ALT F10 for toolbar. Press ALT 0 for help.'),
+			'rich_text_area' => __('Rich Text Area'),
+			'toolbar' => __('Toolbar')
+		));
+		$tb->addI18n('advanced_dlg',array(
+			'about_title' => __('About TinyMCE'),
+			'about_general' => __('About'),
+			'about_help' => __('Help'),
+			'about_license' => __('License'),
+			'about_plugins' => __('Plugins'),
+			'about_plugin' => __('Plugin'),
+			'about_author' => __('Author'),
+			'about_version' => __('Version'),
+			'about_loaded' => __('Loaded plugins'),
+			'anchor_title' => __('Insert/edit anchor'),
+			'anchor_name' => __('Anchor name'),
+			'anchor_invalid' => __('Please specify a valid anchor name.'),
+			'code_title' => __('HTML Source Editor'),
+			'code_wordwrap' => __('Word wrap'),
+			'charmap_title' => __('Select custom character'),
+			'accessibility_help' => __('Accessibility Help'),
+			'accessibility_usage_title' => __('General Usage')
+		));
+		$tb->addI18n('paste',array(
+			'paste_text_desc' => __('Paste as Plain Text'),
+			'paste_word_desc' => __('Paste from Word'),
+			'selectall_desc' => __('Select All'),
+			'plaintext_mode_sticky' => __('Paste is now in plain text mode. Click again to toggle back to regular paste mode. After you paste something you will be returned to regular paste mode.'),
+			'plaintext_mode' => __('Paste is now in plain text mode. Click again to toggle back to regular paste mode.')
+		));
+		$tb->addI18n('paste_dlg',array(
+			'text_title' => __('Use CTRL+V on your keyboard to paste the text into the window.'),
+			'text_linebreaks' => __('Keep linebreaks'),
+			'word_title' => __('Use CTRL+V on your keyboard to paste the text into the window.')
+		));
+		$tb->addI18n('fullscreen',array('desc' => __('Toggle fullscreen mode')));
+		$tb->addI18n('aria',array('rich_text_area' => __('Rich Text Area')));
+		$tb->addI18n('dcControls',array(
+			'inlinecode_desc' => __('Code'),
+			'quote_desc' => __('Quote'),
+			'link_desc' => __('Link'),
+			'media_desc' => __('Add media from media manager'),
+			'webmedia_desc' => __('Add media from web')
+		));
+		$tb->addI18n('dcControls_dlg',array(
+			'provider_not_supported' => __('Provider not supported.'),
+			'webmedia_no_information' => __('Impossible to get media information. Please, try again later.'),
+			'no_media_loaded' => __('No media loaded. Please, load one beore inserting.')
+		));
+		
 		$res =
-		'<link rel="stylesheet" type="text/css" href="style/jsToolBar/jsToolBar.css" />'.
-		'<script type="text/javascript" src="js/jsToolBar/jsToolBar.js"></script>';
-		
-		if (isset($GLOBALS['core']->auth) && $GLOBALS['core']->auth->getOption('enable_wysiwyg')) {
-			$res .= '<script type="text/javascript" src="js/jsToolBar/jsToolBar.wysiwyg.js"></script>';
-		}
-		
-		$res .=
-		'<script type="text/javascript" src="js/jsToolBar/jsToolBar.dotclear.js"></script>'.
+		'<script type="text/javascript" src="js/tiny_mce/tiny_mce.js"></script>'.
+		'<script type="text/javascript" src="js/dcToolBar.js"></script>'.
 		'<script type="text/javascript">'."\n".
 		"//<![CDATA[\n".
-		"jsToolBar.prototype.dialog_url = 'popup.php'; ".
-		"jsToolBar.prototype.iframe_css = '".
-			'body{'.
-				'font: 12px "DejaVu Sans","Lucida Grande","Lucida Sans Unicode",Arial,sans-serif;'.
-				'color : #000;'.
-				'background: #f9f9f9;'.
-				'margin: 0;'.
-				'padding : 2px;'.
-				'border: none;'.
-				(l10n::getTextDirection($GLOBALS['_lang']) == 'rtl' ? 'direction:rtl;' : '').
-			'}'.
-			'pre, code, kbd, samp {'.
-				'font-family:"Courier New",Courier,monospace;'.
-				'font-size : 1.1em;'.
-			'}'.
-			'code {'.
-				'color : #666;'.
-				'font-weight : bold;'.
-			'}'.
-			'body > p:first-child {'.
-				'margin-top: 0;'.
-			'}'.
-		"'; ".
-		"jsToolBar.prototype.base_url = '".html::escapeJS($GLOBALS['core']->blog->host)."'; ".
-		"jsToolBar.prototype.switcher_visual_title = '".html::escapeJS(__('visual'))."'; ".
-		"jsToolBar.prototype.switcher_source_title = '".html::escapeJS(__('source'))."'; ".
-		"jsToolBar.prototype.legend_msg = '".
-		html::escapeJS(__('You can use the following shortcuts to format your text.'))."'; ".
-		"jsToolBar.prototype.elements.blocks.options.none = '".html::escapeJS(__('-- none --'))."'; ".
-		"jsToolBar.prototype.elements.blocks.options.nonebis = '".html::escapeJS(__('-- block format --'))."'; ".
-		"jsToolBar.prototype.elements.blocks.options.p = '".html::escapeJS(__('Paragraph'))."'; ".
-		"jsToolBar.prototype.elements.blocks.options.h1 = '".html::escapeJS(__('Level 1 header'))."'; ".
-		"jsToolBar.prototype.elements.blocks.options.h2 = '".html::escapeJS(__('Level 2 header'))."'; ".
-		"jsToolBar.prototype.elements.blocks.options.h3 = '".html::escapeJS(__('Level 3 header'))."'; ".
-		"jsToolBar.prototype.elements.blocks.options.h4 = '".html::escapeJS(__('Level 4 header'))."'; ".
-		"jsToolBar.prototype.elements.blocks.options.h5 = '".html::escapeJS(__('Level 5 header'))."'; ".
-		"jsToolBar.prototype.elements.blocks.options.h6 = '".html::escapeJS(__('Level 6 header'))."'; ".
-		"jsToolBar.prototype.elements.strong.title = '".html::escapeJS(__('Strong emphasis'))."'; ".
-		"jsToolBar.prototype.elements.em.title = '".html::escapeJS(__('Emphasis'))."'; ".
-		"jsToolBar.prototype.elements.ins.title = '".html::escapeJS(__('Inserted'))."'; ".
-		"jsToolBar.prototype.elements.del.title = '".html::escapeJS(__('Deleted'))."'; ".
-		"jsToolBar.prototype.elements.quote.title = '".html::escapeJS(__('Inline quote'))."'; ".
-		"jsToolBar.prototype.elements.code.title = '".html::escapeJS(__('Code'))."'; ".
-		"jsToolBar.prototype.elements.br.title = '".html::escapeJS(__('Line break'))."'; ".
-		"jsToolBar.prototype.elements.blockquote.title = '".html::escapeJS(__('Blockquote'))."'; ".
-		"jsToolBar.prototype.elements.pre.title = '".html::escapeJS(__('Preformated text'))."'; ".
-		"jsToolBar.prototype.elements.ul.title = '".html::escapeJS(__('Unordered list'))."'; ".
-		"jsToolBar.prototype.elements.ol.title = '".html::escapeJS(__('Ordered list'))."'; ".
-		
-		"jsToolBar.prototype.elements.link.title = '".html::escapeJS(__('Link'))."'; ".
-		"jsToolBar.prototype.elements.link.href_prompt = '".html::escapeJS(__('URL?'))."'; ".
-		"jsToolBar.prototype.elements.link.hreflang_prompt = '".html::escapeJS(__('Language?'))."'; ".
-		
-		"jsToolBar.prototype.elements.img.title = '".html::escapeJS(__('External image'))."'; ".
-		"jsToolBar.prototype.elements.img.src_prompt = '".html::escapeJS(__('URL?'))."'; ".
-		
-		"jsToolBar.prototype.elements.img_select.title = '".html::escapeJS(__('Media chooser'))."'; ".
-		"jsToolBar.prototype.elements.post_link.title = '".html::escapeJS(__('Link to an entry'))."'; ";
-		
-		if (!$GLOBALS['core']->auth->check('media,media_admin',$GLOBALS['core']->blog->id)) {
-			$res .= "jsToolBar.prototype.elements.img_select.disabled = true;\n";
-		}
-		
-		$res .=
+		$tb->getJS().
 		"\n//]]>\n".
 		"</script>\n";
@@ -690,17 +876,21 @@
 	{
 		return
-		'<script type="text/javascript" src="js/tool-man/core.js"></script>'.
-		'<script type="text/javascript" src="js/tool-man/events.js"></script>'.
-		'<script type="text/javascript" src="js/tool-man/css.js"></script>'.
-		'<script type="text/javascript" src="js/tool-man/coordinates.js"></script>'.
-		'<script type="text/javascript" src="js/tool-man/drag.js"></script>'.
-		'<script type="text/javascript" src="js/tool-man/dragsort.js"></script>'.
-		'<script type="text/javascript" src="js/dragsort-tablerows.js"></script>';
+		self::jsLoad('js/tool-man/core.js').
+		self::jsLoad('js/tool-man/events.js').
+		self::jsLoad('js/tool-man/css.js').
+		self::jsLoad('js/tool-man/coordinates.js').
+		self::jsLoad('js/tool-man/drag.js').
+		self::jsLoad('js/tool-man/dragsort.js').
+		self::jsLoad('js/dragsort-tablerows.js');
 	}
 	
 	public static function jsMetaEditor()
 	{
-		return
-		'<script type="text/javascript" src="js/meta-editor.js"></script>';
+		return self::jsLoad('js/meta-editor.js');
+	}
+	
+	public static function jsOEmbed()
+	{
+		return self::jsLoad('js/jquery/jquery.oembed.js');
 	}
 }
Index: inc/admin/lib.pager.php
===================================================================
--- inc/admin/lib.pager.php	(revision 270)
+++ inc/admin/lib.pager.php	(revision 326)
@@ -4,5 +4,5 @@
 # This file is part of Dotclear 2.
 #
-# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
+# Copyright (c) 2003-2010 Olivier Meunier & Association Dotclear
 # Licensed under the GPL version 2.0 license.
 # See LICENSE file or
@@ -12,4 +12,71 @@
 if (!defined('DC_RC_PATH')) { return; }
 
+class adminGenericColumn
+{
+	protected $core;
+	protected $rs;
+	protected $id;
+	protected $title;
+	protected $callback;
+	protected $html;
+	protected $visibility;
+	
+	public function __construct($id,$title,$callback,$html = null)
+	{
+		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;
+		}
+		
+		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();
+			if (!$p || $p->name != 'adminGenericList') {
+				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->visibility = true;
+	}
+	
+	public function getInfo($k)
+	{
+		return property_exists(get_class($this),$k) ? $this->{$k} : null;
+	}
+	
+	public function setVisibility($visibility)
+	{
+		if (is_bool($visibility)) {
+			$this->visibility = $visibility;
+		}
+	}
+	
+	public function isVisible()
+	{
+		return $this->visibility;
+	}
+}
+
 class adminGenericList
 {
@@ -17,4 +84,5 @@
 	protected $rs;
 	protected $rs_count;
+	protected $columns;
 	
 	public function __construct($core,$rs,$rs_count)
@@ -23,11 +91,104 @@
 		$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 = __('&#171;prev.');
 		$this->html_next = __('next&#187;');
-	}
-}
-
-class adminPostList extends adminGenericList
-{
+		
+		# Post columns
+		$this->addColumn('adminPostList','title',__('Title'),array('adminPostList','getTitle'));
+		$this->addColumn('adminPostList','date',__('Date'),array('adminPostList','getDate'));
+		$this->addColumn('adminPostList','category',__('Category'),array('adminPostList','getCategory'));
+		$this->addColumn('adminPostList','author',__('Author'),array('adminPostList','getAuthor'));
+		$this->addColumn('adminPostList','comment',__('Comments'),array('adminPostList','getComments'));
+		$this->addColumn('adminPostList','trackback',__('Trackbacks'),array('adminPostList','getTrackbacks'));
+		$this->addColumn('adminPostList','status',__('Status'),array('adminPostList','getStatus'));
+		
+		# Post (mini list) columns
+		$this->addColumn('adminPostMiniList','title',__('Title'),array('adminPostList','getTitle'));
+		$this->addColumn('adminPostMiniList','date',__('Date'),array('adminPostList','getDate'));
+		$this->addColumn('adminPostMiniList','author',__('Author'),array('adminPostList','getAuthor'));
+		$this->addColumn('adminPostMiniList','status',__('Status'),array('adminPostList','getStatus'));
+		
+		# Comment columns
+		$this->addColumn('adminCommentList','title',__('Title'),array('adminCommentList','getTitle'));
+		$this->addColumn('adminCommentList','date',__('Date'),array('adminCommentList','getDate'));
+		$this->addColumn('adminCommentList','author',__('Author'),array('adminCommentList','getAuthor'));
+		$this->addColumn('adminCommentList','type',__('Type'),array('adminCommentList','getType'));
+		$this->addColumn('adminCommentList','status',__('Status'),array('adminCommentList','getStatus'));
+		$this->addColumn('adminCommentList','edit','',array('adminCommentList','getEdit'));
+		
+		# User columns
+		$this->addColumn('adminUserList','username',__('Username'),array('adminUserList','getUserName'));
+		$this->addColumn('adminUserList','firstname',__('First name'),array('adminUserList','getFirstName'));
+		$this->addColumn('adminUserList','lastname',__('Last name'),array('adminUserList','getLastName'));
+		$this->addColumn('adminUserList','displayname',__('Display name'),array('adminUserList','getDisplayName'));
+		$this->addColumn('adminUserList','entries',__('Entries'),array('adminUserList','getEntries'));
+		
+		$core->callBehavior('adminGenericListConstruct',$this);
+		
+		$this->setColumnsVisibility();
+	}
+	
+	public function addColumn($context,$id,$title,$callback,$html = null)
+	{
+		try {
+			if (!array_key_exists($context,$this->columns)) {
+				$this->columns[$context] = array();
+			}
+			
+			$c = new adminGenericColumn($id,$title,$callback,$html);
+			$this->columns[$context][$c->getInfo('id')] = $c;
+		}
+		catch (Exception $e) {
+			if (DC_DEBUG) {
+				$this->core->error->add($e->getMessage());
+			}
+		}
+	}
+	
+	public 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[$this->context] 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;
+			}
+			$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');
+		}
+	}
+	
+	public function getColumnsForm()
+	{
+		$block = 
+		'<h3>'.__('Displayed information').'</h3>'.
+		'<ul>%s</ul>';
+		
+		$list = array();
+		
+		foreach ($this->columns[$this->context] 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()));
+			
+			array_push($list,$col_html);
+		}
+		
+		return !empty($list) ? sprintf($block,implode('',$list)) : '';
+	}
+	
 	public function display($page,$nb_per_page,$enclose_block='')
 	{
@@ -43,14 +204,13 @@
 			$pager->var_page = 'page';
 			
-			$html_block =
-			'<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>';
+			$html_block = '<table class="maximal clear"><tr>';
+			
+			foreach ($this->columns[$this->context] as $k => $v) {
+				if ($v->isVisible()) {
+					$html_block .= sprintf('<th%s>%s</th>',$v->getInfo('html'),$v->getInfo('title'));
+				}
+			}
+			
+			$html_block .= '</tr>%s</table>';
 			
 			if ($enclose_block) {
@@ -66,5 +226,5 @@
 			while ($this->rs->fetch())
 			{
-				echo $this->postLine();
+				echo $this->displayLine();
 			}
 			
@@ -75,5 +235,49 @@
 	}
 	
-	private function postLine()
+	private function displayLine()
+	{
+		$res = '';
+		
+		foreach ($this->columns[$this->context] as $k => $v) {
+			if ($v->isVisible()) {
+				$c = $v->getInfo('callback');
+				$func = $c[1];
+				$res .= $this->{$c[1]}();
+			}
+		}
+		
+		return sprintf($this->getDefaultLine(),$res);
+	}
+	
+	protected function getDefaultLine()
+	{
+		return '<tr class="line">%s</tr>';
+	}
+}
+
+class adminPostList extends adminGenericList
+{
+	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
+		'<td 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></td>';
+	}
+	
+	protected function getDate()
+	{
+		return '<td class="nowrap">'.dt::dt2str(__('%Y-%m-%d %H:%M'),$this->rs->post_dt).'</td>';
+	}
+	
+	protected function getCategory()
 	{
 		if ($this->core->auth->check('categories',$this->core->blog->id)) {
@@ -90,4 +294,24 @@
 		}
 		
+		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) {
@@ -123,116 +347,18 @@
 		}
 		
-		$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;
-	}
-}
-
-class adminPostMiniList extends adminGenericList
-{
-	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>';
-		}
-	}
-	
-	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).'" '.
+		return '<td class="nowrap status">'.$img_status.' '.$selected.' '.$protected.' '.$attach.'</td>';
+	}
+}
+
+class adminPostMiniList extends adminPostList
+{
+	protected function getTitle()
+	{
+		return
+		'<td 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).'" '.
 		'title="'.html::escapeHTML($this->rs->getURL()).'">'.
-		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;
+		html::escapeHTML($this->rs->post_title).'</a></td>';
 	}
 }
@@ -240,49 +366,29 @@
 class adminCommentList extends adminGenericList
 {
-	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>';
-		}
-	}
-	
-	private function commentLine()
+	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
+		'<td 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).')' : '').'</td>';
+	}
+	
+	protected function getDate()
+	{
+		return '<td class="nowrap">'.dt::dt2str(__('%Y-%m-%d %H:%M'),$this->rs->comment_dt).'</td>';
+	}
+	
+	protected function getAuthor()
 	{
 		global $author, $status, $sortby, $order, $nb_per_page;
@@ -295,12 +401,19 @@
 		'&amp;author='.rawurlencode($this->rs->comment_author);
 		
-		$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);
-		
+		$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()
+	{
 		$img = '<img alt="%1$s" title="%1$s" src="images/%2$s" />';
 		switch ($this->rs->comment_status) {
@@ -319,28 +432,14 @@
 		}
 		
-		$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>'.
+		return '<td class="nowrap status">'.$img_status.'</td>';
+	}
+	
+	protected function getEdit()
+	{
+		$comment_url = 'comment.php?id='.$this->rs->comment_id;
+		
+		return
 		'<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;
 	}
 }
@@ -348,48 +447,5 @@
 class adminUserList extends adminGenericList
 {
-	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>';
-		}
-	}
-	
-	private function userLine()
+	protected function getUserName()
 	{
 		$img = '<img alt="%1$s" title="%1$s" src="images/%2$s" />';
@@ -404,17 +460,34 @@
 			$img_status = sprintf($img,__('superadmin'),'superadmin.png');
 		}
-		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>'.
+		
+		return
+		'<td 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.'</td>';
+	}
+	
+	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
 		'<td class="nowrap"><a href="posts.php?user_id='.$this->rs->user_id.'">'.
-		$this->rs->nb_post.'</a></td>'.
-		'</tr>';
-	}
-}
+		$this->rs->nb_post.'</a></td>';
+	}
+}
+
 ?>
Index: inc/admin/prepend.php
===================================================================
--- inc/admin/prepend.php	(revision 324)
+++ inc/admin/prepend.php	(revision 185)
@@ -4,5 +4,5 @@
 # This file is part of Dotclear 2.
 #
-# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
+# Copyright (c) 2003-2010 Olivier Meunier & Association Dotclear
 # Licensed under the GPL version 2.0 license.
 # See LICENSE file or
@@ -185,43 +185,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));
@@ -311,5 +311,5 @@
 			$count++;
 			$fav = unserialize($v['value']);
-			$_menu['Favorites']->addItem(__($fav['title']),$fav['url'],$fav['small-icon'],
+			$_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']);
@@ -321,5 +321,5 @@
 			$count++;
 			$fav = unserialize($v['value']);
-			$_menu['Favorites']->addItem(__($fav['title']),$fav['url'],$fav['small-icon'],
+			$_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']);
Index: inc/config.php.in
===================================================================
--- inc/config.php.in	(revision 362)
+++ inc/config.php.in	(revision 0)
@@ -4,5 +4,5 @@
 # This file is part of Dotclear 2.
 #
-# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
+# Copyright (c) 2003-2010 Olivier Meunier & Association Dotclear
 # Licensed under the GPL version 2.0 license.
 # See LICENSE file or
@@ -40,7 +40,4 @@
 define('DC_ADMIN_URL','');
 
-// Admin mail from address. For password recovery and such.
-define('DC_ADMIN_MAILFROM','');
-
 // Cookie's name
 define('DC_SESSION_NAME','dcxd');
Index: inc/core/class.dc.auth.php
===================================================================
--- inc/core/class.dc.auth.php	(revision 333)
+++ inc/core/class.dc.auth.php	(revision 3)
@@ -13,52 +13,37 @@
 
 /**
-* @ingroup DC_CORE
-* @nosubgrouping
-* @brief Authentication and user credentials management
-* 
-* dcAuth is a class used to handle everything related to user authentication
-* and credentials. Object is provided by dcCore $auth property.
+@ingroup DC_CORE
+@nosubgrouping
+@brief Authentication and user credentials management
+
+dcAuth is a class used to handle everything related to user authentication
+and credentials. Object is provided by dcCore $auth property.
 */
 class dcAuth
 {
-	/** @var dcCore dcCore instance */
-	protected $core;
-	/** @var connection Database connection object */
-	protected $con;
-	
-	/** @var string User table name */
-	protected $user_table;
-	/** @var string Perm table name */
-	protected $perm_table;
-	
-	/** @var string Current user ID */
-	protected $user_id;
-	/** @var array Array with user information */
-	protected $user_info = array();
-	/** @var array Array with user options */
-	protected $user_options = array();
-	/** @var boolean User must change his password after login */
-	protected $user_change_pwd;
-	/** @var boolean User is super admin */
-	protected $user_admin;
-	/** @var array Permissions for each blog */
-	protected $permissions = array();
-	/** @var boolean User can change its password */
-	protected $allow_pass_change = true;
-	/** @var array List of blogs on which the user has permissions */
-	protected $blogs = array();
-	/** @var integer Count of user blogs */
-	public $blog_count = null;
-	
-	/** @var array Permission types */
-	protected $perm_types;
-	
-	/** @var dcPrefs dcPrefs object */
-	public $user_prefs;
-	
-	/**
-	* Class constructor. Takes dcCore object as single argument.
-	* 
-	* @param dcCore	$core		dcCore object
+	protected $core;		///< <b>dcCore</b> dcCore instance
+	protected $con;		///< <b>connection</b> Database connection object
+	
+	protected $user_table;	///< <b>string</b>	User table name
+	protected $perm_table;	///< <b>string</b>	Perm table name
+	
+	protected $user_id;					///< <b>string</b>		Current user ID
+	protected $user_info = array();		///< <b>array</b>		Array with user information
+	protected $user_options = array();		///< <b>array</b>		Array with user options
+	protected $user_change_pwd;			///< <b>boolean</b>		User must change his password after login
+	protected $user_admin;				///< <b>boolean</b>		User is super admin
+	protected $permissions = array();		///< <b>array</b>		Permissions for each blog
+	protected $allow_pass_change = true;	///< <b>boolean</b>		User can change its password
+	protected $blogs = array();			///< <b>array</b>		List of blogs on which the user has permissions
+	public $blog_count = null;				///< <b>integer</b>		Count of user blogs
+	
+	protected $perm_types;	///< <b>array</b> Permission types
+	
+	public $user_prefs;	///< <b>dcPrefs</b>	dcPrefs object
+	
+	/**
+	Class constructor. Takes dcCore object as single argument.
+	
+	@param	core		<b>dcCore</b>		dcCore object
 	*/
 	public function __construct($core)
@@ -85,15 +70,14 @@
 	//@{
 	/**
-	* Checks if user exists and can log in. <var>$pwd</var> argument is optionnal
-	* while you may need to check user without password. This method will create
-	* credentials and populate all needed object properties.
-	* 
-	* @param string	$user_id		User ID
-	* @param string	$pwd			User password
-	* @param string	$user_key		User key check
-	* @param boolean	$check_blog	checks if user is associated to a blog or not.
-	* @return boolean
-	*/
-	public function checkUser($user_id, $pwd=null, $user_key=null, $check_blog=true)
+	Checks if user exists and can log in. <var>$pwd</var> argument is optionnal
+	while you may need to check user without password. This method will create
+	credentials and populate all needed object properties.
+	
+	@param	user_id	<b>string</b>		User ID
+	@param	pwd		<b>string</b>		User password
+	@param	user_key	<b>string</b>		User key check
+	@return	<b>boolean</b>
+	*/
+	public function checkUser($user_id, $pwd=null, $user_key=null)
 	{
 		# Check user and password
@@ -157,5 +141,5 @@
 		
 		# Get permissions on blogs
-		if ($check_blog && ($this->findUserBlog() === false)) {
+		if ($this->findUserBlog() === false) {
 			return false;
 		}
@@ -164,8 +148,8 @@
 	
 	/**
-	* This method only check current user password.
-	* 
-	* @param string	$pwd			User password
-	* @return boolean
+	This method only check current user password.
+	
+	@param	pwd		<b>string</b>		User password
+	@return	<b>boolean</b>
 	*/
 	public function checkPassword($pwd)
@@ -179,7 +163,7 @@
 	
 	/**
-	* This method checks if user session cookie exists
-	* 
-	* @return boolean
+	This method checks if user session cookie exists
+	
+	@return	<b>boolean</b>
 	*/
 	public function sessionExists()
@@ -189,7 +173,7 @@
 	
 	/**
-	* This method checks user session validity.
-	* 
-	* @return boolean
+	This method checks user session validity.
+	
+	@return	<b>boolean</b>
 	*/
 	public function checkSession($uid=null)
@@ -228,7 +212,7 @@
 	
 	/**
-	* Checks if user is super admin
-	* 
-	* @return boolean
+	Checks if user is super admin
+	
+	@return	<b>boolean</b>
 	*/
 	public function isSuperAdmin()
@@ -238,11 +222,11 @@
 	
 	/**
-	* Checks if user has permissions given in <var>$permissions</var> for blog
-	* <var>$blog_id</var>. <var>$permissions</var> is a coma separated list of
-	* permissions.
-	* 
-	* @param string	$permissions	Permissions list
-	* @param string	$blog_id		Blog ID
-	* @return boolean
+	Checks if user has permissions given in <var>$permissions</var> for blog
+	<var>$blog_id</var>. <var>$permissions</var> is a coma separated list of
+	permissions.
+	
+	@param	permissions	<b>string</b>		Permissions list
+	@param	blog_id		<b>string</b>		Blog ID
+	@return	<b>boolean</b>
 	*/
 	public function check($permissions,$blog_id)
@@ -273,7 +257,7 @@
 	
 	/**
-	* Returns true if user is allowed to change its password.
-	* 
-	* @return	boolean
+	Returns true if user is allowed to change its password.
+	
+	@return	<b>boolean</b>
 	*/
 	public function allowPassChange()
@@ -328,9 +312,8 @@
 	//@{
 	/**
-	* Calls $f function with super admin rights.
-	* Returns the function result.
-	* 
-	* @param callback	$f			Callback function
-	* @return mixed
+	Calls <var>$f</var> function with super admin rights.
+	
+	@param	f		<b>callback</b>	Callback function
+	@return	<b>mixed</b> Function result
 	*/
 	public function sudo($f)
@@ -363,12 +346,11 @@
 	//@{
 	/**
-	* Returns user permissions for a blog as an array which looks like:
-	* 
-	*  - [blog_id]
-	*    - [permission] => true
-	*    - ...
-	* 
-	* @param string	$blog_id		Blog ID
-	* @return array
+	Returns user permissions for a blog as an array which looks like:
+	
+	 - [blog_id]
+	   - [permission] => true
+	   - ...
+	
+	@return	<b>array</b>
 	*/
 	public function getPermissions($blog_id)
@@ -440,7 +422,7 @@
 	
 	/**
-	* Returns current user ID
-	* 
-	* @return string
+	Returns current user ID
+	
+	@return	<b>string</b>
 	*/
 	public function userID()
@@ -450,8 +432,8 @@
 	
 	/**
-	* Returns information about a user .
-	* 
-	* @param string	$n			Information name
-	* @return string
+	Returns information about a user .
+	
+	@param	n		<b>string</b>		Information name
+	@return	<b>string</b> Information value
 	*/
 	public function getInfo($n)
@@ -465,8 +447,8 @@
 	
 	/**
-	* Returns a specific user option
-	* 
-	* @param string	$n			Option name
-	* @return string
+	Returns a specific user option
+	
+	@param	n		<b>string</b>		Option name
+	@return	<b>string</b> Option value
 	*/
 	public function getOption($n)
@@ -479,7 +461,7 @@
 	
 	/**
-	* Returns all user options in an associative array.
-	* 
-	* @return array
+	Returns all user options in an associative array.
+	
+	@return	<b>array</b>
 	*/
 	public function getOptions()
@@ -492,8 +474,8 @@
 	//@{
 	/**
-	* Returns an array with permissions parsed from the string <var>$level</var>
-	* 
-	* @param string	$level		Permissions string
-	* @return array
+	Returns an array with permissions parsed from the string <var>$level</var>
+	
+	@param	level	<b>string</b>		Permissions string
+	@return	<b>array</b>
 	*/
 	public function parsePermissions($level)
@@ -510,7 +492,7 @@
 	
 	/**
-	* Returns <var>perm_types</var> property content.
-	* 
-	* @return array
+	Returns <var>perm_types</var> property content.
+	
+	@return	<b>array</b>
 	*/
 	public function getPermissionsTypes()
@@ -520,8 +502,8 @@
 	
 	/**
-	* Adds a new permission type.
-	* 
-	* @param string	$name		Permission name
-	* @param string	$title		Permission title
+	Adds a new permission type.
+	
+	@param	name		<b>string</b>		Permission name
+	@param	title	<b>string</b>		Permission title
 	*/
 	public function setPermissionType($name,$title)
@@ -534,10 +516,10 @@
 	//@{
 	/**
-	* Add a recover key to a specific user identified by its email and
-	* password.
-	* 
-	* @param string	$user_id		User ID
-	* @param string	$user_email	User Email
-	* @return string
+	Add a recover key to a specific user identified by its email and
+	password.
+	
+	@param	user_id		<b>string</b>		User ID
+	@param	user_email	<b>string</b>		User Email
+	@return	<b>string</b> Recover key
 	*/
 	public function setRecoverKey($user_id,$user_email)
@@ -565,12 +547,12 @@
 	
 	/**
-	* Creates a new user password using recovery key. Returns an array:
-	* 
-	* - user_email
-	* - user_id
-	* - new_pass
-	* 
-	* @param string	$recover_key	Recovery key
-	* @return array
+	Creates a new user password using recovery key. Returns an array:
+	
+	- user_email
+	- user_id
+	- new_pass
+	
+	@param	recover_key	<b>string</b>		Recovery key
+	@return	<b>array</b>
 	*/
 	public function recoverUserPassword($recover_key)
@@ -608,22 +590,22 @@
 	
 	/**
-	* Called after core->addUser
-	* @see dcCore::addUser
-	* @param cursor	$cur			User cursor
+	Called after core->addUser
+	@see		dcCore::addUser
+	@param	cur		<b>cursor</b>		User cursor
 	*/
 	public function afterAddUser($cur) {}
 	
 	/**
-	* Called after core->updUser
-	* @see dcCore::updUser
-	* @param string	$id			User ID
-	* @param cursor	$cur			User cursor
+	Called after core->updUser
+	@see		dcCore::updUser
+	@param	id		<b>string</b>		User ID
+	@param	cur		<b>cursor</b>		User cursor
 	*/
 	public function afterUpdUser($id,$cur) {}
 	
 	/**
-	* Called after core->delUser
-	* @see dcCore::delUser
-	* @param string	$id			User ID
+	Called after core->delUser
+	@see		dcCore::delUser
+	@param	id		<b>string</b>		User ID
 	*/
 	public function afterDelUser($id) {}
Index: inc/core/class.dc.blog.php
===================================================================
--- inc/core/class.dc.blog.php	(revision 407)
+++ inc/core/class.dc.blog.php	(revision 191)
@@ -4,5 +4,5 @@
 # This file is part of Dotclear 2.
 #
-# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
+# Copyright (c) 2003-2010 Olivier Meunier & Association Dotclear
 # Licensed under the GPL version 2.0 license.
 # See LICENSE file or
@@ -21,36 +21,21 @@
 class dcBlog
 {
-	/** @var dcCore dcCore instance */
-	protected $core;
-	/** @var connection Database connection object */
-	public $con;
-	/** @var string Database table prefix */
-	public $prefix;
-	
-	/** @var string Blog ID */
-	public $id;
-	/** @var string Blog unique ID */
-	public $uid;
-	/** @var string Blog name */
-	public $name;
-	/** @var string Blog description */
-	public $desc;
-	/** @var string Blog URL */
-	public $url;
-	/** @var string Blog host */
-	public $host;
-	/** @var string Blog creation date */
-	public $creadt;
-	/** @var string Blog last update date */
-	public $upddt;
-	/** @var string Blog status */
-	public $status;
-	
-	/** @var dcSettings dcSettings object */
-	public $settings;
-	/** @var string Blog theme path */
-	public $themes_path;
-	/** @var string Blog public path */
-	public $public_path;
+	protected $core;	///< <b>dcCore</b> dcCore instance
+	public $con;		///< <b>connection</b>	Database connection object
+	public $prefix;	///< <b>string</b>		Database table prefix
+	
+	public $id;		///< <b>string</b>		Blog ID
+	public $uid;		///< <b>string</b>		Blog unique ID
+	public $name;		///< <b>string</b>		Blog name
+	public $desc;		///< <b>string</b>		Blog description
+	public $url;		///< <b>string</b>		Blog URL
+	public $host;		///< <b>string</b>		Blog host
+	public $creadt;	///< <b>string</b>		Blog creation date
+	public $upddt;		///< <b>string</b>		Blog last update date
+	public $status;	///< <b>string</b>		Blog status
+	
+	public $settings;		///< <b>dcSettings</b>	dcSettings object
+	public $themes_path;	///< <b>string</b>		Blog theme path
+	public $public_path;	///< <b>string</b>		Blog public path
 	
 	private $post_status = array();
@@ -59,6 +44,5 @@
 	private $categories;
 	
-	/** @var boolean Disallow entries password protection */
-	public $without_password = true;
+	public $without_password = true;	///< <b>boolean</b> Disallow entries password protection
 	
 	/**
@@ -407,5 +391,5 @@
 		
 		if (!empty($params['post_type'])) {
-			$strReq .= 'AND P.post_type '.$this->con->in($params['post_type']);
+			$strReq .= "AND post_type = '".$this->con->escape($params['post_type'])."' ";
 		}
 		
@@ -727,6 +711,8 @@
 		if (isset($params['post_type']))
 		{
-			if (is_array($params['post_type']) || $params['post_type'] != '') {
+			if (is_array($params['post_type']) && !empty($params['post_type'])) {
 				$strReq .= 'AND post_type '.$this->con->in($params['post_type']);
+			} elseif ($params['post_type'] != '') {
+				$strReq .= "AND post_type = '".$this->con->escape($params['post_type'])."' ";
 			}
 		}
@@ -872,11 +858,11 @@
 		
 		if($dir > 0) {
-			$sign = '>';
-			$order = 'ASC';
-		}
-		else {
-			$sign = '<';
-			$order = 'DESC';
-		}
+               $sign = '>';
+               $order = 'ASC';
+          }
+          else {
+               $sign = '<';
+               $order = 'DESC';
+          }
 		
 		$params['post_type'] = $post->post_type;
@@ -1039,5 +1025,5 @@
 			$strReq .= "AND post_type = 'post' ";
 		}
-		
+				
 		if (!empty($params['year'])) {
 			$strReq .= 'AND '.$this->con->dateFormat('post_dt','%Y')." = '".sprintf('%04d',$params['year'])."' ";
@@ -1179,5 +1165,5 @@
 		$cur->post_upddt = date('Y-m-d H:i:s');
 		
-		#If user is only "usage", we need to check the post's owner
+		#�If user is only "usage", we need to check the post's owner
 		if (!$this->core->auth->check('contentadmin',$this->id))
 		{
@@ -1782,5 +1768,9 @@
 		if (!empty($params['post_type']))
 		{
-			$strReq .= 'AND post_type '.$this->con->in($params['post_type']);
+			if (is_array($params['post_type']) && !empty($params['post_type'])) {
+				$strReq .= 'AND post_type '.$this->con->in($params['post_type']);
+			} else {
+				$strReq .= "AND post_type = '".$this->con->escape($params['post_type'])."' ";
+			}
 		}
 		
Index: inc/core/class.dc.categories.php
===================================================================
--- inc/core/class.dc.categories.php	(revision 270)
+++ inc/core/class.dc.categories.php	(revision 0)
@@ -4,5 +4,5 @@
 # This file is part of Dotclear 2.
 #
-# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
+# Copyright (c) 2003-2010 Olivier Meunier & Association Dotclear
 # Licensed under the GPL version 2.0 license.
 # See LICENSE file or
Index: inc/core/class.dc.core.php
===================================================================
--- inc/core/class.dc.core.php	(revision 407)
+++ inc/core/class.dc.core.php	(revision 136)
@@ -4,5 +4,5 @@
 # This file is part of Dotclear 2.
 #
-# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
+# Copyright (c) 2003-2010 Olivier Meunier & Association Dotclear
 # Licensed under the GPL version 2.0 license.
 # See LICENSE file or
@@ -27,5 +27,5 @@
 {
 	public $con;		///< <b>connection</b>		Database connection object
-	public $prefix;		///< <b>string</b>			Database tables prefix
+	public $prefix;	///< <b>string</b>			Database tables prefix
 	public $blog;		///< <b>dcBlog</b>			dcBlog object
 	public $error;		///< <b>dcError</b>			dcError object
@@ -36,6 +36,5 @@
 	public $plugins;	///< <b>dcModules</b>		dcModules object
 	public $media;		///< <b>dcMedia</b>			dcMedia object
-	public $postmedia;	///< <b>dcPostMedia</b>		dcPostMedia object
-	public $rest;		///< <b>dcRestServer</b>	dcRestServer object
+	public $rest;		///< <b>dcRestServer</b>		dcRestServer object
 	public $log;		///< <b>dcLog</b>			dcLog object
 	
@@ -64,16 +63,4 @@
 		if ($this->con instanceof mysqlConnection) {
 			mysqlConnection::$weak_locks = true;
-		}
-		
-		# define searchpath for postgresql
-		if ($this->con instanceof pgsqlConnection)
-		{
-			$searchpath = explode ('.',$prefix,2);
-			if (count($searchpath) > 1)
-			{
-				$prefix = $searchpath[1];
-				$sql = 'SET search_path TO '.$searchpath[0].',public;';
-				$this->con->execute($sql);
-			}
 		}
 		
Index: inc/core/class.dc.error.php
===================================================================
--- inc/core/class.dc.error.php	(revision 334)
+++ inc/core/class.dc.error.php	(revision 0)
@@ -4,5 +4,5 @@
 # This file is part of Dotclear 2.
 #
-# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
+# Copyright (c) 2003-2010 Olivier Meunier & Association Dotclear
 # Licensed under the GPL version 2.0 license.
 # See LICENSE file or
@@ -13,24 +13,20 @@
 
 /**
-* @ingroup DC_CORE
-* @brief Error class
-* 
-* dcError is a very simple error class, with a stack. Call dcError::add to
-* add an error in stack. In administration area, errors are automatically
-* displayed.
+@ingroup DC_CORE
+@brief Error class
+
+dcError is a very simple error class, with a stack. Call dcError::add to
+add an error in stack. In administration area, errors are automatically
+displayed.
 */
 class dcError
 {
-	/** @var array Errors stack */
-	protected $errors = array();
-	/** @var boolean True if stack is not empty */
-	protected $flag = false;
-	/** @var string HTML errors list pattern */
-	protected $html_list = "<ul>\n%s</ul>\n";
-	/** @var string HTML error item pattern */
-	protected $html_item = "<li>%s</li>\n";
+	protected $errors = array();				///< <b>array</b>	Errors stack
+	protected $flag = false;					///< <b>boolean</b>	True if stack is not empty
+	protected $html_list = "<ul>\n%s</ul>\n";	///< <b>string</b>	HTML errors list pattern
+	protected $html_item = "<li>%s</li>\n";	///< <b>string</b>	HTML error item pattern
 	
 	/**
-	* Object constructor.
+	Object constructor.
 	*/
 	public function __construct()
@@ -41,7 +37,7 @@
 	
 	/**
-	* Object string representation. Returns errors stack.
-	* 
-	* @return string
+	Object string representation. Returns errors stack.
+	
+	@return	<b>string</b>
 	*/
 	public function __toString()
@@ -58,7 +54,7 @@
 	
 	/**
-	* Adds an error to stack.
-	* 
-	* @param string	$msg			Error message
+	Adds an error to stack.
+	
+	@param	msg		<b>string</b>		Error message
 	*/
 	public function add($msg)
@@ -69,7 +65,7 @@
 	
 	/**
-	* Returns the value of <var>flag</var> property. True if errors stack is not empty
-	* 
-	* @return boolean
+	Returns the value of <var>flag</var> property.
+	
+	@return	<b>boolean</b> True if errors stack is not empty
 	*/
 	public function flag()
@@ -79,5 +75,5 @@
 	
 	/**
-	* Resets errors stack.
+	Resets errors stack.
 	*/
 	public function reset()
@@ -88,7 +84,7 @@
 	
 	/**
-	* Returns <var>errors</var> property.
-	* 
-	* @return array
+	Returns <var>errors</var> property.
+	
+	@return	<b>array</b>
 	*/
 	public function getErrors()
@@ -98,8 +94,8 @@
 	
 	/**
-	* Sets <var>list</var> and <var>item</var> properties.
-	* 
-	* @param string	$list		HTML errors list pattern
-	* @param string	$item		HTML error item pattern
+	Sets <var>list</var> and <var>item</var> properties.
+	
+	@param	list		<b>string</b>		HTML errors list pattern
+	@param	item		<b>string</b>		HTML error item pattern
 	*/
 	public function setHTMLFormat($list,$item)
@@ -110,7 +106,7 @@
 	
 	/**
-	* Returns errors stack as HTML.
-	* 
-	* @return string
+	Returns errors stack as HTML.
+	
+	@return	<b>string</b>
 	*/
 	public function toHTML()
Index: inc/core/class.dc.log.php
===================================================================
--- inc/core/class.dc.log.php	(revision 270)
+++ inc/core/class.dc.log.php	(revision 126)
@@ -4,5 +4,5 @@
 # This file is part of Dotclear 2.
 #
-# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
+# Copyright (c) 2003-2010 Olivier Meunier & Association Dotclear
 # Licensed under the GPL version 2.0 license.
 # See LICENSE file or
Index: inc/core/class.dc.media.php
===================================================================
--- inc/core/class.dc.media.php	(revision 407)
+++ inc/core/class.dc.media.php	(revision 40)
@@ -4,5 +4,5 @@
 # This file is part of Dotclear 2.
 #
-# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
+# Copyright (c) 2003-2010 Olivier Meunier & Association Dotclear
 # Licensed under the GPL version 2.0 license.
 # See LICENSE file or
@@ -23,6 +23,6 @@
 	protected $con;		///< <b>connection</b> Database connection
 	protected $table;		///< <b>string</b> Media table name
+	protected $table_ref;	///< <b>string</b> Post-media relation table name
 	protected $type;		///< <b>string</b> Media type filter
-	protected $postmedia;
 	protected $file_sort = 'name-asc';
 	
@@ -57,5 +57,4 @@
 		$this->core =& $core;
 		$this->con =& $core->con;
-		$this->postmedia = new dcPostMedia($core);
 		
 		if ($this->core->blog == null) {
@@ -64,4 +63,5 @@
 		
 		$this->table = $this->core->prefix.'media';
+		$this->table_ref = $this->core->prefix.'post_media';
 		$root = $this->core->blog->public_path;
 		
@@ -494,12 +494,19 @@
 	public function getPostMedia($post_id,$media_id=null)
 	{
-		$params = array(
-			'post_id' => $post_id,
-			'media_path' => $this->path
-		);
+		$post_id = (integer) $post_id;
+		
+		$strReq =
+		'SELECT media_file, M.media_id, media_path, media_title, media_meta, media_dt, '.
+		'media_creadt, media_upddt, media_private, user_id '.
+		'FROM '.$this->table.' M '.
+		'INNER JOIN '.$this->table_ref.' PM ON (M.media_id = PM.media_id) '.
+		"WHERE media_path = '".$this->path."' ".
+		'AND post_id = '.$post_id.' ';
+		
 		if ($media_id) {
-			$params['media_id'] = (integer) $media_id;
-		}
-		$rs = $this->postmedia->getPostMedia($params);
+			$strReq .= 'AND M.media_id = '.(integer) $media_id.' ';
+		}
+		
+		$rs = $this->con->select($strReq);
 		
 		$res = array();
@@ -516,19 +523,45 @@
 	
 	/**
-	@deprecated since version 2.4
-	@see dcPostMedia::addPostMedia
+	Attaches a media to a post.
+	
+	@param	post_id	<b>integer</b>		Post ID
+	@param	media_id	<b>integer</b>		Optionnal media ID
 	*/
 	public function addPostMedia($post_id,$media_id)
 	{
-		$this->postmedia->addPostMedia($post_id,$media_id);
-	}
-	
-	/**
-	@deprecated since version 2.4
-	@see dcPostMedia::removePostMedia
+		$post_id = (integer) $post_id;
+		$media_id = (integer) $media_id;
+		
+		$f = $this->getPostMedia($post_id,$media_id);
+		
+		if (!empty($f)) {
+			return;
+		}
+		
+		$cur = $this->con->openCursor($this->table_ref);
+		$cur->post_id = $post_id;
+		$cur->media_id = $media_id;
+		
+		$cur->insert();
+		$this->core->blog->triggerBlog();
+	}
+	
+	/**
+	Detaches a media from a post.
+	
+	@param	post_id	<b>integer</b>		Post ID
+	@param	media_id	<b>integer</b>		Optionnal media ID
 	*/
 	public function removePostMedia($post_id,$media_id)
 	{
-		$this->postmedia->removePostMedia($post_id,$media_id,"attachment");
+		$post_id = (integer) $post_id;
+		$media_id = (integer) $media_id;
+		
+		$strReq = 'DELETE FROM '.$this->table_ref.' '.
+				'WHERE post_id = '.$post_id.' '.
+				'AND media_id = '.$media_id.' ';
+		
+		$this->con->execute($strReq);
+		$this->core->blog->triggerBlog();
 	}
 	
Index: inc/core/class.dc.meta.php
===================================================================
--- inc/core/class.dc.meta.php	(revision 270)
+++ inc/core/class.dc.meta.php	(revision 0)
@@ -4,5 +4,5 @@
 # This file is part of Dotclear 2.
 #
-# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
+# Copyright (c) 2003-2010 Olivier Meunier & Association Dotclear
 # Licensed under the GPL version 2.0 license.
 # See LICENSE file or
Index: inc/core/class.dc.modules.php
===================================================================
--- inc/core/class.dc.modules.php	(revision 270)
+++ inc/core/class.dc.modules.php	(revision 43)
@@ -4,5 +4,5 @@
 # This file is part of Dotclear 2.
 #
-# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
+# Copyright (c) 2003-2010 Olivier Meunier & Association Dotclear
 # Licensed under the GPL version 2.0 license.
 # See LICENSE file or
Index: inc/core/class.dc.namespace.php
===================================================================
--- inc/core/class.dc.namespace.php	(revision 270)
+++ inc/core/class.dc.namespace.php	(revision 0)
@@ -4,5 +4,5 @@
 # This file is part of Dotclear 2.
 #
-# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
+# Copyright (c) 2003-2010 Olivier Meunier & Association Dotclear
 # Licensed under the GPL version 2.0 license.
 # See LICENSE file or
Index: inc/core/class.dc.postmedia.php
===================================================================
--- inc/core/class.dc.postmedia.php	(revision 407)
+++ 	(revision )
@@ -1,172 +1,0 @@
-<?php
-# -- BEGIN LICENSE BLOCK ---------------------------------------
-#
-# This file is part of Dotclear 2.
-#
-# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
-# Licensed under the GPL version 2.0 license.
-# See LICENSE file or
-# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
-#
-# -- END LICENSE BLOCK -----------------------------------------
-if (!defined('DC_RC_PATH')) { return; }
-
-class dcPostMedia
-{
-	protected $core;		///< <b>dcCore</b> dcCore instance
-	protected $con;		///< <b>connection</b> Database connection
-	protected $table;		///< <b>string</b> Post-Media table name
-	
-	/**
-	Object constructor.
-	
-	@param	core		<b>dcCore</b>		dcCore instance
-	@param	type		<b>string</b>		Media type filter
-	*/
-	public function __construct($core,$type='')
-	{
-		$this->core =& $core;
-		$this->con =& $core->con;
-		$this->table = $this->core->prefix.'post_media';
-	}
-	
-	/**
-	Returns media items attached to a blog post. Result is an array containing
-	fileItems objects.
-	
-	@param	post_id	<b>integer</b>		Post ID
-	@param	media_id	<b>integer</b>		Optionnal media ID
-	@return	<b>array</b> Array of fileItems
-	*/
-	public function getPostMedia($params=array())
-	{
-		$strReq =
-		'SELECT M.media_file, M.media_id, M.media_path, M.media_title, M.media_meta, M.media_dt, '.
-		'M.media_creadt, M.media_upddt, M.media_private, M.user_id, PM.post_id ';
-		
-		if (!empty($params['columns']) && is_array($params['columns'])) {
-			$strReq .= implode(', ',$params['columns']).', ';
-		}
-		
-		$strReq .=
-		'FROM '.$this->core->prefix.'media M '.
-		'INNER JOIN '.$this->table.' PM ON (M.media_id = PM.media_id) ';
-		
-		if (!empty($params['from'])) {
-			$strReq .= $params['from'].' ';
-		}
-		
-		$where='';
-		if (isset($params['post_id'])) {
-			$where[]="PM.post_id ".$this->con->in($params['post_id']);
-		}
-		if (isset($params['media_id'])) {
-			$where[]="M.media_id ".$this->con->in($params['media_id']);
-		}
-		if (isset($params['media_path'])) {
-			$where[]="M.media_path ".$this->con->in($params['media_path']);
-		}
-		if (isset($params['link_type'])) {
-			$where[]="PM.link_type ".$this->con->in($params['link_type']);
-		} else {
-			$where[]="PM.link_type='attachment'";
-		}
-
-		$strReq .= 'WHERE '.join('AND ',$where).' ';
-
-		if (isset($params['sql'])) {
-			$strReq .= $params['sql'];
-		}
-	//echo $strReq; exit;
-		$rs = $this->con->select($strReq);
-		
-		return $rs;
-	}
-
-	/**
-	Attaches a media to a post.
-	
-	@param	post_id	<b>integer</b>		Post ID
-	@param	media_id	<b>integer</b>		Optionnal media ID
-	*/
-	public function addPostMedia($post_id,$media_id,$link_type='attachment')
-	{
-		$post_id = (integer) $post_id;
-		$media_id = (integer) $media_id;
-		
-		$f = $this->getPostMedia(array('post_id'=>$post_id,'media_id'=>$media_id,'link_type'=>$link_type));
-		
-		if (!$f->isEmpty()) {
-			return;
-		}
-		
-		$cur = $this->con->openCursor($this->table);
-		$cur->post_id = $post_id;
-		$cur->media_id = $media_id;
-		$cur->link_type = $link_type;
-		
-		$cur->insert();
-		$this->core->blog->triggerBlog();
-	}
-	
-	/**
-	Detaches a media from a post.
-	
-	@param	post_id	<b>integer</b>		Post ID
-	@param	media_id	<b>integer</b>		Optionnal media ID
-	*/
-	public function removePostMedia($post_id,$media_id,$link_type=null)
-	{
-		$post_id = (integer) $post_id;
-		$media_id = (integer) $media_id;
-		
-		$strReq = 'DELETE FROM '.$this->table.' '.
-				'WHERE post_id = '.$post_id.' '.
-				'AND media_id = '.$media_id.' ';
-		if ($link_type != null) {
-			$strReq .= "AND link_type = '".$this->con->escape($link_type)."'";
-		}
-		$this->con->execute($strReq);
-		$this->core->blog->triggerBlog();
-	}
-	
-	/**
-	Returns media items attached to a blog post. Result is an array containing
-	fileItems objects.
-	
-	@param	post_id	<b>integer</b>		Post ID
-	@param	media_id	<b>integer</b>		Optionnal media ID
-	@return	<b>array</b> Array of fileItems
-	*/
-	public function getLegacyPostMedia($post_id,$media_id=null)
-	{
-		$post_id = (integer) $post_id;
-		
-		$strReq =
-		'SELECT media_file, M.media_id, media_path, media_title, media_meta, media_dt, '.
-		'media_creadt, media_upddt, media_private, user_id '.
-		'FROM '.$this->table.' M '.
-		'INNER JOIN '.$this->table_ref.' PM ON (M.media_id = PM.media_id) '.
-		"WHERE media_path = '".$this->path."' ".
-		'AND post_id = '.$post_id.' ';
-		
-		if ($media_id) {
-			$strReq .= 'AND M.media_id = '.(integer) $media_id.' ';
-		}
-		
-		$rs = $this->con->select($strReq);
-		
-		$res = array();
-		
-		while ($rs->fetch()) {
-			$f = $this->fileRecord($rs);
-			if ($f !== null) {
-				$res[] = $f;
-			}
-		}
-		
-		return $res;
-	}
-	
-}
-?>
Index: inc/core/class.dc.rest.php
===================================================================
--- inc/core/class.dc.rest.php	(revision 270)
+++ inc/core/class.dc.rest.php	(revision 0)
@@ -4,5 +4,5 @@
 # This file is part of Dotclear 2.
 #
-# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
+# Copyright (c) 2003-2010 Olivier Meunier & Association Dotclear
 # Licensed under the GPL version 2.0 license.
 # See LICENSE file or
Index: inc/core/class.dc.rs.extensions.php
===================================================================
--- inc/core/class.dc.rs.extensions.php	(revision 270)
+++ inc/core/class.dc.rs.extensions.php	(revision 0)
@@ -3,5 +3,5 @@
 # This file is part of Dotclear 2.
 #
-# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
+# Copyright (c) 2003-2010 Olivier Meunier & Association Dotclear
 # Licensed under the GPL version 2.0 license.
 # See LICENSE file or
Index: inc/core/class.dc.settings.php
===================================================================
--- inc/core/class.dc.settings.php	(revision 301)
+++ inc/core/class.dc.settings.php	(revision 0)
@@ -4,5 +4,5 @@
 # This file is part of Dotclear 2.
 #
-# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
+# Copyright (c) 2003-2010 Olivier Meunier & Association Dotclear
 # Licensed under the GPL version 2.0 license.
 # See LICENSE file or
@@ -308,77 +308,4 @@
 	}
 
-	/**
-	Returns a list of settings matching given criteria, for any blog.
-	<b>$params</b> is an array taking the following
-	optionnal parameters:
-	
-	- ns : retrieve setting from given namespace
-	- id : retrieve only settings corresponding to the given id
-	
-	@param	params		<b>array</b>		Parameters
-	@return	<b>record</b>	A record 
-	*/
-	public function getGlobalSettings($params=array())
-	{
-		$strReq = "SELECT * from ".$this->table." ";
-		$where = array();
-		if (!empty($params['ns'])) {
-			$where[] = "setting_ns = '".$this->con->escape($params['ns'])."'";
-		}
-		if (!empty($params['id'])) {
-			$where[] = "setting_id = '".$this->con->escape($params['id'])."'";
-		}
-		if (isset($params['blog_id'])) {
-			if (!empty($params['blog_id'])) {
-				$where[] = "blog_id = '".$this->con->escape($params['blog_id'])."'";
-			} else {
-				$where[] = "blog_id IS NULL";
-			}
-		}
-		if (count($where) != 0) {
-			$strReq .= " WHERE ".join(" AND ", $where);
-		}
-		$strReq .= " ORDER by blog_id";
-		return $this->con->select($strReq);
-	}
-
-	/**
-	Updates a setting from a given record
-	
-	@param	rs		<b>record</b>		the setting to update
-	*/
-	public function updateSetting($rs) 
-	{
-		$cur = $this->con->openCursor($this->table);
-		$cur->setting_id = $rs->setting_id;
-		$cur->setting_value = $rs->setting_value;
-		$cur->setting_type = $rs->setting_type;
-		$cur->setting_label = $rs->setting_label;
-		$cur->blog_id = $rs->blog_id;
-		$cur->setting_ns = $rs->setting_ns;
-		if ($cur->blog_id == null) {
-				$where = 'WHERE blog_id IS NULL ';
-		} else {
-			$where = "WHERE blog_id = '".$this->con->escape($cur->blog_id)."' ";
-		}
-		$cur->update($where."AND setting_id = '".$this->con->escape($cur->setting_id)."' AND setting_ns = '".$this->con->escape($cur->setting_ns)."' ");
-	}
-	
-	/**
-	Drops a setting from a given record
-	
-	@param	rs		<b>record</b>		the setting to drop
-	@return	int		number of deleted records (0 if setting does not exist)
-	*/
-	public function dropSetting($rs) {
-		$strReq = "DELETE FROM ".$this->table.' ';
-		if ($rs->blog_id == null) {
-			$strReq .= 'WHERE blog_id IS NULL ';
-		} else {
-			$strReq .= "WHERE blog_id = '".$this->con->escape($rs->blog_id)."' ";
-		}
-		$strReq .= "AND setting_id = '".$this->con->escape($rs->setting_id)."' AND setting_ns = '".$this->con->escape($rs->setting_ns)."' ";
-		return $this->con->execute($strReq);
-	}
 }
 ?>
Index: inc/core/class.dc.themes.php
===================================================================
--- inc/core/class.dc.themes.php	(revision 270)
+++ inc/core/class.dc.themes.php	(revision 0)
@@ -4,5 +4,5 @@
 # This file is part of Dotclear 2.
 #
-# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
+# Copyright (c) 2003-2010 Olivier Meunier & Association Dotclear
 # Licensed under the GPL version 2.0 license.
 # See LICENSE file or
Index: inc/core/class.dc.trackback.php
===================================================================
--- inc/core/class.dc.trackback.php	(revision 270)
+++ inc/core/class.dc.trackback.php	(revision 0)
@@ -4,5 +4,5 @@
 # This file is part of Dotclear 2.
 #
-# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
+# Copyright (c) 2003-2010 Olivier Meunier & Association Dotclear
 # Licensed under the GPL version 2.0 license.
 # See LICENSE file or
Index: inc/core/class.dc.update.php
===================================================================
--- inc/core/class.dc.update.php	(revision 270)
+++ inc/core/class.dc.update.php	(revision 0)
@@ -4,5 +4,5 @@
 # This file is part of Dotclear 2.
 #
-# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
+# Copyright (c) 2003-2010 Olivier Meunier & Association Dotclear
 # Licensed under the GPL version 2.0 license.
 # See LICENSE file or
Index: inc/core/class.dc.utils.php
===================================================================
--- inc/core/class.dc.utils.php	(revision 270)
+++ inc/core/class.dc.utils.php	(revision 0)
@@ -4,5 +4,5 @@
 # This file is part of Dotclear 2.
 #
-# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
+# Copyright (c) 2003-2010 Olivier Meunier & Association Dotclear
 # Licensed under the GPL version 2.0 license.
 # See LICENSE file or
Index: inc/core/class.dc.xmlrpc.php
===================================================================
--- inc/core/class.dc.xmlrpc.php	(revision 270)
+++ inc/core/class.dc.xmlrpc.php	(revision 0)
@@ -4,5 +4,5 @@
 # This file is part of Dotclear 2.
 #
-# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
+# Copyright (c) 2003-2010 Olivier Meunier & Association Dotclear
 # Licensed under the GPL version 2.0 license.
 # See LICENSE file or
Index: inc/core_error.php
===================================================================
--- inc/core_error.php	(revision 270)
+++ inc/core_error.php	(revision 199)
@@ -4,5 +4,5 @@
 # This file is part of Dotclear 2.
 #
-# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
+# Copyright (c) 2003-2010 Olivier Meunier & Association Dotclear
 # Licensed under the GPL version 2.0 license.
 # See LICENSE file or
Index: inc/dbschema/db-schema.php
===================================================================
--- inc/dbschema/db-schema.php	(revision 407)
+++ inc/dbschema/db-schema.php	(revision 3)
@@ -4,5 +4,5 @@
 # This file is part of Dotclear 2.
 #
-# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
+# Copyright (c) 2003-2010 Olivier Meunier & Association Dotclear
 # Licensed under the GPL version 2.0 license.
 # See LICENSE file or
@@ -152,7 +152,6 @@
 	->media_id	('bigint',	0,	false)
 	->post_id		('bigint',	0,	false)
-	->link_type		('varchar',	32,	false,	"'attachment'")
-	
-	->primary('pk_post_media','media_id','post_id','link_type')
+	
+	->primary('pk_post_media','media_id','post_id')
 	;
 
@@ -236,5 +235,4 @@
 $_s->media->index		('idx_media_user_id',			'btree',	'user_id');
 $_s->post_media->index	('idx_post_media_post_id',		'btree',	'post_id');
-$_s->post_media->index	('idx_post_media_media_id',		'btree',	'media_id');
 $_s->log->index		('idx_log_user_id',				'btree',	'user_id');
 $_s->comment->index		('idx_comment_post_id',			'btree',	'post_id');
Index: inc/dbschema/upgrade-cli.php
===================================================================
--- inc/dbschema/upgrade-cli.php	(revision 270)
+++ inc/dbschema/upgrade-cli.php	(revision 0)
@@ -5,5 +5,5 @@
 # This file is part of Dotclear 2.
 #
-# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
+# Copyright (c) 2003-2010 Olivier Meunier & Association Dotclear
 # Licensed under the GPL version 2.0 license.
 # See LICENSE file or
Index: inc/dbschema/upgrade.php
===================================================================
--- inc/dbschema/upgrade.php	(revision 324)
+++ inc/dbschema/upgrade.php	(revision 107)
@@ -4,5 +4,5 @@
 # This file is part of Dotclear 2.
 #
-# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
+# Copyright (c) 2003-2010 Olivier Meunier & Association Dotclear
 # Licensed under the GPL version 2.0 license.
 # See LICENSE file or
@@ -149,27 +149,27 @@
 				$init_fav = array();
 
-				$init_fav['new_post'] = array('new_post','New entry','post.php',
+				$init_fav['new_post'] = array('new_post',__('New entry'),'post.php',
 					'images/menu/edit.png','images/menu/edit-b.png',
 					'usage,contentadmin',null,'menu-new-post');
-				$init_fav['posts'] = array('posts','Entries','posts.php',
+				$init_fav['posts'] = array('posts',__('Entries'),'posts.php',
 					'images/menu/entries.png','images/menu/entries-b.png',
 					'usage,contentadmin',null,null);
-				$init_fav['comments'] = array('comments','Comments','comments.php',
+				$init_fav['comments'] = array('comments',__('Comments'),'comments.php',
 					'images/menu/comments.png','images/menu/comments-b.png',
 					'usage,contentadmin',null,null);
-				$init_fav['prefs'] = array('prefs','My preferences','preferences.php',
+				$init_fav['prefs'] = array('prefs',__('My preferences'),'preferences.php',
 					'images/menu/user-pref.png','images/menu/user-pref-b.png',
 					'*',null,null);
-				$init_fav['blog_pref'] = array('blog_pref','Blog settings','blog_pref.php',
+				$init_fav['blog_pref'] = array('blog_pref',__('Blog settings'),'blog_pref.php',
 					'images/menu/blog-pref.png','images/menu/blog-pref-b.png',
 					'admin',null,null);
-				$init_fav['blog_theme'] = array('blog_theme','Blog appearance','blog_theme.php',
+				$init_fav['blog_theme'] = array('blog_theme',__('Blog appearance'),'blog_theme.php',
 					'images/menu/themes.png','images/menu/blog-theme-b.png',
 					'admin',null,null);
 
-				$init_fav['pages'] = array('pages','Pages','plugin.php?p=pages',
+				$init_fav['pages'] = array('pages',__('Pages'),'plugin.php?p=pages',
 					'index.php?pf=pages/icon.png','index.php?pf=pages/icon-big.png',
 					'contentadmin,pages',null,null);
-				$init_fav['blogroll'] = array('blogroll','Blogroll','plugin.php?p=blogroll',
+				$init_fav['blogroll'] = array('blogroll',__('Blogroll'),'plugin.php?p=blogroll',
 					'index.php?pf=blogroll/icon-small.png','index.php?pf=blogroll/icon.png',
 					'usage,contentadmin',null,null);
@@ -290,11 +290,4 @@
 			}
 			
-			if (version_compare($version,'2.3.1','<'))
-			{
-				# Remove unecessary file
-				@unlink(DC_ROOT.'/'.'inc/libs/clearbricks/.hgignore');
-			}
-			
-			
 			$core->setVersion('core',DC_VERSION);
 			$core->blogDefaults();
Index: inc/load_plugin_file.php
===================================================================
--- inc/load_plugin_file.php	(revision 270)
+++ inc/load_plugin_file.php	(revision 0)
@@ -4,5 +4,5 @@
 # This file is part of Dotclear 2.
 #
-# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
+# Copyright (c) 2003-2010 Olivier Meunier & Association Dotclear
 # Licensed under the GPL version 2.0 license.
 # See LICENSE file or
Index: inc/prepend.php
===================================================================
--- inc/prepend.php	(revision 407)
+++ inc/prepend.php	(revision 326)
@@ -4,5 +4,5 @@
 # This file is part of Dotclear 2.
 #
-# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
+# Copyright (c) 2003-2010 Olivier Meunier & Association Dotclear
 # Licensed under the GPL version 2.0 license.
 # See LICENSE file or
@@ -41,7 +41,8 @@
 $__autoload['dcCategories']			= dirname(__FILE__).'/core/class.dc.categories.php';
 $__autoload['dcError']				= dirname(__FILE__).'/core/class.dc.error.php';
+$__autoload['dcGenericMeta']			= dirname(__FILE__).'/core/class.dc.genmeta.php';
 $__autoload['dcMeta']				= dirname(__FILE__).'/core/class.dc.meta.php';
+$__autoload['dcUserMeta']			= dirname(__FILE__).'/core/class.dc.usermeta.php';
 $__autoload['dcMedia']				= dirname(__FILE__).'/core/class.dc.media.php';
-$__autoload['dcPostMedia']				= dirname(__FILE__).'/core/class.dc.postmedia.php';
 $__autoload['dcModules']				= dirname(__FILE__).'/core/class.dc.modules.php';
 $__autoload['dcThemes']				= dirname(__FILE__).'/core/class.dc.themes.php';
@@ -69,4 +70,7 @@
 $__autoload['adminCommentList']		= dirname(__FILE__).'/admin/lib.pager.php';
 $__autoload['adminUserList']			= dirname(__FILE__).'/admin/lib.pager.php';
+$__autoload['dcFilterSet']			= dirname(__FILE__).'/admin/class.dc.filter.php';
+$__autoload['dcFilter']				= dirname(__FILE__).'/admin/class.dc.filter.php';
+$__autoload['dcToolBar']				= dirname(__FILE__).'/admin/class.dc.toolbar.php';
 
 $__autoload['dcTemplate']			= dirname(__FILE__).'/public/class.dc.template.php';
@@ -119,5 +123,5 @@
 # Constants
 define('DC_ROOT',path::real(dirname(__FILE__).'/..'));
-define('DC_VERSION','2.4.0-dev');
+define('DC_VERSION','2.3.1');
 define('DC_DIGESTS',dirname(__FILE__).'/digests');
 define('DC_L10N_ROOT',dirname(__FILE__).'/../locales');
Index: inc/public/class.dc.template.php
===================================================================
--- inc/public/class.dc.template.php	(revision 407)
+++ inc/public/class.dc.template.php	(revision 0)
@@ -4,5 +4,5 @@
 # This file is part of Dotclear 2.
 #
-# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
+# Copyright (c) 2003-2010 Olivier Meunier & Association Dotclear
 # Licensed under the GPL version 2.0 license.
 # See LICENSE file or
@@ -54,4 +54,18 @@
 		$this->addValue('ArchiveEntriesCount',array($this,'ArchiveEntriesCount'));
 		$this->addValue('ArchiveURL',array($this,'ArchiveURL'));
+		
+		# Attachments
+		$this->addBlock('Attachments',array($this,'Attachments'));
+		$this->addBlock('AttachmentsHeader',array($this,'AttachmentsHeader'));
+		$this->addBlock('AttachmentsFooter',array($this,'AttachmentsFooter'));
+		$this->addValue('AttachmentMimeType',array($this,'AttachmentMimeType'));
+		$this->addValue('AttachmentType',array($this,'AttachmentType'));
+		$this->addValue('AttachmentFileName',array($this,'AttachmentFileName'));
+		$this->addValue('AttachmentSize',array($this,'AttachmentSize'));
+		$this->addValue('AttachmentTitle',array($this,'AttachmentTitle'));
+		$this->addValue('AttachmentThumbnailURL',array($this,'AttachmentThumbnailURL'));
+		$this->addValue('AttachmentURL',array($this,'AttachmentURL'));
+		$this->addBlock('AttachmentIf',array($this,'AttachmentIf'));
+		$this->addValue('MediaURL',array($this,'MediaURL'));
 		
 		# Blog
@@ -127,4 +141,5 @@
 		$this->addBlock('EntriesHeader',array($this,'EntriesHeader'));
 		$this->addValue('EntryExcerpt',array($this,'EntryExcerpt'));
+		$this->addValue('EntryAttachmentCount',array($this,'EntryAttachmentCount'));
 		$this->addValue('EntryAuthorCommonName',array($this,'EntryAuthorCommonName'));
 		$this->addValue('EntryAuthorDisplayName',array($this,'EntryAuthorDisplayName'));
@@ -308,10 +323,4 @@
 		}
 		
-		if (($node instanceof tplNodeBlock) && !$node->isClosed()) {
-			$errors[] = sprintf(
-				__('Did not find closing tag for block <tpl:%s>. Content has been ignored.'),
-				html::escapeHTML($node->getTag()));
-		}
-		
 		$err = "";
 		if (count($errors) > 0) {
@@ -332,7 +341,4 @@
 		# --BEHAVIOR-- templateBeforeBlock
 		$res = $this->core->callBehavior('templateBeforeBlock',$this->core,$this->current_tag,$attr);
-		
-		# --BEHAVIOR-- templateInsideBlock
-		$this->core->callBehavior('templateInsideBlock',$this->core,$this->current_tag,$attr,array(&$content));
 		
 		if (isset($this->blocks[$this->current_tag])) {
@@ -557,5 +563,5 @@
 		}
 		
-		if (empty($attr['no_context']) && !isset($attr['category']))
+		if (empty($attr['no_context']))
 		{
 			$p .=
@@ -734,4 +740,173 @@
 	}
 	
+	/* Attachments ---------------------------------------- */
+	/*dtd
+	<!ELEMENT tpl:Attachments - - -- Post Attachments loop -->
+	*/
+	public function Attachments($attr,$content)
+	{
+		$res =
+		"<?php\n".
+		'if ($_ctx->posts !== null && $core->media) {'."\n".
+			'$_ctx->attachments = new ArrayObject($core->media->getPostMedia($_ctx->posts->post_id));'."\n".
+		"?>\n".
+		
+		'<?php foreach ($_ctx->attachments as $attach_i => $attach_f) : '.
+		'$GLOBALS[\'attach_i\'] = $attach_i; $GLOBALS[\'attach_f\'] = $attach_f;'.
+		'$_ctx->file_url = $attach_f->file_url; ?>'.
+		$content.
+		'<?php endforeach; $_ctx->attachments = null; unset($attach_i,$attach_f,$_ctx->file_url); ?>'.
+		
+		"<?php } ?>\n";
+		
+		return $res;
+	}
+	
+	/*dtd
+	<!ELEMENT tpl:AttachmentsHeader - - -- First attachments result container -->
+	*/
+	public function AttachmentsHeader($attr,$content)
+	{
+		return
+		"<?php if (\$attach_i == 0) : ?>".
+		$content.
+		"<?php endif; ?>";
+	}
+	
+	/*dtd
+	<!ELEMENT tpl:AttachmentsFooter - - -- Last attachments result container -->
+	*/
+	public function AttachmentsFooter($attr,$content)
+	{
+		return
+		"<?php if (\$attach_i+1 == count(\$_ctx->attachments)) : ?>".
+		$content.
+		"<?php endif; ?>";
+	}
+	
+	/*dtd
+	<!ELEMENT tpl:AttachmentsIf - - -- Test on attachment fields -->
+	<!ATTLIST tpl:AttachmentIf
+	is_image	(0|1)	#IMPLIED	-- test if attachment is an image (value : 1) or not (value : 0)
+	has_thumb	(0|1)	#IMPLIED	-- test if attachment has a square thumnail (value : 1) or not (value : 0)
+	is_mp3	(0|1)	#IMPLIED	-- test if attachment is a mp3 file (value : 1) or not (value : 0)
+	is_flv	(0|1)	#IMPLIED	-- test if attachment is a flv file (value : 1) or not (value : 0)
+	>
+	*/
+	public function AttachmentIf($attr,$content)
+	{
+		$if = array();
+		
+		$operator = isset($attr['operator']) ? $this->getOperator($attr['operator']) : '&&';
+		
+		if (isset($attr['is_image'])) {
+			$sign = (boolean) $attr['is_image'] ? '' : '!';
+			$if[] = $sign.'$attach_f->media_image';
+		}
+		
+		if (isset($attr['has_thumb'])) {
+			$sign = (boolean) $attr['has_thumb'] ? '' : '!';
+			$if[] = $sign.'isset($attach_f->media_thumb[\'sq\'])';
+		}
+		
+		if (isset($attr['is_mp3'])) {
+			$sign = (boolean) $attr['is_mp3'] ? '==' : '!=';
+			$if[] = '$attach_f->type '.$sign.' "audio/mpeg3"';
+		}
+		
+		if (isset($attr['is_flv'])) {
+			$sign = (boolean) $attr['is_flv'] ? '' : '!';
+			$if[] = $sign.
+				'($attach_f->type == "video/x-flv" || '.
+				'$attach_f->type == "video/mp4" || '.
+				'$attach_f->type == "video/x-m4v")';
+		}
+		
+		if (!empty($if)) {
+			return '<?php if('.implode(' '.$operator.' ',$if).') : ?>'.$content.'<?php endif; ?>';
+		} else {
+			return $content;
+		}
+	}
+	
+	/*dtd
+	<!ELEMENT tpl:AttachmentMimeType - O -- Attachment MIME Type -->
+	*/
+	public function AttachmentMimeType($attr)
+	{
+		$f = $this->getFilters($attr);
+		return '<?php echo '.sprintf($f,'$attach_f->type').'; ?>';
+	}
+	
+	/*dtd
+	<!ELEMENT tpl:AttachmentType - O -- Attachment type -->
+	*/
+	public function AttachmentType($attr)
+	{
+		$f = $this->getFilters($attr);
+		return '<?php echo '.sprintf($f,'$attach_f->media_type').'; ?>';
+	}
+	
+	/*dtd
+	<!ELEMENT tpl:AttachmentFileName - O -- Attachment file name -->
+	*/
+	public function AttachmentFileName($attr)
+	{
+		$f = $this->getFilters($attr);
+		return '<?php echo '.sprintf($f,'$attach_f->basename').'; ?>';
+	}
+	
+	/*dtd
+	<!ELEMENT tpl:AttachmentSize - O -- Attachment size -->
+	<!ATTLIST tpl:AttachmentSize
+	full	CDATA	#IMPLIED	-- if set, size is rounded to a human-readable value (in KB, MB, GB, TB)
+	>
+	*/
+	public function AttachmentSize($attr)
+	{
+		$f = $this->getFilters($attr);
+		if (!empty($attr['full'])) {
+			return '<?php echo '.sprintf($f,'$attach_f->size').'; ?>';
+		}
+		return '<?php echo '.sprintf($f,'files::size($attach_f->size)').'; ?>';
+	}
+	
+	/*dtd
+	<!ELEMENT tpl:AttachmentTitle - O -- Attachment title -->
+	*/
+	public function AttachmentTitle($attr)
+	{
+		$f = $this->getFilters($attr);
+		return '<?php echo '.sprintf($f,'$attach_f->media_title').'; ?>';
+	}
+	
+	/*dtd
+	<!ELEMENT tpl:AttachmentThumbnailURL - O -- Attachment square thumbnail URL -->
+	*/
+	public function AttachmentThumbnailURL($attr)
+	{
+		$f = $this->getFilters($attr);
+		return
+		'<?php '.
+		'if (isset($attach_f->media_thumb[\'sq\'])) {'.
+			'echo '.sprintf($f,'$attach_f->media_thumb[\'sq\']').';'.
+		'}'.
+		'?>';
+	}
+	
+	/*dtd
+	<!ELEMENT tpl:AttachmentURL - O -- Attachment URL -->
+	*/
+	public function AttachmentURL($attr)
+	{
+		$f = $this->getFilters($attr);
+		return '<?php echo '.sprintf($f,'$attach_f->file_url').'; ?>';
+	}
+	
+	public function MediaURL($attr)
+	{
+		$f = $this->getFilters($attr);
+		return '<?php echo '.sprintf($f,'$_ctx->file_url').'; ?>';
+	}
 	
 	/* Blog ----------------------------------------------- */
@@ -976,5 +1151,5 @@
 	public function CategoryIf($attr,$content)
 	{
-		$if = new ArrayObject();
+		$if = array();
 		$operator = isset($attr['operator']) ? $this->getOperator($attr['operator']) : '&&';
 		
@@ -998,6 +1173,4 @@
 			$if[] = '$_ctx->categories->cat_desc '.$sign.' ""'; 
 		} 
-		
-		$this->core->callBehavior('tplIfConditions','CategoryIf',$attr,$content,$if);
 		
 		if (!empty($if)) {
@@ -1151,19 +1324,13 @@
 		if (empty($attr['no_context']))
 		{
-			if (!isset($attr['author']))
-			{
-				$p .=
-				'if ($_ctx->exists("users")) { '.
-					"\$params['user_id'] = \$_ctx->users->user_id; ".
-				"}\n";
-			}
+			$p .=
+			'if ($_ctx->exists("users")) { '.
+				"\$params['user_id'] = \$_ctx->users->user_id; ".
+			"}\n";
 			
-			if (!isset($attr['category']) && (!isset($attr['no_category']) || !$attr['no_category']))
-			{
-				$p .=
-				'if ($_ctx->exists("categories")) { '.
-					"\$params['cat_id'] = \$_ctx->categories->cat_id; ".
-				"}\n";
-			}
+			$p .=
+			'if ($_ctx->exists("categories")) { '.
+				"\$params['cat_id'] = \$_ctx->categories->cat_id; ".
+			"}\n";
 			
 			$p .=
@@ -1249,5 +1416,5 @@
 	selected	(0|1)	#IMPLIED	-- post is selected (value : 1) or not (value : 0)
 	has_category	(0|1)	#IMPLIED	-- post has a category (value : 1) or not (value : 0)
-	has_attachment	(0|1)	#IMPLIED	-- post has attachments (value : 1) or not (value : 0) (see Attachment plugin for code)
+	has_attachment	(0|1)	#IMPLIED	-- post has attachments (value : 1) or not (value : 0)
 	comments_active	(0|1)	#IMPLIED	-- comments are active for this post (value : 1) or not (value : 0)
 	pings_active	(0|1)	#IMPLIED	-- trackbacks are active for this post (value : 1) or not (value : 0)
@@ -1260,5 +1427,5 @@
 	public function EntryIf($attr,$content)
 	{
-		$if = new ArrayObject();
+		$if = array();
 		$extended = null;
 		$hascategory = null;
@@ -1317,4 +1484,9 @@
 		}
 		
+		if (isset($attr['has_attachment'])) {
+			$sign = (boolean) $attr['has_attachment'] ? '' : '!';
+			$if[] = $sign.'$_ctx->posts->countMedia()';
+		}
+		
 		if (isset($attr['comments_active'])) {
 			$sign = (boolean) $attr['comments_active'] ? '' : '!';
@@ -1353,8 +1525,6 @@
 		}
 		
-		$this->core->callBehavior('tplIfConditions','EntryIf',$attr,$content,$if);
-		
 		if (!empty($if)) {
-			return '<?php if('.implode(' '.$operator.' ',(array)$if).') : ?>'.$content.'<?php endif; ?>';
+			return '<?php if('.implode(' '.$operator.' ',$if).') : ?>'.$content.'<?php endif; ?>';
 		} else {
 			return $content;
@@ -1451,4 +1621,37 @@
 	}
 	
+	/*dtd
+	<!ELEMENT tpl:EntryAttachmentCount - O -- Number of attachments for entry -->
+	<!ATTLIST tpl:EntryAttachmentCount
+	none	CDATA	#IMPLIED	-- text to display for "no attachment" (default: no attachment)
+	one	CDATA	#IMPLIED	-- text to display for "one attachment" (default: one attachment)
+	more	CDATA	#IMPLIED	-- text to display for "more attachment" (default: %s attachment, %s is replaced by the number of attachments)
+	>
+	*/
+	public function EntryAttachmentCount($attr)
+	{
+		$none = 'no attachment';
+		$one = 'one attachment';
+		$more = '%d attachments';
+		
+		if (isset($attr['none'])) {
+			$none = addslashes($attr['none']);
+		}
+		if (isset($attr['one'])) {
+			$one = addslashes($attr['one']);
+		}
+		if (isset($attr['more'])) {
+			$more = addslashes($attr['more']);
+		}
+		
+		return
+		"<?php if (\$_ctx->posts->countMedia() == 0) {\n".
+		"  printf(__('".$none."'),(integer) \$_ctx->posts->countMedia());\n".
+		"} elseif (\$_ctx->posts->countMedia() == 1) {\n".
+		"  printf(__('".$one."'),(integer) \$_ctx->posts->countMedia());\n".
+		"} else {\n".
+		"  printf(__('".$more."'),(integer) \$_ctx->posts->countMedia());\n".
+		"} ?>";
+	}
 	
 	/*dtd
@@ -2005,6 +2208,4 @@
 			$if[] = $sign.'context::PaginationEnd()';
 		}
-		
-		$this->core->callBehavior('tplIfConditions','PaginationIf',$attr,$content,$if);
 		
 		if (!empty($if)) {
@@ -2281,6 +2482,4 @@
 		}
 		
-		$this->core->callBehavior('tplIfConditions','CommentIf',$attr,$content,$if);
-		
 		if (!empty($if)) {
 			return '<?php if('.implode(' && ',$if).') : ?>'.$content.'<?php endif; ?>';
@@ -2774,5 +2973,5 @@
 	current_mode		CDATA	#IMPLIED	-- tests if current URL mode is the one given in parameter
 	has_tpl			CDATA     #IMPLIED  -- tests if a named template exists
-	has_tag			CDATA     #IMPLIED  -- tests if a named template tag exists (see Tag plugin for code)
+	has_tag			CDATA     #IMPLIED  -- tests if a named template tag exists
 	blog_id			CDATA     #IMPLIED  -- tests if current blog ID is the one given in parameter
 	comments_active	(0|1)	#IMPLIED	-- test if comments are enabled blog-wide 
@@ -2784,5 +2983,5 @@
 	public function SysIf($attr,$content)
 	{
-		$if = new ArrayObject();
+		$if = array();
 		$is_ping = null;
 		
@@ -2830,4 +3029,13 @@
 		}
 		
+		if (isset($attr['has_tag'])) {
+			$sign = '';
+			if (substr($attr['has_tag'],0,1) == '!') {
+				$sign = '!';
+				$attr['has_tag'] = substr($attr['has_tag'],1);
+			}
+			$if[] =  $sign."(\$core->tpl->tagExists('".addslashes($attr['has_tag'])."') )";
+		}
+		
 		if (isset($attr['blog_id'])) {
 			$sign = '';
@@ -2858,6 +3066,4 @@
 			$if[] = '(isset($_search_count) && $_search_count '.html::decodeEntities($attr['search_count']).')';
 		}
-		
-		$this->core->callBehavior('tplIfConditions','SysIf',$attr,$content,$if);
 		
 		if (!empty($if)) {
@@ -3024,7 +3230,4 @@
 		$this->closed = true;
 	}
-	public function isClosed() {
-		return $this->closed;
-	}
 	public function compile($tpl) {
 		if ($this->closed) {
Index: inc/public/lib.tpl.context.php
===================================================================
--- inc/public/lib.tpl.context.php	(revision 270)
+++ inc/public/lib.tpl.context.php	(revision 0)
@@ -4,5 +4,5 @@
 # This file is part of Dotclear 2.
 #
-# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
+# Copyright (c) 2003-2010 Olivier Meunier & Association Dotclear
 # Licensed under the GPL version 2.0 license.
 # See LICENSE file or
Index: inc/public/lib.urlhandlers.php
===================================================================
--- inc/public/lib.urlhandlers.php	(revision 306)
+++ inc/public/lib.urlhandlers.php	(revision 0)
@@ -4,5 +4,5 @@
 # This file is part of Dotclear 2.
 #
-# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
+# Copyright (c) 2003-2010 Olivier Meunier & Association Dotclear
 # Licensed under the GPL version 2.0 license.
 # See LICENSE file or
@@ -204,9 +204,6 @@
 		
 		$n = self::getPageNumber($args);
-		$params = new ArrayObject(array(
-			'lang' => $args));
-		
-		$core->callBehavior('publicLangBeforeGetLangs',$params,$args);
-		
+		
+		$params['lang'] = $args;
 		$_ctx->langs = $core->blog->getLangs($params);
 		
@@ -238,9 +235,6 @@
 		else
 		{
-			$params = new ArrayObject(array(
-				'cat_url' => $args,
-				'post_type' => 'post'));
-			
-			$core->callBehavior('publicCategoryBeforeGetCategories',$params,$args);
+			$params['cat_url'] = $args;
+			$params['post_type'] = 'post';
 			
 			$_ctx->categories = $core->blog->getCategories($params);
@@ -273,11 +267,7 @@
 		elseif (preg_match('|^/([0-9]{4})/([0-9]{2})$|',$args,$m))
 		{
-			$params = new ArrayObject(array(
-				'year' => $m[1],
-				'month' => $m[2],
-				'type' => 'month'));
-			
-			$core->callBehavior('publicArchiveBeforeGetDates',$params,$args);
-			
+			$params['year'] = $m[1];
+			$params['month'] = $m[2];
+			$params['type'] = 'month';
 			$_ctx->archives = $core->blog->getDates($params);
 			
@@ -310,9 +300,7 @@
 			$core->blog->withoutPassword(false);
 			
-			$params = new ArrayObject(array(
-				'post_url' => $args));
-			
-			$core->callBehavior('publicPostBeforeGetPosts',$params,$args);
-
+			$params = new ArrayObject();
+			$params['post_url'] = $args;
+			
 			$_ctx->posts = $core->blog->getPosts($params);
 			
@@ -422,5 +410,5 @@
 						
 						$redir = $_ctx->posts->getURL();
-						$redir .= $core->blog->settings->system->url_scan == 'query_string' ? '&' : '?';
+						$redir .= strpos($redir,'?') !== false ? '&' : '?';
 						
 						try
@@ -493,4 +481,5 @@
 		$cat_url = false;
 		$post_id = null;
+		$params = array();
 		$subtitle = '';
 		
@@ -501,9 +490,6 @@
 		
 		if (preg_match('!^([a-z]{2}(-[a-z]{2})?)/(.*)$!',$args,$m)) {
-			$params = new ArrayObject(array('lang' => $m[1]));
-			
+			$params['lang'] = $m[1];
 			$args = $m[3];
-			
-			$core->callBehavior('publicFeedBeforeGetLangs',$params,$args);
 			
 			$_ctx->langs = $core->blog->getLangs($params);
@@ -549,10 +535,6 @@
 		if ($cat_url)
 		{
-			$params = new ArrayObject(array(
-				'cat_url' => $cat_url,
-				'post_type' => 'post'));
-			
-			$core->callBehavior('publicFeedBeforeGetCategories',$params,$args);
-			
+			$params['cat_url'] = $cat_url;
+			$params['post_type'] = 'post';
 			$_ctx->categories = $core->blog->getCategories($params);
 			
@@ -567,10 +549,6 @@
 		elseif ($post_id)
 		{
-			$params = new ArrayObject(array(
-				'post_id' => $post_id,
-				'post_type' => ''));
-				
-			$core->callBehavior('publicFeedBeforeGetPosts',$params,$args);
-			
+			$params['post_id'] = $post_id;
+			$params['post_type'] = '';
 			$_ctx->posts = $core->blog->getPosts($params);
 			
Index: inc/public/prepend.php
===================================================================
--- inc/public/prepend.php	(revision 270)
+++ inc/public/prepend.php	(revision 0)
@@ -4,5 +4,5 @@
 # This file is part of Dotclear 2.
 #
-# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
+# Copyright (c) 2003-2010 Olivier Meunier & Association Dotclear
 # Licensed under the GPL version 2.0 license.
 # See LICENSE file or
Index: inc/public/rs.extension.php
===================================================================
--- inc/public/rs.extension.php	(revision 270)
+++ inc/public/rs.extension.php	(revision 0)
@@ -4,5 +4,5 @@
 # This file is part of Dotclear 2.
 #
-# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
+# Copyright (c) 2003-2010 Olivier Meunier & Association Dotclear
 # Licensed under the GPL version 2.0 license.
 # See LICENSE file or
