aboutsummaryrefslogtreecommitdiffhomepage
path: root/application/FileUtils.php
diff options
context:
space:
mode:
Diffstat (limited to 'application/FileUtils.php')
-rw-r--r--application/FileUtils.php56
1 files changed, 56 insertions, 0 deletions
diff --git a/application/FileUtils.php b/application/FileUtils.php
index 30560bfc..3f940751 100644
--- a/application/FileUtils.php
+++ b/application/FileUtils.php
@@ -81,4 +81,60 @@ class FileUtils
81 ) 81 )
82 ); 82 );
83 } 83 }
84
85 /**
86 * Recursively deletes a folder content, and deletes itself optionally.
87 * If an excluded file is found, folders won't be deleted.
88 *
89 * Additional security: raise an exception if it tries to delete a folder outside of Shaarli directory.
90 *
91 * @param string $path
92 * @param bool $selfDelete Delete the provided folder if true, only its content if false.
93 * @param array $exclude
94 */
95 public static function clearFolder(string $path, bool $selfDelete, array $exclude = []): bool
96 {
97 $skipped = false;
98
99 if (!is_dir($path)) {
100 throw new IOException(t('Provided path is not a directory.'));
101 }
102
103 if (!static::isPathInShaarliFolder($path)) {
104 throw new IOException(t('Trying to delete a folder outside of Shaarli path.'));
105 }
106
107 foreach (new \DirectoryIterator($path) as $file) {
108 if($file->isDot()) {
109 continue;
110 }
111
112 if (in_array($file->getBasename(), $exclude, true)) {
113 $skipped = true;
114 continue;
115 }
116
117 if ($file->isFile()) {
118 unlink($file->getPathname());
119 } elseif($file->isDir()) {
120 $skipped = static::clearFolder($file->getRealPath(), true, $exclude) || $skipped;
121 }
122 }
123
124 if ($selfDelete && !$skipped) {
125 rmdir($path);
126 }
127
128 return $skipped;
129 }
130
131 /**
132 * Checks that the given path is inside Shaarli directory.
133 */
134 public static function isPathInShaarliFolder(string $path): bool
135 {
136 $rootDirectory = dirname(dirname(__FILE__));
137
138 return strpos(realpath($path), $rootDirectory) !== false;
139 }
84} 140}