GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Xcloner_Archive::get_archive_name_multipart()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * XCloner - Backup and Restore backup plugin for Wordpress
4
 *
5
 * class-xcloner-archive.php
6
 * @author Liuta Ovidiu <[email protected]>
7
 *
8
 *        This program is free software; you can redistribute it and/or modify
9
 *        it under the terms of the GNU General Public License as published by
10
 *        the Free Software Foundation; either version 2 of the License, or
11
 *        (at your option) any later version.
12
 *
13
 *        This program is distributed in the hope that it will be useful,
14
 *        but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 *        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 *        GNU General Public License for more details.
17
 *
18
 *        You should have received a copy of the GNU General Public License
19
 *        along with this program; if not, write to the Free Software
20
 *        Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21
 *        MA 02110-1301, USA.
22
 *
23
 * @link https://github.com/ovidiul/XCloner-Wordpress
24
 *
25
 * @modified 7/31/18 3:10 PM
26
 *
27
 */
28
29
use splitbrain\PHPArchive\Tar;
30
use splitbrain\PHPArchive\Archive;
31
use splitbrain\PHPArchive\FileInfo;
32
33
/**
34
 * Class responsible for adding files to Tar
35
 * Class Xcloner_Archive
36
 */
37
class Xcloner_Archive extends Tar
38
{
39
	/**
40
	 * Process file size per API request
41
	 * @var float|int
42
	 */
43
	private $file_size_per_request_limit = 52428800; //50MB = 52428800; 1MB = 1048576
44
	/**
45
	 * Files count to process per API request
46
	 * @var int
47
	 */
48
	private $files_to_process_per_request = 250; //block of 512 bytes
49
	/**
50
	 * Compression level, 0-uncompressed, 9-maximum compression
51
	 * @var int
52
	 */
53
	private $compression_level = 0; //0-9 , 0 uncompressed
54
	/**
55
	 * Split backup size limit
56
	 * Create a new backup archive file once the set size is reached
57
	 * @var float|int
58
	 */
59
	private $xcloner_split_backup_limit = 2048; //2048MB
60
	/**
61
	 * Number of processed bytes
62
	 * @var int
63
	 */
64
	private $processed_size_bytes = 0;
65
66
    /**
67
     * The backup name encryption suffix
68
     * @var string
69
     */
70
	private $encrypt_suffix = "-enc";
71
72
	/**
73
	 * Archive name
74
	 * @var string
75
	 */
76
	private $archive_name;
77
	/**
78
	 * @var Tar
79
	 */
80
	private $backup_archive;
81
	/**
82
	 * @var Xcloner_File_System
83
	 */
84
	private $filesystem;
85
	/**
86
	 * @var Xcloner_Logger
87
	 */
88
	private $logger;
89
	/**
90
	 * @var Xcloner_Settings
91
	 */
92
	private $xcloner_settings;
93
94
	/**
95
	 * [__construct description]
96
	 * @param Xcloner $xcloner_container XCloner Container
97
	 * @param string $archive_name Achive Name
98
	 */
99
	public function __construct(Xcloner $xcloner_container, $archive_name = "")
100
	{
101
		$this->filesystem = $xcloner_container->get_xcloner_filesystem();
102
		$this->logger = $xcloner_container->get_xcloner_logger()->withName("xcloner_archive");
103
		$this->xcloner_settings = $xcloner_container->get_xcloner_settings();
104
105
		if ($value = $this->xcloner_settings->get_xcloner_option('xcloner_size_limit_per_request')) {
0 ignored issues
show
Bug introduced by
The method get_xcloner_option() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

105
		if ($value = $this->xcloner_settings->/** @scrutinizer ignore-call */ get_xcloner_option('xcloner_size_limit_per_request')) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
106
			$this->file_size_per_request_limit = $value * 1024 * 1024;
107
		} //MB
108
109
		if ($value = $this->xcloner_settings->get_xcloner_option('xcloner_files_to_process_per_request')) {
110
			$this->files_to_process_per_request = $value;
111
		}
112
113
		if ($value = get_option('xcloner_backup_compression_level')) {
114
			$this->compression_level = $value;
115
		}
116
117
		if ($value = get_option('xcloner_split_backup_limit')) {
118
			$this->xcloner_split_backup_limit = $value;
119
		}
120
121
		$this->xcloner_split_backup_limit = $this->xcloner_split_backup_limit * 1024 * 1024; //transform to bytes
122
123
		if (isset($archive_name) && $archive_name) {
124
			$this->set_archive_name($archive_name);
125
		}
126
	}
127
128
	/*
129
     * Rename backup archive
130
     *
131
     * @param string $old_name
132
     * @param string $new_name
133
     *
134
     */
135
	public function rename_archive($old_name, $new_name)
136
	{
137
		$this->logger->info(sprintf("Renaming backup archive %s to %s", $old_name, $new_name));
138
		$storage_filesystem = $this->filesystem->get_storage_filesystem();
139
		$storage_filesystem->rename($old_name, $new_name);
140
	}
141
142
	/*
143
     *
144
     * Set the backup archive name
145
     *
146
     */
147
	public function set_archive_name($name = "", $part = 0, $encrypt_prefix = false)
148
	{
149
150
		$this->archive_name = $this->filesystem->process_backup_name($name);
151
152
		if($encrypt_prefix) {
153
		    $this->archive_name .= $this->encrypt_suffix;
154
        }
155
156
		if ($diff_timestamp_start = $this->filesystem->get_diff_timestamp_start()) {
157
			//$this->archive_name = $this->archive_name."-diff-".date("Y-m-d_H-i",$diff_timestamp_start);
158
			$new_name = $this->archive_name;
159
160
			if (!stristr($new_name, "-diff")) {
161
				$new_name = $this->archive_name."-diff".date("Y-m-d_H-i", $diff_timestamp_start);
0 ignored issues
show
Bug introduced by
$diff_timestamp_start of type string is incompatible with the type integer expected by parameter $timestamp of date(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

161
				$new_name = $this->archive_name."-diff".date("Y-m-d_H-i", /** @scrutinizer ignore-type */ $diff_timestamp_start);
Loading history...
162
			}
163
164
			$this->archive_name = $new_name;
165
166
		}
167
168
		if (isset($part) and $part) {
169
			$new_name = preg_replace('/-part(\d*)/', "-part".$part, $this->archive_name);
170
			if (!stristr($new_name, "-part")) {
171
				$new_name = $this->archive_name."-part".$part;
172
			}
173
174
			$this->archive_name = $new_name;
175
		}
176
177
		return $this;
178
	}
179
180
	/*
181
     *
182
     * Returns the backup archive name
183
     *
184
     * @return string archive name
185
     */
186
	public function get_archive_name()
187
	{
188
		return $this->archive_name;
189
	}
190
191
	/*
192
     *
193
     * Returns the multipart naming for the backup archive
194
     *
195
     * @return string multi-part backup name
196
     */
197
	public function get_archive_name_multipart()
198
	{
199
		$new_name = preg_replace('/-part(\d*)/', "", $this->archive_name);
200
		return $new_name."-multipart".$this->xcloner_settings->get_backup_extension_name(".csv");
201
	}
202
203
	/*
204
     *
205
     * Returns the full backup name including extension
206
     *
207
     */
208
	public function get_archive_name_with_extension()
209
	{
210
		return $this->archive_name.$this->xcloner_settings->get_backup_extension_name();
211
	}
212
213
	/*
214
     *
215
     * Send notification error by E-Mail
216
     *
217
     * @param $to
218
     * @param $from
219
     * @param $subject
220
     * @param $backup_name
221
     * @param $params
222
     * @param $error_message
223
     *
224
     * @return bool
225
     */
226
227
	/**
228
	 * @param string $error_message
229
	 */
230
	public function send_notification_error($to, $from, $subject, $backup_name, $params, $error_message)
0 ignored issues
show
Unused Code introduced by
The parameter $backup_name is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

230
	public function send_notification_error($to, $from, $subject, /** @scrutinizer ignore-unused */ $backup_name, $params, $error_message)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $params is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

230
	public function send_notification_error($to, $from, $subject, $backup_name, /** @scrutinizer ignore-unused */ $params, $error_message)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
231
	{
232
233
		$body = "";
234
		$body .= sprintf(__("Backup Site Url: %s"), get_site_url());
235
		$body .= "<br /><>";
236
237
		$body .= sprintf(__("Error Message: %s"), $error_message);
238
239
		$this->logger->info(sprintf("Sending backup error notification to %s", $to));
240
241
		$admin_email = get_option("admin_email");
242
243
		$headers = array('Content-Type: text/html; charset=UTF-8');
244
245
		if ($admin_email and $from) {
246
			$headers[] = 'From: '.$from.' <'.$admin_email.'>';
247
		}
248
249
		$return = wp_mail($to, $subject, $body, $headers);
250
251
		return $return;
252
	}
253
254
	/*
255
     *
256
     * Send backup archive notfication by E-Mail
257
     *
258
     * @param $to
259
     * @param $from
260
     * @param $subject
261
     * @param $backup_name
262
     * @param $params
263
     * @param string $error_message
264
     * @param array $additional
265
     *
266
     * @return bool
267
     */
268
	public function send_notification(
269
		$to,
270
		$from,
271
		$subject,
272
		$backup_name,
273
		$params,
274
		$error_message = "",
275
		$additional = array()
276
	) {
277
		if (!$from) {
278
			$from = "XCloner Backup";
279
		}
280
281
		if (($error_message)) {
282
			return $this->send_notification_error($to, $from, $subject, $backup_name, $params, $error_message);
283
		}
284
285
		$params = (array)$params;
286
287
		if (!$subject) {
288
			$subject = sprintf(__("New backup generated %s"), $backup_name);
289
		}
290
291
		$body = sprintf(__("Generated Backup Size: %s"), size_format($this->filesystem->get_backup_size($backup_name)));
0 ignored issues
show
Bug introduced by
It seems like size_format($this->files...kup_size($backup_name)) can also be of type false; however, parameter $args of sprintf() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

291
		$body = sprintf(__("Generated Backup Size: %s"), /** @scrutinizer ignore-type */ size_format($this->filesystem->get_backup_size($backup_name)));
Loading history...
292
		$body .= "<br /><br />";
293
294
		if (isset($additional['lines_total'])) {
295
			$body .= sprintf(__("Total files added: %s"), $additional['lines_total']);
296
			$body .= "<br /><br />";
297
		}
298
299
		$backup_parts = $this->filesystem->get_multipart_files($backup_name);
300
301
		if (!$backups_counter = sizeof($backup_parts)) {
302
			$backups_counter = 1;
303
		}
304
305
		$body .= sprintf(__("Backup Parts: %s"), $backups_counter);
306
		$body .= "<br />";
307
308
		if (sizeof($backup_parts)) {
309
			$body .= implode("<br />", $backup_parts);
310
			$body .= "<br />";
311
		}
312
313
		$body .= "<br />";
314
315
		$body .= sprintf(__("Backup Site Url: %s"), get_site_url());
316
		$body .= "<br />";
317
318
		if (isset($params['backup_params']->backup_comments)) {
319
			$body .= __("Backup Comments: ").$params['backup_params']->backup_comments;
320
			$body .= "<br /><br />";
321
		}
322
323
		if ($this->xcloner_settings->get_xcloner_option('xcloner_enable_log')) {
324
			$body .= __("Latest 50 Log Lines: ")."<br />".implode("<br />\n",
325
																		$this->logger->getLastDebugLines(50));
0 ignored issues
show
Bug introduced by
It seems like $this->logger->getLastDebugLines(50) can also be of type false; however, parameter $pieces of implode() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

325
																		/** @scrutinizer ignore-type */ $this->logger->getLastDebugLines(50));
Loading history...
326
		}
327
328
		$attachments = $this->filesystem->get_backup_attachments();
329
330
		$attachments_archive = $this->xcloner_settings->get_xcloner_tmp_path().DS."info.tgz";
331
332
		$tar = new Tar();
333
		$tar->create($attachments_archive);
334
335
		foreach ($attachments as $key => $file) {
336
			$tar->addFile($file, basename($file));
337
		}
338
		$tar->close();
339
340
		$this->logger->info(sprintf("Sending backup notification to %s", $to));
341
342
		$admin_email = get_option("admin_email");
343
344
		$headers = array('Content-Type: text/html; charset=UTF-8', 'From: '.$from.' <'.$admin_email.'>');
0 ignored issues
show
Bug introduced by
Are you sure $admin_email of type false|mixed can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

344
		$headers = array('Content-Type: text/html; charset=UTF-8', 'From: '.$from.' <'./** @scrutinizer ignore-type */ $admin_email.'>');
Loading history...
345
346
		$return = wp_mail($to, $subject, $body, $headers, array($attachments_archive));
347
348
		return $return;
349
	}
350
351
	/*
352
     *
353
     * Incremental Backup method
354
     *
355
     */
356
	public function start_incremental_backup($backup_params, $extra_params, $init)
357
	{
358
		$return = array();
359
360
		if (!isset($extra_params['backup_part'])) {
361
			$extra_params['backup_part'] = 0;
362
		}
363
364
		$return['extra']['backup_part'] = $extra_params['backup_part'];
365
366
		if (isset($extra_params['backup_archive_name'])) {
367
			$this->set_archive_name($extra_params['backup_archive_name'], $return['extra']['backup_part']);
368
		} else {
369
		    $encrypt = false;
370
            if(isset($backup_params['backup_encrypt']) && $backup_params['backup_encrypt']) {
371
                $encrypt = true;
372
            }
373
			$this->set_archive_name($backup_params['backup_name'], 0, $encrypt);
374
		}
375
376
		if (!$this->get_archive_name()) {
377
			$this->set_archive_name();
378
		}
379
380
		$this->backup_archive = new Tar();
381
		$this->backup_archive->setCompression($this->compression_level);
382
383
		$archive_info = $this->filesystem->get_storage_path_file_info($this->get_archive_name_with_extension());
384
385
		if ($init) {
386
			$this->logger->info(sprintf(__("Initializing the backup archive %s"), $this->get_archive_name()));
387
388
			$this->backup_archive->create($archive_info->getPath().DS.$archive_info->getFilename());
389
390
			$return['extra']['backup_init'] = 1;
391
392
		} else {
393
			$this->logger->info(sprintf(__("Opening for append the backup archive %s"), $this->get_archive_name()));
394
395
			$this->backup_archive->openForAppend($archive_info->getPath().DS.$archive_info->getFilename());
396
397
			$return['extra']['backup_init'] = 0;
398
399
		}
400
401
		$return['extra']['backup_archive_name'] = $this->get_archive_name();
402
		$return['extra']['backup_archive_name_full'] = $this->get_archive_name_with_extension();
403
404
		if (!isset($extra_params['start_at_line'])) {
405
			$extra_params['start_at_line'] = 0;
406
		}
407
408
		if (!isset($extra_params['start_at_byte'])) {
409
			$extra_params['start_at_byte'] = 0;
410
		}
411
412
		if (!$this->filesystem->get_tmp_filesystem()->has($this->filesystem->get_included_files_handler())) {
413
			$this->logger->error(sprintf("Missing the includes file handler %s, aborting...",
414
				$this->filesystem->get_included_files_handler()));
415
416
			$return['finished'] = 1;
417
			return $return;
418
		}
419
420
		$included_files_handler = $this->filesystem->get_included_files_handler(1);
421
422
		$file = new SplFileObject($included_files_handler);
423
424
		$file->seek(PHP_INT_MAX);
425
426
		$return['extra']['lines_total'] = ($file->key() - 1);
427
428
		//we skip the first CSV line with headers
429
		if (!$extra_params['start_at_line']) {
430
			$file->seek(1);
431
		} else {
432
			$file->seek($extra_params['start_at_line'] + 1);
433
		}
434
435
		$this->processed_size_bytes = 0;
436
437
		$counter = 0;
438
439
		$start_byte = $extra_params['start_at_byte'];
440
441
		$byte_limit = 0;
0 ignored issues
show
Unused Code introduced by
The assignment to $byte_limit is dead and can be removed.
Loading history...
442
443
		while (!$file->eof() and $counter <= $this->files_to_process_per_request) {
444
			$current_line_str = $file->current();
445
446
			$line = str_getcsv($current_line_str);
0 ignored issues
show
Bug introduced by
It seems like $current_line_str can also be of type array; however, parameter $input of str_getcsv() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

446
			$line = str_getcsv(/** @scrutinizer ignore-type */ $current_line_str);
Loading history...
447
448
			$relative_path = stripslashes($line[0]);
449
450
			$start_filesystem = "start_filesystem";
451
452
			if (isset($line[4])) {
453
				$start_filesystem = $line[4];
454
			}
455
456
			//$adapter = $this->filesystem->get_adapter($start_filesystem);
457
458
			if (!$relative_path || !$this->filesystem->get_filesystem($start_filesystem)->has($relative_path)) {
459
				if ($relative_path != "") {
460
					$this->logger->error(sprintf("Could not add file %b to backup archive, file not found",
461
						$relative_path));
462
				}
463
464
				$extra_params['start_at_line']++;
465
				$file->next();
466
				continue;
467
			}
468
469
			$file_info = $this->filesystem->get_filesystem($start_filesystem)->getMetadata($relative_path);
470
471
			if (!isset($file_info['size'])) {
472
				$file_info['size'] = 0;
473
			}
474
475
			if ($start_filesystem == "tmp_filesystem") {
476
				$file_info['archive_prefix_path'] = $this->xcloner_settings->get_xcloner_tmp_path_suffix();
477
			}
478
479
			$byte_limit = (int)$this->file_size_per_request_limit / 512;
480
481
			$append = 0;
482
483
			if ($file_info['size'] > $byte_limit * 512 or $start_byte) {
484
				$append = 1;
485
			}
486
487
			if (!isset($return['extra']['backup_size'])) {
488
				$return['extra']['backup_size'] = 0;
489
			}
490
491
			$return['extra']['backup_size'] = $archive_info->getSize();
492
493
			$estimated_new_size = $return['extra']['backup_size'] + $file_info['size'];
494
495
			//we create a new backup part if we reach the Split Achive Limit
496
			if ($this->xcloner_split_backup_limit and ($estimated_new_size > $this->xcloner_split_backup_limit) and (!$start_byte)) {
497
				$this->logger->info(sprintf("Backup size limit %s bytes reached, file add estimate %s, attempt to create a new archive ",
498
					$this->xcloner_split_backup_limit, $estimated_new_size));
499
				list($archive_info, $return['extra']['backup_part']) = $this->create_new_backup_part($return['extra']['backup_part']);
500
501
				if ($file_info['size'] > $this->xcloner_split_backup_limit) {
502
					$this->logger->info(sprintf("Excluding %s file as it's size(%s) is bigger than the backup split limit of %s and it won't fit a single backup file",
503
						$file_info['path'], $file_info['size'], $this->xcloner_split_backup_limit));
504
					$extra_params['start_at_line']++;
505
				}
506
507
				$return['extra']['start_at_line'] = $extra_params['start_at_line'];
508
				$return['extra']['start_at_byte'] = 0;
509
510
				$return['finished'] = 0;
511
512
				return $return;
513
			}
514
515
			list($bytes_wrote, $last_position) = $this->add_file_to_archive($file_info, $start_byte, $byte_limit,
516
				$append, $start_filesystem);
517
			$this->processed_size_bytes += $bytes_wrote;
518
519
			//echo" - processed ".$this->processed_size_bytes." bytes ".$this->file_size_per_request_limit." last_position:".$last_position." \n";
520
			$return['extra']['processed_file'] = $file_info['path'];
521
			$return['extra']['processed_file_size'] = $file_info['size'];
522
			$return['extra']['backup_size'] = $archive_info->getSize();
523
524
			if ($last_position > 0) {
525
				$start_byte = $last_position;
526
			} else {
527
				$extra_params['start_at_line']++;
528
				$file->next();
529
				$start_byte = 0;
530
				$counter++;
531
			}
532
533
			if ($this->processed_size_bytes >= $this->file_size_per_request_limit) {
534
				clearstatcache();
535
				$return['extra']['backup_size'] = $archive_info->getSize();
536
537
				$return['finished'] = 0;
538
				$return['extra']['start_at_line'] = $extra_params['start_at_line'];
539
				$return['extra']['start_at_byte'] = $last_position;
540
				$this->logger->info(sprintf("Reached the maximum %s request data limit, returning response",
541
					$this->file_size_per_request_limit));
542
				return $return;
543
			}
544
		}
545
546
		if (!$file->eof()) {
547
			clearstatcache();
548
			$return['extra']['backup_size'] = $archive_info->getSize();
549
550
			$return['finished'] = 0;
551
			$return['extra']['start_at_line'] = $extra_params['start_at_line'];
552
			$return['extra']['start_at_byte'] = $last_position;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $last_position does not seem to be defined for all execution paths leading up to this point.
Loading history...
553
			$this->logger->info(sprintf("We have reached the maximum files to process per request limit of %s, returning response",
554
				$this->files_to_process_per_request));
555
556
			return $return;
557
		}
558
559
		//close the backup archive by adding 2*512 blocks of zero bytes
560
		$this->logger->info(sprintf("Closing the backup archive %s with 2*512 zero bytes blocks.",
561
			$this->get_archive_name_with_extension()));
562
		$this->backup_archive->close();
563
564
		/**
565
		 * XCloner HOOK backup_archive_finished.
566
		 *
567
		 * This will get triggered when a backup archive is finished writing.
568
		 */
569
		//do_action('backup_archive_finished', $this->backup_archive, $this);
570
571
		//updating archive_info
572
		$archive_info = $this->filesystem->get_storage_path_file_info($this->get_archive_name_with_extension());
573
574
		if ($return['extra']['backup_part']) {
575
			$this->write_multipart_file($this->get_archive_name_with_extension());
576
		}
577
578
		$return['extra']['start_at_line'] = $extra_params['start_at_line'] - 1;
579
580
		if (isset($file_info)) {
581
			$return['extra']['processed_file'] = $file_info['path'];
582
			$return['extra']['processed_file_size'] = $file_info['size'];
583
		}
584
585
		clearstatcache();
586
		$return['extra']['backup_size'] = $archive_info->getSize();
587
588
		$return['finished'] = 1;
589
		return $return;
590
	}
591
592
	/*
593
     *
594
     * Write multipart file components
595
     *
596
     */
597
	private function write_multipart_file($path = "")
598
	{
599
		if (!$path) {
600
			$path = $this->get_archive_name_with_extension();
601
		}
602
603
		$file = $this->filesystem->get_filesystem("storage_filesystem_append")->getMetadata($path);
604
		//print_r($file_info);
605
		$line = '"'.$file['path'].'","'.$file['timestamp'].'","'.$file['size'].'"'.PHP_EOL;
606
607
608
		$this->filesystem->get_filesystem("storage_filesystem_append")
609
			->write($this->get_archive_name_multipart(), $line);
610
	}
611
612
	/*
613
     *
614
     * Create a new backup part
615
     *
616
     */
617
	private function create_new_backup_part($part = 0)
618
	{
619
		//close the backup archive by adding 2*512 blocks of zero bytes
620
		$this->logger->info(sprintf("Closing the backup archive %s with 2*512 zero bytes blocks.",
621
			$this->get_archive_name_with_extension()));
622
		$this->backup_archive->close();
623
624
		if (!$part) {
625
			$old_name = $this->get_archive_name_with_extension();
626
			$this->set_archive_name($this->get_archive_name(), ++$part);
627
			$this->rename_archive($old_name, $this->get_archive_name_with_extension());
628
629
			if ($this->filesystem->get_storage_filesystem()->has($this->get_archive_name_multipart())) {
630
				$this->filesystem->get_storage_filesystem()->delete($this->get_archive_name_multipart());
631
			}
632
633
			$this->write_multipart_file($this->get_archive_name_with_extension());
634
635
		} else {
636
			$this->logger->info(sprintf("Creating new multipart info file %s",
637
				$this->get_archive_name_with_extension()));
638
			$this->write_multipart_file($this->get_archive_name_with_extension());
639
		}
640
641
		$this->set_archive_name($this->get_archive_name(), ++$part);
642
643
		$this->logger->info(sprintf("Creating new backup archive part %s", $this->get_archive_name_with_extension()));
644
645
		$this->backup_archive = new Tar();
646
		$this->backup_archive->setCompression($this->compression_level);
647
		$archive_info = $this->filesystem->get_storage_path_file_info($this->get_archive_name_with_extension());
648
		$this->backup_archive->create($archive_info->getPath().DS.$archive_info->getFilename());
649
650
		return array($archive_info, $part);
651
652
	}
653
654
	/*
655
     *
656
     * Add file to archive
657
     *
658
     */
659
660
	/**
661
	 * @param integer $append
662
	 */
663
	public function add_file_to_archive($file_info, $start_at_byte, $byte_limit = 0, $append, $filesystem)
664
	{
665
666
		$start_adapter = $this->filesystem->get_adapter($filesystem);
667
		$start_filesystem = $this->filesystem->get_adapter($filesystem);
668
669
		if (!$file_info['path']) {
670
			return;
671
		}
672
673
		if (isset($file_info['archive_prefix_path'])) {
674
			$file_info['target_path'] = $file_info['archive_prefix_path']."/".$file_info['path'];
675
		} else {
676
			$file_info['target_path'] = $file_info['path'];
677
		}
678
679
		$last_position = $start_at_byte;
680
681
		//$start_adapter = $this->filesystem->get_start_adapter();
682
683
		if (!$append) {
684
			$bytes_wrote = $file_info['size'];
685
			$this->logger->info(sprintf("Adding %s bytes of file %s to archive %s ", $bytes_wrote,
686
				$file_info['target_path'], $this->get_archive_name_with_extension()));
687
			$this->backup_archive->addFile($start_adapter->applyPathPrefix($file_info['path']),
688
				$file_info['target_path']);
689
		} else {
690
			$tmp_file = md5($file_info['path']);
691
692
			//we isolate file to tmp if we are at byte 0, the starting point of file reading
693
			if (!$start_at_byte) {
694
				$this->logger->info(sprintf("Copying %s file to tmp filesystem file %s to prevent reading changes",
695
					$file_info['path'], $tmp_file));
696
				$file_stream = $start_filesystem->readStream($file_info['path']);
697
698
				if (is_resource($file_stream['stream'])) {
699
					$this->filesystem->get_tmp_filesystem()->writeStream($tmp_file, $file_stream['stream']);
700
				}
701
			}
702
703
			if ($this->filesystem->get_tmp_filesystem()->has($tmp_file)) {
704
				$is_tmp = 1;
705
				$last_position = $this->backup_archive->appendFileData($this->filesystem->get_tmp_filesystem_adapter()
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $last_position is correct as $this->backup_archive->a...t_at_byte, $byte_limit) targeting splitbrain\PHPArchive\Tar::appendFileData() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
706
														->applyPathPrefix($tmp_file),
707
					$file_info['target_path'], $start_at_byte, $byte_limit);
708
			} else {
709
				$is_tmp = 0;
710
				$last_position = $this->backup_archive->appendFileData($start_adapter->applyPathPrefix($file_info['path']),
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $last_position is correct as $this->backup_archive->a...t_at_byte, $byte_limit) targeting splitbrain\PHPArchive\Tar::appendFileData() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
711
					$file_info['target_path'], $start_at_byte, $byte_limit);
712
			}
713
714
715
			if ($last_position == -1) {
716
				$bytes_wrote = $file_info['size'] - $start_at_byte;
717
			} else {
718
				$bytes_wrote = $last_position - $start_at_byte;
719
			}
720
721
722
			if ($is_tmp) {
723
				$this->logger->info(sprintf("Appended %s bytes, starting position %s, of tmp file %s (%s) to archive %s ",
724
					$bytes_wrote, $start_at_byte, $tmp_file, $file_info['target_path'], $this->get_archive_name()));
725
			} else {
726
				$this->logger->info(sprintf("Appended %s bytes, starting position %s, of original file %s to archive %s ",
727
					$bytes_wrote, $start_at_byte, $file_info['target_path'], $tmp_file, $this->get_archive_name()));
728
			}
729
730
			//we delete here the isolated tmp file
731
			if ($last_position == -1) {
732
				if ($this->filesystem->get_tmp_filesystem_adapter()->has($tmp_file)) {
733
					$this->logger->info(sprintf("Deleting %s from the tmp filesystem", $tmp_file));
734
					$this->filesystem->get_tmp_filesystem_adapter()->delete($tmp_file);
735
				}
736
			}
737
738
		}
739
740
		return array($bytes_wrote, $last_position);
741
	}
742
743
	/**
744
	 * Open a TAR archive and put the file cursor at the end for data appending
745
	 *
746
	 * If $file is empty, the tar file will be created in memory
747
	 *
748
	 * @param string $file
749
	 * @throws ArchiveIOException
750
	 */
751
	/*
752
    public function openForAppend($file = '')
753
    {
754
        $this->file   = $file;
755
        $this->memory = '';
756
        $this->fh     = 0;
757
758
        if ($this->file) {
759
            // determine compression
760
            if ($this->comptype == Archive::COMPRESS_AUTO) {
761
                $this->setCompression($this->complevel, $this->filetype($file));
762
            }
763
764
            if ($this->comptype === Archive::COMPRESS_GZIP) {
765
                $this->fh = @gzopen($this->file, 'ab'.$this->complevel);
766
            } elseif ($this->comptype === Archive::COMPRESS_BZIP) {
767
                $this->fh = @bzopen($this->file, 'a');
768
            } else {
769
                $this->fh = @fopen($this->file, 'ab');
770
            }
771
772
            if (!$this->fh) {
773
                throw new ArchiveIOException('Could not open file for writing: '.$this->file);
774
            }
775
        }
776
        $this->backup_archive->writeaccess = true;
777
        $this->backup_archive->closed      = false;
778
    }
779
    */
780
781
	/**
782
	 * Append data to a file to the current TAR archive using an existing file in the filesystem
783
	 *
784
	 * @param string $file path to the original file
785
	 * @param int $start starting reading position in file
786
	 * @param int $end end position in reading multiple with 512
787
	 * @param string|FileInfo $fileinfo either the name to us in archive (string) or a FileInfo oject with
788
	 * all meta data, empty to take from original
789
	 * @throws ArchiveIOException
790
	 */
791
	/*
792
     * public function appendFileData($file, $fileinfo = '', $start = 0, $limit = 0)
793
    {
794
		$end = $start+($limit*512);
795
796
		//check to see if we are at the begining of writing the file
797
		if(!$start)
798
		{
799
	        if (is_string($fileinfo)) {
800
				$fileinfo = FileInfo::fromPath($file, $fileinfo);
801
	        }
802
		}
803
804
        if ($this->closed) {
805
            throw new ArchiveIOException('Archive has been closed, files can no longer be added');
806
        }
807
808
        $fp = fopen($file, 'rb');
809
810
        fseek($fp, $start);
811
812
        if (!$fp) {
813
            throw new ArchiveIOException('Could not open file for reading: '.$file);
814
        }
815
816
        // create file header
817
		if(!$start)
818
			$this->backup_archive->writeFileHeader($fileinfo);
819
820
		$bytes = 0;
821
        // write data
822
        while ($end >=ftell($fp) and !feof($fp) ) {
823
            $data = fread($fp, 512);
824
            if ($data === false) {
825
                break;
826
            }
827
            if ($data === '') {
828
                break;
829
            }
830
            $packed = pack("a512", $data);
831
            $bytes += $this->backup_archive->writebytes($packed);
832
        }
833
834
835
836
        //if we are not at the end of file, we return the current position for incremental writing
837
        if(!feof($fp))
838
			$last_position = ftell($fp);
839
		else
840
			$last_position = -1;
841
842
        fclose($fp);
843
844
        return $last_position;
845
    }*/
846
847
	/**
848
	 * Adds a file to a TAR archive by appending it's data
849
	 *
850
	 * @param string $archive name of the archive file
851
	 * @param string $file name of the file to read data from
852
	 * @param string $start start position from where to start reading data
853
	 * @throws ArchiveIOException
854
	 */
855
	/*public function addFileToArchive($archive, $file, $start = 0)
856
    {
857
        $this->openForAppend($archive);
858
        return $start = $this->appendFileData($file, $start, $this->file_size_per_request_limit);
859
    }
860
    */
861
862
}
863