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 | namespace libraries; |
||
4 | |||
5 | /** |
||
6 | * Creating DB backups |
||
7 | * getting backup files |
||
8 | * deleting old backup-files |
||
9 | * |
||
10 | * @author kolia |
||
11 | */ |
||
12 | class Backup |
||
13 | { |
||
14 | |||
15 | /** |
||
16 | * |
||
17 | * @var Backup |
||
18 | */ |
||
19 | protected static $instance; |
||
20 | |||
21 | /** |
||
22 | * Backup directory |
||
23 | * @var string |
||
24 | */ |
||
25 | protected $directory = BACKUPFOLDER; |
||
26 | |||
27 | /** |
||
28 | * Aviable extentions |
||
29 | * @var array |
||
30 | */ |
||
31 | protected $ext = [ |
||
32 | 'sql', |
||
33 | 'zip', |
||
34 | 'gzip', |
||
35 | ]; |
||
36 | |||
37 | /** |
||
38 | * Patterns for backup file names |
||
39 | * key - regex pattern, value - boolean (allow delete) |
||
40 | * @var array |
||
41 | */ |
||
42 | protected $filePatterns = [ |
||
43 | // для файлів із авт. підбором імені. |
||
44 | '/^[a-zA-Z]{1,10}_[0-9]{2}-[0-9]{2}-[0-9]{4}_[0-9]{2}.[0-9]{2}.[0-9]{2}.(zip|gzip|sql|txt)$/' => [ |
||
45 | 'allowDelete' => TRUE, |
||
46 | 'type' => 'default', |
||
47 | ], |
||
48 | // для старіших бекапів із обновлення |
||
49 | '/^[0-9]{10}.(zip|gzip|sql|txt)$/' => [ |
||
50 | 'allowDelete' => TRUE, |
||
51 | 'type' => 'update', |
||
52 | ], |
||
53 | // для новіших бекапів із обновлення |
||
54 | '/^backup.(zip|gzip|sql|txt)$/' => [ |
||
55 | 'allowDelete' => FALSE, |
||
56 | 'type' => 'update', |
||
57 | ], |
||
58 | ]; |
||
59 | |||
60 | /** |
||
61 | * |
||
62 | * @var CodeIgniter |
||
63 | */ |
||
64 | protected $ci; |
||
65 | |||
66 | /** |
||
67 | * |
||
68 | * @var string |
||
69 | */ |
||
70 | public $error; |
||
71 | |||
72 | public function __construct() { |
||
73 | $this->ci = &get_instance(); |
||
74 | $this->ci->load->dbutil(); |
||
75 | } |
||
76 | |||
77 | /** |
||
78 | * |
||
79 | * @return Backup |
||
80 | */ |
||
81 | public static function create() { |
||
82 | (null !== self::$instance) OR self::$instance = new self(); |
||
83 | return self::$instance; |
||
84 | } |
||
85 | |||
86 | /** |
||
87 | * Setting the backup value into the DB |
||
88 | * @param string $key |
||
89 | * @param string|int $value |
||
90 | */ |
||
91 | public function setSetting($key, $value) { |
||
92 | $settings = $this->getSetting(); |
||
93 | if (!is_array($settings)) { //no settings yet |
||
94 | $settings = []; |
||
95 | } |
||
96 | $settings[$key] = $value; |
||
97 | return $this->ci->db->update('settings', ['backup' => serialize($settings)]); |
||
98 | } |
||
99 | |||
100 | /** |
||
101 | * Getting the backup value from the DB |
||
102 | * @param string |
||
103 | * @param string $key |
||
104 | * @return mixed settings array or specified value |
||
105 | */ |
||
106 | public function getSetting($key = NULL) { |
||
107 | $result = $this->ci->db->select('backup')->get('settings'); |
||
108 | if ($result) { |
||
109 | $row = $result->result_array(); |
||
110 | } else { |
||
111 | $row = []; |
||
112 | } |
||
113 | |||
114 | $backupSettings = unserialize($row[0]['backup']); |
||
115 | if (!is_array($backupSettings)) { // no settings yet |
||
116 | return NULL; |
||
117 | } |
||
118 | if ($key != null) { |
||
119 | if (!array_key_exists($key, $backupSettings)) { |
||
120 | return NULL; |
||
121 | } |
||
122 | return $backupSettings[$key]; |
||
123 | } |
||
124 | return $backupSettings; |
||
125 | } |
||
126 | |||
127 | /** |
||
128 | * Creating the backup file |
||
129 | * @param string $ext extention (txt|zip|gzip) |
||
130 | * @param string $prefix |
||
131 | * @param bool|string $fullName (optional) filename |
||
132 | * @param array $params |
||
133 | * @return false|string filename|FALSE |
||
134 | */ |
||
135 | public function createBackup($ext, $prefix = NULL, $fullName = FALSE, $params = []) { |
||
0 ignored issues
–
show
|
|||
136 | if (is_really_writable($this->directory)) { |
||
137 | if ($prefix == null) { |
||
138 | $prefix = 'sql'; |
||
139 | } |
||
140 | if ($fullName === TRUE) { |
||
141 | $fileName = $prefix; |
||
142 | } else { |
||
143 | $fileName = $prefix . '_' . date('d-m-Y_H.i.s'); |
||
144 | } |
||
145 | |||
146 | $params = [ |
||
147 | 'format' => $ext == 'sql' ? 'txt' : $ext, |
||
148 | ]; |
||
149 | |||
150 | $currentDbInstance = $this->ci->db; |
||
151 | |||
152 | $this->initBackupDB(); |
||
153 | |||
154 | $backup = & $this->ci->dbutil->backup($params); |
||
155 | |||
156 | $this->ci->db = $currentDbInstance; |
||
157 | |||
158 | if (write_file($this->directory . '/' . $fileName . '.' . $ext, $backup)) { |
||
159 | return $this->directory . '/' . $fileName . '.' . $ext; |
||
160 | } |
||
161 | $this->error = 'Невозможно создать файл, проверте папку ' . BACKUPFOLDER . ' на возможность записи'; |
||
162 | return FALSE; |
||
163 | } else { |
||
164 | $this->error = 'Невозможно создать снимок базы, проверте папку ' . BACKUPFOLDER . ' на возможность записи'; |
||
165 | return FALSE; |
||
166 | } |
||
167 | } |
||
168 | |||
169 | /** |
||
170 | * Init DB for backup with msql driver |
||
171 | */ |
||
172 | private function initBackupDB() { |
||
173 | // this is just all config keys |
||
174 | $configNames = [ |
||
175 | 'hostname', |
||
176 | 'username', |
||
177 | 'password', |
||
178 | 'database', |
||
179 | 'dbdriver', |
||
180 | 'dbprefix', |
||
181 | 'pconnect', |
||
182 | 'db_debug', |
||
183 | 'cache_on', |
||
184 | 'cachedir', |
||
185 | 'char_set', |
||
186 | 'dbcollat', |
||
187 | 'swap_pre', |
||
188 | 'autoinit', |
||
189 | 'stricton', |
||
190 | ]; |
||
191 | |||
192 | $config = []; |
||
193 | foreach ($configNames as $key) { |
||
194 | $config[$key] = $key == 'dbdriver' ? 'mysql' : $this->ci->db->$key; |
||
195 | } |
||
196 | |||
197 | $this->ci->db = $this->ci->load->database($config, TRUE); |
||
198 | $this->ci->load->dbutil(); |
||
199 | } |
||
200 | |||
201 | /** |
||
202 | * |
||
203 | * @return boolean |
||
0 ignored issues
–
show
|
|||
204 | */ |
||
205 | public function deleteOldFiles() { |
||
206 | $term = $this->getSetting('backup_term'); |
||
207 | $maxSize = ($this->getSetting('backup_maxsize') * 1024 * 1024); |
||
0 ignored issues
–
show
$maxSize is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
208 | |||
209 | $maxSize = 5 * 1024 * 1024; |
||
210 | // if time of file will be lower then delete |
||
211 | $time = time() - (60 * 60 * 24 * 30.5 * $term); |
||
212 | |||
213 | $files = $this->backupFiles(); |
||
214 | // get summary backup size |
||
215 | $size = 0; |
||
216 | foreach ($files as $file) { |
||
217 | $size += $file['size']; |
||
218 | } |
||
219 | |||
220 | // start deleting if overload more then max size |
||
221 | if ($size > $maxSize) { |
||
222 | $deleteSize = $size - $maxSize; |
||
223 | $deleteEdOnSize = 0; |
||
224 | $filesCount = 0; |
||
225 | do { |
||
226 | $fileToDelete = $this->getOldestFileToDelete(); |
||
227 | if ($fileToDelete == FALSE) { // if FALSE then no more files to delete |
||
228 | break; |
||
229 | } |
||
230 | if ($fileToDelete['timeUpdate'] > $time) { // check if not overrun max date |
||
231 | break; |
||
232 | } |
||
233 | $filesCount++; |
||
234 | $deleteEdOnSize += $fileToDelete['size']; |
||
235 | unlink($this->directory . '/' . $fileToDelete['filename']); |
||
236 | } while ($deleteEdOnSize < $deleteSize); |
||
237 | |||
238 | return [ |
||
239 | 'count' => $filesCount, |
||
240 | 'size' => $deleteEdOnSize, |
||
241 | ]; |
||
242 | } |
||
243 | return FALSE; |
||
244 | } |
||
245 | |||
246 | /** |
||
247 | * |
||
248 | * @return boolean |
||
249 | */ |
||
250 | public function getOldestFileToDelete() { |
||
251 | $files_ = $this->backupFiles(); |
||
252 | // getting only files that allow to delete by pattern |
||
253 | $files = []; |
||
254 | foreach ($files_ as $file) { |
||
255 | if ($this->checkFileName($file['filename'], 'allowDelete') && $file['locked'] != 1) { |
||
256 | $files[] = $file; |
||
257 | } |
||
258 | } |
||
259 | |||
260 | if (!count($files) > 0) { |
||
261 | return FALSE; |
||
262 | } |
||
263 | |||
264 | $minKey = 0; |
||
265 | $minTime = $files[0]['timeUpdate']; |
||
266 | |||
267 | $countFiles = count($files); |
||
268 | for ($i = 1; $i < $countFiles; $i++) { |
||
269 | if ($minTime > $files[$i]['timeUpdate']) { |
||
270 | $minTime = $files[$i]['timeUpdate']; |
||
271 | $minKey = $i; |
||
272 | } |
||
273 | } |
||
274 | return $files[$minKey]; |
||
275 | } |
||
276 | |||
277 | /** |
||
278 | * Getting list of backup files |
||
279 | * @return array |
||
280 | */ |
||
281 | public function backupFiles() { |
||
282 | $lockedFiles = $this->getSetting('lockedFiles'); |
||
283 | if (!is_array($lockedFiles)) { |
||
284 | $lockedFiles = []; |
||
285 | } |
||
286 | $files = []; |
||
287 | if ($dir = opendir($this->directory)) { |
||
288 | while (FALSE !== ($fileName = readdir($dir))) { |
||
289 | if ($fileName != '.' & $fileName !== '..') { |
||
0 ignored issues
–
show
Consider adding parentheses for clarity. Current Interpretation:
($fileName != '.') & $fileName !== '..' , Probably Intended Meaning: $fileName != ('.' & $fileName !== '..')
When comparing the result of a bit operation, we suggest to add explicit parenthesis and not to rely on PHP’s built-in operator precedence to ensure the code behaves as intended and to make it more readable. Let’s take a look at these examples: // Returns always int(0).
return 0 === $foo & 4;
return (0 === $foo) & 4;
// More likely intended return: true/false
return 0 === ($foo & 4);
![]() |
|||
290 | if (TRUE === $this->checkFileName($fileName)) { |
||
291 | $file = [ |
||
292 | 'filename' => $fileName, |
||
293 | 'allowDelete' => $this->checkFileName($fileName, 'allowDelete') == TRUE ? 1 : 0, |
||
294 | 'type' => $this->checkFileName($fileName, 'type'), |
||
295 | 'ext' => pathinfo($fileName, PATHINFO_EXTENSION), |
||
296 | 'size' => filesize($this->directory . '/' . $fileName), |
||
297 | 'timeUpdate' => filemtime($this->directory . '/' . $fileName), |
||
298 | ]; |
||
299 | if ($file['type'] == 'default') { |
||
300 | $prefIndex = strpos($fileName, '_'); |
||
301 | $file['prefix'] = substr($fileName, 0, $prefIndex); |
||
302 | } else { |
||
303 | $file['prefix'] = 'update'; |
||
304 | } |
||
305 | if (in_array($fileName, $lockedFiles)) { |
||
306 | $file['locked'] = 1; |
||
307 | } else { |
||
308 | $file['locked'] = 0; |
||
309 | } |
||
310 | $files[] = $file; |
||
311 | } |
||
312 | } |
||
313 | } |
||
314 | closedir($dir); |
||
315 | } |
||
316 | |||
317 | foreach ($files as $key => $row) { |
||
318 | $backaps[$key] = $row['timeUpdate']; |
||
0 ignored issues
–
show
Coding Style
Comprehensibility
introduced
by
$backaps was never initialized. Although not strictly required by PHP, it is generally a good practice to add $backaps = array(); before regardless.
Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code. Let’s take a look at an example: foreach ($collection as $item) {
$myArray['foo'] = $item->getFoo();
if ($item->hasBar()) {
$myArray['bar'] = $item->getBar();
}
// do something with $myArray
}
As you can see in this example, the array This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop. ![]() |
|||
319 | } |
||
320 | |||
321 | array_multisort($backaps, SORT_DESC, $files); |
||
322 | |||
323 | return $files; |
||
324 | } |
||
325 | |||
326 | /** |
||
327 | * Checking file name by pattern |
||
328 | * @param string $fileName |
||
329 | * @param boolean|string $returnValue |
||
330 | * @return boolean|string |
||
331 | */ |
||
332 | protected function checkFileName($fileName, $returnValue = FALSE) { |
||
333 | foreach ($this->filePatterns as $pattern => $params) { |
||
334 | if (preg_match($pattern, $fileName)) { |
||
335 | return $returnValue !== FALSE ? $params[$returnValue] : TRUE; |
||
336 | } |
||
337 | } |
||
338 | return FALSE; |
||
339 | } |
||
340 | |||
341 | /** |
||
342 | * Deleting backup file |
||
343 | * @param string $file |
||
344 | * @return boolean true on success, false on error |
||
345 | */ |
||
346 | public function deleteFile($file) { |
||
347 | if (FALSE === $this->checkFileName($file, 'allowDelete')) { |
||
348 | return FALSE; |
||
349 | } |
||
350 | if (file_exists($this->directory . '/' . $file)) { |
||
351 | return unlink($this->directory . '/' . $file); |
||
352 | } |
||
353 | return FALSE; |
||
354 | } |
||
355 | |||
356 | } |
This check looks from parameters that have been defined for a function or method, but which are not used in the method body.