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 21: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
[hide]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';