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