Directory.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. <?php
  2. declare(strict_types=1);
  3. namespace Sabre\DAV\FSExt;
  4. use Sabre\DAV;
  5. use Sabre\DAV\FS\Node;
  6. /**
  7. * Directory class.
  8. *
  9. * @copyright Copyright (C) fruux GmbH (https://fruux.com/)
  10. * @author Evert Pot (http://evertpot.com/)
  11. * @license http://sabre.io/license/ Modified BSD License
  12. */
  13. class Directory extends Node implements DAV\ICollection, DAV\IQuota, DAV\IMoveTarget
  14. {
  15. /**
  16. * Creates a new file in the directory.
  17. *
  18. * Data will either be supplied as a stream resource, or in certain cases
  19. * as a string. Keep in mind that you may have to support either.
  20. *
  21. * After successful creation of the file, you may choose to return the ETag
  22. * of the new file here.
  23. *
  24. * The returned ETag must be surrounded by double-quotes (The quotes should
  25. * be part of the actual string).
  26. *
  27. * If you cannot accurately determine the ETag, you should not return it.
  28. * If you don't store the file exactly as-is (you're transforming it
  29. * somehow) you should also not return an ETag.
  30. *
  31. * This means that if a subsequent GET to this new file does not exactly
  32. * return the same contents of what was submitted here, you are strongly
  33. * recommended to omit the ETag.
  34. *
  35. * @param string $name Name of the file
  36. * @param resource|string $data Initial payload
  37. *
  38. * @return string|null
  39. */
  40. public function createFile($name, $data = null)
  41. {
  42. // We're not allowing dots
  43. if ('.' == $name || '..' == $name) {
  44. throw new DAV\Exception\Forbidden('Permission denied to . and ..');
  45. }
  46. $newPath = $this->path.'/'.$name;
  47. file_put_contents($newPath, $data);
  48. clearstatcache(true, $newPath);
  49. return '"'.sha1(
  50. fileinode($newPath).
  51. filesize($newPath).
  52. filemtime($newPath)
  53. ).'"';
  54. }
  55. /**
  56. * Creates a new subdirectory.
  57. *
  58. * @param string $name
  59. */
  60. public function createDirectory($name)
  61. {
  62. // We're not allowing dots
  63. if ('.' == $name || '..' == $name) {
  64. throw new DAV\Exception\Forbidden('Permission denied to . and ..');
  65. }
  66. $newPath = $this->path.'/'.$name;
  67. mkdir($newPath);
  68. clearstatcache(true, $newPath);
  69. }
  70. /**
  71. * Returns a specific child node, referenced by its name.
  72. *
  73. * This method must throw Sabre\DAV\Exception\NotFound if the node does not
  74. * exist.
  75. *
  76. * @param string $name
  77. *
  78. * @throws DAV\Exception\NotFound
  79. *
  80. * @return DAV\INode
  81. */
  82. public function getChild($name)
  83. {
  84. $path = $this->path.'/'.$name;
  85. if (!file_exists($path)) {
  86. throw new DAV\Exception\NotFound('File could not be located');
  87. }
  88. if ('.' == $name || '..' == $name) {
  89. throw new DAV\Exception\Forbidden('Permission denied to . and ..');
  90. }
  91. if (is_dir($path)) {
  92. return new self($path);
  93. } else {
  94. return new File($path);
  95. }
  96. }
  97. /**
  98. * Checks if a child exists.
  99. *
  100. * @param string $name
  101. *
  102. * @return bool
  103. */
  104. public function childExists($name)
  105. {
  106. if ('.' == $name || '..' == $name) {
  107. throw new DAV\Exception\Forbidden('Permission denied to . and ..');
  108. }
  109. $path = $this->path.'/'.$name;
  110. return file_exists($path);
  111. }
  112. /**
  113. * Returns an array with all the child nodes.
  114. *
  115. * @return DAV\INode[]
  116. */
  117. public function getChildren()
  118. {
  119. $nodes = [];
  120. $iterator = new \FilesystemIterator(
  121. $this->path,
  122. \FilesystemIterator::CURRENT_AS_SELF
  123. | \FilesystemIterator::SKIP_DOTS
  124. );
  125. foreach ($iterator as $entry) {
  126. $nodes[] = $this->getChild($entry->getFilename());
  127. }
  128. return $nodes;
  129. }
  130. /**
  131. * Deletes all files in this directory, and then itself.
  132. *
  133. * @return bool
  134. */
  135. public function delete()
  136. {
  137. // Deleting all children
  138. foreach ($this->getChildren() as $child) {
  139. $child->delete();
  140. }
  141. // Removing the directory itself
  142. rmdir($this->path);
  143. return true;
  144. }
  145. /**
  146. * Returns available diskspace information.
  147. *
  148. * @return array
  149. */
  150. public function getQuotaInfo()
  151. {
  152. $total = disk_total_space(realpath($this->path));
  153. $free = disk_free_space(realpath($this->path));
  154. return [
  155. $total - $free,
  156. $free,
  157. ];
  158. }
  159. /**
  160. * Moves a node into this collection.
  161. *
  162. * It is up to the implementors to:
  163. * 1. Create the new resource.
  164. * 2. Remove the old resource.
  165. * 3. Transfer any properties or other data.
  166. *
  167. * Generally you should make very sure that your collection can easily move
  168. * the move.
  169. *
  170. * If you don't, just return false, which will trigger sabre/dav to handle
  171. * the move itself. If you return true from this function, the assumption
  172. * is that the move was successful.
  173. *
  174. * @param string $targetName new local file/collection name
  175. * @param string $sourcePath Full path to source node
  176. * @param DAV\INode $sourceNode Source node itself
  177. *
  178. * @return bool
  179. */
  180. public function moveInto($targetName, $sourcePath, DAV\INode $sourceNode)
  181. {
  182. // We only support FSExt\Directory or FSExt\File objects, so
  183. // anything else we want to quickly reject.
  184. if (!$sourceNode instanceof self && !$sourceNode instanceof File) {
  185. return false;
  186. }
  187. // PHP allows us to access protected properties from other objects, as
  188. // long as they are defined in a class that has a shared inheritance
  189. // with the current class.
  190. return rename($sourceNode->path, $this->path.'/'.$targetName);
  191. }
  192. }