Index: inc/admin/actions/class.dcaction.php
===================================================================
--- inc/admin/actions/class.dcaction.php	(revision 2169)
+++ inc/admin/actions/class.dcaction.php	(revision 2072)
@@ -225,5 +225,5 @@
      * @return string the redirection url
      */
-	public function getRedirection($with_selected_entries=false,$params=array()) {
+	public function getRedirection($params=array(),$with_selected_entries=false) {
 		$redir_args = array_merge($params,$this->redir_args);
 		if ($with_selected_entries) {
@@ -240,6 +240,6 @@
      * @access public
      */
-	public function redirect($with_selected_entries=false,$params=array()) {
-		http::redirect($this->getRedirection($with_selected_entries,$params));
+	public function redirect($params=array(),$with_selected_entries=false) {
+		http::redirect($this->getRedirection($params,$with_selected_entries));
 		exit;
 	}	
Index: inc/admin/actions/class.dcactioncomments.php
===================================================================
--- inc/admin/actions/class.dcactioncomments.php	(revision 2169)
+++ inc/admin/actions/class.dcactioncomments.php	(revision 2075)
@@ -46,5 +46,5 @@
 
 		}
-		echo '<p><a class="back" href="'.$this->getRedirection(true).'">'.__('Back to comments list').'</a></p>';
+		echo '<p><a class="back" href="'.$this->getRedirection(array(),true).'">'.__('Back to comments list').'</a></p>';
 	}
 	
@@ -59,5 +59,5 @@
 				html::escapeHTML($this->core->blog->name) => '',
 				__('Comments') => 'comments.php',
-				__('Comments actions') => ''
+				'<span class="page-title">'.__('Comments actions').'</span>' => ''
 			))
 		);
@@ -149,5 +149,5 @@
 		
 		$core->blog->updCommentsStatus($co_ids,$status);
-		$ap->redirect(true,array('upd'=>1));
+		$ap->redirect(array('upd'=>1),true);
 	}
 
@@ -168,5 +168,5 @@
 		
 		$core->blog->delComments($co_ids);
-		$ap->redirect(false,array('del'=>1));
+		$ap->redirect(array('del'=>1), false);
 	}
 }
Index: inc/admin/actions/class.dcactionposts.php
===================================================================
--- inc/admin/actions/class.dcactionposts.php	(revision 2169)
+++ inc/admin/actions/class.dcactionposts.php	(revision 2072)
@@ -44,5 +44,5 @@
 			);
 		}
-		echo '<p><a class="back" href="'.$this->getRedirection(true).'">'.__('Back to entries list').'</a></p>';
+		echo '<p><a class="back" href="'.$this->getRedirection(array(),true).'">'.__('Back to entries list').'</a></p>';
 	}
 	
@@ -60,6 +60,6 @@
 			array(
 				html::escapeHTML($this->core->blog->name) => '',
-				$this->getCallerTitle() => $this->getRedirection(true),
-				__('Entries actions') => ''
+				$this->getCallerTitle() => $this->getRedirection(array(),true),
+				'<span class="page-title">'.__('Entries actions').'</span>' => ''
 			))
 		);
@@ -160,5 +160,5 @@
 		$core->blog->updPostsStatus($posts_ids,$status);
 		
-		$ap->redirect(true,array('upd' => 1));
+		$ap->redirect(array('upd' => 1),true);
 	}
 	
@@ -171,5 +171,5 @@
 		$core->blog->updPostsSelected($posts_ids,$action == 'selected');
 		
-		$ap->redirect(true,array('upd' => 1));
+		$ap->redirect(array('upd' => 1),true);
 	}
 	
@@ -192,5 +192,5 @@
 		$core->blog->delPosts($posts_ids);
 		
-		$ap->redirect(false,array('del',1));
+		$ap->redirect(array('del',1),false);
 	}
 
@@ -221,5 +221,5 @@
 			$core->blog->updPostsCategory($posts_ids, $new_cat_id);
 			
-			$ap->redirect(true,array('upd'=>1));
+			$ap->redirect(array('upd'=>1),true);
 		} else {
 
@@ -228,6 +228,6 @@
 					array(
 						html::escapeHTML($core->blog->name) => '',
-						$ap->getCallerTitle() => $ap->getRedirection(true),
-						__('Change category for this selection') => ''
+						$ap->getCallerTitle() => $ap->getRedirection(array(),true),
+						'<span class="page-title">'.__('Change category for this selection').'</span>' => ''
 			)));
 			# categories list
@@ -280,5 +280,5 @@
 			$cur->update('WHERE post_id '.$core->con->in($posts_ids));
 			
-			$ap->redirect(true,array('upd' => 1));
+			$ap->redirect(array('upd' => 1),true);
 		} else {
 			$usersList = '';
@@ -298,6 +298,6 @@
 					array(
 						html::escapeHTML($core->blog->name) => '',
-						$ap->getCallerTitle() => $ap->getRedirection(true),
-						__('Change author for this selection') => '')),
+						$ap->getCallerTitle() => $ap->getRedirection(array(),true),
+						'<span class="page-title">'.__('Change author for this selection').'</span>' => '')),
 					dcPage::jsLoad('js/jquery/jquery.autocomplete.js').
 					'<script type="text/javascript">'."\n".
@@ -333,5 +333,5 @@
 			$cur->update('WHERE post_id '.$core->con->in($posts_ids));
 			
-			$ap->redirect(true,array('upd' => 1));
+			$ap->redirect(array('upd' => 1),true);
 		} else {
 			$ap->beginPage(
@@ -339,6 +339,6 @@
 					array(
 						html::escapeHTML($core->blog->name) => '',
-						$ap->getCallerTitle() => $ap->getRedirection(true),
-						_('Change language for this selection') => ''
+						$ap->getCallerTitle() => $ap->getRedirection(array(),true),
+						'<span class="page-title">'.__('Change language for this selection').'</span>' => ''
 			)));
 			# lang list
Index: inc/admin/lib.dc.page.php
===================================================================
--- inc/admin/lib.dc.page.php	(revision 2167)
+++ inc/admin/lib.dc.page.php	(revision 2164)
@@ -304,9 +304,6 @@
 	}
 
-	public static function breadcrumb($elements=null,$options=array())
-	{
-		$with_home_link = isset($options['home_link'])?$options['home_link']:true;
-		$hl = isset($options['hl'])?$options['hl']:true;
-		$hl_pos = isset($options['hl_pos'])?$options['hl_pos']:-1;
+	public static function breadcrumb($elements=null,$with_home_link=true,$echo=false)
+	{
 		// First item of array elements should be blog's name, System or Plugins
 		$res = '<h2>'.($with_home_link ?
@@ -314,11 +311,5 @@
 			'<img src="style/dashboard-alt.png" alt="" />');
 		$index = 0;
-		if ($hl_pos < 0) {
-			$hl_pos = count($elements)+$hl_pos;
-		}
 		foreach ($elements as $element => $url) {
-			if ($hl && $index == $hl_pos) {
-				$element = sprintf('<span class="page-title">%s</span>',$element);
-			}
 			$res .= ($with_home_link ? ($index == 1 ? ' : ' : ' &rsaquo; ') : ($index == 0 ? ' ' : ' &rsaquo; ')).
 				($url ? '<a href="'.$url.'">' : '').$element.($url ? '</a>' : '');
@@ -326,4 +317,7 @@
 		}
 		$res .= '</h2>';
+		if ($echo) {
+			echo $res;
+		}
 		return $res;
 	}
@@ -611,4 +605,17 @@
 		self::jsVar('dotclear.msg.load_enhanced_uploader',
 			__('Loading enhanced uploader, please wait.')).
+
+		self::jsVar('dotclear.msg.module_author',
+			__('Author:')).
+		self::jsVar('dotclear.msg.module_details',
+			__('Details')).
+		self::jsVar('dotclear.msg.module_support',
+			__('Support')).
+		self::jsVar('dotclear.msg.module_help',
+			__('Help:')).
+		self::jsVar('dotclear.msg.module_section',
+			__('Section:')).
+		self::jsVar('dotclear.msg.module_tags',
+			__('Tags:')).
 			"\n//]]>\n".
 		"</script>\n";
Index: inc/admin/lib.moduleslist.php
===================================================================
--- inc/admin/lib.moduleslist.php	(revision 2171)
+++ inc/admin/lib.moduleslist.php	(revision 2171)
@@ -0,0 +1,866 @@
+<?php
+
+class adminModulesList
+{
+	public $core;
+	public $modules;
+
+	public static  $allow_multi_install;
+	public static $distributed_modules = array();
+
+	protected $list_id = 'unknow';
+
+	protected $path = false;
+	protected $path_writable = false;
+	protected $path_pattern = false;
+
+	protected $page_url = 'plugins.php';
+	protected $page_qs = '?';
+	protected $page_tab = '';
+
+	public static $nav_indexes = 'abcdefghijklmnopqrstuvwxyz0123456789';
+	protected $nav_list = array();
+	protected $nav_special = 'other';
+
+	protected $sort_field = 'sname';
+	protected $sort_asc = true;
+
+	public function __construct($core, $root, $allow_multi_install=false)
+	{
+		$this->core = $core;
+		self::$allow_multi_install = (boolean) $allow_multi_install;
+		$this->setPathInfo($root);
+		$this->setNavSpecial(__('other'));
+
+		$this->init();
+	}
+
+	protected function init()
+	{
+		return null;
+	}
+
+	public function newList($list_id)
+	{
+		$this->modules = array();
+		$this->page_tab = '';
+		$this->list_id = $list_id;
+
+		return $this;
+	}
+
+	protected function setPathInfo($root)
+	{
+		$paths = explode(PATH_SEPARATOR, $root);
+		$path = array_pop($paths);
+		unset($paths);
+
+		$this->path = $path;
+		if (is_dir($path) && is_writeable($path)) {
+			$this->path_writable = true;
+			$this->path_pattern = preg_quote($path,'!');
+		}
+
+		return $this;
+	}
+
+	public function getPath()
+	{
+		return $this->path;
+	}
+
+	public function isPathWritable()
+	{
+		return $this->path_writable;
+	}
+
+	public function isPathDeletable($root)
+	{
+		return $this->path_writable 
+			&& preg_match('!^'.$this->path_pattern.'!', $root) 
+			&& $this->core->auth->isSuperAdmin();
+	}
+
+	public function setPageURL($url)
+	{
+		$this->page_qs = strpos('?', $url) ? '&' : '?';
+		$this->page_url = $url;
+
+		return $this;
+	}
+
+	public function getPageURL($queries='', $with_tab=true)
+	{
+		return $this->page_url.
+			(!empty($queries) ? $this->page_qs : '').
+			(is_array($queries) ? http_build_query($queries) : $queries).
+			($with_tab && !empty($this->page_tab) ? '#'.$this->page_tab : '');
+	}
+
+	public function setPageTab($tab)
+	{
+		$this->page_tab = $tab;
+
+		return $this;
+	}
+
+	public function getPageTab()
+	{
+		return $this->page_tab;
+	}
+
+	public function getSearchQuery()
+	{
+		$query = !empty($_REQUEST['m_search']) ? trim($_REQUEST['m_search']) : null;
+		return strlen($query) > 1 ? $query : null;
+	}
+
+	public function displaySearchForm()
+	{
+		$query = $this->getSearchQuery();
+
+		if (empty($this->modules) && $query === null) {
+			return $this;
+		}
+
+		echo 
+		'<form action="'.$this->getPageURL().'" method="get" class="fieldset">'.
+		'<p><label for="m_search" class="classic">'.__('Search in repository:').'&nbsp;</label><br />'.
+		form::field(array('m_search','m_search'), 30, 255, html::escapeHTML($query)).
+		'<input type="submit" value="'.__('Search').'" /> ';
+		if ($query) { echo ' <a href="'.$this->getPageURL().'" class="button">'.__('Reset search').'</a>'; }
+		echo '</p>'.
+		'</form>';
+
+		if ($query) {
+			echo 
+			'<p class="message">'.sprintf(
+				__('Found %d result for search "%s":', 'Found %d results for search "%s":', count($this->modules)), 
+				count($this->modules), html::escapeHTML($query)
+				).
+			'</p>';
+		}
+		return $this;
+	}
+
+	public function setNavSpecial($str)
+	{
+		$this->nav_special = (string) $str;
+		$this->nav_list = array_merge(str_split(self::$nav_indexes), array($this->nav_special));
+
+		return $this;
+	}
+
+	public function getNavQuery()
+	{
+		return isset($_REQUEST['m_nav']) && in_array($_REQUEST['m_nav'], $this->nav_list) ? $_REQUEST['m_nav'] : $this->nav_list[0];
+	}
+
+	public function displayNavMenu()
+	{
+		if (empty($this->modules) || $this->getSearchQuery() !== null) {
+			return $this;
+		}
+
+		# Fetch modules required field
+		$indexes = array();
+		foreach ($this->modules as $id => $module) {
+			if (!isset($module[$this->sort_field])) {
+				continue;
+			}
+			$char = substr($module[$this->sort_field], 0, 1);
+			if (!in_array($char, $this->nav_list)) {
+				$char = $this->nav_special;
+			}
+			if (!isset($indexes[$char])) {
+				$indexes[$char] = 0;
+			}
+			$indexes[$char]++;
+		}
+
+		$buttons = array();
+		foreach($this->nav_list as $char) {
+			# Selected letter
+			if ($this->getNavQuery() == $char) {
+				$buttons[] = '<li class="active" title="'.__('current selection').'"><strong> '.$char.' </strong></li>';
+			}
+			# Letter having modules
+			elseif (!empty($indexes[$char])) {
+				$title = sprintf(__('%d module', '%d modules', $indexes[$char]), $indexes[$char]);
+				$buttons[] = '<li class="btn" title="'.$title.'"><a href="'.$this->getPageURL('m_nav='.$char).'" title="'.$title.'"> '.$char.' </a></li>';
+			}
+			# Letter without modules
+			else {
+				$buttons[] = '<li class="btn no-link" title="'.__('no module').'"> '.$char.' </li>';
+			}
+		}
+		# Parse navigation menu
+		echo '<div class="pager">'.__('Browse index:').' <ul>'.implode('',$buttons).'</ul></div>';
+
+		return $this;
+	}
+
+	public function setSortField($field, $asc=true)
+	{
+		$this->sort_field = $field;
+		$this->sort_asc = (boolean) $asc;
+
+		return $this;
+	}
+
+	public function getSortQuery()
+	{
+		return !empty($_REQUEST['m_sort']) ? $_REQUEST['m_sort'] : $this->sort_field;
+	}
+
+	public function displaySortForm()
+	{
+		//not yet implemented
+	}
+
+	public function displayMessage($action)
+	{
+		switch($action) {
+			case 'activate': 
+				$str = __('Module successfully activated.'); break;
+			case 'deactivate': 
+				$str = __('Module successfully deactivated.'); break;
+			case 'delete': 
+				$str = __('Module successfully deleted.'); break;
+			case 'install': 
+				$str = __('Module successfully installed.'); break;
+			case 'update': 
+				$str = __('Module successfully updated.'); break;
+			default:
+				$str = ''; break;
+		}
+		if (!empty($str)) {
+			dcPage::success($str);
+		}
+	}
+
+	public function setModules($modules)
+	{
+		$this->modules = array();
+		foreach($modules as $id => $module) {
+			$this->modules[$id] = self::setModuleInfo($id, $module);
+		}
+
+		return $this;
+	}
+
+	public function getModules()
+	{
+		return $this->modules;
+	}
+
+	public static function setModuleInfo($id, $module)
+	{
+		$label = empty($module['label']) ? $id : $module['label'];
+		$name = __(empty($module['name']) ? $label : $module['name']);
+		
+		return array_merge(
+			# Default values
+			array(
+				'desc' 				=> '',
+				'author' 			=> '',
+				'version' 			=> 0,
+				'current_version' 	=> 0,
+				'root' 				=> '',
+				'root_writable' 	=> false,
+				'permissions' 		=> null,
+				'parent' 			=> null,
+				'priority' 			=> 1000,
+				'standalone_config' => false,
+				'support' 			=> '',
+				'section' 			=> '',
+				'tags' 				=> '',
+				'details' 			=> '',
+				'sshot' 			=> ''
+			),
+			# Module's values
+			$module,
+			# Clean up values
+			array(
+				'id' 				=> $id,
+				'sid' 				=> self::sanitizeString($id),
+				'label' 			=> $label,
+				'name' 				=> $name,
+				'sname' 			=> self::sanitizeString($name)
+			)
+		);
+	}
+
+	public static function setDistributedModules($modules)
+	{
+		self::$distributed_modules = $modules;
+	}
+
+	public static function isDistributedModule($module)
+	{
+		$distributed_modules = self::$distributed_modules;
+
+		return is_array($distributed_modules) && in_array($module, $distributed_modules);
+	}
+
+	public static function sortModules($modules, $field, $asc=true)
+	{
+		$sorter = array();
+		foreach($modules as $id => $module) {
+			$sorter[$id] = isset($module[$field]) ? $module[$field] : $field;
+		}
+		array_multisort($sorter, $asc ? SORT_ASC : SORT_DESC, $modules);
+
+		return $modules;
+	}
+
+	public function displayModulesList($cols=array('name', 'config', 'version', 'desc'), $actions=array(), $nav_limit=false)
+	{
+		echo 
+		'<div class="table-outer">'.
+		'<table id="'.html::escapeHTML($this->list_id).'" class="modules'.(in_array('expander', $cols) ? ' expandable' : '').'">'.
+		'<caption class="hidden">'.html::escapeHTML(__('Modules list')).'</caption><tr>';
+
+		if (in_array('name', $cols)) {
+			echo 
+			'<th class="first nowrap"'.(in_array('icon', $cols) ? ' colspan="2"' : '').'>'.__('Name').'</th>';
+		}
+
+		if (in_array('version', $cols)) {
+			echo 
+			'<th class="nowrap count" scope="col">'.__('Version').'</th>';
+		}
+
+		if (in_array('current_version', $cols)) {
+			echo 
+			'<th class="nowrap count" scope="col">'.__('Current version').'</th>';
+		}
+
+		if (in_array('desc', $cols)) {
+			echo 
+			'<th class="nowrap" scope="col">'.__('Details').'</th>';
+		}
+
+		if (in_array('distrib', $cols)) {
+			echo '<th'.(in_array('desc', $cols) ? '' : ' class="maximal"').'></th>';
+		}
+
+		if (!empty($actions) && $this->core->auth->isSuperAdmin()) {
+			echo 
+			'<th class="minimal nowrap">'.__('Action').'</th>';
+		}
+
+		echo 
+		'</tr>';
+
+		$sort_field = $this->getSortQuery();
+
+		# Sort modules by id
+		$modules = $this->getSearchQuery() === null ?
+			self::sortModules($this->modules, $sort_field, $this->sort_asc) :
+			$this->modules;
+
+		$count = 0;
+		foreach ($modules as $id => $module)
+		{
+			# Show only requested modules
+			if ($nav_limit && $this->getSearchQuery() === null) {
+				$char = substr($module[$sort_field], 0, 1);
+				if (!in_array($char, $this->nav_list)) {
+					$char = $this->nav_special;
+				}
+				if ($this->getNavQuery() != $char) {
+					continue;
+				}
+			}
+
+			echo 
+			'<tr class="line" id="'.html::escapeHTML($this->list_id).'_m_'.html::escapeHTML($id).'">';
+
+			if (in_array('icon', $cols)) {
+				echo 
+				'<td class="module-icon nowrap">'.sprintf(
+					'<img alt="%1$s" title="%1$s" src="%2$s" />', 
+					html::escapeHTML($id), file_exists($module['root'].'/icon.png') ? 'index.php?pf='.$id.'/icon.png' : 'images/module.png'
+				).'</td>';
+			}
+
+			# Link to config file
+			$config = in_array('config', $cols) && !empty($module['root']) && file_exists(path::real($module['root'].'/_config.php'));
+
+			echo 
+			'<td class="module-name nowrap" scope="row">'.($config ? 
+				'<a href="'.$this->getPageURL('module='.$id.'&conf=1').'" title"'.sprintf(__('Configure module "%s"'), html::escapeHTML($module['name'])).'">'.html::escapeHTML($module['name']).'</a>' : 
+				html::escapeHTML($module['name'])
+			).'</td>';
+
+			if (in_array('version', $cols)) {
+				echo 
+				'<td class="module-version nowrap count">'.html::escapeHTML($module['version']).'</td>';
+			}
+
+			if (in_array('current_version', $cols)) {
+				echo 
+				'<td class="module-current-version nowrap count">'.html::escapeHTML($module['current_version']).'</td>';
+			}
+
+			if (in_array('desc', $cols)) {
+				echo 
+				'<td class="module-desc maximal">'.html::escapeHTML($module['desc']).'</td>';
+			}
+
+			if (in_array('distrib', $cols)) {
+				echo 
+				'<td class="module-distrib">'.(self::isDistributedModule($id) ? 
+					'<img src="images/dotclear_pw.png" alt="'.
+					__('Module from official distribution').'" title="'.
+					__('module from official distribution').'" />' 
+				: '').'</td>';
+			}
+
+			if (!empty($actions) && $this->core->auth->isSuperAdmin()) {
+				echo 
+				'<td class="module-actions nowrap">';
+
+				$this->displayLineActions($id, $module, $actions);
+
+				echo
+				'</td>';
+			}
+
+			echo 
+			'</tr>';
+
+			$count++;
+		}
+		echo 
+		'</table></div>';
+
+		if(!$count) {
+			echo 
+			'<p class="message">'.__('No module matches your search.').'</p>';
+		}
+	}
+
+	protected function displayLineActions($id, $module, $actions, $echo=true)
+	{
+		$submits = array();
+
+		# Activate
+		if (in_array('deactivate', $actions) && $module['root_writable']) {
+			$submits[] = '<input type="submit" name="deactivate" value="'.__('Deactivate').'" />';
+		}
+
+		# Deactivate
+		if (in_array('activate', $actions) && $module['root_writable']) {
+			$submits[] = '<input type="submit" name="activate" value="'.__('Activate').'" />';
+		}
+
+		# Delete
+		if (in_array('delete', $actions) && $this->isPathDeletable($module['root'])) {
+			$submits[] = '<input type="submit" class="delete" name="delete" value="'.__('Delete').'" />';
+		}
+
+		# Install (form repository)
+		if (in_array('install', $actions) && $this->path_writable) {
+			$submits[] = '<input type="submit" name="install" value="'.__('Install').'" />';
+		}
+
+		# Update (from repository)
+		if (in_array('update', $actions) && $this->path_writable) {
+			$submits[] = '<input type="submit" name="update" value="'.__('Update').'" />';
+		}
+
+		# Parse form
+		if (!empty($submits)) {
+			$res = 
+			'<form action="'.$this->getPageURL().'" method="post">'.
+			'<div>'.
+			$this->core->formNonce().
+			form::hidden(array('module'), html::escapeHTML($id)).
+			form::hidden(array('tab'), $this->page_tab).
+			implode(' ', $submits).
+			'</div>'.
+			'</form>';
+
+			if (!$echo) {
+				return $res;
+			}
+			echo $res;
+		}
+	}
+
+	public function executeAction($prefix, dcModules $modules, dcRepository $repository)
+	{
+		if (!$this->core->auth->isSuperAdmin() || !$this->isPathWritable()) {
+			return null;
+		}
+
+		# List actions
+		if (!empty($_POST['module'])) {
+
+			$id = $_POST['module'];
+
+			if (!empty($_POST['activate'])) {
+
+				$enabled = $modules->getDisabledModules();
+				if (!isset($enabled[$id])) {
+					throw new Exception(__('No such module.'));
+				}
+
+				# --BEHAVIOR-- moduleBeforeActivate
+				$this->core->callBehavior($type.'BeforeActivate', $id);
+
+				$modules->activateModule($id);
+
+				# --BEHAVIOR-- moduleAfterActivate
+				$this->core->callBehavior($type.'AfterActivate', $id);
+
+				http::redirect($this->getPageURL('msg=activate'));
+			}
+
+			if (!empty($_POST['deactivate'])) {
+
+				if (!$modules->moduleExists($id)) {
+					throw new Exception(__('No such module.'));
+				}
+
+				$module = $modules->getModules($id);
+				$module['id'] = $id;
+
+				if (!$module['root_writable']) {
+					throw new Exception(__('You don\'t have permissions to deactivate this module.'));
+				}
+
+				# --BEHAVIOR-- moduleBeforeDeactivate
+				$this->core->callBehavior($prefix.'BeforeDeactivate', $module);
+
+				$modules->deactivateModule($id);
+
+				# --BEHAVIOR-- moduleAfterDeactivate
+				$this->core->callBehavior($prefix.'AfterDeactivate', $module);
+
+				http::redirect($this->getPageURL('msg=deactivate'));
+			}
+
+			if (!empty($_POST['delete'])) {
+
+				$disabled = $modules->getDisabledModules();
+				if (!isset($disabled[$id])) {
+
+					if (!$modules->moduleExists($id)) {
+						throw new Exception(__('No such module.'));
+					}
+
+					$module = $modules->getModules($id);
+					$module['id'] = $id;
+
+					if (!$this->isPathDeletable($module['root'])) {
+						throw new Exception(__("You don't have permissions to delete this module."));
+					}
+
+					# --BEHAVIOR-- moduleBeforeDelete
+					$this->core->callBehavior($prefix.'BeforeDelete', $module);
+
+					$modules->deleteModule($id);
+
+					# --BEHAVIOR-- moduleAfterDelete
+					$this->core->callBehavior($prefix.'AfterDelete', $module);
+				}
+				else {
+					$modules->deleteModule($id, true);
+				}
+
+				http::redirect($this->getPageURL('msg=delete'));
+			}
+
+			if (!empty($_POST['update'])) {
+
+				$updated = $repository->get();
+				if (!isset($updated[$id])) {
+					throw new Exception(__('No such module.'));
+				}
+
+				if (!$modules->moduleExists($id)) {
+					throw new Exception(__('No such module.'));
+				}
+
+				$module = $updated[$id];
+				$module['id'] = $id;
+			
+				if (!self::$allow_multi_install) {
+					$dest = $module['root'].'/../'.basename($module['file']);
+				}
+				else {
+					$dest = $this->getPath().'/'.basename($module['file']);
+					if ($module['root'] != $dest) {
+						@file_put_contents($module['root'].'/_disabled', '');
+					}
+				}
+
+				# --BEHAVIOR-- moduleBeforeUpdate
+				$this->core->callBehavior($type.'BeforeUpdate', $module);
+
+				$repository->process($module['file'], $dest);
+
+				# --BEHAVIOR-- moduleAfterUpdate
+				$this->core->callBehavior($type.'AfterUpdate', $module);
+
+				http::redirect($this->getPageURL('msg=upadte'));
+			}
+
+			if (!empty($_POST['install'])) {
+
+				$updated = $repository->get();
+				if (!isset($updated[$id])) {
+					throw new Exception(__('No such module.'));
+				}
+
+				$module = $updated[$id];
+				$module['id'] = $id;
+
+				$dest = $this->getPath().'/'.basename($module['file']);
+
+				# --BEHAVIOR-- moduleBeforeAdd
+				$this->core->callBehavior($type.'BeforeAdd', $module);
+
+				$ret_code = $repository->process($module['file'], $dest);
+
+				# --BEHAVIOR-- moduleAfterAdd
+				$this->core->callBehavior($type.'AfterAdd', $module);
+
+				http::redirect($this->getPageURL('msg='.($ret_code == 2 ? 'update' : 'install')));
+			}
+		}
+		# Manual actions
+		elseif (!empty($_POST['upload_pkg']) && !empty($_FILES['pkg_file']) 
+			|| !empty($_POST['fetch_pkg']) && !empty($_POST['pkg_url']))
+		{
+			if (empty($_POST['your_pwd']) || !$this->core->auth->checkPassword(crypt::hmac(DC_MASTER_KEY, $_POST['your_pwd']))) {
+				throw new Exception(__('Password verification failed'));
+			}
+
+			if (!empty($_POST['upload_pkg'])) {
+				files::uploadStatus($_FILES['pkg_file']);
+				
+				$dest = $this->getPath().'/'.$_FILES['pkg_file']['name'];
+				if (!move_uploaded_file($_FILES['pkg_file']['tmp_name'], $dest)) {
+					throw new Exception(__('Unable to move uploaded file.'));
+				}
+			}
+			else {
+				$url = urldecode($_POST['pkg_url']);
+				$dest = $this->getPath().'/'.basename($url);
+				$repository->download($url, $dest);
+			}
+
+			# --BEHAVIOR-- moduleBeforeAdd
+			$this->core->callBehavior($prefix.'BeforeAdd', null);
+
+			$ret_code = $repository->install($dest);
+
+			# --BEHAVIOR-- moduleAfterAdd
+			$this->core->callBehavior($prefix.'AfterAdd', null);
+
+			http::redirect($this->getPageURL('msg='.($ret_code == 2 ? 'update' : 'install')).'#'.$prefix);
+		}
+		return null;
+	}
+
+	public function displayManualForm()
+	{
+		if (!$this->core->auth->isSuperAdmin() || !$this->isPathWritable()) {
+			return null;
+		}
+
+		# 'Upload module' form
+		echo
+		'<form method="post" action="'.$this->getPageURL().'" id="uploadpkg" enctype="multipart/form-data" class="fieldset">'.
+		'<h4>'.__('Upload a zip file').'</h4>'.
+		'<p class="field"><label for="pkg_file" class="classic required"><abbr title="'.__('Required field').'">*</abbr> '.__('Zip file path:').'</label> '.
+		'<input type="file" name="pkg_file" id="pkg_file" /></p>'.
+		'<p class="field"><label for="your_pwd1" class="classic required"><abbr title="'.__('Required field').'">*</abbr> '.__('Your password:').'</label> '.
+		form::password(array('your_pwd','your_pwd1'),20,255).'</p>'.
+		'<p><input type="submit" name="upload_pkg" value="'.__('Upload').'" />'.
+		form::hidden(array('tab'), $this->getPageTab()).
+		$this->core->formNonce().'</p>'.
+		'</form>';
+		
+		# 'Fetch module' form
+		echo
+		'<form method="post" action="'.$this->getPageURL().'" id="fetchpkg" class="fieldset">'.
+		'<h4>'.__('Download a zip file').'</h4>'.
+		'<p class="field"><label for="pkg_url" class="classic required"><abbr title="'.__('Required field').'">*</abbr> '.__('Zip file URL:').'</label> '.
+		form::field(array('pkg_url','pkg_url'),40,255).'</p>'.
+		'<p class="field"><label for="your_pwd2" class="classic required"><abbr title="'.__('Required field').'">*</abbr> '.__('Your password:').'</label> '.
+		form::password(array('your_pwd','your_pwd2'),20,255).'</p>'.
+		'<p><input type="submit" name="fetch_pkg" value="'.__('Download').'" />'.
+		form::hidden(array('tab'), $this->getPageTab()).
+		$this->core->formNonce().'</p>'.
+		'</form>';
+	}
+
+	public static function sanitizeString($str)
+	{
+		return preg_replace('/[^A-Za-z0-9\@\#+_-]/', '', strtolower($str));
+	}
+}
+
+class adminThemesList extends adminModulesList
+{
+	protected $page_url = 'blog_theme.php';
+
+	public function displayModulesList($cols=array('name', 'config', 'version', 'desc'), $actions=array(), $nav_limit=false)
+	{
+		echo 
+		'<div id="'.html::escapeHTML($this->list_id).'" class="modules'.(in_array('expander', $cols) ? ' expandable' : '').' one-box">';
+
+		$sort_field = $this->getSortQuery();
+
+		# Sort modules by id
+		$modules = $this->getSearchQuery() === null ?
+			self::sortModules($this->modules, $sort_field, $this->sort_asc) :
+			$this->modules;
+
+		$res = '';
+		$count = 0;
+		foreach ($modules as $id => $module)
+		{
+			# Show only requested modules
+			if ($nav_limit && $this->getSearchQuery() === null) {
+				$char = substr($module[$sort_field], 0, 1);
+				if (!in_array($char, $this->nav_list)) {
+					$char = $this->nav_special;
+				}
+				if ($this->getNavQuery() != $char) {
+					continue;
+				}
+			}
+
+			$current = $this->core->blog->settings->system->theme == $id;
+
+			if (preg_match('#^http(s)?://#', $this->core->blog->settings->system->themes_url)) {
+				$theme_url = http::concatURL($this->core->blog->settings->system->themes_url, '/'.$id);
+			} else {
+				$theme_url = http::concatURL($this->core->blog->url, $this->core->blog->settings->system->themes_url.'/'.$id);
+			}
+
+			$has_conf = file_exists(path::real($this->core->blog->themes_path.'/'.$id).'/_config.php');
+			$has_css = file_exists(path::real($this->core->blog->themes_path.'/'.$id).'/style.css');
+			$parent = $module['parent'];
+			$has_parent = !empty($module['parent']);
+			if ($has_parent) {
+				$is_parent_present = $this->core->themes->moduleExists($parent);
+			}
+
+			$line = 
+			'<div class="box '.($current ? 'current-theme' : 'theme').'">';
+
+			if (in_array('sshot', $cols)) {
+				# Screenshot from url
+				if (preg_match('#^http(s)?://#', $module['sshot'])) {
+					$sshot = $module['sshot'];
+				}
+				# Screenshot from installed module
+				elseif (file_exists($this->core->blog->themes_path.'/'.$id.'/screenshot.jpg')) {
+					$sshot = $this->getPageURL('shot='.rawurlencode($id));
+				}
+				# Default screenshot
+				else {
+					$sshot = 'images/noscreenshot.png';
+				}
+
+				$line .= 
+				'<div class="module-sshot"><img src="'.$sshot.'" alt="'.__('screenshot.').'" /></div>';
+			}
+
+			if (in_array('name', $cols)) {
+				$line .= 
+				'<h4 class="module-name">'.html::escapeHTML($module['name']).'</h4>';
+			}
+
+			$line .= 
+			'<div class="module-infos">'.
+			'<p>';
+
+			if (in_array('desc', $cols)) {
+				$line .= 
+				'<span class="module-desc">'.html::escapeHTML($module['desc']).'</span> ';
+			}
+
+			if (in_array('author', $cols)) {
+				$line .= 
+				'<span class="module-author">'.sprintf(__('by %s'),html::escapeHTML($module['author'])).'</span> ';
+			}
+
+			if (in_array('version', $cols)) {
+				$line .= 
+				'<span class="module-version">'.sprintf(__('version %s'),html::escapeHTML($module['version'])).'</span> ';
+			}
+
+			if (in_array('parent', $cols) && $has_parent) {
+				if ($is_parent_present) {
+					$line .= 
+					'<span class="module-parent-ok">'.sprintf(__('(built on "%s")'),html::escapeHTML($parent)).'</span> ';
+				}
+				else {
+					$line .= 
+					'<span class="module-parent-missing">'.sprintf(__('(requires "%s")'),html::escapeHTML($parent)).'</span> ';
+				}
+			}
+
+			$line .= 
+			'</p>'.
+			'</div>';
+
+			$line .= 
+			'<div class="modules-actions">';
+			
+			# _GET actions
+			$line .= 
+			'<p>';
+
+			if ($current && $has_css) {
+				$line .= 
+				'<a href="'.$theme_url.'/style.css" class="button">'.__('View stylesheet').'</a> ';
+			}
+			if ($current && $has_conf) {
+				$line .= 
+				'<a href="'.$this->getPageURL('conf=1').'" class="button">'.__('Configure theme').'</a> ';
+			}
+			$line .= 
+			'</p>';
+
+			# Plugins actions
+			if ($current) {
+				# --BEHAVIOR-- adminCurrentThemeDetails
+				$line .= 
+				$this->core->callBehavior('adminCurrentThemeDetails', $this->core, $id, $module);
+			}
+
+			# _POST actions
+			if (!empty($actions) && $this->core->auth->isSuperAdmin()) {
+				$line .=
+				$this->displayLineActions($id, $module, $actions, false);
+			}
+
+			$line .= 
+			'</div>';
+
+			$line .=
+			'</div>';
+
+			$count++;
+
+			$res = $current ? $line.$res : $res.$line;
+		}
+		echo 
+		$res.
+		'</div>';
+
+		if(!$count) {
+			echo 
+			'<p class="message">'.__('No module matches your search.').'</p>';
+		}
+	}
+}
Index: inc/core/class.dc.repository.parser.php
===================================================================
--- inc/core/class.dc.repository.parser.php	(revision 2146)
+++ inc/core/class.dc.repository.parser.php	(revision 2146)
@@ -0,0 +1,91 @@
+<?php
+# -- BEGIN LICENSE BLOCK ---------------------------------------
+#
+# This file is part of Dotclear 2.
+#
+# Copyright (c) 2003-2013 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 Rpeository modules feed parser
+
+Provides an object to parse feed of modules from repository.
+*/
+class dcRepositoryParser
+{
+	protected $xml;
+	protected $items;
+	protected static $bloc = 'http://dotaddict.org/da/';
+
+	public function __construct($data)
+	{
+		if (!is_string($data)) {
+			throw new Exception(__('Failed to read data feed'));
+		}
+
+		$this->xml = simplexml_load_string($data);
+		$this->items = array();
+
+		if ($this->xml === false) {
+			throw new Exception(__('Wrong data feed'));
+		}
+
+		$this->_parse();
+
+		unset($data);
+		unset($this->xml);
+	}
+
+	protected function _parse()
+	{
+		if (empty($this->xml->module)) {
+			return;
+		}
+
+		foreach ($this->xml->module as $i)
+		{
+			$attrs = $i->attributes();
+
+			$item = array();
+
+			# DC/DA shared markers
+			$item['id']		= (string) $attrs['id'];
+			$item['file']		= (string) $i->file;
+			$item['label']		= (string) $i->name; // deprecated
+			$item['name']		= (string) $i->name;
+			$item['version']	= (string) $i->version;
+			$item['author']	= (string) $i->author;
+			$item['desc']		= (string) $i->desc;
+
+			# DA specific markers
+			$item['dc_min'] 	= (string) $i->children(self::$bloc)->dcmin;
+			$item['details'] 	= (string) $i->children(self::$bloc)->details;
+			$item['section'] 	= (string) $i->children(self::$bloc)->section;
+			$item['support'] 	= (string) $i->children(self::$bloc)->support;
+			$item['sshot']		= (string) $i->children(self::$bloc)->sshot;
+			
+			$tags = array();
+			foreach($i->children(self::$bloc)->tags as $t)
+			{
+				$tags[] = (string) $t->tag;
+			}
+			$item['tags']		= implode(', ',$tags);
+			
+			# First filter right now
+			if (defined('DC_DEV') && DC_DEV === true || version_compare(DC_VERSION,$item['dc_min'],'>=')) {
+				$this->items[$item['id']] = $item;
+			}
+		}
+	}
+
+	public function getModules()
+	{
+		return $this->items;
+	}
+}
Index: inc/core/class.dc.repository.php
===================================================================
--- inc/core/class.dc.repository.php	(revision 2156)
+++ inc/core/class.dc.repository.php	(revision 2156)
@@ -0,0 +1,156 @@
+<?php
+
+class dcRepository
+{
+	public $core;
+	public $modules;
+
+	protected $xml_url;
+	protected $data;
+
+	public function __construct(dcModules $modules, $xml_url)
+	{
+		$this->core = $modules->core;
+		$this->modules = $modules;
+		$this->xml_url = $xml_url;
+	}
+
+	public function check($force=false)
+	{
+		if (!$this->xml_url) {
+			return false;
+		}
+		if (($parser = dcRepositoryReader::quickParse($this->xml_url, DC_TPL_CACHE, $force)) === false) {
+			return false;
+		}
+
+		$raw_datas = $parser->getModules();
+
+		uasort($raw_datas, array('self','sort'));
+
+		$skipped = array_keys($this->modules->getDisabledModules());
+		foreach ($skipped as $p_id) {
+			if (isset($raw_datas[$p_id])) {
+				unset($raw_datas[$p_id]);
+			}
+		}
+
+		$updates = array();
+		$current = $this->modules->getModules();
+		foreach ($current as $p_id => $p_infos) {
+			if (isset($raw_datas[$p_id])) {
+				if (self::compare($raw_datas[$p_id]['version'],$p_infos['version'],'>')) {
+					$updates[$p_id] = $raw_datas[$p_id];
+					$updates[$p_id]['root'] = $p_infos['root'];
+					$updates[$p_id]['root_writable'] = $p_infos['root_writable'];
+					$updates[$p_id]['current_version'] = $p_infos['version'];
+				}
+				unset($raw_datas[$p_id]);
+			}
+		}
+
+		$this->data = array(
+			'new'	=> $raw_datas,
+			'update'	=> $updates
+		);
+
+		return true;
+	}
+
+	public function get($update=false)
+	{
+		return $this->data[$update ? 'update' : 'new'];
+	}
+
+	public function search($pattern)
+	{
+		$result = array();
+
+		# Split query into small clean words
+		$patterns = explode(' ', $pattern);
+		array_walk($patterns, array('dcRepository','sanitize'));
+
+		# For each modules
+		foreach ($this->data['new'] as $id => $module) {
+
+			# Split modules infos into small clean word
+			$subjects = explode(' ', $id.' '.$module['name'].' '.$module['desc']);
+			array_walk($subjects, array('dcRepository','sanitize'));
+
+			# Check contents
+			if (!($nb = preg_match_all('/('.implode('|', $patterns).')/', implode(' ', $subjects), $_))) {
+				continue;
+			}
+
+			# Add module to result
+			if (!isset($sorter[$id])) {
+				$sorter[$id] = 0;
+				$result[$id] = $module;
+			}
+
+			# Increment matches count
+			$sorter[$id] += $nb;
+			$result[$id]['accuracy'] = $sorter[$id];
+		}
+		# Sort response by matches count
+		if (!empty($result)) {
+			array_multisort($sorter, SORT_DESC, $result);
+		}
+		return $result;
+	}
+
+	public function process($url, $dest)
+	{
+		$this->download($url, $dest);
+		return $this->install($dest);
+	}
+
+	public function download($url, $dest)
+	{
+		try {
+			$client = netHttp::initClient($url, $path);
+			$client->setUserAgent(self::agent());
+			$client->useGzip(false);
+			$client->setPersistReferers(false);
+			$client->setOutput($dest);
+			$client->get($path);
+			unset($client);
+		}
+		catch (Exception $e) {
+			unset($client);
+			throw new Exception(__('An error occurred while downloading the file.'));
+		}
+	}
+
+	public function install($path)
+	{
+		return dcModules::installPackage($path, $this->modules);
+	}
+
+	public static function agent()
+	{
+		return sprintf('Dotclear/%s)', DC_VERSION);
+	}
+
+	public static function sanitize(&$str, $_)
+	{
+		$str = strtolower(preg_replace('/[^A-Za-z0-9]/', '', $str));
+	}
+
+	private static function compare($v1,$v2,$op)
+	{
+		$v1 = preg_replace('!-r(\d+)$!','-p$1',$v1);
+		$v2 = preg_replace('!-r(\d+)$!','-p$1',$v2);
+		return version_compare($v1,$v2,$op);
+	}
+
+	private static function sort($a,$b)
+	{
+		$c = strtolower($a['id']); 
+		$d = strtolower($b['id']); 
+		if ($c == $d) { 
+			return 0; 
+		} 
+		return ($c < $d) ? -1 : 1; 
+	}
+}
Index: inc/core/class.dc.repository.reader.php
===================================================================
--- inc/core/class.dc.repository.reader.php	(revision 2146)
+++ inc/core/class.dc.repository.reader.php	(revision 2146)
@@ -0,0 +1,209 @@
+<?php
+# -- BEGIN LICENSE BLOCK ---------------------------------------
+#
+# This file is part of Dotclear 2.
+#
+# Copyright (c) 2003-2013 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 Repository modules feed reader
+
+Provides an object to parse feed of modules from repository.
+*/
+class dcRepositoryReader extends netHttp
+{
+	protected $user_agent 		= 'DotClear.org RepoBrowser/0.1';
+	protected $timeout 			= 5;
+	protected $validators 		= null;				///< <b>array</b>	HTTP Cache validators
+	protected $cache_dir 		= null;				///< <b>string</b>	Cache temporary directory
+	protected $cache_file_prefix 	= 'dcrepo';			///< <b>string</b>	Cache file prefix
+	protected $cache_ttl 		= '-30 minutes';		///< <b>string</b>	Cache TTL
+	protected $cache_touch_on_fail = true;
+	protected $force			= false;
+
+	public function __construct()
+	{
+		parent::__construct('');
+		$this->setUserAgent(sprintf('Dotclear/%s)', DC_VERSION));
+	}
+
+	public function parse($url)
+	{
+		$this->validators = array();
+		if ($this->cache_dir)
+		{
+			return $this->withCache($url);
+		}
+		else
+		{
+			if (!$this->getModulesXML($url)) {
+				return false;
+			}
+
+			if ($this->getStatus() != '200') {
+				return false;
+			}
+
+			return new dcRepositoryParser($this->getContent());
+		}
+	}
+
+	public static function quickParse($url, $cache_dir=null, $force=false)
+	{
+		$parser = new self();
+		if ($cache_dir) {
+			$parser->setCacheDir($cache_dir);
+		}
+		if ($force) {
+			$parser->setForce($force);
+		}
+
+		return $parser->parse($url);
+	}
+
+	public function setCacheDir($dir)
+	{
+		$this->cache_dir = null;
+
+		if (!empty($dir) && is_dir($dir) && is_writeable($dir))
+		{
+			$this->cache_dir = $dir;
+			return true;
+		}
+
+		return false;
+	}
+
+	public function setCacheTTL($str)
+	{
+		$str = trim($str);
+		if (!empty($str))
+		{
+			if (substr($str, 0, 1) != '-') {
+				$str = '-'.$str;
+			}
+			$this->cache_ttl = $str;
+		}
+	}
+
+	public function setForce($force)
+	{
+		$this->force = $force;
+	}
+
+	protected function getModulesXML($url)
+	{
+		if (!self::readURL($url, $ssl, $host, $port, $path, $user, $pass)) {
+			return false;
+		}
+		$this->setHost($host, $port);
+		$this->useSSL($ssl);
+		$this->setAuthorization($user, $pass);
+
+		return $this->get($path);
+	}
+
+	protected function withCache($url)
+	{
+		$url_md5 = md5($url);
+		$cached_file = sprintf('%s/%s/%s/%s/%s.ser',
+			$this->cache_dir,
+			$this->cache_file_prefix,
+			substr($url_md5,0,2),
+			substr($url_md5,2,2),
+			$url_md5
+		);
+
+		$may_use_cached = false;
+
+		if (@file_exists($cached_file) && !$this->force)
+		{
+			$may_use_cached = true;
+			$ts = @filemtime($cached_file);
+			if ($ts > strtotime($this->cache_ttl))
+			{
+				# Direct cache
+				return unserialize(file_get_contents($cached_file));
+			}
+			$this->setValidator('IfModifiedSince', $ts);
+		}
+
+		if (!$this->getModulesXML($url))
+		{
+			if ($may_use_cached)
+			{
+				if ($this->cache_touch_on_fail) {
+					@files::touch($cached_file);
+				}
+				# connection failed - fetched from cache
+				return unserialize(file_get_contents($cached_file));
+			}
+			return false;
+		}
+
+		switch ($this->getStatus())
+		{
+			case '304':
+				@files::touch($cached_file);
+				return unserialize(file_get_contents($cached_file));
+			case '200':
+				if ($modules = new dcRepositoryParser($this->getContent()))
+				{
+					try {
+						files::makeDir(dirname($cached_file), true);
+					} catch (Exception $e) {
+						return $modules;
+					}
+
+					if (($fp = @fopen($cached_file, 'wb')))
+					{
+						fwrite($fp, serialize($modules));
+						fclose($fp);
+						files::inheritChmod($cached_file);
+					}
+					return $modules;
+				}
+		}
+
+		return false;
+	}
+
+	protected function buildRequest()
+	{
+		$headers = parent::buildRequest();
+
+		# Cache validators
+		if (!empty($this->validators))
+		{
+			if (isset($this->validators['IfModifiedSince'])) {
+				$headers[] = 'If-Modified-Since: '.$this->validators['IfModifiedSince'];
+			}
+			if (isset($this->validators['IfNoneMatch'])) {
+				if (is_array($this->validators['IfNoneMatch'])) {
+					$etags = implode(',', $this->validators['IfNoneMatch']);
+				} else {
+					$etags = $this->validators['IfNoneMatch'];
+				}
+				$headers[] = '';
+			}
+		}
+
+		return $headers;
+	}
+
+	private function setValidator($key, $value)
+	{
+		if ($key == 'IfModifiedSince') {
+			$value = gmdate('D, d M Y H:i:s', $value).' GMT';
+		}
+
+		$this->validators[$key] = $value;
+	}
+}
Index: inc/prepend.php
===================================================================
--- inc/prepend.php	(revision 1999)
+++ inc/prepend.php	(revision 2147)
@@ -46,4 +46,7 @@
 $__autoload['dcWorkspace']			= dirname(__FILE__).'/core/class.dc.workspace.php';
 $__autoload['dcPrefs']				= dirname(__FILE__).'/core/class.dc.prefs.php';
+$__autoload['dcRepository']			= dirname(__FILE__).'/core/class.dc.repository.php';
+$__autoload['dcRepositoryReader']		= dirname(__FILE__).'/core/class.dc.repository.reader.php';
+$__autoload['dcRepositoryParser']		= dirname(__FILE__).'/core/class.dc.repository.parser.php';
 
 $__autoload['rsExtPost']				= dirname(__FILE__).'/core/class.dc.rs.extensions.php';
@@ -61,4 +64,6 @@
 $__autoload['dcPager']		= dirname(__FILE__).'/admin/lib.pager.php';
 $__autoload['dcAdminCombos']			= dirname(__FILE__).'/admin/lib.admincombos.php';
+$__autoload['adminModulesList']			= dirname(__FILE__).'/admin/lib.moduleslist.php';
+$__autoload['adminThemesList']			= dirname(__FILE__).'/admin/lib.moduleslist.php';
 
 $__autoload['dcTemplate']			= dirname(__FILE__).'/public/class.dc.template.php';
