Index: inc/admin/class.dc.menu.php
===================================================================
--- inc/admin/class.dc.menu.php	(revision 0)
+++ inc/admin/class.dc.menu.php	(revision 3)
@@ -25,15 +25,15 @@
 	}
 	
-	public function addItem($title,$url,$img,$active,$show=true,$id=null)
+	public function addItem($title,$url,$img,$active,$show=true,$id=null,$class=null)
 	{
 		if($show) {
-			$this->items[] = $this->itemDef($title,$url,$img,$active,$id);
+			$this->items[] = $this->itemDef($title,$url,$img,$active,$id,$class);
 		}
 	}
 	
-	public function prependItem($title,$url,$img,$active,$show=true,$id=null)
+	public function prependItem($title,$url,$img,$active,$show=true,$id=null,$class=null)
 	{
 		if ($show) {
-			array_unshift($this->items,$this->itemDef($title,$url,$img,$active,$id));
+			array_unshift($this->items,$this->itemDef($title,$url,$img,$active,$id,$class));
 		}
 	}
@@ -65,5 +65,5 @@
 	}
 	
-	protected function itemDef($title,$url,$img,$active,$id=null)
+	protected function itemDef($title,$url,$img,$active,$id=null,$class=null)
 	{
 		if (is_array($url)) {
@@ -76,5 +76,5 @@
 		
 		return
-		'<li'.(($active) ? ' class="active"' : '').
+		'<li'.(($active || $class) ? ' class="'.(($active) ? 'active ' : '').(($class) ? $class : '').'"' : '').
 		(($id) ? ' id="'.$id.'"' : '').
 		(($img) ? ' style="background-image: url('.$img.');"' : '').
Index: inc/admin/lib.dc.page.php
===================================================================
--- inc/admin/lib.dc.page.php	(revision 17)
+++ inc/admin/lib.dc.page.php	(revision 18)
@@ -118,7 +118,10 @@
 		'<form action="index.php" method="post"><div>'.
 		$blog_box.
-		' - <a href="'.$core->blog->url.'" class="button">'.__('View site').'</a>'.
-		' - '.__('User:').' <strong>'.$core->auth->userID().'</strong>'.
-		' - <a href="index.php?logout=1" class="logout">'.__('Logout').'</a>'.
+		'<a href="'.$core->blog->url.'"onclick="window.open(this.href);return false;" title="'.__('Go to site').' ('.__('new window').')'.'">'.__('Go to site').' <img src="images/outgoing.png" alt="" /></a>'.
+		'</div></form>'.
+		'</div>'.
+		'<div id="info-box2"><form action="index.php" method="post><div>"'.
+		' '.__('User:').' <strong>'.$core->auth->userID().'</strong>'.
+		' - <a href="index.php?logout=1" class="logout">'.__('Logout').' <img src="images/logout.png" alt="" /></a>'.
 		'</div></form>'.
 		'</div>';
@@ -153,6 +156,7 @@
 		echo
 		'</div>'."\n".		// End of #main-menu
-		'<div id="footer"><p><img src="images/dotclear_pw.png" alt="Dotclear" /> '.
-		sprintf(__('Thank you for using %s.'),'<a href="http://dotclear.org/">Dotclear</a>').
+		'<div id="footer"><p>'.
+		sprintf(__('Thank you for using %s.'),'<a href="http://dotclear.org/">Dotclear '.DC_VERSION.'</a>').
+		' <span class="credit"> (Icons by <a href="http://dryicons.com/">Dryicons</a>)</span>'.
 		'</p></div>'."\n".
 		"</div>\n";		// End of #wrapper
@@ -319,5 +323,5 @@
 		
 		echo
-		'<div id="help"><hr /><div class="help-content"><h2>'.__('Help').'</h2>'.
+		'<div id="help"><hr /><div class="help-content clear"><h2>'.__('Help').'</h2>'.
 		$content.
 		'</div></div>';
Index: inc/admin/prepend.php
===================================================================
--- inc/admin/prepend.php	(revision 0)
+++ inc/admin/prepend.php	(revision 3)
@@ -138,4 +138,13 @@
 		http::redirect('auth.php');
 	}
+
+/*	
+	# Check add to my fav fired
+	if (!empty($_REQUEST['add-favorite'])) {
+		$redir = $_SERVER['REQUEST_URI'];
+		# Extract admin page from URI
+		# TO BE COMPLETED
+	}
+*/
 }
 
@@ -159,7 +168,56 @@
 	}
 	unset($hfiles,$locales_root);
+
+	# Standard favorites
+	$_fav = new ArrayObject();
+
+	# [] : Title, URL, small icon, large icon, permissions, id, class
+	# NB : '*' in permissions means any, null means super admin only
+	
+	$_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',
+		'images/menu/edit.png','images/menu/edit-b.png',
+		'usage,contentadmin',null,'menu-new-post'));
+	$_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',
+		'images/menu/comments.png','images/menu/comments-b.png',
+		'usage,contentadmin',null,null));
+	$_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',
+		'images/menu/categories.png','images/menu/categories-b.png',
+		'categories',null,null));
+	$_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',
+		'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',
+		'images/menu/themes.png','images/menu/blog-theme-b.png',
+		'admin',null,null));
+
+	$_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',
+		'images/menu/users.png','images/menu/users-b.png',
+		null,null,null));
+	$_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',
+		'images/menu/langs.png','images/menu/langs-b.png',
+		null,null,null));
 	
 	# Menus creation
 	$_menu['Dashboard'] = new dcMenu('dashboard-menu',null);
+	$_menu['Favorites'] = new dcMenu('favorites-menu','My favorites');
 	$_menu['Blog'] = new dcMenu('blog-menu','Blog');
 	$_menu['System'] = new dcMenu('system-menu','System');
@@ -168,4 +226,7 @@
 	# Loading plugins
 	$core->plugins->loadModules(DC_PLUGINS_ROOT,'admin',$_lang);
+
+	# Loading favorites info from plugins
+	$core->callBehavior('adminDashboardFavs', $core, $_fav);
 	
 	# Set menu titles
@@ -174,5 +235,16 @@
 	$_menu['Blog']->title = __('Blog');
 	$_menu['Plugins']->title = __('Plugins');
-	
+	$_menu['Favorites']->title = __('My favorites');
+
+/*	
+	if (!preg_match('/index.php$/',$_SERVER['REQUEST_URI'])) {
+		# Admin index can't be add in fav's
+		$_menu['Dashboard']->prependItem(__('Add this page to my favorites'),'#','images/menu/add_to_favorites.png',
+			false,$core->auth->check('usage,contentadmin',$core->blog->id),'fav-add');
+	}
+*/
+	$_menu['Dashboard']->prependItem(__('My preferences'),'preferences.php','images/menu/user-pref.png',
+		preg_match('/preferences.php(\?.*)?$/',$_SERVER['REQUEST_URI']),
+		true);
 	$_menu['Dashboard']->prependItem(__('Dashboard'),'index.php','images/menu/dashboard.png',
 		preg_match('/index.php$/',$_SERVER['REQUEST_URI']),
@@ -181,4 +253,7 @@
 	$_menu['Blog']->prependItem(__('Blog appearance'),'blog_theme.php','images/menu/themes.png',
 		preg_match('/blog_theme.php(\?.*)?$/',$_SERVER['REQUEST_URI']),
+		$core->auth->check('admin',$core->blog->id));
+	$_menu['Blog']->prependItem(__('Blog settings'),'blog_pref.php','images/menu/blog-pref.png',
+		preg_match('/blog_pref.php(\?.*)?$/',$_SERVER['REQUEST_URI']),
 		$core->auth->check('admin',$core->blog->id));
 	$_menu['Blog']->prependItem(__('Media manager'),'media.php','images/menu/media.png',
@@ -217,4 +292,35 @@
 		$core->auth->isSuperAdmin() ||
 		$core->auth->check('usage,contentadmin',$core->blog->id) && $core->auth->blog_count > 1);
+
+	// Set favorites menu
+	$ws = $core->auth->user_prefs->addWorkspace('favorites');
+	$count = 0;
+	foreach ($ws->dumpPrefs() as $k => $v) {
+		// User favorites only
+		if (!$v['global']) {
+			$count++;
+			$fav = unserialize($v['value']);
+			$_menu['Favorites']->addItem($fav['title'],$fav['url'],$fav['small-icon'],
+				preg_match('/'.$fav['url'].'(\?.*)?$/',$_SERVER['REQUEST_URI']),
+				(($fav['permissions'] == '*') || $core->auth->check($fav['permissions'],$core->blog->id)),$fav['id'],$fav['class']);
+		}
+	}	
+	if (!$count) {
+		// Global favorites if any
+		foreach ($ws->dumpPrefs() as $k => $v) {
+			$count++;
+			$fav = unserialize($v['value']);
+			$_menu['Favorites']->addItem($fav['title'],$fav['url'],$fav['small-icon'],
+				preg_match('/'.$fav['url'].'(\?.*)?$/',$_SERVER['REQUEST_URI']),
+				(($fav['permissions'] == '*') || $core->auth->check($fav['permissions'],$core->blog->id)),$fav['id'],$fav['class']);
+		}
+	}
+	if (!$count) {
+		// No user or global favorites, add "new entry" fav
+		$_menu['Favorites']->addItem(__('New entry'),'post.php','images/menu/edit.png',
+			preg_match('/post.php$/',$_SERVER['REQUEST_URI']),
+			$core->auth->check('usage,contentadmin',$core->blog->id),'menu-new-post',null);
+	}
+	
 }
 ?>
Index: inc/core/class.dc.auth.php
===================================================================
--- inc/core/class.dc.auth.php	(revision 0)
+++ inc/core/class.dc.auth.php	(revision 3)
@@ -40,4 +40,6 @@
 	protected $perm_types;	///< <b>array</b> Permission types
 	
+	public $user_prefs;	///< <b>dcPrefs</b>	dcPrefs object
+	
 	/**
 	Class constructor. Takes dcCore object as single argument.
@@ -136,4 +138,6 @@
 		$this->user_options = array_merge($this->core->userDefaults(),$rs->options());
 		
+		$this->user_prefs = new dcPrefs($this->core,$this->user_id);
+		
 		# Get permissions on blogs
 		if ($this->findUserBlog() === false) {
Index: inc/core/class.dc.media.php
===================================================================
--- inc/core/class.dc.media.php	(revision 2)
+++ inc/core/class.dc.media.php	(revision 3)
@@ -102,4 +102,8 @@
 		
 		$this->addFileHandler('image/jpeg','create',array($this,'imageMetaCreate'));
+		
+		$this->addFileHandler('image/jpeg','recreate',array($this,'imageThumbCreate'));
+		$this->addFileHandler('image/png','recreate',array($this,'imageThumbCreate'));
+		$this->addFileHandler('image/gif','recreate',array($this,'imageThumbCreate'));
 		
 		$this->addFileHandler('image/jpeg','recreate',array($this,'imageThumbCreate'));
@@ -904,8 +908,19 @@
 		$this->callFileHandler($media_type,'recreate',null,$f->basename); // Args list to be completed as necessary (Franck)
 	}
+
+	/**
+	Calls file handlers registered for recreate event
+	
+	@param	f	<b>fileItem</b>	fileItem object
+	*/
+	public function mediaFireRecreateEvent($f)
+	{
+		$media_type = files::getMimeType($f->basename);
+		$this->callFileHandler($media_type,'recreate',null,$f->basename); // Args list to be completed as necessary (Franck)
+	}
 	
 	/* Image handlers
 	------------------------------------------------------- */
-	public function imageThumbCreate($cur,$f,$media_id,$force=true)
+	public function imageThumbCreate($cur,$f,$force=true)
 	{
 		$file = $this->pwd.'/'.$f;
Index: inc/core/class.dc.prefs.php
===================================================================
--- inc/core/class.dc.prefs.php	(revision 3)
+++ inc/core/class.dc.prefs.php	(revision 3)
@@ -0,0 +1,130 @@
+<?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; }
+
+/**
+@ingroup DC_CORE
+@brief User prefs handler
+
+dcPrefs provides user preferences management. This class instance exists as
+dcAuth $prefs property. You should create a new prefs instance when
+updating another user prefs.
+*/
+class dcPrefs
+{
+	protected $con;		///< <b>connection</b> Database connection object
+	protected $table;		///< <b>string</b> Prefs table name
+	protected $user_id;		///< <b>string</b> User ID
+	
+	protected $workspaces = array();		///< <b>array</b> Associative workspaces array
+	
+	protected $ws;			///< <b>string</b> Current workspace
+	
+	/**
+	Object constructor. Retrieves user prefs and puts them in $workspaces
+	array. Local (user) prefs have a highest priority than global prefs.
+	
+	@param	core		<b>dcCore</b>		dcCore object
+	@param	user_id	<b>string</b>		User ID
+	*/
+	public function __construct($core,$user_id)
+	{
+		$this->con =& $core->con;
+		$this->table = $core->prefix.'pref';
+		$this->user_id =& $user_id;
+		$this->loadPrefs();
+	}
+	
+	/**
+	Retrieves all workspaces (and their prefs) from database, with one query. 
+	*/
+	private function loadPrefs()
+	{
+		$strReq = 'SELECT user_id, pref_id, pref_value, '.
+				'pref_type, pref_label, pref_ws '.
+				'FROM '.$this->table.' '.
+				"WHERE user_id = '".$this->con->escape($this->user_id)."' ".
+				'OR user_id IS NULL '.
+				'ORDER BY pref_ws ASC, pref_id ASC';
+		try {
+			$rs = $this->con->select($strReq);
+		} catch (Exception $e) {
+			trigger_error(__('Unable to retrieve workspaces:').' '.$this->con->error(), E_USER_ERROR);
+		}
+		
+		/* Prevent empty tables (install phase, for instance) */
+		if ($rs->isEmpty()) {
+			return;
+		}
+		
+		do {
+			$ws = trim($rs->f('pref_ws'));
+			if (!$rs->isStart()) {
+				// we have to go up 1 step, since workspaces construction performs a fetch()
+				// at very first time
+				$rs->movePrev();
+			}
+			$this->workspaces[$ws] = new dcWorkspace($GLOBALS['core'], $this->user_id, $ws,$rs);
+		} while(!$rs->isStart());
+	}
+		
+	
+	/**
+	Create a new workspace. If the workspace already exists, return it without modification.
+	
+	@param	ws	<b>string</b>		Workspace name
+	@return	<b>dcWorkspace</b>	The workspace created
+	*/
+	public function addWorkspace($ws)
+	{
+		if (!array_key_exists($ws, $this->workspaces)) {
+			$this->workspaces[$ws] = new dcWorkspace($GLOBALS['core'], $this->user_id, $ws);
+		}
+		return $this->workspaces[$ws];
+	}
+	
+	/**
+	Returns full workspace with all prefs pertaining to it.
+	
+	@param	ws	<b>string</b>		Workspace name
+	@return	<b>dcWorkspace</b>
+	*/
+	public function get($ws)
+	{
+		if (array_key_exists($ws, $this->workspaces)) {
+			return $this->workspaces[$ws];
+		}
+		
+		return null;
+	}
+	
+	/**
+	Magic __get method.
+	@copydoc ::get
+	*/
+	public function __get($n)
+	{
+		return $this->get($n);
+	}
+	
+	/**
+	Returns $workspaces property content.
+	
+	@return	<b>array</b>
+	*/
+	public function dumpWorkspaces()
+	{
+		return $this->workspaces;
+	}
+	
+}
+?>
Index: inc/core/class.dc.workspace.php
===================================================================
--- inc/core/class.dc.workspace.php	(revision 13)
+++ inc/core/class.dc.workspace.php	(revision 13)
@@ -0,0 +1,325 @@
+<?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; }
+
+/**
+@ingroup DC_CORE
+@brief User workspace for preferences handler
+
+*/
+class dcWorkspace
+{
+	protected $con;		///< <b>connection</b> Database connection object
+	protected $table;		///< <b>string</b> Preferences table name
+	protected $user_id;		///< <b>string</b> User ID
+	
+	protected $global_prefs = array();	///< <b>array</b> Global prefs array
+	protected $local_prefs = array();	///< <b>array</b> Local prefs array
+	protected $prefs = array();		///< <b>array</b> Associative prefs array
+	protected $ws;			///< <b>string</b> Current workspace
+	
+	/**
+	Object constructor. Retrieves user prefs and puts them in $prefs
+	array. Local (user) prefs have a highest priority than global prefs.
+	
+	@param	name		<b>string</b>		ID for this workspace
+	*/
+	public function __construct(&$core, $user_id, $name, $rs=null)
+	{
+		if (preg_match('/^[a-zA-Z][a-zA-Z0-9]+$/',$name)) {
+			$this->ws = $name;
+		} else {
+			throw new Exception(sprintf(__('Invalid dcWorkspace: %s'),$name));
+		}
+		
+		$this->con =& $core->con;
+		$this->table = $core->prefix.'pref';
+		$this->user_id =& $user_id;
+		
+		$this->getPrefs($rs);
+	}
+	
+	private function getPrefs($rs=null)
+	{	
+		if ($rs == null) {
+			$strReq = 'SELECT user_id, pref_id, pref_value, '.
+					'pref_type, pref_label, pref_ws '.
+					'FROM '.$this->table.' '.
+					"WHERE (user_id = '".$this->con->escape($this->user_id)."' ".
+					'OR user_id IS NULL) '.
+					"AND pref_ws = '".$this->con->escape($this->ws)."' ".
+					'ORDER BY pref_id ASC ';
+		
+			try {
+				$rs = $this->con->select($strReq);
+			} catch (Exception $e) {
+				trigger_error(__('Unable to retrieve prefs:').' '.$this->con->error(), E_USER_ERROR);
+			}
+		}
+		while ($rs->fetch())
+		{
+			if ($rs->f('pref_ws') != $this->ws){
+				break;
+			}
+			$id = trim($rs->f('pref_id'));
+			$value = $rs->f('pref_value');
+			$type = $rs->f('pref_type');
+			
+			if ($type == 'float' || $type == 'double') {
+				$type = 'float';
+			} elseif ($type != 'boolean' && $type != 'integer') {
+				$type = 'string';
+			}
+			
+			settype($value,$type);
+			
+			$array = $rs->user_id ? 'local' : 'global';
+			
+			$this->{$array.'_prefs'}[$id] = array(
+				'ws' => $this->ws,
+				'value' => $value,
+				'type' => $type,
+				'label' => (string) $rs->f('pref_label'),
+				'global' => $rs->user_id == ''
+			);
+		}
+		
+		$this->prefs = $this->global_prefs;
+		
+		foreach ($this->local_prefs as $id => $v) {
+			$this->prefs[$id] = $v;
+		}
+		
+		return true;
+	}
+	
+	public function prefExists($id,$global=false)
+	{
+		$array = $global ? 'global' : 'local';
+		return isset($this->{$array.'_prefs'}[$id]);
+	}
+	
+	/**
+	Returns pref value if exists.
+	
+	@param	n		<b>string</b>		Pref name
+	@return	<b>mixed</b>
+	*/
+	public function get($n)
+	{
+		if (isset($this->prefs[$n]['value'])) {
+			return $this->prefs[$n]['value'];
+		}
+		
+		return null;
+	}
+	
+	/**
+	Magic __get method.
+	@copydoc ::get
+	*/
+	public function __get($n)
+	{
+		return $this->get($n);
+	}
+	
+	/**
+	Sets a pref in $prefs property. This sets the pref for script
+	execution time only and if pref exists.
+	
+	@param	n		<b>string</b>		Pref name
+	@param	v		<b>mixed</b>		Pref value
+	*/
+	public function set($n,$v)
+	{
+		if (isset($this->prefs[$n])) {
+			$this->prefs[$n]['value'] = $v;
+		}
+	}
+	
+	/**
+	Magic __set method.
+	@copydoc ::set
+	*/
+	public function __set($n,$v)
+	{
+		$this->set($n,$v);
+	}
+	
+	/**
+	Creates or updates a pref.
+	
+	$type could be 'string', 'integer', 'float', 'boolean' or null. If $type is
+	null and pref exists, it will keep current pref type.
+	
+	$value_change allow you to not change pref. Useful if you need to change
+	a pref label or type and don't want to change its value.
+	
+	@param	id			<b>string</b>		Pref ID
+	@param	value		<b>mixed</b>		Pref value
+	@param	type			<b>string</b>		Pref type
+	@param	label		<b>string</b>		Pref label
+	@param	value_change	<b>boolean</b>		Change pref value or not
+	@param	global		<b>boolean</b>		Pref is global
+	*/
+	public function put($id,$value,$type=null,$label=null,$value_change=true,$global=false)
+	{
+		if (!preg_match('/^[a-zA-Z][a-zA-Z0-9_]+$/',$id)) {
+			throw new Exception(sprintf(__('%s is not a valid pref id'),$id));
+		}
+		
+		# We don't want to change pref value
+		if (!$value_change)
+		{
+			if (!$global && $this->prefExists($id,false)) {
+				$value = $this->local_prefs[$id]['value'];
+			} elseif ($this->prefExists($id,true)) {
+				$value = $this->global_prefs[$id]['value'];
+			}
+		}
+		
+		# Pref type
+		if ($type == 'double')
+		{
+			$type = 'float';
+		}
+		elseif ($type === null)
+		{
+			if (!$global && $this->prefExists($id,false)) {
+				$type = $this->local_prefs[$id]['type'];
+			} elseif ($this->prefExists($id,true)) {
+				$type = $this->global_prefs[$id]['type'];
+			} else {
+				$type = 'string';
+			}
+		}
+		elseif ($type != 'boolean' && $type != 'integer' && $type != 'float')
+		{
+			$type = 'string';
+		}
+		
+		# We don't change label
+		if ($label == null)
+		{
+			if (!$global && $this->prefExists($id,false)) {
+				$label = $this->local_prefs[$id]['label'];
+			} elseif ($this->prefExists($id,true)) {
+				$label = $this->global_prefs[$id]['label'];
+			}
+		}
+		
+		settype($value,$type);
+		
+		$cur = $this->con->openCursor($this->table);
+		$cur->pref_value = ($type == 'boolean') ? (string) (integer) $value : (string) $value;
+		$cur->pref_type = $type;
+		$cur->pref_label = $label;
+		
+		#If we are local, compare to global value
+		if (!$global && $this->prefExists($id,true))
+		{
+			$g = $this->global_prefs[$id];
+			$same_pref = $g['ws'] == $this->ws && $g['value'] == $value
+			&& $g['type'] == $type && $g['label'] == $label;
+			
+			# Drop pref if same value as global
+			if ($same_pref && $this->prefExists($id,false)) {
+				$this->drop($id);
+			} elseif ($same_pref) {
+				return;
+			}
+		}
+		
+		if ($this->prefExists($id,$global) && $this->ws == $this->prefs[$id]['ws'])
+		{
+			if ($global) {
+				$where = 'WHERE user_id IS NULL ';
+			} else {
+				$where = "WHERE user_id = '".$this->con->escape($this->user_id)."' ";
+			}
+			
+			$cur->update($where."AND pref_id = '".$this->con->escape($id)."' AND pref_ws = '".$this->con->escape($this->ws)."' ");
+		}
+		else
+		{
+			$cur->pref_id = $id;
+			$cur->user_id = $global ? null : $this->user_id;
+			$cur->pref_ws = $this->ws;
+			
+			$cur->insert();
+		}
+	}
+	
+	/**
+	Removes an existing pref. Workspace 
+	
+	@param	id		<b>string</b>		Pref ID
+	*/
+	public function drop($id)
+	{
+		if (!$this->ws) {
+			throw new Exception(__('No workspace specified'));
+		}
+		
+		$strReq =	'DELETE FROM '.$this->table.' ';
+		
+		if ($this->user_id === null) {
+			$strReq .= 'WHERE user_id IS NULL ';
+			$global = true;
+		} else {
+			$strReq .= "WHERE user_id = '".$this->con->escape($this->user_id)."' ";
+			$global = false;
+		}
+		
+		$strReq .= "AND pref_id = '".$this->con->escape($id)."' ";
+		$strReq .= "AND pref_ws = '".$this->con->escape($this->ws)."' ";
+		
+		$this->con->execute($strReq);
+		
+		if ($this->prefExists($id,$global)) {
+			$array = $global ? 'global' : 'local';
+			unset($this->{$array.'_prefs'}[$id]);
+		}
+	}
+	
+	/**
+	Returns $prefs property content.
+	
+	@return	<b>array</b>
+	*/
+	public function dumpPrefs()
+	{
+		return $this->prefs;
+	}
+	
+	/**
+	Returns $local_prefs property content.
+	
+	@return	<b>array</b>
+	*/
+	public function dumpLocalPrefs()
+	{
+		return $this->local_prefs;
+	}
+
+	/**
+	Returns $global_prefs property content.
+	
+	@return	<b>array</b>
+	*/
+	public function dumpGlobalPrefs()
+	{
+		return $this->global_prefs;
+	}
+
+}
+?>
Index: inc/core_error.php
===================================================================
--- inc/core_error.php	(revision 0)
+++ inc/core_error.php	(revision 3)
@@ -27,5 +27,5 @@
 	font: 62.5%/1.5em "DejaVu Sans","Lucida Grande","Lucida Sans Unicode",Arial,sans-serif;
 	color : #000;
-	background : #eceade;
+	background : #E5E3DA;
 	margin : 0;
 	padding : 0;
Index: inc/dbschema/db-schema.php
===================================================================
--- inc/dbschema/db-schema.php	(revision 0)
+++ inc/dbschema/db-schema.php	(revision 3)
@@ -211,4 +211,15 @@
 	;
 
+$_s->pref
+	->pref_id		('varchar',	255,	false)
+	->user_id			('varchar',	32,	true)
+	->pref_ws		('varchar',	32,	false,	"'system'")
+	->pref_value	('text',		0,	true,	null)
+	->pref_type		('varchar',	8,	false,	"'string'")
+	->pref_label	('text',		0,	true)
+	
+	->unique('uk_pref','pref_ws','pref_id','user_id')
+	;
+
 /* References indexes
 -------------------------------------------------------- */
@@ -228,4 +239,5 @@
 $_s->meta->index		('idx_meta_post_id',	'btree','post_id');
 $_s->meta->index		('idx_meta_meta_type',	'btree','meta_type');
+$_s->pref->index		('idx_pref_user_id',			'btree',	'user_id');
 
 /* Performance indexes
@@ -256,4 +268,5 @@
 $_s->log->reference('fk_log_blog','blog_id','blog','blog_id','cascade','set null');
 $_s->meta->reference('fk_meta_post','post_id','post','post_id','cascade','cascade');
+$_s->pref->reference('fk_pref_user','user_id','user','user_id','cascade','cascade');
 
 /* PostgreSQL specific indexes
@@ -263,4 +276,5 @@
 	$_s->setting->index		('idx_setting_blog_id_null',	'btree',	'(blog_id IS NULL)');
 	$_s->media->index		('idx_media_media_path',		'btree',	'media_path', 'media_dir');
+	$_s->pref->index		('idx_pref_user_id_null',		'btree',	'(user_id IS NULL)');
 }
 ?>
Index: inc/dbschema/upgrade.php
===================================================================
--- inc/dbschema/upgrade.php	(revision 0)
+++ inc/dbschema/upgrade.php	(revision 3)
@@ -143,4 +143,43 @@
 				}
 			}
+
+			if (version_compare($version,'2.3','<'))
+			{
+				# Add global favorites
+				$sqlstr = 'INSERT INTO `dc_pref` (`pref_id`, `user_id`, `pref_ws`, `pref_value`, `pref_type`, `pref_label`) VALUES';
+				$sqlstr .= '(\'g000\', NULL, \'favorites\', \'a:8:{s:4:"name";s:8:"new_post";s:5:"title";'.
+					's:'.strlen(__('New entry')).':"'.__('New entry').'";s:3:"url";s:8:"post.php";'.
+					's:10:"small-icon";s:20:"images/menu/edit.png";s:10:"large-icon";s:22:"images/menu/edit-b.png";'.
+					's:11:"permissions";s:18:"usage,contentadmin";s:2:"id";N;s:5:"class";s:13:"menu-new-post";}\', \'string\', NULL)';
+				$sqlstr .= '(\'g001\', NULL, \'favorites\', \'a:8:{s:4:"name";s:5:"posts";s:5:"title";'.
+					's:'.strlen(__('Entries')).':"'.__('Entries').'";s:3:"url";s:9:"posts.php";'.
+					's:10:"small-icon";s:23:"images/menu/entries.png";s:10:"large-icon";s:25:"images/menu/entries-b.png";'.
+					's:11:"permissions";s:18:"usage,contentadmin";s:2:"id";N;s:5:"class";N;}\', \'string\', NULL)';
+				$sqlstr .= '(\'g002\', NULL, \'favorites\', \'a:8:{s:4:"name";s:8:"comments";s:5:"title";'.
+					's:'.strlen(__('Comments')).':"'.__('Comments').'";s:3:"url";s:12:"comments.php";'.
+					's:10:"small-icon";s:24:"images/menu/comments.png";s:10:"large-icon";s:26:"images/menu/comments-b.png";'.
+					's:11:"permissions";s:18:"usage,contentadmin";s:2:"id";N;s:5:"class";N;}\', \'string\', NULL)';
+				$sqlstr .= '(\'g003\', NULL, \'favorites\', \'a:8:{s:4:"name";s:5:"prefs";s:5:"title";'.
+					's:'.strlen(__('My preferences')).':"'.__('My preferences').'";s:3:"url";s:15:"preferences.php";'.
+					's:10:"small-icon";s:25:"images/menu/user-pref.png";s:10:"large-icon";s:27:"images/menu/user-pref-b.png";'.
+					's:11:"permissions";s:1:"*";s:2:"id";N;s:5:"class";N;}\', \'string\', NULL)';
+				$sqlstr .= '(\'g004\', NULL, \'favorites\', \'a:8:{s:4:"name";s:9:"blog_pref";s:5:"title";'.
+					's:'.strlen(__('Blog settings')).':"'.__('Blog settings').'";s:3:"url";s:13:"blog_pref.php";'.
+					's:10:"small-icon";s:25:"images/menu/blog-pref.png";s:10:"large-icon";s:27:"images/menu/blog-pref-b.png";'.
+					's:11:"permissions";s:5:"admin";s:2:"id";N;s:5:"class";N;}\', \'string\', NULL)';
+				$sqlstr .= '(\'g005\', NULL, \'favorites\', \'a:8:{s:4:"name";s:10:"blog_theme";s:5:"title";'.
+					's:'.strlen(__('Blog appearance')).':"'.__('Blog appearance').'";s:3:"url";s:14:"blog_theme.php";'.
+					's:10:"small-icon";s:22:"images/menu/themes.png";s:10:"large-icon";s:28:"images/menu/blog-theme-b.png";'.
+					's:11:"permissions";s:5:"admin";s:2:"id";N;s:5:"class";N;}\', \'string\', NULL)';
+				$sqlstr .= '(\'g006\', NULL, \'favorites\', \'a:8:{s:4:"name";s:5:"pages";s:5:"title";'.
+					's:'.strlen(__('Pages')).':"'.__('Pages').'";s:3:"url";s:18:"plugin.php?p=pages";'.
+					's:10:"small-icon";s:27:"index.php?pf=pages/icon.png";s:10:"large-icon";s:31:"index.php?pf=pages/icon-big.png";'.
+					's:11:"permissions";s:18:"contentadmin,pages";s:2:"id";N;s:5:"class";N;}\', \'string\', NULL)';
+				$sqlstr .= '(\'g007\', NULL, \'favorites\', \'a:8:{s:4:"name";s:8:"blogroll";s:5:"title";'.
+					's:'.strlen(__('Blogroll')).':"'.__('Blogroll').'";s:3:"url";s:21:"plugin.php?p=blogroll";'.
+					's:10:"small-icon";s:36:"index.php?pf=blogroll/icon-small.png";s:10:"large-icon";s:30:"index.php?pf=blogroll/icon.png";'.
+					's:11:"permissions";s:18:"usage,contentadmin";s:2:"id";N;s:5:"class";N;}\', \'string\', NULL);';
+				$core->con->execute($sqlstr);
+			}
 			
 			$core->setVersion('core',DC_VERSION);
Index: inc/prepend.php
===================================================================
--- inc/prepend.php	(revision 7)
+++ inc/prepend.php	(revision 9)
@@ -53,4 +53,6 @@
 $__autoload['dcXmlRpc']				= dirname(__FILE__).'/core/class.dc.xmlrpc.php';
 $__autoload['dcLog']				= dirname(__FILE__).'/core/class.dc.log.php';
+$__autoload['dcWorkspace']			= dirname(__FILE__).'/core/class.dc.workspace.php';
+$__autoload['dcPrefs']				= dirname(__FILE__).'/core/class.dc.prefs.php';
 
 $__autoload['rsExtPost']				= dirname(__FILE__).'/core/class.dc.rs.extensions.php';
