This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | /** |
||
4 | * This program is free software: you can redistribute it and/or modify |
||
5 | * it under the terms of the GNU Lesser General Public License as published by |
||
6 | * the Free Software Foundation, either version 3 of the License, or |
||
7 | * (at your option) any later version. |
||
8 | * |
||
9 | * This program is distributed in the hope that it will be useful, |
||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
12 | * GNU Lesser General Public License for more details. |
||
13 | * |
||
14 | * You should have received a copy of the GNU Lesser General Public License |
||
15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
||
16 | */ |
||
17 | |||
18 | namespace fkooman\RemoteStorage; |
||
19 | |||
20 | use fkooman\RemoteStorage\Exception\DocumentStorageException; |
||
21 | use fkooman\RemoteStorage\Http\Exception\HttpException; |
||
22 | use RecursiveDirectoryIterator; |
||
23 | use RecursiveIteratorIterator; |
||
24 | use RuntimeException; |
||
25 | |||
26 | class DocumentStorage |
||
27 | { |
||
28 | private $baseDir; |
||
29 | |||
30 | public function __construct($baseDir) |
||
31 | { |
||
32 | // check if baseDir exists, if not, try to create it |
||
33 | if (!is_dir($baseDir)) { |
||
34 | if (false === @mkdir($baseDir, 0770, true)) { |
||
35 | throw new RuntimeException('unable to create baseDir'); |
||
36 | } |
||
37 | } |
||
38 | $this->baseDir = $baseDir; |
||
39 | } |
||
40 | |||
41 | View Code Duplication | public function isDocument(Path $p) |
|
0 ignored issues
–
show
|
|||
42 | { |
||
43 | $documentPath = $this->baseDir.$p->getPath(); |
||
44 | if (false === file_exists($documentPath) || !is_file($documentPath)) { |
||
45 | return false; |
||
46 | } |
||
47 | |||
48 | return true; |
||
49 | } |
||
50 | |||
51 | /** |
||
52 | * Get the full absolute location of the document on the filesystem. |
||
53 | */ |
||
54 | View Code Duplication | public function getDocumentPath(Path $p) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
55 | { |
||
56 | $documentPath = $this->baseDir.$p->getPath(); |
||
57 | if (!is_readable($documentPath)) { |
||
58 | throw new DocumentStorageException('unable to read document'); |
||
59 | } |
||
60 | |||
61 | return $documentPath; |
||
62 | } |
||
63 | |||
64 | public function getDocument(Path $p) |
||
65 | { |
||
66 | $documentPath = $this->baseDir.$p->getPath(); |
||
67 | if (!is_readable($documentPath)) { |
||
68 | throw new DocumentStorageException('unable to read document'); |
||
69 | } |
||
70 | $documentContent = @file_get_contents($documentPath); |
||
71 | if (false === $documentContent) { |
||
72 | throw new DocumentStorageException('error reading document'); |
||
73 | } |
||
74 | |||
75 | return $documentContent; |
||
76 | } |
||
77 | |||
78 | /** |
||
79 | * Store a new document. |
||
80 | * |
||
81 | * @returns an array of all created objects |
||
82 | */ |
||
83 | public function putDocument(Path $p, $documentContent) |
||
84 | { |
||
85 | $folderTree = $p->getFolderTreeFromUserRoot(); |
||
86 | foreach ($folderTree as $pathItem) { |
||
87 | $folderPath = $this->baseDir.$pathItem; |
||
88 | $folderPathAsFile = substr($folderPath, 0, strlen($folderPath) - 1); |
||
89 | if (file_exists($folderPathAsFile) && is_file($folderPathAsFile)) { |
||
90 | throw new HttpException('file already exists in path preventing folder creation', 409); |
||
91 | } |
||
92 | if (!file_exists($folderPath)) { |
||
93 | // create it |
||
94 | if (false === @mkdir($this->baseDir.$pathItem, 0770)) { |
||
95 | throw new DocumentStorageException('unable to create directory'); |
||
96 | } |
||
97 | } |
||
98 | } |
||
99 | |||
100 | $documentPath = $this->baseDir.$p->getPath(); |
||
101 | if (file_exists($documentPath) && is_dir($documentPath)) { |
||
102 | throw new HttpException('document path is already a folder', 409); |
||
103 | } |
||
104 | if (false === @file_put_contents($documentPath, $documentContent, LOCK_EX)) { |
||
105 | throw new DocumentStorageException('unable to write document'); |
||
106 | } |
||
107 | // PHP caches files and doesn't flush on getting file size, so we |
||
108 | // really have to flush the cache manually, otherwise directory listings |
||
109 | // potentially give you the wrong information. This only affects the |
||
110 | // unit tests, as getting a directory listing and putting a file are |
||
111 | // always separate script executions |
||
112 | clearstatcache(true, $documentPath); |
||
113 | |||
114 | return $folderTree; |
||
115 | } |
||
116 | |||
117 | /** |
||
118 | * Delete a document and all empty parent directories if there are any. |
||
119 | * |
||
120 | * @param $p the path of a document to delete |
||
121 | * @returns an array of all deleted objects |
||
122 | */ |
||
123 | public function deleteDocument(Path $p) |
||
124 | { |
||
125 | $documentPath = $this->baseDir.$p->getPath(); |
||
126 | if (false === @unlink($documentPath)) { |
||
127 | throw new DocumentStorageException('unable to delete file'); |
||
128 | } |
||
129 | |||
130 | $deletedObjects = []; |
||
131 | $deletedObjects[] = $p->getPath(); |
||
132 | |||
133 | // delete all empty folders in the tree up to the user root if |
||
134 | // they are empty |
||
135 | foreach ($p->getFolderTreeToUserRoot() as $pathItem) { |
||
136 | if ($this->isEmptyFolder(new Path($pathItem))) { |
||
137 | $this->deleteFolder(new Path($pathItem)); |
||
138 | $deletedObjects[] = $pathItem; |
||
139 | } |
||
140 | } |
||
141 | |||
142 | return $deletedObjects; |
||
143 | } |
||
144 | |||
145 | View Code Duplication | public function isFolder(Path $p) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
146 | { |
||
147 | $folderPath = $this->baseDir.$p->getPath(); |
||
148 | if (false === file_exists($folderPath) || !is_dir($folderPath)) { |
||
149 | return false; |
||
150 | } |
||
151 | |||
152 | return true; |
||
153 | } |
||
154 | |||
155 | public function getFolder(Path $p) |
||
156 | { |
||
157 | $folderPath = $this->baseDir.$p->getPath(); |
||
158 | $entries = glob($folderPath.'*', GLOB_ERR | GLOB_MARK); |
||
159 | if (false === $entries) { |
||
160 | // directory does not exist, return empty list |
||
161 | return []; |
||
162 | } |
||
163 | $folderEntries = []; |
||
164 | foreach ($entries as $e) { |
||
165 | if (is_dir($e)) { |
||
166 | $folderEntries[basename($e).'/'] = []; |
||
167 | } else { |
||
168 | $folderEntries[basename($e)] = [ |
||
169 | 'Content-Length' => filesize($e), |
||
170 | ]; |
||
171 | } |
||
172 | } |
||
173 | |||
174 | return $folderEntries; |
||
175 | } |
||
176 | |||
177 | public function getFolderSize(Path $p) |
||
178 | { |
||
179 | if (!$this->isFolder($p)) { |
||
180 | return 0; |
||
181 | } |
||
182 | $folderPath = $this->baseDir.$p->getPath(); |
||
183 | $size = 0; |
||
184 | foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($folderPath)) as $file) { |
||
185 | $size += $file->getSize(); |
||
186 | } |
||
187 | |||
188 | return $size; |
||
189 | } |
||
190 | |||
191 | private function isEmptyFolder(Path $p) |
||
192 | { |
||
193 | $folderPath = $this->baseDir.$p->getPath(); |
||
194 | |||
195 | $entries = glob($folderPath.'*', GLOB_ERR); |
||
196 | if (false === $entries) { |
||
197 | throw new DocumentStorageException('unable to read folder'); |
||
198 | } |
||
199 | |||
200 | return 0 === count($entries); |
||
201 | } |
||
202 | |||
203 | View Code Duplication | private function deleteFolder(Path $p) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
204 | { |
||
205 | $folderPath = $this->baseDir.$p->getPath(); |
||
206 | if (false === @rmdir($folderPath)) { |
||
207 | throw new DocumentStorageException('unable to delete folder'); |
||
208 | } |
||
209 | } |
||
210 | } |
||
211 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.