Index: inc/admin/lib.dc.page.php
===================================================================
--- inc/admin/lib.dc.page.php	(revision 1256)
+++ inc/admin/lib.dc.page.php	(revision 1462)
@@ -160,5 +160,5 @@
 		if ($core->error->flag()) {
 			echo
-			'<div class="error"><p><strong>'.(count($core->error->getErrors()) > 1 ? __('Errors:') : __('Error:')).'</p></strong>'.
+			'<div class="error"><p><strong>'.(count($core->error->getErrors()) > 1 ? __('Errors:') : __('Error:')).'</strong></p>'.
 			$core->error->toHTML().
 			'</div>';
@@ -466,4 +466,6 @@
 		self::jsVar('dotclear.msg.confirm_delete_theme',
 			__('Are you sure you want to delete "%s" theme?')).
+		self::jsVar('dotclear.msg.confirm_delete_backup',
+			__('Are you sure you want to delete this backup?')).
 		self::jsVar('dotclear.msg.zip_file_content',
 			__('Zip file content')).
Index: inc/admin/lib.pager.php
===================================================================
--- inc/admin/lib.pager.php	(revision 1179)
+++ inc/admin/lib.pager.php	(revision 1364)
@@ -87,5 +87,5 @@
 			html::escapeHTML($this->rs->cat_title));
 		} else {
-			$cat_title = __('None');
+			$cat_title = __('(No cat)');
 		}
 		
Index: inc/config.php.in
===================================================================
--- inc/config.php.in	(revision 1179)
+++ inc/config.php.in	(revision 1535)
@@ -50,5 +50,5 @@
 
 // Template cache directory
-define('DC_TPL_CACHE',dirname(__FILE__).'/../cache');
+define('DC_TPL_CACHE',path::real(dirname(__FILE__).'/..').'/cache');
 
 
Index: inc/core/class.dc.blog.php
===================================================================
--- inc/core/class.dc.blog.php	(revision 1544)
+++ inc/core/class.dc.blog.php	(revision 1545)
@@ -645,18 +645,55 @@
 	private function checkCategory($title,$url,$id=null)
 	{
-		$strReq = 'SELECT cat_id '.
-				'FROM '.$this->prefix.'category '.
-				"WHERE cat_url = '".$this->con->escape($url)."' ".
-				"AND blog_id = '".$this->con->escape($this->id)."' ";
-		
-		if ($id !== null) {
-			$strReq .= 'AND cat_id <> '.(integer) $id.' ';
-		}
+		# Let's check if URL is taken...
+		$strReq = 
+			'SELECT cat_url FROM '.$this->prefix.'category '.
+			"WHERE cat_url = '".$this->con->escape($url)."' ".
+			($id ? 'AND cat_id <> '.(integer) $id. ' ' : '').
+			"AND blog_id = '".$this->con->escape($this->id)."' ".
+			'ORDER BY cat_url DESC';
 		
 		$rs = $this->con->select($strReq);
 		
-		if (!$rs->isEmpty()) {
-			throw new Exception(__('Category URL must be unique.'));
-		}
+		if (!$rs->isEmpty())
+		{
+			if ($this->con->driver() == 'mysql') {
+				$clause = "REGEXP '^".$this->con->escape($url)."[0-9]+$'";
+			} elseif ($this->con->driver() == 'pgsql') {
+				$clause = "~ '^".$this->con->escape($url)."[0-9]+$'";
+			} else {
+				$clause = "LIKE '".$this->con->escape($url)."%'";
+			}
+			$strReq = 
+				'SELECT cat_url FROM '.$this->prefix.'category '.
+				"WHERE cat_url ".$clause.' '.
+				($id ? 'AND cat_id <> '.(integer) $id. ' ' : '').
+				"AND blog_id = '".$this->con->escape($this->id)."' ".
+				'ORDER BY cat_url DESC ';
+			
+			$rs = $this->con->select($strReq);
+			$a = array();
+			while ($rs->fetch()) {
+				$a[] = $rs->cat_url;
+			}
+			
+			natsort($a);
+			$t_url = end($a);
+			
+			if (preg_match('/(.*?)([0-9]+)$/',$t_url,$m)) {
+				$i = (integer) $m[2];
+				$url = $m[1];
+			} else {
+				$i = 1;
+			}
+			
+			return $url.($i+1);
+		}
+		
+		# URL is empty?
+		if ($url == '') {
+			throw new Exception(__('Empty category URL'));
+		}
+		
+		return $url;
 	}
 	
@@ -680,5 +717,5 @@
 		
 		# Check if title or url are unique
-		$this->checkCategory($cur->cat_title,$cur->cat_url,$id);
+		$cur->cat_url = $this->checkCategory($cur->cat_title,$cur->cat_url,$id);
 		
 		if ($cur->cat_desc !== null) {
Index: inc/core/class.dc.media.php
===================================================================
--- inc/core/class.dc.media.php	(revision 1220)
+++ inc/core/class.dc.media.php	(revision 1381)
@@ -30,4 +30,5 @@
 	
 	public $thumb_tp = '%s/.%s_%s.jpg';	///< <b>string</b> Thumbnail file pattern
+	public $thumb_tp_alpha = '%s/.%s_%s.png'; ///< <b>string</b> Thumbnail file pattern (with alpha layer)
 	
 	/**
@@ -298,6 +299,7 @@
 			$f->media_thumb = array();
 			$p = path::info($f->relname);
-			$thumb = sprintf($this->thumb_tp,$this->root.'/'.$p['dirname'],$p['base'],'%s');
-			$thumb_url = sprintf($this->thumb_tp,$this->root_url.$p['dirname'],$p['base'],'%s');
+			$alpha = ($p['extension'] == 'png') || ($p['extension'] == 'PNG');
+			$thumb = sprintf(($alpha ? $this->thumb_tp_alpha : $this->thumb_tp),$this->root.'/'.$p['dirname'],$p['base'],'%s');
+			$thumb_url = sprintf(($alpha ? $this->thumb_tp_alpha : $this->thumb_tp),$this->root_url.$p['dirname'],$p['base'],'%s');
 			
 			# Cleaner URLs
@@ -497,7 +499,8 @@
 	@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($post_id,$media_id=null)
+	@param	return_rs	<b>boolean</b>		Whether to return a resultset (true) or an array (false, default value).
+	@return	<b>array</b> Array or ResultSet of fileItems
+	*/
+	public function getPostMedia($post_id,$media_id=null,$return_rs=false)
 	{
 		$params = array(
@@ -515,9 +518,9 @@
 			$f = $this->fileRecord($rs);
 			if ($f !== null) {
-				$res[] = new ArrayObject($f);
-			}
-		}
-		
-		return $res;
+				$res[] = $return_rs ? new ArrayObject($f) : $f;
+			}
+		}
+		
+		return $return_rs ? staticRecord::newFromArray($res) : $res;
 	}
 	
@@ -920,5 +923,6 @@
 		
 		$p = path::info($file);
-		$thumb = sprintf($this->thumb_tp,$p['dirname'],$p['base'],'%s');
+		$alpha = ($p['extension'] == 'png') || ($p['extension'] == 'PNG');
+		$thumb = sprintf(($alpha ? $this->thumb_tp_alpha : $this->thumb_tp),$p['dirname'],$p['base'],'%s');
 		
 		try
@@ -939,5 +943,5 @@
 					$rate = ($s[0] < 100 ? 95 : ($s[0] < 600 ? 90 : 85));
 					$img->resize($s[0],$s[0],$s[1]);
-					$img->output('jpeg',$thumb_file,$rate);
+					$img->output(($alpha ? 'png' : 'jpeg'),$thumb_file,$rate);
 					$img->loadImage($file);
 				}
@@ -958,8 +962,10 @@
 		{
 			$p = path::info($file->relname);
-			$thumb_old = sprintf($this->thumb_tp,$p['dirname'],$p['base'],'%s');
+			$alpha = ($p['extension'] == 'png') || ($p['extension'] == 'PNG');
+			$thumb_old = sprintf(($alpha ? $this->thumb_tp_alpha : $this->thumb_tp),$p['dirname'],$p['base'],'%s');
 			
 			$p = path::info($newFile->relname);
-			$thumb_new = sprintf($this->thumb_tp,$p['dirname'],$p['base'],'%s');
+			$alpha = ($p['extension'] == 'png') || ($p['extension'] == 'PNG');
+			$thumb_new = sprintf(($alpha ? $this->thumb_tp_alpha : $this->thumb_tp),$p['dirname'],$p['base'],'%s');
 			
 			foreach ($this->thumb_sizes as $suffix => $s) {
@@ -974,5 +980,6 @@
 	{
 		$p = path::info($f);
-		$thumb = sprintf($this->thumb_tp,'',$p['base'],'%s');
+		$alpha = ($p['extension'] == 'png') || ($p['extension'] == 'PNG');
+		$thumb = sprintf(($alpha ? $this->thumb_tp_alpha : $this->thumb_tp),'',$p['base'],'%s');
 		
 		foreach ($this->thumb_sizes as $suffix => $s) {
Index: inc/prepend.php
===================================================================
--- inc/prepend.php	(revision 1233)
+++ inc/prepend.php	(revision 1352)
@@ -123,5 +123,5 @@
 # Constants
 define('DC_ROOT',path::real(dirname(__FILE__).'/..'));
-define('DC_VERSION','2.5.2-dev');
+define('DC_VERSION','2.5.3-dev');
 define('DC_DIGESTS',dirname(__FILE__).'/digests');
 define('DC_L10N_ROOT',dirname(__FILE__).'/../locales');
Index: inc/public/lib.tpl.context.php
===================================================================
--- inc/public/lib.tpl.context.php	(revision 1179)
+++ inc/public/lib.tpl.context.php	(revision 1537)
@@ -416,62 +416,67 @@
 		global $core, $_ctx;
 		
-		$media = new dcMedia($core);
-		$sizes = implode('|',array_keys($media->thumb_sizes)).'|o';
-		if (!preg_match('/^'.$sizes.'$/',$size)) {
-			$size = 's';
-		}
-		$p_url = $core->blog->settings->system->public_url;
-		$p_site = preg_replace('#^(.+?//.+?)/(.*)$#','$1',$core->blog->url);
-		$p_root = $core->blog->public_path;
-		
-		$pattern = '(?:'.preg_quote($p_site,'/').')?'.preg_quote($p_url,'/');
-		$pattern = sprintf('/<img.+?src="%s(.*?\.(?:jpg|jpeg|gif|png))"[^>]+/msui',$pattern);
-		
-		$src = '';
-		$alt = '';
-		
-		# We first look in post content
-		if (!$cat_only && $_ctx->posts)
-		{
-			$subject = ($content_only ? '' : $_ctx->posts->post_excerpt_xhtml).$_ctx->posts->post_content_xhtml;
-			if (preg_match_all($pattern,$subject,$m) > 0)
+		try {
+			$media = new dcMedia($core);
+			$sizes = implode('|',array_keys($media->thumb_sizes)).'|o';
+			if (!preg_match('/^'.$sizes.'$/',$size)) {
+				$size = 's';
+			}
+			$p_url = $core->blog->settings->system->public_url;
+			$p_site = preg_replace('#^(.+?//.+?)/(.*)$#','$1',$core->blog->url);
+			$p_root = $core->blog->public_path;
+			
+			$pattern = '(?:'.preg_quote($p_site,'/').')?'.preg_quote($p_url,'/');
+			$pattern = sprintf('/<img.+?src="%s(.*?\.(?:jpg|jpeg|gif|png))"[^>]+/msui',$pattern);
+			
+			$src = '';
+			$alt = '';
+			
+			# We first look in post content
+			if (!$cat_only && $_ctx->posts)
 			{
-				foreach ($m[1] as $i => $img) {
-					if (($src = self::ContentFirstImageLookup($p_root,$img,$size)) !== false) {
-						$dirname = str_replace('\\', '/', dirname($img)); 
-						$src = $p_url.($dirname != '/' ? $dirname : '').'/'.$src;
-						if (preg_match('/alt="([^"]+)"/',$m[0][$i],$malt)) {
-							$alt = $malt[1];
+				$subject = ($content_only ? '' : $_ctx->posts->post_excerpt_xhtml).$_ctx->posts->post_content_xhtml;
+				if (preg_match_all($pattern,$subject,$m) > 0)
+				{
+					foreach ($m[1] as $i => $img) {
+						if (($src = self::ContentFirstImageLookup($p_root,$img,$size)) !== false) {
+							$dirname = str_replace('\\', '/', dirname($img)); 
+							$src = $p_url.($dirname != '/' ? $dirname : '').'/'.$src;
+							if (preg_match('/alt="([^"]+)"/',$m[0][$i],$malt)) {
+								$alt = $malt[1];
+							}
+							break;
 						}
-						break;
 					}
 				}
 			}
-		}
-		
-		# No src, look in category description if available
-        if (!$src && $with_category && $_ctx->posts->cat_desc)
-        {
-			if (preg_match_all($pattern,$_ctx->posts->cat_desc,$m) > 0)
-			{
-				foreach ($m[1] as $i => $img) {
-					if (($src = self::ContentFirstImageLookup($p_root,$img,$size)) !== false) {
-						$dirname = str_replace('\\', '/', dirname($img)); 
-						$src = $p_url.($dirname != '/' ? $dirname : '').'/'.$src;
-						if (preg_match('/alt="([^"]+)"/',$m[0][$i],$malt)) {
-							$alt = $malt[1];
+			
+			# No src, look in category description if available
+	        if (!$src && $with_category && $_ctx->posts->cat_desc)
+	        {
+				if (preg_match_all($pattern,$_ctx->posts->cat_desc,$m) > 0)
+				{
+					foreach ($m[1] as $i => $img) {
+						if (($src = self::ContentFirstImageLookup($p_root,$img,$size)) !== false) {
+							$dirname = str_replace('\\', '/', dirname($img)); 
+							$src = $p_url.($dirname != '/' ? $dirname : '').'/'.$src;
+							if (preg_match('/alt="([^"]+)"/',$m[0][$i],$malt)) {
+								$alt = $malt[1];
+							}
+							break;
 						}
-						break;
 					}
-				}
-			};
-		}
-		
-		if ($src) {
-			if ($no_tag) {
-				return $src;
-			} else {
-				return '<img alt="'.$alt.'" src="'.$src.'" class="'.$class.'" />';
-			}
+				};
+			}
+			
+			if ($src) {
+				if ($no_tag) {
+					return $src;
+				} else {
+					return '<img alt="'.$alt.'" src="'.$src.'" class="'.$class.'" />';
+				}
+			}
+			
+		} catch (Exception $e) {
+			$core->error->add($e->getMessage());
 		}
 	}
@@ -485,37 +490,41 @@
 		$base = $info['base'];
 		
-		$media = new dcMedia($core);
-		$sizes = implode('|',array_keys($media->thumb_sizes));
-		if (preg_match('/^\.(.+)_('.$sizes.')$/',$base,$m)) {
-			$base = $m[1];
-		}
-		
-		$res = false;
-		if ($size != 'o' && file_exists($root.'/'.$info['dirname'].'/.'.$base.'_'.$size.'.jpg'))
-		{
-			$res = '.'.$base.'_'.$size.'.jpg';
-		}
-		else
-		{
-			$f = $root.'/'.$info['dirname'].'/'.$base;
-			if (file_exists($f.'.'.$info['extension'])) {
-				$res = $base.'.'.$info['extension'];
-			} elseif (file_exists($f.'.jpg')) {
-				$res = $base.'.jpg';
-			} elseif (file_exists($f.'.jpeg')) {
-				$res = $base.'.jpeg';
-			} elseif (file_exists($f.'.png')) {
-				$res = $base.'.png';
-			} elseif (file_exists($f.'.gif')) {
-				$res = $base.'.gif';
-			} elseif (file_exists($f.'.JPG')) {
-				$res = $base.'.JPG';
-			} elseif (file_exists($f.'.JPEG')) {
-				$res = $base.'.JPEG';
-			} elseif (file_exists($f.'.PNG')) {
-				$res = $base.'.PNG';
-			} elseif (file_exists($f.'.GIF')) {
-				$res = $base.'.GIF';
-			}
+		try {
+			$media = new dcMedia($core);
+			$sizes = implode('|',array_keys($media->thumb_sizes));
+			if (preg_match('/^\.(.+)_('.$sizes.')$/',$base,$m)) {
+				$base = $m[1];
+			}
+			
+			$res = false;
+			if ($size != 'o' && file_exists($root.'/'.$info['dirname'].'/.'.$base.'_'.$size.'.jpg'))
+			{
+				$res = '.'.$base.'_'.$size.'.jpg';
+			}
+			else
+			{
+				$f = $root.'/'.$info['dirname'].'/'.$base;
+				if (file_exists($f.'.'.$info['extension'])) {
+					$res = $base.'.'.$info['extension'];
+				} elseif (file_exists($f.'.jpg')) {
+					$res = $base.'.jpg';
+				} elseif (file_exists($f.'.jpeg')) {
+					$res = $base.'.jpeg';
+				} elseif (file_exists($f.'.png')) {
+					$res = $base.'.png';
+				} elseif (file_exists($f.'.gif')) {
+					$res = $base.'.gif';
+				} elseif (file_exists($f.'.JPG')) {
+					$res = $base.'.JPG';
+				} elseif (file_exists($f.'.JPEG')) {
+					$res = $base.'.JPEG';
+				} elseif (file_exists($f.'.PNG')) {
+					$res = $base.'.PNG';
+				} elseif (file_exists($f.'.GIF')) {
+					$res = $base.'.GIF';
+				}
+			}
+		} catch (Exception $e) {
+			$core->error->add($e->getMessage());
 		}
 		
