PageRenderTime 26ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/admin/template/js/qfinder/core/connector/php/php5/CommandHandler/CopyFiles.php

https://gitlab.com/kidaa/quantum
PHP | 216 lines | 151 code | 29 blank | 36 comment | 46 complexity | c90da1335bbf9d333559435ce8ac8e61 MD5 | raw file
Possible License(s): GPL-2.0, MPL-2.0-no-copyleft-exception
  1. <?php
  2. if (!defined('IN_QFINDER')) exit;
  3. require_once QFINDER_CONNECTOR_LIB_DIR . "/CommandHandler/XmlCommandHandlerBase.php";
  4. class QFinder_Connector_CommandHandler_CopyFiles extends QFinder_Connector_CommandHandler_XmlCommandHandlerBase
  5. {
  6. /**
  7. * Command name
  8. *
  9. * @access private
  10. * @var string
  11. */
  12. private $command = "CopyFiles";
  13. /**
  14. * handle request and build XML
  15. * @access protected
  16. *
  17. */
  18. protected function buildXml()
  19. {
  20. if (empty($_POST['QFinderCommand']) || $_POST['QFinderCommand'] != 'true') {
  21. $this->_errorHandler->throwError(QFINDER_CONNECTOR_ERROR_INVALID_REQUEST);
  22. }
  23. $clientPath = $this->_currentFolder->getClientPath();
  24. $sServerDir = $this->_currentFolder->getServerPath();
  25. $currentResourceTypeConfig = $this->_currentFolder->getResourceTypeConfig();
  26. $_config =& QFinder_Connector_Core_Factory::getInstance("Core_Config");
  27. $_aclConfig = $_config->getAccessControlConfig();
  28. $aclMasks = array();
  29. $_resourceTypeConfig = array();
  30. if (!$this->_currentFolder->checkAcl(QFINDER_CONNECTOR_ACL_FILE_RENAME | QFINDER_CONNECTOR_ACL_FILE_UPLOAD | QFINDER_CONNECTOR_ACL_FILE_DELETE)) {
  31. $this->_errorHandler->throwError(QFINDER_CONNECTOR_ERROR_UNAUTHORIZED);
  32. }
  33. // Create the "Errors" node.
  34. $oErrorsNode = new QFinder_Connector_Utils_XmlNode("Errors");
  35. $errorCode = QFINDER_CONNECTOR_ERROR_NONE;
  36. $copied = 0;
  37. $copiedAll = 0;
  38. if (!empty($_POST['copied'])) {
  39. $copiedAll = intval($_POST['copied']);
  40. }
  41. $checkedPaths = array();
  42. $oCopyFilesNode = new Qfinder_Connector_Utils_XmlNode("CopyFiles");
  43. if (!empty($_POST['files']) && is_array($_POST['files'])) {
  44. foreach ($_POST['files'] as $index => $arr) {
  45. if (empty($arr['name'])) {
  46. continue;
  47. }
  48. if (!isset($arr['name'], $arr['type'], $arr['folder'])) {
  49. $this->_errorHandler->throwError(QFINDER_CONNECTOR_ERROR_INVALID_REQUEST);
  50. }
  51. // file name
  52. $name = QFinder_Connector_Utils_FileSystem::convertToFilesystemEncoding($arr['name']);
  53. // resource type
  54. $type = $arr['type'];
  55. // client path
  56. $path = QFinder_Connector_Utils_FileSystem::convertToFilesystemEncoding($arr['folder']);
  57. // options
  58. $options = (!empty($arr['options'])) ? $arr['options'] : '';
  59. $destinationFilePath = $sServerDir.$name;
  60. // check #1 (path)
  61. if (!QFinder_Connector_Utils_FileSystem::checkFileName($name) || preg_match(QFINDER_REGEX_INVALID_PATH, $path)) {
  62. $this->_errorHandler->throwError(QFINDER_CONNECTOR_ERROR_INVALID_REQUEST);
  63. }
  64. // get resource type config for current file
  65. if (!isset($_resourceTypeConfig[$type])) {
  66. $_resourceTypeConfig[$type] = $_config->getResourceTypeConfig($type);
  67. }
  68. // check #2 (resource type)
  69. if (is_null($_resourceTypeConfig[$type])) {
  70. $this->_errorHandler->throwError(QFINDER_CONNECTOR_ERROR_INVALID_REQUEST);
  71. }
  72. // check #3 (extension)
  73. if (!$_resourceTypeConfig[$type]->checkExtension($name, false)) {
  74. $errorCode = QFINDER_CONNECTOR_ERROR_INVALID_EXTENSION;
  75. $this->appendErrorNode($oErrorsNode, $errorCode, $name, $type, $path);
  76. continue;
  77. }
  78. // check #4 (extension) - when moving to another resource type, double check extension
  79. if ($currentResourceTypeConfig->getName() != $type) {
  80. if (!$currentResourceTypeConfig->checkExtension($name, false)) {
  81. $errorCode = QFINDER_CONNECTOR_ERROR_INVALID_EXTENSION;
  82. $this->appendErrorNode($oErrorsNode, $errorCode, $name, $type, $path);
  83. continue;
  84. }
  85. }
  86. // check #5 (hidden folders)
  87. // cache results
  88. if (empty($checkedPaths[$path])) {
  89. $checkedPaths[$path] = true;
  90. if ($_resourceTypeConfig[$type]->checkIsHiddenPath($path)) {
  91. $this->_errorHandler->throwError(QFINDER_CONNECTOR_ERROR_INVALID_REQUEST);
  92. }
  93. }
  94. $sourceFilePath = $_resourceTypeConfig[$type]->getDirectory().$path.$name;
  95. // check #6 (hidden file name)
  96. if ($currentResourceTypeConfig->checkIsHiddenFile($name)) {
  97. $this->_errorHandler->throwError(QFINDER_CONNECTOR_ERROR_INVALID_REQUEST);
  98. }
  99. // check #7 (Access Control, need file view permission to source files)
  100. if (!isset($aclMasks[$type."@".$path])) {
  101. $aclMasks[$type."@".$path] = $_aclConfig->getComputedMask($type, $path);
  102. }
  103. $isAuthorized = (($aclMasks[$type."@".$path] & QFINDER_CONNECTOR_ACL_FILE_VIEW) == QFINDER_CONNECTOR_ACL_FILE_VIEW);
  104. if (!$isAuthorized) {
  105. $this->_errorHandler->throwError(QFINDER_CONNECTOR_ERROR_UNAUTHORIZED);
  106. }
  107. // check #8 (invalid file name)
  108. if (!file_exists($sourceFilePath) || !is_file($sourceFilePath)) {
  109. $errorCode = QFINDER_CONNECTOR_ERROR_FILE_NOT_FOUND;
  110. $this->appendErrorNode($oErrorsNode, $errorCode, $name, $type, $path);
  111. continue;
  112. }
  113. // check #9 (max size)
  114. if ($currentResourceTypeConfig->getName() != $type) {
  115. $maxSize = $currentResourceTypeConfig->getMaxSize();
  116. $fileSize = filesize($sourceFilePath);
  117. if ($maxSize && $fileSize>$maxSize) {
  118. $errorCode = QFINDER_CONNECTOR_ERROR_UPLOADED_TOO_BIG;
  119. $this->appendErrorNode($oErrorsNode, $errorCode, $name, $type, $path);
  120. continue;
  121. }
  122. }
  123. //$overwrite
  124. // finally, no errors so far, we may attempt to copy a file
  125. // protection against copying files to itself
  126. if ($sourceFilePath == $destinationFilePath) {
  127. $errorCode = QFINDER_CONNECTOR_ERROR_SOURCE_AND_TARGET_PATH_EQUAL;
  128. $this->appendErrorNode($oErrorsNode, $errorCode, $name, $type, $path);
  129. continue;
  130. }
  131. // check if file exists if we don't force overwriting
  132. else if (file_exists($destinationFilePath) && strpos($options, "overwrite") === false) {
  133. if (strpos($options, "autorename") !== false) {
  134. $fileName = QFinder_Connector_Utils_FileSystem::autoRename($sServerDir, $name);
  135. $destinationFilePath = $sServerDir.$fileName;
  136. if (!@copy($sourceFilePath, $destinationFilePath)) {
  137. $errorCode = QFINDER_CONNECTOR_ERROR_ACCESS_DENIED;
  138. $this->appendErrorNode($oErrorsNode, $errorCode, $name, $type, $path);
  139. continue;
  140. }
  141. else {
  142. $copied++;
  143. }
  144. }
  145. else {
  146. $errorCode = QFINDER_CONNECTOR_ERROR_ALREADY_EXIST;
  147. $this->appendErrorNode($oErrorsNode, $errorCode, $name, $type, $path);
  148. continue;
  149. }
  150. }
  151. // copy() overwrites without warning
  152. else {
  153. if (!@copy($sourceFilePath, $destinationFilePath)) {
  154. $errorCode = QFINDER_CONNECTOR_ERROR_ACCESS_DENIED;
  155. $this->appendErrorNode($oErrorsNode, $errorCode, $name, $type, $path);
  156. continue;
  157. }
  158. else {
  159. $copied++;
  160. }
  161. }
  162. }
  163. }
  164. $this->_connectorNode->addChild($oCopyFilesNode);
  165. if ($errorCode != QFINDER_CONNECTOR_ERROR_NONE) {
  166. $this->_connectorNode->addChild($oErrorsNode);
  167. }
  168. $oCopyFilesNode->addAttribute("copied", $copied);
  169. $oCopyFilesNode->addAttribute("copiedTotal", $copiedAll + $copied);
  170. /**
  171. * Note: actually we could have more than one error.
  172. * This is just a flag for QFinder interface telling it to check all errors.
  173. */
  174. if ($errorCode != QFINDER_CONNECTOR_ERROR_NONE) {
  175. $this->_errorHandler->throwError(QFINDER_CONNECTOR_ERROR_COPY_FAILED);
  176. }
  177. }
  178. private function appendErrorNode($oErrorsNode, $errorCode, $name, $type, $path)
  179. {
  180. $oErrorNode = new QFinder_Connector_Utils_XmlNode("Error");
  181. $oErrorNode->addAttribute("code", $errorCode);
  182. $oErrorNode->addAttribute("name", QFinder_Connector_Utils_FileSystem::convertToConnectorEncoding($name));
  183. $oErrorNode->addAttribute("type", $type);
  184. $oErrorNode->addAttribute("folder", $path);
  185. $oErrorsNode->addChild($oErrorNode);
  186. }
  187. }