PageRenderTime 43ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/connector/sabre/directory.php

https://github.com/sezuan/core
PHP | 264 lines | 131 code | 33 blank | 100 comment | 26 complexity | b13cba3a85a2d2c236a2851a069acf13 MD5 | raw file
Possible License(s): AGPL-3.0, AGPL-1.0, MPL-2.0-no-copyleft-exception
  1. <?php
  2. /**
  3. * ownCloud
  4. *
  5. * @author Jakob Sack
  6. * @copyright 2011 Jakob Sack kde@jakobsack.de
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
  10. * License as published by the Free Software Foundation; either
  11. * version 3 of the License, or any later version.
  12. *
  13. * This library is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
  17. *
  18. * You should have received a copy of the GNU Affero General Public
  19. * License along with this library. If not, see <http://www.gnu.org/licenses/>.
  20. *
  21. */
  22. class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sabre_DAV_ICollection, Sabre_DAV_IQuota {
  23. /**
  24. * Creates a new file in the directory
  25. *
  26. * Data will either be supplied as a stream resource, or in certain cases
  27. * as a string. Keep in mind that you may have to support either.
  28. *
  29. * After succesful creation of the file, you may choose to return the ETag
  30. * of the new file here.
  31. *
  32. * The returned ETag must be surrounded by double-quotes (The quotes should
  33. * be part of the actual string).
  34. *
  35. * If you cannot accurately determine the ETag, you should not return it.
  36. * If you don't store the file exactly as-is (you're transforming it
  37. * somehow) you should also not return an ETag.
  38. *
  39. * This means that if a subsequent GET to this new file does not exactly
  40. * return the same contents of what was submitted here, you are strongly
  41. * recommended to omit the ETag.
  42. *
  43. * @param string $name Name of the file
  44. * @param resource|string $data Initial payload
  45. * @throws Sabre_DAV_Exception_Forbidden
  46. * @return null|string
  47. */
  48. public function createFile($name, $data = null) {
  49. if (!\OC\Files\Filesystem::isCreatable($this->path)) {
  50. throw new \Sabre_DAV_Exception_Forbidden();
  51. }
  52. if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
  53. $info = OC_FileChunking::decodeName($name);
  54. if (empty($info)) {
  55. throw new Sabre_DAV_Exception_NotImplemented();
  56. }
  57. $chunk_handler = new OC_FileChunking($info);
  58. $chunk_handler->store($info['index'], $data);
  59. if ($chunk_handler->isComplete()) {
  60. $newPath = $this->path . '/' . $info['name'];
  61. $chunk_handler->file_assemble($newPath);
  62. return OC_Connector_Sabre_Node::getETagPropertyForPath($newPath);
  63. }
  64. } else {
  65. $newPath = $this->path . '/' . $name;
  66. // mark file as partial while uploading (ignored by the scanner)
  67. $partpath = $newPath . '.part';
  68. \OC\Files\Filesystem::file_put_contents($partpath, $data);
  69. //detect aborted upload
  70. if (isset ($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PUT' ) {
  71. if (isset($_SERVER['CONTENT_LENGTH'])) {
  72. $expected = $_SERVER['CONTENT_LENGTH'];
  73. $actual = \OC\Files\Filesystem::filesize($partpath);
  74. if ($actual != $expected) {
  75. \OC\Files\Filesystem::unlink($partpath);
  76. throw new Sabre_DAV_Exception_BadRequest(
  77. 'expected filesize ' . $expected . ' got ' . $actual);
  78. }
  79. }
  80. }
  81. // rename to correct path
  82. \OC\Files\Filesystem::rename($partpath, $newPath);
  83. // allow sync clients to send the mtime along in a header
  84. $mtime = OC_Request::hasModificationTime();
  85. if ($mtime !== false) {
  86. if(\OC\Files\Filesystem::touch($newPath, $mtime)) {
  87. header('X-OC-MTime: accepted');
  88. }
  89. }
  90. return OC_Connector_Sabre_Node::getETagPropertyForPath($newPath);
  91. }
  92. return null;
  93. }
  94. /**
  95. * Creates a new subdirectory
  96. *
  97. * @param string $name
  98. * @throws Sabre_DAV_Exception_Forbidden
  99. * @return void
  100. */
  101. public function createDirectory($name) {
  102. if (!\OC\Files\Filesystem::isCreatable($this->path)) {
  103. throw new \Sabre_DAV_Exception_Forbidden();
  104. }
  105. $newPath = $this->path . '/' . $name;
  106. if(!\OC\Files\Filesystem::mkdir($newPath)) {
  107. throw new Sabre_DAV_Exception_Forbidden('Could not create directory '.$newPath);
  108. }
  109. }
  110. /**
  111. * Returns a specific child node, referenced by its name
  112. *
  113. * @param string $name
  114. * @throws Sabre_DAV_Exception_FileNotFound
  115. * @return Sabre_DAV_INode
  116. */
  117. public function getChild($name, $info = null) {
  118. $path = $this->path . '/' . $name;
  119. if (is_null($info)) {
  120. $info = \OC\Files\Filesystem::getFileInfo($path);
  121. }
  122. if (!$info) {
  123. throw new Sabre_DAV_Exception_NotFound('File with name ' . $path . ' could not be located');
  124. }
  125. if ($info['mimetype'] == 'httpd/unix-directory') {
  126. $node = new OC_Connector_Sabre_Directory($path);
  127. } else {
  128. $node = new OC_Connector_Sabre_File($path);
  129. }
  130. $node->setFileinfoCache($info);
  131. return $node;
  132. }
  133. /**
  134. * Returns an array with all the child nodes
  135. *
  136. * @return Sabre_DAV_INode[]
  137. */
  138. public function getChildren() {
  139. $folder_content = \OC\Files\Filesystem::getDirectoryContent($this->path);
  140. $paths = array();
  141. foreach($folder_content as $info) {
  142. $paths[] = $this->path.'/'.$info['name'];
  143. $properties[$this->path.'/'.$info['name']][self::GETETAG_PROPERTYNAME] = '"' . $info['etag'] . '"';
  144. }
  145. if(count($paths)>0) {
  146. //
  147. // the number of arguments within IN conditions are limited in most databases
  148. // we chunk $paths into arrays of 200 items each to meet this criteria
  149. //
  150. $chunks = array_chunk($paths, 200, false);
  151. foreach ($chunks as $pack) {
  152. $placeholders = join(',', array_fill(0, count($pack), '?'));
  153. $query = OC_DB::prepare( 'SELECT * FROM `*PREFIX*properties`'
  154. .' WHERE `userid` = ?' . ' AND `propertypath` IN ('.$placeholders.')' );
  155. array_unshift($pack, OC_User::getUser()); // prepend userid
  156. $result = $query->execute( $pack );
  157. while($row = $result->fetchRow()) {
  158. $propertypath = $row['propertypath'];
  159. $propertyname = $row['propertyname'];
  160. $propertyvalue = $row['propertyvalue'];
  161. if($propertyname !== self::GETETAG_PROPERTYNAME) {
  162. $properties[$propertypath][$propertyname] = $propertyvalue;
  163. }
  164. }
  165. }
  166. }
  167. $nodes = array();
  168. foreach($folder_content as $info) {
  169. $node = $this->getChild($info['name'], $info);
  170. $node->setPropertyCache($properties[$this->path.'/'.$info['name']]);
  171. $nodes[] = $node;
  172. }
  173. return $nodes;
  174. }
  175. /**
  176. * Checks if a child exists.
  177. *
  178. * @param string $name
  179. * @return bool
  180. */
  181. public function childExists($name) {
  182. $path = $this->path . '/' . $name;
  183. return \OC\Files\Filesystem::file_exists($path);
  184. }
  185. /**
  186. * Deletes all files in this directory, and then itself
  187. *
  188. * @return void
  189. * @throws Sabre_DAV_Exception_Forbidden
  190. */
  191. public function delete() {
  192. if (!\OC\Files\Filesystem::isDeletable($this->path)) {
  193. throw new \Sabre_DAV_Exception_Forbidden();
  194. }
  195. if ($this->path != "/Shared") {
  196. foreach($this->getChildren() as $child) $child->delete();
  197. \OC\Files\Filesystem::rmdir($this->path);
  198. }
  199. }
  200. /**
  201. * Returns available diskspace information
  202. *
  203. * @return array
  204. */
  205. public function getQuotaInfo() {
  206. $rootInfo=\OC\Files\Filesystem::getFileInfo('');
  207. return array(
  208. $rootInfo['size'],
  209. \OC\Files\Filesystem::free_space()
  210. );
  211. }
  212. /**
  213. * Returns a list of properties for this nodes.;
  214. *
  215. * The properties list is a list of propertynames the client requested,
  216. * encoded as xmlnamespace#tagName, for example:
  217. * http://www.example.org/namespace#author
  218. * If the array is empty, all properties should be returned
  219. *
  220. * @param array $properties
  221. * @return void
  222. */
  223. public function getProperties($properties) {
  224. $props = parent::getProperties($properties);
  225. if (in_array(self::GETETAG_PROPERTYNAME, $properties) && !isset($props[self::GETETAG_PROPERTYNAME])) {
  226. $props[self::GETETAG_PROPERTYNAME]
  227. = OC_Connector_Sabre_Node::getETagPropertyForPath($this->path);
  228. }
  229. return $props;
  230. }
  231. }