[pLog-svn] r5814 - in plog/trunk: class/action/admin class/controller class/template class/template/editor class/view/admin js/ui js/ui/pages locale/admin templates/admin

oscar at devel.lifetype.net oscar at devel.lifetype.net
Wed Aug 8 16:48:12 EDT 2007


Author: oscar
Date: 2007-08-08 16:48:12 -0400 (Wed, 08 Aug 2007)
New Revision: 5814

Added:
   plog/trunk/class/action/admin/admindeletetemplatefileaction.class.php
   plog/trunk/class/action/admin/adminedittemplateaction.class.php
   plog/trunk/class/action/admin/adminedittemplatefileaction.class.php
   plog/trunk/class/action/admin/adminupdatetemplatefileaction.class.php
   plog/trunk/class/template/editor/
   plog/trunk/class/template/editor/templatetools.class.php
   plog/trunk/class/view/admin/adminedittemplatefileview.class.php
   plog/trunk/class/view/admin/adminedittemplateview.class.php
   plog/trunk/js/ui/pages/templateeditor.js
   plog/trunk/templates/admin/edittemplate.template
   plog/trunk/templates/admin/edittemplate_table.template
   plog/trunk/templates/admin/edittemplatefile.template
Modified:
   plog/trunk/class/controller/admincontrollermap.properties.php
   plog/trunk/class/view/admin/adminsitetemplateslistview.class.php
   plog/trunk/js/ui/ui.js
   plog/trunk/locale/admin/locale_en_UK.php
   plog/trunk/templates/admin/blogtemplates.template
   plog/trunk/templates/admin/globalsettings_templates.template
   plog/trunk/templates/admin/jslocale.template
   plog/trunk/templates/admin/newlinkcategory.template
   plog/trunk/templates/admin/siteblogs_table.template
   plog/trunk/templates/admin/sitetemplates.template
Log:
Added a preliminary version of a template editor, which already allows basic functionality to edit global templates. It is based on ajax with no page refreshes when deleting files or browsing through folders, etc. 

This is written from scratch and it is not based on the current version of the templateeditor, as I found that the code in the current plugin was unsecure and in general not up to par with what we should deliver.


Added: plog/trunk/class/action/admin/admindeletetemplatefileaction.class.php
===================================================================
--- plog/trunk/class/action/admin/admindeletetemplatefileaction.class.php	                        (rev 0)
+++ plog/trunk/class/action/admin/admindeletetemplatefileaction.class.php	2007-08-08 20:48:12 UTC (rev 5814)
@@ -0,0 +1,100 @@
+<?php
+
+	lt_include( PLOG_CLASS_PATH."class/action/admin/adminaction.class.php" );
+	lt_include( PLOG_CLASS_PATH."class/data/validator/templatenamevalidator.class.php" );	
+	lt_include( PLOG_CLASS_PATH."class/data/validator/stringvalidator.class.php" );		
+	lt_include( PLOG_CLASS_PATH."class/data/filter/regexpfilter.class.php" );		
+	lt_include( PLOG_CLASS_PATH."class/template/templatesets/templatesets.class.php" );
+	lt_include( PLOG_CLASS_PATH."class/template/editor/templatetools.class.php" );	
+	lt_include( PLOG_CLASS_PATH."class/view/admin/adminsitetemplateslistview.class.php" );
+	lt_include( PLOG_CLASS_PATH."class/view/admin/adminedittemplateview.class.php" );	
+	lt_include( PLOG_CLASS_PATH."class/view/admin/adminerrordialogview.class.php" );	
+	lt_include( PLOG_CLASS_PATH."class/file/file.class.php" );
+	
+	class AdminDeleteTemplateFileAction extends AdminAction
+	{
+		
+		function __construct( $actionInfo, $request )
+		{
+			$this->AdminAction( $actionInfo, $request );
+			$this->registerFieldValidator( "templateId", new TemplateNameValidator(), false);
+			$this->registerFieldValidator( "path", new StringValidator(), true );
+			$this->registerFieldValidator( "file", new StringValidator(), false );			
+			$view = new AdminErrorDialogView( $this->_blogInfo, $this->_locale->tr( "error_deleting_template_file" ));
+			$this->setValidationErrorView( $view );
+
+			$this->requirePermission( "edit_site_template" );
+		}
+
+		function validate()
+		{
+			if( !parent::validate()) 
+				return false;
+
+			// check that the template really exists
+			$this->_templateId = $this->_request->getFilteredValue( "templateId", new RegexpFilter( "/[^A-Za-z0-9_]/" ));
+			if( !TemplateSets::isTemplate( $this->_templateId )) {
+				$this->_form->setFieldValidationStatus( "templateId", false );
+				$this->validationErrorProcessing();
+				return( false );
+			}
+
+			// if the template exists, check that the path exists too
+			$this->_path = $this->_request->getFilteredValue( "path", new RegexpFilter( "/[^A-Za-z0-9_\/\-]/" ));
+			if( !TemplateTools::isValidTemplatePath( $this->_templateId, $this->_path )) {
+				$this->_form->setFieldValidationStatus( "path", false );
+				$this->validationErrorProcessing();
+				return( false );				
+			}
+
+			// if the template exists, check that the path exists too
+			$this->_file = $this->_request->getFilteredValue( "file", new RegexpFilter( "/[^A-Za-z0-9_\/\-.]/" ));
+			if( !TemplateTools::isValidTemplateFile( $this->_templateId, $this->_path, $this->_file )) {
+				$this->_form->setFieldValidationStatus( "file", false );
+				$this->validationErrorProcessing();
+				return( false );				
+			}			
+
+			// otherwise everything is peachy
+			return( true );
+		}
+		
+		function deleteFile()
+		{
+			$this->_path = TemplateTools::sanitizePath( $this->_path );
+			
+			// load the file
+			$filePath = TemplateSetStorage::getTemplateFolder( $this->_templateId ) . "/". 
+			            $this->_path . "/" .
+			            $this->_file;
+			
+			return( File::delete( $filePath ));
+		}
+		
+		function perform()
+		{						
+			$this->_view = new AdminEditTemplateView( $this->_blogInfo, $this->_templateId, $this->_path );
+			if( $this->deleteFile())
+				$this->_view->setSuccessMessage( $this->_locale->tr( "template_file_deleted_ok" ));
+			else
+				$this->_view->setSuccessMessage( $this->_locale->tr( "error_deleting_template_file" ));			
+				
+			$this->setCommonData();
+			
+			return( true );
+		}
+		
+		function performAjax()
+		{
+			lt_include( PLOG_CLASS_PATH."class/view/admin/ajax/adminajaxview.class.php" );
+			$this->_view = new AdminAjaxView( $this->_blogInfo );
+			
+			if( $this->deleteFile())
+				$this->_view->setSuccessMessage( $this->_locale->tr( "template_file_deleted_ok" ));
+			else
+				$this->_view->setSuccessMessage( $this->_locale->tr( "error_deleting_template_file" ));			
+				
+			return( true );
+		}
+	}
+?>
\ No newline at end of file

Added: plog/trunk/class/action/admin/adminedittemplateaction.class.php
===================================================================
--- plog/trunk/class/action/admin/adminedittemplateaction.class.php	                        (rev 0)
+++ plog/trunk/class/action/admin/adminedittemplateaction.class.php	2007-08-08 20:48:12 UTC (rev 5814)
@@ -0,0 +1,59 @@
+<?php
+	
+	lt_include( PLOG_CLASS_PATH."class/action/admin/adminaction.class.php" );
+	lt_include( PLOG_CLASS_PATH."class/data/validator/templatenamevalidator.class.php" );	
+	lt_include( PLOG_CLASS_PATH."class/data/filter/regexpfilter.class.php" );		
+	lt_include( PLOG_CLASS_PATH."class/template/templatesets/templatesets.class.php" );
+	lt_include( PLOG_CLASS_PATH."class/template/editor/templatetools.class.php" );	
+	lt_include( PLOG_CLASS_PATH."class/view/admin/adminsitetemplateslistview.class.php" );
+	lt_include( PLOG_CLASS_PATH."class/view/admin/adminedittemplateview.class.php" );	
+	
+	class AdminEditTemplateAction extends AdminAction
+	{
+		private $_templateId;
+		private $_path;
+		
+		function __construct( $actionInfo, $request )
+		{
+			$this->AdminAction( $actionInfo, $request );
+			
+			$this->registerFieldValidator( "templateId", new TemplateNameValidator());
+			$view = new AdminSiteTemplatesListView( $this->_blogInfo );
+			$view->setErrorMessage( $this->_locale->tr( "error_loading_template_set" ));
+			$this->setValidationErrorView( $view );
+			
+			$this->requirePermission( "edit_site_template" );
+		}
+		
+		function validate()
+		{
+			if( !parent::validate()) 
+				return false;
+				
+			// check that the template really exists
+			$this->_templateId = $this->_request->getFilteredValue( "templateId", new RegexpFilter( "/[^A-Za-z0-9_]/" ));
+			if( !TemplateSets::isTemplate( $this->_templateId )) {
+				$this->_form->setFieldValidationStatus( "templateId", false );
+				$this->validationErrorProcessing();
+				return( false );
+			}
+			
+			// if the template exists, check that the path exists too
+			$this->_path = $this->_request->getFilteredValue( "path", new RegexpFilter( "/[^A-Za-z0-9_\/\-]/" ));
+			if( !TemplateTools::isValidTemplatePath( $this->_templateId, $this->_path )) {
+				$this->_form->setFieldValidationStatus( "path", false );
+				$this->validationErrorProcessing();
+				return( false );				
+			}
+			
+			// otherwise everything is peachy
+			return( true );
+		}
+		
+		function perform()
+		{
+			$this->_view = new AdminEditTemplateView( $this->_blogInfo, $this->_templateId, TemplateTools::sanitizePath( $this->_path ));
+			$this->setCommonData();
+		}
+	}
+?>
\ No newline at end of file

Added: plog/trunk/class/action/admin/adminedittemplatefileaction.class.php
===================================================================
--- plog/trunk/class/action/admin/adminedittemplatefileaction.class.php	                        (rev 0)
+++ plog/trunk/class/action/admin/adminedittemplatefileaction.class.php	2007-08-08 20:48:12 UTC (rev 5814)
@@ -0,0 +1,90 @@
+<?php
+	
+	lt_include( PLOG_CLASS_PATH."class/action/admin/adminaction.class.php" );
+	lt_include( PLOG_CLASS_PATH."class/data/validator/templatenamevalidator.class.php" );	
+	lt_include( PLOG_CLASS_PATH."class/data/validator/stringvalidator.class.php" );		
+	lt_include( PLOG_CLASS_PATH."class/data/filter/regexpfilter.class.php" );		
+	lt_include( PLOG_CLASS_PATH."class/template/templatesets/templatesets.class.php" );
+	lt_include( PLOG_CLASS_PATH."class/template/editor/templatetools.class.php" );	
+	lt_include( PLOG_CLASS_PATH."class/view/admin/adminsitetemplateslistview.class.php" );
+	lt_include( PLOG_CLASS_PATH."class/view/admin/adminedittemplatefileview.class.php" );	
+	lt_include( PLOG_CLASS_PATH."class/view/admin/adminerrordialogview.class.php" );	
+	lt_include( PLOG_CLASS_PATH."class/file/file.class.php" );		
+	
+	class AdminEditTemplateFileAction extends AdminAction
+	{
+		private $_templateId;
+		private $_path;
+		private $_file;
+		
+		function __construct( $actionInfo, $request )
+		{
+			$this->AdminAction( $actionInfo, $request );
+			
+			$this->registerFieldValidator( "templateId", new TemplateNameValidator(), false);
+			$this->registerFieldValidator( "path", new StringValidator(), true );
+			$this->registerFieldValidator( "file", new StringValidator(), false );			
+			$view = new AdminErrorDialogView( $this->_blogInfo, $this->_locale->tr( "error_loading_template_file" ));
+			$this->setValidationErrorView( $view );
+			
+			$this->requirePermission( "edit_site_template" );
+		}
+		
+		function validate()
+		{
+			if( !parent::validate()) 
+				return false;
+				
+				
+			// check that the template really exists
+			$this->_templateId = $this->_request->getFilteredValue( "templateId", new RegexpFilter( "/[^A-Za-z0-9_]/" ));
+			if( !TemplateSets::isTemplate( $this->_templateId )) {
+				$this->_form->setFieldValidationStatus( "templateId", false );
+				$this->validationErrorProcessing();
+				return( false );
+			}
+			
+			// if the template exists, check that the path exists too
+			$this->_path = $this->_request->getFilteredValue( "path", new RegexpFilter( "/[^A-Za-z0-9_\/\-]/" ));
+			if( !TemplateTools::isValidTemplatePath( $this->_templateId, $this->_path )) {
+				$this->_form->setFieldValidationStatus( "path", false );
+				$this->validationErrorProcessing();
+				return( false );				
+			}
+			
+			// if the template exists, check that the path exists too
+			$this->_file = $this->_request->getFilteredValue( "file", new RegexpFilter( "/[^A-Za-z0-9_\/\-.]/" ));
+			if( !TemplateTools::isValidTemplateFile( $this->_templateId, $this->_path, $this->_file ) ||
+			    !TemplateTools::isEditable( $this->_file )) {
+				$this->_form->setFieldValidationStatus( "file", false );
+				$this->validationErrorProcessing();
+				return( false );				
+			}			
+			
+			// otherwise everything is peachy
+			return( true );
+		}
+		
+		function perform()
+		{
+			$this->_view = new AdminEditTemplateFileView( $this->_blogInfo );
+			
+			$this->_path = TemplateTools::sanitizePath( $this->_path );
+			
+			// load the file
+			$filePath = TemplateSetStorage::getTemplateFolder( $this->_templateId ) . "/". 
+			            $this->_path . "/" .
+			            $this->_file;
+			
+			$f = new File( $filePath );
+			$this->_view->setValue( "fileContent", $f->readContents());
+			$this->_view->setValue( "path", $this->_path );
+			$this->_view->setValue( "file", $this->_file );
+			$this->_view->setValue( "template", $this->_templateId );
+			
+			$this->setCommonData();
+			
+			return( true );
+		}
+	}
+?>
\ No newline at end of file

Added: plog/trunk/class/action/admin/adminupdatetemplatefileaction.class.php
===================================================================
--- plog/trunk/class/action/admin/adminupdatetemplatefileaction.class.php	                        (rev 0)
+++ plog/trunk/class/action/admin/adminupdatetemplatefileaction.class.php	2007-08-08 20:48:12 UTC (rev 5814)
@@ -0,0 +1,93 @@
+<?php
+
+	lt_include( PLOG_CLASS_PATH."class/action/admin/adminaction.class.php" );
+	lt_include( PLOG_CLASS_PATH."class/data/validator/templatenamevalidator.class.php" );	
+	lt_include( PLOG_CLASS_PATH."class/data/validator/stringvalidator.class.php" );		
+	lt_include( PLOG_CLASS_PATH."class/data/filter/regexpfilter.class.php" );		
+	lt_include( PLOG_CLASS_PATH."class/template/templatesets/templatesets.class.php" );
+	lt_include( PLOG_CLASS_PATH."class/template/editor/templatetools.class.php" );	
+	lt_include( PLOG_CLASS_PATH."class/view/admin/adminsitetemplateslistview.class.php" );
+	lt_include( PLOG_CLASS_PATH."class/view/admin/adminedittemplatefileview.class.php" );	
+	lt_include( PLOG_CLASS_PATH."class/file/file.class.php" );
+
+	class AdminUpdateTemplateFileAction extends AdminAction
+	{
+		function __construct( $actionInfo, $request )
+		{
+			$this->AdminAction( $actionInfo, $request );
+			
+			$this->registerFieldValidator( "templateId", new TemplateNameValidator(), false);
+			$this->registerFieldValidator( "path", new StringValidator(), true );
+			$this->registerFieldValidator( "file", new StringValidator(), false );			
+			$view = new AdminSiteTemplatesListView( $this->_blogInfo );
+			$view->setErrorMessage( $this->_locale->tr( "error_loading_template_file" ));
+			$this->setValidationErrorView( $view );
+
+			$this->requirePermission( "edit_global_template" );
+		}
+
+		function validate()
+		{
+			if( !parent::validate()) 
+				return false;
+
+
+			// check that the template really exists
+			$this->_templateId = $this->_request->getFilteredValue( "templateId", new RegexpFilter( "/[^A-Za-z0-9_]/" ));
+			if( !TemplateSets::isTemplate( $this->_templateId )) {
+				$this->_form->setFieldValidationStatus( "templateId", false );
+				$this->validationErrorProcessing();
+				return( false );
+			}
+
+			// if the template exists, check that the path exists too
+			$this->_path = $this->_request->getFilteredValue( "path", new RegexpFilter( "/[^A-Za-z0-9_\/\-]/" ));
+			if( !TemplateTools::isValidTemplatePath( $this->_templateId, $this->_path )) {
+				$this->_form->setFieldValidationStatus( "path", false );
+				$this->validationErrorProcessing();
+				return( false );				
+			}
+
+			// if the template exists, check that the path exists too
+			$this->_file = $this->_request->getFilteredValue( "file", new RegexpFilter( "/[^A-Za-z0-9_\/\-.]/" ));
+			if( !TemplateTools::isValidTemplateFile( $this->_templateId, $this->_path, $this->_file ) ||
+			    !TemplateTools::isEditable( $this->_file )) {
+				$this->_form->setFieldValidationStatus( "file", false );
+				$this->validationErrorProcessing();
+				return( false );				
+			}			
+
+			// otherwise everything is peachy
+			return( true );
+		}
+		
+		function writeFile()
+		{
+			$this->_path = TemplateTools::sanitizePath( $this->_path );
+			
+			// load the file
+			$filePath = TemplateSetStorage::getTemplateFolder( $this->_templateId ) . "/". 
+			            $this->_path . "/" .
+			            $this->_file;
+			
+			$f = new File( $filePath );
+			$f->open( "w+" );
+			return( $f->write( $this->_request->getValue( "fileContent" )));			
+		}
+		
+		function performAjax()
+		{
+			$result = $this->writeFile();
+			
+			lt_include( PLOG_CLASS_PATH."class/view/admin/ajax/adminajaxview.class.php" );
+			$this->_view = new AdminAjaxView( $this->_blogInfo );
+			
+			if( $result )
+				$this->_view->setSuccessMessage( $this->_locale->tr( "template_file_updated_ok" ));
+			else
+				$this->_view->setErrorMessage( $this->_locale->tr( "error_updating_template_file" ));			
+			
+			return( true );			
+		}
+	}
+?>
\ No newline at end of file

Modified: plog/trunk/class/controller/admincontrollermap.properties.php
===================================================================
--- plog/trunk/class/controller/admincontrollermap.properties.php	2007-08-08 20:44:31 UTC (rev 5813)
+++ plog/trunk/class/controller/admincontrollermap.properties.php	2007-08-08 20:48:12 UTC (rev 5814)
@@ -355,4 +355,9 @@
   	$actions["deleteInboxPrivateMessage"] = "AdminDeleteInboxPrivateMessageAction";
   	$actions["deleteOutboxPrivateMessages"] = "AdminDeleteOutboxPrivateMessageAction";
   	$actions["deleteOutboxPrivateMessage"] = "AdminDeleteOutboxPrivateMessageAction";
+	// template editor
+	$actions["editTemplate"] = "AdminEditTemplateAction";
+	$actions["editTemplateFile"] = "AdminEditTemplateFileAction";	
+	$actions["updateTemplateFile"] = "AdminUpdateTemplateFileAction";
+	$actions["deleteTemplateFile"] = "AdminDeleteTemplateFileAction";
 ?>
\ No newline at end of file

Added: plog/trunk/class/template/editor/templatetools.class.php
===================================================================
--- plog/trunk/class/template/editor/templatetools.class.php	                        (rev 0)
+++ plog/trunk/class/template/editor/templatetools.class.php	2007-08-08 20:48:12 UTC (rev 5814)
@@ -0,0 +1,123 @@
+<?php
+
+	class TemplateTools
+	{
+        static function isValidExtension( $name )
+        {
+			lt_include( PLOG_CLASS_PATH."class/config/config.class.php" );
+			lt_include( PLOG_CLASS_PATH."class/data/validator/filenamematchvalidator.class.php" );
+	
+			$config =& Config::getConfig();
+			$allowedExtensions = $config->getValue( "template_editor_editable_extensions" );
+			$v = new FileNameMatchValidator( $allowedExtensions );
+			return( $v->validate( $name ));
+        }
+
+		static function isEditable( $name )
+		{
+			return( TemplateTools::isValidExtension( $name ));
+		}
+
+        static function isImage( $name )
+        {
+		    $extensionList = Array( "jpg", "gif", "png", "bmp" );            
+            $fileExtension = array_pop(explode('.', $name));
+            foreach ($extensionList as $extension) {
+                if ( $fileExtension == trim($extension) ) {
+                    return true;   
+                }
+            }
+            return false;
+        }		
+
+		static function getTemplateFiles( $template, $path = "", $blogId = 0 ) 
+		{
+			lt_include( PLOG_CLASS_PATH."class/file/file.class.php" );
+			lt_include( PLOG_CLASS_PATH."class/misc/glob.class.php" );
+			lt_include( PLOG_CLASS_PATH."class/template/templatesets/templatesetstorage.class.php" );
+			
+			$folder = TemplateSetStorage::getTemplateFolder( $template, $blogId ) . $path;			
+			
+            $templateFiles = Array();
+			/**
+			 * :TODO:
+			 * This could be turned into a DirectoryIterator
+			 */
+            $files = Glob::myGlob( $folder, "*" );
+            foreach ($files as $file) {
+                if ( !File::isDir($file) ) {
+                    $tmp['name'] = basename($file);
+                    $tmp['size'] = filesize($file);
+                    $tmp['isEditable'] = TemplateTools::isValidExtension( $tmp['name'] ) && File::isWritable( $file );
+					$tmp['isRemovable'] = File::isWritable( dirname( $file ));
+                    $tmp['isImage'] = TemplateTools::isImage( $tmp['name'] );
+                    $tmp['url'] = $file;
+					$tmp['isFile'] = true;
+					$tmp['isFolder'] = false;
+
+                    array_push ($templateFiles, $tmp);
+                }
+                elseif ( File::isDir($file) ) {
+                    $tmp['name'] = basename($file);
+					$tmp['isFile'] = false;
+					$tmp['isFolder'] = true;
+                    if ( $tmp['name'] != "backups" ) {
+                        array_push ($templateFiles, $tmp);
+                    }
+                }
+            }
+
+            return $templateFiles;
+        }
+
+        static function isValidTemplateFileName( $name )
+        {
+		    $pattern = '/^[a-zA-Z0-9\._-]*$/';
+            if (preg_match($pattern, $name) ) {
+               return true;
+            } else {
+               return false;
+            }
+        }
+
+		static function isValidTemplatePath( $template, $path = "", $blogId = 0 )
+		{
+			lt_include( PLOG_CLASS_PATH."class/template/templatesets/templatesetstorage.class.php" );
+			$templatePath = TemplateSetStorage::getTemplateFolder( $template, $blogId ) . $path;
+			
+			return( File::isDir( $templatePath ));
+		}
+		
+		static function isValidTemplateFile( $template, $path, $file, $blogId = 0 )
+		{
+			if( !TemplateTools::isValidTemplatePath( $template, $path, $blogId ))
+				return( false );
+				
+			lt_include( PLOG_CLASS_PATH."class/template/templatesets/templatesetstorage.class.php" );
+			$filePath = TemplateSetStorage::getTemplateFolder( $template, $blogId ) .  $path . "/" . $file;						
+			
+			return( File::isReadable( $filePath ));
+		}
+		
+		static function getUpperFolder( $path )
+		{
+			$path = TemplateTools::sanitizePath( $path );
+			
+			$folders = explode( "/", $path );
+			
+			// drop the last element from the array and rebuild the string
+			array_pop( $folders );						
+			return( implode( "/", $folders ));
+		}
+		
+		static function sanitizePath( $path )
+		{
+			$path = preg_replace( "/\/\/+/", "/", $path );
+			if( isset( $path[0] ))
+				if( $path[0] == "/" )
+					$path = substr( $path, 1 );
+				
+			return( $path );
+		}
+	}
+?>
\ No newline at end of file

Added: plog/trunk/class/view/admin/adminedittemplatefileview.class.php
===================================================================
--- plog/trunk/class/view/admin/adminedittemplatefileview.class.php	                        (rev 0)
+++ plog/trunk/class/view/admin/adminedittemplatefileview.class.php	2007-08-08 20:48:12 UTC (rev 5814)
@@ -0,0 +1,12 @@
+<?php
+
+	lt_include( PLOG_CLASS_PATH."class/view/admin/admintemplatedview.class.php" );
+
+	class AdminEditTemplateFileView extends AdminTemplatedView
+	{
+		function __construct( $blogInfo )
+		{
+			$this->AdminTemplatedView( $blogInfo, "edittemplatefile" );
+		}
+	}
+?>
\ No newline at end of file

Added: plog/trunk/class/view/admin/adminedittemplateview.class.php
===================================================================
--- plog/trunk/class/view/admin/adminedittemplateview.class.php	                        (rev 0)
+++ plog/trunk/class/view/admin/adminedittemplateview.class.php	2007-08-08 20:48:12 UTC (rev 5814)
@@ -0,0 +1,36 @@
+<?php
+
+	lt_include( PLOG_CLASS_PATH."class/view/admin/admintemplatedview.class.php" );
+	lt_include( PLOG_CLASS_PATH."class/template/editor/templatetools.class.php" );
+	
+	class AdminEditTemplateView extends AdminTemplatedView
+	{
+		private $_templateId;
+		private $_path;
+		
+		function __construct( $blogInfo, $templateId, $path = "" )
+		{
+			
+			$r =& Request::getRequest();
+			if( $r->isTableOnly())			
+				$this->AdminTemplatedView( $blogInfo, "edittemplate_table" );
+			else
+				$this->AdminTemplatedView( $blogInfo, "edittemplate" );
+			
+			$this->_templateId = $templateId;
+			$this->_path = $path;
+		}
+		
+		function render()
+		{
+			$files = TemplateTools::getTemplateFiles( $this->_templateId, $this->_path, 0 );
+
+			$this->setValue( "files", $files );
+			$this->setValue( "template", $this->_templateId );
+			$this->setValue( "path", $this->_path );
+			$this->setValue( "up", TemplateTools::getUpperFolder( $this->_path ));
+			
+			return( parent::render());
+		}
+	}
+?>

Modified: plog/trunk/class/view/admin/adminsitetemplateslistview.class.php
===================================================================
--- plog/trunk/class/view/admin/adminsitetemplateslistview.class.php	2007-08-08 20:44:31 UTC (rev 5813)
+++ plog/trunk/class/view/admin/adminsitetemplateslistview.class.php	2007-08-08 20:48:12 UTC (rev 5814)
@@ -8,8 +8,7 @@
      * @private
      */	
 	class AdminSiteTemplatesListView extends AdminTemplatedView
-	{
-	
+	{	
 		function AdminSiteTemplatesListView( $blogInfo )
 		{
 			$this->AdminTemplatedView( $blogInfo, "sitetemplates" );

Added: plog/trunk/js/ui/pages/templateeditor.js
===================================================================
--- plog/trunk/js/ui/pages/templateeditor.js	                        (rev 0)
+++ plog/trunk/js/ui/pages/templateeditor.js	2007-08-08 20:48:12 UTC (rev 5814)
@@ -0,0 +1,26 @@
+Lifetype.UI.Pages.TemplateEditor = function() {}
+
+/**
+ * We are going to use this variable to store the current url, so that we
+ * can reload the right url when adding or deleting files
+ */
+Lifetype.UI.Pages.TemplateEditor.currentUrl = null;
+
+Lifetype.UI.Pages.TemplateEditor.loadFolderLink = function( url )
+{
+	Lifetype.UI.DataTable.reload( url + "&output=tableOnly" );
+	Lifetype.UI.Pages.TemplateEditor.currentUrl = url;
+}
+
+YAHOO.util.Event.addListener( window, "load", function() {
+	var t = new Lifetype.Effects.Table( "templateFiles" );
+	t.stripe();
+	t.highlightRows();
+	
+	Lifetype.UI.Pages.TemplateEditor.currentUrl = "";
+	Lifetype.UI.Pages.TemplateEditor.currentUrl += window.location;
+	
+	// reload the list when successfully deleting an item and processing one of the forms
+	Lifetype.Forms.Events.performRequestSuccessEvent.subscribe( function() { Lifetype.UI.DataTable.reload( Lifetype.UI.Pages.TemplateEditor.currentUrl ); });
+	Lifetype.Forms.Events.formProcessorSuccessEvent.subscribe( function() { Lifetype.UI.DataTable.reload(  Lifetype.UI.Pages.TemplateEditor.currentUrl ); });
+});
\ No newline at end of file

Modified: plog/trunk/js/ui/ui.js
===================================================================
--- plog/trunk/js/ui/ui.js	2007-08-08 20:44:31 UTC (rev 5813)
+++ plog/trunk/js/ui/ui.js	2007-08-08 20:48:12 UTC (rev 5814)
@@ -113,7 +113,7 @@
 Lifetype.UI.DataTable.reload = function( url )
 {	
 	url = url.replace(/&amp;/g, "&") + "&output=tableOnly";
-
+	
 	var cObj = YAHOO.util.Connect.asyncRequest('GET', url,
 		callback = {
 			success: function( o ) {
@@ -126,6 +126,8 @@
 	);
 }
 
+Lifetype.UI.DataTable.Events.dataLoaded.subscribe( function() { Lifetype.UI.ContentOverlay.processAnchors() } );
+
 /**
  * Namespace for helper methods
  */

Modified: plog/trunk/locale/admin/locale_en_UK.php
===================================================================
--- plog/trunk/locale/admin/locale_en_UK.php	2007-08-08 20:44:31 UTC (rev 5813)
+++ plog/trunk/locale/admin/locale_en_UK.php	2007-08-08 20:48:12 UTC (rev 5814)
@@ -517,7 +517,6 @@
 $messages['users'] = 'Users';
 $messages['blog_quota_help'] = 'Resource quota in bytes. Set as 0 for unlimited or leave empty to make the blog use the global quota.';
 $messages['edit_blog_settings_updated_ok'] = 'Blog "%s" updated successfully';
-$messages['error_updating_blog_settings'] = 'There was an error updating blog "%s"';
 $messages['error_incorrect_blog_owner'] = 'The user selected as blog owner is not correct';
 $messages['error_fetching_blog'] = 'There was an error fetching the blog';
 $messages['error_updating_blog_settings2'] = 'There was an error updating the blog. Please check the data and try again';
@@ -1293,4 +1292,21 @@
 $messages['editSiteUsers'] = 'Users';
 
 $messages['error_sending_confirmation_message'] = 'There was an error resending the confirmation message';
+
+$messages["SiteTemplateEditor"] = "Site Template Editor";
+$messages["BlogTemplateEditor"] = "Blog Template Editor";
+$messages["TemplateEditorConfig"] = "Template Editor Settings";
+
+$messages["templateeditor_backupfile"] = "Please select the date that you want to recover, template editor will load it to editor automatically. Each template file can have 5 backup files in total.";
+$messages["templateeditor_choose_backupfile"] = "Select backup file to recover";
+
+$messages['error_loading_template_set'] = 'error_loading_template_set';
+$messages['error_loading_template_file'] = 'error_loading_template_file';
+$messages['edit_template_file'] = 'edit_template_file';
+$messages['template_file_updated_ok'] = ' template_file_updated_ok';
+$messages['error_updating_template_file'] = 'error_updating_template_file';
+$messages['template_file_deleted_ok'] = 'template_file_deleted_ok';
+$messages['error_deleting_template_file'] = 'error_deleting_template_file';
+$messages['new_folder'] = 'New Folder';
+$messages['upload_file'] = 'Upload file';
 ?>
\ No newline at end of file

Modified: plog/trunk/templates/admin/blogtemplates.template
===================================================================
--- plog/trunk/templates/admin/blogtemplates.template	2007-08-08 20:44:31 UTC (rev 5813)
+++ plog/trunk/templates/admin/blogtemplates.template	2007-08-08 20:48:12 UTC (rev 5814)
@@ -1,5 +1,6 @@
 {include file="$admintemplatepath/header.template"}
 {include file="$admintemplatepath/navigation.template" showOpt=blogTemplates title=$locale->tr("blogTemplates")}
+{js src="js/ui/pages/templateeditor.js"}
 <script type="text/javascript">
 {literal}
 YAHOO.util.Event.addListener( window, "load", function() {

Added: plog/trunk/templates/admin/edittemplate.template
===================================================================
--- plog/trunk/templates/admin/edittemplate.template	                        (rev 0)
+++ plog/trunk/templates/admin/edittemplate.template	2007-08-08 20:48:12 UTC (rev 5814)
@@ -0,0 +1,32 @@
+{include file="$blogtemplate/header.template"}
+{include file="$blogtemplate/navigation.template" showOpt=siteTemplates title=$locale->tr("siteTemplates")}
+<link rel="stylesheet" href="js/editor/lifetypeeditor.css" type="text/css" />
+{js src="js/editor/lifetypeeditor.js"}
+{js src="js/ui/pages/templateeditor.js"}
+{check_perms adminperm=add_template}
+<div class="extraFunctions">
+	<div class="left">		
+		<a id="newFolderButton" href="?op=newTemplateFolder" rel="overlay">{$locale->tr("new_folder")}</a>&nbsp;|
+		<a id="uploadFileButton" href="?op=newTemplateFile" rel="overlay">{$locale->tr("upload_file")}</a>
+	</div>
+	<div class="right">
+		<a href="?op=editTemplate&amp;templateId={$template}">{$template}</a> &raquo; {$path}
+	</div>
+</div>
+<br style="clear:both" />
+{/check_perms}
+
+<form id="siteTemplatesList" method="post" action="admin.php">
+ {include file="$admintemplatepath/viewvalidateajax.template"}	
+ <div id="list">
+ {include file="$admintemplatepath/edittemplate_table.template"}
+ </div>
+ <div id="list_action_bar">
+   <input type="hidden" name="templateId" value="{$template}" />
+   <input type="hidden" name="path" value="{$path}" />
+   <input type="hidden" name="op" value="deleteTemplateFile" class="submit" />
+   <input type="submit" name="{$locale->tr("delete")}" value="{$locale->tr("delete")}"/>
+ </div>
+</form>
+{include file="$blogtemplate/footernavigation.template"}
+{include file="$blogtemplate/footer.template"}
\ No newline at end of file

Added: plog/trunk/templates/admin/edittemplate_table.template
===================================================================
--- plog/trunk/templates/admin/edittemplate_table.template	                        (rev 0)
+++ plog/trunk/templates/admin/edittemplate_table.template	2007-08-08 20:48:12 UTC (rev 5814)
@@ -0,0 +1,94 @@
+<table class="info" id="templateFiles">
+  <thead>
+   <tr>
+     <th style="width:10px;"><input class="checkbox" type="checkbox" class="check" name="all" id="all" value="1" onclick="toggleAllChecks('siteTemplatesList');" /></th>
+     <th style="width:520px;">{$locale->tr("file")}</th>
+     <th style="width:150px;">{$locale->tr("size")} ({$locale->tr("bytes")})</th>
+     <th style="width:95px;">{$locale->tr("actions")}</th>
+   </tr>
+ </thead>
+ <tbody>
+
+ {if $path != "" }
+ <tr class="{cycle values="odd,even"}">
+  <td>
+   <div align="center"><span style="background-color: #CCCCCC">&nbsp;&nbsp;&nbsp;</span></div>
+  </td>
+  <td  class="col_highlighted">
+   <a href="?op=editTemplate&amp;templateId={$template}&path={$up}" onClick="Lifetype.UI.Pages.TemplateEditor.loadFolderLink(this.href);return(false);">
+    <img src="imgs/admin/icon_folder-16.png" />
+    ..
+   </a>
+  </td>
+  <td>
+  </td>    
+  <td>
+  </td>
+ </tr>
+ {/if}
+ {foreach from=$files item=file}
+  <tr class="{cycle values="odd,even"}">
+   <td>
+      <input class="checkbox" type="checkbox" name="fileIds[{counter}]" value="{$file.name}" />
+   </td>
+   <td  class="col_highlighted">
+	 {if $file.isFile}
+    {if $file.isEditable}
+     <a href="?op=editTemplateFile&amp;templateId={$template}&amp;path={$path}&amp;file={$file.name}" rel="overlay">
+      <img src="imgs/admin/icon_template-16.png" />
+      {$file.name}
+     </a>
+    {elseif $file.isImage}
+     <a href="javascript:Lifetype.UI.Pages.TemplateEditor.openImagePreviewWindow('{$url->getUrl($file.url)}');">
+      <img src="imgs/admin/icon_image-16.png" />
+	   {$file.name}
+	  </a>
+	 {else}
+	  <img src="imgs/admin/icon_other-16.png" />
+	  {$file.name}
+    {/if}
+	 {elseif $file.isFolder}
+     <a href="?op=editTemplate&amp;templateId={$template}&path={$path}/{$file.name}" onClick="Lifetype.UI.Pages.TemplateEditor.loadFolderLink(this.href);return(false);">
+      <img src="imgs/admin/icon_folder-16.png" />
+	   {$file.name}
+     </a>
+	 {/if}
+   </td>
+   <td>
+    {$file.size}
+   </td>    
+   <td>
+    <div class="list_action_button">
+     {if $file.isEditable}
+      <a href="?op=editTemplateFile&amp;templateId={$template}&amp;path={$path}&amp;file={$file.name}" rel="overlay">
+       <img src="imgs/admin/icon_edit-16.png" alt="{$locale->tr("edit")}" />
+      </a>
+     {else}
+      <img src="imgs/admin/icon_empty-16.png" />
+     {/if}
+     {if $file.isRemovable}
+     <a href="?op=deleteTemplateFile&amp;templateId={$template}&amp;path={$path}&amp;file={$file.name}" onClick="Lifetype.Forms.performRequest(this);return(false);">
+      <img src="imgs/admin/icon_delete-16.png" alt="{$locale->tr("delete")}" />
+     </a>
+     {else}
+      <img src="imgs/admin/icon_empty-16.png" />
+     {/if}
+      {** --copy is not implemented yet--
+     {if $file.isEditable}
+       <a href="?op=copyTemplateFile&amp;templateId={$template}&amp;path={$path}&amp;file={$file.name}" id="{$file.name}" onClick="Lifetype.UI.Pages.TemplateEditor.copyTemplateFileTo(this.id, '{$template}', '{$currentSubFolder}')" >
+       <img src="imgs/admin/icon_copy-16.png" alt="{$locale->tr("copy")}" />
+      </a>
+     {else}
+      <img src="imgs/admin/icon_empty-16.png" />
+     {/if} **}
+     {if $file.isImage}
+	   <a href="javascript:Lifetype.UI.Pages.TemplateEditor.openImagePreviewWindow('{$url->getUrl($file.url)}');">
+		<img src="imgs/admin/icon_image-16.png" alt="Preview" />
+	   </a>      
+     {/if}         
+    </div>
+   </td>
+  </tr>
+ {/foreach}
+ </tbody>
+</table>
\ No newline at end of file

Added: plog/trunk/templates/admin/edittemplatefile.template
===================================================================
--- plog/trunk/templates/admin/edittemplatefile.template	                        (rev 0)
+++ plog/trunk/templates/admin/edittemplatefile.template	2007-08-08 20:48:12 UTC (rev 5814)
@@ -0,0 +1,36 @@
+<div class="extraFunctions">
+	<div class="right">
+		<a href="?op=editTemplate&amp;templateId={$template}">{$template}</a> &raquo; {$path}: {$file}
+	</div>
+</div>
+<br style="clear:both" />
+
+{include file="$admintemplatepath/formvalidateajax.template"}
+<form id="editTemplateFile" name="editTemplateFile" method="post" onSubmit="Lifetype.Forms.AjaxFormProcessor(this.id,'?output=json');return(false);">
+ <fieldset class="inputField">
+ <legend>{$locale->tr("edit_template_file")}</legend>  
+  {include file="$admintemplatepath/successmessage.template"}
+  {include file="$admintemplatepath/errormessage.template"}   
+
+  <div class="field">
+   <textarea rows="20" id="fileContent" name="fileContent" style="width:100%">{$fileContent|escape:"html"}</textarea>
+   <script type="text/javascript">var ed1 = new Lifetype.UI.Editor('fileContent','ed1');ed1.init()</script>
+  </div>  
+
+ <select id="smartySnippets">
+  <option value="">Posts loop</option>
+  <option value="">Archives loop</option>
+  <option value="">Links look</option>
+ </select>&nbsp;
+ <a href="#" onClick="return(false);">{$locale->tr("insert")}</a>
+ </fieldset>  
+
+ <div class="buttons">
+  <input type="hidden" name="templateId" value="{$template}" />
+  <input type="hidden" name="path" value="{$path}" />
+  <input type="hidden" name="file" value="{$file}" />
+  <input type="hidden" name="op" value="updateTemplateFile" />
+  <input type="reset" name="{$locale->tr("reset")}" />    
+  <input type="submit" name="{$locale->tr("update")}" value="{$locale->tr("update")}" />
+ </div>
+</form>
\ No newline at end of file

Modified: plog/trunk/templates/admin/globalsettings_templates.template
===================================================================
--- plog/trunk/templates/admin/globalsettings_templates.template	2007-08-08 20:44:31 UTC (rev 5813)
+++ plog/trunk/templates/admin/globalsettings_templates.template	2007-08-08 20:48:12 UTC (rev 5814)
@@ -84,4 +84,17 @@
     <input class="radio" type="radio" id="config[trim_whitespace_output]" name="config[trim_whitespace_output]" value="1" {if $trim_whitespace_output == 1 } checked="checked" {/if} />{$locale->tr("yes")}
     <input class="radio" type="radio" id="config[trim_whitespace_output]" name="config[trim_whitespace_output]" value="0" {if $trim_whitespace_output == 0 } checked="checked" {/if} />{$locale->tr("no")}
    </div>
- </div>
\ No newline at end of file
+   <!-- template_editor_editable_extensions -->
+   <div class="field">
+    <label for="config[template_editor_editable_extensions]">template_editor_editable_extensions</label>
+    <div class="formHelp">{$locale->tr("help_template_editor_editable_extensions")}</div>
+    <input style="width:100%" type="text" id="config[template_editor_editable_extensions]" name="config[template_editor_editable_extensions]" value="{$template_editor_editable_extensions}"/>
+   </div>
+   <!-- template_editor_max_backup_files -->
+   <div class="field">
+    <label for="config[template_editor_max_backup_files]">template_editor_max_backup_files</label>
+    <div class="formHelp">{$locale->tr("help_template_editor_max_backup_files")}</div>
+    <input style="width:100%" type="text" id="config[template_editor_max_backup_files]" name="config[template_editor_max_backup_files]" value="{$template_editor_max_backup_files}"/>
+   </div>
+ </div>
+

Modified: plog/trunk/templates/admin/jslocale.template
===================================================================
--- plog/trunk/templates/admin/jslocale.template	2007-08-08 20:44:31 UTC (rev 5813)
+++ plog/trunk/templates/admin/jslocale.template	2007-08-08 20:48:12 UTC (rev 5814)
@@ -28,4 +28,6 @@
 Lifetype.Locale.add( 'error_no_description_set', "{$locale->tr("error_no_description_set")}" );
 Lifetype.Locale.add( 'enter_location_name', "{$locale->tr("enter_location_name")}" );
 
+Lifetype.Locale.add( 'templateeditor_enter_new_templatefile_name', '{$locale->tr("templateeditor_enter_new_templatefile_name")}' );
+
 </script>
\ No newline at end of file

Modified: plog/trunk/templates/admin/newlinkcategory.template
===================================================================
--- plog/trunk/templates/admin/newlinkcategory.template	2007-08-08 20:44:31 UTC (rev 5813)
+++ plog/trunk/templates/admin/newlinkcategory.template	2007-08-08 20:48:12 UTC (rev 5814)
@@ -1,7 +1,7 @@
 <form id="newLinkCategory" method="post" action="admin.php" onSubmit="Lifetype.UI.Pages.LinkCategories.addSubmitHook(this);return(false);">
    <fieldset class="inputField">
    <legend>{$locale->tr("newLinkCategory")}</legend>   
-   {include file="$admintemplatepath/formvalidateajax.template"}   
+   {include file="$admintemplatepath/formvalidateajax.template"}
    <div class="field">
      <label for="linkCategoryName">{$locale->tr("name")}</label>
      <span class="required">*</span>

Modified: plog/trunk/templates/admin/siteblogs_table.template
===================================================================
--- plog/trunk/templates/admin/siteblogs_table.template	2007-08-08 20:44:31 UTC (rev 5813)
+++ plog/trunk/templates/admin/siteblogs_table.template	2007-08-08 20:48:12 UTC (rev 5814)
@@ -14,7 +14,8 @@
    <tr>
     <td><input class="checkbox" type="checkbox" name="blogIds[{counter}]" value="{$siteblog->getId()}"/></td>
     <td class="col_highlighted">
-     {check_perms adminperm=update_site_blog}<a href="?op=editBlog&amp;blogId={$siteblog->getId()}">{/check_perms}{$siteblog->getBlog()}{check_perms adminperm=update_site_blog}</a>{/check_perms}
+     {check_perms adminperm=update_site_blog}<a href="?op=editBlog&amp;blogId={$siteblog->getId()}" rel="overlay">
+	 {/check_perms}{$siteblog->getBlog()}{check_perms adminperm=update_site_blog}</a>{/check_perms}
     </td>
     <td>
 	    {assign var=ownerInfo value=$siteblog->getOwnerInfo()}

Modified: plog/trunk/templates/admin/sitetemplates.template
===================================================================
--- plog/trunk/templates/admin/sitetemplates.template	2007-08-08 20:44:31 UTC (rev 5813)
+++ plog/trunk/templates/admin/sitetemplates.template	2007-08-08 20:48:12 UTC (rev 5814)
@@ -1,14 +1,6 @@
 {include file="$blogtemplate/header.template"}
 {include file="$blogtemplate/navigation.template" showOpt=siteTemplates title=$locale->tr("siteTemplates")}
-<script type="text/javascript">
-{literal}
-YAHOO.util.Event.addListener( window, "load", function() {
-		var t = new Lifetype.Effects.Table( "list" );
-		t.stripe();
-		t.highlightRows();
-	});
-{/literal}
-</script>
+{js src="js/ui/pages/templateeditor.js"}
 {check_perms adminperm=add_template}
 <div class="extraFunctions">
 	<div class="left">		
@@ -18,48 +10,22 @@
 <br style="clear:both" />
 {/check_perms}
  <form id="siteTemplates" method="post" action="admin.php">
- <div id="list">
+ <div id="list" style="margin-left:30px;">
   {include file="$admintemplatepath/successmessage.template"}
   {include file="$admintemplatepath/errormessage.template"}
-  <table id="list" class="info" summary="{$locale->tr("siteTemplates")}">
-   <thead>
-    <tr>
-      <th><input class="checkbox" type="checkbox" name="all" id="all" value="1" onclick="Lifetype.Forms.toggleAllChecks('siteTemplates');" /></th>
-      <th style="width:90%;">{$locale->tr("template")}</th>
-      <th style="width:10%;">{$locale->tr("actions")}</th>
-    </tr>
-  </thead>
-  <tbody>
-  {foreach from=$templates item=sitetemplate}
-   <tr>
-    <td>
-       <input class="checkbox" type="checkbox" name="templateIds[{counter}]" value="{$sitetemplate->getName()}" />
-    </td>
-    <td  class="col_highlighted">
-	 {if $sitetemplate->hasScreenshot()}
-	  <a href="javascript:Lifetype.UI.Pages.TemplateChooser.openScreenshotWindow('{$sitetemplate->getScreenshotUrl()}');">{$sitetemplate->getName()}</a>
-	 {else}
-      {$sitetemplate->getName()}
-	 {/if} 
-    </td>
-    <td>
-     <div class="list_action_button">
-	  {check_perms adminperm=update_template}
-      <a href="?op=deleteTemplate&amp;templateId={$sitetemplate->getName()}" title="{$locale->tr("delete")}">
-        <img src="imgs/admin/icon_delete-16.png" alt="{$locale->tr("delete")}" />
-      </a>
-      {/check_perms}
-	  {if $sitetemplate->hasScreenshot()}
-	    <a href="javascript:Lifetype.UI.Pages.TemplateChooser.openScreenshotWindow('{$sitetemplate->getScreenshotUrl()}');" title="{$locale->tr("preview")}">
-		  <img src="imgs/admin/icon_image-16.png" alt="{$locale->tr("preview")}" />
-		</a>
-	  {/if}	  
-     </div>
-    </td>
-   </tr>
-  {/foreach}
-  </tbody>
- </table>
+
+ {foreach from=$templates item=sitetemplate}
+  <div class="template-screenshot">
+	<input style="display:none" type="checkbox" name="templateIds[{counter}]" value="{$sitetemplate->getName()}" />
+	<img src="{$sitetemplate->getScreenshotUrl()}" style="height:240px;width:320px" alt="{$sitetemplate->getName()}" />
+	<a href="javascript:Lifetype.UI.Pages.TemplateChooser.openScreenshotWindow('{$sitetemplate->getScreenshotUrl()}');">{$sitetemplate->getName()}</a> |
+	<a href="?op=editTemplate&templateId={$sitetemplate->getName()}">{$locale->tr("edit")}</a> |
+	<a href="?op=copyTemplate&templateId={$sitetemplate->getName()}">{$locale->tr("copy")}</a> |	
+	<a href="?op=tbd">{$locale->tr("delete")}</a>
+  </div>
+ {/foreach}
+
+ <div class="clearer"></div>
  </div>
  <div id="list_action_bar">
    {check_perms adminperm=update_template}	



More information about the pLog-svn mailing list