From ba7950ec5034a465ae32ba862da8d18244016efc Mon Sep 17 00:00:00 2001 From: cdujeu Date: Fri, 30 Sep 2016 09:01:14 +0200 Subject: [PATCH] Broke XMLWriter into pieces: XMLHelper, XMLFilter and serializer NodeXML. --- .../src/pydio/Core/Controller/Controller.php | 5 +- .../src/pydio/Core/Controller/XMLWriter.php | 527 ------------------ .../Core/Http/Message/JsActionTrigger.php | 1 - .../src/pydio/Core/Http/Message/Message.php | 9 +- .../Core/Http/Message/RegistryMessage.php | 11 +- .../pydio/Core/Http/Message/ReloadMessage.php | 6 +- .../pydio/Core/Http/Message/UserMessage.php | 10 +- .../Response/SerializableResponseStream.php | 5 +- .../src/pydio/Core/PluginFramework/Plugin.php | 6 +- .../src/pydio/Core/Serializer/NodeXML.php | 82 +++ .../src/pydio/Core/Serializer/UserXML.php | 53 ++ .../src/pydio/Core/Utils/Vars/XMLFilter.php | 111 ++++ .../core/src/pydio/Core/Utils/XMLHelper.php | 183 ++++++ .../access.ajxp_conf/src/AbstractManager.php | 4 +- .../access.ajxp_conf/src/PluginsManager.php | 17 +- .../src/RepositoriesManager.php | 13 +- .../access.ajxp_conf/src/RolesManager.php | 4 +- .../plugins/access.ftp/FtpAccessDriver.php | 4 +- .../access.mysql/MysqlAccessDriver.php | 29 +- .../plugins/action.share/src/ShareCenter.php | 9 +- .../src/View/MinisiteRenderer.php | 4 +- .../SessionLoginFrontend.php | 2 +- core/src/plugins/boot.conf/BootConfLoader.php | 8 +- .../core.access/src/Model/NodesDiff.php | 7 +- .../core.access/src/Model/NodesList.php | 44 +- .../plugins/core.ajaxplorer/ajxp_registry.xsd | 1 + .../plugins/core.conf/AbstractConfDriver.php | 7 +- core/src/plugins/core.mq/src/MqManager.php | 2 +- core/src/plugins/gui.ajax/RichClient.php | 6 +- core/src/plugins/meta.svn/SvnManager.php | 74 ++- .../plugins/uploader.html/SimpleUpload.php | 5 +- core/src/plugins/uploader.html/manifest.xml | 8 +- .../plugins/uploader.plupload/Pluploader.php | 4 +- 33 files changed, 612 insertions(+), 649 deletions(-) delete mode 100644 core/src/core/src/pydio/Core/Controller/XMLWriter.php create mode 100644 core/src/core/src/pydio/Core/Serializer/NodeXML.php create mode 100644 core/src/core/src/pydio/Core/Utils/Vars/XMLFilter.php create mode 100644 core/src/core/src/pydio/Core/Utils/XMLHelper.php diff --git a/core/src/core/src/pydio/Core/Controller/Controller.php b/core/src/core/src/pydio/Core/Controller/Controller.php index be355f7c61..ff657c2f0e 100644 --- a/core/src/core/src/pydio/Core/Controller/Controller.php +++ b/core/src/core/src/pydio/Core/Controller/Controller.php @@ -20,6 +20,7 @@ */ namespace Pydio\Core\Controller; +use Pydio\Core\Utils\XMLHelper; use Zend\Diactoros\Response; use Zend\Diactoros\ServerRequestFactory; use Psr\Http\Message\ResponseInterface; @@ -217,7 +218,7 @@ public static function run(ServerRequestInterface $request, &$actionNode = null) && $loggedUser->canWrite($ctx->getRepositoryId()."")){ // Special case of "write only" right : return empty listing, no auth error. $response = new Response(); - $response->getBody()->write(XMLWriter::wrapDocument("")); + $response->getBody()->write(XMLHelper::wrapDocument("")); return $response; }else{ throw new AuthRequiredException("208"); @@ -387,7 +388,7 @@ private static function handleRequest($callback, ServerRequestInterface &$reques $request = $request->withParsedBody($httpVars); if(!empty($result)){ - $response->getBody()->write(XMLWriter::wrapDocument($result)); + $response->getBody()->write(XMLHelper::wrapDocument($result)); $response = $response->withHeader("Content-type", "text/xml; charset=UTF-8"); } } diff --git a/core/src/core/src/pydio/Core/Controller/XMLWriter.php b/core/src/core/src/pydio/Core/Controller/XMLWriter.php deleted file mode 100644 index c156c699ee..0000000000 --- a/core/src/core/src/pydio/Core/Controller/XMLWriter.php +++ /dev/null @@ -1,527 +0,0 @@ - - * This file is part of Pydio. - * - * Pydio is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Pydio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with Pydio. If not, see . - * - * The latest code can be found at . - */ -namespace Pydio\Core\Controller; - -use Pydio\Access\Core\Model\AJXP_Node; -use Pydio\Access\Core\IAjxpWrapperProvider; -use Pydio\Core\Model\ContextInterface; -use Pydio\Core\Services\LocaleService; -use Pydio\Core\Services\ApplicationState; -use Pydio\Core\Utils\Vars\InputFilter; -use Pydio\Core\Utils\Vars\StatHelper; -use Pydio\Core\Utils\Vars\StringHelper; -use Pydio\Core\Services; -use Pydio\Core\Services\ConfService; - - -defined('AJXP_EXEC') or die( 'Access not allowed'); - -/** - * XML output Generator - * @package Pydio - * @subpackage Core - */ -class XMLWriter -{ - /** - * @var bool|string - */ - public static $headerSent = false; - - /** - * Output Headers, XML tag and a root node - * @static - * @param string $docNode - * @param array $attributes - */ - public static function header($docNode="tree", $attributes=array()) - { - if(self::$headerSent !== false && self::$headerSent == $docNode) return ; - if(!ApplicationState::sapiIsCli()){ - header('Content-Type: text/xml; charset=UTF-8'); - header('Cache-Control: no-cache'); - } - print(''); - $attString = ""; - if (count($attributes)) { - foreach ($attributes as $name=>$value) { - $attString.="$name=\"$value\" "; - } - } - self::$headerSent = $docNode; - print("<$docNode $attString>"); - - } - /** - * Outputs a closing root not () - * @static - * @param string $docNode - * @param bool $print - * @return void|string - */ - public static function close($docNode="tree", $print = true) - { - if($print){ - print(""); - return ""; - }else{ - return ""; - } - } - - /** - * Wrap xml inside a ... document, including declaration. - * @param $content - * @param string $docNode - * @param array $attributes - * @return string - */ - public static function wrapDocument($content, $docNode = "tree", $attributes = array()){ - - if(self::$headerSent !== false && self::$headerSent == $docNode) { - return $content; - } - //header('Content-Type: text/xml; charset=UTF-8'); - //header('Cache-Control: no-cache'); - $buffer = ''; - $attString = ""; - if (count($attributes)) { - foreach ($attributes as $name=>$value) { - $attString.="$name=\"$value\" "; - } - } - self::$headerSent = $docNode; - $buffer .= "<$docNode $attString>"; - $buffer .= $content; - $buffer .= ""; - return $buffer; - - } - - /** - * @static - * @param string $data - * @param bool $print - * @return string - */ - public static function write($data, $print) - { - if ($print) { - print($data); - return ""; - } else { - return $data; - } - } - - /** - * Ouput the tag - * @static - * @param integer $count - * @param integer $currentPage - * @param integer $totalPages - * @param integer $dirsCount - * @param null $remoteSortAttributes - * @param bool $print - * @return void|string - */ - public static function renderPaginationData($count, $currentPage, $totalPages, $dirsCount = -1, $remoteSortAttributes = null, $print = true) - { - $remoteSortString = ""; - if (is_array($remoteSortAttributes)) { - foreach($remoteSortAttributes as $k => $v) $remoteSortString .= " $k='$v'"; - } - $string = ''; - return XMLWriter::write($string, $print); - } - - /** - * Prints out the XML headers and preamble, then an open node - * @static - * @param $nodeName - * @param $nodeLabel - * @param $isLeaf - * @param array $metaData - * @return void - */ - public static function renderHeaderNode($nodeName, $nodeLabel, $isLeaf, $metaData = array()) - { - if(!ApplicationState::sapiIsCli()) { - header('Content-Type: text/xml; charset=UTF-8'); - header('Cache-Control: no-cache'); - } - print(''); - self::$headerSent = "tree"; - XMLWriter::renderNode($nodeName, $nodeLabel, $isLeaf, $metaData, false); - } - - /** - * @static - * @param \Pydio\Access\Core\Model\AJXP_Node $ajxpNode - * @return void - */ - public static function renderAjxpHeaderNode($ajxpNode) - { - if(!ApplicationState::sapiIsCli()) { - header('Content-Type: text/xml; charset=UTF-8'); - header('Cache-Control: no-cache'); - } - print(''); - self::$headerSent = "tree"; - self::renderAjxpNode($ajxpNode, false); - } - - /** - * The basic node - * @static - * @param string $nodeName - * @param string $nodeLabel - * @param bool $isLeaf - * @param array $metaData - * @param bool $close - * @param bool $print - * @return void|string - */ - public static function renderNode($nodeName, $nodeLabel, $isLeaf, $metaData = array(), $close=true, $print = true) - { - $string = " $value) { - if(InputFilter::detectXSS($value)) $value = "XSS Detected!"; - $value = StringHelper::xmlEntities($value, true); - $string .= " $key=\"$value\""; - } - if ($close) { - $string .= "/>"; - } else { - $string .= ">"; - } - return XMLWriter::write($string, $print); - } - - /** - * @static - * @param \Pydio\Access\Core\Model\AJXP_Node $ajxpNode - * @param bool $close - * @param bool $print - * @return void|string - */ - public static function renderAjxpNode($ajxpNode, $close = true, $print = true) - { - return XMLWriter::renderNode( - $ajxpNode->getPath(), - $ajxpNode->getLabel(), - $ajxpNode->isLeaf(), - $ajxpNode->getNodeInfoMeta(), - $close, - $print); - } - - /** - * Dynamically replace XML keywords with their live values. - * AJXP_SERVER_ACCESS, AJXP_MIMES_*,AJXP_ALL_MESSAGES, etc. - * @static - * @param string $xml - * @param bool $stripSpaces - * @return mixed - */ - public static function replaceAjxpXmlKeywords($xml, $stripSpaces = false) - { - $messages = LocaleService::getMessages(); - $confMessages = LocaleService::getConfigMessages(); - $matches = array(); - $xml = str_replace("AJXP_APPLICATION_TITLE", ConfService::getGlobalConf("APPLICATION_TITLE"), $xml); - $xml = str_replace("AJXP_MIMES_EDITABLE", StatHelper::getAjxpMimes("editable"), $xml); - $xml = str_replace("AJXP_MIMES_IMAGE", StatHelper::getAjxpMimes("image"), $xml); - $xml = str_replace("AJXP_MIMES_AUDIO", StatHelper::getAjxpMimes("audio"), $xml); - $xml = str_replace("AJXP_MIMES_ZIP", StatHelper::getAjxpMimes("zip"), $xml); - $authDriver = ConfService::getAuthDriverImpl(); - if ($authDriver != NULL) { - $loginRedirect = $authDriver->getLoginRedirect(); - $xml = str_replace("AJXP_LOGIN_REDIRECT", ($loginRedirect!==false?"'".$loginRedirect."'":"false"), $xml); - } - $xml = str_replace("AJXP_REMOTE_AUTH", "false", $xml); - $xml = str_replace("AJXP_NOT_REMOTE_AUTH", "true", $xml); - $xml = str_replace("AJXP_ALL_MESSAGES", "MessageHash=".json_encode(LocaleService::getMessages()).";", $xml); - - if (preg_match_all("/AJXP_MESSAGE(\[.*?\])/", $xml, $matches, PREG_SET_ORDER)) { - foreach ($matches as $match) { - $messId = str_replace("]", "", str_replace("[", "", $match[1])); - $xml = str_replace("AJXP_MESSAGE[$messId]", $messages[$messId], $xml); - } - } - if (preg_match_all("/CONF_MESSAGE(\[.*?\])/", $xml, $matches, PREG_SET_ORDER)) { - foreach ($matches as $match) { - $messId = str_replace(array("[", "]"), "", $match[1]); - $message = $messId; - if (array_key_exists($messId, $confMessages)) { - $message = $confMessages[$messId]; - } - $xml = str_replace("CONF_MESSAGE[$messId]", StringHelper::xmlEntities($message), $xml); - } - } - if (preg_match_all("/MIXIN_MESSAGE(\[.*?\])/", $xml, $matches, PREG_SET_ORDER)) { - foreach ($matches as $match) { - $messId = str_replace(array("[", "]"), "", $match[1]); - $message = $messId; - if (array_key_exists($messId, $confMessages)) { - $message = $confMessages[$messId]; - } - $xml = str_replace("MIXIN_MESSAGE[$messId]", StringHelper::xmlEntities($message), $xml); - } - } - if ($stripSpaces) { - $xml = preg_replace("/[\n\r]?/", "", $xml); - $xml = preg_replace("/\t/", " ", $xml); - } - $xml = str_replace(array('xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"','xsi:noNamespaceSchemaLocation="file:../core.ajaxplorer/ajxp_registry.xsd"'), "", $xml); - $tab = array(&$xml); - Controller::applyIncludeHook("xml.filter", $tab); - return $xml; - } - /** - * Send a XML instruction for refreshing the list - * @static - * @param string $nodePath - * @param string $pendingSelection - * @param bool $print - * @return string - */ - public static function reloadDataNode($nodePath="", $pendingSelection="", $print = true) - { - $nodePath = StringHelper::xmlEntities($nodePath, true); - $pendingSelection = StringHelper::xmlEntities($pendingSelection, true); - return XMLWriter::write("", $print); - } - - /** - * Outputs a tag - * @static - * @param bool $print - * @return string - */ - public static function requireAuth($print = true) - { - return XMLWriter::write("", $print); - } - - /** - * List all bookmmarks as XML - * @static - * @param $allBookmarks - * @param ContextInterface $context - * @param bool $print - * @param string $format legacy|node_list - * @return string - */ - public static function writeBookmarks($allBookmarks, $context, $print = true, $format = "legacy") - { - $driver = false; - $repository = $context->getRepository(); - if ($format == "node_list") { - $driver = $repository->getDriverInstance($context); - if (!($driver instanceof IAjxpWrapperProvider)) { - $driver = false; - } - } - $buffer = ""; - foreach ($allBookmarks as $bookmark) { - $path = ""; $title = ""; - if (is_array($bookmark)) { - $path = $bookmark["PATH"]; - $title = $bookmark["TITLE"]; - } else if (is_string($bookmark)) { - $path = $bookmark; - $title = basename($bookmark); - } - if ($format == "node_list") { - if ($driver) { - $node = new AJXP_Node($context->getUrlBase().$path); - $buffer .= XMLWriter::renderAjxpNode($node, true, false); - } else { - $buffer .= XMLWriter::renderNode($path, $title, false, array('icon' => "mime_empty.png"), true, false); - } - } else { - $buffer .= ""; - } - } - if($print) { - print $buffer; - return null; - } else { - return $buffer; - } - } - /** - * Utilitary for generating a tag for the FilesList component - * @static - * @param $config - * @return void - */ - public static function sendFilesListComponentConfig($config) - { - if (is_string($config)) { - print("$config"); - } - } - - /** - * Simple XML element build from associative array. Can pass specific $children for nested elements. - * @param string $tagName - * @param array $attributes - * @param string $xmlChildren - * @return string - */ - public static function toXmlElement($tagName, $attributes, $xmlChildren = ""){ - $buffer = "<$tagName "; - foreach ($attributes as $attName => $attValue){ - $buffer.= "$attName=\"". StringHelper::xmlEntities($attValue) ."\" "; - } - if(!strlen($xmlChildren)) { - $buffer .= "/>"; - } else{ - $buffer .= ">".$xmlChildren.""; - } - return $buffer; - } - /** - * Send a success or error message to the client. - * @static - * @param $logMessage - * @param $errorMessage - * @param bool $print - * @return string - */ - public static function sendMessage($logMessage, $errorMessage, $print = true) - { - if ($errorMessage == null) { - $messageType = "SUCCESS"; - $message = StringHelper::xmlContentEntities($logMessage); - } else { - $messageType = "ERROR"; - $message = StringHelper::xmlContentEntities($errorMessage); - } - return XMLWriter::write("".$message."", $print); - } - - /** - * Create plain PHP associative array from XML. - * - * Example usage: - * $xmlNode = simplexml_load_file('example.xml'); - * $arrayData = xmlToArray($xmlNode); - * echo json_encode($arrayData); - * - * @param \DOMNode $domXml The dom node to load - * @param array $options Associative array of options - * @return array - * @link http://outlandishideas.co.uk/blog/2012/08/xml-to-json/ More info - * @author Tamlyn Rhodes - * @license http://creativecommons.org/publicdomain/mark/1.0/ Public Domain - */ - public static function xmlToArray($domXml, $options = array()) { - $xml = simplexml_import_dom($domXml); - $defaults = array( - 'namespaceSeparator' => ':',//you may want this to be something other than a colon - 'attributePrefix' => '@', //to distinguish between attributes and nodes with the same name - 'alwaysArray' => array(), //array of xml tag names which should always become arrays - 'autoArray' => true, //only create arrays for tags which appear more than once - 'textContent' => '$', //key used for the text content of elements - 'autoText' => true, //skip textContent key if node has no attributes or child nodes - 'keySearch' => false, //optional search and replace on tag and attribute names - 'keyReplace' => false //replace values for above search values (as passed to str_replace()) - ); - $options = array_merge($defaults, $options); - $namespaces = $xml->getDocNamespaces(); - $namespaces[''] = null; //add base (empty) namespace - - //get attributes from all namespaces - $attributesArray = array(); - foreach ($namespaces as $prefix => $namespace) { - foreach ($xml->attributes($namespace) as $attributeName => $attribute) { - //replace characters in attribute name - if ($options['keySearch']) $attributeName = - str_replace($options['keySearch'], $options['keyReplace'], $attributeName); - $attributeKey = $options['attributePrefix'] - . ($prefix ? $prefix . $options['namespaceSeparator'] : '') - . $attributeName; - $attributesArray[$attributeKey] = (string)$attribute; - } - } - - //get child nodes from all namespaces - $tagsArray = array(); - foreach ($namespaces as $prefix => $namespace) { - foreach ($xml->children($namespace) as $childXml) { - //recurse into child nodes - $childArray = self::xmlToArray($childXml, $options); - list($childTagName, $childProperties) = each($childArray); - - //replace characters in tag name - if ($options['keySearch']) $childTagName = - str_replace($options['keySearch'], $options['keyReplace'], $childTagName); - //add namespace prefix, if any - if ($prefix) $childTagName = $prefix . $options['namespaceSeparator'] . $childTagName; - - if (!isset($tagsArray[$childTagName])) { - //only entry with this key - //test if tags of this type should always be arrays, no matter the element count - $tagsArray[$childTagName] = - in_array($childTagName, $options['alwaysArray']) || !$options['autoArray'] - ? array($childProperties) : $childProperties; - } elseif ( - is_array($tagsArray[$childTagName]) && array_keys($tagsArray[$childTagName]) - === range(0, count($tagsArray[$childTagName]) - 1) - ) { - //key already exists and is integer indexed array - $tagsArray[$childTagName][] = $childProperties; - } else { - //key exists so convert to integer indexed array with previous value in position 0 - $tagsArray[$childTagName] = array($tagsArray[$childTagName], $childProperties); - } - } - } - - //get text content of node - $textContentArray = array(); - $plainText = trim((string)$xml); - if ($plainText !== '') $textContentArray[$options['textContent']] = $plainText; - - //stick it all together - $propertiesArray = !$options['autoText'] || $attributesArray || $tagsArray || ($plainText === '') - ? array_merge($attributesArray, $tagsArray, $textContentArray) : $plainText; - - //return node as array - return array( - $xml->getName() => $propertiesArray - ); - } - -} diff --git a/core/src/core/src/pydio/Core/Http/Message/JsActionTrigger.php b/core/src/core/src/pydio/Core/Http/Message/JsActionTrigger.php index 7021560eda..bca1370cdf 100644 --- a/core/src/core/src/pydio/Core/Http/Message/JsActionTrigger.php +++ b/core/src/core/src/pydio/Core/Http/Message/JsActionTrigger.php @@ -20,7 +20,6 @@ */ namespace Pydio\Core\Http\Message; -use Pydio\Core\Controller\XMLWriter; use Pydio\Core\Http\Response\XMLSerializableResponseChunk; defined('AJXP_EXEC') or die('Access not allowed'); diff --git a/core/src/core/src/pydio/Core/Http/Message/Message.php b/core/src/core/src/pydio/Core/Http/Message/Message.php index 36da7c161f..68e03bc578 100644 --- a/core/src/core/src/pydio/Core/Http/Message/Message.php +++ b/core/src/core/src/pydio/Core/Http/Message/Message.php @@ -20,9 +20,9 @@ */ namespace Pydio\Core\Http\Message; -use Pydio\Core\Controller\XMLWriter; use Pydio\Core\Http\Response\JSONSerializableResponseChunk; use Pydio\Core\Http\Response\XMLSerializableResponseChunk; +use Pydio\Core\Utils\Vars\StringHelper; defined('AJXP_EXEC') or die('Access not allowed'); @@ -52,7 +52,12 @@ public function __construct($message) */ public function toXML() { - return XMLWriter::sendMessage($this->message, $this->message); + if(is_string($this->message)){ + $m = $this->message; + }else{ + $m = json_encode($this->message); + } + return "".StringHelper::xmlContentEntities($m).""; } /** diff --git a/core/src/core/src/pydio/Core/Http/Message/RegistryMessage.php b/core/src/core/src/pydio/Core/Http/Message/RegistryMessage.php index d41da2843f..d535329dd3 100644 --- a/core/src/core/src/pydio/Core/Http/Message/RegistryMessage.php +++ b/core/src/core/src/pydio/Core/Http/Message/RegistryMessage.php @@ -20,10 +20,11 @@ */ namespace Pydio\Core\Http\Message; -use Pydio\Core\Controller\XMLWriter; +use Pydio\Core\Utils\Vars\XMLFilter; use Pydio\Core\Http\Response\JSONSerializableResponseChunk; use Pydio\Core\Http\Response\XMLDocSerializableResponseChunk; use Pydio\Core\Services\ApplicationState; +use Pydio\Core\Utils\XMLHelper; defined('AJXP_EXEC') or die('Access not allowed'); @@ -94,14 +95,14 @@ public function toXML() } $nodes = $this->xPathObject->query($this->xPath); if ($nodes->length) { - $xml .= XMLWriter::replaceAjxpXmlKeywords($this->registry->saveXML($nodes->item(0))); + $xml .= XMLFilter::resolveKeywords($this->registry->saveXML($nodes->item(0))); } $xml .= ""; } else { ApplicationState::safeIniSet("zlib.output_compression", "4096"); - $xml = XMLWriter::replaceAjxpXmlKeywords($this->registry->saveXML()); + $xml = XMLFilter::resolveKeywords($this->registry->saveXML()); } $this->renderedXML = $xml; @@ -120,11 +121,11 @@ public function jsonSerializableData() $nodes = $this->xPathObject->query($this->xPath); $data = []; if($nodes->length){ - $data = XMLWriter::xmlToArray($nodes->item(0)); + $data = XMLHelper::xmlToArray($nodes->item(0)); } return $data; }else{ - return XMLWriter::xmlToArray($this->registry); + return XMLHelper::xmlToArray($this->registry); } } diff --git a/core/src/core/src/pydio/Core/Http/Message/ReloadMessage.php b/core/src/core/src/pydio/Core/Http/Message/ReloadMessage.php index 3502486374..d726c36c3e 100644 --- a/core/src/core/src/pydio/Core/Http/Message/ReloadMessage.php +++ b/core/src/core/src/pydio/Core/Http/Message/ReloadMessage.php @@ -20,9 +20,9 @@ */ namespace Pydio\Core\Http\Message; -use Pydio\Core\Controller\XMLWriter; use Pydio\Core\Http\Response\JSONSerializableResponseChunk; use Pydio\Core\Http\Response\XMLSerializableResponseChunk; +use Pydio\Core\Utils\Vars\StringHelper; defined('AJXP_EXEC') or die('Access not allowed'); @@ -68,6 +68,8 @@ public function jsonSerializableKey() */ public function toXML() { - return XMLWriter::reloadDataNode($this->dataNode, $this->pendingSelection, false); + $nodePath = StringHelper::xmlEntities($this->dataNode, true); + $pendingSelection = StringHelper::xmlEntities($this->pendingSelection, true); + return ""; } } \ No newline at end of file diff --git a/core/src/core/src/pydio/Core/Http/Message/UserMessage.php b/core/src/core/src/pydio/Core/Http/Message/UserMessage.php index cb43b93e8d..464f0a3703 100644 --- a/core/src/core/src/pydio/Core/Http/Message/UserMessage.php +++ b/core/src/core/src/pydio/Core/Http/Message/UserMessage.php @@ -20,9 +20,9 @@ */ namespace Pydio\Core\Http\Message; -use Pydio\Core\Controller\XMLWriter; use Pydio\Core\Http\Response\JSONSerializableResponseChunk; use Pydio\Core\Http\Response\XMLSerializableResponseChunk; +use Pydio\Core\Utils\Vars\StringHelper; defined('AJXP_EXEC') or die('Access not allowed'); @@ -53,7 +53,13 @@ public function __construct($message, $level=LOG_LEVEL_INFO) */ public function toXML() { - return XMLWriter::sendMessage($this->level == LOG_LEVEL_INFO?$this->message:null, $this->level == LOG_LEVEL_ERROR?$this->message:null, false); + if ($this->level === LOG_LEVEL_INFO) { + $messageType = "SUCCESS"; + } else { + $messageType = strtoupper($this->level); + } + $message = StringHelper::xmlContentEntities($this->message); + return "".$message.""; } /** diff --git a/core/src/core/src/pydio/Core/Http/Response/SerializableResponseStream.php b/core/src/core/src/pydio/Core/Http/Response/SerializableResponseStream.php index 8b532d095d..70c0ac468d 100644 --- a/core/src/core/src/pydio/Core/Http/Response/SerializableResponseStream.php +++ b/core/src/core/src/pydio/Core/Http/Response/SerializableResponseStream.php @@ -22,8 +22,9 @@ use Psr\Http\Message\StreamInterface; -use Pydio\Core\Controller\XMLWriter; +use Pydio\Core\Utils\Vars\XMLFilter; use Pydio\Core\Http\Message\UserMessage; +use Pydio\Core\Utils\XMLHelper; defined('AJXP_EXEC') or die('Access not allowed'); @@ -190,7 +191,7 @@ protected function serializeData($data, $serializer){ } if($wrap){ - $output = XMLWriter::wrapDocument($buffer); + $output = XMLHelper::wrapDocument($buffer); }else{ if(substr($buffer, 0, 5) !== "".$buffer; diff --git a/core/src/core/src/pydio/Core/PluginFramework/Plugin.php b/core/src/core/src/pydio/Core/PluginFramework/Plugin.php index ed0fb31382..df3f5f3fe0 100644 --- a/core/src/core/src/pydio/Core/PluginFramework/Plugin.php +++ b/core/src/core/src/pydio/Core/PluginFramework/Plugin.php @@ -26,7 +26,7 @@ use Pydio\Core\Services\ConfService; -use Pydio\Core\Controller\XMLWriter; +use Pydio\Core\Utils\Vars\XMLFilter; use Pydio\Log\Core\Logger; defined('AJXP_EXEC') or die( 'Access not allowed'); @@ -460,7 +460,7 @@ public function getManifestLabel() { if($this->manifestXML != null) $this->unserializeManifest(); $l = $this->xPath->query("@label", $this->manifestDoc->documentElement); - if($l->length) return XMLWriter::replaceAjxpXmlKeywords($l->item(0)->nodeValue); + if($l->length) return XMLFilter::resolveKeywords($l->item(0)->nodeValue); else return $this->id; } /** @@ -471,7 +471,7 @@ public function getManifestDescription() { if($this->manifestXML != null) $this->unserializeManifest(); $l = $this->xPath->query("@description", $this->manifestDoc->documentElement); - if($l->length) return XMLWriter::replaceAjxpXmlKeywords($l->item(0)->nodeValue); + if($l->length) return XMLFilter::resolveKeywords($l->item(0)->nodeValue); else return ""; } diff --git a/core/src/core/src/pydio/Core/Serializer/NodeXML.php b/core/src/core/src/pydio/Core/Serializer/NodeXML.php new file mode 100644 index 0000000000..93443d10ca --- /dev/null +++ b/core/src/core/src/pydio/Core/Serializer/NodeXML.php @@ -0,0 +1,82 @@ + + * This file is part of Pydio. + * + * Pydio is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Pydio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Pydio. If not, see . + * + * The latest code can be found at . + */ +namespace Pydio\Core\Serializer; + +use Pydio\Core\Utils\Vars\InputFilter; +use Pydio\Core\Utils\Vars\StringHelper; + +defined('AJXP_EXEC') or die('Access not allowed'); + +/** + * XML Serializer for AJXP_Node objects + * @package Pydio\Core\Serializer + */ +class NodeXML +{ + + /** + * The basic node + * @static + * @param string $nodeName + * @param string $nodeLabel + * @param bool $isLeaf + * @param array $metaData + * @param bool $close + * @return string|void + * @internal param bool $print + */ + public static function toNode($nodeName, $nodeLabel, $isLeaf, $metaData = array(), $close = true) + { + $string = " $value) { + if (InputFilter::detectXSS($value)) $value = "XSS Detected!"; + $value = StringHelper::xmlEntities($value, true); + $string .= " $key=\"$value\""; + } + if ($close) { + $string .= "/>"; + } else { + $string .= ">"; + } + return $string; + } + + /** + * @static + * @param \Pydio\Access\Core\Model\AJXP_Node $node + * @param bool $close + * @return string|void + */ + public static function toXML($node, $close = true) + { + return NodeXML::toNode($node->getPath(), $node->getLabel(), $node->isLeaf(), $node->getNodeInfoMeta(), $close); + } +} \ No newline at end of file diff --git a/core/src/core/src/pydio/Core/Serializer/UserXML.php b/core/src/core/src/pydio/Core/Serializer/UserXML.php index f56bac1855..5f83320280 100644 --- a/core/src/core/src/pydio/Core/Serializer/UserXML.php +++ b/core/src/core/src/pydio/Core/Serializer/UserXML.php @@ -20,11 +20,15 @@ */ namespace Pydio\Core\Serializer; +use Pydio\Access\Core\IAjxpWrapperProvider; +use Pydio\Access\Core\Model\AJXP_Node; +use Pydio\Core\Utils\Vars\XMLFilter; use Pydio\Core\Model\ContextInterface; use Pydio\Core\PluginFramework\PluginsService; use Pydio\Core\Services\ConfService; use Pydio\Core\Services\UsersService; use Pydio\Core\Services\ApplicationState; +use Pydio\Core\Utils\Vars\StringHelper; defined('AJXP_EXEC') or die('Access not allowed'); @@ -34,6 +38,55 @@ */ class UserXML { + /** + * List all bookmmarks as XML + * @static + * @param $allBookmarks + * @param ContextInterface $context + * @param bool $print + * @param string $format legacy|node_list + * @return string + */ + public static function writeBookmarks($allBookmarks, $context, $print = true, $format = "legacy") + { + $driver = false; + $repository = $context->getRepository(); + if ($format == "node_list") { + $driver = $repository->getDriverInstance($context); + if (!($driver instanceof IAjxpWrapperProvider)) { + $driver = false; + } + } + $buffer = ""; + foreach ($allBookmarks as $bookmark) { + $path = ""; + $title = ""; + if (is_array($bookmark)) { + $path = $bookmark["PATH"]; + $title = $bookmark["TITLE"]; + } else if (is_string($bookmark)) { + $path = $bookmark; + $title = basename($bookmark); + } + if ($format == "node_list") { + if ($driver) { + $node = new AJXP_Node($context->getUrlBase() . $path); + $buffer .= NodeXML::toXML($node, true); + } else { + $buffer .= NodeXML::toNode($path, $title, false, array('icon' => "mime_empty.png"), true); + } + } else { + $buffer .= ""; + } + } + if ($print) { + print $buffer; + return null; + } else { + return $buffer; + } + } + /** * Extract all the user data and put it in XML * @param ContextInterface $ctx diff --git a/core/src/core/src/pydio/Core/Utils/Vars/XMLFilter.php b/core/src/core/src/pydio/Core/Utils/Vars/XMLFilter.php new file mode 100644 index 0000000000..6c9ca1f13c --- /dev/null +++ b/core/src/core/src/pydio/Core/Utils/Vars/XMLFilter.php @@ -0,0 +1,111 @@ + + * This file is part of Pydio. + * + * Pydio is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Pydio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Pydio. If not, see . + * + * The latest code can be found at . + */ +namespace Pydio\Core\Utils\Vars; + +use Pydio\Access\Core\Model\AJXP_Node; +use Pydio\Access\Core\IAjxpWrapperProvider; +use Pydio\Core\Controller\Controller; +use Pydio\Core\Model\ContextInterface; +use Pydio\Core\Serializer\NodeXML; +use Pydio\Core\Services\LocaleService; +use Pydio\Core\Services\ApplicationState; +use Pydio\Core\Utils\Vars\InputFilter; +use Pydio\Core\Utils\Vars\StatHelper; +use Pydio\Core\Utils\Vars\StringHelper; +use Pydio\Core\Services; +use Pydio\Core\Services\ConfService; +use Pydio\Core\Utils\XMLHelper; + + +defined('AJXP_EXEC') or die( 'Access not allowed'); + +/** + * Filters XML data with pydio specific keywords + * @package Pydio + * @subpackage Core + */ +class XMLFilter +{ + + /** + * Dynamically replace XML keywords with their live values. + * AJXP_SERVER_ACCESS, AJXP_MIMES_*,AJXP_ALL_MESSAGES, etc. + * @static + * @param string $xml + * @param bool $stripSpaces + * @return mixed + */ + public static function resolveKeywords($xml, $stripSpaces = false) + { + $messages = LocaleService::getMessages(); + $confMessages = LocaleService::getConfigMessages(); + $matches = array(); + $xml = str_replace("AJXP_APPLICATION_TITLE", ConfService::getGlobalConf("APPLICATION_TITLE"), $xml); + $xml = str_replace("AJXP_MIMES_EDITABLE", StatHelper::getAjxpMimes("editable"), $xml); + $xml = str_replace("AJXP_MIMES_IMAGE", StatHelper::getAjxpMimes("image"), $xml); + $xml = str_replace("AJXP_MIMES_AUDIO", StatHelper::getAjxpMimes("audio"), $xml); + $xml = str_replace("AJXP_MIMES_ZIP", StatHelper::getAjxpMimes("zip"), $xml); + $authDriver = ConfService::getAuthDriverImpl(); + if ($authDriver != NULL) { + $loginRedirect = $authDriver->getLoginRedirect(); + $xml = str_replace("AJXP_LOGIN_REDIRECT", ($loginRedirect!==false?"'".$loginRedirect."'":"false"), $xml); + } + $xml = str_replace("AJXP_REMOTE_AUTH", "false", $xml); + $xml = str_replace("AJXP_NOT_REMOTE_AUTH", "true", $xml); + $xml = str_replace("AJXP_ALL_MESSAGES", "MessageHash=".json_encode(LocaleService::getMessages()).";", $xml); + + if (preg_match_all("/AJXP_MESSAGE(\[.*?\])/", $xml, $matches, PREG_SET_ORDER)) { + foreach ($matches as $match) { + $messId = str_replace("]", "", str_replace("[", "", $match[1])); + $xml = str_replace("AJXP_MESSAGE[$messId]", $messages[$messId], $xml); + } + } + if (preg_match_all("/CONF_MESSAGE(\[.*?\])/", $xml, $matches, PREG_SET_ORDER)) { + foreach ($matches as $match) { + $messId = str_replace(array("[", "]"), "", $match[1]); + $message = $messId; + if (array_key_exists($messId, $confMessages)) { + $message = $confMessages[$messId]; + } + $xml = str_replace("CONF_MESSAGE[$messId]", StringHelper::xmlEntities($message), $xml); + } + } + if (preg_match_all("/MIXIN_MESSAGE(\[.*?\])/", $xml, $matches, PREG_SET_ORDER)) { + foreach ($matches as $match) { + $messId = str_replace(array("[", "]"), "", $match[1]); + $message = $messId; + if (array_key_exists($messId, $confMessages)) { + $message = $confMessages[$messId]; + } + $xml = str_replace("MIXIN_MESSAGE[$messId]", StringHelper::xmlEntities($message), $xml); + } + } + if ($stripSpaces) { + $xml = preg_replace("/[\n\r]?/", "", $xml); + $xml = preg_replace("/\t/", " ", $xml); + } + $xml = str_replace(array('xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"','xsi:noNamespaceSchemaLocation="file:../core.ajaxplorer/ajxp_registry.xsd"'), "", $xml); + $tab = array(&$xml); + Controller::applyIncludeHook("xml.filter", $tab); + return $xml; + } + +} diff --git a/core/src/core/src/pydio/Core/Utils/XMLHelper.php b/core/src/core/src/pydio/Core/Utils/XMLHelper.php new file mode 100644 index 0000000000..c13fe327c1 --- /dev/null +++ b/core/src/core/src/pydio/Core/Utils/XMLHelper.php @@ -0,0 +1,183 @@ + + * This file is part of Pydio. + * + * Pydio is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Pydio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Pydio. If not, see . + * + * The latest code can be found at . + */ +namespace Pydio\Core\Utils; + +use Pydio\Core\Utils\Vars\XMLFilter; +use Pydio\Core\Utils\Vars\StringHelper; + +defined('AJXP_EXEC') or die('Access not allowed'); + +/** + * Static methods to help handling XML + * @package Pydio\Core\Utils + */ +class XMLHelper +{ + /** + * @var bool|string + */ + private static $headerSent = false; + + /** + * Simple XML element build from associative array. Can pass specific $children for nested elements. + * @param string $tagName + * @param array $attributes + * @param string $xmlChildren + * @return string + */ + public static function toXmlElement($tagName, $attributes, $xmlChildren = "") + { + $buffer = "<$tagName "; + foreach ($attributes as $attName => $attValue) { + $buffer .= "$attName=\"" . StringHelper::xmlEntities($attValue) . "\" "; + } + if (!strlen($xmlChildren)) { + $buffer .= "/>"; + } else { + $buffer .= ">" . $xmlChildren . ""; + } + return $buffer; + } + + /** + * Create plain PHP associative array from XML. + * + * Example usage: + * $xmlNode = simplexml_load_file('example.xml'); + * $arrayData = xmlToArray($xmlNode); + * echo json_encode($arrayData); + * + * @param \DOMNode $domXml The dom node to load + * @param array $options Associative array of options + * @return array + * @link http://outlandishideas.co.uk/blog/2012/08/xml-to-json/ More info + * @author Tamlyn Rhodes + * @license http://creativecommons.org/publicdomain/mark/1.0/ Public Domain + */ + public static function xmlToArray($domXml, $options = array()) + { + $xml = simplexml_import_dom($domXml); + $defaults = array( + 'namespaceSeparator' => ':',//you may want this to be something other than a colon + 'attributePrefix' => '@', //to distinguish between attributes and nodes with the same name + 'alwaysArray' => array(), //array of xml tag names which should always become arrays + 'autoArray' => true, //only create arrays for tags which appear more than once + 'textContent' => '$', //key used for the text content of elements + 'autoText' => true, //skip textContent key if node has no attributes or child nodes + 'keySearch' => false, //optional search and replace on tag and attribute names + 'keyReplace' => false //replace values for above search values (as passed to str_replace()) + ); + $options = array_merge($defaults, $options); + $namespaces = $xml->getDocNamespaces(); + $namespaces[''] = null; //add base (empty) namespace + + //get attributes from all namespaces + $attributesArray = array(); + foreach ($namespaces as $prefix => $namespace) { + foreach ($xml->attributes($namespace) as $attributeName => $attribute) { + //replace characters in attribute name + if ($options['keySearch']) $attributeName = + str_replace($options['keySearch'], $options['keyReplace'], $attributeName); + $attributeKey = $options['attributePrefix'] + . ($prefix ? $prefix . $options['namespaceSeparator'] : '') + . $attributeName; + $attributesArray[$attributeKey] = (string)$attribute; + } + } + + //get child nodes from all namespaces + $tagsArray = array(); + foreach ($namespaces as $prefix => $namespace) { + foreach ($xml->children($namespace) as $childXml) { + //recurse into child nodes + $childArray = self::xmlToArray($childXml, $options); + list($childTagName, $childProperties) = each($childArray); + + //replace characters in tag name + if ($options['keySearch']) $childTagName = + str_replace($options['keySearch'], $options['keyReplace'], $childTagName); + //add namespace prefix, if any + if ($prefix) $childTagName = $prefix . $options['namespaceSeparator'] . $childTagName; + + if (!isset($tagsArray[$childTagName])) { + //only entry with this key + //test if tags of this type should always be arrays, no matter the element count + $tagsArray[$childTagName] = + in_array($childTagName, $options['alwaysArray']) || !$options['autoArray'] + ? array($childProperties) : $childProperties; + } elseif ( + is_array($tagsArray[$childTagName]) && array_keys($tagsArray[$childTagName]) + === range(0, count($tagsArray[$childTagName]) - 1) + ) { + //key already exists and is integer indexed array + $tagsArray[$childTagName][] = $childProperties; + } else { + //key exists so convert to integer indexed array with previous value in position 0 + $tagsArray[$childTagName] = array($tagsArray[$childTagName], $childProperties); + } + } + } + + //get text content of node + $textContentArray = array(); + $plainText = trim((string)$xml); + if ($plainText !== '') $textContentArray[$options['textContent']] = $plainText; + + //stick it all together + $propertiesArray = !$options['autoText'] || $attributesArray || $tagsArray || ($plainText === '') + ? array_merge($attributesArray, $tagsArray, $textContentArray) : $plainText; + + //return node as array + return array( + $xml->getName() => $propertiesArray + ); + } + + /** + * Wrap xml inside a ... document, including declaration. + * @param $content + * @param string $docNode + * @param array $attributes + * @return string + */ + public static function wrapDocument($content, $docNode = "tree", $attributes = array()) + { + + if (self::$headerSent !== false && self::$headerSent == $docNode) { + return $content; + } + //header('Content-Type: text/xml; charset=UTF-8'); + //header('Cache-Control: no-cache'); + $buffer = ''; + $attString = ""; + if (count($attributes)) { + foreach ($attributes as $name => $value) { + $attString .= "$name=\"$value\" "; + } + } + self::$headerSent = $docNode; + $buffer .= "<$docNode $attString>"; + $buffer .= $content; + $buffer .= ""; + return $buffer; + + } +} \ No newline at end of file diff --git a/core/src/plugins/access.ajxp_conf/src/AbstractManager.php b/core/src/plugins/access.ajxp_conf/src/AbstractManager.php index dfd3c6355a..72e942898d 100644 --- a/core/src/plugins/access.ajxp_conf/src/AbstractManager.php +++ b/core/src/plugins/access.ajxp_conf/src/AbstractManager.php @@ -22,7 +22,7 @@ use Psr\Http\Message\ServerRequestInterface; use Pydio\Access\Core\Model\NodesList; -use Pydio\Core\Controller\XMLWriter; +use Pydio\Core\Utils\Vars\XMLFilter; use Pydio\Core\Model\ContextInterface; use Pydio\Core\PluginFramework\PluginsService; use Pydio\Core\Services\ConfService; @@ -162,7 +162,7 @@ protected function getEditableParameters($ctx, $currentUserIsGroupAdmin, $withLa $att = $node->attributes->item($i); $value = $att->nodeValue; if(in_array($att->nodeName, array("choices", "description", "group", "label"))) { - $value = XMLWriter::replaceAjxpXmlKeywords($value); + $value = XMLFilter::resolveKeywords($value); } $attributes[$att->nodeName] = $value; } diff --git a/core/src/plugins/access.ajxp_conf/src/PluginsManager.php b/core/src/plugins/access.ajxp_conf/src/PluginsManager.php index b7cb9c770a..8e52b7c765 100644 --- a/core/src/plugins/access.ajxp_conf/src/PluginsManager.php +++ b/core/src/plugins/access.ajxp_conf/src/PluginsManager.php @@ -24,7 +24,7 @@ use Psr\Http\Message\ServerRequestInterface; use Pydio\Access\Core\Model\AJXP_Node; use Pydio\Access\Core\Model\NodesList; -use Pydio\Core\Controller\XMLWriter; +use Pydio\Core\Utils\Vars\XMLFilter; use Pydio\Core\Http\Message\ReloadMessage; use Pydio\Core\Http\Message\UserMessage; use Pydio\Core\Http\Message\XMLDocMessage; @@ -100,11 +100,11 @@ public function pluginsActions(ServerRequestInterface $requestInterface, Respons } catch (\Exception $e) { $checkErrorMessage = " (Warning : " . $e->getMessage() . ")"; } - $tParams = XMLWriter::replaceAjxpXmlKeywords($typePlug->getManifestRawContent("server_settings/param[not(@group_switch_name)]")); + $tParams = XMLFilter::resolveKeywords($typePlug->getManifestRawContent("server_settings/param[not(@group_switch_name)]")); $addParams .= ''; $addParams .= str_replace("getManifestLabel() . $checkErrorMessage . "\" group_switch_value=\"" . $typePlug->getId() . "\" ", $tParams); - $addParams .= str_replace("getManifestRawContent("server_settings/param[@group_switch_name]"))); - $addParams .= XMLWriter::replaceAjxpXmlKeywords($typePlug->getManifestRawContent("server_settings/global_param")); + $addParams .= str_replace("getManifestRawContent("server_settings/param[@group_switch_name]"))); + $addParams .= XMLFilter::resolveKeywords($typePlug->getManifestRawContent("server_settings/global_param")); $instancesDefs = $typePlug->getConfigsDefinitions(); if (!empty($instancesDefs) && is_array($instancesDefs)) { foreach ($instancesDefs as $defKey => $defData) { @@ -113,7 +113,7 @@ public function pluginsActions(ServerRequestInterface $requestInterface, Respons } } } - $allParams = XMLWriter::replaceAjxpXmlKeywords($fullManifest->ownerDocument->saveXML($fullManifest)); + $allParams = XMLFilter::resolveKeywords($fullManifest->ownerDocument->saveXML($fullManifest)); $allParams = str_replace('type="plugin_instance:', 'type="group_switch:', $allParams); $allParams = str_replace("", $addParams . "", $allParams); @@ -212,10 +212,7 @@ public function pluginsActions(ServerRequestInterface $requestInterface, Respons $this->mergeExistingParameters($options, $existing); $confStorage->savePluginConfig($pluginId, $options); ConfService::clearAllCaches(); - XMLWriter::header(); - XMLWriter::sendMessage($mess["ajxp_conf.97"], null); - XMLWriter::close(); - + $responseInterface = $responseInterface->withBody(new SerializableResponseStream([new UserMessage($mess["ajxp_conf.97"])])); break; @@ -324,7 +321,7 @@ public function pluginsActions(ServerRequestInterface $requestInterface, Respons $n->appendChild($n->ownerDocument->createAttribute("default")); $n->attributes->getNamedItem("default")->nodeValue = $paramValue; } - $buffer .= XMLWriter::replaceAjxpXmlKeywords($n->ownerDocument->saveXML($n)); + $buffer .= XMLFilter::resolveKeywords($n->ownerDocument->saveXML($n)); } } $buffer .= ""; diff --git a/core/src/plugins/access.ajxp_conf/src/RepositoriesManager.php b/core/src/plugins/access.ajxp_conf/src/RepositoriesManager.php index aa0f1a1ab0..dce6aa7990 100644 --- a/core/src/plugins/access.ajxp_conf/src/RepositoriesManager.php +++ b/core/src/plugins/access.ajxp_conf/src/RepositoriesManager.php @@ -27,7 +27,7 @@ use Pydio\Access\Core\Model\AJXP_Node; use Pydio\Access\Core\Model\NodesList; use Pydio\Access\Core\Model\Repository; -use Pydio\Core\Controller\XMLWriter; +use Pydio\Core\Utils\Vars\XMLFilter; use Pydio\Core\Exception\PydioException; use Pydio\Core\Http\Message\ReloadMessage; use Pydio\Core\Http\Message\UserMessage; @@ -46,6 +46,7 @@ use Pydio\Core\Services\UsersService; use Pydio\Core\Utils\Vars\InputFilter; use Pydio\Core\Utils\Vars\StringHelper; +use Pydio\Core\Utils\XMLHelper; use Pydio\Tests\AbstractTest; use Zend\Diactoros\Response\JsonResponse; @@ -84,7 +85,7 @@ public function repositoriesActions(ServerRequestInterface $requestInterface, Re case "get_drivers_definition": $buffer = ""; - $buffer .= XMLWriter::replaceAjxpXmlKeywords(self::availableDriversToXML("param", "", true)); + $buffer .= XMLFilter::resolveKeywords(self::availableDriversToXML("param", "", true)); $buffer .= ""; $responseInterface = $responseInterface->withBody(new SerializableResponseStream(new XMLDocMessage($buffer))); @@ -1082,7 +1083,7 @@ protected function serializeRepositoryToXML(ContextInterface $ctx, $repository, */ protected function serializeRepositoryDriverInfos(PluginsService $pServ, $format, $plug, $repository){ $manifest = $plug->getManifestRawContent("server_settings/param"); - $manifest = XMLWriter::replaceAjxpXmlKeywords($manifest); + $manifest = XMLFilter::resolveKeywords($manifest); $clientSettings = $plug->getManifestRawContent("client_settings", "xml"); $iconClass = "";$descriptionTemplate = ""; if($clientSettings->length){ @@ -1103,7 +1104,7 @@ protected function serializeRepositoryDriverInfos(PluginsService $pServ, $format foreach ($metas as $metaPlug) { $buffer .= "getId()."\" label=\"". StringHelper::xmlEntities($metaPlug->getManifestLabel()) ."\" description=\"". StringHelper::xmlEntities($metaPlug->getManifestDescription()) ."\">"; $manifest = $metaPlug->getManifestRawContent("server_settings/param"); - $manifest = XMLWriter::replaceAjxpXmlKeywords($manifest); + $manifest = XMLFilter::resolveKeywords($manifest); $buffer .= $manifest; $buffer .= ""; } @@ -1125,7 +1126,7 @@ protected function serializeRepositoryDriverInfos(PluginsService $pServ, $format "id" => $metaPlug->getId(), "label" => $metaPlug->getManifestLabel(), "description" => $metaPlug->getManifestDescription(), - "parameters" => $this->xmlServerParamsToArray(XMLWriter::replaceAjxpXmlKeywords($metaPlug->getManifestRawContent("server_settings/param"))) + "parameters" => $this->xmlServerParamsToArray(XMLFilter::resolveKeywords($metaPlug->getManifestRawContent("server_settings/param"))) ]; } $data = ["driver" => $dData, "metasources" => $metaSources]; @@ -1140,7 +1141,7 @@ protected function serializeRepositoryDriverInfos(PluginsService $pServ, $format protected function xmlServerParamsToArray($xmlParamsString){ $doc = new \DOMDocument(); $doc->loadXML("$xmlParamsString"); - $result = XMLWriter::xmlToArray($doc, ["attributePrefix" => ""]); + $result = XMLHelper::xmlToArray($doc, ["attributePrefix" => ""]); if(isSet($result["parameters"]["param"])){ return $result["parameters"]["param"]; }else{ diff --git a/core/src/plugins/access.ajxp_conf/src/RolesManager.php b/core/src/plugins/access.ajxp_conf/src/RolesManager.php index 822f304288..8dae042bf6 100644 --- a/core/src/plugins/access.ajxp_conf/src/RolesManager.php +++ b/core/src/plugins/access.ajxp_conf/src/RolesManager.php @@ -27,7 +27,7 @@ use Pydio\Access\Core\Model\NodesList; use Pydio\Conf\Core\AbstractUser; use Pydio\Conf\Core\AJXP_Role; -use Pydio\Core\Controller\XMLWriter; +use Pydio\Core\Utils\Vars\XMLFilter; use Pydio\Core\Exception\PydioException; use Pydio\Core\Http\Message\ReloadMessage; use Pydio\Core\Http\Message\UserMessage; @@ -312,7 +312,7 @@ public function rolesActions(ServerRequestInterface $requestInterface, ResponseI $node->attributes->getNamedItem("name")->nodeValue = "AJXP_REPO_SCOPE_ALL/".$pId."/".$origName; $nArr = array(); foreach ($node->attributes as $attrib) { - $nArr[$attrib->nodeName] = XMLWriter::replaceAjxpXmlKeywords($attrib->nodeValue); + $nArr[$attrib->nodeName] = XMLFilter::resolveKeywords($attrib->nodeValue); } $data["SCOPE_PARAMS"][] = $nArr; } diff --git a/core/src/plugins/access.ftp/FtpAccessDriver.php b/core/src/plugins/access.ftp/FtpAccessDriver.php index 4e6f9f99d7..db5f1581d2 100644 --- a/core/src/plugins/access.ftp/FtpAccessDriver.php +++ b/core/src/plugins/access.ftp/FtpAccessDriver.php @@ -35,7 +35,7 @@ use Pydio\Core\Exception\PydioException; use Pydio\Core\Services\LocaleService; use Pydio\Core\Utils\Vars\InputFilter; -use Pydio\Core\Controller\XMLWriter; +use Pydio\Core\Utils\Vars\XMLFilter; use Pydio\Tasks\Task; use Pydio\Tasks\TaskService; @@ -201,7 +201,7 @@ public function uploadActions(ServerRequestInterface &$request, ResponseInterfac "destination" => base64_encode($destinationFolder) ]; - $destCopy = XMLWriter::replaceAjxpXmlKeywords($ctx->getRepository()->getContextOption($ctx, "TMP_UPLOAD")); + $destCopy = XMLFilter::resolveKeywords($ctx->getRepository()->getContextOption($ctx, "TMP_UPLOAD")); $this->logDebug("Upload : tmp upload folder", array($destCopy)); if (!is_dir($destCopy)) { if (!@mkdir($destCopy)) { diff --git a/core/src/plugins/access.mysql/MysqlAccessDriver.php b/core/src/plugins/access.mysql/MysqlAccessDriver.php index 90e6436858..380f475c31 100644 --- a/core/src/plugins/access.mysql/MysqlAccessDriver.php +++ b/core/src/plugins/access.mysql/MysqlAccessDriver.php @@ -22,13 +22,16 @@ use Pydio\Access\Core\AbstractAccessDriver; use Pydio\Access\Core\Model\UserSelection; +use Pydio\Core\Exception\AuthRequiredException; +use Pydio\Core\Http\Message\ReloadMessage; +use Pydio\Core\Http\Message\UserMessage; use Pydio\Core\Model\ContextInterface; use Pydio\Core\Exception\PydioException; use Pydio\Core\Utils\Vars\InputFilter; use Pydio\Core\Utils\Vars\StatHelper; use Pydio\Core\Utils\Vars\StringHelper; -use Pydio\Core\Controller\XMLWriter; +use Pydio\Core\Utils\Vars\XMLFilter; defined('AJXP_EXEC') or die( 'Access not allowed'); @@ -335,9 +338,9 @@ public function switchAction($action, $httpVars, $fileVars, ContextInterface $ct $link = $this->createDbLink($ctx); //AJXP_Exception::errorToXml($link); if ($dir == "") { - XMLWriter::header(); + XMLFilter::header(); $tables = $this->listTables($ctx); - XMLWriter::sendFilesListComponentConfig(''); + XMLFilter::sendFilesListComponentConfig(''); $icon = ($mode == "file_list"?"sql_images/mimes/ICON_SIZE/table_empty.png":"sql_images/mimes/ICON_SIZE/table_empty_tree.png"); foreach ($tables as $tableName) { if(InputFilter::detectXSS($tableName)) { @@ -351,7 +354,7 @@ public function switchAction($action, $httpVars, $fileVars, ContextInterface $ct print ""; } print ""; - XMLWriter::close(); + XMLFilter::close(); } else { $tableName = basename($dir); if(isSet($page))$currentPage = $page; @@ -392,7 +395,7 @@ public function switchAction($action, $httpVars, $fileVars, ContextInterface $ct unset($_SESSION["LAST_SQL_QUERY"]); throw $ex; } - XMLWriter::header(); + XMLFilter::header(); $blobCols = array(); $columnsString = ''; foreach ($result["COLUMNS"] as $col) { @@ -403,10 +406,10 @@ public function switchAction($action, $httpVars, $fileVars, ContextInterface $ct } $columnsString .= ''; - XMLWriter::sendFilesListComponentConfig($columnsString); + XMLFilter::sendFilesListComponentConfig($columnsString); //print ''; if ($result["TOTAL_PAGES"] > 1) { - XMLWriter::renderPaginationData($count, $currentPage, $result["TOTAL_PAGES"]); + XMLFilter::renderPaginationData($count, $currentPage, $result["TOTAL_PAGES"]); } foreach ($result["ROWS"] as $arbitIndex => $row) { print 'closeDbLink($link); return null; @@ -447,17 +450,19 @@ public function switchAction($action, $httpVars, $fileVars, ContextInterface $ct if (isset($logMessage) || isset($errorMessage)) { if(InputFilter::detectXSS($logMessage) || InputFilter::detectXSS($errorMessage)){ - $xmlBuffer = XMLWriter::sendMessage(null, "XSS Detected!", false); + $errorMessage = "XSS detected!"; } - $xmlBuffer .= XMLWriter::sendMessage((isSet($logMessage)?$logMessage:null), (isSet($errorMessage)?$errorMessage:null), false); } + $uMessage = new UserMessage(isSet($logMessage)?$logMessage:$errorMessage, isset($logMessage) ? LOG_LEVEL_ERROR: LOG_LEVEL_INFO); + $xmlBuffer = $uMessage->toXML(); if (isset($requireAuth)) { - $xmlBuffer .= XMLWriter::requireAuth(false); + throw new AuthRequiredException(); } if (( isset($reload_current_node) && $reload_current_node == "true") || (isset($reload_file_list)) ) { - $xmlBuffer .= XMLWriter::reloadDataNode("", "", false); + $relo = new ReloadMessage(); + $xmlBuffer .= $relo->toXML(); } return $xmlBuffer; diff --git a/core/src/plugins/action.share/src/ShareCenter.php b/core/src/plugins/action.share/src/ShareCenter.php index d0eb2c84ab..2b23dff716 100644 --- a/core/src/plugins/action.share/src/ShareCenter.php +++ b/core/src/plugins/action.share/src/ShareCenter.php @@ -48,7 +48,7 @@ use Pydio\Core\Services\UsersService; use Pydio\Core\Services\ApplicationState; use Pydio\Core\Utils\Vars\InputFilter; -use Pydio\Core\Controller\XMLWriter; +use Pydio\Core\Utils\Vars\XMLFilter; use Pydio\Core\PluginFramework\Plugin; use Pydio\Core\PluginFramework\PluginsService; use Pydio\OCS\Model\TargettedLink; @@ -589,10 +589,11 @@ public function switchAction(ServerRequestInterface &$requestInterface, Response if (strpos($action, "sharelist") === false && $this->accessDriver->getId() == "access.demo") { $errorMessage = "This is a demo, all 'write' actions are disabled!"; - if ($httpVars["sub_action"] == "delegate_repo") { - return XMLWriter::sendMessage(null, $errorMessage, false); + if ($httpVars["sub_action"] === "delegate_repo") { + $responseInterface = $responseInterface->withBody(new SerializableResponseStream([new UserMessage($errorMessage, LOG_LEVEL_ERROR)])); + return; } else { - print($errorMessage); + $responseInterface->getBody()->write($errorMessage); } return null; } diff --git a/core/src/plugins/action.share/src/View/MinisiteRenderer.php b/core/src/plugins/action.share/src/View/MinisiteRenderer.php index 31b9c108ba..fd4ab5b588 100644 --- a/core/src/plugins/action.share/src/View/MinisiteRenderer.php +++ b/core/src/plugins/action.share/src/View/MinisiteRenderer.php @@ -33,7 +33,7 @@ use Pydio\Core\Services\RepositoryService; use Pydio\Core\Services\ApplicationState; use Pydio\Core\Utils\Http\UserAgent; -use Pydio\Core\Controller\XMLWriter; +use Pydio\Core\Utils\Vars\XMLFilter; use Pydio\Core\Controller\HTMLWriter; use Pydio\Core\PluginFramework\PluginsService; use Pydio\Share\ShareCenter; @@ -212,7 +212,7 @@ public static function writeHtml(ResponseInterface $responseInterface, ContextIn // UPDATE TEMPLATE $html = file_get_contents(AJXP_INSTALL_PATH."/".AJXP_PLUGINS_FOLDER."/action.share/res/minisite.php"); Controller::applyHook("tpl.filter_html", [$context, &$html]); - $html = XMLWriter::replaceAjxpXmlKeywords($html); + $html = XMLFilter::resolveKeywords($html); $html = str_replace("AJXP_MINISITE_LOGO", $minisiteLogo, $html); $html = str_replace("AJXP_APPLICATION_TITLE", ConfService::getGlobalConf("APPLICATION_TITLE"), $html); $html = str_replace("PYDIO_APP_TITLE", ConfService::getGlobalConf("APPLICATION_TITLE"), $html); diff --git a/core/src/plugins/authfront.session_login/SessionLoginFrontend.php b/core/src/plugins/authfront.session_login/SessionLoginFrontend.php index 600bb88bdf..21c0a04738 100644 --- a/core/src/plugins/authfront.session_login/SessionLoginFrontend.php +++ b/core/src/plugins/authfront.session_login/SessionLoginFrontend.php @@ -32,7 +32,7 @@ use Pydio\Core\Services\ApplicationState; use Pydio\Core\Utils\Http\BruteForceHelper; use Pydio\Core\Utils\Http\CookiesHelper; -use Pydio\Core\Controller\XMLWriter; +use Pydio\Core\Utils\Vars\XMLFilter; use Pydio\Core\Utils\Http\CaptchaProvider; defined('AJXP_EXEC') or die('Access not allowed'); diff --git a/core/src/plugins/boot.conf/BootConfLoader.php b/core/src/plugins/boot.conf/BootConfLoader.php index d46b432293..00a81e6014 100644 --- a/core/src/plugins/boot.conf/BootConfLoader.php +++ b/core/src/plugins/boot.conf/BootConfLoader.php @@ -44,7 +44,7 @@ use Pydio\Core\Utils\Vars\PathUtils; use Pydio\Core\Utils\Vars\StringHelper; use Pydio\Core\Utils\Vars\VarsFilter; -use Pydio\Core\Controller\XMLWriter; +use Pydio\Core\Utils\Vars\XMLFilter; use Pydio\Core\Controller\HTMLWriter; use Pydio\Core\PluginFramework\PluginsService; use Pydio\Core\PluginFramework\SqlTableProvider; @@ -140,10 +140,10 @@ public function printFormFromServerSettings($fullManifest) } catch (Exception $e) { $checkErrorMessage = " (Warning : " . $e->getMessage() . ")"; } - $tParams = XMLWriter::replaceAjxpXmlKeywords($typePlug->getManifestRawContent("server_settings/param")); + $tParams = XMLFilter::resolveKeywords($typePlug->getManifestRawContent("server_settings/param")); $addParams .= ''; $addParams .= str_replace("getManifestLabel() . $checkErrorMessage . "\" group_switch_value=\"" . $typePlug->getId() . "\" ", $tParams); - $addParams .= XMLWriter::replaceAjxpXmlKeywords($typePlug->getManifestRawContent("server_settings/global_param")); + $addParams .= XMLFilter::resolveKeywords($typePlug->getManifestRawContent("server_settings/global_param")); } } $uri = $_SERVER["REQUEST_URI"]; @@ -164,7 +164,7 @@ public function printFormFromServerSettings($fullManifest) if (!$vNodes->length) continue; $vNodes->item(0)->setAttribute("default", $pValue); } - $allParams = XMLWriter::replaceAjxpXmlKeywords($fullManifest->ownerDocument->saveXML($fullManifest)); + $allParams = XMLFilter::resolveKeywords($fullManifest->ownerDocument->saveXML($fullManifest)); $allParams = str_replace('type="plugin_instance:', 'type="group_switch:', $allParams); $allParams = str_replace("", $addParams . "", $allParams); diff --git a/core/src/plugins/core.access/src/Model/NodesDiff.php b/core/src/plugins/core.access/src/Model/NodesDiff.php index 451bd674e2..a7d3352b97 100644 --- a/core/src/plugins/core.access/src/Model/NodesDiff.php +++ b/core/src/plugins/core.access/src/Model/NodesDiff.php @@ -20,10 +20,11 @@ */ namespace Pydio\Access\Core\Model; -use Pydio\Core\Controller\XMLWriter; +use Pydio\Core\Utils\Vars\XMLFilter; use Pydio\Core\Http\Response\JSONSerializableResponseChunk; use Pydio\Core\Http\Response\XMLSerializableResponseChunk; +use Pydio\Core\Serializer\NodeXML; use Pydio\Core\Services\LocaleService; use Pydio\Core\Utils\Vars\StringHelper; @@ -135,7 +136,7 @@ public function toXML() $buffer .= ""; foreach ($this->added as $ajxpNode) { $this->forceLoadNodeInfo($ajxpNode); - $buffer .= XMLWriter::renderAjxpNode($ajxpNode, true, false); + $buffer .= NodeXML::toXML($ajxpNode, true); } $buffer .= ""; } @@ -144,7 +145,7 @@ public function toXML() foreach ($this->updated as $originalPath => $ajxpNode) { $this->forceLoadNodeInfo($ajxpNode); $ajxpNode->original_path = $originalPath; - $buffer .= XMLWriter::renderAjxpNode($ajxpNode, true, false); + $buffer .= NodeXML::toXML($ajxpNode, true); } $buffer .= ""; } diff --git a/core/src/plugins/core.access/src/Model/NodesList.php b/core/src/plugins/core.access/src/Model/NodesList.php index fa664d1d75..8a357a50f0 100644 --- a/core/src/plugins/core.access/src/Model/NodesList.php +++ b/core/src/plugins/core.access/src/Model/NodesList.php @@ -22,11 +22,13 @@ defined('AJXP_EXEC') or die('Access not allowed'); -use Pydio\Core\Controller\XMLWriter; +use Pydio\Core\Utils\Vars\XMLFilter; use Pydio\Core\Http\Response\CLISerializableResponseChunk; use Pydio\Core\Http\Response\JSONSerializableResponseChunk; use Pydio\Core\Http\Response\XMLDocSerializableResponseChunk; +use Pydio\Core\Serializer\NodeXML; use Pydio\Core\Services\LocaleService; +use Pydio\Core\Utils\XMLHelper; use Symfony\Component\Console\Helper\Table; use Symfony\Component\Console\Output\OutputInterface; @@ -124,33 +126,32 @@ public function setRoot($bool){ public function toXML() { $buffer = ""; - $buffer .= XMLWriter::renderAjxpNode($this->parentNode, false, false); + $buffer .= NodeXML::toXML($this->parentNode, false); if(isSet($this->paginationData)){ - $buffer .= XMLWriter::renderPaginationData( + $buffer .= $this->renderPaginationData( $this->paginationData["count"], $this->paginationData["current"], $this->paginationData["total"], $this->paginationData["dirs"], - $this->paginationData["remoteSort"], - false); + $this->paginationData["remoteSort"]); } if(isSet($this->columnsDescription)){ $xmlChildren = []; foreach($this->columnsDescription['columns'] as $column){ - $xmlChildren[] = XMLWriter::toXmlElement("column", $column); + $xmlChildren[] = XMLHelper::toXmlElement("column", $column); } - $xmlConfig = XMLWriter::toXmlElement("columns", $this->columnsDescription['description'], implode("", $xmlChildren)); - $xmlConfig = XMLWriter::toXmlElement("component_config", ["className" => "FilesList"], $xmlConfig); - $buffer .= XMLWriter::toXmlElement("client_configs", [], $xmlConfig); + $xmlConfig = XMLHelper::toXmlElement("columns", $this->columnsDescription['description'], implode("", $xmlChildren)); + $xmlConfig = XMLHelper::toXmlElement("component_config", ["className" => "FilesList"], $xmlConfig); + $buffer .= XMLHelper::toXmlElement("client_configs", [], $xmlConfig); } foreach ($this->children as $child){ if($child instanceof NodesList){ $buffer .= $child->toXML(); }else{ - $buffer .= XMLWriter::renderAjxpNode($child, true, false); + $buffer .= NodeXML::toXML($child, true); } } - $buffer .= XMLWriter::close("tree", false); + $buffer .= ""; return $buffer; } @@ -288,4 +289,25 @@ public function render($output) // Render $table->render(); } + + /** + * Ouput the tag + * @static + * @param integer $count + * @param integer $currentPage + * @param integer $totalPages + * @param integer $dirsCount + * @param null $remoteSortAttributes + * @return void|string + */ + private function renderPaginationData($count, $currentPage, $totalPages, $dirsCount = -1, $remoteSortAttributes = null) + { + $remoteSortString = ""; + if (is_array($remoteSortAttributes)) { + foreach($remoteSortAttributes as $k => $v) $remoteSortString .= " $k='$v'"; + } + return ''; + } + + } \ No newline at end of file diff --git a/core/src/plugins/core.ajaxplorer/ajxp_registry.xsd b/core/src/plugins/core.ajaxplorer/ajxp_registry.xsd index ff15748d45..53b6cf709e 100644 --- a/core/src/plugins/core.ajaxplorer/ajxp_registry.xsd +++ b/core/src/plugins/core.ajaxplorer/ajxp_registry.xsd @@ -521,6 +521,7 @@ + diff --git a/core/src/plugins/core.conf/AbstractConfDriver.php b/core/src/plugins/core.conf/AbstractConfDriver.php index 1e5df79f67..8df7e4086c 100644 --- a/core/src/plugins/core.conf/AbstractConfDriver.php +++ b/core/src/plugins/core.conf/AbstractConfDriver.php @@ -37,6 +37,7 @@ use Pydio\Core\Model\ContextInterface; use Pydio\Core\Model\RepositoryInterface; use Pydio\Core\Model\UserInterface; +use Pydio\Core\Serializer\UserXML; use Pydio\Core\Services\AuthService; use Pydio\Core\Controller\Controller; use Pydio\Core\Services\LocaleService; @@ -50,7 +51,7 @@ use Pydio\Core\Utils\Vars\OptionsHelper; use Pydio\Core\Utils\Vars\StatHelper; -use Pydio\Core\Controller\XMLWriter; +use Pydio\Core\Utils\Vars\XMLFilter; use Pydio\Core\Controller\HTMLWriter; use Pydio\Core\PluginFramework\Plugin; use Pydio\Core\PluginFramework\PluginsService; @@ -734,7 +735,7 @@ public function switchAction(ServerRequestInterface $requestInterface, ResponseI $bmUser->save("user"); } } - $doc = new XMLMessage(XMLWriter::writeBookmarks($bmUser->getBookmarks($repositoryId), $ctx, false, isset($httpVars["format"])?$httpVars["format"]:"legacy")); + $doc = new XMLMessage(UserXML::writeBookmarks($bmUser->getBookmarks($repositoryId), $ctx, false, isset($httpVars["format"]) ? $httpVars["format"] : "legacy")); $x = new SerializableResponseStream([$doc]); $responseInterface = $responseInterface->withBody($x); @@ -1024,7 +1025,7 @@ public function switchAction(ServerRequestInterface $requestInterface, ResponseI } if( in_array($paramNode->getAttribute("name"), $tplDefined) ) continue; if($paramNode->getAttribute('no_templates') == 'true') continue; - $xml.= XMLWriter::replaceAjxpXmlKeywords($paramNode->ownerDocument->saveXML($paramNode)); + $xml.= XMLFilter::resolveKeywords($paramNode->ownerDocument->saveXML($paramNode)); } // ADD LABEL $xml .= ''; diff --git a/core/src/plugins/core.mq/src/MqManager.php b/core/src/plugins/core.mq/src/MqManager.php index 14458faacc..fcb257f732 100644 --- a/core/src/plugins/core.mq/src/MqManager.php +++ b/core/src/plugins/core.mq/src/MqManager.php @@ -43,7 +43,7 @@ use Pydio\Core\Services\ApplicationState; use Pydio\Core\Utils\Vars\StringHelper; -use Pydio\Core\Controller\XMLWriter; +use Pydio\Core\Utils\Vars\XMLFilter; use Pydio\Core\PluginFramework\Plugin; use Pydio\Mq\Core\Message\ConsumeChannelMessage; use Pydio\Notification\Core\IMessageExchanger; diff --git a/core/src/plugins/gui.ajax/RichClient.php b/core/src/plugins/gui.ajax/RichClient.php index bb2b5d8c19..a19005a6a5 100644 --- a/core/src/plugins/gui.ajax/RichClient.php +++ b/core/src/plugins/gui.ajax/RichClient.php @@ -40,7 +40,7 @@ use Pydio\Core\Utils\Reflection\JSPacker; use Pydio\Core\Utils\Reflection\LocaleExtractor; -use Pydio\Core\Controller\XMLWriter; +use Pydio\Core\Utils\Vars\XMLFilter; use Pydio\Core\Controller\HTMLWriter; use Pydio\Core\PluginFramework\Plugin; use Pydio\Core\PluginFramework\PluginsService; @@ -278,7 +278,7 @@ public function getBootGui(ServerRequestInterface &$request, ResponseInterface & $callback->parentNode->removeChild($callback); } } - $START_PARAMETERS["PRELOADED_REGISTRY"] = XMLWriter::replaceAjxpXmlKeywords($clone->saveXML()); + $START_PARAMETERS["PRELOADED_REGISTRY"] = XMLFilter::resolveKeywords($clone->saveXML()); } $JSON_START_PARAMETERS = json_encode($START_PARAMETERS); @@ -311,7 +311,7 @@ public function getBootGui(ServerRequestInterface &$request, ResponseInterface & $ADDITIONAL_FRAMEWORKS = ""; } $content = str_replace("AJXP_ADDITIONAL_JS_FRAMEWORKS", $ADDITIONAL_FRAMEWORKS, $content); - $content = XMLWriter::replaceAjxpXmlKeywords($content, false); + $content = XMLFilter::resolveKeywords($content, false); $content = str_replace("AJXP_REBASE", isSet($START_PARAMETERS["REBASE"])?'':"", $content); if ($JSON_START_PARAMETERS) { $content = str_replace("//AJXP_JSON_START_PARAMETERS", "startParameters = ".$JSON_START_PARAMETERS.";", $content); diff --git a/core/src/plugins/meta.svn/SvnManager.php b/core/src/plugins/meta.svn/SvnManager.php index c0836dcc0a..869a682769 100644 --- a/core/src/plugins/meta.svn/SvnManager.php +++ b/core/src/plugins/meta.svn/SvnManager.php @@ -20,18 +20,24 @@ */ namespace Pydio\Access\Meta\Version; +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\ServerRequestInterface; use Pydio\Access\Core\AbstractAccessDriver; use Pydio\Access\Core\MetaStreamWrapper; use Pydio\Access\Core\Model\AJXP_Node; use Pydio\Access\Core\RecycleBinManager; use Pydio\Access\Core\Model\UserSelection; +use Pydio\Core\Http\Message\ReloadMessage; +use Pydio\Core\Http\Message\UserMessage; +use Pydio\Core\Http\Message\XMLMessage; +use Pydio\Core\Http\Response\SerializableResponseStream; use Pydio\Core\Model\ContextInterface; use Pydio\Core\Services\AuthService; use Pydio\Core\Services\LocaleService; use Pydio\Core\Utils\Vars\InputFilter; -use Pydio\Core\Controller\XMLWriter; +use Pydio\Core\Utils\Vars\XMLFilter; use Pydio\Core\Utils\TextEncoder; use Pydio\Access\Meta\Core\AbstractMetaSource; @@ -176,14 +182,16 @@ public function commitFile($file, $ajxpNode) } /** - * @param $actionName - * @param $httpVars - * @param $filesVars - * @param ContextInterface $ctx + * @param ServerRequestInterface $requestInterface + * @param ResponseInterface $responseInterface * @throws \Exception */ - public function switchAction($actionName, $httpVars, $filesVars, ContextInterface $ctx) + public function switchAction(ServerRequestInterface $requestInterface, ResponseInterface &$responseInterface) { + $actionName = $requestInterface->getAttribute("action"); + $httpVars = $requestInterface->getParsedBody(); + $ctx = $requestInterface->getAttribute("ctx"); + $init = $this->initDirAndSelection($ctx, $httpVars); if ($actionName == "svnlog") { $res1 = ExecSvnCmd("svnversion", $init["DIR"]); @@ -197,16 +205,17 @@ public function switchAction($actionName, $httpVars, $filesVars, ContextInterfac $switches = '--xml -rHEAD:0'; $arg = $init["SELECTION"][0]; $res = ExecSvnCmd($command, $arg, $switches); - XMLWriter::header(); + $serialStream = new SerializableResponseStream(); $lines = explode(PHP_EOL, $res[IDX_STDOUT]); array_shift($lines); if (isSet($currentRev)) { - print("$currentRev"); + $serialStream->addChunk(new XMLMessage("$currentRev")); } else if (isSet($revRange)) { - print(""); + $serialStream->addChunk(new XMLMessage("")); } - print(TextEncoder::toUTF8(implode("", $lines), false)); - XMLWriter::close(); + $serialStream->addChunk(new XMLMessage(implode("", $lines))); + $responseInterface = $responseInterface->withBody($serialStream); + } else if ($actionName == "svndownload") { $revision = $httpVars["revision"]; $realFile = $init["SELECTION"][0]; @@ -296,14 +305,16 @@ public function addSelection($actionName, $httpVars, $filesVars, ContextInterfac } /** - * @param $actionName - * @param $httpVars - * @param $filesVars - * @param ContextInterface $ctx + * @param ServerRequestInterface $requestInterface + * @param ResponseInterface $responseInterface * @throws \Exception */ - public function copyOrMoveSelection($actionName, &$httpVars, $filesVars, ContextInterface $ctx) + public function copyOrMoveSelection(ServerRequestInterface $requestInterface, ResponseInterface &$responseInterface) { + $actionName = $requestInterface->getAttribute("action"); + $httpVars = $requestInterface->getParsedBody(); + $ctx = $requestInterface->getAttribute("ctx"); + if ($actionName != "rename") { $init = $this->initDirAndSelection($ctx, $httpVars, array("DEST_DIR" => InputFilter::decodeSecureMagic($httpVars["dest"]))); $this->commitMessageParams = "To:".$httpVars["dest"].";items:"; @@ -328,17 +339,16 @@ public function copyOrMoveSelection($actionName, &$httpVars, $filesVars, Context if ($actionName != "rename") { $this->commitMessageParams .= "[".implode(",",$init["SELECTION"])."]"; } - $this->commitChanges($actionName, $httpVars, $filesVars, $ctx); + $this->commitChanges($actionName, $httpVars, [], $ctx); if ($actionName != "rename") { - $this->commitChanges($actionName, array("dir" => $httpVars["dest"]), $filesVars, $ctx); + $this->commitChanges($actionName, array("dir" => $httpVars["dest"]), [], $ctx); } $this->logInfo("CopyMove/Rename (svn delegate)", array("files"=>$init["SELECTION"])); $mess = LocaleService::getMessages(); - XMLWriter::header(); - XMLWriter::sendMessage($mess["meta.svn.5"], null); - XMLWriter::reloadDataNode(); - XMLWriter::close(); + + $serialStream = new SerializableResponseStream([new UserMessage($mess["meta.svn.5"]), new ReloadMessage()]); + $responseInterface = $responseInterface->withBody($serialStream); } /** @@ -348,12 +358,18 @@ public function copyOrMoveSelection($actionName, &$httpVars, $filesVars, Context * @param ContextInterface $ctx * @throws \Exception */ - public function deleteSelection($actionName, &$httpVars, $filesVars, ContextInterface $ctx) + public function deleteSelection(ServerRequestInterface $requestInterface, ResponseInterface &$responseInterface) { + $actionName = $requestInterface->getAttribute("action"); + $httpVars = $requestInterface->getParsedBody(); + $ctx = $requestInterface->getAttribute("ctx"); + $init = $this->initDirAndSelection($ctx, $httpVars, array(), true); if (isSet($init["RECYCLE"]) && isSet($init["RECYCLE"]["action"]) && $init["RECYCLE"]["action"] != "delete") { $httpVars["dest"] = TextEncoder::fromUTF8($init["RECYCLE"]["dest"]); - $this->copyOrMoveSelection("move", $httpVars, $filesVars, $ctx); + $updatedRequest = $requestInterface->withAttribute("action", "move")->withParsedBody($httpVars); + $this->copyOrMoveSelection($updatedRequest, $responseInterface); + $userSelection = $init["ORIGINAL_SELECTION"]; $files = $userSelection->getFiles(); if ($actionName == "delete") { @@ -365,21 +381,19 @@ public function deleteSelection($actionName, &$httpVars, $filesVars, ContextInte RecycleBinManager::deleteFromRecycle($file); } } - $this->commitChanges($actionName, array("dir" => RecycleBinManager::getRelativeRecycle()), $filesVars, $ctx); + $this->commitChanges($actionName, array("dir" => RecycleBinManager::getRelativeRecycle()), [], $ctx); return ; } foreach ($init["SELECTION"] as $selectedFile) { $res = ExecSvnCmd('svn delete', $selectedFile, '--force'); } $this->commitMessageParams = "[".implode(",",$init["SELECTION"])."]"; - $this->commitChanges($actionName, $httpVars, $filesVars, $ctx); + $this->commitChanges($actionName, $httpVars, [], $ctx); $this->logInfo("Delete (svn delegate)", array("files"=>$init["SELECTION"])); $mess = LocaleService::getMessages(); - XMLWriter::header(); - XMLWriter::sendMessage($mess["meta.svn.51"], null); - XMLWriter::reloadDataNode(); - XMLWriter::close(); + $serialStream = new SerializableResponseStream([new UserMessage($mess["meta.svn.51"]), new ReloadMessage()]); + $responseInterface = $responseInterface->withBody($serialStream); } /** diff --git a/core/src/plugins/uploader.html/SimpleUpload.php b/core/src/plugins/uploader.html/SimpleUpload.php index 38b2d5c678..51a8ddb897 100644 --- a/core/src/plugins/uploader.html/SimpleUpload.php +++ b/core/src/plugins/uploader.html/SimpleUpload.php @@ -32,8 +32,9 @@ use Pydio\Core\Utils\Vars\InputFilter; use Pydio\Core\Http\Message\ExternalUploadedFile; -use Pydio\Core\Controller\XMLWriter; +use Pydio\Core\Utils\Vars\XMLFilter; use Pydio\Core\PluginFramework\Plugin; +use Pydio\Core\Utils\XMLHelper; use Zend\Diactoros\Response\TextResponse; defined('AJXP_EXEC') or die( 'Access not allowed'); @@ -233,7 +234,7 @@ public function postProcess(\Psr\Http\Message\ServerRequestInterface &$request, $nodesDiffXML = $nodesDiff->toXML(); } $response = $response->withHeader("Content-type", "text/xml; charset=UTF-8"); - $response->getBody()->write(XMLWriter::wrapDocument($nodesDiffXML)); + $response->getBody()->write(XMLHelper::wrapDocument($nodesDiffXML)); /* for further implementation */ if (!isSet($result["PREVENT_NOTIF"])) { diff --git a/core/src/plugins/uploader.html/manifest.xml b/core/src/plugins/uploader.html/manifest.xml index b6c6608725..8f3817d7f9 100644 --- a/core/src/plugins/uploader.html/manifest.xml +++ b/core/src/plugins/uploader.html/manifest.xml @@ -69,9 +69,11 @@ var dragSupported = 'draggable' in new Element('span'); var fileUploadSupported = typeof File != "undefined" && typeof (new XMLHttpRequest()).upload != "undefined" && (window.FileReader || window.FormData); if(fileUploadSupported && dragSupported && pydioUserWriteable){ - ResourcesManager.loadClassesAndApply(["UploaderGlobalListener","UploaderModel"], function(){ - UploaderGlobalListener.initUploaderExtension(); - }); + try{ + ResourcesManager.loadClassesAndApply(["UploaderGlobalListener","UploaderModel"], function(){ + UploaderGlobalListener.initUploaderExtension(); + }); + }catch(e){} } ]]> diff --git a/core/src/plugins/uploader.plupload/Pluploader.php b/core/src/plugins/uploader.plupload/Pluploader.php index a01b7b667b..cd33e65ee8 100644 --- a/core/src/plugins/uploader.plupload/Pluploader.php +++ b/core/src/plugins/uploader.plupload/Pluploader.php @@ -44,7 +44,7 @@ use Pydio\Core\Utils\Vars\InputFilter; use Pydio\Core\Utils\Vars\StatHelper; -use Pydio\Core\Controller\XMLWriter; +use Pydio\Core\Utils\Vars\XMLFilter; use Pydio\Core\PluginFramework\Plugin; defined('AJXP_EXEC') or die( 'Access not allowed'); @@ -121,7 +121,7 @@ public function unifyChunks($action, &$httpVars, &$fileVars, \Pydio\Core\Model\C $remote = false; if (method_exists($driver, "storeFileToCopy")) { $remote = true; - $destCopy = XMLWriter::replaceAjxpXmlKeywords($repository->getContextOption($ctx, "TMP_UPLOAD")); + $destCopy = XMLFilter::resolveKeywords($repository->getContextOption($ctx, "TMP_UPLOAD")); // Make tmp folder a bit more unique using secure_token $tmpFolder = $destCopy."/".$httpVars["secure_token"]; if(!is_dir($tmpFolder)){