PluginProbe ʕ •ᴥ•ʔ
Backup Migration / 2.1.7
Backup Migration v2.1.7
2.1.7 2.1.6 2.1.5.2 trunk 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.6.1 1.4.7 1.4.8 1.4.9 1.4.9.1 2.0.0 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.5.1
backup-backup / includes / external / ftp.php
backup-backup / includes / external Last commit date
contracts 2 weeks ago backupbliss.php 2 weeks ago controller.php 2 weeks ago dropbox.php 2 weeks ago external-storage-manager.php 2 weeks ago ftp.php 2 weeks ago google-drive.php 2 weeks ago s3.php 2 weeks ago
ftp.php
728 lines
1 <?php
2
3 // Namespace
4 namespace BMI\Plugin\External;
5
6 // Use
7 use BMI\Plugin\Backup_Migration_Plugin as BMP;
8 use BMI\Plugin\BMI_Logger as Logger;
9 use BMI\Plugin\BMI_Pro_Core;
10 use BMI\Plugin\BMProAjax as BMProAjax;
11 use BMI\Plugin\Progress\BMI_MigrationProgress as MigrationProgress;
12 use BMI\Plugin\Scanner\BMI_BackupsScanner as Backups;
13 use BMI\Plugin\Dashboard as Dashboard;
14 use function BMI\Plugin\Dashboard\bmi_get_config;
15 use BMI\Plugin\External\Contracts\DeleteBackup;
16
17 if (!defined('ABSPATH')) {
18 exit;
19 }
20
21 require_once BMI_INCLUDES . DIRECTORY_SEPARATOR . 'external' . DIRECTORY_SEPARATOR . 'contracts' . DIRECTORY_SEPARATOR . 'interface-delete-backup.php';
22
23 /**
24 * BMI_External_FTP
25 */
26 class BMI_External_FTP implements DeleteBackup
27 {
28 private $ftp_access_username = false;
29 private $ftp_access_password = false;
30 private $ftp_access_host = false;
31 private $ftp_access_dir = false;
32 private $ftp_access_port = false;
33
34 public function __construct()
35 {
36 // Update FTP config
37 $this->ftp_access_host = get_option('bmi_pro_ftp_host');
38 $this->ftp_access_username = get_option('bmi_pro_ftp_username');
39 $this->ftp_access_password = get_option('bmi_pro_ftp_password');
40 $this->ftp_access_dir = get_option('bmi_pro_ftp_backup_dir');
41 $this->ftp_access_port = get_option('bmi_pro_ftp_port');
42
43 // Delete files
44 add_action('bmi_premium_remove_backup_file', [&$this, 'deleteBackup']);
45 add_action('bmi_premium_remove_backup_json_file', [&$this, 'deleteFtpJson']);
46 }
47
48 private function _custom_ftp_list($ftp_connection, $directory) {
49 // Get the list of files and directories
50 $file_list = ftp_nlist($ftp_connection, $directory);
51
52 $result = [];
53
54 if ($file_list === false) {
55 return $result; // Error occurred during listing
56 }
57
58 foreach ($file_list as $file) {
59 $item_path = $file;
60
61 // Get the file size
62 $size = ftp_size($ftp_connection, $item_path);
63
64 // Only include files (ignore directories)
65 if ($size >= 0) { // Size >= 0 indicates a file
66 $result[] = [
67 'name' => basename($file),
68 'size' => $size,
69 'type' => 'file'
70 ];
71 }
72 }
73
74 return $result;
75 }
76
77 public function get_host() {
78 return $this->ftp_access_host;
79 }
80
81 public function get_user_name() {
82 return $this->ftp_access_username;
83 }
84
85 public function get_password() {
86 return $this->ftp_access_password;
87 }
88
89 public function get_dir() {
90 return $this->ftp_access_dir;
91 }
92
93 public function get_port() {
94 return $this->ftp_access_port;
95 }
96
97 /**
98 * ftpConnect - Connects to FTP Server
99 *
100 * @return bool|\FTP\Connection
101 */
102 public function ftpConnect()
103 {
104 $ftp_server = $this->ftp_access_host;
105 $ftp_username = $this->ftp_access_username;
106 $ftp_password = $this->ftp_access_password;
107 $ftp_port = $this->ftp_access_port;
108
109 if (!$ftp_server || !$ftp_username || !$ftp_password) {
110 return false;
111 }
112
113 if (!function_exists('ftp_connect')) {
114 return false;
115 }
116
117 $ftp_conn = ftp_connect($ftp_server, $ftp_port);
118
119 if (!$ftp_conn) {
120 return false;
121 }
122
123 $login = ftp_login($ftp_conn, $ftp_username, $ftp_password);
124 if ($login) {
125 ftp_pasv($ftp_conn, true);
126 } else {
127 ftp_close($ftp_conn);
128 return false;
129 }
130
131 return $ftp_conn;
132 }
133
134 public function verifyConnection()
135 {
136 $conn_id = $this->ftpConnect();
137
138 $res = false;
139 if ($conn_id !== false) {
140 $res = 'connected';
141 }
142
143 return ['status' => 'success', 'result' => $res];
144
145 }
146
147 /**
148 * checkForBackupsToUpload - Will check for backups that requires to be in sync with cloud
149 *
150 * @return string[]
151 */
152 public function checkForBackupsToUpload()
153 {
154 $isEnabled = Dashboard\bmi_get_config('STORAGE::EXTERNAL::FTP');
155 if (!($isEnabled === true || $isEnabled === 'true')) {
156 update_option('bmip_to_be_uploaded', ['current_upload' => [], 'queue' => []]);
157 return [];
158 }
159
160 require_once BMI_INCLUDES . DIRECTORY_SEPARATOR . 'scanner' . DIRECTORY_SEPARATOR . 'backups.php';
161
162 // Upload Object
163 $requiresUpload = get_option('bmip_to_be_uploaded', [
164 'current_upload' => [],
165 'queue' => [],
166 'failed' => []
167 ]);
168
169 // Local Backups
170 $backups = Backups::getInstance();
171 $backupsAvailable = $backups->getAvailableBackups("local");
172 $localBackups = $backupsAvailable['local'];
173 $localBackups = array_reverse($localBackups);
174
175 // FTP Drive
176 $ftpFailed = false;
177 $ftpBackups = $this->getFtpBackups();
178
179 if ($ftpBackups && isset($ftpBackups['data'])) {
180 $ftpParsed = $this->parseFtpFiles($ftpBackups['data']);
181 } else {
182 return ['status' => 'error']; //Don't requeue FTP if the fetching fails
183 }
184
185 $backupsFiles = isset($ftpParsed['zipFiles']) ? $ftpParsed['zipFiles'] : [];
186 $manifestFiles = isset($ftpParsed['jsonFiles']) ? $ftpParsed['jsonFiles'] : [];
187 $availableManifests = array_column($manifestFiles, 'name');
188 $uploadedBackupStatus = get_option('bmi_uploaded_backups_status', []);
189
190 foreach($localBackups as $name => $details) {
191 $md5 = $details[7];
192 if (isset($uploadedBackupStatus[$md5]) && isset($uploadedBackupStatus[$md5]['ftp'])) {
193 continue;
194 }
195 $isBackupNotExists = !in_array($md5 . '.json', $availableManifests) || !in_array($name, array_column($backupsFiles, 'name'));
196 if ($isBackupNotExists && !(isset($requiresUpload['current_upload']['task']) && $requiresUpload['current_upload']['task'] == 'ftp_' . $md5)) {
197 $requiresUpload['queue']['ftp_' . $md5] = [
198 'name' => $name,
199 'md5' => $md5,
200 'json' => $md5 . '.json'
201 ];
202
203 //As it gets queued again remove any failed tasks
204 if (isset($requiresUpload['failed']['ftp_' . $md5])) unset($requiresUpload['failed']['ftp_' . $md5]);
205 }
206 }
207
208 update_option('bmip_to_be_uploaded', $requiresUpload);
209 return ['status' => 'success'];
210 }
211
212 /**
213 * parseFtpFiles - Parses FTp Drive output files
214 *
215 * @param object $files FTP Files of Return
216 *
217 * @return array of parsed files
218 */
219 public function parseFtpFiles(&$files)
220 {
221 $login_result = $this->ftpConnect();
222 if ($login_result === false) {
223 return [];
224 }
225
226 $parsedFiles = [];
227 $zipFiles = [];
228 $jsonFiles = [];
229 foreach ($files as $index => $file) {
230
231 if ($file['type'] !== 'file') continue;
232
233 $ext = pathinfo($file['name'], PATHINFO_EXTENSION);
234
235 if (in_array($ext, ['zip', 'gz', 'tar'])) {
236 $zipFiles[] = $file;
237 } else if ($ext === 'json') {
238 $jsonFiles[] = $file;
239 }
240 }
241
242 return compact('zipFiles', 'jsonFiles');
243 }
244
245 /**
246 * getFtpBackups - Return list of FTP backups and their MD5s
247 *
248 * @return array|bool status
249 */
250 public function getFtpBackups()
251 {
252 // connect and login to FTP server
253 // Update FTP config
254 $ftpConnect = $this->ftpConnect();
255
256 if ($ftpConnect !== false) {
257 //Get detail files
258 $fileList = $this->_custom_ftp_list($ftpConnect, $this->ftp_access_dir);
259 ftp_close($ftpConnect);
260 return ['status' => 'success', 'data' => $fileList];
261 }
262 return false;
263 }
264
265 /**
266 * uploadManifestFile - It will upload manifest file into BMI directory on FTP
267 *
268 * @return array status
269 */
270 private function uploadManifestFile($mdf, $manifestPath)
271 {
272 $ftpConnect= $this->ftpConnect();
273
274 if ($ftpConnect !== false) {
275 ftp_chdir($ftpConnect, $this->ftp_access_dir);
276 if (ftp_put($ftpConnect, $mdf . '.json', $manifestPath, FTP_ASCII)) {
277 ftp_close($ftpConnect);
278 return ['status' => 'success', 'data' => 'ok'];
279 } else {
280 ftp_close($ftpConnect);
281 return ['status' => 'error', 'data' => 'error'];
282 }
283 }
284 return ['status' => 'error', 'data' => 'error'];
285 }
286
287 /**
288 * getFTPFileContents - Gets file body by filename ftp
289 *
290 * @return array status
291 */
292 public function getFtpFileContents($fileName)
293 {
294 $ftpConnect = $this->ftpConnect();
295 if ($ftpConnect === false){
296 return ['status' => 'error', 'data' => 'error'];
297 }
298
299 ftp_chdir($ftpConnect, $this->ftp_access_dir);
300
301 $temp_file = 'temp.json';
302
303 $file = ftp_get($ftpConnect, BMI_BACKUPS . DIRECTORY_SEPARATOR . $temp_file, $fileName, FTP_BINARY);
304 if ($file) {
305 $file = file_get_contents(BMI_BACKUPS . DIRECTORY_SEPARATOR . $temp_file);
306 }
307 ftp_close($ftpConnect);
308 return ['status' => 'success', 'data' => $file];
309 }
310
311 /**
312 * getFtpDriveFileMeta - Gets file meta data by FTP file ID
313 *
314 * @return array|bool status
315 */
316 public function getFtpDriveFileMeta($fileName)
317 {
318 $ftpConnect = $this->ftpConnect();
319 if ($ftpConnect !== false) {
320 $fileList = $this->_custom_ftp_list($ftpConnect, $this->ftp_access_dir);
321 foreach($fileList as $file) {
322 if($file['name'] === $fileName) {
323 ftp_close($ftpConnect);
324 return ['status' => 'success', 'data' => $file];
325 }
326 }
327 ftp_close($ftpConnect);
328 }
329 return false;
330 }
331
332 /**
333 * @inheritDoc
334 */
335 public function deleteBackup($md5)
336 {
337 $manifestFile = $md5 . '.json';
338 if (file_exists(BMI_BACKUPS . DIRECTORY_SEPARATOR . $manifestFile)) {
339 $manifestContent = json_decode(file_get_contents(BMI_BACKUPS . DIRECTORY_SEPARATOR . $manifestFile));
340 } else {
341 $manifestContent = json_decode($this->getFtpFileContents($manifestFile)['data']);
342 }
343 $backupName = $manifestContent->name;
344 $deleteBackup = $this->deleteFileFtp($backupName);
345 $deleteManifest = $this->deleteFileFtp($md5 . '.json');
346 if ($deleteBackup && $deleteManifest) {
347 return true;
348 }
349 return false;
350 }
351
352 /**
353 * @deprecated Use deleteBackup() instead.
354 */
355 public function deleteFtpDriveBackup($md5) {
356 return $this->deleteBackup($md5);
357 }
358
359 /**
360 * deleteFtpJson - Deletes JSON manifest from FTP
361 * @deprecated Use deleteBackup() instead.
362 *
363 * @return bool status
364 */
365 public function deleteFtpJson($fileName)
366 {
367 $files = $this->getFtpBackups();
368 if (isset($files['status']) && $files['status'] === 'success') {
369 $files = $files['data'];
370 foreach ($files as $index => $file) {
371 if ($file['name'] === $fileName) {
372 $this->deleteFileFtp($fileName);
373 return true;
374 }
375 }
376 }
377 return false;
378 }
379
380 public function getFtpDriveFileContents($fileName, $startRange, $endRange) {
381 $remote_file = $this->ftp_access_dir . DIRECTORY_SEPARATOR . $fileName;
382
383 $ftp_username = urlencode($this->ftp_access_username);
384 $ftp_password = urlencode($this->ftp_access_password);
385 $ftp_port = $this->ftp_access_port;
386 $ftp_server = $this->ftp_access_host;
387
388 $ch = curl_init();
389
390 $url = "ftp://{$ftp_username}:{$ftp_password}@{$ftp_server}:{$ftp_port}/{$remote_file}";
391
392 curl_setopt($ch, CURLOPT_URL, $url);
393 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
394 curl_setopt($ch, CURLOPT_RANGE, "$startRange-$endRange");
395 curl_setopt($ch, CURLOPT_NOPROGRESS, true);
396 curl_setopt($ch, CURLOPT_TIMEOUT, 30);
397
398 $data = curl_exec($ch);
399
400 if(curl_errno($ch)) {
401 $error_message = curl_error($ch);
402 if (is_resource($ch)) {
403 curl_close($ch);
404 }
405 error_log('cURL error: ' . $error_message);
406 return false;
407 }
408
409 if (is_resource($ch)) {
410 curl_close($ch);
411 }
412
413 return ['status' => 'success', 'data' => $data];
414 }
415
416 /**
417 * uploadFtpDriveFiles - It will upload particular file into BMI directory on FTP
418 *
419 * @return array status
420 */
421 public function uploadFtpDriveFiles($uploadURL, $filePath, $manifestPath, $md5, $batch, $bytesPerRequest)
422 {
423 if (!file_exists($filePath)) {
424 update_option('bmip_to_be_uploaded', [
425 'current_upload' => [],
426 'queue' => [],
427 'failed' => []
428 ]);
429
430 return ['status' => 'error'];
431 }
432
433 set_transient('bmip_upload_ongoing', '1', 31);
434
435 $batchNumber = intval($batch);
436 $maxLength = filesize($filePath);
437
438 $toBeUploaded = get_option('bmip_to_be_uploaded', false);
439
440 //Check Exist file in ftp
441 $exist = $this->isExist(basename($filePath), $maxLength);
442
443
444 if ($exist) {
445 $manifestRes = $this->uploadManifestFile($md5, $manifestPath);
446 if ($manifestRes['status'] === 'success') {
447 $uploadedBackupStatus = get_option('bmi_uploaded_backups_status', []);
448 if (!isset($uploadedBackupStatus[$md5])) {
449 $uploadedBackupStatus[$md5] = [];
450 }
451 $uploadedBackupStatus[$md5]['ftp'] = true;
452 update_option('bmi_uploaded_backups_status', $uploadedBackupStatus);
453 do_action('bmi_backup_upload_completed', $md5);
454
455 }
456
457 $task = $toBeUploaded['current_upload']['task'];
458 $toBeUploaded['current_upload'] = [];
459 if (!isset($toBeUploaded['failed'])) {
460 $toBeUploaded['failed'] = [];
461 }
462
463 if (isset($toBeUploaded['failed'][$task])) {
464 unset($toBeUploaded['failed'][$task]);
465 }
466
467 update_option('bmip_to_be_uploaded', $toBeUploaded);
468 return ['status' => 'success', 'data' => []];
469 }
470
471 $chunkSize = 256 * 1024 * 4 * intval($bytesPerRequest / 1024 / 1024);
472
473 $chunkOffset = (($batchNumber - 1) * $chunkSize);
474 $rangeEnd = (($chunkSize * $batchNumber) - 1);
475
476 if ($rangeEnd >= $maxLength) {
477 $rangeEnd = $maxLength - 1;
478 }
479 if (($chunkSize + $chunkOffset) >= $maxLength) {
480 $chunkSize = $rangeEnd - $chunkOffset + 1;
481 }
482 $nextShouldStartAt = $rangeEnd + 1;
483
484 if ($stream = fopen($filePath, 'r')) {
485 if ($maxLength > $chunkOffset) {
486 $binaryData = stream_get_contents($stream, $chunkSize, $chunkOffset);
487 }
488 fclose($stream);
489 }
490
491
492 $ftpConnect = $this->ftpConnect();
493
494 if ($ftpConnect !== false) {
495 // Login to FTP server
496
497 // Change directory to FTP directory
498 ftp_chdir($ftpConnect, $this->ftp_access_dir);
499
500 // Open local file for reading
501 $localFile = fopen($filePath, 'ab');
502 $remote_file = basename($filePath);
503 $user = $this->ftp_access_username;
504 $pass = $this->ftp_access_password;
505 $ftp_host = $this->ftp_access_host;
506 $ftpDirectory = $this->ftp_access_dir;
507 $ftp_port = $this->ftp_access_port;
508
509 $remote_handle = fopen("ftp://$user:$pass@$ftp_host:$ftp_port/$ftpDirectory/$remote_file", 'ab');
510
511 if ($localFile) {
512 fseek($localFile, $chunkOffset);
513 $upload = fwrite($remote_handle, $binaryData);
514
515 // Check if upload was successful
516 if ($upload) {
517
518 $task = $toBeUploaded['current_upload']['task'];
519 if (!isset($toBeUploaded['failed'])) {
520 $toBeUploaded['failed'] = [];
521 }
522
523 if (isset($toBeUploaded['failed'][$task])) {
524 unset($toBeUploaded['failed'][$task]);
525 }
526
527 // All is good
528 if ($toBeUploaded) {
529 $toBeUploaded['current_upload']['batch'] = intval($batch) + 1;
530 $toBeUploaded['current_upload']['progress'] = number_format(($rangeEnd / $maxLength) * 100, 2) . '%';
531 update_option('bmip_to_be_uploaded', $toBeUploaded);
532 }
533
534 // Check finished
535 if ($chunkSize + $chunkOffset >= $maxLength) {
536
537 $manifestRes = $this->uploadManifestFile($md5, $manifestPath);
538 if ($manifestRes['status'] === 'success') {
539 $uploadedBackupStatus = get_option('bmi_uploaded_backups_status', []);
540 if (!isset($uploadedBackupStatus[$md5])) {
541 $uploadedBackupStatus[$md5] = [];
542 }
543 $uploadedBackupStatus[$md5]['ftp'] = true;
544 update_option('bmi_uploaded_backups_status', $uploadedBackupStatus);
545 do_action('bmi_backup_upload_completed', $md5);
546 }
547
548 $task = $toBeUploaded['current_upload']['task'];
549 $toBeUploaded['current_upload'] = [];
550 if (!isset($toBeUploaded['failed'])) {
551 $toBeUploaded['failed'] = [];
552 }
553
554 if (isset($toBeUploaded['failed'][$task])) {
555 unset($toBeUploaded['failed'][$task]);
556 }
557
558 update_option('bmip_to_be_uploaded', $toBeUploaded);
559 }
560 } else {
561 $this->errorFtp($toBeUploaded, 'Error uploading file to FTP server!');
562 }
563
564 // Close local file
565 fclose($localFile);
566 } else {
567 $this->errorFtp($toBeUploaded, 'Error opening local file!');
568 }
569
570 ftp_close($ftpConnect);
571 } else {
572 $this->errorFtp($toBeUploaded, 'Error connecting to FTP server!');
573 }
574 delete_transient('bmip_upload_ongoing');
575 return ['status' => 'success', 'data' => []];
576 }
577
578 public function errorFtp($toBeUploaded, $message)
579 {
580 Logger::error('[BMI PRO] Error during file upload (FTP) Message:' . $message . '!');
581
582 $task = $toBeUploaded['current_upload']['task'];
583 // Requeueing is handled globally
584 // $toBeUploaded['queue'][$task] = [
585 // 'name' => $toBeUploaded['current_upload']['name'],
586 // 'md5' => $toBeUploaded['current_upload']['md5'],
587 // 'json' => $toBeUploaded['current_upload']['json']
588 // ];
589
590 $toBeUploaded['current_upload'] = [];
591 if (!isset($toBeUploaded['failed'])) {
592 $toBeUploaded['failed'] = [];
593 }
594 if (isset($toBeUploaded['failed'][$task])) {
595 $toBeUploaded['failed'][$task]++;
596 } else {
597 $toBeUploaded['failed'][$task] = 1;
598 }
599
600 update_option('bmip_to_be_uploaded', $toBeUploaded);
601 }
602
603 public function uploadFTPDriveFile($fileName)
604 {
605 // Check enable FTP option
606 $isFtpEnable = Dashboard\bmi_get_config('STORAGE::EXTERNAL::FTP');
607
608 if ($isFtpEnable !== true && $isFtpEnable !== 'true') {
609 return ['status' => 'error'];
610 }
611
612 $toBeUploaded = get_option('bmip_to_be_uploaded', false);
613
614 $storageLocalPath = sanitize_text_field(bmi_get_config('STORAGE::LOCAL::PATH'));
615
616 $backupFile = $storageLocalPath . DIRECTORY_SEPARATOR . 'backups' . DIRECTORY_SEPARATOR . $fileName['filename'];
617
618 $ftpConnect = $this->ftpConnect();
619 if ($ftpConnect === false) {
620 return ['status' => 'error'];
621 }
622
623 $fileSize = filesize($backupFile);
624
625 $latest = BMI_BACKUPS . '/latest.log';
626 $latest_progress = BMI_BACKUPS . '/latest_progress.log';
627
628 if ($upload = ftp_nb_put($ftpConnect, DIRECTORY_SEPARATOR . $dir . DIRECTORY_SEPARATOR . $fileName['filename'], $backupFile, FTP_BINARY)) {
629 while ($upload !== FTP_FINISHED && $upload !== FTP_FAILED) {
630 $bytesUploaded = ftp_size($ftpConnect, $fileName['filename']);
631
632 if ($bytesUploaded > 0 && $fileSize > 0) {
633 $progress = ($bytesUploaded / $fileSize) * 100;
634
635 error_log("Upload progress: " . round($progress, 2) . "%\n");
636
637 if ($toBeUploaded) {
638 // $toBeUploaded['current_upload']['batch'] = intval($batch) + 1;
639 $toBeUploaded['current_upload']['progress'] = round($progress, 2) . '%';
640 update_option('bmip_to_be_uploaded', $toBeUploaded);
641 }
642
643 $progress1 = fopen($latest_progress, 'w');
644
645 if (!$progress1){
646 update_option('bmip_to_be_uploaded', [
647 'current_upload' => [],
648 'queue' => [],
649 'failed' => []
650 ]);
651
652 ftp_close($ftpConnect);
653 return ['status' => 'error'];
654 }
655 fwrite($progress1, $progress);
656 fclose($progress1);
657
658 Logger::append('Step', "Upload progress: " . round($progress, 2) . "%\n");
659 }
660
661 $upload = ftp_nb_continue($ftpConnect);
662 }
663
664 ftp_close($ftpConnect);
665 if ($upload === FTP_FAILED) {
666 return ['status' => 'error'];
667 } else {
668 return true;
669 }
670 }
671 return ['status' => 'error'];
672
673 }
674
675 private function deleteFileFtp($fileName)
676 {
677 $remote_file = $fileName;
678 $ftpConnect = $this->ftpConnect();
679
680 if ($ftpConnect === false) {
681 return false;
682 }
683
684 ftp_chdir($ftpConnect, $this->ftp_access_dir);
685
686 if (ftp_size($ftpConnect, $remote_file) !== -1) {
687 if (ftp_delete($ftpConnect, $remote_file)) {
688 ftp_close($ftpConnect);
689 return true;
690 } else {
691 ftp_close($ftpConnect);
692 return false;
693 }
694 } else {
695 ftp_close($ftpConnect);
696 return false;
697 }
698 }
699
700 /**
701 * Check file is exist in the ftp
702 *
703 * @param $fileName
704 * @param $fileSize
705 * @return bool|void
706 */
707 private function isExist($fileName, $fileSize)
708 {
709 $ftpConnect = $this->ftpConnect();
710 if ($ftpConnect === false) {
711 return false;
712 }
713
714 $contents_on_server = ftp_nlist($ftpConnect,$this->ftp_access_dir);
715
716 foreach ($contents_on_server as $fileOnServer) {
717 if ($fileName === basename($fileOnServer)) {
718 if (ftp_size($ftpConnect, $fileOnServer) >= $fileSize) {
719 ftp_close($ftpConnect);
720 return true;
721 }
722 }
723 }
724 ftp_close($ftpConnect);
725 return false;
726 }
727 }
728