1<?php 2 3namespace Sabre\DAV\FSExt; 4 5use Sabre\DAV; 6 7/** 8 * Base node-class 9 * 10 * The node class implements the method used by both the File and the Directory classes 11 * 12 * @copyright Copyright (C) 2007-2015 fruux GmbH (https://fruux.com/). 13 * @author Evert Pot (http://evertpot.com/) 14 * @license http://sabre.io/license/ Modified BSD License 15 */ 16abstract class Node extends DAV\FS\Node implements DAV\IProperties { 17 18 /** 19 * Updates properties on this node, 20 * 21 * @param array $properties 22 * @see Sabre\DAV\IProperties::updateProperties 23 * @return bool|array 24 */ 25 public function updateProperties($properties) { 26 27 $resourceData = $this->getResourceData(); 28 29 foreach($properties as $propertyName=>$propertyValue) { 30 31 // If it was null, we need to delete the property 32 if (is_null($propertyValue)) { 33 if (isset($resourceData['properties'][$propertyName])) { 34 unset($resourceData['properties'][$propertyName]); 35 } 36 } else { 37 $resourceData['properties'][$propertyName] = $propertyValue; 38 } 39 40 } 41 42 $this->putResourceData($resourceData); 43 return true; 44 } 45 46 /** 47 * Returns a list of properties for this nodes.; 48 * 49 * The properties list is a list of propertynames the client requested, encoded as xmlnamespace#tagName, for example: http://www.example.org/namespace#author 50 * If the array is empty, all properties should be returned 51 * 52 * @param array $properties 53 * @return array 54 */ 55 function getProperties($properties) { 56 57 $resourceData = $this->getResourceData(); 58 59 // if the array was empty, we need to return everything 60 if (!$properties) return $resourceData['properties']; 61 62 $props = array(); 63 foreach($properties as $property) { 64 if (isset($resourceData['properties'][$property])) $props[$property] = $resourceData['properties'][$property]; 65 } 66 67 return $props; 68 69 } 70 71 /** 72 * Returns the path to the resource file 73 * 74 * @return string 75 */ 76 protected function getResourceInfoPath() { 77 78 list($parentDir) = DAV\URLUtil::splitPath($this->path); 79 return $parentDir . '/.sabredav'; 80 81 } 82 83 /** 84 * Returns all the stored resource information 85 * 86 * @return array 87 */ 88 protected function getResourceData() { 89 90 $path = $this->getResourceInfoPath(); 91 if (!file_exists($path)) return array('properties' => array()); 92 93 // opening up the file, and creating a shared lock 94 $handle = fopen($path,'r'); 95 flock($handle,LOCK_SH); 96 $data = ''; 97 98 // Reading data until the eof 99 while(!feof($handle)) { 100 $data.=fread($handle,8192); 101 } 102 103 // We're all good 104 fclose($handle); 105 106 // Unserializing and checking if the resource file contains data for this file 107 $data = unserialize($data); 108 if (!isset($data[$this->getName()])) { 109 return array('properties' => array()); 110 } 111 112 $data = $data[$this->getName()]; 113 if (!isset($data['properties'])) $data['properties'] = array(); 114 return $data; 115 116 } 117 118 /** 119 * Updates the resource information 120 * 121 * @param array $newData 122 * @return void 123 */ 124 protected function putResourceData(array $newData) { 125 126 $path = $this->getResourceInfoPath(); 127 128 // opening up the file, and creating a shared lock 129 $handle = fopen($path,'a+'); 130 flock($handle,LOCK_EX); 131 $data = ''; 132 133 rewind($handle); 134 135 // Reading data until the eof 136 while(!feof($handle)) { 137 $data.=fread($handle,8192); 138 } 139 140 // Unserializing and checking if the resource file contains data for this file 141 $data = unserialize($data); 142 $data[$this->getName()] = $newData; 143 ftruncate($handle,0); 144 rewind($handle); 145 146 fwrite($handle,serialize($data)); 147 fclose($handle); 148 149 } 150 151 /** 152 * Renames the node 153 * 154 * @param string $name The new name 155 * @return void 156 */ 157 public function setName($name) { 158 159 list($parentPath, ) = DAV\URLUtil::splitPath($this->path); 160 list(, $newName) = DAV\URLUtil::splitPath($name); 161 $newPath = $parentPath . '/' . $newName; 162 163 // We're deleting the existing resourcedata, and recreating it 164 // for the new path. 165 $resourceData = $this->getResourceData(); 166 $this->deleteResourceData(); 167 168 rename($this->path,$newPath); 169 $this->path = $newPath; 170 $this->putResourceData($resourceData); 171 172 173 } 174 175 /** 176 * @return bool 177 */ 178 public function deleteResourceData() { 179 180 // When we're deleting this node, we also need to delete any resource information 181 $path = $this->getResourceInfoPath(); 182 if (!file_exists($path)) return true; 183 184 // opening up the file, and creating a shared lock 185 $handle = fopen($path,'a+'); 186 flock($handle,LOCK_EX); 187 $data = ''; 188 189 rewind($handle); 190 191 // Reading data until the eof 192 while(!feof($handle)) { 193 $data.=fread($handle,8192); 194 } 195 196 // Unserializing and checking if the resource file contains data for this file 197 $data = unserialize($data); 198 if (isset($data[$this->getName()])) unset($data[$this->getName()]); 199 ftruncate($handle,0); 200 rewind($handle); 201 fwrite($handle,serialize($data)); 202 fclose($handle); 203 204 return true; 205 } 206 207 public function delete() { 208 209 return $this->deleteResourceData(); 210 211 } 212 213} 214 215