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