@@ -40,10 +40,11 @@ public function __construct($parameters) {
4040 }
4141
4242 /**
43+ * @see Operation::checkFileAccess()
4344 * @throws ForbiddenException
4445 */
45- protected function checkFileAccess (string $ path , ?bool $ isDir = null ): void {
46- $ this ->operation ->checkFileAccess ($ path , $ this ->mount , is_bool ($ isDir ) ? $ isDir : $ this ->is_dir ($ path ));
46+ protected function checkFileAccess (string $ path , ?bool $ isDir = null , ? int $ permissions = null ): ? int {
47+ return $ this ->operation ->checkFileAccess ($ path , $ this ->mount , is_bool ($ isDir ) ? $ isDir : $ this ->is_dir ($ path ), null , $ permissions ?? Constants:: PERMISSION_ALL );
4748 }
4849
4950 /*
@@ -59,7 +60,7 @@ protected function checkFileAccess(string $path, ?bool $isDir = null): void {
5960 */
6061 #[\Override]
6162 public function mkdir ($ path ): bool {
62- $ this ->checkFileAccess ($ path , true );
63+ $ this ->checkFileAccess ($ path , true , Constants:: PERMISSION_CREATE );
6364 return $ this ->storage ->mkdir ($ path );
6465 }
6566
@@ -72,7 +73,7 @@ public function mkdir($path): bool {
7273 */
7374 #[\Override]
7475 public function rmdir ($ path ): bool {
75- $ this ->checkFileAccess ($ path , true );
76+ $ this ->checkFileAccess ($ path , true , Constants:: PERMISSION_DELETE );
7677 return $ this ->storage ->rmdir ($ path );
7778 }
7879
@@ -85,7 +86,7 @@ public function rmdir($path): bool {
8586 #[\Override]
8687 public function isCreatable ($ path ): bool {
8788 try {
88- $ this ->checkFileAccess ($ path );
89+ $ this ->checkFileAccess ($ path, null , Constants:: PERMISSION_CREATE );
8990 } catch (ForbiddenException ) {
9091 return false ;
9192 }
@@ -101,7 +102,7 @@ public function isCreatable($path): bool {
101102 #[\Override]
102103 public function isReadable ($ path ): bool {
103104 try {
104- $ this ->checkFileAccess ($ path );
105+ $ this ->checkFileAccess ($ path, null , Constants:: PERMISSION_READ );
105106 } catch (ForbiddenException ) {
106107 return false ;
107108 }
@@ -117,7 +118,7 @@ public function isReadable($path): bool {
117118 #[\Override]
118119 public function isUpdatable ($ path ): bool {
119120 try {
120- $ this ->checkFileAccess ($ path );
121+ $ this ->checkFileAccess ($ path, null , Constants:: PERMISSION_UPDATE );
121122 } catch (ForbiddenException ) {
122123 return false ;
123124 }
@@ -133,7 +134,7 @@ public function isUpdatable($path): bool {
133134 #[\Override]
134135 public function isDeletable ($ path ): bool {
135136 try {
136- $ this ->checkFileAccess ($ path );
137+ $ this ->checkFileAccess ($ path, null , Constants:: PERMISSION_DELETE );
137138 } catch (ForbiddenException ) {
138139 return false ;
139140 }
@@ -143,10 +144,16 @@ public function isDeletable($path): bool {
143144 #[\Override]
144145 public function getPermissions ($ path ): int {
145146 try {
146- $ this ->checkFileAccess ($ path );
147+ $ permissions = $ this ->checkFileAccess ($ path, null , 0 );
147148 } catch (ForbiddenException ) {
148149 return $ this ->mask ;
149150 }
151+
152+ if ($ permissions !== null ) {
153+ // override with permissions granted by the operation, if any
154+ return $ permissions & $ this ->storage ->getPermissions ($ path );
155+ }
156+
150157 return $ this ->storage ->getPermissions ($ path );
151158 }
152159
@@ -159,7 +166,7 @@ public function getPermissions($path): int {
159166 */
160167 #[\Override]
161168 public function file_get_contents ($ path ): string |false {
162- $ this ->checkFileAccess ($ path , false );
169+ $ this ->checkFileAccess ($ path , false , Constants:: PERMISSION_READ );
163170 return $ this ->storage ->file_get_contents ($ path );
164171 }
165172
@@ -173,7 +180,7 @@ public function file_get_contents($path): string|false {
173180 */
174181 #[\Override]
175182 public function file_put_contents (string $ path , mixed $ data ): int |float |false {
176- $ this ->checkFileAccess ($ path , false );
183+ $ this ->checkFileAccess ($ path , false , Constants:: PERMISSION_CREATE | Constants:: PERMISSION_UPDATE );
177184 return $ this ->storage ->file_put_contents ($ path , $ data );
178185 }
179186
@@ -186,7 +193,7 @@ public function file_put_contents(string $path, mixed $data): int|float|false {
186193 */
187194 #[\Override]
188195 public function unlink ($ path ): bool {
189- $ this ->checkFileAccess ($ path , false );
196+ $ this ->checkFileAccess ($ path , false , Constants:: PERMISSION_DELETE );
190197 return $ this ->storage ->unlink ($ path );
191198 }
192199
@@ -201,8 +208,8 @@ public function unlink($path): bool {
201208 #[\Override]
202209 public function rename ($ source , $ target ): bool {
203210 $ isDir = $ this ->is_dir ($ source );
204- $ this ->checkFileAccess ($ source , $ isDir );
205- $ this ->checkFileAccess ($ target , $ isDir );
211+ $ this ->checkFileAccess ($ source , $ isDir, Constants:: PERMISSION_READ | Constants:: PERMISSION_DELETE );
212+ $ this ->checkFileAccess ($ target , $ isDir, Constants:: PERMISSION_CREATE );
206213 return $ this ->storage ->rename ($ source , $ target );
207214 }
208215
@@ -217,8 +224,8 @@ public function rename($source, $target): bool {
217224 #[\Override]
218225 public function copy ($ source , $ target ): bool {
219226 $ isDir = $ this ->is_dir ($ source );
220- $ this ->checkFileAccess ($ source , $ isDir );
221- $ this ->checkFileAccess ($ target , $ isDir );
227+ $ this ->checkFileAccess ($ source , $ isDir, Constants:: PERMISSION_READ );
228+ $ this ->checkFileAccess ($ target , $ isDir, Constants:: PERMISSION_CREATE );
222229 return $ this ->storage ->copy ($ source , $ target );
223230 }
224231
@@ -232,7 +239,18 @@ public function copy($source, $target): bool {
232239 */
233240 #[\Override]
234241 public function fopen ($ path , $ mode ) {
235- $ this ->checkFileAccess ($ path , false );
242+ $ hasPlus = str_contains ($ mode , '+ ' );
243+ $ isRead = str_contains ($ mode , 'r ' );
244+ $ isExclusive = str_contains ($ mode , 'x ' );
245+ $ isWac = str_contains ($ mode , 'w ' ) || str_contains ($ mode , 'a ' ) || str_contains ($ mode , 'c ' );
246+ $ checkPermissions = match (true ) {
247+ $ isWac => Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | ($ hasPlus ? Constants::PERMISSION_READ : 0 ),
248+ $ isExclusive => Constants::PERMISSION_CREATE | ($ hasPlus ? Constants::PERMISSION_READ : 0 ),
249+ $ isRead => Constants::PERMISSION_READ | ($ hasPlus ? Constants::PERMISSION_UPDATE : 0 ),
250+ default => Constants::PERMISSION_ALL ,
251+ };
252+
253+ $ this ->checkFileAccess ($ path , false , $ checkPermissions );
236254 return $ this ->storage ->fopen ($ path , $ mode );
237255 }
238256
@@ -247,7 +265,7 @@ public function fopen($path, $mode) {
247265 */
248266 #[\Override]
249267 public function touch ($ path , $ mtime = null ): bool {
250- $ this ->checkFileAccess ($ path , false );
268+ $ this ->checkFileAccess ($ path , false , Constants:: PERMISSION_CREATE | Constants:: PERMISSION_UPDATE );
251269 return $ this ->storage ->touch ($ path , $ mtime );
252270 }
253271
@@ -278,7 +296,7 @@ public function getCache($path = '', $storage = null): ICache {
278296 */
279297 #[\Override]
280298 public function getDirectDownload ($ path ): array |false {
281- $ this ->checkFileAccess ($ path , false );
299+ $ this ->checkFileAccess ($ path , false , Constants:: PERMISSION_READ );
282300 return $ this ->storage ->getDirectDownload ($ path );
283301 }
284302
@@ -302,7 +320,7 @@ public function getDirectDownloadById(string $fileId): array|false {
302320 // We would have actually a result, so lets see if the user should be able to access it
303321 $ path = $ this ->getCache ()->getPathById ((int )$ fileId );
304322 if ($ path !== null ) {
305- $ this ->checkFileAccess ($ path , false );
323+ $ this ->checkFileAccess ($ path , false , Constants:: PERMISSION_READ );
306324 }
307325
308326 return $ data ;
@@ -321,7 +339,7 @@ public function copyFromStorage(IStorage $sourceStorage, $sourceInternalPath, $t
321339 return $ this ->copy ($ sourceInternalPath , $ targetInternalPath );
322340 }
323341
324- $ this ->checkFileAccess ($ targetInternalPath , $ sourceStorage ->is_dir ($ sourceInternalPath ));
342+ $ this ->checkFileAccess ($ targetInternalPath , $ sourceStorage ->is_dir ($ sourceInternalPath ), Constants:: PERMISSION_CREATE );
325343 return $ this ->storage ->copyFromStorage ($ sourceStorage , $ sourceInternalPath , $ targetInternalPath );
326344 }
327345
@@ -338,7 +356,7 @@ public function moveFromStorage(IStorage $sourceStorage, $sourceInternalPath, $t
338356 return $ this ->rename ($ sourceInternalPath , $ targetInternalPath );
339357 }
340358
341- $ this ->checkFileAccess ($ targetInternalPath , $ sourceStorage ->is_dir ($ sourceInternalPath ));
359+ $ this ->checkFileAccess ($ targetInternalPath , $ sourceStorage ->is_dir ($ sourceInternalPath ), Constants:: PERMISSION_CREATE );
342360 return $ this ->storage ->moveFromStorage ($ sourceStorage , $ sourceInternalPath , $ targetInternalPath );
343361 }
344362
@@ -348,7 +366,7 @@ public function moveFromStorage(IStorage $sourceStorage, $sourceInternalPath, $t
348366 #[\Override]
349367 public function writeStream (string $ path , $ stream , ?int $ size = null ): int {
350368 if (!$ this ->isPartFile ($ path )) {
351- $ this ->checkFileAccess ($ path , false );
369+ $ this ->checkFileAccess ($ path , false , Constants:: PERMISSION_CREATE | Constants:: PERMISSION_UPDATE );
352370 }
353371
354372 $ result = parent ::writeStream ($ path , $ stream , $ size );
@@ -359,7 +377,7 @@ public function writeStream(string $path, $stream, ?int $size = null): int {
359377 // Required for object storage since part file is not in the storage so we cannot check it before moving it to the storage
360378 // As an alternative we might be able to check on the cache update/insert/delete though the Cache wrapper
361379 try {
362- $ this ->checkFileAccess ($ path , false );
380+ $ this ->checkFileAccess ($ path , false , Constants:: PERMISSION_CREATE | Constants:: PERMISSION_UPDATE );
363381 } catch (\Exception $ e ) {
364382 $ this ->storage ->unlink ($ path );
365383 throw $ e ;
0 commit comments