'' ); /** * @access protected */ function __construct(){ // Call parent parent::__construct(); $this->_base = $this->getRootDir(); $this->_plugin->type = 'manager'; } /** * Returns a reference to a Manager object * * This method must be invoked as: *
  $manager = &Manager::getInstance();
* * @access public * @return JCE The editor object. * @since 1.5 */ function &getInstance(){ static $instance; if ( !is_object( $instance ) ){ $instance = new Manager(); } return $instance; } /* * Initialize the Manager plugin * Shortcut to setup Manager elements */ function init(){ // Setup XHR callback funtions $this->setXHR( array( $this, 'getItems' ) ); $this->setXHR( array( $this, 'getFileDetails' ) ); $this->setXHR( array( $this, 'getFolderDetails' ) ); $this->setXHR( array( $this, 'getTree' ) ); $this->setXHR( array( $this, 'getTreeItem' ) ); // Get actions $this->getStdActions(); // Get buttons $this->getStdButtons(); // Store default manager scripts $this->script( array( 'tiny_mce_popup' ), 'tiny_mce' ); $this->script( array( 'mootools' ), 'media' ); $this->script( array( 'tiny_mce_utils', 'jce', 'plugin', 'window', 'listsorter', 'searchables', 'tree', 'upload', 'manager' ) ); // Store default manager css $this->css( array( 'plugin', 'manager', 'upload', 'tree' ) ); $this->css( array( 'window', 'dialog' ), 'skins' ); // Load language files $this->loadLanguages(); } /** * Get the relative base directory variable. * @return string base dir */ function getBase(){ return $this->_base; } /** * Get the base directory. * @return string base dir */ function getBaseDir(){ return Utils::makePath( JPATH_SITE, $this->_base ); } /** * Get the full base url * @return string base url */ function getBaseURL(){ return Utils::makePath( JURI::root(true), $this->_base ); } /** * Return the full user directory path. Create if required * * @param string The base path * @access public * @return Full path to folder */ function getRootDir(){ $user =& JFactory::getUser(); jimport('joomla.filesystem.folder'); // Joomla directories $jdir = array( 'administrator', 'cache', 'components', 'includes', 'language', 'libraries', 'logs', 'media', 'modules', 'plugins', 'templates', 'xmlrpc' ); // Get base directory as shared parameter $base = $this->getSharedParam( 'dir', 'images/stories' ); // Remove whitespace $base = trim( $base ); // Convert slashes / Strip double slashes $base = preg_replace( '/[\\\\]+/', '/', $base ); // Remove first leading slash $base = ltrim( $base, '/' ); // Force default if directory is a joomla directory $parts = explode( '/', $base ); if( in_array( strtolower( $parts[0] ), $jdir ) ){ $base = 'images/stories'; } // Force default directory if base param starts with a variable or a . eg $id if( preg_match( '/[\.\$]/', $base{0} ) ){ $base = 'images/stories'; } // Super Administrators not affected if( $this->isSuperAdmin() ){ // Get the root folder before dynamic variables for Super Admin $parts = explode( '/$', $base ); $base = $parts[0]; }else{ // Replace any path variables $base = preg_replace( array( '/\$id/', '/\$username/', '/\$usertype/', '/\$group/' ), array( $user->id, strtolower( $user->username ), strtolower( $user->usertype ), strtolower( $this->_group->name ) ), $base ); } // Clean $base = preg_replace( array( '/$\w+\b/', '/(\.){2,}/', '/[^A-Za-z0-9:\_\-\/]/' ), '', $base ); // Create the folder $full = Utils::makePath( JPATH_SITE, $base ); if( !JFolder::exists( $full ) ){ $this->folderCreate( $full ); } // Fallback $base = JFolder::exists( $full ) ? $base : 'images/stories'; return $base; } /** * Set the plugin filetypes * Checks for filetypr group name. Default inserted if not available * @param string The filetype list, eg: html=html,htm;text=txt * @access public */ function setFileTypes( $types ){ if( strpos( $types, '=' ) === false ){ $types = 'files=' .$types; } $this->_filetypes = $types; } /** * Return a list of allowed file extensions in selected format * * @access public * @return extension list */ function getFileTypes( $format = 'map' ){ $list = $this->_filetypes; switch( $format ){ case 'list': return $this->listFileTypes( $list ); break; case 'array': return explode( ',', $this->listFileTypes( $list ) ); break; default: case 'map': return $list; break; } } /** * Converts the extensions map to a list * @param string $map The extensions map eg: images=jpg,jpeg,gif,png * @return string jpg,jpeg,gif,png */ function listFileTypes( $map ){ $array = explode( ';', $map ); $icons = array(); foreach( $array as $items ){ $item = explode( '=', $items ); $icons[] = $item[1]; } return implode( ',', $icons ); } /* * Maps upload file types to an upload dialog list, eg: 'images', 'jpeg,jpg,gif,png' * @return json encoded list */ function mapUploadFileTypes(){ // Get the filetype map $list = $this->getFileTypes(); $items = explode( ';', $list ); $map = array(); // [images=jpeg,jpg,gif,png] foreach( $items as $item ){ // ['images', 'jpeg,jpg,gif,png'] $kv = explode( '=', $item ); $extensions = implode( ';', preg_replace( '/(\w+)/i', '*.$1', explode( ',', $kv[1] ) ) ); $map[JText::_( $kv[0] ). ' (' .$extensions. ')'] = $extensions; } // All file types $map[JText::_('All Files') . ' (*.*)'] = '*.*'; return $this->json_encode( $map ); } /* * Returns the result variable * @return var $_result */ function returnResult(){ return $this->_result; } /** * Determine whether FTP mode is enabled * @return boolean */ function isFtp(){ // Initialize variables jimport('joomla.client.helper'); $FTPOptions = JClientHelper::getCredentials('ftp'); return $FTPOptions['enabled'] == 1; } /** * Get the list of files in a given folder * @param string $relative The relative path of the folder * @param string $filter A regex filter option * @return File list array */ function getFiles( $relative, $filter='.' ){ jimport('joomla.filesystem.folder'); $path = Utils::makePath( $this->getBaseDir(), $relative ); $list = JFolder::files( $path, $filter ); if( !empty( $list ) ){ // Sort alphabetically natcasesort( $list ); for ($i = 0; $i < count( $list ); $i++) { $file = utf8_encode( $list[$i] ); $files[] = array( 'url' => Utils::makePath( $relative, $file ), 'name' => $file ); } return $files; }else{ return $list; } } /** * Get the list of folder in a given folder * @param string $relative The relative path of the folder * @return Folder list array */ function getFolders( $relative ){ jimport('joomla.filesystem.folder'); $path = Utils::makePath( $this->getBaseDir(), $relative ); $list = JFolder::folders( $path ); if( !empty( $list ) ){ // Sort alphabetically natcasesort( $list ); for ($i = 0; $i < count( $list ); $i++) { $folder = utf8_encode( $list[$i] ); $folders[] = array( 'url' => Utils::makePath( $relative, $folder ), 'name' => $folder ); } return $folders; }else{ return $list; } } /** * Get a tree node * @param string $dir The relative path of the folder to search * @return Tree node array */ function getTreeItem( $dir ){ $folders = $this->getFolders( utf8_decode( rawurldecode( $dir ) ) ); $array = array(); if( !empty( $folders ) ){ foreach( $folders as $folder ){ $array[] = array( 'id' => $folder['url'], 'name' => $folder['name'], 'class' => 'folder' ); } } $result[] = array( 'folders' => $array ); return $result; } function escape( $string ){ return preg_replace( array( '/%2F/', '/%3F/', '/%40/', '/%2A/', '/%2B/' ), array( '/', '?', '@', '*', '+' ), rawurlencode( $string ) ); } /** * Build a tree list * @param string $dir The relative path of the folder to search * @return Tree html string */ function getTree( $dir ){ $result = $this->getTreeItems( $dir ); return $result; } function getTreeItems( $dir, $root=true, $init=true ){ $result = ''; if( $init ){ $this->treedir = $dir; if( $root ){ $result = ''; } $init = false; return $result; } function getFolderDetails( $dir ){ jimport('joomla.filesystem.folder'); clearstatcache(); $path = Utils::makePath( $this->getBaseDir(), utf8_decode( rawurldecode( $dir ) ) ); $date = Utils::formatDate( @filemtime( $path ) ); $folders = count( JFolder::folders( $path ) ); $files = count( JFolder::files( $path, '\.(' . str_replace( ',', '|', $this->getFileTypes() ) . ')$' ) ); $h = array( 'modified' => $date, 'contents' => $folders. ' ' .JText::_('folders'). ', ' .$files. ' ' .JText::_('files') ); return $h; } function getFileDetails( $file ){ clearstatcache(); $path = Utils::makePath( $this->getBaseDir(), rawurldecode( $file ) ); $url = Utils::makePath( $this->getBaseUrl(), rawurldecode( $file ) ); $date = Utils::formatDate( @filemtime( $path ) ); $size = Utils::formatSize( @filesize( $path ) ); $h = array( 'size' => $size, 'modified' => $date, ); if( preg_match('/\.(jpeg|jpg|gif|png)/i', $file) ){ $dim = @getimagesize( $path ); $width = $dim[0]; $height = $dim[1]; $pw = ( $width >= 100 ) ? 100 : $width; $ph = ( $pw / $width ) * $height; if( $ph > 80 ){ $ph = 80; $pw = ( $ph / $height ) * $width; } $h = array( 'dimensions' => $width. ' x ' .$height, 'size' => $size, 'modified' => $date, 'preview' => array( 'src' => $url, 'width' => round( $pw ), 'height' => round( $ph ) ) ); } return $h; } function getStdActions(){ $this->addAction( 'help', '', '', JText::_('Help') ); if( $this->checkAccess('upload', '1') ){ $this->addAction( 'upload', '', '', JText::_('Upload') ); $this->setXHR( array( $this, 'upload' ) ); } if( $this->checkAccess('folder_new', '1') ){ $this->addAction( 'folder_new', '', '', JText::_('New Folder') ); $this->setXHR( array( $this, 'folderNew' ) ); } } function addAction( $name, $icon, $action, $title ){ $this->_actions[$name] = array( 'name' => $name, 'icon' => $icon, 'action' => $action, 'title' => $title ); } function getActions(){ return $this->json_encode( $this->_actions ); } function removeAction( $name ){ if( array_key_exists( $this->_actions[$name] ) ){ unset( $this->_actions[$name] ); } } function getStdButtons(){ if( $this->checkAccess('folder_delete', '1') ){ $this->addButton( 'folder', 'delete', '', '', JText::_('Delete Folder') ); $this->setXHR( array( $this, 'folderDelete' ) ); } if( $this->checkAccess('folder_rename', '1') ){ $this->addButton( 'folder', 'rename', '', '', JText::_('Rename Folder') ); $this->setXHR( array( $this, 'folderRename' ) ); } if( $this->checkAccess('file_rename', '1') ){ $this->addButton( 'file', 'rename', '', '', JText::_('Rename File') ); $this->setXHR( array( $this, 'fileRename' ) ); } if( $this->checkAccess('file_delete', '1') ){ $this->addButton( 'file', 'delete', '', '', JText::_('Delete Files'), true ); $this->setXHR( array( $this, 'fileDelete' ) ); } if( $this->checkAccess('file_move', '1') ){ $this->addButton( 'file', 'copy', '', '', JText::_('Copy Files'), true ); $this->addButton( 'file', 'cut', '', '', JText::_('Cut Files'), true ); $this->addButton( 'file', 'paste', '', '', JText::_('Paste Files'), true, true ); $this->setXHR( array( $this, 'fileCopy' ) ); $this->setXHR( array( $this, 'fileMove' ) ); } $this->addButton( 'file', 'view', '', '', JText::_('View File') ); $this->addButton( 'file', 'insert', '', '', JText::_('Insert File') ); } function addButton( $type='file', $name, $icon='', $action='', $title, $multiple=false, $trigger=false ){ $this->_buttons[$type][$name] = array( 'name' => $name, 'icon' => $icon, 'action' => $action, 'title' => $title, 'multiple' => $multiple, 'trigger' => $trigger ); } function getButtons(){ return $this->json_encode( $this->_buttons ); } function removeButton( $type, $name ){ if( array_key_exists( $name, $this->_buttons[$type] ) ){ unset( $this->_buttons[$type][$name] ); } } function changeButton( $type, $name, $keys ){ foreach( $keys as $key => $value ){ if( isset( $this->_buttons[$type][$name][$key] ) ){ $this->_buttons[$type][$name][$key] = $value; } } } function addEvent( $name, $function ){ $this->_events[$name] = $function; } function fireEvent( $name, $args=null, $ret=null ){ if( array_key_exists( $name, $this->_events ) ){ return call_user_func_array( array( $this, $this->_events[$name] ), $args ); } return $this->_result; } function getItems( $relative, $args ){ $files = Manager::getFiles( $relative, '\.(?i)(' . str_replace( ',', '|', $this->getFileTypes( 'list' ) ) . ')$' ); $folders = Manager::getFolders( $relative ); $folderArray = array(); $fileArray = array(); if( $folders ){ foreach( $folders as $folder ){ $classes = array(); $classes[] = is_writable( Utils::makePath( $this->getBaseDir(), utf8_decode( $folder['url'] ) ) ) || $this->isFtp() ? 'writable' : 'notwritable'; $classes[] = preg_match( '/[^a-zA-Z0-9:\.\_\-]/', $folder['name'] ) ? 'notsafe' : 'safe'; $folderArray[] = array( 'name' => $folder['name'], 'id' => $folder['url'], 'classes' => implode( ' ', $classes ) ); } } if( $files ){ foreach( $files as $file ){ $classes = array(); $classes[] = is_writable( Utils::makePath( $this->getBaseDir(), utf8_decode( $file['url'] ) ) ) || $this->isFtp() ? 'writable' : 'notwritable'; $classes[] = preg_match( '/[^a-zA-Z0-9\.\_\-]/', $file['name'] ) ? 'notsafe' : 'safe'; $fileArray[] = array( 'name' => $file['name'], 'id' => $file['url'], 'classes' => implode( ' ', $classes ) ); } } $result = array( 'folders' => $folderArray, 'files' => $fileArray ); // Fire Event passing result as reference $this->fireEvent( 'onGetItems', array( &$result, $args ) ); return $result; } function getFileIcon( $ext ){ if( JFile::exists( JCE_LIBRARIES . '/img/icons/' . $ext . '.gif' )){ return $this->image( 'libraries.icons/' . $ext . '.gif' ); }elseif( JFile::exists( $this->getPluginPath() . '/img/icons/' . $ext . '.gif' )){ return $this->image( 'plugins.icons/' . $ext . '.gif' ); }else{ return $this->image( 'libraries.icons/def.gif' ); } } function loadBrowser(){ jimport('joomla.application.component.view'); $browser = new JView( $config = array( 'base_path' => JCE_LIBRARIES, 'layout' => 'browser' ) ); $browser->assign( 'action', $this->getFormAction() ); $browser->display(); } /** * Upload a file. * @return array $error on failure or uploaded file name on success */ function upload(){ $file = JRequest::getVar( 'Filedata', '', 'files', 'array' ); $dir = JRequest::getVar( 'upload-dir', '' ); $overwrite = JRequest::getInt( 'upload-overwrite', 0 ); $name = JRequest::getVar( 'upload-name' ); $flash = JRequest::getInt( 'flash', 0 ); $this->_result = array( 'error' => true, 'result' => '' ); if( isset( $file['name'] ) ){ jimport('joomla.filesystem.file' ); $max_size = intval( $this->getSharedParam( 'max_size', '1024' ) )*1024; $allowable = $this->getFileTypes( 'array' ); $extension = strtolower( JFile::getExt( $file['name'] ) ); if( !$name ){ $name = JFile::stripExt( $file['name'] ); } $path = Utils::makePath( $this->getBaseDir(), rawurldecode( $dir ) ); $dest = Utils::makePath( $path, Utils::makeSafe( $name . '.' . $extension ) ); // Begin conditions if( $file['size'] > $max_size ){ if( !$flash ){ $this->_result['text'] = JText::_('Upload Size Error'); }else{ header('HTTP/1.0 400 File size exceeds maximum size'); echo JText::_('Upload Size Error'); } }elseif( !in_array( $extension, $allowable ) ){ if( !$flash ){ $this->_result['text'] = JText::_('Upload Extension Error'); }else{ header('HTTP/1.0 415 Unsupported Media Type'); echo JText::_('Upload Extension Error'); } }else{ if( $overwrite ){ while( JFile::exists( $dest ) ){ $name .= '_copy'; $dest = Utils::makePath( $path, Utils::makeSafe( $name . '.' . $extension ) ); } } if( !JFile::upload( $file['tmp_name'], $dest ) ){ if( !$flash ){ $this->_result['text'] = JText::_('Upload Error'); }else{ header('HTTP/1.0 400 Bad Request'); echo JText::_('Upload Error'); } }else{ if( !JFile::exists( $dest ) ){ if( !$flash ){ $this->_result['text'] = JText::_('Upload Error'); }else{ header('HTTP/1.0 400 Bad Request'); echo JText::_('Upload Error'); } }else{ if( !$flash ){ $this->_result['text'] = basename( $dest ); $this->_result['error'] = false; } $this->_result = $this->fireEvent('onUpload', array( $dest ) ); } } } } return $this->returnResult(); } /** * Delete the relative file(s). * @param $files the relative path to the file name or comma seperated list of multiple paths. * @return string $error on failure. */ function fileDelete( $files ){ jimport('joomla.filesystem.file'); $files = explode( ",", rawurldecode( $files ) ); foreach( $files as $file ){ $path = Utils::makePath( $this->getBaseDir(), utf8_decode( $file ) ); if( JFile::exists( $path ) ){ if( @!JFile::delete( $path ) ){ $this->_result['error'] = JText::_('Delete File Error'); }else{ $this->_result = $this->fireEvent('onFileDelete', array( rawurldecode( $file ) ) ); } } } return $this->returnResult(); } /** * Delete a folder * @param string $relative The relative path of the folder to delete * @return string $error on failure */ function folderDelete( $relative ){ jimport('joomla.filesystem.folder'); $folder = Utils::makePath( $this->getBaseDir(), utf8_decode( rawurldecode( $relative ) ) ); if( Utils::countFiles( $folder, '^[(index.html)]' ) != 0 || Utils::countDirs( $folder ) != 0 ){ $this->_result['error'] = JText::_('Folder Not Empty'); }else{ if( !@JFolder::delete( $folder ) ){ $this->_result['error'] = JText::_('Delete Folder Error'); }else{ $this->_result = $this->fireEvent('onFolderDelete'); } } return $this->returnResult(); } /* * Rename a file. * @param string $src The relative path of the source file * @param string $dest The name of the new file * @return string $error */ function fileRename( $src, $dest ){ jimport('joomla.filesystem.file'); $src = Utils::makePath( $this->getBaseDir(), utf8_decode( rawurldecode( $src ) ) ); $dir = dirname( $src ); $ext = JFile::getExt( $src ); $dest = Utils::makePath( $dir, $dest.'.'.$ext ); if( !JFile::move( $src, $dest ) ){ $this->_result['error'] = JText::_('Rename File Error'); }else{ $this->_result = $this->fireEvent('onFileRename'); } return $this->returnResult(); } /* * Rename a folder. * @param string $src The relative path of the source file * @param string $dest The name of the new folder * @return array $error */ function folderRename( $src, $dest ){ jimport('joomla.filesystem.folder'); $src = Utils::makePath( $this->getBaseDir(), utf8_decode( rawurldecode( $src ) ) ); $dir = dirname( $src ); $dest = Utils::makePath( $dir, $dest ); if( !JFolder::move( $src, $dest ) ){ $this->_result['error'] = JText::_('Rename Folder Error'); }else{ $this->_result = $this->fireEvent('onFolderRename'); } return $this->returnResult(); } /* * Copy a file. * @param string $files The relative file or comma seperated list of files * @param string $dest The relative path of the destination dir * @return string $error on failure */ function fileCopy( $files, $dest ){ jimport('joomla.filesystem.file'); $files = explode( ",", rawurldecode( $files ) ); foreach( $files as $file ){ $filesrc = Utils::makePath( $this->getBaseDir(), utf8_decode( $file ) ); $filedest = Utils::makePath( $this->getBaseDir(), Utils::makePath( $dest, basename( $file ) ) ); if( !JFile::copy( $filesrc, $filedest ) ){ $this->_result['error'] = JText::_('Copy File Error'); }else{ $this->_result = $this->fireEvent('onFileCopy'); } } return $this->returnResult(); } /* * Copy a file. * @param string $files The relative file or comma seperated list of files * @param string $dest The relative path of the destination dir * @return string $error on failure */ function fileMove( $files, $dest ){ jimport('joomla.filesystem.file'); $files = explode( ",", rawurldecode( $files ) ); foreach( $files as $file ){ $filesrc = Utils::makePath( $this->getBaseDir(), utf8_decode( $file ) ); $filedest = Utils::makePath( $this->getBaseDir(), Utils::makePath( $dest, basename( $file ) ) ); if( !JFile::move( $filesrc, $filedest ) ){ $this->_result['error'] = JText::_('Move File Error'); }else{ $this->_result = $this->fireEvent('onFileMove'); } } return $this->returnResult(); } /** * New folder base function. A wrapper for the JFolder::create function * @param string $folder The folder to create * @return boolean true on success */ function folderCreate( $folder ){ jimport('joomla.filesystem.folder'); jimport('joomla.filesystem.file'); if( @JFolder::create( $folder ) ){ $html = "\n\n \n"; $file = $folder .DS. "index.html"; @JFile::write( $file, $html ); }else{ return false; } return true; } /** * New folder * @param string $dir The base dir * @param string $new_dir The folder to be created * @return string $error on failure */ function folderNew( $dir, $new ){ $dir = Utils::makePath( utf8_decode( rawurldecode( $dir ) ), Utils::makeSafe( $new ) ); $dir = Utils::makePath( $this->getBaseDir(), $dir ); if( !Manager::folderCreate( $dir ) ){ $this->_result['error'] = JText::_('New Folder Error'); }else{ $this->_result = $this->fireEvent('onFolderNew'); } return $this->returnResult(); } } ?>