Version Description
Release date: March 15th, 2022
- New feature: REST API calls for backup and settings management.
- Bug fix: posix_getpgid availability check.
- Update: Updated dependencies.
Download this release
Release Info
Developer | boldgrid |
Plugin | Total Upkeep – WordPress Backup Plugin plus Restore & Migrate by BoldGrid |
Version | 1.15.0 |
Comparing to | |
See all releases |
Code changes from version 1.14.14 to 1.15.0
- admin/class-boldgrid-backup-admin-archive.php +72 -1
- admin/class-boldgrid-backup-admin-core.php +55 -14
- admin/class-boldgrid-backup-admin-cron.php +47 -9
- admin/class-boldgrid-backup-admin-go-pro.php +10 -0
- admin/class-boldgrid-backup-admin-log.php +2 -1
- admin/class-boldgrid-backup-admin-nopriv.php +138 -0
- admin/class-boldgrid-backup-admin-restore-helper.php +1 -1
- admin/class-boldgrid-backup-admin-task-helper.php +124 -0
- admin/class-boldgrid-backup-admin-task.md +129 -0
- admin/class-boldgrid-backup-admin-task.php +297 -0
- admin/class-boldgrid-backup-admin-test.php +6 -0
- admin/class-boldgrid-backup-admin-upload.php +6 -116
- admin/class-boldgrid-backup-admin-utility.php +158 -74
- admin/class-boldgrid-backup-admin-wp-cron.php +2 -1
- admin/compressor/class-boldgrid-backup-admin-compressor-system-zip.php +59 -11
- admin/js/boldgrid-backup-admin-in-progress.js +9 -7
- admin/partials/settings/backup-security.php +1 -1
- boldgrid-backup.php +4 -2
- cli/class-site-check.php +0 -31
- cli/verify-dd66c7edb75333982c82a15ab5b733f0.php +1 -0
- includes/archive/class-factory.php +92 -0
- includes/archive/class-option.php +126 -0
- includes/class-boldgrid-backup-archive-fetcher.php +290 -0
- includes/class-boldgrid-backup-archiver.php +117 -0
- includes/class-boldgrid-backup-restorer.php +251 -0
- includes/class-boldgrid-backup.php +51 -0
- readme.txt +9 -1
- rest/README.MD +141 -0
- rest/class-boldgrid-backup-rest-archive.php +277 -0
- rest/class-boldgrid-backup-rest-controller.php +84 -0
- rest/class-boldgrid-backup-rest-job.php +146 -0
- rest/class-boldgrid-backup-rest-setting.php +195 -0
- rest/class-boldgrid-backup-rest-siteurl.php +178 -0
- rest/class-boldgrid-backup-rest-test.php +107 -0
- rest/class-boldgrid-backup-rest-utility.php +77 -0
- vendor/autoload.php +1 -1
- vendor/boldgrid/library/.travis.yml +32 -10
- vendor/boldgrid/library/README.md +20 -0
- vendor/boldgrid/library/bin/install-wp-tests.sh +8 -5
- vendor/boldgrid/library/composer.json +3 -0
- vendor/boldgrid/library/composer.lock +2039 -0
- vendor/boldgrid/library/src/Library/Configs.php +8 -0
- vendor/boldgrid/library/src/Library/Dashboard/SortWidgets.php +40 -1
- vendor/boldgrid/library/src/Library/RatingPrompt.php +3 -1
- vendor/boldgrid/library/src/Util/Load.php +9 -1
- vendor/boldgrid/library/src/assets/js/rating-prompt.js +4 -1
- vendor/boldgrid/library/src/library.global.php +1 -1
- vendor/boldgrid/library/tests/Library/Library/test-activity.php +1 -1
- vendor/boldgrid/library/tests/Library/Library/test-rating-prompt.php +1 -1
- vendor/boldgrid/library/tests/Library/Plugin/test-factory.php +1 -1
- vendor/boldgrid/library/tests/Library/Plugin/test-notice.php +1 -1
- vendor/boldgrid/library/tests/Library/Plugin/test-page.php +1 -1
- vendor/boldgrid/library/tests/Library/Plugin/test-plugin.php +1 -1
- vendor/boldgrid/library/tests/Library/Plugin/test-plugins.php +1 -1
- vendor/boldgrid/library/tests/Library/Theme/test-theme.php +1 -1
- vendor/boldgrid/library/tests/Library/Theme/test-themes.php +1 -1
- vendor/boldgrid/library/tests/Library/Theme/test-update-data.php +1 -1
- vendor/boldgrid/library/tests/bootstrap.php +10 -1
- vendor/boldgrid/library/yarn.lock +12 -12
- vendor/composer/autoload_real.php +7 -7
- vendor/composer/autoload_static.php +4 -4
- vendor/composer/installed.json +15 -13
- vendor/phpseclib/phpseclib/BACKERS.md +5 -1
- vendor/phpseclib/phpseclib/README.md +8 -2
- vendor/phpseclib/phpseclib/phpseclib/Crypt/Base.php +113 -5
- vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA.php +6 -6
- vendor/phpseclib/phpseclib/phpseclib/File/ASN1.php +12 -0
- vendor/phpseclib/phpseclib/phpseclib/File/X509.php +2 -2
- vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger.php +1 -1
- vendor/phpseclib/phpseclib/phpseclib/Net/SFTP.php +670 -110
- vendor/phpseclib/phpseclib/phpseclib/Net/SSH2.php +328 -80
- vendor/phpseclib/phpseclib/phpseclib/bootstrap.php +2 -1
admin/class-boldgrid-backup-admin-archive.php
CHANGED
@@ -106,6 +106,36 @@ class Boldgrid_Backup_Admin_Archive {
|
|
106 |
*/
|
107 |
public $view_details_url = '';
|
108 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
109 |
/**
|
110 |
* Constructor.
|
111 |
*
|
@@ -113,7 +143,11 @@ class Boldgrid_Backup_Admin_Archive {
|
|
113 |
*
|
114 |
* @param Boldgrid_Backup_Admin_Core $core Core class object.
|
115 |
*/
|
116 |
-
public function __construct( $core ) {
|
|
|
|
|
|
|
|
|
117 |
$this->core = $core;
|
118 |
}
|
119 |
|
@@ -234,6 +268,28 @@ class Boldgrid_Backup_Admin_Archive {
|
|
234 |
return $this->core->wp_filesystem->size( $this->filepath );
|
235 |
}
|
236 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
237 |
/**
|
238 |
* Init.
|
239 |
*
|
@@ -277,6 +333,10 @@ class Boldgrid_Backup_Admin_Archive {
|
|
277 |
$this->compressor = ! empty( $this->log['compressor'] ) ? $this->log['compressor'] : 'php_zip';
|
278 |
|
279 |
$this->view_details_url = admin_url( 'admin.php?page=boldgrid-backup-archive-details&filename=' . $this->filename );
|
|
|
|
|
|
|
|
|
280 |
}
|
281 |
|
282 |
/**
|
@@ -482,6 +542,17 @@ class Boldgrid_Backup_Admin_Archive {
|
|
482 |
return $this->core->archive_log->write( $this->log );
|
483 |
}
|
484 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
485 |
/**
|
486 |
* Update an archive's timestamp based on the time in the log.
|
487 |
*
|
106 |
*/
|
107 |
public $view_details_url = '';
|
108 |
|
109 |
+
/**
|
110 |
+
* Archive id.
|
111 |
+
*
|
112 |
+
* The archive id is the archive's id as found in the boldgrid_backup_backups option.
|
113 |
+
*
|
114 |
+
* This class includes the self::set_id() method to set the actual id, but this class doesn't actually
|
115 |
+
* call that method to set the id. The id is generally set within Boldgrid\Backup\Archive\Factory.
|
116 |
+
*
|
117 |
+
* @since SINCEVERSION
|
118 |
+
* @access private
|
119 |
+
* @var int
|
120 |
+
*
|
121 |
+
* @see Boldgrid\Backup\Archive\Option for more information about the boldgrid_backup_backups option.
|
122 |
+
*/
|
123 |
+
private $id;
|
124 |
+
|
125 |
+
/**
|
126 |
+
* The archive key.
|
127 |
+
*
|
128 |
+
* When retrieving a list of archives, you'll get an array, and this is the archives location in
|
129 |
+
* the array.
|
130 |
+
*
|
131 |
+
* @since SINCEVERSION
|
132 |
+
* @access private
|
133 |
+
* @var int
|
134 |
+
*
|
135 |
+
* @see self::init() To see this property initialized.
|
136 |
+
*/
|
137 |
+
private $key;
|
138 |
+
|
139 |
/**
|
140 |
* Constructor.
|
141 |
*
|
143 |
*
|
144 |
* @param Boldgrid_Backup_Admin_Core $core Core class object.
|
145 |
*/
|
146 |
+
public function __construct( Boldgrid_Backup_Admin_Core $core = null ) {
|
147 |
+
if ( empty( $core ) ) {
|
148 |
+
$core = apply_filters( 'boldgrid_backup_get_core', null );
|
149 |
+
}
|
150 |
+
|
151 |
$this->core = $core;
|
152 |
}
|
153 |
|
268 |
return $this->core->wp_filesystem->size( $this->filepath );
|
269 |
}
|
270 |
|
271 |
+
/**
|
272 |
+
* Get the archive id.
|
273 |
+
*
|
274 |
+
* @since SINCEVERSION
|
275 |
+
*
|
276 |
+
* @return int
|
277 |
+
*/
|
278 |
+
public function get_id() {
|
279 |
+
return $this->id;
|
280 |
+
}
|
281 |
+
|
282 |
+
/**
|
283 |
+
* Get the archive key.
|
284 |
+
*
|
285 |
+
* @since SINCEVERSION
|
286 |
+
*
|
287 |
+
* @return int
|
288 |
+
*/
|
289 |
+
public function get_key() {
|
290 |
+
return $this->key;
|
291 |
+
}
|
292 |
+
|
293 |
/**
|
294 |
* Init.
|
295 |
*
|
333 |
$this->compressor = ! empty( $this->log['compressor'] ) ? $this->log['compressor'] : 'php_zip';
|
334 |
|
335 |
$this->view_details_url = admin_url( 'admin.php?page=boldgrid-backup-archive-details&filename=' . $this->filename );
|
336 |
+
|
337 |
+
// Set our key.
|
338 |
+
$details = $this->get_by_name( $this->filename );
|
339 |
+
$this->key = isset( $details['key'] ) ? $details['key'] : null;
|
340 |
}
|
341 |
|
342 |
/**
|
542 |
return $this->core->archive_log->write( $this->log );
|
543 |
}
|
544 |
|
545 |
+
/**
|
546 |
+
* Set the archive id.
|
547 |
+
*
|
548 |
+
* @since SINCEVERSION
|
549 |
+
*
|
550 |
+
* @param int $id The archive id.
|
551 |
+
*/
|
552 |
+
public function set_id( $id ) {
|
553 |
+
$this->id = (int) $id;
|
554 |
+
}
|
555 |
+
|
556 |
/**
|
557 |
* Update an archive's timestamp based on the time in the log.
|
558 |
*
|
admin/class-boldgrid-backup-admin-core.php
CHANGED
@@ -1340,7 +1340,10 @@ class Boldgrid_Backup_Admin_Core {
|
|
1340 |
// If changed, then update the siteurl in the database.
|
1341 |
if ( $restored_wp_siteurl !== $wp_siteurl ) {
|
1342 |
$update_siteurl_success =
|
1343 |
-
Boldgrid_Backup_Admin_Utility::update_siteurl(
|
|
|
|
|
|
|
1344 |
|
1345 |
if ( ! $update_siteurl_success ) {
|
1346 |
// Display an error notice.
|
@@ -2321,10 +2324,16 @@ class Boldgrid_Backup_Admin_Core {
|
|
2321 |
*
|
2322 |
* @see https://codex.wordpress.org/Function_Reference/flush_rewrite_rules
|
2323 |
*
|
2324 |
-
* @param
|
|
|
|
|
|
|
|
|
|
|
|
|
2325 |
* @return array An array of archive file information.
|
2326 |
*/
|
2327 |
-
public function restore_archive_file( $dryrun = false ) {
|
2328 |
$this->restoring_archive_file = true;
|
2329 |
|
2330 |
$this->logger->init( 'restore-' . time() . '.log' );
|
@@ -2336,6 +2345,14 @@ class Boldgrid_Backup_Admin_Core {
|
|
2336 |
|
2337 |
$restore_ok = true;
|
2338 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2339 |
// If a restoration was not requested, then abort.
|
2340 |
if ( empty( $_POST['restore_now'] ) ) { // phpcs:ignore WordPress.CSRF.NonceVerification.NoNonceVerification
|
2341 |
$error_message = esc_html__( 'Invalid restore_now value.', 'boldgrid-backup' );
|
@@ -2343,6 +2360,12 @@ class Boldgrid_Backup_Admin_Core {
|
|
2343 |
return [ 'error' => $error_message ];
|
2344 |
}
|
2345 |
|
|
|
|
|
|
|
|
|
|
|
|
|
2346 |
// Check if functional.
|
2347 |
if ( ! $this->test->run_functionality_tests() ) {
|
2348 |
$error_message = esc_html__( 'Functionality tests fail.', 'boldgrid-backup' );
|
@@ -2350,12 +2373,15 @@ class Boldgrid_Backup_Admin_Core {
|
|
2350 |
return [ 'error' => $error_message ];
|
2351 |
}
|
2352 |
|
2353 |
-
|
2354 |
-
|
2355 |
-
|
2356 |
-
|
2357 |
-
|
2358 |
-
|
|
|
|
|
|
|
2359 |
$archive_key = (int) $_POST['archive_key'];
|
2360 |
} else {
|
2361 |
$error_message = esc_html__( 'Invalid key for the selected archive file.', 'boldgrid-backup' );
|
@@ -2363,8 +2389,15 @@ class Boldgrid_Backup_Admin_Core {
|
|
2363 |
return [ 'error' => $error_message ];
|
2364 |
}
|
2365 |
|
2366 |
-
|
2367 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2368 |
$archive_filename = sanitize_file_name( $_POST['archive_filename'] );
|
2369 |
} else {
|
2370 |
$error_message = esc_html__( 'Invalid filename for the selected archive file.', 'boldgrid-backup' );
|
@@ -2655,7 +2688,10 @@ class Boldgrid_Backup_Admin_Core {
|
|
2655 |
$this->is_archiving_update_protection = ! empty( $_POST['is_updating'] ) &&
|
2656 |
'true' === $_POST['is_updating'];
|
2657 |
|
2658 |
-
$
|
|
|
|
|
|
|
2659 |
|
2660 |
/*
|
2661 |
* If there were any errors encountered during the backup, save them to the In Progress data.
|
@@ -3007,7 +3043,11 @@ class Boldgrid_Backup_Admin_Core {
|
|
3007 |
wp_send_json_error();
|
3008 |
}
|
3009 |
|
3010 |
-
|
|
|
|
|
|
|
|
|
3011 |
|
3012 |
/*
|
3013 |
* Generate success message and add as a user notice.
|
@@ -3070,7 +3110,8 @@ class Boldgrid_Backup_Admin_Core {
|
|
3070 |
}
|
3071 |
|
3072 |
// Perform the backup operation.
|
3073 |
-
$
|
|
|
3074 |
}
|
3075 |
|
3076 |
/**
|
1340 |
// If changed, then update the siteurl in the database.
|
1341 |
if ( $restored_wp_siteurl !== $wp_siteurl ) {
|
1342 |
$update_siteurl_success =
|
1343 |
+
Boldgrid_Backup_Admin_Utility::update_siteurl( array(
|
1344 |
+
'old_siteurl' => $restored_wp_siteurl,
|
1345 |
+
'siteurl' => $wp_siteurl,
|
1346 |
+
) );
|
1347 |
|
1348 |
if ( ! $update_siteurl_success ) {
|
1349 |
// Display an error notice.
|
2324 |
*
|
2325 |
* @see https://codex.wordpress.org/Function_Reference/flush_rewrite_rules
|
2326 |
*
|
2327 |
+
* @param bool $dryrun An optional switch to perform a dry run test.
|
2328 |
+
* @param array $args {
|
2329 |
+
* An optional array of args.
|
2330 |
+
*
|
2331 |
+
* @type int $archive_key An archive key.
|
2332 |
+
* @type string $archive_filename An archive filename.
|
2333 |
+
* }
|
2334 |
* @return array An array of archive file information.
|
2335 |
*/
|
2336 |
+
public function restore_archive_file( $dryrun = false, array $args = [] ) {
|
2337 |
$this->restoring_archive_file = true;
|
2338 |
|
2339 |
$this->logger->init( 'restore-' . time() . '.log' );
|
2345 |
|
2346 |
$restore_ok = true;
|
2347 |
|
2348 |
+
/*
|
2349 |
+
* This is a generic method to restore an archive. Do not assume the request to restore is coming
|
2350 |
+
* from a user directly via $_POST.
|
2351 |
+
*
|
2352 |
+
* Refer to check_ajax_referer usage below to help protect ajax requests.
|
2353 |
+
*/
|
2354 |
+
$is_post_restore = isset( $_POST['action'] ) && 'boldgrid_backup_restore_archive' === $_POST['action']; // phpcs:ignore WordPress.CSRF.NonceVerification.NoNonceVerification
|
2355 |
+
|
2356 |
// If a restoration was not requested, then abort.
|
2357 |
if ( empty( $_POST['restore_now'] ) ) { // phpcs:ignore WordPress.CSRF.NonceVerification.NoNonceVerification
|
2358 |
$error_message = esc_html__( 'Invalid restore_now value.', 'boldgrid-backup' );
|
2360 |
return [ 'error' => $error_message ];
|
2361 |
}
|
2362 |
|
2363 |
+
if ( $is_post_restore && ! check_ajax_referer( 'boldgrid_backup_restore_archive', 'archive_auth', false ) ) {
|
2364 |
+
$error_message = esc_html__( 'Invalid nonce.', 'boldgrid-backup' );
|
2365 |
+
$this->logger->add( $error_message );
|
2366 |
+
return [ 'error' => $error_message ];
|
2367 |
+
}
|
2368 |
+
|
2369 |
// Check if functional.
|
2370 |
if ( ! $this->test->run_functionality_tests() ) {
|
2371 |
$error_message = esc_html__( 'Functionality tests fail.', 'boldgrid-backup' );
|
2373 |
return [ 'error' => $error_message ];
|
2374 |
}
|
2375 |
|
2376 |
+
/*
|
2377 |
+
* Get our archive key.
|
2378 |
+
*
|
2379 |
+
* It can be passed in via $args or $_POST.
|
2380 |
+
*/
|
2381 |
+
$archive_key = false;
|
2382 |
+
if ( isset( $args['archive_key'] ) ) {
|
2383 |
+
$archive_key = (int) $args['archive_key'];
|
2384 |
+
} elseif ( isset( $_POST['archive_key'] ) && is_numeric( $_POST['archive_key'] ) ) { // phpcs:ignore WordPress.CSRF.NonceVerification.NoNonceVerification
|
2385 |
$archive_key = (int) $_POST['archive_key'];
|
2386 |
} else {
|
2387 |
$error_message = esc_html__( 'Invalid key for the selected archive file.', 'boldgrid-backup' );
|
2389 |
return [ 'error' => $error_message ];
|
2390 |
}
|
2391 |
|
2392 |
+
/*
|
2393 |
+
* Get our archive filename.
|
2394 |
+
*
|
2395 |
+
* It can be passed in via $args or $_POST.
|
2396 |
+
*/
|
2397 |
+
$archive_filename = false;
|
2398 |
+
if ( ! empty( $args['archive_filename'] ) ) {
|
2399 |
+
$archive_filename = sanitize_file_name( $args['archive_filename'] );
|
2400 |
+
} elseif ( ! empty( $_POST['archive_filename'] ) ) { // phpcs:ignore WordPress.CSRF.NonceVerification.NoNonceVerification
|
2401 |
$archive_filename = sanitize_file_name( $_POST['archive_filename'] );
|
2402 |
} else {
|
2403 |
$error_message = esc_html__( 'Invalid filename for the selected archive file.', 'boldgrid-backup' );
|
2688 |
$this->is_archiving_update_protection = ! empty( $_POST['is_updating'] ) &&
|
2689 |
'true' === $_POST['is_updating'];
|
2690 |
|
2691 |
+
$archiver = new Boldgrid_Backup_Archiver();
|
2692 |
+
$archiver->run();
|
2693 |
+
|
2694 |
+
$archive_info = $archiver->get_info();
|
2695 |
|
2696 |
/*
|
2697 |
* If there were any errors encountered during the backup, save them to the In Progress data.
|
3043 |
wp_send_json_error();
|
3044 |
}
|
3045 |
|
3046 |
+
// Do the actual restoration.
|
3047 |
+
$restorer = new Boldgrid_Backup_Restorer();
|
3048 |
+
$restorer->run();
|
3049 |
+
|
3050 |
+
$archive_info = $restorer->get_info();
|
3051 |
|
3052 |
/*
|
3053 |
* Generate success message and add as a user notice.
|
3110 |
}
|
3111 |
|
3112 |
// Perform the backup operation.
|
3113 |
+
$archiver = new Boldgrid_Backup_Archiver();
|
3114 |
+
$archiver->run();
|
3115 |
}
|
3116 |
|
3117 |
/**
|
admin/class-boldgrid-backup-admin-cron.php
CHANGED
@@ -202,6 +202,7 @@ class Boldgrid_Backup_Admin_Cron {
|
|
202 |
if ( 'cron' === $scheduler && $this->core->scheduler->is_available( $scheduler ) ) {
|
203 |
$this->core->scheduler->clear_all_schedules();
|
204 |
|
|
|
205 |
if ( ! empty( $schedule ) ) {
|
206 |
$scheduled = $this->add_cron_entry( $settings );
|
207 |
}
|
@@ -347,7 +348,7 @@ class Boldgrid_Backup_Admin_Cron {
|
|
347 |
$settings = $this->core->settings->get_settings();
|
348 |
}
|
349 |
|
350 |
-
if (
|
351 |
return false;
|
352 |
}
|
353 |
|
@@ -1080,7 +1081,10 @@ class Boldgrid_Backup_Admin_Cron {
|
|
1080 |
/**
|
1081 |
* Hook into "wp_ajax_nopriv_boldgrid_backup_run_backup" and generate backup.
|
1082 |
*
|
1083 |
-
*
|
|
|
|
|
|
|
1084 |
*
|
1085 |
* @see Boldgrid_Backup_Admin_Cron::is_valid_call()
|
1086 |
*
|
@@ -1091,9 +1095,10 @@ class Boldgrid_Backup_Admin_Cron {
|
|
1091 |
wp_die( esc_html__( 'Error: Invalid request.', 'boldgrid-backup' ) );
|
1092 |
}
|
1093 |
|
1094 |
-
$
|
|
|
1095 |
|
1096 |
-
return $
|
1097 |
}
|
1098 |
|
1099 |
/**
|
@@ -1106,16 +1111,49 @@ class Boldgrid_Backup_Admin_Cron {
|
|
1106 |
* @return array An array of archive file information.
|
1107 |
*/
|
1108 |
public function restore() {
|
|
|
|
|
|
|
|
|
1109 |
if ( ! $this->is_valid_call() ) {
|
1110 |
wp_die( esc_html__( 'Error: Invalid request.', 'boldgrid-backup' ) );
|
1111 |
}
|
1112 |
|
1113 |
-
|
1114 |
-
|
1115 |
-
|
|
|
1116 |
|
1117 |
-
|
1118 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1119 |
}
|
1120 |
|
1121 |
return $archive_info;
|
202 |
if ( 'cron' === $scheduler && $this->core->scheduler->is_available( $scheduler ) ) {
|
203 |
$this->core->scheduler->clear_all_schedules();
|
204 |
|
205 |
+
$scheduled = false;
|
206 |
if ( ! empty( $schedule ) ) {
|
207 |
$scheduled = $this->add_cron_entry( $settings );
|
208 |
}
|
348 |
$settings = $this->core->settings->get_settings();
|
349 |
}
|
350 |
|
351 |
+
if ( empty( $settings['site_check']['enabled'] ) ) {
|
352 |
return false;
|
353 |
}
|
354 |
|
1081 |
/**
|
1082 |
* Hook into "wp_ajax_nopriv_boldgrid_backup_run_backup" and generate backup.
|
1083 |
*
|
1084 |
+
* A scheduled backup (via cron) will call a url which ultimately triggers this method to be ran
|
1085 |
+
* to backup the site.
|
1086 |
+
*
|
1087 |
+
* @since 1.6.1
|
1088 |
*
|
1089 |
* @see Boldgrid_Backup_Admin_Cron::is_valid_call()
|
1090 |
*
|
1095 |
wp_die( esc_html__( 'Error: Invalid request.', 'boldgrid-backup' ) );
|
1096 |
}
|
1097 |
|
1098 |
+
$archiver = new Boldgrid_Backup_Archiver();
|
1099 |
+
$archiver->run();
|
1100 |
|
1101 |
+
return $archiver->get_info();
|
1102 |
}
|
1103 |
|
1104 |
/**
|
1111 |
* @return array An array of archive file information.
|
1112 |
*/
|
1113 |
public function restore() {
|
1114 |
+
// phpcs:disable WordPress.CSRF.NonceVerification.NoNonceVerification
|
1115 |
+
$task_id = ! empty( $_POST['task_id'] ) ? $_POST['task_id'] : null;
|
1116 |
+
// phpcs:enable WordPress.CSRF.NonceVerification.NoNonceVerification
|
1117 |
+
|
1118 |
if ( ! $this->is_valid_call() ) {
|
1119 |
wp_die( esc_html__( 'Error: Invalid request.', 'boldgrid-backup' ) );
|
1120 |
}
|
1121 |
|
1122 |
+
// A default error to return if restoration is not started in conditionals below.
|
1123 |
+
$archive_info = [
|
1124 |
+
'error' => __( 'Unknown error attempting restore.', 'boldgrid-backup' ),
|
1125 |
+
];
|
1126 |
|
1127 |
+
/*
|
1128 |
+
* Restore an archive.
|
1129 |
+
*
|
1130 |
+
* As of @SINCEVERSION, archives can be restored via REST. If we have a task, we're handling
|
1131 |
+
* a REST restore. Otherwise, we're handling a standard restore request.
|
1132 |
+
*/
|
1133 |
+
if ( ! empty( $task_id ) ) {
|
1134 |
+
$task = new Boldgrid_Backup_Admin_Task();
|
1135 |
+
$task_found = $task->init_by_id( $task_id );
|
1136 |
+
$restorer = new Boldgrid_Backup_Restorer();
|
1137 |
+
|
1138 |
+
if ( ! $task_found ) {
|
1139 |
+
$archive_info = [
|
1140 |
+
'error' => __( 'Resore error: Unable to instantiate task.', 'boldgrid-backup' ),
|
1141 |
+
];
|
1142 |
+
} elseif ( false !== $task->get_data( 'url' ) ) {
|
1143 |
+
$restorer->run_by_url( $task->get_data( 'url' ) );
|
1144 |
+
$archive_info = $restorer->get_info();
|
1145 |
+
} elseif ( false !== $task->get_data( 'backup_id' ) ) {
|
1146 |
+
$restorer->run_by_id( $task->get_data( 'backup_id' ) );
|
1147 |
+
$archive_info = $restorer->get_info();
|
1148 |
+
} else {
|
1149 |
+
$archive_info = [
|
1150 |
+
'error' => __( 'Restore error: Missing url / id.', 'boldgrid-backup' ),
|
1151 |
+
];
|
1152 |
+
}
|
1153 |
+
} else {
|
1154 |
+
if ( $this->core->restore_helper->prepare_restore() ) {
|
1155 |
+
$archive_info = $this->core->restore_archive_file();
|
1156 |
+
}
|
1157 |
}
|
1158 |
|
1159 |
return $archive_info;
|
admin/class-boldgrid-backup-admin-go-pro.php
CHANGED
@@ -197,6 +197,16 @@ class Boldgrid_Backup_Admin_Go_Pro {
|
|
197 |
public function get_premium_url( $source = 'bgbkup', $url = 'https://www.boldgrid.com/update-backup' ) {
|
198 |
$url = add_query_arg( 'source', $source, $url );
|
199 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
200 |
return $url;
|
201 |
}
|
202 |
}
|
197 |
public function get_premium_url( $source = 'bgbkup', $url = 'https://www.boldgrid.com/update-backup' ) {
|
198 |
$url = add_query_arg( 'source', $source, $url );
|
199 |
|
200 |
+
/**
|
201 |
+
* Allow the filtering of the premium url.
|
202 |
+
*
|
203 |
+
* @since SINCEVERISON
|
204 |
+
*
|
205 |
+
* @param string $url The url to be filtered.
|
206 |
+
* @param string $source A label (used in the url) to uniquely identify this link.
|
207 |
+
*/
|
208 |
+
$url = apply_filters( 'boldgrid_backup_premium_url', $url, $source );
|
209 |
+
|
210 |
return $url;
|
211 |
}
|
212 |
}
|
admin/class-boldgrid-backup-admin-log.php
CHANGED
@@ -121,7 +121,8 @@ class Boldgrid_Backup_Admin_Log {
|
|
121 |
|
122 |
$this->add( 'WordPress Version: ' . get_bloginfo( 'version' ) );
|
123 |
|
124 |
-
$
|
|
|
125 |
|
126 |
$pgid_support = Boldgrid_Backup_Admin_Test::is_getpgid_supported();
|
127 |
$this->add( 'getpgid support: ' . ( $pgid_support ? 'Available' : 'Unavailable' ) );
|
121 |
|
122 |
$this->add( 'WordPress Version: ' . get_bloginfo( 'version' ) );
|
123 |
|
124 |
+
$version = defined( 'BOLDGRID_BACKUP_VERSION' ) ? BOLDGRID_BACKUP_VERSION : 'Unknown';
|
125 |
+
$this->add( 'Total Upkeep version: ' . $version );
|
126 |
|
127 |
$pgid_support = Boldgrid_Backup_Admin_Test::is_getpgid_supported();
|
128 |
$this->add( 'getpgid support: ' . ( $pgid_support ? 'Available' : 'Unavailable' ) );
|
admin/class-boldgrid-backup-admin-nopriv.php
ADDED
@@ -0,0 +1,138 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* File: class-boldgrid-backup-admin-nopriv.php
|
4 |
+
*
|
5 |
+
* @link https://www.boldgrid.com
|
6 |
+
* @since SINCEVERSION
|
7 |
+
*
|
8 |
+
* @package Boldgrid_Backup
|
9 |
+
* @subpackage Boldgrid_Backup/admin
|
10 |
+
* @copyright BoldGrid
|
11 |
+
* @version $Id$
|
12 |
+
* @author BoldGrid <support@boldgrid.com>
|
13 |
+
*/
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Class: Boldgrid_Backup_Admin_Nopriv
|
17 |
+
*
|
18 |
+
* This is a generic utility class for nopriv calls.
|
19 |
+
*
|
20 |
+
* It includes methods like making an async call to trigger a backup.
|
21 |
+
*
|
22 |
+
* @since SINCEVERSION
|
23 |
+
*/
|
24 |
+
class Boldgrid_Backup_Admin_Nopriv {
|
25 |
+
/**
|
26 |
+
* Generate a backup.
|
27 |
+
*
|
28 |
+
* This makes an async call to generate a backup, so that the calling method knows a backup has
|
29 |
+
* been instantiated and can continue on to other things right away.
|
30 |
+
*
|
31 |
+
* @since SINCEVERSION
|
32 |
+
*
|
33 |
+
* @param array $args {
|
34 |
+
* Optional. An array of args.
|
35 |
+
*
|
36 |
+
* @type string $task_id A task id (if one already exists).
|
37 |
+
* }
|
38 |
+
* @return mixed The results of the wp_remote_post call. An array of data on success, or a WP_Error
|
39 |
+
* on fail.
|
40 |
+
* Example return data when creating a backup via rest: https://pastebin.com/BeACwA2k
|
41 |
+
*/
|
42 |
+
public function do_backup( $args = [] ) {
|
43 |
+
$url = $this->get_backup_url();
|
44 |
+
|
45 |
+
$body = [
|
46 |
+
/*
|
47 |
+
* Sometimes a task id will already be defined before the backup is started. One example
|
48 |
+
* is when a backup is started via REST. It (1) creates a task, (2) calls this method to
|
49 |
+
* start the backup, (3) immediately returns the tasks id - which a status can be queried
|
50 |
+
* for ASAP.
|
51 |
+
*/
|
52 |
+
'task_id' => ! empty( $args['task_id'] ) ? $args['task_id'] : '',
|
53 |
+
];
|
54 |
+
|
55 |
+
$post_args = [
|
56 |
+
'timeout' => 1,
|
57 |
+
'blocking' => false,
|
58 |
+
'sslverify' => apply_filters( 'https_local_ssl_verify', false ),
|
59 |
+
'body' => $body,
|
60 |
+
];
|
61 |
+
|
62 |
+
return wp_remote_post( $url, $post_args );
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Restore a backup via url.
|
67 |
+
*
|
68 |
+
* @since SINCEVERSION
|
69 |
+
*
|
70 |
+
* @param array $args An optional array of args.
|
71 |
+
* @return mixed Response from wp_remote_post.
|
72 |
+
*/
|
73 |
+
public function do_restore( $args = [] ) {
|
74 |
+
$url = $this->get_restore_url();
|
75 |
+
|
76 |
+
$body = [
|
77 |
+
/*
|
78 |
+
* Sometimes a task id will already be defined before the restore is started. One example
|
79 |
+
* is when a restore is started via REST. It (1) creates a task, (2) calls this method to
|
80 |
+
* start the restore, (3) immediately returns the tasks id - which a status can be queried
|
81 |
+
* for ASAP.
|
82 |
+
*/
|
83 |
+
'task_id' => ! empty( $args['task_id'] ) ? $args['task_id'] : '',
|
84 |
+
'restore_now' => 1,
|
85 |
+
];
|
86 |
+
|
87 |
+
$post_args = [
|
88 |
+
'timeout' => 1,
|
89 |
+
'blocking' => false,
|
90 |
+
'sslverify' => apply_filters( 'https_local_ssl_verify', false ),
|
91 |
+
'body' => $body,
|
92 |
+
];
|
93 |
+
|
94 |
+
return wp_remote_post( $url, $post_args );
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Get the nopriv url for generating a backup.
|
99 |
+
*
|
100 |
+
* @since SINCEVERSION
|
101 |
+
*
|
102 |
+
* @return string
|
103 |
+
*/
|
104 |
+
public function get_backup_url() {
|
105 |
+
$core = apply_filters( 'boldgrid_backup_get_core', null );
|
106 |
+
|
107 |
+
return add_query_arg(
|
108 |
+
[
|
109 |
+
'action' => 'boldgrid_backup_run_backup',
|
110 |
+
'id' => $core->get_backup_identifier(),
|
111 |
+
'secret' => $core->cron->get_cron_secret(),
|
112 |
+
'doing_wp_cron' => time(),
|
113 |
+
],
|
114 |
+
admin_url( 'admin-ajax.php' )
|
115 |
+
);
|
116 |
+
}
|
117 |
+
|
118 |
+
/**
|
119 |
+
* Get the nopriv url for restoring a backup via url.
|
120 |
+
*
|
121 |
+
* @since SINCEVERSION
|
122 |
+
*
|
123 |
+
* @return string
|
124 |
+
*/
|
125 |
+
public function get_restore_url() {
|
126 |
+
$core = apply_filters( 'boldgrid_backup_get_core', null );
|
127 |
+
|
128 |
+
return add_query_arg(
|
129 |
+
[
|
130 |
+
'action' => 'boldgrid_backup_run_restore',
|
131 |
+
'id' => $core->get_backup_identifier(),
|
132 |
+
'secret' => $core->cron->get_cron_secret(),
|
133 |
+
'doing_wp_cron' => time(),
|
134 |
+
],
|
135 |
+
admin_url( 'admin-ajax.php' )
|
136 |
+
);
|
137 |
+
}
|
138 |
+
}
|
admin/class-boldgrid-backup-admin-restore-helper.php
CHANGED
@@ -92,7 +92,7 @@ class Boldgrid_Backup_Admin_Restore_Helper {
|
|
92 |
* @since 1.5.1
|
93 |
*/
|
94 |
public function post_restore_htaccess() {
|
95 |
-
add_action( 'shutdown', 'flush_rewrite_rules' );
|
96 |
}
|
97 |
|
98 |
/**
|
92 |
* @since 1.5.1
|
93 |
*/
|
94 |
public function post_restore_htaccess() {
|
95 |
+
add_action( 'shutdown', '\Boldgrid_Backup_Admin_Utility::flush_rewrite_rules' );
|
96 |
}
|
97 |
|
98 |
/**
|
admin/class-boldgrid-backup-admin-task-helper.php
ADDED
@@ -0,0 +1,124 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* File: class-boldgrid-backup-admin-task-helper.php
|
4 |
+
*
|
5 |
+
* @link https://www.boldgrid.com
|
6 |
+
* @since SINCEVERSION
|
7 |
+
*
|
8 |
+
* @package Boldgrid_Backup
|
9 |
+
* @subpackage Boldgrid_Backup/admin
|
10 |
+
* @copyright BoldGrid
|
11 |
+
* @version $Id$
|
12 |
+
* @author BoldGrid <support@boldgrid.com>
|
13 |
+
*/
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Class: Boldgrid_Backup_Admin_Task_Helper
|
17 |
+
*
|
18 |
+
* This class is a helper class for the Boldgrid_Backup_Admin_Task class.
|
19 |
+
*
|
20 |
+
* An example of tasks can be found here: admin/class-boldgrid-backup-admin-task.md#example-tasks
|
21 |
+
*
|
22 |
+
* @since SINCEVERSION
|
23 |
+
*/
|
24 |
+
class Boldgrid_Backup_Admin_Task_Helper {
|
25 |
+
/**
|
26 |
+
* Option name storing our tasks.
|
27 |
+
*
|
28 |
+
* @since SINCEVERSION
|
29 |
+
* @access private
|
30 |
+
* @var string
|
31 |
+
*/
|
32 |
+
private $option = 'boldgrid_backup_tasks';
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Get a task by id.
|
36 |
+
*
|
37 |
+
* @since SINCEVERSION
|
38 |
+
*
|
39 |
+
* @param string $id A task id.
|
40 |
+
* @return array
|
41 |
+
*/
|
42 |
+
public function get_by_id( $id ) {
|
43 |
+
$return_task = [];
|
44 |
+
|
45 |
+
$tasks = $this->get_tasks();
|
46 |
+
|
47 |
+
foreach ( $tasks as $task ) {
|
48 |
+
if ( $task['id'] === $id ) {
|
49 |
+
$return_task = $task;
|
50 |
+
break;
|
51 |
+
}
|
52 |
+
}
|
53 |
+
|
54 |
+
return $return_task;
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Get all tasks.
|
59 |
+
*
|
60 |
+
* @since SINCEVERSION
|
61 |
+
*
|
62 |
+
* @return array
|
63 |
+
*/
|
64 |
+
public function get_tasks() {
|
65 |
+
return get_option( $this->option, [] );
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Update a task.
|
70 |
+
*
|
71 |
+
* @since SINCEVERSION
|
72 |
+
*
|
73 |
+
* @param array $update_task The task that needs updating.
|
74 |
+
* @return bool True on success.
|
75 |
+
*/
|
76 |
+
public function update( $update_task ) {
|
77 |
+
// A task id is required.
|
78 |
+
if ( empty( $update_task['id'] ) ) {
|
79 |
+
return false;
|
80 |
+
}
|
81 |
+
|
82 |
+
$tasks = $this->get_tasks();
|
83 |
+
|
84 |
+
$existing_task = $this->get_by_id( $update_task['id'] );
|
85 |
+
|
86 |
+
/*
|
87 |
+
* Add our task to $tasks.
|
88 |
+
*
|
89 |
+
* If the task already exists, find it and update it. Otherwise, add it.
|
90 |
+
*/
|
91 |
+
if ( ! empty( $existing_task ) ) {
|
92 |
+
foreach ( $tasks as $key => $task ) {
|
93 |
+
// Keep looking for our task by id until it's found.
|
94 |
+
if ( $task['id'] !== $update_task['id'] ) {
|
95 |
+
continue;
|
96 |
+
}
|
97 |
+
|
98 |
+
// It's been found. Replace the task by the task passed into this method.
|
99 |
+
$tasks[ $key ] = $update_task;
|
100 |
+
break;
|
101 |
+
}
|
102 |
+
} else {
|
103 |
+
// This is a new task. Simply add it to the list.
|
104 |
+
$tasks[] = $update_task;
|
105 |
+
}
|
106 |
+
|
107 |
+
return $this->update_tasks( $tasks );
|
108 |
+
}
|
109 |
+
|
110 |
+
/**
|
111 |
+
* Update all tasks.
|
112 |
+
*
|
113 |
+
* @since SINCEVERSION
|
114 |
+
*
|
115 |
+
* @param array $tasks An array of all our tasks.
|
116 |
+
*/
|
117 |
+
public function update_tasks( $tasks ) {
|
118 |
+
if ( ! is_array( $tasks ) ) {
|
119 |
+
return false;
|
120 |
+
}
|
121 |
+
|
122 |
+
update_option( $this->option, $tasks );
|
123 |
+
}
|
124 |
+
}
|
admin/class-boldgrid-backup-admin-task.md
ADDED
@@ -0,0 +1,129 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Tasks vs. Jobs
|
2 |
+
|
3 |
+
## Jobs
|
4 |
+
|
5 |
+
Jobs is a "jobs queue". The queue is checked every 5 minutes, and if a job is found, it is ran. Each
|
6 |
+
job in the queue is really just a WordPress action/hook that is ran. When it is completed, it is marked
|
7 |
+
as complete. The next time the jobs queue is processed, it will run the next action in line.
|
8 |
+
|
9 |
+
For example, when a backup is made, 2 items may be add to the the jobs queue:
|
10 |
+
1. Upload to Google Drive
|
11 |
+
2. Upload to Amazon S3
|
12 |
+
|
13 |
+
Every 5 minutes the jobs queue is triggered. First, the Google Drive upload will be processed. When
|
14 |
+
it is done, it will be flagged as complete. 5 minutes later, when the queue is processed again, it will
|
15 |
+
find that the Amazon S3 job is next, and it will run the action for that.
|
16 |
+
|
17 |
+
## Tasks
|
18 |
+
|
19 |
+
A tasks is a thing to do, like "make a backup".
|
20 |
+
|
21 |
+
Here's an example of how a task works:
|
22 |
+
|
23 |
+
1. A Rest API call comes in to create a backup. We create a new backup task and then execute it.
|
24 |
+
|
25 |
+
```
|
26 |
+
$task = new Boldgrid_Backup_Admin_Task();
|
27 |
+
$task->init( [ 'type' => 'backup' ] );
|
28 |
+
|
29 |
+
// Trigger our backup.
|
30 |
+
$nopriv = new Boldgrid_Backup_Admin_Nopriv();
|
31 |
+
$nopriv->do_backup( [ 'task_id' => $task->get_id() ] );
|
32 |
+
```
|
33 |
+
|
34 |
+
This new task now has an id, status, a start time, etc.
|
35 |
+
|
36 |
+
2. Let's say that backup takes 5 minutes. Throughout that time, other Rest API calls can request the
|
37 |
+
status of that task. They'll continue to see "in progress" until the backup is complete and then the
|
38 |
+
task status will be "complete".
|
39 |
+
|
40 |
+
## The Difference
|
41 |
+
|
42 |
+
Jobs is a collection of jobs:
|
43 |
+
|
44 |
+
```
|
45 |
+
jobs queue
|
46 |
+
1. job
|
47 |
+
2. job
|
48 |
+
3. job
|
49 |
+
```
|
50 |
+
|
51 |
+
Theoretically, it could look like this (but it doesn't):
|
52 |
+
|
53 |
+
```
|
54 |
+
jobs queue
|
55 |
+
1. task
|
56 |
+
2. task
|
57 |
+
3. task
|
58 |
+
```
|
59 |
+
|
60 |
+
Tasks were written ~2 or so years after the jobs queue was written, and are completely independent.
|
61 |
+
While a task and a job could be the same, the only similarities within Total Upkeep is that they represent
|
62 |
+
an action, and have things like a start time, a status, etc.
|
63 |
+
|
64 |
+
Jobs are a wordpress action/hook and belong to the jobs queue. Tasks are independent and could potentially
|
65 |
+
float around the system. Tasks are really just a tracking system for things to do.
|
66 |
+
|
67 |
+
# Example tasks
|
68 |
+
|
69 |
+
```
|
70 |
+
wp option get boldgrid_backup_tasks
|
71 |
+
array (
|
72 |
+
0 => array (
|
73 |
+
'id' => '1597861098-2e90c6',
|
74 |
+
'type' => 'backup',
|
75 |
+
'created_at' => 1597861098,
|
76 |
+
'started_at' => 1597861098,
|
77 |
+
'completed_at' => 1597861109,
|
78 |
+
'status' => 'done',
|
79 |
+
'data' => array (),
|
80 |
+
),
|
81 |
+
1 => array (
|
82 |
+
'id' => '1597861521-1b2848',
|
83 |
+
'type' => 'backup',
|
84 |
+
'created_at' => 1597861521,
|
85 |
+
'started_at' => 1597861522,
|
86 |
+
'completed_at' => 1597861527,
|
87 |
+
'status' => 'done',
|
88 |
+
'data' => array(),
|
89 |
+
),
|
90 |
+
2 => array (
|
91 |
+
'id' => '1598616953-986059',
|
92 |
+
'type' => 'backup',
|
93 |
+
'created_at' => 1598616953,
|
94 |
+
'started_at' => 1598616954,
|
95 |
+
'completed_at' => 1598616959,
|
96 |
+
'status' => 'done',
|
97 |
+
'data' => array(),
|
98 |
+
),
|
99 |
+
3 => array (
|
100 |
+
'id' => '1598617517-e6f0a3',
|
101 |
+
'type' => 'backup',
|
102 |
+
'created_at' => 1598617517,
|
103 |
+
'started_at' => 1598617518,
|
104 |
+
'completed_at' => 1598617523,
|
105 |
+
'status' => 'done',
|
106 |
+
'data' => array(),
|
107 |
+
),
|
108 |
+
4 => array (
|
109 |
+
'id' => '1598619019-8d3da6',
|
110 |
+
'type' => 'backup',
|
111 |
+
'created_at' => 1598619019,
|
112 |
+
'started_at' => 1598619020,
|
113 |
+
'completed_at' => NULL,
|
114 |
+
'status' => 'in_progress',
|
115 |
+
'data' => array(),
|
116 |
+
),
|
117 |
+
5 => array (
|
118 |
+
'id' => '1598619948-985ee2',
|
119 |
+
'type' => 'restore',
|
120 |
+
'created_at' => '2020-08-28T13:05:48+00:00',
|
121 |
+
'started_at' => 1598619949,
|
122 |
+
'completed_at' => 1598619951,
|
123 |
+
'status' => 'done',
|
124 |
+
'data' => array (
|
125 |
+
'backup_id' => '4',
|
126 |
+
),
|
127 |
+
),
|
128 |
+
)
|
129 |
+
```
|
admin/class-boldgrid-backup-admin-task.php
ADDED
@@ -0,0 +1,297 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* File: class-boldgrid-backup-admin-task.php
|
4 |
+
*
|
5 |
+
* @link https://www.boldgrid.com
|
6 |
+
* @since SINCEVERSION
|
7 |
+
*
|
8 |
+
* @package Boldgrid_Backup
|
9 |
+
* @subpackage Boldgrid_Backup/admin
|
10 |
+
* @copyright BoldGrid
|
11 |
+
* @version $Id$
|
12 |
+
* @author BoldGrid <support@boldgrid.com>
|
13 |
+
*/
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Class: Boldgrid_Backup_Admin_Task
|
17 |
+
*
|
18 |
+
* Tasks are similar to the jobs queue, but not quite the same. Please see class-boldgrid-backup-admin-task.md
|
19 |
+
*
|
20 |
+
* @since SINCEVERSION
|
21 |
+
*
|
22 |
+
* @todo Look into merging tasks with the jobs queue.
|
23 |
+
*/
|
24 |
+
class Boldgrid_Backup_Admin_Task {
|
25 |
+
/**
|
26 |
+
* A date format used in returning times.
|
27 |
+
*
|
28 |
+
* For example, 'c' in date( 'c', time() ).
|
29 |
+
*
|
30 |
+
* @since SINCEVERSION
|
31 |
+
* @var string
|
32 |
+
*/
|
33 |
+
public $date_format;
|
34 |
+
|
35 |
+
/**
|
36 |
+
* The time this task was completed.
|
37 |
+
*
|
38 |
+
* @since SINCEVERSION
|
39 |
+
* @access private
|
40 |
+
* @var int
|
41 |
+
*/
|
42 |
+
private $completed_at;
|
43 |
+
|
44 |
+
/**
|
45 |
+
* The time this task was created.
|
46 |
+
*
|
47 |
+
* @since SINCEVERSION
|
48 |
+
* @access private
|
49 |
+
* @var int
|
50 |
+
*/
|
51 |
+
private $created_at;
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Misc data associated with this task.
|
55 |
+
*
|
56 |
+
* @since SINCEVERSION
|
57 |
+
* @access private
|
58 |
+
* @var array
|
59 |
+
*/
|
60 |
+
private $data;
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Our helper class.
|
64 |
+
*
|
65 |
+
* @since SINCEVERSION
|
66 |
+
* @access private
|
67 |
+
* @var Boldgrid_Backup_Admin_Task_Helper
|
68 |
+
*/
|
69 |
+
private $helper;
|
70 |
+
|
71 |
+
/**
|
72 |
+
* The task id.
|
73 |
+
*
|
74 |
+
* @since SINCEVERSION
|
75 |
+
* @access private
|
76 |
+
* @var string
|
77 |
+
*/
|
78 |
+
private $id;
|
79 |
+
|
80 |
+
/**
|
81 |
+
* The time this task was started.
|
82 |
+
*
|
83 |
+
* @since SINCEVERSION
|
84 |
+
* @access private
|
85 |
+
* @var int
|
86 |
+
*/
|
87 |
+
private $started_at;
|
88 |
+
|
89 |
+
/**
|
90 |
+
* The task type.
|
91 |
+
*
|
92 |
+
* For example: backup
|
93 |
+
*
|
94 |
+
* @since SINCEVERSION
|
95 |
+
* @access private
|
96 |
+
* @var string
|
97 |
+
*/
|
98 |
+
private $type;
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Constructor.
|
102 |
+
*
|
103 |
+
* @since SINCEVERSION
|
104 |
+
*/
|
105 |
+
public function __construct() {
|
106 |
+
$this->helper = new Boldgrid_Backup_Admin_Task_Helper();
|
107 |
+
}
|
108 |
+
|
109 |
+
/**
|
110 |
+
* Mark this task as being complete.
|
111 |
+
*
|
112 |
+
* @since SINCEVERSION
|
113 |
+
*/
|
114 |
+
public function end() {
|
115 |
+
$this->completed_at = time();
|
116 |
+
|
117 |
+
$this->update();
|
118 |
+
}
|
119 |
+
|
120 |
+
/**
|
121 |
+
* Get the properties of this class.
|
122 |
+
*
|
123 |
+
* @since SINCEVERSION
|
124 |
+
*
|
125 |
+
* @return array
|
126 |
+
*/
|
127 |
+
public function get() {
|
128 |
+
return [
|
129 |
+
'id' => $this->id,
|
130 |
+
'type' => $this->type,
|
131 |
+
'created_at' => empty( $this->date_format ) ? $this->created_at : date( $this->date_format, $this->created_at ),
|
132 |
+
'started_at' => empty( $this->started_at ) ?
|
133 |
+
null :
|
134 |
+
( empty( $this->date_format ) ? $this->started_at : date( $this->date_format, $this->started_at ) ),
|
135 |
+
'completed_at' => empty( $this->completed_at ) ?
|
136 |
+
null :
|
137 |
+
( empty( $this->date_format ) ? $this->completed_at : date( $this->date_format, $this->completed_at ) ),
|
138 |
+
'status' => $this->get_status(),
|
139 |
+
'data' => $this->data,
|
140 |
+
];
|
141 |
+
}
|
142 |
+
|
143 |
+
/**
|
144 |
+
* Get a specific value from the data.
|
145 |
+
*
|
146 |
+
* @since SINCEVERSION
|
147 |
+
*
|
148 |
+
* @param string $key The key to get.
|
149 |
+
* @param mixed $default The default value to return.
|
150 |
+
* @return mixed
|
151 |
+
*/
|
152 |
+
public function get_data( $key, $default = false ) {
|
153 |
+
return isset( $this->data[ $key ] ) ? $this->data[ $key ] : $default;
|
154 |
+
}
|
155 |
+
|
156 |
+
/**
|
157 |
+
* Get our task id.
|
158 |
+
*
|
159 |
+
* @since SINCEVERSION
|
160 |
+
*
|
161 |
+
* @return string
|
162 |
+
*/
|
163 |
+
public function get_id() {
|
164 |
+
return $this->id;
|
165 |
+
}
|
166 |
+
|
167 |
+
/**
|
168 |
+
* Get the status of this task.
|
169 |
+
*
|
170 |
+
* @since SINCEVERSION
|
171 |
+
*
|
172 |
+
* @return string
|
173 |
+
*/
|
174 |
+
public function get_status() {
|
175 |
+
if ( empty( $this->started_at ) ) {
|
176 |
+
$status = 'pending';
|
177 |
+
} elseif ( empty( $this->completed_at ) ) {
|
178 |
+
$status = 'in_progress';
|
179 |
+
} else {
|
180 |
+
$status = 'done';
|
181 |
+
}
|
182 |
+
|
183 |
+
return $status;
|
184 |
+
}
|
185 |
+
|
186 |
+
/**
|
187 |
+
* Initialize a new task.
|
188 |
+
*
|
189 |
+
* @since SINCEVERSION
|
190 |
+
*
|
191 |
+
* @param array $args An array of args.
|
192 |
+
* @return bool True if this task was initialized.
|
193 |
+
*/
|
194 |
+
public function init( $args ) {
|
195 |
+
$this->id = ! empty( $args['id'] ) ? $args['id'] : $this->set_id();
|
196 |
+
$this->created_at = ! empty( $args['created_at'] ) ? $args['created_at'] : time();
|
197 |
+
$this->started_at = ! empty( $args['started_at'] ) ? $args['started_at'] : null;
|
198 |
+
$this->completed_at = ! empty( $args['completed_at'] ) ? $args['completed_at'] : null;
|
199 |
+
$this->data = ! empty( $args['data'] ) ? $args['data'] : [];
|
200 |
+
|
201 |
+
// You must supply a type.
|
202 |
+
$type = ! empty( $args['type'] ) ? $args['type'] : null;
|
203 |
+
if ( empty( $type ) ) {
|
204 |
+
return false;
|
205 |
+
} elseif ( ! $this->set_type( $type ) ) {
|
206 |
+
return false;
|
207 |
+
}
|
208 |
+
|
209 |
+
return true;
|
210 |
+
}
|
211 |
+
|
212 |
+
/**
|
213 |
+
* Init this task by a task id.
|
214 |
+
*
|
215 |
+
* @since SINCEVERSION
|
216 |
+
*
|
217 |
+
* @param string $id A task id.
|
218 |
+
* @return bool True if this task was initialized.
|
219 |
+
*/
|
220 |
+
public function init_by_id( $id ) {
|
221 |
+
$task = $this->helper->get_by_id( $id );
|
222 |
+
|
223 |
+
return empty( $task ) ? false : $this->init( $task );
|
224 |
+
}
|
225 |
+
|
226 |
+
|
227 |
+
/**
|
228 |
+
* Create a new task id.
|
229 |
+
*
|
230 |
+
* @since SINCEVERSION
|
231 |
+
*
|
232 |
+
* @return string
|
233 |
+
*/
|
234 |
+
private function set_id() {
|
235 |
+
// A task id is the current time + 6 random chars.
|
236 |
+
$this->id = time() . '-' . substr( md5( time() ), -6 );
|
237 |
+
|
238 |
+
return $this->id;
|
239 |
+
}
|
240 |
+
|
241 |
+
/**
|
242 |
+
* Set our task type.
|
243 |
+
*
|
244 |
+
* @since SINCEVERSION
|
245 |
+
*
|
246 |
+
* @param string $type Our task type.
|
247 |
+
* @return bool True if the type was set.
|
248 |
+
*/
|
249 |
+
private function set_type( $type ) {
|
250 |
+
$valid_types = [
|
251 |
+
'backup',
|
252 |
+
'restore',
|
253 |
+
];
|
254 |
+
|
255 |
+
if ( ! in_array( $type, $valid_types, true ) ) {
|
256 |
+
return false;
|
257 |
+
}
|
258 |
+
|
259 |
+
$this->type = $type;
|
260 |
+
|
261 |
+
return true;
|
262 |
+
}
|
263 |
+
|
264 |
+
/**
|
265 |
+
* Start this task.
|
266 |
+
*
|
267 |
+
* @since SINCEVERSION
|
268 |
+
*/
|
269 |
+
public function start() {
|
270 |
+
$this->started_at = time();
|
271 |
+
|
272 |
+
$this->update();
|
273 |
+
}
|
274 |
+
|
275 |
+
/**
|
276 |
+
* Update data for a task.
|
277 |
+
*
|
278 |
+
* @since SINCEVERSION
|
279 |
+
*
|
280 |
+
* @param string key The key to update.
|
281 |
+
* @param mixed $value The value to assign to the key.
|
282 |
+
*/
|
283 |
+
public function update_data( $key, $value ) {
|
284 |
+
$this->data[ $key ] = $value;
|
285 |
+
|
286 |
+
$this->update();
|
287 |
+
}
|
288 |
+
|
289 |
+
/**
|
290 |
+
* Update / save this task.
|
291 |
+
*
|
292 |
+
* @since SINCEVERSION
|
293 |
+
*/
|
294 |
+
public function update() {
|
295 |
+
return $this->helper->update( $this->get() );
|
296 |
+
}
|
297 |
+
}
|
admin/class-boldgrid-backup-admin-test.php
CHANGED
@@ -526,6 +526,12 @@ class Boldgrid_Backup_Admin_Test {
|
|
526 |
return false;
|
527 |
}
|
528 |
|
|
|
|
|
|
|
|
|
|
|
|
|
529 |
self::$is_getpgid_supported = false !== posix_getpgid( $pid );
|
530 |
|
531 |
return self::$is_getpgid_supported;
|
526 |
return false;
|
527 |
}
|
528 |
|
529 |
+
// posix_getpgid() may not be available in all environments. Win 10 user running xampp for example.
|
530 |
+
if ( ! function_exists( 'posix_getpgid' ) ) {
|
531 |
+
self::$is_getpgid_supported = false;
|
532 |
+
return false;
|
533 |
+
}
|
534 |
+
|
535 |
self::$is_getpgid_supported = false !== posix_getpgid( $pid );
|
536 |
|
537 |
return self::$is_getpgid_supported;
|
admin/class-boldgrid-backup-admin-upload.php
CHANGED
@@ -424,126 +424,16 @@ class Boldgrid_Backup_Admin_Upload {
|
|
424 |
);
|
425 |
}
|
426 |
|
427 |
-
$url
|
428 |
-
$url_regex = '/' . $this->core->configs['url_regex'] . '/i';
|
429 |
|
430 |
-
|
431 |
-
|
432 |
-
array(
|
433 |
-
'error' => __( 'Invalid URL address.', 'boldgrid-backup' ),
|
434 |
-
)
|
435 |
-
);
|
436 |
-
}
|
437 |
-
|
438 |
-
$backup_directory = $this->core->backup_dir->get();
|
439 |
-
|
440 |
-
if ( ! $this->core->backup_dir->is_valid( $backup_directory ) &&
|
441 |
-
! empty( $this->core->backup_dir->errors ) ) {
|
442 |
-
wp_send_json_error(
|
443 |
-
array(
|
444 |
-
'error' => implode( '<br />', $this->core->backup_dir->errors ),
|
445 |
-
)
|
446 |
-
);
|
447 |
-
}
|
448 |
-
|
449 |
-
$filepath = $this->get_save_path( basename( $url ) );
|
450 |
-
|
451 |
-
$allowed_content_types = array(
|
452 |
-
'application/octet-stream',
|
453 |
-
'binary/octet-stream',
|
454 |
-
'application/zip',
|
455 |
-
);
|
456 |
-
|
457 |
-
$response = wp_remote_get(
|
458 |
-
$url, array(
|
459 |
-
'filename' => $filepath,
|
460 |
-
'headers' => 'Accept: ' . implode( ', ', $allowed_content_types ),
|
461 |
-
'sslverify' => false,
|
462 |
-
'stream' => true,
|
463 |
-
'timeout' => MINUTE_IN_SECONDS * 20,
|
464 |
-
)
|
465 |
-
);
|
466 |
-
|
467 |
-
if ( is_array( $response ) && ! is_wp_error( $response ) &&
|
468 |
-
in_array( $response['headers']['content-type'], $allowed_content_types, true ) ) {
|
469 |
-
$logger->add( 'Archive downloaded successfully.' );
|
470 |
-
$logger->add( 'Headers: ' . ( empty( $response['headers'] ) ? 'Empty' : print_r( $response['headers'], 1 ) ) ); // phpcs:ignore
|
471 |
-
|
472 |
-
// Determine the archive log file path.
|
473 |
-
$log_filepath = $filepath;
|
474 |
-
|
475 |
-
if ( ! empty( $response['headers']['content-disposition'] ) ) {
|
476 |
-
$log_filepath = trim(
|
477 |
-
str_replace(
|
478 |
-
'attachment; filename=', '', $response['headers']['content-disposition']
|
479 |
-
), '"'
|
480 |
-
);
|
481 |
-
|
482 |
-
$log_filepath = $this->core->backup_dir->get_path_to( $log_filepath );
|
483 |
-
}
|
484 |
-
|
485 |
-
$log_filepath = $this->core->archive_log->path_from_zip( $log_filepath );
|
486 |
-
$filename = basename( $filepath );
|
487 |
-
|
488 |
-
// Restore the log file from the archive.
|
489 |
-
$restored = $this->core->archive_log->restore_by_zip( $filepath, basename( $log_filepath ) );
|
490 |
-
$logger->add( 'Log restored from zip: ' . ( $restored ? 'Success' : 'Fail' ) );
|
491 |
-
|
492 |
-
// Update the archive file modification time, based on the log file contents.
|
493 |
-
$this->core->remote->post_download( $filepath );
|
494 |
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
wp_send_json_success(
|
499 |
-
[
|
500 |
-
'filepath' => $filepath,
|
501 |
-
'detailsUrl' => admin_url(
|
502 |
-
'admin.php?page=boldgrid-backup-archive-details&filename=' .
|
503 |
-
basename( $filepath )
|
504 |
-
),
|
505 |
-
'archiveFilename' => $filename,
|
506 |
-
'archiveKey' => $archive['key'],
|
507 |
-
]
|
508 |
-
);
|
509 |
-
} else {
|
510 |
-
// Get the data from the $response that we want to print to the log.
|
511 |
-
// @todo simply the below.
|
512 |
-
if ( is_wp_error( $response ) ) {
|
513 |
-
$log_data = $response;
|
514 |
-
} elseif ( is_array( $response ) ) {
|
515 |
-
$log_data = array();
|
516 |
-
|
517 |
-
if ( ! empty( $response['body'] ) ) {
|
518 |
-
$log_data['body'] = $response['body'];
|
519 |
-
}
|
520 |
-
if ( ! empty( $response['response'] ) ) {
|
521 |
-
$log_data['response'] = $response['response'];
|
522 |
-
}
|
523 |
-
}
|
524 |
-
|
525 |
-
$logger->add( 'Failed to download archive. Additional info: ' . print_r( $log_data, 1 ) ); // phpcs:ignore
|
526 |
-
$this->core->wp_filesystem->delete( $filepath );
|
527 |
-
}
|
528 |
-
|
529 |
-
// Determine the error message the user will see and return it.
|
530 |
-
$error_message = __( 'Could not retrieve the remote file.', 'boldgrid-backup' );
|
531 |
-
if ( is_wp_error( $response ) ) {
|
532 |
-
// Example: cURL error 28: Connection timed out after 100001 milliseconds.
|
533 |
-
$error_message .= ' ' . $response->get_error_message();
|
534 |
-
} elseif ( ! empty( $response['response']['code'] && ! empty( $response['response']['message'] ) ) ) {
|
535 |
-
// Example: 403 Forbidden
|
536 |
-
$error_message .= ' ' . $response['response']['code'] . ' ' . $response['response']['message'];
|
537 |
} else {
|
538 |
-
|
539 |
-
$error_message .= ' ' . __( 'Unknown error. It may not be a ZIP file, or the link is no longer valid.', 'boldgrid-backup' );
|
540 |
}
|
541 |
-
|
542 |
-
wp_send_json_error(
|
543 |
-
[
|
544 |
-
'error' => $error_message,
|
545 |
-
]
|
546 |
-
);
|
547 |
}
|
548 |
|
549 |
/**
|
424 |
);
|
425 |
}
|
426 |
|
427 |
+
$url = ! empty( $_POST['url'] ) ? esc_url_raw( $_POST['url'] ) : null;
|
|
|
428 |
|
429 |
+
$archive_fetcher = new Boldgrid_Backup_Archive_Fetcher( $url );
|
430 |
+
$archive_fetcher->download();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
431 |
|
432 |
+
if ( $archive_fetcher->has_error() ) {
|
433 |
+
wp_send_json_error( [ 'error' => $archive_fetcher->get_error() ] );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
434 |
} else {
|
435 |
+
wp_send_json_success( $archive_fetcher->get_info() );
|
|
|
436 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
437 |
}
|
438 |
|
439 |
/**
|
admin/class-boldgrid-backup-admin-utility.php
CHANGED
@@ -94,6 +94,40 @@ class Boldgrid_Backup_Admin_Utility {
|
|
94 |
return $site_id;
|
95 |
}
|
96 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
97 |
/**
|
98 |
* Custom error handler.
|
99 |
*
|
@@ -323,6 +357,42 @@ class Boldgrid_Backup_Admin_Utility {
|
|
323 |
return true;
|
324 |
}
|
325 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
326 |
/**
|
327 |
* Increase the PHP max execution time.
|
328 |
*
|
@@ -723,6 +793,27 @@ class Boldgrid_Backup_Admin_Utility {
|
|
723 |
return true;
|
724 |
}
|
725 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
726 |
/**
|
727 |
* Replace the siteurl in the WordPress database.
|
728 |
*
|
@@ -733,103 +824,96 @@ class Boldgrid_Backup_Admin_Utility {
|
|
733 |
*
|
734 |
* @static
|
735 |
*
|
736 |
-
* @param
|
737 |
-
*
|
|
|
|
|
|
|
|
|
|
|
738 |
* @return bool
|
739 |
*/
|
740 |
-
public static function update_siteurl( $
|
741 |
-
|
742 |
-
|
|
|
743 |
|
744 |
-
|
745 |
-
|
|
|
|
|
|
|
746 |
return false;
|
747 |
}
|
748 |
-
|
749 |
-
// Validate the new siteurl.
|
750 |
-
if ( false === filter_var( $new_siteurl, FILTER_VALIDATE_URL, $filter_options ) ) {
|
751 |
return false;
|
752 |
}
|
753 |
|
754 |
-
|
|
|
|
|
|
|
|
|
|
|
755 |
$old_siteurl = untrailingslashit( $old_siteurl );
|
756 |
$new_siteurl = untrailingslashit( $new_siteurl );
|
757 |
|
758 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
759 |
remove_all_filters( 'pre_update_option_siteurl' );
|
760 |
|
761 |
-
// Update the WP otion "siteurl".
|
762 |
update_option( 'siteurl', $new_siteurl );
|
763 |
-
|
764 |
-
|
765 |
-
|
766 |
-
|
767 |
-
|
768 |
-
|
769 |
-
|
770 |
-
|
771 |
-
|
772 |
-
|
773 |
-
|
774 |
-
|
775 |
-
'
|
776 |
-
|
777 |
-
|
778 |
-
|
779 |
-
|
780 |
-
)
|
781 |
-
)
|
782 |
);
|
783 |
|
|
|
|
|
|
|
|
|
784 |
// Check if the upload_url_path needs to be updated.
|
785 |
$upload_url_path = get_option( 'upload_url_path' );
|
786 |
-
|
787 |
if ( ! empty( $upload_url_path ) ) {
|
788 |
$upload_url_path = str_replace( $old_siteurl, $new_siteurl, $upload_url_path );
|
789 |
-
|
790 |
update_option( 'upload_url_path', $upload_url_path );
|
791 |
}
|
792 |
|
793 |
-
|
794 |
-
|
795 |
-
|
796 |
-
|
797 |
-
|
798 |
-
|
799 |
-
|
800 |
-
|
801 |
-
|
802 |
-
|
803 |
-
|
804 |
-
|
805 |
-
);
|
806 |
-
|
807 |
-
// phpcs:enable WordPress.DB.PreparedSQLPlaceholders
|
808 |
-
|
809 |
-
// If there are no matches options, then return.
|
810 |
-
if ( ! $matched_options ) {
|
811 |
-
return true;
|
812 |
-
}
|
813 |
-
|
814 |
-
// Replace the siteurl in matched options.
|
815 |
-
foreach ( $matched_options as $option_name ) {
|
816 |
-
$option_value = get_option( $option_name[0] );
|
817 |
-
|
818 |
-
// Replace siteurl.
|
819 |
-
$option_value = self::str_replace_recursive(
|
820 |
-
$old_siteurl,
|
821 |
-
$new_siteurl,
|
822 |
-
$option_value
|
823 |
-
);
|
824 |
-
|
825 |
-
// Replace siteurl escaped with slashes.
|
826 |
-
$option_value = self::str_replace_recursive(
|
827 |
-
addslashes( $old_siteurl ),
|
828 |
-
addslashes( $new_siteurl ),
|
829 |
-
$option_value
|
830 |
-
);
|
831 |
-
|
832 |
-
update_option( $option_name[0], $option_value );
|
833 |
}
|
834 |
|
835 |
return true;
|
94 |
return $site_id;
|
95 |
}
|
96 |
|
97 |
+
/**
|
98 |
+
* Database find and replace.
|
99 |
+
*
|
100 |
+
* Take note we also have self::option_find_replace that does a find and replace specific to option
|
101 |
+
* values because they are serialized. It uses self::str_replace_recursive.
|
102 |
+
*
|
103 |
+
* @since SINCEVERSION
|
104 |
+
*
|
105 |
+
* @param string $table
|
106 |
+
* @param string $column
|
107 |
+
* @param string $find
|
108 |
+
* @param string $replace
|
109 |
+
*/
|
110 |
+
public static function db_find_replace( $table, $column, $find, $replace ) {
|
111 |
+
global $wpdb;
|
112 |
+
|
113 |
+
// phpcs:disable WordPress.DB.PreparedSQLPlaceholders.UnquotedComplexPlaceholder, WordPress.DB.PreparedSQLPlaceholders.LikeWildcardsInQuery
|
114 |
+
$wpdb->query(
|
115 |
+
$wpdb->prepare(
|
116 |
+
'UPDATE `' . $wpdb->prefix . '%1$s`
|
117 |
+
SET `%2$s` = REPLACE( `%3$s`, "%4$s", "%5$s" )
|
118 |
+
WHERE `%6$s` LIKE "%%%7$s%%";',
|
119 |
+
$table,
|
120 |
+
$column,
|
121 |
+
$column,
|
122 |
+
$find,
|
123 |
+
$replace,
|
124 |
+
$column,
|
125 |
+
$wpdb->esc_like( $find )
|
126 |
+
)
|
127 |
+
);
|
128 |
+
// phpcs:enable
|
129 |
+
}
|
130 |
+
|
131 |
/**
|
132 |
* Custom error handler.
|
133 |
*
|
357 |
return true;
|
358 |
}
|
359 |
|
360 |
+
/**
|
361 |
+
* Find and replace for option values.
|
362 |
+
*
|
363 |
+
* Similar to self::db_find_replace. This one is special however because it ends up using
|
364 |
+
* self::str_replace_recursive for the replacement mechanism.
|
365 |
+
*
|
366 |
+
* @since SINCEVERSION
|
367 |
+
*
|
368 |
+
* @param string $find
|
369 |
+
* @param string $replace
|
370 |
+
*/
|
371 |
+
public static function option_find_replace( $find, $replace ) {
|
372 |
+
global $wpdb;
|
373 |
+
|
374 |
+
$matched_options = $wpdb->get_results(
|
375 |
+
$wpdb->prepare(
|
376 |
+
'SELECT `option_name`
|
377 |
+
FROM `' . $wpdb->prefix . 'options`
|
378 |
+
WHERE `option_value` LIKE %s;',
|
379 |
+
'%' . $wpdb->esc_like( $find ) . '%'
|
380 |
+
),
|
381 |
+
ARRAY_N
|
382 |
+
);
|
383 |
+
|
384 |
+
if ( empty( $matched_options ) ) {
|
385 |
+
return;
|
386 |
+
}
|
387 |
+
|
388 |
+
foreach ( $matched_options as $option_name ) {
|
389 |
+
$option_value = get_option( $option_name[0] );
|
390 |
+
$option_value = self::str_replace_recursive( $find, $replace, $option_value );
|
391 |
+
|
392 |
+
update_option( $option_name[0], $option_value );
|
393 |
+
}
|
394 |
+
}
|
395 |
+
|
396 |
/**
|
397 |
* Increase the PHP max execution time.
|
398 |
*
|
793 |
return true;
|
794 |
}
|
795 |
|
796 |
+
/**
|
797 |
+
* A wrapper for WordPress' flush_rewrite_rules.
|
798 |
+
*
|
799 |
+
* Wrapper function is necessary because rewriting the .htaccess only works if the
|
800 |
+
* save_mod_rewrite_rules() function exists, which only does in admin. This method ensures it's
|
801 |
+
* there.
|
802 |
+
*
|
803 |
+
* @link https://core.trac.wordpress.org/ticket/51805
|
804 |
+
*
|
805 |
+
* @param bool $hard Whether to update .htaccess (hard flush) or just update rewrite_rules option
|
806 |
+
* (soft flush).
|
807 |
+
*/
|
808 |
+
public static function flush_rewrite_rules( $hard = true ) {
|
809 |
+
// A requirement for rewriting the .htaccess file.
|
810 |
+
if ( $hard && ! function_exists( 'save_mod_rewrite_rules' ) ) {
|
811 |
+
require_once ABSPATH . 'wp-admin/includes/misc.php';
|
812 |
+
}
|
813 |
+
|
814 |
+
flush_rewrite_rules( $hard );
|
815 |
+
}
|
816 |
+
|
817 |
/**
|
818 |
* Replace the siteurl in the WordPress database.
|
819 |
*
|
824 |
*
|
825 |
* @static
|
826 |
*
|
827 |
+
* @param array $args {
|
828 |
+
* An array of arguments.
|
829 |
+
*
|
830 |
+
* @type string $old_siteurl The old/restored siteurl to find and be replaced.
|
831 |
+
* @type string $siteurl The siteurl to replace the old siteurl.
|
832 |
+
* @type bool $flush Whether or not to flush the rewrite rules.
|
833 |
+
* }
|
834 |
* @return bool
|
835 |
*/
|
836 |
+
public static function update_siteurl( $args = array() ) {
|
837 |
+
wp_parse_args( $args, array(
|
838 |
+
'flush' => false,
|
839 |
+
) );
|
840 |
|
841 |
+
$old_siteurl = $args['old_siteurl'];
|
842 |
+
$new_siteurl = $args['siteurl'];
|
843 |
+
|
844 |
+
// Validate.
|
845 |
+
if ( false === filter_var( $old_siteurl, FILTER_VALIDATE_URL ) ) {
|
846 |
return false;
|
847 |
}
|
848 |
+
if ( false === filter_var( $new_siteurl, FILTER_VALIDATE_URL ) ) {
|
|
|
|
|
849 |
return false;
|
850 |
}
|
851 |
|
852 |
+
/*
|
853 |
+
* Ensure the site url does not end in a trailing slash.
|
854 |
+
*
|
855 |
+
* This is best practice. IE when you manually edit your home / siteurl in the dashboard on
|
856 |
+
* the Settings > General page, WordPress will automatically untrailingslahsit.
|
857 |
+
*/
|
858 |
$old_siteurl = untrailingslashit( $old_siteurl );
|
859 |
$new_siteurl = untrailingslashit( $new_siteurl );
|
860 |
|
861 |
+
/*
|
862 |
+
* Find and replace option values.
|
863 |
+
*
|
864 |
+
* Do this before updating the "siteurl" and "home" via the update_option calls below. Otherwise,
|
865 |
+
* we'll runing into:
|
866 |
+
* # Old url: domain.com
|
867 |
+
* # Requested new url: domain.com/514/514
|
868 |
+
* # Resulting url: domain.com/514/514/514/514
|
869 |
+
*/
|
870 |
+
self::option_find_replace( $old_siteurl, $new_siteurl );
|
871 |
+
|
872 |
remove_all_filters( 'pre_update_option_siteurl' );
|
873 |
|
|
|
874 |
update_option( 'siteurl', $new_siteurl );
|
875 |
+
update_option( 'home', $new_siteurl );
|
876 |
+
|
877 |
+
$replacers = array(
|
878 |
+
// Post content.
|
879 |
+
array(
|
880 |
+
'table' => 'posts',
|
881 |
+
'column' => 'post_content',
|
882 |
+
'find' => $old_siteurl,
|
883 |
+
'replace' => $new_siteurl,
|
884 |
+
),
|
885 |
+
// Custom urls in menus.
|
886 |
+
array(
|
887 |
+
'table' => 'postmeta',
|
888 |
+
'column' => 'meta_value',
|
889 |
+
'find' => $old_siteurl,
|
890 |
+
'replace' => $new_siteurl,
|
891 |
+
),
|
|
|
|
|
892 |
);
|
893 |
|
894 |
+
foreach ( $replacers as $replacer ) {
|
895 |
+
self::db_find_replace( $replacer['table'], $replacer['column'], $replacer['find'], $replacer['replace'] );
|
896 |
+
}
|
897 |
+
|
898 |
// Check if the upload_url_path needs to be updated.
|
899 |
$upload_url_path = get_option( 'upload_url_path' );
|
|
|
900 |
if ( ! empty( $upload_url_path ) ) {
|
901 |
$upload_url_path = str_replace( $old_siteurl, $new_siteurl, $upload_url_path );
|
|
|
902 |
update_option( 'upload_url_path', $upload_url_path );
|
903 |
}
|
904 |
|
905 |
+
/*
|
906 |
+
* If requested (false by default), flush the rewrite rules.
|
907 |
+
*
|
908 |
+
* Why not make this a standard operation? We would except for the fact that the
|
909 |
+
* Boldgrid_Backup_Admin_Restore_Helper class adds the "flush_rewrite_rules" function to the
|
910 |
+
* "shutdown" hook. Does it need to be done at shutdown? Not entirely sure.
|
911 |
+
*
|
912 |
+
* This optional action is helpful when updating the site url outside of a restoration process,
|
913 |
+
* IE a stand alone REST call to update the site url.
|
914 |
+
*/
|
915 |
+
if ( ! empty( $args['flush'] ) ) {
|
916 |
+
self::flush_rewrite_rules();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
917 |
}
|
918 |
|
919 |
return true;
|
admin/class-boldgrid-backup-admin-wp-cron.php
CHANGED
@@ -349,6 +349,7 @@ class Boldgrid_Backup_Admin_WP_Cron {
|
|
349 |
* @since 1.5.1
|
350 |
*/
|
351 |
public function backup() {
|
352 |
-
$
|
|
|
353 |
}
|
354 |
}
|
349 |
* @since 1.5.1
|
350 |
*/
|
351 |
public function backup() {
|
352 |
+
$archiver = new Boldgrid_Backup_Archiver();
|
353 |
+
$archiver->run();
|
354 |
}
|
355 |
}
|
admin/compressor/class-boldgrid-backup-admin-compressor-system-zip.php
CHANGED
@@ -20,6 +20,19 @@
|
|
20 |
* @since 1.13.0
|
21 |
*/
|
22 |
class Boldgrid_Backup_Admin_Compressor_System_Zip extends Boldgrid_Backup_Admin_Compressor {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
/**
|
24 |
* An array of files that should be archived.
|
25 |
*
|
@@ -125,6 +138,8 @@ class Boldgrid_Backup_Admin_Compressor_System_Zip extends Boldgrid_Backup_Admin_
|
|
125 |
* @type bool save 1
|
126 |
* @type int total_size 0
|
127 |
* }
|
|
|
|
|
128 |
*/
|
129 |
public function archive_files( $filelist, &$info ) {
|
130 |
if ( $info['dryrun'] ) {
|
@@ -143,8 +158,9 @@ class Boldgrid_Backup_Admin_Compressor_System_Zip extends Boldgrid_Backup_Admin_
|
|
143 |
|
144 |
Boldgrid_Backup_Admin_In_Progress_Data::set_arg( 'step', 3 );
|
145 |
|
146 |
-
$this->zip();
|
147 |
|
|
|
148 |
$this->zip_sql();
|
149 |
|
150 |
Boldgrid_Backup_Admin_In_Progress_Data::delete_arg( 'step' );
|
@@ -152,7 +168,9 @@ class Boldgrid_Backup_Admin_Compressor_System_Zip extends Boldgrid_Backup_Admin_
|
|
152 |
// Actions to take when we're all done / cleanup.
|
153 |
$this->core->wp_filesystem->delete( $this->filelist_path );
|
154 |
|
155 |
-
return true
|
|
|
|
|
156 |
}
|
157 |
|
158 |
/**
|
@@ -207,6 +225,9 @@ class Boldgrid_Backup_Admin_Compressor_System_Zip extends Boldgrid_Backup_Admin_
|
|
207 |
* Run the command to actually zip the files.
|
208 |
*
|
209 |
* @since 1.13.0
|
|
|
|
|
|
|
210 |
*/
|
211 |
private function zip() {
|
212 |
$this->core->logger->add( 'Starting to close the zip file.' );
|
@@ -214,12 +235,14 @@ class Boldgrid_Backup_Admin_Compressor_System_Zip extends Boldgrid_Backup_Admin_
|
|
214 |
|
215 |
$this->temp_folder->create();
|
216 |
|
217 |
-
$this->close();
|
218 |
|
219 |
$this->temp_folder->delete();
|
220 |
|
221 |
$this->core->logger->add( 'Finished closing the zip file.' );
|
222 |
$this->core->logger->add_memory();
|
|
|
|
|
223 |
}
|
224 |
|
225 |
/**
|
@@ -264,13 +287,21 @@ class Boldgrid_Backup_Admin_Compressor_System_Zip extends Boldgrid_Backup_Admin_
|
|
264 |
|
265 |
foreach ( $filelist_chunks as $filelist_chunk ) {
|
266 |
$chunk_start_time = microtime( true );
|
267 |
-
|
268 |
-
$this->zip_proc( $filelist_chunk );
|
|
|
|
|
|
|
|
|
|
|
269 |
$chunks_closed++;
|
270 |
$percent_complete = round( $chunks_closed / $total_chunks, 2 );
|
271 |
$chunk_end_time = microtime( true );
|
272 |
$close_duration = $chunk_end_time - $chunk_start_time;
|
|
|
273 |
Boldgrid_Backup_Admin_In_Progress_Data::set_arg( 'percent_closed', $percent_complete );
|
|
|
|
|
274 |
$this->core->logger->add(
|
275 |
'Chunk closed in ' .
|
276 |
$close_duration .
|
@@ -279,6 +310,8 @@ class Boldgrid_Backup_Admin_Compressor_System_Zip extends Boldgrid_Backup_Admin_
|
|
279 |
);
|
280 |
$this->core->logger->add_memory();
|
281 |
}
|
|
|
|
|
282 |
}
|
283 |
|
284 |
/**
|
@@ -299,12 +332,19 @@ class Boldgrid_Backup_Admin_Compressor_System_Zip extends Boldgrid_Backup_Admin_
|
|
299 |
* @since 1.14.0
|
300 |
*
|
301 |
* @param array $filelist_chunk Array of Files to be added.
|
|
|
302 |
*/
|
303 |
private function zip_proc( $filelist_chunk ) {
|
|
|
|
|
304 |
$descriptorspec = array(
|
305 |
0 => array( 'pipe', 'r' ), // stdin is a pipe that the child will read from.
|
306 |
1 => array( 'pipe', 'w' ), // stdout is a pipe that the child will write to.
|
307 |
-
|
|
|
|
|
|
|
|
|
308 |
);
|
309 |
|
310 |
$cwd = ABSPATH;
|
@@ -319,11 +359,6 @@ class Boldgrid_Backup_Admin_Compressor_System_Zip extends Boldgrid_Backup_Admin_
|
|
319 |
);
|
320 |
|
321 |
if ( is_resource( $process ) ) {
|
322 |
-
/* $pipes now looks like this:
|
323 |
-
* 0 => writeable handle connected to child stdin
|
324 |
-
* 1 => readable handle connected to child stdout
|
325 |
-
* Any error output will be appended to /tmp/error-output.txt
|
326 |
-
*/
|
327 |
foreach ( $filelist_chunk as $file ) {
|
328 |
fwrite( $pipes[0], $file . "\n" ); //phpcs:ignore WordPress.WP.AlternativeFunctions
|
329 |
}
|
@@ -332,10 +367,23 @@ class Boldgrid_Backup_Admin_Compressor_System_Zip extends Boldgrid_Backup_Admin_
|
|
332 |
|
333 |
fclose( $pipes[1] ); //phpcs:ignore WordPress.WP.AlternativeFunctions
|
334 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
335 |
// It is important that you close any pipes before calling.
|
336 |
// proc_close in order to avoid a deadlock.
|
337 |
proc_close( $process );
|
|
|
|
|
338 |
}
|
|
|
|
|
339 |
}
|
340 |
|
341 |
/**
|
20 |
* @since 1.13.0
|
21 |
*/
|
22 |
class Boldgrid_Backup_Admin_Compressor_System_Zip extends Boldgrid_Backup_Admin_Compressor {
|
23 |
+
/**
|
24 |
+
* An error message.
|
25 |
+
*
|
26 |
+
* If we encounter an error while zipping, the error may be placed here - key phrase "may be placed
|
27 |
+
* here". At the introduction of this class property, it is being used in only one place. The entire
|
28 |
+
* class was not checked and tested to ensure all methods add any errors they run into here.
|
29 |
+
*
|
30 |
+
* @since SINCEVERSION
|
31 |
+
* @access private
|
32 |
+
* @var string
|
33 |
+
*/
|
34 |
+
private $error;
|
35 |
+
|
36 |
/**
|
37 |
* An array of files that should be archived.
|
38 |
*
|
138 |
* @type bool save 1
|
139 |
* @type int total_size 0
|
140 |
* }
|
141 |
+
* @return mixed True on success, an array on failure. This approach has been taken to follow the
|
142 |
+
* standards already set by the pcl-zip and php-zip classes.
|
143 |
*/
|
144 |
public function archive_files( $filelist, &$info ) {
|
145 |
if ( $info['dryrun'] ) {
|
158 |
|
159 |
Boldgrid_Backup_Admin_In_Progress_Data::set_arg( 'step', 3 );
|
160 |
|
161 |
+
$zip_success = $this->zip();
|
162 |
|
163 |
+
// @todo Simliar to the zip call above which returns a success status, so should zip_sql.
|
164 |
$this->zip_sql();
|
165 |
|
166 |
Boldgrid_Backup_Admin_In_Progress_Data::delete_arg( 'step' );
|
168 |
// Actions to take when we're all done / cleanup.
|
169 |
$this->core->wp_filesystem->delete( $this->filelist_path );
|
170 |
|
171 |
+
return true === $zip_success ? true : array(
|
172 |
+
'error' => $this->error,
|
173 |
+
);
|
174 |
}
|
175 |
|
176 |
/**
|
225 |
* Run the command to actually zip the files.
|
226 |
*
|
227 |
* @since 1.13.0
|
228 |
+
*
|
229 |
+
* @return bool True on success. Do note that $this->close() calls $this->zip_proc(), which will
|
230 |
+
* store any error messages in $this->error.
|
231 |
*/
|
232 |
private function zip() {
|
233 |
$this->core->logger->add( 'Starting to close the zip file.' );
|
235 |
|
236 |
$this->temp_folder->create();
|
237 |
|
238 |
+
$success = $this->close();
|
239 |
|
240 |
$this->temp_folder->delete();
|
241 |
|
242 |
$this->core->logger->add( 'Finished closing the zip file.' );
|
243 |
$this->core->logger->add_memory();
|
244 |
+
|
245 |
+
return $success;
|
246 |
}
|
247 |
|
248 |
/**
|
287 |
|
288 |
foreach ( $filelist_chunks as $filelist_chunk ) {
|
289 |
$chunk_start_time = microtime( true );
|
290 |
+
|
291 |
+
$success = $this->zip_proc( $filelist_chunk );
|
292 |
+
if ( ! $success ) {
|
293 |
+
return false;
|
294 |
+
}
|
295 |
+
|
296 |
+
// Process some stats.
|
297 |
$chunks_closed++;
|
298 |
$percent_complete = round( $chunks_closed / $total_chunks, 2 );
|
299 |
$chunk_end_time = microtime( true );
|
300 |
$close_duration = $chunk_end_time - $chunk_start_time;
|
301 |
+
|
302 |
Boldgrid_Backup_Admin_In_Progress_Data::set_arg( 'percent_closed', $percent_complete );
|
303 |
+
|
304 |
+
// Add messages to the log.
|
305 |
$this->core->logger->add(
|
306 |
'Chunk closed in ' .
|
307 |
$close_duration .
|
310 |
);
|
311 |
$this->core->logger->add_memory();
|
312 |
}
|
313 |
+
|
314 |
+
return true;
|
315 |
}
|
316 |
|
317 |
/**
|
332 |
* @since 1.14.0
|
333 |
*
|
334 |
* @param array $filelist_chunk Array of Files to be added.
|
335 |
+
* @return bool True on success.
|
336 |
*/
|
337 |
private function zip_proc( $filelist_chunk ) {
|
338 |
+
$has_error = false;
|
339 |
+
|
340 |
$descriptorspec = array(
|
341 |
0 => array( 'pipe', 'r' ), // stdin is a pipe that the child will read from.
|
342 |
1 => array( 'pipe', 'w' ), // stdout is a pipe that the child will write to.
|
343 |
+
/**
|
344 |
+
* Initially we sent errors to /tmp/error-output.txt. This caused warnings when the file
|
345 |
+
* was not writable. For any error messages, see $pipes[2] further down this method.
|
346 |
+
*/
|
347 |
+
2 => array( 'pipe', 'w' ),
|
348 |
);
|
349 |
|
350 |
$cwd = ABSPATH;
|
359 |
);
|
360 |
|
361 |
if ( is_resource( $process ) ) {
|
|
|
|
|
|
|
|
|
|
|
362 |
foreach ( $filelist_chunk as $file ) {
|
363 |
fwrite( $pipes[0], $file . "\n" ); //phpcs:ignore WordPress.WP.AlternativeFunctions
|
364 |
}
|
367 |
|
368 |
fclose( $pipes[1] ); //phpcs:ignore WordPress.WP.AlternativeFunctions
|
369 |
|
370 |
+
// Check for any errors.
|
371 |
+
$stderr = stream_get_contents( $pipes[2] );
|
372 |
+
fclose( $pipes[2] ); //phpcs:ignore WordPress.WP.AlternativeFunctions
|
373 |
+
if ( ! empty( $stderr ) ) {
|
374 |
+
$this->error = $stderr;
|
375 |
+
$this->core->logger->add( 'Error zipping files with system zip: ' . $stderr );
|
376 |
+
$has_error = true;
|
377 |
+
}
|
378 |
+
|
379 |
// It is important that you close any pipes before calling.
|
380 |
// proc_close in order to avoid a deadlock.
|
381 |
proc_close( $process );
|
382 |
+
} else {
|
383 |
+
$has_error = true;
|
384 |
}
|
385 |
+
|
386 |
+
return ! $has_error;
|
387 |
}
|
388 |
|
389 |
/**
|
admin/js/boldgrid-backup-admin-in-progress.js
CHANGED
@@ -191,12 +191,13 @@ BOLDGRID.BACKUP = BOLDGRID.BACKUP || {};
|
|
191 |
* @since 1.14.13
|
192 |
*/
|
193 |
onClickCancel: function() {
|
|
|
194 |
/*
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
$.ajax( {
|
201 |
url: ajaxurl,
|
202 |
data: {
|
@@ -206,8 +207,9 @@ BOLDGRID.BACKUP = BOLDGRID.BACKUP || {};
|
|
206 |
type: 'post'
|
207 |
} );
|
208 |
|
209 |
-
$( '#bgbkup_progress_actions' ).html(
|
210 |
-
' <span class="spinner inline"></span>'
|
|
|
211 |
},
|
212 |
|
213 |
/**
|
191 |
* @since 1.14.13
|
192 |
*/
|
193 |
onClickCancel: function() {
|
194 |
+
|
195 |
/*
|
196 |
+
* Make the ajax call to cancel the backup.
|
197 |
+
*
|
198 |
+
* No success, error, or complete callback is passed to the ajax call. Status updates will
|
199 |
+
* be handled naturally by the in progress system.
|
200 |
+
*/
|
201 |
$.ajax( {
|
202 |
url: ajaxurl,
|
203 |
data: {
|
207 |
type: 'post'
|
208 |
} );
|
209 |
|
210 |
+
$( '#bgbkup_progress_actions' ).html(
|
211 |
+
wp.i18n.__( 'Canceling backup', 'boldgrid-backup' ) + ' <span class="spinner inline"></span>'
|
212 |
+
);
|
213 |
},
|
214 |
|
215 |
/**
|
admin/partials/settings/backup-security.php
CHANGED
@@ -69,7 +69,7 @@ if ( ! $is_premium ) {
|
|
69 |
<tr><td colspan="2">
|
70 |
<div class="bg-box-bottom premium wp-clearfix">
|
71 |
<?php
|
72 |
-
$get_premium_url = '
|
73 |
printf(
|
74 |
// translators: 1: Get premium button/link, 2: Opening <a> tag, 3: Closing </a> tag.
|
75 |
esc_html__(
|
69 |
<tr><td colspan="2">
|
70 |
<div class="bg-box-bottom premium wp-clearfix">
|
71 |
<?php
|
72 |
+
$get_premium_url = $this->core->go_pro->get_premium_url( 'bgbkup-settings-security' );
|
73 |
printf(
|
74 |
// translators: 1: Get premium button/link, 2: Opening <a> tag, 3: Closing </a> tag.
|
75 |
esc_html__(
|
boldgrid-backup.php
CHANGED
@@ -16,7 +16,7 @@
|
|
16 |
* Plugin Name: Total Upkeep
|
17 |
* Plugin URI: https://www.boldgrid.com/boldgrid-backup/
|
18 |
* Description: Automated backups, remote backup to Amazon S3 and Google Drive, stop website crashes before they happen and more. Total Upkeep is the backup solution you need.
|
19 |
-
* Version: 1.
|
20 |
* Author: BoldGrid
|
21 |
* Author URI: https://www.boldgrid.com/
|
22 |
* License: GPL-2.0+
|
@@ -50,6 +50,8 @@ if ( ! defined( 'BOLDGRID_BACKUP_TITLE' ) ) {
|
|
50 |
define( 'BOLDGRID_BACKUP_TITLE', 'Total Upkeep' );
|
51 |
}
|
52 |
|
|
|
|
|
53 |
/**
|
54 |
* The code that runs during plugin activation.
|
55 |
* This action is documented in includes/class-boldgrid-backup-activator.php
|
@@ -140,7 +142,7 @@ function load_boldgrid_backup() {
|
|
140 |
*
|
141 |
* Run the plugin only if on a wp-admin page or when DOING_CRON.
|
142 |
*/
|
143 |
-
if ( is_admin() || ( defined( 'DOING_CRON' ) && DOING_CRON ) || defined( 'WP_CLI' ) && WP_CLI ) {
|
144 |
// If we could not load boldgrid_backup (missing system requirements), abort.
|
145 |
if ( load_boldgrid_backup() ) {
|
146 |
require_once BOLDGRID_BACKUP_PATH . '/includes/class-boldgrid-backup.php';
|
16 |
* Plugin Name: Total Upkeep
|
17 |
* Plugin URI: https://www.boldgrid.com/boldgrid-backup/
|
18 |
* Description: Automated backups, remote backup to Amazon S3 and Google Drive, stop website crashes before they happen and more. Total Upkeep is the backup solution you need.
|
19 |
+
* Version: 1.15.0
|
20 |
* Author: BoldGrid
|
21 |
* Author URI: https://www.boldgrid.com/
|
22 |
* License: GPL-2.0+
|
50 |
define( 'BOLDGRID_BACKUP_TITLE', 'Total Upkeep' );
|
51 |
}
|
52 |
|
53 |
+
require_once BOLDGRID_BACKUP_PATH . '/rest/class-boldgrid-backup-rest-utility.php';
|
54 |
+
|
55 |
/**
|
56 |
* The code that runs during plugin activation.
|
57 |
* This action is documented in includes/class-boldgrid-backup-activator.php
|
142 |
*
|
143 |
* Run the plugin only if on a wp-admin page or when DOING_CRON.
|
144 |
*/
|
145 |
+
if ( is_admin() || ( defined( 'DOING_CRON' ) && DOING_CRON ) || defined( 'WP_CLI' ) && WP_CLI || Boldgrid_Backup_Rest_Utility::is_rest() ) {
|
146 |
// If we could not load boldgrid_backup (missing system requirements), abort.
|
147 |
if ( load_boldgrid_backup() ) {
|
148 |
require_once BOLDGRID_BACKUP_PATH . '/includes/class-boldgrid-backup.php';
|
cli/class-site-check.php
CHANGED
@@ -158,37 +158,6 @@ class Site_Check {
|
|
158 |
return $success;
|
159 |
}
|
160 |
|
161 |
-
/**
|
162 |
-
* Check if a port is open.
|
163 |
-
*
|
164 |
-
* @since 1.10.0
|
165 |
-
* @static
|
166 |
-
*
|
167 |
-
* @link https://www.php.net/manual/en/function.fsockopen.php
|
168 |
-
*
|
169 |
-
* @param int $port Port number (1-65535).
|
170 |
-
* @param string $host Optional hostname; defaults to "localhost".
|
171 |
-
* @param int $timeout Connect timeout, in seconds; defaults to 5.
|
172 |
-
* @param int $errno If provided, holds the system level error number that occurred in the system-level connect() call.
|
173 |
-
* @param string $errstr The error message as a string.
|
174 |
-
* @return bool
|
175 |
-
*/
|
176 |
-
public static function check_port( $port, $host = 'localhost', $timeout = 5, &$errno, &$errstr ) {
|
177 |
-
// Check for valid port reange.
|
178 |
-
if ( 0 > $port || 65535 < $port ) {
|
179 |
-
return false;
|
180 |
-
}
|
181 |
-
|
182 |
-
$res = @fsockopen( $host, $port, $errno, $errstr, $timeout ); // phpcs:ignore Generic.PHP.NoSilencedErrors
|
183 |
-
|
184 |
-
if ( is_resource( $res ) ) {
|
185 |
-
fclose( $res );
|
186 |
-
return true;
|
187 |
-
}
|
188 |
-
|
189 |
-
return false;
|
190 |
-
}
|
191 |
-
|
192 |
/**
|
193 |
* Perform a site check.
|
194 |
*
|
158 |
return $success;
|
159 |
}
|
160 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
161 |
/**
|
162 |
* Perform a site check.
|
163 |
*
|
cli/verify-dd66c7edb75333982c82a15ab5b733f0.php
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
<?php // phpcs:disable
|
includes/archive/class-factory.php
ADDED
@@ -0,0 +1,92 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Factory class.
|
4 |
+
*
|
5 |
+
* @link https://www.boldgrid.com
|
6 |
+
* @since SINCEVERSION
|
7 |
+
*
|
8 |
+
* @package Boldgrid\Backup
|
9 |
+
* @subpackage Boldgrid\Backup\Archive
|
10 |
+
* @copyright BoldGrid
|
11 |
+
* @author BoldGrid <support@boldgrid.com>
|
12 |
+
*/
|
13 |
+
|
14 |
+
namespace Boldgrid\Backup\Archive;
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Class: Factory
|
18 |
+
*
|
19 |
+
* A factory for getting an archive of type Boldgrid_Backup_Admin_Archive.
|
20 |
+
*
|
21 |
+
* @since SINCEVERSION
|
22 |
+
*/
|
23 |
+
class Factory {
|
24 |
+
/**
|
25 |
+
* Get an archive by filename.
|
26 |
+
*
|
27 |
+
* @since SINCEVERSION
|
28 |
+
*
|
29 |
+
* @param string $filename The filename of a backup.
|
30 |
+
* @return Boldgrid_Backup_Admin_Archive
|
31 |
+
*/
|
32 |
+
public static function get_by_filename( $filename ) {
|
33 |
+
$archive = new \Boldgrid_Backup_Admin_Archive();
|
34 |
+
|
35 |
+
$archive->init_by_filename( $filename );
|
36 |
+
|
37 |
+
$archive = self::set_id( $archive );
|
38 |
+
|
39 |
+
return $archive;
|
40 |
+
}
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Get a backup by id.
|
44 |
+
*
|
45 |
+
* @since SINCEVERSION
|
46 |
+
*
|
47 |
+
* @param string $id The backup id.
|
48 |
+
* @return Boldgrid_Backup_Admin_Archive
|
49 |
+
*/
|
50 |
+
public static function get_by_id( $id ) {
|
51 |
+
$archive = new \Boldgrid_Backup_Admin_Archive();
|
52 |
+
|
53 |
+
// Get the filename of our backup based on id.
|
54 |
+
$option = new Option();
|
55 |
+
$option_row = $option->get_by_key( 'id', (int) $id );
|
56 |
+
$filename = ! empty( $option_row['filename'] ) ? $option_row['filename'] : null;
|
57 |
+
|
58 |
+
if ( ! empty( $filename ) ) {
|
59 |
+
$archive->init_by_filename( $filename );
|
60 |
+
}
|
61 |
+
|
62 |
+
return $archive;
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Give a backup an id.
|
67 |
+
*
|
68 |
+
* @since SINCEVERSION
|
69 |
+
*
|
70 |
+
* @param Boldgrid_Backup_Admin_Archive $archive An archive.
|
71 |
+
* @return Boldgrid_Backup_Admin_Archive
|
72 |
+
*/
|
73 |
+
private static function set_id( $archive ) {
|
74 |
+
$option = new Option();
|
75 |
+
|
76 |
+
$option_row = $option->get_by_key( 'filename', $archive->filename );
|
77 |
+
|
78 |
+
if ( empty( $option_row ) ) {
|
79 |
+
$option_row = [ 'filename' => $archive->filename ];
|
80 |
+
}
|
81 |
+
|
82 |
+
if ( isset( $option_row['id'] ) ) {
|
83 |
+
$archive->set_id( $option_row['id'] );
|
84 |
+
} else {
|
85 |
+
$archive->set_id( $option->get_next_id() );
|
86 |
+
|
87 |
+
$option->update_by_filename( $archive->filename, 'id', $archive->get_id() );
|
88 |
+
}
|
89 |
+
|
90 |
+
return $archive;
|
91 |
+
}
|
92 |
+
}
|
includes/archive/class-option.php
ADDED
@@ -0,0 +1,126 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Option class.
|
4 |
+
*
|
5 |
+
* @link https://www.boldgrid.com
|
6 |
+
* @since SINCEVERSION
|
7 |
+
*
|
8 |
+
* @package Boldgrid\Backup
|
9 |
+
* @subpackage Boldgrid\Backup\Archive
|
10 |
+
* @copyright BoldGrid
|
11 |
+
* @author BoldGrid <support@boldgrid.com>
|
12 |
+
*/
|
13 |
+
|
14 |
+
namespace Boldgrid\Backup\Archive;
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Class: Option
|
18 |
+
*
|
19 |
+
* This class is used to manage the boldgrid_backup_backups option.
|
20 |
+
*
|
21 |
+
* In it's first implementation, each entry in the array represents a single backup, and has an id and
|
22 |
+
* a filename. For examples, please see: https://pastebin.com/Wuey2zvP
|
23 |
+
*
|
24 |
+
* @since SINCEVERSION
|
25 |
+
*/
|
26 |
+
class Option {
|
27 |
+
/**
|
28 |
+
* The option name storing backups.
|
29 |
+
*
|
30 |
+
* @since SINCEVERSION
|
31 |
+
* @access private
|
32 |
+
* @var string
|
33 |
+
*/
|
34 |
+
private $option = 'boldgrid_backup_backups';
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Get all our backups.
|
38 |
+
*
|
39 |
+
* @since SINCEVERSION
|
40 |
+
*
|
41 |
+
* @return array
|
42 |
+
*/
|
43 |
+
public function get_all() {
|
44 |
+
return get_option( $this->option, [] );
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Get one backup.
|
49 |
+
*
|
50 |
+
* @since SINCEVERSION
|
51 |
+
*
|
52 |
+
* @param string $filename The filename to look for.
|
53 |
+
* @return array
|
54 |
+
*/
|
55 |
+
public function get_by_key( $key, $value ) {
|
56 |
+
$found_backup = [];
|
57 |
+
|
58 |
+
$backups = $this->get_all();
|
59 |
+
|
60 |
+
foreach ( $backups as $backup ) {
|
61 |
+
if ( isset( $backup[ $key ] ) && $backup[ $key ] === $value ) {
|
62 |
+
$found_backup = $backup;
|
63 |
+
break;
|
64 |
+
}
|
65 |
+
}
|
66 |
+
|
67 |
+
return $found_backup;
|
68 |
+
}
|
69 |
+
|
70 |
+
/**
|
71 |
+
* Get a new id for a new backup being added to the list.
|
72 |
+
*
|
73 |
+
* @since SINCEVERSION
|
74 |
+
*
|
75 |
+
* @return int
|
76 |
+
*/
|
77 |
+
public function get_next_id() {
|
78 |
+
$next_id = 1;
|
79 |
+
|
80 |
+
$backups = $this->get_all();
|
81 |
+
|
82 |
+
foreach ( $backups as $backup ) {
|
83 |
+
$id = isset( $backup['id'] ) ? $backup['id'] : 1;
|
84 |
+
|
85 |
+
$next_id = $id >= $next_id ? ( $id + 1 ) : $next_id;
|
86 |
+
}
|
87 |
+
|
88 |
+
return $next_id;
|
89 |
+
}
|
90 |
+
|
91 |
+
/**
|
92 |
+
* Update a backup entry based on the filename.
|
93 |
+
*
|
94 |
+
* @since SINCEVERSION
|
95 |
+
*
|
96 |
+
* @param string $filename The filename to update attributes of.
|
97 |
+
* @param string $key The key to update.
|
98 |
+
* @param string $value The value for the key.
|
99 |
+
*/
|
100 |
+
public function update_by_filename( $filename, $key, $value ) {
|
101 |
+
$found = false;
|
102 |
+
|
103 |
+
$backups = $this->get_all();
|
104 |
+
|
105 |
+
// Find our backup by filename, and update the key.
|
106 |
+
foreach ( $backups as $k => $backup ) {
|
107 |
+
if ( ! empty( $backup['filename'] ) && $backup['filename'] === $filename ) {
|
108 |
+
$found = true;
|
109 |
+
|
110 |
+
$backups[ $k ][ $key ] = $value;
|
111 |
+
|
112 |
+
break;
|
113 |
+
}
|
114 |
+
}
|
115 |
+
|
116 |
+
// If the backup was not found in the array, add it.
|
117 |
+
if ( ! $found ) {
|
118 |
+
$backups[] = [
|
119 |
+
'filename' => $filename,
|
120 |
+
$key => $value,
|
121 |
+
];
|
122 |
+
}
|
123 |
+
|
124 |
+
update_option( $this->option, $backups );
|
125 |
+
}
|
126 |
+
}
|
includes/class-boldgrid-backup-archive-fetcher.php
ADDED
@@ -0,0 +1,290 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* File: class-boldgrid-backup-archive-fetcher.php
|
4 |
+
*
|
5 |
+
* @link https://www.boldgrid.com
|
6 |
+
* @since SINCEVERSION
|
7 |
+
*
|
8 |
+
* @package Boldgrid_Backup
|
9 |
+
* @subpackage Boldgrid_Backup/includes
|
10 |
+
* @copyright BoldGrid
|
11 |
+
* @version $Id$
|
12 |
+
* @author BoldGrid <support@boldgrid.com>
|
13 |
+
*/
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Class: Boldgrid_Backup_Archive_Fetcher
|
17 |
+
*
|
18 |
+
* This class is used to download archives from a url.
|
19 |
+
*
|
20 |
+
* The contents of this class were originally in the Boldgrid_Backup_Admin_Upload class, and have been
|
21 |
+
* moved here for reusability.
|
22 |
+
*
|
23 |
+
* @since SINCEVERSION
|
24 |
+
*/
|
25 |
+
class Boldgrid_Backup_Archive_Fetcher {
|
26 |
+
/**
|
27 |
+
* The url to download.
|
28 |
+
*
|
29 |
+
* @since SINCEVERSION
|
30 |
+
* @param string
|
31 |
+
*/
|
32 |
+
public $url;
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Allowed content types.
|
36 |
+
*
|
37 |
+
* @since SINCVERSION
|
38 |
+
* @access private
|
39 |
+
* @var array
|
40 |
+
*/
|
41 |
+
private $allowed_content_types = [
|
42 |
+
'application/octet-stream',
|
43 |
+
'binary/octet-stream',
|
44 |
+
'application/zip',
|
45 |
+
];
|
46 |
+
|
47 |
+
/**
|
48 |
+
* The core class object.
|
49 |
+
*
|
50 |
+
* @since SINCEVERSION
|
51 |
+
* @access private
|
52 |
+
* @var Boldgrid_Backup_Admin_Core
|
53 |
+
*/
|
54 |
+
private $core;
|
55 |
+
|
56 |
+
/**
|
57 |
+
* An error message.
|
58 |
+
*
|
59 |
+
* @since SINCEVERSION
|
60 |
+
* @access private
|
61 |
+
* @var string
|
62 |
+
*/
|
63 |
+
private $error;
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Filepath to our archive.
|
67 |
+
*
|
68 |
+
* @since SINCEVERSION
|
69 |
+
* @access private
|
70 |
+
* @var string
|
71 |
+
*/
|
72 |
+
private $filepath;
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Fetcher info.
|
76 |
+
*
|
77 |
+
* After a successful fetch, this array will have info about our new backup.
|
78 |
+
*
|
79 |
+
* @since SINCEVERSION
|
80 |
+
* @access private
|
81 |
+
* @var array {
|
82 |
+
* @type string $filepath The filepath to the archive.
|
83 |
+
* @type string $detailsUrl The admin url to the details page for this archive.
|
84 |
+
* @type string $archiveFilename The filename of the archive.
|
85 |
+
* @type int $archiveKey The archive key.
|
86 |
+
* }
|
87 |
+
*/
|
88 |
+
private $info = [];
|
89 |
+
|
90 |
+
/**
|
91 |
+
* The path to the archive's log.
|
92 |
+
*
|
93 |
+
* @since SINCEVERSION
|
94 |
+
* @access private
|
95 |
+
* @var string
|
96 |
+
*/
|
97 |
+
private $log_filepath;
|
98 |
+
|
99 |
+
/**
|
100 |
+
* The response received when trying to download the file.
|
101 |
+
*
|
102 |
+
* @since SINCEVERSION
|
103 |
+
* @access private
|
104 |
+
* @var mixed
|
105 |
+
*/
|
106 |
+
private $response;
|
107 |
+
|
108 |
+
/**
|
109 |
+
* Constructor.
|
110 |
+
*
|
111 |
+
* @since SINCEVERSION
|
112 |
+
*
|
113 |
+
* @param string $url The url we will be downloading.
|
114 |
+
*/
|
115 |
+
public function __construct( $url ) {
|
116 |
+
$this->core = apply_filters( 'boldgrid_backup_get_core', null );
|
117 |
+
|
118 |
+
$this->url = $url;
|
119 |
+
}
|
120 |
+
|
121 |
+
/**
|
122 |
+
* Download a backup file from a remote server.
|
123 |
+
*
|
124 |
+
* @since SINCEVERSION
|
125 |
+
*
|
126 |
+
* @return bool True on success.
|
127 |
+
*/
|
128 |
+
public function download() {
|
129 |
+
if ( ! $this->is_valid_url() ) {
|
130 |
+
$this->error = __( 'Invalid URL address.', 'boldgrid-backup' );
|
131 |
+
return false;
|
132 |
+
}
|
133 |
+
|
134 |
+
if ( ! $this->is_valid_backupdir() ) {
|
135 |
+
$this->error = implode( '<br />', $this->core->backup_dir->errors );
|
136 |
+
return false;
|
137 |
+
}
|
138 |
+
|
139 |
+
$this->filepath = $this->core->upload->get_save_path( basename( $this->url ) );
|
140 |
+
|
141 |
+
$this->response = wp_remote_get(
|
142 |
+
$this->url,
|
143 |
+
[
|
144 |
+
'filename' => $this->filepath,
|
145 |
+
'headers' => 'Accept: ' . implode( ', ', $this->allowed_content_types ),
|
146 |
+
'sslverify' => false,
|
147 |
+
'stream' => true,
|
148 |
+
'timeout' => MINUTE_IN_SECONDS * 20,
|
149 |
+
]
|
150 |
+
);
|
151 |
+
|
152 |
+
if ( $this->is_call_successful() ) {
|
153 |
+
$this->post_successful_download();
|
154 |
+
|
155 |
+
return true;
|
156 |
+
} else {
|
157 |
+
$this->core->wp_filesystem->delete( $this->filepath );
|
158 |
+
|
159 |
+
$this->error = __(
|
160 |
+
'Could not retrieve the remote file. It may not be a ZIP file, or the link is no longer valid.',
|
161 |
+
'boldgrid-backup'
|
162 |
+
);
|
163 |
+
|
164 |
+
return false;
|
165 |
+
}
|
166 |
+
}
|
167 |
+
|
168 |
+
/**
|
169 |
+
* Get our error message.
|
170 |
+
*
|
171 |
+
* @since SINCEVERSION
|
172 |
+
*
|
173 |
+
* @return string
|
174 |
+
*/
|
175 |
+
public function get_error() {
|
176 |
+
return $this->error;
|
177 |
+
}
|
178 |
+
|
179 |
+
/**
|
180 |
+
* Get our array of info after a successful download.
|
181 |
+
*
|
182 |
+
* @since SINCEVERSION
|
183 |
+
*
|
184 |
+
* @return array
|
185 |
+
*/
|
186 |
+
public function get_info() {
|
187 |
+
return $this->info;
|
188 |
+
}
|
189 |
+
|
190 |
+
/**
|
191 |
+
* Whether or not we encountered an error during the download process.
|
192 |
+
*
|
193 |
+
* @since SINCEVERSION
|
194 |
+
*
|
195 |
+
* @return bool
|
196 |
+
*/
|
197 |
+
public function has_error() {
|
198 |
+
return ! empty( $this->error );
|
199 |
+
}
|
200 |
+
|
201 |
+
/**
|
202 |
+
* Whether or not the call to download the file was successful.
|
203 |
+
*
|
204 |
+
* This does not represent the success of the download() method, but instead the state of the
|
205 |
+
* wp_remote_get call.
|
206 |
+
*
|
207 |
+
* @since SINCEVERSION
|
208 |
+
*
|
209 |
+
* @return bool True on success.
|
210 |
+
*/
|
211 |
+
private function is_call_successful() {
|
212 |
+
return is_array( $this->response ) &&
|
213 |
+
! is_wp_error( $this->response ) &&
|
214 |
+
in_array( $this->response['headers']['content-type'], $this->allowed_content_types, true );
|
215 |
+
}
|
216 |
+
|
217 |
+
/**
|
218 |
+
* Validate our backup directory.
|
219 |
+
*
|
220 |
+
* @since SINCEVERSION
|
221 |
+
*
|
222 |
+
* @return bool True if valid.
|
223 |
+
*/
|
224 |
+
private function is_valid_backupdir() {
|
225 |
+
$backup_directory = $this->core->backup_dir->get();
|
226 |
+
|
227 |
+
return $this->core->backup_dir->is_valid( $backup_directory ) && empty( $this->core->backup_dir->errors );
|
228 |
+
}
|
229 |
+
|
230 |
+
/**
|
231 |
+
* Validate our download url.
|
232 |
+
*
|
233 |
+
* @since SINCEVERSION
|
234 |
+
*
|
235 |
+
* @return bool True if valid.
|
236 |
+
*/
|
237 |
+
private function is_valid_url() {
|
238 |
+
$url_regex = '/' . $this->core->configs['url_regex'] . '/i';
|
239 |
+
|
240 |
+
return preg_match( $url_regex, $this->url );
|
241 |
+
}
|
242 |
+
|
243 |
+
/**
|
244 |
+
* Steps to take if our raw wp_remote_get() call to download the backup was successful.
|
245 |
+
*
|
246 |
+
* @since SINCEVERSION
|
247 |
+
*/
|
248 |
+
private function post_successful_download() {
|
249 |
+
$this->set_logfilepath();
|
250 |
+
|
251 |
+
$filename = basename( $this->filepath );
|
252 |
+
|
253 |
+
// Restore the log file from the archive.
|
254 |
+
$this->core->archive_log->restore_by_zip( $this->filepath, basename( $this->log_filepath ) );
|
255 |
+
|
256 |
+
// Update the archive file modification time, based on the log file contents.
|
257 |
+
$this->core->remote->post_download( $this->filepath );
|
258 |
+
|
259 |
+
// Get the archive details.
|
260 |
+
$archive = $this->core->archive->get_by_name( $filename );
|
261 |
+
|
262 |
+
$this->info = [
|
263 |
+
'filepath' => $this->filepath,
|
264 |
+
'detailsUrl' => admin_url( 'admin.php?page=boldgrid-backup-archive-details&filename=' . basename( $this->filepath ) ),
|
265 |
+
'archiveFilename' => $filename,
|
266 |
+
'archiveKey' => $archive['key'],
|
267 |
+
];
|
268 |
+
}
|
269 |
+
|
270 |
+
/**
|
271 |
+
* Set the archive log filepath.
|
272 |
+
*
|
273 |
+
* @since SINCEVERSION
|
274 |
+
*/
|
275 |
+
private function set_logfilepath() {
|
276 |
+
$this->log_filepath = $this->filepath;
|
277 |
+
|
278 |
+
if ( ! empty( $this->response['headers']['content-disposition'] ) ) {
|
279 |
+
$this->log_filepath = trim(
|
280 |
+
str_replace(
|
281 |
+
'attachment; filename=', '', $this->response['headers']['content-disposition']
|
282 |
+
), '"'
|
283 |
+
);
|
284 |
+
|
285 |
+
$this->log_filepath = $this->core->backup_dir->get_path_to( $this->log_filepath );
|
286 |
+
}
|
287 |
+
|
288 |
+
$this->log_filepath = $this->core->archive_log->path_from_zip( $this->log_filepath );
|
289 |
+
}
|
290 |
+
}
|
includes/class-boldgrid-backup-archiver.php
ADDED
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* File: class-boldgrid-backup-archiver.php
|
4 |
+
*
|
5 |
+
* @link https://www.boldgrid.com
|
6 |
+
* @since SINCEVERSION
|
7 |
+
*
|
8 |
+
* @package Boldgrid_Backup
|
9 |
+
* @subpackage Boldgrid_Backup/includes
|
10 |
+
* @copyright BoldGrid
|
11 |
+
* @version $Id$
|
12 |
+
* @author BoldGrid <support@boldgrid.com>
|
13 |
+
*/
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Class: Boldgrid_Backup_Archiver
|
17 |
+
*
|
18 |
+
* Originally, all methods for archiving a file have lived in Boldgrid_Backup_Admin_Core. This class,
|
19 |
+
* over time, will absorb those methods.
|
20 |
+
*
|
21 |
+
* @since SINCEVERSION
|
22 |
+
*/
|
23 |
+
class Boldgrid_Backup_Archiver {
|
24 |
+
/**
|
25 |
+
* Admin core.
|
26 |
+
*
|
27 |
+
* @since SINCEVERSION
|
28 |
+
* @access private
|
29 |
+
* @var Boldgrid_Backup_Admin_Core
|
30 |
+
*/
|
31 |
+
private $core;
|
32 |
+
|
33 |
+
/**
|
34 |
+
* An array of info about our archive.
|
35 |
+
*
|
36 |
+
* @since SINCEVERSION
|
37 |
+
* @access private
|
38 |
+
* @var array
|
39 |
+
*/
|
40 |
+
private $info;
|
41 |
+
|
42 |
+
/**
|
43 |
+
* An instance of Boldgrid_Backup_Admin_Task.
|
44 |
+
*
|
45 |
+
* @since SINCEVERSION
|
46 |
+
* @access private
|
47 |
+
* @var Boldgrid_Backup_Admin_Task
|
48 |
+
*/
|
49 |
+
private $task;
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Constructor.
|
53 |
+
*
|
54 |
+
* @since SINCEVERSION
|
55 |
+
*/
|
56 |
+
public function __construct() {
|
57 |
+
$this->core = apply_filters( 'boldgrid_backup_get_core', null );
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Steps to take when archiving is complete.
|
62 |
+
*
|
63 |
+
* @since SINCEVERSION
|
64 |
+
*/
|
65 |
+
public function complete() {
|
66 |
+
$this->core->logger->add( 'Backup complete!' );
|
67 |
+
$this->core->logger->add_memory();
|
68 |
+
|
69 |
+
$this->task->end();
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Get our archive info.
|
74 |
+
*
|
75 |
+
* @since SINCEVERSION
|
76 |
+
*
|
77 |
+
* @return array
|
78 |
+
*/
|
79 |
+
public function get_info() {
|
80 |
+
return $this->info;
|
81 |
+
}
|
82 |
+
|
83 |
+
/**
|
84 |
+
* Steps to take before an archive is started.
|
85 |
+
*
|
86 |
+
* @since SINCEVERSION
|
87 |
+
*/
|
88 |
+
public function init() {
|
89 |
+
// Init our logger.
|
90 |
+
$this->core->logger->init( 'archive-' . time() . '.log' );
|
91 |
+
$this->core->logger->add( 'Backup process initialized.' );
|
92 |
+
|
93 |
+
// Init our task.
|
94 |
+
$this->task = new Boldgrid_Backup_Admin_Task();
|
95 |
+
if ( ! empty( $_POST['task_id'] ) ) { // phpcs:ignore
|
96 |
+
$this->task->init_by_id( $_POST['task_id'] ); // phpcs:ignore
|
97 |
+
} else {
|
98 |
+
$this->task->init( [ 'type' => 'backup' ] );
|
99 |
+
}
|
100 |
+
$this->task->start();
|
101 |
+
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* Create an archive.
|
105 |
+
*
|
106 |
+
* Do everything.
|
107 |
+
*
|
108 |
+
* @since SINCEVERSION
|
109 |
+
*/
|
110 |
+
public function run() {
|
111 |
+
$this->init();
|
112 |
+
|
113 |
+
$this->info = $this->core->archive_files( true );
|
114 |
+
|
115 |
+
$this->complete();
|
116 |
+
}
|
117 |
+
}
|
includes/class-boldgrid-backup-restorer.php
ADDED
@@ -0,0 +1,251 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* File: class-boldgrid-backup-restorer.php
|
4 |
+
*
|
5 |
+
* @link https://www.boldgrid.com
|
6 |
+
* @since SINCEVERSION
|
7 |
+
*
|
8 |
+
* @package Boldgrid_Backup
|
9 |
+
* @subpackage Boldgrid_Backup/includes
|
10 |
+
* @copyright BoldGrid
|
11 |
+
* @version $Id$
|
12 |
+
* @author BoldGrid <support@boldgrid.com>
|
13 |
+
*/
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Class: Boldgrid_Backup_Restorer
|
17 |
+
*
|
18 |
+
* Originally, all methods for restoring a file have lived in Boldgrid_Backup_Admin_Core. This class,
|
19 |
+
* over time, will absorb those methods.
|
20 |
+
*
|
21 |
+
* @since SINCEVERSION
|
22 |
+
*/
|
23 |
+
class Boldgrid_Backup_Restorer {
|
24 |
+
/**
|
25 |
+
* Admin core.
|
26 |
+
*
|
27 |
+
* @since SINCEVERSION
|
28 |
+
* @access private
|
29 |
+
* @var Boldgrid_Backup_Admin_Core
|
30 |
+
*/
|
31 |
+
private $core;
|
32 |
+
|
33 |
+
/**
|
34 |
+
* An array of info about our archive.
|
35 |
+
*
|
36 |
+
* @since SINCEVERSION
|
37 |
+
* @access private
|
38 |
+
* @var array
|
39 |
+
*/
|
40 |
+
private $info;
|
41 |
+
|
42 |
+
/**
|
43 |
+
* An instance of Boldgrid_Backup_Admin_Task.
|
44 |
+
*
|
45 |
+
* @since SINCEVERSION
|
46 |
+
* @access private
|
47 |
+
* @var Boldgrid_Backup_Admin_Task
|
48 |
+
*/
|
49 |
+
private $task;
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Constructor.
|
53 |
+
*
|
54 |
+
* @since SINCEVERSION
|
55 |
+
*/
|
56 |
+
public function __construct() {
|
57 |
+
$this->core = apply_filters( 'boldgrid_backup_get_core', null );
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Steps to take when archiving is complete.
|
62 |
+
*
|
63 |
+
* @since SINCEVERSION
|
64 |
+
*/
|
65 |
+
public function complete() {
|
66 |
+
// Update the log.
|
67 |
+
$this->core->logger->add( 'Restoration complete!' );
|
68 |
+
$this->core->logger->add_memory();
|
69 |
+
|
70 |
+
if ( $this->has_error() ) {
|
71 |
+
$this->core->logger->add( 'Error during restoration: ' . $this->get_error() );
|
72 |
+
}
|
73 |
+
|
74 |
+
// End the task.
|
75 |
+
$this->task->end();
|
76 |
+
}
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Get our error message.
|
80 |
+
*
|
81 |
+
* @since SINCEVERSION
|
82 |
+
*
|
83 |
+
* @return string
|
84 |
+
*/
|
85 |
+
private function get_error() {
|
86 |
+
return ! empty( $this->info['error'] ) ? $this->info['error'] : __( 'Unknown error', 'boldgrid-backup' );
|
87 |
+
}
|
88 |
+
|
89 |
+
/**
|
90 |
+
* Get our archive info.
|
91 |
+
*
|
92 |
+
* @since SINCEVERSION
|
93 |
+
*
|
94 |
+
* @return array
|
95 |
+
*/
|
96 |
+
public function get_info() {
|
97 |
+
return $this->info;
|
98 |
+
}
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Whether or not we have an error.
|
102 |
+
*
|
103 |
+
* @since SINCEVERSION
|
104 |
+
*
|
105 |
+
* @return bool
|
106 |
+
*/
|
107 |
+
private function has_error() {
|
108 |
+
return ! empty( $this->info['error'] );
|
109 |
+
}
|
110 |
+
|
111 |
+
/**
|
112 |
+
* Steps to take before an archive is started.
|
113 |
+
*
|
114 |
+
* @since SINCEVERSION
|
115 |
+
*/
|
116 |
+
public function init() {
|
117 |
+
// Init our logger.
|
118 |
+
$this->core->logger->init( 'restore-' . time() . '.log' );
|
119 |
+
$this->core->logger->add( 'Restore process initialized.' );
|
120 |
+
$this->core->logger->add_memory();
|
121 |
+
|
122 |
+
/*
|
123 |
+
* Setup our task.
|
124 |
+
*
|
125 |
+
* We're either starting a new task, or continuing on an existing task.
|
126 |
+
*/
|
127 |
+
$this->task = new Boldgrid_Backup_Admin_Task();
|
128 |
+
if ( ! empty( $_POST['task_id'] ) ) { // phpcs:ignore
|
129 |
+
$this->task->init_by_id( $_POST['task_id'] ); // phpcs:ignore
|
130 |
+
} else {
|
131 |
+
$this->task->init( [ 'type' => 'restore' ] );
|
132 |
+
}
|
133 |
+
$this->task->start();
|
134 |
+
}
|
135 |
+
|
136 |
+
/**
|
137 |
+
* Restore a backup by id.
|
138 |
+
*
|
139 |
+
* @since SINCEVERSION
|
140 |
+
*
|
141 |
+
* @param string $id The backup id.
|
142 |
+
*/
|
143 |
+
public function restore_by_id( $id ) {
|
144 |
+
$archive = Boldgrid\Backup\Archive\Factory::get_by_id( $id );
|
145 |
+
|
146 |
+
$this->restore_by_key( $archive->get_key(), $archive->filename );
|
147 |
+
}
|
148 |
+
|
149 |
+
/**
|
150 |
+
* Restore an archive by key (and filename).
|
151 |
+
*
|
152 |
+
* @since SINCEVERSION
|
153 |
+
*
|
154 |
+
* @param int $key The archive key to restore.
|
155 |
+
* @param string $filename The archive filename to restore.
|
156 |
+
*/
|
157 |
+
public function restore_by_key( $key, $filename ) {
|
158 |
+
$restore_args = [
|
159 |
+
'archive_key' => $key,
|
160 |
+
'archive_filename' => $filename,
|
161 |
+
];
|
162 |
+
|
163 |
+
$this->info = $this->core->restore_archive_file( false, $restore_args );
|
164 |
+
}
|
165 |
+
|
166 |
+
/**
|
167 |
+
* Restore a site by url.
|
168 |
+
*
|
169 |
+
* @since SINCEVERSION
|
170 |
+
*
|
171 |
+
* @param string $url A url to a zip file.
|
172 |
+
*/
|
173 |
+
public function restore_by_url( $url ) {
|
174 |
+
// Download the backup file.
|
175 |
+
$archive_fetcher = new Boldgrid_Backup_Archive_Fetcher( $url );
|
176 |
+
$archive_fetcher->download();
|
177 |
+
|
178 |
+
// If we have errors, abort.
|
179 |
+
if ( $archive_fetcher->has_error() ) {
|
180 |
+
$this->set_error( $archive_fetcher->get_error() );
|
181 |
+
return;
|
182 |
+
}
|
183 |
+
|
184 |
+
// Restore the new archive just downloaded.
|
185 |
+
$info = $archive_fetcher->get_info();
|
186 |
+
$this->restore_by_key( $info['archiveKey'], $info['archiveFilename'] );
|
187 |
+
}
|
188 |
+
|
189 |
+
/**
|
190 |
+
* Run a basic restore.
|
191 |
+
*
|
192 |
+
* This mimics a standard call to core->restore_archive_file, except it adds additional things
|
193 |
+
* like tasks and logs.
|
194 |
+
*
|
195 |
+
* @since SINCEVERSION
|
196 |
+
*/
|
197 |
+
public function run() {
|
198 |
+
$this->init();
|
199 |
+
|
200 |
+
$this->info = $this->core->restore_archive_file();
|
201 |
+
|
202 |
+
$this->complete();
|
203 |
+
}
|
204 |
+
|
205 |
+
/**
|
206 |
+
* Run a restoration by backup id.
|
207 |
+
*
|
208 |
+
* Method run_by_id: This method, does more than just restoration. Handles logging, etc.
|
209 |
+
* Method restore_by_id: Handles just the restoration, nothing more.
|
210 |
+
*
|
211 |
+
* @since SINCEVERSION
|
212 |
+
*
|
213 |
+
* @param int $id The backup id.
|
214 |
+
*/
|
215 |
+
public function run_by_id( $id ) {
|
216 |
+
$this->init();
|
217 |
+
|
218 |
+
$this->restore_by_id( $id );
|
219 |
+
|
220 |
+
$this->complete();
|
221 |
+
}
|
222 |
+
|
223 |
+
/**
|
224 |
+
* Run a restoration by a url.
|
225 |
+
*
|
226 |
+
* Method run_by_url: This method, does more than just restoration. Handles logging, etc.
|
227 |
+
* Method restore_by_url: Handles just the restoration, nothing more.
|
228 |
+
*
|
229 |
+
* @since SINCEVERSION
|
230 |
+
*
|
231 |
+
* @param string $url A url to a zip file.
|
232 |
+
*/
|
233 |
+
public function run_by_url( $url ) {
|
234 |
+
$this->init();
|
235 |
+
|
236 |
+
$this->restore_by_url( $url );
|
237 |
+
|
238 |
+
$this->complete();
|
239 |
+
}
|
240 |
+
|
241 |
+
/**
|
242 |
+
* Set an error message.
|
243 |
+
*
|
244 |
+
* @since SINCEVERSION
|
245 |
+
*
|
246 |
+
* @param string $message The error message to set.
|
247 |
+
*/
|
248 |
+
private function set_error( $message ) {
|
249 |
+
$this->info['error'] = $message;
|
250 |
+
}
|
251 |
+
}
|
includes/class-boldgrid-backup.php
CHANGED
@@ -294,12 +294,36 @@ class Boldgrid_Backup {
|
|
294 |
|
295 |
require_once BOLDGRID_BACKUP_PATH . '/includes/class-boldgrid-backup-activator.php';
|
296 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
297 |
require_once BOLDGRID_BACKUP_PATH . '/admin/class-boldgrid-backup-admin-usage.php';
|
298 |
|
299 |
// Logs system.
|
300 |
require_once BOLDGRID_BACKUP_PATH . '/admin/class-boldgrid-backup-admin-log.php';
|
301 |
require_once BOLDGRID_BACKUP_PATH . '/admin/class-boldgrid-backup-admin-log-page.php';
|
302 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
303 |
require_once BOLDGRID_BACKUP_PATH . '/admin/class-boldgrid-backup-admin-plugin-notices.php';
|
304 |
|
305 |
// Orphaned files.
|
@@ -551,6 +575,24 @@ class Boldgrid_Backup {
|
|
551 |
$this->loader->add_action( 'admin_notices', $plugin_admin_core->notice, 'plugin_renamed_notice' );
|
552 |
$this->loader->add_action( 'wp_ajax_dismissBoldgridNotice', 'Boldgrid\Library\Library\Notice', 'dismiss' );
|
553 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
554 |
$usage = new Boldgrid_Backup_Admin_Usage();
|
555 |
|
556 |
$this->loader->add_action( 'admin_init', $usage, 'admin_init' );
|
@@ -583,6 +625,15 @@ class Boldgrid_Backup {
|
|
583 |
$this->loader->add_filter( 'Boldgrid\Library\Plugin\Notices\admin_enqueue_scripts', $plugin_notices, 'filter' );
|
584 |
|
585 |
$this->loader->add_action( 'admin_enqueue_scripts', $plugin_admin_core, 'add_thickbox' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
586 |
}
|
587 |
|
588 |
/**
|
294 |
|
295 |
require_once BOLDGRID_BACKUP_PATH . '/includes/class-boldgrid-backup-activator.php';
|
296 |
|
297 |
+
// REST API support.
|
298 |
+
require_once BOLDGRID_BACKUP_PATH . '/rest/class-boldgrid-backup-rest-controller.php';
|
299 |
+
require_once BOLDGRID_BACKUP_PATH . '/rest/class-boldgrid-backup-rest-job.php';
|
300 |
+
require_once BOLDGRID_BACKUP_PATH . '/rest/class-boldgrid-backup-rest-setting.php';
|
301 |
+
require_once BOLDGRID_BACKUP_PATH . '/rest/class-boldgrid-backup-rest-archive.php';
|
302 |
+
require_once BOLDGRID_BACKUP_PATH . '/rest/class-boldgrid-backup-rest-test.php';
|
303 |
+
require_once BOLDGRID_BACKUP_PATH . '/rest/class-boldgrid-backup-rest-siteurl.php';
|
304 |
+
|
305 |
require_once BOLDGRID_BACKUP_PATH . '/admin/class-boldgrid-backup-admin-usage.php';
|
306 |
|
307 |
// Logs system.
|
308 |
require_once BOLDGRID_BACKUP_PATH . '/admin/class-boldgrid-backup-admin-log.php';
|
309 |
require_once BOLDGRID_BACKUP_PATH . '/admin/class-boldgrid-backup-admin-log-page.php';
|
310 |
|
311 |
+
require_once BOLDGRID_BACKUP_PATH . '/admin/class-boldgrid-backup-admin-nopriv.php';
|
312 |
+
|
313 |
+
// Task system.
|
314 |
+
require_once BOLDGRID_BACKUP_PATH . '/admin/class-boldgrid-backup-admin-task.php';
|
315 |
+
require_once BOLDGRID_BACKUP_PATH . '/admin/class-boldgrid-backup-admin-task-helper.php';
|
316 |
+
|
317 |
+
// Archiver and Restorer classes.
|
318 |
+
require_once BOLDGRID_BACKUP_PATH . '/includes/class-boldgrid-backup-archiver.php';
|
319 |
+
require_once BOLDGRID_BACKUP_PATH . '/includes/class-boldgrid-backup-restorer.php';
|
320 |
+
|
321 |
+
require_once BOLDGRID_BACKUP_PATH . '/includes/class-boldgrid-backup-archive-fetcher.php';
|
322 |
+
|
323 |
+
// Archive namespace.
|
324 |
+
require_once BOLDGRID_BACKUP_PATH . '/includes/archive/class-factory.php';
|
325 |
+
require_once BOLDGRID_BACKUP_PATH . '/includes/archive/class-option.php';
|
326 |
+
|
327 |
require_once BOLDGRID_BACKUP_PATH . '/admin/class-boldgrid-backup-admin-plugin-notices.php';
|
328 |
|
329 |
// Orphaned files.
|
575 |
$this->loader->add_action( 'admin_notices', $plugin_admin_core->notice, 'plugin_renamed_notice' );
|
576 |
$this->loader->add_action( 'wp_ajax_dismissBoldgridNotice', 'Boldgrid\Library\Library\Notice', 'dismiss' );
|
577 |
|
578 |
+
// Register REST endpoints.
|
579 |
+
add_action( 'rest_api_init', function() use ( $plugin_admin_core ) {
|
580 |
+
$rest_job = new Boldgrid_Backup_Rest_Job( $plugin_admin_core );
|
581 |
+
$rest_job->register_routes();
|
582 |
+
|
583 |
+
$rest_archive = new Boldgrid_Backup_Rest_Archive( $plugin_admin_core );
|
584 |
+
$rest_archive->register_routes();
|
585 |
+
|
586 |
+
$rest_setting = new Boldgrid_Backup_Rest_Setting( $plugin_admin_core );
|
587 |
+
$rest_setting->register_routes();
|
588 |
+
|
589 |
+
$rest_test = new Boldgrid_Backup_Rest_Test( $plugin_admin_core );
|
590 |
+
$rest_test->register_routes();
|
591 |
+
|
592 |
+
$rest_siteurl = new Boldgrid_Backup_Rest_Siteurl( $plugin_admin_core );
|
593 |
+
$rest_siteurl->register_routes();
|
594 |
+
} );
|
595 |
+
|
596 |
$usage = new Boldgrid_Backup_Admin_Usage();
|
597 |
|
598 |
$this->loader->add_action( 'admin_init', $usage, 'admin_init' );
|
625 |
$this->loader->add_filter( 'Boldgrid\Library\Plugin\Notices\admin_enqueue_scripts', $plugin_notices, 'filter' );
|
626 |
|
627 |
$this->loader->add_action( 'admin_enqueue_scripts', $plugin_admin_core, 'add_thickbox' );
|
628 |
+
|
629 |
+
/*
|
630 |
+
* Things to do in a dev environment.
|
631 |
+
*
|
632 |
+
* @link https://make.wordpress.org/core/2020/07/24/new-wp_get_environment_type-function-in-wordpress-5-5/
|
633 |
+
*/
|
634 |
+
if ( defined( 'WP_ENVIRONMENT_TYPE' ) && 'development' === WP_ENVIRONMENT_TYPE ) {
|
635 |
+
$this->loader->add_action( 'admin_footer', 'Boldgrid_Backup_Rest_Utility', 'insert_nonce' );
|
636 |
+
}
|
637 |
}
|
638 |
|
639 |
/**
|
readme.txt
CHANGED
@@ -4,7 +4,7 @@ Tags: backup, cloud backup, database backup, restore, wordpress backup
|
|
4 |
Requires at least: 4.4
|
5 |
Tested up to: 5.9
|
6 |
Requires PHP: 5.4
|
7 |
-
Stable tag: 1.
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
10 |
|
@@ -132,6 +132,14 @@ Have a problem? First, take a look at our [Getting Started](https://www.boldgrid
|
|
132 |
|
133 |
== Changelog ==
|
134 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
135 |
= 1.14.14 =
|
136 |
|
137 |
Release date: February 24th, 2022
|
4 |
Requires at least: 4.4
|
5 |
Tested up to: 5.9
|
6 |
Requires PHP: 5.4
|
7 |
+
Stable tag: 1.15.0
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
10 |
|
132 |
|
133 |
== Changelog ==
|
134 |
|
135 |
+
= 1.15.0 =
|
136 |
+
|
137 |
+
Release date: March 15th, 2022
|
138 |
+
|
139 |
+
* New feature: REST API calls for backup and settings management.
|
140 |
+
* Bug fix: posix_getpgid availability check.
|
141 |
+
* Update: Updated dependencies.
|
142 |
+
|
143 |
= 1.14.14 =
|
144 |
|
145 |
Release date: February 24th, 2022
|
rest/README.MD
ADDED
@@ -0,0 +1,141 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Rest API
|
2 |
+
|
3 |
+
## Authentication
|
4 |
+
|
5 |
+
### How are Total Upkeep's Rest API calls authenticated?
|
6 |
+
|
7 |
+
REST API calls are authenticated with a [permissions callback](https://developer.wordpress.org/rest-api/extending-the-rest-api/adding-custom-endpoints/#permissions-callback).
|
8 |
+
|
9 |
+
Each registered route includes a permission_callback:
|
10 |
+
|
11 |
+
```php
|
12 |
+
register_rest_route( $this->namespace, '/' . $this->resource, [
|
13 |
+
[
|
14 |
+
'methods' => WP_REST_Server::READABLE,
|
15 |
+
'callback' => [ $this, 'get_items' ],
|
16 |
+
'permission_callback' => [ $this, 'permission_check' ],
|
17 |
+
],
|
18 |
+
'schema' => [ $this, 'get_schema' ],
|
19 |
+
] );
|
20 |
+
```
|
21 |
+
|
22 |
+
Our rest classes extend `Boldgrid_Backup_Rest_Controller`, which includes the `permission_check` method.
|
23 |
+
|
24 |
+
### Are there any public Rest calls?
|
25 |
+
|
26 |
+
No.
|
27 |
+
|
28 |
+
### How can I make a Rest call if no routes are public?
|
29 |
+
|
30 |
+
All calls will need to be authenticated. Please see [Using the REST API / Authentication](https://developer.wordpress.org/rest-api/using-the-rest-api/authentication/).
|
31 |
+
|
32 |
+
> For developers making manual Ajax requests, the nonce will need to be passed with each request. The API uses nonces with the
|
33 |
+
> action set to wp_rest. These can then be passed to the API via the _wpnonce data parameter (either POST data or in the query for
|
34 |
+
> GET requests), or via the X-WP-Nonce header. If no nonce is provided the API will set the current user to 0, turning the request
|
35 |
+
> into an unauthenticated request, even if you’re logged into WordPress.
|
36 |
+
|
37 |
+
The examples on this page use the `X-WP-Nonce` method.
|
38 |
+
|
39 |
+
# Manual Testing
|
40 |
+
|
41 |
+
## Setup
|
42 |
+
|
43 |
+
Before testing the jQuery calls on this page, be sure to add the following to your wp-config.php:
|
44 |
+
|
45 |
+
`define( 'WP_ENVIRONMENT_TYPE', 'development' );`
|
46 |
+
|
47 |
+
This will:
|
48 |
+
|
49 |
+
1. Add the `wp_rest` nonce to all your admin pages
|
50 |
+
1. Add your site url as `bgbkup_site_url`. This is a hidden input, who's value is used in the example calls below.
|
51 |
+
|
52 |
+
Failure to do the above, and you will have unauthenticated calls, resulting in a 403.
|
53 |
+
|
54 |
+
## Archives
|
55 |
+
|
56 |
+
### Get a list of archives
|
57 |
+
|
58 |
+
```
|
59 |
+
jQuery.ajax( {
|
60 |
+
url: jQuery( '#bgbkup_site_url' ).val() + '/wp-json/bgbkup/v1/archives/',
|
61 |
+
method: 'GET',
|
62 |
+
beforeSend: function ( xhr ) {
|
63 |
+
xhr.setRequestHeader( 'X-WP-Nonce', jQuery( '#wp_rest' ).val() );
|
64 |
+
}
|
65 |
+
} ).done( function ( response ) {
|
66 |
+
console.log( response );
|
67 |
+
} );
|
68 |
+
```
|
69 |
+
|
70 |
+
### Create
|
71 |
+
|
72 |
+
```
|
73 |
+
jQuery.ajax( {
|
74 |
+
url: jQuery( '#bgbkup_site_url' ).val() + '/wp-json/bgbkup/v1/archives',
|
75 |
+
method: 'POST',
|
76 |
+
beforeSend: function ( xhr ) {
|
77 |
+
xhr.setRequestHeader( 'X-WP-Nonce', jQuery( '#wp_rest' ).val() );
|
78 |
+
}
|
79 |
+
} ).done( function ( response ) {
|
80 |
+
console.log( response );
|
81 |
+
} );
|
82 |
+
```
|
83 |
+
|
84 |
+
### Restore
|
85 |
+
|
86 |
+
#### Restore via id
|
87 |
+
|
88 |
+
Take note of the `id=4` in the url.
|
89 |
+
|
90 |
+
```
|
91 |
+
jQuery.ajax( {
|
92 |
+
url: jQuery( '#bgbkup_site_url' ).val() + '/wp-json/bgbkup/v1/archives/?id=4',
|
93 |
+
method: 'PUT',
|
94 |
+
beforeSend: function ( xhr ) {
|
95 |
+
xhr.setRequestHeader( 'X-WP-Nonce', jQuery( '#wp_rest' ).val() );
|
96 |
+
}
|
97 |
+
} ).done( function ( response ) {
|
98 |
+
console.log( response );
|
99 |
+
} );
|
100 |
+
```
|
101 |
+
|
102 |
+
#### Restore via url
|
103 |
+
|
104 |
+
This needs to be fleshed out more.
|
105 |
+
|
106 |
+
```
|
107 |
+
jQuery.ajax({
|
108 |
+
url: 'https://domain.com/wp-json/bgbkup/v1/archives/?url=' + encodeURIComponent( <URL> ),
|
109 |
+
type: 'put'
|
110 |
+
});
|
111 |
+
```
|
112 |
+
|
113 |
+
## Site URL ##
|
114 |
+
|
115 |
+
### Get ###
|
116 |
+
|
117 |
+
```
|
118 |
+
jQuery.ajax( {
|
119 |
+
url: jQuery( '#bgbkup_site_url' ).val() + '/wp-json/bgbkup/v1/siteurl',
|
120 |
+
method: 'GET',
|
121 |
+
beforeSend: function ( xhr ) {
|
122 |
+
xhr.setRequestHeader( 'X-WP-Nonce', jQuery( '#wp_rest' ).val() );
|
123 |
+
}
|
124 |
+
} ).done( function ( response ) {
|
125 |
+
console.log( response );
|
126 |
+
} );
|
127 |
+
```
|
128 |
+
|
129 |
+
### Set ###
|
130 |
+
|
131 |
+
```
|
132 |
+
jQuery.ajax( {
|
133 |
+
url: jQuery( '#bgbkup_site_url' ).val() + '/wp-json/bgbkup/v1/siteurl/?siteurl=https://[NEW_SITE_URL]',
|
134 |
+
method: 'POST',
|
135 |
+
beforeSend: function ( xhr ) {
|
136 |
+
xhr.setRequestHeader( 'X-WP-Nonce', jQuery( '#wp_rest' ).val() );
|
137 |
+
}
|
138 |
+
} ).done( function ( response ) {
|
139 |
+
console.log( response );
|
140 |
+
} );
|
141 |
+
```
|
rest/class-boldgrid-backup-rest-archive.php
ADDED
@@ -0,0 +1,277 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* File: class-boldgrid-backup-rest-archive.php
|
4 |
+
*
|
5 |
+
* @link https://www.boldgrid.com
|
6 |
+
* @since SINCEVERSION
|
7 |
+
*
|
8 |
+
* @package Boldgrid_Backup
|
9 |
+
* @copyright BoldGrid
|
10 |
+
* @version $Id$
|
11 |
+
* @author BoldGrid <support@boldgrid.com>
|
12 |
+
*/
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Class: Boldgrid_Backup_Rest_Archive
|
16 |
+
*
|
17 |
+
* REST endpoints to perform simple archive manipulation.
|
18 |
+
*
|
19 |
+
* @since SINCEVERSION
|
20 |
+
*/
|
21 |
+
class Boldgrid_Backup_Rest_Archive extends Boldgrid_Backup_Rest_Controller {
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Resource name.
|
25 |
+
*
|
26 |
+
* @since SINCEVERSION
|
27 |
+
* @access private
|
28 |
+
* @var string
|
29 |
+
*/
|
30 |
+
protected $resource = 'archives';
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Register all routes.
|
34 |
+
*
|
35 |
+
* @since SINCEVERSION
|
36 |
+
*/
|
37 |
+
public function register_routes() {
|
38 |
+
$this->register_creation();
|
39 |
+
$this->register_restore();
|
40 |
+
$this->register_list();
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Register the route for creating an archive.
|
45 |
+
*
|
46 |
+
* @since SINCEVERSION
|
47 |
+
*/
|
48 |
+
public function register_creation() {
|
49 |
+
register_rest_route( $this->namespace, '/' . $this->resource, [
|
50 |
+
[
|
51 |
+
'methods' => WP_REST_Server::CREATABLE,
|
52 |
+
'callback' => [ $this, 'create_item' ],
|
53 |
+
'permission_callback' => [ $this, 'permission_check' ],
|
54 |
+
],
|
55 |
+
'schema' => [ $this, 'get_schema' ],
|
56 |
+
] );
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Register the route for restoring a backup.
|
61 |
+
*
|
62 |
+
* @since SINCEVERSION
|
63 |
+
*/
|
64 |
+
public function register_restore() {
|
65 |
+
register_rest_route( $this->namespace, '/' . $this->resource, [
|
66 |
+
[
|
67 |
+
'methods' => 'PUT',
|
68 |
+
'callback' => [ $this, 'restore' ],
|
69 |
+
'permission_callback' => [ $this, 'permission_check' ],
|
70 |
+
'args' => [
|
71 |
+
'url' => [
|
72 |
+
'required' => false,
|
73 |
+
'description' => esc_html__( 'Route URL to restore.', 'boldgrid-backup' ),
|
74 |
+
'type' => 'string',
|
75 |
+
'sanitation_callback' => function ( $field ) {
|
76 |
+
return esc_url_raw( $field );
|
77 |
+
},
|
78 |
+
],
|
79 |
+
'id' => [
|
80 |
+
'required' => false,
|
81 |
+
'description' => esc_html__( 'Backup id to restore.', 'boldgrid-backup' ),
|
82 |
+
'type' => 'integer',
|
83 |
+
'sanitation_callback' => function ( $field ) {
|
84 |
+
return (int) $field;
|
85 |
+
},
|
86 |
+
],
|
87 |
+
],
|
88 |
+
],
|
89 |
+
'schema' => [ $this, 'get_schema' ],
|
90 |
+
] );
|
91 |
+
}
|
92 |
+
|
93 |
+
/**
|
94 |
+
* Register the route for viewing a list of backups.
|
95 |
+
*
|
96 |
+
* @since SINCEVERSION
|
97 |
+
*/
|
98 |
+
public function register_list() {
|
99 |
+
register_rest_route( $this->namespace, '/' . $this->resource, [
|
100 |
+
[
|
101 |
+
'methods' => WP_REST_Server::READABLE,
|
102 |
+
'callback' => [ $this, 'get_items' ],
|
103 |
+
'permission_callback' => [ $this, 'permission_check' ],
|
104 |
+
],
|
105 |
+
'schema' => [ $this, 'get_schema' ],
|
106 |
+
] );
|
107 |
+
}
|
108 |
+
|
109 |
+
/**
|
110 |
+
* Get our sample schema for an archive.
|
111 |
+
*
|
112 |
+
* @since SINCEVERSION
|
113 |
+
*
|
114 |
+
* @return array Schema Format.
|
115 |
+
*/
|
116 |
+
public function get_schema() {
|
117 |
+
$schema = [
|
118 |
+
'$schema' => 'http://json-schema.org/draft-04/schema#',
|
119 |
+
'title' => $this->resource,
|
120 |
+
'type' => 'object',
|
121 |
+
'properties' => [
|
122 |
+
'id' => [
|
123 |
+
'context' => [ 'view' ],
|
124 |
+
'description' => esc_html__( 'Unique identifier for the object.', 'boldgrid-backup' ),
|
125 |
+
'type' => 'string',
|
126 |
+
],
|
127 |
+
'title' => [
|
128 |
+
'context' => [ 'view' ],
|
129 |
+
'description' => esc_html__( 'Name of the archive.', 'boldgrid-backup' ),
|
130 |
+
'type' => 'string',
|
131 |
+
],
|
132 |
+
'description' => [
|
133 |
+
'context' => [ 'view' ],
|
134 |
+
'description' => esc_html__( 'Description of the archive.', 'boldgrid-backup' ),
|
135 |
+
'type' => 'array',
|
136 |
+
],
|
137 |
+
'filename' => [
|
138 |
+
'context' => [ 'view' ],
|
139 |
+
'description' => esc_html__( 'Filename of backup.', 'boldgrid-backup' ),
|
140 |
+
'type' => 'string',
|
141 |
+
],
|
142 |
+
'url' => [
|
143 |
+
'context' => [ 'view' ],
|
144 |
+
'description' => esc_html__( 'Download link for the backup.', 'boldgrid-backup' ),
|
145 |
+
'type' => 'string',
|
146 |
+
],
|
147 |
+
'creation_date' => [
|
148 |
+
'context' => [ 'view' ],
|
149 |
+
'description' => esc_html__( 'Date the archive was created.', 'boldgrid-backup' ),
|
150 |
+
'type' => 'string',
|
151 |
+
],
|
152 |
+
],
|
153 |
+
];
|
154 |
+
|
155 |
+
return $schema;
|
156 |
+
}
|
157 |
+
|
158 |
+
/**
|
159 |
+
* Prepare the item for the REST response.
|
160 |
+
*
|
161 |
+
* @since SINCEVERSION
|
162 |
+
*
|
163 |
+
* @param mixed $item WordPress representation of the item.
|
164 |
+
* @param WP_REST_Request $request Request object.
|
165 |
+
* @return mixed
|
166 |
+
*/
|
167 |
+
public function prepare_item_for_response( $item, $request ) {
|
168 |
+
return $this->filter_schema_properties( $item );
|
169 |
+
}
|
170 |
+
|
171 |
+
/**
|
172 |
+
* Create a new archive.
|
173 |
+
*
|
174 |
+
* For examples, please see rest/README.MD
|
175 |
+
*
|
176 |
+
* @since SINCEVERSION
|
177 |
+
*
|
178 |
+
* @see Boldgrid_Backup_Rest_Controller::permission_check for more information if you are getting
|
179 |
+
* a 401 unauthorized error.
|
180 |
+
*
|
181 |
+
* @param WP_REST_Request $request Full data about the request.
|
182 |
+
* @return array Job Resource.
|
183 |
+
*/
|
184 |
+
public function create_item( $request ) {
|
185 |
+
// Initialize a new task.
|
186 |
+
$task = new Boldgrid_Backup_Admin_Task();
|
187 |
+
$task->init( [ 'type' => 'backup' ] );
|
188 |
+
$task->update();
|
189 |
+
$task->date_format = 'c';
|
190 |
+
|
191 |
+
// Trigger our backup.
|
192 |
+
$nopriv = new Boldgrid_Backup_Admin_Nopriv();
|
193 |
+
$nopriv->do_backup( [ 'task_id' => $task->get_id() ] );
|
194 |
+
|
195 |
+
return new WP_REST_Response( $task->get(), 200 );
|
196 |
+
}
|
197 |
+
|
198 |
+
/**
|
199 |
+
* Get all archives for a WordPress.
|
200 |
+
*
|
201 |
+
* For examples, please see rest/README.MD
|
202 |
+
*
|
203 |
+
* @since SINCEVERSION
|
204 |
+
*
|
205 |
+
* @param WP_REST_Request $request Full data about the request.
|
206 |
+
* @return array A collection of archive resources.
|
207 |
+
*/
|
208 |
+
public function get_items( $request ) {
|
209 |
+
// Init our list of raw backup data.
|
210 |
+
$core = apply_filters( 'boldgrid_backup_get_core', null );
|
211 |
+
$core->archives_all->init();
|
212 |
+
|
213 |
+
// Init our list of backups to return.
|
214 |
+
$backups = [];
|
215 |
+
|
216 |
+
foreach ( $core->archives_all->all as $backup ) {
|
217 |
+
$archive = Boldgrid\Backup\Archive\Factory::get_by_filename( $backup['filename'] );
|
218 |
+
$url = $archive->generate_download_link( $backup['filename'] );
|
219 |
+
|
220 |
+
$backups[] = [
|
221 |
+
'id' => $archive->get_id(),
|
222 |
+
'title' => $archive->get_attribute( 'title' ),
|
223 |
+
'description' => $archive->get_attribute( 'description' ),
|
224 |
+
'url' => $url['download_url'],
|
225 |
+
'filename' => $backup['filename'],
|
226 |
+
'creation_date' => date( 'c', $archive->timestamp ),
|
227 |
+
];
|
228 |
+
}
|
229 |
+
|
230 |
+
foreach ( $backups as &$backup ) {
|
231 |
+
$backup = $this->prepare_item_for_response( $backup, $request );
|
232 |
+
}
|
233 |
+
|
234 |
+
return $backups;
|
235 |
+
}
|
236 |
+
|
237 |
+
/**
|
238 |
+
* Restore an archive.
|
239 |
+
*
|
240 |
+
* For examples, please see rest/README.MD
|
241 |
+
*
|
242 |
+
* @since SINCEVERSION
|
243 |
+
*
|
244 |
+
* @param WP_REST_Request $request Full data about the request.
|
245 |
+
* @return array Job Resource.
|
246 |
+
*/
|
247 |
+
public function restore( $request ) {
|
248 |
+
$id = $request->get_param( 'id' );
|
249 |
+
$url = $request->get_param( 'url' );
|
250 |
+
|
251 |
+
// Initialize a new task.
|
252 |
+
$task = new Boldgrid_Backup_Admin_Task();
|
253 |
+
$task->init( [ 'type' => 'restore' ] );
|
254 |
+
$task->date_format = 'c';
|
255 |
+
|
256 |
+
if ( ! empty( $url ) || ! empty( $id ) ) {
|
257 |
+
// Update our task with either url or backup id.
|
258 |
+
if ( ! empty( $url ) ) {
|
259 |
+
$task->update_data( 'url', $url );
|
260 |
+
} else {
|
261 |
+
$task->update_data( 'backup_id', $id );
|
262 |
+
}
|
263 |
+
|
264 |
+
// Trigger our backup.
|
265 |
+
$nopriv = new Boldgrid_Backup_Admin_Nopriv();
|
266 |
+
$nopriv->do_restore( [ 'task_id' => $task->get_id() ] );
|
267 |
+
} else { // phpcs:ignore
|
268 |
+
return new WP_Error(
|
269 |
+
'bgbkup_rest_missing_param',
|
270 |
+
__( 'Unable to restore. Missing required parameters.', 'boldgrid-backup' ),
|
271 |
+
[ 'status' => 400 ]
|
272 |
+
);
|
273 |
+
}
|
274 |
+
|
275 |
+
return new WP_REST_Response( $task->get(), 200 );
|
276 |
+
}
|
277 |
+
}
|
rest/class-boldgrid-backup-rest-controller.php
ADDED
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* File: class-boldgrid-backup-rest-controller.php
|
4 |
+
*
|
5 |
+
* @link https://www.boldgrid.com
|
6 |
+
* @since SINCEVERSION
|
7 |
+
*
|
8 |
+
* @package Boldgrid_Backup
|
9 |
+
* @copyright BoldGrid
|
10 |
+
* @version $Id$
|
11 |
+
* @author BoldGrid <support@boldgrid.com>
|
12 |
+
*/
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Class: Boldgrid_Backup_Rest_Controller
|
16 |
+
*
|
17 |
+
* A base class for the wp rest controller.
|
18 |
+
*
|
19 |
+
* @since SINCEVERSION
|
20 |
+
*/
|
21 |
+
class Boldgrid_Backup_Rest_Controller extends WP_REST_Controller {
|
22 |
+
|
23 |
+
/**
|
24 |
+
* The core class object.
|
25 |
+
*
|
26 |
+
* @since SINCEVERSION
|
27 |
+
* @access private
|
28 |
+
* @var Boldgrid_Backup_Admin_Core
|
29 |
+
*/
|
30 |
+
protected $core;
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Namespace of the class.
|
34 |
+
*
|
35 |
+
* @since SINCEVERSION
|
36 |
+
* @access private
|
37 |
+
* @var string
|
38 |
+
*/
|
39 |
+
protected $namespace = 'bgbkup/v1';
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Setup the core backup class.
|
43 |
+
*
|
44 |
+
* @since SINCEVERSION
|
45 |
+
* @param Boldgrid_Backup_Admin_Core $core Core Backup class.
|
46 |
+
*/
|
47 |
+
public function __construct( $core ) {
|
48 |
+
$this->core = $core;
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Ensure user has access to any of the archive endpoints.
|
53 |
+
*
|
54 |
+
* @since SINCEVERSION
|
55 |
+
*
|
56 |
+
* @return boolean Has Access?
|
57 |
+
*/
|
58 |
+
public function permission_check() {
|
59 |
+
return current_user_can( 'activate_plugins' );
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Make sure that an item only has the items present in the schema.
|
64 |
+
*
|
65 |
+
* @since SINCEVERSION
|
66 |
+
*
|
67 |
+
* @param array $item Resource Item.
|
68 |
+
* @return array Updated resource item.
|
69 |
+
*/
|
70 |
+
protected function filter_schema_properties( $item ) {
|
71 |
+
$resource = [];
|
72 |
+
$schema = $this->get_schema();
|
73 |
+
foreach ( $schema['properties'] as $name => $property ) {
|
74 |
+
if ( isset( $item[ $name ] ) ) {
|
75 |
+
$resource[ $name ] = $item[ $name ];
|
76 |
+
} else {
|
77 |
+
$resource[ $name ] = 'array' === $property['type'] ? [] : null;
|
78 |
+
}
|
79 |
+
}
|
80 |
+
|
81 |
+
return $resource;
|
82 |
+
}
|
83 |
+
|
84 |
+
}
|
rest/class-boldgrid-backup-rest-job.php
ADDED
@@ -0,0 +1,146 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* File: class-boldgrid-backup-rest-job.php
|
4 |
+
*
|
5 |
+
* @link https://www.boldgrid.com
|
6 |
+
* @since SINCEVERSION
|
7 |
+
*
|
8 |
+
* @package Boldgrid_Backup
|
9 |
+
* @copyright BoldGrid
|
10 |
+
* @version $Id$
|
11 |
+
* @author BoldGrid <support@boldgrid.com>
|
12 |
+
*/
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Class: Boldgrid_Backup_Rest_Job
|
16 |
+
*
|
17 |
+
* REST endpoints to perform get jobs.
|
18 |
+
*
|
19 |
+
* @since SINCEVERSION
|
20 |
+
*/
|
21 |
+
class Boldgrid_Backup_Rest_Job extends Boldgrid_Backup_Rest_Controller {
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Resource name.
|
25 |
+
*
|
26 |
+
* @since SINCEVERSION
|
27 |
+
* @access private
|
28 |
+
* @var string
|
29 |
+
*/
|
30 |
+
protected $resource = 'jobs';
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Register the routes for the objects of the controller.
|
34 |
+
*
|
35 |
+
* @since SINCEVERSION
|
36 |
+
*/
|
37 |
+
public function register_routes() {
|
38 |
+
register_rest_route( $this->namespace, '/' . $this->resource . '/(?P<id>[\w-]+)', [
|
39 |
+
[
|
40 |
+
'methods' => WP_REST_Server::READABLE,
|
41 |
+
'callback' => [ $this, 'get_item' ],
|
42 |
+
'permission_callback' => [ $this, 'permission_check' ],
|
43 |
+
'args' => [
|
44 |
+
'id' => [
|
45 |
+
'required' => true,
|
46 |
+
'context' => [ 'view' ],
|
47 |
+
'description' => esc_html__( 'Unique identifier for the object.', 'boldgrid-backup' ),
|
48 |
+
'type' => 'string',
|
49 |
+
],
|
50 |
+
],
|
51 |
+
],
|
52 |
+
'schema' => [ $this, 'get_schema' ],
|
53 |
+
] );
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Get our sample schema for comments.
|
58 |
+
*
|
59 |
+
* @since SINCEVERSION
|
60 |
+
*
|
61 |
+
* @return array Schema Format.
|
62 |
+
*/
|
63 |
+
public function get_schema() {
|
64 |
+
$schema = [
|
65 |
+
'$schema' => 'http://json-schema.org/draft-04/schema#',
|
66 |
+
'title' => 'job',
|
67 |
+
'type' => 'object',
|
68 |
+
'properties' => [
|
69 |
+
'id' => [
|
70 |
+
'context' => [ 'view' ],
|
71 |
+
'description' => esc_html__( 'Unique identifier for the object.', 'boldgrid-backup' ),
|
72 |
+
'type' => 'string',
|
73 |
+
],
|
74 |
+
'type' => [
|
75 |
+
'context' => [ 'view' ],
|
76 |
+
'description' => esc_html__( 'Type of job.', 'boldgrid-backup' ),
|
77 |
+
'type' => 'string',
|
78 |
+
'enum' => [
|
79 |
+
'backup',
|
80 |
+
'restoration',
|
81 |
+
],
|
82 |
+
],
|
83 |
+
'status' => [
|
84 |
+
'context' => [ 'view' ],
|
85 |
+
'description' => esc_html__( 'Currently status of the job.', 'boldgrid-backup' ),
|
86 |
+
'type' => 'string',
|
87 |
+
],
|
88 |
+
'started_at' => [
|
89 |
+
'context' => [ 'view' ],
|
90 |
+
'description' => esc_html__( 'Information attached to the start of the prcoess.', 'boldgrid-backup' ),
|
91 |
+
'type' => 'string',
|
92 |
+
],
|
93 |
+
'completed_at' => [
|
94 |
+
'context' => [ 'view' ],
|
95 |
+
'description' => esc_html__( 'Results of the process.', 'boldgrid-backup' ),
|
96 |
+
'type' => 'string',
|
97 |
+
],
|
98 |
+
],
|
99 |
+
];
|
100 |
+
|
101 |
+
return $schema;
|
102 |
+
}
|
103 |
+
|
104 |
+
/**
|
105 |
+
* Prepare the item for the REST response.
|
106 |
+
*
|
107 |
+
* @since SINCEVERSION
|
108 |
+
*
|
109 |
+
* @param mixed $item WordPress representation of the item.
|
110 |
+
* @param WP_REST_Request $request Request object.
|
111 |
+
* @return mixed
|
112 |
+
*/
|
113 |
+
public function prepare_item_for_response( $item, $request ) {
|
114 |
+
return $this->filter_schema_properties( $item );
|
115 |
+
}
|
116 |
+
|
117 |
+
/**
|
118 |
+
* Get one item from the collection.
|
119 |
+
*
|
120 |
+
* Example call:
|
121 |
+
* jQuery.get( 'https://domain/wp-json/bgbkup/v1/jobs/<JOB-ID>' );
|
122 |
+
*
|
123 |
+
* @since SINCEVERSION
|
124 |
+
*
|
125 |
+
* @param WP_REST_Request $request Full data about the request.
|
126 |
+
* @return WP_Error|WP_REST_Response
|
127 |
+
*/
|
128 |
+
public function get_item( $request ) {
|
129 |
+
$id = $request->get_param( 'id' );
|
130 |
+
|
131 |
+
$task = new Boldgrid_Backup_Admin_Task();
|
132 |
+
$found = $task->init_by_id( $id );
|
133 |
+
|
134 |
+
$task->date_format = 'c';
|
135 |
+
|
136 |
+
$item = $found ? $task->get() : null;
|
137 |
+
if ( ! empty( $item ) ) {
|
138 |
+
$data = $this->prepare_item_for_response( $item, $request );
|
139 |
+
return new WP_REST_Response( $data, 200 );
|
140 |
+
} else {
|
141 |
+
return new WP_Error( 'no_job', esc_html__( 'Job Not found', 'boldgrid-backup' ), [
|
142 |
+
'status' => 404,
|
143 |
+
] );
|
144 |
+
}
|
145 |
+
}
|
146 |
+
}
|
rest/class-boldgrid-backup-rest-setting.php
ADDED
@@ -0,0 +1,195 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* File: class-boldgrid-backup-rest-setting.php
|
4 |
+
*
|
5 |
+
* @link https://www.boldgrid.com
|
6 |
+
* @since SINCEVERSION
|
7 |
+
*
|
8 |
+
* @package Boldgrid_Backup
|
9 |
+
* @copyright BoldGrid
|
10 |
+
* @version $Id$
|
11 |
+
* @author BoldGrid <support@boldgrid.com>
|
12 |
+
*/
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Class: Boldgrid_Backup_Rest_Setting
|
16 |
+
*
|
17 |
+
* REST endpoints to access the backup settings.
|
18 |
+
*
|
19 |
+
* @since SINCEVERSION
|
20 |
+
*/
|
21 |
+
class Boldgrid_Backup_Rest_Setting extends Boldgrid_Backup_Rest_Controller {
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Resource name.
|
25 |
+
*
|
26 |
+
* @since SINCEVERSION
|
27 |
+
* @access private
|
28 |
+
* @var string
|
29 |
+
*/
|
30 |
+
protected $resource = 'settings';
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Register the routes for the objects of the controller.
|
34 |
+
*
|
35 |
+
* @since SINCEVERSION
|
36 |
+
*/
|
37 |
+
public function register_routes() {
|
38 |
+
$this->register_get();
|
39 |
+
$this->register_update();
|
40 |
+
}
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Register the route for creating a backup.
|
44 |
+
*
|
45 |
+
* @since SINCEVERSION
|
46 |
+
*/
|
47 |
+
public function register_get() {
|
48 |
+
register_rest_route( $this->namespace, '/' . $this->resource, [
|
49 |
+
[
|
50 |
+
'methods' => WP_REST_Server::READABLE,
|
51 |
+
'callback' => [ $this, 'get_item' ],
|
52 |
+
'permission_callback' => [ $this, 'permission_check' ],
|
53 |
+
],
|
54 |
+
'schema' => [ $this, 'get_schema' ],
|
55 |
+
] );
|
56 |
+
}
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Register router for updating settings.
|
60 |
+
*
|
61 |
+
* @since SINCEVERSION
|
62 |
+
*/
|
63 |
+
public function register_update() {
|
64 |
+
register_rest_route( $this->namespace, '/' . $this->resource, [
|
65 |
+
[
|
66 |
+
'methods' => WP_REST_Server::EDITABLE,
|
67 |
+
'callback' => [ $this, 'update_item' ],
|
68 |
+
'permission_callback' => [ $this, 'permission_check' ],
|
69 |
+
],
|
70 |
+
'schema' => [ $this, 'get_schema' ],
|
71 |
+
] );
|
72 |
+
}
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Prepare the item for the REST response.
|
76 |
+
*
|
77 |
+
* @since SINCEVERSION
|
78 |
+
*
|
79 |
+
* @param mixed $item WordPress representation of the item.
|
80 |
+
* @param WP_REST_Request $request Request object.
|
81 |
+
* @return mixed
|
82 |
+
*/
|
83 |
+
public function prepare_item_for_response( $item, $request ) {
|
84 |
+
return $this->filter_schema_properties( $item );
|
85 |
+
}
|
86 |
+
|
87 |
+
/**
|
88 |
+
* Get schema for settings.
|
89 |
+
*
|
90 |
+
* @since SINCEVERSION
|
91 |
+
*
|
92 |
+
* @return array Schema Format.
|
93 |
+
*/
|
94 |
+
public function get_schema() {
|
95 |
+
$schema = [
|
96 |
+
'$schema' => 'http://json-schema.org/draft-04/schema#',
|
97 |
+
'title' => $this->resource,
|
98 |
+
'type' => 'object',
|
99 |
+
'properties' => [
|
100 |
+
'schedule' => [
|
101 |
+
'context' => [ 'view' ],
|
102 |
+
'description' => esc_html__( 'Date the backup was created.', 'boldgrid-backup' ),
|
103 |
+
'type' => 'array',
|
104 |
+
],
|
105 |
+
'autoupdate' => [
|
106 |
+
'context' => [ 'view' ],
|
107 |
+
'description' => esc_html__( 'Automatic Update.', 'boldgrid-backup' ),
|
108 |
+
'type' => 'array',
|
109 |
+
],
|
110 |
+
'notification_email' => [
|
111 |
+
'context' => [ 'view' ],
|
112 |
+
'description' => esc_html__( 'Email to notify got backups.', 'boldgrid-backup' ),
|
113 |
+
'type' => 'string',
|
114 |
+
],
|
115 |
+
'auto_backup' => [
|
116 |
+
'context' => [ 'view' ],
|
117 |
+
'description' => esc_html__( 'Does a site have auto backups enabled?', 'boldgrid-backup' ),
|
118 |
+
'type' => 'integer',
|
119 |
+
],
|
120 |
+
'auto_backup' => [
|
121 |
+
'context' => [ 'view' ],
|
122 |
+
'description' => esc_html__( 'Does a site have auto rollback enabled?', 'boldgrid-backup' ),
|
123 |
+
'type' => 'integer',
|
124 |
+
],
|
125 |
+
'folder_exclusion_include' => [
|
126 |
+
'context' => [ 'view' ],
|
127 |
+
'description' => esc_html__( 'Directories and files to include.', 'boldgrid-backup' ),
|
128 |
+
'type' => 'string',
|
129 |
+
],
|
130 |
+
'folder_exclusion_exclude' => [
|
131 |
+
'context' => [ 'view' ],
|
132 |
+
'description' => esc_html__( 'Directories and files to exclude.', 'boldgrid-backup' ),
|
133 |
+
'type' => 'string',
|
134 |
+
],
|
135 |
+
],
|
136 |
+
];
|
137 |
+
|
138 |
+
return $schema;
|
139 |
+
}
|
140 |
+
|
141 |
+
/**
|
142 |
+
* Get the users plugin settings.
|
143 |
+
*
|
144 |
+
* @since SINCEVERSION
|
145 |
+
*
|
146 |
+
* @param WP_REST_Request $request Request object.
|
147 |
+
* @return array Plugin settings.
|
148 |
+
*/
|
149 |
+
public function get_item( $request ) {
|
150 |
+
$settings = get_option( 'boldgrid_backup_settings', [] );
|
151 |
+
$boldgrid_settings = get_option( 'boldgrid_settings' );
|
152 |
+
|
153 |
+
$settings['autoupdate'] = isset( $boldgrid_settings['autoupdate'] ) ? $boldgrid_settings['autoupdate'] : null;
|
154 |
+
|
155 |
+
return $this->prepare_item_for_response( $settings, $request );
|
156 |
+
}
|
157 |
+
|
158 |
+
/**
|
159 |
+
* Update settings through API.
|
160 |
+
*
|
161 |
+
* @since SINCEVERSION
|
162 |
+
*
|
163 |
+
* @param WP_REST_Request $request Request object.
|
164 |
+
* @return array Updated Settings.
|
165 |
+
*/
|
166 |
+
public function update_item( $request ) {
|
167 |
+
$schema = $this->get_schema();
|
168 |
+
$settings = get_option( 'boldgrid_backup_settings', [] );
|
169 |
+
$requested_settings = $request->get_param( 'settings' );
|
170 |
+
|
171 |
+
foreach ( $schema['properties'] as $name => $value ) {
|
172 |
+
if ( isset( $requested_settings[ $name ] ) ) {
|
173 |
+
$settings[ $name ] = $requested_settings[ $name ];
|
174 |
+
}
|
175 |
+
}
|
176 |
+
|
177 |
+
$scheduler = new Boldgrid_Backup_Admin_Scheduler( $this->core );
|
178 |
+
$settings['scheduler'] = $scheduler->get();
|
179 |
+
|
180 |
+
$admin_settings = new Boldgrid_Backup_Admin_Settings( $this->core );
|
181 |
+
$settings = $admin_settings->update_cron( $settings );
|
182 |
+
|
183 |
+
// Update Settings.
|
184 |
+
update_option( 'boldgrid_backup_settings', $settings );
|
185 |
+
|
186 |
+
// Update the auto update setting.
|
187 |
+
if ( ! empty( $requested_settings['autoupdate'] ) ) {
|
188 |
+
$boldgrid_settings = get_option( 'boldgrid_settings' );
|
189 |
+
$boldgrid_settings['autoupdate'] = $requested_settings['autoupdate'];
|
190 |
+
update_option( 'boldgrid_settings', $boldgrid_settings );
|
191 |
+
}
|
192 |
+
|
193 |
+
return $this->get_item( $request );
|
194 |
+
}
|
195 |
+
}
|
rest/class-boldgrid-backup-rest-siteurl.php
ADDED
@@ -0,0 +1,178 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* File: class-boldgrid-backup-rest-siteurl.php
|
4 |
+
*
|
5 |
+
* @link https://www.boldgrid.com
|
6 |
+
* @since SINCEVERSION
|
7 |
+
*
|
8 |
+
* @package Boldgrid_Backup
|
9 |
+
* @copyright BoldGrid
|
10 |
+
* @version $Id$
|
11 |
+
* @author BoldGrid <support@boldgrid.com>
|
12 |
+
*/
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Class: Boldgrid_Backup_Rest_Siteurl
|
16 |
+
*
|
17 |
+
* REST endpoint for the siteurl.
|
18 |
+
*
|
19 |
+
* @since SINCEVERSION
|
20 |
+
*/
|
21 |
+
class Boldgrid_Backup_Rest_Siteurl extends Boldgrid_Backup_Rest_Controller {
|
22 |
+
/**
|
23 |
+
* Resource name.
|
24 |
+
*
|
25 |
+
* @since SINCEVERSION
|
26 |
+
* @access private
|
27 |
+
* @var string
|
28 |
+
*/
|
29 |
+
protected $resource = 'siteurl';
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Register the routes for the objects of the controller.
|
33 |
+
*
|
34 |
+
* @since SINCEVERSION
|
35 |
+
*/
|
36 |
+
public function register_routes() {
|
37 |
+
$this->register_get();
|
38 |
+
$this->register_update();
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Register the route for creating a backup.
|
43 |
+
*
|
44 |
+
* @since SINCEVERSION
|
45 |
+
*/
|
46 |
+
public function register_get() {
|
47 |
+
register_rest_route( $this->namespace, '/' . $this->resource, [
|
48 |
+
[
|
49 |
+
'methods' => WP_REST_Server::READABLE,
|
50 |
+
'callback' => [ $this, 'get_item' ],
|
51 |
+
'permission_callback' => [ $this, 'permission_check' ],
|
52 |
+
],
|
53 |
+
'schema' => [ $this, 'get_schema' ],
|
54 |
+
] );
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Register router for updating settings.
|
59 |
+
*
|
60 |
+
* @since SINCEVERSION
|
61 |
+
*/
|
62 |
+
public function register_update() {
|
63 |
+
register_rest_route( $this->namespace, '/' . $this->resource, [
|
64 |
+
[
|
65 |
+
'methods' => WP_REST_Server::EDITABLE,
|
66 |
+
'callback' => [ $this, 'update_item' ],
|
67 |
+
'permission_callback' => [ $this, 'permission_check' ],
|
68 |
+
'args' => array(
|
69 |
+
'siteurl' => array(
|
70 |
+
'required' => true,
|
71 |
+
'description' => esc_html__( 'New site url.', 'boldgrid-backup' ),
|
72 |
+
'type' => 'string',
|
73 |
+
'sanitation_callback' => function ( $field ) {
|
74 |
+
return esc_url_raw( $field );
|
75 |
+
},
|
76 |
+
),
|
77 |
+
),
|
78 |
+
],
|
79 |
+
'schema' => [ $this, 'get_schema' ],
|
80 |
+
] );
|
81 |
+
}
|
82 |
+
|
83 |
+
/**
|
84 |
+
* Prepare the item for the REST response.
|
85 |
+
*
|
86 |
+
* @since SINCEVERSION
|
87 |
+
*
|
88 |
+
* @param mixed $item WordPress representation of the item.
|
89 |
+
* @param WP_REST_Request $request Request object.
|
90 |
+
* @return mixed
|
91 |
+
*/
|
92 |
+
public function prepare_item_for_response( $item, $request ) {
|
93 |
+
return $this->filter_schema_properties( $item );
|
94 |
+
}
|
95 |
+
|
96 |
+
/**
|
97 |
+
* Get schema for settings.
|
98 |
+
*
|
99 |
+
* @since SINCEVERSION
|
100 |
+
*
|
101 |
+
* @return array Schema Format.
|
102 |
+
*/
|
103 |
+
public function get_schema() {
|
104 |
+
$schema = [
|
105 |
+
'$schema' => 'http://json-schema.org/draft-04/schema#',
|
106 |
+
'title' => $this->resource,
|
107 |
+
'type' => 'object',
|
108 |
+
'properties' => [
|
109 |
+
'home' => [
|
110 |
+
'context' => [ 'view' ],
|
111 |
+
'description' => esc_html__( 'Home.', 'boldgrid-backup' ),
|
112 |
+
'type' => 'string',
|
113 |
+
],
|
114 |
+
'siteurl' => [
|
115 |
+
'context' => [ 'view' ],
|
116 |
+
'description' => esc_html__( 'Siteurl.', 'boldgrid-backup' ),
|
117 |
+
'type' => 'string',
|
118 |
+
],
|
119 |
+
'old_home' => [
|
120 |
+
'context' => [ 'view' ],
|
121 |
+
'description' => esc_html__( 'Old home (before changing).', 'boldgrid-backup' ),
|
122 |
+
'type' => 'string',
|
123 |
+
],
|
124 |
+
'old_siteurl' => [
|
125 |
+
'context' => [ 'view' ],
|
126 |
+
'description' => esc_html__( 'Old siteurl (before changing).', 'boldgrid-backup' ),
|
127 |
+
'type' => 'string',
|
128 |
+
],
|
129 |
+
],
|
130 |
+
];
|
131 |
+
|
132 |
+
return $schema;
|
133 |
+
}
|
134 |
+
|
135 |
+
/**
|
136 |
+
* Get the users plugin settings.
|
137 |
+
*
|
138 |
+
* @since SINCEVERSION
|
139 |
+
*
|
140 |
+
* @param WP_REST_Request $request Request object.
|
141 |
+
* @return array Plugin settings.
|
142 |
+
*/
|
143 |
+
public function get_item( $request ) {
|
144 |
+
return $this->prepare_item_for_response( array(
|
145 |
+
'home' => get_option( 'home' ),
|
146 |
+
'siteurl' => get_option( 'siteurl' ),
|
147 |
+
), $request );
|
148 |
+
}
|
149 |
+
|
150 |
+
/**
|
151 |
+
* Update a site url via a REST call.
|
152 |
+
*
|
153 |
+
* @since SINCEVERSION
|
154 |
+
*
|
155 |
+
* @param WP_REST_Request $request Request object.
|
156 |
+
* @return array Updated Settings.
|
157 |
+
*/
|
158 |
+
public function update_item( $request ) {
|
159 |
+
$old_home = get_option( 'home' );
|
160 |
+
$old_siteurl = get_option( 'siteurl' );
|
161 |
+
|
162 |
+
// Get the new site url.
|
163 |
+
$siteurl = $request->get_param( 'siteurl' );
|
164 |
+
|
165 |
+
Boldgrid_Backup_Admin_Utility::update_siteurl( array(
|
166 |
+
'old_siteurl' => $old_siteurl,
|
167 |
+
'siteurl' => $siteurl,
|
168 |
+
'flush' => true,
|
169 |
+
) );
|
170 |
+
|
171 |
+
return $this->prepare_item_for_response( array(
|
172 |
+
'old_home' => $old_home,
|
173 |
+
'old_siteurl' => $old_siteurl,
|
174 |
+
'home' => get_option( 'home' ),
|
175 |
+
'siteurl' => get_option( 'siteurl' ),
|
176 |
+
), $request );
|
177 |
+
}
|
178 |
+
}
|
rest/class-boldgrid-backup-rest-test.php
ADDED
@@ -0,0 +1,107 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* File: class-boldgrid-backup-rest-test.php
|
4 |
+
*
|
5 |
+
* @link https://www.boldgrid.com
|
6 |
+
* @since SINCEVERSION
|
7 |
+
*
|
8 |
+
* @package Boldgrid_Backup
|
9 |
+
* @copyright BoldGrid
|
10 |
+
* @version $Id$
|
11 |
+
* @author BoldGrid <support@boldgrid.com>
|
12 |
+
*/
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Class: Boldgrid_Backup_Rest_Test
|
16 |
+
*
|
17 |
+
* REST endpoints to access the backup preflight check results.
|
18 |
+
*
|
19 |
+
* @since SINCEVERSION
|
20 |
+
*/
|
21 |
+
class Boldgrid_Backup_Rest_Test extends Boldgrid_Backup_Rest_Controller {
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Resource name.
|
25 |
+
*
|
26 |
+
* @since SINCEVERSION
|
27 |
+
* @access private
|
28 |
+
* @var string
|
29 |
+
*/
|
30 |
+
protected $resource = 'test';
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Register the routes for the objects of the controller.
|
34 |
+
*
|
35 |
+
* @since SINCEVERSION
|
36 |
+
*/
|
37 |
+
public function register_routes() {
|
38 |
+
$this->register_get();
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Register the route for getting test results.
|
43 |
+
*
|
44 |
+
* @since SINCEVERSION
|
45 |
+
*/
|
46 |
+
public function register_get() {
|
47 |
+
register_rest_route( $this->namespace, '/' . $this->resource, [
|
48 |
+
[
|
49 |
+
'methods' => WP_REST_Server::READABLE,
|
50 |
+
'callback' => [ $this, 'get_item' ],
|
51 |
+
'permission_callback' => [ $this, 'permission_check' ],
|
52 |
+
],
|
53 |
+
'schema' => [ $this, 'get_schema' ],
|
54 |
+
] );
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Prepare the item for the REST response.
|
59 |
+
*
|
60 |
+
* @since SINCEVERSION
|
61 |
+
*
|
62 |
+
* @param mixed $item WordPress representation of the item.
|
63 |
+
* @param WP_REST_Request $request Request object.
|
64 |
+
* @return mixed
|
65 |
+
*/
|
66 |
+
public function prepare_item_for_response( $item, $request ) {
|
67 |
+
return $this->filter_schema_properties( $item );
|
68 |
+
}
|
69 |
+
|
70 |
+
/**
|
71 |
+
* Get schema for results.
|
72 |
+
*
|
73 |
+
* @since SINCEVERSION
|
74 |
+
*
|
75 |
+
* @return array Schema Format.
|
76 |
+
*/
|
77 |
+
public function get_schema() {
|
78 |
+
$schema = [
|
79 |
+
'$schema' => 'http://json-schema.org/draft-04/schema#',
|
80 |
+
'title' => $this->resource,
|
81 |
+
'type' => 'object',
|
82 |
+
'properties' => [
|
83 |
+
'passed' => [
|
84 |
+
'context' => [ 'view' ],
|
85 |
+
'description' => esc_html__( 'Whether or not the site passed the preflight check.', 'boldgrid-backup' ),
|
86 |
+
'type' => 'bool',
|
87 |
+
],
|
88 |
+
],
|
89 |
+
];
|
90 |
+
|
91 |
+
return $schema;
|
92 |
+
}
|
93 |
+
|
94 |
+
/**
|
95 |
+
* Get the the preflight check results.
|
96 |
+
*
|
97 |
+
* @since SINCEVERSION
|
98 |
+
*
|
99 |
+
* @param WP_REST_Request $request Request object.
|
100 |
+
* @return array Preflight check results.
|
101 |
+
*/
|
102 |
+
public function get_item( $request ) {
|
103 |
+
$preflight_test = new Boldgrid_Backup_Admin_Test( $this->core );
|
104 |
+
$settings['passed'] = $preflight_test->run_functionality_tests();
|
105 |
+
return $this->prepare_item_for_response( $settings, $request );
|
106 |
+
}
|
107 |
+
}
|
rest/class-boldgrid-backup-rest-utility.php
ADDED
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* File: class-boldgrid-backup-rest-utility.php
|
4 |
+
*
|
5 |
+
* @link https://www.boldgrid.com
|
6 |
+
* @since SINCEVERSION
|
7 |
+
*
|
8 |
+
* @package Boldgrid_Backup
|
9 |
+
* @copyright BoldGrid
|
10 |
+
* @version $Id$
|
11 |
+
* @author BoldGrid <support@boldgrid.com>
|
12 |
+
*/
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Class: Boldgrid_Backup_Rest_Utility
|
16 |
+
*
|
17 |
+
* @since SINCEVERSION
|
18 |
+
*/
|
19 |
+
class Boldgrid_Backup_Rest_Utility {
|
20 |
+
/**
|
21 |
+
* Get the current url.
|
22 |
+
*
|
23 |
+
* @since SINCEVERSION
|
24 |
+
*
|
25 |
+
* @return string
|
26 |
+
*/
|
27 |
+
public static function get_current_url() {
|
28 |
+
$url = '';
|
29 |
+
|
30 |
+
if ( ! empty( $_SERVER['HTTP_HOST'] ) ) {
|
31 |
+
$url = ( is_ssl() ? 'https' : 'http' ) . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
|
32 |
+
}
|
33 |
+
|
34 |
+
return $url;
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Echo a wp_rest nonce to the screen.
|
39 |
+
*
|
40 |
+
* This method is only using for testing, and is only called in a dev environment.
|
41 |
+
*
|
42 |
+
* @since SINCEVERSION
|
43 |
+
*
|
44 |
+
* @see Boldgrid_Backup::define_admin_hooks() For more info on how this method is used within a
|
45 |
+
* dev environment.
|
46 |
+
* @see rest/README.MD For a list of example rest calls that depend on this
|
47 |
+
* method.
|
48 |
+
*/
|
49 |
+
public static function insert_nonce() {
|
50 |
+
wp_nonce_field( 'wp_rest', 'wp_rest' );
|
51 |
+
echo '<input type="hidden" id="bgbkup_site_url" value="' . esc_attr( get_site_url() ) . '" />';
|
52 |
+
}
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Whether or not we're in a REST call.
|
56 |
+
*
|
57 |
+
* @since SINCEVERSION
|
58 |
+
*
|
59 |
+
* @return bool
|
60 |
+
*/
|
61 |
+
public static function is_rest() {
|
62 |
+
$current_url = self::get_current_url();
|
63 |
+
|
64 |
+
// True when the current url begins with http://domain.com/wp-json/.
|
65 |
+
$rest_prefix = get_site_url( null, 'wp-json/' );
|
66 |
+
$in_pretty_permalink = substr( $current_url, 0, strlen( $rest_prefix ) ) === $rest_prefix;
|
67 |
+
|
68 |
+
// True when the current url begins with http://domain.com/index.php/wp-json/
|
69 |
+
$rest_prefix = get_site_url( null, 'index.php/wp-json/' );
|
70 |
+
$in_index_url = substr( $current_url, 0, strlen( $rest_prefix ) ) === $rest_prefix;
|
71 |
+
|
72 |
+
// True when url includes the rest_route parameter.
|
73 |
+
$in_get = ! empty( $_GET['rest_route'] ); // phpcs:ignore
|
74 |
+
|
75 |
+
return $in_pretty_permalink || $in_index_url || $in_get;
|
76 |
+
}
|
77 |
+
}
|
vendor/autoload.php
CHANGED
@@ -4,4 +4,4 @@
|
|
4 |
|
5 |
require_once __DIR__ . '/composer/autoload_real.php';
|
6 |
|
7 |
-
return
|
4 |
|
5 |
require_once __DIR__ . '/composer/autoload_real.php';
|
6 |
|
7 |
+
return ComposerAutoloaderInit21ce95d681fa0cbccf157df200b627c0::getLoader();
|
vendor/boldgrid/library/.travis.yml
CHANGED
@@ -1,26 +1,48 @@
|
|
1 |
language: php
|
2 |
|
3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
|
5 |
notifications:
|
6 |
email:
|
7 |
on_success: never
|
8 |
on_failure: change
|
9 |
|
10 |
-
php
|
11 |
-
- 5.6
|
12 |
|
13 |
-
language: node_js
|
14 |
node_js:
|
15 |
-
|
16 |
|
17 |
env:
|
18 |
- WP_VERSION=latest WP_MULTISITE=0
|
19 |
|
20 |
-
|
21 |
-
|
22 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
|
24 |
script:
|
25 |
-
- phpunit --debug
|
26 |
-
|
|
|
|
1 |
language: php
|
2 |
|
3 |
+
# Distrubution / environments: https://docs.travis-ci.com/user/reference/overview/
|
4 |
+
# Ubuntu Trusty does not support php8: https://docs.travis-ci.com/user/languages/php/
|
5 |
+
dist: focal
|
6 |
+
|
7 |
+
services:
|
8 |
+
# Specifically including MySQL was not needed with Trusty, but other environments do need it.
|
9 |
+
- mysql
|
10 |
|
11 |
notifications:
|
12 |
email:
|
13 |
on_success: never
|
14 |
on_failure: change
|
15 |
|
16 |
+
language: php, node_js
|
|
|
17 |
|
|
|
18 |
node_js:
|
19 |
+
- lts/*
|
20 |
|
21 |
env:
|
22 |
- WP_VERSION=latest WP_MULTISITE=0
|
23 |
|
24 |
+
matrix:
|
25 |
+
include:
|
26 |
+
- php: 7.4
|
27 |
+
before_script:
|
28 |
+
- yarn install
|
29 |
+
# Remove phpunit and install best phpunit version based on this environment.
|
30 |
+
- composer update phpunit/phpunit
|
31 |
+
# A note on our composer / yarn usage:
|
32 |
+
# Our composer post-autoload-dump script will copy files from within node_modules/* to our plugin
|
33 |
+
# and then delete the node_modules folder. If node_modules are needed after this point, such
|
34 |
+
# as for "yarn run js-lint", another "yarn install" will be needed.
|
35 |
+
- composer install -o
|
36 |
+
- bash bin/install-wp-tests.sh wordpress_test root '' localhost $WP_VERSION
|
37 |
+
- php: 8.0
|
38 |
+
before_script:
|
39 |
+
- yarn install
|
40 |
+
- composer update phpunit/phpunit
|
41 |
+
- composer install -o
|
42 |
+
- bash bin/install-wp-tests.sh wordpress_test root '' localhost $WP_VERSION
|
43 |
|
44 |
script:
|
45 |
+
- vendor/phpunit/phpunit/phpunit --debug
|
46 |
+
# Temporarily disabling js-lint. @todo This needs to be fixed.
|
47 |
+
# The current config used, eslint-config-wordpress, is deprecated. That packages names replacements.
|
48 |
+
# - yarn run js-lint
|
vendor/boldgrid/library/README.md
CHANGED
@@ -11,6 +11,26 @@ composer require boldgrid/library
|
|
11 |
|
12 |
## Changelog ##
|
13 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
### 2.13.3 ###
|
15 |
|
16 |
Release date: October 13th, 2020
|
11 |
|
12 |
## Changelog ##
|
13 |
|
14 |
+
### 2.13.6 ###
|
15 |
+
|
16 |
+
Release date: March 15th, 2022
|
17 |
+
|
18 |
+
* Update: Allow configs to be updated via an option.
|
19 |
+
* Update: Misc updates to automated tests.
|
20 |
+
* Bug fix: Avoid issues on the ftp filesystem.
|
21 |
+
|
22 |
+
### 2.13.5 ###
|
23 |
+
|
24 |
+
Release date: September 8, 2021
|
25 |
+
|
26 |
+
* Bug Fix: Review prompt prevents admins from deleting other user accounts [#192](https://github.com/BoldGrid/post-and-page-builder/issues/192)
|
27 |
+
|
28 |
+
### 2.13.4 ###
|
29 |
+
|
30 |
+
Release date: June 10th, 2021
|
31 |
+
|
32 |
+
* Bug Fix: Avoid PHP Error in Dashboard/SortWidgets.php by validating widget containers.
|
33 |
+
|
34 |
### 2.13.3 ###
|
35 |
|
36 |
Release date: October 13th, 2020
|
vendor/boldgrid/library/bin/install-wp-tests.sh
CHANGED
@@ -19,14 +19,16 @@ set -ex
|
|
19 |
install_wp() {
|
20 |
mkdir -p $WP_CORE_DIR
|
21 |
|
22 |
-
if [ $WP_VERSION == 'latest' ]; then
|
23 |
local ARCHIVE_NAME='latest'
|
24 |
else
|
25 |
local ARCHIVE_NAME="wordpress-$WP_VERSION"
|
26 |
fi
|
27 |
|
28 |
-
|
29 |
-
|
|
|
|
|
30 |
|
31 |
wget -nv -O $WP_CORE_DIR/wp-content/db.php https://raw.github.com/markoheijnen/wp-mysqli/master/db.php
|
32 |
}
|
@@ -42,9 +44,10 @@ install_test_suite() {
|
|
42 |
# set up testing suite
|
43 |
mkdir -p $WP_TESTS_DIR
|
44 |
cd $WP_TESTS_DIR
|
45 |
-
svn co --quiet https://develop.svn.wordpress.org/branches/5.2/tests/phpunit/includes/
|
46 |
|
47 |
-
|
|
|
|
|
48 |
sed $ioption "s:dirname( __FILE__ ) . '/src/':'$WP_CORE_DIR':" wp-tests-config.php
|
49 |
sed $ioption "s/youremptytestdbnamehere/$DB_NAME/" wp-tests-config.php
|
50 |
sed $ioption "s/yourusernamehere/$DB_USER/" wp-tests-config.php
|
19 |
install_wp() {
|
20 |
mkdir -p $WP_CORE_DIR
|
21 |
|
22 |
+
if [ $WP_VERSION == 'latest' ]; then
|
23 |
local ARCHIVE_NAME='latest'
|
24 |
else
|
25 |
local ARCHIVE_NAME="wordpress-$WP_VERSION"
|
26 |
fi
|
27 |
|
28 |
+
# Install the WordPress files.
|
29 |
+
# Unzip quietly (-qq) so the automated tests are not flooded with the unzip output.
|
30 |
+
wget -nv -O /tmp/wordpress-latest.zip https://wordpress.org/nightly-builds/wordpress-latest.zip
|
31 |
+
unzip -qq /tmp/wordpress-latest.zip -d /tmp
|
32 |
|
33 |
wget -nv -O $WP_CORE_DIR/wp-content/db.php https://raw.github.com/markoheijnen/wp-mysqli/master/db.php
|
34 |
}
|
44 |
# set up testing suite
|
45 |
mkdir -p $WP_TESTS_DIR
|
46 |
cd $WP_TESTS_DIR
|
|
|
47 |
|
48 |
+
# As each new version of WP is released, the branch should be updated in the 2 lines below.
|
49 |
+
svn co --quiet https://develop.svn.wordpress.org/branches/5.9/tests/phpunit/includes/
|
50 |
+
wget -nv -O wp-tests-config.php https://develop.svn.wordpress.org/branches/5.9/wp-tests-config-sample.php
|
51 |
sed $ioption "s:dirname( __FILE__ ) . '/src/':'$WP_CORE_DIR':" wp-tests-config.php
|
52 |
sed $ioption "s/youremptytestdbnamehere/$DB_NAME/" wp-tests-config.php
|
53 |
sed $ioption "s/yourusernamehere/$DB_USER/" wp-tests-config.php
|
vendor/boldgrid/library/composer.json
CHANGED
@@ -35,5 +35,8 @@
|
|
35 |
"post-autoload-dump": [
|
36 |
"yarn && yarn run cpx 'node_modules/jquery-toggles/toggles.min.js' 'build/' && yarn run cpx 'node_modules/jquery-toggles/css/toggles-full.css' 'build/' && yarn run rimraf node_modules"
|
37 |
]
|
|
|
|
|
|
|
38 |
}
|
39 |
}
|
35 |
"post-autoload-dump": [
|
36 |
"yarn && yarn run cpx 'node_modules/jquery-toggles/toggles.min.js' 'build/' && yarn run cpx 'node_modules/jquery-toggles/css/toggles-full.css' 'build/' && yarn run rimraf node_modules"
|
37 |
]
|
38 |
+
},
|
39 |
+
"require-dev": {
|
40 |
+
"yoast/phpunit-polyfills": "^1.0"
|
41 |
}
|
42 |
}
|
vendor/boldgrid/library/composer.lock
ADDED
@@ -0,0 +1,2039 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"_readme": [
|
3 |
+
"This file locks the dependencies of your project to a known state",
|
4 |
+
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
5 |
+
"This file is @generated automatically"
|
6 |
+
],
|
7 |
+
"content-hash": "81680ded536dd0cad4416e4e04092729",
|
8 |
+
"packages": [],
|
9 |
+
"packages-dev": [
|
10 |
+
{
|
11 |
+
"name": "doctrine/instantiator",
|
12 |
+
"version": "1.4.1",
|
13 |
+
"source": {
|
14 |
+
"type": "git",
|
15 |
+
"url": "https://github.com/doctrine/instantiator.git",
|
16 |
+
"reference": "10dcfce151b967d20fde1b34ae6640712c3891bc"
|
17 |
+
},
|
18 |
+
"dist": {
|
19 |
+
"type": "zip",
|
20 |
+
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc",
|
21 |
+
"reference": "10dcfce151b967d20fde1b34ae6640712c3891bc",
|
22 |
+
"shasum": ""
|
23 |
+
},
|
24 |
+
"require": {
|
25 |
+
"php": "^7.1 || ^8.0"
|
26 |
+
},
|
27 |
+
"require-dev": {
|
28 |
+
"doctrine/coding-standard": "^9",
|
29 |
+
"ext-pdo": "*",
|
30 |
+
"ext-phar": "*",
|
31 |
+
"phpbench/phpbench": "^0.16 || ^1",
|
32 |
+
"phpstan/phpstan": "^1.4",
|
33 |
+
"phpstan/phpstan-phpunit": "^1",
|
34 |
+
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
|
35 |
+
"vimeo/psalm": "^4.22"
|
36 |
+
},
|
37 |
+
"type": "library",
|
38 |
+
"autoload": {
|
39 |
+
"psr-4": {
|
40 |
+
"Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
|
41 |
+
}
|
42 |
+
},
|
43 |
+
"notification-url": "https://packagist.org/downloads/",
|
44 |
+
"license": [
|
45 |
+
"MIT"
|
46 |
+
],
|
47 |
+
"authors": [
|
48 |
+
{
|
49 |
+
"name": "Marco Pivetta",
|
50 |
+
"email": "ocramius@gmail.com",
|
51 |
+
"homepage": "https://ocramius.github.io/"
|
52 |
+
}
|
53 |
+
],
|
54 |
+
"description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
|
55 |
+
"homepage": "https://www.doctrine-project.org/projects/instantiator.html",
|
56 |
+
"keywords": [
|
57 |
+
"constructor",
|
58 |
+
"instantiate"
|
59 |
+
],
|
60 |
+
"funding": [
|
61 |
+
{
|
62 |
+
"url": "https://www.doctrine-project.org/sponsorship.html",
|
63 |
+
"type": "custom"
|
64 |
+
},
|
65 |
+
{
|
66 |
+
"url": "https://www.patreon.com/phpdoctrine",
|
67 |
+
"type": "patreon"
|
68 |
+
},
|
69 |
+
{
|
70 |
+
"url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator",
|
71 |
+
"type": "tidelift"
|
72 |
+
}
|
73 |
+
],
|
74 |
+
"time": "2022-03-03T08:28:38+00:00"
|
75 |
+
},
|
76 |
+
{
|
77 |
+
"name": "myclabs/deep-copy",
|
78 |
+
"version": "1.11.0",
|
79 |
+
"source": {
|
80 |
+
"type": "git",
|
81 |
+
"url": "https://github.com/myclabs/DeepCopy.git",
|
82 |
+
"reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614"
|
83 |
+
},
|
84 |
+
"dist": {
|
85 |
+
"type": "zip",
|
86 |
+
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614",
|
87 |
+
"reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614",
|
88 |
+
"shasum": ""
|
89 |
+
},
|
90 |
+
"require": {
|
91 |
+
"php": "^7.1 || ^8.0"
|
92 |
+
},
|
93 |
+
"conflict": {
|
94 |
+
"doctrine/collections": "<1.6.8",
|
95 |
+
"doctrine/common": "<2.13.3 || >=3,<3.2.2"
|
96 |
+
},
|
97 |
+
"require-dev": {
|
98 |
+
"doctrine/collections": "^1.6.8",
|
99 |
+
"doctrine/common": "^2.13.3 || ^3.2.2",
|
100 |
+
"phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13"
|
101 |
+
},
|
102 |
+
"type": "library",
|
103 |
+
"autoload": {
|
104 |
+
"files": [
|
105 |
+
"src/DeepCopy/deep_copy.php"
|
106 |
+
],
|
107 |
+
"psr-4": {
|
108 |
+
"DeepCopy\\": "src/DeepCopy/"
|
109 |
+
}
|
110 |
+
},
|
111 |
+
"notification-url": "https://packagist.org/downloads/",
|
112 |
+
"license": [
|
113 |
+
"MIT"
|
114 |
+
],
|
115 |
+
"description": "Create deep copies (clones) of your objects",
|
116 |
+
"keywords": [
|
117 |
+
"clone",
|
118 |
+
"copy",
|
119 |
+
"duplicate",
|
120 |
+
"object",
|
121 |
+
"object graph"
|
122 |
+
],
|
123 |
+
"funding": [
|
124 |
+
{
|
125 |
+
"url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy",
|
126 |
+
"type": "tidelift"
|
127 |
+
}
|
128 |
+
],
|
129 |
+
"time": "2022-03-03T13:19:32+00:00"
|
130 |
+
},
|
131 |
+
{
|
132 |
+
"name": "nikic/php-parser",
|
133 |
+
"version": "v4.13.2",
|
134 |
+
"source": {
|
135 |
+
"type": "git",
|
136 |
+
"url": "https://github.com/nikic/PHP-Parser.git",
|
137 |
+
"reference": "210577fe3cf7badcc5814d99455df46564f3c077"
|
138 |
+
},
|
139 |
+
"dist": {
|
140 |
+
"type": "zip",
|
141 |
+
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/210577fe3cf7badcc5814d99455df46564f3c077",
|
142 |
+
"reference": "210577fe3cf7badcc5814d99455df46564f3c077",
|
143 |
+
"shasum": ""
|
144 |
+
},
|
145 |
+
"require": {
|
146 |
+
"ext-tokenizer": "*",
|
147 |
+
"php": ">=7.0"
|
148 |
+
},
|
149 |
+
"require-dev": {
|
150 |
+
"ircmaxell/php-yacc": "^0.0.7",
|
151 |
+
"phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0"
|
152 |
+
},
|
153 |
+
"bin": [
|
154 |
+
"bin/php-parse"
|
155 |
+
],
|
156 |
+
"type": "library",
|
157 |
+
"extra": {
|
158 |
+
"branch-alias": {
|
159 |
+
"dev-master": "4.9-dev"
|
160 |
+
}
|
161 |
+
},
|
162 |
+
"autoload": {
|
163 |
+
"psr-4": {
|
164 |
+
"PhpParser\\": "lib/PhpParser"
|
165 |
+
}
|
166 |
+
},
|
167 |
+
"notification-url": "https://packagist.org/downloads/",
|
168 |
+
"license": [
|
169 |
+
"BSD-3-Clause"
|
170 |
+
],
|
171 |
+
"authors": [
|
172 |
+
{
|
173 |
+
"name": "Nikita Popov"
|
174 |
+
}
|
175 |
+
],
|
176 |
+
"description": "A PHP parser written in PHP",
|
177 |
+
"keywords": [
|
178 |
+
"parser",
|
179 |
+
"php"
|
180 |
+
],
|
181 |
+
"time": "2021-11-30T19:35:32+00:00"
|
182 |
+
},
|
183 |
+
{
|
184 |
+
"name": "phar-io/manifest",
|
185 |
+
"version": "2.0.3",
|
186 |
+
"source": {
|
187 |
+
"type": "git",
|
188 |
+
"url": "https://github.com/phar-io/manifest.git",
|
189 |
+
"reference": "97803eca37d319dfa7826cc2437fc020857acb53"
|
190 |
+
},
|
191 |
+
"dist": {
|
192 |
+
"type": "zip",
|
193 |
+
"url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53",
|
194 |
+
"reference": "97803eca37d319dfa7826cc2437fc020857acb53",
|
195 |
+
"shasum": ""
|
196 |
+
},
|
197 |
+
"require": {
|
198 |
+
"ext-dom": "*",
|
199 |
+
"ext-phar": "*",
|
200 |
+
"ext-xmlwriter": "*",
|
201 |
+
"phar-io/version": "^3.0.1",
|
202 |
+
"php": "^7.2 || ^8.0"
|
203 |
+
},
|
204 |
+
"type": "library",
|
205 |
+
"extra": {
|
206 |
+
"branch-alias": {
|
207 |
+
"dev-master": "2.0.x-dev"
|
208 |
+
}
|
209 |
+
},
|
210 |
+
"autoload": {
|
211 |
+
"classmap": [
|
212 |
+
"src/"
|
213 |
+
]
|
214 |
+
},
|
215 |
+
"notification-url": "https://packagist.org/downloads/",
|
216 |
+
"license": [
|
217 |
+
"BSD-3-Clause"
|
218 |
+
],
|
219 |
+
"authors": [
|
220 |
+
{
|
221 |
+
"name": "Arne Blankerts",
|
222 |
+
"email": "arne@blankerts.de",
|
223 |
+
"role": "Developer"
|
224 |
+
},
|
225 |
+
{
|
226 |
+
"name": "Sebastian Heuer",
|
227 |
+
"email": "sebastian@phpeople.de",
|
228 |
+
"role": "Developer"
|
229 |
+
},
|
230 |
+
{
|
231 |
+
"name": "Sebastian Bergmann",
|
232 |
+
"email": "sebastian@phpunit.de",
|
233 |
+
"role": "Developer"
|
234 |
+
}
|
235 |
+
],
|
236 |
+
"description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
|
237 |
+
"time": "2021-07-20T11:28:43+00:00"
|
238 |
+
},
|
239 |
+
{
|
240 |
+
"name": "phar-io/version",
|
241 |
+
"version": "3.2.1",
|
242 |
+
"source": {
|
243 |
+
"type": "git",
|
244 |
+
"url": "https://github.com/phar-io/version.git",
|
245 |
+
"reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74"
|
246 |
+
},
|
247 |
+
"dist": {
|
248 |
+
"type": "zip",
|
249 |
+
"url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
|
250 |
+
"reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
|
251 |
+
"shasum": ""
|
252 |
+
},
|
253 |
+
"require": {
|
254 |
+
"php": "^7.2 || ^8.0"
|
255 |
+
},
|
256 |
+
"type": "library",
|
257 |
+
"autoload": {
|
258 |
+
"classmap": [
|
259 |
+
"src/"
|
260 |
+
]
|
261 |
+
},
|
262 |
+
"notification-url": "https://packagist.org/downloads/",
|
263 |
+
"license": [
|
264 |
+
"BSD-3-Clause"
|
265 |
+
],
|
266 |
+
"authors": [
|
267 |
+
{
|
268 |
+
"name": "Arne Blankerts",
|
269 |
+
"email": "arne@blankerts.de",
|
270 |
+
"role": "Developer"
|
271 |
+
},
|
272 |
+
{
|
273 |
+
"name": "Sebastian Heuer",
|
274 |
+
"email": "sebastian@phpeople.de",
|
275 |
+
"role": "Developer"
|
276 |
+
},
|
277 |
+
{
|
278 |
+
"name": "Sebastian Bergmann",
|
279 |
+
"email": "sebastian@phpunit.de",
|
280 |
+
"role": "Developer"
|
281 |
+
}
|
282 |
+
],
|
283 |
+
"description": "Library for handling version information and constraints",
|
284 |
+
"time": "2022-02-21T01:04:05+00:00"
|
285 |
+
},
|
286 |
+
{
|
287 |
+
"name": "phpdocumentor/reflection-common",
|
288 |
+
"version": "2.2.0",
|
289 |
+
"source": {
|
290 |
+
"type": "git",
|
291 |
+
"url": "https://github.com/phpDocumentor/ReflectionCommon.git",
|
292 |
+
"reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b"
|
293 |
+
},
|
294 |
+
"dist": {
|
295 |
+
"type": "zip",
|
296 |
+
"url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b",
|
297 |
+
"reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b",
|
298 |
+
"shasum": ""
|
299 |
+
},
|
300 |
+
"require": {
|
301 |
+
"php": "^7.2 || ^8.0"
|
302 |
+
},
|
303 |
+
"type": "library",
|
304 |
+
"extra": {
|
305 |
+
"branch-alias": {
|
306 |
+
"dev-2.x": "2.x-dev"
|
307 |
+
}
|
308 |
+
},
|
309 |
+
"autoload": {
|
310 |
+
"psr-4": {
|
311 |
+
"phpDocumentor\\Reflection\\": "src/"
|
312 |
+
}
|
313 |
+
},
|
314 |
+
"notification-url": "https://packagist.org/downloads/",
|
315 |
+
"license": [
|
316 |
+
"MIT"
|
317 |
+
],
|
318 |
+
"authors": [
|
319 |
+
{
|
320 |
+
"name": "Jaap van Otterdijk",
|
321 |
+
"email": "opensource@ijaap.nl"
|
322 |
+
}
|
323 |
+
],
|
324 |
+
"description": "Common reflection classes used by phpdocumentor to reflect the code structure",
|
325 |
+
"homepage": "http://www.phpdoc.org",
|
326 |
+
"keywords": [
|
327 |
+
"FQSEN",
|
328 |
+
"phpDocumentor",
|
329 |
+
"phpdoc",
|
330 |
+
"reflection",
|
331 |
+
"static analysis"
|
332 |
+
],
|
333 |
+
"time": "2020-06-27T09:03:43+00:00"
|
334 |
+
},
|
335 |
+
{
|
336 |
+
"name": "phpdocumentor/reflection-docblock",
|
337 |
+
"version": "5.3.0",
|
338 |
+
"source": {
|
339 |
+
"type": "git",
|
340 |
+
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
|
341 |
+
"reference": "622548b623e81ca6d78b721c5e029f4ce664f170"
|
342 |
+
},
|
343 |
+
"dist": {
|
344 |
+
"type": "zip",
|
345 |
+
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170",
|
346 |
+
"reference": "622548b623e81ca6d78b721c5e029f4ce664f170",
|
347 |
+
"shasum": ""
|
348 |
+
},
|
349 |
+
"require": {
|
350 |
+
"ext-filter": "*",
|
351 |
+
"php": "^7.2 || ^8.0",
|
352 |
+
"phpdocumentor/reflection-common": "^2.2",
|
353 |
+
"phpdocumentor/type-resolver": "^1.3",
|
354 |
+
"webmozart/assert": "^1.9.1"
|
355 |
+
},
|
356 |
+
"require-dev": {
|
357 |
+
"mockery/mockery": "~1.3.2",
|
358 |
+
"psalm/phar": "^4.8"
|
359 |
+
},
|
360 |
+
"type": "library",
|
361 |
+
"extra": {
|
362 |
+
"branch-alias": {
|
363 |
+
"dev-master": "5.x-dev"
|
364 |
+
}
|
365 |
+
},
|
366 |
+
"autoload": {
|
367 |
+
"psr-4": {
|
368 |
+
"phpDocumentor\\Reflection\\": "src"
|
369 |
+
}
|
370 |
+
},
|
371 |
+
"notification-url": "https://packagist.org/downloads/",
|
372 |
+
"license": [
|
373 |
+
"MIT"
|
374 |
+
],
|
375 |
+
"authors": [
|
376 |
+
{
|
377 |
+
"name": "Mike van Riel",
|
378 |
+
"email": "me@mikevanriel.com"
|
379 |
+
},
|
380 |
+
{
|
381 |
+
"name": "Jaap van Otterdijk",
|
382 |
+
"email": "account@ijaap.nl"
|
383 |
+
}
|
384 |
+
],
|
385 |
+
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
|
386 |
+
"time": "2021-10-19T17:43:47+00:00"
|
387 |
+
},
|
388 |
+
{
|
389 |
+
"name": "phpdocumentor/type-resolver",
|
390 |
+
"version": "1.6.0",
|
391 |
+
"source": {
|
392 |
+
"type": "git",
|
393 |
+
"url": "https://github.com/phpDocumentor/TypeResolver.git",
|
394 |
+
"reference": "93ebd0014cab80c4ea9f5e297ea48672f1b87706"
|
395 |
+
},
|
396 |
+
"dist": {
|
397 |
+
"type": "zip",
|
398 |
+
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/93ebd0014cab80c4ea9f5e297ea48672f1b87706",
|
399 |
+
"reference": "93ebd0014cab80c4ea9f5e297ea48672f1b87706",
|
400 |
+
"shasum": ""
|
401 |
+
},
|
402 |
+
"require": {
|
403 |
+
"php": "^7.2 || ^8.0",
|
404 |
+
"phpdocumentor/reflection-common": "^2.0"
|
405 |
+
},
|
406 |
+
"require-dev": {
|
407 |
+
"ext-tokenizer": "*",
|
408 |
+
"psalm/phar": "^4.8"
|
409 |
+
},
|
410 |
+
"type": "library",
|
411 |
+
"extra": {
|
412 |
+
"branch-alias": {
|
413 |
+
"dev-1.x": "1.x-dev"
|
414 |
+
}
|
415 |
+
},
|
416 |
+
"autoload": {
|
417 |
+
"psr-4": {
|
418 |
+
"phpDocumentor\\Reflection\\": "src"
|
419 |
+
}
|
420 |
+
},
|
421 |
+
"notification-url": "https://packagist.org/downloads/",
|
422 |
+
"license": [
|
423 |
+
"MIT"
|
424 |
+
],
|
425 |
+
"authors": [
|
426 |
+
{
|
427 |
+
"name": "Mike van Riel",
|
428 |
+
"email": "me@mikevanriel.com"
|
429 |
+
}
|
430 |
+
],
|
431 |
+
"description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
|
432 |
+
"time": "2022-01-04T19:58:01+00:00"
|
433 |
+
},
|
434 |
+
{
|
435 |
+
"name": "phpspec/prophecy",
|
436 |
+
"version": "v1.15.0",
|
437 |
+
"source": {
|
438 |
+
"type": "git",
|
439 |
+
"url": "https://github.com/phpspec/prophecy.git",
|
440 |
+
"reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13"
|
441 |
+
},
|
442 |
+
"dist": {
|
443 |
+
"type": "zip",
|
444 |
+
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/bbcd7380b0ebf3961ee21409db7b38bc31d69a13",
|
445 |
+
"reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13",
|
446 |
+
"shasum": ""
|
447 |
+
},
|
448 |
+
"require": {
|
449 |
+
"doctrine/instantiator": "^1.2",
|
450 |
+
"php": "^7.2 || ~8.0, <8.2",
|
451 |
+
"phpdocumentor/reflection-docblock": "^5.2",
|
452 |
+
"sebastian/comparator": "^3.0 || ^4.0",
|
453 |
+
"sebastian/recursion-context": "^3.0 || ^4.0"
|
454 |
+
},
|
455 |
+
"require-dev": {
|
456 |
+
"phpspec/phpspec": "^6.0 || ^7.0",
|
457 |
+
"phpunit/phpunit": "^8.0 || ^9.0"
|
458 |
+
},
|
459 |
+
"type": "library",
|
460 |
+
"extra": {
|
461 |
+
"branch-alias": {
|
462 |
+
"dev-master": "1.x-dev"
|
463 |
+
}
|
464 |
+
},
|
465 |
+
"autoload": {
|
466 |
+
"psr-4": {
|
467 |
+
"Prophecy\\": "src/Prophecy"
|
468 |
+
}
|
469 |
+
},
|
470 |
+
"notification-url": "https://packagist.org/downloads/",
|
471 |
+
"license": [
|
472 |
+
"MIT"
|
473 |
+
],
|
474 |
+
"authors": [
|
475 |
+
{
|
476 |
+
"name": "Konstantin Kudryashov",
|
477 |
+
"email": "ever.zet@gmail.com",
|
478 |
+
"homepage": "http://everzet.com"
|
479 |
+
},
|
480 |
+
{
|
481 |
+
"name": "Marcello Duarte",
|
482 |
+
"email": "marcello.duarte@gmail.com"
|
483 |
+
}
|
484 |
+
],
|
485 |
+
"description": "Highly opinionated mocking framework for PHP 5.3+",
|
486 |
+
"homepage": "https://github.com/phpspec/prophecy",
|
487 |
+
"keywords": [
|
488 |
+
"Double",
|
489 |
+
"Dummy",
|
490 |
+
"fake",
|
491 |
+
"mock",
|
492 |
+
"spy",
|
493 |
+
"stub"
|
494 |
+
],
|
495 |
+
"time": "2021-12-08T12:19:24+00:00"
|
496 |
+
},
|
497 |
+
{
|
498 |
+
"name": "phpunit/php-code-coverage",
|
499 |
+
"version": "9.2.15",
|
500 |
+
"source": {
|
501 |
+
"type": "git",
|
502 |
+
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
|
503 |
+
"reference": "2e9da11878c4202f97915c1cb4bb1ca318a63f5f"
|
504 |
+
},
|
505 |
+
"dist": {
|
506 |
+
"type": "zip",
|
507 |
+
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2e9da11878c4202f97915c1cb4bb1ca318a63f5f",
|
508 |
+
"reference": "2e9da11878c4202f97915c1cb4bb1ca318a63f5f",
|
509 |
+
"shasum": ""
|
510 |
+
},
|
511 |
+
"require": {
|
512 |
+
"ext-dom": "*",
|
513 |
+
"ext-libxml": "*",
|
514 |
+
"ext-xmlwriter": "*",
|
515 |
+
"nikic/php-parser": "^4.13.0",
|
516 |
+
"php": ">=7.3",
|
517 |
+
"phpunit/php-file-iterator": "^3.0.3",
|
518 |
+
"phpunit/php-text-template": "^2.0.2",
|
519 |
+
"sebastian/code-unit-reverse-lookup": "^2.0.2",
|
520 |
+
"sebastian/complexity": "^2.0",
|
521 |
+
"sebastian/environment": "^5.1.2",
|
522 |
+
"sebastian/lines-of-code": "^1.0.3",
|
523 |
+
"sebastian/version": "^3.0.1",
|
524 |
+
"theseer/tokenizer": "^1.2.0"
|
525 |
+
},
|
526 |
+
"require-dev": {
|
527 |
+
"phpunit/phpunit": "^9.3"
|
528 |
+
},
|
529 |
+
"suggest": {
|
530 |
+
"ext-pcov": "*",
|
531 |
+
"ext-xdebug": "*"
|
532 |
+
},
|
533 |
+
"type": "library",
|
534 |
+
"extra": {
|
535 |
+
"branch-alias": {
|
536 |
+
"dev-master": "9.2-dev"
|
537 |
+
}
|
538 |
+
},
|
539 |
+
"autoload": {
|
540 |
+
"classmap": [
|
541 |
+
"src/"
|
542 |
+
]
|
543 |
+
},
|
544 |
+
"notification-url": "https://packagist.org/downloads/",
|
545 |
+
"license": [
|
546 |
+
"BSD-3-Clause"
|
547 |
+
],
|
548 |
+
"authors": [
|
549 |
+
{
|
550 |
+
"name": "Sebastian Bergmann",
|
551 |
+
"email": "sebastian@phpunit.de",
|
552 |
+
"role": "lead"
|
553 |
+
}
|
554 |
+
],
|
555 |
+
"description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
|
556 |
+
"homepage": "https://github.com/sebastianbergmann/php-code-coverage",
|
557 |
+
"keywords": [
|
558 |
+
"coverage",
|
559 |
+
"testing",
|
560 |
+
"xunit"
|
561 |
+
],
|
562 |
+
"funding": [
|
563 |
+
{
|
564 |
+
"url": "https://github.com/sebastianbergmann",
|
565 |
+
"type": "github"
|
566 |
+
}
|
567 |
+
],
|
568 |
+
"time": "2022-03-07T09:28:20+00:00"
|
569 |
+
},
|
570 |
+
{
|
571 |
+
"name": "phpunit/php-file-iterator",
|
572 |
+
"version": "3.0.6",
|
573 |
+
"source": {
|
574 |
+
"type": "git",
|
575 |
+
"url": "https://github.com/sebastianbergmann/php-file-iterator.git",
|
576 |
+
"reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf"
|
577 |
+
},
|
578 |
+
"dist": {
|
579 |
+
"type": "zip",
|
580 |
+
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf",
|
581 |
+
"reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf",
|
582 |
+
"shasum": ""
|
583 |
+
},
|
584 |
+
"require": {
|
585 |
+
"php": ">=7.3"
|
586 |
+
},
|
587 |
+
"require-dev": {
|
588 |
+
"phpunit/phpunit": "^9.3"
|
589 |
+
},
|
590 |
+
"type": "library",
|
591 |
+
"extra": {
|
592 |
+
"branch-alias": {
|
593 |
+
"dev-master": "3.0-dev"
|
594 |
+
}
|
595 |
+
},
|
596 |
+
"autoload": {
|
597 |
+
"classmap": [
|
598 |
+
"src/"
|
599 |
+
]
|
600 |
+
},
|
601 |
+
"notification-url": "https://packagist.org/downloads/",
|
602 |
+
"license": [
|
603 |
+
"BSD-3-Clause"
|
604 |
+
],
|
605 |
+
"authors": [
|
606 |
+
{
|
607 |
+
"name": "Sebastian Bergmann",
|
608 |
+
"email": "sebastian@phpunit.de",
|
609 |
+
"role": "lead"
|
610 |
+
}
|
611 |
+
],
|
612 |
+
"description": "FilterIterator implementation that filters files based on a list of suffixes.",
|
613 |
+
"homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
|
614 |
+
"keywords": [
|
615 |
+
"filesystem",
|
616 |
+
"iterator"
|
617 |
+
],
|
618 |
+
"funding": [
|
619 |
+
{
|
620 |
+
"url": "https://github.com/sebastianbergmann",
|
621 |
+
"type": "github"
|
622 |
+
}
|
623 |
+
],
|
624 |
+
"time": "2021-12-02T12:48:52+00:00"
|
625 |
+
},
|
626 |
+
{
|
627 |
+
"name": "phpunit/php-invoker",
|
628 |
+
"version": "3.1.1",
|
629 |
+
"source": {
|
630 |
+
"type": "git",
|
631 |
+
"url": "https://github.com/sebastianbergmann/php-invoker.git",
|
632 |
+
"reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67"
|
633 |
+
},
|
634 |
+
"dist": {
|
635 |
+
"type": "zip",
|
636 |
+
"url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
|
637 |
+
"reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
|
638 |
+
"shasum": ""
|
639 |
+
},
|
640 |
+
"require": {
|
641 |
+
"php": ">=7.3"
|
642 |
+
},
|
643 |
+
"require-dev": {
|
644 |
+
"ext-pcntl": "*",
|
645 |
+
"phpunit/phpunit": "^9.3"
|
646 |
+
},
|
647 |
+
"suggest": {
|
648 |
+
"ext-pcntl": "*"
|
649 |
+
},
|
650 |
+
"type": "library",
|
651 |
+
"extra": {
|
652 |
+
"branch-alias": {
|
653 |
+
"dev-master": "3.1-dev"
|
654 |
+
}
|
655 |
+
},
|
656 |
+
"autoload": {
|
657 |
+
"classmap": [
|
658 |
+
"src/"
|
659 |
+
]
|
660 |
+
},
|
661 |
+
"notification-url": "https://packagist.org/downloads/",
|
662 |
+
"license": [
|
663 |
+
"BSD-3-Clause"
|
664 |
+
],
|
665 |
+
"authors": [
|
666 |
+
{
|
667 |
+
"name": "Sebastian Bergmann",
|
668 |
+
"email": "sebastian@phpunit.de",
|
669 |
+
"role": "lead"
|
670 |
+
}
|
671 |
+
],
|
672 |
+
"description": "Invoke callables with a timeout",
|
673 |
+
"homepage": "https://github.com/sebastianbergmann/php-invoker/",
|
674 |
+
"keywords": [
|
675 |
+
"process"
|
676 |
+
],
|
677 |
+
"funding": [
|
678 |
+
{
|
679 |
+
"url": "https://github.com/sebastianbergmann",
|
680 |
+
"type": "github"
|
681 |
+
}
|
682 |
+
],
|
683 |
+
"time": "2020-09-28T05:58:55+00:00"
|
684 |
+
},
|
685 |
+
{
|
686 |
+
"name": "phpunit/php-text-template",
|
687 |
+
"version": "2.0.4",
|
688 |
+
"source": {
|
689 |
+
"type": "git",
|
690 |
+
"url": "https://github.com/sebastianbergmann/php-text-template.git",
|
691 |
+
"reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28"
|
692 |
+
},
|
693 |
+
"dist": {
|
694 |
+
"type": "zip",
|
695 |
+
"url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28",
|
696 |
+
"reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28",
|
697 |
+
"shasum": ""
|
698 |
+
},
|
699 |
+
"require": {
|
700 |
+
"php": ">=7.3"
|
701 |
+
},
|
702 |
+
"require-dev": {
|
703 |
+
"phpunit/phpunit": "^9.3"
|
704 |
+
},
|
705 |
+
"type": "library",
|
706 |
+
"extra": {
|
707 |
+
"branch-alias": {
|
708 |
+
"dev-master": "2.0-dev"
|
709 |
+
}
|
710 |
+
},
|
711 |
+
"autoload": {
|
712 |
+
"classmap": [
|
713 |
+
"src/"
|
714 |
+
]
|
715 |
+
},
|
716 |
+
"notification-url": "https://packagist.org/downloads/",
|
717 |
+
"license": [
|
718 |
+
"BSD-3-Clause"
|
719 |
+
],
|
720 |
+
"authors": [
|
721 |
+
{
|
722 |
+
"name": "Sebastian Bergmann",
|
723 |
+
"email": "sebastian@phpunit.de",
|
724 |
+
"role": "lead"
|
725 |
+
}
|
726 |
+
],
|
727 |
+
"description": "Simple template engine.",
|
728 |
+
"homepage": "https://github.com/sebastianbergmann/php-text-template/",
|
729 |
+
"keywords": [
|
730 |
+
"template"
|
731 |
+
],
|
732 |
+
"funding": [
|
733 |
+
{
|
734 |
+
"url": "https://github.com/sebastianbergmann",
|
735 |
+
"type": "github"
|
736 |
+
}
|
737 |
+
],
|
738 |
+
"time": "2020-10-26T05:33:50+00:00"
|
739 |
+
},
|
740 |
+
{
|
741 |
+
"name": "phpunit/php-timer",
|
742 |
+
"version": "5.0.3",
|
743 |
+
"source": {
|
744 |
+
"type": "git",
|
745 |
+
"url": "https://github.com/sebastianbergmann/php-timer.git",
|
746 |
+
"reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2"
|
747 |
+
},
|
748 |
+
"dist": {
|
749 |
+
"type": "zip",
|
750 |
+
"url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2",
|
751 |
+
"reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2",
|
752 |
+
"shasum": ""
|
753 |
+
},
|
754 |
+
"require": {
|
755 |
+
"php": ">=7.3"
|
756 |
+
},
|
757 |
+
"require-dev": {
|
758 |
+
"phpunit/phpunit": "^9.3"
|
759 |
+
},
|
760 |
+
"type": "library",
|
761 |
+
"extra": {
|
762 |
+
"branch-alias": {
|
763 |
+
"dev-master": "5.0-dev"
|
764 |
+
}
|
765 |
+
},
|
766 |
+
"autoload": {
|
767 |
+
"classmap": [
|
768 |
+
"src/"
|
769 |
+
]
|
770 |
+
},
|
771 |
+
"notification-url": "https://packagist.org/downloads/",
|
772 |
+
"license": [
|
773 |
+
"BSD-3-Clause"
|
774 |
+
],
|
775 |
+
"authors": [
|
776 |
+
{
|
777 |
+
"name": "Sebastian Bergmann",
|
778 |
+
"email": "sebastian@phpunit.de",
|
779 |
+
"role": "lead"
|
780 |
+
}
|
781 |
+
],
|
782 |
+
"description": "Utility class for timing",
|
783 |
+
"homepage": "https://github.com/sebastianbergmann/php-timer/",
|
784 |
+
"keywords": [
|
785 |
+
"timer"
|
786 |
+
],
|
787 |
+
"funding": [
|
788 |
+
{
|
789 |
+
"url": "https://github.com/sebastianbergmann",
|
790 |
+
"type": "github"
|
791 |
+
}
|
792 |
+
],
|
793 |
+
"time": "2020-10-26T13:16:10+00:00"
|
794 |
+
},
|
795 |
+
{
|
796 |
+
"name": "phpunit/phpunit",
|
797 |
+
"version": "9.5.18",
|
798 |
+
"source": {
|
799 |
+
"type": "git",
|
800 |
+
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
801 |
+
"reference": "1b5856028273bfd855e60a887278857d872ec67a"
|
802 |
+
},
|
803 |
+
"dist": {
|
804 |
+
"type": "zip",
|
805 |
+
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/1b5856028273bfd855e60a887278857d872ec67a",
|
806 |
+
"reference": "1b5856028273bfd855e60a887278857d872ec67a",
|
807 |
+
"shasum": ""
|
808 |
+
},
|
809 |
+
"require": {
|
810 |
+
"doctrine/instantiator": "^1.3.1",
|
811 |
+
"ext-dom": "*",
|
812 |
+
"ext-json": "*",
|
813 |
+
"ext-libxml": "*",
|
814 |
+
"ext-mbstring": "*",
|
815 |
+
"ext-xml": "*",
|
816 |
+
"ext-xmlwriter": "*",
|
817 |
+
"myclabs/deep-copy": "^1.10.1",
|
818 |
+
"phar-io/manifest": "^2.0.3",
|
819 |
+
"phar-io/version": "^3.0.2",
|
820 |
+
"php": ">=7.3",
|
821 |
+
"phpspec/prophecy": "^1.12.1",
|
822 |
+
"phpunit/php-code-coverage": "^9.2.13",
|
823 |
+
"phpunit/php-file-iterator": "^3.0.5",
|
824 |
+
"phpunit/php-invoker": "^3.1.1",
|
825 |
+
"phpunit/php-text-template": "^2.0.3",
|
826 |
+
"phpunit/php-timer": "^5.0.2",
|
827 |
+
"sebastian/cli-parser": "^1.0.1",
|
828 |
+
"sebastian/code-unit": "^1.0.6",
|
829 |
+
"sebastian/comparator": "^4.0.5",
|
830 |
+
"sebastian/diff": "^4.0.3",
|
831 |
+
"sebastian/environment": "^5.1.3",
|
832 |
+
"sebastian/exporter": "^4.0.3",
|
833 |
+
"sebastian/global-state": "^5.0.1",
|
834 |
+
"sebastian/object-enumerator": "^4.0.3",
|
835 |
+
"sebastian/resource-operations": "^3.0.3",
|
836 |
+
"sebastian/type": "^2.3.4",
|
837 |
+
"sebastian/version": "^3.0.2"
|
838 |
+
},
|
839 |
+
"require-dev": {
|
840 |
+
"ext-pdo": "*",
|
841 |
+
"phpspec/prophecy-phpunit": "^2.0.1"
|
842 |
+
},
|
843 |
+
"suggest": {
|
844 |
+
"ext-soap": "*",
|
845 |
+
"ext-xdebug": "*"
|
846 |
+
},
|
847 |
+
"bin": [
|
848 |
+
"phpunit"
|
849 |
+
],
|
850 |
+
"type": "library",
|
851 |
+
"extra": {
|
852 |
+
"branch-alias": {
|
853 |
+
"dev-master": "9.5-dev"
|
854 |
+
}
|
855 |
+
},
|
856 |
+
"autoload": {
|
857 |
+
"files": [
|
858 |
+
"src/Framework/Assert/Functions.php"
|
859 |
+
],
|
860 |
+
"classmap": [
|
861 |
+
"src/"
|
862 |
+
]
|
863 |
+
},
|
864 |
+
"notification-url": "https://packagist.org/downloads/",
|
865 |
+
"license": [
|
866 |
+
"BSD-3-Clause"
|
867 |
+
],
|
868 |
+
"authors": [
|
869 |
+
{
|
870 |
+
"name": "Sebastian Bergmann",
|
871 |
+
"email": "sebastian@phpunit.de",
|
872 |
+
"role": "lead"
|
873 |
+
}
|
874 |
+
],
|
875 |
+
"description": "The PHP Unit Testing framework.",
|
876 |
+
"homepage": "https://phpunit.de/",
|
877 |
+
"keywords": [
|
878 |
+
"phpunit",
|
879 |
+
"testing",
|
880 |
+
"xunit"
|
881 |
+
],
|
882 |
+
"funding": [
|
883 |
+
{
|
884 |
+
"url": "https://phpunit.de/sponsors.html",
|
885 |
+
"type": "custom"
|
886 |
+
},
|
887 |
+
{
|
888 |
+
"url": "https://github.com/sebastianbergmann",
|
889 |
+
"type": "github"
|
890 |
+
}
|
891 |
+
],
|
892 |
+
"time": "2022-03-08T06:52:28+00:00"
|
893 |
+
},
|
894 |
+
{
|
895 |
+
"name": "sebastian/cli-parser",
|
896 |
+
"version": "1.0.1",
|
897 |
+
"source": {
|
898 |
+
"type": "git",
|
899 |
+
"url": "https://github.com/sebastianbergmann/cli-parser.git",
|
900 |
+
"reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2"
|
901 |
+
},
|
902 |
+
"dist": {
|
903 |
+
"type": "zip",
|
904 |
+
"url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2",
|
905 |
+
"reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2",
|
906 |
+
"shasum": ""
|
907 |
+
},
|
908 |
+
"require": {
|
909 |
+
"php": ">=7.3"
|
910 |
+
},
|
911 |
+
"require-dev": {
|
912 |
+
"phpunit/phpunit": "^9.3"
|
913 |
+
},
|
914 |
+
"type": "library",
|
915 |
+
"extra": {
|
916 |
+
"branch-alias": {
|
917 |
+
"dev-master": "1.0-dev"
|
918 |
+
}
|
919 |
+
},
|
920 |
+
"autoload": {
|
921 |
+
"classmap": [
|
922 |
+
"src/"
|
923 |
+
]
|
924 |
+
},
|
925 |
+
"notification-url": "https://packagist.org/downloads/",
|
926 |
+
"license": [
|
927 |
+
"BSD-3-Clause"
|
928 |
+
],
|
929 |
+
"authors": [
|
930 |
+
{
|
931 |
+
"name": "Sebastian Bergmann",
|
932 |
+
"email": "sebastian@phpunit.de",
|
933 |
+
"role": "lead"
|
934 |
+
}
|
935 |
+
],
|
936 |
+
"description": "Library for parsing CLI options",
|
937 |
+
"homepage": "https://github.com/sebastianbergmann/cli-parser",
|
938 |
+
"funding": [
|
939 |
+
{
|
940 |
+
"url": "https://github.com/sebastianbergmann",
|
941 |
+
"type": "github"
|
942 |
+
}
|
943 |
+
],
|
944 |
+
"time": "2020-09-28T06:08:49+00:00"
|
945 |
+
},
|
946 |
+
{
|
947 |
+
"name": "sebastian/code-unit",
|
948 |
+
"version": "1.0.8",
|
949 |
+
"source": {
|
950 |
+
"type": "git",
|
951 |
+
"url": "https://github.com/sebastianbergmann/code-unit.git",
|
952 |
+
"reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120"
|
953 |
+
},
|
954 |
+
"dist": {
|
955 |
+
"type": "zip",
|
956 |
+
"url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120",
|
957 |
+
"reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120",
|
958 |
+
"shasum": ""
|
959 |
+
},
|
960 |
+
"require": {
|
961 |
+
"php": ">=7.3"
|
962 |
+
},
|
963 |
+
"require-dev": {
|
964 |
+
"phpunit/phpunit": "^9.3"
|
965 |
+
},
|
966 |
+
"type": "library",
|
967 |
+
"extra": {
|
968 |
+
"branch-alias": {
|
969 |
+
"dev-master": "1.0-dev"
|
970 |
+
}
|
971 |
+
},
|
972 |
+
"autoload": {
|
973 |
+
"classmap": [
|
974 |
+
"src/"
|
975 |
+
]
|
976 |
+
},
|
977 |
+
"notification-url": "https://packagist.org/downloads/",
|
978 |
+
"license": [
|
979 |
+
"BSD-3-Clause"
|
980 |
+
],
|
981 |
+
"authors": [
|
982 |
+
{
|
983 |
+
"name": "Sebastian Bergmann",
|
984 |
+
"email": "sebastian@phpunit.de",
|
985 |
+
"role": "lead"
|
986 |
+
}
|
987 |
+
],
|
988 |
+
"description": "Collection of value objects that represent the PHP code units",
|
989 |
+
"homepage": "https://github.com/sebastianbergmann/code-unit",
|
990 |
+
"funding": [
|
991 |
+
{
|
992 |
+
"url": "https://github.com/sebastianbergmann",
|
993 |
+
"type": "github"
|
994 |
+
}
|
995 |
+
],
|
996 |
+
"time": "2020-10-26T13:08:54+00:00"
|
997 |
+
},
|
998 |
+
{
|
999 |
+
"name": "sebastian/code-unit-reverse-lookup",
|
1000 |
+
"version": "2.0.3",
|
1001 |
+
"source": {
|
1002 |
+
"type": "git",
|
1003 |
+
"url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
|
1004 |
+
"reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5"
|
1005 |
+
},
|
1006 |
+
"dist": {
|
1007 |
+
"type": "zip",
|
1008 |
+
"url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
|
1009 |
+
"reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
|
1010 |
+
"shasum": ""
|
1011 |
+
},
|
1012 |
+
"require": {
|
1013 |
+
"php": ">=7.3"
|
1014 |
+
},
|
1015 |
+
"require-dev": {
|
1016 |
+
"phpunit/phpunit": "^9.3"
|
1017 |
+
},
|
1018 |
+
"type": "library",
|
1019 |
+
"extra": {
|
1020 |
+
"branch-alias": {
|
1021 |
+
"dev-master": "2.0-dev"
|
1022 |
+
}
|
1023 |
+
},
|
1024 |
+
"autoload": {
|
1025 |
+
"classmap": [
|
1026 |
+
"src/"
|
1027 |
+
]
|
1028 |
+
},
|
1029 |
+
"notification-url": "https://packagist.org/downloads/",
|
1030 |
+
"license": [
|
1031 |
+
"BSD-3-Clause"
|
1032 |
+
],
|
1033 |
+
"authors": [
|
1034 |
+
{
|
1035 |
+
"name": "Sebastian Bergmann",
|
1036 |
+
"email": "sebastian@phpunit.de"
|
1037 |
+
}
|
1038 |
+
],
|
1039 |
+
"description": "Looks up which function or method a line of code belongs to",
|
1040 |
+
"homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
|
1041 |
+
"funding": [
|
1042 |
+
{
|
1043 |
+
"url": "https://github.com/sebastianbergmann",
|
1044 |
+
"type": "github"
|
1045 |
+
}
|
1046 |
+
],
|
1047 |
+
"time": "2020-09-28T05:30:19+00:00"
|
1048 |
+
},
|
1049 |
+
{
|
1050 |
+
"name": "sebastian/comparator",
|
1051 |
+
"version": "4.0.6",
|
1052 |
+
"source": {
|
1053 |
+
"type": "git",
|
1054 |
+
"url": "https://github.com/sebastianbergmann/comparator.git",
|
1055 |
+
"reference": "55f4261989e546dc112258c7a75935a81a7ce382"
|
1056 |
+
},
|
1057 |
+
"dist": {
|
1058 |
+
"type": "zip",
|
1059 |
+
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55f4261989e546dc112258c7a75935a81a7ce382",
|
1060 |
+
"reference": "55f4261989e546dc112258c7a75935a81a7ce382",
|
1061 |
+
"shasum": ""
|
1062 |
+
},
|
1063 |
+
"require": {
|
1064 |
+
"php": ">=7.3",
|
1065 |
+
"sebastian/diff": "^4.0",
|
1066 |
+
"sebastian/exporter": "^4.0"
|
1067 |
+
},
|
1068 |
+
"require-dev": {
|
1069 |
+
"phpunit/phpunit": "^9.3"
|
1070 |
+
},
|
1071 |
+
"type": "library",
|
1072 |
+
"extra": {
|
1073 |
+
"branch-alias": {
|
1074 |
+
"dev-master": "4.0-dev"
|
1075 |
+
}
|
1076 |
+
},
|
1077 |
+
"autoload": {
|
1078 |
+
"classmap": [
|
1079 |
+
"src/"
|
1080 |
+
]
|
1081 |
+
},
|
1082 |
+
"notification-url": "https://packagist.org/downloads/",
|
1083 |
+
"license": [
|
1084 |
+
"BSD-3-Clause"
|
1085 |
+
],
|
1086 |
+
"authors": [
|
1087 |
+
{
|
1088 |
+
"name": "Sebastian Bergmann",
|
1089 |
+
"email": "sebastian@phpunit.de"
|
1090 |
+
},
|
1091 |
+
{
|
1092 |
+
"name": "Jeff Welch",
|
1093 |
+
"email": "whatthejeff@gmail.com"
|
1094 |
+
},
|
1095 |
+
{
|
1096 |
+
"name": "Volker Dusch",
|
1097 |
+
"email": "github@wallbash.com"
|
1098 |
+
},
|
1099 |
+
{
|
1100 |
+
"name": "Bernhard Schussek",
|
1101 |
+
"email": "bschussek@2bepublished.at"
|
1102 |
+
}
|
1103 |
+
],
|
1104 |
+
"description": "Provides the functionality to compare PHP values for equality",
|
1105 |
+
"homepage": "https://github.com/sebastianbergmann/comparator",
|
1106 |
+
"keywords": [
|
1107 |
+
"comparator",
|
1108 |
+
"compare",
|
1109 |
+
"equality"
|
1110 |
+
],
|
1111 |
+
"funding": [
|
1112 |
+
{
|
1113 |
+
"url": "https://github.com/sebastianbergmann",
|
1114 |
+
"type": "github"
|
1115 |
+
}
|
1116 |
+
],
|
1117 |
+
"time": "2020-10-26T15:49:45+00:00"
|
1118 |
+
},
|
1119 |
+
{
|
1120 |
+
"name": "sebastian/complexity",
|
1121 |
+
"version": "2.0.2",
|
1122 |
+
"source": {
|
1123 |
+
"type": "git",
|
1124 |
+
"url": "https://github.com/sebastianbergmann/complexity.git",
|
1125 |
+
"reference": "739b35e53379900cc9ac327b2147867b8b6efd88"
|
1126 |
+
},
|
1127 |
+
"dist": {
|
1128 |
+
"type": "zip",
|
1129 |
+
"url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88",
|
1130 |
+
"reference": "739b35e53379900cc9ac327b2147867b8b6efd88",
|
1131 |
+
"shasum": ""
|
1132 |
+
},
|
1133 |
+
"require": {
|
1134 |
+
"nikic/php-parser": "^4.7",
|
1135 |
+
"php": ">=7.3"
|
1136 |
+
},
|
1137 |
+
"require-dev": {
|
1138 |
+
"phpunit/phpunit": "^9.3"
|
1139 |
+
},
|
1140 |
+
"type": "library",
|
1141 |
+
"extra": {
|
1142 |
+
"branch-alias": {
|
1143 |
+
"dev-master": "2.0-dev"
|
1144 |
+
}
|
1145 |
+
},
|
1146 |
+
"autoload": {
|
1147 |
+
"classmap": [
|
1148 |
+
"src/"
|
1149 |
+
]
|
1150 |
+
},
|
1151 |
+
"notification-url": "https://packagist.org/downloads/",
|
1152 |
+
"license": [
|
1153 |
+
"BSD-3-Clause"
|
1154 |
+
],
|
1155 |
+
"authors": [
|
1156 |
+
{
|
1157 |
+
"name": "Sebastian Bergmann",
|
1158 |
+
"email": "sebastian@phpunit.de",
|
1159 |
+
"role": "lead"
|
1160 |
+
}
|
1161 |
+
],
|
1162 |
+
"description": "Library for calculating the complexity of PHP code units",
|
1163 |
+
"homepage": "https://github.com/sebastianbergmann/complexity",
|
1164 |
+
"funding": [
|
1165 |
+
{
|
1166 |
+
"url": "https://github.com/sebastianbergmann",
|
1167 |
+
"type": "github"
|
1168 |
+
}
|
1169 |
+
],
|
1170 |
+
"time": "2020-10-26T15:52:27+00:00"
|
1171 |
+
},
|
1172 |
+
{
|
1173 |
+
"name": "sebastian/diff",
|
1174 |
+
"version": "4.0.4",
|
1175 |
+
"source": {
|
1176 |
+
"type": "git",
|
1177 |
+
"url": "https://github.com/sebastianbergmann/diff.git",
|
1178 |
+
"reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d"
|
1179 |
+
},
|
1180 |
+
"dist": {
|
1181 |
+
"type": "zip",
|
1182 |
+
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d",
|
1183 |
+
"reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d",
|
1184 |
+
"shasum": ""
|
1185 |
+
},
|
1186 |
+
"require": {
|
1187 |
+
"php": ">=7.3"
|
1188 |
+
},
|
1189 |
+
"require-dev": {
|
1190 |
+
"phpunit/phpunit": "^9.3",
|
1191 |
+
"symfony/process": "^4.2 || ^5"
|
1192 |
+
},
|
1193 |
+
"type": "library",
|
1194 |
+
"extra": {
|
1195 |
+
"branch-alias": {
|
1196 |
+
"dev-master": "4.0-dev"
|
1197 |
+
}
|
1198 |
+
},
|
1199 |
+
"autoload": {
|
1200 |
+
"classmap": [
|
1201 |
+
"src/"
|
1202 |
+
]
|
1203 |
+
},
|
1204 |
+
"notification-url": "https://packagist.org/downloads/",
|
1205 |
+
"license": [
|
1206 |
+
"BSD-3-Clause"
|
1207 |
+
],
|
1208 |
+
"authors": [
|
1209 |
+
{
|
1210 |
+
"name": "Sebastian Bergmann",
|
1211 |
+
"email": "sebastian@phpunit.de"
|
1212 |
+
},
|
1213 |
+
{
|
1214 |
+
"name": "Kore Nordmann",
|
1215 |
+
"email": "mail@kore-nordmann.de"
|
1216 |
+
}
|
1217 |
+
],
|
1218 |
+
"description": "Diff implementation",
|
1219 |
+
"homepage": "https://github.com/sebastianbergmann/diff",
|
1220 |
+
"keywords": [
|
1221 |
+
"diff",
|
1222 |
+
"udiff",
|
1223 |
+
"unidiff",
|
1224 |
+
"unified diff"
|
1225 |
+
],
|
1226 |
+
"funding": [
|
1227 |
+
{
|
1228 |
+
"url": "https://github.com/sebastianbergmann",
|
1229 |
+
"type": "github"
|
1230 |
+
}
|
1231 |
+
],
|
1232 |
+
"time": "2020-10-26T13:10:38+00:00"
|
1233 |
+
},
|
1234 |
+
{
|
1235 |
+
"name": "sebastian/environment",
|
1236 |
+
"version": "5.1.3",
|
1237 |
+
"source": {
|
1238 |
+
"type": "git",
|
1239 |
+
"url": "https://github.com/sebastianbergmann/environment.git",
|
1240 |
+
"reference": "388b6ced16caa751030f6a69e588299fa09200ac"
|
1241 |
+
},
|
1242 |
+
"dist": {
|
1243 |
+
"type": "zip",
|
1244 |
+
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/388b6ced16caa751030f6a69e588299fa09200ac",
|
1245 |
+
"reference": "388b6ced16caa751030f6a69e588299fa09200ac",
|
1246 |
+
"shasum": ""
|
1247 |
+
},
|
1248 |
+
"require": {
|
1249 |
+
"php": ">=7.3"
|
1250 |
+
},
|
1251 |
+
"require-dev": {
|
1252 |
+
"phpunit/phpunit": "^9.3"
|
1253 |
+
},
|
1254 |
+
"suggest": {
|
1255 |
+
"ext-posix": "*"
|
1256 |
+
},
|
1257 |
+
"type": "library",
|
1258 |
+
"extra": {
|
1259 |
+
"branch-alias": {
|
1260 |
+
"dev-master": "5.1-dev"
|
1261 |
+
}
|
1262 |
+
},
|
1263 |
+
"autoload": {
|
1264 |
+
"classmap": [
|
1265 |
+
"src/"
|
1266 |
+
]
|
1267 |
+
},
|
1268 |
+
"notification-url": "https://packagist.org/downloads/",
|
1269 |
+
"license": [
|
1270 |
+
"BSD-3-Clause"
|
1271 |
+
],
|
1272 |
+
"authors": [
|
1273 |
+
{
|
1274 |
+
"name": "Sebastian Bergmann",
|
1275 |
+
"email": "sebastian@phpunit.de"
|
1276 |
+
}
|
1277 |
+
],
|
1278 |
+
"description": "Provides functionality to handle HHVM/PHP environments",
|
1279 |
+
"homepage": "http://www.github.com/sebastianbergmann/environment",
|
1280 |
+
"keywords": [
|
1281 |
+
"Xdebug",
|
1282 |
+
"environment",
|
1283 |
+
"hhvm"
|
1284 |
+
],
|
1285 |
+
"funding": [
|
1286 |
+
{
|
1287 |
+
"url": "https://github.com/sebastianbergmann",
|
1288 |
+
"type": "github"
|
1289 |
+
}
|
1290 |
+
],
|
1291 |
+
"time": "2020-09-28T05:52:38+00:00"
|
1292 |
+
},
|
1293 |
+
{
|
1294 |
+
"name": "sebastian/exporter",
|
1295 |
+
"version": "4.0.4",
|
1296 |
+
"source": {
|
1297 |
+
"type": "git",
|
1298 |
+
"url": "https://github.com/sebastianbergmann/exporter.git",
|
1299 |
+
"reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9"
|
1300 |
+
},
|
1301 |
+
"dist": {
|
1302 |
+
"type": "zip",
|
1303 |
+
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/65e8b7db476c5dd267e65eea9cab77584d3cfff9",
|
1304 |
+
"reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9",
|
1305 |
+
"shasum": ""
|
1306 |
+
},
|
1307 |
+
"require": {
|
1308 |
+
"php": ">=7.3",
|
1309 |
+
"sebastian/recursion-context": "^4.0"
|
1310 |
+
},
|
1311 |
+
"require-dev": {
|
1312 |
+
"ext-mbstring": "*",
|
1313 |
+
"phpunit/phpunit": "^9.3"
|
1314 |
+
},
|
1315 |
+
"type": "library",
|
1316 |
+
"extra": {
|
1317 |
+
"branch-alias": {
|
1318 |
+
"dev-master": "4.0-dev"
|
1319 |
+
}
|
1320 |
+
},
|
1321 |
+
"autoload": {
|
1322 |
+
"classmap": [
|
1323 |
+
"src/"
|
1324 |
+
]
|
1325 |
+
},
|
1326 |
+
"notification-url": "https://packagist.org/downloads/",
|
1327 |
+
"license": [
|
1328 |
+
"BSD-3-Clause"
|
1329 |
+
],
|
1330 |
+
"authors": [
|
1331 |
+
{
|
1332 |
+
"name": "Sebastian Bergmann",
|
1333 |
+
"email": "sebastian@phpunit.de"
|
1334 |
+
},
|
1335 |
+
{
|
1336 |
+
"name": "Jeff Welch",
|
1337 |
+
"email": "whatthejeff@gmail.com"
|
1338 |
+
},
|
1339 |
+
{
|
1340 |
+
"name": "Volker Dusch",
|
1341 |
+
"email": "github@wallbash.com"
|
1342 |
+
},
|
1343 |
+
{
|
1344 |
+
"name": "Adam Harvey",
|
1345 |
+
"email": "aharvey@php.net"
|
1346 |
+
},
|
1347 |
+
{
|
1348 |
+
"name": "Bernhard Schussek",
|
1349 |
+
"email": "bschussek@gmail.com"
|
1350 |
+
}
|
1351 |
+
],
|
1352 |
+
"description": "Provides the functionality to export PHP variables for visualization",
|
1353 |
+
"homepage": "https://www.github.com/sebastianbergmann/exporter",
|
1354 |
+
"keywords": [
|
1355 |
+
"export",
|
1356 |
+
"exporter"
|
1357 |
+
],
|
1358 |
+
"funding": [
|
1359 |
+
{
|
1360 |
+
"url": "https://github.com/sebastianbergmann",
|
1361 |
+
"type": "github"
|
1362 |
+
}
|
1363 |
+
],
|
1364 |
+
"time": "2021-11-11T14:18:36+00:00"
|
1365 |
+
},
|
1366 |
+
{
|
1367 |
+
"name": "sebastian/global-state",
|
1368 |
+
"version": "5.0.5",
|
1369 |
+
"source": {
|
1370 |
+
"type": "git",
|
1371 |
+
"url": "https://github.com/sebastianbergmann/global-state.git",
|
1372 |
+
"reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2"
|
1373 |
+
},
|
1374 |
+
"dist": {
|
1375 |
+
"type": "zip",
|
1376 |
+
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2",
|
1377 |
+
"reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2",
|
1378 |
+
"shasum": ""
|
1379 |
+
},
|
1380 |
+
"require": {
|
1381 |
+
"php": ">=7.3",
|
1382 |
+
"sebastian/object-reflector": "^2.0",
|
1383 |
+
"sebastian/recursion-context": "^4.0"
|
1384 |
+
},
|
1385 |
+
"require-dev": {
|
1386 |
+
"ext-dom": "*",
|
1387 |
+
"phpunit/phpunit": "^9.3"
|
1388 |
+
},
|
1389 |
+
"suggest": {
|
1390 |
+
"ext-uopz": "*"
|
1391 |
+
},
|
1392 |
+
"type": "library",
|
1393 |
+
"extra": {
|
1394 |
+
"branch-alias": {
|
1395 |
+
"dev-master": "5.0-dev"
|
1396 |
+
}
|
1397 |
+
},
|
1398 |
+
"autoload": {
|
1399 |
+
"classmap": [
|
1400 |
+
"src/"
|
1401 |
+
]
|
1402 |
+
},
|
1403 |
+
"notification-url": "https://packagist.org/downloads/",
|
1404 |
+
"license": [
|
1405 |
+
"BSD-3-Clause"
|
1406 |
+
],
|
1407 |
+
"authors": [
|
1408 |
+
{
|
1409 |
+
"name": "Sebastian Bergmann",
|
1410 |
+
"email": "sebastian@phpunit.de"
|
1411 |
+
}
|
1412 |
+
],
|
1413 |
+
"description": "Snapshotting of global state",
|
1414 |
+
"homepage": "http://www.github.com/sebastianbergmann/global-state",
|
1415 |
+
"keywords": [
|
1416 |
+
"global state"
|
1417 |
+
],
|
1418 |
+
"funding": [
|
1419 |
+
{
|
1420 |
+
"url": "https://github.com/sebastianbergmann",
|
1421 |
+
"type": "github"
|
1422 |
+
}
|
1423 |
+
],
|
1424 |
+
"time": "2022-02-14T08:28:10+00:00"
|
1425 |
+
},
|
1426 |
+
{
|
1427 |
+
"name": "sebastian/lines-of-code",
|
1428 |
+
"version": "1.0.3",
|
1429 |
+
"source": {
|
1430 |
+
"type": "git",
|
1431 |
+
"url": "https://github.com/sebastianbergmann/lines-of-code.git",
|
1432 |
+
"reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc"
|
1433 |
+
},
|
1434 |
+
"dist": {
|
1435 |
+
"type": "zip",
|
1436 |
+
"url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc",
|
1437 |
+
"reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc",
|
1438 |
+
"shasum": ""
|
1439 |
+
},
|
1440 |
+
"require": {
|
1441 |
+
"nikic/php-parser": "^4.6",
|
1442 |
+
"php": ">=7.3"
|
1443 |
+
},
|
1444 |
+
"require-dev": {
|
1445 |
+
"phpunit/phpunit": "^9.3"
|
1446 |
+
},
|
1447 |
+
"type": "library",
|
1448 |
+
"extra": {
|
1449 |
+
"branch-alias": {
|
1450 |
+
"dev-master": "1.0-dev"
|
1451 |
+
}
|
1452 |
+
},
|
1453 |
+
"autoload": {
|
1454 |
+
"classmap": [
|
1455 |
+
"src/"
|
1456 |
+
]
|
1457 |
+
},
|
1458 |
+
"notification-url": "https://packagist.org/downloads/",
|
1459 |
+
"license": [
|
1460 |
+
"BSD-3-Clause"
|
1461 |
+
],
|
1462 |
+
"authors": [
|
1463 |
+
{
|
1464 |
+
"name": "Sebastian Bergmann",
|
1465 |
+
"email": "sebastian@phpunit.de",
|
1466 |
+
"role": "lead"
|
1467 |
+
}
|
1468 |
+
],
|
1469 |
+
"description": "Library for counting the lines of code in PHP source code",
|
1470 |
+
"homepage": "https://github.com/sebastianbergmann/lines-of-code",
|
1471 |
+
"funding": [
|
1472 |
+
{
|
1473 |
+
"url": "https://github.com/sebastianbergmann",
|
1474 |
+
"type": "github"
|
1475 |
+
}
|
1476 |
+
],
|
1477 |
+
"time": "2020-11-28T06:42:11+00:00"
|
1478 |
+
},
|
1479 |
+
{
|
1480 |
+
"name": "sebastian/object-enumerator",
|
1481 |
+
"version": "4.0.4",
|
1482 |
+
"source": {
|
1483 |
+
"type": "git",
|
1484 |
+
"url": "https://github.com/sebastianbergmann/object-enumerator.git",
|
1485 |
+
"reference": "5c9eeac41b290a3712d88851518825ad78f45c71"
|
1486 |
+
},
|
1487 |
+
"dist": {
|
1488 |
+
"type": "zip",
|
1489 |
+
"url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71",
|
1490 |
+
"reference": "5c9eeac41b290a3712d88851518825ad78f45c71",
|
1491 |
+
"shasum": ""
|
1492 |
+
},
|
1493 |
+
"require": {
|
1494 |
+
"php": ">=7.3",
|
1495 |
+
"sebastian/object-reflector": "^2.0",
|
1496 |
+
"sebastian/recursion-context": "^4.0"
|
1497 |
+
},
|
1498 |
+
"require-dev": {
|
1499 |
+
"phpunit/phpunit": "^9.3"
|
1500 |
+
},
|
1501 |
+
"type": "library",
|
1502 |
+
"extra": {
|
1503 |
+
"branch-alias": {
|
1504 |
+
"dev-master": "4.0-dev"
|
1505 |
+
}
|
1506 |
+
},
|
1507 |
+
"autoload": {
|
1508 |
+
"classmap": [
|
1509 |
+
"src/"
|
1510 |
+
]
|
1511 |
+
},
|
1512 |
+
"notification-url": "https://packagist.org/downloads/",
|
1513 |
+
"license": [
|
1514 |
+
"BSD-3-Clause"
|
1515 |
+
],
|
1516 |
+
"authors": [
|
1517 |
+
{
|
1518 |
+
"name": "Sebastian Bergmann",
|
1519 |
+
"email": "sebastian@phpunit.de"
|
1520 |
+
}
|
1521 |
+
],
|
1522 |
+
"description": "Traverses array structures and object graphs to enumerate all referenced objects",
|
1523 |
+
"homepage": "https://github.com/sebastianbergmann/object-enumerator/",
|
1524 |
+
"funding": [
|
1525 |
+
{
|
1526 |
+
"url": "https://github.com/sebastianbergmann",
|
1527 |
+
"type": "github"
|
1528 |
+
}
|
1529 |
+
],
|
1530 |
+
"time": "2020-10-26T13:12:34+00:00"
|
1531 |
+
},
|
1532 |
+
{
|
1533 |
+
"name": "sebastian/object-reflector",
|
1534 |
+
"version": "2.0.4",
|
1535 |
+
"source": {
|
1536 |
+
"type": "git",
|
1537 |
+
"url": "https://github.com/sebastianbergmann/object-reflector.git",
|
1538 |
+
"reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7"
|
1539 |
+
},
|
1540 |
+
"dist": {
|
1541 |
+
"type": "zip",
|
1542 |
+
"url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7",
|
1543 |
+
"reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7",
|
1544 |
+
"shasum": ""
|
1545 |
+
},
|
1546 |
+
"require": {
|
1547 |
+
"php": ">=7.3"
|
1548 |
+
},
|
1549 |
+
"require-dev": {
|
1550 |
+
"phpunit/phpunit": "^9.3"
|
1551 |
+
},
|
1552 |
+
"type": "library",
|
1553 |
+
"extra": {
|
1554 |
+
"branch-alias": {
|
1555 |
+
"dev-master": "2.0-dev"
|
1556 |
+
}
|
1557 |
+
},
|
1558 |
+
"autoload": {
|
1559 |
+
"classmap": [
|
1560 |
+
"src/"
|
1561 |
+
]
|
1562 |
+
},
|
1563 |
+
"notification-url": "https://packagist.org/downloads/",
|
1564 |
+
"license": [
|
1565 |
+
"BSD-3-Clause"
|
1566 |
+
],
|
1567 |
+
"authors": [
|
1568 |
+
{
|
1569 |
+
"name": "Sebastian Bergmann",
|
1570 |
+
"email": "sebastian@phpunit.de"
|
1571 |
+
}
|
1572 |
+
],
|
1573 |
+
"description": "Allows reflection of object attributes, including inherited and non-public ones",
|
1574 |
+
"homepage": "https://github.com/sebastianbergmann/object-reflector/",
|
1575 |
+
"funding": [
|
1576 |
+
{
|
1577 |
+
"url": "https://github.com/sebastianbergmann",
|
1578 |
+
"type": "github"
|
1579 |
+
}
|
1580 |
+
],
|
1581 |
+
"time": "2020-10-26T13:14:26+00:00"
|
1582 |
+
},
|
1583 |
+
{
|
1584 |
+
"name": "sebastian/recursion-context",
|
1585 |
+
"version": "4.0.4",
|
1586 |
+
"source": {
|
1587 |
+
"type": "git",
|
1588 |
+
"url": "https://github.com/sebastianbergmann/recursion-context.git",
|
1589 |
+
"reference": "cd9d8cf3c5804de4341c283ed787f099f5506172"
|
1590 |
+
},
|
1591 |
+
"dist": {
|
1592 |
+
"type": "zip",
|
1593 |
+
"url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172",
|
1594 |
+
"reference": "cd9d8cf3c5804de4341c283ed787f099f5506172",
|
1595 |
+
"shasum": ""
|
1596 |
+
},
|
1597 |
+
"require": {
|
1598 |
+
"php": ">=7.3"
|
1599 |
+
},
|
1600 |
+
"require-dev": {
|
1601 |
+
"phpunit/phpunit": "^9.3"
|
1602 |
+
},
|
1603 |
+
"type": "library",
|
1604 |
+
"extra": {
|
1605 |
+
"branch-alias": {
|
1606 |
+
"dev-master": "4.0-dev"
|
1607 |
+
}
|
1608 |
+
},
|
1609 |
+
"autoload": {
|
1610 |
+
"classmap": [
|
1611 |
+
"src/"
|
1612 |
+
]
|
1613 |
+
},
|
1614 |
+
"notification-url": "https://packagist.org/downloads/",
|
1615 |
+
"license": [
|
1616 |
+
"BSD-3-Clause"
|
1617 |
+
],
|
1618 |
+
"authors": [
|
1619 |
+
{
|
1620 |
+
"name": "Sebastian Bergmann",
|
1621 |
+
"email": "sebastian@phpunit.de"
|
1622 |
+
},
|
1623 |
+
{
|
1624 |
+
"name": "Jeff Welch",
|
1625 |
+
"email": "whatthejeff@gmail.com"
|
1626 |
+
},
|
1627 |
+
{
|
1628 |
+
"name": "Adam Harvey",
|
1629 |
+
"email": "aharvey@php.net"
|
1630 |
+
}
|
1631 |
+
],
|
1632 |
+
"description": "Provides functionality to recursively process PHP variables",
|
1633 |
+
"homepage": "http://www.github.com/sebastianbergmann/recursion-context",
|
1634 |
+
"funding": [
|
1635 |
+
{
|
1636 |
+
"url": "https://github.com/sebastianbergmann",
|
1637 |
+
"type": "github"
|
1638 |
+
}
|
1639 |
+
],
|
1640 |
+
"time": "2020-10-26T13:17:30+00:00"
|
1641 |
+
},
|
1642 |
+
{
|
1643 |
+
"name": "sebastian/resource-operations",
|
1644 |
+
"version": "3.0.3",
|
1645 |
+
"source": {
|
1646 |
+
"type": "git",
|
1647 |
+
"url": "https://github.com/sebastianbergmann/resource-operations.git",
|
1648 |
+
"reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8"
|
1649 |
+
},
|
1650 |
+
"dist": {
|
1651 |
+
"type": "zip",
|
1652 |
+
"url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
|
1653 |
+
"reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
|
1654 |
+
"shasum": ""
|
1655 |
+
},
|
1656 |
+
"require": {
|
1657 |
+
"php": ">=7.3"
|
1658 |
+
},
|
1659 |
+
"require-dev": {
|
1660 |
+
"phpunit/phpunit": "^9.0"
|
1661 |
+
},
|
1662 |
+
"type": "library",
|
1663 |
+
"extra": {
|
1664 |
+
"branch-alias": {
|
1665 |
+
"dev-master": "3.0-dev"
|
1666 |
+
}
|
1667 |
+
},
|
1668 |
+
"autoload": {
|
1669 |
+
"classmap": [
|
1670 |
+
"src/"
|
1671 |
+
]
|
1672 |
+
},
|
1673 |
+
"notification-url": "https://packagist.org/downloads/",
|
1674 |
+
"license": [
|
1675 |
+
"BSD-3-Clause"
|
1676 |
+
],
|
1677 |
+
"authors": [
|
1678 |
+
{
|
1679 |
+
"name": "Sebastian Bergmann",
|
1680 |
+
"email": "sebastian@phpunit.de"
|
1681 |
+
}
|
1682 |
+
],
|
1683 |
+
"description": "Provides a list of PHP built-in functions that operate on resources",
|
1684 |
+
"homepage": "https://www.github.com/sebastianbergmann/resource-operations",
|
1685 |
+
"funding": [
|
1686 |
+
{
|
1687 |
+
"url": "https://github.com/sebastianbergmann",
|
1688 |
+
"type": "github"
|
1689 |
+
}
|
1690 |
+
],
|
1691 |
+
"time": "2020-09-28T06:45:17+00:00"
|
1692 |
+
},
|
1693 |
+
{
|
1694 |
+
"name": "sebastian/type",
|
1695 |
+
"version": "2.3.4",
|
1696 |
+
"source": {
|
1697 |
+
"type": "git",
|
1698 |
+
"url": "https://github.com/sebastianbergmann/type.git",
|
1699 |
+
"reference": "b8cd8a1c753c90bc1a0f5372170e3e489136f914"
|
1700 |
+
},
|
1701 |
+
"dist": {
|
1702 |
+
"type": "zip",
|
1703 |
+
"url": "https://api.github.com/repos/sebastianbergmann/type/zipball/b8cd8a1c753c90bc1a0f5372170e3e489136f914",
|
1704 |
+
"reference": "b8cd8a1c753c90bc1a0f5372170e3e489136f914",
|
1705 |
+
"shasum": ""
|
1706 |
+
},
|
1707 |
+
"require": {
|
1708 |
+
"php": ">=7.3"
|
1709 |
+
},
|
1710 |
+
"require-dev": {
|
1711 |
+
"phpunit/phpunit": "^9.3"
|
1712 |
+
},
|
1713 |
+
"type": "library",
|
1714 |
+
"extra": {
|
1715 |
+
"branch-alias": {
|
1716 |
+
"dev-master": "2.3-dev"
|
1717 |
+
}
|
1718 |
+
},
|
1719 |
+
"autoload": {
|
1720 |
+
"classmap": [
|
1721 |
+
"src/"
|
1722 |
+
]
|
1723 |
+
},
|
1724 |
+
"notification-url": "https://packagist.org/downloads/",
|
1725 |
+
"license": [
|
1726 |
+
"BSD-3-Clause"
|
1727 |
+
],
|
1728 |
+
"authors": [
|
1729 |
+
{
|
1730 |
+
"name": "Sebastian Bergmann",
|
1731 |
+
"email": "sebastian@phpunit.de",
|
1732 |
+
"role": "lead"
|
1733 |
+
}
|
1734 |
+
],
|
1735 |
+
"description": "Collection of value objects that represent the types of the PHP type system",
|
1736 |
+
"homepage": "https://github.com/sebastianbergmann/type",
|
1737 |
+
"funding": [
|
1738 |
+
{
|
1739 |
+
"url": "https://github.com/sebastianbergmann",
|
1740 |
+
"type": "github"
|
1741 |
+
}
|
1742 |
+
],
|
1743 |
+
"time": "2021-06-15T12:49:02+00:00"
|
1744 |
+
},
|
1745 |
+
{
|
1746 |
+
"name": "sebastian/version",
|
1747 |
+
"version": "3.0.2",
|
1748 |
+
"source": {
|
1749 |
+
"type": "git",
|
1750 |
+
"url": "https://github.com/sebastianbergmann/version.git",
|
1751 |
+
"reference": "c6c1022351a901512170118436c764e473f6de8c"
|
1752 |
+
},
|
1753 |
+
"dist": {
|
1754 |
+
"type": "zip",
|
1755 |
+
"url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c",
|
1756 |
+
"reference": "c6c1022351a901512170118436c764e473f6de8c",
|
1757 |
+
"shasum": ""
|
1758 |
+
},
|
1759 |
+
"require": {
|
1760 |
+
"php": ">=7.3"
|
1761 |
+
},
|
1762 |
+
"type": "library",
|
1763 |
+
"extra": {
|
1764 |
+
"branch-alias": {
|
1765 |
+
"dev-master": "3.0-dev"
|
1766 |
+
}
|
1767 |
+
},
|
1768 |
+
"autoload": {
|
1769 |
+
"classmap": [
|
1770 |
+
"src/"
|
1771 |
+
]
|
1772 |
+
},
|
1773 |
+
"notification-url": "https://packagist.org/downloads/",
|
1774 |
+
"license": [
|
1775 |
+
"BSD-3-Clause"
|
1776 |
+
],
|
1777 |
+
"authors": [
|
1778 |
+
{
|
1779 |
+
"name": "Sebastian Bergmann",
|
1780 |
+
"email": "sebastian@phpunit.de",
|
1781 |
+
"role": "lead"
|
1782 |
+
}
|
1783 |
+
],
|
1784 |
+
"description": "Library that helps with managing the version number of Git-hosted PHP projects",
|
1785 |
+
"homepage": "https://github.com/sebastianbergmann/version",
|
1786 |
+
"funding": [
|
1787 |
+
{
|
1788 |
+
"url": "https://github.com/sebastianbergmann",
|
1789 |
+
"type": "github"
|
1790 |
+
}
|
1791 |
+
],
|
1792 |
+
"time": "2020-09-28T06:39:44+00:00"
|
1793 |
+
},
|
1794 |
+
{
|
1795 |
+
"name": "symfony/polyfill-ctype",
|
1796 |
+
"version": "v1.25.0",
|
1797 |
+
"source": {
|
1798 |
+
"type": "git",
|
1799 |
+
"url": "https://github.com/symfony/polyfill-ctype.git",
|
1800 |
+
"reference": "30885182c981ab175d4d034db0f6f469898070ab"
|
1801 |
+
},
|
1802 |
+
"dist": {
|
1803 |
+
"type": "zip",
|
1804 |
+
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/30885182c981ab175d4d034db0f6f469898070ab",
|
1805 |
+
"reference": "30885182c981ab175d4d034db0f6f469898070ab",
|
1806 |
+
"shasum": ""
|
1807 |
+
},
|
1808 |
+
"require": {
|
1809 |
+
"php": ">=7.1"
|
1810 |
+
},
|
1811 |
+
"provide": {
|
1812 |
+
"ext-ctype": "*"
|
1813 |
+
},
|
1814 |
+
"suggest": {
|
1815 |
+
"ext-ctype": "For best performance"
|
1816 |
+
},
|
1817 |
+
"type": "library",
|
1818 |
+
"extra": {
|
1819 |
+
"branch-alias": {
|
1820 |
+
"dev-main": "1.23-dev"
|
1821 |
+
},
|
1822 |
+
"thanks": {
|
1823 |
+
"name": "symfony/polyfill",
|
1824 |
+
"url": "https://github.com/symfony/polyfill"
|
1825 |
+
}
|
1826 |
+
},
|
1827 |
+
"autoload": {
|
1828 |
+
"files": [
|
1829 |
+
"bootstrap.php"
|
1830 |
+
],
|
1831 |
+
"psr-4": {
|
1832 |
+
"Symfony\\Polyfill\\Ctype\\": ""
|
1833 |
+
}
|
1834 |
+
},
|
1835 |
+
"notification-url": "https://packagist.org/downloads/",
|
1836 |
+
"license": [
|
1837 |
+
"MIT"
|
1838 |
+
],
|
1839 |
+
"authors": [
|
1840 |
+
{
|
1841 |
+
"name": "Gert de Pagter",
|
1842 |
+
"email": "BackEndTea@gmail.com"
|
1843 |
+
},
|
1844 |
+
{
|
1845 |
+
"name": "Symfony Community",
|
1846 |
+
"homepage": "https://symfony.com/contributors"
|
1847 |
+
}
|
1848 |
+
],
|
1849 |
+
"description": "Symfony polyfill for ctype functions",
|
1850 |
+
"homepage": "https://symfony.com",
|
1851 |
+
"keywords": [
|
1852 |
+
"compatibility",
|
1853 |
+
"ctype",
|
1854 |
+
"polyfill",
|
1855 |
+
"portable"
|
1856 |
+
],
|
1857 |
+
"funding": [
|
1858 |
+
{
|
1859 |
+
"url": "https://symfony.com/sponsor",
|
1860 |
+
"type": "custom"
|
1861 |
+
},
|
1862 |
+
{
|
1863 |
+
"url": "https://github.com/fabpot",
|
1864 |
+
"type": "github"
|
1865 |
+
},
|
1866 |
+
{
|
1867 |
+
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
1868 |
+
"type": "tidelift"
|
1869 |
+
}
|
1870 |
+
],
|
1871 |
+
"time": "2021-10-20T20:35:02+00:00"
|
1872 |
+
},
|
1873 |
+
{
|
1874 |
+
"name": "theseer/tokenizer",
|
1875 |
+
"version": "1.2.1",
|
1876 |
+
"source": {
|
1877 |
+
"type": "git",
|
1878 |
+
"url": "https://github.com/theseer/tokenizer.git",
|
1879 |
+
"reference": "34a41e998c2183e22995f158c581e7b5e755ab9e"
|
1880 |
+
},
|
1881 |
+
"dist": {
|
1882 |
+
"type": "zip",
|
1883 |
+
"url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e",
|
1884 |
+
"reference": "34a41e998c2183e22995f158c581e7b5e755ab9e",
|
1885 |
+
"shasum": ""
|
1886 |
+
},
|
1887 |
+
"require": {
|
1888 |
+
"ext-dom": "*",
|
1889 |
+
"ext-tokenizer": "*",
|
1890 |
+
"ext-xmlwriter": "*",
|
1891 |
+
"php": "^7.2 || ^8.0"
|
1892 |
+
},
|
1893 |
+
"type": "library",
|
1894 |
+
"autoload": {
|
1895 |
+
"classmap": [
|
1896 |
+
"src/"
|
1897 |
+
]
|
1898 |
+
},
|
1899 |
+
"notification-url": "https://packagist.org/downloads/",
|
1900 |
+
"license": [
|
1901 |
+
"BSD-3-Clause"
|
1902 |
+
],
|
1903 |
+
"authors": [
|
1904 |
+
{
|
1905 |
+
"name": "Arne Blankerts",
|
1906 |
+
"email": "arne@blankerts.de",
|
1907 |
+
"role": "Developer"
|
1908 |
+
}
|
1909 |
+
],
|
1910 |
+
"description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
|
1911 |
+
"funding": [
|
1912 |
+
{
|
1913 |
+
"url": "https://github.com/theseer",
|
1914 |
+
"type": "github"
|
1915 |
+
}
|
1916 |
+
],
|
1917 |
+
"time": "2021-07-28T10:34:58+00:00"
|
1918 |
+
},
|
1919 |
+
{
|
1920 |
+
"name": "webmozart/assert",
|
1921 |
+
"version": "1.10.0",
|
1922 |
+
"source": {
|
1923 |
+
"type": "git",
|
1924 |
+
"url": "https://github.com/webmozarts/assert.git",
|
1925 |
+
"reference": "6964c76c7804814a842473e0c8fd15bab0f18e25"
|
1926 |
+
},
|
1927 |
+
"dist": {
|
1928 |
+
"type": "zip",
|
1929 |
+
"url": "https://api.github.com/repos/webmozarts/assert/zipball/6964c76c7804814a842473e0c8fd15bab0f18e25",
|
1930 |
+
"reference": "6964c76c7804814a842473e0c8fd15bab0f18e25",
|
1931 |
+
"shasum": ""
|
1932 |
+
},
|
1933 |
+
"require": {
|
1934 |
+
"php": "^7.2 || ^8.0",
|
1935 |
+
"symfony/polyfill-ctype": "^1.8"
|
1936 |
+
},
|
1937 |
+
"conflict": {
|
1938 |
+
"phpstan/phpstan": "<0.12.20",
|
1939 |
+
"vimeo/psalm": "<4.6.1 || 4.6.2"
|
1940 |
+
},
|
1941 |
+
"require-dev": {
|
1942 |
+
"phpunit/phpunit": "^8.5.13"
|
1943 |
+
},
|
1944 |
+
"type": "library",
|
1945 |
+
"extra": {
|
1946 |
+
"branch-alias": {
|
1947 |
+
"dev-master": "1.10-dev"
|
1948 |
+
}
|
1949 |
+
},
|
1950 |
+
"autoload": {
|
1951 |
+
"psr-4": {
|
1952 |
+
"Webmozart\\Assert\\": "src/"
|
1953 |
+
}
|
1954 |
+
},
|
1955 |
+
"notification-url": "https://packagist.org/downloads/",
|
1956 |
+
"license": [
|
1957 |
+
"MIT"
|
1958 |
+
],
|
1959 |
+
"authors": [
|
1960 |
+
{
|
1961 |
+
"name": "Bernhard Schussek",
|
1962 |
+
"email": "bschussek@gmail.com"
|
1963 |
+
}
|
1964 |
+
],
|
1965 |
+
"description": "Assertions to validate method input/output with nice error messages.",
|
1966 |
+
"keywords": [
|
1967 |
+
"assert",
|
1968 |
+
"check",
|
1969 |
+
"validate"
|
1970 |
+
],
|
1971 |
+
"time": "2021-03-09T10:59:23+00:00"
|
1972 |
+
},
|
1973 |
+
{
|
1974 |
+
"name": "yoast/phpunit-polyfills",
|
1975 |
+
"version": "1.0.3",
|
1976 |
+
"source": {
|
1977 |
+
"type": "git",
|
1978 |
+
"url": "https://github.com/Yoast/PHPUnit-Polyfills.git",
|
1979 |
+
"reference": "5ea3536428944955f969bc764bbe09738e151ada"
|
1980 |
+
},
|
1981 |
+
"dist": {
|
1982 |
+
"type": "zip",
|
1983 |
+
"url": "https://api.github.com/repos/Yoast/PHPUnit-Polyfills/zipball/5ea3536428944955f969bc764bbe09738e151ada",
|
1984 |
+
"reference": "5ea3536428944955f969bc764bbe09738e151ada",
|
1985 |
+
"shasum": ""
|
1986 |
+
},
|
1987 |
+
"require": {
|
1988 |
+
"php": ">=5.4",
|
1989 |
+
"phpunit/phpunit": "^4.8.36 || ^5.7.21 || ^6.0 || ^7.0 || ^8.0 || ^9.0"
|
1990 |
+
},
|
1991 |
+
"require-dev": {
|
1992 |
+
"yoast/yoastcs": "^2.2.0"
|
1993 |
+
},
|
1994 |
+
"type": "library",
|
1995 |
+
"extra": {
|
1996 |
+
"branch-alias": {
|
1997 |
+
"dev-main": "1.x-dev",
|
1998 |
+
"dev-develop": "1.x-dev"
|
1999 |
+
}
|
2000 |
+
},
|
2001 |
+
"autoload": {
|
2002 |
+
"files": [
|
2003 |
+
"phpunitpolyfills-autoload.php"
|
2004 |
+
]
|
2005 |
+
},
|
2006 |
+
"notification-url": "https://packagist.org/downloads/",
|
2007 |
+
"license": [
|
2008 |
+
"BSD-3-Clause"
|
2009 |
+
],
|
2010 |
+
"authors": [
|
2011 |
+
{
|
2012 |
+
"name": "Team Yoast",
|
2013 |
+
"email": "support@yoast.com",
|
2014 |
+
"homepage": "https://yoast.com"
|
2015 |
+
},
|
2016 |
+
{
|
2017 |
+
"name": "Contributors",
|
2018 |
+
"homepage": "https://github.com/Yoast/PHPUnit-Polyfills/graphs/contributors"
|
2019 |
+
}
|
2020 |
+
],
|
2021 |
+
"description": "Set of polyfills for changed PHPUnit functionality to allow for creating PHPUnit cross-version compatible tests",
|
2022 |
+
"homepage": "https://github.com/Yoast/PHPUnit-Polyfills",
|
2023 |
+
"keywords": [
|
2024 |
+
"phpunit",
|
2025 |
+
"polyfill",
|
2026 |
+
"testing"
|
2027 |
+
],
|
2028 |
+
"time": "2021-11-23T01:37:03+00:00"
|
2029 |
+
}
|
2030 |
+
],
|
2031 |
+
"aliases": [],
|
2032 |
+
"minimum-stability": "stable",
|
2033 |
+
"stability-flags": [],
|
2034 |
+
"prefer-stable": false,
|
2035 |
+
"prefer-lowest": false,
|
2036 |
+
"platform": [],
|
2037 |
+
"platform-dev": [],
|
2038 |
+
"plugin-api-version": "1.1.0"
|
2039 |
+
}
|
vendor/boldgrid/library/src/Library/Configs.php
CHANGED
@@ -82,6 +82,14 @@ class Configs {
|
|
82 |
}
|
83 |
}
|
84 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
85 |
return self::$configs = wp_parse_args( $configs, $defaults );
|
86 |
}
|
87 |
|
82 |
}
|
83 |
}
|
84 |
|
85 |
+
/*
|
86 |
+
* Allow the default configs to be filtered via an option, bg_library_configs.
|
87 |
+
*
|
88 |
+
* Filtering via a actual filter (above) may be difficult due to timing / plugin load order.
|
89 |
+
*/
|
90 |
+
$option_overrides = get_option( 'bglib_configs', array() );
|
91 |
+
$defaults = wp_parse_args( $option_overrides, $defaults );
|
92 |
+
|
93 |
return self::$configs = wp_parse_args( $configs, $defaults );
|
94 |
}
|
95 |
|
vendor/boldgrid/library/src/Library/Dashboard/SortWidgets.php
CHANGED
@@ -144,6 +144,11 @@ class SortWidgets {
|
|
144 |
/**
|
145 |
* Sort the widgets as containted in the global $wp_meta_boxes.
|
146 |
*
|
|
|
|
|
|
|
|
|
|
|
147 |
* @since 2.9.0
|
148 |
*/
|
149 |
public function sortGlobal() {
|
@@ -157,10 +162,44 @@ class SortWidgets {
|
|
157 |
continue;
|
158 |
}
|
159 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
160 |
// First, remove the widget from where it is now.
|
161 |
unset( $wp_meta_boxes['dashboard'][$widget['container']][$widget['priority']][$id] );
|
162 |
|
163 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
164 |
$wp_meta_boxes['dashboard'][ $configs['container'] ][ $configs['priority'] ] =
|
165 |
array( $id => $widget['widget'] ) +
|
166 |
$wp_meta_boxes['dashboard'][ $configs['container'] ][ $configs['priority'] ];
|
144 |
/**
|
145 |
* Sort the widgets as containted in the global $wp_meta_boxes.
|
146 |
*
|
147 |
+
* We're not actually "sorting". This method will look in our configs and find the BoldGrid widgets
|
148 |
+
* that we want to appear at the top of the dashboard, and put them there at the top. It does this
|
149 |
+
* by removing the widget from wherever it is and then adding it to the beginning of the array of
|
150 |
+
* widgets.
|
151 |
+
*
|
152 |
* @since 2.9.0
|
153 |
*/
|
154 |
public function sortGlobal() {
|
162 |
continue;
|
163 |
}
|
164 |
|
165 |
+
/*
|
166 |
+
* Avoid the following error: Fatal error: Uncaught Error: Unsupported operand types.
|
167 |
+
*
|
168 |
+
* This is a very edge case, and we cannot reproduce it, but we need to avoid the fatal.
|
169 |
+
* It is caused when we are trying move our metabox to the beginning using:
|
170 |
+
* $boxes = $our_metabox + $boxes.
|
171 |
+
*
|
172 |
+
* Validate $boxes in the above scenario.
|
173 |
+
*/
|
174 |
+
if ( ! is_array( $wp_meta_boxes['dashboard'][ $configs['container'] ][ $configs['priority'] ] ) ) {
|
175 |
+
$wp_meta_boxes['dashboard'][ $configs['container'] ][ $configs['priority'] ] = array();
|
176 |
+
}
|
177 |
+
|
178 |
// First, remove the widget from where it is now.
|
179 |
unset( $wp_meta_boxes['dashboard'][$widget['container']][$widget['priority']][$id] );
|
180 |
|
181 |
+
/*
|
182 |
+
* Then, add it to the beginning of the array.
|
183 |
+
*
|
184 |
+
* We can't use array_unshift because we don't want the array keys to change.
|
185 |
+
*
|
186 |
+
* In the example below, we are setting "boldgrid-notifications" as the first metabox in
|
187 |
+
* $wp_meta_boxes['dashboard']['normal']['core']. This is how we are making it show atop
|
188 |
+
* other metaboxes.
|
189 |
+
*
|
190 |
+
* Before: Array(
|
191 |
+
* [dashboard_site_health] => Array,
|
192 |
+
* [dashboard_right_now] => Array,
|
193 |
+
* [dashboard_activity] => Array,
|
194 |
+
* )
|
195 |
+
*
|
196 |
+
* After: Array(
|
197 |
+
* [boldgrid-notifications] => Array,
|
198 |
+
* [dashboard_site_health] => Array,
|
199 |
+
* [dashboard_right_now] => Array,
|
200 |
+
* [dashboard_activity] => Array,
|
201 |
+
* )
|
202 |
+
*/
|
203 |
$wp_meta_boxes['dashboard'][ $configs['container'] ][ $configs['priority'] ] =
|
204 |
array( $id => $widget['widget'] ) +
|
205 |
$wp_meta_boxes['dashboard'][ $configs['container'] ][ $configs['priority'] ];
|
vendor/boldgrid/library/src/Library/RatingPrompt.php
CHANGED
@@ -127,7 +127,9 @@ class RatingPrompt {
|
|
127 |
foreach ( $slides as $slide ) {
|
128 |
echo $slide;
|
129 |
}
|
130 |
-
|
|
|
|
|
131 |
echo '</div>';
|
132 |
}
|
133 |
}
|
127 |
foreach ( $slides as $slide ) {
|
128 |
echo $slide;
|
129 |
}
|
130 |
+
|
131 |
+
// This Nonce was causing conflicts with core nonces. Added a prefix to the nonce name.
|
132 |
+
wp_nonce_field( 'bglib-rating-prompt', 'bglib_rating_prompt_nonce' );
|
133 |
echo '</div>';
|
134 |
}
|
135 |
}
|
vendor/boldgrid/library/src/Util/Load.php
CHANGED
@@ -285,6 +285,14 @@ class Load {
|
|
285 |
* @return bool
|
286 |
*/
|
287 |
public function isValidPath( $path ) {
|
288 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
289 |
}
|
290 |
}
|
285 |
* @return bool
|
286 |
*/
|
287 |
public function isValidPath( $path ) {
|
288 |
+
$wp_filesystem = Version::getWpFilesystem();
|
289 |
+
|
290 |
+
// This is a band-aid. Avoid issues on the ftp filesystem.
|
291 |
+
$is_ftp = 'ftpext' === get_filesystem_method() && 'WP_Filesystem_FTPext' === get_class( $wp_filesystem );
|
292 |
+
if ( $is_ftp && ! empty( $wp_filesystem->errors->errors ) ) {
|
293 |
+
return false;
|
294 |
+
}
|
295 |
+
|
296 |
+
return $wp_filesystem->exists( trailingslashit( $path ) . 'vendor/boldgrid/library' );
|
297 |
}
|
298 |
}
|
vendor/boldgrid/library/src/assets/js/rating-prompt.js
CHANGED
@@ -19,6 +19,9 @@ BOLDGRID.LIBRARY = BOLDGRID.LIBRARY || {};
|
|
19 |
/**
|
20 |
* @summary Dismiss (or snooze) a rating prompt.
|
21 |
*
|
|
|
|
|
|
|
22 |
* @since 2.7.7
|
23 |
*
|
24 |
* @param string name
|
@@ -31,7 +34,7 @@ BOLDGRID.LIBRARY = BOLDGRID.LIBRARY || {};
|
|
31 |
type: type,
|
32 |
length: length,
|
33 |
name: name,
|
34 |
-
security: $( '.bglib-rating-prompt #
|
35 |
};
|
36 |
|
37 |
$.ajax( {
|
19 |
/**
|
20 |
* @summary Dismiss (or snooze) a rating prompt.
|
21 |
*
|
22 |
+
* As of 2.13.5, the nonce's ID has been changed from '_wpnonce' to
|
23 |
+
* bglib_rating_prompt_nonce. This is to prevent conflicts with core nonces.
|
24 |
+
*
|
25 |
* @since 2.7.7
|
26 |
*
|
27 |
* @param string name
|
34 |
type: type,
|
35 |
length: length,
|
36 |
name: name,
|
37 |
+
security: $( '.bglib-rating-prompt #bglib_rating_prompt_nonce' ).val()
|
38 |
};
|
39 |
|
40 |
$.ajax( {
|
vendor/boldgrid/library/src/library.global.php
CHANGED
@@ -7,7 +7,7 @@ defined( 'WPFORMS_SHAREASALE_ID' ) || define( 'WPFORMS_SHAREASALE_ID', '1581233'
|
|
7 |
|
8 |
return array(
|
9 |
// libraryVersion is used to put the version number on js/css files.
|
10 |
-
'libraryVersion' => '2.13.
|
11 |
'api' => 'https://api.boldgrid.com',
|
12 |
'option' => 'license',
|
13 |
'key' => get_site_option( 'boldgrid_api_key', null ),
|
7 |
|
8 |
return array(
|
9 |
// libraryVersion is used to put the version number on js/css files.
|
10 |
+
'libraryVersion' => '2.13.6',
|
11 |
'api' => 'https://api.boldgrid.com',
|
12 |
'option' => 'license',
|
13 |
'key' => get_site_option( 'boldgrid_api_key', null ),
|
vendor/boldgrid/library/tests/Library/Library/test-activity.php
CHANGED
@@ -27,7 +27,7 @@ class Test_Activty extends WP_UnitTestCase {
|
|
27 |
/**
|
28 |
*
|
29 |
*/
|
30 |
-
public function
|
31 |
$this->reset();
|
32 |
|
33 |
$this->activityClass = new \Boldgrid\Library\Library\Activity( 'boldgrid-backup' );
|
27 |
/**
|
28 |
*
|
29 |
*/
|
30 |
+
public function set_up() {
|
31 |
$this->reset();
|
32 |
|
33 |
$this->activityClass = new \Boldgrid\Library\Library\Activity( 'boldgrid-backup' );
|
vendor/boldgrid/library/tests/Library/Library/test-rating-prompt.php
CHANGED
@@ -178,7 +178,7 @@ class Test_Rating_Prompt extends WP_UnitTestCase {
|
|
178 |
/**
|
179 |
* Setup.
|
180 |
*/
|
181 |
-
public function
|
182 |
$this->ratingPrompt = new \Boldgrid\Library\Library\RatingPrompt();
|
183 |
|
184 |
$this->reset();
|
178 |
/**
|
179 |
* Setup.
|
180 |
*/
|
181 |
+
public function set_up() {
|
182 |
$this->ratingPrompt = new \Boldgrid\Library\Library\RatingPrompt();
|
183 |
|
184 |
$this->reset();
|
vendor/boldgrid/library/tests/Library/Plugin/test-factory.php
CHANGED
@@ -30,7 +30,7 @@ class Test_BoldGrid_Library_Library_Plugin_Factory extends WP_UnitTestCase {
|
|
30 |
*
|
31 |
* @since 2.12.2
|
32 |
*/
|
33 |
-
public function
|
34 |
$plugin_data = array(
|
35 |
'Name' => 'Total Upkeep',
|
36 |
'PluginURI' => 'https://www.boldgrid.com/boldgrid-backup/',
|
30 |
*
|
31 |
* @since 2.12.2
|
32 |
*/
|
33 |
+
public function set_up() {
|
34 |
$plugin_data = array(
|
35 |
'Name' => 'Total Upkeep',
|
36 |
'PluginURI' => 'https://www.boldgrid.com/boldgrid-backup/',
|
vendor/boldgrid/library/tests/Library/Plugin/test-notice.php
CHANGED
@@ -22,7 +22,7 @@ class Test_BoldGrid_Library_Library_Plugin_Notice extends WP_UnitTestCase {
|
|
22 |
*
|
23 |
* @since 2.12.2
|
24 |
*/
|
25 |
-
public function
|
26 |
$this->sample_plugin = Plugin\Factory::create( 'boldgrid-backup/boldgrid-backup.php' );
|
27 |
$this->sample_notice_array = array(
|
28 |
'id' => 'bgbkup_database_encryption',
|
22 |
*
|
23 |
* @since 2.12.2
|
24 |
*/
|
25 |
+
public function set_up() {
|
26 |
$this->sample_plugin = Plugin\Factory::create( 'boldgrid-backup/boldgrid-backup.php' );
|
27 |
$this->sample_notice_array = array(
|
28 |
'id' => 'bgbkup_database_encryption',
|
vendor/boldgrid/library/tests/Library/Plugin/test-page.php
CHANGED
@@ -22,7 +22,7 @@ class Test_BoldGrid_Library_Library_Plugin_Page extends WP_UnitTestCase {
|
|
22 |
*
|
23 |
* @since 2.12.2
|
24 |
*/
|
25 |
-
public function
|
26 |
$this->config = array(
|
27 |
'pages' => array(
|
28 |
'boldgrid-backup-premium-features',
|
22 |
*
|
23 |
* @since 2.12.2
|
24 |
*/
|
25 |
+
public function set_up() {
|
26 |
$this->config = array(
|
27 |
'pages' => array(
|
28 |
'boldgrid-backup-premium-features',
|
vendor/boldgrid/library/tests/Library/Plugin/test-plugin.php
CHANGED
@@ -22,7 +22,7 @@ class Test_BoldGrid_Library_Library_Plugin_Plugin extends WP_UnitTestCase {
|
|
22 |
*
|
23 |
* @since 2.12.2
|
24 |
*/
|
25 |
-
public function
|
26 |
$this->config = array(
|
27 |
'pages' => array(
|
28 |
'boldgrid-backup-premium-features',
|
22 |
*
|
23 |
* @since 2.12.2
|
24 |
*/
|
25 |
+
public function set_up() {
|
26 |
$this->config = array(
|
27 |
'pages' => array(
|
28 |
'boldgrid-backup-premium-features',
|
vendor/boldgrid/library/tests/Library/Plugin/test-plugins.php
CHANGED
@@ -29,7 +29,7 @@ class Test_BoldGrid_Library_Library_Plugin_Plugins extends WP_UnitTestCase {
|
|
29 |
*
|
30 |
* @since 1.7.7
|
31 |
*/
|
32 |
-
public function
|
33 |
$plugin_dirs = scandir( ABSPATH . '/wp-content/plugins/' );
|
34 |
$this->expected_plugins = array();
|
35 |
$this->expected_plugin_slugs = array();
|
29 |
*
|
30 |
* @since 1.7.7
|
31 |
*/
|
32 |
+
public function set_up() {
|
33 |
$plugin_dirs = scandir( ABSPATH . '/wp-content/plugins/' );
|
34 |
$this->expected_plugins = array();
|
35 |
$this->expected_plugin_slugs = array();
|
vendor/boldgrid/library/tests/Library/Theme/test-theme.php
CHANGED
@@ -27,7 +27,7 @@ class Test_BoldGrid_Library_Library_Theme_Theme extends WP_UnitTestCase {
|
|
27 |
*
|
28 |
* @since 1.7.7
|
29 |
*/
|
30 |
-
public function
|
31 |
// Setup our configs.
|
32 |
delete_site_transient( 'update_themes' );
|
33 |
$this->stylesheet = 'twentytwenty';
|
27 |
*
|
28 |
* @since 1.7.7
|
29 |
*/
|
30 |
+
public function set_up() {
|
31 |
// Setup our configs.
|
32 |
delete_site_transient( 'update_themes' );
|
33 |
$this->stylesheet = 'twentytwenty';
|
vendor/boldgrid/library/tests/Library/Theme/test-themes.php
CHANGED
@@ -29,7 +29,7 @@ class Test_BoldGrid_Library_Library_Theme_Themes extends WP_UnitTestCase {
|
|
29 |
*
|
30 |
* @since 1.7.7
|
31 |
*/
|
32 |
-
public function
|
33 |
global $wpdb;
|
34 |
|
35 |
$this->themes = new Theme\Themes();
|
29 |
*
|
30 |
* @since 1.7.7
|
31 |
*/
|
32 |
+
public function set_up() {
|
33 |
global $wpdb;
|
34 |
|
35 |
$this->themes = new Theme\Themes();
|
vendor/boldgrid/library/tests/Library/Theme/test-update-data.php
CHANGED
@@ -29,7 +29,7 @@ class Test_BoldGrid_Library_Library_Theme_UpdateData extends WP_UnitTestCase {
|
|
29 |
*
|
30 |
* @since 1.7.7
|
31 |
*/
|
32 |
-
public function
|
33 |
// Setup our configs.
|
34 |
delete_transient( 'boldgrid_theme_information' );
|
35 |
$this->transient_data = array(
|
29 |
*
|
30 |
* @since 1.7.7
|
31 |
*/
|
32 |
+
public function set_up() {
|
33 |
// Setup our configs.
|
34 |
delete_transient( 'boldgrid_theme_information' );
|
35 |
$this->transient_data = array(
|
vendor/boldgrid/library/tests/bootstrap.php
CHANGED
@@ -45,5 +45,14 @@ require_once dirname( dirname( __FILE__ ) ) . '/src/Library/Activity.php';
|
|
45 |
require_once dirname( dirname( __FILE__ ) ) . '/src/Util/Option.php';
|
46 |
require_once dirname( dirname( __FILE__ ) ) . '/src/Util/Version.php';
|
47 |
|
48 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
|
|
45 |
require_once dirname( dirname( __FILE__ ) ) . '/src/Util/Option.php';
|
46 |
require_once dirname( dirname( __FILE__ ) ) . '/src/Util/Version.php';
|
47 |
|
48 |
+
/*
|
49 |
+
* Yoast/PHPUnit-Polyfills, required for running the WP test suite.
|
50 |
+
* Please see https://make.wordpress.org/core/2021/09/27/changes-to-the-wordpress-core-php-test-suite/
|
51 |
+
*
|
52 |
+
* The WP Core test suite can now run on all PHPUnit versions between PHPUnit 5.7.21 up to the latest
|
53 |
+
* release (at the time of writing: PHPUnit 9.5.10), which allows for running the test suite against
|
54 |
+
* all supported PHP versions using the most appropriate PHPUnit version for that PHP version.
|
55 |
+
*/
|
56 |
+
require_once dirname( dirname( __FILE__ ) ) . '/vendor/yoast/phpunit-polyfills/phpunitpolyfills-autoload.php';
|
57 |
|
58 |
+
require $_tests_dir . '/includes/bootstrap.php';
|
vendor/boldgrid/library/yarn.lock
CHANGED
@@ -1255,9 +1255,9 @@ inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3:
|
|
1255 |
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
1256 |
|
1257 |
ini@~1.3.0:
|
1258 |
-
version "1.3.
|
1259 |
-
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.
|
1260 |
-
integrity sha512-
|
1261 |
|
1262 |
inquirer@^6.2.2:
|
1263 |
version "6.5.2"
|
@@ -1579,9 +1579,9 @@ lodash.unescape@4.0.1:
|
|
1579 |
integrity sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw=
|
1580 |
|
1581 |
lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4:
|
1582 |
-
version "4.17.
|
1583 |
-
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.
|
1584 |
-
integrity sha512-
|
1585 |
|
1586 |
loglevel-colored-level-prefix@^1.0.0:
|
1587 |
version "1.0.0"
|
@@ -2747,9 +2747,9 @@ write@1.0.3:
|
|
2747 |
mkdirp "^0.5.1"
|
2748 |
|
2749 |
y18n@^4.0.0:
|
2750 |
-
version "4.0.
|
2751 |
-
resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.
|
2752 |
-
integrity sha512-
|
2753 |
|
2754 |
yallist@^3.0.0, yallist@^3.0.3:
|
2755 |
version "3.1.1"
|
@@ -2757,9 +2757,9 @@ yallist@^3.0.0, yallist@^3.0.3:
|
|
2757 |
integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
|
2758 |
|
2759 |
yargs-parser@^13.1.1:
|
2760 |
-
version "13.1.
|
2761 |
-
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.
|
2762 |
-
integrity sha512-
|
2763 |
dependencies:
|
2764 |
camelcase "^5.0.0"
|
2765 |
decamelize "^1.2.0"
|
1255 |
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
1256 |
|
1257 |
ini@~1.3.0:
|
1258 |
+
version "1.3.7"
|
1259 |
+
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.7.tgz#a09363e1911972ea16d7a8851005d84cf09a9a84"
|
1260 |
+
integrity sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==
|
1261 |
|
1262 |
inquirer@^6.2.2:
|
1263 |
version "6.5.2"
|
1579 |
integrity sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw=
|
1580 |
|
1581 |
lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4:
|
1582 |
+
version "4.17.21"
|
1583 |
+
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
1584 |
+
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
1585 |
|
1586 |
loglevel-colored-level-prefix@^1.0.0:
|
1587 |
version "1.0.0"
|
2747 |
mkdirp "^0.5.1"
|
2748 |
|
2749 |
y18n@^4.0.0:
|
2750 |
+
version "4.0.1"
|
2751 |
+
resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.1.tgz#8db2b83c31c5d75099bb890b23f3094891e247d4"
|
2752 |
+
integrity sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==
|
2753 |
|
2754 |
yallist@^3.0.0, yallist@^3.0.3:
|
2755 |
version "3.1.1"
|
2757 |
integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
|
2758 |
|
2759 |
yargs-parser@^13.1.1:
|
2760 |
+
version "13.1.2"
|
2761 |
+
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38"
|
2762 |
+
integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==
|
2763 |
dependencies:
|
2764 |
camelcase "^5.0.0"
|
2765 |
decamelize "^1.2.0"
|
vendor/composer/autoload_real.php
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
// autoload_real.php @generated by Composer
|
4 |
|
5 |
-
class
|
6 |
{
|
7 |
private static $loader;
|
8 |
|
@@ -22,15 +22,15 @@ class ComposerAutoloaderInit651c2267921840af4e23d4a1a286ef03
|
|
22 |
return self::$loader;
|
23 |
}
|
24 |
|
25 |
-
spl_autoload_register(array('
|
26 |
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
27 |
-
spl_autoload_unregister(array('
|
28 |
|
29 |
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
|
30 |
if ($useStaticLoader) {
|
31 |
require_once __DIR__ . '/autoload_static.php';
|
32 |
|
33 |
-
call_user_func(\Composer\Autoload\
|
34 |
} else {
|
35 |
$map = require __DIR__ . '/autoload_namespaces.php';
|
36 |
foreach ($map as $namespace => $path) {
|
@@ -51,19 +51,19 @@ class ComposerAutoloaderInit651c2267921840af4e23d4a1a286ef03
|
|
51 |
$loader->register(true);
|
52 |
|
53 |
if ($useStaticLoader) {
|
54 |
-
$includeFiles = Composer\Autoload\
|
55 |
} else {
|
56 |
$includeFiles = require __DIR__ . '/autoload_files.php';
|
57 |
}
|
58 |
foreach ($includeFiles as $fileIdentifier => $file) {
|
59 |
-
|
60 |
}
|
61 |
|
62 |
return $loader;
|
63 |
}
|
64 |
}
|
65 |
|
66 |
-
function
|
67 |
{
|
68 |
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
69 |
require $file;
|
2 |
|
3 |
// autoload_real.php @generated by Composer
|
4 |
|
5 |
+
class ComposerAutoloaderInit21ce95d681fa0cbccf157df200b627c0
|
6 |
{
|
7 |
private static $loader;
|
8 |
|
22 |
return self::$loader;
|
23 |
}
|
24 |
|
25 |
+
spl_autoload_register(array('ComposerAutoloaderInit21ce95d681fa0cbccf157df200b627c0', 'loadClassLoader'), true, true);
|
26 |
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
27 |
+
spl_autoload_unregister(array('ComposerAutoloaderInit21ce95d681fa0cbccf157df200b627c0', 'loadClassLoader'));
|
28 |
|
29 |
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
|
30 |
if ($useStaticLoader) {
|
31 |
require_once __DIR__ . '/autoload_static.php';
|
32 |
|
33 |
+
call_user_func(\Composer\Autoload\ComposerStaticInit21ce95d681fa0cbccf157df200b627c0::getInitializer($loader));
|
34 |
} else {
|
35 |
$map = require __DIR__ . '/autoload_namespaces.php';
|
36 |
foreach ($map as $namespace => $path) {
|
51 |
$loader->register(true);
|
52 |
|
53 |
if ($useStaticLoader) {
|
54 |
+
$includeFiles = Composer\Autoload\ComposerStaticInit21ce95d681fa0cbccf157df200b627c0::$files;
|
55 |
} else {
|
56 |
$includeFiles = require __DIR__ . '/autoload_files.php';
|
57 |
}
|
58 |
foreach ($includeFiles as $fileIdentifier => $file) {
|
59 |
+
composerRequire21ce95d681fa0cbccf157df200b627c0($fileIdentifier, $file);
|
60 |
}
|
61 |
|
62 |
return $loader;
|
63 |
}
|
64 |
}
|
65 |
|
66 |
+
function composerRequire21ce95d681fa0cbccf157df200b627c0($fileIdentifier, $file)
|
67 |
{
|
68 |
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
69 |
require $file;
|
vendor/composer/autoload_static.php
CHANGED
@@ -4,7 +4,7 @@
|
|
4 |
|
5 |
namespace Composer\Autoload;
|
6 |
|
7 |
-
class
|
8 |
{
|
9 |
public static $files = array (
|
10 |
'decc78cc4436b1292c6c0d151b19445c' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/bootstrap.php',
|
@@ -91,9 +91,9 @@ class ComposerStaticInit651c2267921840af4e23d4a1a286ef03
|
|
91 |
public static function getInitializer(ClassLoader $loader)
|
92 |
{
|
93 |
return \Closure::bind(function () use ($loader) {
|
94 |
-
$loader->prefixLengthsPsr4 =
|
95 |
-
$loader->prefixDirsPsr4 =
|
96 |
-
$loader->classMap =
|
97 |
|
98 |
}, null, ClassLoader::class);
|
99 |
}
|
4 |
|
5 |
namespace Composer\Autoload;
|
6 |
|
7 |
+
class ComposerStaticInit21ce95d681fa0cbccf157df200b627c0
|
8 |
{
|
9 |
public static $files = array (
|
10 |
'decc78cc4436b1292c6c0d151b19445c' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/bootstrap.php',
|
91 |
public static function getInitializer(ClassLoader $loader)
|
92 |
{
|
93 |
return \Closure::bind(function () use ($loader) {
|
94 |
+
$loader->prefixLengthsPsr4 = ComposerStaticInit21ce95d681fa0cbccf157df200b627c0::$prefixLengthsPsr4;
|
95 |
+
$loader->prefixDirsPsr4 = ComposerStaticInit21ce95d681fa0cbccf157df200b627c0::$prefixDirsPsr4;
|
96 |
+
$loader->classMap = ComposerStaticInit21ce95d681fa0cbccf157df200b627c0::$classMap;
|
97 |
|
98 |
}, null, ClassLoader::class);
|
99 |
}
|
vendor/composer/installed.json
CHANGED
@@ -1,20 +1,23 @@
|
|
1 |
[
|
2 |
{
|
3 |
"name": "boldgrid/library",
|
4 |
-
"version": "2.13.
|
5 |
-
"version_normalized": "2.13.
|
6 |
"source": {
|
7 |
"type": "git",
|
8 |
"url": "https://github.com/BoldGrid/library.git",
|
9 |
-
"reference": "
|
10 |
},
|
11 |
"dist": {
|
12 |
"type": "zip",
|
13 |
-
"url": "https://api.github.com/repos/BoldGrid/library/zipball/
|
14 |
-
"reference": "
|
15 |
"shasum": ""
|
16 |
},
|
17 |
-
"
|
|
|
|
|
|
|
18 |
"type": "library",
|
19 |
"installation-source": "dist",
|
20 |
"autoload": {
|
@@ -60,7 +63,6 @@
|
|
60 |
"url": "https://github.com/chland/tdcron",
|
61 |
"reference": "origin/master"
|
62 |
},
|
63 |
-
"time": "2018-01-23T14:06:12+00:00",
|
64 |
"type": "library",
|
65 |
"installation-source": "source"
|
66 |
},
|
@@ -125,17 +127,17 @@
|
|
125 |
},
|
126 |
{
|
127 |
"name": "phpseclib/phpseclib",
|
128 |
-
"version": "2.0.
|
129 |
-
"version_normalized": "2.0.
|
130 |
"source": {
|
131 |
"type": "git",
|
132 |
"url": "https://github.com/phpseclib/phpseclib.git",
|
133 |
-
"reference": "
|
134 |
},
|
135 |
"dist": {
|
136 |
"type": "zip",
|
137 |
-
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/
|
138 |
-
"reference": "
|
139 |
"shasum": ""
|
140 |
},
|
141 |
"require": {
|
@@ -152,7 +154,7 @@
|
|
152 |
"ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.",
|
153 |
"ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations."
|
154 |
},
|
155 |
-
"time": "
|
156 |
"type": "library",
|
157 |
"installation-source": "dist",
|
158 |
"autoload": {
|
1 |
[
|
2 |
{
|
3 |
"name": "boldgrid/library",
|
4 |
+
"version": "2.13.6",
|
5 |
+
"version_normalized": "2.13.6.0",
|
6 |
"source": {
|
7 |
"type": "git",
|
8 |
"url": "https://github.com/BoldGrid/library.git",
|
9 |
+
"reference": "f225b4cabbd3758b2beebf0ec890959c6bea2564"
|
10 |
},
|
11 |
"dist": {
|
12 |
"type": "zip",
|
13 |
+
"url": "https://api.github.com/repos/BoldGrid/library/zipball/f225b4cabbd3758b2beebf0ec890959c6bea2564",
|
14 |
+
"reference": "f225b4cabbd3758b2beebf0ec890959c6bea2564",
|
15 |
"shasum": ""
|
16 |
},
|
17 |
+
"require-dev": {
|
18 |
+
"yoast/phpunit-polyfills": "^1.0"
|
19 |
+
},
|
20 |
+
"time": "2022-03-15T17:39:20+00:00",
|
21 |
"type": "library",
|
22 |
"installation-source": "dist",
|
23 |
"autoload": {
|
63 |
"url": "https://github.com/chland/tdcron",
|
64 |
"reference": "origin/master"
|
65 |
},
|
|
|
66 |
"type": "library",
|
67 |
"installation-source": "source"
|
68 |
},
|
127 |
},
|
128 |
{
|
129 |
"name": "phpseclib/phpseclib",
|
130 |
+
"version": "2.0.36",
|
131 |
+
"version_normalized": "2.0.36.0",
|
132 |
"source": {
|
133 |
"type": "git",
|
134 |
"url": "https://github.com/phpseclib/phpseclib.git",
|
135 |
+
"reference": "a97547126396548c224703a267a30af1592be146"
|
136 |
},
|
137 |
"dist": {
|
138 |
"type": "zip",
|
139 |
+
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/a97547126396548c224703a267a30af1592be146",
|
140 |
+
"reference": "a97547126396548c224703a267a30af1592be146",
|
141 |
"shasum": ""
|
142 |
},
|
143 |
"require": {
|
154 |
"ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.",
|
155 |
"ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations."
|
156 |
},
|
157 |
+
"time": "2022-01-30T08:48:36+00:00",
|
158 |
"type": "library",
|
159 |
"installation-source": "dist",
|
160 |
"autoload": {
|
vendor/phpseclib/phpseclib/BACKERS.md
CHANGED
@@ -4,5 +4,9 @@ phpseclib ongoing development is made possible by [Tidelift](https://tidelift.co
|
|
4 |
|
5 |
## Backers
|
6 |
|
|
|
|
|
7 |
- Zane Hooper
|
8 |
-
- [Setasign](https://www.setasign.com/)
|
|
|
|
4 |
|
5 |
## Backers
|
6 |
|
7 |
+
- Allan Simon
|
8 |
+
- Raghu Veer Dendukuri
|
9 |
- Zane Hooper
|
10 |
+
- [Setasign](https://www.setasign.com/)
|
11 |
+
- [Charles Severance](https://github.com/csev)
|
12 |
+
- [Rachel Fish](https://github.com/itsrachelfish)
|
vendor/phpseclib/phpseclib/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
# phpseclib - PHP Secure Communications Library
|
2 |
|
3 |
-
[![Build Status](https://travis-ci.com/phpseclib/phpseclib.svg?branch=2.0)](https://travis-ci.com/phpseclib/phpseclib)
|
4 |
|
5 |
## Supporting phpseclib
|
6 |
|
@@ -52,7 +52,7 @@ SSH-2, SFTP, X.509, an arbitrary-precision integer arithmetic library, Ed25519 /
|
|
52 |
* Composer compatible (PSR-0 autoloading)
|
53 |
* Install using Composer: `composer require phpseclib/phpseclib:~1.0`
|
54 |
* Install using PEAR: See [phpseclib PEAR Channel Documentation](http://phpseclib.sourceforge.net/pear.htm)
|
55 |
-
* [Download 1.0.
|
56 |
|
57 |
## Security contact information
|
58 |
|
@@ -66,6 +66,12 @@ Need Support?
|
|
66 |
* [Create a Support Ticket on GitHub](https://github.com/phpseclib/phpseclib/issues/new)
|
67 |
* [Browse the Support Forum](http://www.frostjedi.com/phpbb/viewforum.php?f=46) (no longer in use)
|
68 |
|
|
|
|
|
|
|
|
|
|
|
|
|
69 |
## Contributing
|
70 |
|
71 |
1. Fork the Project
|
1 |
# phpseclib - PHP Secure Communications Library
|
2 |
|
3 |
+
[![Build Status](https://travis-ci.com/phpseclib/phpseclib.svg?branch=2.0)](https://travis-ci.com/github/phpseclib/phpseclib)
|
4 |
|
5 |
## Supporting phpseclib
|
6 |
|
52 |
* Composer compatible (PSR-0 autoloading)
|
53 |
* Install using Composer: `composer require phpseclib/phpseclib:~1.0`
|
54 |
* Install using PEAR: See [phpseclib PEAR Channel Documentation](http://phpseclib.sourceforge.net/pear.htm)
|
55 |
+
* [Download 1.0.20 as ZIP](http://sourceforge.net/projects/phpseclib/files/phpseclib1.0.20.zip/download)
|
56 |
|
57 |
## Security contact information
|
58 |
|
66 |
* [Create a Support Ticket on GitHub](https://github.com/phpseclib/phpseclib/issues/new)
|
67 |
* [Browse the Support Forum](http://www.frostjedi.com/phpbb/viewforum.php?f=46) (no longer in use)
|
68 |
|
69 |
+
## Special Thanks
|
70 |
+
|
71 |
+
Special Thanks to our Patreon sponsors!:
|
72 |
+
|
73 |
+
- Allan Simon
|
74 |
+
|
75 |
## Contributing
|
76 |
|
77 |
1. Fork the Project
|
vendor/phpseclib/phpseclib/phpseclib/Crypt/Base.php
CHANGED
@@ -79,7 +79,11 @@ abstract class Base
|
|
79 |
/**
|
80 |
* Encrypt / decrypt using the Cipher Feedback mode (8bit)
|
81 |
*/
|
82 |
-
const MODE_CFB8 =
|
|
|
|
|
|
|
|
|
83 |
/**
|
84 |
* Encrypt / decrypt using the Output Feedback mode.
|
85 |
*
|
@@ -484,6 +488,7 @@ abstract class Base
|
|
484 |
case self::MODE_CTR:
|
485 |
case self::MODE_CFB:
|
486 |
case self::MODE_CFB8:
|
|
|
487 |
case self::MODE_OFB:
|
488 |
case self::MODE_STREAM:
|
489 |
$this->mode = $mode;
|
@@ -773,8 +778,25 @@ abstract class Base
|
|
773 |
}
|
774 |
}
|
775 |
return $ciphertext;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
776 |
case self::MODE_OFB:
|
777 |
return $this->_openssl_ofb_process($plaintext, $this->encryptIV, $this->enbuffer);
|
|
|
|
|
778 |
}
|
779 |
}
|
780 |
|
@@ -959,12 +981,14 @@ abstract class Base
|
|
959 |
}
|
960 |
break;
|
961 |
case self::MODE_CFB8:
|
|
|
|
|
962 |
$ciphertext = '';
|
963 |
$len = strlen($plaintext);
|
964 |
$iv = $this->encryptIV;
|
965 |
|
966 |
for ($i = 0; $i < $len; ++$i) {
|
967 |
-
$ciphertext
|
968 |
$iv = substr($iv, 1) . $c;
|
969 |
}
|
970 |
|
@@ -976,6 +1000,21 @@ abstract class Base
|
|
976 |
}
|
977 |
}
|
978 |
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
979 |
case self::MODE_OFB:
|
980 |
$xor = $this->encryptIV;
|
981 |
if (strlen($buffer['xor'])) {
|
@@ -1116,6 +1155,21 @@ abstract class Base
|
|
1116 |
}
|
1117 |
}
|
1118 |
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1119 |
case self::MODE_OFB:
|
1120 |
$plaintext = $this->_openssl_ofb_process($ciphertext, $this->decryptIV, $this->debuffer);
|
1121 |
}
|
@@ -1290,7 +1344,7 @@ abstract class Base
|
|
1290 |
$iv = $this->decryptIV;
|
1291 |
|
1292 |
for ($i = 0; $i < $len; ++$i) {
|
1293 |
-
$plaintext
|
1294 |
$iv = substr($iv, 1) . $ciphertext[$i];
|
1295 |
}
|
1296 |
|
@@ -1302,6 +1356,21 @@ abstract class Base
|
|
1302 |
}
|
1303 |
}
|
1304 |
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1305 |
case self::MODE_OFB:
|
1306 |
$xor = $this->decryptIV;
|
1307 |
if (strlen($buffer['xor'])) {
|
@@ -1864,6 +1933,7 @@ abstract class Base
|
|
1864 |
self::MODE_CFB => 'ncfb',
|
1865 |
self::MODE_CFB8 => MCRYPT_MODE_CFB,
|
1866 |
self::MODE_OFB => MCRYPT_MODE_NOFB,
|
|
|
1867 |
self::MODE_STREAM => MCRYPT_MODE_STREAM,
|
1868 |
);
|
1869 |
|
@@ -2446,7 +2516,7 @@ abstract class Base
|
|
2446 |
for ($_i = 0; $_i < $_len; ++$_i) {
|
2447 |
$in = $_iv;
|
2448 |
'.$encrypt_block.'
|
2449 |
-
$_ciphertext
|
2450 |
$_iv = substr($_iv, 1) . $_c;
|
2451 |
}
|
2452 |
|
@@ -2468,7 +2538,7 @@ abstract class Base
|
|
2468 |
for ($_i = 0; $_i < $_len; ++$_i) {
|
2469 |
$in = $_iv;
|
2470 |
'.$encrypt_block.'
|
2471 |
-
$_plaintext
|
2472 |
$_iv = substr($_iv, 1) . $_text[$_i];
|
2473 |
}
|
2474 |
|
@@ -2480,6 +2550,44 @@ abstract class Base
|
|
2480 |
}
|
2481 |
}
|
2482 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2483 |
return $_plaintext;
|
2484 |
';
|
2485 |
break;
|
79 |
/**
|
80 |
* Encrypt / decrypt using the Cipher Feedback mode (8bit)
|
81 |
*/
|
82 |
+
const MODE_CFB8 = 6;
|
83 |
+
/**
|
84 |
+
* Encrypt / decrypt using the Output Feedback mode (8bit)
|
85 |
+
*/
|
86 |
+
const MODE_OFB8 = 7;
|
87 |
/**
|
88 |
* Encrypt / decrypt using the Output Feedback mode.
|
89 |
*
|
488 |
case self::MODE_CTR:
|
489 |
case self::MODE_CFB:
|
490 |
case self::MODE_CFB8:
|
491 |
+
case self::MODE_OFB8:
|
492 |
case self::MODE_OFB:
|
493 |
case self::MODE_STREAM:
|
494 |
$this->mode = $mode;
|
778 |
}
|
779 |
}
|
780 |
return $ciphertext;
|
781 |
+
case self::MODE_OFB8:
|
782 |
+
$ciphertext = '';
|
783 |
+
$len = strlen($plaintext);
|
784 |
+
$iv = $this->encryptIV;
|
785 |
+
|
786 |
+
for ($i = 0; $i < $len; ++$i) {
|
787 |
+
$xor = openssl_encrypt($iv, $this->cipher_name_openssl_ecb, $this->key, $this->openssl_options, $this->decryptIV);
|
788 |
+
$ciphertext.= $plaintext[$i] ^ $xor;
|
789 |
+
$iv = substr($iv, 1) . $xor[0];
|
790 |
+
}
|
791 |
+
|
792 |
+
if ($this->continuousBuffer) {
|
793 |
+
$this->encryptIV = $iv;
|
794 |
+
}
|
795 |
+
break;
|
796 |
case self::MODE_OFB:
|
797 |
return $this->_openssl_ofb_process($plaintext, $this->encryptIV, $this->enbuffer);
|
798 |
+
case self::MODE_OFB8:
|
799 |
+
// OpenSSL has built in support for cfb8 but not ofb8
|
800 |
}
|
801 |
}
|
802 |
|
981 |
}
|
982 |
break;
|
983 |
case self::MODE_CFB8:
|
984 |
+
// compared to regular CFB, which encrypts a block at a time,
|
985 |
+
// here, we're encrypting a byte at a time
|
986 |
$ciphertext = '';
|
987 |
$len = strlen($plaintext);
|
988 |
$iv = $this->encryptIV;
|
989 |
|
990 |
for ($i = 0; $i < $len; ++$i) {
|
991 |
+
$ciphertext.= ($c = $plaintext[$i] ^ $this->_encryptBlock($iv));
|
992 |
$iv = substr($iv, 1) . $c;
|
993 |
}
|
994 |
|
1000 |
}
|
1001 |
}
|
1002 |
break;
|
1003 |
+
case self::MODE_OFB8:
|
1004 |
+
$ciphertext = '';
|
1005 |
+
$len = strlen($plaintext);
|
1006 |
+
$iv = $this->encryptIV;
|
1007 |
+
|
1008 |
+
for ($i = 0; $i < $len; ++$i) {
|
1009 |
+
$xor = $this->_encryptBlock($iv);
|
1010 |
+
$ciphertext.= $plaintext[$i] ^ $xor;
|
1011 |
+
$iv = substr($iv, 1) . $xor[0];
|
1012 |
+
}
|
1013 |
+
|
1014 |
+
if ($this->continuousBuffer) {
|
1015 |
+
$this->encryptIV = $iv;
|
1016 |
+
}
|
1017 |
+
break;
|
1018 |
case self::MODE_OFB:
|
1019 |
$xor = $this->encryptIV;
|
1020 |
if (strlen($buffer['xor'])) {
|
1155 |
}
|
1156 |
}
|
1157 |
break;
|
1158 |
+
case self::MODE_OFB8:
|
1159 |
+
$plaintext = '';
|
1160 |
+
$len = strlen($ciphertext);
|
1161 |
+
$iv = $this->decryptIV;
|
1162 |
+
|
1163 |
+
for ($i = 0; $i < $len; ++$i) {
|
1164 |
+
$xor = openssl_encrypt($iv, $this->cipher_name_openssl_ecb, $this->key, $this->openssl_options, $this->decryptIV);
|
1165 |
+
$plaintext.= $ciphertext[$i] ^ $xor;
|
1166 |
+
$iv = substr($iv, 1) . $xor[0];
|
1167 |
+
}
|
1168 |
+
|
1169 |
+
if ($this->continuousBuffer) {
|
1170 |
+
$this->decryptIV = $iv;
|
1171 |
+
}
|
1172 |
+
break;
|
1173 |
case self::MODE_OFB:
|
1174 |
$plaintext = $this->_openssl_ofb_process($ciphertext, $this->decryptIV, $this->debuffer);
|
1175 |
}
|
1344 |
$iv = $this->decryptIV;
|
1345 |
|
1346 |
for ($i = 0; $i < $len; ++$i) {
|
1347 |
+
$plaintext.= $ciphertext[$i] ^ $this->_encryptBlock($iv);
|
1348 |
$iv = substr($iv, 1) . $ciphertext[$i];
|
1349 |
}
|
1350 |
|
1356 |
}
|
1357 |
}
|
1358 |
break;
|
1359 |
+
case self::MODE_OFB8:
|
1360 |
+
$plaintext = '';
|
1361 |
+
$len = strlen($ciphertext);
|
1362 |
+
$iv = $this->decryptIV;
|
1363 |
+
|
1364 |
+
for ($i = 0; $i < $len; ++$i) {
|
1365 |
+
$xor = $this->_encryptBlock($iv);
|
1366 |
+
$plaintext.= $ciphertext[$i] ^ $xor;
|
1367 |
+
$iv = substr($iv, 1) . $xor[0];
|
1368 |
+
}
|
1369 |
+
|
1370 |
+
if ($this->continuousBuffer) {
|
1371 |
+
$this->decryptIV = $iv;
|
1372 |
+
}
|
1373 |
+
break;
|
1374 |
case self::MODE_OFB:
|
1375 |
$xor = $this->decryptIV;
|
1376 |
if (strlen($buffer['xor'])) {
|
1933 |
self::MODE_CFB => 'ncfb',
|
1934 |
self::MODE_CFB8 => MCRYPT_MODE_CFB,
|
1935 |
self::MODE_OFB => MCRYPT_MODE_NOFB,
|
1936 |
+
self::MODE_OFB8 => MCRYPT_MODE_OFB,
|
1937 |
self::MODE_STREAM => MCRYPT_MODE_STREAM,
|
1938 |
);
|
1939 |
|
2516 |
for ($_i = 0; $_i < $_len; ++$_i) {
|
2517 |
$in = $_iv;
|
2518 |
'.$encrypt_block.'
|
2519 |
+
$_ciphertext.= ($_c = $_text[$_i] ^ $in);
|
2520 |
$_iv = substr($_iv, 1) . $_c;
|
2521 |
}
|
2522 |
|
2538 |
for ($_i = 0; $_i < $_len; ++$_i) {
|
2539 |
$in = $_iv;
|
2540 |
'.$encrypt_block.'
|
2541 |
+
$_plaintext.= $_text[$_i] ^ $in;
|
2542 |
$_iv = substr($_iv, 1) . $_text[$_i];
|
2543 |
}
|
2544 |
|
2550 |
}
|
2551 |
}
|
2552 |
|
2553 |
+
return $_plaintext;
|
2554 |
+
';
|
2555 |
+
break;
|
2556 |
+
case self::MODE_OFB8:
|
2557 |
+
$encrypt = $init_encrypt . '
|
2558 |
+
$_ciphertext = "";
|
2559 |
+
$_len = strlen($_text);
|
2560 |
+
$_iv = $self->encryptIV;
|
2561 |
+
|
2562 |
+
for ($_i = 0; $_i < $_len; ++$_i) {
|
2563 |
+
$in = $_iv;
|
2564 |
+
'.$encrypt_block.'
|
2565 |
+
$_ciphertext.= $_text[$_i] ^ $in;
|
2566 |
+
$_iv = substr($_iv, 1) . $in[0];
|
2567 |
+
}
|
2568 |
+
|
2569 |
+
if ($self->continuousBuffer) {
|
2570 |
+
$self->encryptIV = $_iv;
|
2571 |
+
}
|
2572 |
+
|
2573 |
+
return $_ciphertext;
|
2574 |
+
';
|
2575 |
+
$decrypt = $init_encrypt . '
|
2576 |
+
$_plaintext = "";
|
2577 |
+
$_len = strlen($_text);
|
2578 |
+
$_iv = $self->decryptIV;
|
2579 |
+
|
2580 |
+
for ($_i = 0; $_i < $_len; ++$_i) {
|
2581 |
+
$in = $_iv;
|
2582 |
+
'.$encrypt_block.'
|
2583 |
+
$_plaintext.= $_text[$_i] ^ $in;
|
2584 |
+
$_iv = substr($_iv, 1) . $in[0];
|
2585 |
+
}
|
2586 |
+
|
2587 |
+
if ($self->continuousBuffer) {
|
2588 |
+
$self->decryptIV = $_iv;
|
2589 |
+
}
|
2590 |
+
|
2591 |
return $_plaintext;
|
2592 |
';
|
2593 |
break;
|
vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA.php
CHANGED
@@ -470,7 +470,7 @@ class RSA
|
|
470 |
case defined('MATH_BIGINTEGER_OPENSSL_DISABLE'):
|
471 |
define('CRYPT_RSA_MODE', self::MODE_INTERNAL);
|
472 |
break;
|
473 |
-
case extension_loaded('openssl') && file_exists($this->configFile):
|
474 |
// some versions of XAMPP have mismatched versions of OpenSSL which causes it not to work
|
475 |
$versions = array();
|
476 |
|
@@ -878,9 +878,9 @@ class RSA
|
|
878 |
);
|
879 |
$key = "openssh-key-v1\0$key";
|
880 |
|
881 |
-
return "-----BEGIN OPENSSH PRIVATE KEY-----\
|
882 |
-
chunk_split(base64_encode($key), 70) .
|
883 |
-
"-----END OPENSSH PRIVATE KEY
|
884 |
default: // eg. self::PRIVATE_FORMAT_PKCS1
|
885 |
$components = array();
|
886 |
foreach ($raw as $name => $value) {
|
@@ -2580,9 +2580,9 @@ class RSA
|
|
2580 |
$offset+= $patternMatch ? 0 : 1;
|
2581 |
}
|
2582 |
|
2583 |
-
// we do
|
2584 |
// to protect against timing attacks
|
2585 |
-
if (!$hashesMatch
|
2586 |
user_error('Decryption error');
|
2587 |
return false;
|
2588 |
}
|
470 |
case defined('MATH_BIGINTEGER_OPENSSL_DISABLE'):
|
471 |
define('CRYPT_RSA_MODE', self::MODE_INTERNAL);
|
472 |
break;
|
473 |
+
case function_exists('phpinfo') && extension_loaded('openssl') && file_exists($this->configFile):
|
474 |
// some versions of XAMPP have mismatched versions of OpenSSL which causes it not to work
|
475 |
$versions = array();
|
476 |
|
878 |
);
|
879 |
$key = "openssh-key-v1\0$key";
|
880 |
|
881 |
+
return "-----BEGIN OPENSSH PRIVATE KEY-----\n" .
|
882 |
+
chunk_split(base64_encode($key), 70, "\n") .
|
883 |
+
"-----END OPENSSH PRIVATE KEY-----\n";
|
884 |
default: // eg. self::PRIVATE_FORMAT_PKCS1
|
885 |
$components = array();
|
886 |
foreach ($raw as $name => $value) {
|
2580 |
$offset+= $patternMatch ? 0 : 1;
|
2581 |
}
|
2582 |
|
2583 |
+
// we do | instead of || to avoid https://en.wikipedia.org/wiki/Short-circuit_evaluation
|
2584 |
// to protect against timing attacks
|
2585 |
+
if (!$hashesMatch | !$patternMatch) {
|
2586 |
user_error('Decryption error');
|
2587 |
return false;
|
2588 |
}
|
vendor/phpseclib/phpseclib/phpseclib/File/ASN1.php
CHANGED
@@ -234,6 +234,9 @@ class ASN1
|
|
234 |
{
|
235 |
$current = array('start' => $start);
|
236 |
|
|
|
|
|
|
|
237 |
$type = ord($encoded[$encoded_pos++]);
|
238 |
$startOffset = 1;
|
239 |
|
@@ -244,6 +247,9 @@ class ASN1
|
|
244 |
$tag = 0;
|
245 |
// process septets (since the eighth bit is ignored, it's not an octet)
|
246 |
do {
|
|
|
|
|
|
|
247 |
$temp = ord($encoded[$encoded_pos++]);
|
248 |
$startOffset++;
|
249 |
$loop = $temp >> 7;
|
@@ -260,6 +266,9 @@ class ASN1
|
|
260 |
$start+= $startOffset;
|
261 |
|
262 |
// Length, as discussed in paragraph 8.1.3 of X.690-0207.pdf#page=13
|
|
|
|
|
|
|
263 |
$length = ord($encoded[$encoded_pos++]);
|
264 |
$start++;
|
265 |
if ($length == 0x80) { // indefinite length
|
@@ -993,7 +1002,10 @@ class ASN1
|
|
993 |
case self::TYPE_GENERALIZED_TIME:
|
994 |
$format = $mapping['type'] == self::TYPE_UTC_TIME ? 'y' : 'Y';
|
995 |
$format.= 'mdHis';
|
|
|
996 |
$date = new DateTime($source, new DateTimeZone('GMT'));
|
|
|
|
|
997 |
$value = $date->format($format) . 'Z';
|
998 |
break;
|
999 |
case self::TYPE_BIT_STRING:
|
234 |
{
|
235 |
$current = array('start' => $start);
|
236 |
|
237 |
+
if (!isset($encoded[$encoded_pos])) {
|
238 |
+
return false;
|
239 |
+
}
|
240 |
$type = ord($encoded[$encoded_pos++]);
|
241 |
$startOffset = 1;
|
242 |
|
247 |
$tag = 0;
|
248 |
// process septets (since the eighth bit is ignored, it's not an octet)
|
249 |
do {
|
250 |
+
if (!isset($encoded[$encoded_pos])) {
|
251 |
+
return false;
|
252 |
+
}
|
253 |
$temp = ord($encoded[$encoded_pos++]);
|
254 |
$startOffset++;
|
255 |
$loop = $temp >> 7;
|
266 |
$start+= $startOffset;
|
267 |
|
268 |
// Length, as discussed in paragraph 8.1.3 of X.690-0207.pdf#page=13
|
269 |
+
if (!isset($encoded[$encoded_pos])) {
|
270 |
+
return false;
|
271 |
+
}
|
272 |
$length = ord($encoded[$encoded_pos++]);
|
273 |
$start++;
|
274 |
if ($length == 0x80) { // indefinite length
|
1002 |
case self::TYPE_GENERALIZED_TIME:
|
1003 |
$format = $mapping['type'] == self::TYPE_UTC_TIME ? 'y' : 'Y';
|
1004 |
$format.= 'mdHis';
|
1005 |
+
// if $source does _not_ include timezone information within it then assume that the timezone is GMT
|
1006 |
$date = new DateTime($source, new DateTimeZone('GMT'));
|
1007 |
+
// if $source _does_ include timezone information within it then convert the time to GMT
|
1008 |
+
$date->setTimezone(new DateTimeZone('GMT'));
|
1009 |
$value = $date->format($format) . 'Z';
|
1010 |
break;
|
1011 |
case self::TYPE_BIT_STRING:
|
vendor/phpseclib/phpseclib/phpseclib/File/X509.php
CHANGED
@@ -1622,7 +1622,6 @@ class X509
|
|
1622 |
$id = $extensions[$i]['extnId'];
|
1623 |
$value = &$extensions[$i]['extnValue'];
|
1624 |
$value = base64_decode($value);
|
1625 |
-
$decoded = $asn1->decodeBER($value);
|
1626 |
/* [extnValue] contains the DER encoding of an ASN.1 value
|
1627 |
corresponding to the extension type identified by extnID */
|
1628 |
$map = $this->_getMapping($id);
|
@@ -1630,6 +1629,7 @@ class X509
|
|
1630 |
$decoder = $id == 'id-ce-nameConstraints' ?
|
1631 |
array($this, '_decodeNameConstraintIP') :
|
1632 |
array($this, '_decodeIP');
|
|
|
1633 |
$mapped = $asn1->asn1map($decoded[0], $map, array('iPAddress' => $decoder));
|
1634 |
$value = $mapped === false ? $decoded[0] : $mapped;
|
1635 |
|
@@ -5058,7 +5058,7 @@ class X509
|
|
5058 |
$temp = $str;
|
5059 |
} else {
|
5060 |
$temp = preg_replace('#.*?^-+[^-]+-+[\r\n ]*$#ms', '', $str, 1);
|
5061 |
-
$temp = preg_replace('#-+END.*[\r\n ]*.*#ms', '', $
|
5062 |
}
|
5063 |
// remove new lines
|
5064 |
$temp = str_replace(array("\r", "\n", ' '), '', $temp);
|
1622 |
$id = $extensions[$i]['extnId'];
|
1623 |
$value = &$extensions[$i]['extnValue'];
|
1624 |
$value = base64_decode($value);
|
|
|
1625 |
/* [extnValue] contains the DER encoding of an ASN.1 value
|
1626 |
corresponding to the extension type identified by extnID */
|
1627 |
$map = $this->_getMapping($id);
|
1629 |
$decoder = $id == 'id-ce-nameConstraints' ?
|
1630 |
array($this, '_decodeNameConstraintIP') :
|
1631 |
array($this, '_decodeIP');
|
1632 |
+
$decoded = $asn1->decodeBER($value);
|
1633 |
$mapped = $asn1->asn1map($decoded[0], $map, array('iPAddress' => $decoder));
|
1634 |
$value = $mapped === false ? $decoded[0] : $mapped;
|
1635 |
|
5058 |
$temp = $str;
|
5059 |
} else {
|
5060 |
$temp = preg_replace('#.*?^-+[^-]+-+[\r\n ]*$#ms', '', $str, 1);
|
5061 |
+
$temp = preg_replace('#-+END.*[\r\n ]*.*#ms', '', $temp, 1);
|
5062 |
}
|
5063 |
// remove new lines
|
5064 |
$temp = str_replace(array("\r", "\n", ' '), '', $temp);
|
vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger.php
CHANGED
@@ -263,7 +263,7 @@ class BigInteger
|
|
263 |
}
|
264 |
}
|
265 |
|
266 |
-
if (extension_loaded('openssl') && !defined('MATH_BIGINTEGER_OPENSSL_DISABLE') && !defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) {
|
267 |
// some versions of XAMPP have mismatched versions of OpenSSL which causes it not to work
|
268 |
$versions = array();
|
269 |
|
263 |
}
|
264 |
}
|
265 |
|
266 |
+
if (function_exists('phpinfo') && extension_loaded('openssl') && !defined('MATH_BIGINTEGER_OPENSSL_DISABLE') && !defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) {
|
267 |
// some versions of XAMPP have mismatched versions of OpenSSL which causes it not to work
|
268 |
$versions = array();
|
269 |
|
vendor/phpseclib/phpseclib/phpseclib/Net/SFTP.php
CHANGED
@@ -5,9 +5,7 @@
|
|
5 |
*
|
6 |
* PHP version 5
|
7 |
*
|
8 |
-
*
|
9 |
-
* implemented by the popular OpenSSH SFTP server". If you want SFTPv4/5/6 support, provide me with access
|
10 |
-
* to an SFTPv4/5/6 server.
|
11 |
*
|
12 |
* The API for this library is modeled after the API from PHP's {@link http://php.net/book.ftp FTP extension}.
|
13 |
*
|
@@ -154,6 +152,24 @@ class SFTP extends SSH2
|
|
154 |
*/
|
155 |
var $version;
|
156 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
157 |
/**
|
158 |
* Current working directory
|
159 |
*
|
@@ -269,6 +285,39 @@ class SFTP extends SSH2
|
|
269 |
*/
|
270 |
var $preserveTime = false;
|
271 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
272 |
/**
|
273 |
* Default Constructor.
|
274 |
*
|
@@ -289,15 +338,13 @@ class SFTP extends SSH2
|
|
289 |
$this->packet_types = array(
|
290 |
1 => 'NET_SFTP_INIT',
|
291 |
2 => 'NET_SFTP_VERSION',
|
292 |
-
/* the format of SSH_FXP_OPEN changed between SFTPv4 and SFTPv5+:
|
293 |
-
SFTPv5+: http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.1.1
|
294 |
-
pre-SFTPv5 : http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-6.3 */
|
295 |
3 => 'NET_SFTP_OPEN',
|
296 |
4 => 'NET_SFTP_CLOSE',
|
297 |
5 => 'NET_SFTP_READ',
|
298 |
6 => 'NET_SFTP_WRITE',
|
299 |
7 => 'NET_SFTP_LSTAT',
|
300 |
9 => 'NET_SFTP_SETSTAT',
|
|
|
301 |
11 => 'NET_SFTP_OPENDIR',
|
302 |
12 => 'NET_SFTP_READDIR',
|
303 |
13 => 'NET_SFTP_REMOVE',
|
@@ -305,18 +352,13 @@ class SFTP extends SSH2
|
|
305 |
15 => 'NET_SFTP_RMDIR',
|
306 |
16 => 'NET_SFTP_REALPATH',
|
307 |
17 => 'NET_SFTP_STAT',
|
308 |
-
/* the format of SSH_FXP_RENAME changed between SFTPv4 and SFTPv5+:
|
309 |
-
SFTPv5+: http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.3
|
310 |
-
pre-SFTPv5 : http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-6.5 */
|
311 |
18 => 'NET_SFTP_RENAME',
|
312 |
19 => 'NET_SFTP_READLINK',
|
313 |
20 => 'NET_SFTP_SYMLINK',
|
|
|
314 |
|
315 |
101=> 'NET_SFTP_STATUS',
|
316 |
102=> 'NET_SFTP_HANDLE',
|
317 |
-
/* the format of SSH_FXP_NAME changed between SFTPv3 and SFTPv4+:
|
318 |
-
SFTPv4+: http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-9.4
|
319 |
-
pre-SFTPv4 : http://tools.ietf.org/html/draft-ietf-secsh-filexfer-02#section-7 */
|
320 |
103=> 'NET_SFTP_DATA',
|
321 |
104=> 'NET_SFTP_NAME',
|
322 |
105=> 'NET_SFTP_ATTRS',
|
@@ -361,25 +403,59 @@ class SFTP extends SSH2
|
|
361 |
// the order, in this case, matters quite a lot - see \phpseclib\Net\SFTP::_parseAttributes() to understand why
|
362 |
$this->attributes = array(
|
363 |
0x00000001 => 'NET_SFTP_ATTR_SIZE',
|
364 |
-
0x00000002 => 'NET_SFTP_ATTR_UIDGID',
|
|
|
365 |
0x00000004 => 'NET_SFTP_ATTR_PERMISSIONS',
|
366 |
0x00000008 => 'NET_SFTP_ATTR_ACCESSTIME',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
367 |
// 0x80000000 will yield a floating point on 32-bit systems and converting floating points to integers
|
368 |
// yields inconsistent behavior depending on how php is compiled. so we left shift -1 (which, in
|
369 |
// two's compliment, consists of all 1 bits) by 31. on 64-bit systems this'll yield 0xFFFFFFFF80000000.
|
370 |
// that's not a problem, however, and 'anded' and a 32-bit number, as all the leading 1 bits are ignored.
|
371 |
(-1 << 31) & 0xFFFFFFFF => 'NET_SFTP_ATTR_EXTENDED'
|
372 |
);
|
373 |
-
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-6.3
|
374 |
-
// the flag definitions change somewhat in SFTPv5+. if SFTPv5+ support is added to this library, maybe name
|
375 |
-
// the array for that $this->open5_flags and similarly alter the constant names.
|
376 |
$this->open_flags = array(
|
377 |
0x00000001 => 'NET_SFTP_OPEN_READ',
|
378 |
0x00000002 => 'NET_SFTP_OPEN_WRITE',
|
379 |
0x00000004 => 'NET_SFTP_OPEN_APPEND',
|
380 |
0x00000008 => 'NET_SFTP_OPEN_CREATE',
|
381 |
0x00000010 => 'NET_SFTP_OPEN_TRUNCATE',
|
382 |
-
0x00000020 => 'NET_SFTP_OPEN_EXCL'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
383 |
);
|
384 |
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-5.2
|
385 |
// see \phpseclib\Net\SFTP::_parseLongname() for an explanation
|
@@ -401,6 +477,7 @@ class SFTP extends SSH2
|
|
401 |
$this->status_codes,
|
402 |
$this->attributes,
|
403 |
$this->open_flags,
|
|
|
404 |
$this->file_types
|
405 |
);
|
406 |
|
@@ -413,18 +490,32 @@ class SFTP extends SSH2
|
|
413 |
}
|
414 |
|
415 |
/**
|
416 |
-
*
|
417 |
*
|
418 |
-
* @param string $username
|
419 |
* @return bool
|
420 |
* @access public
|
421 |
*/
|
422 |
-
function
|
423 |
{
|
424 |
-
if (!
|
425 |
return false;
|
426 |
}
|
427 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
428 |
$this->window_size_server_to_client[self::CHANNEL] = $this->window_size;
|
429 |
|
430 |
$packet = pack(
|
@@ -446,6 +537,8 @@ class SFTP extends SSH2
|
|
446 |
$response = $this->_get_channel_packet(self::CHANNEL, true);
|
447 |
if ($response === false) {
|
448 |
return false;
|
|
|
|
|
449 |
}
|
450 |
|
451 |
$packet = pack(
|
@@ -492,6 +585,8 @@ class SFTP extends SSH2
|
|
492 |
if ($response === false) {
|
493 |
return false;
|
494 |
}
|
|
|
|
|
495 |
}
|
496 |
|
497 |
$this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_DATA;
|
@@ -506,11 +601,13 @@ class SFTP extends SSH2
|
|
506 |
return false;
|
507 |
}
|
508 |
|
|
|
|
|
509 |
if (strlen($response) < 4) {
|
510 |
return false;
|
511 |
}
|
512 |
extract(unpack('Nversion', $this->_string_shift($response, 4)));
|
513 |
-
$this->
|
514 |
while (!empty($response)) {
|
515 |
if (strlen($response) < 4) {
|
516 |
return false;
|
@@ -525,21 +622,22 @@ class SFTP extends SSH2
|
|
525 |
$this->extensions[$key] = $value;
|
526 |
}
|
527 |
|
528 |
-
|
529 |
-
SFTPv4+ defines a 'newline' extension. SFTPv3 seems to have unofficial support for it via 'newline@vandyke.com',
|
530 |
-
however, I'm not sure what 'newline@vandyke.com' is supposed to do (the fact that it's unofficial means that it's
|
531 |
-
not in the official SFTPv3 specs) and 'newline@vandyke.com' / 'newline' are likely not drop-in substitutes for
|
532 |
-
one another due to the fact that 'newline' comes with a SSH_FXF_TEXT bitmask whereas it seems unlikely that
|
533 |
-
'newline@vandyke.com' would.
|
534 |
-
*/
|
535 |
-
/*
|
536 |
-
if (isset($this->extensions['newline@vandyke.com'])) {
|
537 |
-
$this->extensions['newline'] = $this->extensions['newline@vandyke.com'];
|
538 |
-
unset($this->extensions['newline@vandyke.com']);
|
539 |
-
}
|
540 |
-
*/
|
541 |
|
542 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
543 |
|
544 |
/*
|
545 |
A Note on SFTPv4/5/6 support:
|
@@ -564,12 +662,60 @@ class SFTP extends SSH2
|
|
564 |
in draft-ietf-secsh-filexfer-13 would be quite impossible. As such, what \phpseclib\Net\SFTP would do is close the
|
565 |
channel and reopen it with a new and updated SSH_FXP_INIT packet.
|
566 |
*/
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
573 |
}
|
574 |
|
575 |
$this->pwd = $this->_realpath('.');
|
@@ -629,6 +775,26 @@ class SFTP extends SSH2
|
|
629 |
$this->canonicalize_paths = false;
|
630 |
}
|
631 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
632 |
/**
|
633 |
* Returns the current directory name
|
634 |
*
|
@@ -637,6 +803,10 @@ class SFTP extends SSH2
|
|
637 |
*/
|
638 |
function pwd()
|
639 |
{
|
|
|
|
|
|
|
|
|
640 |
return $this->pwd;
|
641 |
}
|
642 |
|
@@ -678,6 +848,10 @@ class SFTP extends SSH2
|
|
678 |
*/
|
679 |
function realpath($path)
|
680 |
{
|
|
|
|
|
|
|
|
|
681 |
return $this->_realpath($path);
|
682 |
}
|
683 |
|
@@ -760,7 +934,7 @@ class SFTP extends SSH2
|
|
760 |
*/
|
761 |
function chdir($dir)
|
762 |
{
|
763 |
-
if (
|
764 |
return false;
|
765 |
}
|
766 |
|
@@ -917,7 +1091,7 @@ class SFTP extends SSH2
|
|
917 |
*/
|
918 |
function _list($dir, $raw = true)
|
919 |
{
|
920 |
-
if (
|
921 |
return false;
|
922 |
}
|
923 |
|
@@ -972,13 +1146,17 @@ class SFTP extends SSH2
|
|
972 |
}
|
973 |
extract(unpack('Nlength', $this->_string_shift($response, 4)));
|
974 |
$shortname = $this->_string_shift($response, $length);
|
975 |
-
|
976 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
977 |
}
|
978 |
-
extract(unpack('Nlength', $this->_string_shift($response, 4)));
|
979 |
-
$longname = $this->_string_shift($response, $length);
|
980 |
$attributes = $this->_parseAttributes($response);
|
981 |
-
if (!isset($attributes['type'])) {
|
982 |
$fileType = $this->_parseLongname($longname);
|
983 |
if ($fileType) {
|
984 |
$attributes['type'] = $fileType;
|
@@ -1138,10 +1316,6 @@ class SFTP extends SSH2
|
|
1138 |
*/
|
1139 |
function size($filename)
|
1140 |
{
|
1141 |
-
if (!($this->bitmap & SSH2::MASK_LOGIN)) {
|
1142 |
-
return false;
|
1143 |
-
}
|
1144 |
-
|
1145 |
$result = $this->stat($filename);
|
1146 |
if ($result === false) {
|
1147 |
return false;
|
@@ -1258,7 +1432,7 @@ class SFTP extends SSH2
|
|
1258 |
*/
|
1259 |
function stat($filename)
|
1260 |
{
|
1261 |
-
if (
|
1262 |
return false;
|
1263 |
}
|
1264 |
|
@@ -1315,7 +1489,7 @@ class SFTP extends SSH2
|
|
1315 |
*/
|
1316 |
function lstat($filename)
|
1317 |
{
|
1318 |
-
if (
|
1319 |
return false;
|
1320 |
}
|
1321 |
|
@@ -1429,7 +1603,7 @@ class SFTP extends SSH2
|
|
1429 |
*/
|
1430 |
function touch($filename, $time = null, $atime = null)
|
1431 |
{
|
1432 |
-
if (
|
1433 |
return false;
|
1434 |
}
|
1435 |
|
@@ -1445,9 +1619,25 @@ class SFTP extends SSH2
|
|
1445 |
$atime = $time;
|
1446 |
}
|
1447 |
|
1448 |
-
$
|
1449 |
-
|
1450 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1451 |
if (!$this->_send_sftp_packet(NET_SFTP_OPEN, $packet)) {
|
1452 |
return false;
|
1453 |
}
|
@@ -1470,19 +1660,47 @@ class SFTP extends SSH2
|
|
1470 |
/**
|
1471 |
* Changes file or directory owner
|
1472 |
*
|
|
|
|
|
|
|
|
|
|
|
1473 |
* Returns true on success or false on error.
|
1474 |
*
|
1475 |
* @param string $filename
|
1476 |
-
* @param int $uid
|
1477 |
* @param bool $recursive
|
1478 |
* @return bool
|
1479 |
* @access public
|
1480 |
*/
|
1481 |
function chown($filename, $uid, $recursive = false)
|
1482 |
{
|
1483 |
-
|
1484 |
-
|
1485 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1486 |
|
1487 |
return $this->_setstat($filename, $attr, $recursive);
|
1488 |
}
|
@@ -1490,17 +1708,24 @@ class SFTP extends SSH2
|
|
1490 |
/**
|
1491 |
* Changes file or directory group
|
1492 |
*
|
|
|
|
|
|
|
|
|
|
|
1493 |
* Returns true on success or false on error.
|
1494 |
*
|
1495 |
* @param string $filename
|
1496 |
-
* @param int $gid
|
1497 |
* @param bool $recursive
|
1498 |
* @return bool
|
1499 |
* @access public
|
1500 |
*/
|
1501 |
function chgrp($filename, $gid, $recursive = false)
|
1502 |
{
|
1503 |
-
$attr =
|
|
|
|
|
1504 |
|
1505 |
return $this->_setstat($filename, $attr, $recursive);
|
1506 |
}
|
@@ -1567,7 +1792,7 @@ class SFTP extends SSH2
|
|
1567 |
*/
|
1568 |
function _setstat($filename, $attr, $recursive)
|
1569 |
{
|
1570 |
-
if (
|
1571 |
return false;
|
1572 |
}
|
1573 |
|
@@ -1585,9 +1810,10 @@ class SFTP extends SSH2
|
|
1585 |
return $result;
|
1586 |
}
|
1587 |
|
1588 |
-
|
1589 |
-
|
1590 |
-
|
|
|
1591 |
return false;
|
1592 |
}
|
1593 |
|
@@ -1657,7 +1883,10 @@ class SFTP extends SSH2
|
|
1657 |
return false;
|
1658 |
}
|
1659 |
} else {
|
1660 |
-
|
|
|
|
|
|
|
1661 |
return false;
|
1662 |
}
|
1663 |
|
@@ -1672,7 +1901,10 @@ class SFTP extends SSH2
|
|
1672 |
}
|
1673 |
}
|
1674 |
|
1675 |
-
|
|
|
|
|
|
|
1676 |
return false;
|
1677 |
}
|
1678 |
|
@@ -1697,7 +1929,7 @@ class SFTP extends SSH2
|
|
1697 |
*/
|
1698 |
function readlink($link)
|
1699 |
{
|
1700 |
-
if (
|
1701 |
return false;
|
1702 |
}
|
1703 |
|
@@ -1747,15 +1979,44 @@ class SFTP extends SSH2
|
|
1747 |
*/
|
1748 |
function symlink($target, $link)
|
1749 |
{
|
1750 |
-
if (
|
1751 |
return false;
|
1752 |
}
|
1753 |
|
1754 |
//$target = $this->_realpath($target);
|
1755 |
$link = $this->_realpath($link);
|
1756 |
|
1757 |
-
|
1758 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1759 |
return false;
|
1760 |
}
|
1761 |
|
@@ -1788,7 +2049,7 @@ class SFTP extends SSH2
|
|
1788 |
*/
|
1789 |
function mkdir($dir, $mode = -1, $recursive = false)
|
1790 |
{
|
1791 |
-
if (
|
1792 |
return false;
|
1793 |
}
|
1794 |
|
@@ -1857,7 +2118,7 @@ class SFTP extends SSH2
|
|
1857 |
*/
|
1858 |
function rmdir($dir)
|
1859 |
{
|
1860 |
-
if (
|
1861 |
return false;
|
1862 |
}
|
1863 |
|
@@ -1906,7 +2167,8 @@ class SFTP extends SSH2
|
|
1906 |
* contain as many bytes as filename.ext does on your local filesystem. If your filename.ext is 1MB then that is how
|
1907 |
* large $remote_file will be, as well.
|
1908 |
*
|
1909 |
-
* Setting $mode to self::SOURCE_CALLBACK will use $data as callback function, which gets only one parameter -- number
|
|
|
1910 |
*
|
1911 |
* If $data is a resource then it'll be used as a resource instead.
|
1912 |
*
|
@@ -1942,7 +2204,7 @@ class SFTP extends SSH2
|
|
1942 |
*/
|
1943 |
function put($remote_file, $data, $mode = self::SOURCE_STRING, $start = -1, $local_start = -1, $progressCallback = null)
|
1944 |
{
|
1945 |
-
if (
|
1946 |
return false;
|
1947 |
}
|
1948 |
|
@@ -1953,10 +2215,14 @@ class SFTP extends SSH2
|
|
1953 |
|
1954 |
$this->_remove_from_stat_cache($remote_file);
|
1955 |
|
1956 |
-
$
|
1957 |
-
|
1958 |
-
|
1959 |
-
|
|
|
|
|
|
|
|
|
1960 |
|
1961 |
if ($start >= 0) {
|
1962 |
$offset = $start;
|
@@ -1966,10 +2232,17 @@ class SFTP extends SSH2
|
|
1966 |
$offset = $size !== false ? $size : 0;
|
1967 |
} else {
|
1968 |
$offset = 0;
|
1969 |
-
$
|
|
|
|
|
|
|
|
|
1970 |
}
|
1971 |
|
1972 |
-
$packet = pack('Na*
|
|
|
|
|
|
|
1973 |
if (!$this->_send_sftp_packet(NET_SFTP_OPEN, $packet)) {
|
1974 |
return false;
|
1975 |
}
|
@@ -2078,6 +2351,8 @@ class SFTP extends SSH2
|
|
2078 |
}
|
2079 |
}
|
2080 |
|
|
|
|
|
2081 |
if (!$this->_read_put_responses($i)) {
|
2082 |
if ($mode & self::SOURCE_LOCAL_FILE) {
|
2083 |
fclose($fp);
|
@@ -2086,18 +2361,33 @@ class SFTP extends SSH2
|
|
2086 |
return false;
|
2087 |
}
|
2088 |
|
2089 |
-
if ($mode &
|
2090 |
-
if ($this->preserveTime) {
|
2091 |
-
$stat = fstat($fp);
|
2092 |
-
$this->touch($remote_file, $stat['mtime'], $stat['atime']);
|
2093 |
-
}
|
2094 |
-
|
2095 |
if (isset($fp) && is_resource($fp)) {
|
2096 |
fclose($fp);
|
2097 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2098 |
}
|
2099 |
|
2100 |
-
return $
|
2101 |
}
|
2102 |
|
2103 |
/**
|
@@ -2184,7 +2474,7 @@ class SFTP extends SSH2
|
|
2184 |
*/
|
2185 |
function get($remote_file, $local_file = false, $offset = 0, $length = -1, $progressCallback = null)
|
2186 |
{
|
2187 |
-
if (
|
2188 |
return false;
|
2189 |
}
|
2190 |
|
@@ -2193,7 +2483,10 @@ class SFTP extends SSH2
|
|
2193 |
return false;
|
2194 |
}
|
2195 |
|
2196 |
-
$packet = pack('Na*
|
|
|
|
|
|
|
2197 |
if (!$this->_send_sftp_packet(NET_SFTP_OPEN, $packet)) {
|
2198 |
return false;
|
2199 |
}
|
@@ -2293,7 +2586,14 @@ class SFTP extends SSH2
|
|
2293 |
if ($fclose_check) {
|
2294 |
fclose($fp);
|
2295 |
}
|
2296 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2297 |
}
|
2298 |
$response = null;
|
2299 |
}
|
@@ -2338,7 +2638,7 @@ class SFTP extends SSH2
|
|
2338 |
*/
|
2339 |
function delete($path, $recursive = true)
|
2340 |
{
|
2341 |
-
if (
|
2342 |
return false;
|
2343 |
}
|
2344 |
|
@@ -2467,6 +2767,10 @@ class SFTP extends SSH2
|
|
2467 |
function file_exists($path)
|
2468 |
{
|
2469 |
if ($this->use_stat_cache) {
|
|
|
|
|
|
|
|
|
2470 |
$path = $this->_realpath($path);
|
2471 |
|
2472 |
$result = $this->_query_stat_cache($path);
|
@@ -2537,6 +2841,10 @@ class SFTP extends SSH2
|
|
2537 |
*/
|
2538 |
function is_readable($path)
|
2539 |
{
|
|
|
|
|
|
|
|
|
2540 |
$path = $this->_realpath($path);
|
2541 |
|
2542 |
$packet = pack('Na*N2', strlen($path), $path, NET_SFTP_OPEN_READ, 0);
|
@@ -2565,6 +2873,10 @@ class SFTP extends SSH2
|
|
2565 |
*/
|
2566 |
function is_writable($path)
|
2567 |
{
|
|
|
|
|
|
|
|
|
2568 |
$path = $this->_realpath($path);
|
2569 |
|
2570 |
$packet = pack('Na*N2', strlen($path), $path, NET_SFTP_OPEN_WRITE, 0);
|
@@ -2745,6 +3057,10 @@ class SFTP extends SSH2
|
|
2745 |
*/
|
2746 |
function _get_xstat_cache_prop($path, $prop, $type)
|
2747 |
{
|
|
|
|
|
|
|
|
|
2748 |
if ($this->use_stat_cache) {
|
2749 |
$path = $this->_realpath($path);
|
2750 |
|
@@ -2765,7 +3081,9 @@ class SFTP extends SSH2
|
|
2765 |
}
|
2766 |
|
2767 |
/**
|
2768 |
-
* Renames a file or a directory on the SFTP server
|
|
|
|
|
2769 |
*
|
2770 |
* @param string $oldname
|
2771 |
* @param string $newname
|
@@ -2774,7 +3092,7 @@ class SFTP extends SSH2
|
|
2774 |
*/
|
2775 |
function rename($oldname, $newname)
|
2776 |
{
|
2777 |
-
if (
|
2778 |
return false;
|
2779 |
}
|
2780 |
|
@@ -2786,6 +3104,18 @@ class SFTP extends SSH2
|
|
2786 |
|
2787 |
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.3
|
2788 |
$packet = pack('Na*Na*', strlen($oldname), $oldname, strlen($newname), $newname);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2789 |
if (!$this->_send_sftp_packet(NET_SFTP_RENAME, $packet)) {
|
2790 |
return false;
|
2791 |
}
|
@@ -2815,6 +3145,31 @@ class SFTP extends SSH2
|
|
2815 |
return true;
|
2816 |
}
|
2817 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2818 |
/**
|
2819 |
* Parse Attributes
|
2820 |
*
|
@@ -2826,16 +3181,56 @@ class SFTP extends SSH2
|
|
2826 |
*/
|
2827 |
function _parseAttributes(&$response)
|
2828 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2829 |
$attr = array();
|
2830 |
-
if (strlen($response) <
|
2831 |
user_error('Malformed file attributes');
|
2832 |
return array();
|
2833 |
}
|
2834 |
-
extract(unpack(
|
2835 |
-
|
|
|
|
|
2836 |
foreach ($this->attributes as $key => $value) {
|
2837 |
switch ($flags & $key) {
|
2838 |
-
case
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2839 |
// The size attribute is defined as an unsigned 64-bit integer.
|
2840 |
// The following will use floats on 32-bit platforms, if necessary.
|
2841 |
// As can be seen in the BigInteger class, floats are generally
|
@@ -2844,14 +3239,14 @@ class SFTP extends SSH2
|
|
2844 |
// of precision. Interpreted in filesize, 2^50 bytes = 1024 TiB.
|
2845 |
$attr['size'] = hexdec(bin2hex($this->_string_shift($response, 8)));
|
2846 |
break;
|
2847 |
-
case NET_SFTP_ATTR_UIDGID:
|
2848 |
if (strlen($response) < 8) {
|
2849 |
user_error('Malformed file attributes');
|
2850 |
return $attr;
|
2851 |
}
|
2852 |
$attr+= unpack('Nuid/Ngid', $this->_string_shift($response, 8));
|
2853 |
break;
|
2854 |
-
case NET_SFTP_ATTR_PERMISSIONS:
|
2855 |
if (strlen($response) < 4) {
|
2856 |
user_error('Malformed file attributes');
|
2857 |
return $attr;
|
@@ -2865,14 +3260,134 @@ class SFTP extends SSH2
|
|
2865 |
$attr+= array('type' => $fileType);
|
2866 |
}
|
2867 |
break;
|
2868 |
-
case NET_SFTP_ATTR_ACCESSTIME:
|
|
|
|
|
|
|
|
|
2869 |
if (strlen($response) < 8) {
|
2870 |
user_error('Malformed file attributes');
|
2871 |
return $attr;
|
2872 |
}
|
2873 |
$attr+= unpack('Natime/Nmtime', $this->_string_shift($response, 8));
|
2874 |
break;
|
2875 |
-
case
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2876 |
if (strlen($response) < 4) {
|
2877 |
user_error('Malformed file attributes');
|
2878 |
return $attr;
|
@@ -3055,6 +3570,8 @@ class SFTP extends SSH2
|
|
3055 |
*/
|
3056 |
function _get_sftp_packet($request_id = null)
|
3057 |
{
|
|
|
|
|
3058 |
if (isset($request_id) && isset($this->requestBuffer[$request_id])) {
|
3059 |
$this->packet_type = $this->requestBuffer[$request_id]['packet_type'];
|
3060 |
$temp = $this->requestBuffer[$request_id]['packet'];
|
@@ -3071,11 +3588,17 @@ class SFTP extends SSH2
|
|
3071 |
// SFTP packet length
|
3072 |
while (strlen($this->packet_buffer) < 4) {
|
3073 |
$temp = $this->_get_channel_packet(self::CHANNEL, true);
|
3074 |
-
if (
|
|
|
|
|
|
|
3075 |
$this->packet_type = false;
|
3076 |
$this->packet_buffer = '';
|
3077 |
return false;
|
3078 |
}
|
|
|
|
|
|
|
3079 |
$this->packet_buffer.= $temp;
|
3080 |
}
|
3081 |
if (strlen($this->packet_buffer) < 4) {
|
@@ -3085,9 +3608,8 @@ class SFTP extends SSH2
|
|
3085 |
$tempLength = $length;
|
3086 |
$tempLength-= strlen($this->packet_buffer);
|
3087 |
|
3088 |
-
|
3089 |
// 256 * 1024 is what SFTP_MAX_MSG_LENGTH is set to in OpenSSH's sftp-common.h
|
3090 |
-
if ($tempLength > 256 * 1024) {
|
3091 |
user_error('Invalid SFTP packet size');
|
3092 |
return false;
|
3093 |
}
|
@@ -3205,13 +3727,51 @@ class SFTP extends SSH2
|
|
3205 |
*/
|
3206 |
function getSupportedVersions()
|
3207 |
{
|
3208 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3209 |
if (isset($this->extensions['versions'])) {
|
3210 |
$temp['extensions'] = $this->extensions['versions'];
|
3211 |
}
|
3212 |
return $temp;
|
3213 |
}
|
3214 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3215 |
/**
|
3216 |
* Disconnect
|
3217 |
*
|
5 |
*
|
6 |
* PHP version 5
|
7 |
*
|
8 |
+
* Supports SFTPv2/3/4/5/6. Defaults to v3.
|
|
|
|
|
9 |
*
|
10 |
* The API for this library is modeled after the API from PHP's {@link http://php.net/book.ftp FTP extension}.
|
11 |
*
|
152 |
*/
|
153 |
var $version;
|
154 |
|
155 |
+
/**
|
156 |
+
* Default Server SFTP version
|
157 |
+
*
|
158 |
+
* @var int
|
159 |
+
* @see self::_initChannel()
|
160 |
+
* @access private
|
161 |
+
*/
|
162 |
+
var $defaultVersion;
|
163 |
+
|
164 |
+
/**
|
165 |
+
* Preferred SFTP version
|
166 |
+
*
|
167 |
+
* @var int
|
168 |
+
* @see self::_initChannel()
|
169 |
+
* @access private
|
170 |
+
*/
|
171 |
+
var $preferredVersion = 3;
|
172 |
+
|
173 |
/**
|
174 |
* Current working directory
|
175 |
*
|
285 |
*/
|
286 |
var $preserveTime = false;
|
287 |
|
288 |
+
/**
|
289 |
+
* Arbitrary Length Packets Flag
|
290 |
+
*
|
291 |
+
* Determines whether or not packets of any length should be allowed,
|
292 |
+
* in cases where the server chooses the packet length (such as
|
293 |
+
* directory listings). By default, packets are only allowed to be
|
294 |
+
* 256 * 1024 bytes (SFTP_MAX_MSG_LENGTH from OpenSSH's sftp-common.h)
|
295 |
+
*
|
296 |
+
* @see self::enableArbitraryLengthPackets()
|
297 |
+
* @see self::_get_sftp_packet()
|
298 |
+
* @var bool
|
299 |
+
* @access private
|
300 |
+
*/
|
301 |
+
var $allow_arbitrary_length_packets = false;
|
302 |
+
|
303 |
+
/**
|
304 |
+
* Was the last packet due to the channels being closed or not?
|
305 |
+
*
|
306 |
+
* @see self::get()
|
307 |
+
* @see self::get_sftp_packet()
|
308 |
+
* @var bool
|
309 |
+
* @access private
|
310 |
+
*/
|
311 |
+
var $channel_close = false;
|
312 |
+
|
313 |
+
/**
|
314 |
+
* Has the SFTP channel been partially negotiated?
|
315 |
+
*
|
316 |
+
* @var bool
|
317 |
+
* @access private
|
318 |
+
*/
|
319 |
+
var $partial_init = false;
|
320 |
+
|
321 |
/**
|
322 |
* Default Constructor.
|
323 |
*
|
338 |
$this->packet_types = array(
|
339 |
1 => 'NET_SFTP_INIT',
|
340 |
2 => 'NET_SFTP_VERSION',
|
|
|
|
|
|
|
341 |
3 => 'NET_SFTP_OPEN',
|
342 |
4 => 'NET_SFTP_CLOSE',
|
343 |
5 => 'NET_SFTP_READ',
|
344 |
6 => 'NET_SFTP_WRITE',
|
345 |
7 => 'NET_SFTP_LSTAT',
|
346 |
9 => 'NET_SFTP_SETSTAT',
|
347 |
+
10 => 'NET_SFTP_FSETSTAT',
|
348 |
11 => 'NET_SFTP_OPENDIR',
|
349 |
12 => 'NET_SFTP_READDIR',
|
350 |
13 => 'NET_SFTP_REMOVE',
|
352 |
15 => 'NET_SFTP_RMDIR',
|
353 |
16 => 'NET_SFTP_REALPATH',
|
354 |
17 => 'NET_SFTP_STAT',
|
|
|
|
|
|
|
355 |
18 => 'NET_SFTP_RENAME',
|
356 |
19 => 'NET_SFTP_READLINK',
|
357 |
20 => 'NET_SFTP_SYMLINK',
|
358 |
+
21 => 'NET_SFTP_LINK',
|
359 |
|
360 |
101=> 'NET_SFTP_STATUS',
|
361 |
102=> 'NET_SFTP_HANDLE',
|
|
|
|
|
|
|
362 |
103=> 'NET_SFTP_DATA',
|
363 |
104=> 'NET_SFTP_NAME',
|
364 |
105=> 'NET_SFTP_ATTRS',
|
403 |
// the order, in this case, matters quite a lot - see \phpseclib\Net\SFTP::_parseAttributes() to understand why
|
404 |
$this->attributes = array(
|
405 |
0x00000001 => 'NET_SFTP_ATTR_SIZE',
|
406 |
+
0x00000002 => 'NET_SFTP_ATTR_UIDGID', // defined in SFTPv3, removed in SFTPv4+
|
407 |
+
0x00000080 => 'NET_SFTP_ATTR_OWNERGROUP', // defined in SFTPv4+
|
408 |
0x00000004 => 'NET_SFTP_ATTR_PERMISSIONS',
|
409 |
0x00000008 => 'NET_SFTP_ATTR_ACCESSTIME',
|
410 |
+
0x00000010 => 'NET_SFTP_ATTR_CREATETIME', // SFTPv4+
|
411 |
+
0x00000020 => 'NET_SFTP_ATTR_MODIFYTIME',
|
412 |
+
0x00000040 => 'NET_SFTP_ATTR_ACL',
|
413 |
+
0x00000100 => 'NET_SFTP_ATTR_SUBSECOND_TIMES',
|
414 |
+
0x00000200 => 'NET_SFTP_ATTR_BITS', // SFTPv5+
|
415 |
+
0x00000400 => 'NET_SFTP_ATTR_ALLOCATION_SIZE', // SFTPv6+
|
416 |
+
0x00000800 => 'NET_SFTP_ATTR_TEXT_HINT',
|
417 |
+
0x00001000 => 'NET_SFTP_ATTR_MIME_TYPE',
|
418 |
+
0x00002000 => 'NET_SFTP_ATTR_LINK_COUNT',
|
419 |
+
0x00004000 => 'NET_SFTP_ATTR_UNTRANSLATED_NAME',
|
420 |
+
0x00008000 => 'NET_SFTP_ATTR_CTIME',
|
421 |
// 0x80000000 will yield a floating point on 32-bit systems and converting floating points to integers
|
422 |
// yields inconsistent behavior depending on how php is compiled. so we left shift -1 (which, in
|
423 |
// two's compliment, consists of all 1 bits) by 31. on 64-bit systems this'll yield 0xFFFFFFFF80000000.
|
424 |
// that's not a problem, however, and 'anded' and a 32-bit number, as all the leading 1 bits are ignored.
|
425 |
(-1 << 31) & 0xFFFFFFFF => 'NET_SFTP_ATTR_EXTENDED'
|
426 |
);
|
|
|
|
|
|
|
427 |
$this->open_flags = array(
|
428 |
0x00000001 => 'NET_SFTP_OPEN_READ',
|
429 |
0x00000002 => 'NET_SFTP_OPEN_WRITE',
|
430 |
0x00000004 => 'NET_SFTP_OPEN_APPEND',
|
431 |
0x00000008 => 'NET_SFTP_OPEN_CREATE',
|
432 |
0x00000010 => 'NET_SFTP_OPEN_TRUNCATE',
|
433 |
+
0x00000020 => 'NET_SFTP_OPEN_EXCL',
|
434 |
+
0x00000040 => 'NET_SFTP_OPEN_TEXT' // defined in SFTPv4
|
435 |
+
);
|
436 |
+
// SFTPv5+ changed the flags up:
|
437 |
+
// https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-8.1.1.3
|
438 |
+
$this->open_flags5 = array(
|
439 |
+
// when SSH_FXF_ACCESS_DISPOSITION is a 3 bit field that controls how the file is opened
|
440 |
+
0x00000000 => 'NET_SFTP_OPEN_CREATE_NEW',
|
441 |
+
0x00000001 => 'NET_SFTP_OPEN_CREATE_TRUNCATE',
|
442 |
+
0x00000002 => 'NET_SFTP_OPEN_OPEN_EXISTING',
|
443 |
+
0x00000003 => 'NET_SFTP_OPEN_OPEN_OR_CREATE',
|
444 |
+
0x00000004 => 'NET_SFTP_OPEN_TRUNCATE_EXISTING',
|
445 |
+
// the rest of the flags are not supported
|
446 |
+
0x00000008 => 'NET_SFTP_OPEN_APPEND_DATA', // "the offset field of SS_FXP_WRITE requests is ignored"
|
447 |
+
0x00000010 => 'NET_SFTP_OPEN_APPEND_DATA_ATOMIC',
|
448 |
+
0x00000020 => 'NET_SFTP_OPEN_TEXT_MODE',
|
449 |
+
0x00000040 => 'NET_SFTP_OPEN_BLOCK_READ',
|
450 |
+
0x00000080 => 'NET_SFTP_OPEN_BLOCK_WRITE',
|
451 |
+
0x00000100 => 'NET_SFTP_OPEN_BLOCK_DELETE',
|
452 |
+
0x00000200 => 'NET_SFTP_OPEN_BLOCK_ADVISORY',
|
453 |
+
0x00000400 => 'NET_SFTP_OPEN_NOFOLLOW',
|
454 |
+
0x00000800 => 'NET_SFTP_OPEN_DELETE_ON_CLOSE',
|
455 |
+
0x00001000 => 'NET_SFTP_OPEN_ACCESS_AUDIT_ALARM_INFO',
|
456 |
+
0x00002000 => 'NET_SFTP_OPEN_ACCESS_BACKUP',
|
457 |
+
0x00004000 => 'NET_SFTP_OPEN_BACKUP_STREAM',
|
458 |
+
0x00008000 => 'NET_SFTP_OPEN_OVERRIDE_OWNER',
|
459 |
);
|
460 |
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-5.2
|
461 |
// see \phpseclib\Net\SFTP::_parseLongname() for an explanation
|
477 |
$this->status_codes,
|
478 |
$this->attributes,
|
479 |
$this->open_flags,
|
480 |
+
$this->open_flags5,
|
481 |
$this->file_types
|
482 |
);
|
483 |
|
490 |
}
|
491 |
|
492 |
/**
|
493 |
+
* Check a few things before SFTP functions are called
|
494 |
*
|
|
|
495 |
* @return bool
|
496 |
* @access public
|
497 |
*/
|
498 |
+
function _precheck()
|
499 |
{
|
500 |
+
if (!($this->bitmap & SSH2::MASK_LOGIN)) {
|
501 |
return false;
|
502 |
}
|
503 |
|
504 |
+
if ($this->pwd === false) {
|
505 |
+
return $this->_init_sftp_connection();
|
506 |
+
}
|
507 |
+
|
508 |
+
return true;
|
509 |
+
}
|
510 |
+
|
511 |
+
/**
|
512 |
+
* Partially initialize an SFTP connection
|
513 |
+
*
|
514 |
+
* @return bool
|
515 |
+
* @access public
|
516 |
+
*/
|
517 |
+
function _partial_init_sftp_connection()
|
518 |
+
{
|
519 |
$this->window_size_server_to_client[self::CHANNEL] = $this->window_size;
|
520 |
|
521 |
$packet = pack(
|
537 |
$response = $this->_get_channel_packet(self::CHANNEL, true);
|
538 |
if ($response === false) {
|
539 |
return false;
|
540 |
+
} elseif ($response === true && $this->isTimeout()) {
|
541 |
+
return false;
|
542 |
}
|
543 |
|
544 |
$packet = pack(
|
585 |
if ($response === false) {
|
586 |
return false;
|
587 |
}
|
588 |
+
} elseif ($response === true && $this->isTimeout()) {
|
589 |
+
return false;
|
590 |
}
|
591 |
|
592 |
$this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_DATA;
|
601 |
return false;
|
602 |
}
|
603 |
|
604 |
+
$this->use_request_id = true;
|
605 |
+
|
606 |
if (strlen($response) < 4) {
|
607 |
return false;
|
608 |
}
|
609 |
extract(unpack('Nversion', $this->_string_shift($response, 4)));
|
610 |
+
$this->defaultVersion = $version;
|
611 |
while (!empty($response)) {
|
612 |
if (strlen($response) < 4) {
|
613 |
return false;
|
622 |
$this->extensions[$key] = $value;
|
623 |
}
|
624 |
|
625 |
+
$this->partial_init = true;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
626 |
|
627 |
+
return true;
|
628 |
+
}
|
629 |
+
|
630 |
+
/**
|
631 |
+
* (Re)initializes the SFTP channel
|
632 |
+
*
|
633 |
+
* @return bool
|
634 |
+
* @access private
|
635 |
+
*/
|
636 |
+
function _init_sftp_connection()
|
637 |
+
{
|
638 |
+
if (!$this->partial_init && !$this->_partial_init_sftp_connection()) {
|
639 |
+
return false;
|
640 |
+
}
|
641 |
|
642 |
/*
|
643 |
A Note on SFTPv4/5/6 support:
|
662 |
in draft-ietf-secsh-filexfer-13 would be quite impossible. As such, what \phpseclib\Net\SFTP would do is close the
|
663 |
channel and reopen it with a new and updated SSH_FXP_INIT packet.
|
664 |
*/
|
665 |
+
$this->version = $this->defaultVersion;
|
666 |
+
if (isset($this->extensions['versions']) && (!$this->preferredVersion || $this->preferredVersion != $this->version)) {
|
667 |
+
$versions = explode(',', $this->extensions['versions']);
|
668 |
+
$supported = array(6, 5, 4);
|
669 |
+
if ($this->preferredVersion) {
|
670 |
+
$supported = array_diff($supported, array($this->preferredVersion));
|
671 |
+
array_unshift($supported, $this->preferredVersion);
|
672 |
+
}
|
673 |
+
foreach ($supported as $ver) {
|
674 |
+
if (in_array($ver, $versions)) {
|
675 |
+
if ($ver === $this->version) {
|
676 |
+
break;
|
677 |
+
}
|
678 |
+
$this->version = (int) $ver;
|
679 |
+
$packet = pack('Na*Na*', strlen('version-select'), 'version-select', strlen($ver), $ver);
|
680 |
+
if (!$this->_send_sftp_packet(NET_SFTP_EXTENDED, $packet)) {
|
681 |
+
return false;
|
682 |
+
}
|
683 |
+
$response = $this->_get_sftp_packet();
|
684 |
+
if ($this->packet_type != NET_SFTP_STATUS) {
|
685 |
+
user_error('Expected SSH_FXP_STATUS');
|
686 |
+
return false;
|
687 |
+
}
|
688 |
+
|
689 |
+
if (strlen($response) < 4) {
|
690 |
+
return false;
|
691 |
+
}
|
692 |
+
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
|
693 |
+
if ($status != NET_SFTP_STATUS_OK) {
|
694 |
+
$this->_logError($response, $status);
|
695 |
+
return false;
|
696 |
+
}
|
697 |
+
|
698 |
+
break;
|
699 |
+
}
|
700 |
+
}
|
701 |
+
}
|
702 |
+
|
703 |
+
/*
|
704 |
+
SFTPv4+ defines a 'newline' extension. SFTPv3 seems to have unofficial support for it via 'newline@vandyke.com',
|
705 |
+
however, I'm not sure what 'newline@vandyke.com' is supposed to do (the fact that it's unofficial means that it's
|
706 |
+
not in the official SFTPv3 specs) and 'newline@vandyke.com' / 'newline' are likely not drop-in substitutes for
|
707 |
+
one another due to the fact that 'newline' comes with a SSH_FXF_TEXT bitmask whereas it seems unlikely that
|
708 |
+
'newline@vandyke.com' would.
|
709 |
+
*/
|
710 |
+
/*
|
711 |
+
if (isset($this->extensions['newline@vandyke.com'])) {
|
712 |
+
$this->extensions['newline'] = $this->extensions['newline@vandyke.com'];
|
713 |
+
unset($this->extensions['newline@vandyke.com']);
|
714 |
+
}
|
715 |
+
*/
|
716 |
+
|
717 |
+
if ($this->version < 2 || $this->version > 6) {
|
718 |
+
return false;
|
719 |
}
|
720 |
|
721 |
$this->pwd = $this->_realpath('.');
|
775 |
$this->canonicalize_paths = false;
|
776 |
}
|
777 |
|
778 |
+
/**
|
779 |
+
* Enable arbitrary length packets
|
780 |
+
*
|
781 |
+
* @access public
|
782 |
+
*/
|
783 |
+
function enableArbitraryLengthPackets()
|
784 |
+
{
|
785 |
+
$this->allow_arbitrary_length_packets = true;
|
786 |
+
}
|
787 |
+
|
788 |
+
/**
|
789 |
+
* Disable arbitrary length packets
|
790 |
+
*
|
791 |
+
* @access public
|
792 |
+
*/
|
793 |
+
function disableArbitraryLengthPackets()
|
794 |
+
{
|
795 |
+
$this->allow_arbitrary_length_packets = false;
|
796 |
+
}
|
797 |
+
|
798 |
/**
|
799 |
* Returns the current directory name
|
800 |
*
|
803 |
*/
|
804 |
function pwd()
|
805 |
{
|
806 |
+
if (!$this->_precheck()) {
|
807 |
+
return false;
|
808 |
+
}
|
809 |
+
|
810 |
return $this->pwd;
|
811 |
}
|
812 |
|
848 |
*/
|
849 |
function realpath($path)
|
850 |
{
|
851 |
+
if (!$this->_precheck()) {
|
852 |
+
return false;
|
853 |
+
}
|
854 |
+
|
855 |
return $this->_realpath($path);
|
856 |
}
|
857 |
|
934 |
*/
|
935 |
function chdir($dir)
|
936 |
{
|
937 |
+
if (!$this->_precheck()) {
|
938 |
return false;
|
939 |
}
|
940 |
|
1091 |
*/
|
1092 |
function _list($dir, $raw = true)
|
1093 |
{
|
1094 |
+
if (!$this->_precheck()) {
|
1095 |
return false;
|
1096 |
}
|
1097 |
|
1146 |
}
|
1147 |
extract(unpack('Nlength', $this->_string_shift($response, 4)));
|
1148 |
$shortname = $this->_string_shift($response, $length);
|
1149 |
+
// SFTPv4 "removed the long filename from the names structure-- it can now be
|
1150 |
+
// built from information available in the attrs structure."
|
1151 |
+
if ($this->version < 4) {
|
1152 |
+
if (strlen($response) < 4) {
|
1153 |
+
return false;
|
1154 |
+
}
|
1155 |
+
extract(unpack('Nlength', $this->_string_shift($response, 4)));
|
1156 |
+
$longname = $this->_string_shift($response, $length);
|
1157 |
}
|
|
|
|
|
1158 |
$attributes = $this->_parseAttributes($response);
|
1159 |
+
if (!isset($attributes['type']) && $this->version < 4) {
|
1160 |
$fileType = $this->_parseLongname($longname);
|
1161 |
if ($fileType) {
|
1162 |
$attributes['type'] = $fileType;
|
1316 |
*/
|
1317 |
function size($filename)
|
1318 |
{
|
|
|
|
|
|
|
|
|
1319 |
$result = $this->stat($filename);
|
1320 |
if ($result === false) {
|
1321 |
return false;
|
1432 |
*/
|
1433 |
function stat($filename)
|
1434 |
{
|
1435 |
+
if (!$this->_precheck()) {
|
1436 |
return false;
|
1437 |
}
|
1438 |
|
1489 |
*/
|
1490 |
function lstat($filename)
|
1491 |
{
|
1492 |
+
if (!$this->_precheck()) {
|
1493 |
return false;
|
1494 |
}
|
1495 |
|
1603 |
*/
|
1604 |
function touch($filename, $time = null, $atime = null)
|
1605 |
{
|
1606 |
+
if (!$this->_precheck()) {
|
1607 |
return false;
|
1608 |
}
|
1609 |
|
1619 |
$atime = $time;
|
1620 |
}
|
1621 |
|
1622 |
+
if ($this->version < 4) {
|
1623 |
+
$attr = pack('N3', NET_SFTP_ATTR_ACCESSTIME, $atime, $time);
|
1624 |
+
} else {
|
1625 |
+
$attr = pack(
|
1626 |
+
'N5',
|
1627 |
+
NET_SFTP_ATTR_ACCESSTIME | NET_SFTP_ATTR_MODIFYTIME,
|
1628 |
+
$atime / 4294967296,
|
1629 |
+
$atime,
|
1630 |
+
$time / 4294967296,
|
1631 |
+
$time
|
1632 |
+
);
|
1633 |
+
}
|
1634 |
+
|
1635 |
+
$packet = pack('Na*', strlen($filename), $filename);
|
1636 |
+
$packet.= $this->version >= 5 ?
|
1637 |
+
pack('N2', 0, NET_SFTP_OPEN_OPEN_EXISTING) :
|
1638 |
+
pack('N', NET_SFTP_OPEN_WRITE | NET_SFTP_OPEN_CREATE | NET_SFTP_OPEN_EXCL);
|
1639 |
+
$packet.= $attr;
|
1640 |
+
|
1641 |
if (!$this->_send_sftp_packet(NET_SFTP_OPEN, $packet)) {
|
1642 |
return false;
|
1643 |
}
|
1660 |
/**
|
1661 |
* Changes file or directory owner
|
1662 |
*
|
1663 |
+
* $uid should be an int for SFTPv3 and a string for SFTPv4+. Ideally the string
|
1664 |
+
* would be of the form "user@dns_domain" but it does not need to be.
|
1665 |
+
* `$sftp->getSupportedVersions()['version']` will return the specific version
|
1666 |
+
* that's being used.
|
1667 |
+
*
|
1668 |
* Returns true on success or false on error.
|
1669 |
*
|
1670 |
* @param string $filename
|
1671 |
+
* @param int|string $uid
|
1672 |
* @param bool $recursive
|
1673 |
* @return bool
|
1674 |
* @access public
|
1675 |
*/
|
1676 |
function chown($filename, $uid, $recursive = false)
|
1677 |
{
|
1678 |
+
/*
|
1679 |
+
quoting <https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-7.5>,
|
1680 |
+
|
1681 |
+
"To avoid a representation that is tied to a particular underlying
|
1682 |
+
implementation at the client or server, the use of UTF-8 strings has
|
1683 |
+
been chosen. The string should be of the form "user@dns_domain".
|
1684 |
+
This will allow for a client and server that do not use the same
|
1685 |
+
local representation the ability to translate to a common syntax that
|
1686 |
+
can be interpreted by both. In the case where there is no
|
1687 |
+
translation available to the client or server, the attribute value
|
1688 |
+
must be constructed without the "@"."
|
1689 |
+
|
1690 |
+
phpseclib _could_ auto append the dns_domain to $uid BUT what if it shouldn't
|
1691 |
+
have one? phpseclib would have no way of knowing so rather than guess phpseclib
|
1692 |
+
will just use whatever value the user provided
|
1693 |
+
*/
|
1694 |
+
|
1695 |
+
$attr = $this->version < 4 ?
|
1696 |
+
// quoting <http://www.kernel.org/doc/man-pages/online/pages/man2/chown.2.html>,
|
1697 |
+
// "if the owner or group is specified as -1, then that ID is not changed"
|
1698 |
+
pack('N3', NET_SFTP_ATTR_UIDGID, $uid, -1) :
|
1699 |
+
// quoting <https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-7.5>,
|
1700 |
+
// "If either the owner or group field is zero length, the field should be
|
1701 |
+
// considered absent, and no change should be made to that specific field
|
1702 |
+
// during a modification operation"
|
1703 |
+
pack('NNa*Na*', NET_SFTP_ATTR_OWNERGROUP, strlen($uid), $uid, 0, '');
|
1704 |
|
1705 |
return $this->_setstat($filename, $attr, $recursive);
|
1706 |
}
|
1708 |
/**
|
1709 |
* Changes file or directory group
|
1710 |
*
|
1711 |
+
* $gid should be an int for SFTPv3 and a string for SFTPv4+. Ideally the string
|
1712 |
+
* would be of the form "user@dns_domain" but it does not need to be.
|
1713 |
+
* `$sftp->getSupportedVersions()['version']` will return the specific version
|
1714 |
+
* that's being used.
|
1715 |
+
*
|
1716 |
* Returns true on success or false on error.
|
1717 |
*
|
1718 |
* @param string $filename
|
1719 |
+
* @param int|string $gid
|
1720 |
* @param bool $recursive
|
1721 |
* @return bool
|
1722 |
* @access public
|
1723 |
*/
|
1724 |
function chgrp($filename, $gid, $recursive = false)
|
1725 |
{
|
1726 |
+
$attr = $this->version < 4 ?
|
1727 |
+
pack('N3', NET_SFTP_ATTR_UIDGID, -1, $gid) :
|
1728 |
+
pack('NNa*Na*', NET_SFTP_ATTR_OWNERGROUP, 0, '', strlen($gid), $gid);
|
1729 |
|
1730 |
return $this->_setstat($filename, $attr, $recursive);
|
1731 |
}
|
1792 |
*/
|
1793 |
function _setstat($filename, $attr, $recursive)
|
1794 |
{
|
1795 |
+
if (!$this->_precheck()) {
|
1796 |
return false;
|
1797 |
}
|
1798 |
|
1810 |
return $result;
|
1811 |
}
|
1812 |
|
1813 |
+
$packet = $this->version >= 4 ?
|
1814 |
+
pack('Na*a*Ca*', strlen($filename), $filename, substr($attr, 0, 4), NET_SFTP_TYPE_UNKNOWN, substr($attr, 4)) :
|
1815 |
+
pack('Na*a*', strlen($filename), $filename, $attr);
|
1816 |
+
if (!$this->_send_sftp_packet(NET_SFTP_SETSTAT, $packet)) {
|
1817 |
return false;
|
1818 |
}
|
1819 |
|
1883 |
return false;
|
1884 |
}
|
1885 |
} else {
|
1886 |
+
$packet = $this->version >= 4 ?
|
1887 |
+
pack('Na*Ca*', strlen($temp), $temp, NET_SFTP_TYPE_UNKNOWN, $attr) :
|
1888 |
+
pack('Na*a*', strlen($temp), $temp, $attr);
|
1889 |
+
if (!$this->_send_sftp_packet(NET_SFTP_SETSTAT, $packet)) {
|
1890 |
return false;
|
1891 |
}
|
1892 |
|
1901 |
}
|
1902 |
}
|
1903 |
|
1904 |
+
$packet = $this->version >= 4 ?
|
1905 |
+
pack('Na*Ca*', strlen($temp), $temp, NET_SFTP_TYPE_UNKNOWN, $attr) :
|
1906 |
+
pack('Na*a*', strlen($temp), $temp, $attr);
|
1907 |
+
if (!$this->_send_sftp_packet(NET_SFTP_SETSTAT, $packet)) {
|
1908 |
return false;
|
1909 |
}
|
1910 |
|
1929 |
*/
|
1930 |
function readlink($link)
|
1931 |
{
|
1932 |
+
if (!$this->_precheck()) {
|
1933 |
return false;
|
1934 |
}
|
1935 |
|
1979 |
*/
|
1980 |
function symlink($target, $link)
|
1981 |
{
|
1982 |
+
if (!$this->_precheck()) {
|
1983 |
return false;
|
1984 |
}
|
1985 |
|
1986 |
//$target = $this->_realpath($target);
|
1987 |
$link = $this->_realpath($link);
|
1988 |
|
1989 |
+
/* quoting https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-09#section-12.1 :
|
1990 |
+
|
1991 |
+
Changed the SYMLINK packet to be LINK and give it the ability to
|
1992 |
+
create hard links. Also change it's packet number because many
|
1993 |
+
implementation implemented SYMLINK with the arguments reversed.
|
1994 |
+
Hopefully the new argument names make it clear which way is which.
|
1995 |
+
*/
|
1996 |
+
if ($this->version == 6) {
|
1997 |
+
$type = NET_SFTP_LINK;
|
1998 |
+
$packet = pack('Na*Na*C', strlen($link), $link, strlen($target), $target, 1);
|
1999 |
+
} else {
|
2000 |
+
$type = NET_SFTP_SYMLINK;
|
2001 |
+
/* quoting http://bxr.su/OpenBSD/usr.bin/ssh/PROTOCOL#347 :
|
2002 |
+
|
2003 |
+
3.1. sftp: Reversal of arguments to SSH_FXP_SYMLINK
|
2004 |
+
|
2005 |
+
When OpenSSH's sftp-server was implemented, the order of the arguments
|
2006 |
+
to the SSH_FXP_SYMLINK method was inadvertently reversed. Unfortunately,
|
2007 |
+
the reversal was not noticed until the server was widely deployed. Since
|
2008 |
+
fixing this to follow the specification would cause incompatibility, the
|
2009 |
+
current order was retained. For correct operation, clients should send
|
2010 |
+
SSH_FXP_SYMLINK as follows:
|
2011 |
+
|
2012 |
+
uint32 id
|
2013 |
+
string targetpath
|
2014 |
+
string linkpath */
|
2015 |
+
$packet = substr($this->server_identifier, 0, 15) == 'SSH-2.0-OpenSSH' ?
|
2016 |
+
pack('Na*Na*', strlen($target), $target, strlen($link), $link) :
|
2017 |
+
pack('Na*Na*', strlen($link), $link, strlen($target), $target);
|
2018 |
+
}
|
2019 |
+
if (!$this->_send_sftp_packet($type, $packet)) {
|
2020 |
return false;
|
2021 |
}
|
2022 |
|
2049 |
*/
|
2050 |
function mkdir($dir, $mode = -1, $recursive = false)
|
2051 |
{
|
2052 |
+
if (!$this->_precheck()) {
|
2053 |
return false;
|
2054 |
}
|
2055 |
|
2118 |
*/
|
2119 |
function rmdir($dir)
|
2120 |
{
|
2121 |
+
if (!$this->_precheck()) {
|
2122 |
return false;
|
2123 |
}
|
2124 |
|
2167 |
* contain as many bytes as filename.ext does on your local filesystem. If your filename.ext is 1MB then that is how
|
2168 |
* large $remote_file will be, as well.
|
2169 |
*
|
2170 |
+
* Setting $mode to self::SOURCE_CALLBACK will use $data as callback function, which gets only one parameter -- number
|
2171 |
+
* of bytes to return, and returns a string if there is some data or null if there is no more data
|
2172 |
*
|
2173 |
* If $data is a resource then it'll be used as a resource instead.
|
2174 |
*
|
2204 |
*/
|
2205 |
function put($remote_file, $data, $mode = self::SOURCE_STRING, $start = -1, $local_start = -1, $progressCallback = null)
|
2206 |
{
|
2207 |
+
if (!$this->_precheck()) {
|
2208 |
return false;
|
2209 |
}
|
2210 |
|
2215 |
|
2216 |
$this->_remove_from_stat_cache($remote_file);
|
2217 |
|
2218 |
+
if ($this->version >= 5) {
|
2219 |
+
$flags = NET_SFTP_OPEN_OPEN_OR_CREATE;
|
2220 |
+
} else {
|
2221 |
+
$flags = NET_SFTP_OPEN_WRITE | NET_SFTP_OPEN_CREATE;
|
2222 |
+
// according to the SFTP specs, NET_SFTP_OPEN_APPEND should "force all writes to append data at the end of the file."
|
2223 |
+
// in practice, it doesn't seem to do that.
|
2224 |
+
//$flags|= ($mode & SFTP::RESUME) ? NET_SFTP_OPEN_APPEND : NET_SFTP_OPEN_TRUNCATE;
|
2225 |
+
}
|
2226 |
|
2227 |
if ($start >= 0) {
|
2228 |
$offset = $start;
|
2232 |
$offset = $size !== false ? $size : 0;
|
2233 |
} else {
|
2234 |
$offset = 0;
|
2235 |
+
if ($this->version >= 5) {
|
2236 |
+
$flags = NET_SFTP_OPEN_CREATE_TRUNCATE;
|
2237 |
+
} else {
|
2238 |
+
$flags|= NET_SFTP_OPEN_TRUNCATE;
|
2239 |
+
}
|
2240 |
}
|
2241 |
|
2242 |
+
$packet = pack('Na*', strlen($remote_file), $remote_file);
|
2243 |
+
$packet.= $this->version >= 5 ?
|
2244 |
+
pack('N3', 0, $flags, 0) :
|
2245 |
+
pack('N2', $flags, 0);
|
2246 |
if (!$this->_send_sftp_packet(NET_SFTP_OPEN, $packet)) {
|
2247 |
return false;
|
2248 |
}
|
2351 |
}
|
2352 |
}
|
2353 |
|
2354 |
+
$result = $this->_close_handle($handle);
|
2355 |
+
|
2356 |
if (!$this->_read_put_responses($i)) {
|
2357 |
if ($mode & self::SOURCE_LOCAL_FILE) {
|
2358 |
fclose($fp);
|
2361 |
return false;
|
2362 |
}
|
2363 |
|
2364 |
+
if ($mode & SFTP::SOURCE_LOCAL_FILE) {
|
|
|
|
|
|
|
|
|
|
|
2365 |
if (isset($fp) && is_resource($fp)) {
|
2366 |
fclose($fp);
|
2367 |
}
|
2368 |
+
|
2369 |
+
if ($this->preserveTime) {
|
2370 |
+
$stat = stat($data);
|
2371 |
+
if ($this->version < 4) {
|
2372 |
+
$attr = pack('N3', NET_SFTP_ATTR_ACCESSTIME, $stat['atime'], $stat['mtime']);
|
2373 |
+
} else {
|
2374 |
+
$attr = pack(
|
2375 |
+
'N5',
|
2376 |
+
NET_SFTP_ATTR_ACCESSTIME | NET_SFTP_ATTR_MODIFYTIME,
|
2377 |
+
$stat['atime'] / 4294967296,
|
2378 |
+
$stat['atime'],
|
2379 |
+
$stat['mtime'] / 4294967296,
|
2380 |
+
$stat['mtime']
|
2381 |
+
);
|
2382 |
+
}
|
2383 |
+
|
2384 |
+
if (!$this->_setstat($remote_file, $attr, false)) {
|
2385 |
+
user_error('Error setting file time');
|
2386 |
+
}
|
2387 |
+
}
|
2388 |
}
|
2389 |
|
2390 |
+
return $result;
|
2391 |
}
|
2392 |
|
2393 |
/**
|
2474 |
*/
|
2475 |
function get($remote_file, $local_file = false, $offset = 0, $length = -1, $progressCallback = null)
|
2476 |
{
|
2477 |
+
if (!$this->_precheck()) {
|
2478 |
return false;
|
2479 |
}
|
2480 |
|
2483 |
return false;
|
2484 |
}
|
2485 |
|
2486 |
+
$packet = pack('Na*', strlen($remote_file), $remote_file);
|
2487 |
+
$packet.= $this->version >= 5 ?
|
2488 |
+
pack('N3', 0, NET_SFTP_OPEN_OPEN_EXISTING, 0) :
|
2489 |
+
pack('N2', NET_SFTP_OPEN_READ, 0);
|
2490 |
if (!$this->_send_sftp_packet(NET_SFTP_OPEN, $packet)) {
|
2491 |
return false;
|
2492 |
}
|
2586 |
if ($fclose_check) {
|
2587 |
fclose($fp);
|
2588 |
}
|
2589 |
+
// maybe the file was successfully transferred, maybe it wasn't
|
2590 |
+
if ($this->channel_close) {
|
2591 |
+
$this->partial_init = false;
|
2592 |
+
$this->_init_sftp_connection();
|
2593 |
+
return false;
|
2594 |
+
} else {
|
2595 |
+
user_error('Expected SSH_FX_DATA or SSH_FXP_STATUS');
|
2596 |
+
}
|
2597 |
}
|
2598 |
$response = null;
|
2599 |
}
|
2638 |
*/
|
2639 |
function delete($path, $recursive = true)
|
2640 |
{
|
2641 |
+
if (!$this->_precheck()) {
|
2642 |
return false;
|
2643 |
}
|
2644 |
|
2767 |
function file_exists($path)
|
2768 |
{
|
2769 |
if ($this->use_stat_cache) {
|
2770 |
+
if (!$this->_precheck()) {
|
2771 |
+
return false;
|
2772 |
+
}
|
2773 |
+
|
2774 |
$path = $this->_realpath($path);
|
2775 |
|
2776 |
$result = $this->_query_stat_cache($path);
|
2841 |
*/
|
2842 |
function is_readable($path)
|
2843 |
{
|
2844 |
+
if (!$this->_precheck()) {
|
2845 |
+
return false;
|
2846 |
+
}
|
2847 |
+
|
2848 |
$path = $this->_realpath($path);
|
2849 |
|
2850 |
$packet = pack('Na*N2', strlen($path), $path, NET_SFTP_OPEN_READ, 0);
|
2873 |
*/
|
2874 |
function is_writable($path)
|
2875 |
{
|
2876 |
+
if (!$this->_precheck()) {
|
2877 |
+
return false;
|
2878 |
+
}
|
2879 |
+
|
2880 |
$path = $this->_realpath($path);
|
2881 |
|
2882 |
$packet = pack('Na*N2', strlen($path), $path, NET_SFTP_OPEN_WRITE, 0);
|
3057 |
*/
|
3058 |
function _get_xstat_cache_prop($path, $prop, $type)
|
3059 |
{
|
3060 |
+
if (!$this->_precheck()) {
|
3061 |
+
return false;
|
3062 |
+
}
|
3063 |
+
|
3064 |
if ($this->use_stat_cache) {
|
3065 |
$path = $this->_realpath($path);
|
3066 |
|
3081 |
}
|
3082 |
|
3083 |
/**
|
3084 |
+
* Renames a file or a directory on the SFTP server.
|
3085 |
+
*
|
3086 |
+
* If the file already exists this will return false
|
3087 |
*
|
3088 |
* @param string $oldname
|
3089 |
* @param string $newname
|
3092 |
*/
|
3093 |
function rename($oldname, $newname)
|
3094 |
{
|
3095 |
+
if (!$this->_precheck()) {
|
3096 |
return false;
|
3097 |
}
|
3098 |
|
3104 |
|
3105 |
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.3
|
3106 |
$packet = pack('Na*Na*', strlen($oldname), $oldname, strlen($newname), $newname);
|
3107 |
+
if ($this->version >= 5) {
|
3108 |
+
/* quoting https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-05#section-6.5 ,
|
3109 |
+
|
3110 |
+
'flags' is 0 or a combination of:
|
3111 |
+
|
3112 |
+
SSH_FXP_RENAME_OVERWRITE 0x00000001
|
3113 |
+
SSH_FXP_RENAME_ATOMIC 0x00000002
|
3114 |
+
SSH_FXP_RENAME_NATIVE 0x00000004
|
3115 |
+
|
3116 |
+
(none of these are currently supported) */
|
3117 |
+
$packet.= "\0\0\0\0";
|
3118 |
+
}
|
3119 |
if (!$this->_send_sftp_packet(NET_SFTP_RENAME, $packet)) {
|
3120 |
return false;
|
3121 |
}
|
3145 |
return true;
|
3146 |
}
|
3147 |
|
3148 |
+
/**
|
3149 |
+
* Parse Time
|
3150 |
+
*
|
3151 |
+
* See '7.7. Times' of draft-ietf-secsh-filexfer-13 for more info.
|
3152 |
+
*
|
3153 |
+
* @param string $key
|
3154 |
+
* @param int $flags
|
3155 |
+
* @param string $response
|
3156 |
+
* @return array
|
3157 |
+
* @access private
|
3158 |
+
*/
|
3159 |
+
function _parseTime($key, $flags, &$response)
|
3160 |
+
{
|
3161 |
+
if (strlen($response) < 8) {
|
3162 |
+
user_error('Malformed file attributes');
|
3163 |
+
return array();
|
3164 |
+
}
|
3165 |
+
$attr = array();
|
3166 |
+
$attr[$key] = hexdec(bin2hex($this->_string_shift($response, 8)));
|
3167 |
+
if ($flags & NET_SFTP_ATTR_SUBSECOND_TIMES) {
|
3168 |
+
$attr+= extract(unpack('N' . $key . '_nseconds', $this->_string_shift($response, 4)));
|
3169 |
+
}
|
3170 |
+
return $attr;
|
3171 |
+
}
|
3172 |
+
|
3173 |
/**
|
3174 |
* Parse Attributes
|
3175 |
*
|
3181 |
*/
|
3182 |
function _parseAttributes(&$response)
|
3183 |
{
|
3184 |
+
if ($this->version >= 4) {
|
3185 |
+
$length = 5;
|
3186 |
+
$format = 'Nflags/Ctype';
|
3187 |
+
} else {
|
3188 |
+
$length = 4;
|
3189 |
+
$format = 'Nflags';
|
3190 |
+
}
|
3191 |
+
|
3192 |
$attr = array();
|
3193 |
+
if (strlen($response) < $length) {
|
3194 |
user_error('Malformed file attributes');
|
3195 |
return array();
|
3196 |
}
|
3197 |
+
extract(unpack($format, $this->_string_shift($response, $length)));
|
3198 |
+
if (isset($type)) {
|
3199 |
+
$attr['type'] = $type;
|
3200 |
+
}
|
3201 |
foreach ($this->attributes as $key => $value) {
|
3202 |
switch ($flags & $key) {
|
3203 |
+
case NET_SFTP_ATTR_UIDGID:
|
3204 |
+
if ($this->version > 3) {
|
3205 |
+
continue 2;
|
3206 |
+
}
|
3207 |
+
break;
|
3208 |
+
case NET_SFTP_ATTR_CREATETIME:
|
3209 |
+
case NET_SFTP_ATTR_MODIFYTIME:
|
3210 |
+
case NET_SFTP_ATTR_ACL:
|
3211 |
+
case NET_SFTP_ATTR_OWNERGROUP:
|
3212 |
+
case NET_SFTP_ATTR_SUBSECOND_TIMES:
|
3213 |
+
if ($this->version < 4) {
|
3214 |
+
continue 2;
|
3215 |
+
}
|
3216 |
+
break;
|
3217 |
+
case NET_SFTP_ATTR_BITS:
|
3218 |
+
if ($this->version < 5) {
|
3219 |
+
continue 2;
|
3220 |
+
}
|
3221 |
+
break;
|
3222 |
+
case NET_SFTP_ATTR_ALLOCATION_SIZE:
|
3223 |
+
case NET_SFTP_ATTR_TEXT_HINT:
|
3224 |
+
case NET_SFTP_ATTR_MIME_TYPE:
|
3225 |
+
case NET_SFTP_ATTR_LINK_COUNT:
|
3226 |
+
case NET_SFTP_ATTR_UNTRANSLATED_NAME:
|
3227 |
+
case NET_SFTP_ATTR_CTIME:
|
3228 |
+
if ($this->version < 6) {
|
3229 |
+
continue 2;
|
3230 |
+
}
|
3231 |
+
}
|
3232 |
+
switch ($flags & $key) {
|
3233 |
+
case NET_SFTP_ATTR_SIZE: // 0x00000001
|
3234 |
// The size attribute is defined as an unsigned 64-bit integer.
|
3235 |
// The following will use floats on 32-bit platforms, if necessary.
|
3236 |
// As can be seen in the BigInteger class, floats are generally
|
3239 |
// of precision. Interpreted in filesize, 2^50 bytes = 1024 TiB.
|
3240 |
$attr['size'] = hexdec(bin2hex($this->_string_shift($response, 8)));
|
3241 |
break;
|
3242 |
+
case NET_SFTP_ATTR_UIDGID: // 0x00000002 (SFTPv3 or earlier)
|
3243 |
if (strlen($response) < 8) {
|
3244 |
user_error('Malformed file attributes');
|
3245 |
return $attr;
|
3246 |
}
|
3247 |
$attr+= unpack('Nuid/Ngid', $this->_string_shift($response, 8));
|
3248 |
break;
|
3249 |
+
case NET_SFTP_ATTR_PERMISSIONS: // 0x00000004
|
3250 |
if (strlen($response) < 4) {
|
3251 |
user_error('Malformed file attributes');
|
3252 |
return $attr;
|
3260 |
$attr+= array('type' => $fileType);
|
3261 |
}
|
3262 |
break;
|
3263 |
+
case NET_SFTP_ATTR_ACCESSTIME: // 0x00000008
|
3264 |
+
if ($this->version >= 4) {
|
3265 |
+
$attr+= $this->_parseTime('atime', $flags, $response);
|
3266 |
+
break;
|
3267 |
+
}
|
3268 |
if (strlen($response) < 8) {
|
3269 |
user_error('Malformed file attributes');
|
3270 |
return $attr;
|
3271 |
}
|
3272 |
$attr+= unpack('Natime/Nmtime', $this->_string_shift($response, 8));
|
3273 |
break;
|
3274 |
+
case NET_SFTP_ATTR_CREATETIME: // 0x00000010 (SFTPv4+)
|
3275 |
+
$attr+= $this->_parseTime('createtime', $flags, $response);
|
3276 |
+
break;
|
3277 |
+
case NET_SFTP_ATTR_MODIFYTIME: // 0x00000020
|
3278 |
+
$attr+= $this->_parseTime('mtime', $flags, $response);
|
3279 |
+
break;
|
3280 |
+
case NET_SFTP_ATTR_ACL: // 0x00000040
|
3281 |
+
// access control list
|
3282 |
+
// see https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-04#section-5.7
|
3283 |
+
// currently unsupported
|
3284 |
+
if (strlen($response) < 4) {
|
3285 |
+
user_error('Malformed file attributes');
|
3286 |
+
return $attr;
|
3287 |
+
}
|
3288 |
+
extract(unpack('Ncount', $this->_string_shift($response, 4)));
|
3289 |
+
for ($i = 0; $i < $count; $i++) {
|
3290 |
+
if (strlen($response) < 16) {
|
3291 |
+
user_error('Malformed file attributes');
|
3292 |
+
return $attr;
|
3293 |
+
}
|
3294 |
+
extract(unpack('Ntype/Nflag/Nmask/Nlength', $this->_string_shift($response, 16)));
|
3295 |
+
if (strlen($response) < $length) {
|
3296 |
+
user_error('Malformed file attributes');
|
3297 |
+
return $attr;
|
3298 |
+
}
|
3299 |
+
$this->_string_shift($response, $length); // who
|
3300 |
+
}
|
3301 |
+
break;
|
3302 |
+
case NET_SFTP_ATTR_OWNERGROUP: // 0x00000080
|
3303 |
+
if (strlen($response) < 4) {
|
3304 |
+
user_error('Malformed file attributes');
|
3305 |
+
return $attr;
|
3306 |
+
}
|
3307 |
+
extract(unpack('Nlength', $this->_string_shift($response, 4)));
|
3308 |
+
if (strlen($response) < $length) {
|
3309 |
+
user_error('Malformed file attributes');
|
3310 |
+
return $attr;
|
3311 |
+
}
|
3312 |
+
$attr['owner'] = $this->_string_shift($response, $length);
|
3313 |
+
|
3314 |
+
if (strlen($response) < 4) {
|
3315 |
+
user_error('Malformed file attributes');
|
3316 |
+
return $attr;
|
3317 |
+
}
|
3318 |
+
extract(unpack('Nlength', $this->_string_shift($response, 4)));
|
3319 |
+
if (strlen($response) < $length) {
|
3320 |
+
user_error('Malformed file attributes');
|
3321 |
+
return $attr;
|
3322 |
+
}
|
3323 |
+
$attr['group'] = $this->_string_shift($response, $length);
|
3324 |
+
break;
|
3325 |
+
case NET_SFTP_ATTR_SUBSECOND_TIMES: // 0x00000100
|
3326 |
+
break;
|
3327 |
+
case NET_SFTP_ATTR_BITS: // 0x00000200 (SFTPv5+)
|
3328 |
+
// see https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-05#section-5.8
|
3329 |
+
// currently unsupported
|
3330 |
+
// tells if you file is:
|
3331 |
+
// readonly, system, hidden, case inensitive, archive, encrypted, compressed, sparse
|
3332 |
+
// append only, immutable, sync
|
3333 |
+
if (strlen($response) < 8) {
|
3334 |
+
user_error('Malformed file attributes');
|
3335 |
+
return $attr;
|
3336 |
+
}
|
3337 |
+
extract(unpack('Nattrib-bits/Nattrib-bits-valid', $this->_string_shift($response, 8)));
|
3338 |
+
break;
|
3339 |
+
case NET_SFTP_ATTR_ALLOCATION_SIZE: // 0x00000400 (SFTPv6+)
|
3340 |
+
// see https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-7.4
|
3341 |
+
// represents the number of bytes htat the file consumes on the disk. will
|
3342 |
+
// usually be larger than the 'size' field
|
3343 |
+
$attr['allocation-size'] = hexdec(bin2hex($this->_string_shift($response, 8)));
|
3344 |
+
break;
|
3345 |
+
case NET_SFTP_ATTR_TEXT_HINT: // 0x00000800
|
3346 |
+
// https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-7.10
|
3347 |
+
// currently unsupported
|
3348 |
+
// tells if file is "known text", "guessed text", "known binary", "guessed binary"
|
3349 |
+
extract(unpack('Ctext-hint', $this->_string_shift($response)));
|
3350 |
+
break;
|
3351 |
+
case NET_SFTP_ATTR_MIME_TYPE: // 0x00001000
|
3352 |
+
// see https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-7.11
|
3353 |
+
if (strlen($response) < 4) {
|
3354 |
+
user_error('Malformed file attributes');
|
3355 |
+
return $attr;
|
3356 |
+
}
|
3357 |
+
extract(unpack('Nlength', $this->_string_shift($response, 4)));
|
3358 |
+
if (strlen($response) < $length) {
|
3359 |
+
user_error('Malformed file attributes');
|
3360 |
+
return $attr;
|
3361 |
+
}
|
3362 |
+
$attr['mime-type'] = $this->_string_shift($response, $length);
|
3363 |
+
break;
|
3364 |
+
case NET_SFTP_ATTR_LINK_COUNT: // 0x00002000
|
3365 |
+
// see https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-7.12
|
3366 |
+
if (strlen($response) < 4) {
|
3367 |
+
user_error('Malformed file attributes');
|
3368 |
+
return $attr;
|
3369 |
+
}
|
3370 |
+
$attr+= unpack('Nlink-count', $this->_string_shift($response, 4));
|
3371 |
+
break;
|
3372 |
+
case NET_SFTP_ATTR_UNTRANSLATED_NAME:// 0x00004000
|
3373 |
+
// see https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-7.13
|
3374 |
+
if (strlen($response) < 4) {
|
3375 |
+
user_error('Malformed file attributes');
|
3376 |
+
return $attr;
|
3377 |
+
}
|
3378 |
+
extract(unpack('Nlength', $this->_string_shift($response, 4)));
|
3379 |
+
if (strlen($response) < $length) {
|
3380 |
+
user_error('Malformed file attributes');
|
3381 |
+
return $attr;
|
3382 |
+
}
|
3383 |
+
$attr['untranslated-name'] = $this->_string_shift($response, $length);
|
3384 |
+
break;
|
3385 |
+
case NET_SFTP_ATTR_CTIME: // 0x00008000
|
3386 |
+
// 'ctime' contains the last time the file attributes were changed. The
|
3387 |
+
// exact meaning of this field depends on the server.
|
3388 |
+
$attr+= $this->_parseTime('ctime', $flags, $response);
|
3389 |
+
break;
|
3390 |
+
case NET_SFTP_ATTR_EXTENDED: // 0x80000000
|
3391 |
if (strlen($response) < 4) {
|
3392 |
user_error('Malformed file attributes');
|
3393 |
return $attr;
|
3570 |
*/
|
3571 |
function _get_sftp_packet($request_id = null)
|
3572 |
{
|
3573 |
+
$this->channel_close = false;
|
3574 |
+
|
3575 |
if (isset($request_id) && isset($this->requestBuffer[$request_id])) {
|
3576 |
$this->packet_type = $this->requestBuffer[$request_id]['packet_type'];
|
3577 |
$temp = $this->requestBuffer[$request_id]['packet'];
|
3588 |
// SFTP packet length
|
3589 |
while (strlen($this->packet_buffer) < 4) {
|
3590 |
$temp = $this->_get_channel_packet(self::CHANNEL, true);
|
3591 |
+
if ($temp === true) {
|
3592 |
+
if ($this->channel_status[self::CHANNEL] === NET_SSH2_MSG_CHANNEL_CLOSE) {
|
3593 |
+
$this->channel_close = true;
|
3594 |
+
}
|
3595 |
$this->packet_type = false;
|
3596 |
$this->packet_buffer = '';
|
3597 |
return false;
|
3598 |
}
|
3599 |
+
if ($temp === false) {
|
3600 |
+
return false;
|
3601 |
+
}
|
3602 |
$this->packet_buffer.= $temp;
|
3603 |
}
|
3604 |
if (strlen($this->packet_buffer) < 4) {
|
3608 |
$tempLength = $length;
|
3609 |
$tempLength-= strlen($this->packet_buffer);
|
3610 |
|
|
|
3611 |
// 256 * 1024 is what SFTP_MAX_MSG_LENGTH is set to in OpenSSH's sftp-common.h
|
3612 |
+
if (!$this->allow_arbitrary_length_packets && !$this->use_request_id && $tempLength > 256 * 1024) {
|
3613 |
user_error('Invalid SFTP packet size');
|
3614 |
return false;
|
3615 |
}
|
3727 |
*/
|
3728 |
function getSupportedVersions()
|
3729 |
{
|
3730 |
+
if (!($this->bitmap & SSH2::MASK_LOGIN)) {
|
3731 |
+
return false;
|
3732 |
+
}
|
3733 |
+
|
3734 |
+
if (!$this->partial_init) {
|
3735 |
+
$this->_partial_init_sftp_connection();
|
3736 |
+
}
|
3737 |
+
|
3738 |
+
$temp = array('version' => $this->defaultVersion);
|
3739 |
if (isset($this->extensions['versions'])) {
|
3740 |
$temp['extensions'] = $this->extensions['versions'];
|
3741 |
}
|
3742 |
return $temp;
|
3743 |
}
|
3744 |
|
3745 |
+
/**
|
3746 |
+
* Get supported SFTP versions
|
3747 |
+
*
|
3748 |
+
* @return array
|
3749 |
+
* @access public
|
3750 |
+
*/
|
3751 |
+
function getNegotiatedVersion()
|
3752 |
+
{
|
3753 |
+
if (!$this->_precheck()) {
|
3754 |
+
return false;
|
3755 |
+
}
|
3756 |
+
|
3757 |
+
return $this->version;
|
3758 |
+
}
|
3759 |
+
|
3760 |
+
/**
|
3761 |
+
* Set preferred version
|
3762 |
+
*
|
3763 |
+
* If you're preferred version isn't supported then the highest supported
|
3764 |
+
* version of SFTP will be utilized. Set to null or false or int(0) to
|
3765 |
+
* unset the preferred version
|
3766 |
+
*
|
3767 |
+
* @param int $version
|
3768 |
+
* @access public
|
3769 |
+
*/
|
3770 |
+
function setPreferredVersion($version)
|
3771 |
+
{
|
3772 |
+
$this->preferredVersion = $version;
|
3773 |
+
}
|
3774 |
+
|
3775 |
/**
|
3776 |
* Disconnect
|
3777 |
*
|
vendor/phpseclib/phpseclib/phpseclib/Net/SSH2.php
CHANGED
@@ -70,6 +70,25 @@ use phpseclib\System\SSH\Agent;
|
|
70 |
*/
|
71 |
class SSH2
|
72 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
73 |
/**#@+
|
74 |
* Execution Bitmap Masks
|
75 |
*
|
@@ -970,6 +989,71 @@ class SSH2
|
|
970 |
*/
|
971 |
var $auth = array();
|
972 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
973 |
/**
|
974 |
* Default Constructor.
|
975 |
*
|
@@ -1210,8 +1294,8 @@ class SSH2
|
|
1210 |
$read = array($this->fsock);
|
1211 |
$write = $except = null;
|
1212 |
$start = microtime(true);
|
1213 |
-
$sec = floor($this->curTimeout);
|
1214 |
-
$usec = 1000000 * ($this->curTimeout - $sec);
|
1215 |
// on windows this returns a "Warning: Invalid CRT parameters detected" error
|
1216 |
// the !count() is done as a workaround for <https://bugs.php.net/42682>
|
1217 |
if (!@stream_select($read, $write, $except, $sec, $usec) && !count($read)) {
|
@@ -1226,6 +1310,7 @@ class SSH2
|
|
1226 |
if (strlen($temp) == 255) {
|
1227 |
continue;
|
1228 |
}
|
|
|
1229 |
if ($temp === false) {
|
1230 |
return false;
|
1231 |
}
|
@@ -1347,6 +1432,7 @@ class SSH2
|
|
1347 |
function _key_exchange($kexinit_payload_server = false)
|
1348 |
{
|
1349 |
$preferred = $this->preferred;
|
|
|
1350 |
|
1351 |
$kex_algorithms = isset($preferred['kex']) ?
|
1352 |
$preferred['kex'] :
|
@@ -1430,7 +1516,7 @@ class SSH2
|
|
1430 |
0
|
1431 |
);
|
1432 |
|
1433 |
-
if ($
|
1434 |
if (!$this->_send_binary_packet($kexinit_payload_client)) {
|
1435 |
return false;
|
1436 |
}
|
@@ -1446,6 +1532,8 @@ class SSH2
|
|
1446 |
user_error('Expected SSH_MSG_KEXINIT');
|
1447 |
return false;
|
1448 |
}
|
|
|
|
|
1449 |
}
|
1450 |
|
1451 |
$response = $kexinit_payload_server;
|
@@ -1518,7 +1606,7 @@ class SSH2
|
|
1518 |
extract(unpack('Cfirst_kex_packet_follows', $this->_string_shift($response, 1)));
|
1519 |
$first_kex_packet_follows = $first_kex_packet_follows != 0;
|
1520 |
|
1521 |
-
if (
|
1522 |
return false;
|
1523 |
}
|
1524 |
|
@@ -1558,19 +1646,25 @@ class SSH2
|
|
1558 |
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
1559 |
}
|
1560 |
|
|
|
|
|
|
|
|
|
|
|
|
|
1561 |
$compression_algorithm_out = $this->_array_intersect_first($c2s_compression_algorithms, $this->compression_algorithms_client_to_server);
|
1562 |
if ($compression_algorithm_out === false) {
|
1563 |
user_error('No compatible client to server compression algorithms found');
|
1564 |
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
1565 |
}
|
1566 |
-
|
1567 |
|
1568 |
-
$compression_algorithm_in = $this->_array_intersect_first($s2c_compression_algorithms, $this->
|
1569 |
if ($compression_algorithm_in === false) {
|
1570 |
user_error('No compatible server to client compression algorithms found');
|
1571 |
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
1572 |
}
|
1573 |
-
|
1574 |
|
1575 |
// Only relevant in diffie-hellman-group-exchange-sha{1,256}, otherwise empty.
|
1576 |
$exchange_hash_rfc4419 = '';
|
@@ -2003,6 +2097,8 @@ class SSH2
|
|
2003 |
}
|
2004 |
$this->hmac_check->setKey(substr($key, 0, $checkKeyLength));
|
2005 |
|
|
|
|
|
2006 |
return true;
|
2007 |
}
|
2008 |
|
@@ -2131,7 +2227,7 @@ class SSH2
|
|
2131 |
|
2132 |
// try logging with 'none' as an authentication method first since that's what
|
2133 |
// PuTTY does
|
2134 |
-
if (substr($this->server_identifier, 0,
|
2135 |
if ($this->_login($username)) {
|
2136 |
return true;
|
2137 |
}
|
@@ -2163,9 +2259,61 @@ class SSH2
|
|
2163 |
return $this->_login_helper($username);
|
2164 |
}
|
2165 |
|
2166 |
-
|
2167 |
-
if (
|
2168 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2169 |
}
|
2170 |
}
|
2171 |
return false;
|
@@ -2275,7 +2423,9 @@ class SSH2
|
|
2275 |
case NET_SSH2_MSG_USERAUTH_SUCCESS:
|
2276 |
$this->bitmap |= self::MASK_LOGIN;
|
2277 |
return true;
|
2278 |
-
|
|
|
|
|
2279 |
default:
|
2280 |
return false;
|
2281 |
}
|
@@ -2347,6 +2497,7 @@ class SSH2
|
|
2347 |
}
|
2348 |
extract(unpack('Nlength', $this->_string_shift($response, 4)));
|
2349 |
$auth_methods = explode(',', $this->_string_shift($response, $length));
|
|
|
2350 |
if (!strlen($response)) {
|
2351 |
return false;
|
2352 |
}
|
@@ -2519,6 +2670,8 @@ class SSH2
|
|
2519 |
case NET_SSH2_MSG_USERAUTH_SUCCESS:
|
2520 |
return true;
|
2521 |
case NET_SSH2_MSG_USERAUTH_FAILURE:
|
|
|
|
|
2522 |
return false;
|
2523 |
}
|
2524 |
|
@@ -2627,8 +2780,9 @@ class SSH2
|
|
2627 |
if (strlen($response) < 4) {
|
2628 |
return false;
|
2629 |
}
|
2630 |
-
extract(unpack('
|
2631 |
-
$this->
|
|
|
2632 |
return false;
|
2633 |
case NET_SSH2_MSG_USERAUTH_PK_OK:
|
2634 |
// we'll just take it on faith that the public key blob and the public key algorithm name are as
|
@@ -2669,6 +2823,8 @@ class SSH2
|
|
2669 |
switch ($type) {
|
2670 |
case NET_SSH2_MSG_USERAUTH_FAILURE:
|
2671 |
// either the login is bad or the server employs multi-factor authentication
|
|
|
|
|
2672 |
return false;
|
2673 |
case NET_SSH2_MSG_USERAUTH_SUCCESS:
|
2674 |
$this->bitmap |= self::MASK_LOGIN;
|
@@ -2795,26 +2951,12 @@ class SSH2
|
|
2795 |
return false;
|
2796 |
}
|
2797 |
|
2798 |
-
$
|
2799 |
-
if (
|
2800 |
-
|
2801 |
-
|
2802 |
-
return false;
|
2803 |
-
}
|
2804 |
-
|
2805 |
-
if (!strlen($response)) {
|
2806 |
-
return false;
|
2807 |
}
|
2808 |
-
list(, $type) = unpack('C', $this->_string_shift($response, 1));
|
2809 |
|
2810 |
-
switch ($type) {
|
2811 |
-
case NET_SSH2_MSG_CHANNEL_SUCCESS:
|
2812 |
-
break;
|
2813 |
-
case NET_SSH2_MSG_CHANNEL_FAILURE:
|
2814 |
-
default:
|
2815 |
-
user_error('Unable to request pseudo-terminal');
|
2816 |
-
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
|
2817 |
-
}
|
2818 |
$this->in_request_pty_exec = true;
|
2819 |
}
|
2820 |
|
@@ -2935,6 +3077,13 @@ class SSH2
|
|
2935 |
return false;
|
2936 |
}
|
2937 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2938 |
$packet = pack(
|
2939 |
'CNNa*C',
|
2940 |
NET_SSH2_MSG_CHANNEL_REQUEST,
|
@@ -2947,7 +3096,12 @@ class SSH2
|
|
2947 |
return false;
|
2948 |
}
|
2949 |
|
2950 |
-
$this->
|
|
|
|
|
|
|
|
|
|
|
2951 |
|
2952 |
$this->bitmap |= self::MASK_SHELL;
|
2953 |
|
@@ -3319,7 +3473,7 @@ class SSH2
|
|
3319 |
$read = array($this->fsock);
|
3320 |
$write = $except = null;
|
3321 |
|
3322 |
-
if (
|
3323 |
if ($this->keepAlive <= 0) {
|
3324 |
@stream_select($read, $write, $except, null);
|
3325 |
} else {
|
@@ -3350,8 +3504,8 @@ class SSH2
|
|
3350 |
$this->curTimeout-= $elapsed;
|
3351 |
}
|
3352 |
|
3353 |
-
$sec = floor($this->curTimeout);
|
3354 |
-
$usec = 1000000 * ($this->curTimeout - $sec);
|
3355 |
|
3356 |
// on windows this returns a "Warning: Invalid CRT parameters detected" error
|
3357 |
if (!@stream_select($read, $write, $except, $sec, $usec) && !count($read)) {
|
@@ -3365,7 +3519,7 @@ class SSH2
|
|
3365 |
|
3366 |
if (!is_resource($this->fsock) || feof($this->fsock)) {
|
3367 |
$this->bitmap = 0;
|
3368 |
-
user_error('Connection closed prematurely');
|
3369 |
return false;
|
3370 |
}
|
3371 |
|
@@ -3373,7 +3527,8 @@ class SSH2
|
|
3373 |
$raw = stream_get_contents($this->fsock, $this->decrypt_block_size);
|
3374 |
|
3375 |
if (!strlen($raw)) {
|
3376 |
-
|
|
|
3377 |
}
|
3378 |
|
3379 |
if ($this->decrypt !== false) {
|
@@ -3436,9 +3591,41 @@ class SSH2
|
|
3436 |
}
|
3437 |
}
|
3438 |
|
3439 |
-
|
3440 |
-
|
3441 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3442 |
|
3443 |
$this->get_seq_no++;
|
3444 |
|
@@ -3513,6 +3700,10 @@ class SSH2
|
|
3513 |
|
3514 |
// only called when we've already logged in
|
3515 |
if (($this->bitmap & self::MASK_CONNECTED) && $this->isAuthenticated()) {
|
|
|
|
|
|
|
|
|
3516 |
switch (ord($payload[0])) {
|
3517 |
case NET_SSH2_MSG_CHANNEL_REQUEST:
|
3518 |
if (strlen($payload) == 31) {
|
@@ -3714,7 +3905,20 @@ class SSH2
|
|
3714 |
function _get_channel_packet($client_channel, $skip_extended = false)
|
3715 |
{
|
3716 |
if (!empty($this->channel_buffers[$client_channel])) {
|
3717 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3718 |
}
|
3719 |
|
3720 |
while (true) {
|
@@ -3788,10 +3992,7 @@ class SSH2
|
|
3788 |
if ($client_channel == $channel && $this->channel_status[$channel] == NET_SSH2_MSG_CHANNEL_DATA) {
|
3789 |
return $data;
|
3790 |
}
|
3791 |
-
|
3792 |
-
$this->channel_buffers[$channel] = array();
|
3793 |
-
}
|
3794 |
-
$this->channel_buffers[$channel][] = $data;
|
3795 |
|
3796 |
continue 2;
|
3797 |
case NET_SSH2_MSG_CHANNEL_REQUEST:
|
@@ -3870,20 +4071,15 @@ class SSH2
|
|
3870 |
$result = $client_channel == $channel ? true : $this->_get_channel_packet($client_channel, $skip_extended);
|
3871 |
$this->_on_channel_open();
|
3872 |
return $result;
|
3873 |
-
|
3874 |
-
default:
|
3875 |
user_error('Unable to open channel');
|
3876 |
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
|
3877 |
-
|
3878 |
-
|
3879 |
-
|
3880 |
-
|
3881 |
-
|
3882 |
-
|
3883 |
-
continue 3;
|
3884 |
-
case NET_SSH2_MSG_CHANNEL_FAILURE:
|
3885 |
-
user_error('Error opening channel');
|
3886 |
-
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
|
3887 |
}
|
3888 |
break;
|
3889 |
case NET_SSH2_MSG_CHANNEL_REQUEST:
|
@@ -3892,6 +4088,14 @@ class SSH2
|
|
3892 |
return true;
|
3893 |
case NET_SSH2_MSG_CHANNEL_FAILURE:
|
3894 |
return false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3895 |
default:
|
3896 |
user_error('Unable to fulfill channel request');
|
3897 |
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
|
@@ -3905,10 +4109,6 @@ class SSH2
|
|
3905 |
|
3906 |
switch ($type) {
|
3907 |
case NET_SSH2_MSG_CHANNEL_DATA:
|
3908 |
-
//if ($this->channel_status[$channel] == NET_SSH2_MSG_IGNORE) {
|
3909 |
-
// $this->channel_status[$channel] = NET_SSH2_MSG_CHANNEL_DATA;
|
3910 |
-
//}
|
3911 |
-
|
3912 |
/*
|
3913 |
if ($channel == self::CHANNEL_EXEC) {
|
3914 |
// SCP requires null packets, such as this, be sent. further, in the case of the ssh.com SSH server
|
@@ -3935,10 +4135,7 @@ class SSH2
|
|
3935 |
if ($client_channel == $channel) {
|
3936 |
return $data;
|
3937 |
}
|
3938 |
-
|
3939 |
-
$this->channel_buffers[$channel] = array();
|
3940 |
-
}
|
3941 |
-
$this->channel_buffers[$channel][] = $data;
|
3942 |
break;
|
3943 |
case NET_SSH2_MSG_CHANNEL_CLOSE:
|
3944 |
$this->curTimeout = 5;
|
@@ -3957,7 +4154,7 @@ class SSH2
|
|
3957 |
case NET_SSH2_MSG_CHANNEL_EOF:
|
3958 |
break;
|
3959 |
default:
|
3960 |
-
user_error(
|
3961 |
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
|
3962 |
}
|
3963 |
}
|
@@ -3982,11 +4179,27 @@ class SSH2
|
|
3982 |
return false;
|
3983 |
}
|
3984 |
|
3985 |
-
|
3986 |
-
|
3987 |
-
|
3988 |
-
|
3989 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3990 |
|
3991 |
// 4 (packet length) + 1 (padding length) + 4 (minimal padding amount) == 9
|
3992 |
$packet_length = strlen($data) + 9;
|
@@ -4014,10 +4227,10 @@ class SSH2
|
|
4014 |
|
4015 |
if (defined('NET_SSH2_LOGGING')) {
|
4016 |
$current = microtime(true);
|
4017 |
-
$message_number = isset($this->message_numbers[ord($
|
4018 |
$message_number = '-> ' . $message_number .
|
4019 |
' (since last: ' . round($current - $this->last_packet, 4) . ', network: ' . round($stop - $start, 4) . 's)';
|
4020 |
-
$this->_append_log($message_number,
|
4021 |
$this->last_packet = $current;
|
4022 |
}
|
4023 |
|
@@ -4712,10 +4925,12 @@ class SSH2
|
|
4712 |
*/
|
4713 |
function getSupportedCompressionAlgorithms()
|
4714 |
{
|
4715 |
-
|
4716 |
-
|
4717 |
-
|
4718 |
-
|
|
|
|
|
4719 |
}
|
4720 |
|
4721 |
/**
|
@@ -4730,18 +4945,24 @@ class SSH2
|
|
4730 |
{
|
4731 |
$this->_connect();
|
4732 |
|
|
|
|
|
|
|
|
|
|
|
|
|
4733 |
return array(
|
4734 |
'kex' => $this->kex_algorithm,
|
4735 |
'hostkey' => $this->signature_format,
|
4736 |
'client_to_server' => array(
|
4737 |
'crypt' => $this->encrypt->name,
|
4738 |
'mac' => $this->hmac_create->name,
|
4739 |
-
'comp' =>
|
4740 |
),
|
4741 |
'server_to_client' => array(
|
4742 |
'crypt' => $this->decrypt->name,
|
4743 |
'mac' => $this->hmac_check->name,
|
4744 |
-
'comp' =>
|
4745 |
)
|
4746 |
);
|
4747 |
}
|
@@ -5143,4 +5364,31 @@ class SSH2
|
|
5143 |
);
|
5144 |
}
|
5145 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5146 |
}
|
70 |
*/
|
71 |
class SSH2
|
72 |
{
|
73 |
+
/**#@+
|
74 |
+
* Compression Types
|
75 |
+
*
|
76 |
+
* @access private
|
77 |
+
*/
|
78 |
+
/**
|
79 |
+
* No compression
|
80 |
+
*/
|
81 |
+
const NET_SSH2_COMPRESSION_NONE = 1;
|
82 |
+
/**
|
83 |
+
* zlib compression
|
84 |
+
*/
|
85 |
+
const NET_SSH2_COMPRESSION_ZLIB = 2;
|
86 |
+
/**
|
87 |
+
* zlib@openssh.com
|
88 |
+
*/
|
89 |
+
const NET_SSH2_COMPRESSION_ZLIB_AT_OPENSSH = 3;
|
90 |
+
/**#@-*/
|
91 |
+
|
92 |
/**#@+
|
93 |
* Execution Bitmap Masks
|
94 |
*
|
989 |
*/
|
990 |
var $auth = array();
|
991 |
|
992 |
+
/**
|
993 |
+
* The authentication methods that may productively continue authentication.
|
994 |
+
*
|
995 |
+
* @see https://tools.ietf.org/html/rfc4252#section-5.1
|
996 |
+
* @var array|null
|
997 |
+
* @access private
|
998 |
+
*/
|
999 |
+
var $auth_methods_to_continue = null;
|
1000 |
+
|
1001 |
+
/**
|
1002 |
+
* Compression method
|
1003 |
+
*
|
1004 |
+
* @var int
|
1005 |
+
* @access private
|
1006 |
+
*/
|
1007 |
+
var $compress = self::NET_SSH2_COMPRESSION_NONE;
|
1008 |
+
|
1009 |
+
/**
|
1010 |
+
* Decompression method
|
1011 |
+
*
|
1012 |
+
* @var resource|object
|
1013 |
+
* @access private
|
1014 |
+
*/
|
1015 |
+
var $decompress = self::NET_SSH2_COMPRESSION_NONE;
|
1016 |
+
|
1017 |
+
/**
|
1018 |
+
* Compression context
|
1019 |
+
*
|
1020 |
+
* @var int
|
1021 |
+
* @access private
|
1022 |
+
*/
|
1023 |
+
var $compress_context;
|
1024 |
+
|
1025 |
+
/**
|
1026 |
+
* Decompression context
|
1027 |
+
*
|
1028 |
+
* @var resource|object
|
1029 |
+
* @access private
|
1030 |
+
*/
|
1031 |
+
var $decompress_context;
|
1032 |
+
|
1033 |
+
/**
|
1034 |
+
* Regenerate Compression Context
|
1035 |
+
*
|
1036 |
+
* @var bool
|
1037 |
+
* @access private
|
1038 |
+
*/
|
1039 |
+
var $regenerate_compression_context = false;
|
1040 |
+
|
1041 |
+
/**
|
1042 |
+
* Regenerate Decompression Context
|
1043 |
+
*
|
1044 |
+
* @var bool
|
1045 |
+
* @access private
|
1046 |
+
*/
|
1047 |
+
var $regenerate_decompression_context = false;
|
1048 |
+
|
1049 |
+
/**
|
1050 |
+
* Smart multi-factor authentication flag
|
1051 |
+
*
|
1052 |
+
* @var bool
|
1053 |
+
* @access private
|
1054 |
+
*/
|
1055 |
+
var $smartMFA = true;
|
1056 |
+
|
1057 |
/**
|
1058 |
* Default Constructor.
|
1059 |
*
|
1294 |
$read = array($this->fsock);
|
1295 |
$write = $except = null;
|
1296 |
$start = microtime(true);
|
1297 |
+
$sec = (int) floor($this->curTimeout);
|
1298 |
+
$usec = (int) (1000000 * ($this->curTimeout - $sec));
|
1299 |
// on windows this returns a "Warning: Invalid CRT parameters detected" error
|
1300 |
// the !count() is done as a workaround for <https://bugs.php.net/42682>
|
1301 |
if (!@stream_select($read, $write, $except, $sec, $usec) && !count($read)) {
|
1310 |
if (strlen($temp) == 255) {
|
1311 |
continue;
|
1312 |
}
|
1313 |
+
|
1314 |
if ($temp === false) {
|
1315 |
return false;
|
1316 |
}
|
1432 |
function _key_exchange($kexinit_payload_server = false)
|
1433 |
{
|
1434 |
$preferred = $this->preferred;
|
1435 |
+
$send_kex = true;
|
1436 |
|
1437 |
$kex_algorithms = isset($preferred['kex']) ?
|
1438 |
$preferred['kex'] :
|
1516 |
0
|
1517 |
);
|
1518 |
|
1519 |
+
if ($kexinit_payload_server === false) {
|
1520 |
if (!$this->_send_binary_packet($kexinit_payload_client)) {
|
1521 |
return false;
|
1522 |
}
|
1532 |
user_error('Expected SSH_MSG_KEXINIT');
|
1533 |
return false;
|
1534 |
}
|
1535 |
+
|
1536 |
+
$send_kex = false;
|
1537 |
}
|
1538 |
|
1539 |
$response = $kexinit_payload_server;
|
1606 |
extract(unpack('Cfirst_kex_packet_follows', $this->_string_shift($response, 1)));
|
1607 |
$first_kex_packet_follows = $first_kex_packet_follows != 0;
|
1608 |
|
1609 |
+
if ($send_kex && !$this->_send_binary_packet($kexinit_payload_client)) {
|
1610 |
return false;
|
1611 |
}
|
1612 |
|
1646 |
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
1647 |
}
|
1648 |
|
1649 |
+
$compression_map = array(
|
1650 |
+
'none' => self::NET_SSH2_COMPRESSION_NONE,
|
1651 |
+
'zlib' => self::NET_SSH2_COMPRESSION_ZLIB,
|
1652 |
+
'zlib@openssh.com' => self::NET_SSH2_COMPRESSION_ZLIB_AT_OPENSSH
|
1653 |
+
);
|
1654 |
+
|
1655 |
$compression_algorithm_out = $this->_array_intersect_first($c2s_compression_algorithms, $this->compression_algorithms_client_to_server);
|
1656 |
if ($compression_algorithm_out === false) {
|
1657 |
user_error('No compatible client to server compression algorithms found');
|
1658 |
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
1659 |
}
|
1660 |
+
$this->compress = $compression_map[$compression_algorithm_out];
|
1661 |
|
1662 |
+
$compression_algorithm_in = $this->_array_intersect_first($s2c_compression_algorithms, $this->compression_algorithms_server_to_client);
|
1663 |
if ($compression_algorithm_in === false) {
|
1664 |
user_error('No compatible server to client compression algorithms found');
|
1665 |
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
1666 |
}
|
1667 |
+
$this->decompress = $compression_map[$compression_algorithm_in];
|
1668 |
|
1669 |
// Only relevant in diffie-hellman-group-exchange-sha{1,256}, otherwise empty.
|
1670 |
$exchange_hash_rfc4419 = '';
|
2097 |
}
|
2098 |
$this->hmac_check->setKey(substr($key, 0, $checkKeyLength));
|
2099 |
|
2100 |
+
$this->regenerate_compression_context = $this->regenerate_decompression_context = true;
|
2101 |
+
|
2102 |
return true;
|
2103 |
}
|
2104 |
|
2227 |
|
2228 |
// try logging with 'none' as an authentication method first since that's what
|
2229 |
// PuTTY does
|
2230 |
+
if (substr($this->server_identifier, 0, 15) != 'SSH-2.0-CoreFTP' && $this->auth_methods_to_continue === null) {
|
2231 |
if ($this->_login($username)) {
|
2232 |
return true;
|
2233 |
}
|
2259 |
return $this->_login_helper($username);
|
2260 |
}
|
2261 |
|
2262 |
+
while (count($args)) {
|
2263 |
+
if (!$this->auth_methods_to_continue || !$this->smartMFA) {
|
2264 |
+
$newargs = $args;
|
2265 |
+
$args = array();
|
2266 |
+
} else {
|
2267 |
+
$newargs = array();
|
2268 |
+
foreach ($this->auth_methods_to_continue as $method) {
|
2269 |
+
switch ($method) {
|
2270 |
+
case 'publickey':
|
2271 |
+
foreach ($args as $key => $arg) {
|
2272 |
+
if (is_object($arg)) {
|
2273 |
+
$newargs[] = $arg;
|
2274 |
+
unset($args[$key]);
|
2275 |
+
break;
|
2276 |
+
}
|
2277 |
+
}
|
2278 |
+
break;
|
2279 |
+
case 'keyboard-interactive':
|
2280 |
+
$hasArray = $hasString = false;
|
2281 |
+
foreach ($args as $arg) {
|
2282 |
+
if ($hasArray || is_array($arg)) {
|
2283 |
+
$hasArray = true;
|
2284 |
+
break;
|
2285 |
+
}
|
2286 |
+
if ($hasString || is_string($arg)) {
|
2287 |
+
$hasString = true;
|
2288 |
+
break;
|
2289 |
+
}
|
2290 |
+
}
|
2291 |
+
if ($hasArray && $hasString) {
|
2292 |
+
foreach ($args as $key => $arg) {
|
2293 |
+
if (is_array($arg)) {
|
2294 |
+
$newargs[] = $arg;
|
2295 |
+
break 2;
|
2296 |
+
}
|
2297 |
+
}
|
2298 |
+
}
|
2299 |
+
case 'password':
|
2300 |
+
foreach ($args as $key => $arg) {
|
2301 |
+
$newargs[] = $arg;
|
2302 |
+
unset($args[$key]);
|
2303 |
+
break;
|
2304 |
+
}
|
2305 |
+
}
|
2306 |
+
}
|
2307 |
+
}
|
2308 |
+
|
2309 |
+
if (!count($newargs)) {
|
2310 |
+
return false;
|
2311 |
+
}
|
2312 |
+
|
2313 |
+
foreach ($newargs as $arg) {
|
2314 |
+
if ($this->_login_helper($username, $arg)) {
|
2315 |
+
return true;
|
2316 |
+
}
|
2317 |
}
|
2318 |
}
|
2319 |
return false;
|
2423 |
case NET_SSH2_MSG_USERAUTH_SUCCESS:
|
2424 |
$this->bitmap |= self::MASK_LOGIN;
|
2425 |
return true;
|
2426 |
+
case NET_SSH2_MSG_USERAUTH_FAILURE:
|
2427 |
+
extract(unpack('Nmethodlistlen', $this->_string_shift($response, 4)));
|
2428 |
+
$this->auth_methods_to_continue = explode(',', $this->_string_shift($response, $methodlistlen));
|
2429 |
default:
|
2430 |
return false;
|
2431 |
}
|
2497 |
}
|
2498 |
extract(unpack('Nlength', $this->_string_shift($response, 4)));
|
2499 |
$auth_methods = explode(',', $this->_string_shift($response, $length));
|
2500 |
+
$this->auth_methods_to_continue = $auth_methods;
|
2501 |
if (!strlen($response)) {
|
2502 |
return false;
|
2503 |
}
|
2670 |
case NET_SSH2_MSG_USERAUTH_SUCCESS:
|
2671 |
return true;
|
2672 |
case NET_SSH2_MSG_USERAUTH_FAILURE:
|
2673 |
+
extract(unpack('Nmethodlistlen', $this->_string_shift($response, 4)));
|
2674 |
+
$this->auth_methods_to_continue = explode(',', $this->_string_shift($response, $methodlistlen));
|
2675 |
return false;
|
2676 |
}
|
2677 |
|
2780 |
if (strlen($response) < 4) {
|
2781 |
return false;
|
2782 |
}
|
2783 |
+
extract(unpack('Nmethodlistlen', $this->_string_shift($response, 4)));
|
2784 |
+
$this->auth_methods_to_continue = explode(',', $this->_string_shift($response, $methodlistlen));
|
2785 |
+
$this->errors[] = 'SSH_MSG_USERAUTH_FAILURE';
|
2786 |
return false;
|
2787 |
case NET_SSH2_MSG_USERAUTH_PK_OK:
|
2788 |
// we'll just take it on faith that the public key blob and the public key algorithm name are as
|
2823 |
switch ($type) {
|
2824 |
case NET_SSH2_MSG_USERAUTH_FAILURE:
|
2825 |
// either the login is bad or the server employs multi-factor authentication
|
2826 |
+
extract(unpack('Nmethodlistlen', $this->_string_shift($response, 4)));
|
2827 |
+
$this->auth_methods_to_continue = explode(',', $this->_string_shift($response, $methodlistlen));
|
2828 |
return false;
|
2829 |
case NET_SSH2_MSG_USERAUTH_SUCCESS:
|
2830 |
$this->bitmap |= self::MASK_LOGIN;
|
2951 |
return false;
|
2952 |
}
|
2953 |
|
2954 |
+
$this->channel_status[self::CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_REQUEST;
|
2955 |
+
if (!$this->_get_channel_packet(self::CHANNEL_EXEC)) {
|
2956 |
+
user_error('Unable to request pseudo-terminal');
|
2957 |
+
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
|
|
|
|
|
|
|
|
|
|
|
2958 |
}
|
|
|
2959 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2960 |
$this->in_request_pty_exec = true;
|
2961 |
}
|
2962 |
|
3077 |
return false;
|
3078 |
}
|
3079 |
|
3080 |
+
$this->channel_status[self::CHANNEL_SHELL] = NET_SSH2_MSG_CHANNEL_REQUEST;
|
3081 |
+
|
3082 |
+
if (!$this->_get_channel_packet(self::CHANNEL_SHELL)) {
|
3083 |
+
user_error('Unable to request pseudo-terminal');
|
3084 |
+
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
|
3085 |
+
}
|
3086 |
+
|
3087 |
$packet = pack(
|
3088 |
'CNNa*C',
|
3089 |
NET_SSH2_MSG_CHANNEL_REQUEST,
|
3096 |
return false;
|
3097 |
}
|
3098 |
|
3099 |
+
$response = $this->_get_channel_packet(self::CHANNEL_SHELL);
|
3100 |
+
if ($response === false) {
|
3101 |
+
return false;
|
3102 |
+
}
|
3103 |
+
|
3104 |
+
$this->channel_status[self::CHANNEL_SHELL] = NET_SSH2_MSG_CHANNEL_DATA;
|
3105 |
|
3106 |
$this->bitmap |= self::MASK_SHELL;
|
3107 |
|
3473 |
$read = array($this->fsock);
|
3474 |
$write = $except = null;
|
3475 |
|
3476 |
+
if (!$this->curTimeout) {
|
3477 |
if ($this->keepAlive <= 0) {
|
3478 |
@stream_select($read, $write, $except, null);
|
3479 |
} else {
|
3504 |
$this->curTimeout-= $elapsed;
|
3505 |
}
|
3506 |
|
3507 |
+
$sec = (int)floor($this->curTimeout);
|
3508 |
+
$usec = (int)(1000000 * ($this->curTimeout - $sec));
|
3509 |
|
3510 |
// on windows this returns a "Warning: Invalid CRT parameters detected" error
|
3511 |
if (!@stream_select($read, $write, $except, $sec, $usec) && !count($read)) {
|
3519 |
|
3520 |
if (!is_resource($this->fsock) || feof($this->fsock)) {
|
3521 |
$this->bitmap = 0;
|
3522 |
+
user_error('Connection closed (by server) prematurely ' . $elapsed . 's');
|
3523 |
return false;
|
3524 |
}
|
3525 |
|
3527 |
$raw = stream_get_contents($this->fsock, $this->decrypt_block_size);
|
3528 |
|
3529 |
if (!strlen($raw)) {
|
3530 |
+
user_error('No data received from server');
|
3531 |
+
return false;
|
3532 |
}
|
3533 |
|
3534 |
if ($this->decrypt !== false) {
|
3591 |
}
|
3592 |
}
|
3593 |
|
3594 |
+
switch ($this->decompress) {
|
3595 |
+
case self::NET_SSH2_COMPRESSION_ZLIB_AT_OPENSSH:
|
3596 |
+
if (!$this->isAuthenticated()) {
|
3597 |
+
break;
|
3598 |
+
}
|
3599 |
+
case self::NET_SSH2_COMPRESSION_ZLIB:
|
3600 |
+
if ($this->regenerate_decompression_context) {
|
3601 |
+
$this->regenerate_decompression_context = false;
|
3602 |
+
|
3603 |
+
$cmf = ord($payload[0]);
|
3604 |
+
$cm = $cmf & 0x0F;
|
3605 |
+
if ($cm != 8) { // deflate
|
3606 |
+
user_error("Only CM = 8 ('deflate') is supported ($cm)");
|
3607 |
+
}
|
3608 |
+
$cinfo = ($cmf & 0xF0) >> 4;
|
3609 |
+
if ($cinfo > 7) {
|
3610 |
+
user_error("CINFO above 7 is not allowed ($cinfo)");
|
3611 |
+
}
|
3612 |
+
$windowSize = 1 << ($cinfo + 8);
|
3613 |
+
|
3614 |
+
$flg = ord($payload[1]);
|
3615 |
+
//$fcheck = $flg && 0x0F;
|
3616 |
+
if ((($cmf << 8) | $flg) % 31) {
|
3617 |
+
user_error('fcheck failed');
|
3618 |
+
}
|
3619 |
+
$fdict = boolval($flg & 0x20);
|
3620 |
+
$flevel = ($flg & 0xC0) >> 6;
|
3621 |
+
|
3622 |
+
$this->decompress_context = inflate_init(ZLIB_ENCODING_RAW, array('window' => $cinfo + 8));
|
3623 |
+
$payload = substr($payload, 2);
|
3624 |
+
}
|
3625 |
+
if ($this->decompress_context) {
|
3626 |
+
$payload = inflate_add($this->decompress_context, $payload, ZLIB_PARTIAL_FLUSH);
|
3627 |
+
}
|
3628 |
+
}
|
3629 |
|
3630 |
$this->get_seq_no++;
|
3631 |
|
3700 |
|
3701 |
// only called when we've already logged in
|
3702 |
if (($this->bitmap & self::MASK_CONNECTED) && $this->isAuthenticated()) {
|
3703 |
+
if (is_bool($payload)) {
|
3704 |
+
return $payload;
|
3705 |
+
}
|
3706 |
+
|
3707 |
switch (ord($payload[0])) {
|
3708 |
case NET_SSH2_MSG_CHANNEL_REQUEST:
|
3709 |
if (strlen($payload) == 31) {
|
3905 |
function _get_channel_packet($client_channel, $skip_extended = false)
|
3906 |
{
|
3907 |
if (!empty($this->channel_buffers[$client_channel])) {
|
3908 |
+
switch ($this->channel_status[$client_channel]) {
|
3909 |
+
case NET_SSH2_MSG_CHANNEL_REQUEST:
|
3910 |
+
foreach ($this->channel_buffers[$client_channel] as $i => $packet) {
|
3911 |
+
switch (ord($packet[0])) {
|
3912 |
+
case NET_SSH2_MSG_CHANNEL_SUCCESS:
|
3913 |
+
case NET_SSH2_MSG_CHANNEL_FAILURE:
|
3914 |
+
unset($this->channel_buffers[$client_channel][$i]);
|
3915 |
+
return substr($packet, 1);
|
3916 |
+
}
|
3917 |
+
}
|
3918 |
+
break;
|
3919 |
+
default:
|
3920 |
+
return substr(array_shift($this->channel_buffers[$client_channel]), 1);
|
3921 |
+
}
|
3922 |
}
|
3923 |
|
3924 |
while (true) {
|
3992 |
if ($client_channel == $channel && $this->channel_status[$channel] == NET_SSH2_MSG_CHANNEL_DATA) {
|
3993 |
return $data;
|
3994 |
}
|
3995 |
+
$this->channel_buffers[$channel][] = chr($type) . $data;
|
|
|
|
|
|
|
3996 |
|
3997 |
continue 2;
|
3998 |
case NET_SSH2_MSG_CHANNEL_REQUEST:
|
4071 |
$result = $client_channel == $channel ? true : $this->_get_channel_packet($client_channel, $skip_extended);
|
4072 |
$this->_on_channel_open();
|
4073 |
return $result;
|
4074 |
+
case NET_SSH2_MSG_CHANNEL_OPEN_FAILURE:
|
|
|
4075 |
user_error('Unable to open channel');
|
4076 |
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
|
4077 |
+
default:
|
4078 |
+
if ($client_channel == $channel) {
|
4079 |
+
user_error('Unexpected response to open request');
|
4080 |
+
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
|
4081 |
+
}
|
4082 |
+
return $this->_get_channel_packet($client_channel, $skip_extended);
|
|
|
|
|
|
|
|
|
4083 |
}
|
4084 |
break;
|
4085 |
case NET_SSH2_MSG_CHANNEL_REQUEST:
|
4088 |
return true;
|
4089 |
case NET_SSH2_MSG_CHANNEL_FAILURE:
|
4090 |
return false;
|
4091 |
+
case NET_SSH2_MSG_CHANNEL_DATA:
|
4092 |
+
if (strlen($response) < 4) {
|
4093 |
+
return false;
|
4094 |
+
}
|
4095 |
+
extract(unpack('Nlength', $this->_string_shift($response, 4)));
|
4096 |
+
$data = $this->_string_shift($response, $length);
|
4097 |
+
$this->channel_buffers[$channel][] = chr($type) . $data;
|
4098 |
+
return $this->_get_channel_packet($client_channel, $skip_extended);
|
4099 |
default:
|
4100 |
user_error('Unable to fulfill channel request');
|
4101 |
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
|
4109 |
|
4110 |
switch ($type) {
|
4111 |
case NET_SSH2_MSG_CHANNEL_DATA:
|
|
|
|
|
|
|
|
|
4112 |
/*
|
4113 |
if ($channel == self::CHANNEL_EXEC) {
|
4114 |
// SCP requires null packets, such as this, be sent. further, in the case of the ssh.com SSH server
|
4135 |
if ($client_channel == $channel) {
|
4136 |
return $data;
|
4137 |
}
|
4138 |
+
$this->channel_buffers[$channel][] = chr($type) . $data;
|
|
|
|
|
|
|
4139 |
break;
|
4140 |
case NET_SSH2_MSG_CHANNEL_CLOSE:
|
4141 |
$this->curTimeout = 5;
|
4154 |
case NET_SSH2_MSG_CHANNEL_EOF:
|
4155 |
break;
|
4156 |
default:
|
4157 |
+
user_error("Error reading channel data ($type)");
|
4158 |
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
|
4159 |
}
|
4160 |
}
|
4179 |
return false;
|
4180 |
}
|
4181 |
|
4182 |
+
if (!isset($logged)) {
|
4183 |
+
$logged = $data;
|
4184 |
+
}
|
4185 |
+
|
4186 |
+
switch ($this->compress) {
|
4187 |
+
case self::NET_SSH2_COMPRESSION_ZLIB_AT_OPENSSH:
|
4188 |
+
if (!$this->isAuthenticated()) {
|
4189 |
+
break;
|
4190 |
+
}
|
4191 |
+
case self::NET_SSH2_COMPRESSION_ZLIB:
|
4192 |
+
if (!$this->regenerate_compression_context) {
|
4193 |
+
$header = '';
|
4194 |
+
} else {
|
4195 |
+
$this->regenerate_compression_context = false;
|
4196 |
+
$this->compress_context = deflate_init(ZLIB_ENCODING_RAW, array('window' => 15));
|
4197 |
+
$header = "\x78\x9C";
|
4198 |
+
}
|
4199 |
+
if ($this->compress_context) {
|
4200 |
+
$data = $header . deflate_add($this->compress_context, $data, ZLIB_PARTIAL_FLUSH);
|
4201 |
+
}
|
4202 |
+
}
|
4203 |
|
4204 |
// 4 (packet length) + 1 (padding length) + 4 (minimal padding amount) == 9
|
4205 |
$packet_length = strlen($data) + 9;
|
4227 |
|
4228 |
if (defined('NET_SSH2_LOGGING')) {
|
4229 |
$current = microtime(true);
|
4230 |
+
$message_number = isset($this->message_numbers[ord($logged[0])]) ? $this->message_numbers[ord($logged[0])] : 'UNKNOWN (' . ord($logged[0]) . ')';
|
4231 |
$message_number = '-> ' . $message_number .
|
4232 |
' (since last: ' . round($current - $this->last_packet, 4) . ', network: ' . round($stop - $start, 4) . 's)';
|
4233 |
+
$this->_append_log($message_number, $logged);
|
4234 |
$this->last_packet = $current;
|
4235 |
}
|
4236 |
|
4925 |
*/
|
4926 |
function getSupportedCompressionAlgorithms()
|
4927 |
{
|
4928 |
+
$algos = array('none'); // REQUIRED no compression
|
4929 |
+
if (function_exists('deflate_init')) {
|
4930 |
+
$algos[] = 'zlib@openssh.com'; // https://datatracker.ietf.org/doc/html/draft-miller-secsh-compression-delayed
|
4931 |
+
$algos[] = 'zlib';
|
4932 |
+
}
|
4933 |
+
return $algos;
|
4934 |
}
|
4935 |
|
4936 |
/**
|
4945 |
{
|
4946 |
$this->_connect();
|
4947 |
|
4948 |
+
$compression_map = array(
|
4949 |
+
self::NET_SSH2_COMPRESSION_NONE => 'none',
|
4950 |
+
self::NET_SSH2_COMPRESSION_ZLIB => 'zlib',
|
4951 |
+
self::NET_SSH2_COMPRESSION_ZLIB_AT_OPENSSH => 'zlib@openssh.com'
|
4952 |
+
);
|
4953 |
+
|
4954 |
return array(
|
4955 |
'kex' => $this->kex_algorithm,
|
4956 |
'hostkey' => $this->signature_format,
|
4957 |
'client_to_server' => array(
|
4958 |
'crypt' => $this->encrypt->name,
|
4959 |
'mac' => $this->hmac_create->name,
|
4960 |
+
'comp' => $compression_map[$this->compress],
|
4961 |
),
|
4962 |
'server_to_client' => array(
|
4963 |
'crypt' => $this->decrypt->name,
|
4964 |
'mac' => $this->hmac_check->name,
|
4965 |
+
'comp' => $compression_map[$this->decompress],
|
4966 |
)
|
4967 |
);
|
4968 |
}
|
5364 |
);
|
5365 |
}
|
5366 |
}
|
5367 |
+
|
5368 |
+
/**
|
5369 |
+
* Return the list of authentication methods that may productively continue authentication.
|
5370 |
+
*
|
5371 |
+
* @see https://tools.ietf.org/html/rfc4252#section-5.1
|
5372 |
+
* @return array|null
|
5373 |
+
*/
|
5374 |
+
function getAuthMethodsToContinue()
|
5375 |
+
{
|
5376 |
+
return $this->auth_methods_to_continue;
|
5377 |
+
}
|
5378 |
+
|
5379 |
+
/**
|
5380 |
+
* Enables "smart" multi-factor authentication (MFA)
|
5381 |
+
*/
|
5382 |
+
function enableSmartMFA()
|
5383 |
+
{
|
5384 |
+
$this->smartMFA = true;
|
5385 |
+
}
|
5386 |
+
|
5387 |
+
/**
|
5388 |
+
* Disables "smart" multi-factor authentication (MFA)
|
5389 |
+
*/
|
5390 |
+
function disableSmartMFA()
|
5391 |
+
{
|
5392 |
+
$this->smartMFA = false;
|
5393 |
+
}
|
5394 |
}
|
vendor/phpseclib/phpseclib/phpseclib/bootstrap.php
CHANGED
@@ -7,7 +7,8 @@
|
|
7 |
|
8 |
if (extension_loaded('mbstring')) {
|
9 |
// 2 - MB_OVERLOAD_STRING
|
10 |
-
|
|
|
11 |
throw new \UnexpectedValueException(
|
12 |
'Overloading of string functions using mbstring.func_overload ' .
|
13 |
'is not supported by phpseclib.'
|
7 |
|
8 |
if (extension_loaded('mbstring')) {
|
9 |
// 2 - MB_OVERLOAD_STRING
|
10 |
+
// mbstring.func_overload is deprecated in php 7.2 and removed in php 8.0.
|
11 |
+
if (version_compare(PHP_VERSION, '8.0.0') < 0 && ini_get('mbstring.func_overload') & 2) {
|
12 |
throw new \UnexpectedValueException(
|
13 |
'Overloading of string functions using mbstring.func_overload ' .
|
14 |
'is not supported by phpseclib.'
|