Line 37: | Line 37: | ||
Let's write a plugin that adds a new server side command to the connector. | Let's write a plugin that adds a new server side command to the connector. | ||
+ | |||
+ | For the sake of simplicity, we'll first create a simple '''plugin.php''' that just does exactly what we need: | ||
+ | |||
+ | <source lang="php"> | ||
+ | <?php | ||
+ | |||
+ | // Include base XML command handler | ||
+ | require_once CKFINDER_CONNECTOR_LIB_DIR . "/CommandHandler/XmlCommandHandlerBase.php"; | ||
+ | |||
+ | // Since we will send a XML response, we'll extend the XmlCommandHandler | ||
+ | class CKFinder_Connector_CommandHandler_FileSize extends CKFinder_Connector_CommandHandler_XmlCommandHandlerBase | ||
+ | { | ||
+ | // The buildXml method is used to construct an XML response | ||
+ | function buildXml() | ||
+ | { | ||
+ | $fileName = $_GET["fileName"]; | ||
+ | $filePath = CKFinder_Connector_Utils_FileSystem::combinePaths($this->_currentFolder->getServerPath(), $fileName); | ||
+ | |||
+ | // Adding a <FileSize> element to the XML response. | ||
+ | $oNode = new Ckfinder_Connector_Utils_XmlNode("FileSize"); | ||
+ | $oNode->addAttribute("size", filesize($filePath)); | ||
+ | $this->_connectorNode->addChild($oNode); | ||
+ | } | ||
+ | |||
+ | // Register the "FileSize" command | ||
+ | function onBeforeExecuteCommand( &$command ) | ||
+ | { | ||
+ | if ( $command == 'FileSize' ) | ||
+ | { | ||
+ | $this->sendResponse(); | ||
+ | // false = stop further execution. | ||
+ | return false; | ||
+ | } | ||
+ | |||
+ | return true ; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | $CommandHandler_FileSize = new CKFinder_Connector_CommandHandler_FileSize(); | ||
+ | // Register the onBeforeExecuteCommand method to be called by the BeforeExecuteCommand hook. | ||
+ | $config['Hooks']['BeforeExecuteCommand'][] = array($CommandHandler_FileSize, "onBeforeExecuteCommand"); | ||
+ | </source> | ||
+ | |||
+ | The full source code of a plugin with all necessary security checks: | ||
<source lang="php"> | <source lang="php"> | ||
Line 75: | Line 119: | ||
} | } | ||
− | // Make sure that the file name is really ok and has not been sent by | + | // Make sure that the file name is really ok and has not been sent by a hacker |
if (!CKFinder_Connector_Utils_FileSystem::checkFileName($fileName) || $resourceTypeInfo->checkIsHiddenFile($fileName)) { | if (!CKFinder_Connector_Utils_FileSystem::checkFileName($fileName) || $resourceTypeInfo->checkIsHiddenFile($fileName)) { | ||
$this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_REQUEST); | $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_REQUEST); | ||
Line 88: | Line 132: | ||
$size = filesize($filePath); | $size = filesize($filePath); | ||
+ | // *** The main part of this plugin **** | ||
+ | // Adding a <FileSize> element to the XML response. | ||
$oNode = new Ckfinder_Connector_Utils_XmlNode("FileSize"); | $oNode = new Ckfinder_Connector_Utils_XmlNode("FileSize"); | ||
$oNode->addAttribute("size", $size); | $oNode->addAttribute("size", $size); | ||
Line 93: | Line 139: | ||
} | } | ||
+ | // Register the "FileSize" command | ||
function onBeforeExecuteCommand( &$command ) | function onBeforeExecuteCommand( &$command ) | ||
{ | { | ||
Line 98: | Line 145: | ||
{ | { | ||
$this->sendResponse(); | $this->sendResponse(); | ||
+ | // false = stop further execution. | ||
return false; | return false; | ||
} | } | ||
Line 106: | Line 154: | ||
$CommandHandler_FileSize = new CKFinder_Connector_CommandHandler_FileSize(); | $CommandHandler_FileSize = new CKFinder_Connector_CommandHandler_FileSize(); | ||
+ | // Register the onBeforeExecuteCommand method to be called by the BeforeExecuteCommand hook. | ||
$config['Hooks']['BeforeExecuteCommand'][] = array($CommandHandler_FileSize, "onBeforeExecuteCommand"); | $config['Hooks']['BeforeExecuteCommand'][] = array($CommandHandler_FileSize, "onBeforeExecuteCommand"); | ||
+ | // (Optional) Register a javascript plugin named "dummy" | ||
$config['Plugins'][] = 'dummy'; | $config['Plugins'][] = 'dummy'; | ||
</source> | </source> | ||
{{#CUSTOMTITLE:Writing PHP Plugins}} | {{#CUSTOMTITLE:Writing PHP Plugins}} |
Revision as of 20:13, 17 May 2010
CKFinder functionality can be extended with server side plugins. Althought the full source code of CKFinder server connector is available and it can be changed in any way, a much better way of enhancing CKFinder connector is to create a plugin.
The main advantages of plugins are:
- Upgrades are much easier.
- The plugin code is in a single place.
- Plugins can be easily turned off when are not needed anymore.
Common use cases:
- Adding new server side command (i.e. fileditor and imageresize plugin).
- Working with uploaded file (i.e. watermark plugin).
- Extending the information returned by the Init command (i.e. imageresize plugin).
Contents
Creating a plugin
Step1: Create plugin folder
Create a directory for your plugin inside of the "plugins" directory (by default CKFinder comes with three plugins: dummy, fileeditor, imagreresize). Let's use "myplugin" as the plugin name and use the same name for our new folder.
Step2: Create plugin file
Inside of your plugin's folder ("myplugin") create an empty file named plugin.php.
Step3: Add plugin definition
// Let's create an empty PHP file for now
Step4: Enable plugin
Add an include_once/require_once statement in the PHP configuration file (config.php):
include_once "plugins/myplugin/plugin.php";
Adding new server side command
Let's write a plugin that adds a new server side command to the connector.
For the sake of simplicity, we'll first create a simple plugin.php that just does exactly what we need:
<?php // Include base XML command handler require_once CKFINDER_CONNECTOR_LIB_DIR . "/CommandHandler/XmlCommandHandlerBase.php"; // Since we will send a XML response, we'll extend the XmlCommandHandler class CKFinder_Connector_CommandHandler_FileSize extends CKFinder_Connector_CommandHandler_XmlCommandHandlerBase { // The buildXml method is used to construct an XML response function buildXml() { $fileName = $_GET["fileName"]; $filePath = CKFinder_Connector_Utils_FileSystem::combinePaths($this->_currentFolder->getServerPath(), $fileName); // Adding a <FileSize> element to the XML response. $oNode = new Ckfinder_Connector_Utils_XmlNode("FileSize"); $oNode->addAttribute("size", filesize($filePath)); $this->_connectorNode->addChild($oNode); } // Register the "FileSize" command function onBeforeExecuteCommand( &$command ) { if ( $command == 'FileSize' ) { $this->sendResponse(); // false = stop further execution. return false; } return true ; } } $CommandHandler_FileSize = new CKFinder_Connector_CommandHandler_FileSize(); // Register the onBeforeExecuteCommand method to be called by the BeforeExecuteCommand hook. $config['Hooks']['BeforeExecuteCommand'][] = array($CommandHandler_FileSize, "onBeforeExecuteCommand");
The full source code of a plugin with all necessary security checks:
<?php // A simple protection against calling this file directly. if (!defined('IN_CKFINDER')) exit; // Include base XML command handler require_once CKFINDER_CONNECTOR_LIB_DIR . "/CommandHandler/XmlCommandHandlerBase.php"; // Since we will send a XML response, we'll reuse the XmlCommandHandler class CKFinder_Connector_CommandHandler_FileSize extends CKFinder_Connector_CommandHandler_XmlCommandHandlerBase { // The buildXml method is used to construct an XML response function buildXml() { // A "must have", checking whether the connector is enabled and the basic parameters (like current folder) are safe. $this->checkConnector(); $this->checkRequest(); // Checking ACL permissions, we're just getting an information about a file, so FILE_VIEW permission seems to be ok. if (!$this->_currentFolder->checkAcl(CKFINDER_CONNECTOR_ACL_FILE_VIEW)) { $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_UNAUTHORIZED); } // Make sure we actually received a file name if (!isset($_GET["fileName"])) { $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_NAME); } $fileName = CKFinder_Connector_Utils_FileSystem::convertToFilesystemEncoding($_GET["fileName"]); $resourceTypeInfo = $this->_currentFolder->getResourceTypeConfig(); // Use the resource type configuration object to check whether the extension of a file to check is really allowed. if (!$resourceTypeInfo->checkExtension($fileName)) { $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_EXTENSION); } // Make sure that the file name is really ok and has not been sent by a hacker if (!CKFinder_Connector_Utils_FileSystem::checkFileName($fileName) || $resourceTypeInfo->checkIsHiddenFile($fileName)) { $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_REQUEST); } $filePath = CKFinder_Connector_Utils_FileSystem::combinePaths($this->_currentFolder->getServerPath(), $fileName); if (!file_exists($filePath) || !is_file($filePath)) { $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_FILE_NOT_FOUND); } $size = filesize($filePath); // *** The main part of this plugin **** // Adding a <FileSize> element to the XML response. $oNode = new Ckfinder_Connector_Utils_XmlNode("FileSize"); $oNode->addAttribute("size", $size); $this->_connectorNode->addChild($oNode); } // Register the "FileSize" command function onBeforeExecuteCommand( &$command ) { if ( $command == 'FileSize' ) { $this->sendResponse(); // false = stop further execution. return false; } return true ; } } $CommandHandler_FileSize = new CKFinder_Connector_CommandHandler_FileSize(); // Register the onBeforeExecuteCommand method to be called by the BeforeExecuteCommand hook. $config['Hooks']['BeforeExecuteCommand'][] = array($CommandHandler_FileSize, "onBeforeExecuteCommand"); // (Optional) Register a javascript plugin named "dummy" $config['Plugins'][] = 'dummy';