Version Description
- remote storage password encryption addon for database
- vendor cleanup packages
- database silent fail fix
- copyright changes
- jstree fix database display
- microtime float div fix
- manage backups data order fix
Download this release
Release Info
Developer | xcloner |
Plugin | XCloner – Backup and Restore |
Version | 4.0.9 |
Comparing to | |
See all releases |
Code changes from version 4.0.8 to 4.0.9
- README.txt +10 -1
- admin/class-xcloner-admin.php +164 -163
- admin/css/xcloner-admin.css +184 -184
- admin/js/xcloner-admin.js +100 -107
- admin/js/xcloner-backup-class.js +403 -440
- admin/js/xcloner-manage-backups-class.js +1 -1
- admin/partials/xcloner_console_page.php +31 -28
- admin/partials/xcloner_generate_backups_page.php +552 -504
- admin/partials/xcloner_init_page.php +240 -209
- admin/partials/xcloner_manage_backups_page.php +240 -201
- admin/partials/xcloner_remote_storage_page.php +1027 -847
- admin/partials/xcloner_restore_page.php +451 -383
- admin/partials/xcloner_scheduled_backups_page.php +185 -167
- composer.json +2 -1
- composer.lock +102 -37
- includes/class-xcloner-activator.php +105 -66
- includes/class-xcloner-api.php +1117 -1055
- includes/class-xcloner-archive.php +738 -624
- includes/class-xcloner-deactivator.php +31 -15
- includes/class-xcloner-file-system.php +1060 -980
- includes/class-xcloner-file-transfer.php +157 -95
- includes/class-xcloner-i18n.php +40 -26
- includes/class-xcloner-loader.php +176 -134
- includes/class-xcloner-logger.php +71 -82
- includes/class-xcloner-remote-storage.php +624 -570
- includes/class-xcloner-requirements.php +110 -113
- includes/class-xcloner-sanitization.php +40 -45
- includes/class-xcloner-scheduler.php +276 -300
- includes/class-xcloner-settings.php +740 -628
- includes/class-xcloner.php +137 -121
- public/class-xcloner-public.php +7 -6
- vendor/composer/ClassLoader.php +8 -4
- vendor/composer/LICENSE +1 -1
- vendor/composer/autoload_files.php +4 -3
- vendor/composer/autoload_psr4.php +1 -1
- vendor/composer/autoload_static.php +8 -7
- vendor/composer/installed.json +854 -787
- vendor/defuse/php-encryption/.gitignore +11 -0
- vendor/defuse/php-encryption/.php_cs +60 -0
- vendor/defuse/php-encryption/LICENSE +21 -0
- vendor/defuse/php-encryption/README.md +102 -0
- vendor/defuse/php-encryption/bin/generate-defuse-key +14 -0
- vendor/defuse/php-encryption/composer.json +35 -0
- vendor/defuse/php-encryption/dist/Makefile +37 -0
- vendor/defuse/php-encryption/dist/box.json +25 -0
- vendor/defuse/php-encryption/dist/signingkey.asc +52 -0
- vendor/defuse/php-encryption/docs/CryptoDetails.md +64 -0
- vendor/defuse/php-encryption/docs/FAQ.md +51 -0
- vendor/defuse/php-encryption/docs/InstallingAndVerifying.md +53 -0
- vendor/defuse/php-encryption/docs/InternalDeveloperDocs.md +166 -0
- vendor/defuse/php-encryption/docs/Tutorial.md +314 -0
- vendor/defuse/php-encryption/docs/UpgradingFromV1.2.md +51 -0
- vendor/defuse/php-encryption/docs/classes/Crypto.md +280 -0
- vendor/defuse/php-encryption/docs/classes/File.md +486 -0
- vendor/defuse/php-encryption/docs/classes/Key.md +117 -0
- vendor/defuse/php-encryption/docs/classes/KeyProtectedByPassword.md +259 -0
- vendor/defuse/php-encryption/psalm.xml +12 -0
- vendor/defuse/php-encryption/src/Core.php +448 -0
- vendor/defuse/php-encryption/src/Crypto.php +445 -0
- vendor/defuse/php-encryption/src/DerivedKeys.php +50 -0
- vendor/defuse/php-encryption/src/Encoding.php +268 -0
- vendor/defuse/php-encryption/src/Exception/BadFormatException.php +7 -0
- vendor/defuse/php-encryption/src/Exception/CryptoException.php +7 -0
- vendor/defuse/php-encryption/src/Exception/EnvironmentIsBrokenException.php +7 -0
- vendor/defuse/php-encryption/src/Exception/IOException.php +7 -0
- vendor/defuse/php-encryption/src/Exception/WrongKeyOrModifiedCiphertextException.php +7 -0
- vendor/defuse/php-encryption/src/File.php +762 -0
- vendor/defuse/php-encryption/src/Key.php +94 -0
- vendor/defuse/php-encryption/src/KeyOrPassword.php +149 -0
- vendor/defuse/php-encryption/src/KeyProtectedByPassword.php +145 -0
- vendor/defuse/php-encryption/src/RuntimeTests.php +228 -0
- vendor/gliterd/backblaze-b2/CHANGELOG.md +22 -0
- vendor/gliterd/backblaze-b2/CONDUCT.md +74 -0
- vendor/gliterd/backblaze-b2/CONTRIBUTING.md +32 -0
- vendor/gliterd/backblaze-b2/LICENSE +21 -0
- vendor/gliterd/backblaze-b2/README.md +141 -0
- vendor/gliterd/backblaze-b2/composer.json +42 -0
- vendor/gliterd/backblaze-b2/phpunit.hhvm.xml +24 -0
- vendor/gliterd/backblaze-b2/phpunit.php +3 -0
- vendor/gliterd/backblaze-b2/phpunit.xml +29 -0
- vendor/gliterd/backblaze-b2/src/Bucket.php +42 -0
- vendor/gliterd/backblaze-b2/src/Client.php +479 -0
- vendor/gliterd/backblaze-b2/src/ErrorHandler.php +38 -0
- vendor/gliterd/backblaze-b2/src/Exceptions/B2Exception.php +7 -0
- vendor/gliterd/backblaze-b2/src/Exceptions/BadJsonException.php +7 -0
- vendor/gliterd/backblaze-b2/src/Exceptions/BadValueException.php +7 -0
- vendor/gliterd/backblaze-b2/src/Exceptions/BucketAlreadyExistsException.php +7 -0
- vendor/gliterd/backblaze-b2/src/Exceptions/BucketNotEmptyException.php +7 -0
- vendor/gliterd/backblaze-b2/src/Exceptions/FileNotPresentException.php +7 -0
- vendor/gliterd/backblaze-b2/src/Exceptions/NotFoundException.php +7 -0
- vendor/gliterd/backblaze-b2/src/Exceptions/ValidationException.php +7 -0
- vendor/gliterd/backblaze-b2/src/File.php +114 -0
- vendor/gliterd/backblaze-b2/src/Http/Client.php +37 -0
- vendor/gliterd/backblaze-b2/tests/ClientTest.php +113 -0
README.txt
CHANGED
@@ -3,7 +3,7 @@ Contributors: xcloner
|
|
3 |
Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=AAPE8PLAE554S
|
4 |
Tags: backup plugin, restore plugin, database backup, duplicate, full site backup, website cloner, wordpress backup, database restore, webdav, azure, ftp, sftp, amazon s3, dropbox, google drive, differential backup
|
5 |
Requires at least: 3.0.1
|
6 |
-
Tested up to:
|
7 |
Stable tag: 4.0.8
|
8 |
|
9 |
Backup your site, restore to any web location, send your backups to Dropbox, Amazon S3, Azure, FTP, SFTP, WebDAV, Google Drive with XCloner plugin.
|
@@ -112,6 +112,15 @@ Immigration Attorney Montana <a href="https://www.immigrationlawofmt.com" target
|
|
112 |
|
113 |
== Changelog ==
|
114 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
115 |
= 4.0.8 =
|
116 |
* updated vendor library dependencies, AWS, phpseclib
|
117 |
* TAR compression fix
|
3 |
Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=AAPE8PLAE554S
|
4 |
Tags: backup plugin, restore plugin, database backup, duplicate, full site backup, website cloner, wordpress backup, database restore, webdav, azure, ftp, sftp, amazon s3, dropbox, google drive, differential backup
|
5 |
Requires at least: 3.0.1
|
6 |
+
Tested up to: 5.0
|
7 |
Stable tag: 4.0.8
|
8 |
|
9 |
Backup your site, restore to any web location, send your backups to Dropbox, Amazon S3, Azure, FTP, SFTP, WebDAV, Google Drive with XCloner plugin.
|
112 |
|
113 |
== Changelog ==
|
114 |
|
115 |
+
= 4.0.9 =
|
116 |
+
* remote storage password encryption addon for database
|
117 |
+
* vendor cleanup packages
|
118 |
+
* database silent fail fix
|
119 |
+
* copyright changes
|
120 |
+
* jstree fix database display
|
121 |
+
* microtime float div fix
|
122 |
+
* manage backups data order fix
|
123 |
+
|
124 |
= 4.0.8 =
|
125 |
* updated vendor library dependencies, AWS, phpseclib
|
126 |
* TAR compression fix
|
admin/class-xcloner-admin.php
CHANGED
@@ -27,7 +27,7 @@ class Xcloner_Admin {
|
|
27 |
*
|
28 |
* @since 1.0.0
|
29 |
* @access private
|
30 |
-
* @var string
|
31 |
*/
|
32 |
private $plugin_name;
|
33 |
|
@@ -36,27 +36,28 @@ class Xcloner_Admin {
|
|
36 |
*
|
37 |
* @since 1.0.0
|
38 |
* @access private
|
39 |
-
* @var string
|
40 |
*/
|
41 |
private $version;
|
42 |
-
|
43 |
private $xcloner_container;
|
|
|
44 |
/**
|
45 |
* Initialize the class and set its properties.
|
46 |
*
|
47 |
* @since 1.0.0
|
48 |
-
*
|
49 |
-
* @param string
|
|
|
50 |
*/
|
51 |
-
public function __construct( Xcloner $xcloner_container) {
|
52 |
|
53 |
-
$this->plugin_name
|
54 |
-
$this->version
|
55 |
-
$this->xcloner_container
|
56 |
}
|
57 |
-
|
58 |
-
public function get_xcloner_container()
|
59 |
-
{
|
60 |
return $this->xcloner_container;
|
61 |
}
|
62 |
|
@@ -65,10 +66,11 @@ class Xcloner_Admin {
|
|
65 |
*
|
66 |
* @since 1.0.0
|
67 |
*/
|
68 |
-
public function enqueue_styles($hook) {
|
69 |
-
|
70 |
-
if(!stristr($hook, "page_"
|
71 |
return;
|
|
|
72 |
|
73 |
/**
|
74 |
* This function is provided for demonstration purposes only.
|
@@ -82,12 +84,12 @@ class Xcloner_Admin {
|
|
82 |
* class.
|
83 |
*/
|
84 |
|
85 |
-
wp_enqueue_style( $this->plugin_name."_materialize", plugin_dir_url( __FILE__ ) . 'css/materialize.min.css', array(), $this->version, 'all' );
|
86 |
-
wp_enqueue_style( $this->plugin_name."_materialize.clockpicker", plugin_dir_url( __FILE__ ) . 'css/materialize.clockpicker.css', array(), $this->version, 'all' );
|
87 |
-
wp_enqueue_style( $this->plugin_name."_materialize.icons", '//fonts.googleapis.com/icon?family=Material+Icons', array(), $this->version, 'all' );
|
88 |
-
wp_enqueue_style( $this->plugin_name."_jquery.datatables", plugin_dir_url( __FILE__ ) . 'css/jquery.dataTables.min.css', array(), $this->version, 'all' );
|
89 |
-
wp_enqueue_style( $this->plugin_name."_jquery.datatables.responsive", plugin_dir_url( __FILE__ ) . 'css/responsive.dataTables.css', array(), $this->version, 'all' );
|
90 |
-
wp_enqueue_style( $this->plugin_name."_jstree", dirname(plugin_dir_url( __FILE__ )) . '/vendor/vakata/jstree/dist/themes/default/style.min.css', array(), '3.3', 'all' );
|
91 |
wp_enqueue_style( $this->plugin_name, plugin_dir_url( __FILE__ ) . 'css/xcloner-admin.css', array(), $this->version, 'all' );
|
92 |
|
93 |
}
|
@@ -97,11 +99,12 @@ class Xcloner_Admin {
|
|
97 |
*
|
98 |
* @since 1.0.0
|
99 |
*/
|
100 |
-
public function enqueue_scripts($hook) {
|
101 |
|
102 |
-
if(!stristr($hook, "page_"
|
103 |
return;
|
104 |
-
|
|
|
105 |
/**
|
106 |
* This function is provided for demonstration purposes only.
|
107 |
*
|
@@ -113,177 +116,175 @@ class Xcloner_Admin {
|
|
113 |
* between the defined hooks and the functions defined in this
|
114 |
* class.
|
115 |
*/
|
116 |
-
|
117 |
add_thickbox();
|
118 |
-
wp_enqueue_script('plugin-install');
|
119 |
-
wp_enqueue_script('updates');
|
120 |
-
wp_enqueue_script( $this->plugin_name."_materialize", plugin_dir_url( __FILE__ ) . 'js/materialize.min.js', array( 'jquery' ), $this->version, false );
|
121 |
-
wp_enqueue_script( $this->plugin_name."_materialize.clockpicker", plugin_dir_url( __FILE__ ) . 'js/materialize.clockpicker.js', array( 'jquery' ), $this->version, false );
|
122 |
-
wp_enqueue_script( $this->plugin_name."_jquery.datatables", plugin_dir_url( __FILE__ ) . 'js/jquery.dataTables.min.js', array( 'jquery' ), $this->version, false );
|
123 |
-
wp_enqueue_script( $this->plugin_name."_jquery.datatables.respnsive", plugin_dir_url( __FILE__ ) . 'js/dataTables.responsive.js', array( 'jquery' ), $this->version, false );
|
124 |
-
wp_enqueue_script( $this->plugin_name."_vakata", dirname(plugin_dir_url( __FILE__ )) . '/vendor/vakata/jstree/dist/jstree.min.js', array( 'jquery' ), '3.3', false );
|
125 |
-
wp_enqueue_script( $this->plugin_name."_xcloner-backup-class", plugin_dir_url( __FILE__ ) . 'js/xcloner-backup-class.js', array( 'jquery' ), $this->version, false );
|
126 |
-
wp_enqueue_script( $this->plugin_name."_xcloner-scheduler-class", plugin_dir_url( __FILE__ ) . 'js/xcloner-scheduler-class.js', array( 'jquery' ), $this->version, false );
|
127 |
-
wp_enqueue_script( $this->plugin_name."_xcloner-restore-class", plugin_dir_url( __FILE__ ) . 'js/xcloner-restore-class.js', array( 'jquery' ), $this->version, false );
|
128 |
-
wp_enqueue_script( $this->plugin_name."_xcloner-manage-backups-class", plugin_dir_url( __FILE__ ) . 'js/xcloner-manage-backups-class.js', array( 'jquery' ), $this->version, false );
|
129 |
-
wp_enqueue_script( $this->plugin_name."_xcloner-remote-storage-class", plugin_dir_url( __FILE__ ) . 'js/xcloner-remote-storage-class.js', array( 'jquery' ), $this->version, false );
|
130 |
wp_enqueue_script( $this->plugin_name, plugin_dir_url( __FILE__ ) . 'js/xcloner-admin.js', array( 'jquery' ), $this->version, false );
|
131 |
-
|
132 |
|
133 |
}
|
134 |
-
|
135 |
-
public function xcloner_init_page()
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
}
|
140 |
-
|
141 |
-
public function xcloner_remote_storage_page()
|
142 |
-
{
|
143 |
$xcloner_sanitization = $this->get_xcloner_container()->get_xcloner_sanitization();
|
144 |
-
$remote_storage
|
145 |
-
|
146 |
-
|
147 |
-
if(isset($_POST['action']))
|
148 |
-
|
149 |
-
$
|
150 |
-
$remote_storage->save($_POST['action']);
|
151 |
}
|
152 |
-
|
153 |
-
if(isset($_POST['authentification_code']) && $_POST['authentification_code'] != "")
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
$remote_storage->set_access_token($_POST['authentification_code']);
|
158 |
}
|
159 |
-
|
160 |
-
if(isset($_POST['connection_check']) && $_POST['connection_check'])
|
161 |
-
|
162 |
-
$remote_storage->check($_POST['action']);
|
163 |
}
|
164 |
-
|
165 |
-
require_once("partials/xcloner_remote_storage_page.php");
|
166 |
-
|
167 |
}
|
168 |
-
|
169 |
-
public function xcloner_scheduled_backups_page()
|
170 |
-
{
|
171 |
$requirements = $this->xcloner_container->get_xcloner_requirements();
|
172 |
-
|
173 |
-
if(
|
174 |
-
|
175 |
-
|
176 |
return false;
|
177 |
}
|
178 |
-
|
179 |
-
require_once("partials/xcloner_scheduled_backups_page.php");
|
180 |
-
|
181 |
}
|
182 |
-
|
183 |
-
public function xcloner_manage_backups_page()
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
}
|
188 |
-
|
189 |
-
public function xcloner_debugger_page()
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
}
|
194 |
-
|
195 |
-
public function xcloner_restore_page()
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
}
|
200 |
-
|
201 |
-
public function xcloner_generate_backups_page()
|
202 |
-
{
|
203 |
$requirements = $this->xcloner_container->get_xcloner_requirements();
|
204 |
-
|
205 |
-
if(
|
206 |
-
|
207 |
-
|
208 |
return false;
|
209 |
}
|
210 |
-
|
211 |
-
require_once("partials/xcloner_generate_backups_page.php");
|
|
|
212 |
return;
|
213 |
}
|
214 |
-
|
215 |
-
public function xcloner_settings_page()
|
216 |
-
{
|
217 |
// check user capabilities
|
218 |
-
if (!current_user_can('manage_options')) {
|
219 |
return;
|
220 |
}
|
221 |
-
|
222 |
// add error/update messages
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
<h1><?= esc_html(get_admin_page_title()); ?></h1>
|
247 |
-
|
248 |
<ul class="nav-tab-wrapper row">
|
249 |
-
<li><a href="?page=xcloner_settings_page&tab=general_options"
|
250 |
-
|
251 |
-
|
252 |
-
<li><a href="?page=xcloner_settings_page&tab=
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
253 |
</ul>
|
254 |
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
if( $active_tab == 'general_options' ) {
|
261 |
-
|
262 |
-
settings_fields('xcloner_general_settings_group');
|
263 |
-
do_settings_sections('xcloner_settings_page');
|
264 |
-
|
265 |
-
}elseif( $active_tab == 'mysql_options' ) {
|
266 |
-
|
267 |
-
settings_fields('xcloner_mysql_settings_group');
|
268 |
-
do_settings_sections('xcloner_mysql_settings_page');
|
269 |
-
}elseif( $active_tab == 'system_options' ) {
|
270 |
-
|
271 |
-
settings_fields('xcloner_system_settings_group');
|
272 |
-
do_settings_sections('xcloner_system_settings_page');
|
273 |
-
}elseif( $active_tab == 'cleanup_options' ) {
|
274 |
-
|
275 |
-
settings_fields('xcloner_cleanup_settings_group');
|
276 |
-
do_settings_sections('xcloner_cleanup_settings_page');
|
277 |
}
|
278 |
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
|
|
|
|
|
|
283 |
|
284 |
-
</div>
|
285 |
-
<?php
|
286 |
-
|
287 |
}
|
288 |
|
289 |
}
|
27 |
*
|
28 |
* @since 1.0.0
|
29 |
* @access private
|
30 |
+
* @var string $plugin_name The ID of this plugin.
|
31 |
*/
|
32 |
private $plugin_name;
|
33 |
|
36 |
*
|
37 |
* @since 1.0.0
|
38 |
* @access private
|
39 |
+
* @var string $version The current version of this plugin.
|
40 |
*/
|
41 |
private $version;
|
42 |
+
|
43 |
private $xcloner_container;
|
44 |
+
|
45 |
/**
|
46 |
* Initialize the class and set its properties.
|
47 |
*
|
48 |
* @since 1.0.0
|
49 |
+
*
|
50 |
+
* @param string $plugin_name The name of this plugin.
|
51 |
+
* @param string $version The version of this plugin.
|
52 |
*/
|
53 |
+
public function __construct( Xcloner $xcloner_container ) {
|
54 |
|
55 |
+
$this->plugin_name = $xcloner_container->get_plugin_name();
|
56 |
+
$this->version = $xcloner_container->get_version();
|
57 |
+
$this->xcloner_container = $xcloner_container;
|
58 |
}
|
59 |
+
|
60 |
+
public function get_xcloner_container() {
|
|
|
61 |
return $this->xcloner_container;
|
62 |
}
|
63 |
|
66 |
*
|
67 |
* @since 1.0.0
|
68 |
*/
|
69 |
+
public function enqueue_styles( $hook ) {
|
70 |
+
|
71 |
+
if ( ! stristr( $hook, "page_" . $this->plugin_name ) || ( isset( $_GET['option'] ) and $_GET['option'] == "com_cloner" ) ) {
|
72 |
return;
|
73 |
+
}
|
74 |
|
75 |
/**
|
76 |
* This function is provided for demonstration purposes only.
|
84 |
* class.
|
85 |
*/
|
86 |
|
87 |
+
wp_enqueue_style( $this->plugin_name . "_materialize", plugin_dir_url( __FILE__ ) . 'css/materialize.min.css', array(), $this->version, 'all' );
|
88 |
+
wp_enqueue_style( $this->plugin_name . "_materialize.clockpicker", plugin_dir_url( __FILE__ ) . 'css/materialize.clockpicker.css', array(), $this->version, 'all' );
|
89 |
+
wp_enqueue_style( $this->plugin_name . "_materialize.icons", '//fonts.googleapis.com/icon?family=Material+Icons', array(), $this->version, 'all' );
|
90 |
+
wp_enqueue_style( $this->plugin_name . "_jquery.datatables", plugin_dir_url( __FILE__ ) . 'css/jquery.dataTables.min.css', array(), $this->version, 'all' );
|
91 |
+
wp_enqueue_style( $this->plugin_name . "_jquery.datatables.responsive", plugin_dir_url( __FILE__ ) . 'css/responsive.dataTables.css', array(), $this->version, 'all' );
|
92 |
+
wp_enqueue_style( $this->plugin_name . "_jstree", dirname( plugin_dir_url( __FILE__ ) ) . '/vendor/vakata/jstree/dist/themes/default/style.min.css', array(), '3.3', 'all' );
|
93 |
wp_enqueue_style( $this->plugin_name, plugin_dir_url( __FILE__ ) . 'css/xcloner-admin.css', array(), $this->version, 'all' );
|
94 |
|
95 |
}
|
99 |
*
|
100 |
* @since 1.0.0
|
101 |
*/
|
102 |
+
public function enqueue_scripts( $hook ) {
|
103 |
|
104 |
+
if ( ! stristr( $hook, "page_" . $this->plugin_name ) ) {
|
105 |
return;
|
106 |
+
}
|
107 |
+
|
108 |
/**
|
109 |
* This function is provided for demonstration purposes only.
|
110 |
*
|
116 |
* between the defined hooks and the functions defined in this
|
117 |
* class.
|
118 |
*/
|
119 |
+
|
120 |
add_thickbox();
|
121 |
+
wp_enqueue_script( 'plugin-install' );
|
122 |
+
wp_enqueue_script( 'updates' );
|
123 |
+
wp_enqueue_script( $this->plugin_name . "_materialize", plugin_dir_url( __FILE__ ) . 'js/materialize.min.js', array( 'jquery' ), $this->version, false );
|
124 |
+
wp_enqueue_script( $this->plugin_name . "_materialize.clockpicker", plugin_dir_url( __FILE__ ) . 'js/materialize.clockpicker.js', array( 'jquery' ), $this->version, false );
|
125 |
+
wp_enqueue_script( $this->plugin_name . "_jquery.datatables", plugin_dir_url( __FILE__ ) . 'js/jquery.dataTables.min.js', array( 'jquery' ), $this->version, false );
|
126 |
+
wp_enqueue_script( $this->plugin_name . "_jquery.datatables.respnsive", plugin_dir_url( __FILE__ ) . 'js/dataTables.responsive.js', array( 'jquery' ), $this->version, false );
|
127 |
+
wp_enqueue_script( $this->plugin_name . "_vakata", dirname( plugin_dir_url( __FILE__ ) ) . '/vendor/vakata/jstree/dist/jstree.min.js', array( 'jquery' ), '3.3', false );
|
128 |
+
wp_enqueue_script( $this->plugin_name . "_xcloner-backup-class", plugin_dir_url( __FILE__ ) . 'js/xcloner-backup-class.js', array( 'jquery' ), $this->version, false );
|
129 |
+
wp_enqueue_script( $this->plugin_name . "_xcloner-scheduler-class", plugin_dir_url( __FILE__ ) . 'js/xcloner-scheduler-class.js', array( 'jquery' ), $this->version, false );
|
130 |
+
wp_enqueue_script( $this->plugin_name . "_xcloner-restore-class", plugin_dir_url( __FILE__ ) . 'js/xcloner-restore-class.js', array( 'jquery' ), $this->version, false );
|
131 |
+
wp_enqueue_script( $this->plugin_name . "_xcloner-manage-backups-class", plugin_dir_url( __FILE__ ) . 'js/xcloner-manage-backups-class.js', array( 'jquery' ), $this->version, false );
|
132 |
+
wp_enqueue_script( $this->plugin_name . "_xcloner-remote-storage-class", plugin_dir_url( __FILE__ ) . 'js/xcloner-remote-storage-class.js', array( 'jquery' ), $this->version, false );
|
133 |
wp_enqueue_script( $this->plugin_name, plugin_dir_url( __FILE__ ) . 'js/xcloner-admin.js', array( 'jquery' ), $this->version, false );
|
134 |
+
|
135 |
|
136 |
}
|
137 |
+
|
138 |
+
public function xcloner_init_page() {
|
139 |
+
require_once( "partials/xcloner_init_page.php" );
|
140 |
+
|
|
|
141 |
}
|
142 |
+
|
143 |
+
public function xcloner_remote_storage_page() {
|
|
|
144 |
$xcloner_sanitization = $this->get_xcloner_container()->get_xcloner_sanitization();
|
145 |
+
$remote_storage = $this->get_xcloner_container()->get_xcloner_remote_storage();
|
146 |
+
|
147 |
+
|
148 |
+
if ( isset( $_POST['action'] ) ) {
|
149 |
+
$_POST['action'] = $xcloner_sanitization->sanitize_input_as_string( $_POST['action'] );
|
150 |
+
$remote_storage->save( $_POST['action'] );
|
|
|
151 |
}
|
152 |
+
|
153 |
+
if ( isset( $_POST['authentification_code'] ) && $_POST['authentification_code'] != "" ) {
|
154 |
+
$_POST['authentification_code'] = $xcloner_sanitization->sanitize_input_as_string( $_POST['authentification_code'] );
|
155 |
+
|
156 |
+
$remote_storage->set_access_token( $_POST['authentification_code'] );
|
|
|
157 |
}
|
158 |
+
|
159 |
+
if ( isset( $_POST['connection_check'] ) && $_POST['connection_check'] ) {
|
160 |
+
$remote_storage->check( $_POST['action'] );
|
|
|
161 |
}
|
162 |
+
|
163 |
+
require_once( "partials/xcloner_remote_storage_page.php" );
|
164 |
+
|
165 |
}
|
166 |
+
|
167 |
+
public function xcloner_scheduled_backups_page() {
|
|
|
168 |
$requirements = $this->xcloner_container->get_xcloner_requirements();
|
169 |
+
|
170 |
+
if ( ! $requirements->check_backup_ready_status() ) {
|
171 |
+
require_once( "partials/xcloner_init_page.php" );
|
172 |
+
|
173 |
return false;
|
174 |
}
|
175 |
+
|
176 |
+
require_once( "partials/xcloner_scheduled_backups_page.php" );
|
177 |
+
|
178 |
}
|
179 |
+
|
180 |
+
public function xcloner_manage_backups_page() {
|
181 |
+
require_once( "partials/xcloner_manage_backups_page.php" );
|
182 |
+
|
|
|
183 |
}
|
184 |
+
|
185 |
+
public function xcloner_debugger_page() {
|
186 |
+
require_once( "partials/xcloner_console_page.php" );
|
187 |
+
|
|
|
188 |
}
|
189 |
+
|
190 |
+
public function xcloner_restore_page() {
|
191 |
+
require_once( "partials/xcloner_restore_page.php" );
|
192 |
+
|
|
|
193 |
}
|
194 |
+
|
195 |
+
public function xcloner_generate_backups_page() {
|
|
|
196 |
$requirements = $this->xcloner_container->get_xcloner_requirements();
|
197 |
+
|
198 |
+
if ( ! $requirements->check_backup_ready_status() ) {
|
199 |
+
require_once( "partials/xcloner_init_page.php" );
|
200 |
+
|
201 |
return false;
|
202 |
}
|
203 |
+
|
204 |
+
require_once( "partials/xcloner_generate_backups_page.php" );
|
205 |
+
|
206 |
return;
|
207 |
}
|
208 |
+
|
209 |
+
public function xcloner_settings_page() {
|
|
|
210 |
// check user capabilities
|
211 |
+
if ( ! current_user_can( 'manage_options' ) ) {
|
212 |
return;
|
213 |
}
|
214 |
+
|
215 |
// add error/update messages
|
216 |
+
|
217 |
+
// check if the user have submitted the settings
|
218 |
+
// wordpress will add the "settings-updated" $_GET parameter to the url
|
219 |
+
if ( isset( $_GET['settings-updated'] ) ) {
|
220 |
+
// add settings saved message with the class of "updated"
|
221 |
+
add_settings_error( 'wporg_messages', 'wporg_message', __( 'Settings Saved', 'wporg' ), 'updated' );
|
222 |
+
}
|
223 |
+
|
224 |
+
// show error/update messages
|
225 |
+
settings_errors( 'wporg_messages' );
|
226 |
+
?>
|
227 |
+
|
228 |
+
<?php
|
229 |
+
$xcloner_sanitization = $this->get_xcloner_container()->get_xcloner_sanitization();
|
230 |
+
|
231 |
+
if ( isset( $_GET['tab'] ) ) {
|
232 |
+
$active_tab = $xcloner_sanitization->sanitize_input_as_string( $_GET['tab'] );
|
233 |
+
} // end if
|
234 |
+
else {
|
235 |
+
$active_tab = "general_options";
|
236 |
+
}
|
237 |
+
|
238 |
+
?>
|
239 |
+
<h1><?= esc_html( get_admin_page_title() ); ?></h1>
|
240 |
+
|
241 |
<ul class="nav-tab-wrapper row">
|
242 |
+
<li><a href="?page=xcloner_settings_page&tab=general_options"
|
243 |
+
class="nav-tab col s12 m3 l2 <?php echo $active_tab == 'general_options' ? 'nav-tab-active' : ''; ?>"><?php echo __( 'General Options', 'xcloner-backup-and-restore' ) ?></a>
|
244 |
+
</li>
|
245 |
+
<li><a href="?page=xcloner_settings_page&tab=mysql_options"
|
246 |
+
class="nav-tab col s12 m3 l2 <?php echo $active_tab == 'mysql_options' ? 'nav-tab-active' : ''; ?>"><?php echo __( 'Mysql Options', 'xcloner-backup-and-restore' ) ?></a>
|
247 |
+
</li>
|
248 |
+
<li><a href="?page=xcloner_settings_page&tab=system_options"
|
249 |
+
class="nav-tab col s12 m3 l2 <?php echo $active_tab == 'system_options' ? 'nav-tab-active' : ''; ?>"><?php echo __( 'System Options', 'xcloner-backup-and-restore' ) ?></a>
|
250 |
+
</li>
|
251 |
+
<li><a href="?page=xcloner_settings_page&tab=cleanup_options"
|
252 |
+
class="nav-tab col s12 m3 l2 <?php echo $active_tab == 'cleanup_options' ? 'nav-tab-active' : ''; ?>"><?php echo __( 'Cleanup Options', 'xcloner-backup-and-restore' ) ?></a>
|
253 |
+
</li>
|
254 |
</ul>
|
255 |
|
256 |
+
<div class="wrap">
|
257 |
+
|
258 |
+
<form action="options.php" method="post">
|
259 |
+
<?php
|
260 |
+
|
261 |
+
if ( $active_tab == 'general_options' ) {
|
262 |
+
|
263 |
+
settings_fields( 'xcloner_general_settings_group' );
|
264 |
+
do_settings_sections( 'xcloner_settings_page' );
|
265 |
+
|
266 |
+
} elseif ( $active_tab == 'mysql_options' ) {
|
267 |
+
|
268 |
+
settings_fields( 'xcloner_mysql_settings_group' );
|
269 |
+
do_settings_sections( 'xcloner_mysql_settings_page' );
|
270 |
+
} elseif ( $active_tab == 'system_options' ) {
|
271 |
+
|
272 |
+
settings_fields( 'xcloner_system_settings_group' );
|
273 |
+
do_settings_sections( 'xcloner_system_settings_page' );
|
274 |
+
} elseif ( $active_tab == 'cleanup_options' ) {
|
275 |
+
|
276 |
+
settings_fields( 'xcloner_cleanup_settings_group' );
|
277 |
+
do_settings_sections( 'xcloner_cleanup_settings_page' );
|
278 |
}
|
279 |
|
280 |
+
// output save settings button
|
281 |
+
submit_button( 'Save Settings' );
|
282 |
+
?>
|
283 |
+
</form>
|
284 |
+
|
285 |
+
</div>
|
286 |
+
<?php
|
287 |
|
|
|
|
|
|
|
288 |
}
|
289 |
|
290 |
}
|
admin/css/xcloner-admin.css
CHANGED
@@ -6,8 +6,9 @@
|
|
6 |
|
7 |
html {
|
8 |
font-family: GillSans, Calibri, Trebuchet, sans-serif;
|
9 |
-
|
10 |
-
|
|
|
11 |
@font-face {
|
12 |
font-family: 'Material Icons';
|
13 |
font-style: normal;
|
@@ -20,139 +21,135 @@ html {
|
|
20 |
url(../fontsMaterialIcons-Regular.ttf) format('truetype');
|
21 |
}*/
|
22 |
|
23 |
-
|
24 |
-
|
25 |
-
h1{
|
26 |
-
font-size: 23px;
|
27 |
}
|
28 |
|
29 |
-
h2{
|
30 |
-
|
31 |
}
|
32 |
|
33 |
-
.input-field{
|
34 |
-
|
35 |
}
|
36 |
|
37 |
td, th {
|
38 |
-
|
39 |
}
|
40 |
|
41 |
.form-table th {
|
42 |
-
|
43 |
}
|
44 |
|
45 |
a.nav-tab.col {
|
46 |
padding: 10px;
|
47 |
}
|
48 |
|
49 |
-
|
50 |
-
|
51 |
-
cursor: pointer;
|
52 |
}
|
53 |
|
54 |
-
.card-panel{
|
55 |
-
|
56 |
}
|
57 |
|
58 |
-
|
59 |
-
|
60 |
-
display: none;
|
61 |
}
|
62 |
|
63 |
-
.nav-tab-wrapper li{
|
64 |
-
|
65 |
}
|
66 |
|
67 |
-
.nav-tab-wrapper-content .tab-content{
|
68 |
-
|
69 |
}
|
70 |
|
71 |
-
.nav-tab-wrapper-content .tab-content.active{
|
72 |
-
|
73 |
}
|
74 |
|
75 |
.input-field label.active {
|
76 |
-
|
77 |
}
|
78 |
|
79 |
-
.xcloner-debugger .console{
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
}
|
84 |
|
85 |
-
#error_modal textarea{
|
86 |
-
|
87 |
}
|
88 |
|
89 |
-
#error_modal .msg{
|
90 |
-
|
91 |
}
|
92 |
|
93 |
-
#generate_backup .backup-status, #generate_backup ul.backup-status > li{
|
94 |
-
|
95 |
}
|
96 |
|
97 |
-
ul.backup-name{
|
98 |
-
|
99 |
}
|
100 |
|
101 |
-
#generate_backup .status-body ul.backup-name li, #generate_backup ul.logged-databases
|
102 |
-
|
103 |
}
|
104 |
|
105 |
#generate_backup .backup-done .collapsible-body {
|
106 |
-
|
107 |
}
|
108 |
|
109 |
-
#generate_backup .status-body > ul, #generate_backup .status-body ul.logged-tables{
|
110 |
-
|
111 |
-
|
112 |
overflow-y: auto;
|
113 |
-
|
114 |
}
|
115 |
|
116 |
-
#generate_backup .action-buttons .cancel,
|
117 |
-
#generate_backup .action-buttons .restart{
|
118 |
-
|
119 |
-
}
|
120 |
|
121 |
-
.modal-footer .modal-close.btn-flat{
|
122 |
-
|
123 |
}
|
124 |
|
125 |
-
.collapsible-body{
|
126 |
-
|
127 |
}
|
128 |
|
129 |
-
.select-wrapper+label {
|
130 |
font-size: 1rem;
|
131 |
}
|
132 |
|
133 |
-
#schedule_backup .server-time h2{
|
134 |
-
|
135 |
}
|
136 |
|
137 |
-
#schedule_backup_success{
|
138 |
-
|
139 |
}
|
140 |
|
141 |
-
#scheduled_backups_wrapper .dataTables_length,
|
142 |
-
#manage_backups_wrapper
|
143 |
-
|
144 |
}
|
145 |
|
146 |
-
table#scheduled_backups{
|
147 |
-
|
148 |
}
|
149 |
|
150 |
-
#scheduled_backups td, #scheduled_backups th{
|
151 |
-
|
152 |
}
|
153 |
|
154 |
-
#scheduled_backups i.status{
|
155 |
-
|
156 |
}
|
157 |
|
158 |
.site-backup_page_xcloner_scheduled_backups_page #server_time h2 {
|
@@ -161,236 +158,239 @@ table#scheduled_backups{
|
|
161 |
padding: 10px 10px 5px 10px;
|
162 |
}
|
163 |
|
164 |
-
textarea.materialize-textarea{
|
165 |
-
|
166 |
-
|
167 |
}
|
168 |
|
169 |
#scheduled_backups .edit, #scheduled_backups .status.active, #scheduled_backups .delete,
|
170 |
#manage_backups .download, #manage_backups .cloud-upload, #manage_backups .delete, #manage_backups .list-backup-content,
|
171 |
-
.backup-done .download, .backup-done .cloud-upload, .backup-done .delete, .backup-done .list-backup-content,
|
172 |
-
#manage_backups .copy-remote-to-local
|
173 |
-
|
174 |
}
|
175 |
|
176 |
-
#scheduled_backups .status.inactive{
|
177 |
-
|
178 |
}
|
179 |
|
180 |
-
table.dataTable thead th, table.dataTable tfoot th{
|
181 |
-
|
182 |
}
|
183 |
|
184 |
-
table.dataTable tr.odd {
|
185 |
-
|
|
|
186 |
|
187 |
-
|
188 |
-
|
189 |
-
display: none;
|
190 |
}
|
191 |
|
192 |
-
#manage_backups ul.multipart
|
193 |
-
|
194 |
-
|
195 |
}
|
196 |
-
|
197 |
-
|
198 |
-
|
|
|
199 |
}
|
200 |
|
201 |
-
.
|
202 |
-
|
203 |
}
|
204 |
-
|
205 |
-
|
|
|
206 |
}
|
207 |
|
208 |
-
.remote-storage .
|
209 |
-
|
210 |
}
|
211 |
|
|
|
|
|
|
|
212 |
|
213 |
-
#manage_backups td.checkbox{
|
214 |
-
|
215 |
}
|
216 |
|
217 |
-
#remote_storage_modal{
|
218 |
-
|
219 |
}
|
220 |
|
221 |
-
#remote_storage_modal .label label{
|
222 |
-
|
223 |
}
|
224 |
|
225 |
-
#remote_storage_modal .label{
|
226 |
-
|
227 |
}
|
228 |
|
229 |
-
#remote_storage_modal .status{
|
230 |
-
|
231 |
}
|
232 |
|
233 |
-
#remote_storage_modal .status-text.error{
|
234 |
-
|
235 |
}
|
236 |
|
237 |
-
#remote_storage_modal .status-text{
|
238 |
-
|
239 |
}
|
240 |
|
241 |
-
#backup-status h5{
|
242 |
font-size: 18px;
|
243 |
}
|
244 |
|
245 |
-
#backup-status .row .item .title{
|
246 |
width: 100px;
|
247 |
display: inline-block;
|
248 |
font-weight: bold;
|
249 |
}
|
250 |
|
251 |
-
.xcloner-restore li.steps{
|
252 |
-
|
253 |
}
|
254 |
|
255 |
-
.xcloner-restore .steps.show{
|
256 |
-
|
257 |
}
|
258 |
|
259 |
-
.xcloner-restore li .collapsible-body{
|
260 |
-
|
261 |
}
|
262 |
|
263 |
-
.xcloner-restore select.browser-default{
|
264 |
-
|
265 |
-
|
266 |
}
|
267 |
|
268 |
-
.xcloner-restore .steps .progress{
|
269 |
-
|
270 |
}
|
271 |
|
272 |
-
.xcloner-restore .status > div{
|
273 |
-
|
274 |
}
|
275 |
|
276 |
-
.xcloner-restore .toggler{
|
277 |
-
|
278 |
}
|
279 |
|
280 |
-
.xcloner-restore .toggler .normal{
|
281 |
-
|
282 |
}
|
283 |
|
284 |
-
.xcloner-restore .toggler .cancel{
|
285 |
-
|
286 |
}
|
287 |
|
288 |
-
.xcloner-restore .toggler.cancel .normal{
|
289 |
-
|
290 |
}
|
291 |
|
292 |
-
.xcloner-restore .toggler.cancel .cancel{
|
293 |
-
|
294 |
}
|
295 |
|
296 |
-
.xcloner-restore ul.text-steps li{
|
297 |
-
|
298 |
}
|
299 |
|
300 |
-
.xcloner-restore ul.text-steps li.warning{
|
301 |
-
|
302 |
}
|
303 |
|
304 |
-
.xcloner-restore ul.text-steps ul li{
|
305 |
-
|
306 |
}
|
307 |
|
308 |
-
.xcloner-restore ul.text-steps ul{
|
309 |
-
|
310 |
}
|
311 |
|
312 |
-
.xcloner-restore ul.text-steps{
|
313 |
-
|
314 |
}
|
315 |
|
316 |
-
.xcloner-restore .restore-remote-backup-step .files-list{
|
317 |
-
|
318 |
overflow: auto;
|
319 |
margin: 10px 5px;
|
320 |
}
|
321 |
|
322 |
-
#backup_cotent_modal .modal-content .files-list span{
|
323 |
-
|
324 |
}
|
325 |
|
326 |
-
.xcloner-restore .query-box{
|
327 |
-
|
328 |
}
|
329 |
|
330 |
-
.xcloner-restore .query-box .query-list{
|
331 |
-
|
332 |
}
|
333 |
|
334 |
-
.xcloner-restore .restore-remote-database-step h5{
|
335 |
-
|
336 |
margin-bottom: 25px;
|
337 |
}
|
338 |
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
font-weight: bold;
|
343 |
}
|
344 |
|
345 |
-
.jstree-icon.jstree-checkbox.jstree-checkbox-disabled{
|
346 |
-
|
347 |
}
|
348 |
|
349 |
-
#xcloner_regex_exclude{
|
350 |
-
|
351 |
}
|
352 |
|
353 |
ul.xcloner_regex_exclude_limit li:nth-of-type(n+2) {
|
354 |
-
display:none;
|
355 |
}
|
356 |
|
357 |
-
.xcloner-restore .btn.waves-effect.waves-light.grey{
|
358 |
-
|
359 |
}
|
360 |
|
361 |
-
.xcloner-restore #xcloner_restore_finish{
|
362 |
-
|
363 |
}
|
364 |
|
365 |
-
ul.files-list li{
|
366 |
-
|
367 |
-
|
368 |
}
|
369 |
|
370 |
-
#manage_backups_wrapper #manage_backups_filter{
|
371 |
-
|
372 |
}
|
373 |
|
374 |
-
#generate_backup_form .progress, .xcloner-restore .progress{
|
375 |
-
|
376 |
height: 4px !important;
|
377 |
}
|
378 |
|
379 |
-
i.backup_warning{
|
380 |
-
|
381 |
}
|
382 |
|
383 |
-
.col.remote-storage-selection{
|
384 |
-
|
385 |
}
|
386 |
|
387 |
.remote-storage #authentification_code {
|
388 |
-
|
389 |
}
|
390 |
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
}
|
396 |
}
|
6 |
|
7 |
html {
|
8 |
font-family: GillSans, Calibri, Trebuchet, sans-serif;
|
9 |
+
}
|
10 |
+
|
11 |
+
/*
|
12 |
@font-face {
|
13 |
font-family: 'Material Icons';
|
14 |
font-style: normal;
|
21 |
url(../fontsMaterialIcons-Regular.ttf) format('truetype');
|
22 |
}*/
|
23 |
|
24 |
+
h1 {
|
25 |
+
font-size: 23px;
|
|
|
|
|
26 |
}
|
27 |
|
28 |
+
h2 {
|
29 |
+
font-size: 18px;
|
30 |
}
|
31 |
|
32 |
+
.input-field {
|
33 |
+
margin-top: 0px;
|
34 |
}
|
35 |
|
36 |
td, th {
|
37 |
+
padding-top: 0px !important;
|
38 |
}
|
39 |
|
40 |
.form-table th {
|
41 |
+
padding-top: 10px !important;
|
42 |
}
|
43 |
|
44 |
a.nav-tab.col {
|
45 |
padding: 10px;
|
46 |
}
|
47 |
|
48 |
+
span.shorten_string {
|
49 |
+
cursor: pointer;
|
|
|
50 |
}
|
51 |
|
52 |
+
.card-panel {
|
53 |
+
min-height: 60px;
|
54 |
}
|
55 |
|
56 |
+
.dashboard .additional_system_info {
|
57 |
+
display: none;
|
|
|
58 |
}
|
59 |
|
60 |
+
.nav-tab-wrapper li {
|
61 |
+
margin-bottom: 0px;
|
62 |
}
|
63 |
|
64 |
+
.nav-tab-wrapper-content .tab-content {
|
65 |
+
display: none;
|
66 |
}
|
67 |
|
68 |
+
.nav-tab-wrapper-content .tab-content.active {
|
69 |
+
display: block;
|
70 |
}
|
71 |
|
72 |
.input-field label.active {
|
73 |
+
font-size: 1rem;
|
74 |
}
|
75 |
|
76 |
+
.xcloner-debugger .console {
|
77 |
+
height: 450px;
|
78 |
+
min-height: 300px;
|
79 |
+
overflow: auto;
|
80 |
}
|
81 |
|
82 |
+
#error_modal textarea {
|
83 |
+
height: 150px;
|
84 |
}
|
85 |
|
86 |
+
#error_modal .msg {
|
87 |
+
font-size: 14px;
|
88 |
}
|
89 |
|
90 |
+
#generate_backup .backup-status, #generate_backup ul.backup-status > li {
|
91 |
+
display: none;
|
92 |
}
|
93 |
|
94 |
+
ul.backup-name {
|
95 |
+
margin-top: 1.78rem;
|
96 |
}
|
97 |
|
98 |
+
#generate_backup .status-body ul.backup-name li, #generate_backup ul.logged-databases li {
|
99 |
+
font-weight: bold;
|
100 |
}
|
101 |
|
102 |
#generate_backup .backup-done .collapsible-body {
|
103 |
+
margin-top: 1.83rem;
|
104 |
}
|
105 |
|
106 |
+
#generate_backup .status-body > ul, #generate_backup .status-body ul.logged-tables {
|
107 |
+
margin: 5px 10px;
|
108 |
+
max-height: 200px;
|
109 |
overflow-y: auto;
|
110 |
+
margin-top: 1.78rem;
|
111 |
}
|
112 |
|
113 |
+
#generate_backup .action-buttons .cancel,
|
114 |
+
#generate_backup .action-buttons .restart {
|
115 |
+
display: none;
|
116 |
+
}
|
117 |
|
118 |
+
.modal-footer .modal-close.btn-flat {
|
119 |
+
color: #fff;
|
120 |
}
|
121 |
|
122 |
+
.collapsible-body {
|
123 |
+
padding: 0px 10px;
|
124 |
}
|
125 |
|
126 |
+
.select-wrapper + label {
|
127 |
font-size: 1rem;
|
128 |
}
|
129 |
|
130 |
+
#schedule_backup .server-time h2 {
|
131 |
+
color: #fff;
|
132 |
}
|
133 |
|
134 |
+
#schedule_backup_success {
|
135 |
+
display: none;
|
136 |
}
|
137 |
|
138 |
+
#scheduled_backups_wrapper .dataTables_length,
|
139 |
+
#manage_backups_wrapper .dataTables_length {
|
140 |
+
display: none;
|
141 |
}
|
142 |
|
143 |
+
table#scheduled_backups {
|
144 |
+
font-size: 16px;
|
145 |
}
|
146 |
|
147 |
+
#scheduled_backups td, #scheduled_backups th {
|
148 |
+
padding-top: 8px !important;
|
149 |
}
|
150 |
|
151 |
+
#scheduled_backups i.status {
|
152 |
+
color: #fff;
|
153 |
}
|
154 |
|
155 |
.site-backup_page_xcloner_scheduled_backups_page #server_time h2 {
|
158 |
padding: 10px 10px 5px 10px;
|
159 |
}
|
160 |
|
161 |
+
textarea.materialize-textarea {
|
162 |
+
overflow: auto;
|
163 |
+
resize: auto;
|
164 |
}
|
165 |
|
166 |
#scheduled_backups .edit, #scheduled_backups .status.active, #scheduled_backups .delete,
|
167 |
#manage_backups .download, #manage_backups .cloud-upload, #manage_backups .delete, #manage_backups .list-backup-content,
|
168 |
+
.backup-done .download, .backup-done .cloud-upload, .backup-done .delete, .backup-done .list-backup-content,
|
169 |
+
#manage_backups .copy-remote-to-local, #manage_backups .expand-multipart {
|
170 |
+
color: #4db6ac;
|
171 |
}
|
172 |
|
173 |
+
#scheduled_backups .status.inactive {
|
174 |
+
color: #d32f2f;
|
175 |
}
|
176 |
|
177 |
+
table.dataTable thead th, table.dataTable tfoot th {
|
178 |
+
padding-left: 10px;
|
179 |
}
|
180 |
|
181 |
+
table.dataTable tr.odd {
|
182 |
+
background-color: #fff;
|
183 |
+
}
|
184 |
|
185 |
+
table.dataTable tr.even {
|
186 |
+
background-color: #f3f3f3;
|
|
|
187 |
}
|
188 |
|
189 |
+
#manage_backups ul.multipart {
|
190 |
+
margin-left: 20px;
|
191 |
+
display: none;
|
192 |
}
|
193 |
+
|
194 |
+
#manage_backups ul.multipart li {
|
195 |
+
padding: 5px;
|
196 |
+
list-style-type: square;
|
197 |
}
|
198 |
|
199 |
+
a.expand-multipart.remove {
|
200 |
+
display: none;
|
201 |
}
|
202 |
+
|
203 |
+
.remote-storage .label label {
|
204 |
+
font-size: 16px;
|
205 |
}
|
206 |
|
207 |
+
.remote-storage .label {
|
208 |
+
padding-top: 25px;
|
209 |
}
|
210 |
|
211 |
+
.remote-storage .collapsible-header {
|
212 |
+
padding: 2px 5px;
|
213 |
+
}
|
214 |
|
215 |
+
#manage_backups td.checkbox {
|
216 |
+
vertical-align: top;
|
217 |
}
|
218 |
|
219 |
+
#remote_storage_modal {
|
220 |
+
min-height: 350px;
|
221 |
}
|
222 |
|
223 |
+
#remote_storage_modal .label label {
|
224 |
+
font-size: 16px;
|
225 |
}
|
226 |
|
227 |
+
#remote_storage_modal .label {
|
228 |
+
padding-top: 25px;
|
229 |
}
|
230 |
|
231 |
+
#remote_storage_modal .status {
|
232 |
+
display: none;
|
233 |
}
|
234 |
|
235 |
+
#remote_storage_modal .status-text.error {
|
236 |
+
color: red;
|
237 |
}
|
238 |
|
239 |
+
#remote_storage_modal .status-text {
|
240 |
+
font-weight: bold;
|
241 |
}
|
242 |
|
243 |
+
#backup-status h5 {
|
244 |
font-size: 18px;
|
245 |
}
|
246 |
|
247 |
+
#backup-status .row .item .title {
|
248 |
width: 100px;
|
249 |
display: inline-block;
|
250 |
font-weight: bold;
|
251 |
}
|
252 |
|
253 |
+
.xcloner-restore li.steps {
|
254 |
+
display: none;
|
255 |
}
|
256 |
|
257 |
+
.xcloner-restore .steps.show {
|
258 |
+
display: block;
|
259 |
}
|
260 |
|
261 |
+
.xcloner-restore li .collapsible-body {
|
262 |
+
padding: 25px 10px 15px 10px;
|
263 |
}
|
264 |
|
265 |
+
.xcloner-restore select.browser-default {
|
266 |
+
height: 36px;
|
267 |
+
font-size: 18px;
|
268 |
}
|
269 |
|
270 |
+
.xcloner-restore .steps .progress {
|
271 |
+
display: none;
|
272 |
}
|
273 |
|
274 |
+
.xcloner-restore .status > div {
|
275 |
+
margin: 10px 0px 0px 0px;
|
276 |
}
|
277 |
|
278 |
+
.xcloner-restore .toggler {
|
279 |
+
display: inline-block;
|
280 |
}
|
281 |
|
282 |
+
.xcloner-restore .toggler .normal {
|
283 |
+
display: block;
|
284 |
}
|
285 |
|
286 |
+
.xcloner-restore .toggler .cancel {
|
287 |
+
display: none;
|
288 |
}
|
289 |
|
290 |
+
.xcloner-restore .toggler.cancel .normal {
|
291 |
+
display: none;
|
292 |
}
|
293 |
|
294 |
+
.xcloner-restore .toggler.cancel .cancel {
|
295 |
+
display: block;
|
296 |
}
|
297 |
|
298 |
+
.xcloner-restore ul.text-steps li {
|
299 |
+
list-style-type: decimal;
|
300 |
}
|
301 |
|
302 |
+
.xcloner-restore ul.text-steps li.warning {
|
303 |
+
color: red;
|
304 |
}
|
305 |
|
306 |
+
.xcloner-restore ul.text-steps ul li {
|
307 |
+
list-style-type: disc;
|
308 |
}
|
309 |
|
310 |
+
.xcloner-restore ul.text-steps ul {
|
311 |
+
margin: 10px;
|
312 |
}
|
313 |
|
314 |
+
.xcloner-restore ul.text-steps {
|
315 |
+
margin-left: 20px;
|
316 |
}
|
317 |
|
318 |
+
.xcloner-restore .restore-remote-backup-step .files-list {
|
319 |
+
max-height: 250px;
|
320 |
overflow: auto;
|
321 |
margin: 10px 5px;
|
322 |
}
|
323 |
|
324 |
+
#backup_cotent_modal .modal-content .files-list span {
|
325 |
+
cursor: pointer;
|
326 |
}
|
327 |
|
328 |
+
.xcloner-restore .query-box {
|
329 |
+
display: none;
|
330 |
}
|
331 |
|
332 |
+
.xcloner-restore .query-box .query-list {
|
333 |
+
height: 10rem;
|
334 |
}
|
335 |
|
336 |
+
.xcloner-restore .restore-remote-database-step h5 {
|
337 |
+
margin-top: -10px;
|
338 |
margin-bottom: 25px;
|
339 |
}
|
340 |
|
341 |
+
.regex_pattern {
|
342 |
+
cursor: pointer;
|
343 |
+
font-weight: bold;
|
|
|
344 |
}
|
345 |
|
346 |
+
.jstree-icon.jstree-checkbox.jstree-checkbox-disabled {
|
347 |
+
opacity: 0.3;
|
348 |
}
|
349 |
|
350 |
+
#xcloner_regex_exclude {
|
351 |
+
height: 5rem;
|
352 |
}
|
353 |
|
354 |
ul.xcloner_regex_exclude_limit li:nth-of-type(n+2) {
|
355 |
+
display: none;
|
356 |
}
|
357 |
|
358 |
+
.xcloner-restore .btn.waves-effect.waves-light.grey {
|
359 |
+
margin-top: -2px;
|
360 |
}
|
361 |
|
362 |
+
.xcloner-restore #xcloner_restore_finish {
|
363 |
+
display: none;
|
364 |
}
|
365 |
|
366 |
+
ul.files-list li {
|
367 |
+
padding: 0px;
|
368 |
+
white-space: pre;
|
369 |
}
|
370 |
|
371 |
+
#manage_backups_wrapper #manage_backups_filter {
|
372 |
+
min-width: 250px;
|
373 |
}
|
374 |
|
375 |
+
#generate_backup_form .progress, .xcloner-restore .progress {
|
376 |
+
width: 100% !important;
|
377 |
height: 4px !important;
|
378 |
}
|
379 |
|
380 |
+
i.backup_warning {
|
381 |
+
color: red;
|
382 |
}
|
383 |
|
384 |
+
.col.remote-storage-selection {
|
385 |
+
padding-top: 20px;
|
386 |
}
|
387 |
|
388 |
.remote-storage #authentification_code {
|
389 |
+
display: none;
|
390 |
}
|
391 |
|
392 |
+
@media only screen and (min-width: 993px) {
|
393 |
+
.dashboard .backup-ready {
|
394 |
+
float: right;
|
395 |
+
}
|
|
|
396 |
}
|
admin/js/xcloner-admin.js
CHANGED
@@ -1,126 +1,119 @@
|
|
1 |
-
(function(
|
2 |
-
|
3 |
-
|
4 |
-
jQuery(document).ready(function(){
|
5 |
-
|
6 |
-
jQuery("span.shorten_string").click(function(){
|
7 |
-
jQuery(this).toggleClass("full");
|
8 |
-
doShortText(jQuery(this));
|
9 |
-
})
|
10 |
-
|
11 |
-
jQuery("span.shorten_string").each(function(){
|
12 |
-
doShortText(jQuery(this));
|
13 |
-
})
|
14 |
-
|
15 |
-
jQuery("#xcloner_regex_exclude").on("focus", function(){
|
16 |
-
jQuery("ul.xcloner_regex_exclude_limit li").fadeIn();
|
17 |
-
})
|
18 |
-
|
19 |
-
jQuery(".regex_pattern").on("click", function(){
|
20 |
-
jQuery(this).select();
|
21 |
-
})
|
22 |
-
|
23 |
-
jQuery(".btn.system_info_toggle").on("click", function(){
|
24 |
-
jQuery(".additional_system_info").toggle();
|
25 |
-
})
|
26 |
-
|
27 |
-
jQuery("a.download-logger").on("click", function(e){
|
28 |
-
var xcloner_manage_backups = new Xcloner_Manage_Backups();
|
29 |
-
|
30 |
-
var hash = jQuery(this).attr('href');
|
31 |
-
var id = hash.substr(1)
|
32 |
-
|
33 |
-
if(id)
|
34 |
-
{
|
35 |
-
xcloner_manage_backups.download_backup_by_name(id);
|
36 |
-
}
|
37 |
-
|
38 |
-
e.preventDefault();
|
39 |
-
})
|
40 |
-
|
41 |
-
jQuery(".nav-tab-wrapper.content li").on("click", function(e){
|
42 |
-
jQuery(".nav-tab-wrapper li a").removeClass("nav-tab-active");
|
43 |
-
jQuery(this).find('a').addClass("nav-tab-active");
|
44 |
-
jQuery(".nav-tab-wrapper-content .tab-content").removeClass('active');
|
45 |
-
jQuery(".nav-tab-wrapper-content "+jQuery(this).find('a').attr('href')).addClass('active');
|
46 |
-
|
47 |
-
e.preventDefault();
|
48 |
-
|
49 |
-
location.hash = jQuery(this).find('a').attr('href')+"_hash";
|
50 |
-
|
51 |
-
})
|
52 |
-
|
53 |
-
var hash = window.location.hash;
|
54 |
-
if(hash){
|
55 |
-
next_tab(hash.replace("_hash",""));
|
56 |
-
}
|
57 |
-
})
|
58 |
-
|
59 |
-
})( jQuery );
|
60 |
|
|
|
61 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
62 |
|
63 |
|
64 |
//jQuery( document ).ajaxError(function(err, request) {
|
65 |
-
|
66 |
//});
|
67 |
|
68 |
-
function next_tab(hash){
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
function doShortText(elem)
|
74 |
-
{
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
elem.attr("data-text", text).text(first+"..."+last);
|
85 |
}
|
86 |
|
87 |
/** global: xcloner_backup */
|
88 |
-
function show_ajax_error(title, msg, json){
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
jQuery("#error_modal .body").text(JSON.stringify(json));
|
111 |
-
var error_modal = jQuery("#error_modal").modal();
|
112 |
-
error_modal.modal('open');
|
113 |
}
|
114 |
|
115 |
var ID = function () {
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
};
|
121 |
|
122 |
|
123 |
-
var getUrlParam = function(name) {
|
124 |
return (location.search.split(name + '=')[1] || '').split('&')[0];
|
125 |
}
|
126 |
|
1 |
+
(function ($) {
|
2 |
+
'use strict';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
|
4 |
+
jQuery(document).ready(function () {
|
5 |
|
6 |
+
jQuery("span.shorten_string").click(function () {
|
7 |
+
jQuery(this).toggleClass("full");
|
8 |
+
doShortText(jQuery(this));
|
9 |
+
})
|
10 |
+
|
11 |
+
jQuery("span.shorten_string").each(function () {
|
12 |
+
doShortText(jQuery(this));
|
13 |
+
})
|
14 |
+
|
15 |
+
jQuery("#xcloner_regex_exclude").on("focus", function () {
|
16 |
+
jQuery("ul.xcloner_regex_exclude_limit li").fadeIn();
|
17 |
+
})
|
18 |
+
|
19 |
+
jQuery(".regex_pattern").on("click", function () {
|
20 |
+
jQuery(this).select();
|
21 |
+
})
|
22 |
+
|
23 |
+
jQuery(".btn.system_info_toggle").on("click", function () {
|
24 |
+
jQuery(".additional_system_info").toggle();
|
25 |
+
})
|
26 |
+
|
27 |
+
jQuery("a.download-logger").on("click", function (e) {
|
28 |
+
var xcloner_manage_backups = new Xcloner_Manage_Backups();
|
29 |
+
|
30 |
+
var hash = jQuery(this).attr('href');
|
31 |
+
var id = hash.substr(1)
|
32 |
+
|
33 |
+
if (id) {
|
34 |
+
xcloner_manage_backups.download_backup_by_name(id);
|
35 |
+
}
|
36 |
+
|
37 |
+
e.preventDefault();
|
38 |
+
})
|
39 |
+
|
40 |
+
jQuery(".nav-tab-wrapper.content li").on("click", function (e) {
|
41 |
+
jQuery(".nav-tab-wrapper li a").removeClass("nav-tab-active");
|
42 |
+
jQuery(this).find('a').addClass("nav-tab-active");
|
43 |
+
jQuery(".nav-tab-wrapper-content .tab-content").removeClass('active');
|
44 |
+
jQuery(".nav-tab-wrapper-content " + jQuery(this).find('a').attr('href')).addClass('active');
|
45 |
+
|
46 |
+
e.preventDefault();
|
47 |
+
|
48 |
+
location.hash = jQuery(this).find('a').attr('href') + "_hash";
|
49 |
+
|
50 |
+
})
|
51 |
+
|
52 |
+
var hash = window.location.hash;
|
53 |
+
if (hash) {
|
54 |
+
next_tab(hash.replace("_hash", ""));
|
55 |
+
}
|
56 |
+
})
|
57 |
+
|
58 |
+
})(jQuery);
|
59 |
|
60 |
|
61 |
//jQuery( document ).ajaxError(function(err, request) {
|
62 |
+
//show_ajax_error("dd", "dd12", request)
|
63 |
//});
|
64 |
|
65 |
+
function next_tab(hash) {
|
66 |
+
jQuery(".nav-tab-wrapper").find("li a[href='" + hash + "']").trigger('click');
|
67 |
+
location.hash = hash;
|
68 |
+
}
|
69 |
+
|
70 |
+
function doShortText(elem) {
|
71 |
+
if (elem.hasClass("full")) {
|
72 |
+
elem.text(elem.attr("data-text"));
|
73 |
+
return;
|
74 |
+
}
|
75 |
+
var text = elem.text()
|
76 |
+
var text_lenght = text.length;
|
77 |
+
var first = text.substr(0, 10);
|
78 |
+
var last = text.substr(text_lenght - 20, text_lenght);
|
79 |
+
|
80 |
+
elem.attr("data-text", text).text(first + "..." + last);
|
|
|
81 |
}
|
82 |
|
83 |
/** global: xcloner_backup */
|
84 |
+
function show_ajax_error(title, msg, json) {
|
85 |
+
|
86 |
+
//var json = jQuery.parseJSON( body )
|
87 |
+
|
88 |
+
if (typeof xcloner_backup !== 'undefined') {
|
89 |
+
xcloner_backup.cancel_backup();
|
90 |
+
}
|
91 |
+
|
92 |
+
if (json.responseText) {
|
93 |
+
msg = msg + ": " + json.responseText;
|
94 |
+
}
|
95 |
+
|
96 |
+
jQuery("#error_modal .title").text(title);
|
97 |
+
jQuery("#error_modal .msg").text(msg);
|
98 |
+
|
99 |
+
if (json.status) {
|
100 |
+
jQuery("#error_modal .status").text(json.status + " " + json.statusText);
|
101 |
+
}
|
102 |
+
|
103 |
+
jQuery("#error_modal .body").text(JSON.stringify(json));
|
104 |
+
var error_modal = jQuery("#error_modal").modal();
|
105 |
+
error_modal.modal('open');
|
|
|
|
|
|
|
106 |
}
|
107 |
|
108 |
var ID = function () {
|
109 |
+
// Math.random should be unique because of its seeding algorithm.
|
110 |
+
// Convert it to base 36 (numbers + letters), and grab the first 9 characters
|
111 |
+
// after the decimal.
|
112 |
+
return '_' + Math.random().toString(36).substr(2, 9);
|
113 |
};
|
114 |
|
115 |
|
116 |
+
var getUrlParam = function (name) {
|
117 |
return (location.search.split(name + '=')[1] || '').split('&')[0];
|
118 |
}
|
119 |
|
admin/js/xcloner-backup-class.js
CHANGED
@@ -1,441 +1,404 @@
|
|
1 |
-
class Xcloner_Backup{
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
var callback = 'do_'+action+'_callback';
|
406 |
-
var data = JSON.stringify(this.params);
|
407 |
-
var $this = this;
|
408 |
-
|
409 |
-
jQuery.ajax({
|
410 |
-
url: ajaxurl,
|
411 |
-
dataType: 'json',
|
412 |
-
type: 'POST',
|
413 |
-
data: {'action': action, 'data': data, 'init': init, 'hash': hash, 'API_ID': ID()},
|
414 |
-
error: function(err) {
|
415 |
-
show_ajax_error("Communication Error", "", err)
|
416 |
-
$this.init_resume(elem, action, init);
|
417 |
-
//console.log(err);
|
418 |
-
}
|
419 |
-
}).done(function(json) {
|
420 |
-
if(json.hash){
|
421 |
-
$this.params.hash = json.hash;
|
422 |
-
//console.log(json.hash);
|
423 |
-
}
|
424 |
-
if(json.error !== undefined){
|
425 |
-
show_ajax_error("Communication Error", "", json.error_message);
|
426 |
-
$this.init_resume(elem, action, init);
|
427 |
-
return;
|
428 |
-
}
|
429 |
-
|
430 |
-
$this.resume = new Object();
|
431 |
-
|
432 |
-
$this[callback](elem, action, json)
|
433 |
-
|
434 |
-
});
|
435 |
-
}
|
436 |
-
|
437 |
-
getSize(bytes, conv = 1024*1024)
|
438 |
-
{
|
439 |
-
return (bytes/conv).toFixed(2);
|
440 |
-
}
|
441 |
}
|
1 |
+
class Xcloner_Backup {
|
2 |
+
|
3 |
+
constructor() {
|
4 |
+
this.cancel = 0;
|
5 |
+
this.params;
|
6 |
+
this.generate_hash = false;
|
7 |
+
this.last_dumpfile = "";
|
8 |
+
this.last_backup_file = ""
|
9 |
+
this.backup_part = 0
|
10 |
+
this.backup_size_total = 0;
|
11 |
+
this.resume = new Object();
|
12 |
+
}
|
13 |
+
|
14 |
+
get_form_params() {
|
15 |
+
var table_params = []
|
16 |
+
var files_params = []
|
17 |
+
var extra = []
|
18 |
+
|
19 |
+
jQuery.each(jQuery("#jstree_database_container").jstree("get_checked", true), function () {
|
20 |
+
|
21 |
+
var object = new Object();
|
22 |
+
object.id = this.id
|
23 |
+
object.parent = this.parent
|
24 |
+
|
25 |
+
var index = table_params.length;
|
26 |
+
table_params[index] = object
|
27 |
+
});
|
28 |
+
|
29 |
+
jQuery.each(jQuery("#jstree_files_container").jstree("get_checked", true), function () {
|
30 |
+
//console.log(this.id+"-"+this.parent);
|
31 |
+
|
32 |
+
var object = new Object();
|
33 |
+
object.id = this.id
|
34 |
+
object.parent = this.parent
|
35 |
+
|
36 |
+
var index = files_params.length;
|
37 |
+
files_params[index] = object
|
38 |
+
});
|
39 |
+
|
40 |
+
var $return = new Object();
|
41 |
+
$return.table_params = table_params;
|
42 |
+
$return.files_params = files_params;
|
43 |
+
$return.backup_params = jQuery('#generate_backup_form').serializeArray();
|
44 |
+
|
45 |
+
return $return;
|
46 |
+
}
|
47 |
+
|
48 |
+
do_backup_database_callback(elem, action, json) {
|
49 |
+
if (json.extra)
|
50 |
+
this.params.extra = json.extra;
|
51 |
+
|
52 |
+
if (json.extra.stats) {
|
53 |
+
if (json.extra.stats.tables_count !== undefined) {
|
54 |
+
jQuery(elem).find(".table-counter").text(parseInt(json.extra.stats.tables_count));
|
55 |
+
}
|
56 |
+
|
57 |
+
if (json.extra.stats.database_count !== undefined) {
|
58 |
+
jQuery(elem).find(".database-counter").text(parseInt(json.extra.stats.database_count));
|
59 |
+
}
|
60 |
+
|
61 |
+
if (json.extra.stats.total_records !== undefined) {
|
62 |
+
jQuery(elem).find(".total-records").text(parseInt(json.extra.stats.total_records));
|
63 |
+
}
|
64 |
+
}
|
65 |
+
|
66 |
+
if (json.extra.tableName) {
|
67 |
+
jQuery(elem).find(".last-logged-table").text(json.extra.databaseName + "." + json.extra.tableName + " (" + json.extra.processedRecords + " records)");
|
68 |
+
}
|
69 |
+
|
70 |
+
if (json.extra.processedRecords !== undefined && !json.extra.startAtRecord && !json.extra.endDump) {
|
71 |
+
var records = parseInt(jQuery(elem).find(".total-records").attr('data-processed')) + parseInt(json.extra.processedRecords);
|
72 |
+
|
73 |
+
var percent = 100 * parseInt(records) / parseInt(jQuery(elem).find(".total-records").text());
|
74 |
+
jQuery(elem).find('.progress .determinate').css('width', percent + '%');
|
75 |
+
|
76 |
+
jQuery(elem).find(".total-records").attr('data-processed', records);
|
77 |
+
jQuery(elem).find(".status-body ul.logged-tables").prepend(jQuery("<li>").text(json.extra.databaseName + "." + json.extra.tableName + " (" + json.extra.processedRecords + " records)"));
|
78 |
+
}
|
79 |
+
|
80 |
+
if (json.extra.dumpfile !== undefined) {
|
81 |
+
var db_text = (json.extra.dumpfile + " (" + this.getSize(json.extra.dumpsize, 1024) + " KB)");
|
82 |
+
|
83 |
+
if (!jQuery(this.last_dumpfile).hasClass(json.extra.dumpfile)) {
|
84 |
+
this.last_dumpfile = (jQuery("<li>").addClass(json.extra.dumpfile).html(db_text)).prependTo("ul.logged-databases");
|
85 |
+
}
|
86 |
+
else {
|
87 |
+
jQuery(this.last_dumpfile).html(db_text)
|
88 |
+
}
|
89 |
+
|
90 |
+
}
|
91 |
+
|
92 |
+
if (!json.finished /*&& !this.cancel*/) {
|
93 |
+
|
94 |
+
this.do_ajax(elem, action);
|
95 |
+
return false;
|
96 |
+
}
|
97 |
+
|
98 |
+
|
99 |
+
jQuery(elem).find(".last-logged-table").text('done');
|
100 |
+
jQuery(elem).find('.progress .determinate').css('width', '100%');
|
101 |
+
|
102 |
+
this.do_backup_files();
|
103 |
+
|
104 |
+
}
|
105 |
+
|
106 |
+
do_backup_database() {
|
107 |
+
if (!jQuery('#jstree_database_container').length) {
|
108 |
+
this.do_backup_files();
|
109 |
+
return;
|
110 |
+
}
|
111 |
+
|
112 |
+
/*if(this.cancel)
|
113 |
+
return false;*/
|
114 |
+
|
115 |
+
var elem = "#generate_backup ul.backup-status li.database-backup";
|
116 |
+
jQuery(elem).show();
|
117 |
+
jQuery(elem + ' .status-body').show();
|
118 |
+
|
119 |
+
jQuery(elem).find(".total-records").text(0);
|
120 |
+
jQuery(elem).find(".total-records").attr('data-processed', 0);
|
121 |
+
jQuery(elem).find(".table-counter").text(0);
|
122 |
+
jQuery(elem).find(".database-counter").text(0);
|
123 |
+
jQuery(elem).find(".logged-databases").html("");
|
124 |
+
jQuery(elem).find(".logged-tables").html("");
|
125 |
+
|
126 |
+
this.last_dumpfile = 0;
|
127 |
+
|
128 |
+
jQuery(elem).find('.progress .determinate').css('width', '0%');
|
129 |
+
|
130 |
+
this.do_ajax(elem, 'backup_database', 1);
|
131 |
+
}
|
132 |
+
|
133 |
+
do_scan_filesystem_callback(elem, action, json) {
|
134 |
+
|
135 |
+
if (json.total_files_num) {
|
136 |
+
jQuery(".file-system .file-counter").text(parseInt(json.total_files_num) + parseInt(jQuery(".file-system .file-counter").text()));
|
137 |
+
}
|
138 |
+
|
139 |
+
if (json.total_files_size) {
|
140 |
+
var size = parseFloat(json.total_files_size) + parseFloat(jQuery(".file-system .file-size-total").text())
|
141 |
+
jQuery(".file-system .file-size-total").text(size.toFixed(2));
|
142 |
+
}
|
143 |
+
|
144 |
+
if (json.last_logged_file) {
|
145 |
+
jQuery(".file-system .last-logged-file").text(json.last_logged_file);
|
146 |
+
}
|
147 |
+
|
148 |
+
if (!json.finished /*&& !this.cancel*/) {
|
149 |
+
|
150 |
+
this.do_ajax(elem, action);
|
151 |
+
return false;
|
152 |
+
}
|
153 |
+
|
154 |
+
//finished
|
155 |
+
jQuery(elem).find('.progress .indeterminate').removeClass('indeterminate').addClass('determinate').css('width', '100%');
|
156 |
+
jQuery(".file-system .last-logged-file").text('done');
|
157 |
+
|
158 |
+
//this.do_backup_database();
|
159 |
+
this.do_backup_database();
|
160 |
+
|
161 |
+
}
|
162 |
+
|
163 |
+
do_scan_filesystem() {
|
164 |
+
/*if(this.cancel)
|
165 |
+
return false;*/
|
166 |
+
|
167 |
+
var elem = "#generate_backup ul.backup-status li.file-system";
|
168 |
+
jQuery(elem).show();
|
169 |
+
jQuery(elem + ' .status-body').show();
|
170 |
+
jQuery(elem).find('.collapsible-header').trigger('click');
|
171 |
+
|
172 |
+
jQuery(".file-system .file-counter").text(0);
|
173 |
+
jQuery(".file-system .last-logged-file").text("");
|
174 |
+
jQuery(".file-system .file-size-total").text(0);
|
175 |
+
jQuery('.file-system .progress div').removeClass('determinate').addClass('indeterminate').css('width', '0%');
|
176 |
+
|
177 |
+
|
178 |
+
this.do_ajax(elem, 'scan_filesystem', 1);
|
179 |
+
|
180 |
+
}
|
181 |
+
|
182 |
+
do_backup_files_callback(elem, action, json) {
|
183 |
+
/*if(this.cancel)
|
184 |
+
return false;*/
|
185 |
+
|
186 |
+
if (json.extra) {
|
187 |
+
this.params.extra = json.extra;
|
188 |
+
}
|
189 |
+
|
190 |
+
if (json.extra) {
|
191 |
+
if (json.extra.start_at_line !== undefined) {
|
192 |
+
jQuery(elem).find(".file-counter").text(parseInt(json.extra.start_at_line));
|
193 |
+
}
|
194 |
+
|
195 |
+
if (json.extra.start_at_line !== undefined) {
|
196 |
+
//var prev_backup_size = parseInt(jQuery(elem).find(".file-size-total").attr('data-processed'));
|
197 |
+
jQuery(elem).find(".file-size-total").text(this.getSize(this.backup_size_total + parseInt(json.extra.backup_size)));
|
198 |
+
//var backup_size = parseInt(json.extra.backup_size);
|
199 |
+
}
|
200 |
+
|
201 |
+
}
|
202 |
+
|
203 |
+
if (json.extra.processed_file) {
|
204 |
+
if (json.extra.start_at_byte !== undefined && json.extra.start_at_byte) {
|
205 |
+
var processed_size = json.extra.start_at_byte;
|
206 |
+
}
|
207 |
+
else {
|
208 |
+
var processed_size = json.extra.processed_file_size;
|
209 |
+
}
|
210 |
+
|
211 |
+
jQuery(elem).find(".last-logged-file").text(json.extra.processed_file + " (" + this.getSize(processed_size, 1024) + " KB)");
|
212 |
+
}
|
213 |
+
|
214 |
+
if (json.extra.processed_file !== undefined) {
|
215 |
+
|
216 |
+
var backup_text = json.extra.backup_archive_name_full + " (" + this.getSize(json.extra.backup_size) + ") MB";
|
217 |
+
|
218 |
+
if (this.backup_part != json.extra.backup_part) {
|
219 |
+
this.backup_part = json.extra.backup_part;
|
220 |
+
this.backup_size_total = this.backup_size_total + json.extra.backup_size;
|
221 |
+
}
|
222 |
+
|
223 |
+
if (!jQuery(this.last_backup_file).hasClass(json.extra.backup_archive_name)) {
|
224 |
+
this.last_backup_file = (jQuery("<li>").addClass(json.extra.backup_archive_name).html(backup_text)).prependTo(jQuery(elem).find(".status-body .backup-name"));
|
225 |
+
}
|
226 |
+
|
227 |
+
jQuery(this.last_backup_file).html(backup_text)
|
228 |
+
|
229 |
+
}
|
230 |
+
|
231 |
+
|
232 |
+
if (json.extra.lines_total) {
|
233 |
+
var percent = 100 * parseInt(json.extra.start_at_line) / parseInt(json.extra.lines_total);
|
234 |
+
jQuery(elem).find('.progress .determinate').css('width', percent + '%');
|
235 |
+
}
|
236 |
+
|
237 |
+
if (!json.finished /*&& !this.cancel*/) {
|
238 |
+
|
239 |
+
this.do_ajax(elem, action);
|
240 |
+
return false;
|
241 |
+
}
|
242 |
+
|
243 |
+
jQuery(elem).find(".last-logged-file").text('done');
|
244 |
+
jQuery(".backup-done .cloud-upload").attr("href", "#" + json.extra.backup_parent);
|
245 |
+
jQuery(".backup-done .download").attr("href", "#" + json.extra.backup_parent);
|
246 |
+
jQuery(".backup-done .list-backup-content").attr("href", "#" + json.extra.backup_parent);
|
247 |
+
|
248 |
+
//this.restart_backup();
|
249 |
+
this.do_backup_done()
|
250 |
+
}
|
251 |
+
|
252 |
+
do_backup_files() {
|
253 |
+
if (this.cancel)
|
254 |
+
return false;
|
255 |
+
|
256 |
+
var elem = "#generate_backup ul.backup-status li.files-backup";
|
257 |
+
jQuery(elem).show();
|
258 |
+
jQuery(elem + ' .status-body').show();
|
259 |
+
jQuery(elem).find('.collapsible-header').trigger('click');
|
260 |
+
|
261 |
+
jQuery(elem).find(".file-size-total").text(0);
|
262 |
+
jQuery(elem).find(".file-size-total").attr('data-processed', 0);
|
263 |
+
jQuery(elem).find(".file-counter").text(0);
|
264 |
+
jQuery(elem).find(".last-logged-file").text("");
|
265 |
+
|
266 |
+
jQuery(elem).find('.progress .determinate').css('width', '0%');
|
267 |
+
|
268 |
+
this.do_ajax(elem, 'backup_files', 1);
|
269 |
+
}
|
270 |
+
|
271 |
+
do_backup_done() {
|
272 |
+
var elem = "#generate_backup ul.backup-status li.backup-done";
|
273 |
+
jQuery(elem).show();
|
274 |
+
jQuery(elem + ' .status-body').show();
|
275 |
+
jQuery(elem).find('.collapsible-header').trigger('click');
|
276 |
+
|
277 |
+
this.set_cancel(false)
|
278 |
+
jQuery('#generate_backup .action-buttons a').hide();
|
279 |
+
jQuery('#generate_backup .action-buttons .start').css('display', 'inline-block');
|
280 |
+
|
281 |
+
}
|
282 |
+
|
283 |
+
do_save_schedule_callback(elem, action, json) {
|
284 |
+
jQuery("#schedule_backup_success").show();
|
285 |
+
}
|
286 |
+
|
287 |
+
cancel_backup() {
|
288 |
+
this.set_cancel(true)
|
289 |
+
jQuery('#generate_backup .action-buttons a').hide();
|
290 |
+
jQuery('#generate_backup .action-buttons .start').css('display', 'inline-block');
|
291 |
+
jQuery('#generate_backup .action-buttons .restart').css('display', 'inline-block');
|
292 |
+
|
293 |
+
//this.restart_backup();
|
294 |
+
}
|
295 |
+
|
296 |
+
restart_backup() {
|
297 |
+
this.set_cancel(false);
|
298 |
+
|
299 |
+
jQuery('#generate_backup .action-buttons a').hide();
|
300 |
+
jQuery('#generate_backup .action-buttons .cancel').css('display', 'inline-block');
|
301 |
+
|
302 |
+
if (this.resume.action) {
|
303 |
+
//console.log(this.resume.action)
|
304 |
+
this.do_ajax(this.resume.elem, this.resume.action, this.resume.params);
|
305 |
+
this.resume = new Object();
|
306 |
+
return;
|
307 |
+
}
|
308 |
+
|
309 |
+
this.start_backup()
|
310 |
+
}
|
311 |
+
|
312 |
+
start_backup() {
|
313 |
+
|
314 |
+
this.resume = new Object()
|
315 |
+
this.set_cancel(false);
|
316 |
+
jQuery('#generate_backup .action-buttons a').hide();
|
317 |
+
jQuery('#generate_backup .action-buttons .cancel').css('display', 'inline-block');
|
318 |
+
|
319 |
+
|
320 |
+
this.generate_hash = true;
|
321 |
+
//this.cancel = false;
|
322 |
+
this.backup_size_total = 0;
|
323 |
+
this.last_backup_file = "";
|
324 |
+
this.backup_part = 0;
|
325 |
+
jQuery('#generate_backup ul.backup-name li').remove();
|
326 |
+
|
327 |
+
jQuery('#generate_backup ul.backup-status > li').hide();
|
328 |
+
jQuery('#generate_backup .backup-status').show();
|
329 |
+
|
330 |
+
this.params = this.get_form_params();
|
331 |
+
|
332 |
+
|
333 |
+
this.do_scan_filesystem();
|
334 |
+
|
335 |
+
}
|
336 |
+
|
337 |
+
set_cancel(status) {
|
338 |
+
if (status) {
|
339 |
+
//document.dispatchEvent(new CustomEvent("xcloner_restore_update_progress", {detail: {percent: 0, class: 'determinate' }}));
|
340 |
+
//jQuery("#generate_backup .collapsible-header.active .progress > div").add
|
341 |
+
}
|
342 |
+
this.cancel = status
|
343 |
+
}
|
344 |
+
|
345 |
+
get_cancel(status) {
|
346 |
+
return this.cancel
|
347 |
+
}
|
348 |
+
|
349 |
+
init_resume(elem, action, init) {
|
350 |
+
this.resume.elem = elem
|
351 |
+
this.resume.action = action
|
352 |
+
this.resume.init = init
|
353 |
+
}
|
354 |
+
|
355 |
+
/** global: ajaxurl */
|
356 |
+
do_ajax(elem, action, init = 0) {
|
357 |
+
var hash = '';
|
358 |
+
if (this.params.hash !== undefined)
|
359 |
+
hash = this.params.hash;
|
360 |
+
else if (this.generate_hash)
|
361 |
+
hash = 'generate_hash';
|
362 |
+
|
363 |
+
|
364 |
+
if (this.cancel == true) {
|
365 |
+
this.init_resume(elem, action, init);
|
366 |
+
return;
|
367 |
+
}
|
368 |
+
|
369 |
+
var callback = 'do_' + action + '_callback';
|
370 |
+
var data = JSON.stringify(this.params);
|
371 |
+
var $this = this;
|
372 |
+
|
373 |
+
jQuery.ajax({
|
374 |
+
url: ajaxurl,
|
375 |
+
dataType: 'json',
|
376 |
+
type: 'POST',
|
377 |
+
data: {'action': action, 'data': data, 'init': init, 'hash': hash, 'API_ID': ID()},
|
378 |
+
error: function (err) {
|
379 |
+
show_ajax_error("Communication Error", "", err)
|
380 |
+
$this.init_resume(elem, action, init);
|
381 |
+
//console.log(err);
|
382 |
+
}
|
383 |
+
}).done(function (json) {
|
384 |
+
if (json.hash) {
|
385 |
+
$this.params.hash = json.hash;
|
386 |
+
//console.log(json.hash);
|
387 |
+
}
|
388 |
+
if (json.error !== undefined) {
|
389 |
+
show_ajax_error("Communication Error", "", json.error_message);
|
390 |
+
$this.init_resume(elem, action, init);
|
391 |
+
return;
|
392 |
+
}
|
393 |
+
|
394 |
+
$this.resume = new Object();
|
395 |
+
|
396 |
+
$this[callback](elem, action, json)
|
397 |
+
|
398 |
+
});
|
399 |
+
}
|
400 |
+
|
401 |
+
getSize(bytes, conv = 1024 * 1024) {
|
402 |
+
return (bytes / conv).toFixed(2);
|
403 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
404 |
}
|
admin/js/xcloner-manage-backups-class.js
CHANGED
@@ -203,7 +203,7 @@ jQuery(document).ready(function(){
|
|
203 |
var dataTable = jQuery('#manage_backups').DataTable( {
|
204 |
'responsive': true,
|
205 |
'bFilter': true,
|
206 |
-
"order": [[
|
207 |
buttons: [
|
208 |
'selectAll',
|
209 |
'selectNone'
|
203 |
var dataTable = jQuery('#manage_backups').DataTable( {
|
204 |
'responsive': true,
|
205 |
'bFilter': true,
|
206 |
+
"order": [[ 2, "desc" ]],
|
207 |
buttons: [
|
208 |
'selectAll',
|
209 |
'selectNone'
|
admin/partials/xcloner_console_page.php
CHANGED
@@ -1,33 +1,36 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
$xcloner_settings
|
4 |
-
$logger
|
5 |
-
$logger_content
|
6 |
?>
|
7 |
<div class="col s12 ">
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
<?php if($xcloner_settings->get_xcloner_option('xcloner_enable_log'))
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
|
|
|
|
|
|
33 |
</div>
|
1 |
<?php
|
2 |
|
3 |
+
$xcloner_settings = $this->get_xcloner_container()->get_xcloner_settings();
|
4 |
+
$logger = $this->get_xcloner_container()->get_xcloner_logger();
|
5 |
+
$logger_content = $logger->getLastDebugLines();
|
6 |
?>
|
7 |
<div class="col s12 ">
|
8 |
+
<div>
|
9 |
+
<h5 class="left-align">
|
10 |
+
<?php echo __( 'XCloner Debugger Dashboard', 'xcloner-backup-and-restore' ) ?>
|
11 |
+
</h5>
|
12 |
+
|
13 |
+
<?php if ( $xcloner_settings->get_xcloner_option( 'xcloner_enable_log' ) ) : ?>
|
14 |
+
<ul class="collapsible xcloner-debugger" data-collapsible="accordion">
|
15 |
+
<li class="active">
|
16 |
+
<div class="collapsible-header active"><i class="material-icons">bug_report</i>XCloner Debugger
|
17 |
+
</div>
|
18 |
+
<div class="collapsible-body">
|
19 |
+
<div class="console" id="xcloner-console"><?php if ( isset( $logger_content ) ) {
|
20 |
+
echo implode( "<br />\n", $logger_content );
|
21 |
+
} ?></div>
|
22 |
+
</div>
|
23 |
+
</li>
|
24 |
+
</ul>
|
25 |
+
<script>
|
26 |
+
jQuery(document).ready(function () {
|
27 |
+
var objDiv = document.getElementById("xcloner-console");
|
28 |
+
objDiv.scrollTop = objDiv.scrollHeight;
|
29 |
+
/*setInterval(function(){
|
30 |
+
getXclonerLog();
|
31 |
+
}, 2000);*/
|
32 |
+
})
|
33 |
+
</script>
|
34 |
+
<?php endif; ?>
|
35 |
+
</div>
|
36 |
</div>
|
admin/partials/xcloner_generate_backups_page.php
CHANGED
@@ -1,545 +1,593 @@
|
|
1 |
-
<?php
|
2 |
-
$xcloner_settings
|
3 |
$xcloner_remote_storage = $this->get_xcloner_container()->get_xcloner_remote_storage();
|
4 |
-
$available_storages
|
5 |
-
$xcloner_scheduler
|
6 |
-
$tab
|
7 |
?>
|
8 |
|
9 |
<script>var xcloner_backup = new Xcloner_Backup();</script>
|
10 |
|
11 |
-
<h1><?= esc_html(get_admin_page_title()); ?></h1>
|
12 |
-
|
13 |
<ul class="nav-tab-wrapper content row">
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
<?php
|
18 |
-
|
19 |
-
|
20 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
</ul>
|
22 |
|
23 |
<form action="" method="POST" id="generate_backup_form">
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
98 |
<?php endif ?>
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
260 |
<div class="row">
|
261 |
<div class="input-field inline col s10 m11 l7">
|
262 |
<select id="backup_type" class="" name="backup_type">
|
263 |
-
<option value=""><?php echo __("Full Backup","xcloner-backup-and-restore")
|
264 |
-
<option value="diff"><?php echo __("Differential Backups","xcloner-backup-and-restore")
|
265 |
-
<option value="full_diff"><?php echo __("Full Backup + Differential Backups","xcloner-backup-and-restore")
|
266 |
</select>
|
267 |
-
<label for="backup_type"><?php echo __('Scheduled Backup Type','xcloner-backup-and-restore')?></label>
|
268 |
</div>
|
269 |
<div class="col s2 m1">
|
270 |
<a class="btn-floating tooltipped btn-small" data-html="true" data-position="center" data-delay="50" data-tooltip="<ul style='max-width:760px; text-align:left;'>
|
271 |
-
<li><?php echo __("Full Backup = it will generate a full backup of all included files each time schedule runs","xcloner-backup-and-restore")
|
272 |
-
<li><?php echo __("Differentials Backups = backups will include only changed files since the schedule started to run","xcloner-backup-and-restore")
|
273 |
-
<li><?php echo __("Full Backup + Differential Backups = the first time schedule runs, it will create a full backup and all next scheduled backups will include only files created/modified since that last full backup; a full backup is recreated when the number of changed files is bigger than the 'Differetial Backups Max Days' XCloner option.","xcloner-backup-and-restore")
|
274 |
</ul>"><i class="material-icons">help_outline</i></a>
|
275 |
</div>
|
276 |
</div>
|
277 |
-->
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
|
|
282 |
<?php
|
283 |
$schedules = $xcloner_scheduler->get_available_intervals();
|
284 |
-
|
285 |
-
foreach($schedules as $key
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
<?php
|
290 |
}
|
291 |
-
?>
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
<?php if(sizeof($available_storages))
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
<?php endif?>
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
|
|
319 |
</form>
|
320 |
|
321 |
<!-- Error Modal Structure -->
|
322 |
<div id="error_modal" class="modal">
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
|
|
333 |
</div>
|
334 |
|
335 |
<!-- List Backup Content Modal-->
|
336 |
<div id="backup_cotent_modal" class="modal">
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
</div>
|
347 |
|
348 |
<!-- Remote Storage Modal Structure -->
|
349 |
<div id="remote_storage_modal" class="modal">
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
|
|
|
|
|
|
383 |
</div>
|
384 |
-
|
385 |
<script>
|
386 |
-
jQuery(function () {
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
});
|
543 |
|
544 |
|
545 |
</script>
|
1 |
+
<?php
|
2 |
+
$xcloner_settings = $this->get_xcloner_container()->get_xcloner_settings();
|
3 |
$xcloner_remote_storage = $this->get_xcloner_container()->get_xcloner_remote_storage();
|
4 |
+
$available_storages = $xcloner_remote_storage->get_available_storages();
|
5 |
+
$xcloner_scheduler = $this->get_xcloner_container()->get_xcloner_scheduler();
|
6 |
+
$tab = 1;
|
7 |
?>
|
8 |
|
9 |
<script>var xcloner_backup = new Xcloner_Backup();</script>
|
10 |
|
11 |
+
<h1><?= esc_html( get_admin_page_title() ); ?></h1>
|
12 |
+
|
13 |
<ul class="nav-tab-wrapper content row">
|
14 |
+
<li><a href="#backup_options"
|
15 |
+
class="nav-tab col s12 m3 l2 nav-tab-active"><?php echo $tab . ". " . __( 'Backup Options', 'xcloner-backup-and-restore' ) ?></a>
|
16 |
+
</li>
|
17 |
+
<?php if ( $xcloner_settings->get_enable_mysql_backup() ): ?>
|
18 |
+
<li><a href="#database_options"
|
19 |
+
class="nav-tab col s12 m3 l2 "><?php echo ++ $tab . ". " . __( 'Database Options', 'xcloner-backup-and-restore' ) ?></a>
|
20 |
+
</li>
|
21 |
+
<?php endif ?>
|
22 |
+
<li><a href="#files_options"
|
23 |
+
class="nav-tab col s12 m3 l2 "><?php echo ++ $tab . ". " . __( 'Files Options', 'xcloner-backup-and-restore' ) ?></a>
|
24 |
+
</li>
|
25 |
+
<li><a href="#generate_backup"
|
26 |
+
class="nav-tab col s12 m3 l2 "><?php echo ++ $tab . ". " . __( 'Generate Backup', 'xcloner-backup-and-restore' ) ?></a>
|
27 |
+
</li>
|
28 |
+
<li><a href="#schedule_backup"
|
29 |
+
class="nav-tab col s12 m3 l2 "><?php echo ++ $tab . ". " . __( 'Schedule Backup', 'xcloner-backup-and-restore' ) ?></a>
|
30 |
+
</li>
|
31 |
</ul>
|
32 |
|
33 |
<form action="" method="POST" id="generate_backup_form">
|
34 |
+
<div class="nav-tab-wrapper-content">
|
35 |
+
<!-- Backup Options Content Tab-->
|
36 |
+
<div id="backup_options" class="tab-content active">
|
37 |
+
<div class="row">
|
38 |
+
<div class="input-field inline col s12 m10 l6">
|
39 |
+
<i class="material-icons prefix">input</i>
|
40 |
+
<input name="backup_name" id="backup_name" type="text"
|
41 |
+
value=<?php echo $xcloner_settings->get_default_backup_name() ?>>
|
42 |
+
<label for="backup_name"><?php echo __( 'Backup Name', 'xcloner-backup-and-restore' ) ?></label>
|
43 |
+
</div>
|
44 |
+
<div class="hide-on-small-only m2">
|
45 |
+
<a class="btn-floating tooltipped btn-small" data-position="right" data-delay="50"
|
46 |
+
data-tooltip="<?php echo __( 'The default backup name, supported tags [time], [hostname], [domain]', 'xcloner-backup-and-restore' ) ?>"
|
47 |
+
data-tooltip-id=""><i class="material-icons">help_outline</i></a>
|
48 |
+
</div>
|
49 |
+
</div>
|
50 |
+
|
51 |
+
<div class="row">
|
52 |
+
<div class="input-field inline col s12 m10 l6">
|
53 |
+
<i class="material-icons prefix">email</i>
|
54 |
+
<input name="email_notification" id="email_notification" type="text"
|
55 |
+
value="<?php echo get_option( 'admin_email' ); ?>">
|
56 |
+
<label for="email_notification"><?php echo __( 'Send Email Notification To', 'xcloner-backup-and-restore' ) ?></label>
|
57 |
+
</div>
|
58 |
+
<div class="hide-on-small-only m2">
|
59 |
+
<a class="btn-floating tooltipped btn-small" data-position="right" data-delay="50"
|
60 |
+
data-tooltip="<?php echo __( 'If left blank, no notification will be sent', 'xcloner-backup-and-restore' ) ?>"
|
61 |
+
data-tooltip-id=""><i class="material-icons">help_outline</i></a>
|
62 |
+
</div>
|
63 |
+
</div>
|
64 |
+
|
65 |
+
<div class="row">
|
66 |
+
<div class="input-field inline col s10 m10 l6">
|
67 |
+
<i class="material-icons prefix">access_time</i>
|
68 |
+
<input type="datetime-local" id="diff_start_date" class="datepicker_max_today"
|
69 |
+
name="diff_start_date">
|
70 |
+
<label for="diff_start_date"><?php echo __( 'Backup Only Files Modified/Created After', 'xcloner-backup-and-restore' ) ?></label>
|
71 |
+
</div>
|
72 |
+
<div class="hide-on-small-only m2">
|
73 |
+
<a class="btn-floating tooltipped btn-small" data-html="true" data-position="center" data-delay="50"
|
74 |
+
data-tooltip="<?php echo __( "This option allows you to create a differential backup that will include only <br> changed files since the set date, leave blank to include all files", "xcloner-backup-and-restore" ) ?>"><i
|
75 |
+
class="material-icons">help_outline</i></a>
|
76 |
+
</div>
|
77 |
+
</div>
|
78 |
+
|
79 |
+
<div class="row">
|
80 |
+
<div class="input-field col s12 m10 l6">
|
81 |
+
<i class="material-icons prefix">input</i>
|
82 |
+
<textarea name="backup_comments" id="backup_comments" class="materialize-textarea"></textarea>
|
83 |
+
<label for="backup_comments"><?php echo __( 'Backup Comments', 'xcloner-backup-and-restore' ) ?></label>
|
84 |
+
</div>
|
85 |
+
<div class="hide-on-small-only m2">
|
86 |
+
<a class="btn-floating tooltipped btn-small" data-position="right" data-delay="50"
|
87 |
+
data-tooltip="<?php echo __( 'Some default backup comments that will be stored inside the backup archive', 'xcloner-backup-and-restore' ) ?>"
|
88 |
+
data-tooltip-id=""><i class="material-icons">help_outline</i></a>
|
89 |
+
</div>
|
90 |
+
</div>
|
91 |
+
|
92 |
+
<div class="row">
|
93 |
+
<div class="input-field col s12 m10 l6 right-align">
|
94 |
+
<a class="waves-effect waves-light btn" onclick="next_tab('#database_options');"><i
|
95 |
+
class="material-icons right">skip_next</i>Next</a>
|
96 |
+
</div>
|
97 |
+
</div>
|
98 |
+
</div>
|
99 |
+
|
100 |
+
<?php if ( $xcloner_settings->get_enable_mysql_backup() ): ?>
|
101 |
+
<div id="database_options" class="tab-content">
|
102 |
+
<h2><?php echo __( 'Select database data to include in the backup', 'xcloner-backup-and-restore' ) ?>:
|
103 |
+
<a class="btn-floating tooltipped btn-small" data-position="right" data-delay="50"
|
104 |
+
data-tooltip="<?php echo __( 'Enable the \'Backup only WP tables\' setting if you don\'t want to show all other databases and tables not related to this Wordpress install', 'xcloner-backup-and-restore' ); ?>"
|
105 |
+
data-tooltip-id=""><i class="material-icons">help_outline</i></a>
|
106 |
+
</h2>
|
107 |
+
|
108 |
+
<!-- database/tables tree -->
|
109 |
+
<div class="row">
|
110 |
+
<div class="col s12 l6">
|
111 |
+
<div id="jstree_database_container"></div>
|
112 |
+
</div>
|
113 |
+
</div>
|
114 |
+
|
115 |
+
<div class="row">
|
116 |
+
<div class="input-field col s12 m10 l6 right-align">
|
117 |
+
<a class="waves-effect waves-light btn" onclick="next_tab('#files_options');"><i
|
118 |
+
class="material-icons right">skip_next</i>Next</a>
|
119 |
+
</div>
|
120 |
+
</div>
|
121 |
+
|
122 |
+
</div>
|
123 |
<?php endif ?>
|
124 |
+
|
125 |
+
<div id="files_options" class="tab-content">
|
126 |
+
<h2><?php echo __( 'Select from below the files/folders you want to exclude from your Backup Archive', 'xcloner-backup-and-restore' ) ?>
|
127 |
+
:
|
128 |
+
<a class="btn-floating tooltipped btn-small" data-position="bottom" data-delay="50" data-html="true"
|
129 |
+
data-tooltip="<?php echo __( 'You can navigate below through all your site structure(Backup Start Location) to exclude any file/folder you need by clicking the checkbox near it. <br />If the checkobx is disabled, then it matches a Regex Exclude File option and it can\'t be unchecked', 'xcloner-backup-and-restore' ); ?>"
|
130 |
+
data-tooltip-id=""><i class="material-icons">help_outline</i></a>
|
131 |
+
</h2>
|
132 |
+
|
133 |
+
<!-- Files System Container -->
|
134 |
+
<div class="row">
|
135 |
+
<div class="col s12 l6">
|
136 |
+
<div id="jstree_files_container"></div>
|
137 |
+
</div>
|
138 |
+
</div>
|
139 |
+
|
140 |
+
<div class="row">
|
141 |
+
<div class="input-field col s12 m10 l6 right-align">
|
142 |
+
<a class="waves-effect waves-light btn" onclick="next_tab('#generate_backup');"><i
|
143 |
+
class="material-icons right">skip_next</i>Next</a>
|
144 |
+
</div>
|
145 |
+
</div>
|
146 |
+
|
147 |
+
</div>
|
148 |
+
<div id="generate_backup" class="tab-content">
|
149 |
+
<div class="row ">
|
150 |
+
<div class="col s12 l10 center action-buttons">
|
151 |
+
<a class="waves-effect waves-light btn-large teal darken-1 start"
|
152 |
+
onclick="xcloner_backup.start_backup()">Start Backup<i
|
153 |
+
class="material-icons left">forward</i></a>
|
154 |
+
<a class="waves-effect waves-light btn-large teal darken-1 restart"
|
155 |
+
onclick="xcloner_backup.restart_backup()">Restart Backup<i class="material-icons left">cached</i></a>
|
156 |
+
<a class="waves-effect waves-light btn-large red darken-1 cancel"
|
157 |
+
onclick="xcloner_backup.cancel_backup()">Cancel Backup<i
|
158 |
+
class="material-icons left">cancel</i></a>
|
159 |
+
</div>
|
160 |
+
<div class="col l10 s12">
|
161 |
+
<ul class="backup-status collapsible" data-collapsible="accordion">
|
162 |
+
<li class="file-system">
|
163 |
+
<div class="collapsible-header">
|
164 |
+
<i class="material-icons">folder</i><?php echo __( 'Scanning The File System...', 'xcloner-backup-and-restore' ) ?>
|
165 |
+
|
166 |
+
<p class="right"><?php echo sprintf( __( 'Found %s files (%s)', 'xcloner-backup-and-restore' ), '<span class="file-counter">0</span>', '<span class="file-size-total">0</span>MB' ) ?></p>
|
167 |
+
|
168 |
+
<div>
|
169 |
+
<p class="right"><span class="last-logged-file"></span></p>
|
170 |
+
</div>
|
171 |
+
|
172 |
+
<div class="progress">
|
173 |
+
<div class="indeterminate"></div>
|
174 |
+
</div>
|
175 |
+
</div>
|
176 |
+
<div class="collapsible-body status-body"></div>
|
177 |
+
</li>
|
178 |
+
<?php if ( $xcloner_settings->get_enable_mysql_backup() ): ?>
|
179 |
+
<li class="database-backup">
|
180 |
+
<div class="collapsible-header">
|
181 |
+
<i class="material-icons">storage</i><?php echo __( 'Generating the Mysql Backup...', 'xcloner-backup-and-restore' ) ?>
|
182 |
+
|
183 |
+
<p class="right"><?php echo sprintf( __( 'Found %s tables in %s databases (%s)', 'xcloner-backup-and-restore' ), '<span class="table-counter">0</span>', '<span class="database-counter">0</span>', '<span data-processed="0" class="total-records">0</span> records', 'xcloner-backup-and-restore' ) ?></p>
|
184 |
+
|
185 |
+
<div>
|
186 |
+
<p class="right"><span class="last-logged-table"></span></p>
|
187 |
+
</div>
|
188 |
+
|
189 |
+
<div class="progress">
|
190 |
+
<div class="determinate" style="width:0%"></div>
|
191 |
+
</div>
|
192 |
+
</div>
|
193 |
+
<div class="collapsible-body status-body">
|
194 |
+
<div class="row">
|
195 |
+
<div class="col l7 s12">
|
196 |
+
<ul class="logged-tables"></ul>
|
197 |
+
</div>
|
198 |
+
<div class="col l5 s12">
|
199 |
+
<ul class="logged-databases right"></ul>
|
200 |
+
</div>
|
201 |
+
</div>
|
202 |
+
</div>
|
203 |
+
</li>
|
204 |
+
<?php endif ?>
|
205 |
+
<li class="files-backup">
|
206 |
+
<div class="collapsible-header">
|
207 |
+
<i class="material-icons">archive</i><?php echo __( 'Adding Files to Archive...', 'xcloner-backup-and-restore' ) ?>
|
208 |
+
|
209 |
+
<p class="right"><?php echo sprintf( __( 'Adding %s files (%s)', 'xcloner-backup-and-restore' ), '<span class="file-counter">0</span>', '<span data-processed="0" class="file-size-total">0</span>MB' ) ?></p>
|
210 |
+
|
211 |
+
<div>
|
212 |
+
<p class="right"><span class="last-logged-file"></span></p>
|
213 |
+
</div>
|
214 |
+
|
215 |
+
<div class="progress">
|
216 |
+
<div class="determinate" style="width:0%"></div>
|
217 |
+
</div>
|
218 |
+
</div>
|
219 |
+
<div class="collapsible-body status-body">
|
220 |
+
<div class="row">
|
221 |
+
<div class="col l3 s12">
|
222 |
+
<h2><?php echo __( "Backup Parts", 'xcloner-backup-and-restore' ) ?>: </h2>
|
223 |
+
</div>
|
224 |
+
<div class="col l9 s12">
|
225 |
+
<ul class="backup-name"></ul>
|
226 |
+
</div>
|
227 |
+
</div>
|
228 |
+
</div>
|
229 |
+
</li>
|
230 |
+
<li class="backup-done">
|
231 |
+
<div class="collapsible-header">
|
232 |
+
<i class="material-icons">done</i><?php echo __( 'Backup Done', 'xcloner-backup-and-restore' ) ?>
|
233 |
+
|
234 |
+
<p class="right">
|
235 |
+
<?php if ( sizeof( $available_storages ) ): ?>
|
236 |
+
<a href="#" class="cloud-upload"
|
237 |
+
title="<?php echo __( "Send Backup To Remote Storage", 'xcloner-backup-and-restore' ) ?>"><i
|
238 |
+
class="material-icons">cloud_upload</i></a>
|
239 |
+
<?php endif ?>
|
240 |
+
<a href="#" class="download"
|
241 |
+
title="<?php echo __( "Download Backup", 'xcloner-backup-and-restore' ) ?>"><i
|
242 |
+
class="material-icons">file_download</i></a>
|
243 |
+
<a href="#" class="list-backup-content"
|
244 |
+
title="<?php echo __( "List Backup Content", 'xcloner-backup-and-restore' ) ?>"><i
|
245 |
+
class="material-icons">folder_open</i></a>
|
246 |
+
</p>
|
247 |
+
|
248 |
+
<div class="progress">
|
249 |
+
<div class="determinate" style="width:100%"></div>
|
250 |
+
</div>
|
251 |
+
|
252 |
+
</div>
|
253 |
+
<div class="collapsible-body center-align">
|
254 |
+
<div class="row">
|
255 |
+
<h5><?php echo __( "Thank you for using XCloner.", 'xcloner-backup-and-restore' ) ?></h5>
|
256 |
+
<h6><?php echo sprintf( __( "We would love to hear about your experience in the %s.", 'xcloner-backup-and-restore' ), '<a href="https://wordpress.org/support/plugin/xcloner-backup-and-restore/reviews/" target="_blank">Wordpress XCloner Reviews Section</a>' ) ?></h6>
|
257 |
+
<a class="twitter-follow-button" href="https://twitter.com/thinkovi"
|
258 |
+
data-show-count="false">Follow @thinkovi</a>
|
259 |
+
<script src="//platform.twitter.com/widgets.js" async="" charset="utf-8"></script>
|
260 |
+
|
261 |
+
<br/>
|
262 |
+
<!-- XCLONER SPONSORS AREA-->
|
263 |
+
<!-- END XCLONER SPONSORS AREA-->
|
264 |
+
</div>
|
265 |
+
</div>
|
266 |
+
</li>
|
267 |
+
</ul>
|
268 |
+
</div>
|
269 |
+
|
270 |
+
</div>
|
271 |
+
</div>
|
272 |
+
|
273 |
+
<div id="schedule_backup" class="tab-content">
|
274 |
+
|
275 |
+
<div class="row">
|
276 |
+
<div id="schedule_backup_success" class="col s12 l6 updated settings-error notice is-dismissible">
|
277 |
+
<p><strong><?php echo __( 'Schedule Saved', 'xcloner-backup-and-restore' ) ?></strong></p>
|
278 |
+
<button type="button" class="notice-dismiss"><span
|
279 |
+
class="screen-reader-text"><?php echo __( '(Dismiss this notice.', 'xcloner-backup-and-restore' ) ?></span>
|
280 |
+
</button>
|
281 |
+
</div>
|
282 |
+
</div>
|
283 |
+
|
284 |
+
<div class="row">
|
285 |
+
<div class="input-field inline col s12 l7">
|
286 |
+
<input type="text" id="schedule_name" class="" name="schedule_name" required>
|
287 |
+
<label for="schedule_name"><?php echo __( 'Schedule Name', 'xcloner-backup-and-restore' ) ?></label>
|
288 |
+
</div>
|
289 |
+
</div>
|
290 |
+
|
291 |
+
<div class="row">
|
292 |
+
<div class="input-field inline col s12 m8 l4">
|
293 |
+
<input type="datetime-local" id="datepicker" class="datepicker" name="schedule_start_date">
|
294 |
+
<label for="datepicker"><?php echo __( 'Schedule Backup To Start On:', 'xcloner-backup-and-restore' ) ?></label>
|
295 |
+
</div>
|
296 |
+
<div class="input-field inline col s12 m4 l3">
|
297 |
+
<input id="timepicker_ampm_dark" class="timepicker" type="time" name="schedule_start_time">
|
298 |
+
<label for="timepicker_ampm_dark"><?php echo __( 'At:', 'xcloner-backup-and-restore' ) ?></label>
|
299 |
+
</div>
|
300 |
+
</div>
|
301 |
+
|
302 |
+
<!--
|
303 |
<div class="row">
|
304 |
<div class="input-field inline col s10 m11 l7">
|
305 |
<select id="backup_type" class="" name="backup_type">
|
306 |
+
<option value=""><?php echo __( "Full Backup", "xcloner-backup-and-restore" ); ?></option>
|
307 |
+
<option value="diff"><?php echo __( "Differential Backups", "xcloner-backup-and-restore" ); ?></option>
|
308 |
+
<option value="full_diff"><?php echo __( "Full Backup + Differential Backups", "xcloner-backup-and-restore" ); ?></option>
|
309 |
</select>
|
310 |
+
<label for="backup_type"><?php echo __( 'Scheduled Backup Type', 'xcloner-backup-and-restore' ) ?></label>
|
311 |
</div>
|
312 |
<div class="col s2 m1">
|
313 |
<a class="btn-floating tooltipped btn-small" data-html="true" data-position="center" data-delay="50" data-tooltip="<ul style='max-width:760px; text-align:left;'>
|
314 |
+
<li><?php echo __( "Full Backup = it will generate a full backup of all included files each time schedule runs", "xcloner-backup-and-restore" ); ?></li>
|
315 |
+
<li><?php echo __( "Differentials Backups = backups will include only changed files since the schedule started to run", "xcloner-backup-and-restore" ); ?></li>
|
316 |
+
<li><?php echo __( "Full Backup + Differential Backups = the first time schedule runs, it will create a full backup and all next scheduled backups will include only files created/modified since that last full backup; a full backup is recreated when the number of changed files is bigger than the 'Differetial Backups Max Days' XCloner option.", "xcloner-backup-and-restore" ); ?></li>
|
317 |
</ul>"><i class="material-icons">help_outline</i></a>
|
318 |
</div>
|
319 |
</div>
|
320 |
-->
|
321 |
+
<div class="row">
|
322 |
+
<div class="input-field col s12 l7">
|
323 |
+
<select name="schedule_frequency" id="schedule_frequency" class="validate" required>
|
324 |
+
<option value="" disabled
|
325 |
+
selected><?php echo __( 'please select', 'xcloner-backup-and-restore' ) ?></option>
|
326 |
<?php
|
327 |
$schedules = $xcloner_scheduler->get_available_intervals();
|
328 |
+
|
329 |
+
foreach ( $schedules as $key => $schedule ) {
|
330 |
+
?>
|
331 |
+
<option value="<?php echo $key ?>"><?php echo $schedule['display'] ?></option>
|
332 |
+
<?php
|
|
|
333 |
}
|
334 |
+
?>
|
335 |
+
</select>
|
336 |
+
<label><?php echo __( 'Schedule Frequency', 'xcloner-backup-and-restore' ) ?></label>
|
337 |
+
</div>
|
338 |
+
</div>
|
339 |
+
|
340 |
+
<?php if ( sizeof( $available_storages ) ): ?>
|
341 |
+
<div class="row">
|
342 |
+
<div class="input-field col s12 m12 l7">
|
343 |
+
<select name="schedule_storage" id="schedule_storage" class="validate">
|
344 |
+
<option value="" selected><?php echo __( 'none', 'xcloner-backup-and-restore' ) ?></option>
|
345 |
+
<?php foreach ( $available_storages as $storage => $text ): ?>
|
346 |
+
<option value="<?php echo $storage ?>"><?php echo $text ?></option>
|
347 |
+
<?php endforeach ?>
|
348 |
+
</select>
|
349 |
+
<label><?php echo __( 'Send To Remote Storage', 'xcloner-backup-and-restore' ) ?></label>
|
350 |
+
</div>
|
351 |
+
</div>
|
352 |
+
<?php endif ?>
|
353 |
+
<div class="row">
|
354 |
+
<div class="col s12 l7">
|
355 |
+
<button class="right btn waves-effect waves-light submit_schedule" type="submit"
|
356 |
+
name="action"><?php echo __( "Submit", 'xcloner-backup-and-restore' ) ?>
|
357 |
+
<i class="material-icons right">send</i>
|
358 |
+
</button>
|
359 |
+
</div>
|
360 |
+
</div>
|
361 |
+
</div>
|
362 |
+
</div>
|
363 |
</form>
|
364 |
|
365 |
<!-- Error Modal Structure -->
|
366 |
<div id="error_modal" class="modal">
|
367 |
+
<a title="Online Help" href="https://wordpress.org/support/plugin/xcloner-backup-and-restore" target="_blank"><i
|
368 |
+
class="material-icons medium right">help</i></a>
|
369 |
+
<div class="modal-content">
|
370 |
+
<h4 class="title_line"><span class="title"></span></h4>
|
371 |
+
<!--<h5 class="title_line"><?php echo __( 'Message' ) ?>: <span class="msg.old"></span></h5>-->
|
372 |
+
<h5><?php echo __( 'Response Code', 'xcloner-backup-and-restore' ) ?>: <span class="status"></span></h5>
|
373 |
+
<textarea class="body" rows="5"></textarea>
|
374 |
+
</div>
|
375 |
+
<div class="modal-footer">
|
376 |
+
<a class=" modal-action modal-close waves-effect waves-green btn-flat red darken-2"><?php echo __( 'Close', 'xcloner-backup-and-restore' ) ?></a>
|
377 |
+
</div>
|
378 |
</div>
|
379 |
|
380 |
<!-- List Backup Content Modal-->
|
381 |
<div id="backup_cotent_modal" class="modal">
|
382 |
+
<div class="modal-content">
|
383 |
+
<h4><?php echo sprintf( __( "Listing Backup Content ", 'xcloner-backup-and-restore' ), "" ) ?></h4>
|
384 |
+
<h5 class="backup-name"></h5>
|
385 |
+
|
386 |
+
<div class="progress">
|
387 |
+
<div class="indeterminate"></div>
|
388 |
+
</div>
|
389 |
+
<ul class="files-list"></ul>
|
390 |
+
</div>
|
391 |
</div>
|
392 |
|
393 |
<!-- Remote Storage Modal Structure -->
|
394 |
<div id="remote_storage_modal" class="modal">
|
395 |
+
<form method="POST" class="remote-storage-form">
|
396 |
+
<input type="hidden" name="file" class="backup_name">
|
397 |
+
<div class="modal-content">
|
398 |
+
<h4><?php echo __( "Remote Storage Transfer", 'xcloner-backup-and-restore' ) ?></h4>
|
399 |
+
<p>
|
400 |
+
<?php if ( sizeof( $available_storages ) ): ?>
|
401 |
+
<div class="row">
|
402 |
+
<div class="col s12 label">
|
403 |
+
<label><?php echo __( sprintf( 'Send %s to remote storage', "<span class='backup_name'></span>" ), 'xcloner-backup-and-restore' ) ?></label>
|
404 |
+
</div>
|
405 |
+
<div class="input-field col s8 m10">
|
406 |
+
<select name="transfer_storage" id="transfer_storage" class="validate" required>
|
407 |
+
<option value=""
|
408 |
+
selected><?php echo __( 'please select...', 'xcloner-backup-and-restore' ) ?></option>
|
409 |
+
<?php foreach ( $available_storages as $storage => $text ): ?>
|
410 |
+
<option value="<?php echo $storage ?>"><?php echo $text ?></option>
|
411 |
+
<?php endforeach ?>
|
412 |
+
</select>
|
413 |
+
|
414 |
+
</div>
|
415 |
+
<div class="s4 m2 right">
|
416 |
+
<button type="submit" class="upload-submit btn-floating btn-large waves-effect waves-light teal"><i
|
417 |
+
class="material-icons">file_upload</i></submit>
|
418 |
+
</div>
|
419 |
+
</div>
|
420 |
+
<div class="row status">
|
421 |
+
<?php echo __( "Uploading backup to the selected remote storage...", 'xcloner-backup-and-restore' ) ?>
|
422 |
+
<span class="status-text"></span>
|
423 |
+
<div class="progress">
|
424 |
+
<div class="indeterminate"></div>
|
425 |
+
</div>
|
426 |
+
</div>
|
427 |
+
<?php endif ?>
|
428 |
+
</p>
|
429 |
+
</div>
|
430 |
+
</form>
|
431 |
</div>
|
432 |
+
|
433 |
<script>
|
434 |
+
jQuery(function () {
|
435 |
+
|
436 |
+
jQuery('.col select').material_select();
|
437 |
+
jQuery("select[required]").css({display: "block", height: 0, padding: 0, width: 0, position: 'absolute'});
|
438 |
+
jQuery(".backup-done .cloud-upload").on("click", function (e) {
|
439 |
+
var xcloner_manage_backups = new Xcloner_Manage_Backups();
|
440 |
+
var hash = jQuery(this).attr('href');
|
441 |
+
var id = hash.substr(1)
|
442 |
+
|
443 |
+
e.preventDefault();
|
444 |
+
xcloner_manage_backups.cloud_upload(id)
|
445 |
+
})
|
446 |
+
|
447 |
+
jQuery("#generate_backup_form").on("submit", function () {
|
448 |
+
|
449 |
+
xcloner_backup.params = xcloner_backup.get_form_params();
|
450 |
+
var data = JSON.stringify(xcloner_backup.params);
|
451 |
+
|
452 |
+
xcloner_backup.set_cancel(false);
|
453 |
+
|
454 |
+
xcloner_backup.do_ajax(data, "save_schedule")
|
455 |
+
return false;
|
456 |
+
})
|
457 |
+
|
458 |
+
jQuery(".backup-done .download").on("click", function (e) {
|
459 |
+
var xcloner_manage_backups = new Xcloner_Manage_Backups();
|
460 |
+
var hash = jQuery(this).attr('href');
|
461 |
+
var id = hash.substr(1)
|
462 |
+
|
463 |
+
e.preventDefault();
|
464 |
+
xcloner_manage_backups.download_backup_by_name(id)
|
465 |
+
})
|
466 |
+
|
467 |
+
jQuery(".backup-done .list-backup-content").on("click", function (e) {
|
468 |
+
var xcloner_manage_backups = new Xcloner_Manage_Backups();
|
469 |
+
var hash = jQuery(this).attr('href');
|
470 |
+
var id = hash.substr(1)
|
471 |
+
|
472 |
+
e.preventDefault();
|
473 |
+
xcloner_manage_backups.list_backup_content(id)
|
474 |
+
})
|
475 |
+
|
476 |
+
jQuery('.timepicker').pickatime({
|
477 |
+
default: 'now',
|
478 |
+
min: [7, 30],
|
479 |
+
twelvehour: false, // change to 12 hour AM/PM clock from 24 hour
|
480 |
+
donetext: 'OK',
|
481 |
+
autoclose: false,
|
482 |
+
vibrate: true // vibrate the device when dragging clock hand
|
483 |
+
});
|
484 |
+
|
485 |
+
var date_picker = jQuery('.datepicker').pickadate({
|
486 |
+
format: 'd mmmm yyyy',
|
487 |
+
selectMonths: true, // Creates a dropdown to control month
|
488 |
+
selectYears: 15, // Creates a dropdown of 15 years to control year
|
489 |
+
min: +0.1,
|
490 |
+
onSet: function () {
|
491 |
+
//this.close();
|
492 |
+
}
|
493 |
+
});
|
494 |
+
|
495 |
+
var date_picker_allowed = jQuery('.datepicker_max_today').pickadate({
|
496 |
+
format: 'd mmmm yyyy',
|
497 |
+
selectMonths: true, // Creates a dropdown to control month
|
498 |
+
selectYears: 15, // Creates a dropdown of 15 years to control year
|
499 |
+
max: +0.1,
|
500 |
+
onSet: function () {
|
501 |
+
//this.close();
|
502 |
+
}
|
503 |
+
});
|
504 |
+
|
505 |
+
<?php if($xcloner_settings->get_enable_mysql_backup()):?>
|
506 |
+
jQuery('#jstree_database_container').jstree({
|
507 |
+
'core': {
|
508 |
+
'check_callback': true,
|
509 |
+
'data': {
|
510 |
+
'method': 'POST',
|
511 |
+
'dataType': 'json',
|
512 |
+
'url': ajaxurl,
|
513 |
+
'data': function (node) {
|
514 |
+
var data = {
|
515 |
+
'action': 'get_database_tables_action',
|
516 |
+
'id': node.id
|
517 |
+
}
|
518 |
+
return data;
|
519 |
+
}
|
520 |
+
},
|
521 |
+
|
522 |
+
'error': function (err) {
|
523 |
+
//alert("We have encountered a communication error with the server, please review the javascript console.");
|
524 |
+
var json = jQuery.parseJSON(err.data)
|
525 |
+
show_ajax_error("Error Loading Database Structure ", err.reason, json.xhr);
|
526 |
+
},
|
527 |
+
|
528 |
+
'strings': {'Loading ...': 'Loading the database structure...'},
|
529 |
+
'themes': {
|
530 |
+
"variant": "default"
|
531 |
+
},
|
532 |
+
},
|
533 |
+
'checkbox': {
|
534 |
+
three_state: true
|
535 |
+
},
|
536 |
+
'plugins': [
|
537 |
+
"checkbox",
|
538 |
+
"massload",
|
539 |
+
"search",
|
540 |
+
//"sort",
|
541 |
+
//"state",
|
542 |
+
"types",
|
543 |
+
"unique",
|
544 |
+
"wholerow"
|
545 |
+
]
|
546 |
+
});
|
547 |
+
<?php endif ?>
|
548 |
+
|
549 |
+
jQuery('#jstree_files_container').jstree({
|
550 |
+
'core': {
|
551 |
+
'check_callback': true,
|
552 |
+
'data': {
|
553 |
+
'method': 'POST',
|
554 |
+
'dataType': 'json',
|
555 |
+
'url': ajaxurl,
|
556 |
+
'data': function (node) {
|
557 |
+
var data = {
|
558 |
+
'action': 'get_file_system_action',
|
559 |
+
'id': node.id
|
560 |
+
}
|
561 |
+
return data;
|
562 |
+
}
|
563 |
+
},
|
564 |
+
|
565 |
+
'error': function (err) {
|
566 |
+
//alert("We have encountered a communication error with the server, please review the javascript console.");
|
567 |
+
var json = jQuery.parseJSON(err.data)
|
568 |
+
show_ajax_error("Error Loading Files Structure ", err.reason, json.xhr);
|
569 |
+
},
|
570 |
+
|
571 |
+
'strings': {'Loading ...': 'Loading the database structure...'},
|
572 |
+
'themes': {
|
573 |
+
"variant": "default"
|
574 |
+
},
|
575 |
+
},
|
576 |
+
'checkbox': {
|
577 |
+
three_state: true
|
578 |
+
},
|
579 |
+
'plugins': [
|
580 |
+
"checkbox",
|
581 |
+
"massload",
|
582 |
+
"search",
|
583 |
+
//"sort",
|
584 |
+
//"state",
|
585 |
+
"types",
|
586 |
+
"unique",
|
587 |
+
"wholerow"
|
588 |
+
]
|
589 |
+
});
|
590 |
+
});
|
591 |
|
592 |
|
593 |
</script>
|
admin/partials/xcloner_init_page.php
CHANGED
@@ -12,11 +12,11 @@
|
|
12 |
* @subpackage Xcloner/admin/partials
|
13 |
*/
|
14 |
|
15 |
-
$requirements
|
16 |
-
$xcloner_settings
|
17 |
-
$xcloner_file_system
|
18 |
-
$logger
|
19 |
-
$xcloner_scheduler
|
20 |
|
21 |
$logger_content = $logger->getLastDebugLines();
|
22 |
|
@@ -25,219 +25,250 @@ $time_format = get_option( 'time_format' );
|
|
25 |
|
26 |
//$xcloner_file_system->cleanup_tmp_directories();
|
27 |
|
28 |
-
if($requirements->check_backup_ready_status())
|
29 |
-
|
30 |
-
$latest_backup = $xcloner_file_system->get_latest_backup();
|
31 |
$xcloner_file_system->backup_storage_cleanup();
|
32 |
}
|
33 |
?>
|
34 |
|
35 |
<div class="row">
|
36 |
-
|
37 |
-
|
38 |
-
<?php echo __('Backup Dashboard', 'xcloner-backup-and-restore') ?>
|
39 |
-
|
40 |
-
|
41 |
</div>
|
42 |
|
43 |
-
<?php if(isset($latest_backup['timestamp']) and $latest_backup['timestamp'] < strtotime("-1 day")): ?>
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
<?php
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
69 |
<?php endif ?>
|
70 |
|
71 |
|
72 |
-
|
73 |
<!-- This file should primarily consist of HTML with a little bit of PHP. -->
|
74 |
<div class="row dashboard">
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
* @subpackage Xcloner/admin/partials
|
13 |
*/
|
14 |
|
15 |
+
$requirements = $this->get_xcloner_container()->get_xcloner_requirements();
|
16 |
+
$xcloner_settings = $this->get_xcloner_container()->get_xcloner_settings();
|
17 |
+
$xcloner_file_system = $this->get_xcloner_container()->get_xcloner_filesystem();
|
18 |
+
$logger = $this->get_xcloner_container()->get_xcloner_logger();
|
19 |
+
$xcloner_scheduler = $this->get_xcloner_container()->get_xcloner_scheduler();
|
20 |
|
21 |
$logger_content = $logger->getLastDebugLines();
|
22 |
|
25 |
|
26 |
//$xcloner_file_system->cleanup_tmp_directories();
|
27 |
|
28 |
+
if ( $requirements->check_backup_ready_status() ) {
|
29 |
+
$latest_backup = $xcloner_file_system->get_latest_backup();
|
|
|
30 |
$xcloner_file_system->backup_storage_cleanup();
|
31 |
}
|
32 |
?>
|
33 |
|
34 |
<div class="row">
|
35 |
+
<div class="col s12">
|
36 |
+
<h5 class="left-align">
|
37 |
+
<?php echo __( 'Backup Dashboard', 'xcloner-backup-and-restore' ) ?>
|
38 |
+
</h5>
|
39 |
+
</div>
|
40 |
</div>
|
41 |
|
42 |
+
<?php if ( isset( $latest_backup['timestamp'] ) and $latest_backup['timestamp'] < strtotime( "-1 day" ) ): ?>
|
43 |
+
<div id="setting-error-" class="error settings-error notice is-dismissible">
|
44 |
+
<p><strong>
|
45 |
+
<?php echo __( 'Your latest backup is older than 24 hours, please create a new backup to keep your site protected.', 'xcloner-backup-and-restore' ) ?>
|
46 |
+
</strong>
|
47 |
+
</p>
|
48 |
+
<button type="button" class="notice-dismiss"><span class="screen-reader-text">Dismiss this notice.</span>
|
49 |
+
</button>
|
50 |
+
</div>
|
51 |
+
<?php endif ?>
|
52 |
+
|
53 |
+
<?php if ( ! isset( $latest_backup['timestamp'] ) ): ?>
|
54 |
+
<div id="setting-error-" class="error settings-error notice is-dismissible">
|
55 |
+
<p><strong>
|
56 |
+
<?php echo __( 'You have no backup that I could find, please generate a new backup to keep your site protected.', 'xcloner-backup-and-restore' ) ?>
|
57 |
+
</strong>
|
58 |
+
</p>
|
59 |
+
<button type="button" class="notice-dismiss"><span class="screen-reader-text">Dismiss this notice.</span>
|
60 |
+
</button>
|
61 |
+
</div>
|
62 |
+
<?php endif ?>
|
63 |
+
|
64 |
+
<?php if ( ! $requirements->check_backup_ready_status() ): ?>
|
65 |
+
<div id="setting-error-" class="error settings-error notice is-dismissible">
|
66 |
+
<p><strong>
|
67 |
+
<?php echo __( 'Backup system not ready, please check and fix the issues marked in red', 'xcloner-backup-and-restore' ) ?>
|
68 |
+
</strong>
|
69 |
+
</p>
|
70 |
+
<button type="button" class="notice-dismiss"><span class="screen-reader-text">Dismiss this notice.</span>
|
71 |
+
</button>
|
72 |
+
</div>
|
73 |
+
|
74 |
<?php endif ?>
|
75 |
|
76 |
|
|
|
77 |
<!-- This file should primarily consist of HTML with a little bit of PHP. -->
|
78 |
<div class="row dashboard">
|
79 |
+
<div class="col s12 m12 l7">
|
80 |
+
|
81 |
+
<div class="row">
|
82 |
+
|
83 |
+
<ul class="collapsible xcloner-debugger" data-collapsible="accordion">
|
84 |
+
|
85 |
+
<li class="active">
|
86 |
+
<div class="collapsible-header active"><i class="material-icons">info</i>Backup Status</div>
|
87 |
+
<div class="collapsible-body">
|
88 |
+
<div class="" id="backup-status">
|
89 |
+
<div class="row">
|
90 |
+
<h5><?php echo __( "Latest Backup", 'xcloner-backup-and-restore' ) ?></h5>
|
91 |
+
<blockquote>
|
92 |
+
<?php if ( $latest_backup ): ?>
|
93 |
+
<div class="item">
|
94 |
+
<div class="title"><?php echo __( "Backup Name", 'xcloner-backup-and-restore' ) ?>
|
95 |
+
:
|
96 |
+
</div>
|
97 |
+
<?php echo $latest_backup['basename'] ?>
|
98 |
+
</div>
|
99 |
+
<div class="item">
|
100 |
+
<div class="title">
|
101 |
+
<?php echo __( "Backup Size", 'xcloner-backup-and-restore' ) ?>:
|
102 |
+
</div>
|
103 |
+
<?php echo size_format( $latest_backup['size'] ) ?>
|
104 |
+
</div>
|
105 |
+
<div class="item">
|
106 |
+
<div class="title"><?php echo __( "Backup Date", 'xcloner-backup-and-restore' ) ?>
|
107 |
+
:
|
108 |
+
</div>
|
109 |
+
<?php
|
110 |
+
echo date( $date_format . " " . $time_format, $latest_backup['timestamp'] + ( get_option( 'gmt_offset' ) * HOUR_IN_SECONDS ) )
|
111 |
+
?>
|
112 |
+
</div>
|
113 |
+
<?php else: ?>
|
114 |
+
<div class="item">
|
115 |
+
<div class="title"><?php echo __( "No Backup Yet", 'xcloner-backup-and-restore' ) ?></div>
|
116 |
+
</div>
|
117 |
+
<?php endif ?>
|
118 |
+
</blockquote>
|
119 |
+
<div>
|
120 |
+
<h5><?php echo __( "Backup Storage Usage", 'xcloner-backup-and-restore' ) ?></h5>
|
121 |
+
<blockquote>
|
122 |
+
<div class="item">
|
123 |
+
<div class="title"><?php echo __( "Total Size", 'xcloner-backup-and-restore' ) ?>
|
124 |
+
:
|
125 |
+
</div>
|
126 |
+
<?php echo size_format( $xcloner_file_system->get_storage_usage() ); ?>
|
127 |
+
</div>
|
128 |
+
</blockquote>
|
129 |
+
<h5><?php echo __( "Next Scheduled Backup", 'xcloner-backup-and-restore' ) ?></h5>
|
130 |
+
<blockquote>
|
131 |
+
<div class="item">
|
132 |
+
<?php
|
133 |
+
$list = ( $xcloner_scheduler->get_next_run_schedule() );
|
134 |
+
|
135 |
+
if ( is_array( $list ) ) {
|
136 |
+
$xcloner_file_system->sort_by( $list, "next_run_time", "asc" );
|
137 |
+
}
|
138 |
+
|
139 |
+
if ( isset( $list[0] ) ) {
|
140 |
+
$latest_schedule = $list[0];
|
141 |
+
}
|
142 |
+
?>
|
143 |
+
<?php if ( isset( $latest_schedule->name ) ): ?>
|
144 |
+
<div class="title"><?php echo __( "Schedule Name", 'xcloner-backup-and-restore' ) ?>
|
145 |
+
:
|
146 |
+
</div>
|
147 |
+
<?php echo $latest_schedule->name; ?>
|
148 |
+
<?php endif; ?>
|
149 |
+
</div>
|
150 |
+
<div class="item">
|
151 |
+
<div class="title"><?php echo __( "Next Call", 'xcloner-backup-and-restore' ) ?>
|
152 |
+
:
|
153 |
+
</div>
|
154 |
+
<?php if ( isset( $latest_schedule->next_run_time ) ) {
|
155 |
+
echo date( $date_format . " " . $time_format, $latest_schedule->next_run_time );
|
156 |
+
} else {
|
157 |
+
echo __( "Unscheduled", 'xcloner-backup-and-restore' );
|
158 |
+
}
|
159 |
+
?>
|
160 |
+
</div>
|
161 |
+
</blockquote>
|
162 |
+
</div>
|
163 |
+
</div>
|
164 |
+
</li>
|
165 |
+
|
166 |
+
<?php if ( $xcloner_settings->get_xcloner_option( 'xcloner_enable_log' ) ) : ?>
|
167 |
+
<li class="active">
|
168 |
+
<div class="collapsible-header active">
|
169 |
+
<i class="material-icons">bug_report</i><?php echo __( 'XCloner Debugger', 'xcloner-backup-and-restore' ) ?>
|
170 |
+
<div class="right">
|
171 |
+
<a href="#<?php echo $logger_basename = basename( $logger->get_main_logger_url() ) ?>"
|
172 |
+
class="download-logger" title="<?php echo $logger_basename ?>">
|
173 |
+
<span class="shorten_string"><?php echo $logger_basename ?> </span>
|
174 |
+
</a>
|
175 |
+
</div>
|
176 |
+
</div>
|
177 |
+
<div class="collapsible-body">
|
178 |
+
<div class="console" id="xcloner-console"><?php if ( $logger_content ) {
|
179 |
+
echo implode( "<br />\n", array_reverse( $logger_content ) );
|
180 |
+
} ?></div>
|
181 |
+
</div>
|
182 |
+
</li>
|
183 |
+
<script>
|
184 |
+
jQuery(document).ready(function () {
|
185 |
+
var objDiv = document.getElementById("xcloner-console");
|
186 |
+
objDiv.scrollTop = objDiv.scrollHeight;
|
187 |
+
/*setInterval(function(){
|
188 |
+
getXclonerLog();
|
189 |
+
}, 2000);*/
|
190 |
+
})
|
191 |
+
</script>
|
192 |
+
<?php endif; ?>
|
193 |
+
|
194 |
+
</ul>
|
195 |
+
|
196 |
+
</div>
|
197 |
+
|
198 |
+
|
199 |
+
</div>
|
200 |
+
<div class="col s12 m12 l5">
|
201 |
+
|
202 |
+
<div class="card blue-grey darken-1 z-depth-4 backup-ready">
|
203 |
+
<div class="card-content white-text">
|
204 |
+
<span class="card-title"><?php echo __( "System Check", 'xcloner-backup-and-restore' ) ?></span>
|
205 |
+
<ul>
|
206 |
+
<li class="card-panel <?php echo( $requirements->check_xcloner_start_path( 1 ) ? "teal" : "red" ) ?> lighten-2">
|
207 |
+
<?php echo __( 'Backup Start Location', 'xcloner-backup-and-restore' ) ?>: <span
|
208 |
+
class="shorten_string "><?php echo $requirements->check_xcloner_start_path(); ?></span>
|
209 |
+
</li>
|
210 |
+
<li class="card-panel <?php echo( $requirements->check_xcloner_store_path( 1 ) ? "teal" : "red" ) ?> lighten-2">
|
211 |
+
<?php echo __( 'Backup Storage Location', 'xcloner-backup-and-restore' ) ?>: <span
|
212 |
+
class="shorten_string"><?php echo $requirements->check_xcloner_store_path(); ?></span>
|
213 |
+
</li>
|
214 |
+
<li class="card-panel <?php echo( $requirements->check_xcloner_tmp_path( 1 ) ? "teal" : "red" ) ?> lighten-2">
|
215 |
+
<?php echo __( 'Temporary Location', 'xcloner-backup-and-restore' ) ?>: <span
|
216 |
+
class="shorten_string"><?php echo $requirements->check_xcloner_tmp_path(); ?></span>
|
217 |
+
</li>
|
218 |
+
|
219 |
+
<li class="card-panel <?php echo( $requirements->check_min_php_version( 1 ) ? "teal" : "red" ) ?> lighten-2">
|
220 |
+
<?php echo __( 'PHP Version Check', 'xcloner-backup-and-restore' ) ?>
|
221 |
+
: <?php echo $requirements->check_min_php_version(); ?>
|
222 |
+
( >= <?php echo $requirements->get_constant( 'min_php_version' ) ?>)
|
223 |
+
</li>
|
224 |
+
<li class="card-panel <?php echo( $requirements->check_safe_mode( 1 ) ? "teal" : "orange" ) ?> lighten-2">
|
225 |
+
<?php echo __( 'PHP Safe Mode', 'xcloner-backup-and-restore' ) ?>
|
226 |
+
: <?php echo $requirements->check_safe_mode(); ?>
|
227 |
+
( <?php echo $requirements->get_constant( 'safe_mode' ) ?>)
|
228 |
+
</li>
|
229 |
+
<li class="card-panel <?php echo( $requirements->check_backup_ready_status() ? "teal" : "red" ) ?> lighten-2">
|
230 |
+
<?php echo( $requirements->check_backup_ready_status() ? __( 'BACKUP READY', 'xcloner-backup-and-restore' ) : __( 'Backup not ready, please check above requirements', 'xcloner-backup-and-restore' ) ) ?>
|
231 |
+
<i class="material-icons right tiny"><?php echo( $requirements->check_backup_ready_status() ? 'thumb_up' : 'thumb_down' ) ?></i>
|
232 |
+
</li>
|
233 |
+
</ul>
|
234 |
+
<ul class="additional_system_info">
|
235 |
+
<li class="card-panel grey darken-1">
|
236 |
+
<?php echo __( 'PHP max_execution_time', 'xcloner-backup-and-restore' ) ?>
|
237 |
+
: <?php echo $requirements->get_max_execution_time(); ?>
|
238 |
+
</li>
|
239 |
+
<li class="card-panel grey darken-1">
|
240 |
+
<?php echo __( 'PHP memory_limit', 'xcloner-backup-and-restore' ) ?>
|
241 |
+
: <?php echo $requirements->get_memory_limit(); ?>
|
242 |
+
</li>
|
243 |
+
<li class="card-panel grey darken-1">
|
244 |
+
<?php echo __( 'PHP open_basedir', 'xcloner-backup-and-restore' ) ?>
|
245 |
+
: <?php echo $requirements->get_open_basedir(); ?>
|
246 |
+
</li>
|
247 |
+
<?php
|
248 |
+
$data = array();
|
249 |
+
if ( $requirements->check_backup_ready_status() ) {
|
250 |
+
$data = $xcloner_file_system->estimate_read_write_time();
|
251 |
+
}
|
252 |
+
?>
|
253 |
+
<li class="card-panel grey darken-1">
|
254 |
+
<?php echo __( 'Reading Time 1MB Block', 'xcloner-backup-and-restore' ) ?>
|
255 |
+
: <?php echo( isset( $data['reading_time'] ) ? $data['reading_time'] : __( "unknown" ) ); ?>
|
256 |
+
</li>
|
257 |
+
<li class="card-panel grey darken-1">
|
258 |
+
<?php echo __( 'Writing Time 1MB Block', 'xcloner-backup-and-restore' ) ?>
|
259 |
+
: <?php echo( isset( $data['writing_time'] ) ? $data['writing_time'] : __( "unknown" ) ); ?>
|
260 |
+
</li>
|
261 |
+
<li class="card-panel grey darken-1">
|
262 |
+
<?php echo __( 'Free Disk Space', 'xcloner-backup-and-restore' ) ?>
|
263 |
+
: <?php echo $requirements->get_free_disk_space();; ?>
|
264 |
+
</li>
|
265 |
+
</ul>
|
266 |
+
</div>
|
267 |
+
<div class="card-action">
|
268 |
+
<a class="waves-effect waves-light btn system_info_toggle blue darken-1"><i class="material-icons left">list</i><?php echo __( 'Toggle Additional System Info', 'xcloner-backup-and-restore' ) ?>
|
269 |
+
</a>
|
270 |
+
</div>
|
271 |
+
</div>
|
272 |
+
|
273 |
+
</div>
|
274 |
+
</div>
|
admin/partials/xcloner_manage_backups_page.php
CHANGED
@@ -1,13 +1,12 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
$xcloner_file_system
|
4 |
-
$xcloner_sanitization
|
5 |
-
$xcloner_remote_storage
|
6 |
-
$storage_selection
|
7 |
-
|
8 |
-
if(isset($_GET['storage_selection']) and $_GET['storage_selection'])
|
9 |
-
|
10 |
-
$storage_selection = $xcloner_sanitization->sanitize_input_as_string($_GET['storage_selection']);
|
11 |
}
|
12 |
|
13 |
$backup_list = $xcloner_file_system->get_backup_archives_list($storage_selection);
|
@@ -18,197 +17,237 @@ $available_storages = $xcloner_remote_storage->get_available_storages();
|
|
18 |
?>
|
19 |
|
20 |
<div class="row">
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
<?php
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
<
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
</
|
177 |
-
|
178 |
-
|
179 |
-
<
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
214 |
|
1 |
<?php
|
2 |
|
3 |
+
$xcloner_file_system = $this->get_xcloner_container()->get_xcloner_filesystem();
|
4 |
+
$xcloner_sanitization = $this->get_xcloner_container()->get_xcloner_sanitization();
|
5 |
+
$xcloner_remote_storage = $this->get_xcloner_container()->get_xcloner_remote_storage();
|
6 |
+
$storage_selection = "";
|
7 |
+
|
8 |
+
if (isset($_GET['storage_selection']) and $_GET['storage_selection']) {
|
9 |
+
$storage_selection = $xcloner_sanitization->sanitize_input_as_string($_GET['storage_selection']);
|
|
|
10 |
}
|
11 |
|
12 |
$backup_list = $xcloner_file_system->get_backup_archives_list($storage_selection);
|
17 |
?>
|
18 |
|
19 |
<div class="row">
|
20 |
+
<div class="col s12 m6 l9">
|
21 |
+
<h1><?= esc_html(get_admin_page_title()); ?></h1>
|
22 |
+
</div>
|
23 |
+
<?php if (sizeof($available_storages)): ?>
|
24 |
+
<div class="col s12 m6 l3 remote-storage-selection">
|
25 |
+
<select name="storage_selection" id="storage_selection" class="validate" required>
|
26 |
+
|
27 |
+
<?php if ($storage_selection): ?>
|
28 |
+
<option value=""
|
29 |
+
selected><?php echo __('Change To Local Storage...', 'xcloner-backup-and-restore') ?></option>
|
30 |
+
<?php else: ?>
|
31 |
+
<option value=""
|
32 |
+
selected><?php echo __('Change To Remote Storage...', 'xcloner-backup-and-restore') ?></option>
|
33 |
+
<?php endif; ?>
|
34 |
+
|
35 |
+
<?php foreach ($available_storages as $storage => $text): ?>
|
36 |
+
<option value="<?php echo $storage ?>"<?php if ($storage == $storage_selection)
|
37 |
+
echo "selected" ?>><?php echo $text ?></option>
|
38 |
+
<?php endforeach ?>
|
39 |
+
</select>
|
40 |
+
<?php endif ?>
|
41 |
+
</div>
|
42 |
+
|
43 |
+
<table id="manage_backups">
|
44 |
+
<thead>
|
45 |
+
<tr class="grey lighten-2">
|
46 |
+
<th class="no-sort">
|
47 |
+
<p>
|
48 |
+
<input name="select_all" class="" id="select_all" value="1" type="checkbox">
|
49 |
+
<label for="select_all"> </label>
|
50 |
+
</p>
|
51 |
+
</th>
|
52 |
+
<th data-field="id"><?php echo __("Backup Name", 'xcloner-backup-and-restore') ?></th>
|
53 |
+
<th data-field="name"><?php echo __("Created Time", 'xcloner-backup-and-restore') ?></th>
|
54 |
+
<th data-field="name"><?php echo __("Size", 'xcloner-backup-and-restore') ?></th>
|
55 |
+
<th class="no-sort" data-field="price"><?php echo __("Action", 'xcloner-backup-and-restore') ?></th>
|
56 |
+
|
57 |
+
</tr>
|
58 |
+
</thead>
|
59 |
+
|
60 |
+
<tbody>
|
61 |
+
|
62 |
+
|
63 |
+
<?php
|
64 |
+
$i = 0;
|
65 |
+
foreach ($backup_list as $file_info):?>
|
66 |
+
<?php
|
67 |
+
if ($storage_selection == "gdrive") {
|
68 |
+
$file_info['path'] = $file_info['filename'] . "." . $file_info['extension'];
|
69 |
+
}
|
70 |
+
$file_exists_on_local_storage = true;
|
71 |
+
|
72 |
+
if ($storage_selection) {
|
73 |
+
if (!$xcloner_file_system->get_storage_filesystem()->has($file_info['path'])) {
|
74 |
+
$file_exists_on_local_storage = false;
|
75 |
+
}
|
76 |
+
}
|
77 |
+
|
78 |
+
?>
|
79 |
+
<?php if (!isset($file_info['parent'])): ?>
|
80 |
+
|
81 |
+
<tr>
|
82 |
+
<td class="checkbox">
|
83 |
+
<p>
|
84 |
+
<input name="backup[]" value="<?php echo $file_info['basename'] ?>" type="checkbox"
|
85 |
+
id="checkbox_<?php echo ++$i ?>">
|
86 |
+
<label for="checkbox_<?php echo $i ?>"> </label>
|
87 |
+
</p>
|
88 |
+
</td>
|
89 |
+
<td>
|
90 |
+
<span class=""><?php echo $file_info['path'] ?></span>
|
91 |
+
<?php if (!$file_exists_on_local_storage): ?>
|
92 |
+
<a href="#"
|
93 |
+
title="<?php echo __("File does not exists on local storage",
|
94 |
+
"xcloner-backup-and-restore") ?>"><i
|
95 |
+
class="material-icons backup_warning">warning</i></a>
|
96 |
+
<?php endif ?>
|
97 |
+
<?php
|
98 |
+
if (isset($file_info['childs']) and is_array($file_info['childs'])):
|
99 |
+
?>
|
100 |
+
<a href="#" title="expand" class="expand-multipart add"><i
|
101 |
+
class="material-icons">add</i></a>
|
102 |
+
<a href="#" title="collapse" class="expand-multipart remove"><i class="material-icons">remove</i></a>
|
103 |
+
<ul class="multipart">
|
104 |
+
<?php foreach ($file_info['childs'] as $child): ?>
|
105 |
+
<li>
|
106 |
+
<?php echo $child[0] ?> (<?php echo size_format($child[2]) ?>)
|
107 |
+
<?php
|
108 |
+
$child_exists_on_local_storage = true;
|
109 |
+
if ($storage_selection) {
|
110 |
+
if (!$xcloner_file_system->get_storage_filesystem()->has($child[0])) {
|
111 |
+
$child_exists_on_local_storage = false;
|
112 |
+
}
|
113 |
+
}
|
114 |
+
?>
|
115 |
+
<?php if (!$child_exists_on_local_storage): ?>
|
116 |
+
<a href="#"
|
117 |
+
title="<?php echo __("File does not exists on local storage",
|
118 |
+
"xcloner-backup-and-restore") ?>"><i
|
119 |
+
class="material-icons backup_warning">warning</i></a>
|
120 |
+
<?php endif ?>
|
121 |
+
<?php if (!$storage_selection) : ?>
|
122 |
+
<a href="#<?php echo $child[0]; ?>" class="download"
|
123 |
+
title="Download Backup"><i class="material-icons">file_download</i></a>
|
124 |
+
<a href="#<?php echo $child[0] ?>" class="list-backup-content"
|
125 |
+
title="<?php echo __('List Backup Content',
|
126 |
+
'xcloner-backup-and-restore') ?>"><i
|
127 |
+
class="material-icons">folder_open</i></a>
|
128 |
+
<?php elseif ($storage_selection != "gdrive" && !$xcloner_file_system->get_storage_filesystem()->has($child[0])): ?>
|
129 |
+
<a href="#<?php echo $child[0] ?>" class="copy-remote-to-local"
|
130 |
+
title="<?php echo __('Push Backup To Local Storage',
|
131 |
+
'xcloner-backup-and-restore') ?>"><i
|
132 |
+
class="material-icons">file_upload</i></a>
|
133 |
+
<?php endif ?>
|
134 |
+
</li>
|
135 |
+
<?php endforeach; ?>
|
136 |
+
</ul>
|
137 |
+
<?php endif; ?>
|
138 |
+
</td>
|
139 |
+
<td><?php if (isset($file_info['timestamp']))
|
140 |
+
echo date("Y-m-d H:i", $file_info['timestamp']) ?></td>
|
141 |
+
<td><?php echo size_format($file_info['size']) ?></td>
|
142 |
+
<td>
|
143 |
+
<?php if (!$storage_selection): ?>
|
144 |
+
<a href="#<?php echo $file_info['basename']; ?>" class="download"
|
145 |
+
title="<?php echo __('Download Backup', 'xcloner-backup-and-restore') ?>"><i
|
146 |
+
class="material-icons">file_download</i></a>
|
147 |
+
|
148 |
+
<?php if (sizeof($available_storages)): ?>
|
149 |
+
<a href="#<?php echo $file_info['basename'] ?>" class="cloud-upload"
|
150 |
+
title="<?php echo __('Send Backup To Remote Storage',
|
151 |
+
'xcloner-backup-and-restore') ?>"><i
|
152 |
+
class="material-icons">cloud_upload</i></a>
|
153 |
+
<?php endif ?>
|
154 |
+
<a href="#<?php echo $file_info['basename'] ?>" class="list-backup-content"
|
155 |
+
title="<?php echo __('List Backup Content', 'xcloner-backup-and-restore') ?>"><i
|
156 |
+
class="material-icons">folder_open</i></a>
|
157 |
+
<?php endif; ?>
|
158 |
+
|
159 |
+
<a href="#<?php echo $file_info['basename'] ?>" class="delete"
|
160 |
+
title="<?php echo __('Delete Backup', 'xcloner-backup-and-restore') ?>"><i
|
161 |
+
class="material-icons">delete</i></a>
|
162 |
+
<?php if ($storage_selection and !$file_exists_on_local_storage): ?>
|
163 |
+
<a href="#<?php echo $file_info['basename']; ?>" class="copy-remote-to-local"
|
164 |
+
title="<?php echo __('Push Backup To Local Storage', 'xcloner-backup-and-restore') ?>"><i
|
165 |
+
class="material-icons">file_upload</i></a>
|
166 |
+
<?php endif ?>
|
167 |
+
|
168 |
+
</td>
|
169 |
+
|
170 |
+
</tr>
|
171 |
+
|
172 |
+
<?php endif ?>
|
173 |
+
<?php endforeach ?>
|
174 |
+
|
175 |
+
</tbody>
|
176 |
+
</table>
|
177 |
+
|
178 |
+
<a class="waves-effect waves-light btn delete-all"><i
|
179 |
+
class="material-icons left">delete</i><?php echo __("Delete", 'xcloner-backup-and-restore') ?></a>
|
180 |
+
|
181 |
+
<!-- List Backup Content Modal-->
|
182 |
+
<div id="backup_cotent_modal" class="modal">
|
183 |
+
<div class="modal-content">
|
184 |
+
<h4><?php echo sprintf(__("Listing Backup Content ", 'xcloner-backup-and-restore'), "") ?></h4>
|
185 |
+
<h5 class="backup-name"></h5>
|
186 |
+
|
187 |
+
<div class="progress">
|
188 |
+
<div class="indeterminate"></div>
|
189 |
+
</div>
|
190 |
+
<ul class="files-list"></ul>
|
191 |
+
</div>
|
192 |
+
</div>
|
193 |
+
|
194 |
+
<!-- Local Transfer Modal-->
|
195 |
+
<div id="local_storage_upload_modal" class="modal">
|
196 |
+
<div class="modal-content">
|
197 |
+
<h4>
|
198 |
+
<?php echo sprintf(__("Transfer Remote Backup To Local Storage", 'xcloner-backup-and-restore'), "") ?>
|
199 |
+
</h4>
|
200 |
+
<h5 class="backup-name"></h5>
|
201 |
+
|
202 |
+
<div class="row status">
|
203 |
+
<div class="progress">
|
204 |
+
<div class="indeterminate"></div>
|
205 |
+
</div>
|
206 |
+
<?php echo __("Uploading backup to the local storage filesystem...", 'xcloner-backup-and-restore') ?>
|
207 |
+
<span class="status-text"></span>
|
208 |
+
</div>
|
209 |
+
</div>
|
210 |
+
</div>
|
211 |
+
|
212 |
+
<!-- Remote Storage Modal Structure -->
|
213 |
+
<div id="remote_storage_modal" class="modal">
|
214 |
+
<form method="POST" class="remote-storage-form">
|
215 |
+
<input type="hidden" name="file" class="backup_name">
|
216 |
+
<div class="modal-content">
|
217 |
+
<h4><?php echo __("Remote Storage Transfer", 'xcloner-backup-and-restore') ?></h4>
|
218 |
+
<p>
|
219 |
+
<?php if (sizeof($available_storages)): ?>
|
220 |
+
<div class="row">
|
221 |
+
<div class="col s12 label">
|
222 |
+
<label><?php echo sprintf(__('Send %s to remote storage', 'xcloner-backup-and-restore'),
|
223 |
+
"<span class='backup_name'></span>") ?></label>
|
224 |
+
</div>
|
225 |
+
<div class="input-field col s8 m10">
|
226 |
+
<select name="transfer_storage" id="transfer_storage" class="validate" required>
|
227 |
+
<option value=""
|
228 |
+
selected><?php echo __('please select...', 'xcloner-backup-and-restore') ?></option>
|
229 |
+
<?php foreach ($available_storages as $storage => $text): ?>
|
230 |
+
<option value="<?php echo $storage ?>"><?php echo $text ?></option>
|
231 |
+
<?php endforeach ?>
|
232 |
+
</select>
|
233 |
+
|
234 |
+
</div>
|
235 |
+
<div class="s4 m2 right">
|
236 |
+
<button type="submit"
|
237 |
+
class="upload-submit btn-floating btn-large waves-effect waves-light teal"><i
|
238 |
+
class="material-icons">file_upload</i></submit>
|
239 |
+
</div>
|
240 |
+
</div>
|
241 |
+
<div class="row status">
|
242 |
+
<?php echo __("Uploading backup to the selected remote storage...", 'xcloner-backup-and-restore') ?>
|
243 |
+
<span class="status-text"></span>
|
244 |
+
<div class="progress">
|
245 |
+
<div class="indeterminate"></div>
|
246 |
+
</div>
|
247 |
+
</div>
|
248 |
+
<?php endif ?>
|
249 |
+
</p>
|
250 |
+
</div>
|
251 |
+
</form>
|
252 |
+
</div>
|
253 |
|
admin/partials/xcloner_remote_storage_page.php
CHANGED
@@ -1,865 +1,1045 @@
|
|
1 |
-
<?php
|
2 |
$remote_storage = $this->get_xcloner_container()->get_xcloner_remote_storage();
|
3 |
|
4 |
$gdrive_auth_url = "";
|
5 |
|
6 |
-
if(method_exists($remote_storage, "get_gdrive_auth_url"))
|
7 |
$gdrive_auth_url = $remote_storage->get_gdrive_auth_url();
|
|
|
8 |
|
9 |
$gdrive_construct = $remote_storage->gdrive_construct();
|
10 |
?>
|
11 |
-
<h1><?= esc_html(get_admin_page_title()); ?></h1>
|
12 |
|
13 |
<form class="remote-storage-form" method="POST">
|
14 |
|
15 |
-
<input type="hidden" id="connection_check" name="connection_check" value="">
|
16 |
-
|
17 |
-
<div class="row remote-storage">
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
<i class="material-icons">computer</i><?php echo __("Dropbox Storage",'xcloner-backup-and-restore')?>
|
350 |
-
<div class="switch right">
|
351 |
-
<label>
|
352 |
-
Off
|
353 |
-
<input type="checkbox" name="xcloner_dropbox_enable" class="status" value="1" <?php if(get_option("xcloner_dropbox_enable")) echo "checked"?> \>
|
354 |
-
<span class="lever"></span>
|
355 |
-
On
|
356 |
-
</label>
|
357 |
-
</div>
|
358 |
-
</div>
|
359 |
-
<div class="collapsible-body">
|
360 |
-
|
361 |
-
<div class="row">
|
362 |
-
<div class="col s12 m3 label">
|
363 |
-
|
364 |
-
</div>
|
365 |
-
<div class=" col s12 m6">
|
366 |
-
<p>
|
367 |
-
<?php echo sprintf(__('Visit %s and get your "App secret".'), "<a href='https://www.dropbox.com/developers/apps' target='_blank'>https://www.dropbox.com/developers/apps</a>")?>
|
368 |
-
</p>
|
369 |
-
</div>
|
370 |
-
</div>
|
371 |
-
|
372 |
-
<div class="row">
|
373 |
-
<div class="col s12 m3 label">
|
374 |
-
<label for="dropbox_access_token"><?php echo __("Dropbox Access Token",'xcloner-backup-and-restore')?></label>
|
375 |
-
</div>
|
376 |
-
<div class=" col s12 m6">
|
377 |
-
<input placeholder="<?php echo __("Dropbox Access Token",'xcloner-backup-and-restore')?>" id="dropbox_access_token" type="text" name="xcloner_dropbox_access_token" class="validate" value="<?php echo get_option("xcloner_dropbox_access_token")?>" autocomplete="off" >
|
378 |
-
</div>
|
379 |
-
</div>
|
380 |
-
|
381 |
-
|
382 |
-
<div class="row">
|
383 |
-
<div class="col s12 m3 label">
|
384 |
-
<label for="dropbox_app_secret"><?php echo __("Dropbox App Secret",'xcloner-backup-and-restore')?></label>
|
385 |
-
</div>
|
386 |
-
<div class=" col s12 m6">
|
387 |
-
<input placeholder="<?php echo __("Dropbox App Secret",'xcloner-backup-and-restore')?>" id="dropbox_app_secret" type="text" name="xcloner_dropbox_app_secret" class="validate" value="<?php echo get_option("xcloner_dropbox_app_secret")?>" autocomplete="off" >
|
388 |
-
</div>
|
389 |
-
</div>
|
390 |
-
|
391 |
-
<div class="row">
|
392 |
-
<div class="col s12 m3 label">
|
393 |
-
<label for="dropbox_prefix"><?php echo __("Dropbox Prefix",'xcloner-backup-and-restore')?></label>
|
394 |
-
</div>
|
395 |
-
<div class=" col s12 m6">
|
396 |
-
<input placeholder="<?php echo __("Dropbox Prefix",'xcloner-backup-and-restore')?>" id="dropbox_prefix" type="text" name="xcloner_dropbox_prefix" class="validate" value="<?php echo get_option("xcloner_dropbox_prefix")?>">
|
397 |
-
</div>
|
398 |
-
</div>
|
399 |
-
|
400 |
-
<div class="row">
|
401 |
-
<div class="col s12 m3 label">
|
402 |
-
<label for="dropbox_cleanup_days"><?php echo __("Dropbox Cleanup (days)",'xcloner-backup-and-restore')?></label>
|
403 |
-
</div>
|
404 |
-
<div class=" col s12 m6">
|
405 |
-
<input placeholder="<?php echo __("how many days to keep the backups for",'xcloner-backup-and-restore')?>" id="dropbox_cleanup_days" type="text" name="xcloner_dropbox_cleanup_days" class="validate" value="<?php echo get_option("xcloner_dropbox_cleanup_days")?>">
|
406 |
-
</div>
|
407 |
-
</div>
|
408 |
-
|
409 |
-
<div class="row">
|
410 |
-
<div class="col s6 m4">
|
411 |
-
<button class="btn waves-effect waves-light" type="submit" name="action" id="action" value="dropbox"><?php echo __("Save Settings",'xcloner-backup-and-restore')?>
|
412 |
-
<i class="material-icons right">save</i>
|
413 |
-
</button>
|
414 |
-
</div>
|
415 |
-
<div class="col s6 m4">
|
416 |
-
<button class="btn waves-effect waves-light orange" type="submit" name="action" id="action" value="dropbox" onclick="jQuery('#connection_check').val('1')"><?php echo __("Verify",'xcloner-backup-and-restore')?>
|
417 |
-
<i class="material-icons right">import_export</i>
|
418 |
-
</button>
|
419 |
-
</div>
|
420 |
-
</div>
|
421 |
-
|
422 |
-
</div>
|
423 |
-
</li>
|
424 |
-
|
425 |
-
<!-- AZURE STORAGE-->
|
426 |
-
<li id="azure">
|
427 |
-
<div class="collapsible-header">
|
428 |
-
<i class="material-icons">computer</i><?php echo __("Azure Blob Storage",'xcloner-backup-and-restore')?>
|
429 |
-
<div class="switch right">
|
430 |
-
<label>
|
431 |
-
Off
|
432 |
-
<input type="checkbox" name="xcloner_azure_enable" class="status" value="1" <?php if(get_option("xcloner_azure_enable")) echo "checked"?> \>
|
433 |
-
<span class="lever"></span>
|
434 |
-
On
|
435 |
-
</label>
|
436 |
-
</div>
|
437 |
-
</div>
|
438 |
-
<div class="collapsible-body">
|
439 |
-
|
440 |
-
<div class="row">
|
441 |
-
<div class="col s12 m3 label">
|
442 |
-
|
443 |
-
</div>
|
444 |
-
<div class=" col s12 m6">
|
445 |
-
<p>
|
446 |
-
<?php echo sprintf(__('Visit %s and get your "Api Key".','xcloner-backup-and-restore'), '<a href="https://azure.microsoft.com/en-us/services/storage/blobs/" target="_blank">https://azure.microsoft.com/en-us/services/storage/blobs/</a>')?>
|
447 |
-
</p>
|
448 |
-
</div>
|
449 |
-
</div>
|
450 |
-
|
451 |
-
<div class="row">
|
452 |
-
<div class="col s12 m3 label">
|
453 |
-
<label for="azure_account_name"><?php echo __("Azure Account Name",'xcloner-backup-and-restore')?></label>
|
454 |
-
</div>
|
455 |
-
<div class=" col s12 m6">
|
456 |
-
<input placeholder="<?php echo __("Azure Account Name",'xcloner-backup-and-restore')?>" id="azure_account_name" type="text" name="xcloner_azure_account_name" class="validate" value="<?php echo get_option("xcloner_azure_account_name")?>" autocomplete="off" >
|
457 |
-
</div>
|
458 |
-
</div>
|
459 |
-
|
460 |
-
|
461 |
-
<div class="row">
|
462 |
-
<div class="col s12 m3 label">
|
463 |
-
<label for="azure_api_key"><?php echo __("Azure Api Key",'xcloner-backup-and-restore')?></label>
|
464 |
-
</div>
|
465 |
-
<div class=" col s12 m6">
|
466 |
-
<input placeholder="<?php echo __("Azure Api Key",'xcloner-backup-and-restore')?>" id="azure_api_key" type="text" name="xcloner_azure_api_key" class="validate" value="<?php echo get_option("xcloner_azure_api_key")?>" autocomplete="off" >
|
467 |
-
</div>
|
468 |
-
</div>
|
469 |
-
|
470 |
-
<div class="row">
|
471 |
-
<div class="col s12 m3 label">
|
472 |
-
<label for="azure_container"><?php echo __("Azure Container",'xcloner-backup-and-restore')?></label>
|
473 |
-
</div>
|
474 |
-
<div class=" col s12 m6">
|
475 |
-
<input placeholder="<?php echo __("Azure Container",'xcloner-backup-and-restore')?>" id="azure_container" type="text" name="xcloner_azure_container" class="validate" value="<?php echo get_option("xcloner_azure_container")?>">
|
476 |
-
</div>
|
477 |
-
</div>
|
478 |
-
|
479 |
-
<div class="row">
|
480 |
-
<div class="col s12 m3 label">
|
481 |
-
<label for="azure_cleanup_days"><?php echo __("Azure Cleanup (days)",'xcloner-backup-and-restore')?></label>
|
482 |
-
</div>
|
483 |
-
<div class=" col s12 m6">
|
484 |
-
<input placeholder="<?php echo __("how many days to keep the backups for",'xcloner-backup-and-restore')?>" id="azure_cleanup_days" type="text" name="xcloner_azure_cleanup_days" class="validate" value="<?php echo get_option("xcloner_azure_cleanup_days")?>">
|
485 |
-
</div>
|
486 |
-
</div>
|
487 |
-
|
488 |
-
<div class="row">
|
489 |
-
<div class="col s6 m4">
|
490 |
-
<button class="btn waves-effect waves-light" type="submit" name="action" id="action" value="azure"><?php echo __("Save Settings",'xcloner-backup-and-restore')?>
|
491 |
-
<i class="material-icons right">save</i>
|
492 |
-
</button>
|
493 |
-
</div>
|
494 |
-
<div class="col s6 m4">
|
495 |
-
<button class="btn waves-effect waves-light orange" type="submit" name="action" id="action" value="azure" onclick="jQuery('#connection_check').val('1')"><?php echo __("Verify",'xcloner-backup-and-restore')?>
|
496 |
-
<i class="material-icons right">import_export</i>
|
497 |
-
</button>
|
498 |
-
</div>
|
499 |
-
</div>
|
500 |
-
|
501 |
-
</div>
|
502 |
-
</li>
|
503 |
-
|
504 |
-
<!-- BACKBLAZE STORAGE-->
|
505 |
-
<li id="backblaze">
|
506 |
-
<div class="collapsible-header">
|
507 |
-
<i class="material-icons">computer</i><?php echo __("Backblaze Storage",'xcloner-backup-and-restore')?>
|
508 |
-
<div class="switch right">
|
509 |
-
<label>
|
510 |
-
Off
|
511 |
-
<input type="checkbox" name="xcloner_backblaze_enable" class="status" value="1" <?php if(get_option("xcloner_backblaze_enable")) echo "checked"?> \>
|
512 |
-
<span class="lever"></span>
|
513 |
-
On
|
514 |
-
</label>
|
515 |
-
</div>
|
516 |
-
</div>
|
517 |
-
<div class="collapsible-body">
|
518 |
-
|
519 |
-
<div class="row">
|
520 |
-
<div class="col s12 m3 label">
|
521 |
-
|
522 |
-
</div>
|
523 |
-
<div class=" col s12 m6">
|
524 |
-
<p>
|
525 |
-
<?php echo sprintf(__('Visit %s and get your Account Id and Application Key.','xcloner-backup-and-restore'), '<a href="https://secure.backblaze.com/b2_buckets.htm" target="_blank">https://secure.backblaze.com/b2_buckets.htm</a>')?>
|
526 |
-
</p>
|
527 |
-
</div>
|
528 |
-
</div>
|
529 |
-
|
530 |
-
<div class="row">
|
531 |
-
<div class="col s12 m3 label">
|
532 |
-
<label for="backblaze_account_id"><?php echo __("Backblaze Account Id",'xcloner-backup-and-restore')?></label>
|
533 |
-
</div>
|
534 |
-
<div class=" col s12 m6">
|
535 |
-
<input placeholder="<?php echo __("Backblaze Account Id",'xcloner-backup-and-restore')?>" id="backblaze_account_id" type="text" name="xcloner_backblaze_account_id" class="validate" value="<?php echo get_option("xcloner_backblaze_account_id")?>" autocomplete="off" >
|
536 |
-
</div>
|
537 |
-
</div>
|
538 |
-
|
539 |
-
|
540 |
-
<div class="row">
|
541 |
-
<div class="col s12 m3 label">
|
542 |
-
<label for="backblaze_application_key"><?php echo __("Backblaze Application Key",'xcloner-backup-and-restore')?></label>
|
543 |
-
</div>
|
544 |
-
<div class=" col s12 m6">
|
545 |
-
<input placeholder="<?php echo __("Backblaze Application Key",'xcloner-backup-and-restore')?>" id="backblaze_application_key" type="text" name="xcloner_backblaze_application_key" class="validate" value="<?php echo get_option("xcloner_backblaze_application_key")?>" autocomplete="off" >
|
546 |
-
</div>
|
547 |
-
</div>
|
548 |
-
|
549 |
-
<div class="row">
|
550 |
-
<div class="col s12 m3 label">
|
551 |
-
<label for="backblaze_bucket_name"><?php echo __("Backblaze Bucket Name",'xcloner-backup-and-restore')?></label>
|
552 |
-
</div>
|
553 |
-
<div class=" col s12 m6">
|
554 |
-
<input placeholder="<?php echo __("Backblaze Bucket Name",'xcloner-backup-and-restore')?>" id="backblaze_bucket_name" type="text" name="xcloner_backblaze_bucket_name" class="validate" value="<?php echo get_option("xcloner_backblaze_bucket_name")?>" autocomplete="off" >
|
555 |
-
</div>
|
556 |
-
</div>
|
557 |
-
|
558 |
-
<div class="row">
|
559 |
-
<div class="col s12 m3 label">
|
560 |
-
<label for="backblaze_cleanup_days"><?php echo __("Backblaze Cleanup (days)",'xcloner-backup-and-restore')?></label>
|
561 |
-
</div>
|
562 |
-
<div class=" col s12 m6">
|
563 |
-
<input placeholder="<?php echo __("how many days to keep the backups for",'xcloner-backup-and-restore')?>" id="backblaze_cleanup_days" type="text" name="xcloner_backblaze_cleanup_days" class="validate" value="<?php echo get_option("xcloner_backblaze_cleanup_days")?>">
|
564 |
-
</div>
|
565 |
-
</div>
|
566 |
-
|
567 |
-
<div class="row">
|
568 |
-
<div class="col s6 m4">
|
569 |
-
<button class="btn waves-effect waves-light" type="submit" name="action" id="action" value="backblaze"><?php echo __("Save Settings",'xcloner-backup-and-restore')?>
|
570 |
-
<i class="material-icons right">save</i>
|
571 |
-
</button>
|
572 |
-
</div>
|
573 |
-
<div class="col s6 m4">
|
574 |
-
<button class="btn waves-effect waves-light orange" type="submit" name="action" id="action" value="backblaze" onclick="jQuery('#connection_check').val('1')"><?php echo __("Verify",'xcloner-backup-and-restore')?>
|
575 |
-
<i class="material-icons right">import_export</i>
|
576 |
-
</button>
|
577 |
-
</div>
|
578 |
-
</div>
|
579 |
-
|
580 |
-
</div>
|
581 |
-
</li>
|
582 |
-
|
583 |
-
<!-- WEBDAV STORAGE-->
|
584 |
-
<li id="webdav">
|
585 |
-
<div class="collapsible-header">
|
586 |
-
<i class="material-icons">computer</i><?php echo __("WebDAV Storage",'xcloner-backup-and-restore')?>
|
587 |
-
<div class="switch right">
|
588 |
-
<label>
|
589 |
-
Off
|
590 |
-
<input type="checkbox" name="xcloner_webdav_enable" class="status" value="1" <?php if(get_option("xcloner_webdav_enable")) echo "checked"?> \>
|
591 |
-
<span class="lever"></span>
|
592 |
-
On
|
593 |
-
</label>
|
594 |
-
</div>
|
595 |
-
</div>
|
596 |
-
<div class="collapsible-body">
|
597 |
-
|
598 |
-
<div class="row">
|
599 |
-
<div class="col s12 m3 label">
|
600 |
-
|
601 |
-
</div>
|
602 |
-
<div class=" col s12 m6">
|
603 |
-
<p>
|
604 |
-
<?php //echo sprintf(__('Visit %s and get your Account Id and Application Key.','xcloner-backup-and-restore'), '<a href="https://secure.backblaze.com/b2_buckets.htm" target="_blank">https://secure.backblaze.com/b2_buckets.htm</a>')?>
|
605 |
-
</p>
|
606 |
-
</div>
|
607 |
-
</div>
|
608 |
-
|
609 |
-
<div class="row">
|
610 |
-
<div class="col s12 m3 label">
|
611 |
-
<label for="webdav_url"><?php echo __("WebDAV Base Url",'xcloner-backup-and-restore')?></label>
|
612 |
-
</div>
|
613 |
-
<div class=" col s12 m6">
|
614 |
-
<input placeholder="<?php echo __("WebDAV Base Url",'xcloner-backup-and-restore')?>" id="webdav_url" type="text" name="xcloner_webdav_url" class="validate" value="<?php echo get_option("xcloner_webdav_url")?>" autocomplete="off" >
|
615 |
-
</div>
|
616 |
-
</div>
|
617 |
-
|
618 |
-
<div class="row">
|
619 |
-
<div class="col s12 m3 label">
|
620 |
-
<label for="webdav_username"><?php echo __("WebDAV Username",'xcloner-backup-and-restore')?></label>
|
621 |
-
</div>
|
622 |
-
<div class=" col s12 m6">
|
623 |
-
<input placeholder="<?php echo __("WebDAV Username",'xcloner-backup-and-restore')?>" id="webdav_username" type="text" name="xcloner_webdav_username" class="validate" value="<?php echo get_option("xcloner_webdav_username")?>" autocomplete="off" >
|
624 |
-
</div>
|
625 |
-
</div>
|
626 |
-
|
627 |
-
<div class="row">
|
628 |
-
<div class="col s12 m3 label">
|
629 |
-
<label for="webdav_password"><?php echo __("WebDAV Password",'xcloner-backup-and-restore')?></label>
|
630 |
-
</div>
|
631 |
-
<div class=" col s12 m6">
|
632 |
-
<input placeholder="<?php echo __("WebDAV Password",'xcloner-backup-and-restore')?>" id="webdav_password" type="password" name="xcloner_webdav_password" class="validate" value="<?php echo get_option("xcloner_webdav_password")?>" autocomplete="off" >
|
633 |
-
</div>
|
634 |
-
</div>
|
635 |
-
|
636 |
-
<div class="row">
|
637 |
-
<div class="col s12 m3 label">
|
638 |
-
<label for="webdav_target_folder"><?php echo __("WebDAV Target Folder",'xcloner-backup-and-restore')?></label>
|
639 |
-
</div>
|
640 |
-
<div class=" col s12 m6">
|
641 |
-
<input placeholder="<?php echo __("WebDAV Target Folder",'xcloner-backup-and-restore')?>" id="webdav_target_folder" type="text" name="xcloner_webdav_target_folder" class="validate" value="<?php echo get_option("xcloner_webdav_target_folder")?>" autocomplete="off" >
|
642 |
-
</div>
|
643 |
-
</div>
|
644 |
-
|
645 |
-
<div class="row">
|
646 |
-
<div class="col s12 m3 label">
|
647 |
-
<label for="webdav_cleanup_days"><?php echo __("WebDAV Cleanup (days)",'xcloner-backup-and-restore')?></label>
|
648 |
-
</div>
|
649 |
-
<div class=" col s12 m6">
|
650 |
-
<input placeholder="<?php echo __("how many days to keep the backups for",'xcloner-backup-and-restore')?>" id="webdav_cleanup_days" type="text" name="xcloner_webdav_cleanup_days" class="validate" value="<?php echo get_option("xcloner_webdav_cleanup_days")?>">
|
651 |
-
</div>
|
652 |
-
</div>
|
653 |
-
|
654 |
-
<div class="row">
|
655 |
-
<div class="col s6 m4">
|
656 |
-
<button class="btn waves-effect waves-light" type="submit" name="action" id="action" value="webdav"><?php echo __("Save Settings",'xcloner-backup-and-restore')?>
|
657 |
-
<i class="material-icons right">save</i>
|
658 |
-
</button>
|
659 |
-
</div>
|
660 |
-
<div class="col s6 m4">
|
661 |
-
<button class="btn waves-effect waves-light orange" type="submit" name="action" id="action" value="webdav" onclick="jQuery('#connection_check').val('1')"><?php echo __("Verify",'xcloner-backup-and-restore')?>
|
662 |
-
<i class="material-icons right">import_export</i>
|
663 |
-
</button>
|
664 |
-
</div>
|
665 |
-
</div>
|
666 |
-
|
667 |
-
</div>
|
668 |
-
</li>
|
669 |
-
|
670 |
-
<!-- Google DRIVE STORAGE-->
|
671 |
-
<li id="gdrive">
|
672 |
-
<div class="collapsible-header">
|
673 |
-
<i class="material-icons">computer</i><?php echo __("Google Drive Storage",'xcloner-backup-and-restore')?>
|
674 |
-
<?php if($gdrive_construct):?>
|
675 |
-
<div class="switch right">
|
676 |
-
<label>
|
677 |
-
Off
|
678 |
-
<input type="checkbox" name="xcloner_gdrive_enable" class="status" value="1" <?php if(get_option("xcloner_gdrive_enable")) echo "checked"?> \>
|
679 |
-
<span class="lever"></span>
|
680 |
-
On
|
681 |
-
</label>
|
682 |
-
</div>
|
683 |
-
<?php endif?>
|
684 |
-
</div>
|
685 |
-
<div class="collapsible-body">
|
686 |
-
|
687 |
-
<?php if($gdrive_construct) : ?>
|
688 |
-
|
689 |
-
<div class="row">
|
690 |
-
<div class="col s12 m3 label">
|
691 |
-
|
692 |
-
</div>
|
693 |
-
<div class=" col s12 m9">
|
694 |
-
<p>
|
695 |
-
<?php echo sprintf(__('Visit %s to create a new application and get your Client ID and Client Secret.','xcloner-backup-and-restore'), '<a href="https://console.developers.google.com" target="_blank">https://console.developers.google.com</a>')?>
|
696 |
-
<a href="https://youtu.be/YXUVPUVgG8k" target="_blank" class="btn-floating tooltipped btn-small" data-position="right" data-delay="50" data-html="true"
|
697 |
-
data-tooltip="<?php echo sprintf(__('Click here to view a short video explaining how to create the Client ID and Client Secret as well as connecting XCloner with the Google Drive API %s','xcloner-backup-and-restore'),"<br />https://youtu.be/YXUVPUVgG8k")?>" data-tooltip-id="92c95730-94e9-7b59-bd52-14adc30d5e3e"><i class="material-icons">help_outline</i></a>
|
698 |
-
</p>
|
699 |
-
</div>
|
700 |
-
</div>
|
701 |
-
|
702 |
-
<div class="row">
|
703 |
-
<div class="col s12 m3 label">
|
704 |
-
<label for="gdrive_client_id"><?php echo __("Client ID",'xcloner-backup-and-restore')?></label>
|
705 |
-
</div>
|
706 |
-
<div class=" col s12 m6">
|
707 |
-
<input placeholder="<?php echo __("Google Client ID",'xcloner-backup-and-restore')?>" id="gdrive_client_id" type="text" name="xcloner_gdrive_client_id" class="validate" value="<?php echo get_option("xcloner_gdrive_client_id")?>">
|
708 |
-
</div>
|
709 |
-
</div>
|
710 |
-
|
711 |
-
<div class="row">
|
712 |
-
<div class="col s12 m3 label">
|
713 |
-
<label for="gdrive_client_secret"><?php echo __("Client Secret",'xcloner-backup-and-restore')?></label>
|
714 |
-
</div>
|
715 |
-
<div class=" col s12 m6">
|
716 |
-
<input placeholder="<?php echo __("Google Client Secret",'xcloner-backup-and-restore')?>" id="gdrive_client_secret" type="text" name="xcloner_gdrive_client_secret" class="validate" value="<?php echo get_option("xcloner_gdrive_client_secret")?>">
|
717 |
-
</div>
|
718 |
-
</div>
|
719 |
-
|
720 |
-
|
721 |
-
<div class="row">
|
722 |
-
<div class="col s12 m3 label">
|
723 |
-
|
724 |
-
</div>
|
725 |
-
<div class=" col s12 m6">
|
726 |
-
<a class="btn" target="_blank" id="gdrive_authorization_click" onclick="jQuery('#authentification_code').show()" href="<?php echo $gdrive_auth_url?>"><?php echo sprintf(__('Authorize Google Drive','xcloner-backup-and-restore'))?></a>
|
727 |
-
<input type="text" name="authentification_code" id="authentification_code" placeholder="<?php echo __("Paste Authorization Code Here","xcloner-backup-and-restore")?>">
|
728 |
-
</div>
|
729 |
-
</div>
|
730 |
-
|
731 |
-
<div class="row">
|
732 |
-
<div class="col s12 m3 label">
|
733 |
-
<label for="gdrive_target_folder"><?php echo __("Folder ID or Root Path",'xcloner-backup-and-restore')?>
|
734 |
-
<a class="btn-floating tooltipped btn-small" data-position="right" data-delay="50" data-html="true" \
|
735 |
-
data-tooltip="<?php echo __('Folder ID can be found by right clicking on the folder name and selecting \'Get shareable link\' menu, format https://drive.google.com/open?id={FOLDER_ID}<br />
|
736 |
-
If you supply a folder name, it has to exists in the drive root and start with / , example /backups.xcloner.com/','xcloner-backup-and-restore')?>" data-tooltip-id="92c95730-94e9-7b59-bd52-14adc30d5e3e"><i class="material-icons">help_outline</i></a>
|
737 |
-
</label>
|
738 |
-
</div>
|
739 |
-
<div class=" col s12 m6">
|
740 |
-
<input placeholder="<?php echo __("Target Folder ID or Root Path",'xcloner-backup-and-restore')?>" id="gdrive_target_folder" type="text" name="xcloner_gdrive_target_folder" class="validate" value="<?php echo get_option("xcloner_gdrive_target_folder")?>" autocomplete="off" >
|
741 |
-
</div>
|
742 |
-
</div>
|
743 |
-
|
744 |
-
<div class="row">
|
745 |
-
<div class="col s12 m3 label">
|
746 |
-
<label for="gdrive_cleanup_days"><?php echo __("Google Drive Cleanup (days)",'xcloner-backup-and-restore')?></label>
|
747 |
-
</div>
|
748 |
-
<div class=" col s12 m6">
|
749 |
-
<input placeholder="<?php echo __("how many days to keep the backups for",'xcloner-backup-and-restore')?>" id="gdrive_cleanup_days" type="text" name="xcloner_gdrive_cleanup_days" class="validate" value="<?php echo get_option("xcloner_gdrive_cleanup_days")?>">
|
750 |
-
</div>
|
751 |
-
</div>
|
752 |
-
|
753 |
-
<div class="row">
|
754 |
-
<div class="col s12 m3 label">
|
755 |
-
<label for="gdrive_empty_trash"><?php echo __("Keeps Deleted Backups in Trash",'xcloner-backup-and-restore')?></label>
|
756 |
-
</div>
|
757 |
-
<div class=" col s12 m6 input-field inline">
|
758 |
-
<input name="xcloner_gdrive_empty_trash" type="radio" value="0" id="gdrive_empty_trash_off" <?php if(!get_option("xcloner_gdrive_empty_trash",0)) echo "checked"?> />
|
759 |
-
<label for="gdrive_empty_trash_off"><?php echo __("Enabled",'xcloner-backup-and-restore')?></label>
|
760 |
-
|
761 |
-
<input name="xcloner_gdrive_empty_trash" type="radio" value="1" id="gdrive_empty_trash_on" <?php if(get_option("xcloner_gdrive_empty_trash",0)) echo "checked"?> />
|
762 |
-
<label for="gdrive_empty_trash_on"><?php echo __("Disabled",'xcloner-backup-and-restore')?></label>
|
763 |
-
</div>
|
764 |
-
</div>
|
765 |
-
|
766 |
-
<div class="row">
|
767 |
-
<div class="col s6 m4">
|
768 |
-
<button class="btn waves-effect waves-light" type="submit" name="action" id="action" value="gdrive"><?php echo __("Save Settings",'xcloner-backup-and-restore')?>
|
769 |
-
<i class="material-icons right">save</i>
|
770 |
-
</button>
|
771 |
-
</div>
|
772 |
-
<div class="col s6 m4">
|
773 |
-
<button class="btn waves-effect waves-light orange" type="submit" name="action" id="action" value="gdrive" onclick="jQuery('#connection_check').val('1')"><?php echo __("Verify",'xcloner-backup-and-restore')?>
|
774 |
-
<i class="material-icons right">import_export</i>
|
775 |
-
</button>
|
776 |
-
</div>
|
777 |
-
</div>
|
778 |
-
<?php else:?>
|
779 |
-
|
780 |
-
<div class="row">
|
781 |
-
<div class=" col s12">
|
782 |
-
<div class="center">
|
783 |
-
<?php
|
784 |
-
$url = wp_nonce_url(self_admin_url('update.php?action=install-plugin&plugin=xcloner-google-drive'), 'install-plugin_xcloner-google-drive');
|
785 |
?>
|
786 |
-
|
787 |
-
|
788 |
-
|
789 |
-
|
790 |
-
|
791 |
-
|
792 |
-
|
793 |
-
|
794 |
-
|
795 |
-
|
796 |
-
|
797 |
-
|
798 |
-
|
799 |
-
|
800 |
-
|
801 |
-
|
802 |
-
|
803 |
-
|
804 |
-
|
805 |
-
|
806 |
-
|
807 |
-
|
808 |
-
|
809 |
-
|
810 |
-
|
811 |
-
|
812 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
813 |
|
814 |
</form>
|
815 |
|
816 |
<script>
|
817 |
-
|
818 |
-
function checkEndpoint(){
|
819 |
-
if(jQuery("#aws_region").val() != ""){
|
820 |
-
jQuery('#aws_endpoint').parent().parent().hide();
|
821 |
-
}else{
|
822 |
-
jQuery('#aws_endpoint').parent().parent().show();
|
823 |
-
}
|
824 |
-
}
|
825 |
|
826 |
-
|
827 |
-
|
828 |
-
|
829 |
-
|
830 |
-
|
831 |
-
|
832 |
-
|
833 |
-
|
834 |
-
|
835 |
-
|
836 |
-
|
837 |
-
|
838 |
-
|
839 |
-
|
840 |
-
|
841 |
-
|
842 |
-
|
843 |
-
|
844 |
-
|
845 |
-
|
846 |
-
|
847 |
-
|
848 |
-
|
849 |
-
|
850 |
-
|
851 |
-
|
852 |
-
|
853 |
-
|
854 |
-
|
855 |
-
|
856 |
-
|
857 |
-
|
858 |
-
|
859 |
-
|
860 |
-
|
861 |
-
|
862 |
-
|
863 |
-
|
864 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
865 |
</script>
|
1 |
+
<?php
|
2 |
$remote_storage = $this->get_xcloner_container()->get_xcloner_remote_storage();
|
3 |
|
4 |
$gdrive_auth_url = "";
|
5 |
|
6 |
+
if ( method_exists( $remote_storage, "get_gdrive_auth_url" ) ) {
|
7 |
$gdrive_auth_url = $remote_storage->get_gdrive_auth_url();
|
8 |
+
}
|
9 |
|
10 |
$gdrive_construct = $remote_storage->gdrive_construct();
|
11 |
?>
|
12 |
+
<h1><?= esc_html( get_admin_page_title() ); ?></h1>
|
13 |
|
14 |
<form class="remote-storage-form" method="POST">
|
15 |
|
16 |
+
<input type="hidden" id="connection_check" name="connection_check" value="">
|
17 |
+
|
18 |
+
<div class="row remote-storage">
|
19 |
+
<div class="col s12 m12 l10">
|
20 |
+
<ul class="collapsible popout" data-collapsible="accordion">
|
21 |
+
<!-- FTP STORAGE-->
|
22 |
+
<li id="ftp">
|
23 |
+
<div class="collapsible-header">
|
24 |
+
<i class="material-icons">computer</i><?php echo __( "FTP Storage", 'xcloner-backup-and-restore' ) ?>
|
25 |
+
<div class="switch right">
|
26 |
+
<label>
|
27 |
+
Off
|
28 |
+
<input type="checkbox" name="xcloner_ftp_enable" class="status"
|
29 |
+
value="1" <?php if ( get_option( "xcloner_ftp_enable" ) )
|
30 |
+
echo "checked" ?> \>
|
31 |
+
<span class="lever"></span>
|
32 |
+
On
|
33 |
+
</label>
|
34 |
+
</div>
|
35 |
+
</div>
|
36 |
+
<div class="collapsible-body">
|
37 |
+
<div class="row">
|
38 |
+
<div class="col s12 m3 label">
|
39 |
+
<label for="ftp_host"><?php echo __( "Ftp Hostname", 'xcloner-backup-and-restore' ) ?></label>
|
40 |
+
</div>
|
41 |
+
<div class="col s12 m6">
|
42 |
+
<input placeholder="<?php echo __( "Ftp Hostname", 'xcloner-backup-and-restore' ) ?>"
|
43 |
+
id="ftp_host" type="text" name="xcloner_ftp_hostname" class="validate"
|
44 |
+
value="<?php echo get_option( "xcloner_ftp_hostname" ) ?>">
|
45 |
+
</div>
|
46 |
+
<div class=" col s12 m2">
|
47 |
+
<input placeholder="<?php echo __( "Ftp Port", 'xcloner-backup-and-restore' ) ?>"
|
48 |
+
id="ftp_port" type="text" name="xcloner_ftp_port" class="validate"
|
49 |
+
value="<?php echo get_option( "xcloner_ftp_port", 21 ) ?>">
|
50 |
+
</div>
|
51 |
+
</div>
|
52 |
+
|
53 |
+
<div class="row">
|
54 |
+
<div class="col s12 m3 label">
|
55 |
+
<label for="ftp_username"><?php echo __( "Ftp Username", 'xcloner-backup-and-restore' ) ?></label>
|
56 |
+
</div>
|
57 |
+
<div class=" col s12 m6">
|
58 |
+
<input placeholder="<?php echo __( "Ftp Username", 'xcloner-backup-and-restore' ) ?>"
|
59 |
+
id="ftp_username" type="text" name="xcloner_ftp_username" class="validate"
|
60 |
+
value="<?php echo get_option( "xcloner_ftp_username" ) ?>" autocomplete="off">
|
61 |
+
</div>
|
62 |
+
</div>
|
63 |
+
|
64 |
+
|
65 |
+
<div class="row">
|
66 |
+
<div class="col s12 m3 label">
|
67 |
+
<label for="ftp_password"><?php echo __( "Ftp Password", 'xcloner-backup-and-restore' ) ?></label>
|
68 |
+
</div>
|
69 |
+
<div class=" col s12 m6">
|
70 |
+
<input placeholder="<?php echo __( "Ftp Password", 'xcloner-backup-and-restore' ) ?>"
|
71 |
+
id="ftp_password" type="password" name="xcloner_ftp_password" class="validate"
|
72 |
+
value="<?php echo get_option( "xcloner_ftp_password" ) ?>" autocomplete="off">
|
73 |
+
</div>
|
74 |
+
</div>
|
75 |
+
|
76 |
+
<div class="row">
|
77 |
+
<div class="col s12 m3 label">
|
78 |
+
<label for="ftp_root"><?php echo __( "Ftp Storage Folder", 'xcloner-backup-and-restore' ) ?></label>
|
79 |
+
</div>
|
80 |
+
<div class=" col s12 m6">
|
81 |
+
<input placeholder="<?php echo __( "Ftp Storage Folder", 'xcloner-backup-and-restore' ) ?>"
|
82 |
+
id="ftp_root" type="text" name="xcloner_ftp_path" class="validate"
|
83 |
+
value="<?php echo get_option( "xcloner_ftp_path" ) ?>">
|
84 |
+
</div>
|
85 |
+
</div>
|
86 |
+
|
87 |
+
<div class="row">
|
88 |
+
<div class="col s12 m3 label">
|
89 |
+
<label for="ftp_root"><?php echo __( "Ftp Transfer Mode", 'xcloner-backup-and-restore' ) ?></label>
|
90 |
+
</div>
|
91 |
+
<div class=" col s12 m6 input-field inline">
|
92 |
+
<input name="xcloner_ftp_transfer_mode" type="radio" id="passive"
|
93 |
+
value="1" <?php if ( get_option( "xcloner_ftp_transfer_mode", 1 ) )
|
94 |
+
echo "checked" ?> />
|
95 |
+
<label for="passive"><?php echo __( "Passive", 'xcloner-backup-and-restore' ) ?></label>
|
96 |
+
|
97 |
+
<input name="xcloner_ftp_transfer_mode" type="radio" id="active"
|
98 |
+
value="0" <?php if ( ! get_option( "xcloner_ftp_transfer_mode", 1 ) )
|
99 |
+
echo "checked" ?> />
|
100 |
+
<label for="active"><?php echo __( "Active", 'xcloner-backup-and-restore' ) ?></label>
|
101 |
+
</div>
|
102 |
+
</div>
|
103 |
+
|
104 |
+
<div class="row">
|
105 |
+
<div class="col s12 m3 label">
|
106 |
+
<label for="ftp_ssl_mode"><?php echo __( "Ftp Secure Connection", 'xcloner-backup-and-restore' ) ?></label>
|
107 |
+
</div>
|
108 |
+
<div class=" col s12 m6 input-field inline">
|
109 |
+
<input name="xcloner_ftp_ssl_mode" type="radio" id="ftp_ssl_mode_inactive"
|
110 |
+
value="0" <?php if ( ! get_option( "xcloner_ftp_ssl_mode" ) )
|
111 |
+
echo "checked" ?> />
|
112 |
+
<label for="ftp_ssl_mode_inactive"><?php echo __( "Disable", 'xcloner-backup-and-restore' ) ?></label>
|
113 |
+
|
114 |
+
<input name="xcloner_ftp_ssl_mode" type="radio" id="ftp_ssl_mode_active"
|
115 |
+
value="1" <?php if ( get_option( "xcloner_ftp_ssl_mode" ) )
|
116 |
+
echo "checked" ?> />
|
117 |
+
<label for="ftp_ssl_mode_active"><?php echo __( "Enable", 'xcloner-backup-and-restore' ) ?></label>
|
118 |
+
</div>
|
119 |
+
</div>
|
120 |
+
|
121 |
+
<div class="row">
|
122 |
+
<div class="col s12 m3 label">
|
123 |
+
<label for="ftp_timeout"><?php echo __( "Ftp Timeout", 'xcloner-backup-and-restore' ) ?></label>
|
124 |
+
</div>
|
125 |
+
<div class=" col s12 m2">
|
126 |
+
<input placeholder="<?php echo __( "Ftp Timeout", 'xcloner-backup-and-restore' ) ?>"
|
127 |
+
id="ftp_timeout" type="text" name="xcloner_ftp_timeout" class="validate"
|
128 |
+
value="<?php echo get_option( "xcloner_ftp_timeout", 30 ) ?>">
|
129 |
+
</div>
|
130 |
+
</div>
|
131 |
+
|
132 |
+
<div class="row">
|
133 |
+
<div class="col s12 m3 label">
|
134 |
+
<label for="ftp_cleanup_days"><?php echo __( "Ftp Cleanup (days)", 'xcloner-backup-and-restore' ) ?></label>
|
135 |
+
</div>
|
136 |
+
<div class=" col s12 m6">
|
137 |
+
<input placeholder="<?php echo __( "how many days to keep the backups for", 'xcloner-backup-and-restore' ) ?>"
|
138 |
+
id="ftp_cleanup_days" type="text" name="xcloner_ftp_cleanup_days"
|
139 |
+
class="validate" value="<?php echo get_option( "xcloner_ftp_cleanup_days" ) ?>">
|
140 |
+
</div>
|
141 |
+
</div>
|
142 |
+
|
143 |
+
<div class="row">
|
144 |
+
<div class="col s6 m4">
|
145 |
+
<button class="btn waves-effect waves-light" type="submit" name="action" id="action"
|
146 |
+
value="ftp"><?php echo __( "Save Settings", 'xcloner-backup-and-restore' ) ?>
|
147 |
+
<i class="material-icons right">save</i>
|
148 |
+
</button>
|
149 |
+
</div>
|
150 |
+
<div class="col s6 m4">
|
151 |
+
<button class="btn waves-effect waves-light orange" type="submit" name="action"
|
152 |
+
id="action" value="ftp"
|
153 |
+
onclick="jQuery('#connection_check').val('1')"><?php echo __( "Verify", 'xcloner-backup-and-restore' ) ?>
|
154 |
+
<i class="material-icons right">import_export</i>
|
155 |
+
</button>
|
156 |
+
</div>
|
157 |
+
</div>
|
158 |
+
|
159 |
+
</div>
|
160 |
+
</li>
|
161 |
+
<!-- SFTP STORAGE-->
|
162 |
+
<li id="sftp">
|
163 |
+
<div class="collapsible-header">
|
164 |
+
<i class="material-icons">computer</i><?php echo __( "SFTP Storage", 'xcloner-backup-and-restore' ) ?>
|
165 |
+
<div class="switch right">
|
166 |
+
<label>
|
167 |
+
Off
|
168 |
+
<input type="checkbox" name="xcloner_sftp_enable" class="status"
|
169 |
+
value="1" <?php if ( get_option( "xcloner_sftp_enable" ) )
|
170 |
+
echo "checked" ?> \>
|
171 |
+
<span class="lever"></span>
|
172 |
+
On
|
173 |
+
</label>
|
174 |
+
</div>
|
175 |
+
</div>
|
176 |
+
<div class="collapsible-body">
|
177 |
+
<div class="row">
|
178 |
+
<div class="col s12 m3 label">
|
179 |
+
<label for="sftp_host"><?php echo __( "SFTP Hostname", 'xcloner-backup-and-restore' ) ?></label>
|
180 |
+
</div>
|
181 |
+
<div class="col s12 m6">
|
182 |
+
<input placeholder="<?php echo __( "SFTP Hostname", 'xcloner-backup-and-restore' ) ?>"
|
183 |
+
id="sftp_host" type="text" name="xcloner_sftp_hostname" class="validate"
|
184 |
+
value="<?php echo get_option( "xcloner_sftp_hostname" ) ?>">
|
185 |
+
</div>
|
186 |
+
<div class=" col s12 m2">
|
187 |
+
<input placeholder="<?php echo __( "SFTP Port", 'xcloner-backup-and-restore' ) ?>"
|
188 |
+
id="sftp_port" type="text" name="xcloner_sftp_port" class="validate"
|
189 |
+
value="<?php echo get_option( "xcloner_sftp_port", 22 ) ?>">
|
190 |
+
</div>
|
191 |
+
</div>
|
192 |
+
|
193 |
+
<div class="row">
|
194 |
+
<div class="col s12 m3 label">
|
195 |
+
<label for="sftp_username"><?php echo __( "SFTP Username", 'xcloner-backup-and-restore' ) ?></label>
|
196 |
+
</div>
|
197 |
+
<div class=" col s12 m6">
|
198 |
+
<input placeholder="<?php echo __( "SFTP Username", 'xcloner-backup-and-restore' ) ?>"
|
199 |
+
id="sftp_username" type="text" name="xcloner_sftp_username" class="validate"
|
200 |
+
value="<?php echo get_option( "xcloner_sftp_username" ) ?>" autocomplete="off">
|
201 |
+
</div>
|
202 |
+
</div>
|
203 |
+
|
204 |
+
|
205 |
+
<div class="row">
|
206 |
+
<div class="col s12 m3 label">
|
207 |
+
<label for="sftp_password"><?php echo __( "SFTP or Private Key Password", 'xcloner-backup-and-restore' ) ?></label>
|
208 |
+
</div>
|
209 |
+
<div class=" col s12 m6">
|
210 |
+
<input placeholder="<?php echo __( "SFTP or Private Key Password", 'xcloner-backup-and-restore' ) ?>"
|
211 |
+
id="ftp_spassword" type="password" name="xcloner_sftp_password" class="validate"
|
212 |
+
value="<?php echo get_option( "xcloner_sftp_password" ) ?>" autocomplete="off">
|
213 |
+
</div>
|
214 |
+
</div>
|
215 |
+
|
216 |
+
<div class="row">
|
217 |
+
<div class="col s12 m3 label">
|
218 |
+
<label for="sftp_private_key"><?php echo __( "SFTP Private Key(RSA)", 'xcloner-backup-and-restore' ) ?></label>
|
219 |
+
</div>
|
220 |
+
<div class=" col s12 m6">
|
221 |
+
<textarea rows="5"
|
222 |
+
placeholder="<?php echo __( "Local Server Path or Contents of the SFTP Private Key RSA File", 'xcloner-backup-and-restore' ) ?>"
|
223 |
+
id="sftp_private_key" type="text" name="xcloner_sftp_private_key"
|
224 |
+
class="validate"
|
225 |
+
value=""><?php echo get_option( "xcloner_sftp_private_key" ) ?></textarea>
|
226 |
+
</div>
|
227 |
+
</div>
|
228 |
+
|
229 |
+
<div class="row">
|
230 |
+
<div class="col s12 m3 label">
|
231 |
+
<label for="sftp_root"><?php echo __( "SFTP Storage Folder", 'xcloner-backup-and-restore' ) ?></label>
|
232 |
+
</div>
|
233 |
+
<div class=" col s12 m6">
|
234 |
+
<input placeholder="<?php echo __( "SFTP Storage Folder", 'xcloner-backup-and-restore' ) ?>"
|
235 |
+
id="sftp_root" type="text" name="xcloner_sftp_path" class="validate"
|
236 |
+
value="<?php echo get_option( "xcloner_sftp_path" ) ?>">
|
237 |
+
</div>
|
238 |
+
</div>
|
239 |
+
|
240 |
+
<div class="row">
|
241 |
+
<div class="col s12 m3 label">
|
242 |
+
<label for="sftp_timeout"><?php echo __( "SFTP Timeout", 'xcloner-backup-and-restore' ) ?></label>
|
243 |
+
</div>
|
244 |
+
<div class=" col s12 m2">
|
245 |
+
<input placeholder="<?php echo __( "SFTP Timeout", 'xcloner-backup-and-restore' ) ?>"
|
246 |
+
id="sftp_timeout" type="text" name="xcloner_sftp_timeout" class="validate"
|
247 |
+
value="<?php echo get_option( "xcloner_sftp_timeout", 30 ) ?>">
|
248 |
+
</div>
|
249 |
+
</div>
|
250 |
+
|
251 |
+
<div class="row">
|
252 |
+
<div class="col s12 m3 label">
|
253 |
+
<label for="sftp_cleanup_days"><?php echo __( "SFTP Cleanup (days)", 'xcloner-backup-and-restore' ) ?></label>
|
254 |
+
</div>
|
255 |
+
<div class=" col s12 m6">
|
256 |
+
<input placeholder="<?php echo __( "how many days to keep the backups for", 'xcloner-backup-and-restore' ) ?>"
|
257 |
+
id="sftp_cleanup_days" type="text" name="xcloner_sftp_cleanup_days"
|
258 |
+
class="validate" value="<?php echo get_option( "xcloner_sftp_cleanup_days" ) ?>">
|
259 |
+
</div>
|
260 |
+
</div>
|
261 |
+
|
262 |
+
<div class="row">
|
263 |
+
<div class="col s6 m4">
|
264 |
+
<button class="btn waves-effect waves-light" type="submit" name="action" id="action"
|
265 |
+
value="sftp"><?php echo __( "Save Settings", 'xcloner-backup-and-restore' ) ?>
|
266 |
+
<i class="material-icons right">save</i>
|
267 |
+
</button>
|
268 |
+
</div>
|
269 |
+
<div class="col s6 m4">
|
270 |
+
<button class="btn waves-effect waves-light orange" type="submit" name="action"
|
271 |
+
id="action" value="sftp"
|
272 |
+
onclick="jQuery('#connection_check').val('1')"><?php echo __( "Verify", 'xcloner-backup-and-restore' ) ?>
|
273 |
+
<i class="material-icons right">import_export</i>
|
274 |
+
</button>
|
275 |
+
</div>
|
276 |
+
</div>
|
277 |
+
|
278 |
+
</div>
|
279 |
+
</li>
|
280 |
+
|
281 |
+
<!-- AWS STORAGE-->
|
282 |
+
<li id="aws">
|
283 |
+
<div class="collapsible-header">
|
284 |
+
<i class="material-icons">computer</i><?php echo __( "S3 Storage", 'xcloner-backup-and-restore' ) ?>
|
285 |
+
<div class="switch right">
|
286 |
+
<label>
|
287 |
+
Off
|
288 |
+
<input type="checkbox" name="xcloner_aws_enable" class="status"
|
289 |
+
value="1" <?php if ( get_option( "xcloner_aws_enable" ) )
|
290 |
+
echo "checked" ?> \>
|
291 |
+
<span class="lever"></span>
|
292 |
+
On
|
293 |
+
</label>
|
294 |
+
</div>
|
295 |
+
</div>
|
296 |
+
<div class="collapsible-body">
|
297 |
+
|
298 |
+
<div class="row">
|
299 |
+
<div class="col s12 m3 label">
|
300 |
+
|
301 |
+
</div>
|
302 |
+
<div class=" col s12 m6">
|
303 |
+
<p>
|
304 |
+
<?php echo sprintf( __( 'Visit %s and get your "Key" and "Secret <br />Visit %s to install your own S3 like service.' ), "<a href='https://aws.amazon.com/s3/' target='_blank'>https://aws.amazon.com/s3/</a>", "<a href='https://minio.io/' target='_blank'>https://minio.io/</a>" ) ?>
|
305 |
+
</p>
|
306 |
+
</div>
|
307 |
+
</div>
|
308 |
+
|
309 |
+
<div class="row">
|
310 |
+
<div class="col s12 m3 label">
|
311 |
+
<label for="aws_key"><?php echo __( "S3 Key", 'xcloner-backup-and-restore' ) ?></label>
|
312 |
+
</div>
|
313 |
+
<div class=" col s12 m6">
|
314 |
+
<input placeholder="<?php echo __( "S3 Key", 'xcloner-backup-and-restore' ) ?>"
|
315 |
+
id="aws_key" type="text" name="xcloner_aws_key" class="validate"
|
316 |
+
value="<?php echo get_option( "xcloner_aws_key" ) ?>" autocomplete="off">
|
317 |
+
</div>
|
318 |
+
</div>
|
319 |
+
|
320 |
+
<div class="row">
|
321 |
+
<div class="col s12 m3 label">
|
322 |
+
<label for="aws_secret"><?php echo __( "S3 Secret", 'xcloner-backup-and-restore' ) ?></label>
|
323 |
+
</div>
|
324 |
+
<div class=" col s12 m6">
|
325 |
+
<input placeholder="<?php echo __( "S3 Secret", 'xcloner-backup-and-restore' ) ?>"
|
326 |
+
id="aws_secret" type="text" name="xcloner_aws_secret" class="validate"
|
327 |
+
value="<?php echo get_option( "xcloner_aws_secret" ) ?>" autocomplete="off">
|
328 |
+
</div>
|
329 |
+
</div>
|
330 |
+
|
331 |
+
<div class="row">
|
332 |
+
<div class="col s12 m3 label">
|
333 |
+
<label for="aws_region"><?php echo __( "S3 Region", 'xcloner-backup-and-restore' ) ?></label>
|
334 |
+
</div>
|
335 |
+
<div class=" col s12 m6">
|
336 |
+
<select placeholder="<?php echo __( "example: us-east-1", 'xcloner-backup-and-restore' ) ?>"
|
337 |
+
id="aws_region" type="text" name="xcloner_aws_region" class="validate"
|
338 |
+
value="<?php echo get_option( "xcloner_aws_region" ) ?>" autocomplete="off">
|
339 |
+
<option readonly
|
340 |
+
value=""><?php echo __( "Please Select AWS S3 Region or Leave Unselected for Custom Endpoint" ) ?></option>
|
341 |
+
<?php
|
342 |
+
$aws_regions = $remote_storage->get_aws_regions();
|
343 |
+
|
344 |
+
foreach ( $aws_regions as $key => $region ) {
|
345 |
+
?>
|
346 |
+
<option value="<?php echo $key ?>" <?php echo( $key == get_option( 'xcloner_aws_region' ) ? "selected" : "" ) ?>><?php echo $region ?>
|
347 |
+
= <?php echo $key ?></option>
|
348 |
+
<?php
|
349 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
350 |
?>
|
351 |
+
</select>
|
352 |
+
</div>
|
353 |
+
</div>
|
354 |
+
|
355 |
+
<div class="row">
|
356 |
+
<div class="col s12 m3 label">
|
357 |
+
<label for="aws_endpoint"><?php echo __( "S3 EndPoint", 'xcloner-backup-and-restore' ) ?></label>
|
358 |
+
</div>
|
359 |
+
<div class=" col s12 m6">
|
360 |
+
<input placeholder="<?php echo __( "S3 EndPoint, leave blank if you want to use the default Amazon AWS Service", 'xcloner-backup-and-restore' ) ?>"
|
361 |
+
id="aws_endpoint" type="text" name="xcloner_aws_endpoint" class="validate"
|
362 |
+
value="<?php echo get_option( "xcloner_aws_endpoint" ) ?>" autocomplete="off">
|
363 |
+
</div>
|
364 |
+
</div>
|
365 |
+
|
366 |
+
<div class="row">
|
367 |
+
<div class="col s12 m3 label">
|
368 |
+
<label for="aws_bucket_name"><?php echo __( "S3 Bucket Name", 'xcloner-backup-and-restore' ) ?></label>
|
369 |
+
</div>
|
370 |
+
<div class=" col s12 m6">
|
371 |
+
<input placeholder="<?php echo __( "S3 Bucket Name", 'xcloner-backup-and-restore' ) ?>"
|
372 |
+
id="aws_bucket_name" type="text" name="xcloner_aws_bucket_name" class="validate"
|
373 |
+
value="<?php echo get_option( "xcloner_aws_bucket_name" ) ?>" autocomplete="off">
|
374 |
+
</div>
|
375 |
+
</div>
|
376 |
+
|
377 |
+
<div class="row">
|
378 |
+
<div class="col s12 m3 label">
|
379 |
+
<label for="aws_prefix"><?php echo __( "S3 Prefix", 'xcloner-backup-and-restore' ) ?></label>
|
380 |
+
</div>
|
381 |
+
<div class=" col s12 m6">
|
382 |
+
<input placeholder="<?php echo __( "S3 Prefix, use / ending to define a folder", 'xcloner-backup-and-restore' ) ?>"
|
383 |
+
id="aws_prefix" type="text" name="xcloner_aws_prefix" class="validate"
|
384 |
+
value="<?php echo get_option( "xcloner_aws_prefix" ) ?>" autocomplete="off">
|
385 |
+
</div>
|
386 |
+
</div>
|
387 |
+
|
388 |
+
<div class="row">
|
389 |
+
<div class="col s12 m3 label">
|
390 |
+
<label for="aws_cleanup_days"><?php echo __( "S3 Cleanup (days)", 'xcloner-backup-and-restore' ) ?></label>
|
391 |
+
</div>
|
392 |
+
<div class=" col s12 m6">
|
393 |
+
<input placeholder="<?php echo __( "how many days to keep the backups for", 'xcloner-backup-and-restore' ) ?>"
|
394 |
+
id="aws_cleanup_days" type="text" name="xcloner_aws_cleanup_days"
|
395 |
+
class="validate" value="<?php echo get_option( "xcloner_aws_cleanup_days" ) ?>">
|
396 |
+
</div>
|
397 |
+
</div>
|
398 |
+
|
399 |
+
<div class="row">
|
400 |
+
<div class="col s6 m4">
|
401 |
+
<button class="btn waves-effect waves-light" type="submit" name="action" id="action"
|
402 |
+
value="aws"><?php echo __( "Save Settings", 'xcloner-backup-and-restore' ) ?>
|
403 |
+
<i class="material-icons right">save</i>
|
404 |
+
</button>
|
405 |
+
</div>
|
406 |
+
<div class="col s6 m4">
|
407 |
+
<button class="btn waves-effect waves-light orange" type="submit" name="action"
|
408 |
+
id="action" value="aws"
|
409 |
+
onclick="jQuery('#connection_check').val('1')"><?php echo __( "Verify", 'xcloner-backup-and-restore' ) ?>
|
410 |
+
<i class="material-icons right">import_export</i>
|
411 |
+
</button>
|
412 |
+
</div>
|
413 |
+
</div>
|
414 |
+
|
415 |
+
</div>
|
416 |
+
</li>
|
417 |
+
|
418 |
+
<!-- DROPBOX STORAGE-->
|
419 |
+
<li id="dropbox">
|
420 |
+
<div class="collapsible-header">
|
421 |
+
<i class="material-icons">computer</i><?php echo __( "Dropbox Storage", 'xcloner-backup-and-restore' ) ?>
|
422 |
+
<div class="switch right">
|
423 |
+
<label>
|
424 |
+
Off
|
425 |
+
<input type="checkbox" name="xcloner_dropbox_enable" class="status"
|
426 |
+
value="1" <?php if ( get_option( "xcloner_dropbox_enable" ) )
|
427 |
+
echo "checked" ?> \>
|
428 |
+
<span class="lever"></span>
|
429 |
+
On
|
430 |
+
</label>
|
431 |
+
</div>
|
432 |
+
</div>
|
433 |
+
<div class="collapsible-body">
|
434 |
+
|
435 |
+
<div class="row">
|
436 |
+
<div class="col s12 m3 label">
|
437 |
+
|
438 |
+
</div>
|
439 |
+
<div class=" col s12 m6">
|
440 |
+
<p>
|
441 |
+
<?php echo sprintf( __( 'Visit %s and get your "App secret".' ), "<a href='https://www.dropbox.com/developers/apps' target='_blank'>https://www.dropbox.com/developers/apps</a>" ) ?>
|
442 |
+
</p>
|
443 |
+
</div>
|
444 |
+
</div>
|
445 |
+
|
446 |
+
<div class="row">
|
447 |
+
<div class="col s12 m3 label">
|
448 |
+
<label for="dropbox_access_token"><?php echo __( "Dropbox Access Token", 'xcloner-backup-and-restore' ) ?></label>
|
449 |
+
</div>
|
450 |
+
<div class=" col s12 m6">
|
451 |
+
<input placeholder="<?php echo __( "Dropbox Access Token", 'xcloner-backup-and-restore' ) ?>"
|
452 |
+
id="dropbox_access_token" type="text" name="xcloner_dropbox_access_token"
|
453 |
+
class="validate"
|
454 |
+
value="<?php echo get_option( "xcloner_dropbox_access_token" ) ?>"
|
455 |
+
autocomplete="off">
|
456 |
+
</div>
|
457 |
+
</div>
|
458 |
+
|
459 |
+
|
460 |
+
<div class="row">
|
461 |
+
<div class="col s12 m3 label">
|
462 |
+
<label for="dropbox_app_secret"><?php echo __( "Dropbox App Secret", 'xcloner-backup-and-restore' ) ?></label>
|
463 |
+
</div>
|
464 |
+
<div class=" col s12 m6">
|
465 |
+
<input placeholder="<?php echo __( "Dropbox App Secret", 'xcloner-backup-and-restore' ) ?>"
|
466 |
+
id="dropbox_app_secret" type="text" name="xcloner_dropbox_app_secret"
|
467 |
+
class="validate" value="<?php echo get_option( "xcloner_dropbox_app_secret" ) ?>"
|
468 |
+
autocomplete="off">
|
469 |
+
</div>
|
470 |
+
</div>
|
471 |
+
|
472 |
+
<div class="row">
|
473 |
+
<div class="col s12 m3 label">
|
474 |
+
<label for="dropbox_prefix"><?php echo __( "Dropbox Prefix", 'xcloner-backup-and-restore' ) ?></label>
|
475 |
+
</div>
|
476 |
+
<div class=" col s12 m6">
|
477 |
+
<input placeholder="<?php echo __( "Dropbox Prefix", 'xcloner-backup-and-restore' ) ?>"
|
478 |
+
id="dropbox_prefix" type="text" name="xcloner_dropbox_prefix" class="validate"
|
479 |
+
value="<?php echo get_option( "xcloner_dropbox_prefix" ) ?>">
|
480 |
+
</div>
|
481 |
+
</div>
|
482 |
+
|
483 |
+
<div class="row">
|
484 |
+
<div class="col s12 m3 label">
|
485 |
+
<label for="dropbox_cleanup_days"><?php echo __( "Dropbox Cleanup (days)", 'xcloner-backup-and-restore' ) ?></label>
|
486 |
+
</div>
|
487 |
+
<div class=" col s12 m6">
|
488 |
+
<input placeholder="<?php echo __( "how many days to keep the backups for", 'xcloner-backup-and-restore' ) ?>"
|
489 |
+
id="dropbox_cleanup_days" type="text" name="xcloner_dropbox_cleanup_days"
|
490 |
+
class="validate"
|
491 |
+
value="<?php echo get_option( "xcloner_dropbox_cleanup_days" ) ?>">
|
492 |
+
</div>
|
493 |
+
</div>
|
494 |
+
|
495 |
+
<div class="row">
|
496 |
+
<div class="col s6 m4">
|
497 |
+
<button class="btn waves-effect waves-light" type="submit" name="action" id="action"
|
498 |
+
value="dropbox"><?php echo __( "Save Settings", 'xcloner-backup-and-restore' ) ?>
|
499 |
+
<i class="material-icons right">save</i>
|
500 |
+
</button>
|
501 |
+
</div>
|
502 |
+
<div class="col s6 m4">
|
503 |
+
<button class="btn waves-effect waves-light orange" type="submit" name="action"
|
504 |
+
id="action" value="dropbox"
|
505 |
+
onclick="jQuery('#connection_check').val('1')"><?php echo __( "Verify", 'xcloner-backup-and-restore' ) ?>
|
506 |
+
<i class="material-icons right">import_export</i>
|
507 |
+
</button>
|
508 |
+
</div>
|
509 |
+
</div>
|
510 |
+
|
511 |
+
</div>
|
512 |
+
</li>
|
513 |
+
|
514 |
+
<!-- AZURE STORAGE-->
|
515 |
+
<li id="azure">
|
516 |
+
<div class="collapsible-header">
|
517 |
+
<i class="material-icons">computer</i><?php echo __( "Azure Blob Storage", 'xcloner-backup-and-restore' ) ?>
|
518 |
+
<div class="switch right">
|
519 |
+
<label>
|
520 |
+
Off
|
521 |
+
<input type="checkbox" name="xcloner_azure_enable" class="status"
|
522 |
+
value="1" <?php if ( get_option( "xcloner_azure_enable" ) )
|
523 |
+
echo "checked" ?> \>
|
524 |
+
<span class="lever"></span>
|
525 |
+
On
|
526 |
+
</label>
|
527 |
+
</div>
|
528 |
+
</div>
|
529 |
+
<div class="collapsible-body">
|
530 |
+
|
531 |
+
<div class="row">
|
532 |
+
<div class="col s12 m3 label">
|
533 |
+
|
534 |
+
</div>
|
535 |
+
<div class=" col s12 m6">
|
536 |
+
<p>
|
537 |
+
<?php echo sprintf( __( 'Visit %s and get your "Api Key".', 'xcloner-backup-and-restore' ), '<a href="https://azure.microsoft.com/en-us/services/storage/blobs/" target="_blank">https://azure.microsoft.com/en-us/services/storage/blobs/</a>' ) ?>
|
538 |
+
</p>
|
539 |
+
</div>
|
540 |
+
</div>
|
541 |
+
|
542 |
+
<div class="row">
|
543 |
+
<div class="col s12 m3 label">
|
544 |
+
<label for="azure_account_name"><?php echo __( "Azure Account Name", 'xcloner-backup-and-restore' ) ?></label>
|
545 |
+
</div>
|
546 |
+
<div class=" col s12 m6">
|
547 |
+
<input placeholder="<?php echo __( "Azure Account Name", 'xcloner-backup-and-restore' ) ?>"
|
548 |
+
id="azure_account_name" type="text" name="xcloner_azure_account_name"
|
549 |
+
class="validate" value="<?php echo get_option( "xcloner_azure_account_name" ) ?>"
|
550 |
+
autocomplete="off">
|
551 |
+
</div>
|
552 |
+
</div>
|
553 |
+
|
554 |
+
|
555 |
+
<div class="row">
|
556 |
+
<div class="col s12 m3 label">
|
557 |
+
<label for="azure_api_key"><?php echo __( "Azure Api Key", 'xcloner-backup-and-restore' ) ?></label>
|
558 |
+
</div>
|
559 |
+
<div class=" col s12 m6">
|
560 |
+
<input placeholder="<?php echo __( "Azure Api Key", 'xcloner-backup-and-restore' ) ?>"
|
561 |
+
id="azure_api_key" type="text" name="xcloner_azure_api_key" class="validate"
|
562 |
+
value="<?php echo get_option( "xcloner_azure_api_key" ) ?>" autocomplete="off">
|
563 |
+
</div>
|
564 |
+
</div>
|
565 |
+
|
566 |
+
<div class="row">
|
567 |
+
<div class="col s12 m3 label">
|
568 |
+
<label for="azure_container"><?php echo __( "Azure Container", 'xcloner-backup-and-restore' ) ?></label>
|
569 |
+
</div>
|
570 |
+
<div class=" col s12 m6">
|
571 |
+
<input placeholder="<?php echo __( "Azure Container", 'xcloner-backup-and-restore' ) ?>"
|
572 |
+
id="azure_container" type="text" name="xcloner_azure_container" class="validate"
|
573 |
+
value="<?php echo get_option( "xcloner_azure_container" ) ?>">
|
574 |
+
</div>
|
575 |
+
</div>
|
576 |
+
|
577 |
+
<div class="row">
|
578 |
+
<div class="col s12 m3 label">
|
579 |
+
<label for="azure_cleanup_days"><?php echo __( "Azure Cleanup (days)", 'xcloner-backup-and-restore' ) ?></label>
|
580 |
+
</div>
|
581 |
+
<div class=" col s12 m6">
|
582 |
+
<input placeholder="<?php echo __( "how many days to keep the backups for", 'xcloner-backup-and-restore' ) ?>"
|
583 |
+
id="azure_cleanup_days" type="text" name="xcloner_azure_cleanup_days"
|
584 |
+
class="validate"
|
585 |
+
value="<?php echo get_option( "xcloner_azure_cleanup_days" ) ?>">
|
586 |
+
</div>
|
587 |
+
</div>
|
588 |
+
|
589 |
+
<div class="row">
|
590 |
+
<div class="col s6 m4">
|
591 |
+
<button class="btn waves-effect waves-light" type="submit" name="action" id="action"
|
592 |
+
value="azure"><?php echo __( "Save Settings", 'xcloner-backup-and-restore' ) ?>
|
593 |
+
<i class="material-icons right">save</i>
|
594 |
+
</button>
|
595 |
+
</div>
|
596 |
+
<div class="col s6 m4">
|
597 |
+
<button class="btn waves-effect waves-light orange" type="submit" name="action"
|
598 |
+
id="action" value="azure"
|
599 |
+
onclick="jQuery('#connection_check').val('1')"><?php echo __( "Verify", 'xcloner-backup-and-restore' ) ?>
|
600 |
+
<i class="material-icons right">import_export</i>
|
601 |
+
</button>
|
602 |
+
</div>
|
603 |
+
</div>
|
604 |
+
|
605 |
+
</div>
|
606 |
+
</li>
|
607 |
+
|
608 |
+
<!-- BACKBLAZE STORAGE-->
|
609 |
+
<li id="backblaze">
|
610 |
+
<div class="collapsible-header">
|
611 |
+
<i class="material-icons">computer</i><?php echo __( "Backblaze Storage", 'xcloner-backup-and-restore' ) ?>
|
612 |
+
<div class="switch right">
|
613 |
+
<label>
|
614 |
+
Off
|
615 |
+
<input type="checkbox" name="xcloner_backblaze_enable" class="status"
|
616 |
+
value="1" <?php if ( get_option( "xcloner_backblaze_enable" ) )
|
617 |
+
echo "checked" ?> \>
|
618 |
+
<span class="lever"></span>
|
619 |
+
On
|
620 |
+
</label>
|
621 |
+
</div>
|
622 |
+
</div>
|
623 |
+
<div class="collapsible-body">
|
624 |
+
|
625 |
+
<div class="row">
|
626 |
+
<div class="col s12 m3 label">
|
627 |
+
|
628 |
+
</div>
|
629 |
+
<div class=" col s12 m6">
|
630 |
+
<p>
|
631 |
+
<?php echo sprintf( __( 'Visit %s and get your Account Id and Application Key.', 'xcloner-backup-and-restore' ), '<a href="https://secure.backblaze.com/b2_buckets.htm" target="_blank">https://secure.backblaze.com/b2_buckets.htm</a>' ) ?>
|
632 |
+
</p>
|
633 |
+
</div>
|
634 |
+
</div>
|
635 |
+
|
636 |
+
<div class="row">
|
637 |
+
<div class="col s12 m3 label">
|
638 |
+
<label for="backblaze_account_id"><?php echo __( "Backblaze Account Id", 'xcloner-backup-and-restore' ) ?></label>
|
639 |
+
</div>
|
640 |
+
<div class=" col s12 m6">
|
641 |
+
<input placeholder="<?php echo __( "Backblaze Account Id", 'xcloner-backup-and-restore' ) ?>"
|
642 |
+
id="backblaze_account_id" type="text" name="xcloner_backblaze_account_id"
|
643 |
+
class="validate"
|
644 |
+
value="<?php echo get_option( "xcloner_backblaze_account_id" ) ?>"
|
645 |
+
autocomplete="off">
|
646 |
+
</div>
|
647 |
+
</div>
|
648 |
+
|
649 |
+
|
650 |
+
<div class="row">
|
651 |
+
<div class="col s12 m3 label">
|
652 |
+
<label for="backblaze_application_key"><?php echo __( "Backblaze Application Key", 'xcloner-backup-and-restore' ) ?></label>
|
653 |
+
</div>
|
654 |
+
<div class=" col s12 m6">
|
655 |
+
<input placeholder="<?php echo __( "Backblaze Application Key", 'xcloner-backup-and-restore' ) ?>"
|
656 |
+
id="backblaze_application_key" type="text"
|
657 |
+
name="xcloner_backblaze_application_key" class="validate"
|
658 |
+
value="<?php echo get_option( "xcloner_backblaze_application_key" ) ?>"
|
659 |
+
autocomplete="off">
|
660 |
+
</div>
|
661 |
+
</div>
|
662 |
+
|
663 |
+
<div class="row">
|
664 |
+
<div class="col s12 m3 label">
|
665 |
+
<label for="backblaze_bucket_name"><?php echo __( "Backblaze Bucket Name", 'xcloner-backup-and-restore' ) ?></label>
|
666 |
+
</div>
|
667 |
+
<div class=" col s12 m6">
|
668 |
+
<input placeholder="<?php echo __( "Backblaze Bucket Name", 'xcloner-backup-and-restore' ) ?>"
|
669 |
+
id="backblaze_bucket_name" type="text" name="xcloner_backblaze_bucket_name"
|
670 |
+
class="validate"
|
671 |
+
value="<?php echo get_option( "xcloner_backblaze_bucket_name" ) ?>"
|
672 |
+
autocomplete="off">
|
673 |
+
</div>
|
674 |
+
</div>
|
675 |
+
|
676 |
+
<div class="row">
|
677 |
+
<div class="col s12 m3 label">
|
678 |
+
<label for="backblaze_cleanup_days"><?php echo __( "Backblaze Cleanup (days)", 'xcloner-backup-and-restore' ) ?></label>
|
679 |
+
</div>
|
680 |
+
<div class=" col s12 m6">
|
681 |
+
<input placeholder="<?php echo __( "how many days to keep the backups for", 'xcloner-backup-and-restore' ) ?>"
|
682 |
+
id="backblaze_cleanup_days" type="text" name="xcloner_backblaze_cleanup_days"
|
683 |
+
class="validate"
|
684 |
+
value="<?php echo get_option( "xcloner_backblaze_cleanup_days" ) ?>">
|
685 |
+
</div>
|
686 |
+
</div>
|
687 |
+
|
688 |
+
<div class="row">
|
689 |
+
<div class="col s6 m4">
|
690 |
+
<button class="btn waves-effect waves-light" type="submit" name="action" id="action"
|
691 |
+
value="backblaze"><?php echo __( "Save Settings", 'xcloner-backup-and-restore' ) ?>
|
692 |
+
<i class="material-icons right">save</i>
|
693 |
+
</button>
|
694 |
+
</div>
|
695 |
+
<div class="col s6 m4">
|
696 |
+
<button class="btn waves-effect waves-light orange" type="submit" name="action"
|
697 |
+
id="action" value="backblaze"
|
698 |
+
onclick="jQuery('#connection_check').val('1')"><?php echo __( "Verify", 'xcloner-backup-and-restore' ) ?>
|
699 |
+
<i class="material-icons right">import_export</i>
|
700 |
+
</button>
|
701 |
+
</div>
|
702 |
+
</div>
|
703 |
+
|
704 |
+
</div>
|
705 |
+
</li>
|
706 |
+
|
707 |
+
<!-- WEBDAV STORAGE-->
|
708 |
+
<li id="webdav">
|
709 |
+
<div class="collapsible-header">
|
710 |
+
<i class="material-icons">computer</i><?php echo __( "WebDAV Storage", 'xcloner-backup-and-restore' ) ?>
|
711 |
+
<div class="switch right">
|
712 |
+
<label>
|
713 |
+
Off
|
714 |
+
<input type="checkbox" name="xcloner_webdav_enable" class="status"
|
715 |
+
value="1" <?php if ( get_option( "xcloner_webdav_enable" ) )
|
716 |
+
echo "checked" ?> \>
|
717 |
+
<span class="lever"></span>
|
718 |
+
On
|
719 |
+
</label>
|
720 |
+
</div>
|
721 |
+
</div>
|
722 |
+
<div class="collapsible-body">
|
723 |
+
|
724 |
+
<div class="row">
|
725 |
+
<div class="col s12 m3 label">
|
726 |
+
|
727 |
+
</div>
|
728 |
+
<div class=" col s12 m6">
|
729 |
+
<p>
|
730 |
+
<?php //echo sprintf(__('Visit %s and get your Account Id and Application Key.','xcloner-backup-and-restore'), '<a href="https://secure.backblaze.com/b2_buckets.htm" target="_blank">https://secure.backblaze.com/b2_buckets.htm</a>')?>
|
731 |
+
</p>
|
732 |
+
</div>
|
733 |
+
</div>
|
734 |
+
|
735 |
+
<div class="row">
|
736 |
+
<div class="col s12 m3 label">
|
737 |
+
<label for="webdav_url"><?php echo __( "WebDAV Base Url", 'xcloner-backup-and-restore' ) ?></label>
|
738 |
+
</div>
|
739 |
+
<div class=" col s12 m6">
|
740 |
+
<input placeholder="<?php echo __( "WebDAV Base Url", 'xcloner-backup-and-restore' ) ?>"
|
741 |
+
id="webdav_url" type="text" name="xcloner_webdav_url" class="validate"
|
742 |
+
value="<?php echo get_option( "xcloner_webdav_url" ) ?>" autocomplete="off">
|
743 |
+
</div>
|
744 |
+
</div>
|
745 |
+
|
746 |
+
<div class="row">
|
747 |
+
<div class="col s12 m3 label">
|
748 |
+
<label for="webdav_username"><?php echo __( "WebDAV Username", 'xcloner-backup-and-restore' ) ?></label>
|
749 |
+
</div>
|
750 |
+
<div class=" col s12 m6">
|
751 |
+
<input placeholder="<?php echo __( "WebDAV Username", 'xcloner-backup-and-restore' ) ?>"
|
752 |
+
id="webdav_username" type="text" name="xcloner_webdav_username" class="validate"
|
753 |
+
value="<?php echo get_option( "xcloner_webdav_username" ) ?>" autocomplete="off">
|
754 |
+
</div>
|
755 |
+
</div>
|
756 |
+
|
757 |
+
<div class="row">
|
758 |
+
<div class="col s12 m3 label">
|
759 |
+
<label for="webdav_password"><?php echo __( "WebDAV Password", 'xcloner-backup-and-restore' ) ?></label>
|
760 |
+
</div>
|
761 |
+
<div class=" col s12 m6">
|
762 |
+
<input placeholder="<?php echo __( "WebDAV Password", 'xcloner-backup-and-restore' ) ?>"
|
763 |
+
id="webdav_password" type="password" name="xcloner_webdav_password"
|
764 |
+
class="validate" value="<?php echo get_option( "xcloner_webdav_password" ) ?>"
|
765 |
+
autocomplete="off">
|
766 |
+
</div>
|
767 |
+
</div>
|
768 |
+
|
769 |
+
<div class="row">
|
770 |
+
<div class="col s12 m3 label">
|
771 |
+
<label for="webdav_target_folder"><?php echo __( "WebDAV Target Folder", 'xcloner-backup-and-restore' ) ?></label>
|
772 |
+
</div>
|
773 |
+
<div class=" col s12 m6">
|
774 |
+
<input placeholder="<?php echo __( "WebDAV Target Folder", 'xcloner-backup-and-restore' ) ?>"
|
775 |
+
id="webdav_target_folder" type="text" name="xcloner_webdav_target_folder"
|
776 |
+
class="validate"
|
777 |
+
value="<?php echo get_option( "xcloner_webdav_target_folder" ) ?>"
|
778 |
+
autocomplete="off">
|
779 |
+
</div>
|
780 |
+
</div>
|
781 |
+
|
782 |
+
<div class="row">
|
783 |
+
<div class="col s12 m3 label">
|
784 |
+
<label for="webdav_cleanup_days"><?php echo __( "WebDAV Cleanup (days)", 'xcloner-backup-and-restore' ) ?></label>
|
785 |
+
</div>
|
786 |
+
<div class=" col s12 m6">
|
787 |
+
<input placeholder="<?php echo __( "how many days to keep the backups for", 'xcloner-backup-and-restore' ) ?>"
|
788 |
+
id="webdav_cleanup_days" type="text" name="xcloner_webdav_cleanup_days"
|
789 |
+
class="validate"
|
790 |
+
value="<?php echo get_option( "xcloner_webdav_cleanup_days" ) ?>">
|
791 |
+
</div>
|
792 |
+
</div>
|
793 |
+
|
794 |
+
<div class="row">
|
795 |
+
<div class="col s6 m4">
|
796 |
+
<button class="btn waves-effect waves-light" type="submit" name="action" id="action"
|
797 |
+
value="webdav"><?php echo __( "Save Settings", 'xcloner-backup-and-restore' ) ?>
|
798 |
+
<i class="material-icons right">save</i>
|
799 |
+
</button>
|
800 |
+
</div>
|
801 |
+
<div class="col s6 m4">
|
802 |
+
<button class="btn waves-effect waves-light orange" type="submit" name="action"
|
803 |
+
id="action" value="webdav"
|
804 |
+
onclick="jQuery('#connection_check').val('1')"><?php echo __( "Verify", 'xcloner-backup-and-restore' ) ?>
|
805 |
+
<i class="material-icons right">import_export</i>
|
806 |
+
</button>
|
807 |
+
</div>
|
808 |
+
</div>
|
809 |
+
|
810 |
+
</div>
|
811 |
+
</li>
|
812 |
+
|
813 |
+
<!-- Google DRIVE STORAGE-->
|
814 |
+
<li id="gdrive">
|
815 |
+
<div class="collapsible-header">
|
816 |
+
<i class="material-icons">computer</i><?php echo __( "Google Drive Storage", 'xcloner-backup-and-restore' ) ?>
|
817 |
+
<?php if ( $gdrive_construct ): ?>
|
818 |
+
<div class="switch right">
|
819 |
+
<label>
|
820 |
+
Off
|
821 |
+
<input type="checkbox" name="xcloner_gdrive_enable" class="status"
|
822 |
+
value="1" <?php if ( get_option( "xcloner_gdrive_enable" ) )
|
823 |
+
echo "checked" ?> \>
|
824 |
+
<span class="lever"></span>
|
825 |
+
On
|
826 |
+
</label>
|
827 |
+
</div>
|
828 |
+
<?php endif ?>
|
829 |
+
</div>
|
830 |
+
<div class="collapsible-body">
|
831 |
+
|
832 |
+
<?php if ( $gdrive_construct ) : ?>
|
833 |
+
|
834 |
+
<div class="row">
|
835 |
+
<div class="col s12 m3 label">
|
836 |
+
|
837 |
+
</div>
|
838 |
+
<div class=" col s12 m9">
|
839 |
+
<p>
|
840 |
+
<?php echo sprintf( __( 'Visit %s to create a new application and get your Client ID and Client Secret.', 'xcloner-backup-and-restore' ), '<a href="https://console.developers.google.com" target="_blank">https://console.developers.google.com</a>' ) ?>
|
841 |
+
<a href="https://youtu.be/YXUVPUVgG8k" target="_blank"
|
842 |
+
class="btn-floating tooltipped btn-small" data-position="right"
|
843 |
+
data-delay="50" data-html="true"
|
844 |
+
data-tooltip="<?php echo sprintf( __( 'Click here to view a short video explaining how to create the Client ID and Client Secret as well as connecting XCloner with the Google Drive API %s', 'xcloner-backup-and-restore' ), "<br />https://youtu.be/YXUVPUVgG8k" ) ?>"
|
845 |
+
data-tooltip-id="92c95730-94e9-7b59-bd52-14adc30d5e3e"><i
|
846 |
+
class="material-icons">help_outline</i></a>
|
847 |
+
</p>
|
848 |
+
</div>
|
849 |
+
</div>
|
850 |
+
|
851 |
+
<div class="row">
|
852 |
+
<div class="col s12 m3 label">
|
853 |
+
<label for="gdrive_client_id"><?php echo __( "Client ID", 'xcloner-backup-and-restore' ) ?></label>
|
854 |
+
</div>
|
855 |
+
<div class=" col s12 m6">
|
856 |
+
<input placeholder="<?php echo __( "Google Client ID", 'xcloner-backup-and-restore' ) ?>"
|
857 |
+
id="gdrive_client_id" type="text" name="xcloner_gdrive_client_id"
|
858 |
+
class="validate"
|
859 |
+
value="<?php echo get_option( "xcloner_gdrive_client_id" ) ?>">
|
860 |
+
</div>
|
861 |
+
</div>
|
862 |
+
|
863 |
+
<div class="row">
|
864 |
+
<div class="col s12 m3 label">
|
865 |
+
<label for="gdrive_client_secret"><?php echo __( "Client Secret", 'xcloner-backup-and-restore' ) ?></label>
|
866 |
+
</div>
|
867 |
+
<div class=" col s12 m6">
|
868 |
+
<input placeholder="<?php echo __( "Google Client Secret", 'xcloner-backup-and-restore' ) ?>"
|
869 |
+
id="gdrive_client_secret" type="text" name="xcloner_gdrive_client_secret"
|
870 |
+
class="validate"
|
871 |
+
value="<?php echo get_option( "xcloner_gdrive_client_secret" ) ?>">
|
872 |
+
</div>
|
873 |
+
</div>
|
874 |
+
|
875 |
+
|
876 |
+
<div class="row">
|
877 |
+
<div class="col s12 m3 label">
|
878 |
+
|
879 |
+
</div>
|
880 |
+
<div class=" col s12 m6">
|
881 |
+
<a class="btn" target="_blank" id="gdrive_authorization_click"
|
882 |
+
onclick="jQuery('#authentification_code').show()"
|
883 |
+
href="<?php echo $gdrive_auth_url ?>"><?php echo sprintf( __( 'Authorize Google Drive', 'xcloner-backup-and-restore' ) ) ?></a>
|
884 |
+
<input type="text" name="authentification_code" id="authentification_code"
|
885 |
+
placeholder="<?php echo __( "Paste Authorization Code Here", "xcloner-backup-and-restore" ) ?>">
|
886 |
+
</div>
|
887 |
+
</div>
|
888 |
+
|
889 |
+
<div class="row">
|
890 |
+
<div class="col s12 m3 label">
|
891 |
+
<label for="gdrive_target_folder"><?php echo __( "Folder ID or Root Path", 'xcloner-backup-and-restore' ) ?>
|
892 |
+
<a class="btn-floating tooltipped btn-small" data-position="right"
|
893 |
+
data-delay="50" data-html="true" \
|
894 |
+
data-tooltip="<?php echo __( 'Folder ID can be found by right clicking on the folder name and selecting \'Get shareable link\' menu, format https://drive.google.com/open?id={FOLDER_ID}<br />
|
895 |
+
If you supply a folder name, it has to exists in the drive root and start with / , example /backups.xcloner.com/', 'xcloner-backup-and-restore' ) ?>"
|
896 |
+
data-tooltip-id="92c95730-94e9-7b59-bd52-14adc30d5e3e"><i
|
897 |
+
class="material-icons">help_outline</i></a>
|
898 |
+
</label>
|
899 |
+
</div>
|
900 |
+
<div class=" col s12 m6">
|
901 |
+
<input placeholder="<?php echo __( "Target Folder ID or Root Path", 'xcloner-backup-and-restore' ) ?>"
|
902 |
+
id="gdrive_target_folder" type="text" name="xcloner_gdrive_target_folder"
|
903 |
+
class="validate"
|
904 |
+
value="<?php echo get_option( "xcloner_gdrive_target_folder" ) ?>"
|
905 |
+
autocomplete="off">
|
906 |
+
</div>
|
907 |
+
</div>
|
908 |
+
|
909 |
+
<div class="row">
|
910 |
+
<div class="col s12 m3 label">
|
911 |
+
<label for="gdrive_cleanup_days"><?php echo __( "Google Drive Cleanup (days)", 'xcloner-backup-and-restore' ) ?></label>
|
912 |
+
</div>
|
913 |
+
<div class=" col s12 m6">
|
914 |
+
<input placeholder="<?php echo __( "how many days to keep the backups for", 'xcloner-backup-and-restore' ) ?>"
|
915 |
+
id="gdrive_cleanup_days" type="text" name="xcloner_gdrive_cleanup_days"
|
916 |
+
class="validate"
|
917 |
+
value="<?php echo get_option( "xcloner_gdrive_cleanup_days" ) ?>">
|
918 |
+
</div>
|
919 |
+
</div>
|
920 |
+
|
921 |
+
<div class="row">
|
922 |
+
<div class="col s12 m3 label">
|
923 |
+
<label for="gdrive_empty_trash"><?php echo __( "Keeps Deleted Backups in Trash", 'xcloner-backup-and-restore' ) ?></label>
|
924 |
+
</div>
|
925 |
+
<div class=" col s12 m6 input-field inline">
|
926 |
+
<input name="xcloner_gdrive_empty_trash" type="radio" value="0"
|
927 |
+
id="gdrive_empty_trash_off" <?php if ( ! get_option( "xcloner_gdrive_empty_trash", 0 ) )
|
928 |
+
echo "checked" ?> />
|
929 |
+
<label for="gdrive_empty_trash_off"><?php echo __( "Enabled", 'xcloner-backup-and-restore' ) ?></label>
|
930 |
+
|
931 |
+
<input name="xcloner_gdrive_empty_trash" type="radio" value="1"
|
932 |
+
id="gdrive_empty_trash_on" <?php if ( get_option( "xcloner_gdrive_empty_trash", 0 ) )
|
933 |
+
echo "checked" ?> />
|
934 |
+
<label for="gdrive_empty_trash_on"><?php echo __( "Disabled", 'xcloner-backup-and-restore' ) ?></label>
|
935 |
+
</div>
|
936 |
+
</div>
|
937 |
+
|
938 |
+
<div class="row">
|
939 |
+
<div class="col s6 m4">
|
940 |
+
<button class="btn waves-effect waves-light" type="submit" name="action" id="action"
|
941 |
+
value="gdrive"><?php echo __( "Save Settings", 'xcloner-backup-and-restore' ) ?>
|
942 |
+
<i class="material-icons right">save</i>
|
943 |
+
</button>
|
944 |
+
</div>
|
945 |
+
<div class="col s6 m4">
|
946 |
+
<button class="btn waves-effect waves-light orange" type="submit" name="action"
|
947 |
+
id="action" value="gdrive"
|
948 |
+
onclick="jQuery('#connection_check').val('1')"><?php echo __( "Verify", 'xcloner-backup-and-restore' ) ?>
|
949 |
+
<i class="material-icons right">import_export</i>
|
950 |
+
</button>
|
951 |
+
</div>
|
952 |
+
</div>
|
953 |
+
<?php else: ?>
|
954 |
+
|
955 |
+
<div class="row">
|
956 |
+
<div class=" col s12">
|
957 |
+
<div class="center">
|
958 |
+
<?php
|
959 |
+
$url = wp_nonce_url( self_admin_url( 'update.php?action=install-plugin&plugin=xcloner-google-drive' ), 'install-plugin_xcloner-google-drive' );
|
960 |
+
?>
|
961 |
+
<h6><?php echo __( "This storage option requires the XCloner-Google-Drive Wordpress Plugin to be installed and activated." ) ?></h6>
|
962 |
+
<h6><?php echo __( "PHP 5.5 minimum version is required." ) ?></h6>
|
963 |
+
<br/>
|
964 |
+
<a class="install-now btn" data-slug="xcloner-google-drive"
|
965 |
+
href="<?php echo $url; ?>"
|
966 |
+
aria-label="Install XCloner Google Drive 1.0.0 now"
|
967 |
+
data-name="XCloner Google Drive 1.0.0">
|
968 |
+
<?php echo sprintf( __( 'Install Now', 'xcloner-backup-and-restore' ) ) ?>
|
969 |
+
</a>
|
970 |
+
|
971 |
+
<a href="<?php echo admin_url( "plugin-install.php" ) ?>?tab=plugin-information&plugin=xcloner-google-drive&TB_iframe=true&width=772&height=499"
|
972 |
+
class="btn thickbox open-plugin-details-modal"
|
973 |
+
aria-label="More information about Theme Check 20160523.1"
|
974 |
+
data-title="Theme Check 20160523.1">
|
975 |
+
<!--
|
976 |
+
<a class="btn" href="https://github.com/ovidiul/XCloner-Google-Drive/archive/master.zip">
|
977 |
+
-->
|
978 |
+
<?php echo sprintf( __( 'More Details', 'xcloner-backup-and-restore' ) ) ?>
|
979 |
+
</a>
|
980 |
+
</div>
|
981 |
+
</div>
|
982 |
+
</div>
|
983 |
+
|
984 |
+
<?php endif; ?>
|
985 |
+
|
986 |
+
</div>
|
987 |
+
</li>
|
988 |
+
|
989 |
+
|
990 |
+
</ul>
|
991 |
+
</div>
|
992 |
+
</div>
|
993 |
|
994 |
</form>
|
995 |
|
996 |
<script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
997 |
|
998 |
+
function checkEndpoint() {
|
999 |
+
if (jQuery("#aws_region").val() != "") {
|
1000 |
+
jQuery('#aws_endpoint').parent().parent().hide();
|
1001 |
+
} else {
|
1002 |
+
jQuery('#aws_endpoint').parent().parent().show();
|
1003 |
+
}
|
1004 |
+
}
|
1005 |
+
|
1006 |
+
jQuery(document).ready(function () {
|
1007 |
+
|
1008 |
+
var remote_storage = new Xcloner_Remote_Storage();
|
1009 |
+
|
1010 |
+
checkEndpoint()
|
1011 |
+
jQuery("#aws_region").on("change", function () {
|
1012 |
+
checkEndpoint();
|
1013 |
+
|
1014 |
+
})
|
1015 |
+
|
1016 |
+
jQuery(".remote-storage .status").on("change", function () {
|
1017 |
+
remote_storage.toggle_status(this);
|
1018 |
+
})
|
1019 |
+
|
1020 |
+
jQuery(".remote-storage-form #action").on("click", function () {
|
1021 |
+
var tag = jQuery(this).val()
|
1022 |
+
window.location.hash = "#" + tag;
|
1023 |
+
})
|
1024 |
+
|
1025 |
+
jQuery("#gdrive_authorization_click").on("click", function (e) {
|
1026 |
+
|
1027 |
+
var href = (jQuery(this).attr("href"))
|
1028 |
+
|
1029 |
+
var new_href = href.replace(/(client_id=).*?(&)/, '$1' + jQuery("#gdrive_client_id").val() + '$2');
|
1030 |
+
|
1031 |
+
jQuery(this).attr("href", new_href)
|
1032 |
+
|
1033 |
+
});
|
1034 |
+
|
1035 |
+
if (location.hash)
|
1036 |
+
jQuery(location.hash + " div.collapsible-header").addClass("active");
|
1037 |
+
|
1038 |
+
jQuery('.collapsible').collapsible();
|
1039 |
+
|
1040 |
+
Materialize.updateTextFields();
|
1041 |
+
|
1042 |
+
|
1043 |
+
});
|
1044 |
+
|
1045 |
</script>
|
admin/partials/xcloner_restore_page.php
CHANGED
@@ -1,402 +1,470 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
$xcloner_settings
|
4 |
-
$logger
|
5 |
-
$xcloner_file_system
|
6 |
-
$xcloner_file_transfer
|
7 |
|
8 |
-
$start = 0
|
9 |
|
10 |
$backup_list = $xcloner_file_system->get_latest_backups();
|
11 |
|
12 |
?>
|
13 |
|
14 |
-
<h1><?= esc_html(get_admin_page_title()); ?></h1>
|
15 |
|
16 |
-
<script>
|
17 |
-
|
18 |
</script>
|
19 |
|
20 |
<div class="row xcloner-restore">
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
</
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
<?php endif ?>
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
<div class="col s12">
|
233 |
-
<a class="btn-floating tooltipped btn-small right" data-position="left" data-delay="50" data-html="true" data-tooltip="<?php echo __('I will attempt to replace all mysql backup records matching the provided Source Url with the provided Target Url. <br />Leave blank the Target Url if you would like to skip this option. <br />As a bonus, I will also replace all matching serialized data and fix it\'s parsing.','xcloner-backup-and-restore')?>" data-tooltip-id="92c95730-94e9-7b59-bd52-14adc30d5e3e"><i class="material-icons">help_outline</i></a>
|
234 |
-
<h5><?php echo __('Target Mysql Search and Replace','xcloner-backup-and-restore')?></h5>
|
235 |
-
</div>
|
236 |
-
<div class="col s12">
|
237 |
-
<div class="input-field col s12 m6 ">
|
238 |
-
<input type="text" name="wp_home_url" id="wp_home_url" class="validate" placeholder="WP Home Url" value="<?php echo home_url();?>">
|
239 |
-
<label><?php echo __("Source Home Url",'xcloner-backup-and-restore')?></label>
|
240 |
-
</div>
|
241 |
-
|
242 |
-
<div class="input-field col s12 m6 ">
|
243 |
-
<input type="text" name="remote_restore_url" id="remote_restore_url" class="validate" placeholder="Restore Target Url">
|
244 |
-
<label><?php echo __("With Target Home Url",'xcloner-backup-and-restore')?></label>
|
245 |
-
</div>
|
246 |
-
|
247 |
-
<?php if( site_url() != home_url()) : ?>
|
248 |
-
<div class="input-field col s12 m6 ">
|
249 |
-
<input type="text" name="wp_site_url" id="wp_site_url" class="validate" placeholder="WP Site Url" value="<?php echo site_url();?>">
|
250 |
-
<label><?php echo __("Source Site Url",'xcloner-backup-and-restore')?></label>
|
251 |
-
</div>
|
252 |
-
|
253 |
-
<div class="input-field col s12 m6 ">
|
254 |
-
<input type="text" name="remote_restore_site_url" id="remote_restore_site_url" class="validate" placeholder="Restore Target Url">
|
255 |
-
<label><?php echo __("With Target Site Url",'xcloner-backup-and-restore')?></label>
|
256 |
-
</div>
|
257 |
-
|
258 |
-
<?php endif;?>
|
259 |
-
</div>
|
260 |
-
|
261 |
-
</div>
|
262 |
-
|
263 |
-
<div class=" col s12 l7">
|
264 |
-
<div class="input-field row">
|
265 |
-
<select id="remote_database_file" name="remote_database_file" class="browser-default">
|
266 |
-
<option value="" disabled selected><?php echo __("Please select the target database backup file to restore",'xcloner-backup-and-restore')?></option>
|
267 |
-
</select>
|
268 |
-
|
269 |
-
<label></label>
|
270 |
-
</div>
|
271 |
-
|
272 |
-
<div class="progress">
|
273 |
-
<div class="determinate" style="width: 0%"></div>
|
274 |
-
</div>
|
275 |
-
|
276 |
-
<div class="status"></div>
|
277 |
-
<div class="query-box">
|
278 |
-
<h6><?php echo __('Use the field below to fix your mysql query and Retry again the Restore, or replace with # to Skip next', 'xcloner-backup-and-restore')?></h6>
|
279 |
-
<textarea class="query-list" cols="5"></textarea>
|
280 |
-
</div>
|
281 |
-
</div>
|
282 |
-
|
283 |
-
<div class="col s12 l5 right-align">
|
284 |
-
<div class="toggler">
|
285 |
-
<button class="btn waves-effect waves-light restore_remote_mysqldump normal " type="submit" id="" name="action"><?php echo __("Restore",'xcloner-backup-and-restore')?>
|
286 |
-
<i class="material-icons left">navigate_before</i>
|
287 |
-
</button>
|
288 |
-
<button class="btn waves-effect waves-light red restore_remote_mysqldump cancel" type="submit" id="" name="action"><?php echo __("Cancel",'xcloner-backup-and-restore')?>
|
289 |
-
<i class="material-icons right">close</i>
|
290 |
-
</button>
|
291 |
-
</div>
|
292 |
-
|
293 |
-
<button class="btn waves-effect waves-light grey" type="submit" title="<?php echo __("Skip Next",'xcloner-backup-and-restore')?>" id="skip_restore_remote_database_step" name="action"><?php echo __("Skip Next",'xcloner-backup-and-restore')?>
|
294 |
-
<i class="material-icons right">navigate_next</i>
|
295 |
-
</button>
|
296 |
-
|
297 |
-
</div>
|
298 |
-
|
299 |
-
</div>
|
300 |
-
</li>
|
301 |
-
|
302 |
-
<li data-step="5" class="restore-finish-step steps active">
|
303 |
-
<div class="collapsible-header"><i class="material-icons">folder_open</i><?php echo __("Finishing up...",'xcloner-backup-and-restore')?>
|
304 |
-
</div>
|
305 |
-
<div class="collapsible-body row">
|
306 |
-
|
307 |
-
<div class="row">
|
308 |
-
<div class="col s4">
|
309 |
-
<label><?php echo __("Update wp-config.php mysql details and update the Target Site Url",'xcloner-backup-and-restore')?></label>
|
310 |
-
</div>
|
311 |
-
|
312 |
-
<div class="col s8">
|
313 |
-
<div class="switch">
|
314 |
-
<label>
|
315 |
-
Off
|
316 |
-
<input type="checkbox" id="update_remote_site_url" name="update_remote_site_url" checked value="1">
|
317 |
-
<span class="lever"></span>
|
318 |
-
On
|
319 |
-
</label>
|
320 |
-
</div>
|
321 |
-
</div>
|
322 |
-
</div>
|
323 |
-
|
324 |
-
<div class="row">
|
325 |
-
<div class="col s4">
|
326 |
-
<label><?php echo __("Delete Restored Backup Temporary Folder",'xcloner-backup-and-restore')?></label>
|
327 |
-
</div>
|
328 |
-
<div class="col s8">
|
329 |
-
<div class="switch">
|
330 |
-
<label>
|
331 |
-
Off
|
332 |
-
<input type="checkbox" id="delete_backup_temporary_folder" name="delete_backup_temporary_folder" checked value="1">
|
333 |
-
<span class="lever"></span>
|
334 |
-
On
|
335 |
-
</label>
|
336 |
-
</div>
|
337 |
-
</div>
|
338 |
-
</div>
|
339 |
-
|
340 |
-
<div class="row">
|
341 |
-
<div class="col s4">
|
342 |
-
<label><?php echo __("Delete Restore Script",'xcloner-backup-and-restore')?></label>
|
343 |
-
</div>
|
344 |
-
<div class="col s8">
|
345 |
-
<div class="switch">
|
346 |
-
<label>
|
347 |
-
Off
|
348 |
-
<input type="checkbox" id="delete_restore_script" name="delete_restore_script" checked value="1">
|
349 |
-
<span class="lever"></span>
|
350 |
-
On
|
351 |
-
</label>
|
352 |
-
</div>
|
353 |
-
</div>
|
354 |
-
</div>
|
355 |
-
|
356 |
-
<div class=" row col s12">
|
357 |
-
<div class="status"></div>
|
358 |
-
</div>
|
359 |
-
|
360 |
-
<div class=" row col s12 center-align" id="xcloner_restore_finish">
|
361 |
-
<h5><?php echo __("Thank you for using XCloner.",'xcloner-backup-and-restore')?></h5>
|
362 |
-
<h6><?php echo sprintf(__("We would love to hear about your experience in the %s.", 'xcloner-backup-and-restore'),'<a href="https://wordpress.org/support/plugin/xcloner-backup-and-restore" target="_blank">Wordpress XCloner forums</a>') ?></h6>
|
363 |
-
<a class="twitter-follow-button" href="https://twitter.com/thinkovi" data-show-count="false">Follow @thinkovi</a>
|
364 |
-
<script src="//platform.twitter.com/widgets.js" async="" charset="utf-8"></script>
|
365 |
-
</div>
|
366 |
-
|
367 |
-
<div class="col s12 center-align">
|
368 |
-
<div class="row">
|
369 |
-
<div class="col s6 right-align">
|
370 |
-
<button class="btn waves-effect waves-light teal" type="submit" id="restore_finish" name="action"><?php echo __("Finish",'xcloner-backup-and-restore')?>
|
371 |
-
<i class="material-icons right">navigate_next</i>
|
372 |
-
</button>
|
373 |
-
</div>
|
374 |
-
|
375 |
-
<div id="open_target_site" class="col s6 left-align">
|
376 |
-
<a disabled="disabled" href="#" class="btn waves-effect waves-light teal" type="button" target="_blank"><?php echo __("Open Target Site",'xcloner-backup-and-restore')?>
|
377 |
-
<i class="material-icons right">navigate_next</i>
|
378 |
-
</a>
|
379 |
-
</div>
|
380 |
-
</div>
|
381 |
-
</div>
|
382 |
-
</div>
|
383 |
-
</li>
|
384 |
-
|
385 |
-
</ul>
|
386 |
-
</div>
|
387 |
-
</div>
|
388 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
389 |
|
390 |
|
391 |
<!-- List Backup Content Modal-->
|
392 |
<div id="backup_cotent_modal" class="modal">
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
</div>
|
1 |
<?php
|
2 |
|
3 |
+
$xcloner_settings = $this->get_xcloner_container()->get_xcloner_settings();
|
4 |
+
$logger = $this->get_xcloner_container()->get_xcloner_logger();
|
5 |
+
$xcloner_file_system = $this->get_xcloner_container()->get_xcloner_filesystem();
|
6 |
+
$xcloner_file_transfer = $this->get_xcloner_container()->get_xcloner_file_transfer();
|
7 |
|
8 |
+
$start = 0;
|
9 |
|
10 |
$backup_list = $xcloner_file_system->get_latest_backups();
|
11 |
|
12 |
?>
|
13 |
|
14 |
+
<h1><?= esc_html( get_admin_page_title() ); ?></h1>
|
15 |
|
16 |
+
<script>
|
17 |
+
var xcloner_auth_key = '<?php echo md5( AUTH_KEY )?>';
|
18 |
</script>
|
19 |
|
20 |
<div class="row xcloner-restore">
|
21 |
+
<div class="col s12">
|
22 |
+
<ul class="collapsible xcloner-restore " data-collapsible="accordion">
|
23 |
+
<li data-step="1" class="restore-script-upload-step steps active show">
|
24 |
+
<div class="collapsible-header active"><i
|
25 |
+
class="material-icons">settings_remote</i><?php echo __( "Restore Script Upload", 'xcloner-backup-and-restore' ) ?>
|
26 |
+
</div>
|
27 |
+
<div class="collapsible-body row">
|
28 |
+
|
29 |
+
<ul class="text-steps">
|
30 |
+
<li><?php echo __( "If you want to do a <strong>Local Target System Restore</strong>, leave Url field below empty and click 'Check Connection', you can skip the next steps.", 'xcloner-backup-and-restore' ) ?>
|
31 |
+
</li>
|
32 |
+
<li><?php echo __( "If you want to do a <strong>Remote Target System Restore</strong>, please download the restore script from", 'xcloner-backup-and-restore' ) ?>
|
33 |
+
<a href='#'
|
34 |
+
onclick="window.location=ajaxurl+'?action=download_restore_script&phar=true'"><strong><?php echo __( "here", 'xcloner-backup-and-restore' ) ?></strong></a>
|
35 |
+
</li>
|
36 |
+
<li>
|
37 |
+
<?php echo __( "Extract the restore script archive files on your new host", 'xcloner-backup-and-restore' ) ?>
|
38 |
+
</li>
|
39 |
+
<li>
|
40 |
+
<?php echo __( "Provide url below to the <u>xcloner_restore.php</u> restore script, like http://my_restore_site.com/xcloner_restore.php", 'xcloner-backup-and-restore' ) ?>
|
41 |
+
</li>
|
42 |
+
<li>
|
43 |
+
<?php echo __( "If your server is not web accessible, like a localhost computer, you can use a DynDNS service or install a blank copy of Wordpress with XCloner in the same environment and start the restore from there.", 'xcloner-backup-and-restore' ) ?>
|
44 |
+
</li>
|
45 |
+
<?php if ( is_ssl() ): ?>
|
46 |
+
<li class="warning">
|
47 |
+
<?php echo __( "We have detected your connection to the site as being secure, so your restore script address must start with https://." ) ?>
|
48 |
+
</li>
|
49 |
+
<?php endif ?>
|
50 |
+
|
51 |
+
</ul>
|
52 |
+
|
53 |
+
<div class="input-field col l9 s12">
|
54 |
+
<input value="<?php echo ( is_ssl() ) ? "https://" : "" ?>" id="restore_script_url" type="text"
|
55 |
+
class="validate"
|
56 |
+
placeholder="Url to XCloner Restore Script, example http://myddns.com/xcloner/xcloner_restore.php">
|
57 |
+
<label for="restore_script_url"></label>
|
58 |
+
<div id="url_validation_status" class="status"></div>
|
59 |
+
</div>
|
60 |
+
<div class="col l3 s12 right-align">
|
61 |
+
<button class="btn waves-effect waves-light" type="submit" id="validate_url"
|
62 |
+
name="action"><?php echo __( "Check Connection", 'xcloner-backup-and-restore' ) ?>
|
63 |
+
<i class="material-icons right">send</i>
|
64 |
+
</button>
|
65 |
+
</div>
|
66 |
+
</div>
|
67 |
+
</li>
|
68 |
+
|
69 |
+
<li data-step="2" class="backup-upload-step steps">
|
70 |
+
<div class="collapsible-header active"><i
|
71 |
+
class="material-icons">file_upload</i><?php echo __( "Upload Local Backup Archive To Target Host", 'xcloner-backup-and-restore' ) ?>
|
72 |
+
</div>
|
73 |
+
<div class="collapsible-body row">
|
74 |
+
<p><?php echo __( "You can skip this step if you want to transfer the archive in some other way, make sure you upload it in the same directory as the restore script from the previous step.", 'xcloner-backup-and-restore' ) ?></p>
|
75 |
+
<div class="input-field col s12 l7">
|
76 |
+
<select id="backup_file" name="backup_file" class="browser-default">
|
77 |
+
<option value="" disabled
|
78 |
+
selected><?php echo __( "Please select a local backup archive to upload to target host", 'xcloner-backup-and-restore' ) ?></option>
|
79 |
+
<?php if ( is_array( $backup_list ) ): ?>
|
80 |
+
<?php foreach ( $backup_list as $file ): ?>
|
81 |
+
<option value="<?php echo $file['basename'] ?>">
|
82 |
+
<?php echo $file['basename'] ?> (<?php echo size_format( $file['size'] ) ?>)
|
83 |
+
</option>
|
84 |
+
<?php endforeach ?>
|
85 |
<?php endif ?>
|
86 |
+
</select>
|
87 |
+
|
88 |
+
<label> </label>
|
89 |
+
<div class="progress">
|
90 |
+
<div class="determinate" style="width: 0%"></div>
|
91 |
+
</div>
|
92 |
+
<div class="status"></div>
|
93 |
+
</div>
|
94 |
+
<div class="col s12 l5 right-align">
|
95 |
+
<div class="toggler">
|
96 |
+
<button class="btn waves-effect waves-light upload-backup normal" type="submit" id=""
|
97 |
+
name="action"><?php echo __( "Upload", 'xcloner-backup-and-restore' ) ?>
|
98 |
+
<i class="material-icons left">navigate_before</i>
|
99 |
+
</button>
|
100 |
+
<button class="btn waves-effect waves-light red upload-backup cancel" type="submit" id=""
|
101 |
+
name="action"><?php echo __( "Cancel", 'xcloner-backup-and-restore' ) ?>
|
102 |
+
<i class="material-icons right">close</i>
|
103 |
+
</button>
|
104 |
+
</div>
|
105 |
+
<button class="btn waves-effect waves-light grey" type="submit"
|
106 |
+
title="<?php echo __( "Skip Next", 'xcloner-backup-and-restore' ) ?>"
|
107 |
+
id="skip_upload_backup"
|
108 |
+
name="action"><?php echo __( "Skip Next", 'xcloner-backup-and-restore' ) ?>
|
109 |
+
<i class="material-icons right">navigate_next</i>
|
110 |
+
</button>
|
111 |
+
</div>
|
112 |
+
</div>
|
113 |
+
</li>
|
114 |
+
|
115 |
+
<li data-step="3" class="restore-remote-backup-step steps active">
|
116 |
+
<div class="collapsible-header"><i
|
117 |
+
class="material-icons">folder_open</i><?php echo __( "Restore Files Backup Available On Target Location", 'xcloner-backup-and-restore' ) ?>
|
118 |
+
<i class="material-icons right" title="Refresh Target Backup Files List"
|
119 |
+
id="refresh_remote_backup_file">cached</i>
|
120 |
+
|
121 |
+
<div class="switch right">
|
122 |
+
<label>
|
123 |
+
<?php echo __( 'Verbose Output', 'xcloner-backup-and-restore' ) ?>
|
124 |
+
<input type="checkbox" id="toggle_file_restore_display" name="toggle_file_restore_display"
|
125 |
+
class="" checked value="1">
|
126 |
+
<span class="lever"></span>
|
127 |
+
|
128 |
+
</label>
|
129 |
+
</div>
|
130 |
+
</div>
|
131 |
+
<div class="collapsible-body row">
|
132 |
+
|
133 |
+
<div class=" col s12 l7">
|
134 |
+
<div class="input-field row">
|
135 |
+
<div class="col s12">
|
136 |
+
<a class="btn-floating tooltipped btn-small right" data-html="true" data-position="left"
|
137 |
+
data-delay="50"
|
138 |
+
data-tooltip="<?php echo __( "This is the directory where you would like to restore the backup archive files.<br />
|
139 |
+
Please use this with caution when restoring to a live site.", 'xcloner-backup-and-restore' ) ?>"><i
|
140 |
+
class="material-icons">help_outline</i>
|
141 |
+
</a>
|
142 |
+
<h5><?php echo __( "Restore Target Path:", 'xcloner-backup-and-restore' ) ?></h5>
|
143 |
+
<input type="text" name="remote_restore_path" id="remote_restore_path" class="validate"
|
144 |
+
placeholder="Restore Target Path">
|
145 |
+
<label></label>
|
146 |
+
</div>
|
147 |
+
|
148 |
+
</div>
|
149 |
+
|
150 |
+
<div class="input-field row">
|
151 |
+
<div class="col s12">
|
152 |
+
<a href="#backup_localhost-2017-04-03_10-58-sql-diff2017-03-22_00-00-5b6c4.tgz"
|
153 |
+
class="list-backup-content btn-floating tooltipped btn-small right"
|
154 |
+
data-tooltip="<?php echo __( 'Click To List The Selected Backup Content', 'xcloner-backup-and-restore' ) ?>">
|
155 |
+
<i class="material-icons">folder_open</i>
|
156 |
+
</a>
|
157 |
+
<h5><?php echo __( "Restore Backup Archive:", 'xcloner-backup-and-restore' ) ?></h5>
|
158 |
+
<select id="remote_backup_file" name="remote_backup_file" class="browser-default">
|
159 |
+
<option value="" disabled
|
160 |
+
selected><?php echo __( "Please select the target backup file to restore", 'xcloner-backup-and-restore' ) ?></option>
|
161 |
+
</select>
|
162 |
+
<label></label>
|
163 |
+
</div>
|
164 |
+
|
165 |
+
<div class="col s12">
|
166 |
+
<input class="with-gap" name="filter_files" type="radio" id="filter_files_all" checked
|
167 |
+
value="" disabled/>
|
168 |
+
<label for="filter_files_all" class="tooltipped" data-position="right"
|
169 |
+
data-tooltip="<?php echo __( "Restore all backup files. Available only when doing a Remote Target System Restore", 'xcloner-backup-and-restore' ) ?>"><?php echo __( "Restore All Files", "xcloner-backup-and-restore" ) ?></label>
|
170 |
+
|
171 |
+
<input class="with-gap" name="filter_files" type="radio" id="filter_files_wp_content"
|
172 |
+
value="/^wp-content\/(.*)/"/>
|
173 |
+
<label for="filter_files_wp_content" class="tooltipped"
|
174 |
+
data-tooltip="<?php echo __( 'Restore the files only of the wp-content/ folder', 'xcloner-backup-and-restore' ) ?>">
|
175 |
+
<?php echo __( "Only wp-content", "xcloner-backup-and-restore" ) ?>
|
176 |
+
</label>
|
177 |
+
|
178 |
+
<input class="with-gap" name="filter_files" type="radio" id="filter_files_plugins"
|
179 |
+
value="/^wp-content\/plugins(.*)/"/>
|
180 |
+
<label for="filter_files_plugins" class="tooltipped"
|
181 |
+
data-tooltip="<?php echo __( 'Restore the files only of the wp-content/plugins/ folder', 'xcloner-backup-and-restore' ) ?>">
|
182 |
+
<?php echo __( "Only Plugins", "xcloner-backup-and-restore" ) ?>
|
183 |
+
</label>
|
184 |
+
|
185 |
+
<input class="with-gap" name="filter_files" type="radio" id="filter_files_uploads"
|
186 |
+
value="/^wp-content\/uploads(.*)/"/>
|
187 |
+
<label for="filter_files_uploads" class="tooltipped"
|
188 |
+
data-tooltip="<?php echo __( 'Restore the files only of the wp-content/uploads/ folder only', 'xcloner-backup-and-restore' ) ?>">
|
189 |
+
<?php echo __( "Only Uploads", "xcloner-backup-and-restore" ) ?>
|
190 |
+
</label>
|
191 |
+
|
192 |
+
<input class="with-gap" name="filter_files" type="radio" id="filter_files_themes"
|
193 |
+
value="/^wp-content\/themes(.*)/"/>
|
194 |
+
<label for="filter_files_themes" class="tooltipped"
|
195 |
+
data-tooltip="<?php echo __( 'Restore the files only of the wp-content/themes/ folder', 'xcloner-backup-and-restore' ) ?>">
|
196 |
+
<?php echo __( "Only Themes", "xcloner-backup-and-restore" ) ?>
|
197 |
+
</label>
|
198 |
+
|
199 |
+
<input class="with-gap" name="filter_files" type="radio" id="filter_files_database"
|
200 |
+
value="/^xcloner-(.*)\/(.*)\.sql/"/>
|
201 |
+
<label for="filter_files_database" class="tooltipped"
|
202 |
+
data-tooltip="<?php echo __( 'Restore the database-sql.sql mysql backup from the xcloner-xxxxx/ folder', 'xcloner-backup-and-restore' ) ?>">
|
203 |
+
<?php echo __( "Only Database Backup", "xcloner-backup-and-restore" ) ?>
|
204 |
+
</label>
|
205 |
+
</div>
|
206 |
+
</div>
|
207 |
+
|
208 |
+
<div class="progress">
|
209 |
+
<div class="indeterminate" style="width: 0%"></div>
|
210 |
+
</div>
|
211 |
+
|
212 |
+
<div class="status"></div>
|
213 |
+
<ul class="files-list"></ul>
|
214 |
+
</div>
|
215 |
+
|
216 |
+
<div class="col s12 l5 right-align">
|
217 |
+
<div class="toggler">
|
218 |
+
<button class="btn waves-effect waves-light restore_remote_backup normal " type="submit"
|
219 |
+
id="" name="action"><?php echo __( "Restore", 'xcloner-backup-and-restore' ) ?>
|
220 |
+
<i class="material-icons left">navigate_before</i>
|
221 |
+
</button>
|
222 |
+
<button class="btn waves-effect waves-light red restore_remote_backup cancel" type="submit"
|
223 |
+
id="" name="action"><?php echo __( "Cancel", 'xcloner-backup-and-restore' ) ?>
|
224 |
+
<i class="material-icons right">close</i>
|
225 |
+
</button>
|
226 |
+
</div>
|
227 |
+
<button class="btn waves-effect waves-light grey" type="submit"
|
228 |
+
title="<?php echo __( "Skip Next", 'xcloner-backup-and-restore' ) ?>"
|
229 |
+
id="skip_remote_backup_step"
|
230 |
+
name="action"><?php echo __( "Skip Next", 'xcloner-backup-and-restore' ) ?>
|
231 |
+
<i class="material-icons right">navigate_next</i>
|
232 |
+
</button>
|
233 |
+
</div>
|
234 |
+
</div>
|
235 |
+
</li>
|
236 |
+
|
237 |
+
<li data-step="4" class="restore-remote-database-step steps active">
|
238 |
+
<div class="collapsible-header"><i
|
239 |
+
class="material-icons">list</i><?php echo __( "Restore Target Database - Search and Replace", 'xcloner-backup-and-restore' ) ?>
|
240 |
+
<i class="material-icons right" title="Refresh Database Backup Files List"
|
241 |
+
id="refresh_database_file">cached</i>
|
242 |
+
</div>
|
243 |
+
<div class="collapsible-body row">
|
244 |
+
|
245 |
+
<div id="remote-restore-options">
|
246 |
+
<div class="col s12">
|
247 |
+
<a class="btn-floating tooltipped btn-small right" data-position="left" data-delay="50"
|
248 |
+
data-html="true"
|
249 |
+
data-tooltip="<?php echo __( 'Please provide below the mysql connection details for the target host database.<br />For live sites we recommend using a new separate database.', 'xcloner-backup-and-restore' ) ?>"
|
250 |
+
data-tooltip-id="92c95730-94e9-7b59-bd52-14adc30d5e3e"><i class="material-icons">help_outline</i></a>
|
251 |
+
<h5><?php echo __( 'Target Mysql Details', 'xcloner-backup-and-restore' ) ?></h5>
|
252 |
+
</div>
|
253 |
+
<div class=" col s12">
|
254 |
+
<div class="input-field col s12 m6">
|
255 |
+
<input type="text" name="remote_mysql_host" id="remote_mysql_host" class="validate"
|
256 |
+
placeholder="Target Mysql Hostname">
|
257 |
+
<label><?php echo __( "Target Mysql Hostname", 'xcloner-backup-and-restore' ) ?></label>
|
258 |
+
</div>
|
259 |
+
|
260 |
+
<div class="input-field col s12 m6">
|
261 |
+
<input type="text" name="remote_mysql_db" id="remote_mysql_db" class="validate"
|
262 |
+
placeholder="Target Mysql Database">
|
263 |
+
<label><?php echo __( "Target Mysql Database", 'xcloner-backup-and-restore' ) ?></label>
|
264 |
+
</div>
|
265 |
+
|
266 |
+
<div class="input-field col s12 m6">
|
267 |
+
<input type="text" name="remote_mysql_user" id="remote_mysql_user" class="validate"
|
268 |
+
placeholder="Target Mysql Username">
|
269 |
+
<label><?php echo __( "Target Mysql Username", 'xcloner-backup-and-restore' ) ?></label>
|
270 |
+
</div>
|
271 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
272 |
|
273 |
+
<div class="input-field col s12 m6">
|
274 |
+
<input type="text" name="remote_mysql_pass" id="remote_mysql_pass" class="validate"
|
275 |
+
placeholder="Target Mysql Password">
|
276 |
+
<label><?php echo __( "Target Mysql Password", 'xcloner-backup-and-restore' ) ?></label>
|
277 |
+
</div>
|
278 |
+
|
279 |
+
</div>
|
280 |
+
<div class="col s12">
|
281 |
+
<a class="btn-floating tooltipped btn-small right" data-position="left" data-delay="50"
|
282 |
+
data-html="true"
|
283 |
+
data-tooltip="<?php echo __( 'I will attempt to replace all mysql backup records matching the provided Source Url with the provided Target Url. <br />Leave blank the Target Url if you would like to skip this option. <br />As a bonus, I will also replace all matching serialized data and fix it\'s parsing.', 'xcloner-backup-and-restore' ) ?>"
|
284 |
+
data-tooltip-id="92c95730-94e9-7b59-bd52-14adc30d5e3e"><i class="material-icons">help_outline</i></a>
|
285 |
+
<h5><?php echo __( 'Target Mysql Search and Replace', 'xcloner-backup-and-restore' ) ?></h5>
|
286 |
+
</div>
|
287 |
+
<div class="col s12">
|
288 |
+
<div class="input-field col s12 m6 ">
|
289 |
+
<input type="text" name="wp_home_url" id="wp_home_url" class="validate"
|
290 |
+
placeholder="WP Home Url" value="<?php echo home_url(); ?>">
|
291 |
+
<label><?php echo __( "Source Home Url", 'xcloner-backup-and-restore' ) ?></label>
|
292 |
+
</div>
|
293 |
+
|
294 |
+
<div class="input-field col s12 m6 ">
|
295 |
+
<input type="text" name="remote_restore_url" id="remote_restore_url" class="validate"
|
296 |
+
placeholder="Restore Target Url">
|
297 |
+
<label><?php echo __( "With Target Home Url", 'xcloner-backup-and-restore' ) ?></label>
|
298 |
+
</div>
|
299 |
+
|
300 |
+
<?php if ( site_url() != home_url() ) : ?>
|
301 |
+
<div class="input-field col s12 m6 ">
|
302 |
+
<input type="text" name="wp_site_url" id="wp_site_url" class="validate"
|
303 |
+
placeholder="WP Site Url" value="<?php echo site_url(); ?>">
|
304 |
+
<label><?php echo __( "Source Site Url", 'xcloner-backup-and-restore' ) ?></label>
|
305 |
+
</div>
|
306 |
+
|
307 |
+
<div class="input-field col s12 m6 ">
|
308 |
+
<input type="text" name="remote_restore_site_url" id="remote_restore_site_url"
|
309 |
+
class="validate" placeholder="Restore Target Url">
|
310 |
+
<label><?php echo __( "With Target Site Url", 'xcloner-backup-and-restore' ) ?></label>
|
311 |
+
</div>
|
312 |
+
|
313 |
+
<?php endif; ?>
|
314 |
+
</div>
|
315 |
+
|
316 |
+
</div>
|
317 |
+
|
318 |
+
<div class=" col s12 l7">
|
319 |
+
<div class="input-field row">
|
320 |
+
<select id="remote_database_file" name="remote_database_file" class="browser-default">
|
321 |
+
<option value="" disabled
|
322 |
+
selected><?php echo __( "Please select the target database backup file to restore", 'xcloner-backup-and-restore' ) ?></option>
|
323 |
+
</select>
|
324 |
+
|
325 |
+
<label></label>
|
326 |
+
</div>
|
327 |
+
|
328 |
+
<div class="progress">
|
329 |
+
<div class="determinate" style="width: 0%"></div>
|
330 |
+
</div>
|
331 |
+
|
332 |
+
<div class="status"></div>
|
333 |
+
<div class="query-box">
|
334 |
+
<h6><?php echo __( 'Use the field below to fix your mysql query and Retry again the Restore, or replace with # to Skip next', 'xcloner-backup-and-restore' ) ?></h6>
|
335 |
+
<textarea class="query-list" cols="5"></textarea>
|
336 |
+
</div>
|
337 |
+
</div>
|
338 |
+
|
339 |
+
<div class="col s12 l5 right-align">
|
340 |
+
<div class="toggler">
|
341 |
+
<button class="btn waves-effect waves-light restore_remote_mysqldump normal " type="submit"
|
342 |
+
id="" name="action"><?php echo __( "Restore", 'xcloner-backup-and-restore' ) ?>
|
343 |
+
<i class="material-icons left">navigate_before</i>
|
344 |
+
</button>
|
345 |
+
<button class="btn waves-effect waves-light red restore_remote_mysqldump cancel"
|
346 |
+
type="submit" id=""
|
347 |
+
name="action"><?php echo __( "Cancel", 'xcloner-backup-and-restore' ) ?>
|
348 |
+
<i class="material-icons right">close</i>
|
349 |
+
</button>
|
350 |
+
</div>
|
351 |
+
|
352 |
+
<button class="btn waves-effect waves-light grey" type="submit"
|
353 |
+
title="<?php echo __( "Skip Next", 'xcloner-backup-and-restore' ) ?>"
|
354 |
+
id="skip_restore_remote_database_step"
|
355 |
+
name="action"><?php echo __( "Skip Next", 'xcloner-backup-and-restore' ) ?>
|
356 |
+
<i class="material-icons right">navigate_next</i>
|
357 |
+
</button>
|
358 |
+
|
359 |
+
</div>
|
360 |
+
|
361 |
+
</div>
|
362 |
+
</li>
|
363 |
+
|
364 |
+
<li data-step="5" class="restore-finish-step steps active">
|
365 |
+
<div class="collapsible-header"><i
|
366 |
+
class="material-icons">folder_open</i><?php echo __( "Finishing up...", 'xcloner-backup-and-restore' ) ?>
|
367 |
+
</div>
|
368 |
+
<div class="collapsible-body row">
|
369 |
+
|
370 |
+
<div class="row">
|
371 |
+
<div class="col s4">
|
372 |
+
<label><?php echo __( "Update wp-config.php mysql details and update the Target Site Url", 'xcloner-backup-and-restore' ) ?></label>
|
373 |
+
</div>
|
374 |
+
|
375 |
+
<div class="col s8">
|
376 |
+
<div class="switch">
|
377 |
+
<label>
|
378 |
+
Off
|
379 |
+
<input type="checkbox" id="update_remote_site_url" name="update_remote_site_url"
|
380 |
+
checked value="1">
|
381 |
+
<span class="lever"></span>
|
382 |
+
On
|
383 |
+
</label>
|
384 |
+
</div>
|
385 |
+
</div>
|
386 |
+
</div>
|
387 |
+
|
388 |
+
<div class="row">
|
389 |
+
<div class="col s4">
|
390 |
+
<label><?php echo __( "Delete Restored Backup Temporary Folder", 'xcloner-backup-and-restore' ) ?></label>
|
391 |
+
</div>
|
392 |
+
<div class="col s8">
|
393 |
+
<div class="switch">
|
394 |
+
<label>
|
395 |
+
Off
|
396 |
+
<input type="checkbox" id="delete_backup_temporary_folder"
|
397 |
+
name="delete_backup_temporary_folder" checked value="1">
|
398 |
+
<span class="lever"></span>
|
399 |
+
On
|
400 |
+
</label>
|
401 |
+
</div>
|
402 |
+
</div>
|
403 |
+
</div>
|
404 |
+
|
405 |
+
<div class="row">
|
406 |
+
<div class="col s4">
|
407 |
+
<label><?php echo __( "Delete Restore Script", 'xcloner-backup-and-restore' ) ?></label>
|
408 |
+
</div>
|
409 |
+
<div class="col s8">
|
410 |
+
<div class="switch">
|
411 |
+
<label>
|
412 |
+
Off
|
413 |
+
<input type="checkbox" id="delete_restore_script" name="delete_restore_script"
|
414 |
+
checked value="1">
|
415 |
+
<span class="lever"></span>
|
416 |
+
On
|
417 |
+
</label>
|
418 |
+
</div>
|
419 |
+
</div>
|
420 |
+
</div>
|
421 |
+
|
422 |
+
<div class=" row col s12">
|
423 |
+
<div class="status"></div>
|
424 |
+
</div>
|
425 |
+
|
426 |
+
<div class=" row col s12 center-align" id="xcloner_restore_finish">
|
427 |
+
<h5><?php echo __( "Thank you for using XCloner.", 'xcloner-backup-and-restore' ) ?></h5>
|
428 |
+
<h6><?php echo sprintf( __( "We would love to hear about your experience in the %s.", 'xcloner-backup-and-restore' ), '<a href="https://wordpress.org/support/plugin/xcloner-backup-and-restore" target="_blank">Wordpress XCloner forums</a>' ) ?></h6>
|
429 |
+
<a class="twitter-follow-button" href="https://twitter.com/thinkovi" data-show-count="false">Follow
|
430 |
+
@thinkovi</a>
|
431 |
+
<script src="//platform.twitter.com/widgets.js" async="" charset="utf-8"></script>
|
432 |
+
</div>
|
433 |
+
|
434 |
+
<div class="col s12 center-align">
|
435 |
+
<div class="row">
|
436 |
+
<div class="col s6 right-align">
|
437 |
+
<button class="btn waves-effect waves-light teal" type="submit" id="restore_finish"
|
438 |
+
name="action"><?php echo __( "Finish", 'xcloner-backup-and-restore' ) ?>
|
439 |
+
<i class="material-icons right">navigate_next</i>
|
440 |
+
</button>
|
441 |
+
</div>
|
442 |
+
|
443 |
+
<div id="open_target_site" class="col s6 left-align">
|
444 |
+
<a disabled="disabled" href="#" class="btn waves-effect waves-light teal" type="button"
|
445 |
+
target="_blank"><?php echo __( "Open Target Site", 'xcloner-backup-and-restore' ) ?>
|
446 |
+
<i class="material-icons right">navigate_next</i>
|
447 |
+
</a>
|
448 |
+
</div>
|
449 |
+
</div>
|
450 |
+
</div>
|
451 |
+
</div>
|
452 |
+
</li>
|
453 |
+
|
454 |
+
</ul>
|
455 |
+
</div>
|
456 |
+
</div>
|
457 |
|
458 |
|
459 |
<!-- List Backup Content Modal-->
|
460 |
<div id="backup_cotent_modal" class="modal">
|
461 |
+
<div class="modal-content">
|
462 |
+
<h4><?php echo sprintf( __( "Listing Backup Content ", 'xcloner-backup-and-restore' ), "" ) ?></h4>
|
463 |
+
<h5 class="backup-name"></h5>
|
464 |
+
|
465 |
+
<div class="progress">
|
466 |
+
<div class="indeterminate"></div>
|
467 |
+
</div>
|
468 |
+
<ul class="files-list"></ul>
|
469 |
+
</div>
|
470 |
</div>
|
admin/partials/xcloner_scheduled_backups_page.php
CHANGED
@@ -2,192 +2,210 @@
|
|
2 |
$xcloner_scheduler = $this->get_xcloner_container()->get_xcloner_scheduler();
|
3 |
|
4 |
$xcloner_remote_storage = $this->get_xcloner_container()->get_xcloner_remote_storage();
|
5 |
-
$available_storages
|
6 |
?>
|
7 |
-
<?php if(!defined("DISABLE_WP_CRON") || !DISABLE_WP_CRON): ?>
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
|
|
|
|
15 |
|
16 |
-
<h1><?= esc_html(get_admin_page_title()); ?></h1>
|
17 |
|
18 |
<div class="row">
|
19 |
-
<table id="scheduled_backups" class="col s12" cellspacing="0" width="100%">
|
20 |
<thead>
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
</thead>
|
32 |
<tfoot>
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
</tfoot>
|
44 |
<tbody>
|
45 |
-
</tbody>
|
46 |
-
</table>
|
47 |
</div>
|
48 |
|
49 |
<div class="row">
|
50 |
-
|
51 |
-
|
52 |
-
|
|
|
53 |
</div>
|
54 |
|
55 |
|
56 |
<!-- Modal Structure -->
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
|
|
|
|
|
|
|
|
96 |
<select id="backup_type" class="" name="backup_type" id="backup_type">
|
97 |
-
<option value=""><?php echo __("Full Backup","xcloner-backup-and-restore")
|
98 |
-
<option value="diff"><?php echo __("Differential Backups","xcloner-backup-and-restore")
|
99 |
-
<option value="full_diff"><?php echo __("Full Backup + Differential Backups","xcloner-backup-and-restore")
|
100 |
</select>
|
101 |
-
<label for="backup_type"><?php echo __('Scheduled Backup Type','xcloner-backup-and-restore')?></label>
|
102 |
</div>-->
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
191 |
</form>
|
192 |
</div>
|
193 |
|
2 |
$xcloner_scheduler = $this->get_xcloner_container()->get_xcloner_scheduler();
|
3 |
|
4 |
$xcloner_remote_storage = $this->get_xcloner_container()->get_xcloner_remote_storage();
|
5 |
+
$available_storages = $xcloner_remote_storage->get_available_storages();
|
6 |
?>
|
7 |
+
<?php if ( ! defined( "DISABLE_WP_CRON" ) || ! DISABLE_WP_CRON ): ?>
|
8 |
+
<div id="setting-error-" class="error settings-error notice is-dismissible">
|
9 |
+
<p><strong>
|
10 |
+
<?php echo sprintf( __( 'We have noticed that DISABLE_WP_CRON is disabled, we recommend enabling that and setting up wp-cron.php to run manually through your hosting account scheduler as explained <a href="%s" target="_blank">here</a>', 'xcloner-backup-and-restore' ), "http://www.inmotionhosting.com/support/website/wordpress/disabling-the-wp-cronphp-in-wordpress" ) ?>
|
11 |
+
</strong>
|
12 |
+
</p>
|
13 |
+
<button type="button" class="notice-dismiss"><span class="screen-reader-text">Dismiss this notice.</span>
|
14 |
+
</button>
|
15 |
+
</div>
|
16 |
+
<?php endif ?>
|
17 |
|
18 |
+
<h1><?= esc_html( get_admin_page_title() ); ?></h1>
|
19 |
|
20 |
<div class="row">
|
21 |
+
<table id="scheduled_backups" class="col s12" cellspacing="0" width="100%">
|
22 |
<thead>
|
23 |
+
<tr class="grey lighten-2">
|
24 |
+
<th><?php echo __( 'ID', 'xcloner-backup-and-restore' ) ?></th>
|
25 |
+
<th><?php echo __( 'Schedule Name', 'xcloner-backup-and-restore' ) ?></th>
|
26 |
+
<th><?php echo __( 'Recurrence', 'xcloner-backup-and-restore' ) ?></th>
|
27 |
+
<th class="hide-on-med-and-down"><?php echo __( 'Next Execution', 'xcloner-backup-and-restore' ) ?></th>
|
28 |
+
<th><?php echo __( 'Remote Storage', 'xcloner-backup-and-restore' ) ?></th>
|
29 |
+
<th class="hide-on-med-and-down"><?php echo __( 'Last Backup', 'xcloner-backup-and-restore' ) ?></th>
|
30 |
+
<th><?php echo __( 'Status', 'xcloner-backup-and-restore' ) ?></th>
|
31 |
+
<th class="no-sort"><?php echo __( 'Action', 'xcloner-backup-and-restore' ) ?></th>
|
32 |
+
</tr>
|
33 |
</thead>
|
34 |
<tfoot>
|
35 |
+
<tr>
|
36 |
+
<th><?php echo __( 'ID', 'xcloner-backup-and-restore' ) ?></th>
|
37 |
+
<th><?php echo __( 'Schedule Name', 'xcloner-backup-and-restore' ) ?></th>
|
38 |
+
<th><?php echo __( 'Recurrence', 'xcloner-backup-and-restore' ) ?></th>
|
39 |
+
<th class="hide-on-med-and-down"><?php echo __( 'Next Execution', 'xcloner-backup-and-restore' ) ?></th>
|
40 |
+
<th><?php echo __( 'Remote Storage', 'xcloner-backup-and-restore' ) ?></th>
|
41 |
+
<th class="hide-on-med-and-down"><?php echo __( 'Last Backup', 'xcloner-backup-and-restore' ) ?></th>
|
42 |
+
<th><?php echo __( 'Status', 'xcloner-backup-and-restore' ) ?></th>
|
43 |
+
<th><?php echo __( 'Action', 'xcloner-backup-and-restore' ) ?></th>
|
44 |
+
</tr>
|
45 |
</tfoot>
|
46 |
<tbody>
|
47 |
+
</tbody>
|
48 |
+
</table>
|
49 |
</div>
|
50 |
|
51 |
<div class="row">
|
52 |
+
<div class="col s12 m6 offset-m6 teal lighten-1" id="server_time">
|
53 |
+
<h2><?php echo __( 'Current Server Time', 'xcloner-backup-and-restore' ) ?>: <span
|
54 |
+
class="right"><?php echo current_time( 'mysql' ); ?></span></h2>
|
55 |
+
</div>
|
56 |
</div>
|
57 |
|
58 |
|
59 |
<!-- Modal Structure -->
|
60 |
+
<div id="edit_schedule" class="modal">
|
61 |
+
<form method="POST" action="" id="save_schedule">
|
62 |
+
<input type="hidden" name="id" id="schedule_id_hidden">
|
63 |
+
<input type="hidden" name="action" value="save_schedule">
|
64 |
+
<div class="modal-content">
|
65 |
+
|
66 |
+
<div class="row">
|
67 |
+
<div class="col s12 m6">
|
68 |
+
<h4><?php echo __( 'Edit Schedule', 'xcloner-backup-and-restore' ) ?> #<span
|
69 |
+
id="schedule_id"></span></h4>
|
70 |
+
</div>
|
71 |
+
|
72 |
+
<div class="col s12 m6 right-align">
|
73 |
+
<div class="switch">
|
74 |
+
<label>
|
75 |
+
<?php echo __( 'Off', 'xcloner-backup-and-restore' ) ?>
|
76 |
+
<input type="checkbox" id="status" name="status" value="1">
|
77 |
+
<span class="lever"></span>
|
78 |
+
<?php echo __( 'On', 'xcloner-backup-and-restore' ) ?>
|
79 |
+
</label>
|
80 |
+
</div>
|
81 |
+
</div>
|
82 |
+
</div>
|
83 |
+
|
84 |
+
<p>
|
85 |
+
|
86 |
+
<ul class="nav-tab-wrapper content row">
|
87 |
+
<li><a href="#scheduler_settings"
|
88 |
+
class="nav-tab col s12 m6 nav-tab-active"><?php echo __( 'Scheduler Settings', 'xcloner-backup-and-restore' ) ?></a>
|
89 |
+
</li>
|
90 |
+
<li><a href="#advanced_scheduler_settings"
|
91 |
+
class="nav-tab col s12 m6"><?php echo __( 'Advanced', 'xcloner-backup-and-restore' ) ?></a></li>
|
92 |
+
</ul>
|
93 |
+
|
94 |
+
<div class="nav-tab-wrapper-content">
|
95 |
+
<div id="scheduler_settings" class="tab-content active">
|
96 |
+
|
97 |
+
<div class="row">
|
98 |
+
<div class="input-field col s12">
|
99 |
+
<input placeholder="" name="schedule_name" id="schedule_name" type="text" required value="">
|
100 |
+
<label for="schedule_name"><?php echo __( 'Schedule Name', 'xcloner-backup-and-restore' ) ?></label>
|
101 |
+
</div>
|
102 |
+
<!--<div class="input-field inline col s12 l6">
|
103 |
<select id="backup_type" class="" name="backup_type" id="backup_type">
|
104 |
+
<option value=""><?php echo __( "Full Backup", "xcloner-backup-and-restore" ); ?></option>
|
105 |
+
<option value="diff"><?php echo __( "Differential Backups", "xcloner-backup-and-restore" ); ?></option>
|
106 |
+
<option value="full_diff"><?php echo __( "Full Backup + Differential Backups", "xcloner-backup-and-restore" ); ?></option>
|
107 |
</select>
|
108 |
+
<label for="backup_type"><?php echo __( 'Scheduled Backup Type', 'xcloner-backup-and-restore' ) ?></label>
|
109 |
</div>-->
|
110 |
+
</div>
|
111 |
+
|
112 |
+
<div class="row">
|
113 |
+
<div class="input-field col s12 l6">
|
114 |
+
<input placeholder="" name="schedule_start_date" id="schedule_start_date" type="datetime"
|
115 |
+
value="">
|
116 |
+
<label for="schedule_start_date"
|
117 |
+
class="active"><?php echo __( 'Schedule Start At', 'xcloner-backup-and-restore' ) ?>
|
118 |
+
:</label>
|
119 |
+
</div>
|
120 |
+
|
121 |
+
<div class="input-field col s12 l6">
|
122 |
+
<select name="schedule_frequency" id="schedule_frequency" class="validate" required>
|
123 |
+
<option value="" disabled
|
124 |
+
selected><?php echo __( 'Schedule Recurrence', 'xcloner-backup-and-restore' ) ?></option>
|
125 |
+
<?php
|
126 |
+
$schedules = $xcloner_scheduler->get_available_intervals();
|
127 |
+
|
128 |
+
foreach ( $schedules as $key => $schedule ) {
|
129 |
+
?>
|
130 |
+
<option value="<?php echo $key ?>"><?php echo $schedule['display'] ?></option>
|
131 |
+
<?php
|
132 |
+
}
|
133 |
+
?>
|
134 |
+
</select>
|
135 |
+
</div>
|
136 |
+
</div>
|
137 |
+
|
138 |
+
<?php if ( sizeof( $available_storages ) ): ?>
|
139 |
+
<div class="row">
|
140 |
+
<div class="input-field col s12 l12">
|
141 |
+
<select name="schedule_storage" id="schedule_storage" class="validate">
|
142 |
+
<option value=""
|
143 |
+
selected><?php echo __( 'none', 'xcloner-backup-and-restore' ) ?></option>
|
144 |
+
<?php foreach ( $available_storages as $storage => $text ): ?>
|
145 |
+
<option value="<?php echo $storage ?>"><?php echo $text ?></option>
|
146 |
+
<?php endforeach ?>
|
147 |
+
</select>
|
148 |
+
<label><?php echo __( 'Send To Remote Storage ', 'xcloner-backup-and-restore' ) ?></label>
|
149 |
+
</div>
|
150 |
+
</div>
|
151 |
+
<?php endif ?>
|
152 |
+
|
153 |
+
<div class="row">
|
154 |
+
<div class="input-field col s12 l12">
|
155 |
+
<input placeholder="" name="email_notification" id="email_notification" type="text"
|
156 |
+
value="">
|
157 |
+
<label for="email_notification"><?php echo __( 'Email Notification Address', 'xcloner-backup-and-restore' ) ?></label>
|
158 |
+
</div>
|
159 |
+
</div>
|
160 |
+
|
161 |
+
<div class="row">
|
162 |
+
<div class="input-field col s12 l12">
|
163 |
+
<input placeholder="" name="diff_start_date" id="diff_start_date" type="text"
|
164 |
+
class="datepicker_max_today" value="">
|
165 |
+
<label for="diff_start_date"><?php echo __( 'Backup Only Files Modified/Created After', 'xcloner-backup-and-restore' ) ?></label>
|
166 |
+
</div>
|
167 |
+
</div>
|
168 |
+
</div>
|
169 |
+
|
170 |
+
<div id="advanced_scheduler_settings" class="tab-content">
|
171 |
+
<div class="row">
|
172 |
+
<div class="input-field col s12 l12">
|
173 |
+
<input placeholder="" name="backup_name" id="backup_name" type="text" required value="">
|
174 |
+
<label for="backup_name"><?php echo __( 'Backup Name', 'xcloner-backup-and-restore' ) ?></label>
|
175 |
+
</div>
|
176 |
+
</div>
|
177 |
+
|
178 |
+
<div class="row">
|
179 |
+
<div class="input-field col s12 l12">
|
180 |
+
<textarea id="table_params" name="table_params" class="materialize-textarea"
|
181 |
+
rows="15"></textarea>
|
182 |
+
<label for="table_params"
|
183 |
+
class="active"><?php echo __( 'Included Database Data', 'xcloner-backup-and-restore' ) ?></label>
|
184 |
+
</div>
|
185 |
+
</div>
|
186 |
+
|
187 |
+
<div class="row">
|
188 |
+
<div class="input-field col s12 l12">
|
189 |
+
<textarea id="excluded_files" name="excluded_files" class="materialize-textarea"
|
190 |
+
rows="15"></textarea>
|
191 |
+
<label for="excluded_files"
|
192 |
+
class="active"><?php echo __( 'Excluded Files', 'xcloner-backup-and-restore' ) ?></label>
|
193 |
+
</div>
|
194 |
+
</div>
|
195 |
+
</div>
|
196 |
+
</div>
|
197 |
+
|
198 |
+
<div class="row">
|
199 |
+
|
200 |
+
<div class="input-field col s12 ">
|
201 |
+
<button class="right btn waves-effect waves-light" type="submit"
|
202 |
+
name="action"><?php echo __( 'Save', 'xcloner-backup-and-restore' ) ?>
|
203 |
+
<i class="material-icons right">send</i>
|
204 |
+
</button>
|
205 |
+
</div>
|
206 |
+
</div>
|
207 |
+
</p>
|
208 |
+
</div>
|
209 |
</form>
|
210 |
</div>
|
211 |
|
composer.json
CHANGED
@@ -9,7 +9,8 @@
|
|
9 |
"league/flysystem-aws-s3-v3": "^1.0",
|
10 |
"mhetreramesh/flysystem-backblaze": "^1.0",
|
11 |
"league/flysystem-webdav": "^1.0",
|
12 |
-
"srmklive/flysystem-dropbox-v2": "^1.0"
|
|
|
13 |
},
|
14 |
"prefer-stable": true
|
15 |
}
|
9 |
"league/flysystem-aws-s3-v3": "^1.0",
|
10 |
"mhetreramesh/flysystem-backblaze": "^1.0",
|
11 |
"league/flysystem-webdav": "^1.0",
|
12 |
+
"srmklive/flysystem-dropbox-v2": "^1.0",
|
13 |
+
"defuse/php-encryption": "^2.2"
|
14 |
},
|
15 |
"prefer-stable": true
|
16 |
}
|
composer.lock
CHANGED
@@ -1,10 +1,10 @@
|
|
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#
|
5 |
"This file is @generated automatically"
|
6 |
],
|
7 |
-
"content-hash": "
|
8 |
"packages": [
|
9 |
{
|
10 |
"name": "aws/aws-sdk-php",
|
@@ -129,30 +129,35 @@
|
|
129 |
"time": "2018-03-04T13:23:48+00:00"
|
130 |
},
|
131 |
{
|
132 |
-
"name": "
|
133 |
-
"version": "
|
134 |
"source": {
|
135 |
"type": "git",
|
136 |
-
"url": "https://github.com/
|
137 |
-
"reference": "
|
138 |
},
|
139 |
"dist": {
|
140 |
"type": "zip",
|
141 |
-
"url": "https://api.github.com/repos/
|
142 |
-
"reference": "
|
143 |
"shasum": ""
|
144 |
},
|
145 |
"require": {
|
146 |
-
"
|
147 |
-
"
|
|
|
148 |
},
|
149 |
"require-dev": {
|
150 |
-
"
|
|
|
151 |
},
|
|
|
|
|
|
|
152 |
"type": "library",
|
153 |
"autoload": {
|
154 |
"psr-4": {
|
155 |
-
"
|
156 |
}
|
157 |
},
|
158 |
"notification-url": "https://packagist.org/downloads/",
|
@@ -161,35 +166,43 @@
|
|
161 |
],
|
162 |
"authors": [
|
163 |
{
|
164 |
-
"name": "
|
165 |
-
"email": "
|
166 |
-
"homepage": "https://
|
|
|
|
|
|
|
|
|
|
|
167 |
}
|
168 |
],
|
169 |
-
"description": "
|
170 |
-
"homepage": "https://github.com/cwhite92/b2-sdk-php",
|
171 |
"keywords": [
|
172 |
-
"
|
173 |
-
"
|
174 |
-
"
|
175 |
-
"
|
176 |
-
"
|
177 |
-
"
|
|
|
|
|
|
|
|
|
178 |
],
|
179 |
-
"time": "
|
180 |
},
|
181 |
{
|
182 |
"name": "gliterd/backblaze-b2",
|
183 |
-
"version": "
|
184 |
"source": {
|
185 |
"type": "git",
|
186 |
"url": "https://github.com/gliterd/backblaze-b2.git",
|
187 |
-
"reference": "
|
188 |
},
|
189 |
"dist": {
|
190 |
"type": "zip",
|
191 |
-
"url": "https://api.github.com/repos/gliterd/backblaze-b2/zipball/
|
192 |
-
"reference": "
|
193 |
"shasum": ""
|
194 |
},
|
195 |
"require": {
|
@@ -197,7 +210,9 @@
|
|
197 |
"php": ">=5.5.0"
|
198 |
},
|
199 |
"require-dev": {
|
200 |
-
"phpunit/phpunit": "4.8.*"
|
|
|
|
|
201 |
},
|
202 |
"type": "library",
|
203 |
"autoload": {
|
@@ -228,7 +243,7 @@
|
|
228 |
"filesystem",
|
229 |
"storage"
|
230 |
],
|
231 |
-
"time": "
|
232 |
},
|
233 |
{
|
234 |
"name": "guzzlehttp/guzzle",
|
@@ -587,6 +602,7 @@
|
|
587 |
}
|
588 |
],
|
589 |
"description": "Flysystem adapter for Windows Azure",
|
|
|
590 |
"time": "2016-07-10T19:08:39+00:00"
|
591 |
},
|
592 |
{
|
@@ -685,24 +701,24 @@
|
|
685 |
},
|
686 |
{
|
687 |
"name": "mhetreramesh/flysystem-backblaze",
|
688 |
-
"version": "1.
|
689 |
"source": {
|
690 |
"type": "git",
|
691 |
"url": "https://github.com/gliterd/flysystem-backblaze.git",
|
692 |
-
"reference": "
|
693 |
},
|
694 |
"dist": {
|
695 |
"type": "zip",
|
696 |
-
"url": "https://api.github.com/repos/gliterd/flysystem-backblaze/zipball/
|
697 |
-
"reference": "
|
698 |
"shasum": ""
|
699 |
},
|
700 |
"require": {
|
701 |
-
"cwhite92/b2-sdk-php": "^1.2",
|
702 |
"gliterd/backblaze-b2": "*",
|
703 |
"league/flysystem": "~1.0",
|
704 |
"mikey179/vfsstream": "*",
|
705 |
-
"php": ">=5.
|
|
|
706 |
},
|
707 |
"require-dev": {
|
708 |
"phpunit/phpunit": "~4.0||~5.0",
|
@@ -736,7 +752,7 @@
|
|
736 |
"client",
|
737 |
"filesystem"
|
738 |
],
|
739 |
-
"time": "
|
740 |
},
|
741 |
{
|
742 |
"name": "microsoft/azure-storage",
|
@@ -976,6 +992,55 @@
|
|
976 |
],
|
977 |
"time": "2016-12-03T22:08:25+00:00"
|
978 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
979 |
{
|
980 |
"name": "phpseclib/phpseclib",
|
981 |
"version": "2.0.11",
|
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": "920a4f6a39e43da5eab4ff35b172d146",
|
8 |
"packages": [
|
9 |
{
|
10 |
"name": "aws/aws-sdk-php",
|
129 |
"time": "2018-03-04T13:23:48+00:00"
|
130 |
},
|
131 |
{
|
132 |
+
"name": "defuse/php-encryption",
|
133 |
+
"version": "v2.2.0",
|
134 |
"source": {
|
135 |
"type": "git",
|
136 |
+
"url": "https://github.com/defuse/php-encryption.git",
|
137 |
+
"reference": "0d4d27c368ca6798bc162469e43248c363c73495"
|
138 |
},
|
139 |
"dist": {
|
140 |
"type": "zip",
|
141 |
+
"url": "https://api.github.com/repos/defuse/php-encryption/zipball/0d4d27c368ca6798bc162469e43248c363c73495",
|
142 |
+
"reference": "0d4d27c368ca6798bc162469e43248c363c73495",
|
143 |
"shasum": ""
|
144 |
},
|
145 |
"require": {
|
146 |
+
"ext-openssl": "*",
|
147 |
+
"paragonie/random_compat": "~2.0",
|
148 |
+
"php": ">=5.4.0"
|
149 |
},
|
150 |
"require-dev": {
|
151 |
+
"nikic/php-parser": "^2.0|^3.0|^4.0",
|
152 |
+
"phpunit/phpunit": "^4|^5"
|
153 |
},
|
154 |
+
"bin": [
|
155 |
+
"bin/generate-defuse-key"
|
156 |
+
],
|
157 |
"type": "library",
|
158 |
"autoload": {
|
159 |
"psr-4": {
|
160 |
+
"Defuse\\Crypto\\": "src"
|
161 |
}
|
162 |
},
|
163 |
"notification-url": "https://packagist.org/downloads/",
|
166 |
],
|
167 |
"authors": [
|
168 |
{
|
169 |
+
"name": "Taylor Hornby",
|
170 |
+
"email": "taylor@defuse.ca",
|
171 |
+
"homepage": "https://defuse.ca/"
|
172 |
+
},
|
173 |
+
{
|
174 |
+
"name": "Scott Arciszewski",
|
175 |
+
"email": "info@paragonie.com",
|
176 |
+
"homepage": "https://paragonie.com"
|
177 |
}
|
178 |
],
|
179 |
+
"description": "Secure PHP Encryption Library",
|
|
|
180 |
"keywords": [
|
181 |
+
"aes",
|
182 |
+
"authenticated encryption",
|
183 |
+
"cipher",
|
184 |
+
"crypto",
|
185 |
+
"cryptography",
|
186 |
+
"encrypt",
|
187 |
+
"encryption",
|
188 |
+
"openssl",
|
189 |
+
"security",
|
190 |
+
"symmetric key cryptography"
|
191 |
],
|
192 |
+
"time": "2018-04-23T19:33:40+00:00"
|
193 |
},
|
194 |
{
|
195 |
"name": "gliterd/backblaze-b2",
|
196 |
+
"version": "1.0.4",
|
197 |
"source": {
|
198 |
"type": "git",
|
199 |
"url": "https://github.com/gliterd/backblaze-b2.git",
|
200 |
+
"reference": "5427b10b93b0ba24f06f80623b502c7d1d7fcd72"
|
201 |
},
|
202 |
"dist": {
|
203 |
"type": "zip",
|
204 |
+
"url": "https://api.github.com/repos/gliterd/backblaze-b2/zipball/5427b10b93b0ba24f06f80623b502c7d1d7fcd72",
|
205 |
+
"reference": "5427b10b93b0ba24f06f80623b502c7d1d7fcd72",
|
206 |
"shasum": ""
|
207 |
},
|
208 |
"require": {
|
210 |
"php": ">=5.5.0"
|
211 |
},
|
212 |
"require-dev": {
|
213 |
+
"phpunit/phpunit": "4.8.*",
|
214 |
+
"scrutinizer/ocular": "~1.1",
|
215 |
+
"squizlabs/php_codesniffer": "~2.3"
|
216 |
},
|
217 |
"type": "library",
|
218 |
"autoload": {
|
243 |
"filesystem",
|
244 |
"storage"
|
245 |
],
|
246 |
+
"time": "2018-07-03T11:52:32+00:00"
|
247 |
},
|
248 |
{
|
249 |
"name": "guzzlehttp/guzzle",
|
602 |
}
|
603 |
],
|
604 |
"description": "Flysystem adapter for Windows Azure",
|
605 |
+
"abandoned": "league/flysystem-azure-blob-storage",
|
606 |
"time": "2016-07-10T19:08:39+00:00"
|
607 |
},
|
608 |
{
|
701 |
},
|
702 |
{
|
703 |
"name": "mhetreramesh/flysystem-backblaze",
|
704 |
+
"version": "1.1.4",
|
705 |
"source": {
|
706 |
"type": "git",
|
707 |
"url": "https://github.com/gliterd/flysystem-backblaze.git",
|
708 |
+
"reference": "bce0372dfe40baa1e16b54e93c3400a568059070"
|
709 |
},
|
710 |
"dist": {
|
711 |
"type": "zip",
|
712 |
+
"url": "https://api.github.com/repos/gliterd/flysystem-backblaze/zipball/bce0372dfe40baa1e16b54e93c3400a568059070",
|
713 |
+
"reference": "bce0372dfe40baa1e16b54e93c3400a568059070",
|
714 |
"shasum": ""
|
715 |
},
|
716 |
"require": {
|
|
|
717 |
"gliterd/backblaze-b2": "*",
|
718 |
"league/flysystem": "~1.0",
|
719 |
"mikey179/vfsstream": "*",
|
720 |
+
"php": ">=5.6.0",
|
721 |
+
"psr/http-message-implementation": "*"
|
722 |
},
|
723 |
"require-dev": {
|
724 |
"phpunit/phpunit": "~4.0||~5.0",
|
752 |
"client",
|
753 |
"filesystem"
|
754 |
],
|
755 |
+
"time": "2018-06-29T12:06:41+00:00"
|
756 |
},
|
757 |
{
|
758 |
"name": "microsoft/azure-storage",
|
992 |
],
|
993 |
"time": "2016-12-03T22:08:25+00:00"
|
994 |
},
|
995 |
+
{
|
996 |
+
"name": "paragonie/random_compat",
|
997 |
+
"version": "v2.0.15",
|
998 |
+
"source": {
|
999 |
+
"type": "git",
|
1000 |
+
"url": "https://github.com/paragonie/random_compat.git",
|
1001 |
+
"reference": "10bcb46e8f3d365170f6de9d05245aa066b81f09"
|
1002 |
+
},
|
1003 |
+
"dist": {
|
1004 |
+
"type": "zip",
|
1005 |
+
"url": "https://api.github.com/repos/paragonie/random_compat/zipball/10bcb46e8f3d365170f6de9d05245aa066b81f09",
|
1006 |
+
"reference": "10bcb46e8f3d365170f6de9d05245aa066b81f09",
|
1007 |
+
"shasum": ""
|
1008 |
+
},
|
1009 |
+
"require": {
|
1010 |
+
"php": ">=5.2.0"
|
1011 |
+
},
|
1012 |
+
"require-dev": {
|
1013 |
+
"phpunit/phpunit": "4.*|5.*"
|
1014 |
+
},
|
1015 |
+
"suggest": {
|
1016 |
+
"ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
|
1017 |
+
},
|
1018 |
+
"type": "library",
|
1019 |
+
"autoload": {
|
1020 |
+
"files": [
|
1021 |
+
"lib/random.php"
|
1022 |
+
]
|
1023 |
+
},
|
1024 |
+
"notification-url": "https://packagist.org/downloads/",
|
1025 |
+
"license": [
|
1026 |
+
"MIT"
|
1027 |
+
],
|
1028 |
+
"authors": [
|
1029 |
+
{
|
1030 |
+
"name": "Paragon Initiative Enterprises",
|
1031 |
+
"email": "security@paragonie.com",
|
1032 |
+
"homepage": "https://paragonie.com"
|
1033 |
+
}
|
1034 |
+
],
|
1035 |
+
"description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
|
1036 |
+
"keywords": [
|
1037 |
+
"csprng",
|
1038 |
+
"polyfill",
|
1039 |
+
"pseudorandom",
|
1040 |
+
"random"
|
1041 |
+
],
|
1042 |
+
"time": "2018-06-08T15:26:40+00:00"
|
1043 |
+
},
|
1044 |
{
|
1045 |
"name": "phpseclib/phpseclib",
|
1046 |
"version": "2.0.11",
|
includes/class-xcloner-activator.php
CHANGED
@@ -1,13 +1,29 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
/**
|
4 |
-
*
|
5 |
*
|
6 |
-
*
|
7 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8 |
*
|
9 |
-
* @package Xcloner
|
10 |
-
* @subpackage Xcloner/includes
|
11 |
*/
|
12 |
|
13 |
/**
|
@@ -19,38 +35,48 @@
|
|
19 |
* @package Xcloner
|
20 |
* @subpackage Xcloner/includes
|
21 |
* @author Liuta Ovidiu <info@thinkovi.com>
|
|
|
22 |
*/
|
23 |
class Xcloner_Activator {
|
24 |
|
|
|
|
|
|
|
|
|
25 |
const xcloner_db_version = '1.1.7';
|
|
|
|
|
|
|
|
|
26 |
const xcloner_minimum_version = '5.6.0';
|
|
|
27 |
/**
|
28 |
-
*
|
29 |
*
|
30 |
-
*
|
31 |
*
|
32 |
* @since 1.0.0
|
33 |
*/
|
34 |
public static function activate() {
|
35 |
-
|
36 |
global $wpdb;
|
37 |
-
|
38 |
-
if(version_compare(phpversion(), Xcloner_Activator::xcloner_minimum_version, '<'))
|
39 |
-
|
40 |
-
|
|
|
41 |
}
|
42 |
-
|
43 |
-
$charset_collate = $wpdb->get_charset_collate();
|
44 |
-
|
45 |
$installed_ver = get_option( "xcloner_db_version" );
|
46 |
-
|
47 |
$xcloner_db_version = Xcloner_Activator::xcloner_db_version;
|
48 |
-
|
49 |
$xcloner_scheduler_table = $wpdb->prefix . "xcloner_scheduler";
|
50 |
-
|
51 |
-
if($installed_ver != $xcloner_db_version)
|
52 |
-
|
53 |
-
$xcloner_schedule_sql="CREATE TABLE `".$xcloner_scheduler_table."` (
|
54 |
`id` int(11) NOT NULL AUTO_INCREMENT,
|
55 |
`name` varchar(255) NOT NULL,
|
56 |
`recurrence` varchar(25) NOT NULL,
|
@@ -61,58 +87,71 @@ class Xcloner_Activator {
|
|
61 |
`status` int(1) NOT NULL,
|
62 |
`last_backup` varchar(100) DEFAULT NULL,
|
63 |
PRIMARY KEY (`id`)
|
64 |
-
) "
|
65 |
";
|
66 |
-
|
67 |
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
|
68 |
dbDelta( $xcloner_schedule_sql );
|
69 |
-
|
70 |
update_option( "xcloner_db_version", $xcloner_db_version );
|
71 |
}
|
72 |
-
|
73 |
-
if(get_option('xcloner_backup_compression_level') === false)
|
74 |
-
update_option('xcloner_backup_compression_level', 0);
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
if(get_option('
|
86 |
-
update_option('
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
if(get_option('
|
98 |
-
update_option('
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
109 |
/*if(!get_option('xcloner_diff_backup_recreate_period'))
|
110 |
update_option('xcloner_diff_backup_recreate_period', 10);
|
111 |
* */
|
112 |
-
|
113 |
-
if(!get_option('xcloner_regex_exclude'))
|
114 |
-
update_option('xcloner_regex_exclude', "(wp-content\/updraft|wp-content\/uploads\/wp_all_backup)(.*)$".PHP_EOL."(.*)\.(svn|git)(.*)$".PHP_EOL."wp-content\/cache(.*)$".PHP_EOL."(.*)error_log$");
|
|
|
115 |
|
116 |
}
|
117 |
-
|
118 |
}
|
1 |
<?php
|
|
|
2 |
/**
|
3 |
+
* XCloner - Backup and Restore backup plugin for Wordpress
|
4 |
*
|
5 |
+
* class-xcloner-activator.php
|
6 |
+
* @author Liuta Ovidiu <info@thinkovi.com>
|
7 |
+
*
|
8 |
+
* This program is free software; you can redistribute it and/or modify
|
9 |
+
* it under the terms of the GNU General Public License as published by
|
10 |
+
* the Free Software Foundation; either version 2 of the License, or
|
11 |
+
* (at your option) any later version.
|
12 |
+
*
|
13 |
+
* This program is distributed in the hope that it will be useful,
|
14 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16 |
+
* GNU General Public License for more details.
|
17 |
+
*
|
18 |
+
* You should have received a copy of the GNU General Public License
|
19 |
+
* along with this program; if not, write to the Free Software
|
20 |
+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
21 |
+
* MA 02110-1301, USA.
|
22 |
+
*
|
23 |
+
* @link https://github.com/ovidiul/XCloner-Wordpress
|
24 |
+
*
|
25 |
+
* @modified 7/31/18 3:28 PM
|
26 |
*
|
|
|
|
|
27 |
*/
|
28 |
|
29 |
/**
|
35 |
* @package Xcloner
|
36 |
* @subpackage Xcloner/includes
|
37 |
* @author Liuta Ovidiu <info@thinkovi.com>
|
38 |
+
* @link http://www.thinkovi.com
|
39 |
*/
|
40 |
class Xcloner_Activator {
|
41 |
|
42 |
+
/**
|
43 |
+
* XCloner Database Version
|
44 |
+
* @var string
|
45 |
+
*/
|
46 |
const xcloner_db_version = '1.1.7';
|
47 |
+
/**
|
48 |
+
* Minimum required PHP version to run this plugin.
|
49 |
+
* @var string
|
50 |
+
*/
|
51 |
const xcloner_minimum_version = '5.6.0';
|
52 |
+
|
53 |
/**
|
54 |
+
* Triggered when XCloner is activated.
|
55 |
*
|
56 |
+
* This method will get trigger once XCloner plugin is activated.
|
57 |
*
|
58 |
* @since 1.0.0
|
59 |
*/
|
60 |
public static function activate() {
|
61 |
+
|
62 |
global $wpdb;
|
63 |
+
|
64 |
+
if ( version_compare( phpversion(), Xcloner_Activator::xcloner_minimum_version, '<' ) ) {
|
65 |
+
wp_die( '<p>' . sprintf( __( "XCloner requires minimum PHP version %s in order to run correctly. We have detected your version as %s" ), Xcloner_Activator::xcloner_minimum_version, phpversion() ) . '</p>', __( "XCloner Activation Error" ), array( 'response' => 500,
|
66 |
+
'back_link' => true
|
67 |
+
) );
|
68 |
}
|
69 |
+
|
70 |
+
$charset_collate = $wpdb->get_charset_collate();
|
71 |
+
|
72 |
$installed_ver = get_option( "xcloner_db_version" );
|
73 |
+
|
74 |
$xcloner_db_version = Xcloner_Activator::xcloner_db_version;
|
75 |
+
|
76 |
$xcloner_scheduler_table = $wpdb->prefix . "xcloner_scheduler";
|
77 |
+
|
78 |
+
if ( $installed_ver != $xcloner_db_version ) {
|
79 |
+
$xcloner_schedule_sql = "CREATE TABLE `" . $xcloner_scheduler_table . "` (
|
|
|
80 |
`id` int(11) NOT NULL AUTO_INCREMENT,
|
81 |
`name` varchar(255) NOT NULL,
|
82 |
`recurrence` varchar(25) NOT NULL,
|
87 |
`status` int(1) NOT NULL,
|
88 |
`last_backup` varchar(100) DEFAULT NULL,
|
89 |
PRIMARY KEY (`id`)
|
90 |
+
) " . $charset_collate . ";
|
91 |
";
|
92 |
+
|
93 |
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
|
94 |
dbDelta( $xcloner_schedule_sql );
|
95 |
+
|
96 |
update_option( "xcloner_db_version", $xcloner_db_version );
|
97 |
}
|
98 |
+
|
99 |
+
if ( get_option( 'xcloner_backup_compression_level' ) === false ) {
|
100 |
+
update_option( 'xcloner_backup_compression_level', 0 );
|
101 |
+
}
|
102 |
+
|
103 |
+
if ( get_option( 'xcloner_enable_log' ) === false ) {
|
104 |
+
update_option( 'xcloner_enable_log', 1 );
|
105 |
+
}
|
106 |
+
|
107 |
+
if ( get_option( 'xcloner_enable_mysql_backup' ) === false ) {
|
108 |
+
update_option( 'xcloner_enable_mysql_backup', 1 );
|
109 |
+
}
|
110 |
+
|
111 |
+
if ( get_option( 'xcloner_system_settings_page' ) === false ) {
|
112 |
+
update_option( 'xcloner_system_settings_page', 100 );
|
113 |
+
}
|
114 |
+
|
115 |
+
if ( get_option( 'xcloner_files_to_process_per_request' ) === false ) {
|
116 |
+
update_option( 'xcloner_files_to_process_per_request', 250 );
|
117 |
+
}
|
118 |
+
|
119 |
+
if ( get_option( 'xcloner_database_records_per_request' ) === false ) {
|
120 |
+
update_option( 'xcloner_database_records_per_request', 10000 );
|
121 |
+
}
|
122 |
+
|
123 |
+
if ( get_option( 'xcloner_exclude_files_larger_than_mb' ) === false ) {
|
124 |
+
update_option( 'xcloner_exclude_files_larger_than_mb', 0 );
|
125 |
+
}
|
126 |
+
|
127 |
+
if ( get_option( 'xcloner_split_backup_limit' ) === false ) {
|
128 |
+
update_option( 'xcloner_split_backup_limit', 2048 );
|
129 |
+
}
|
130 |
+
|
131 |
+
if ( get_option( 'xcloner_size_limit_per_request' ) === false ) {
|
132 |
+
update_option( 'xcloner_size_limit_per_request', 50 );
|
133 |
+
}
|
134 |
+
|
135 |
+
if ( get_option( 'xcloner_cleanup_retention_limit_days' ) === false ) {
|
136 |
+
update_option( 'xcloner_cleanup_retention_limit_days', 60 );
|
137 |
+
}
|
138 |
+
|
139 |
+
if ( get_option( 'xcloner_cleanup_retention_limit_archives' ) === false ) {
|
140 |
+
update_option( 'xcloner_cleanup_retention_limit_archives', 100 );
|
141 |
+
}
|
142 |
+
|
143 |
+
if ( get_option( 'xcloner_directories_to_scan_per_request' ) === false ) {
|
144 |
+
update_option( 'xcloner_directories_to_scan_per_request', 25 );
|
145 |
+
}
|
146 |
+
|
147 |
/*if(!get_option('xcloner_diff_backup_recreate_period'))
|
148 |
update_option('xcloner_diff_backup_recreate_period', 10);
|
149 |
* */
|
150 |
+
|
151 |
+
if ( ! get_option( 'xcloner_regex_exclude' ) ) {
|
152 |
+
update_option( 'xcloner_regex_exclude', "(wp-content\/updraft|wp-content\/uploads\/wp_all_backup)(.*)$" . PHP_EOL . "(.*)\.(svn|git)(.*)$" . PHP_EOL . "wp-content\/cache(.*)$" . PHP_EOL . "(.*)error_log$" );
|
153 |
+
}
|
154 |
|
155 |
}
|
156 |
+
|
157 |
}
|
includes/class-xcloner-api.php
CHANGED
@@ -1,4 +1,30 @@
|
|
1 |
<?php
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
|
3 |
use League\Flysystem\Config;
|
4 |
use League\Flysystem\Filesystem;
|
@@ -11,1062 +37,1098 @@ use splitbrain\PHPArchive\Archive;
|
|
11 |
use splitbrain\PHPArchive\FileInfo;
|
12 |
|
13 |
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
227 |
$response['error'] = 1;
|
228 |
-
$response['error_message'] = $wpdb->last_error/*."--".$wpdb->last_query
|
229 |
-
|
|
|
230 |
}
|
231 |
-
|
232 |
$scheduler->update_wp_cron_hooks();
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
583 |
-
|
584 |
-
|
585 |
-
|
586 |
-
|
587 |
-
|
588 |
-
|
589 |
-
|
590 |
-
|
591 |
-
|
592 |
-
|
593 |
-
|
594 |
-
|
595 |
-
|
596 |
-
|
597 |
-
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
-
|
603 |
-
|
604 |
-
|
605 |
-
|
606 |
-
|
607 |
-
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
|
615 |
-
|
616 |
-
|
617 |
-
|
618 |
-
|
619 |
-
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
-
|
626 |
-
|
627 |
-
|
628 |
-
|
629 |
-
|
630 |
-
|
631 |
-
|
632 |
-
|
633 |
-
|
634 |
-
|
635 |
-
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
|
640 |
-
|
641 |
-
|
642 |
-
|
643 |
-
|
644 |
-
|
645 |
-
|
646 |
-
|
647 |
-
|
648 |
-
|
649 |
-
|
650 |
-
|
651 |
-
|
652 |
-
|
653 |
-
|
654 |
-
|
655 |
-
|
656 |
-
|
657 |
-
|
658 |
-
|
659 |
-
|
660 |
-
|
661 |
-
|
662 |
-
|
663 |
-
|
664 |
-
|
665 |
-
|
666 |
-
|
667 |
-
|
668 |
-
|
669 |
-
|
670 |
-
|
671 |
-
|
672 |
-
|
673 |
-
|
674 |
-
|
675 |
-
|
676 |
-
|
677 |
-
|
678 |
-
|
679 |
-
|
680 |
-
|
681 |
-
|
682 |
-
|
683 |
-
|
684 |
-
|
685 |
-
|
686 |
-
|
687 |
-
|
688 |
-
|
689 |
-
|
690 |
-
|
691 |
-
|
692 |
-
|
693 |
-
|
694 |
-
|
695 |
-
|
696 |
-
|
697 |
-
|
698 |
-
|
699 |
-
|
700 |
-
|
701 |
-
|
702 |
-
|
703 |
-
|
704 |
-
|
705 |
-
|
706 |
-
|
707 |
-
|
708 |
-
|
709 |
-
|
710 |
-
|
711 |
-
|
712 |
-
|
713 |
-
|
714 |
-
|
715 |
-
|
716 |
-
|
717 |
-
|
718 |
-
|
719 |
-
|
720 |
-
|
721 |
-
|
722 |
-
|
723 |
-
|
724 |
-
|
725 |
-
|
726 |
-
|
727 |
-
|
728 |
-
|
729 |
-
|
730 |
-
|
731 |
-
|
732 |
-
|
733 |
-
|
734 |
-
|
735 |
-
|
736 |
-
|
737 |
-
|
738 |
-
|
739 |
-
|
740 |
-
|
741 |
-
|
742 |
-
|
743 |
-
|
744 |
-
|
745 |
-
|
746 |
-
|
747 |
-
|
748 |
-
|
749 |
-
|
750 |
-
|
751 |
-
|
752 |
-
|
753 |
-
|
754 |
-
|
755 |
-
|
756 |
-
|
757 |
-
|
758 |
-
|
759 |
-
|
760 |
-
|
761 |
-
|
762 |
-
|
763 |
-
|
764 |
-
|
765 |
-
|
766 |
-
|
767 |
-
|
768 |
-
|
769 |
-
|
770 |
-
|
771 |
-
|
772 |
-
|
773 |
-
|
774 |
-
|
775 |
-
|
776 |
-
|
777 |
-
|
778 |
-
|
779 |
-
|
780 |
-
|
781 |
-
|
782 |
-
|
783 |
-
|
784 |
-
|
785 |
-
|
786 |
-
|
787 |
-
|
788 |
-
|
789 |
-
|
790 |
-
|
791 |
-
|
792 |
-
|
793 |
-
|
794 |
-
|
795 |
-
|
796 |
-
|
797 |
-
|
798 |
-
|
799 |
-
|
800 |
-
|
801 |
-
|
802 |
-
|
803 |
-
|
804 |
-
|
805 |
-
|
806 |
-
|
807 |
-
|
808 |
-
|
809 |
-
|
810 |
-
|
811 |
-
|
812 |
-
|
813 |
-
|
814 |
-
|
815 |
-
|
816 |
-
|
817 |
-
|
818 |
-
|
819 |
-
|
820 |
-
|
821 |
-
|
822 |
-
|
823 |
-
|
824 |
-
|
825 |
-
|
826 |
-
|
827 |
-
|
828 |
-
|
829 |
-
|
830 |
-
|
831 |
-
|
832 |
-
|
833 |
-
|
834 |
-
|
835 |
-
|
836 |
-
|
837 |
-
|
838 |
-
|
839 |
-
|
840 |
-
|
841 |
-
|
842 |
-
|
843 |
-
|
844 |
-
|
845 |
-
|
846 |
-
|
847 |
-
|
848 |
-
|
849 |
-
|
850 |
-
|
851 |
-
|
852 |
-
|
853 |
-
|
854 |
-
|
855 |
-
|
856 |
-
|
857 |
-
|
858 |
-
|
859 |
-
|
860 |
-
|
861 |
-
|
862 |
-
|
863 |
-
|
864 |
-
|
865 |
-
|
866 |
-
|
867 |
-
|
868 |
-
|
869 |
-
|
870 |
-
|
871 |
-
|
872 |
-
|
873 |
-
|
874 |
-
|
875 |
-
|
876 |
-
|
877 |
-
|
878 |
-
|
879 |
-
|
880 |
-
|
881 |
-
|
882 |
-
|
883 |
-
|
884 |
-
|
885 |
-
|
886 |
-
|
887 |
-
|
888 |
-
|
889 |
-
|
890 |
-
|
891 |
-
|
892 |
-
|
893 |
-
|
894 |
-
|
895 |
-
|
896 |
-
|
897 |
-
|
898 |
-
|
899 |
-
|
900 |
-
|
901 |
-
|
902 |
-
|
903 |
-
|
904 |
-
|
905 |
-
|
906 |
-
|
907 |
-
|
908 |
-
|
909 |
-
|
910 |
-
|
911 |
-
|
912 |
-
|
913 |
-
|
914 |
-
|
915 |
-
|
916 |
-
|
917 |
-
|
918 |
-
|
919 |
-
|
920 |
-
|
921 |
-
|
922 |
-
|
923 |
-
|
924 |
-
|
925 |
-
|
926 |
-
|
927 |
-
|
928 |
-
|
929 |
-
|
930 |
-
|
931 |
-
|
932 |
-
|
933 |
-
|
934 |
-
|
935 |
-
|
936 |
-
|
937 |
-
|
938 |
-
|
939 |
-
|
940 |
-
|
941 |
-
|
942 |
-
|
943 |
-
|
944 |
-
|
945 |
-
|
946 |
-
|
947 |
-
|
948 |
-
|
949 |
-
|
950 |
-
|
951 |
-
|
952 |
-
|
953 |
-
|
954 |
-
|
955 |
-
|
956 |
-
|
957 |
-
|
958 |
-
|
959 |
-
|
960 |
-
|
961 |
-
|
962 |
-
|
963 |
-
|
964 |
-
|
965 |
-
|
966 |
-
|
967 |
-
|
968 |
-
|
969 |
-
|
970 |
-
|
971 |
-
|
972 |
-
|
973 |
-
|
974 |
-
|
975 |
-
|
976 |
-
|
977 |
-
|
978 |
-
|
979 |
-
|
980 |
-
|
981 |
-
|
982 |
-
|
983 |
-
|
984 |
-
|
985 |
-
|
986 |
-
|
987 |
-
|
988 |
-
|
989 |
-
|
990 |
-
|
991 |
-
|
992 |
-
|
993 |
-
|
994 |
-
|
995 |
-
|
996 |
-
|
997 |
-
|
998 |
-
|
999 |
-
|
1000 |
-
|
1001 |
-
|
1002 |
-
|
1003 |
-
|
1004 |
-
|
1005 |
-
|
1006 |
-
|
1007 |
-
|
1008 |
-
|
1009 |
-
|
1010 |
-
|
1011 |
-
|
1012 |
-
|
1013 |
-
|
1014 |
-
|
1015 |
-
|
1016 |
-
|
1017 |
-
|
1018 |
-
|
1019 |
-
|
1020 |
-
|
1021 |
-
|
1022 |
-
|
1023 |
-
|
1024 |
-
|
1025 |
-
|
1026 |
-
|
1027 |
-
|
1028 |
-
|
1029 |
-
|
1030 |
-
|
1031 |
-
|
1032 |
-
|
1033 |
-
|
1034 |
-
|
1035 |
-
|
1036 |
-
|
1037 |
-
|
1038 |
-
|
1039 |
-
|
1040 |
-
|
1041 |
-
|
1042 |
-
|
1043 |
-
|
1044 |
-
|
1045 |
-
|
1046 |
-
|
1047 |
-
|
1048 |
-
|
1049 |
-
|
1050 |
-
|
1051 |
-
|
1052 |
-
|
1053 |
-
|
1054 |
-
|
1055 |
-
|
1056 |
-
|
1057 |
-
|
1058 |
-
|
1059 |
-
|
1060 |
-
|
1061 |
-
|
1062 |
-
|
1063 |
-
|
1064 |
-
|
1065 |
-
|
1066 |
-
|
1067 |
-
|
1068 |
-
|
1069 |
-
|
1070 |
-
|
1071 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1072 |
}
|
1 |
<?php
|
2 |
+
/**
|
3 |
+
* XCloner - Backup and Restore backup plugin for Wordpress
|
4 |
+
*
|
5 |
+
* class-xcloner-api.php
|
6 |
+
* @author Liuta Ovidiu <info@thinkovi.com>
|
7 |
+
*
|
8 |
+
* This program is free software; you can redistribute it and/or modify
|
9 |
+
* it under the terms of the GNU General Public License as published by
|
10 |
+
* the Free Software Foundation; either version 2 of the License, or
|
11 |
+
* (at your option) any later version.
|
12 |
+
*
|
13 |
+
* This program is distributed in the hope that it will be useful,
|
14 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16 |
+
* GNU General Public License for more details.
|
17 |
+
*
|
18 |
+
* You should have received a copy of the GNU General Public License
|
19 |
+
* along with this program; if not, write to the Free Software
|
20 |
+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
21 |
+
* MA 02110-1301, USA.
|
22 |
+
*
|
23 |
+
* @link https://github.com/ovidiul/XCloner-Wordpress
|
24 |
+
*
|
25 |
+
* @modified 7/31/18 3:00 PM
|
26 |
+
*
|
27 |
+
*/
|
28 |
|
29 |
use League\Flysystem\Config;
|
30 |
use League\Flysystem\Filesystem;
|
37 |
use splitbrain\PHPArchive\FileInfo;
|
38 |
|
39 |
|
40 |
+
/**
|
41 |
+
* XCloner Api Class
|
42 |
+
*/
|
43 |
+
class Xcloner_Api
|
44 |
+
{
|
45 |
+
|
46 |
+
private $xcloner_database;
|
47 |
+
private $xcloner_settings;
|
48 |
+
private $xcloner_file_system;
|
49 |
+
private $xcloner_requirements;
|
50 |
+
private $xcloner_sanitization;
|
51 |
+
private $archive_system;
|
52 |
+
private $form_params;
|
53 |
+
private $logger;
|
54 |
+
private $xcloner_container;
|
55 |
+
|
56 |
+
/**
|
57 |
+
* XCloner_Api construct class
|
58 |
+
*
|
59 |
+
* @param Xcloner $xcloner_container [description]
|
60 |
+
*/
|
61 |
+
public function __construct(Xcloner $xcloner_container)
|
62 |
+
{
|
63 |
+
global $wpdb;
|
64 |
+
|
65 |
+
if (WP_DEBUG) {
|
66 |
+
error_reporting(0);
|
67 |
+
}
|
68 |
+
|
69 |
+
if (ob_get_length()) {
|
70 |
+
ob_end_clean();
|
71 |
+
}
|
72 |
+
ob_start();
|
73 |
+
|
74 |
+
$wpdb->show_errors = false;
|
75 |
+
|
76 |
+
$this->xcloner_container = $xcloner_container;
|
77 |
+
|
78 |
+
$this->xcloner_settings = $xcloner_container->get_xcloner_settings();
|
79 |
+
$this->logger = $xcloner_container->get_xcloner_logger()->withName("xcloner_api");
|
80 |
+
$this->xcloner_file_system = $xcloner_container->get_xcloner_filesystem();
|
81 |
+
$this->xcloner_sanitization = $xcloner_container->get_xcloner_sanitization();
|
82 |
+
$this->xcloner_requirements = $xcloner_container->get_xcloner_requirements();
|
83 |
+
$this->archive_system = $xcloner_container->get_archive_system();
|
84 |
+
$this->xcloner_database = $xcloner_container->get_xcloner_database();
|
85 |
+
$this->xcloner_scheduler = $xcloner_container->get_xcloner_scheduler();
|
86 |
+
|
87 |
+
if (isset($_POST['API_ID'])) {
|
88 |
+
$this->logger->info("Processing ajax request ID " . substr($this->xcloner_sanitization->sanitize_input_as_string($_POST['API_ID']),
|
89 |
+
0, 15));
|
90 |
+
}
|
91 |
+
|
92 |
+
}
|
93 |
+
|
94 |
+
/**
|
95 |
+
* Get XCloner Container
|
96 |
+
* @return XCloner return the XCloner container
|
97 |
+
*/
|
98 |
+
public function get_xcloner_container()
|
99 |
+
{
|
100 |
+
return $this->xcloner_container;
|
101 |
+
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* Check if user has access to this class
|
105 |
+
* @return die() returns die() if user is not allowed
|
106 |
+
* @link http://www.wordpress.org
|
107 |
+
*/
|
108 |
+
private function check_access()
|
109 |
+
{
|
110 |
+
if (function_exists('current_user_can') && !current_user_can('manage_options')) {
|
111 |
+
die("Not allowed access here!");
|
112 |
+
}
|
113 |
+
}
|
114 |
+
|
115 |
+
/**
|
116 |
+
* Initialize the database connection
|
117 |
+
*/
|
118 |
+
public function init_db()
|
119 |
+
{
|
120 |
+
return;
|
121 |
+
|
122 |
+
|
123 |
+
$data['dbHostname'] = $this->xcloner_settings->get_db_hostname();
|
124 |
+
$data['dbUsername'] = $this->xcloner_settings->get_db_username();
|
125 |
+
$data['dbPassword'] = $this->xcloner_settings->get_db_password();
|
126 |
+
$data['dbDatabase'] = $this->xcloner_settings->get_db_database();
|
127 |
+
|
128 |
+
|
129 |
+
$data['recordsPerSession'] = $this->xcloner_settings->get_xcloner_option('xcloner_database_records_per_request');
|
130 |
+
$data['TEMP_DBPROCESS_FILE'] = $this->xcloner_settings->get_xcloner_tmp_path() . DS . ".database";
|
131 |
+
$data['TEMP_DUMP_FILE'] = $this->xcloner_settings->get_xcloner_tmp_path() . DS . "database-sql.sql";
|
132 |
+
|
133 |
+
try {
|
134 |
+
$this->xcloner_database->init($data);
|
135 |
+
|
136 |
+
} catch (Exception $e) {
|
137 |
+
|
138 |
+
$this->send_response($e->getMessage());
|
139 |
+
$this->logger->error($e->getMessage());
|
140 |
+
|
141 |
+
}
|
142 |
+
|
143 |
+
return $this->xcloner_database;
|
144 |
+
|
145 |
+
|
146 |
+
}
|
147 |
+
|
148 |
+
/*
|
149 |
+
* Save Schedule API
|
150 |
+
*/
|
151 |
+
public function save_schedule()
|
152 |
+
{
|
153 |
+
global $wpdb;
|
154 |
+
|
155 |
+
$this->check_access();
|
156 |
+
|
157 |
+
$scheduler = $this->xcloner_scheduler;
|
158 |
+
$params = array();
|
159 |
+
$schedule = array();
|
160 |
+
$response = array();
|
161 |
+
|
162 |
+
if (isset($_POST['data'])) {
|
163 |
+
$params = json_decode(stripslashes($_POST['data']));
|
164 |
+
}
|
165 |
+
|
166 |
+
$this->process_params($params);
|
167 |
+
|
168 |
+
if (isset($_POST['id'])) {
|
169 |
+
|
170 |
+
$this->form_params['backup_params']['backup_name'] = $this->xcloner_sanitization->sanitize_input_as_string($_POST['backup_name']);
|
171 |
+
$this->form_params['backup_params']['email_notification'] = $this->xcloner_sanitization->sanitize_input_as_string($_POST['email_notification']);
|
172 |
+
if ($_POST['diff_start_date']) {
|
173 |
+
$this->form_params['backup_params']['diff_start_date'] = strtotime($this->xcloner_sanitization->sanitize_input_as_string($_POST['diff_start_date']));
|
174 |
+
} else {
|
175 |
+
$this->form_params['backup_params']['diff_start_date'] = "";
|
176 |
+
}
|
177 |
+
$this->form_params['backup_params']['schedule_name'] = $this->xcloner_sanitization->sanitize_input_as_string($_POST['schedule_name']);
|
178 |
+
$this->form_params['backup_params']['start_at'] = strtotime($_POST['schedule_start_date']);
|
179 |
+
$this->form_params['backup_params']['schedule_frequency'] = $this->xcloner_sanitization->sanitize_input_as_string($_POST['schedule_frequency']);
|
180 |
+
$this->form_params['backup_params']['schedule_storage'] = $this->xcloner_sanitization->sanitize_input_as_string($_POST['schedule_storage']);
|
181 |
+
$this->form_params['database'] = (stripslashes($this->xcloner_sanitization->sanitize_input_as_raw($_POST['table_params'])));
|
182 |
+
$this->form_params['excluded_files'] = (stripslashes($this->xcloner_sanitization->sanitize_input_as_raw($_POST['excluded_files'])));
|
183 |
+
|
184 |
+
//$this->form_params['backup_params']['backup_type'] = $this->xcloner_sanitization->sanitize_input_as_string($_POST['backup_type']);
|
185 |
+
|
186 |
+
$tables = explode(PHP_EOL, $this->form_params['database']);
|
187 |
+
$return = array();
|
188 |
+
|
189 |
+
foreach ($tables as $table) {
|
190 |
+
$table = str_replace("\r", "", $table);
|
191 |
+
$data = explode(".", $table);
|
192 |
+
if (isset($data[1])) {
|
193 |
+
$return[$data[0]][] = $data[1];
|
194 |
+
}
|
195 |
+
}
|
196 |
+
|
197 |
+
$this->form_params['database'] = ($return);
|
198 |
+
|
199 |
+
$excluded_files = explode(PHP_EOL, $this->form_params['excluded_files']);
|
200 |
+
$return = array();
|
201 |
+
|
202 |
+
foreach ($excluded_files as $file) {
|
203 |
+
$file = str_replace("\r", "", $file);
|
204 |
+
if ($file) {
|
205 |
+
$return[] = $file;
|
206 |
+
}
|
207 |
+
}
|
208 |
+
|
209 |
+
$this->form_params['excluded_files'] = ($return);
|
210 |
+
|
211 |
+
$schedule['start_at'] = $this->form_params['backup_params']['start_at'];
|
212 |
+
|
213 |
+
if (!isset($_POST['status'])) {
|
214 |
+
$schedule['status'] = 0;
|
215 |
+
} else {
|
216 |
+
$schedule['status'] = $this->xcloner_sanitization->sanitize_input_as_int($_POST['status']);
|
217 |
+
}
|
218 |
+
} else {
|
219 |
+
|
220 |
+
$schedule['status'] = 1;
|
221 |
+
$schedule['start_at'] = strtotime($this->form_params['backup_params']['schedule_start_date'] .
|
222 |
+
" " . $this->form_params['backup_params']['schedule_start_time']);
|
223 |
+
|
224 |
+
if ($schedule['start_at'] <= time()) {
|
225 |
+
$schedule['start_at'] = "";
|
226 |
+
}
|
227 |
+
}
|
228 |
+
|
229 |
+
if (!$schedule['start_at']) {
|
230 |
+
$schedule['start_at'] = date('Y-m-d H:i:s', time());
|
231 |
+
} else {
|
232 |
+
$schedule['start_at'] = date('Y-m-d H:i:s',
|
233 |
+
$schedule['start_at'] - (get_option('gmt_offset') * HOUR_IN_SECONDS));
|
234 |
+
}
|
235 |
+
|
236 |
+
$schedule['name'] = $this->form_params['backup_params']['schedule_name'];
|
237 |
+
$schedule['recurrence'] = $this->form_params['backup_params']['schedule_frequency'];
|
238 |
+
if (!isset($this->form_params['backup_params']['schedule_storage'])) {
|
239 |
+
$this->form_params['backup_params']['schedule_storage'] = "";
|
240 |
+
}
|
241 |
+
$schedule['remote_storage'] = $this->form_params['backup_params']['schedule_storage'];
|
242 |
+
//$schedule['backup_type'] = $this->form_params['backup_params']['backup_type'];
|
243 |
+
$schedule['params'] = json_encode($this->form_params);
|
244 |
+
|
245 |
+
if (!isset($_POST['id'])) {
|
246 |
+
$wpdb->insert(
|
247 |
+
$wpdb->prefix . 'xcloner_scheduler',
|
248 |
+
$schedule,
|
249 |
+
array(
|
250 |
+
'%s',
|
251 |
+
'%s'
|
252 |
+
)
|
253 |
+
);
|
254 |
+
} else {
|
255 |
+
$wpdb->update(
|
256 |
+
$wpdb->prefix . 'xcloner_scheduler',
|
257 |
+
$schedule,
|
258 |
+
array('id' => $_POST['id']),
|
259 |
+
array(
|
260 |
+
'%s',
|
261 |
+
'%s'
|
262 |
+
)
|
263 |
+
);
|
264 |
+
}
|
265 |
+
if (isset($_POST['id'])) {
|
266 |
+
$scheduler->update_cron_hook($_POST['id']);
|
267 |
+
}
|
268 |
+
|
269 |
+
if ($wpdb->last_error) {
|
270 |
$response['error'] = 1;
|
271 |
+
$response['error_message'] = $wpdb->last_error/*."--".$wpdb->last_query*/
|
272 |
+
;
|
273 |
+
|
274 |
}
|
275 |
+
|
276 |
$scheduler->update_wp_cron_hooks();
|
277 |
+
$response['finished'] = 1;
|
278 |
+
|
279 |
+
$this->send_response($response);
|
280 |
+
}
|
281 |
+
|
282 |
+
/*
|
283 |
+
*
|
284 |
+
* Backup Files API
|
285 |
+
*
|
286 |
+
*/
|
287 |
+
public function backup_files()
|
288 |
+
{
|
289 |
+
$this->check_access();
|
290 |
+
|
291 |
+
$params = json_decode(stripslashes($_POST['data']));
|
292 |
+
|
293 |
+
$init = (int)$_POST['init'];
|
294 |
+
|
295 |
+
if ($params === null) {
|
296 |
+
die('{"status":false,"msg":"The post_data parameter must be valid JSON"}');
|
297 |
+
}
|
298 |
+
|
299 |
+
$this->process_params($params);
|
300 |
+
|
301 |
+
$return['finished'] = 1;
|
302 |
+
|
303 |
+
//$return = $this->archive_system->start_incremental_backup($this->form_params['backup_params'], $this->form_params['extra'], $init);
|
304 |
+
try {
|
305 |
+
$return = $this->archive_system->start_incremental_backup($this->form_params['backup_params'],
|
306 |
+
$this->form_params['extra'], $init);
|
307 |
+
} catch (Exception $e) {
|
308 |
+
$return = array();
|
309 |
+
$return['error'] = true;
|
310 |
+
$return['status'] = 500;
|
311 |
+
$return['error_message'] = $e->getMessage();
|
312 |
+
|
313 |
+
return $this->send_response($return, $hash = 1);
|
314 |
+
}
|
315 |
+
|
316 |
+
if ($return['finished']) {
|
317 |
+
$return['extra']['backup_parent'] = $this->archive_system->get_archive_name_with_extension();
|
318 |
+
if ($this->xcloner_file_system->is_part($this->archive_system->get_archive_name_with_extension())) {
|
319 |
+
$return['extra']['backup_parent'] = $this->archive_system->get_archive_name_multipart();
|
320 |
+
}
|
321 |
+
}
|
322 |
+
|
323 |
+
$data = $return;
|
324 |
+
|
325 |
+
//check if backup is finished
|
326 |
+
if ($return['finished']) {
|
327 |
+
if (isset($this->form_params['backup_params']['email_notification']) and $to = $this->form_params['backup_params']['email_notification']) {
|
328 |
+
try {
|
329 |
+
$from = "";
|
330 |
+
$subject = "";
|
331 |
+
$additional['lines_total'] = $return['extra']['lines_total'];
|
332 |
+
$this->archive_system->send_notification($to, $from, $subject, $return['extra']['backup_parent'],
|
333 |
+
$this->form_params, "", $additional);
|
334 |
+
} catch (Exception $e) {
|
335 |
+
$this->logger->error($e->getMessage());
|
336 |
+
}
|
337 |
+
}
|
338 |
+
$this->xcloner_file_system->remove_tmp_filesystem();
|
339 |
+
}
|
340 |
+
|
341 |
+
return $this->send_response($data, $hash = 1);
|
342 |
+
}
|
343 |
+
|
344 |
+
/*
|
345 |
+
*
|
346 |
+
* Backup Database API
|
347 |
+
*
|
348 |
+
*/
|
349 |
+
public function backup_database()
|
350 |
+
{
|
351 |
+
$this->check_access();
|
352 |
+
|
353 |
+
$params = json_decode(stripslashes($_POST['data']));
|
354 |
+
|
355 |
+
$init = (int)$_POST['init'];
|
356 |
+
|
357 |
+
if ($params === null) {
|
358 |
+
die('{"status":false,"msg":"The post_data parameter must be valid JSON"}');
|
359 |
+
}
|
360 |
+
|
361 |
+
$this->process_params($params);
|
362 |
+
|
363 |
+
//$xcloner_database = $this->init_db();
|
364 |
+
$return = $this->xcloner_database->start_database_recursion($this->form_params['database'],
|
365 |
+
$this->form_params['extra'], $init);
|
366 |
+
|
367 |
+
if (isset($return['error']) and $return['error']) {
|
368 |
+
$data['finished'] = 1;
|
369 |
+
} else {
|
370 |
+
$data['finished'] = $return['finished'];
|
371 |
+
}
|
372 |
+
|
373 |
+
$data['extra'] = $return;
|
374 |
+
|
375 |
+
return $this->send_response($data, $hash = 1);
|
376 |
+
}
|
377 |
+
|
378 |
+
/*
|
379 |
+
*
|
380 |
+
* Scan Filesystem API
|
381 |
+
*
|
382 |
+
*/
|
383 |
+
public function scan_filesystem()
|
384 |
+
{
|
385 |
+
$this->check_access();
|
386 |
+
|
387 |
+
$params = json_decode(stripslashes($_POST['data']));
|
388 |
+
$init = (int)$_POST['init'];
|
389 |
+
|
390 |
+
if ($params === null) {
|
391 |
+
die('{"status":false,"msg":"The post_data parameter must be valid JSON"}');
|
392 |
+
}
|
393 |
+
|
394 |
+
$hash = $this->process_params($params);
|
395 |
+
|
396 |
+
$this->xcloner_file_system->set_excluded_files($this->form_params['excluded_files']);
|
397 |
+
|
398 |
+
$return = $this->xcloner_file_system->start_file_recursion($init);
|
399 |
+
|
400 |
+
$data["finished"] = !$return;
|
401 |
+
$data["total_files_num"] = $this->xcloner_file_system->get_scanned_files_num();
|
402 |
+
$data["last_logged_file"] = $this->xcloner_file_system->last_logged_file();
|
403 |
+
$data["total_files_size"] = sprintf("%.2f",
|
404 |
+
$this->xcloner_file_system->get_scanned_files_total_size() / (1024 * 1024));
|
405 |
+
|
406 |
+
return $this->send_response($data, $hash = 1);
|
407 |
+
}
|
408 |
+
|
409 |
+
/*
|
410 |
+
*
|
411 |
+
* Process params sent by the user
|
412 |
+
*
|
413 |
+
*/
|
414 |
+
private function process_params($params)
|
415 |
+
{
|
416 |
+
if (isset($params->hash)) {
|
417 |
+
$this->xcloner_settings->set_hash($params->hash);
|
418 |
+
}
|
419 |
+
|
420 |
+
$this->form_params['extra'] = array();
|
421 |
+
$this->form_params['backup_params'] = array();
|
422 |
+
|
423 |
+
$this->form_params['database'] = array();
|
424 |
+
|
425 |
+
if (isset($params->backup_params)) {
|
426 |
+
foreach ($params->backup_params as $param) {
|
427 |
+
$this->form_params['backup_params'][$param->name] = $this->xcloner_sanitization->sanitize_input_as_string($param->value);
|
428 |
+
$this->logger->debug("Adding form parameter " . $param->name . "." . $param->value . "\n", array(
|
429 |
+
'POST',
|
430 |
+
'fields filter'
|
431 |
+
));
|
432 |
+
}
|
433 |
+
}
|
434 |
+
|
435 |
+
$this->form_params['database'] = array();
|
436 |
+
|
437 |
+
if (isset($params->table_params)) {
|
438 |
+
foreach ($params->table_params as $param) {
|
439 |
+
$this->form_params['database'][$param->parent][] = $this->xcloner_sanitization->sanitize_input_as_raw($param->id);
|
440 |
+
$this->logger->debug("Adding database filter " . $param->parent . "." . $param->id . "\n", array(
|
441 |
+
'POST',
|
442 |
+
'database filter'
|
443 |
+
));
|
444 |
+
}
|
445 |
+
}
|
446 |
+
|
447 |
+
$this->form_params['excluded_files'] = array();
|
448 |
+
if (isset($params->files_params)) {
|
449 |
+
foreach ($params->files_params as $param) {
|
450 |
+
$this->form_params['excluded_files'][] = $this->xcloner_sanitization->sanitize_input_as_relative_path($param->id);
|
451 |
+
}
|
452 |
+
|
453 |
+
$unique_exclude_files = array();
|
454 |
+
|
455 |
+
foreach ($params->files_params as $key => $param) {
|
456 |
+
if (!in_array($param->parent, $this->form_params['excluded_files'])) {
|
457 |
+
//$this->form_params['excluded_files'][] = $this->xcloner_sanitization->sanitize_input_as_relative_path($param->id);
|
458 |
+
$unique_exclude_files[] = $param->id;
|
459 |
+
$this->logger->debug("Adding file filter " . $param->id . "\n", array(
|
460 |
+
'POST',
|
461 |
+
'exclude files filter'
|
462 |
+
));
|
463 |
+
}
|
464 |
+
}
|
465 |
+
$this->form_params['excluded_files'] = (array)$unique_exclude_files;
|
466 |
+
|
467 |
+
}
|
468 |
+
|
469 |
+
//$this->form_params['excluded_files'] = array_merge($this->form_params['excluded_files'], $this->exclude_files_by_default);
|
470 |
+
|
471 |
+
if (isset($params->extra)) {
|
472 |
+
foreach ($params->extra as $key => $value) {
|
473 |
+
$this->form_params['extra'][$key] = $this->xcloner_sanitization->sanitize_input_as_raw($value);
|
474 |
+
}
|
475 |
+
}
|
476 |
+
|
477 |
+
if (isset($this->form_params['backup_params']['diff_start_date']) and $this->form_params['backup_params']['diff_start_date']) {
|
478 |
+
$this->form_params['backup_params']['diff_start_date'] = strtotime($this->form_params['backup_params']['diff_start_date']);
|
479 |
+
$this->xcloner_file_system->set_diff_timestamp_start($this->form_params['backup_params']['diff_start_date']);
|
480 |
+
}
|
481 |
+
|
482 |
+
return $this->xcloner_settings->get_hash();
|
483 |
+
}
|
484 |
+
|
485 |
+
/*
|
486 |
+
*
|
487 |
+
* Get file list for tree view API
|
488 |
+
*
|
489 |
+
*/
|
490 |
+
public function get_file_system_action()
|
491 |
+
{
|
492 |
+
$this->check_access();
|
493 |
+
|
494 |
+
$folder = $this->xcloner_sanitization->sanitize_input_as_relative_path($_POST['id']);
|
495 |
+
|
496 |
+
$data = array();
|
497 |
+
|
498 |
+
if ($folder == "#") {
|
499 |
+
|
500 |
+
$folder = "/";
|
501 |
+
$data[] = array(
|
502 |
+
'id' => $folder,
|
503 |
+
'parent' => '#',
|
504 |
+
'text' => $this->xcloner_settings->get_xcloner_start_path(),
|
505 |
+
//'children' => true,
|
506 |
+
'state' => array('selected' => false, 'opened' => true),
|
507 |
+
'icon' => plugin_dir_url(dirname(__FILE__)) . "/admin/assets/file-icon-root.png"
|
508 |
+
);
|
509 |
+
}
|
510 |
+
|
511 |
+
try {
|
512 |
+
$files = $this->xcloner_file_system->list_directory($folder);
|
513 |
+
} catch (Exception $e) {
|
514 |
+
|
515 |
+
print $e->getMessage();
|
516 |
+
$this->logger->error($e->getMessage());
|
517 |
+
|
518 |
+
return;
|
519 |
+
}
|
520 |
+
|
521 |
+
$type = array();
|
522 |
+
foreach ($files as $key => $row) {
|
523 |
+
$type[$key] = $row['type'];
|
524 |
+
}
|
525 |
+
array_multisort($type, SORT_ASC, $files);
|
526 |
+
|
527 |
+
foreach ($files as $file) {
|
528 |
+
$children = false;
|
529 |
+
$text = $file['basename'];
|
530 |
+
|
531 |
+
if ($file['type'] == "dir") {
|
532 |
+
$children = true;
|
533 |
+
} else {
|
534 |
+
$text .= " (" . $this->xcloner_requirements->file_format_size($file['size']) . ")";
|
535 |
+
}
|
536 |
+
|
537 |
+
if ($this->xcloner_file_system->is_excluded($file)) {
|
538 |
+
$selected = true;
|
539 |
+
} else {
|
540 |
+
$selected = false;
|
541 |
+
}
|
542 |
+
|
543 |
+
$data[] = array(
|
544 |
+
'id' => $file['path'],
|
545 |
+
'parent' => $folder,
|
546 |
+
'text' => $text,
|
547 |
+
//'title' => "test",
|
548 |
+
'children' => $children,
|
549 |
+
'state' => array('selected' => $selected, 'opened' => false, "checkbox_disabled" => $selected),
|
550 |
+
'icon' => plugin_dir_url(dirname(__FILE__)) . "/admin/assets/file-icon-" . strtolower(substr($file['type'],
|
551 |
+
0, 1)) . ".png"
|
552 |
+
);
|
553 |
+
}
|
554 |
+
|
555 |
+
|
556 |
+
return $this->send_response($data, 0);
|
557 |
+
}
|
558 |
+
|
559 |
+
/*
|
560 |
+
*
|
561 |
+
* Get databases/tables list for frontend tree display API
|
562 |
+
*
|
563 |
+
*/
|
564 |
+
public function get_database_tables_action()
|
565 |
+
{
|
566 |
+
$this->check_access();
|
567 |
+
|
568 |
+
$database = $this->xcloner_sanitization->sanitize_input_as_raw($_POST['id']);
|
569 |
+
|
570 |
+
$data = array();
|
571 |
+
|
572 |
+
$xcloner_backup_only_wp_tables = $this->xcloner_settings->get_xcloner_option('xcloner_backup_only_wp_tables');
|
573 |
+
|
574 |
+
if ($database == "#") {
|
575 |
+
try {
|
576 |
+
$return = $this->xcloner_database->get_all_databases();
|
577 |
+
} catch (Exception $e) {
|
578 |
+
$this->logger->error($e->getMessage());
|
579 |
+
}
|
580 |
+
|
581 |
+
foreach ($return as $database) {
|
582 |
+
if ($xcloner_backup_only_wp_tables and $database['name'] != $this->xcloner_settings->get_db_database()) {
|
583 |
+
continue;
|
584 |
+
}
|
585 |
+
|
586 |
+
$state = array();
|
587 |
+
|
588 |
+
if ($database['name'] == $this->xcloner_settings->get_db_database()) {
|
589 |
+
$state['selected'] = true;
|
590 |
+
if ($database['num_tables'] < 25) {
|
591 |
+
$state['opened'] = false;
|
592 |
+
}
|
593 |
+
}
|
594 |
+
|
595 |
+
$data[] = array(
|
596 |
+
'id' => $database['name'],
|
597 |
+
'parent' => '#',
|
598 |
+
'text' => $database['name'] . " (" . (int)$database['num_tables'] . ")",
|
599 |
+
'children' => true,
|
600 |
+
'state' => $state,
|
601 |
+
'icon' => plugin_dir_url(dirname(__FILE__)) . "/admin/assets/database-icon.png"
|
602 |
+
);
|
603 |
+
}
|
604 |
+
|
605 |
+
} else {
|
606 |
+
|
607 |
+
try {
|
608 |
+
$return = $this->xcloner_database->list_tables($database, "", 1);
|
609 |
+
} catch (Exception $e) {
|
610 |
+
$this->logger->error($e->getMessage());
|
611 |
+
}
|
612 |
+
|
613 |
+
foreach ($return as $table) {
|
614 |
+
$state = array();
|
615 |
+
|
616 |
+
if ($xcloner_backup_only_wp_tables and !stristr($table['name'],
|
617 |
+
$this->xcloner_settings->get_table_prefix())) {
|
618 |
+
continue;
|
619 |
+
}
|
620 |
+
|
621 |
+
if (isset($database['name']) and $database['name'] == $this->xcloner_settings->get_db_database()) {
|
622 |
+
$state = array('selected' => true);
|
623 |
+
}
|
624 |
+
|
625 |
+
$data[] = array(
|
626 |
+
'id' => $database . "." . $table['name'],
|
627 |
+
'parent' => $database,
|
628 |
+
'text' => $table['name'] . " (" . (int)$table['records'] . ")",
|
629 |
+
'children' => false,
|
630 |
+
'state' => $state,
|
631 |
+
'icon' => plugin_dir_url(dirname(__FILE__)) . "/admin/assets/table-icon.png"
|
632 |
+
);
|
633 |
+
}
|
634 |
+
}
|
635 |
+
|
636 |
+
return $this->send_response($data, 0);
|
637 |
+
}
|
638 |
+
|
639 |
+
/*
|
640 |
+
*
|
641 |
+
* Get schedule by id API
|
642 |
+
*
|
643 |
+
*/
|
644 |
+
public function get_schedule_by_id()
|
645 |
+
{
|
646 |
+
$this->check_access();
|
647 |
+
|
648 |
+
$schedule_id = $this->xcloner_sanitization->sanitize_input_as_int($_GET['id']);
|
649 |
+
$scheduler = $this->xcloner_scheduler;
|
650 |
+
$data = $scheduler->get_schedule_by_id($schedule_id);
|
651 |
+
|
652 |
+
$data['start_at'] = date("Y-m-d H:i",
|
653 |
+
strtotime($data['start_at']) + (get_option('gmt_offset') * HOUR_IN_SECONDS));
|
654 |
+
if (isset($data['backup_params']->diff_start_date) && $data['backup_params']->diff_start_date != "") {
|
655 |
+
$data['backup_params']->diff_start_date = date("Y-m-d", ($data['backup_params']->diff_start_date));
|
656 |
+
}
|
657 |
+
|
658 |
+
return $this->send_response($data);
|
659 |
+
}
|
660 |
+
|
661 |
+
/*
|
662 |
+
*
|
663 |
+
* Get Schedule list API
|
664 |
+
*
|
665 |
+
*/
|
666 |
+
public function get_scheduler_list()
|
667 |
+
{
|
668 |
+
$this->check_access();
|
669 |
+
|
670 |
+
$scheduler = $this->xcloner_scheduler;
|
671 |
+
$data = $scheduler->get_scheduler_list();
|
672 |
+
$return['data'] = array();
|
673 |
+
|
674 |
+
foreach ($data as $res) {
|
675 |
+
$action = "<a href=\"#" . $res->id . "\" class=\"edit\" title='Edit'> <i class=\"material-icons \">edit</i></a>
|
676 |
+
<a href=\"#" . $res->id . "\" class=\"delete\" title='Delete'><i class=\"material-icons \">delete</i></a>";
|
677 |
+
if ($res->status) {
|
678 |
+
$status = '<i class="material-icons active status">timer</i>';
|
679 |
+
} else {
|
680 |
+
$status = '<i class="material-icons status inactive">timer_off</i>';
|
681 |
+
}
|
682 |
+
|
683 |
+
$next_run_time = wp_next_scheduled('xcloner_scheduler_' . $res->id, array($res->id));
|
684 |
+
|
685 |
+
$next_run = date(get_option('date_format') . " " . get_option('time_format'), $next_run_time);
|
686 |
+
|
687 |
+
$remote_storage = $res->remote_storage;
|
688 |
+
|
689 |
+
if (!$next_run_time >= time()) {
|
690 |
+
$next_run = " ";
|
691 |
+
}
|
692 |
+
|
693 |
+
if (trim($next_run)) {
|
694 |
+
$date_text = date(get_option('date_format') . " " . get_option('time_format'),
|
695 |
+
$next_run_time + (get_option('gmt_offset') * HOUR_IN_SECONDS));
|
696 |
+
|
697 |
+
if ($next_run_time >= time()) {
|
698 |
+
$next_run = "in " . human_time_diff($next_run_time, time());
|
699 |
+
} else {
|
700 |
+
$next_run = __("executed", 'xcloner-backup-and-restore');
|
701 |
+
}
|
702 |
+
|
703 |
+
$next_run = "<a href='#' title='" . $date_text . "'>" . $next_run . "</a>";
|
704 |
+
//$next_run .=" ($date_text)";
|
705 |
+
}
|
706 |
+
|
707 |
+
$backup_text = "";
|
708 |
+
$backup_size = "";
|
709 |
+
$backup_time = "";
|
710 |
+
|
711 |
+
if ($res->last_backup) {
|
712 |
+
if ($this->xcloner_file_system->get_storage_filesystem()->has($res->last_backup)) {
|
713 |
+
$metadata = $this->xcloner_file_system->get_storage_filesystem()->getMetadata($res->last_backup);
|
714 |
+
$backup_size = size_format($this->xcloner_file_system->get_backup_size($res->last_backup));
|
715 |
+
$backup_time = date(get_option('date_format') . " " . get_option('time_format'),
|
716 |
+
$metadata['timestamp'] + (get_option('gmt_offset') * HOUR_IN_SECONDS));
|
717 |
+
}
|
718 |
+
|
719 |
+
$backup_text = "<span title='" . $backup_time . "' class='shorten_string'>" . $res->last_backup . " (" . $backup_size . ")</span>";
|
720 |
+
}
|
721 |
+
|
722 |
+
$schedules = wp_get_schedules();
|
723 |
+
|
724 |
+
if (isset($schedules[$res->recurrence])) {
|
725 |
+
$res->recurrence = $schedules[$res->recurrence]['display'];
|
726 |
+
}
|
727 |
+
|
728 |
+
$return['data'][] = array(
|
729 |
+
$res->id,
|
730 |
+
$res->name,
|
731 |
+
$res->recurrence,/*$res->start_at,*/
|
732 |
+
$next_run,
|
733 |
+
$remote_storage,
|
734 |
+
$backup_text,
|
735 |
+
$status,
|
736 |
+
$action
|
737 |
+
);
|
738 |
+
}
|
739 |
+
|
740 |
+
return $this->send_response($return, 0);
|
741 |
+
}
|
742 |
+
|
743 |
+
/*
|
744 |
+
*
|
745 |
+
* Delete Schedule by ID API
|
746 |
+
*
|
747 |
+
*/
|
748 |
+
public function delete_schedule_by_id()
|
749 |
+
{
|
750 |
+
$this->check_access();
|
751 |
+
|
752 |
+
$schedule_id = $this->xcloner_sanitization->sanitize_input_as_int($_GET['id']);
|
753 |
+
$scheduler = $this->xcloner_scheduler;
|
754 |
+
$data['finished'] = $scheduler->delete_schedule_by_id($schedule_id);
|
755 |
+
|
756 |
+
return $this->send_response($data);
|
757 |
+
}
|
758 |
+
|
759 |
+
/*
|
760 |
+
*
|
761 |
+
* Delete backup by name from the storage path
|
762 |
+
*
|
763 |
+
*/
|
764 |
+
public function delete_backup_by_name()
|
765 |
+
{
|
766 |
+
$this->check_access();
|
767 |
+
|
768 |
+
$backup_name = $this->xcloner_sanitization->sanitize_input_as_string($_POST['name']);
|
769 |
+
$storage_selection = $this->xcloner_sanitization->sanitize_input_as_string($_POST['storage_selection']);
|
770 |
+
|
771 |
+
$data['finished'] = $this->xcloner_file_system->delete_backup_by_name($backup_name, $storage_selection);
|
772 |
+
|
773 |
+
return $this->send_response($data);
|
774 |
+
}
|
775 |
+
|
776 |
+
public function list_backup_files()
|
777 |
+
{
|
778 |
+
$this->check_access();
|
779 |
+
|
780 |
+
$backup_parts = array();
|
781 |
+
|
782 |
+
$source_backup_file = $this->xcloner_sanitization->sanitize_input_as_string($_POST['file']);
|
783 |
+
$start = $this->xcloner_sanitization->sanitize_input_as_int($_POST['start']);
|
784 |
+
$return['part'] = $this->xcloner_sanitization->sanitize_input_as_int($_POST['part']);
|
785 |
+
|
786 |
+
$backup_file = $source_backup_file;
|
787 |
+
|
788 |
+
if ($this->xcloner_file_system->is_multipart($backup_file)) {
|
789 |
+
$backup_parts = $this->xcloner_file_system->get_multipart_files($backup_file);
|
790 |
+
$backup_file = $backup_parts[$return['part']];
|
791 |
+
}
|
792 |
+
|
793 |
+
try {
|
794 |
+
$tar = new Tar();
|
795 |
+
$tar->open($this->xcloner_settings->get_xcloner_store_path() . DS . $backup_file, $start);
|
796 |
+
|
797 |
+
$data = $tar->contents(get_option('xcloner_files_to_process_per_request'));
|
798 |
+
} catch (Exception $e) {
|
799 |
+
$return['error'] = true;
|
800 |
+
$return['message'] = $e->getMessage();
|
801 |
+
$this->send_response($return, 0);
|
802 |
+
}
|
803 |
+
|
804 |
+
$return['files'] = array();
|
805 |
+
$return['finished'] = 1;
|
806 |
+
$return['total_size'] = filesize($this->xcloner_settings->get_xcloner_store_path() . DS . $backup_file);
|
807 |
+
$i = 0;
|
808 |
+
|
809 |
+
if (isset($data['extracted_files']) and is_array($data['extracted_files'])) {
|
810 |
+
foreach ($data['extracted_files'] as $file) {
|
811 |
+
$return['files'][$i]['path'] = $file->getPath();
|
812 |
+
$return['files'][$i]['size'] = $file->getSize();
|
813 |
+
$return['files'][$i]['mtime'] = date(get_option('date_format') . " " . get_option('time_format'),
|
814 |
+
$file->getMtime());
|
815 |
+
|
816 |
+
$i++;
|
817 |
+
}
|
818 |
+
}
|
819 |
+
|
820 |
+
if (isset($data['start'])) {
|
821 |
+
$return['start'] = $data['start'];
|
822 |
+
$return['finished'] = 0;
|
823 |
+
} else {
|
824 |
+
if ($this->xcloner_file_system->is_multipart($source_backup_file)) {
|
825 |
+
$return['start'] = 0;
|
826 |
+
|
827 |
+
++$return['part'];
|
828 |
+
|
829 |
+
if ($return['part'] < sizeof($backup_parts)) {
|
830 |
+
$return['finished'] = 0;
|
831 |
+
}
|
832 |
+
|
833 |
+
}
|
834 |
+
}
|
835 |
+
|
836 |
+
$this->send_response($return, 0);
|
837 |
+
}
|
838 |
+
|
839 |
+
/*
|
840 |
+
* Copy remote backup to local storage
|
841 |
+
*/
|
842 |
+
public function copy_backup_remote_to_local()
|
843 |
+
{
|
844 |
+
|
845 |
+
$this->check_access();
|
846 |
+
|
847 |
+
$backup_file = $this->xcloner_sanitization->sanitize_input_as_string($_POST['file']);
|
848 |
+
$storage_type = $this->xcloner_sanitization->sanitize_input_as_string($_POST['storage_type']);
|
849 |
+
|
850 |
+
$xcloner_remote_storage = $this->get_xcloner_container()->get_xcloner_remote_storage();
|
851 |
+
|
852 |
+
$return = array();
|
853 |
+
|
854 |
+
try {
|
855 |
+
if (method_exists($xcloner_remote_storage, "copy_backup_remote_to_local")) {
|
856 |
+
$return = call_user_func_array(array(
|
857 |
+
$xcloner_remote_storage,
|
858 |
+
"copy_backup_remote_to_local"
|
859 |
+
), array($backup_file, $storage_type));
|
860 |
+
}
|
861 |
+
} catch (Exception $e) {
|
862 |
+
|
863 |
+
$return['error'] = 1;
|
864 |
+
$return['message'] = $e->getMessage();
|
865 |
+
}
|
866 |
+
|
867 |
+
if (!$return) {
|
868 |
+
$return['error'] = 1;
|
869 |
+
$return['message'] = "Upload failed, please check the error log for more information!";
|
870 |
+
}
|
871 |
+
|
872 |
+
|
873 |
+
$this->send_response($return, 0);
|
874 |
+
|
875 |
+
}
|
876 |
+
|
877 |
+
/*
|
878 |
+
*
|
879 |
+
* Upload backup to remote API
|
880 |
+
*
|
881 |
+
*/
|
882 |
+
public function upload_backup_to_remote()
|
883 |
+
{
|
884 |
+
$this->check_access();
|
885 |
+
|
886 |
+
$backup_file = $this->xcloner_sanitization->sanitize_input_as_string($_POST['file']);
|
887 |
+
$storage_type = $this->xcloner_sanitization->sanitize_input_as_string($_POST['storage_type']);
|
888 |
+
|
889 |
+
$xcloner_remote_storage = $this->get_xcloner_container()->get_xcloner_remote_storage();
|
890 |
+
|
891 |
+
$return = array();
|
892 |
+
|
893 |
+
try {
|
894 |
+
if (method_exists($xcloner_remote_storage, "upload_backup_to_storage")) {
|
895 |
+
$return = call_user_func_array(array(
|
896 |
+
$xcloner_remote_storage,
|
897 |
+
"upload_backup_to_storage"
|
898 |
+
), array($backup_file, $storage_type));
|
899 |
+
}
|
900 |
+
} catch (Exception $e) {
|
901 |
+
|
902 |
+
$return['error'] = 1;
|
903 |
+
$return['message'] = $e->getMessage();
|
904 |
+
}
|
905 |
+
|
906 |
+
if (!$return) {
|
907 |
+
$return['error'] = 1;
|
908 |
+
$return['message'] = "Upload failed, please check the error log for more information!";
|
909 |
+
}
|
910 |
+
|
911 |
+
|
912 |
+
$this->send_response($return, 0);
|
913 |
+
|
914 |
+
}
|
915 |
+
|
916 |
+
/*
|
917 |
+
*
|
918 |
+
* Remote Storage Status Save
|
919 |
+
*
|
920 |
+
*/
|
921 |
+
public function remote_storage_save_status()
|
922 |
+
{
|
923 |
+
$this->check_access();
|
924 |
+
|
925 |
+
$xcloner_remote_storage = $this->get_xcloner_container()->get_xcloner_remote_storage();
|
926 |
+
|
927 |
+
$return['finished'] = $xcloner_remote_storage->change_storage_status($_POST['id'], $_POST['value']);
|
928 |
+
|
929 |
+
$this->send_response($return, 0);
|
930 |
+
}
|
931 |
+
|
932 |
+
|
933 |
+
public function download_restore_script()
|
934 |
+
{
|
935 |
+
$this->check_access();
|
936 |
+
|
937 |
+
@ob_end_clean();
|
938 |
+
|
939 |
+
$adapter = new Local(dirname(__DIR__), LOCK_EX, 'SKIP_LINKS');
|
940 |
+
$xcloner_plugin_filesystem = new Filesystem($adapter, new Config([
|
941 |
+
'disable_asserts' => true,
|
942 |
+
]));
|
943 |
+
|
944 |
+
/* Generate PHAR FILE
|
945 |
+
$file = 'restore/vendor.built';
|
946 |
+
|
947 |
+
if(file_exists($file))
|
948 |
+
unlink($file);
|
949 |
+
$phar2 = new Phar($file, 0, 'vendor.phar');
|
950 |
+
|
951 |
+
// add all files in the project, only include php files
|
952 |
+
$phar2->buildFromIterator(
|
953 |
+
new RecursiveIteratorIterator(
|
954 |
+
new RecursiveDirectoryIterator(__DIR__.'/vendor/')),
|
955 |
+
__DIR__);
|
956 |
+
|
957 |
+
$phar2->setStub($phar2->createDefaultStub('vendor/autoload.php', 'vendor/autoload.php'));
|
958 |
+
* */
|
959 |
+
|
960 |
+
$tmp_file = $this->xcloner_settings->get_xcloner_tmp_path() . DS . "xcloner-restore.tgz";
|
961 |
+
|
962 |
+
$tar = new Tar();
|
963 |
+
$tar->create($tmp_file);
|
964 |
+
|
965 |
+
$tar->addFile(dirname(__DIR__) . "/restore/vendor.build.txt", "vendor.phar");
|
966 |
+
//$tar->addFile(dirname(__DIR__)."/restore/vendor.tgz", "vendor.tgz");
|
967 |
+
|
968 |
+
$files = $xcloner_plugin_filesystem->listContents("vendor/", true);
|
969 |
+
foreach ($files as $file) {
|
970 |
+
$tar->addFile(dirname(__DIR__) . DS . $file['path'], $file['path']);
|
971 |
+
}
|
972 |
+
|
973 |
+
$content = file_get_contents(dirname(__DIR__) . "/restore/xcloner_restore.php");
|
974 |
+
$content = str_replace("define('AUTH_KEY', '');", "define('AUTH_KEY', '" . md5(AUTH_KEY) . "');", $content);
|
975 |
+
|
976 |
+
$tar->addData("xcloner_restore.php", $content);
|
977 |
+
|
978 |
+
$tar->close();
|
979 |
+
|
980 |
+
if (file_exists($tmp_file)) {
|
981 |
+
header('Content-Description: File Transfer');
|
982 |
+
header('Content-Type: application/octet-stream');
|
983 |
+
header('Content-Disposition: attachment; filename="' . basename($tmp_file) . '"');
|
984 |
+
header('Expires: 0');
|
985 |
+
header('Cache-Control: must-revalidate');
|
986 |
+
header('Pragma: public');
|
987 |
+
header('Content-Length: ' . filesize($tmp_file));
|
988 |
+
readfile($tmp_file);
|
989 |
+
|
990 |
+
}
|
991 |
+
|
992 |
+
@unlink($tmp_file);
|
993 |
+
exit;
|
994 |
+
}
|
995 |
+
|
996 |
+
/*
|
997 |
+
*
|
998 |
+
* Download backup by Name from the Storage Path
|
999 |
+
*
|
1000 |
+
*/
|
1001 |
+
public function download_backup_by_name()
|
1002 |
+
{
|
1003 |
+
$this->check_access();
|
1004 |
+
|
1005 |
+
@ob_end_clean();
|
1006 |
+
|
1007 |
+
$backup_name = $this->xcloner_sanitization->sanitize_input_as_string($_GET['name']);
|
1008 |
+
|
1009 |
+
|
1010 |
+
$metadata = $this->xcloner_file_system->get_storage_filesystem()->getMetadata($backup_name);
|
1011 |
+
$read_stream = $this->xcloner_file_system->get_storage_filesystem()->readStream($backup_name);
|
1012 |
+
|
1013 |
+
|
1014 |
+
header('Pragma: public');
|
1015 |
+
header('Expires: 0');
|
1016 |
+
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
|
1017 |
+
header('Cache-Control: private', false);
|
1018 |
+
header('Content-Transfer-Encoding: binary');
|
1019 |
+
header('Content-Disposition: attachment; filename="' . $metadata['path'] . '";');
|
1020 |
+
header('Content-Type: application/octet-stream');
|
1021 |
+
header('Content-Length: ' . $metadata['size']);
|
1022 |
+
|
1023 |
+
@ob_end_clean();
|
1024 |
+
|
1025 |
+
$chunkSize = 1024 * 1024;
|
1026 |
+
while (!feof($read_stream)) {
|
1027 |
+
$buffer = fread($read_stream, $chunkSize);
|
1028 |
+
echo $buffer;
|
1029 |
+
}
|
1030 |
+
fclose($read_stream);
|
1031 |
+
exit;
|
1032 |
+
|
1033 |
+
}
|
1034 |
+
|
1035 |
+
/*
|
1036 |
+
* Restore upload backup
|
1037 |
+
*/
|
1038 |
+
public function restore_upload_backup()
|
1039 |
+
{
|
1040 |
+
$this->check_access();
|
1041 |
+
|
1042 |
+
$return['part'] = 0;
|
1043 |
+
$return['total_parts'] = 0;
|
1044 |
+
$return['uploaded_size'] = 0;
|
1045 |
+
$is_multipart = 0;
|
1046 |
+
|
1047 |
+
$file = $this->xcloner_sanitization->sanitize_input_as_string($_POST['file']);
|
1048 |
+
$hash = $this->xcloner_sanitization->sanitize_input_as_string($_POST['hash']);
|
1049 |
+
|
1050 |
+
if (isset($_POST['part'])) {
|
1051 |
+
$return['part'] = $this->xcloner_sanitization->sanitize_input_as_int($_POST['part']);
|
1052 |
+
}
|
1053 |
+
|
1054 |
+
if (isset($_POST['uploaded_size'])) {
|
1055 |
+
$return['uploaded_size'] = $this->xcloner_sanitization->sanitize_input_as_int($_POST['uploaded_size']);
|
1056 |
+
}
|
1057 |
+
|
1058 |
+
$start = $this->xcloner_sanitization->sanitize_input_as_string($_POST['start']);
|
1059 |
+
$target_url = $this->xcloner_sanitization->sanitize_input_as_string($_POST['target_url']);
|
1060 |
+
|
1061 |
+
$return['total_size'] = $this->xcloner_file_system->get_backup_size($file);
|
1062 |
+
|
1063 |
+
if ($this->xcloner_file_system->is_multipart($file)) {
|
1064 |
+
$backup_parts = $this->xcloner_file_system->get_multipart_files($file);
|
1065 |
+
|
1066 |
+
$return['total_parts'] = sizeof($backup_parts) + 1;
|
1067 |
+
|
1068 |
+
if ($return['part'] and isset($backup_parts[$return['part'] - 1])) {
|
1069 |
+
$file = $backup_parts[$return['part'] - 1];
|
1070 |
+
}
|
1071 |
+
|
1072 |
+
$is_multipart = 1;
|
1073 |
+
}
|
1074 |
+
|
1075 |
+
try {
|
1076 |
+
|
1077 |
+
$xcloner_file_transfer = $this->get_xcloner_container()->get_xcloner_file_transfer();
|
1078 |
+
$xcloner_file_transfer->set_target($target_url);
|
1079 |
+
$return['start'] = $xcloner_file_transfer->transfer_file($file, $start, $hash);
|
1080 |
+
|
1081 |
+
} catch (Exception $e) {
|
1082 |
+
|
1083 |
+
$return = array();
|
1084 |
+
$return['error'] = true;
|
1085 |
+
$return['status'] = 500;
|
1086 |
+
$return['message'] = "CURL communication error with the restore host. " . $e->getMessage();
|
1087 |
+
$this->send_response($return, 0);
|
1088 |
+
|
1089 |
+
}
|
1090 |
+
|
1091 |
+
$return['status'] = 200;
|
1092 |
+
|
1093 |
+
//we have finished the upload
|
1094 |
+
if (!$return['start'] and $is_multipart) {
|
1095 |
+
$return['part']++;
|
1096 |
+
$return['uploaded_size'] += $this->xcloner_file_system->get_storage_filesystem()->getSize($file);
|
1097 |
+
}
|
1098 |
+
|
1099 |
+
$this->send_response($return, 0);
|
1100 |
+
}
|
1101 |
+
|
1102 |
+
/*
|
1103 |
+
* Restore backup
|
1104 |
+
*/
|
1105 |
+
public function restore_backup()
|
1106 |
+
{
|
1107 |
+
$this->check_access();
|
1108 |
+
|
1109 |
+
define("XCLONER_PLUGIN_ACCESS", 1);
|
1110 |
+
include_once(dirname(__DIR__) . DS . "restore" . DS . "xcloner_restore.php");
|
1111 |
+
|
1112 |
+
return;
|
1113 |
+
}
|
1114 |
+
|
1115 |
+
/*
|
1116 |
+
*
|
1117 |
+
* Send the json response back
|
1118 |
+
*
|
1119 |
+
*/
|
1120 |
+
private function send_response($data, $attach_hash = 1)
|
1121 |
+
{
|
1122 |
+
|
1123 |
+
if ($attach_hash and null !== $this->xcloner_settings->get_hash()) {
|
1124 |
+
$data['hash'] = $this->xcloner_settings->get_hash();
|
1125 |
+
}
|
1126 |
+
|
1127 |
+
if (ob_get_length()) {
|
1128 |
+
ob_clean();
|
1129 |
+
}
|
1130 |
+
wp_send_json($data);
|
1131 |
+
|
1132 |
+
die();
|
1133 |
+
}
|
1134 |
}
|
includes/class-xcloner-archive.php
CHANGED
@@ -1,608 +1,721 @@
|
|
1 |
<?php
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
use splitbrain\PHPArchive\Tar;
|
3 |
use splitbrain\PHPArchive\Archive;
|
4 |
use splitbrain\PHPArchive\FileInfo;
|
5 |
|
|
|
|
|
|
|
|
|
6 |
class Xcloner_Archive extends Tar
|
7 |
{
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
583 |
-
|
584 |
-
|
585 |
-
|
586 |
-
|
587 |
-
|
588 |
-
|
589 |
-
|
590 |
-
|
591 |
-
|
592 |
-
|
593 |
-
|
594 |
-
|
595 |
-
|
596 |
-
|
597 |
-
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
-
|
603 |
-
|
604 |
-
|
605 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
606 |
/**
|
607 |
* Open a TAR archive and put the file cursor at the end for data appending
|
608 |
*
|
@@ -640,21 +753,22 @@ class Xcloner_Archive extends Tar
|
|
640 |
$this->backup_archive->closed = false;
|
641 |
}
|
642 |
*/
|
643 |
-
|
644 |
-
|
645 |
* Append data to a file to the current TAR archive using an existing file in the filesystem
|
646 |
*
|
647 |
-
* @param string
|
648 |
-
* @param int
|
649 |
-
* @param int
|
650 |
-
* @param string|FileInfo $fileinfo either the name to us in archive (string) or a FileInfo oject with
|
|
|
651 |
* @throws ArchiveIOException
|
652 |
*/
|
653 |
/*
|
654 |
* public function appendFileData($file, $fileinfo = '', $start = 0, $limit = 0)
|
655 |
{
|
656 |
$end = $start+($limit*512);
|
657 |
-
|
658 |
//check to see if we are at the begining of writing the file
|
659 |
if(!$start)
|
660 |
{
|
@@ -662,15 +776,15 @@ class Xcloner_Archive extends Tar
|
|
662 |
$fileinfo = FileInfo::fromPath($file, $fileinfo);
|
663 |
}
|
664 |
}
|
665 |
-
|
666 |
if ($this->closed) {
|
667 |
throw new ArchiveIOException('Archive has been closed, files can no longer be added');
|
668 |
}
|
669 |
|
670 |
$fp = fopen($file, 'rb');
|
671 |
-
|
672 |
fseek($fp, $start);
|
673 |
-
|
674 |
if (!$fp) {
|
675 |
throw new ArchiveIOException('Could not open file for reading: '.$file);
|
676 |
}
|
@@ -678,7 +792,7 @@ class Xcloner_Archive extends Tar
|
|
678 |
// create file header
|
679 |
if(!$start)
|
680 |
$this->backup_archive->writeFileHeader($fileinfo);
|
681 |
-
|
682 |
$bytes = 0;
|
683 |
// write data
|
684 |
while ($end >=ftell($fp) and !feof($fp) ) {
|
@@ -692,33 +806,33 @@ class Xcloner_Archive extends Tar
|
|
692 |
$packed = pack("a512", $data);
|
693 |
$bytes += $this->backup_archive->writebytes($packed);
|
694 |
}
|
695 |
-
|
696 |
-
|
697 |
-
|
698 |
//if we are not at the end of file, we return the current position for incremental writing
|
699 |
if(!feof($fp))
|
700 |
$last_position = ftell($fp);
|
701 |
else
|
702 |
$last_position = -1;
|
703 |
-
|
704 |
fclose($fp);
|
705 |
-
|
706 |
return $last_position;
|
707 |
}*/
|
708 |
-
|
709 |
/**
|
710 |
* Adds a file to a TAR archive by appending it's data
|
711 |
*
|
712 |
-
* @param string $archive
|
713 |
-
* @param string $file
|
714 |
-
* @param string $start
|
715 |
* @throws ArchiveIOException
|
716 |
*/
|
717 |
-
|
718 |
-
|
719 |
-
|
720 |
-
|
721 |
-
|
722 |
-
|
723 |
|
724 |
}
|
1 |
<?php
|
2 |
+
/**
|
3 |
+
* XCloner - Backup and Restore backup plugin for Wordpress
|
4 |
+
*
|
5 |
+
* class-xcloner-archive.php
|
6 |
+
* @author Liuta Ovidiu <info@thinkovi.com>
|
7 |
+
*
|
8 |
+
* This program is free software; you can redistribute it and/or modify
|
9 |
+
* it under the terms of the GNU General Public License as published by
|
10 |
+
* the Free Software Foundation; either version 2 of the License, or
|
11 |
+
* (at your option) any later version.
|
12 |
+
*
|
13 |
+
* This program is distributed in the hope that it will be useful,
|
14 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16 |
+
* GNU General Public License for more details.
|
17 |
+
*
|
18 |
+
* You should have received a copy of the GNU General Public License
|
19 |
+
* along with this program; if not, write to the Free Software
|
20 |
+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
21 |
+
* MA 02110-1301, USA.
|
22 |
+
*
|
23 |
+
* @link https://github.com/ovidiul/XCloner-Wordpress
|
24 |
+
*
|
25 |
+
* @modified 7/31/18 3:10 PM
|
26 |
+
*
|
27 |
+
*/
|
28 |
+
|
29 |
use splitbrain\PHPArchive\Tar;
|
30 |
use splitbrain\PHPArchive\Archive;
|
31 |
use splitbrain\PHPArchive\FileInfo;
|
32 |
|
33 |
+
/**
|
34 |
+
* Class responsible for adding files to Tar
|
35 |
+
* Class Xcloner_Archive
|
36 |
+
*/
|
37 |
class Xcloner_Archive extends Tar
|
38 |
{
|
39 |
+
/**
|
40 |
+
* Process file size per API request
|
41 |
+
* @var float|int
|
42 |
+
*/
|
43 |
+
private $file_size_per_request_limit = 52428800; //50MB = 52428800; 1MB = 1048576
|
44 |
+
/**
|
45 |
+
* Files count to process per API request
|
46 |
+
* @var int
|
47 |
+
*/
|
48 |
+
private $files_to_process_per_request = 250; //block of 512 bytes
|
49 |
+
/**
|
50 |
+
* Compression level, 0-uncompressed, 9-maximum compression
|
51 |
+
* @var int
|
52 |
+
*/
|
53 |
+
private $compression_level = 0; //0-9 , 0 uncompressed
|
54 |
+
/**
|
55 |
+
* Split backup size limit
|
56 |
+
* Create a new backup archive file once the set size is reached
|
57 |
+
* @var float|int
|
58 |
+
*/
|
59 |
+
private $xcloner_split_backup_limit = 2048; //2048MB
|
60 |
+
/**
|
61 |
+
* Number of processed bytes
|
62 |
+
* @var int
|
63 |
+
*/
|
64 |
+
private $processed_size_bytes = 0;
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Archive name
|
68 |
+
* @var string
|
69 |
+
*/
|
70 |
+
private $archive_name;
|
71 |
+
/**
|
72 |
+
* @var Tar
|
73 |
+
*/
|
74 |
+
private $backup_archive;
|
75 |
+
/**
|
76 |
+
* @var Xcloner_File_System
|
77 |
+
*/
|
78 |
+
private $filesystem;
|
79 |
+
/**
|
80 |
+
* @var Xcloner_Logger
|
81 |
+
*/
|
82 |
+
private $logger;
|
83 |
+
/**
|
84 |
+
* @var Xcloner_Settings
|
85 |
+
*/
|
86 |
+
private $xcloner_settings;
|
87 |
+
|
88 |
+
/**
|
89 |
+
* [__construct description]
|
90 |
+
* @param Xcloner $xcloner_container XCloner Container
|
91 |
+
* @param string $archive_name Achive Name
|
92 |
+
*/
|
93 |
+
public function __construct(Xcloner $xcloner_container, $archive_name = "")
|
94 |
+
{
|
95 |
+
$this->filesystem = $xcloner_container->get_xcloner_filesystem();
|
96 |
+
$this->logger = $xcloner_container->get_xcloner_logger()->withName("xcloner_archive");
|
97 |
+
$this->xcloner_settings = $xcloner_container->get_xcloner_settings();
|
98 |
+
|
99 |
+
if ($value = $this->xcloner_settings->get_xcloner_option('xcloner_size_limit_per_request')) {
|
100 |
+
$this->file_size_per_request_limit = $value * 1024 * 1024;
|
101 |
+
} //MB
|
102 |
+
|
103 |
+
if ($value = $this->xcloner_settings->get_xcloner_option('xcloner_files_to_process_per_request')) {
|
104 |
+
$this->files_to_process_per_request = $value;
|
105 |
+
}
|
106 |
+
|
107 |
+
if ($value = get_option('xcloner_backup_compression_level')) {
|
108 |
+
$this->compression_level = $value;
|
109 |
+
}
|
110 |
+
|
111 |
+
if ($value = get_option('xcloner_split_backup_limit')) {
|
112 |
+
$this->xcloner_split_backup_limit = $value;
|
113 |
+
}
|
114 |
+
|
115 |
+
$this->xcloner_split_backup_limit = $this->xcloner_split_backup_limit * 1024 * 1024; //transform to bytes
|
116 |
+
|
117 |
+
if (isset($archive_name) && $archive_name) {
|
118 |
+
$this->set_archive_name($archive_name);
|
119 |
+
}
|
120 |
+
}
|
121 |
+
|
122 |
+
/*
|
123 |
+
* Rename backup archive
|
124 |
+
*
|
125 |
+
* @param string $old_name
|
126 |
+
* @param string $new_name
|
127 |
+
*
|
128 |
+
*/
|
129 |
+
public function rename_archive($old_name, $new_name)
|
130 |
+
{
|
131 |
+
$this->logger->info(sprintf("Renaming backup archive %s to %s", $old_name, $new_name));
|
132 |
+
$storage_filesystem = $this->filesystem->get_storage_filesystem();
|
133 |
+
$storage_filesystem->rename($old_name, $new_name);
|
134 |
+
}
|
135 |
+
|
136 |
+
/*
|
137 |
+
*
|
138 |
+
* Set the backup archive name
|
139 |
+
*
|
140 |
+
*/
|
141 |
+
public function set_archive_name($name = "", $part = 0)
|
142 |
+
{
|
143 |
+
|
144 |
+
$this->archive_name = $this->filesystem->process_backup_name($name);
|
145 |
+
|
146 |
+
if ($diff_timestamp_start = $this->filesystem->get_diff_timestamp_start()) {
|
147 |
+
//$this->archive_name = $this->archive_name."-diff-".date("Y-m-d_H-i",$diff_timestamp_start);
|
148 |
+
$new_name = $this->archive_name;
|
149 |
+
|
150 |
+
if (!stristr($new_name, "-diff")) {
|
151 |
+
$new_name = $this->archive_name . "-diff" . date("Y-m-d_H-i", $diff_timestamp_start);
|
152 |
+
}
|
153 |
+
|
154 |
+
$this->archive_name = $new_name;
|
155 |
+
|
156 |
+
}
|
157 |
+
|
158 |
+
if (isset($part) and $part) {
|
159 |
+
$new_name = preg_replace('/-part(\d*)/', "-part" . $part, $this->archive_name);
|
160 |
+
if (!stristr($new_name, "-part")) {
|
161 |
+
$new_name = $this->archive_name . "-part" . $part;
|
162 |
+
}
|
163 |
+
|
164 |
+
$this->archive_name = $new_name;
|
165 |
+
}
|
166 |
+
|
167 |
+
return $this;
|
168 |
+
}
|
169 |
+
|
170 |
+
/*
|
171 |
+
*
|
172 |
+
* Returns the backup archive name
|
173 |
+
*
|
174 |
+
* @return string archive name
|
175 |
+
*/
|
176 |
+
public function get_archive_name()
|
177 |
+
{
|
178 |
+
return $this->archive_name;
|
179 |
+
}
|
180 |
+
|
181 |
+
/*
|
182 |
+
*
|
183 |
+
* Returns the multipart naming for the backup archive
|
184 |
+
*
|
185 |
+
* @return string multi-part backup name
|
186 |
+
*/
|
187 |
+
public function get_archive_name_multipart()
|
188 |
+
{
|
189 |
+
$new_name = preg_replace('/-part(\d*)/', "", $this->archive_name);
|
190 |
+
return $new_name . "-multipart" . $this->xcloner_settings->get_backup_extension_name(".csv");
|
191 |
+
}
|
192 |
+
|
193 |
+
/*
|
194 |
+
*
|
195 |
+
* Returns the full backup name including extension
|
196 |
+
*
|
197 |
+
*/
|
198 |
+
public function get_archive_name_with_extension()
|
199 |
+
{
|
200 |
+
return $this->archive_name . $this->xcloner_settings->get_backup_extension_name();
|
201 |
+
}
|
202 |
+
|
203 |
+
/*
|
204 |
+
*
|
205 |
+
* Send notification error by E-Mail
|
206 |
+
*
|
207 |
+
* @param $to
|
208 |
+
* @param $from
|
209 |
+
* @param $subject
|
210 |
+
* @param $backup_name
|
211 |
+
* @param $params
|
212 |
+
* @param $error_message
|
213 |
+
*
|
214 |
+
* @return bool
|
215 |
+
*/
|
216 |
+
public function send_notification_error($to, $from, $subject, $backup_name, $params, $error_message)
|
217 |
+
{
|
218 |
+
|
219 |
+
$body = "";
|
220 |
+
$body .= sprintf(__("Backup Site Url: %s"), get_site_url());
|
221 |
+
$body .= "<br /><>";
|
222 |
+
|
223 |
+
$body .= sprintf(__("Error Message: %s"), $error_message);
|
224 |
+
|
225 |
+
$this->logger->info(sprintf("Sending backup error notification to %s", $to));
|
226 |
+
|
227 |
+
$admin_email = get_option("admin_email");
|
228 |
+
|
229 |
+
$headers = array('Content-Type: text/html; charset=UTF-8');
|
230 |
+
|
231 |
+
if ($admin_email and $from) {
|
232 |
+
$headers[] = 'From: ' . $from . ' <' . $admin_email . '>';
|
233 |
+
}
|
234 |
+
|
235 |
+
$return = wp_mail($to, $subject, $body, $headers);
|
236 |
+
|
237 |
+
return $return;
|
238 |
+
}
|
239 |
+
|
240 |
+
/*
|
241 |
+
*
|
242 |
+
* Send backup archive notfication by E-Mail
|
243 |
+
*
|
244 |
+
* @param $to
|
245 |
+
* @param $from
|
246 |
+
* @param $subject
|
247 |
+
* @param $backup_name
|
248 |
+
* @param $params
|
249 |
+
* @param string $error_message
|
250 |
+
* @param array $additional
|
251 |
+
*
|
252 |
+
* @return bool
|
253 |
+
*/
|
254 |
+
public function send_notification(
|
255 |
+
$to,
|
256 |
+
$from,
|
257 |
+
$subject,
|
258 |
+
$backup_name,
|
259 |
+
$params,
|
260 |
+
$error_message = "",
|
261 |
+
$additional = array()
|
262 |
+
) {
|
263 |
+
if (!$from) {
|
264 |
+
$from = "XCloner Backup";
|
265 |
+
}
|
266 |
+
|
267 |
+
if (($error_message)) {
|
268 |
+
return $this->send_notification_error($to, $from, $subject, $backup_name, $params, $error_message);
|
269 |
+
}
|
270 |
+
|
271 |
+
$params = (array)$params;
|
272 |
+
|
273 |
+
if (!$subject) {
|
274 |
+
$subject = sprintf(__("New backup generated %s"), $backup_name);
|
275 |
+
}
|
276 |
+
|
277 |
+
$body = sprintf(__("Generated Backup Size: %s"), size_format($this->filesystem->get_backup_size($backup_name)));
|
278 |
+
$body .= "<br /><br />";
|
279 |
+
|
280 |
+
if (isset($additional['lines_total'])) {
|
281 |
+
$body .= sprintf(__("Total files added: %s"), $additional['lines_total']);
|
282 |
+
$body .= "<br /><br />";
|
283 |
+
}
|
284 |
+
|
285 |
+
$backup_parts = $this->filesystem->get_multipart_files($backup_name);
|
286 |
+
|
287 |
+
if (!$backups_counter = sizeof($backup_parts)) {
|
288 |
+
$backups_counter = 1;
|
289 |
+
}
|
290 |
+
|
291 |
+
$body .= sprintf(__("Backup Parts: %s"), $backups_counter);
|
292 |
+
$body .= "<br />";
|
293 |
+
|
294 |
+
if (sizeof($backup_parts)) {
|
295 |
+
$body .= implode("<br />", $backup_parts);
|
296 |
+
$body .= "<br />";
|
297 |
+
}
|
298 |
+
|
299 |
+
$body .= "<br />";
|
300 |
+
|
301 |
+
$body .= sprintf(__("Backup Site Url: %s"), get_site_url());
|
302 |
+
$body .= "<br />";
|
303 |
+
|
304 |
+
if (isset($params['backup_params']->backup_comments)) {
|
305 |
+
$body .= __("Backup Comments: ") . $params['backup_params']->backup_comments;
|
306 |
+
$body .= "<br /><br />";
|
307 |
+
}
|
308 |
+
|
309 |
+
if ($this->xcloner_settings->get_xcloner_option('xcloner_enable_log')) {
|
310 |
+
$body .= __("Latest 50 Log Lines: ") . "<br />" . implode("<br />\n",
|
311 |
+
$this->logger->getLastDebugLines(50));
|
312 |
+
}
|
313 |
+
|
314 |
+
$attachments = $this->filesystem->get_backup_attachments();
|
315 |
+
|
316 |
+
$attachments_archive = $this->xcloner_settings->get_xcloner_tmp_path() . DS . "info.tgz";
|
317 |
+
|
318 |
+
$tar = new Tar();
|
319 |
+
$tar->create($attachments_archive);
|
320 |
+
|
321 |
+
foreach ($attachments as $key => $file) {
|
322 |
+
$tar->addFile($file, basename($file));
|
323 |
+
}
|
324 |
+
$tar->close();
|
325 |
+
|
326 |
+
$this->logger->info(sprintf("Sending backup notification to %s", $to));
|
327 |
+
|
328 |
+
$admin_email = get_option("admin_email");
|
329 |
+
|
330 |
+
$headers = array('Content-Type: text/html; charset=UTF-8', 'From: ' . $from . ' <' . $admin_email . '>');
|
331 |
+
|
332 |
+
$return = wp_mail($to, $subject, $body, $headers, array($attachments_archive));
|
333 |
+
|
334 |
+
return $return;
|
335 |
+
}
|
336 |
+
|
337 |
+
/*
|
338 |
+
*
|
339 |
+
* Incremental Backup method
|
340 |
+
*
|
341 |
+
*/
|
342 |
+
public function start_incremental_backup($backup_params, $extra_params, $init)
|
343 |
+
{
|
344 |
+
$return = array();
|
345 |
+
|
346 |
+
if (!isset($extra_params['backup_part'])) {
|
347 |
+
$extra_params['backup_part'] = 0;
|
348 |
+
}
|
349 |
+
|
350 |
+
$return['extra']['backup_part'] = $extra_params['backup_part'];
|
351 |
+
|
352 |
+
if (isset($extra_params['backup_archive_name'])) {
|
353 |
+
$this->set_archive_name($extra_params['backup_archive_name'], $return['extra']['backup_part']);
|
354 |
+
} else {
|
355 |
+
$this->set_archive_name($backup_params['backup_name']);
|
356 |
+
}
|
357 |
+
|
358 |
+
if (!$this->get_archive_name()) {
|
359 |
+
$this->set_archive_name();
|
360 |
+
}
|
361 |
+
|
362 |
+
$this->backup_archive = new Tar();
|
363 |
+
$this->backup_archive->setCompression($this->compression_level);
|
364 |
+
|
365 |
+
$archive_info = $this->filesystem->get_storage_path_file_info($this->get_archive_name_with_extension());
|
366 |
+
|
367 |
+
if ($init) {
|
368 |
+
$this->logger->info(sprintf(__("Initializing the backup archive %s"), $this->get_archive_name()));
|
369 |
+
|
370 |
+
$this->backup_archive->create($archive_info->getPath() . DS . $archive_info->getFilename());
|
371 |
+
|
372 |
+
$return['extra']['backup_init'] = 1;
|
373 |
+
|
374 |
+
} else {
|
375 |
+
$this->logger->info(sprintf(__("Opening for append the backup archive %s"), $this->get_archive_name()));
|
376 |
+
|
377 |
+
$this->backup_archive->openForAppend($archive_info->getPath() . DS . $archive_info->getFilename());
|
378 |
+
|
379 |
+
$return['extra']['backup_init'] = 0;
|
380 |
+
|
381 |
+
}
|
382 |
+
|
383 |
+
$return['extra']['backup_archive_name'] = $this->get_archive_name();
|
384 |
+
$return['extra']['backup_archive_name_full'] = $this->get_archive_name_with_extension();
|
385 |
+
|
386 |
+
if (!isset($extra_params['start_at_line'])) {
|
387 |
+
$extra_params['start_at_line'] = 0;
|
388 |
+
}
|
389 |
+
|
390 |
+
if (!isset($extra_params['start_at_byte'])) {
|
391 |
+
$extra_params['start_at_byte'] = 0;
|
392 |
+
}
|
393 |
+
|
394 |
+
if (!$this->filesystem->get_tmp_filesystem()->has($this->filesystem->get_included_files_handler())) {
|
395 |
+
$this->logger->error(sprintf("Missing the includes file handler %s, aborting...",
|
396 |
+
$this->filesystem->get_included_files_handler()));
|
397 |
+
|
398 |
+
$return['finished'] = 1;
|
399 |
+
return $return;
|
400 |
+
}
|
401 |
+
|
402 |
+
$included_files_handler = $this->filesystem->get_included_files_handler(1);
|
403 |
+
|
404 |
+
$file = new SplFileObject($included_files_handler);
|
405 |
+
|
406 |
+
$file->seek(PHP_INT_MAX);
|
407 |
+
|
408 |
+
$return['extra']['lines_total'] = ($file->key() - 1);
|
409 |
+
|
410 |
+
//we skip the first CSV line with headers
|
411 |
+
if (!$extra_params['start_at_line']) {
|
412 |
+
$file->seek(1);
|
413 |
+
} else {
|
414 |
+
$file->seek($extra_params['start_at_line'] + 1);
|
415 |
+
}
|
416 |
+
|
417 |
+
$this->processed_size_bytes = 0;
|
418 |
+
|
419 |
+
$counter = 0;
|
420 |
+
|
421 |
+
$start_byte = $extra_params['start_at_byte'];
|
422 |
+
|
423 |
+
$byte_limit = 0;
|
424 |
+
|
425 |
+
while (!$file->eof() and $counter <= $this->files_to_process_per_request) {
|
426 |
+
$current_line_str = $file->current();
|
427 |
+
|
428 |
+
$line = str_getcsv($current_line_str);
|
429 |
+
|
430 |
+
$relative_path = stripslashes($line[0]);
|
431 |
+
|
432 |
+
$start_filesystem = "start_filesystem";
|
433 |
+
|
434 |
+
if (isset($line[4])) {
|
435 |
+
$start_filesystem = $line[4];
|
436 |
+
}
|
437 |
+
|
438 |
+
//$adapter = $this->filesystem->get_adapter($start_filesystem);
|
439 |
+
|
440 |
+
if (!$relative_path || !$this->filesystem->get_filesystem($start_filesystem)->has($relative_path)) {
|
441 |
+
if ($relative_path != "") {
|
442 |
+
$this->logger->error(sprintf("Could not add file %b to backup archive, file not found",
|
443 |
+
$relative_path));
|
444 |
+
}
|
445 |
+
|
446 |
+
$extra_params['start_at_line']++;
|
447 |
+
$file->next();
|
448 |
+
continue;
|
449 |
+
}
|
450 |
+
|
451 |
+
$file_info = $this->filesystem->get_filesystem($start_filesystem)->getMetadata($relative_path);
|
452 |
+
|
453 |
+
if (!isset($file_info['size'])) {
|
454 |
+
$file_info['size'] = 0;
|
455 |
+
}
|
456 |
+
|
457 |
+
if ($start_filesystem == "tmp_filesystem") {
|
458 |
+
$file_info['archive_prefix_path'] = $this->xcloner_settings->get_xcloner_tmp_path_suffix();
|
459 |
+
}
|
460 |
+
|
461 |
+
$byte_limit = (int)$this->file_size_per_request_limit / 512;
|
462 |
+
|
463 |
+
$append = 0;
|
464 |
+
|
465 |
+
if ($file_info['size'] > $byte_limit * 512 or $start_byte) {
|
466 |
+
$append = 1;
|
467 |
+
}
|
468 |
+
|
469 |
+
if (!isset($return['extra']['backup_size'])) {
|
470 |
+
$return['extra']['backup_size'] = 0;
|
471 |
+
}
|
472 |
+
|
473 |
+
$return['extra']['backup_size'] = $archive_info->getSize();
|
474 |
+
|
475 |
+
$estimated_new_size = $return['extra']['backup_size'] + $file_info['size'];
|
476 |
+
|
477 |
+
//we create a new backup part if we reach the Split Achive Limit
|
478 |
+
if ($this->xcloner_split_backup_limit and ($estimated_new_size > $this->xcloner_split_backup_limit) and (!$start_byte)) {
|
479 |
+
$this->logger->info(sprintf("Backup size limit %s bytes reached, file add estimate %s, attempt to create a new archive ",
|
480 |
+
$this->xcloner_split_backup_limit, $estimated_new_size));
|
481 |
+
list($archive_info, $return['extra']['backup_part']) = $this->create_new_backup_part($return['extra']['backup_part']);
|
482 |
+
|
483 |
+
if ($file_info['size'] > $this->xcloner_split_backup_limit) {
|
484 |
+
$this->logger->info(sprintf("Excluding %s file as it's size(%s) is bigger than the backup split limit of %s and it won't fit a single backup file",
|
485 |
+
$file_info['path'], $file_info['size'], $this->xcloner_split_backup_limit));
|
486 |
+
$extra_params['start_at_line']++;
|
487 |
+
}
|
488 |
+
|
489 |
+
$return['extra']['start_at_line'] = $extra_params['start_at_line'];
|
490 |
+
$return['extra']['start_at_byte'] = 0;
|
491 |
+
|
492 |
+
$return['finished'] = 0;
|
493 |
+
|
494 |
+
return $return;
|
495 |
+
}
|
496 |
+
|
497 |
+
list($bytes_wrote, $last_position) = $this->add_file_to_archive($file_info, $start_byte, $byte_limit,
|
498 |
+
$append, $start_filesystem);
|
499 |
+
$this->processed_size_bytes += $bytes_wrote;
|
500 |
+
|
501 |
+
//echo" - processed ".$this->processed_size_bytes." bytes ".$this->file_size_per_request_limit." last_position:".$last_position." \n";
|
502 |
+
$return['extra']['processed_file'] = $file_info['path'];
|
503 |
+
$return['extra']['processed_file_size'] = $file_info['size'];
|
504 |
+
$return['extra']['backup_size'] = $archive_info->getSize();
|
505 |
+
|
506 |
+
if ($last_position > 0) {
|
507 |
+
$start_byte = $last_position;
|
508 |
+
} else {
|
509 |
+
$extra_params['start_at_line']++;
|
510 |
+
$file->next();
|
511 |
+
$start_byte = 0;
|
512 |
+
$counter++;
|
513 |
+
}
|
514 |
+
|
515 |
+
if ($this->processed_size_bytes >= $this->file_size_per_request_limit) {
|
516 |
+
clearstatcache();
|
517 |
+
$return['extra']['backup_size'] = $archive_info->getSize();
|
518 |
+
|
519 |
+
$return['finished'] = 0;
|
520 |
+
$return['extra']['start_at_line'] = $extra_params['start_at_line'];
|
521 |
+
$return['extra']['start_at_byte'] = $last_position;
|
522 |
+
$this->logger->info(sprintf("Reached the maximum %s request data limit, returning response",
|
523 |
+
$this->file_size_per_request_limit));
|
524 |
+
return $return;
|
525 |
+
}
|
526 |
+
}
|
527 |
+
|
528 |
+
if (!$file->eof()) {
|
529 |
+
clearstatcache();
|
530 |
+
$return['extra']['backup_size'] = $archive_info->getSize();
|
531 |
+
|
532 |
+
$return['finished'] = 0;
|
533 |
+
$return['extra']['start_at_line'] = $extra_params['start_at_line'];
|
534 |
+
$return['extra']['start_at_byte'] = $last_position;
|
535 |
+
$this->logger->info(sprintf("We have reached the maximum files to process per request limit of %s, returning response",
|
536 |
+
$this->files_to_process_per_request));
|
537 |
+
|
538 |
+
return $return;
|
539 |
+
}
|
540 |
+
|
541 |
+
//close the backup archive by adding 2*512 blocks of zero bytes
|
542 |
+
$this->logger->info(sprintf("Closing the backup archive %s with 2*512 zero bytes blocks.",
|
543 |
+
$this->get_archive_name_with_extension()));
|
544 |
+
$this->backup_archive->close();
|
545 |
+
|
546 |
+
/**
|
547 |
+
* XCloner HOOK backup_archive_finished.
|
548 |
+
*
|
549 |
+
* This will get triggered when a backup archive is finished writing.
|
550 |
+
*/
|
551 |
+
//do_action('backup_archive_finished', $this->backup_archive, $this);
|
552 |
+
|
553 |
+
//updating archive_info
|
554 |
+
$archive_info = $this->filesystem->get_storage_path_file_info($this->get_archive_name_with_extension());
|
555 |
+
|
556 |
+
if ($return['extra']['backup_part']) {
|
557 |
+
$this->write_multipart_file($this->get_archive_name_with_extension());
|
558 |
+
}
|
559 |
+
|
560 |
+
$return['extra']['start_at_line'] = $extra_params['start_at_line'] - 1;
|
561 |
+
|
562 |
+
if (isset($file_info)) {
|
563 |
+
$return['extra']['processed_file'] = $file_info['path'];
|
564 |
+
$return['extra']['processed_file_size'] = $file_info['size'];
|
565 |
+
}
|
566 |
+
|
567 |
+
clearstatcache();
|
568 |
+
$return['extra']['backup_size'] = $archive_info->getSize();
|
569 |
+
|
570 |
+
$return['finished'] = 1;
|
571 |
+
return $return;
|
572 |
+
}
|
573 |
+
|
574 |
+
/*
|
575 |
+
*
|
576 |
+
* Write multipart file components
|
577 |
+
*
|
578 |
+
*/
|
579 |
+
private function write_multipart_file($path)
|
580 |
+
{
|
581 |
+
$path = $this->get_archive_name_with_extension();
|
582 |
+
|
583 |
+
$file = $this->filesystem->get_filesystem("storage_filesystem_append")->getMetadata($path);
|
584 |
+
//print_r($file_info);
|
585 |
+
$line = '"' . $file['path'] . '","' . $file['timestamp'] . '","' . $file['size'] . '"' . PHP_EOL;
|
586 |
+
|
587 |
+
|
588 |
+
$this->filesystem->get_filesystem("storage_filesystem_append")
|
589 |
+
->write($this->get_archive_name_multipart(), $line);
|
590 |
+
}
|
591 |
+
|
592 |
+
/*
|
593 |
+
*
|
594 |
+
* Create a new backup part
|
595 |
+
*
|
596 |
+
*/
|
597 |
+
private function create_new_backup_part($part = 0)
|
598 |
+
{
|
599 |
+
//close the backup archive by adding 2*512 blocks of zero bytes
|
600 |
+
$this->logger->info(sprintf("Closing the backup archive %s with 2*512 zero bytes blocks.",
|
601 |
+
$this->get_archive_name_with_extension()));
|
602 |
+
$this->backup_archive->close();
|
603 |
+
|
604 |
+
if (!$part) {
|
605 |
+
$old_name = $this->get_archive_name_with_extension();
|
606 |
+
$this->set_archive_name($this->get_archive_name(), ++$part);
|
607 |
+
$this->rename_archive($old_name, $this->get_archive_name_with_extension());
|
608 |
+
|
609 |
+
if ($this->filesystem->get_storage_filesystem()->has($this->get_archive_name_multipart())) {
|
610 |
+
$this->filesystem->get_storage_filesystem()->delete($this->get_archive_name_multipart());
|
611 |
+
}
|
612 |
+
|
613 |
+
$this->write_multipart_file($this->get_archive_name_with_extension());
|
614 |
+
|
615 |
+
} else {
|
616 |
+
$this->logger->info(sprintf("Creating new multipart info file %s",
|
617 |
+
$this->get_archive_name_with_extension()));
|
618 |
+
$this->write_multipart_file($this->get_archive_name_with_extension());
|
619 |
+
}
|
620 |
+
|
621 |
+
$this->set_archive_name($this->get_archive_name(), ++$part);
|
622 |
+
|
623 |
+
$this->logger->info(sprintf("Creating new backup archive part %s", $this->get_archive_name_with_extension()));
|
624 |
+
|
625 |
+
$this->backup_archive = new Tar();
|
626 |
+
$this->backup_archive->setCompression($this->compression_level);
|
627 |
+
$archive_info = $this->filesystem->get_storage_path_file_info($this->get_archive_name_with_extension());
|
628 |
+
$this->backup_archive->create($archive_info->getPath() . DS . $archive_info->getFilename());
|
629 |
+
|
630 |
+
return array($archive_info, $part);
|
631 |
+
|
632 |
+
}
|
633 |
+
|
634 |
+
/*
|
635 |
+
*
|
636 |
+
* Add file to archive
|
637 |
+
*
|
638 |
+
*/
|
639 |
+
public function add_file_to_archive($file_info, $start_at_byte, $byte_limit = 0, $append, $filesystem)
|
640 |
+
{
|
641 |
+
|
642 |
+
$start_adapter = $this->filesystem->get_adapter($filesystem);
|
643 |
+
$start_filesystem = $this->filesystem->get_adapter($filesystem);
|
644 |
+
|
645 |
+
if (!$file_info['path']) {
|
646 |
+
return;
|
647 |
+
}
|
648 |
+
|
649 |
+
if (isset($file_info['archive_prefix_path'])) {
|
650 |
+
$file_info['target_path'] = $file_info['archive_prefix_path'] . "/" . $file_info['path'];
|
651 |
+
} else {
|
652 |
+
$file_info['target_path'] = $file_info['path'];
|
653 |
+
}
|
654 |
+
|
655 |
+
$last_position = $start_at_byte;
|
656 |
+
|
657 |
+
//$start_adapter = $this->filesystem->get_start_adapter();
|
658 |
+
|
659 |
+
if (!$append) {
|
660 |
+
$bytes_wrote = $file_info['size'];
|
661 |
+
$this->logger->info(sprintf("Adding %s bytes of file %s to archive %s ", $bytes_wrote,
|
662 |
+
$file_info['target_path'], $this->get_archive_name_with_extension()));
|
663 |
+
$this->backup_archive->addFile($start_adapter->applyPathPrefix($file_info['path']),
|
664 |
+
$file_info['target_path']);
|
665 |
+
} else {
|
666 |
+
$tmp_file = md5($file_info['path']);
|
667 |
+
|
668 |
+
//we isolate file to tmp if we are at byte 0, the starting point of file reading
|
669 |
+
if (!$start_at_byte) {
|
670 |
+
$this->logger->info(sprintf("Copying %s file to tmp filesystem file %s to prevent reading changes",
|
671 |
+
$file_info['path'], $tmp_file));
|
672 |
+
$file_stream = $start_filesystem->readStream($file_info['path']);
|
673 |
+
|
674 |
+
if (is_resource($file_stream['stream'])) {
|
675 |
+
$this->filesystem->get_tmp_filesystem()->writeStream($tmp_file, $file_stream['stream']);
|
676 |
+
}
|
677 |
+
}
|
678 |
+
|
679 |
+
if ($this->filesystem->get_tmp_filesystem()->has($tmp_file)) {
|
680 |
+
$is_tmp = 1;
|
681 |
+
$last_position = $this->backup_archive->appendFileData($this->filesystem->get_tmp_filesystem_adapter()
|
682 |
+
->applyPathPrefix($tmp_file),
|
683 |
+
$file_info['target_path'], $start_at_byte, $byte_limit);
|
684 |
+
} else {
|
685 |
+
$is_tmp = 0;
|
686 |
+
$last_position = $this->backup_archive->appendFileData($start_adapter->applyPathPrefix($file_info['path']),
|
687 |
+
$file_info['target_path'], $start_at_byte, $byte_limit);
|
688 |
+
}
|
689 |
+
|
690 |
+
|
691 |
+
if ($last_position == -1) {
|
692 |
+
$bytes_wrote = $file_info['size'] - $start_at_byte;
|
693 |
+
} else {
|
694 |
+
$bytes_wrote = $last_position - $start_at_byte;
|
695 |
+
}
|
696 |
+
|
697 |
+
|
698 |
+
if ($is_tmp) {
|
699 |
+
$this->logger->info(sprintf("Appended %s bytes, starting position %s, of tmp file %s (%s) to archive %s ",
|
700 |
+
$bytes_wrote, $start_at_byte, $tmp_file, $file_info['target_path'], $this->get_archive_name()));
|
701 |
+
} else {
|
702 |
+
$this->logger->info(sprintf("Appended %s bytes, starting position %s, of original file %s to archive %s ",
|
703 |
+
$bytes_wrote, $start_at_byte, $file_info['target_path'], $tmp_file, $this->get_archive_name()));
|
704 |
+
}
|
705 |
+
|
706 |
+
//we delete here the isolated tmp file
|
707 |
+
if ($last_position == -1) {
|
708 |
+
if ($this->filesystem->get_tmp_filesystem_adapter()->has($tmp_file)) {
|
709 |
+
$this->logger->info(sprintf("Deleting %s from the tmp filesystem", $tmp_file));
|
710 |
+
$this->filesystem->get_tmp_filesystem_adapter()->delete($tmp_file);
|
711 |
+
}
|
712 |
+
}
|
713 |
+
|
714 |
+
}
|
715 |
+
|
716 |
+
return array($bytes_wrote, $last_position);
|
717 |
+
}
|
718 |
+
|
719 |
/**
|
720 |
* Open a TAR archive and put the file cursor at the end for data appending
|
721 |
*
|
753 |
$this->backup_archive->closed = false;
|
754 |
}
|
755 |
*/
|
756 |
+
|
757 |
+
/**
|
758 |
* Append data to a file to the current TAR archive using an existing file in the filesystem
|
759 |
*
|
760 |
+
* @param string $file path to the original file
|
761 |
+
* @param int $start starting reading position in file
|
762 |
+
* @param int $end end position in reading multiple with 512
|
763 |
+
* @param string|FileInfo $fileinfo either the name to us in archive (string) or a FileInfo oject with
|
764 |
+
* all meta data, empty to take from original
|
765 |
* @throws ArchiveIOException
|
766 |
*/
|
767 |
/*
|
768 |
* public function appendFileData($file, $fileinfo = '', $start = 0, $limit = 0)
|
769 |
{
|
770 |
$end = $start+($limit*512);
|
771 |
+
|
772 |
//check to see if we are at the begining of writing the file
|
773 |
if(!$start)
|
774 |
{
|
776 |
$fileinfo = FileInfo::fromPath($file, $fileinfo);
|
777 |
}
|
778 |
}
|
779 |
+
|
780 |
if ($this->closed) {
|
781 |
throw new ArchiveIOException('Archive has been closed, files can no longer be added');
|
782 |
}
|
783 |
|
784 |
$fp = fopen($file, 'rb');
|
785 |
+
|
786 |
fseek($fp, $start);
|
787 |
+
|
788 |
if (!$fp) {
|
789 |
throw new ArchiveIOException('Could not open file for reading: '.$file);
|
790 |
}
|
792 |
// create file header
|
793 |
if(!$start)
|
794 |
$this->backup_archive->writeFileHeader($fileinfo);
|
795 |
+
|
796 |
$bytes = 0;
|
797 |
// write data
|
798 |
while ($end >=ftell($fp) and !feof($fp) ) {
|
806 |
$packed = pack("a512", $data);
|
807 |
$bytes += $this->backup_archive->writebytes($packed);
|
808 |
}
|
809 |
+
|
810 |
+
|
811 |
+
|
812 |
//if we are not at the end of file, we return the current position for incremental writing
|
813 |
if(!feof($fp))
|
814 |
$last_position = ftell($fp);
|
815 |
else
|
816 |
$last_position = -1;
|
817 |
+
|
818 |
fclose($fp);
|
819 |
+
|
820 |
return $last_position;
|
821 |
}*/
|
822 |
+
|
823 |
/**
|
824 |
* Adds a file to a TAR archive by appending it's data
|
825 |
*
|
826 |
+
* @param string $archive name of the archive file
|
827 |
+
* @param string $file name of the file to read data from
|
828 |
+
* @param string $start start position from where to start reading data
|
829 |
* @throws ArchiveIOException
|
830 |
*/
|
831 |
+
/*public function addFileToArchive($archive, $file, $start = 0)
|
832 |
+
{
|
833 |
+
$this->openForAppend($archive);
|
834 |
+
return $start = $this->appendFileData($file, $start, $this->file_size_per_request_limit);
|
835 |
+
}
|
836 |
+
*/
|
837 |
|
838 |
}
|
includes/class-xcloner-deactivator.php
CHANGED
@@ -1,13 +1,29 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
/**
|
4 |
-
*
|
5 |
*
|
6 |
-
*
|
7 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8 |
*
|
9 |
-
* @package Xcloner
|
10 |
-
* @subpackage Xcloner/includes
|
11 |
*/
|
12 |
|
13 |
/**
|
@@ -19,7 +35,9 @@
|
|
19 |
* @package Xcloner
|
20 |
* @subpackage Xcloner/includes
|
21 |
* @author Liuta Ovidiu <info@thinkovi.com>
|
|
|
22 |
*/
|
|
|
23 |
class Xcloner_Deactivator {
|
24 |
|
25 |
/**
|
@@ -30,18 +48,16 @@ class Xcloner_Deactivator {
|
|
30 |
* @since 1.0.0
|
31 |
*/
|
32 |
public static function deactivate() {
|
33 |
-
|
34 |
global $xcloner_plugin;
|
35 |
-
|
36 |
-
if(is_a($xcloner_plugin, 'Xcloner'))
|
37 |
-
|
38 |
-
try{
|
39 |
$xcloner_plugin->get_xcloner_filesystem()->cleanup_tmp_directories();
|
40 |
-
}catch(Exception $e)
|
41 |
-
|
42 |
-
$xcloner_plugin->trigger_message_notice($e->getMessage());
|
43 |
}
|
44 |
-
|
45 |
$xcloner_scheduler = $xcloner_plugin->get_xcloner_scheduler();
|
46 |
$xcloner_scheduler->deactivate_wp_cron_hooks();
|
47 |
}
|
1 |
<?php
|
|
|
2 |
/**
|
3 |
+
* XCloner - Backup and Restore backup plugin for Wordpress
|
4 |
*
|
5 |
+
* class-xcloner-deactivator.php
|
6 |
+
* @author Liuta Ovidiu <info@thinkovi.com>
|
7 |
+
*
|
8 |
+
* This program is free software; you can redistribute it and/or modify
|
9 |
+
* it under the terms of the GNU General Public License as published by
|
10 |
+
* the Free Software Foundation; either version 2 of the License, or
|
11 |
+
* (at your option) any later version.
|
12 |
+
*
|
13 |
+
* This program is distributed in the hope that it will be useful,
|
14 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16 |
+
* GNU General Public License for more details.
|
17 |
+
*
|
18 |
+
* You should have received a copy of the GNU General Public License
|
19 |
+
* along with this program; if not, write to the Free Software
|
20 |
+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
21 |
+
* MA 02110-1301, USA.
|
22 |
+
*
|
23 |
+
* @link https://github.com/ovidiul/XCloner-Wordpress
|
24 |
+
*
|
25 |
+
* @modified 7/31/18 3:28 PM
|
26 |
*
|
|
|
|
|
27 |
*/
|
28 |
|
29 |
/**
|
35 |
* @package Xcloner
|
36 |
* @subpackage Xcloner/includes
|
37 |
* @author Liuta Ovidiu <info@thinkovi.com>
|
38 |
+
* @link http://www.thinkovi.com
|
39 |
*/
|
40 |
+
|
41 |
class Xcloner_Deactivator {
|
42 |
|
43 |
/**
|
48 |
* @since 1.0.0
|
49 |
*/
|
50 |
public static function deactivate() {
|
51 |
+
|
52 |
global $xcloner_plugin;
|
53 |
+
|
54 |
+
if ( is_a( $xcloner_plugin, 'Xcloner' ) ) {
|
55 |
+
try {
|
|
|
56 |
$xcloner_plugin->get_xcloner_filesystem()->cleanup_tmp_directories();
|
57 |
+
} catch ( Exception $e ) {
|
58 |
+
$xcloner_plugin->trigger_message_notice( $e->getMessage() );
|
|
|
59 |
}
|
60 |
+
|
61 |
$xcloner_scheduler = $xcloner_plugin->get_xcloner_scheduler();
|
62 |
$xcloner_scheduler->deactivate_wp_cron_hooks();
|
63 |
}
|
includes/class-xcloner-file-system.php
CHANGED
@@ -1,992 +1,1072 @@
|
|
1 |
<?php
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
use League\Flysystem\Config;
|
3 |
use League\Flysystem\Filesystem;
|
4 |
use League\Flysystem\Util;
|
5 |
use League\Flysystem\Adapter\Local;
|
6 |
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
303 |
{
|
304 |
$location = $this->$adapter->applyPathPrefix($path);
|
305 |
$spl_info = new SplFileInfo($location);
|
306 |
-
|
307 |
return ($spl_info);
|
308 |
}
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
583 |
-
|
584 |
-
|
585 |
-
|
586 |
-
|
587 |
-
|
588 |
-
|
589 |
-
|
590 |
-
|
591 |
-
|
592 |
-
|
593 |
-
|
594 |
-
|
595 |
-
|
596 |
-
|
597 |
-
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
-
|
603 |
-
|
604 |
-
|
605 |
-
|
606 |
-
|
607 |
-
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
|
615 |
-
|
616 |
-
|
617 |
-
|
618 |
-
|
619 |
-
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
-
|
626 |
-
|
627 |
-
|
628 |
-
|
629 |
-
|
630 |
-
|
631 |
-
|
632 |
-
|
633 |
-
|
634 |
-
|
635 |
-
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
|
640 |
-
|
641 |
-
|
642 |
-
|
643 |
-
|
644 |
-
|
645 |
-
|
646 |
-
|
647 |
-
|
648 |
-
|
649 |
-
|
650 |
-
|
651 |
-
|
652 |
-
|
653 |
-
|
654 |
-
|
655 |
-
|
656 |
-
|
657 |
-
|
658 |
-
|
659 |
-
|
660 |
-
|
661 |
-
|
662 |
-
|
663 |
-
|
664 |
-
|
665 |
-
|
666 |
-
|
667 |
-
|
668 |
-
|
669 |
-
|
670 |
-
|
671 |
-
|
672 |
-
|
673 |
-
|
674 |
-
|
675 |
-
|
676 |
-
|
677 |
-
|
678 |
-
|
679 |
-
|
680 |
-
|
681 |
-
|
682 |
-
|
683 |
-
|
684 |
-
|
685 |
-
|
686 |
-
|
687 |
-
|
688 |
-
|
689 |
-
|
690 |
-
|
691 |
-
|
692 |
-
|
693 |
-
|
694 |
-
|
695 |
-
|
696 |
-
|
697 |
-
|
698 |
-
|
699 |
-
|
700 |
-
|
701 |
-
|
702 |
-
|
703 |
-
|
704 |
-
|
705 |
-
|
706 |
-
|
707 |
-
|
708 |
-
|
709 |
-
|
710 |
-
|
711 |
-
|
712 |
-
|
713 |
-
|
714 |
-
|
715 |
-
|
716 |
-
|
717 |
-
|
718 |
-
|
719 |
-
|
720 |
-
|
721 |
-
|
722 |
-
|
723 |
-
|
724 |
-
|
725 |
-
|
726 |
-
|
727 |
-
|
728 |
-
|
729 |
-
|
730 |
-
|
731 |
-
|
732 |
-
|
733 |
-
|
734 |
-
|
735 |
-
|
736 |
-
|
737 |
-
|
738 |
-
|
739 |
-
|
740 |
-
|
741 |
-
|
742 |
-
|
743 |
-
|
744 |
-
|
745 |
-
|
746 |
-
|
747 |
-
|
748 |
-
|
749 |
-
|
750 |
-
|
751 |
-
|
752 |
-
|
753 |
-
|
754 |
-
|
755 |
-
|
756 |
-
|
757 |
-
|
758 |
-
|
759 |
-
|
760 |
-
|
761 |
-
|
762 |
-
|
763 |
-
|
764 |
-
|
765 |
-
|
766 |
-
|
767 |
-
|
768 |
-
|
769 |
-
|
770 |
-
|
771 |
-
|
772 |
-
|
773 |
-
|
774 |
-
|
775 |
-
|
776 |
-
|
777 |
-
|
778 |
-
|
779 |
-
|
780 |
-
|
781 |
-
|
782 |
-
|
783 |
-
|
784 |
-
|
785 |
-
|
786 |
-
|
787 |
-
|
788 |
-
|
789 |
-
|
790 |
-
|
791 |
-
|
792 |
-
|
793 |
-
|
794 |
-
|
795 |
-
|
796 |
-
|
797 |
-
|
798 |
-
|
799 |
-
|
800 |
-
|
801 |
-
|
802 |
-
|
803 |
-
|
804 |
-
|
805 |
-
|
806 |
-
|
807 |
-
|
808 |
-
|
809 |
-
|
810 |
-
|
811 |
-
|
812 |
-
|
813 |
-
|
814 |
-
|
815 |
-
|
816 |
-
|
817 |
-
|
818 |
-
|
819 |
-
|
820 |
-
|
821 |
-
|
822 |
-
|
823 |
-
|
824 |
-
|
825 |
-
|
826 |
-
|
827 |
-
|
828 |
-
|
829 |
-
|
830 |
-
|
831 |
-
|
832 |
-
|
833 |
-
|
834 |
-
|
835 |
-
|
836 |
-
|
837 |
-
|
838 |
-
|
839 |
-
|
840 |
-
|
841 |
-
|
842 |
-
|
843 |
-
|
844 |
-
|
845 |
-
|
846 |
-
|
847 |
-
|
848 |
-
|
849 |
-
|
850 |
-
|
851 |
-
|
852 |
-
|
853 |
-
|
854 |
-
|
855 |
-
|
856 |
-
|
857 |
-
|
858 |
-
|
859 |
-
|
860 |
-
|
861 |
-
|
862 |
-
|
863 |
-
|
864 |
-
|
865 |
-
|
866 |
-
|
867 |
-
|
868 |
-
|
869 |
-
|
870 |
-
|
871 |
-
|
872 |
-
|
873 |
-
|
874 |
-
|
875 |
-
|
876 |
-
|
877 |
-
|
878 |
-
|
879 |
-
|
880 |
-
|
881 |
-
|
882 |
-
|
883 |
-
|
884 |
-
|
885 |
-
|
886 |
-
|
887 |
-
|
888 |
-
|
889 |
-
|
890 |
-
|
891 |
-
|
892 |
-
|
893 |
-
|
894 |
-
|
895 |
-
|
896 |
-
|
897 |
-
|
898 |
-
|
899 |
-
|
900 |
-
|
901 |
-
|
902 |
-
|
903 |
-
|
904 |
-
|
905 |
-
|
906 |
-
|
907 |
-
|
908 |
-
|
909 |
-
|
910 |
-
|
911 |
-
|
912 |
-
|
913 |
-
|
914 |
-
|
915 |
-
|
916 |
-
|
917 |
-
|
918 |
-
|
919 |
-
|
920 |
-
|
921 |
-
|
922 |
-
|
923 |
-
|
924 |
-
|
925 |
-
|
926 |
-
|
927 |
-
|
928 |
-
|
929 |
-
|
930 |
-
|
931 |
-
|
932 |
-
|
933 |
-
|
934 |
-
|
935 |
-
|
936 |
-
|
937 |
-
|
938 |
-
|
939 |
-
|
940 |
-
|
941 |
-
|
942 |
-
|
943 |
-
|
944 |
-
|
945 |
-
|
946 |
-
|
947 |
-
|
948 |
-
|
949 |
-
|
950 |
-
|
951 |
-
|
952 |
-
|
953 |
-
|
954 |
-
|
955 |
-
|
956 |
-
|
957 |
-
|
958 |
-
|
959 |
-
|
960 |
-
|
961 |
-
|
962 |
-
|
963 |
-
|
964 |
-
|
965 |
-
|
966 |
-
|
967 |
-
|
968 |
-
|
969 |
-
|
970 |
-
|
971 |
-
|
972 |
-
|
973 |
-
|
974 |
-
|
975 |
-
|
976 |
-
|
977 |
-
|
978 |
-
|
979 |
-
|
980 |
-
|
981 |
-
|
982 |
-
|
983 |
-
|
984 |
-
|
985 |
-
|
986 |
-
|
987 |
-
|
988 |
-
|
989 |
-
|
990 |
-
|
991 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
992 |
}
|
1 |
<?php
|
2 |
+
/**
|
3 |
+
* XCloner - Backup and Restore backup plugin for Wordpress
|
4 |
+
*
|
5 |
+
* class-xcloner-file-system.php
|
6 |
+
* @author Liuta Ovidiu <info@thinkovi.com>
|
7 |
+
*
|
8 |
+
* This program is free software; you can redistribute it and/or modify
|
9 |
+
* it under the terms of the GNU General Public License as published by
|
10 |
+
* the Free Software Foundation; either version 2 of the License, or
|
11 |
+
* (at your option) any later version.
|
12 |
+
*
|
13 |
+
* This program is distributed in the hope that it will be useful,
|
14 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16 |
+
* GNU General Public License for more details.
|
17 |
+
*
|
18 |
+
* You should have received a copy of the GNU General Public License
|
19 |
+
* along with this program; if not, write to the Free Software
|
20 |
+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
21 |
+
* MA 02110-1301, USA.
|
22 |
+
*
|
23 |
+
* @link https://github.com/ovidiul/XCloner-Wordpress
|
24 |
+
*
|
25 |
+
* @modified 7/31/18 3:46 PM
|
26 |
+
*
|
27 |
+
*/
|
28 |
+
|
29 |
use League\Flysystem\Config;
|
30 |
use League\Flysystem\Filesystem;
|
31 |
use League\Flysystem\Util;
|
32 |
use League\Flysystem\Adapter\Local;
|
33 |
|
34 |
+
/**
|
35 |
+
* Class Xcloner_File_System
|
36 |
+
*/
|
37 |
+
class Xcloner_File_System
|
38 |
+
{
|
39 |
+
|
40 |
+
private $excluded_files = "";
|
41 |
+
private $additional_regex_patterns = array();
|
42 |
+
private $excluded_files_by_default = array("administrator/backups", "wp-content/backups");
|
43 |
+
private $included_files_handler = "backup_files.csv";
|
44 |
+
private $temp_dir_handler = ".dir";
|
45 |
+
public $filesystem;
|
46 |
+
public $tmp_filesystem;
|
47 |
+
public $storage_filesystem;
|
48 |
+
private $xcloner_container;
|
49 |
+
private $diff_timestamp_start = "";
|
50 |
+
|
51 |
+
private $logger;
|
52 |
+
private $start_adapter;
|
53 |
+
private $tmp_adapter;
|
54 |
+
private $storage_adapter;
|
55 |
+
private $xcloner_settings;
|
56 |
+
private $start_filesystem;
|
57 |
+
private $tmp_filesystem_append;
|
58 |
+
private $storage_filesystem_append;
|
59 |
+
|
60 |
+
private $files_counter;
|
61 |
+
private $files_size;
|
62 |
+
private $last_logged_file;
|
63 |
+
private $folders_to_process_per_session = 25;
|
64 |
+
private $backup_archive_extensions = array("tar", "tgz", "tar.gz", "gz", "csv");
|
65 |
+
private $backup_name_tags = array('[time]', '[hostname]', '[domain]');
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Xcloner_File_System constructor.
|
69 |
+
* @param Xcloner $xcloner_container
|
70 |
+
* @param string $hash
|
71 |
+
*/
|
72 |
+
public function __construct(Xcloner $xcloner_container, $hash = "")
|
73 |
+
{
|
74 |
+
$this->xcloner_container = $xcloner_container;
|
75 |
+
|
76 |
+
$this->logger = $xcloner_container->get_xcloner_logger()->withName("xcloner_file_system");
|
77 |
+
$this->xcloner_settings = $xcloner_container->get_xcloner_settings();
|
78 |
+
|
79 |
+
try {
|
80 |
+
|
81 |
+
$this->start_adapter = new Local($this->xcloner_settings->get_xcloner_start_path(), LOCK_EX, 'SKIP_LINKS');
|
82 |
+
$this->start_filesystem = new Filesystem($this->start_adapter, new Config([
|
83 |
+
'disable_asserts' => true,
|
84 |
+
]));
|
85 |
+
|
86 |
+
$this->tmp_adapter = new Local($this->xcloner_settings->get_xcloner_tmp_path(), LOCK_EX, 'SKIP_LINKS');
|
87 |
+
$this->tmp_filesystem = new Filesystem($this->tmp_adapter, new Config([
|
88 |
+
'disable_asserts' => true,
|
89 |
+
]));
|
90 |
+
$adapter = new Local($this->xcloner_settings->get_xcloner_tmp_path(), LOCK_EX | FILE_APPEND, 'SKIP_LINKS');
|
91 |
+
$this->tmp_filesystem_append = new Filesystem($adapter, new Config([
|
92 |
+
'disable_asserts' => true,
|
93 |
+
]));
|
94 |
+
|
95 |
+
$adapter = new Local($this->xcloner_settings->get_xcloner_store_path(), LOCK_EX, 'SKIP_LINKS');
|
96 |
+
$this->storage_filesystem = new Filesystem($adapter, new Config([
|
97 |
+
'disable_asserts' => true,
|
98 |
+
]));
|
99 |
+
|
100 |
+
$this->storage_adapter = new Local($this->xcloner_settings->get_xcloner_store_path(), FILE_APPEND,
|
101 |
+
'SKIP_LINKS');
|
102 |
+
$this->storage_filesystem_append = new Filesystem($this->storage_adapter, new Config([
|
103 |
+
'disable_asserts' => true,
|
104 |
+
]));
|
105 |
+
} catch (Exception $e) {
|
106 |
+
$this->logger->error("Filesystem Initialization Error: " . $e->getMessage());
|
107 |
+
}
|
108 |
+
|
109 |
+
|
110 |
+
if ($value = get_option('xcloner_directories_to_scan_per_request')) {
|
111 |
+
$this->folders_to_process_per_session = $value;
|
112 |
+
}
|
113 |
+
|
114 |
+
}
|
115 |
+
|
116 |
+
/**
|
117 |
+
* Set differential timestamp date
|
118 |
+
* @param string $timestamp
|
119 |
+
*/
|
120 |
+
public function set_diff_timestamp_start($timestamp = "")
|
121 |
+
{
|
122 |
+
if ($timestamp) {
|
123 |
+
$this->logger->info(sprintf("Setting Differential Timestamp To %s", date("Y-m-d", $timestamp)), array(
|
124 |
+
"FILESYSTEM",
|
125 |
+
"DIFF"
|
126 |
+
));
|
127 |
+
$this->diff_timestamp_start = $timestamp;
|
128 |
+
}
|
129 |
+
}
|
130 |
+
|
131 |
+
/**
|
132 |
+
* Gets the differential timestamp date
|
133 |
+
* @return string
|
134 |
+
*/
|
135 |
+
public function get_diff_timestamp_start()
|
136 |
+
{
|
137 |
+
return $this->diff_timestamp_start;
|
138 |
+
}
|
139 |
+
|
140 |
+
private function get_xcloner_container()
|
141 |
+
{
|
142 |
+
return $this->xcloner_container;
|
143 |
+
}
|
144 |
+
|
145 |
+
public function set_hash($hash)
|
146 |
+
{
|
147 |
+
$this->xcloner_settings->set_hash($hash);
|
148 |
+
}
|
149 |
+
|
150 |
+
public function get_hash($hash)
|
151 |
+
{
|
152 |
+
$this->xcloner_settings->get_hash();
|
153 |
+
}
|
154 |
+
|
155 |
+
public function get_tmp_filesystem()
|
156 |
+
{
|
157 |
+
return $this->tmp_filesystem;
|
158 |
+
}
|
159 |
+
|
160 |
+
public function get_storage_filesystem($remote_storage_selection = "")
|
161 |
+
{
|
162 |
+
if ($remote_storage_selection != "") {
|
163 |
+
$remote_storage = $this->get_xcloner_container()->get_xcloner_remote_storage();
|
164 |
+
$method = "get_" . $remote_storage_selection . "_filesystem";
|
165 |
+
|
166 |
+
if (!method_exists($remote_storage, $method)) {
|
167 |
+
return false;
|
168 |
+
}
|
169 |
+
|
170 |
+
list($adapter, $filesystem) = $remote_storage->$method();
|
171 |
+
|
172 |
+
return $filesystem;
|
173 |
+
}
|
174 |
+
|
175 |
+
return $this->storage_filesystem;
|
176 |
+
}
|
177 |
+
|
178 |
+
public function get_tmp_filesystem_adapter()
|
179 |
+
{
|
180 |
+
return $this->tmp_adapter;
|
181 |
+
}
|
182 |
+
|
183 |
+
public function get_tmp_filesystem_append()
|
184 |
+
{
|
185 |
+
return $this->tmp_filesystem_append;
|
186 |
+
}
|
187 |
+
|
188 |
+
public function get_start_adapter()
|
189 |
+
{
|
190 |
+
return $this->start_adapter;
|
191 |
+
}
|
192 |
+
|
193 |
+
public function get_start_filesystem()
|
194 |
+
{
|
195 |
+
return $this->start_filesystem;
|
196 |
+
}
|
197 |
+
|
198 |
+
public function get_logger()
|
199 |
+
{
|
200 |
+
return $this->logger;
|
201 |
+
}
|
202 |
+
|
203 |
+
public function get_start_path_file_info($file)
|
204 |
+
{
|
205 |
+
$info = $this->getMetadataFull('start_adapter', $file);
|
206 |
+
|
207 |
+
return $this->start_filesystem->normalizeFileInfo($info);
|
208 |
+
}
|
209 |
+
|
210 |
+
public function get_storage_path_file_info($file)
|
211 |
+
{
|
212 |
+
return $this->getMetadataFull('storage_adapter', $file);
|
213 |
+
}
|
214 |
+
|
215 |
+
public function get_included_files_handler($metadata = 0)
|
216 |
+
{
|
217 |
+
$path = $this->included_files_handler;
|
218 |
+
if (!$metadata) {
|
219 |
+
return $path;
|
220 |
+
}
|
221 |
+
|
222 |
+
$spl_info = $this->getMetadataFull('tmp_adapter', $path);
|
223 |
+
|
224 |
+
return $spl_info;
|
225 |
+
|
226 |
+
}
|
227 |
+
|
228 |
+
public function get_temp_dir_handler()
|
229 |
+
{
|
230 |
+
return $this->temp_dir_handler;
|
231 |
+
}
|
232 |
+
|
233 |
+
public function get_latest_backup()
|
234 |
+
{
|
235 |
+
$files = $this->get_backup_archives_list();
|
236 |
+
|
237 |
+
if (is_array($files)) {
|
238 |
+
$this->sort_by($files, "timestamp", "desc");
|
239 |
+
}
|
240 |
+
|
241 |
+
$new_list = array();
|
242 |
+
|
243 |
+
foreach ($files as $key => $file) {
|
244 |
+
if (!isset($file['parent'])) {
|
245 |
+
$new_list[] = ($files[$key]);
|
246 |
+
}
|
247 |
+
}
|
248 |
+
|
249 |
+
if (isset($new_list[0])) {
|
250 |
+
return $new_list[0];
|
251 |
+
}
|
252 |
+
}
|
253 |
+
|
254 |
+
public function get_latest_backups()
|
255 |
+
{
|
256 |
+
$files = $this->get_backup_archives_list();
|
257 |
+
|
258 |
+
if (is_array($files)) {
|
259 |
+
$this->sort_by($files, "timestamp", "desc");
|
260 |
+
}
|
261 |
+
|
262 |
+
$new_list = array();
|
263 |
+
|
264 |
+
foreach ($files as $key => $file) {
|
265 |
+
if (!isset($file['parent'])) {
|
266 |
+
$new_list[] = ($files[$key]);
|
267 |
+
}
|
268 |
+
}
|
269 |
+
|
270 |
+
return $new_list;
|
271 |
+
}
|
272 |
+
|
273 |
+
public function get_storage_usage()
|
274 |
+
{
|
275 |
+
$files = $this->get_backup_archives_list();
|
276 |
+
$total = 0;
|
277 |
+
|
278 |
+
if (is_array($files)) {
|
279 |
+
foreach ($files as $file) {
|
280 |
+
$total += $file['size'];
|
281 |
+
}
|
282 |
+
}
|
283 |
+
|
284 |
+
return $total;
|
285 |
+
}
|
286 |
+
|
287 |
+
public function is_part($backup_name)
|
288 |
+
{
|
289 |
+
if (stristr($backup_name, "-part")) {
|
290 |
+
return true;
|
291 |
+
}
|
292 |
+
|
293 |
+
return false;
|
294 |
+
}
|
295 |
+
|
296 |
+
public function is_multipart($backup_name)
|
297 |
+
{
|
298 |
+
if (stristr($backup_name, "-multipart")) {
|
299 |
+
return true;
|
300 |
+
}
|
301 |
+
|
302 |
+
return false;
|
303 |
+
}
|
304 |
+
|
305 |
+
public function get_backup_size($backup_name)
|
306 |
+
{
|
307 |
+
$backup_size = $this->get_storage_filesystem()->getSize($backup_name);
|
308 |
+
if ($this->is_multipart($backup_name)) {
|
309 |
+
$backup_parts = $this->get_multipart_files($backup_name);
|
310 |
+
foreach ($backup_parts as $part_file) {
|
311 |
+
$backup_size += $this->get_storage_filesystem()->getSize($part_file);
|
312 |
+
}
|
313 |
+
}
|
314 |
+
|
315 |
+
return $backup_size;
|
316 |
+
}
|
317 |
+
|
318 |
+
public function get_multipart_files($backup_name, $storage_selection = "")
|
319 |
+
{
|
320 |
+
$files = array();
|
321 |
+
|
322 |
+
if ($this->is_multipart($backup_name)) {
|
323 |
+
$lines = explode(PHP_EOL, $this->get_storage_filesystem($storage_selection)->read($backup_name));
|
324 |
+
foreach ($lines as $line) {
|
325 |
+
if ($line) {
|
326 |
+
$data = str_getcsv($line);
|
327 |
+
$files[] = $data[0];
|
328 |
+
}
|
329 |
+
}
|
330 |
+
}
|
331 |
+
|
332 |
+
return $files;
|
333 |
+
}
|
334 |
+
|
335 |
+
public function delete_backup_by_name($backup_name, $storage_selection = "")
|
336 |
+
{
|
337 |
+
if ($this->is_multipart($backup_name)) {
|
338 |
+
$lines = explode(PHP_EOL, $this->get_storage_filesystem($storage_selection)->read($backup_name));
|
339 |
+
foreach ($lines as $line) {
|
340 |
+
if ($line) {
|
341 |
+
$data = str_getcsv($line);
|
342 |
+
$this->get_storage_filesystem($storage_selection)->delete($data[0]);
|
343 |
+
}
|
344 |
+
}
|
345 |
+
}
|
346 |
+
|
347 |
+
if ($this->get_storage_filesystem($storage_selection)->delete($backup_name)) {
|
348 |
+
$return = true;
|
349 |
+
} else {
|
350 |
+
$return = false;
|
351 |
+
}
|
352 |
+
|
353 |
+
return $return;
|
354 |
+
}
|
355 |
+
|
356 |
+
public function getMetadataFull($adapter = "storage_adapter", $path)
|
357 |
{
|
358 |
$location = $this->$adapter->applyPathPrefix($path);
|
359 |
$spl_info = new SplFileInfo($location);
|
360 |
+
|
361 |
return ($spl_info);
|
362 |
}
|
363 |
+
|
364 |
+
|
365 |
+
public function get_backup_archives_list($storage_selection = "")
|
366 |
+
{
|
367 |
+
$list = array();
|
368 |
+
|
369 |
+
|
370 |
+
if (method_exists($this->get_storage_filesystem($storage_selection), "listContents")) {
|
371 |
+
$list = $this->get_storage_filesystem($storage_selection)->listContents();
|
372 |
+
}
|
373 |
+
|
374 |
+
$backup_files = array();
|
375 |
+
$parents = array();
|
376 |
+
|
377 |
+
foreach ($list as $file_info) {
|
378 |
+
if (isset($file_info['extension']) and $file_info['extension'] == "csv") {
|
379 |
+
$data = array();
|
380 |
+
|
381 |
+
$lines = explode(PHP_EOL, $this->get_storage_filesystem($storage_selection)->read($file_info['path']));
|
382 |
+
foreach ($lines as $line) {
|
383 |
+
if ($line) {
|
384 |
+
$data = str_getcsv($line);
|
385 |
+
if (is_array($data)) {
|
386 |
+
$parents[$data[0]] = $file_info['basename'];
|
387 |
+
$file_info['childs'][] = $data;
|
388 |
+
$file_info['size'] += $data[2];
|
389 |
+
}
|
390 |
+
}
|
391 |
+
}
|
392 |
+
|
393 |
+
}
|
394 |
+
|
395 |
+
if ($file_info['type'] == 'file' and isset($file_info['extension']) and in_array($file_info['extension'],
|
396 |
+
$this->backup_archive_extensions)) {
|
397 |
+
$backup_files[$file_info['path']] = $file_info;
|
398 |
+
}
|
399 |
+
}
|
400 |
+
|
401 |
+
foreach ($backup_files as $key => $file_info) {
|
402 |
+
if (!isset($backup_files[$key]['timestamp'])) {
|
403 |
+
//$backup_files[$key]['timestamp'] = $this->get_storage_filesystem($storage_selection)->getTimestamp($file_info['path']);
|
404 |
+
}
|
405 |
+
|
406 |
+
if (isset($parents[$file_info['basename']])) {
|
407 |
+
$backup_files[$key]['parent'] = $parents[$file_info['basename']];
|
408 |
+
}
|
409 |
+
}
|
410 |
+
|
411 |
+
return $backup_files;
|
412 |
+
}
|
413 |
+
|
414 |
+
public function start_file_recursion($init = 0)
|
415 |
+
{
|
416 |
+
if ($init) {
|
417 |
+
$this->logger->info(sprintf(__("Starting the filesystem scanner on root folder %s"),
|
418 |
+
$this->xcloner_settings->get_xcloner_start_path()));
|
419 |
+
$this->do_system_init();
|
420 |
+
}
|
421 |
+
|
422 |
+
if ($this->tmp_filesystem->has($this->get_temp_dir_handler())) {
|
423 |
+
//.dir exists, we presume we have files to iterate
|
424 |
+
$content = $this->tmp_filesystem->read($this->get_temp_dir_handler());
|
425 |
+
$files = array_filter(explode("\n", $content));
|
426 |
+
$this->tmp_filesystem->delete($this->get_temp_dir_handler());
|
427 |
+
|
428 |
+
$counter = 0;
|
429 |
+
foreach ($files as $file) {
|
430 |
+
if ($counter < $this->folders_to_process_per_session) {
|
431 |
+
$this->build_files_list($file);
|
432 |
+
$counter++;
|
433 |
+
} else {
|
434 |
+
$this->tmp_filesystem_append->write($this->get_temp_dir_handler(), $file . "\n");
|
435 |
+
}
|
436 |
+
}
|
437 |
+
} else {
|
438 |
+
$this->build_files_list();
|
439 |
+
}
|
440 |
+
|
441 |
+
if ($this->scan_finished()) {
|
442 |
+
$metadata_dumpfile = $this->get_tmp_filesystem()->getMetadata("index.html");
|
443 |
+
$this->store_file($metadata_dumpfile, 'tmp_filesystem');
|
444 |
+
$this->files_counter++;
|
445 |
+
|
446 |
+
//adding included dump file to the included files list
|
447 |
+
if ($this->get_tmp_filesystem()->has($this->get_included_files_handler())) {
|
448 |
+
$metadata_dumpfile = $this->get_tmp_filesystem()->getMetadata($this->get_included_files_handler());
|
449 |
+
$this->store_file($metadata_dumpfile, 'tmp_filesystem');
|
450 |
+
$this->files_counter++;
|
451 |
+
}
|
452 |
+
|
453 |
+
//adding a default index.html to the temp xcloner folder
|
454 |
+
if (!$this->get_tmp_filesystem()->has("index.html")) {
|
455 |
+
$this->get_tmp_filesystem()->write("index.html", "");
|
456 |
+
}
|
457 |
+
|
458 |
+
//adding the default log file
|
459 |
+
if ($this->get_tmp_filesystem()->has($this->xcloner_settings->get_logger_filename(1))) {
|
460 |
+
$metadata_dumpfile = $this->get_tmp_filesystem()->getMetadata($this->xcloner_settings->get_logger_filename(1));
|
461 |
+
$this->store_file($metadata_dumpfile, 'tmp_filesystem');
|
462 |
+
$this->files_counter++;
|
463 |
+
}
|
464 |
+
|
465 |
+
return false;
|
466 |
+
}
|
467 |
+
|
468 |
+
return true;
|
469 |
+
}
|
470 |
+
|
471 |
+
public function get_backup_attachments()
|
472 |
+
{
|
473 |
+
$return = array();
|
474 |
+
|
475 |
+
$files_list_file = $this->xcloner_settings->get_xcloner_tmp_path() . DS . $this->get_included_files_handler();
|
476 |
+
if (file_exists($files_list_file)) {
|
477 |
+
$return[] = $files_list_file;
|
478 |
+
}
|
479 |
+
|
480 |
+
if ($this->xcloner_settings->get_xcloner_option('xcloner_enable_log')) {
|
481 |
+
$log_file = $this->xcloner_settings->get_xcloner_tmp_path() . DS . $this->xcloner_settings->get_logger_filename(1);
|
482 |
+
if (!file_exists($log_file)) {
|
483 |
+
$log_file = $this->xcloner_settings->get_xcloner_store_path() . DS . $this->xcloner_settings->get_logger_filename();
|
484 |
+
}
|
485 |
+
|
486 |
+
if (file_exists($log_file)) {
|
487 |
+
$return[] = $log_file;
|
488 |
+
}
|
489 |
+
}
|
490 |
+
|
491 |
+
return $return;
|
492 |
+
}
|
493 |
+
|
494 |
+
public function remove_tmp_filesystem()
|
495 |
+
{
|
496 |
+
//delete the temporary folder
|
497 |
+
$this->logger->debug(sprintf("Deleting the temporary storage folder %s",
|
498 |
+
$this->xcloner_settings->get_xcloner_tmp_path()));
|
499 |
+
|
500 |
+
$contents = $this->get_tmp_filesystem()->listContents();
|
501 |
+
|
502 |
+
if (is_array($contents)) {
|
503 |
+
foreach ($contents as $file_info) {
|
504 |
+
$this->get_tmp_filesystem()->delete($file_info['path']);
|
505 |
+
}
|
506 |
+
}
|
507 |
+
|
508 |
+
@rmdir($this->xcloner_settings->get_xcloner_tmp_path());
|
509 |
+
|
510 |
+
return;
|
511 |
+
}
|
512 |
+
|
513 |
+
public function cleanup_tmp_directories()
|
514 |
+
{
|
515 |
+
$adapter = new Local($this->xcloner_settings->get_xcloner_tmp_path(false), LOCK_EX | FILE_APPEND, 'SKIP_LINKS');
|
516 |
+
$tmp_filesystem = new Filesystem($adapter, new Config([
|
517 |
+
'disable_asserts' => true,
|
518 |
+
]));
|
519 |
+
|
520 |
+
$contents = $tmp_filesystem->listContents();
|
521 |
+
|
522 |
+
foreach ($contents as $file) {
|
523 |
+
|
524 |
+
if (preg_match("/.xcloner-(.*)/", $file['path'])) {
|
525 |
+
if ($file['timestamp'] < strtotime("-1days")) {
|
526 |
+
$tmp_filesystem->deleteDir($file['path']);
|
527 |
+
$this->logger->debug(sprintf("Delete temporary directory %s", $file['path']));
|
528 |
+
}
|
529 |
+
}
|
530 |
+
}
|
531 |
+
|
532 |
+
return true;
|
533 |
+
}
|
534 |
+
|
535 |
+
private function do_system_init()
|
536 |
+
{
|
537 |
+
$this->files_counter = 0;
|
538 |
+
|
539 |
+
if (!$this->storage_filesystem->has("index.html")) {
|
540 |
+
$this->storage_filesystem->write("index.html", "");
|
541 |
+
}
|
542 |
+
|
543 |
+
if (!$this->tmp_filesystem->has("index.html")) {
|
544 |
+
$this->tmp_filesystem->write("index.html", "");
|
545 |
+
}
|
546 |
+
|
547 |
+
if ($this->tmp_filesystem->has($this->get_included_files_handler())) {
|
548 |
+
$this->tmp_filesystem->delete($this->get_included_files_handler());
|
549 |
+
}
|
550 |
+
|
551 |
+
if ($this->tmp_filesystem->has($this->get_temp_dir_handler())) {
|
552 |
+
$this->tmp_filesystem->delete($this->get_temp_dir_handler());
|
553 |
+
}
|
554 |
+
}
|
555 |
+
|
556 |
+
public function get_scanned_files_num()
|
557 |
+
{
|
558 |
+
return $this->files_counter;
|
559 |
+
}
|
560 |
+
|
561 |
+
public function get_scanned_files_total_size()
|
562 |
+
{
|
563 |
+
return $this->files_size;
|
564 |
+
}
|
565 |
+
|
566 |
+
public function last_logged_file()
|
567 |
+
{
|
568 |
+
return $this->last_logged_file;
|
569 |
+
}
|
570 |
+
|
571 |
+
public static function is_regex($regex)
|
572 |
+
{
|
573 |
+
return preg_match("/^\^(.*)\$$/i", $regex);
|
574 |
+
}
|
575 |
+
|
576 |
+
public function set_excluded_files($excluded_files = array())
|
577 |
+
{
|
578 |
+
if (!is_array($excluded_files)) {
|
579 |
+
$excluded_files = array();
|
580 |
+
}
|
581 |
+
|
582 |
+
foreach ($excluded_files as $excl) {
|
583 |
+
|
584 |
+
if ($this->is_regex($excl)) {
|
585 |
+
$this->additional_regex_patterns[] = $excl;
|
586 |
+
}
|
587 |
+
}
|
588 |
+
|
589 |
+
$this->excluded_files = array_merge($excluded_files, $this->excluded_files_by_default);
|
590 |
+
|
591 |
+
return $this->excluded_files;
|
592 |
+
}
|
593 |
+
|
594 |
+
public function get_excluded_files()
|
595 |
+
{
|
596 |
+
return $this->excluded_files_by_default;
|
597 |
+
}
|
598 |
+
|
599 |
+
public function list_directory($path)
|
600 |
+
{
|
601 |
+
return $this->start_filesystem->listContents($path);
|
602 |
+
}
|
603 |
+
|
604 |
+
public function build_files_list($folder = "")
|
605 |
+
{
|
606 |
+
$this->logger->debug(sprintf(("Building the files system list")));
|
607 |
+
|
608 |
+
//if we start with the root folder(empty value), we initializa the file system
|
609 |
+
if (!$folder) {
|
610 |
+
|
611 |
+
}
|
612 |
+
|
613 |
+
try {
|
614 |
+
|
615 |
+
$files = $this->start_filesystem->listContents($folder);
|
616 |
+
foreach ($files as $file) {
|
617 |
+
if (!is_readable($this->xcloner_settings->get_xcloner_start_path() . DS . $file['path'])) {
|
618 |
+
$this->logger->info(sprintf(__("Excluding %s from the filesystem list, file not readable"),
|
619 |
+
$file['path']), array(
|
620 |
+
"FILESYSTEM SCAN",
|
621 |
+
"NOT READABLE"
|
622 |
+
));
|
623 |
+
} elseif (!$matching_pattern = $this->is_excluded($file)) {
|
624 |
+
$this->logger->info(sprintf(__("Adding %s to the filesystem list"), $file['path']), array(
|
625 |
+
"FILESYSTEM SCAN",
|
626 |
+
"INCLUDE"
|
627 |
+
));
|
628 |
+
$file['visibility'] = $this->start_filesystem->getVisibility($file['path']);
|
629 |
+
if ($this->store_file($file)) {
|
630 |
+
$this->files_counter++;
|
631 |
+
}
|
632 |
+
if (isset($file['size'])) {
|
633 |
+
$this->files_size += $file['size'];
|
634 |
+
}
|
635 |
+
|
636 |
+
} else {
|
637 |
+
$this->logger->info(sprintf(__("Excluding %s from the filesystem list, matching pattern %s"),
|
638 |
+
$file['path'], $matching_pattern), array(
|
639 |
+
"FILESYSTEM SCAN",
|
640 |
+
"EXCLUDE"
|
641 |
+
));
|
642 |
+
}
|
643 |
+
}
|
644 |
+
|
645 |
+
} catch (Exception $e) {
|
646 |
+
|
647 |
+
$this->logger->error($e->getMessage());
|
648 |
+
|
649 |
+
}
|
650 |
+
|
651 |
+
}
|
652 |
+
|
653 |
+
public function estimate_read_write_time()
|
654 |
+
{
|
655 |
+
$tmp_file = ".xcloner" . substr(md5(time()), 0, 5);
|
656 |
+
|
657 |
+
$start_time = microtime(true);
|
658 |
+
|
659 |
+
$data = str_repeat(rand(0, 9), 1024 * 1024); //write 1MB data
|
660 |
+
|
661 |
+
try {
|
662 |
+
$this->tmp_filesystem->write($tmp_file, $data);
|
663 |
+
|
664 |
+
$end_time = microtime(true) - $start_time;
|
665 |
+
|
666 |
+
$return['writing_time'] = $end_time;
|
667 |
+
|
668 |
+
$return['reading_time'] = $this->estimate_reading_time($tmp_file);
|
669 |
+
|
670 |
+
$this->tmp_filesystem->delete($tmp_file);
|
671 |
+
|
672 |
+
} catch (Exception $e) {
|
673 |
+
|
674 |
+
$this->logger->error($e->getMessage());
|
675 |
+
|
676 |
+
}
|
677 |
+
|
678 |
+
return $return;
|
679 |
+
}
|
680 |
+
|
681 |
+
public function backup_storage_cleanup()
|
682 |
+
{
|
683 |
+
$this->logger->info(sprintf(("Cleaning the backup storage on matching rules")));
|
684 |
+
|
685 |
+
$_storage_size = 0;
|
686 |
+
$_backup_files_list = array();
|
687 |
+
|
688 |
+
//rule date limit
|
689 |
+
$current_timestamp = strtotime("-" . $this->xcloner_settings->get_xcloner_option('xcloner_cleanup_retention_limit_days') . " days");
|
690 |
+
|
691 |
+
$files = $this->storage_filesystem->listContents();
|
692 |
+
|
693 |
+
if (is_array($files)) {
|
694 |
+
foreach ($files as $file) {
|
695 |
+
if (isset($file['extension']) and in_array($file['extension'], $this->backup_archive_extensions)) {
|
696 |
+
$_storage_size += $file['size']; //bytes
|
697 |
+
$_backup_files_list[] = $file;
|
698 |
+
}
|
699 |
+
}
|
700 |
+
}
|
701 |
+
|
702 |
+
|
703 |
+
$this->sort_by($_backup_files_list, "timestamp", "asc");
|
704 |
+
|
705 |
+
$_backups_counter = sizeof($_backup_files_list);
|
706 |
+
|
707 |
+
foreach ($_backup_files_list as $file) {
|
708 |
+
//processing rule folder capacity
|
709 |
+
if ($this->xcloner_settings->get_xcloner_option('xcloner_cleanup_capacity_limit') &&
|
710 |
+
$_storage_size >= ($set_storage_limit = 1024 * 1024 * $this->xcloner_settings->get_xcloner_option('xcloner_cleanup_capacity_limit'))) //bytes
|
711 |
+
{
|
712 |
+
$this->storage_filesystem->delete($file['path']);
|
713 |
+
$_storage_size -= $file['size'];
|
714 |
+
$this->logger->info("Deleting backup " . $file['path'] . " matching rule", array(
|
715 |
+
"STORAGE SIZE LIMIT",
|
716 |
+
$_storage_size . " >= " . $set_storage_limit
|
717 |
+
));
|
718 |
+
}
|
719 |
+
|
720 |
+
//processing rule days limit
|
721 |
+
if ($this->xcloner_settings->get_xcloner_option('xcloner_cleanup_retention_limit_days') && $current_timestamp >= $file['timestamp']) {
|
722 |
+
$this->storage_filesystem->delete($file['path']);
|
723 |
+
$this->logger->info("Deleting backup " . $file['path'] . " matching rule", array(
|
724 |
+
"RETENTION LIMIT TIMESTAMP",
|
725 |
+
$file['timestamp'] . " =< " . $this->xcloner_settings->get_xcloner_option('xcloner_cleanup_retention_limit_days')
|
726 |
+
));
|
727 |
+
}
|
728 |
+
|
729 |
+
//processing backup countert limit
|
730 |
+
if ($this->xcloner_settings->get_xcloner_option('xcloner_cleanup_retention_limit_archives') && $_backups_counter >= $this->xcloner_settings->get_xcloner_option('xcloner_cleanup_retention_limit_archives')) {
|
731 |
+
$this->storage_filesystem->delete($file['path']);
|
732 |
+
$_backups_counter--;
|
733 |
+
$this->logger->info("Deleting backup " . $file['path'] . " matching rule", array(
|
734 |
+
"BACKUP QUANTITY LIMIT",
|
735 |
+
$_backups_counter . " >= " . $this->xcloner_settings->get_xcloner_option('xcloner_cleanup_retention_limit_archives')
|
736 |
+
));
|
737 |
+
}
|
738 |
+
|
739 |
+
|
740 |
+
}
|
741 |
+
|
742 |
+
}
|
743 |
+
|
744 |
+
public function estimate_reading_time($tmp_file)
|
745 |
+
{
|
746 |
+
$this->logger->debug(sprintf(("Estimating file system reading time")));
|
747 |
+
|
748 |
+
$start_time = microtime(true);
|
749 |
+
|
750 |
+
if ($this->tmp_filesystem->has($tmp_file)) {
|
751 |
+
$this->tmp_filesystem->read($tmp_file);
|
752 |
+
}
|
753 |
+
|
754 |
+
$end_time = microtime(true) - $start_time;
|
755 |
+
|
756 |
+
return $end_time;
|
757 |
+
|
758 |
+
}
|
759 |
+
|
760 |
+
public function process_backup_name($name = "", $max_length = 100)
|
761 |
+
{
|
762 |
+
if (!$name) {
|
763 |
+
$name = $this->xcloner_settings->get_default_backup_name();
|
764 |
+
}
|
765 |
+
|
766 |
+
foreach ($this->backup_name_tags as $tag) {
|
767 |
+
if ($tag == '[time]') {
|
768 |
+
$name = str_replace($tag, date("Y-m-d_H-i"), $name);
|
769 |
+
} elseif ($tag == '[hostname]') {
|
770 |
+
$name = str_replace($tag, gethostname(), $name);
|
771 |
+
} elseif ($tag == '[domain]') {
|
772 |
+
$domain = parse_url(admin_url(), PHP_URL_HOST);
|
773 |
+
$name = str_replace($tag, $domain, $name);
|
774 |
+
}
|
775 |
+
}
|
776 |
+
|
777 |
+
if ($max_length) {
|
778 |
+
$name = substr($name, 0, $max_length);
|
779 |
+
}
|
780 |
+
|
781 |
+
return $name;
|
782 |
+
}
|
783 |
+
|
784 |
+
public function sort_by(&$array, $field, $direction = 'asc')
|
785 |
+
{
|
786 |
+
if (strtolower($direction) == "desc" || $direction == SORT_DESC) {
|
787 |
+
$direction = SORT_DESC;
|
788 |
+
} else {
|
789 |
+
$direction = SORT_ASC;
|
790 |
+
}
|
791 |
+
|
792 |
+
$array = $this->array_orderby($array, $field, $direction);
|
793 |
+
|
794 |
+
return true;
|
795 |
+
}
|
796 |
+
|
797 |
+
private function array_orderby()
|
798 |
+
{
|
799 |
+
$args = func_get_args();
|
800 |
+
$data = array_shift($args);
|
801 |
+
|
802 |
+
foreach ($args as $n => $field) {
|
803 |
+
if (is_string($field)) {
|
804 |
+
$tmp = array();
|
805 |
+
foreach ($data as $key => $row) {
|
806 |
+
if (is_array($row)) {
|
807 |
+
$tmp[$key] = $row[$field];
|
808 |
+
} else {
|
809 |
+
$tmp[$key] = $row->$field;
|
810 |
+
}
|
811 |
+
}
|
812 |
+
$args[$n] = $tmp;
|
813 |
+
}
|
814 |
+
}
|
815 |
+
$args[] = &$data;
|
816 |
+
|
817 |
+
call_user_func_array('array_multisort', $args);
|
818 |
+
|
819 |
+
return array_pop($args);
|
820 |
+
}
|
821 |
+
|
822 |
+
private function check_file_diff_time($file)
|
823 |
+
{
|
824 |
+
if ($this->get_diff_timestamp_start() != "") {
|
825 |
+
$fileMeta = $this->getMetadataFull("start_adapter", $file['path']);
|
826 |
+
$timestamp = $fileMeta->getMTime();
|
827 |
+
if ($timestamp < $fileMeta->getCTime()) {
|
828 |
+
$timestamp = $fileMeta->getCTime();
|
829 |
+
}
|
830 |
+
|
831 |
+
if ($timestamp <= $this->get_diff_timestamp_start()) {
|
832 |
+
return " file DIFF timestamp " . $timestamp . " < " . $this->diff_timestamp_start;
|
833 |
+
}
|
834 |
+
}
|
835 |
+
|
836 |
+
return false;
|
837 |
+
}
|
838 |
+
|
839 |
+
public function is_excluded($file)
|
840 |
+
{
|
841 |
+
$this->logger->debug(sprintf(("Checking if %s is excluded"), $file['path']));
|
842 |
+
|
843 |
+
if ($xcloner_exclude_files_larger_than_mb = $this->xcloner_settings->get_xcloner_option('xcloner_exclude_files_larger_than_mb')) {
|
844 |
+
if (isset($file['size']) && $file['size'] > $this->calc_to_bytes($xcloner_exclude_files_larger_than_mb)) {
|
845 |
+
return "> " . $xcloner_exclude_files_larger_than_mb . "MB";
|
846 |
+
}
|
847 |
+
}
|
848 |
+
|
849 |
+
if (!is_array($this->excluded_files) || !sizeof($this->excluded_files)) {
|
850 |
+
$this->set_excluded_files();
|
851 |
+
}
|
852 |
+
|
853 |
+
if (is_array($this->excluded_files)) {
|
854 |
+
foreach ($this->excluded_files as $excluded_file_pattern) {
|
855 |
+
if ($excluded_file_pattern == "/") {
|
856 |
+
$needle = "$";
|
857 |
+
} else {
|
858 |
+
$needle = "$" . $excluded_file_pattern;
|
859 |
+
}
|
860 |
+
|
861 |
+
if (strstr("$" . $file['path'], $needle)) {
|
862 |
+
return $excluded_file_pattern;
|
863 |
+
}
|
864 |
+
}
|
865 |
+
}
|
866 |
+
|
867 |
+
if ($regex = $this->is_excluded_regex($file)) {
|
868 |
+
return $regex;
|
869 |
+
}
|
870 |
+
|
871 |
+
if ($file['type'] == "file") {
|
872 |
+
$check_file_diff_timestamp = $this->check_file_diff_time($file);
|
873 |
+
if ($check_file_diff_timestamp) {
|
874 |
+
return $check_file_diff_timestamp;
|
875 |
+
}
|
876 |
+
}
|
877 |
+
|
878 |
+
return false;
|
879 |
+
}
|
880 |
+
|
881 |
+
/*REGEX examples
|
882 |
+
*
|
883 |
+
* exclude all except .php file
|
884 |
+
* PATTERN: ^(.*)\.(.+)$(?<!(php))
|
885 |
+
*
|
886 |
+
* exclude all except .php and .txt
|
887 |
+
* PATTERN: ^(.*)\.(.+)$(?<!(php|txt))";
|
888 |
+
*
|
889 |
+
* exclude all .svn and .git
|
890 |
+
* PATTERN: ^(.*)\.(svn|git)(.*)$";
|
891 |
+
*
|
892 |
+
* exclude root directory /test
|
893 |
+
* PATTERN: "^\/test(.*)$";
|
894 |
+
*
|
895 |
+
* exclude the wp-admin folder
|
896 |
+
* PATTERN: ^(\/wp-admin)(.*)$";
|
897 |
+
*
|
898 |
+
* exclude the wp-admin, wp-includes and wp-config.php
|
899 |
+
* PATTERN: ^\/(wp-admin|wp-includes|wp-config.php)(.*)$";
|
900 |
+
*
|
901 |
+
* exclude all .avi files
|
902 |
+
* PATTERN: ^(.*)$(?<=(avi))";
|
903 |
+
*
|
904 |
+
* exclude all .jpg and gif files
|
905 |
+
* PATTERN: ^(.*)$(?<=(gif|jpg))";
|
906 |
+
*
|
907 |
+
* exclude all cache folders from wp-content/
|
908 |
+
* PATTERN: ^\/wp-content(.*)\/cache($|\/)(.*)";
|
909 |
+
*
|
910 |
+
* exclude the backup folders
|
911 |
+
* PATTERN: (^|^\/)(wp-content\/backups|administrator\/backups)(.*)$";
|
912 |
+
*/
|
913 |
+
private function is_excluded_regex($file)
|
914 |
+
{
|
915 |
+
//$this->logger->debug(sprintf(("Checking if %s is excluded"), $file['path']));
|
916 |
+
|
917 |
+
$regex_patterns = explode(PHP_EOL, $this->xcloner_settings->get_xcloner_option('xcloner_regex_exclude'));
|
918 |
+
|
919 |
+
if (is_array($this->additional_regex_patterns)) {
|
920 |
+
$regex_patterns = array_merge($regex_patterns, $this->additional_regex_patterns);
|
921 |
+
}
|
922 |
+
|
923 |
+
//print_r($regex_patterns);exit;
|
924 |
+
|
925 |
+
if (is_array($regex_patterns)) {
|
926 |
+
//$this->excluded_files = array();
|
927 |
+
//$this->excluded_files[] ="(.*)\.(git)(.*)$";
|
928 |
+
//$this->excluded_files[] ="wp-content\/backups(.*)$";
|
929 |
+
|
930 |
+
foreach ($regex_patterns as $excluded_file_pattern) {
|
931 |
+
|
932 |
+
if (substr($excluded_file_pattern, strlen($excluded_file_pattern) - 1,
|
933 |
+
strlen($excluded_file_pattern)) == "\r") {
|
934 |
+
$excluded_file_pattern = substr($excluded_file_pattern, 0, strlen($excluded_file_pattern) - 1);
|
935 |
+
}
|
936 |
+
|
937 |
+
if ($file['path'] == "/") {
|
938 |
+
$needle = "/";
|
939 |
+
} else {
|
940 |
+
$needle = "/" . $file['path'];
|
941 |
+
}
|
942 |
+
//echo $needle."---".$excluded_file_pattern."---\n";
|
943 |
+
|
944 |
+
if (@preg_match("/(^|^\/)" . $excluded_file_pattern . "/i", $needle)) {
|
945 |
+
return $excluded_file_pattern;
|
946 |
+
}
|
947 |
+
}
|
948 |
+
}
|
949 |
+
|
950 |
+
return false;
|
951 |
+
}
|
952 |
+
|
953 |
+
public function store_file($file, $storage = 'start_filesystem')
|
954 |
+
{
|
955 |
+
$this->logger->debug(sprintf("Storing %s in the backup list", $file['path']));
|
956 |
+
|
957 |
+
if (!isset($file['size'])) {
|
958 |
+
$file['size'] = 0;
|
959 |
+
}
|
960 |
+
if (!isset($file['visibility'])) {
|
961 |
+
$file['visibility'] = "private";
|
962 |
+
}
|
963 |
+
|
964 |
+
$csv_filename = str_replace('"', '""', $file['path']);
|
965 |
+
|
966 |
+
$line = '"' . ($csv_filename) . '","' . $file['timestamp'] . '","' . $file['size'] . '","' . $file['visibility'] . '","' . $storage . '"' . PHP_EOL;
|
967 |
+
|
968 |
+
$this->last_logged_file = $file['path'];
|
969 |
+
|
970 |
+
if ($file['type'] == "dir") {
|
971 |
+
try {
|
972 |
+
$this->tmp_filesystem_append->write($this->get_temp_dir_handler(), $file['path'] . "\n");
|
973 |
+
} catch (Exception $e) {
|
974 |
+
$this->logger->error($e->getMessage());
|
975 |
+
}
|
976 |
+
}
|
977 |
+
|
978 |
+
if ($this->get_diff_timestamp_start()) {
|
979 |
+
if ($file['type'] != "file" && $response = $this->check_file_diff_time($file)) {
|
980 |
+
$this->logger->info(sprintf("Directory %s archiving skipped on differential backup %s", $file['path'],
|
981 |
+
$response), array(
|
982 |
+
"FILESYSTEM SCAN",
|
983 |
+
"DIR DIFF"
|
984 |
+
));
|
985 |
+
|
986 |
+
return false;
|
987 |
+
}
|
988 |
+
}
|
989 |
+
|
990 |
+
try {
|
991 |
+
if (!$this->tmp_filesystem_append->has($this->get_included_files_handler())) {
|
992 |
+
//adding fix for UTF-8 CSV preview
|
993 |
+
$start_line = "\xEF\xBB\xBF" . '"Filename","Timestamp","Size","Visibility","Storage"' . PHP_EOL;
|
994 |
+
$this->tmp_filesystem_append->write($this->get_included_files_handler(), $start_line);
|
995 |
+
}
|
996 |
+
|
997 |
+
$this->tmp_filesystem_append->write($this->get_included_files_handler(), $line);
|
998 |
+
|
999 |
+
} catch (Exception $e) {
|
1000 |
+
|
1001 |
+
$this->logger->error($e->getMessage());
|
1002 |
+
}
|
1003 |
+
|
1004 |
+
return true;
|
1005 |
+
}
|
1006 |
+
|
1007 |
+
public function get_fileystem_handler()
|
1008 |
+
{
|
1009 |
+
return $this;
|
1010 |
+
}
|
1011 |
+
|
1012 |
+
public function get_filesystem($system = "")
|
1013 |
+
{
|
1014 |
+
if ($system == "storage_filesystem_append") {
|
1015 |
+
return $this->storage_filesystem_append;
|
1016 |
+
} elseif ($system == "tmp_filesystem_append") {
|
1017 |
+
return $this->tmp_filesystem_append;
|
1018 |
+
} elseif ($system == "tmp_filesystem") {
|
1019 |
+
return $this->tmp_filesystem;
|
1020 |
+
} elseif ($system == "storage_filesystem") {
|
1021 |
+
return $this->storage_filesystem;
|
1022 |
+
} else {
|
1023 |
+
return $this->start_filesystem;
|
1024 |
+
}
|
1025 |
+
}
|
1026 |
+
|
1027 |
+
public function get_adapter($system)
|
1028 |
+
{
|
1029 |
+
if ($system == "tmp_filesystem") {
|
1030 |
+
return $this->tmp_adapter;
|
1031 |
+
} elseif ($system == "storage_filesystem") {
|
1032 |
+
return $this->storage_adapter;
|
1033 |
+
} else {
|
1034 |
+
return $this->start_adapter;
|
1035 |
+
}
|
1036 |
+
}
|
1037 |
+
|
1038 |
+
/**
|
1039 |
+
* File scan finished
|
1040 |
+
* Method called when file scan is finished
|
1041 |
+
*
|
1042 |
+
* @return bool
|
1043 |
+
*/
|
1044 |
+
private function scan_finished()
|
1045 |
+
{
|
1046 |
+
if ($this->tmp_filesystem_append->has($this->get_temp_dir_handler()) &&
|
1047 |
+
$this->tmp_filesystem_append->getSize($this->get_temp_dir_handler())) {
|
1048 |
+
return false;
|
1049 |
+
}
|
1050 |
+
|
1051 |
+
if ($this->tmp_filesystem->has($this->get_temp_dir_handler())) {
|
1052 |
+
$this->tmp_filesystem->delete($this->get_temp_dir_handler());
|
1053 |
+
}
|
1054 |
+
|
1055 |
+
$this->logger->debug(sprintf(("File scan finished")));
|
1056 |
+
|
1057 |
+
return true;
|
1058 |
+
}
|
1059 |
+
|
1060 |
+
/**
|
1061 |
+
* Calculate bytes from MB value
|
1062 |
+
*
|
1063 |
+
* @param int $mb_size
|
1064 |
+
*
|
1065 |
+
* @return float|int
|
1066 |
+
*/
|
1067 |
+
private function calc_to_bytes($mb_size)
|
1068 |
+
{
|
1069 |
+
return $mb_size * (1024 * 1024);
|
1070 |
+
}
|
1071 |
+
|
1072 |
}
|
includes/class-xcloner-file-transfer.php
CHANGED
@@ -1,102 +1,164 @@
|
|
1 |
<?php
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
|
3 |
-
class Xcloner_File_Transfer extends Xcloner_File_System
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
57 |
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
|
58 |
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 60);
|
59 |
curl_setopt($ch, CURLOPT_TIMEOUT, 1200);
|
60 |
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
102 |
}
|
1 |
<?php
|
2 |
+
/**
|
3 |
+
* XCloner - Backup and Restore backup plugin for Wordpress
|
4 |
+
*
|
5 |
+
* class-xcloner-file-transfer.php
|
6 |
+
* @author Liuta Ovidiu <info@thinkovi.com>
|
7 |
+
*
|
8 |
+
* This program is free software; you can redistribute it and/or modify
|
9 |
+
* it under the terms of the GNU General Public License as published by
|
10 |
+
* the Free Software Foundation; either version 2 of the License, or
|
11 |
+
* (at your option) any later version.
|
12 |
+
*
|
13 |
+
* This program is distributed in the hope that it will be useful,
|
14 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16 |
+
* GNU General Public License for more details.
|
17 |
+
*
|
18 |
+
* You should have received a copy of the GNU General Public License
|
19 |
+
* along with this program; if not, write to the Free Software
|
20 |
+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
21 |
+
* MA 02110-1301, USA.
|
22 |
+
*
|
23 |
+
* @link https://github.com/ovidiul/XCloner-Wordpress
|
24 |
+
*
|
25 |
+
* @modified 7/25/18 1:46 PM
|
26 |
+
*
|
27 |
+
*/
|
28 |
|
29 |
+
class Xcloner_File_Transfer extends Xcloner_File_System
|
30 |
+
{
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Target url web address of the restore script
|
34 |
+
* @var string
|
35 |
+
*/
|
36 |
+
private $target_url;
|
37 |
+
/**
|
38 |
+
* Transfer data limit in bytes
|
39 |
+
* @var int
|
40 |
+
*/
|
41 |
+
private $transfer_limit = 1048576; //bytes 1MB= 1048576 300KB = 358400
|
42 |
+
|
43 |
+
|
44 |
+
/**
|
45 |
+
* @param $target_url
|
46 |
+
*
|
47 |
+
* @return mixed
|
48 |
+
*/
|
49 |
+
public function set_target($target_url)
|
50 |
+
{
|
51 |
+
return $this->target_url = $target_url;
|
52 |
+
}
|
53 |
+
|
54 |
+
/**
|
55 |
+
* @return mixed
|
56 |
+
*/
|
57 |
+
public function get_target()
|
58 |
+
{
|
59 |
+
return $this->target_url;
|
60 |
+
}
|
61 |
+
|
62 |
+
|
63 |
+
/**
|
64 |
+
* @param $file
|
65 |
+
* @param int $start
|
66 |
+
* @param string $hash
|
67 |
+
*
|
68 |
+
* @return bool|int
|
69 |
+
* @throws Exception
|
70 |
+
*/
|
71 |
+
public function transfer_file($file, $start = 0, $hash = "")
|
72 |
+
{
|
73 |
+
if (!$this->target_url) {
|
74 |
+
throw new Exception("Please setup a target url for upload");
|
75 |
+
}
|
76 |
+
|
77 |
+
|
78 |
+
$fp = $this->get_storage_filesystem()->readStream($file);
|
79 |
+
|
80 |
+
fseek($fp, $start, SEEK_SET);
|
81 |
+
|
82 |
+
$binary_data = fread($fp, $this->transfer_limit);
|
83 |
+
|
84 |
+
$tmp_filename = "xcloner_upload_" . substr(md5(time()), 0, 5);
|
85 |
+
|
86 |
+
$this->get_tmp_filesystem()->write($tmp_filename, $binary_data);
|
87 |
+
|
88 |
+
$tmp_file_path = $this->get_tmp_filesystem_adapter()->applyPathPrefix($tmp_filename);
|
89 |
+
|
90 |
+
$send_array = array();
|
91 |
+
|
92 |
+
$send_array['file'] = $file;
|
93 |
+
$send_array['start'] = $start;
|
94 |
+
$send_array['xcloner_action'] = "write_file";
|
95 |
+
$send_array['hash'] = $hash;
|
96 |
+
#$send_array['blob'] = $binary_data;
|
97 |
+
$send_array['blob'] = $this->curl_file_create($tmp_file_path, 'application/x-binary', $tmp_filename);
|
98 |
+
|
99 |
+
//$data = http_build_query($send_array);
|
100 |
+
|
101 |
+
$this->get_logger()->info(sprintf("Sending curl request to %s with %s data of file %s starting position %s using temporary file %s",
|
102 |
+
$this->target_url, $this->transfer_limit, $file, $start, $tmp_filename));
|
103 |
+
|
104 |
+
|
105 |
+
$ch = curl_init();
|
106 |
+
curl_setopt($ch, CURLOPT_URL, $this->target_url);
|
107 |
+
|
108 |
+
curl_setopt($ch, CURLOPT_POST, 1);
|
109 |
+
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
|
110 |
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
|
111 |
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 60);
|
112 |
curl_setopt($ch, CURLOPT_TIMEOUT, 1200);
|
113 |
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
114 |
+
|
115 |
+
curl_setopt($ch, CURLOPT_POSTFIELDS, $send_array);
|
116 |
+
curl_setopt($ch, CURLOPT_VERBOSE, true);
|
117 |
+
|
118 |
+
$original_result = curl_exec($ch);
|
119 |
+
|
120 |
+
$this->get_tmp_filesystem()->delete($tmp_filename);
|
121 |
+
|
122 |
+
$result = json_decode($original_result);
|
123 |
+
|
124 |
+
if (!$result) {
|
125 |
+
throw new Exception("We have received no valid response from the remote host, original message: " . $original_result);
|
126 |
+
}
|
127 |
+
|
128 |
+
if ($result->status != 200) {
|
129 |
+
throw new Exception($result->response);
|
130 |
+
}
|
131 |
+
|
132 |
+
if (ftell($fp) >= $this->get_storage_filesystem()->getSize($file)) {
|
133 |
+
$this->get_logger()->info(sprintf("Upload done for file %s to target url %s, transferred a total of %s bytes",
|
134 |
+
$file, $this->target_url, ftell($fp)));
|
135 |
+
$this->remove_tmp_filesystem();
|
136 |
+
|
137 |
+
return false;
|
138 |
+
}
|
139 |
+
|
140 |
+
return ftell($fp);
|
141 |
+
}
|
142 |
+
|
143 |
+
/**
|
144 |
+
* @param $filename
|
145 |
+
* @param string $mimetype
|
146 |
+
* @param string $postname
|
147 |
+
*
|
148 |
+
* @return CURLFile|string
|
149 |
+
*/
|
150 |
+
private function curl_file_create($filename, $mimetype = '', $postname = '')
|
151 |
+
{
|
152 |
+
if (!function_exists('curl_file_create')) {
|
153 |
+
|
154 |
+
return "@$filename;filename="
|
155 |
+
. ($postname ?: basename($filename))
|
156 |
+
. ($mimetype ? ";type=$mimetype" : '');
|
157 |
+
|
158 |
+
} else {
|
159 |
+
|
160 |
+
return curl_file_create($filename, $mimetype, $postname);
|
161 |
+
|
162 |
+
}
|
163 |
+
}
|
164 |
}
|
includes/class-xcloner-i18n.php
CHANGED
@@ -1,18 +1,32 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
/**
|
4 |
-
*
|
5 |
*
|
6 |
-
*
|
7 |
-
*
|
8 |
*
|
9 |
-
*
|
10 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
*
|
12 |
-
* @package Xcloner
|
13 |
-
* @subpackage Xcloner/includes
|
14 |
*/
|
15 |
|
|
|
16 |
/**
|
17 |
* Define the internationalization functionality.
|
18 |
*
|
@@ -24,24 +38,24 @@
|
|
24 |
* @subpackage Xcloner/includes
|
25 |
* @author Liuta Ovidiu <info@thinkovi.com>
|
26 |
*/
|
27 |
-
class Xcloner_i18n
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
|
46 |
|
47 |
}
|
1 |
<?php
|
|
|
2 |
/**
|
3 |
+
* XCloner - Backup and Restore backup plugin for Wordpress
|
4 |
*
|
5 |
+
* class-xcloner-i18n.php
|
6 |
+
* @author Liuta Ovidiu <info@thinkovi.com>
|
7 |
*
|
8 |
+
* This program is free software; you can redistribute it and/or modify
|
9 |
+
* it under the terms of the GNU General Public License as published by
|
10 |
+
* the Free Software Foundation; either version 2 of the License, or
|
11 |
+
* (at your option) any later version.
|
12 |
+
*
|
13 |
+
* This program is distributed in the hope that it will be useful,
|
14 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16 |
+
* GNU General Public License for more details.
|
17 |
+
*
|
18 |
+
* You should have received a copy of the GNU General Public License
|
19 |
+
* along with this program; if not, write to the Free Software
|
20 |
+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
21 |
+
* MA 02110-1301, USA.
|
22 |
+
*
|
23 |
+
* @link https://github.com/ovidiul/XCloner-Wordpress
|
24 |
+
*
|
25 |
+
* @modified 7/25/18 1:46 PM
|
26 |
*
|
|
|
|
|
27 |
*/
|
28 |
|
29 |
+
|
30 |
/**
|
31 |
* Define the internationalization functionality.
|
32 |
*
|
38 |
* @subpackage Xcloner/includes
|
39 |
* @author Liuta Ovidiu <info@thinkovi.com>
|
40 |
*/
|
41 |
+
class Xcloner_i18n
|
42 |
+
{
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Load the plugin text domain for translation.
|
46 |
+
*
|
47 |
+
* @since 1.0.0
|
48 |
+
*/
|
49 |
+
public function load_plugin_textdomain()
|
50 |
+
{
|
51 |
+
|
52 |
+
load_plugin_textdomain(
|
53 |
+
'xcloner-backup-and-restore',
|
54 |
+
false,
|
55 |
+
dirname(dirname(plugin_basename(__FILE__))) . '/languages/'
|
56 |
+
);
|
57 |
+
|
58 |
+
}
|
59 |
|
60 |
|
61 |
}
|
includes/class-xcloner-loader.php
CHANGED
@@ -1,15 +1,32 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
/**
|
4 |
-
*
|
5 |
*
|
6 |
-
*
|
7 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8 |
*
|
9 |
-
* @package Xcloner
|
10 |
-
* @subpackage Xcloner/includes
|
11 |
*/
|
12 |
|
|
|
13 |
/**
|
14 |
* Register all actions and filters for the plugin.
|
15 |
*
|
@@ -21,132 +38,157 @@
|
|
21 |
* @subpackage Xcloner/includes
|
22 |
* @author Liuta Ovidiu <info@thinkovi.com>
|
23 |
*/
|
24 |
-
class Xcloner_Loader
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
152 |
}
|
1 |
<?php
|
|
|
2 |
/**
|
3 |
+
* XCloner - Backup and Restore backup plugin for Wordpress
|
4 |
*
|
5 |
+
* class-xcloner-loader.php
|
6 |
+
* @author Liuta Ovidiu <info@thinkovi.com>
|
7 |
+
*
|
8 |
+
* This program is free software; you can redistribute it and/or modify
|
9 |
+
* it under the terms of the GNU General Public License as published by
|
10 |
+
* the Free Software Foundation; either version 2 of the License, or
|
11 |
+
* (at your option) any later version.
|
12 |
+
*
|
13 |
+
* This program is distributed in the hope that it will be useful,
|
14 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16 |
+
* GNU General Public License for more details.
|
17 |
+
*
|
18 |
+
* You should have received a copy of the GNU General Public License
|
19 |
+
* along with this program; if not, write to the Free Software
|
20 |
+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
21 |
+
* MA 02110-1301, USA.
|
22 |
+
*
|
23 |
+
* @link https://github.com/ovidiul/XCloner-Wordpress
|
24 |
+
*
|
25 |
+
* @modified 7/25/18 1:46 PM
|
26 |
*
|
|
|
|
|
27 |
*/
|
28 |
|
29 |
+
|
30 |
/**
|
31 |
* Register all actions and filters for the plugin.
|
32 |
*
|
38 |
* @subpackage Xcloner/includes
|
39 |
* @author Liuta Ovidiu <info@thinkovi.com>
|
40 |
*/
|
41 |
+
class Xcloner_Loader
|
42 |
+
{
|
43 |
+
|
44 |
+
/**
|
45 |
+
* The array of actions registered with WordPress.
|
46 |
+
*
|
47 |
+
* @since 1.0.0
|
48 |
+
* @access protected
|
49 |
+
* @var array $actions The actions registered with WordPress to fire when the plugin loads.
|
50 |
+
*/
|
51 |
+
protected $actions;
|
52 |
+
|
53 |
+
/**
|
54 |
+
* The array of filters registered with WordPress.
|
55 |
+
*
|
56 |
+
* @since 1.0.0
|
57 |
+
* @access protected
|
58 |
+
* @var array $filters The filters registered with WordPress to fire when the plugin loads.
|
59 |
+
*/
|
60 |
+
protected $filters;
|
61 |
+
|
62 |
+
private $xcloner_plugin;
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Initialize the collections used to maintain the actions and filters.
|
66 |
+
*
|
67 |
+
* @since 1.0.0
|
68 |
+
*/
|
69 |
+
public function __construct(Xcloner $xcloner_container)
|
70 |
+
{
|
71 |
+
|
72 |
+
$this->actions = array();
|
73 |
+
$this->filters = array();
|
74 |
+
|
75 |
+
$this->xcloner_container = $xcloner_container;
|
76 |
+
|
77 |
+
}
|
78 |
+
|
79 |
+
public function xcloner_backup_add_admin_menu()
|
80 |
+
{
|
81 |
+
if (function_exists('add_menu_page')) {
|
82 |
+
add_menu_page(__('Site Backup', 'xcloner-backup-and-restore'),
|
83 |
+
__('Site Backup', 'xcloner-backup-and-restore'), 'manage_options', 'xcloner_init_page',
|
84 |
+
array($this->xcloner_container, 'xcloner_display'), 'dashicons-backup');
|
85 |
+
}
|
86 |
+
|
87 |
+
if (function_exists('add_submenu_page')) {
|
88 |
+
|
89 |
+
add_submenu_page('xcloner_init_page', __('XCloner Dashboard', 'xcloner-backup-and-restore'),
|
90 |
+
__('Dashboard', 'xcloner-backup-and-restore'), 'manage_options', 'xcloner_init_page',
|
91 |
+
array($this->xcloner_container, 'xcloner_display'));
|
92 |
+
add_submenu_page('xcloner_init_page', __('XCloner Backup Settings', 'xcloner-backup-and-restore'),
|
93 |
+
__('Settings', 'xcloner-backup-and-restore'), 'manage_options', 'xcloner_settings_page',
|
94 |
+
array($this->xcloner_container, 'xcloner_display'));
|
95 |
+
add_submenu_page('xcloner_init_page', __('Remote Storage Settings', 'xcloner-backup-and-restore'),
|
96 |
+
__('Remote Storage', 'xcloner-backup-and-restore'), 'manage_options', 'xcloner_remote_storage_page',
|
97 |
+
array($this->xcloner_container, 'xcloner_display'));
|
98 |
+
add_submenu_page('xcloner_init_page', __('Manage Backups', 'xcloner-backup-and-restore'),
|
99 |
+
__('Manage Backups', 'xcloner-backup-and-restore'), 'manage_options', 'xcloner_manage_backups_page',
|
100 |
+
array($this->xcloner_container, 'xcloner_display'));
|
101 |
+
add_submenu_page('xcloner_init_page', __('Scheduled Backups', 'xcloner-backup-and-restore'),
|
102 |
+
__('Scheduled Backups', 'xcloner-backup-and-restore'), 'manage_options',
|
103 |
+
'xcloner_scheduled_backups_page', array($this->xcloner_container, 'xcloner_display'));
|
104 |
+
add_submenu_page('xcloner_init_page', __('Generate Backups', 'xcloner-backup-and-restore'),
|
105 |
+
__('Generate Backups', 'xcloner-backup-and-restore'), 'manage_options', 'xcloner_generate_backups_page',
|
106 |
+
array($this->xcloner_container, 'xcloner_display'));
|
107 |
+
add_submenu_page('xcloner_init_page', __('Restore Backups', 'xcloner-backup-and-restore'),
|
108 |
+
__('Restore Backups', 'xcloner-backup-and-restore'), 'manage_options', 'xcloner_restore_page',
|
109 |
+
array($this->xcloner_container, 'xcloner_display'));
|
110 |
+
}
|
111 |
+
|
112 |
+
}
|
113 |
+
|
114 |
+
|
115 |
+
/**
|
116 |
+
* Add a new action to the collection to be registered with WordPress.
|
117 |
+
*
|
118 |
+
* @since 1.0.0
|
119 |
+
* @param string $hook The name of the WordPress action that is being registered.
|
120 |
+
* @param object $component A reference to the instance of the object on which the action is defined.
|
121 |
+
* @param string $callback The name of the function definition on the $component.
|
122 |
+
* @param int $priority Optional. he priority at which the function should be fired. Default is 10.
|
123 |
+
* @param int $accepted_args Optional. The number of arguments that should be passed to the $callback. Default is 1.
|
124 |
+
*/
|
125 |
+
public function add_action($hook, $component, $callback, $priority = 10, $accepted_args = 1)
|
126 |
+
{
|
127 |
+
$this->actions = $this->add($this->actions, $hook, $component, $callback, $priority, $accepted_args);
|
128 |
+
}
|
129 |
+
|
130 |
+
/**
|
131 |
+
* Add a new filter to the collection to be registered with WordPress.
|
132 |
+
*
|
133 |
+
* @since 1.0.0
|
134 |
+
* @param string $hook The name of the WordPress filter that is being registered.
|
135 |
+
* @param object $component A reference to the instance of the object on which the filter is defined.
|
136 |
+
* @param string $callback The name of the function definition on the $component.
|
137 |
+
* @param int $priority Optional. he priority at which the function should be fired. Default is 10.
|
138 |
+
* @param int $accepted_args Optional. The number of arguments that should be passed to the $callback. Default is 1
|
139 |
+
*/
|
140 |
+
public function add_filter($hook, $component, $callback, $priority = 10, $accepted_args = 1)
|
141 |
+
{
|
142 |
+
$this->filters = $this->add($this->filters, $hook, $component, $callback, $priority, $accepted_args);
|
143 |
+
}
|
144 |
+
|
145 |
+
/**
|
146 |
+
* A utility function that is used to register the actions and hooks into a single
|
147 |
+
* collection.
|
148 |
+
*
|
149 |
+
* @since 1.0.0
|
150 |
+
* @access private
|
151 |
+
* @param array $hooks The collection of hooks that is being registered (that is, actions or filters).
|
152 |
+
* @param string $hook The name of the WordPress filter that is being registered.
|
153 |
+
* @param object $component A reference to the instance of the object on which the filter is defined.
|
154 |
+
* @param string $callback The name of the function definition on the $component.
|
155 |
+
* @param int $priority The priority at which the function should be fired.
|
156 |
+
* @param int $accepted_args The number of arguments that should be passed to the $callback.
|
157 |
+
* @return array The collection of actions and filters registered with WordPress.
|
158 |
+
*/
|
159 |
+
private function add($hooks, $hook, $component, $callback, $priority, $accepted_args)
|
160 |
+
{
|
161 |
+
|
162 |
+
$hooks[] = array(
|
163 |
+
'hook' => $hook,
|
164 |
+
'component' => $component,
|
165 |
+
'callback' => $callback,
|
166 |
+
'priority' => $priority,
|
167 |
+
'accepted_args' => $accepted_args
|
168 |
+
);
|
169 |
+
|
170 |
+
return $hooks;
|
171 |
+
|
172 |
+
}
|
173 |
+
|
174 |
+
/**
|
175 |
+
* Register the filters and actions with WordPress.
|
176 |
+
*
|
177 |
+
* @since 1.0.0
|
178 |
+
*/
|
179 |
+
public function run()
|
180 |
+
{
|
181 |
+
|
182 |
+
foreach ($this->filters as $hook) {
|
183 |
+
add_filter($hook['hook'], array($hook['component'], $hook['callback']), $hook['priority'],
|
184 |
+
$hook['accepted_args']);
|
185 |
+
}
|
186 |
+
|
187 |
+
foreach ($this->actions as $hook) {
|
188 |
+
add_action($hook['hook'], array($hook['component'], $hook['callback']), $hook['priority'],
|
189 |
+
$hook['accepted_args']);
|
190 |
+
}
|
191 |
+
|
192 |
+
}
|
193 |
+
|
194 |
}
|
includes/class-xcloner-logger.php
CHANGED
@@ -4,117 +4,106 @@ use Monolog\Logger;
|
|
4 |
use Monolog\Handler\StreamHandler;
|
5 |
use Monolog\Handler\RotatingFileHandler;
|
6 |
|
7 |
-
class Xcloner_Logger extends Logger{
|
8 |
-
|
9 |
-
private $logger_path
|
10 |
private $max_logger_files = 7;
|
11 |
private $main_logger_url;
|
12 |
-
|
13 |
-
public function __construct(Xcloner $xcloner_container, $logger_name = "xcloner_logger")
|
14 |
-
|
15 |
-
|
16 |
-
{
|
17 |
-
$xcloner_settings
|
18 |
-
}else{
|
19 |
-
$xcloner_settings = $xcloner_container->get_xcloner_settings();
|
20 |
}
|
21 |
-
|
22 |
$hash = $xcloner_settings->get_hash();
|
23 |
-
if($hash == "-"
|
24 |
-
{
|
25 |
$hash = "";
|
26 |
}
|
27 |
-
|
28 |
-
$logger_path
|
29 |
-
$logger_path_tmp
|
30 |
-
|
31 |
-
if($hash)
|
32 |
-
|
33 |
-
$logger_path_tmp = $xcloner_settings->get_xcloner_tmp_path().DS.$xcloner_settings->get_logger_filename(1);
|
34 |
}
|
35 |
-
|
36 |
$this->logger_path = $logger_path;
|
37 |
-
|
38 |
-
if(!is_dir($xcloner_settings->get_xcloner_store_path()) or !is_writable($xcloner_settings->get_xcloner_store_path()))
|
39 |
-
|
40 |
-
$logger_path = 'php://stderr';
|
41 |
$logger_path_tmp = "";
|
42 |
}
|
43 |
-
|
44 |
-
if(
|
45 |
-
|
46 |
-
$logger_path = 'php://stderr';
|
47 |
$logger_path_tmp = "";
|
48 |
}
|
49 |
-
|
50 |
// create a log channel
|
51 |
-
parent::__construct($logger_name);
|
52 |
-
|
53 |
$debug_level = Logger::INFO;
|
54 |
-
|
55 |
-
if(WP_DEBUG)
|
56 |
-
{
|
57 |
$debug_level = Logger::DEBUG;
|
58 |
}
|
59 |
|
60 |
-
|
61 |
-
if($logger_path)
|
62 |
-
|
63 |
-
|
64 |
-
{
|
65 |
-
$stream = new
|
66 |
-
}else{
|
67 |
-
$stream = new RotatingFileHandler($logger_path, $this->max_logger_files, $debug_level);
|
68 |
}
|
69 |
-
|
70 |
-
$this->pushHandler($stream);
|
71 |
-
|
72 |
-
$this->main_logger_url =
|
73 |
}
|
74 |
-
|
75 |
-
if($hash and $logger_path_tmp)
|
76 |
-
|
77 |
-
$this->pushHandler(new StreamHandler($logger_path_tmp, $debug_level));
|
78 |
}
|
79 |
-
|
80 |
//return $this;
|
81 |
}
|
82 |
-
|
83 |
-
function get_main_logger_url()
|
84 |
-
{
|
85 |
return $this->main_logger_url;
|
86 |
}
|
87 |
-
|
88 |
-
function getLastDebugLines($totalLines = 200)
|
89 |
-
{
|
90 |
$lines = array();
|
91 |
-
|
92 |
-
if(!file_exists($this->main_logger_url) or !is_readable($this->main_logger_url))
|
93 |
return false;
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
$
|
|
|
98 |
$lastLine = "";
|
99 |
-
|
100 |
// Loop backword until we have our lines or we reach the start
|
101 |
-
while($pos > 0 && count($lines) < $totalLines) {
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
}
|
115 |
-
|
116 |
-
$lines = array_reverse($lines);
|
117 |
-
|
118 |
return $lines;
|
119 |
}
|
120 |
}
|
4 |
use Monolog\Handler\StreamHandler;
|
5 |
use Monolog\Handler\RotatingFileHandler;
|
6 |
|
7 |
+
class Xcloner_Logger extends Logger {
|
8 |
+
|
9 |
+
private $logger_path;
|
10 |
private $max_logger_files = 7;
|
11 |
private $main_logger_url;
|
12 |
+
|
13 |
+
public function __construct( Xcloner $xcloner_container, $logger_name = "xcloner_logger" ) {
|
14 |
+
if ( ! $xcloner_container->get_xcloner_settings() ) {
|
15 |
+
$xcloner_settings = new Xcloner_Settings( $xcloner_container );
|
16 |
+
} else {
|
17 |
+
$xcloner_settings = $xcloner_container->get_xcloner_settings();
|
|
|
|
|
18 |
}
|
19 |
+
|
20 |
$hash = $xcloner_settings->get_hash();
|
21 |
+
if ( $hash == "-" . $xcloner_settings->get_server_unique_hash( 5 ) ) {
|
|
|
22 |
$hash = "";
|
23 |
}
|
24 |
+
|
25 |
+
$logger_path = $xcloner_settings->get_xcloner_store_path() . DS . $xcloner_settings->get_logger_filename();
|
26 |
+
$logger_path_tmp = "";
|
27 |
+
|
28 |
+
if ( $hash ) {
|
29 |
+
$logger_path_tmp = $xcloner_settings->get_xcloner_tmp_path() . DS . $xcloner_settings->get_logger_filename( 1 );
|
|
|
30 |
}
|
31 |
+
|
32 |
$this->logger_path = $logger_path;
|
33 |
+
|
34 |
+
if ( ! is_dir( $xcloner_settings->get_xcloner_store_path() ) or ! is_writable( $xcloner_settings->get_xcloner_store_path() ) ) {
|
35 |
+
$logger_path = 'php://stderr';
|
|
|
36 |
$logger_path_tmp = "";
|
37 |
}
|
38 |
+
|
39 |
+
if ( ! $xcloner_settings->get_xcloner_option( 'xcloner_enable_log' ) ) {
|
40 |
+
$logger_path = 'php://stderr';
|
|
|
41 |
$logger_path_tmp = "";
|
42 |
}
|
43 |
+
|
44 |
// create a log channel
|
45 |
+
parent::__construct( $logger_name );
|
46 |
+
|
47 |
$debug_level = Logger::INFO;
|
48 |
+
|
49 |
+
if ( WP_DEBUG ) {
|
|
|
50 |
$debug_level = Logger::DEBUG;
|
51 |
}
|
52 |
|
53 |
+
|
54 |
+
if ( $logger_path ) {
|
55 |
+
if ( ! $xcloner_settings->get_xcloner_option( 'xcloner_enable_log' ) ) {
|
56 |
+
$stream = new StreamHandler( $logger_path, $debug_level );
|
57 |
+
} else {
|
58 |
+
$stream = new RotatingFileHandler( $logger_path, $this->max_logger_files, $debug_level );
|
|
|
|
|
59 |
}
|
60 |
+
|
61 |
+
$this->pushHandler( $stream );
|
62 |
+
|
63 |
+
$this->main_logger_url = $stream->getUrl();
|
64 |
}
|
65 |
+
|
66 |
+
if ( $hash and $logger_path_tmp ) {
|
67 |
+
$this->pushHandler( new StreamHandler( $logger_path_tmp, $debug_level ) );
|
|
|
68 |
}
|
69 |
+
|
70 |
//return $this;
|
71 |
}
|
72 |
+
|
73 |
+
function get_main_logger_url() {
|
|
|
74 |
return $this->main_logger_url;
|
75 |
}
|
76 |
+
|
77 |
+
function getLastDebugLines( $totalLines = 200 ) {
|
|
|
78 |
$lines = array();
|
79 |
+
|
80 |
+
if ( ! file_exists( $this->main_logger_url ) or ! is_readable( $this->main_logger_url ) ) {
|
81 |
return false;
|
82 |
+
}
|
83 |
+
|
84 |
+
$fp = fopen( $this->main_logger_url, 'r' );
|
85 |
+
fseek( $fp, - 1, SEEK_END );
|
86 |
+
$pos = ftell( $fp );
|
87 |
$lastLine = "";
|
88 |
+
|
89 |
// Loop backword until we have our lines or we reach the start
|
90 |
+
while ( $pos > 0 && count( $lines ) < $totalLines ) {
|
91 |
+
|
92 |
+
$C = fgetc( $fp );
|
93 |
+
if ( $C == "\n" ) {
|
94 |
+
// skip empty lines
|
95 |
+
if ( trim( $lastLine ) != "" ) {
|
96 |
+
$lines[] = $lastLine;
|
97 |
+
}
|
98 |
+
$lastLine = '';
|
99 |
+
} else {
|
100 |
+
$lastLine = $C . $lastLine;
|
101 |
+
}
|
102 |
+
fseek( $fp, $pos -- );
|
103 |
}
|
104 |
+
|
105 |
+
$lines = array_reverse( $lines );
|
106 |
+
|
107 |
return $lines;
|
108 |
}
|
109 |
}
|
includes/class-xcloner-remote-storage.php
CHANGED
@@ -1,4 +1,31 @@
|
|
1 |
<?php
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
use League\Flysystem\Config;
|
3 |
use League\Flysystem\Filesystem;
|
4 |
|
@@ -6,8 +33,6 @@ use League\Flysystem\Adapter\Ftp as Adapter;
|
|
6 |
|
7 |
use League\Flysystem\Sftp\SftpAdapter;
|
8 |
|
9 |
-
#use League\Flysystem\Dropbox\DropboxAdapter;
|
10 |
-
#use Dropbox\Client;
|
11 |
use Srmklive\Dropbox\Client\DropboxClient;
|
12 |
use Srmklive\Dropbox\Adapter\DropboxAdapter;
|
13 |
|
@@ -18,707 +43,736 @@ use Aws\S3\S3Client;
|
|
18 |
use League\Flysystem\AwsS3v3\AwsS3Adapter;
|
19 |
|
20 |
use Mhetreramesh\Flysystem\BackblazeAdapter;
|
21 |
-
use
|
22 |
|
23 |
use Sabre\DAV\Client as SabreClient;
|
24 |
use League\Flysystem\WebDAV\WebDAVAdapter;
|
25 |
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
|
|
|
|
|
|
30 |
private $storage_fields = array(
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
private $aws_regions = array(
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
private $xcloner_sanitization;
|
133 |
private $xcloner_file_system;
|
134 |
private $logger;
|
135 |
private $xcloner;
|
136 |
-
|
137 |
-
public function __construct(Xcloner $xcloner_container)
|
138 |
-
|
139 |
-
$this->
|
140 |
-
$this->
|
141 |
-
$this->
|
142 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
143 |
}
|
144 |
-
|
145 |
-
|
146 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
147 |
return $this->xcloner_container;
|
148 |
}
|
149 |
-
|
150 |
-
public function get_available_storages()
|
151 |
-
{
|
152 |
$return = array();
|
153 |
-
foreach($this->storage_fields as $storage
|
154 |
-
|
155 |
-
$check_field
|
156 |
-
|
157 |
-
|
158 |
}
|
159 |
-
|
160 |
return $return;
|
161 |
}
|
162 |
-
|
163 |
-
public function save($action = "ftp")
|
164 |
-
|
165 |
-
if(!$action)
|
166 |
-
{
|
167 |
return false;
|
168 |
}
|
169 |
-
|
170 |
-
$storage = $this->xcloner_sanitization->sanitize_input_as_string($action);
|
171 |
-
$this->logger->debug(sprintf("Saving the remote storage %s options", strtoupper($action)));
|
172 |
-
|
173 |
-
if(is_array($this->storage_fields[$storage]))
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
$
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
if(!method_exists($this->xcloner_sanitization, $sanitize_method))
|
184 |
$sanitize_method = "sanitize_input_as_string";
|
185 |
-
|
186 |
-
|
187 |
-
|
|
|
188 |
}
|
189 |
-
|
190 |
-
$this->xcloner->trigger_message(__("%s storage settings saved.", 'xcloner-backup-and-restore'), "success", $this->storage_fields[$action]['text']);
|
191 |
}
|
192 |
-
|
193 |
}
|
194 |
-
|
195 |
-
public function check($action = "ftp")
|
196 |
-
|
197 |
-
|
198 |
-
$this->
|
199 |
-
$this->
|
200 |
-
|
201 |
-
|
202 |
-
$this->xcloner->trigger_message("%s connection error: ".$e->getMessage(), "error", $this->storage_fields[$action]['text']);
|
203 |
}
|
204 |
}
|
205 |
-
|
206 |
-
public function verify_filesystem($storage_type)
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
if(!method_exists($this, $method))
|
213 |
return false;
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
{
|
221 |
-
if(!is_array($filesystem->listContents()))
|
222 |
-
throw new Exception(__("Could not read data",'xcloner-backup-and-restore'));
|
223 |
-
|
224 |
-
|
|
|
225 |
return true;
|
226 |
}
|
227 |
-
|
228 |
//testing write access
|
229 |
-
if(
|
230 |
-
throw new Exception(__("Could not write data",'xcloner-backup-and-restore'));
|
231 |
-
|
232 |
-
|
|
|
233 |
//testing read access
|
234 |
-
if(
|
235 |
-
throw new Exception(__("Could not read data",'xcloner-backup-and-restore'));
|
236 |
-
|
237 |
-
|
|
|
238 |
//delete test file
|
239 |
-
if(
|
240 |
-
throw new Exception(__("Could not delete data",'xcloner-backup-and-restore'));
|
241 |
-
|
242 |
-
|
|
|
243 |
return true;
|
244 |
}
|
245 |
-
|
246 |
-
public function upload_backup_to_storage($file, $storage)
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
$this->logger->info(sprintf("File not found %s in local storage", $file));
|
251 |
return false;
|
252 |
}
|
253 |
-
|
254 |
-
$method = "get_"
|
255 |
-
|
256 |
-
if(!method_exists($this, $method))
|
257 |
return false;
|
258 |
-
|
259 |
-
|
260 |
-
|
|
|
261 |
//doing remote storage cleaning here
|
262 |
-
$this->clean_remote_storage($storage, $remote_storage_filesystem);
|
263 |
-
|
264 |
-
$this->logger->info(sprintf("Transferring backup %s to remote storage %s", $file, strtoupper($storage)), array(""));
|
265 |
-
|
266 |
/*if(!$this->xcloner_file_system->get_storage_filesystem()->has($file))
|
267 |
{
|
268 |
$this->logger->info(sprintf("File not found %s in local storage", $file));
|
269 |
return false;
|
270 |
}*/
|
271 |
-
|
272 |
-
$backup_file_stream = $this->xcloner_file_system->get_storage_filesystem()->readStream($file);
|
273 |
|
274 |
-
|
275 |
-
|
276 |
-
|
|
|
|
|
277 |
return false;
|
278 |
}
|
279 |
-
|
280 |
-
if($this->xcloner_file_system->is_multipart($file))
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
$this->
|
287 |
-
|
288 |
-
$backup_file_stream = $this->xcloner_file_system->get_storage_filesystem()->readStream($part_file);
|
289 |
-
if(!$remote_storage_filesystem->writeStream($part_file, $backup_file_stream))
|
290 |
return false;
|
|
|
291 |
}
|
|
|
292 |
}
|
293 |
-
|
294 |
-
$this->logger->info(sprintf("Upload done, disconnecting from remote storage %s", strtoupper($storage)));
|
295 |
-
|
296 |
return true;
|
297 |
-
|
298 |
}
|
299 |
-
|
300 |
-
public function copy_backup_remote_to_local($file, $storage)
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
$target_filename = $file;
|
305 |
-
|
306 |
-
if(!method_exists($this, $method))
|
307 |
return false;
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
{
|
313 |
-
$this->logger->info(sprintf("File not found %s in remote storage %s", $file, strtoupper($storage)));
|
|
|
314 |
return false;
|
315 |
}
|
316 |
-
|
317 |
-
if($storage == "gdrive")
|
318 |
-
|
319 |
-
$
|
320 |
-
$target_filename = $metadata['filename'].".".$metadata['extension'];
|
321 |
}
|
322 |
-
|
323 |
-
$this->logger->info(sprintf("Transferring backup %s to local storage from %s storage", $file, strtoupper($storage)), array(""));
|
324 |
-
|
325 |
-
$backup_file_stream = $remote_storage_filesystem->readStream($file);
|
326 |
|
327 |
-
|
328 |
-
|
329 |
-
|
|
|
|
|
|
|
|
|
330 |
return false;
|
331 |
}
|
332 |
-
|
333 |
-
if($this->xcloner_file_system->is_multipart($target_filename))
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
$
|
340 |
-
|
341 |
-
$backup_file_stream = $remote_storage_filesystem->readStream($part_file);
|
342 |
-
if(!$this->xcloner_file_system->get_storage_filesystem()->writeStream($part_file, $backup_file_stream))
|
343 |
return false;
|
|
|
344 |
}
|
|
|
345 |
}
|
346 |
-
|
347 |
-
$this->logger->info(sprintf("Upload done, disconnecting from remote storage %s", strtoupper($storage)));
|
348 |
-
|
349 |
return true;
|
350 |
-
|
351 |
}
|
352 |
-
|
353 |
-
public function clean_remote_storage($storage, $remote_storage_filesystem)
|
354 |
-
|
355 |
-
$
|
356 |
-
|
357 |
-
{
|
358 |
-
$this->logger->info(sprintf("Doing %s remote storage cleanup for %s days limit", strtoupper($storage), $expire_days));
|
359 |
$files = $remote_storage_filesystem->listContents();
|
360 |
-
|
361 |
-
$current_timestamp = strtotime("-"
|
362 |
-
|
363 |
-
if(is_array($files))
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
|
|
|
|
|
|
372 |
}
|
373 |
-
|
374 |
}
|
375 |
}
|
376 |
}
|
377 |
-
|
378 |
-
public function get_azure_filesystem()
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
{
|
384 |
-
throw new Exception("AZURE BLOB requires PHP 5.6 to be installed!");
|
385 |
}
|
386 |
-
|
387 |
-
if (!class_exists('XmlWriter'))
|
388 |
-
|
389 |
-
throw new Exception("AZURE BLOB requires libxml PHP module to be installed with XmlWriter class enabled!");
|
390 |
}
|
391 |
-
|
392 |
$endpoint = sprintf(
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
);
|
397 |
-
|
398 |
-
$blobRestProxy = ServicesBuilder::getInstance()->createBlobService($endpoint);
|
399 |
-
|
400 |
-
$adapter = new AzureAdapter($blobRestProxy, get_option("xcloner_azure_container"));
|
401 |
-
|
402 |
-
$filesystem = new Filesystem($adapter, new Config([
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
return array($adapter, $filesystem);
|
407 |
}
|
408 |
-
|
409 |
-
public function get_dropbox_filesystem()
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
{
|
415 |
-
throw new Exception("DROPBOX requires PHP 5.6 to be installed!");
|
416 |
}
|
417 |
-
|
418 |
-
$client = new DropboxClient(get_option("xcloner_dropbox_access_token"));
|
419 |
-
$adapter = new DropboxAdapter($client, get_option("xcloner_dropbox_prefix"));
|
420 |
-
|
421 |
-
$filesystem = new Filesystem($adapter, new Config([
|
422 |
-
'disable_asserts' => true,
|
423 |
-
]));
|
424 |
|
425 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
426 |
}
|
427 |
-
|
428 |
-
public function get_aws_filesystem()
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
{
|
434 |
-
throw new Exception("S3 class requires PHP 5.6 to be installed!");
|
435 |
}
|
436 |
-
|
437 |
-
if (!class_exists('XmlWriter'))
|
438 |
-
|
439 |
-
throw new Exception("AZURE BLOB requires libxml PHP module to be installed with XmlWriter class enabled!");
|
440 |
}
|
441 |
-
|
442 |
-
|
443 |
$credentials = array(
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
);
|
451 |
-
|
452 |
-
if(get_option('xcloner_aws_endpoint') != "" && !get_option("xcloner_aws_region")){
|
453 |
-
|
454 |
-
$credentials['endpoint'] = get_option('xcloner_aws_endpoint');
|
455 |
#$credentials['use_path_style_endpoint'] = true;
|
456 |
#$credentials['bucket_endpoint'] = false;
|
457 |
-
|
458 |
-
|
459 |
-
}
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
$
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
return array($adapter, $filesystem);
|
470 |
}
|
471 |
-
|
472 |
-
public function get_backblaze_filesystem()
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
$
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
return array($adapter, $filesystem);
|
490 |
}
|
491 |
-
|
492 |
-
public function get_webdav_filesystem()
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
{
|
498 |
-
throw new Exception("WEBDAV API requires PHP 5.6 to be installed!");
|
499 |
}
|
500 |
-
|
501 |
$settings = array(
|
502 |
-
'baseUri'
|
503 |
-
'userName'
|
504 |
-
'password'
|
505 |
//'proxy' => 'locahost:8888',
|
506 |
);
|
507 |
-
|
508 |
-
|
509 |
-
$client
|
510 |
-
$adapter
|
511 |
-
$filesystem = new Filesystem($adapter, new Config([
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
return array($adapter, $filesystem);
|
516 |
}
|
517 |
-
|
518 |
-
|
519 |
-
public function gdrive_construct()
|
520 |
-
{
|
521 |
|
522 |
//if((function_exists("is_plugin_active") && !is_plugin_active("xcloner-google-drive/xcloner-google-drive.php")) || !file_exists(__DIR__ . "/../../xcloner-google-drive/vendor/autoload.php"))
|
523 |
-
if(!class_exists('Google_Client'))
|
524 |
-
{
|
525 |
return false;
|
526 |
}
|
527 |
-
|
528 |
//require_once(__DIR__ . "/../../xcloner-google-drive/vendor/autoload.php");
|
529 |
-
|
530 |
$client = new \Google_Client();
|
531 |
-
$client->setApplicationName($this->gdrive_app_name);
|
532 |
-
$client->setClientId(get_option("xcloner_gdrive_client_id"));
|
533 |
-
$client->setClientSecret(get_option("xcloner_gdrive_client_secret"));
|
534 |
-
|
535 |
//$redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']."?page=xcloner_remote_storage_page&action=set_gdrive_code";
|
536 |
$redirect_uri = "urn:ietf:wg:oauth:2.0:oob";
|
537 |
-
|
538 |
-
$client->setRedirectUri($redirect_uri); //urn:ietf:wg:oauth:2.0:oob
|
539 |
-
$client->addScope("https://www.googleapis.com/auth/drive");
|
540 |
-
$client->setAccessType('offline');
|
541 |
-
|
542 |
return $client;
|
543 |
}
|
544 |
-
|
545 |
-
public function get_gdrive_auth_url()
|
546 |
-
{
|
547 |
$client = $this->gdrive_construct();
|
548 |
-
|
549 |
-
if(
|
550 |
return false;
|
551 |
-
|
|
|
552 |
return $authUrl = $client->createAuthUrl();
|
553 |
}
|
554 |
-
|
555 |
-
public function set_access_token($code)
|
556 |
-
{
|
557 |
$client = $this->gdrive_construct();
|
558 |
-
|
559 |
-
if(
|
560 |
-
{
|
561 |
$error_msg = "Could not initialize the Google Drive Class, please check that the xcloner-google-drive plugin is enabled...";
|
562 |
-
$this->logger->error($error_msg);
|
|
|
563 |
return false;
|
564 |
}
|
565 |
|
566 |
-
$token = $client->fetchAccessTokenWithAuthCode($code);
|
567 |
-
$client->setAccessToken($token);
|
568 |
-
|
569 |
-
update_option("xcloner_gdrive_access_token", $token['access_token']);
|
570 |
-
update_option("xcloner_gdrive_refresh_token", $token['refresh_token']);
|
571 |
-
|
572 |
-
$redirect_url = ('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']."?page=xcloner_remote_storage_page#gdrive");
|
573 |
-
|
574 |
?>
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
<?php
|
579 |
-
|
580 |
}
|
581 |
-
|
582 |
/*
|
583 |
* php composer.phar remove nao-pon/flysystem-google-drive
|
584 |
*
|
585 |
*/
|
586 |
-
public function get_gdrive_filesystem()
|
587 |
-
|
588 |
-
|
589 |
-
|
590 |
-
{
|
591 |
-
throw new Exception("Google Drive API requires PHP 5.6 to be installed!");
|
592 |
}
|
593 |
-
|
594 |
-
$this->logger->info(sprintf("Creating the Google Drive remote storage connection"), array(""));
|
595 |
-
|
596 |
$client = $this->gdrive_construct();
|
597 |
-
|
598 |
-
if(
|
599 |
-
{
|
600 |
$error_msg = "Could not initialize the Google Drive Class, please check that the xcloner-google-drive plugin is enabled...";
|
601 |
-
$this->logger->error($error_msg);
|
602 |
-
throw new Exception($error_msg);
|
603 |
-
}
|
604 |
-
|
605 |
-
$client->refreshToken(get_option("xcloner_gdrive_refresh_token"));
|
606 |
-
|
607 |
-
$service = new \Google_Service_Drive($client);
|
608 |
-
|
609 |
/*if( get_option("xcloner_gdrive_empty_trash",0) ){
|
610 |
$this->logger->info(sprintf("Doing a Google Drive emptyTrash call"), array(""));
|
611 |
$service->files->emptyTrash();
|
612 |
}*/
|
613 |
-
|
614 |
$parent = 'root';
|
615 |
-
$dir
|
616 |
-
|
617 |
-
$folderID = get_option("xcloner_gdrive_target_folder");
|
618 |
-
|
619 |
-
$tmp = parse_url($folderID);
|
620 |
-
|
621 |
-
if(isset($tmp['query']))
|
622 |
-
|
623 |
-
$folderID = str_replace("id=", "", $tmp['query']);
|
624 |
}
|
625 |
-
|
626 |
-
if(stristr($folderID, "/"))
|
627 |
-
|
628 |
-
$
|
629 |
-
|
630 |
-
|
631 |
-
|
632 |
-
|
633 |
-
|
634 |
-
|
635 |
-
|
636 |
-
foreach ($response as $obj) {
|
637 |
-
$folderID = $obj->getId();
|
638 |
}
|
639 |
-
}else{
|
640 |
-
$this->xcloner->trigger_message(sprintf(__("Could not find folder ID by name %s", 'xcloner-backup-and-restore'), $folderID), "error");
|
641 |
}
|
642 |
}
|
643 |
-
|
644 |
-
$this->logger->info(sprintf("Using target folder with ID %s on the remote storage", $folderID));
|
645 |
-
|
646 |
-
if(class_exists('XCloner_Google_Drive_Adapter')){
|
647 |
-
$adapter = new XCloner_Google_Drive_Adapter($service, $folderID);
|
648 |
-
}else{
|
649 |
-
$adapter = new \Hypweb\Flysystem\GoogleDrive\GoogleDriveAdapter($service, $folderID);
|
650 |
-
}
|
651 |
-
|
652 |
-
$filesystem = new \League\Flysystem\Filesystem($adapter, new Config([
|
653 |
-
|
654 |
-
|
655 |
-
|
656 |
-
|
657 |
-
return array($adapter, $filesystem);
|
658 |
}
|
659 |
-
|
660 |
-
public function get_ftp_filesystem()
|
661 |
-
|
662 |
-
|
663 |
-
|
664 |
-
|
665 |
-
|
666 |
-
|
667 |
-
|
668 |
-
|
669 |
-
|
670 |
-
|
671 |
-
|
672 |
-
|
673 |
-
|
674 |
-
|
675 |
-
|
676 |
-
|
677 |
$adapter->connect();
|
678 |
-
|
679 |
-
$filesystem = new Filesystem($adapter, new Config([
|
680 |
-
|
681 |
-
|
682 |
-
|
683 |
-
return array($adapter, $filesystem);
|
684 |
}
|
685 |
-
|
686 |
-
public function get_sftp_filesystem()
|
687 |
-
|
688 |
-
|
689 |
-
|
690 |
-
|
691 |
-
|
692 |
-
|
693 |
-
|
694 |
-
|
695 |
-
|
696 |
-
|
697 |
-
|
698 |
-
|
699 |
-
|
700 |
-
|
701 |
-
|
702 |
$adapter->connect();
|
703 |
-
|
704 |
-
$filesystem = new Filesystem($adapter, new Config([
|
705 |
-
|
706 |
-
|
707 |
-
|
708 |
-
return array($adapter, $filesystem);
|
709 |
}
|
710 |
-
|
711 |
-
public function change_storage_status($field, $value)
|
712 |
-
{
|
713 |
-
$field = $this->xcloner_sanitization->sanitize_input_as_string($field);
|
714 |
-
$value = $this->xcloner_sanitization->sanitize_input_as_int($value);
|
715 |
|
716 |
-
|
|
|
|
|
|
|
|
|
717 |
}
|
718 |
-
|
719 |
-
public function get_aws_regions()
|
720 |
-
{
|
721 |
return $this->aws_regions;
|
722 |
}
|
723 |
-
|
724 |
}
|
1 |
<?php
|
2 |
+
/**
|
3 |
+
* XCloner - Backup and Restore backup plugin for Wordpress
|
4 |
+
*
|
5 |
+
* class-xcloner-remote-storage.php
|
6 |
+
* @author Liuta Ovidiu <info@thinkovi.com>
|
7 |
+
*
|
8 |
+
* This program is free software; you can redistribute it and/or modify
|
9 |
+
* it under the terms of the GNU General Public License as published by
|
10 |
+
* the Free Software Foundation; either version 2 of the License, or
|
11 |
+
* (at your option) any later version.
|
12 |
+
*
|
13 |
+
* This program is distributed in the hope that it will be useful,
|
14 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16 |
+
* GNU General Public License for more details.
|
17 |
+
*
|
18 |
+
* You should have received a copy of the GNU General Public License
|
19 |
+
* along with this program; if not, write to the Free Software
|
20 |
+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
21 |
+
* MA 02110-1301, USA.
|
22 |
+
*
|
23 |
+
* @link https://github.com/ovidiul/XCloner-Wordpress
|
24 |
+
*
|
25 |
+
* @modified 7/25/18 2:15 PM
|
26 |
+
*
|
27 |
+
*/
|
28 |
+
|
29 |
use League\Flysystem\Config;
|
30 |
use League\Flysystem\Filesystem;
|
31 |
|
33 |
|
34 |
use League\Flysystem\Sftp\SftpAdapter;
|
35 |
|
|
|
|
|
36 |
use Srmklive\Dropbox\Client\DropboxClient;
|
37 |
use Srmklive\Dropbox\Adapter\DropboxAdapter;
|
38 |
|
43 |
use League\Flysystem\AwsS3v3\AwsS3Adapter;
|
44 |
|
45 |
use Mhetreramesh\Flysystem\BackblazeAdapter;
|
46 |
+
use BackblazeB2\Client as B2Client;
|
47 |
|
48 |
use Sabre\DAV\Client as SabreClient;
|
49 |
use League\Flysystem\WebDAV\WebDAVAdapter;
|
50 |
|
51 |
+
/**
|
52 |
+
* Class Xcloner_Remote_Storage
|
53 |
+
*/
|
54 |
+
class Xcloner_Remote_Storage {
|
55 |
+
|
56 |
+
private $gdrive_app_name = "XCloner Backup and Restore";
|
57 |
+
|
58 |
private $storage_fields = array(
|
59 |
+
"option_prefix" => "xcloner_",
|
60 |
+
"ftp" => array(
|
61 |
+
"text" => "FTP",
|
62 |
+
"ftp_enable" => "int",
|
63 |
+
"ftp_hostname" => "string",
|
64 |
+
"ftp_port" => "int",
|
65 |
+
"ftp_username" => "string",
|
66 |
+
"ftp_password" => "raw",
|
67 |
+
"ftp_path" => "path",
|
68 |
+
"ftp_transfer_mode" => "int",
|
69 |
+
"ftp_ssl_mode" => "int",
|
70 |
+
"ftp_timeout" => "int",
|
71 |
+
"ftp_cleanup_days" => "float",
|
72 |
+
),
|
73 |
+
"sftp" => array(
|
74 |
+
"text" => "SFTP",
|
75 |
+
"sftp_enable" => "int",
|
76 |
+
"sftp_hostname" => "string",
|
77 |
+
"sftp_port" => "int",
|
78 |
+
"sftp_username" => "string",
|
79 |
+
"sftp_password" => "raw",
|
80 |
+
"sftp_path" => "path",
|
81 |
+
"sftp_private_key" => "raw",
|
82 |
+
"sftp_timeout" => "int",
|
83 |
+
"sftp_cleanup_days" => "float",
|
84 |
+
),
|
85 |
+
"aws" => array(
|
86 |
+
"text" => "S3",
|
87 |
+
"aws_enable" => "int",
|
88 |
+
"aws_key" => "string",
|
89 |
+
"aws_secret" => "raw",
|
90 |
+
"aws_endpoint" => "string",
|
91 |
+
"aws_region" => "string",
|
92 |
+
"aws_bucket_name" => "string",
|
93 |
+
"aws_prefix" => "string",
|
94 |
+
"aws_cleanup_days" => "float",
|
95 |
+
),
|
96 |
+
"dropbox" => array(
|
97 |
+
"text" => "Dropbox",
|
98 |
+
"dropbox_enable" => "int",
|
99 |
+
"dropbox_access_token" => "string",
|
100 |
+
"dropbox_app_secret" => "raw",
|
101 |
+
"dropbox_prefix" => "string",
|
102 |
+
"dropbox_cleanup_days" => "float",
|
103 |
+
),
|
104 |
+
"azure" => array(
|
105 |
+
"text" => "Azure BLOB",
|
106 |
+
"azure_enable" => "int",
|
107 |
+
"azure_account_name" => "string",
|
108 |
+
"azure_api_key" => "string",
|
109 |
+
"azure_container" => "string",
|
110 |
+
"azure_cleanup_days" => "float",
|
111 |
+
),
|
112 |
+
"backblaze" => array(
|
113 |
+
"text" => "Backblaze",
|
114 |
+
"backblaze_enable" => "int",
|
115 |
+
"backblaze_account_id" => "string",
|
116 |
+
"backblaze_application_key" => "string",
|
117 |
+
"backblaze_bucket_name" => "string",
|
118 |
+
"backblaze_cleanup_days" => "float",
|
119 |
+
),
|
120 |
+
|
121 |
+
"webdav" => array(
|
122 |
+
"text" => "WebDAV",
|
123 |
+
"webdav_enable" => "int",
|
124 |
+
"webdav_url" => "string",
|
125 |
+
"webdav_username" => "string",
|
126 |
+
"webdav_password" => "raw",
|
127 |
+
"webdav_target_folder" => "string",
|
128 |
+
"webdav_cleanup_days" => "float",
|
129 |
+
),
|
130 |
+
|
131 |
+
"gdrive" => array(
|
132 |
+
"text" => "Google Drive",
|
133 |
+
"gdrive_enable" => "int",
|
134 |
+
"gdrive_access_code" => "string",
|
135 |
+
"gdrive_client_id" => "string",
|
136 |
+
"gdrive_client_secret" => "raw",
|
137 |
+
"gdrive_target_folder" => "string",
|
138 |
+
"gdrive_cleanup_days" => "float",
|
139 |
+
"gdrive_empty_trash" => "int",
|
140 |
+
),
|
141 |
+
);
|
142 |
+
|
143 |
+
private $aws_regions = array(
|
144 |
+
'us-east-1' => 'US East (N. Virginia)',
|
145 |
+
'us-east-2' => 'US East (Ohio)',
|
146 |
+
'us-west-1' => 'US West (N. California)',
|
147 |
+
'us-west-2' => 'US West (Oregon)',
|
148 |
+
'ca-central-1' => 'Canada (Central)',
|
149 |
+
'eu-west-1' => 'EU (Ireland)',
|
150 |
+
'eu-central-1' => 'EU (Frankfurt)',
|
151 |
+
'eu-west-2' => 'EU (London)',
|
152 |
+
'ap-northeast-1' => 'Asia Pacific (Tokyo)',
|
153 |
+
'ap-northeast-2' => 'Asia Pacific (Seoul)',
|
154 |
+
'ap-southeast-1' => 'Asia Pacific (Singapore)',
|
155 |
+
'ap-southeast-2' => 'Asia Pacific (Sydney)',
|
156 |
+
'ap-south-1' => 'Asia Pacific (Mumbai)',
|
157 |
+
'sa-east-1' => 'South America (São Paulo)'
|
158 |
+
);
|
159 |
+
|
160 |
private $xcloner_sanitization;
|
161 |
private $xcloner_file_system;
|
162 |
private $logger;
|
163 |
private $xcloner;
|
164 |
+
|
165 |
+
public function __construct( Xcloner $xcloner_container ) {
|
166 |
+
$this->xcloner_sanitization = $xcloner_container->get_xcloner_sanitization();
|
167 |
+
$this->xcloner_file_system = $xcloner_container->get_xcloner_filesystem();
|
168 |
+
$this->logger = $xcloner_container->get_xcloner_logger()->withName( "xcloner_remote_storage" );
|
169 |
+
$this->xcloner = $xcloner_container;
|
170 |
+
|
171 |
+
foreach($this->storage_fields as $main_key=>$array){
|
172 |
+
|
173 |
+
if(is_array($array)) {
|
174 |
+
foreach ($array as $key => $type) {
|
175 |
+
|
176 |
+
if( $type == "raw") {
|
177 |
+
add_filter("pre_update_option_" . $this->storage_fields['option_prefix'] . $key,
|
178 |
+
function ($value) {
|
179 |
+
|
180 |
+
return $this->simple_crypt($value, 'e');
|
181 |
+
|
182 |
+
}, 10, 1);
|
183 |
+
|
184 |
+
add_filter("option_" . $this->storage_fields['option_prefix'] . $key, function ($value) {
|
185 |
+
|
186 |
+
return $this->simple_crypt($value, 'd');
|
187 |
+
|
188 |
+
}, 10, 1);
|
189 |
+
}
|
190 |
+
|
191 |
+
}
|
192 |
+
}
|
193 |
+
}
|
194 |
+
|
195 |
}
|
196 |
+
|
197 |
+
/**
|
198 |
+
* Encrypts and Decrypt a string based on openssl lib
|
199 |
+
*
|
200 |
+
* @param $string
|
201 |
+
* @param string $action
|
202 |
+
* @return string
|
203 |
+
*/
|
204 |
+
private function simple_crypt( $string, $action = 'e' ) {
|
205 |
+
// you may change these values to your own
|
206 |
+
$secret_key = NONCE_KEY;
|
207 |
+
$secret_iv = NONCE_SALT;
|
208 |
+
|
209 |
+
$output = $string;
|
210 |
+
$encrypt_method = "AES-256-CBC";
|
211 |
+
$key = hash( 'sha256', $secret_key );
|
212 |
+
$iv = substr( hash( 'sha256', $secret_iv ), 0, 16 );
|
213 |
+
|
214 |
+
if( $action == 'e' && function_exists('openssl_encrypt')) {
|
215 |
+
$output = base64_encode( openssl_encrypt( $string, $encrypt_method, $key, 0, $iv ) );
|
216 |
+
}
|
217 |
+
else if( $action == 'd' && function_exists('openssl_decrypt') && base64_decode( $string )){
|
218 |
+
$decrypt = openssl_decrypt( base64_decode( $string ), $encrypt_method, $key, 0, $iv );
|
219 |
+
if($decrypt) {
|
220 |
+
//we check if decrypt was succesful
|
221 |
+
$output = $decrypt;
|
222 |
+
}
|
223 |
+
}
|
224 |
+
|
225 |
+
return $output;
|
226 |
+
}
|
227 |
+
|
228 |
+
private function get_xcloner_container() {
|
229 |
return $this->xcloner_container;
|
230 |
}
|
231 |
+
|
232 |
+
public function get_available_storages() {
|
|
|
233 |
$return = array();
|
234 |
+
foreach ( $this->storage_fields as $storage => $data ) {
|
235 |
+
$check_field = $this->storage_fields["option_prefix"] . $storage . "_enable";
|
236 |
+
if ( get_option( $check_field ) ) {
|
237 |
+
$return[ $storage ] = $data['text'];
|
238 |
+
}
|
239 |
}
|
240 |
+
|
241 |
return $return;
|
242 |
}
|
243 |
+
|
244 |
+
public function save( $action = "ftp" ) {
|
245 |
+
if ( ! $action ) {
|
|
|
|
|
246 |
return false;
|
247 |
}
|
248 |
+
|
249 |
+
$storage = $this->xcloner_sanitization->sanitize_input_as_string( $action );
|
250 |
+
$this->logger->debug( sprintf( "Saving the remote storage %s options", strtoupper( $action ) ) );
|
251 |
+
|
252 |
+
if ( is_array( $this->storage_fields[ $storage ] ) ) {
|
253 |
+
foreach ( $this->storage_fields[ $storage ] as $field => $validation ) {
|
254 |
+
$check_field = $this->storage_fields["option_prefix"] . $field;
|
255 |
+
$sanitize_method = "sanitize_input_as_" . $validation;
|
256 |
+
|
257 |
+
if ( ! isset( $_POST[ $check_field ] ) ) {
|
258 |
+
$_POST[ $check_field ] = 0;
|
259 |
+
}
|
260 |
+
|
261 |
+
if ( ! method_exists( $this->xcloner_sanitization, $sanitize_method ) ) {
|
|
|
262 |
$sanitize_method = "sanitize_input_as_string";
|
263 |
+
}
|
264 |
+
|
265 |
+
$sanitized_value = $this->xcloner_sanitization->$sanitize_method( stripslashes( $_POST[ $check_field ] ) );
|
266 |
+
update_option( $check_field, $sanitized_value );
|
267 |
}
|
268 |
+
|
269 |
+
$this->xcloner->trigger_message( __( "%s storage settings saved.", 'xcloner-backup-and-restore' ), "success", $this->storage_fields[ $action ]['text'] );
|
270 |
}
|
271 |
+
|
272 |
}
|
273 |
+
|
274 |
+
public function check( $action = "ftp" ) {
|
275 |
+
try {
|
276 |
+
$this->verify_filesystem( $action );
|
277 |
+
$this->xcloner->trigger_message( __( "%s connection is valid.", 'xcloner-backup-and-restore' ), "success", $this->storage_fields[ $action ]['text'] );
|
278 |
+
$this->logger->debug( sprintf( "Connection to remote storage %s is valid", strtoupper( $action ) ) );
|
279 |
+
} catch ( Exception $e ) {
|
280 |
+
$this->xcloner->trigger_message( "%s connection error: " . $e->getMessage(), "error", $this->storage_fields[ $action ]['text'] );
|
|
|
281 |
}
|
282 |
}
|
283 |
+
|
284 |
+
public function verify_filesystem( $storage_type ) {
|
285 |
+
$method = "get_" . $storage_type . "_filesystem";
|
286 |
+
|
287 |
+
$this->logger->info( sprintf( "Checking validity of the remote storage %s filesystem", strtoupper( $storage_type ) ) );
|
288 |
+
|
289 |
+
if ( ! method_exists( $this, $method ) ) {
|
|
|
290 |
return false;
|
291 |
+
}
|
292 |
+
|
293 |
+
list( $adapter, $filesystem ) = $this->$method();
|
294 |
+
|
295 |
+
$test_file = substr( ".xcloner_" . md5( time() ), 0, 15 );
|
296 |
+
|
297 |
+
if ( $storage_type == "gdrive" ) {
|
298 |
+
if ( ! is_array( $filesystem->listContents() ) ) {
|
299 |
+
throw new Exception( __( "Could not read data", 'xcloner-backup-and-restore' ) );
|
300 |
+
}
|
301 |
+
$this->logger->debug( sprintf( "I can list data from remote storage %s", strtoupper( $storage_type ) ) );
|
302 |
+
|
303 |
return true;
|
304 |
}
|
305 |
+
|
306 |
//testing write access
|
307 |
+
if ( ! $filesystem->write( $test_file, "data" ) ) {
|
308 |
+
throw new Exception( __( "Could not write data", 'xcloner-backup-and-restore' ) );
|
309 |
+
}
|
310 |
+
$this->logger->debug( sprintf( "I can write data to remote storage %s", strtoupper( $storage_type ) ) );
|
311 |
+
|
312 |
//testing read access
|
313 |
+
if ( ! $filesystem->has( $test_file ) ) {
|
314 |
+
throw new Exception( __( "Could not read data", 'xcloner-backup-and-restore' ) );
|
315 |
+
}
|
316 |
+
$this->logger->debug( sprintf( "I can read data to remote storage %s", strtoupper( $storage_type ) ) );
|
317 |
+
|
318 |
//delete test file
|
319 |
+
if ( ! $filesystem->delete( $test_file ) ) {
|
320 |
+
throw new Exception( __( "Could not delete data", 'xcloner-backup-and-restore' ) );
|
321 |
+
}
|
322 |
+
$this->logger->debug( sprintf( "I can delete data to remote storage %s", strtoupper( $storage_type ) ) );
|
323 |
+
|
324 |
return true;
|
325 |
}
|
326 |
+
|
327 |
+
public function upload_backup_to_storage( $file, $storage ) {
|
328 |
+
if ( ! $this->xcloner_file_system->get_storage_filesystem()->has( $file ) ) {
|
329 |
+
$this->logger->info( sprintf( "File not found %s in local storage", $file ) );
|
330 |
+
|
|
|
331 |
return false;
|
332 |
}
|
333 |
+
|
334 |
+
$method = "get_" . $storage . "_filesystem";
|
335 |
+
|
336 |
+
if ( ! method_exists( $this, $method ) ) {
|
337 |
return false;
|
338 |
+
}
|
339 |
+
|
340 |
+
list( $remote_storage_adapter, $remote_storage_filesystem ) = $this->$method();
|
341 |
+
|
342 |
//doing remote storage cleaning here
|
343 |
+
$this->clean_remote_storage( $storage, $remote_storage_filesystem );
|
344 |
+
|
345 |
+
$this->logger->info( sprintf( "Transferring backup %s to remote storage %s", $file, strtoupper( $storage ) ), array( "" ) );
|
346 |
+
|
347 |
/*if(!$this->xcloner_file_system->get_storage_filesystem()->has($file))
|
348 |
{
|
349 |
$this->logger->info(sprintf("File not found %s in local storage", $file));
|
350 |
return false;
|
351 |
}*/
|
|
|
|
|
352 |
|
353 |
+
$backup_file_stream = $this->xcloner_file_system->get_storage_filesystem()->readStream( $file );
|
354 |
+
|
355 |
+
if ( ! $remote_storage_filesystem->writeStream( $file, $backup_file_stream ) ) {
|
356 |
+
$this->logger->info( sprintf( "Could not transfer file %s", $file ) );
|
357 |
+
|
358 |
return false;
|
359 |
}
|
360 |
+
|
361 |
+
if ( $this->xcloner_file_system->is_multipart( $file ) ) {
|
362 |
+
$parts = $this->xcloner_file_system->get_multipart_files( $file );
|
363 |
+
if ( is_array( $parts ) ) {
|
364 |
+
foreach ( $parts as $part_file ) {
|
365 |
+
$this->logger->info( sprintf( "Transferring backup %s to remote storage %s", $part_file, strtoupper( $storage ) ), array( "" ) );
|
366 |
+
|
367 |
+
$backup_file_stream = $this->xcloner_file_system->get_storage_filesystem()->readStream( $part_file );
|
368 |
+
if ( ! $remote_storage_filesystem->writeStream( $part_file, $backup_file_stream ) ) {
|
|
|
|
|
369 |
return false;
|
370 |
+
}
|
371 |
}
|
372 |
+
}
|
373 |
}
|
374 |
+
|
375 |
+
$this->logger->info( sprintf( "Upload done, disconnecting from remote storage %s", strtoupper( $storage ) ) );
|
376 |
+
|
377 |
return true;
|
378 |
+
|
379 |
}
|
380 |
+
|
381 |
+
public function copy_backup_remote_to_local( $file, $storage ) {
|
382 |
+
$method = "get_" . $storage . "_filesystem";
|
383 |
+
|
|
|
384 |
$target_filename = $file;
|
385 |
+
|
386 |
+
if ( ! method_exists( $this, $method ) ) {
|
387 |
return false;
|
388 |
+
}
|
389 |
+
|
390 |
+
list( $remote_storage_adapter, $remote_storage_filesystem ) = $this->$method();
|
391 |
+
|
392 |
+
if ( ! $remote_storage_filesystem->has( $file ) ) {
|
393 |
+
$this->logger->info( sprintf( "File not found %s in remote storage %s", $file, strtoupper( $storage ) ) );
|
394 |
+
|
395 |
return false;
|
396 |
}
|
397 |
+
|
398 |
+
if ( $storage == "gdrive" ) {
|
399 |
+
$metadata = $remote_storage_filesystem->getMetadata( $file );
|
400 |
+
$target_filename = $metadata['filename'] . "." . $metadata['extension'];
|
|
|
401 |
}
|
|
|
|
|
|
|
|
|
402 |
|
403 |
+
$this->logger->info( sprintf( "Transferring backup %s to local storage from %s storage", $file, strtoupper( $storage ) ), array( "" ) );
|
404 |
+
|
405 |
+
$backup_file_stream = $remote_storage_filesystem->readStream( $file );
|
406 |
+
|
407 |
+
if ( ! $this->xcloner_file_system->get_storage_filesystem()->writeStream( $target_filename, $backup_file_stream ) ) {
|
408 |
+
$this->logger->info( sprintf( "Could not transfer file %s", $file ) );
|
409 |
+
|
410 |
return false;
|
411 |
}
|
412 |
+
|
413 |
+
if ( $this->xcloner_file_system->is_multipart( $target_filename ) ) {
|
414 |
+
$parts = $this->xcloner_file_system->get_multipart_files( $file, $storage );
|
415 |
+
if ( is_array( $parts ) ) {
|
416 |
+
foreach ( $parts as $part_file ) {
|
417 |
+
$this->logger->info( sprintf( "Transferring backup %s to local storage from %s storage", $part_file, strtoupper( $storage ) ), array( "" ) );
|
418 |
+
|
419 |
+
$backup_file_stream = $remote_storage_filesystem->readStream( $part_file );
|
420 |
+
if ( ! $this->xcloner_file_system->get_storage_filesystem()->writeStream( $part_file, $backup_file_stream ) ) {
|
|
|
|
|
421 |
return false;
|
422 |
+
}
|
423 |
}
|
424 |
+
}
|
425 |
}
|
426 |
+
|
427 |
+
$this->logger->info( sprintf( "Upload done, disconnecting from remote storage %s", strtoupper( $storage ) ) );
|
428 |
+
|
429 |
return true;
|
430 |
+
|
431 |
}
|
432 |
+
|
433 |
+
public function clean_remote_storage( $storage, $remote_storage_filesystem ) {
|
434 |
+
$check_field = $this->storage_fields["option_prefix"] . $storage . "_cleanup_days";
|
435 |
+
if ( $expire_days = get_option( $check_field ) ) {
|
436 |
+
$this->logger->info( sprintf( "Doing %s remote storage cleanup for %s days limit", strtoupper( $storage ), $expire_days ) );
|
|
|
|
|
437 |
$files = $remote_storage_filesystem->listContents();
|
438 |
+
|
439 |
+
$current_timestamp = strtotime( "-" . $expire_days . " days" );
|
440 |
+
|
441 |
+
if ( is_array( $files ) ) {
|
442 |
+
foreach ( $files as $file ) {
|
443 |
+
$file['timestamp'] = $remote_storage_filesystem->getTimestamp( $file['path'] );
|
444 |
+
|
445 |
+
if ( $current_timestamp >= $file['timestamp'] ) {
|
446 |
+
$remote_storage_filesystem->delete( $file['path'] );
|
447 |
+
$this->logger->info( "Deleting remote file " . $file['path'] . " matching rule", array(
|
448 |
+
"RETENTION LIMIT TIMESTAMP",
|
449 |
+
$file['timestamp'] . " =< " . $expire_days
|
450 |
+
) );
|
451 |
+
}
|
452 |
+
|
453 |
}
|
|
|
454 |
}
|
455 |
}
|
456 |
}
|
457 |
+
|
458 |
+
public function get_azure_filesystem() {
|
459 |
+
$this->logger->info( sprintf( "Creating the AZURE BLOB remote storage connection" ), array( "" ) );
|
460 |
+
|
461 |
+
if ( version_compare( phpversion(), '5.6.0', '<' ) ) {
|
462 |
+
throw new Exception( "AZURE BLOB requires PHP 5.6 to be installed!" );
|
|
|
|
|
463 |
}
|
464 |
+
|
465 |
+
if ( ! class_exists( 'XmlWriter' ) ) {
|
466 |
+
throw new Exception( "AZURE BLOB requires libxml PHP module to be installed with XmlWriter class enabled!" );
|
|
|
467 |
}
|
468 |
+
|
469 |
$endpoint = sprintf(
|
470 |
+
'DefaultEndpointsProtocol=https;AccountName=%s;AccountKey=%s',
|
471 |
+
get_option( "xcloner_azure_account_name" ),
|
472 |
+
get_option( "xcloner_azure_api_key" )
|
473 |
);
|
474 |
+
|
475 |
+
$blobRestProxy = ServicesBuilder::getInstance()->createBlobService( $endpoint );
|
476 |
+
|
477 |
+
$adapter = new AzureAdapter( $blobRestProxy, get_option( "xcloner_azure_container" ) );
|
478 |
+
|
479 |
+
$filesystem = new Filesystem( $adapter, new Config( [
|
480 |
+
'disable_asserts' => true,
|
481 |
+
] ) );
|
482 |
+
|
483 |
+
return array( $adapter, $filesystem );
|
484 |
}
|
485 |
+
|
486 |
+
public function get_dropbox_filesystem() {
|
487 |
+
$this->logger->info( sprintf( "Creating the DROPBOX remote storage connection" ), array( "" ) );
|
488 |
+
|
489 |
+
if ( version_compare( phpversion(), '5.6.0', '<' ) ) {
|
490 |
+
throw new Exception( "DROPBOX requires PHP 5.6 to be installed!" );
|
|
|
|
|
491 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
492 |
|
493 |
+
$client = new DropboxClient( get_option( "xcloner_dropbox_access_token" ) );
|
494 |
+
$adapter = new DropboxAdapter( $client, get_option( "xcloner_dropbox_prefix" ) );
|
495 |
+
|
496 |
+
$filesystem = new Filesystem( $adapter, new Config( [
|
497 |
+
'disable_asserts' => true,
|
498 |
+
] ) );
|
499 |
+
|
500 |
+
return array( $adapter, $filesystem );
|
501 |
}
|
502 |
+
|
503 |
+
public function get_aws_filesystem() {
|
504 |
+
$this->logger->info( sprintf( "Creating the S3 remote storage connection" ), array( "" ) );
|
505 |
+
|
506 |
+
if ( version_compare( phpversion(), '5.6.0', '<' ) ) {
|
507 |
+
throw new Exception( "S3 class requires PHP 5.6 to be installed!" );
|
|
|
|
|
508 |
}
|
509 |
+
|
510 |
+
if ( ! class_exists( 'XmlWriter' ) ) {
|
511 |
+
throw new Exception( "AZURE BLOB requires libxml PHP module to be installed with XmlWriter class enabled!" );
|
|
|
512 |
}
|
513 |
+
|
514 |
+
|
515 |
$credentials = array(
|
516 |
+
'credentials' => array(
|
517 |
+
'key' => get_option( "xcloner_aws_key" ),
|
518 |
+
'secret' => get_option( "xcloner_aws_secret" )
|
519 |
+
),
|
520 |
+
'region' => get_option( "xcloner_aws_region" ),
|
521 |
+
'version' => 'latest',
|
522 |
);
|
523 |
+
|
524 |
+
if ( get_option( 'xcloner_aws_endpoint' ) != "" && ! get_option( "xcloner_aws_region" ) ) {
|
525 |
+
|
526 |
+
$credentials['endpoint'] = get_option( 'xcloner_aws_endpoint' );
|
527 |
#$credentials['use_path_style_endpoint'] = true;
|
528 |
#$credentials['bucket_endpoint'] = false;
|
529 |
+
|
530 |
+
|
531 |
+
}
|
532 |
+
|
533 |
+
$client = new S3Client( $credentials );
|
534 |
+
|
535 |
+
$adapter = new AwsS3Adapter( $client, get_option( "xcloner_aws_bucket_name" ), get_option( "xcloner_aws_prefix" ) );
|
536 |
+
$filesystem = new Filesystem( $adapter, new Config( [
|
537 |
+
'disable_asserts' => true,
|
538 |
+
] ) );
|
539 |
+
|
540 |
+
return array( $adapter, $filesystem );
|
|
|
541 |
}
|
542 |
+
|
543 |
+
public function get_backblaze_filesystem() {
|
544 |
+
$this->logger->info( sprintf( "Creating the BACKBLAZE remote storage connection" ), array( "" ) );
|
545 |
+
|
546 |
+
if ( version_compare( phpversion(), '5.6.0', '<' ) ) {
|
547 |
+
throw new Exception( "BACKBLAZE API requires PHP 5.6 to be installed!" );
|
548 |
+
}
|
549 |
+
|
550 |
+
|
551 |
+
$client = new B2Client( get_option( "xcloner_backblaze_account_id" ), get_option( "xcloner_backblaze_application_key" ) );
|
552 |
+
$adapter = new BackblazeAdapter( $client, get_option( "xcloner_backblaze_bucket_name" ) );
|
553 |
+
|
554 |
+
$filesystem = new Filesystem( $adapter, new Config( [
|
555 |
+
'disable_asserts' => true,
|
556 |
+
] ) );
|
557 |
+
|
558 |
+
return array( $adapter, $filesystem );
|
|
|
|
|
559 |
}
|
560 |
+
|
561 |
+
public function get_webdav_filesystem() {
|
562 |
+
$this->logger->info( sprintf( "Creating the WEBDAV remote storage connection" ), array( "" ) );
|
563 |
+
|
564 |
+
if ( version_compare( phpversion(), '5.6.0', '<' ) ) {
|
565 |
+
throw new Exception( "WEBDAV API requires PHP 5.6 to be installed!" );
|
|
|
|
|
566 |
}
|
567 |
+
|
568 |
$settings = array(
|
569 |
+
'baseUri' => get_option( "xcloner_webdav_url" ),
|
570 |
+
'userName' => get_option( "xcloner_webdav_username" ),
|
571 |
+
'password' => get_option( "xcloner_webdav_password" ),
|
572 |
//'proxy' => 'locahost:8888',
|
573 |
);
|
574 |
+
|
575 |
+
|
576 |
+
$client = new SabreClient( $settings );
|
577 |
+
$adapter = new WebDAVAdapter( $client, get_option( "xcloner_webdav_target_folder" ) );
|
578 |
+
$filesystem = new Filesystem( $adapter, new Config( [
|
579 |
+
'disable_asserts' => true,
|
580 |
+
] ) );
|
581 |
+
|
582 |
+
return array( $adapter, $filesystem );
|
583 |
}
|
584 |
+
|
585 |
+
|
586 |
+
public function gdrive_construct() {
|
|
|
587 |
|
588 |
//if((function_exists("is_plugin_active") && !is_plugin_active("xcloner-google-drive/xcloner-google-drive.php")) || !file_exists(__DIR__ . "/../../xcloner-google-drive/vendor/autoload.php"))
|
589 |
+
if ( ! class_exists( 'Google_Client' ) ) {
|
|
|
590 |
return false;
|
591 |
}
|
592 |
+
|
593 |
//require_once(__DIR__ . "/../../xcloner-google-drive/vendor/autoload.php");
|
594 |
+
|
595 |
$client = new \Google_Client();
|
596 |
+
$client->setApplicationName( $this->gdrive_app_name );
|
597 |
+
$client->setClientId( get_option( "xcloner_gdrive_client_id" ) );
|
598 |
+
$client->setClientSecret( get_option( "xcloner_gdrive_client_secret" ) );
|
599 |
+
|
600 |
//$redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']."?page=xcloner_remote_storage_page&action=set_gdrive_code";
|
601 |
$redirect_uri = "urn:ietf:wg:oauth:2.0:oob";
|
602 |
+
|
603 |
+
$client->setRedirectUri( $redirect_uri ); //urn:ietf:wg:oauth:2.0:oob
|
604 |
+
$client->addScope( "https://www.googleapis.com/auth/drive" );
|
605 |
+
$client->setAccessType( 'offline' );
|
606 |
+
|
607 |
return $client;
|
608 |
}
|
609 |
+
|
610 |
+
public function get_gdrive_auth_url() {
|
|
|
611 |
$client = $this->gdrive_construct();
|
612 |
+
|
613 |
+
if ( ! $client ) {
|
614 |
return false;
|
615 |
+
}
|
616 |
+
|
617 |
return $authUrl = $client->createAuthUrl();
|
618 |
}
|
619 |
+
|
620 |
+
public function set_access_token( $code ) {
|
|
|
621 |
$client = $this->gdrive_construct();
|
622 |
+
|
623 |
+
if ( ! $client ) {
|
|
|
624 |
$error_msg = "Could not initialize the Google Drive Class, please check that the xcloner-google-drive plugin is enabled...";
|
625 |
+
$this->logger->error( $error_msg );
|
626 |
+
|
627 |
return false;
|
628 |
}
|
629 |
|
630 |
+
$token = $client->fetchAccessTokenWithAuthCode( $code );
|
631 |
+
$client->setAccessToken( $token );
|
632 |
+
|
633 |
+
update_option( "xcloner_gdrive_access_token", $token['access_token'] );
|
634 |
+
update_option( "xcloner_gdrive_refresh_token", $token['refresh_token'] );
|
635 |
+
|
636 |
+
$redirect_url = ( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'] . "?page=xcloner_remote_storage_page#gdrive" );
|
637 |
+
|
638 |
?>
|
639 |
+
<script>
|
640 |
+
window.location = '<?php echo $redirect_url?>';
|
641 |
+
</script>
|
642 |
<?php
|
643 |
+
|
644 |
}
|
645 |
+
|
646 |
/*
|
647 |
* php composer.phar remove nao-pon/flysystem-google-drive
|
648 |
*
|
649 |
*/
|
650 |
+
public function get_gdrive_filesystem() {
|
651 |
+
|
652 |
+
if ( version_compare( phpversion(), '5.6.0', '<' ) ) {
|
653 |
+
throw new Exception( "Google Drive API requires PHP 5.6 to be installed!" );
|
|
|
|
|
654 |
}
|
655 |
+
|
656 |
+
$this->logger->info( sprintf( "Creating the Google Drive remote storage connection" ), array( "" ) );
|
657 |
+
|
658 |
$client = $this->gdrive_construct();
|
659 |
+
|
660 |
+
if ( ! $client ) {
|
|
|
661 |
$error_msg = "Could not initialize the Google Drive Class, please check that the xcloner-google-drive plugin is enabled...";
|
662 |
+
$this->logger->error( $error_msg );
|
663 |
+
throw new Exception( $error_msg );
|
664 |
+
}
|
665 |
+
|
666 |
+
$client->refreshToken( get_option( "xcloner_gdrive_refresh_token" ) );
|
667 |
+
|
668 |
+
$service = new \Google_Service_Drive( $client );
|
669 |
+
|
670 |
/*if( get_option("xcloner_gdrive_empty_trash",0) ){
|
671 |
$this->logger->info(sprintf("Doing a Google Drive emptyTrash call"), array(""));
|
672 |
$service->files->emptyTrash();
|
673 |
}*/
|
674 |
+
|
675 |
$parent = 'root';
|
676 |
+
$dir = basename( get_option( "xcloner_gdrive_target_folder" ) );
|
677 |
+
|
678 |
+
$folderID = get_option( "xcloner_gdrive_target_folder" );
|
679 |
+
|
680 |
+
$tmp = parse_url( $folderID );
|
681 |
+
|
682 |
+
if ( isset( $tmp['query'] ) ) {
|
683 |
+
$folderID = str_replace( "id=", "", $tmp['query'] );
|
|
|
684 |
}
|
685 |
+
|
686 |
+
if ( stristr( $folderID, "/" ) ) {
|
687 |
+
$query = sprintf( 'mimeType = \'application/vnd.google-apps.folder\' and \'%s\' in parents and name contains \'%s\'', $parent, $dir );
|
688 |
+
$response = $service->files->listFiles( [
|
689 |
+
'pageSize' => 1,
|
690 |
+
'q' => $query
|
691 |
+
] );
|
692 |
+
|
693 |
+
if ( sizeof( $response ) ) {
|
694 |
+
foreach ( $response as $obj ) {
|
695 |
+
$folderID = $obj->getId();
|
|
|
|
|
696 |
}
|
697 |
+
} else {
|
698 |
+
$this->xcloner->trigger_message( sprintf( __( "Could not find folder ID by name %s", 'xcloner-backup-and-restore' ), $folderID ), "error" );
|
699 |
}
|
700 |
}
|
701 |
+
|
702 |
+
$this->logger->info( sprintf( "Using target folder with ID %s on the remote storage", $folderID ) );
|
703 |
+
|
704 |
+
if ( class_exists( 'XCloner_Google_Drive_Adapter' ) ) {
|
705 |
+
$adapter = new XCloner_Google_Drive_Adapter( $service, $folderID );
|
706 |
+
} else {
|
707 |
+
$adapter = new \Hypweb\Flysystem\GoogleDrive\GoogleDriveAdapter( $service, $folderID );
|
708 |
+
}
|
709 |
+
|
710 |
+
$filesystem = new \League\Flysystem\Filesystem( $adapter, new Config( [
|
711 |
+
'disable_asserts' => true,
|
712 |
+
] ) );
|
713 |
+
|
714 |
+
|
715 |
+
return array( $adapter, $filesystem );
|
716 |
}
|
717 |
+
|
718 |
+
public function get_ftp_filesystem() {
|
719 |
+
$this->logger->info( sprintf( "Creating the FTP remote storage connection" ), array( "" ) );
|
720 |
+
|
721 |
+
$adapter = new Adapter( [
|
722 |
+
'host' => get_option( "xcloner_ftp_hostname" ),
|
723 |
+
'username' => get_option( "xcloner_ftp_username" ),
|
724 |
+
'password' => get_option( "xcloner_ftp_password" ),
|
725 |
+
|
726 |
+
/** optional config settings */
|
727 |
+
'port' => get_option( "xcloner_ftp_port", 21 ),
|
728 |
+
'root' => get_option( "xcloner_ftp_path" ),
|
729 |
+
'passive' => get_option( "xcloner_ftp_transfer_mode" ),
|
730 |
+
'ssl' => get_option( "xcloner_ftp_ssl_mode" ),
|
731 |
+
'timeout' => get_option( "xcloner_ftp_timeout", 30 ),
|
732 |
+
] );
|
733 |
+
|
|
|
734 |
$adapter->connect();
|
735 |
+
|
736 |
+
$filesystem = new Filesystem( $adapter, new Config( [
|
737 |
+
'disable_asserts' => true,
|
738 |
+
] ) );
|
739 |
+
|
740 |
+
return array( $adapter, $filesystem );
|
741 |
}
|
742 |
+
|
743 |
+
public function get_sftp_filesystem() {
|
744 |
+
$this->logger->info( sprintf( "Creating the SFTP remote storage connection" ), array( "" ) );
|
745 |
+
|
746 |
+
$adapter = new SftpAdapter( [
|
747 |
+
'host' => get_option( "xcloner_sftp_hostname" ),
|
748 |
+
'username' => get_option( "xcloner_sftp_username" ),
|
749 |
+
'password' => get_option( "xcloner_sftp_password" ),
|
750 |
+
|
751 |
+
/** optional config settings */
|
752 |
+
'port' => get_option( "xcloner_sftp_port", 22 ),
|
753 |
+
'root' => get_option( "xcloner_sftp_path" ),
|
754 |
+
'privateKey' => get_option( "xcloner_sftp_private_key" ),
|
755 |
+
'timeout' => get_option( "xcloner_ftp_timeout", 30 ),
|
756 |
+
] );
|
757 |
+
|
|
|
758 |
$adapter->connect();
|
759 |
+
|
760 |
+
$filesystem = new Filesystem( $adapter, new Config( [
|
761 |
+
'disable_asserts' => true,
|
762 |
+
] ) );
|
763 |
+
|
764 |
+
return array( $adapter, $filesystem );
|
765 |
}
|
|
|
|
|
|
|
|
|
|
|
766 |
|
767 |
+
public function change_storage_status( $field, $value ) {
|
768 |
+
$field = $this->xcloner_sanitization->sanitize_input_as_string( $field );
|
769 |
+
$value = $this->xcloner_sanitization->sanitize_input_as_int( $value );
|
770 |
+
|
771 |
+
return update_option( $field, $value );
|
772 |
}
|
773 |
+
|
774 |
+
public function get_aws_regions() {
|
|
|
775 |
return $this->aws_regions;
|
776 |
}
|
777 |
+
|
778 |
}
|
includes/class-xcloner-requirements.php
CHANGED
@@ -1,69 +1,67 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
class Xcloner_Requirements
|
4 |
-
|
5 |
-
|
6 |
-
var $
|
7 |
-
|
8 |
-
|
9 |
private $xcloner_settings;
|
10 |
private $xcloner_container;
|
11 |
-
|
12 |
-
public function __construct(Xcloner $xcloner_container)
|
13 |
-
{
|
14 |
$this->xcloner_container = $xcloner_container;
|
15 |
-
$this->xcloner_settings
|
16 |
}
|
17 |
-
|
18 |
-
private function get_xcloner_container()
|
19 |
-
{
|
20 |
return $this->xcloner_container;
|
21 |
}
|
22 |
-
|
23 |
-
public function check_backup_ready_status()
|
24 |
-
|
25 |
-
if(!$this->check_min_php_version(1))
|
26 |
return false;
|
27 |
-
|
28 |
-
|
|
|
29 |
return false;
|
30 |
-
|
31 |
-
|
|
|
32 |
return false;
|
33 |
-
|
34 |
-
|
|
|
35 |
return false;
|
36 |
-
|
37 |
-
|
|
|
38 |
return false;
|
39 |
-
|
40 |
-
|
|
|
41 |
}
|
42 |
-
|
43 |
-
public function get_constant($var)
|
44 |
-
{
|
45 |
return $this->$var;
|
46 |
}
|
47 |
-
|
48 |
-
public function check_min_php_version($return_bool = 0)
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
{
|
53 |
-
if(version_compare(phpversion(), $this->min_php_version, '<'))
|
54 |
return false;
|
55 |
-
else
|
56 |
return true;
|
|
|
57 |
}
|
58 |
-
|
59 |
return phpversion();
|
60 |
}
|
61 |
-
|
62 |
-
public function check_safe_mode($return_bool=0)
|
63 |
-
{
|
64 |
/*no longer needed for PHP 7*/
|
65 |
$safe_mode = "Off";
|
66 |
-
|
67 |
/*if($return_bool)
|
68 |
{
|
69 |
if( ini_get('safe_mode') )
|
@@ -75,98 +73,97 @@ class Xcloner_Requirements
|
|
75 |
if( ini_get('safe_mode') )
|
76 |
$safe_mode = "On";
|
77 |
* */
|
78 |
-
|
79 |
return $safe_mode;
|
80 |
}
|
81 |
-
|
82 |
-
public function check_xcloner_start_path($return_bool=0)
|
83 |
-
{
|
84 |
$path = $this->xcloner_settings->get_xcloner_start_path();
|
85 |
-
|
86 |
-
if($return_bool)
|
87 |
-
|
88 |
-
if(!file_exists($path))
|
89 |
return false;
|
90 |
-
|
91 |
-
|
|
|
92 |
}
|
93 |
-
|
94 |
return $path;
|
95 |
}
|
96 |
-
|
97 |
-
public function check_xcloner_tmp_path($return_bool=0)
|
98 |
-
{
|
99 |
$path = $this->xcloner_settings->get_xcloner_tmp_path();
|
100 |
-
|
101 |
-
if($return_bool)
|
102 |
-
|
103 |
-
if(!file_exists($path))
|
104 |
return false;
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
|
|
|
|
110 |
}
|
111 |
-
|
112 |
return $path;
|
113 |
}
|
114 |
-
|
115 |
-
public function check_xcloner_store_path($return_bool=0)
|
116 |
-
{
|
117 |
$path = $this->xcloner_settings->get_xcloner_store_path();
|
118 |
-
|
119 |
-
if($return_bool)
|
120 |
-
|
121 |
-
if(!file_exists($path))
|
122 |
return false;
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
|
|
|
|
128 |
}
|
129 |
-
|
130 |
return $path;
|
131 |
}
|
132 |
-
|
133 |
-
public function get_max_execution_time()
|
134 |
-
|
135 |
-
return ini_get('max_execution_time');
|
136 |
}
|
137 |
-
|
138 |
-
public function get_memory_limit()
|
139 |
-
|
140 |
-
return ini_get('memory_limit');
|
141 |
}
|
142 |
-
|
143 |
-
public function get_open_basedir()
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
if(!$open_basedir)
|
148 |
$open_basedir = "none";
|
149 |
-
|
|
|
|
|
150 |
}
|
151 |
-
|
152 |
-
public function get_free_disk_space()
|
153 |
-
|
154 |
-
return $this->file_format_size(disk_free_space($this->xcloner_settings->get_xcloner_store_path()));
|
155 |
}
|
156 |
-
|
157 |
-
public function file_format_size($bytes, $decimals = 2) {
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
|
|
170 |
}
|
171 |
}
|
|
|
172 |
?>
|
1 |
<?php
|
2 |
|
3 |
+
class Xcloner_Requirements {
|
4 |
+
|
5 |
+
var $min_php_version = "5.6.0";
|
6 |
+
var $safe_mode = "Off";
|
7 |
+
|
|
|
8 |
private $xcloner_settings;
|
9 |
private $xcloner_container;
|
10 |
+
|
11 |
+
public function __construct( Xcloner $xcloner_container ) {
|
|
|
12 |
$this->xcloner_container = $xcloner_container;
|
13 |
+
$this->xcloner_settings = $xcloner_container->get_xcloner_settings();
|
14 |
}
|
15 |
+
|
16 |
+
private function get_xcloner_container() {
|
|
|
17 |
return $this->xcloner_container;
|
18 |
}
|
19 |
+
|
20 |
+
public function check_backup_ready_status() {
|
21 |
+
if ( ! $this->check_min_php_version( 1 ) ) {
|
|
|
22 |
return false;
|
23 |
+
}
|
24 |
+
|
25 |
+
if ( ! $this->check_safe_mode( 1 ) ) {
|
26 |
return false;
|
27 |
+
}
|
28 |
+
|
29 |
+
if ( ! $this->check_xcloner_start_path( 1 ) ) {
|
30 |
return false;
|
31 |
+
}
|
32 |
+
|
33 |
+
if ( ! $this->check_xcloner_store_path( 1 ) ) {
|
34 |
return false;
|
35 |
+
}
|
36 |
+
|
37 |
+
if ( ! $this->check_xcloner_tmp_path( 1 ) ) {
|
38 |
return false;
|
39 |
+
}
|
40 |
+
|
41 |
+
return true;
|
42 |
}
|
43 |
+
|
44 |
+
public function get_constant( $var ) {
|
|
|
45 |
return $this->$var;
|
46 |
}
|
47 |
+
|
48 |
+
public function check_min_php_version( $return_bool = 0 ) {
|
49 |
+
|
50 |
+
if ( $return_bool == 1 ) {
|
51 |
+
if ( version_compare( phpversion(), $this->min_php_version, '<' ) ) {
|
|
|
|
|
52 |
return false;
|
53 |
+
} else {
|
54 |
return true;
|
55 |
+
}
|
56 |
}
|
57 |
+
|
58 |
return phpversion();
|
59 |
}
|
60 |
+
|
61 |
+
public function check_safe_mode( $return_bool = 0 ) {
|
|
|
62 |
/*no longer needed for PHP 7*/
|
63 |
$safe_mode = "Off";
|
64 |
+
|
65 |
/*if($return_bool)
|
66 |
{
|
67 |
if( ini_get('safe_mode') )
|
73 |
if( ini_get('safe_mode') )
|
74 |
$safe_mode = "On";
|
75 |
* */
|
76 |
+
|
77 |
return $safe_mode;
|
78 |
}
|
79 |
+
|
80 |
+
public function check_xcloner_start_path( $return_bool = 0 ) {
|
|
|
81 |
$path = $this->xcloner_settings->get_xcloner_start_path();
|
82 |
+
|
83 |
+
if ( $return_bool ) {
|
84 |
+
if ( ! file_exists( $path ) ) {
|
|
|
85 |
return false;
|
86 |
+
}
|
87 |
+
|
88 |
+
return is_readable( $path );
|
89 |
}
|
90 |
+
|
91 |
return $path;
|
92 |
}
|
93 |
+
|
94 |
+
public function check_xcloner_tmp_path( $return_bool = 0 ) {
|
|
|
95 |
$path = $this->xcloner_settings->get_xcloner_tmp_path();
|
96 |
+
|
97 |
+
if ( $return_bool ) {
|
98 |
+
if ( ! file_exists( $path ) ) {
|
|
|
99 |
return false;
|
100 |
+
}
|
101 |
+
|
102 |
+
if ( ! is_writeable( $path ) ) {
|
103 |
+
@chmod( $path, 0777 );
|
104 |
+
}
|
105 |
+
|
106 |
+
return is_writeable( $path );
|
107 |
}
|
108 |
+
|
109 |
return $path;
|
110 |
}
|
111 |
+
|
112 |
+
public function check_xcloner_store_path( $return_bool = 0 ) {
|
|
|
113 |
$path = $this->xcloner_settings->get_xcloner_store_path();
|
114 |
+
|
115 |
+
if ( $return_bool ) {
|
116 |
+
if ( ! file_exists( $path ) ) {
|
|
|
117 |
return false;
|
118 |
+
}
|
119 |
+
|
120 |
+
if ( ! is_writeable( $path ) ) {
|
121 |
+
@chmod( $path, 0777 );
|
122 |
+
}
|
123 |
+
|
124 |
+
return is_writeable( $path );
|
125 |
}
|
126 |
+
|
127 |
return $path;
|
128 |
}
|
129 |
+
|
130 |
+
public function get_max_execution_time() {
|
131 |
+
return ini_get( 'max_execution_time' );
|
|
|
132 |
}
|
133 |
+
|
134 |
+
public function get_memory_limit() {
|
135 |
+
return ini_get( 'memory_limit' );
|
|
|
136 |
}
|
137 |
+
|
138 |
+
public function get_open_basedir() {
|
139 |
+
$open_basedir = ini_get( 'open_basedir' );
|
140 |
+
|
141 |
+
if ( ! $open_basedir ) {
|
|
|
142 |
$open_basedir = "none";
|
143 |
+
}
|
144 |
+
|
145 |
+
return $open_basedir;
|
146 |
}
|
147 |
+
|
148 |
+
public function get_free_disk_space() {
|
149 |
+
return $this->file_format_size( disk_free_space( $this->xcloner_settings->get_xcloner_store_path() ) );
|
|
|
150 |
}
|
151 |
+
|
152 |
+
public function file_format_size( $bytes, $decimals = 2 ) {
|
153 |
+
$unit_list = array( 'B', 'KB', 'MB', 'GB', 'PB' );
|
154 |
+
|
155 |
+
if ( $bytes == 0 ) {
|
156 |
+
return $bytes . ' ' . $unit_list[0];
|
157 |
+
}
|
158 |
+
|
159 |
+
$unit_count = count( $unit_list );
|
160 |
+
for ( $i = $unit_count - 1; $i >= 0; $i -- ) {
|
161 |
+
$power = $i * 10;
|
162 |
+
if ( ( $bytes >> $power ) >= 1 ) {
|
163 |
+
return round( $bytes / ( 1 << $power ), $decimals ) . ' ' . $unit_list[ $i ];
|
164 |
+
}
|
165 |
+
}
|
166 |
}
|
167 |
}
|
168 |
+
|
169 |
?>
|
includes/class-xcloner-sanitization.php
CHANGED
@@ -1,64 +1,59 @@
|
|
1 |
<?php
|
|
|
2 |
use League\Flysystem\Util;
|
3 |
|
4 |
class Xcloner_Sanitization {
|
5 |
-
|
6 |
-
public function __construct(){
|
7 |
-
|
8 |
-
|
9 |
-
{
|
10 |
-
return filter_var($option, FILTER_SANITIZE_NUMBER_INT);
|
11 |
}
|
12 |
-
|
13 |
-
public function sanitize_input_as_float($option)
|
14 |
-
|
15 |
-
return filter_var($option, FILTER_VALIDATE_FLOAT);
|
16 |
}
|
17 |
-
|
18 |
-
public function sanitize_input_as_string($option)
|
19 |
-
|
20 |
-
return filter_var($option, FILTER_SANITIZE_STRING);
|
21 |
}
|
22 |
-
|
23 |
-
public function sanitize_input_as_absolute_path($option)
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
add_settings_error('xcloner_error_message', '', __($e->getMessage()), 'error');
|
31 |
}
|
32 |
-
|
33 |
-
if($path and !is_dir($path)){
|
34 |
-
add_settings_error('xcloner_error_message', '', __(sprintf('Invalid Server Path %s'
|
|
|
35 |
return false;
|
36 |
}
|
37 |
-
|
38 |
return $path;
|
39 |
}
|
40 |
-
|
41 |
-
public function sanitize_input_as_path($option)
|
42 |
-
|
43 |
-
return filter_var($option, FILTER_SANITIZE_URL);
|
44 |
}
|
45 |
-
|
46 |
-
public function sanitize_input_as_relative_path($option)
|
47 |
-
|
48 |
-
$option =
|
49 |
-
|
50 |
-
|
51 |
return $option;
|
52 |
}
|
53 |
-
|
54 |
-
public function sanitize_input_as_email($option)
|
55 |
-
|
56 |
-
return filter_var($option, FILTER_SANITIZE_EMAIL);
|
57 |
}
|
58 |
|
59 |
-
public function sanitize_input_as_raw($option)
|
60 |
-
|
61 |
-
return filter_var($option, FILTER_UNSAFE_RAW);
|
62 |
}
|
63 |
-
|
64 |
}
|
1 |
<?php
|
2 |
+
|
3 |
use League\Flysystem\Util;
|
4 |
|
5 |
class Xcloner_Sanitization {
|
6 |
+
|
7 |
+
public function __construct() {
|
8 |
+
}
|
9 |
+
|
10 |
+
public function sanitize_input_as_int( $option ) {
|
11 |
+
return filter_var( $option, FILTER_SANITIZE_NUMBER_INT );
|
12 |
}
|
13 |
+
|
14 |
+
public function sanitize_input_as_float( $option ) {
|
15 |
+
return filter_var( $option, FILTER_VALIDATE_FLOAT );
|
|
|
16 |
}
|
17 |
+
|
18 |
+
public function sanitize_input_as_string( $option ) {
|
19 |
+
return filter_var( $option, FILTER_SANITIZE_STRING );
|
|
|
20 |
}
|
21 |
+
|
22 |
+
public function sanitize_input_as_absolute_path( $option ) {
|
23 |
+
$path = filter_var( $option, FILTER_SANITIZE_URL );
|
24 |
+
|
25 |
+
try {
|
26 |
+
$option = Util::normalizePath( $path );
|
27 |
+
} catch ( Exception $e ) {
|
28 |
+
add_settings_error( 'xcloner_error_message', '', __( $e->getMessage() ), 'error' );
|
|
|
29 |
}
|
30 |
+
|
31 |
+
if ( $path and ! is_dir( $path ) ) {
|
32 |
+
add_settings_error( 'xcloner_error_message', '', __( sprintf( 'Invalid Server Path %s', $option ) ), 'error' );
|
33 |
+
|
34 |
return false;
|
35 |
}
|
36 |
+
|
37 |
return $path;
|
38 |
}
|
39 |
+
|
40 |
+
public function sanitize_input_as_path( $option ) {
|
41 |
+
return filter_var( $option, FILTER_SANITIZE_URL );
|
|
|
42 |
}
|
43 |
+
|
44 |
+
public function sanitize_input_as_relative_path( $option ) {
|
45 |
+
$option = filter_var( $option, FILTER_SANITIZE_URL );
|
46 |
+
$option = str_replace( "..", "", $option );
|
47 |
+
|
|
|
48 |
return $option;
|
49 |
}
|
50 |
+
|
51 |
+
public function sanitize_input_as_email( $option ) {
|
52 |
+
return filter_var( $option, FILTER_SANITIZE_EMAIL );
|
|
|
53 |
}
|
54 |
|
55 |
+
public function sanitize_input_as_raw( $option ) {
|
56 |
+
return filter_var( $option, FILTER_UNSAFE_RAW );
|
|
|
57 |
}
|
58 |
+
|
59 |
}
|
includes/class-xcloner-scheduler.php
CHANGED
@@ -1,396 +1,372 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
class Xcloner_Scheduler{
|
4 |
-
|
5 |
private $db;
|
6 |
private $scheduler_table = "xcloner_scheduler";
|
7 |
-
|
8 |
private $xcloner_remote_storage;
|
9 |
private $archive_system;
|
10 |
private $xcloner_database;
|
11 |
private $xcloner_settings;
|
12 |
private $logger;
|
13 |
private $xcloner_file_system;
|
14 |
-
|
15 |
-
private $allowed_schedules = array("hourly", "twicedaily", "daily", "weekly", "monthly");
|
|
|
16 |
/*public function __call($method, $args) {
|
17 |
echo "$method is not defined";
|
18 |
}*/
|
19 |
|
20 |
-
public function __construct(Xcloner $xcloner_container)
|
21 |
-
{
|
22 |
global $wpdb;
|
23 |
-
|
24 |
-
$this->db
|
25 |
-
$wpdb->show_errors
|
26 |
-
|
27 |
-
$this->xcloner_container
|
28 |
-
$this->xcloner_settings
|
29 |
-
|
30 |
-
$this->scheduler_table
|
31 |
}
|
32 |
-
|
33 |
-
private function get_xcloner_container()
|
34 |
-
{
|
35 |
return $this->xcloner_container;
|
36 |
}
|
37 |
-
|
38 |
-
private function set_xcloner_container(Xcloner $container)
|
39 |
-
{
|
40 |
$this->xcloner_container = $container;
|
41 |
}
|
42 |
-
|
43 |
-
public function get_scheduler_list($return_only_enabled = 0 )
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
$
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
{
|
54 |
-
$res->next_run_time = wp_next_scheduled('xcloner_scheduler_'.$res->id, array($res->id))+(get_option( 'gmt_offset' ) * HOUR_IN_SECONDS);
|
55 |
-
$new_list[] = $res;
|
56 |
}
|
57 |
-
|
|
|
58 |
}
|
|
|
59 |
return $list;
|
60 |
}
|
61 |
-
|
62 |
-
public function get_next_run_schedule($xcloner_file_system = "")
|
63 |
-
|
64 |
-
$list = $this->get_scheduler_list($return_only_enabled = 1);
|
65 |
|
66 |
return $list;
|
67 |
}
|
68 |
-
|
69 |
-
public function get_schedule_by_id_object($id)
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
return $data;
|
74 |
}
|
75 |
-
|
76 |
-
public function get_schedule_by_id($id)
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
if(!$data)
|
81 |
return false;
|
82 |
-
|
83 |
-
|
84 |
-
|
|
|
85 |
//print_r($params);
|
86 |
-
$data['params']
|
87 |
-
$data['backup_params']
|
88 |
-
$data['table_params']
|
89 |
-
$data['excluded_files'] = json_encode($params->excluded_files);
|
90 |
-
|
91 |
-
|
92 |
return $data;
|
93 |
}
|
94 |
-
|
95 |
-
public function delete_schedule_by_id($id)
|
96 |
-
|
97 |
-
$hook
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
return $data;
|
103 |
}
|
104 |
-
|
105 |
-
public function deactivate_wp_cron_hooks()
|
106 |
-
{
|
107 |
$list = $this->get_scheduler_list();
|
108 |
-
|
109 |
-
foreach($list as $schedule)
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
$timestamp
|
114 |
-
wp_unschedule_event( $timestamp, $hook, array($schedule->id) );
|
115 |
}
|
116 |
}
|
117 |
-
|
118 |
-
public function update_wp_cron_hooks()
|
119 |
-
{
|
120 |
$list = $this->get_scheduler_list();
|
121 |
-
|
122 |
-
foreach($list as $schedule)
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
//adding the xcloner_scheduler hook with xcloner_scheduler_callback callback
|
127 |
-
add_action( $hook, array($this, 'xcloner_scheduler_callback'), 10,
|
128 |
-
|
129 |
-
if ( ! wp_next_scheduled( $hook, array($schedule->id) ) and $schedule->status) {
|
130 |
-
|
131 |
-
if($schedule->recurrence == "single")
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
wp_schedule_event( strtotime($schedule->start_at), $schedule->recurrence, $hook, array($schedule->id) );
|
136 |
}
|
137 |
-
|
138 |
-
}elseif(
|
139 |
-
|
140 |
-
$timestamp
|
141 |
-
wp_unschedule_event( $timestamp, $hook, array($schedule->id) );
|
142 |
}
|
143 |
}
|
144 |
-
|
145 |
}
|
146 |
-
|
147 |
-
public function update_cron_hook($id)
|
148 |
-
|
149 |
-
$
|
150 |
-
|
151 |
-
|
152 |
-
$timestamp
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
{
|
159 |
-
|
160 |
-
}else{
|
161 |
-
wp_schedule_event( strtotime($schedule->start_at), $schedule->recurrence, $hook, array($schedule->id) );
|
162 |
}
|
163 |
-
|
164 |
}
|
165 |
-
}
|
166 |
-
|
167 |
-
public function disable_single_cron($schedule_id)
|
168 |
-
|
169 |
-
$hook
|
170 |
-
$timestamp
|
171 |
-
|
172 |
-
|
173 |
$schedule['status'] = 0;
|
174 |
-
|
175 |
-
$update = $this->db->update(
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
|
|
185 |
}
|
186 |
-
|
187 |
-
public function update_hash($schedule_id, $hash)
|
188 |
-
{
|
189 |
$schedule['hash'] = $hash;
|
190 |
-
|
191 |
-
$update = $this->db->update(
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
{
|
205 |
$schedule['last_backup'] = $last_backup;
|
206 |
-
|
207 |
-
$update = $this->db->update(
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
{
|
221 |
-
set_time_limit(0);
|
222 |
-
|
223 |
$xcloner = new XCloner();
|
224 |
$xcloner->init();
|
225 |
-
$this->set_xcloner_container($xcloner);
|
226 |
-
|
227 |
#$hash = $this->xcloner_settings->get_hash();
|
228 |
#$this->get_xcloner_container()->get_xcloner_settings()->set_hash($hash);
|
229 |
-
|
230 |
//$this->xcloner_settings = $this->get_xcloner_container()->get_xcloner_settings();
|
231 |
-
$this->xcloner_file_system
|
232 |
-
$this->xcloner_database
|
233 |
-
$this->archive_system
|
234 |
-
$this->logger
|
235 |
-
$this->xcloner_remote_storage
|
236 |
-
|
237 |
-
$this->logger->info(sprintf("New schedule hash is %s", $this->xcloner_settings->get_hash()));
|
238 |
-
|
239 |
-
if(isset($schedule['backup_params']->diff_start_date) && $schedule['backup_params']->diff_start_date)
|
240 |
-
|
241 |
-
$this->xcloner_file_system->set_diff_timestamp_start($schedule['backup_params']->diff_start_date);
|
242 |
}
|
243 |
-
|
244 |
-
if($schedule['recurrence'] == "single")
|
245 |
-
|
246 |
-
$this->disable_single_cron($schedule['id']);
|
247 |
}
|
248 |
-
|
249 |
-
if(
|
250 |
-
|
251 |
-
|
252 |
return;
|
253 |
}
|
254 |
-
|
255 |
//echo $this->get_xcloner_container()->get_xcloner_settings()->get_hash(); exit;
|
256 |
-
|
257 |
-
$this->update_hash($schedule['id'], $this->xcloner_settings->get_hash());
|
258 |
-
|
259 |
-
$this->logger->info(sprintf("Starting cron schedule '%s'", $schedule['name']), array("CRON"));
|
260 |
-
|
261 |
-
$this->xcloner_file_system->set_excluded_files(json_decode($schedule['excluded_files']));
|
262 |
-
|
263 |
-
$init
|
264 |
$continue = 1;
|
265 |
|
266 |
-
while($continue)
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
$init = 0;
|
271 |
}
|
272 |
-
|
273 |
-
$this->logger->info(sprintf("File scan finished"), array("CRON"));
|
274 |
-
|
275 |
-
$this->logger->info(sprintf("Starting the database backup"), array("CRON"));
|
276 |
-
|
277 |
-
$init
|
278 |
$return['finished'] = 0;
|
279 |
-
|
280 |
-
while(
|
281 |
-
|
282 |
-
$
|
283 |
-
$init = 0;
|
284 |
}
|
285 |
-
|
286 |
-
$this->logger->info(sprintf("Database backup done"), array("CRON"));
|
287 |
-
|
288 |
-
$this->logger->info(sprintf("Starting file archive process"), array("CRON"));
|
289 |
-
|
290 |
-
$init
|
291 |
$return['finished'] = 0;
|
292 |
-
$return['extra']
|
293 |
-
|
294 |
-
while(
|
295 |
-
|
296 |
-
$
|
297 |
-
$init = 0;
|
298 |
}
|
299 |
-
$this->logger->info(sprintf("File archive process FINISHED."), array("CRON"));
|
300 |
-
|
301 |
//getting the last backup archive file
|
302 |
$return['extra']['backup_parent'] = $this->archive_system->get_archive_name_with_extension();
|
303 |
-
if($this->xcloner_file_system->is_part($this->archive_system->get_archive_name_with_extension()))
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
{
|
310 |
$backup_file = $return['extra']['backup_parent'];
|
311 |
-
|
312 |
-
$this->logger->info(sprintf("Transferring backup to remote storage %s", strtoupper($schedule['remote_storage'])), array("CRON"));
|
313 |
-
|
314 |
-
if(method_exists($this->xcloner_remote_storage, "upload_backup_to_storage"))
|
315 |
-
call_user_func_array(
|
|
|
|
|
|
|
|
|
316 |
}
|
317 |
-
|
318 |
-
if(isset($schedule['backup_params']->email_notification) and $to
|
319 |
-
|
320 |
-
|
321 |
-
$from = "";
|
322 |
$additional['lines_total'] = $return['extra']['lines_total'];
|
323 |
-
$subject
|
324 |
-
|
325 |
-
$this->archive_system->send_notification($to, $from, $subject, $return['extra']['backup_parent'], $schedule, "", $additional);
|
326 |
-
|
327 |
-
}catch(Exception $e)
|
328 |
-
|
329 |
-
$this->logger->error($e->getMessage());
|
330 |
}
|
331 |
}
|
332 |
-
|
333 |
//CHECK IF WE SHOULD DELETE BACKUP AFTER REMOTE TRANSFER IS DONE
|
334 |
-
if($schedule['remote_storage'] && $this->xcloner_settings->get_xcloner_option('xcloner_cleanup_delete_after_remote_transfer'))
|
335 |
-
|
336 |
-
$this->
|
337 |
-
|
338 |
-
|
339 |
}
|
340 |
-
|
341 |
$this->xcloner_file_system->remove_tmp_filesystem();
|
342 |
-
|
343 |
$this->xcloner_file_system->backup_storage_cleanup();
|
344 |
-
|
345 |
//DO TMP FILESYSTEM CLEANUP
|
346 |
$this->xcloner_file_system->cleanup_tmp_directories();
|
347 |
}
|
348 |
-
|
349 |
-
public function xcloner_scheduler_callback($id, $schedule = "")
|
350 |
-
|
351 |
-
|
352 |
-
{
|
353 |
-
$schedule = $this->get_schedule_by_id($id);
|
354 |
}
|
355 |
-
|
356 |
-
try{
|
357 |
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
|
|
|
|
362 |
//send email to site admin if email notification is not set in the scheduler
|
363 |
-
if(!isset($schedule['backup_params']->email_notification) ||
|
364 |
-
|
365 |
-
$schedule['backup_params']->email_notification = get_option('admin_email');
|
366 |
}
|
367 |
-
|
368 |
-
if(isset($schedule['backup_params']->email_notification) && $to
|
369 |
-
{
|
370 |
$from = "";
|
371 |
-
$this->archive_system->send_notification($to, $from, $schedule['name']." - backup error","", "", $e->getMessage());
|
372 |
}
|
373 |
-
|
374 |
}
|
375 |
-
|
376 |
}
|
377 |
-
|
378 |
-
public function get_available_intervals()
|
379 |
-
|
380 |
-
$schedules = wp_get_schedules();
|
381 |
$new_schedules = array();
|
382 |
-
|
383 |
-
foreach ($schedules as $key => $row) {
|
384 |
-
if(in_array($key, $this->allowed_schedules))
|
385 |
-
|
386 |
-
$
|
387 |
-
$intervals[$key] = $row['interval'];
|
388 |
}
|
389 |
}
|
390 |
-
|
391 |
-
array_multisort($intervals, SORT_ASC, $new_schedules);
|
|
|
392 |
return $new_schedules;
|
393 |
}
|
394 |
-
|
395 |
-
|
396 |
}
|
1 |
<?php
|
2 |
|
3 |
+
class Xcloner_Scheduler {
|
4 |
+
|
5 |
private $db;
|
6 |
private $scheduler_table = "xcloner_scheduler";
|
7 |
+
|
8 |
private $xcloner_remote_storage;
|
9 |
private $archive_system;
|
10 |
private $xcloner_database;
|
11 |
private $xcloner_settings;
|
12 |
private $logger;
|
13 |
private $xcloner_file_system;
|
14 |
+
|
15 |
+
private $allowed_schedules = array( "hourly", "twicedaily", "daily", "weekly", "monthly" );
|
16 |
+
|
17 |
/*public function __call($method, $args) {
|
18 |
echo "$method is not defined";
|
19 |
}*/
|
20 |
|
21 |
+
public function __construct( Xcloner $xcloner_container ) {
|
|
|
22 |
global $wpdb;
|
23 |
+
|
24 |
+
$this->db = $wpdb;
|
25 |
+
$wpdb->show_errors = false;
|
26 |
+
|
27 |
+
$this->xcloner_container = $xcloner_container;
|
28 |
+
$this->xcloner_settings = $xcloner_container->get_xcloner_settings();
|
29 |
+
|
30 |
+
$this->scheduler_table = $this->db->prefix . $this->scheduler_table;
|
31 |
}
|
32 |
+
|
33 |
+
private function get_xcloner_container() {
|
|
|
34 |
return $this->xcloner_container;
|
35 |
}
|
36 |
+
|
37 |
+
private function set_xcloner_container( Xcloner $container ) {
|
|
|
38 |
$this->xcloner_container = $container;
|
39 |
}
|
40 |
+
|
41 |
+
public function get_scheduler_list( $return_only_enabled = 0 ) {
|
42 |
+
$list = $this->db->get_results( "SELECT * FROM " . $this->scheduler_table );
|
43 |
+
|
44 |
+
if ( $return_only_enabled ) {
|
45 |
+
$new_list = array();
|
46 |
+
|
47 |
+
foreach ( $list as $res ) {
|
48 |
+
if ( $res->status ) {
|
49 |
+
$res->next_run_time = wp_next_scheduled( 'xcloner_scheduler_' . $res->id, array( $res->id ) ) + ( get_option( 'gmt_offset' ) * HOUR_IN_SECONDS );
|
50 |
+
$new_list[] = $res;
|
|
|
|
|
|
|
51 |
}
|
52 |
+
}
|
53 |
+
$list = $new_list;
|
54 |
}
|
55 |
+
|
56 |
return $list;
|
57 |
}
|
58 |
+
|
59 |
+
public function get_next_run_schedule( $xcloner_file_system = "" ) {
|
60 |
+
$list = $this->get_scheduler_list( $return_only_enabled = 1 );
|
|
|
61 |
|
62 |
return $list;
|
63 |
}
|
64 |
+
|
65 |
+
public function get_schedule_by_id_object( $id ) {
|
66 |
+
$data = $this->db->get_row( "SELECT * FROM " . $this->scheduler_table . " WHERE id=" . $id );
|
67 |
+
|
|
|
68 |
return $data;
|
69 |
}
|
70 |
+
|
71 |
+
public function get_schedule_by_id( $id ) {
|
72 |
+
$data = $this->db->get_row( "SELECT * FROM " . $this->scheduler_table . " WHERE id=" . $id, ARRAY_A );
|
73 |
+
|
74 |
+
if ( ! $data ) {
|
|
|
75 |
return false;
|
76 |
+
}
|
77 |
+
|
78 |
+
$params = json_decode( $data['params'] );
|
79 |
+
|
80 |
//print_r($params);
|
81 |
+
$data['params'] = "";
|
82 |
+
$data['backup_params'] = $params->backup_params;
|
83 |
+
$data['table_params'] = json_encode( $params->database );
|
84 |
+
$data['excluded_files'] = json_encode( $params->excluded_files );
|
85 |
+
|
86 |
+
|
87 |
return $data;
|
88 |
}
|
89 |
+
|
90 |
+
public function delete_schedule_by_id( $id ) {
|
91 |
+
$hook = 'xcloner_scheduler_' . $id;
|
92 |
+
wp_clear_scheduled_hook( $hook, array( $id ) );
|
93 |
+
|
94 |
+
$data = $this->db->delete( $this->scheduler_table, array( 'id' => $id ) );
|
95 |
+
|
|
|
96 |
return $data;
|
97 |
}
|
98 |
+
|
99 |
+
public function deactivate_wp_cron_hooks() {
|
|
|
100 |
$list = $this->get_scheduler_list();
|
101 |
+
|
102 |
+
foreach ( $list as $schedule ) {
|
103 |
+
$hook = 'xcloner_scheduler_' . $schedule->id;
|
104 |
+
|
105 |
+
$timestamp = wp_next_scheduled( $hook, array( $schedule->id ) );
|
106 |
+
wp_unschedule_event( $timestamp, $hook, array( $schedule->id ) );
|
|
|
107 |
}
|
108 |
}
|
109 |
+
|
110 |
+
public function update_wp_cron_hooks() {
|
|
|
111 |
$list = $this->get_scheduler_list();
|
112 |
+
|
113 |
+
foreach ( $list as $schedule ) {
|
114 |
+
$hook = 'xcloner_scheduler_' . $schedule->id;
|
115 |
+
|
|
|
116 |
//adding the xcloner_scheduler hook with xcloner_scheduler_callback callback
|
117 |
+
add_action( $hook, array( $this, 'xcloner_scheduler_callback' ), 10, 1 );
|
118 |
+
|
119 |
+
if ( ! wp_next_scheduled( $hook, array( $schedule->id ) ) and $schedule->status ) {
|
120 |
+
|
121 |
+
if ( $schedule->recurrence == "single" ) {
|
122 |
+
wp_schedule_single_event( strtotime( $schedule->start_at ), $hook, array( $schedule->id ) );
|
123 |
+
} else {
|
124 |
+
wp_schedule_event( strtotime( $schedule->start_at ), $schedule->recurrence, $hook, array( $schedule->id ) );
|
|
|
125 |
}
|
126 |
+
|
127 |
+
} elseif ( ! $schedule->status ) {
|
128 |
+
$timestamp = wp_next_scheduled( $hook, array( $schedule->id ) );
|
129 |
+
wp_unschedule_event( $timestamp, $hook, array( $schedule->id ) );
|
|
|
130 |
}
|
131 |
}
|
132 |
+
|
133 |
}
|
134 |
+
|
135 |
+
public function update_cron_hook( $id ) {
|
136 |
+
$schedule = $this->get_schedule_by_id_object( $id );
|
137 |
+
$hook = 'xcloner_scheduler_' . $schedule->id;
|
138 |
+
|
139 |
+
$timestamp = wp_next_scheduled( $hook, array( $schedule->id ) );
|
140 |
+
wp_unschedule_event( $timestamp, $hook, array( $schedule->id ) );
|
141 |
+
|
142 |
+
if ( $schedule->status ) {
|
143 |
+
|
144 |
+
if ( $schedule->recurrence == "single" ) {
|
145 |
+
wp_schedule_single_event( strtotime( $schedule->start_at ), $hook, array( $schedule->id ) );
|
146 |
+
} else {
|
147 |
+
wp_schedule_event( strtotime( $schedule->start_at ), $schedule->recurrence, $hook, array( $schedule->id ) );
|
|
|
|
|
148 |
}
|
149 |
+
|
150 |
}
|
151 |
+
}
|
152 |
+
|
153 |
+
public function disable_single_cron( $schedule_id ) {
|
154 |
+
$hook = 'xcloner_scheduler_' . $schedule_id;
|
155 |
+
$timestamp = wp_next_scheduled( $hook, array( $schedule_id ) );
|
156 |
+
wp_unschedule_event( $timestamp, $hook, array( $schedule_id ) );
|
157 |
+
|
|
|
158 |
$schedule['status'] = 0;
|
159 |
+
|
160 |
+
$update = $this->db->update(
|
161 |
+
$this->scheduler_table,
|
162 |
+
$schedule,
|
163 |
+
array( 'id' => $schedule_id ),
|
164 |
+
array(
|
165 |
+
'%s',
|
166 |
+
'%s'
|
167 |
+
)
|
168 |
+
);
|
169 |
+
|
170 |
+
return $update;
|
171 |
}
|
172 |
+
|
173 |
+
public function update_hash( $schedule_id, $hash ) {
|
|
|
174 |
$schedule['hash'] = $hash;
|
175 |
+
|
176 |
+
$update = $this->db->update(
|
177 |
+
$this->scheduler_table,
|
178 |
+
$schedule,
|
179 |
+
array( 'id' => $schedule_id ),
|
180 |
+
array(
|
181 |
+
'%s',
|
182 |
+
'%s'
|
183 |
+
)
|
184 |
+
);
|
185 |
+
|
186 |
+
return $update;
|
187 |
+
}
|
188 |
+
|
189 |
+
public function update_last_backup( $schedule_id, $last_backup ) {
|
190 |
$schedule['last_backup'] = $last_backup;
|
191 |
+
|
192 |
+
$update = $this->db->update(
|
193 |
+
$this->scheduler_table,
|
194 |
+
$schedule,
|
195 |
+
array( 'id' => $schedule_id ),
|
196 |
+
array(
|
197 |
+
'%s',
|
198 |
+
'%s'
|
199 |
+
)
|
200 |
+
);
|
201 |
+
|
202 |
+
return $update;
|
203 |
+
}
|
204 |
+
|
205 |
+
private function _xcloner_scheduler_callback( $id, $schedule ) {
|
206 |
+
set_time_limit( 0 );
|
207 |
+
|
208 |
$xcloner = new XCloner();
|
209 |
$xcloner->init();
|
210 |
+
$this->set_xcloner_container( $xcloner );
|
211 |
+
|
212 |
#$hash = $this->xcloner_settings->get_hash();
|
213 |
#$this->get_xcloner_container()->get_xcloner_settings()->set_hash($hash);
|
214 |
+
|
215 |
//$this->xcloner_settings = $this->get_xcloner_container()->get_xcloner_settings();
|
216 |
+
$this->xcloner_file_system = $this->get_xcloner_container()->get_xcloner_filesystem();
|
217 |
+
$this->xcloner_database = $this->get_xcloner_container()->get_xcloner_database();
|
218 |
+
$this->archive_system = $this->get_xcloner_container()->get_archive_system();
|
219 |
+
$this->logger = $this->get_xcloner_container()->get_xcloner_logger()->withName( "xcloner_scheduler" );
|
220 |
+
$this->xcloner_remote_storage = $this->get_xcloner_container()->get_xcloner_remote_storage();
|
221 |
+
|
222 |
+
$this->logger->info( sprintf( "New schedule hash is %s", $this->xcloner_settings->get_hash() ) );
|
223 |
+
|
224 |
+
if ( isset( $schedule['backup_params']->diff_start_date ) && $schedule['backup_params']->diff_start_date ) {
|
225 |
+
$this->xcloner_file_system->set_diff_timestamp_start( $schedule['backup_params']->diff_start_date );
|
|
|
226 |
}
|
227 |
+
|
228 |
+
if ( $schedule['recurrence'] == "single" ) {
|
229 |
+
$this->disable_single_cron( $schedule['id'] );
|
|
|
230 |
}
|
231 |
+
|
232 |
+
if ( ! $schedule ) {
|
233 |
+
$this->logger->info( sprintf( "Could not load schedule with id'%s'", $id ), array( "CRON" ) );
|
234 |
+
|
235 |
return;
|
236 |
}
|
237 |
+
|
238 |
//echo $this->get_xcloner_container()->get_xcloner_settings()->get_hash(); exit;
|
239 |
+
|
240 |
+
$this->update_hash( $schedule['id'], $this->xcloner_settings->get_hash() );
|
241 |
+
|
242 |
+
$this->logger->info( sprintf( "Starting cron schedule '%s'", $schedule['name'] ), array( "CRON" ) );
|
243 |
+
|
244 |
+
$this->xcloner_file_system->set_excluded_files( json_decode( $schedule['excluded_files'] ) );
|
245 |
+
|
246 |
+
$init = 1;
|
247 |
$continue = 1;
|
248 |
|
249 |
+
while ( $continue ) {
|
250 |
+
$continue = $this->xcloner_file_system->start_file_recursion( $init );
|
251 |
+
|
|
|
252 |
$init = 0;
|
253 |
}
|
254 |
+
|
255 |
+
$this->logger->info( sprintf( "File scan finished" ), array( "CRON" ) );
|
256 |
+
|
257 |
+
$this->logger->info( sprintf( "Starting the database backup" ), array( "CRON" ) );
|
258 |
+
|
259 |
+
$init = 1;
|
260 |
$return['finished'] = 0;
|
261 |
+
|
262 |
+
while ( ! $return['finished'] ) {
|
263 |
+
$return = $this->xcloner_database->start_database_recursion( (array) json_decode( $schedule['table_params'] ), $return, $init );
|
264 |
+
$init = 0;
|
|
|
265 |
}
|
266 |
+
|
267 |
+
$this->logger->info( sprintf( "Database backup done" ), array( "CRON" ) );
|
268 |
+
|
269 |
+
$this->logger->info( sprintf( "Starting file archive process" ), array( "CRON" ) );
|
270 |
+
|
271 |
+
$init = 0;
|
272 |
$return['finished'] = 0;
|
273 |
+
$return['extra'] = array();
|
274 |
+
|
275 |
+
while ( ! $return['finished'] ) {
|
276 |
+
$return = $this->archive_system->start_incremental_backup( (array) $schedule['backup_params'], $return['extra'], $init );
|
277 |
+
$init = 0;
|
|
|
278 |
}
|
279 |
+
$this->logger->info( sprintf( "File archive process FINISHED." ), array( "CRON" ) );
|
280 |
+
|
281 |
//getting the last backup archive file
|
282 |
$return['extra']['backup_parent'] = $this->archive_system->get_archive_name_with_extension();
|
283 |
+
if ( $this->xcloner_file_system->is_part( $this->archive_system->get_archive_name_with_extension() ) ) {
|
284 |
+
$return['extra']['backup_parent'] = $this->archive_system->get_archive_name_multipart();
|
285 |
+
}
|
286 |
+
|
287 |
+
$this->update_last_backup( $schedule['id'], $return['extra']['backup_parent'] );
|
288 |
+
|
289 |
+
if ( isset( $schedule['remote_storage'] ) && $schedule['remote_storage'] && array_key_exists( $schedule['remote_storage'], $this->xcloner_remote_storage->get_available_storages() ) ) {
|
290 |
$backup_file = $return['extra']['backup_parent'];
|
291 |
+
|
292 |
+
$this->logger->info( sprintf( "Transferring backup to remote storage %s", strtoupper( $schedule['remote_storage'] ) ), array( "CRON" ) );
|
293 |
+
|
294 |
+
if ( method_exists( $this->xcloner_remote_storage, "upload_backup_to_storage" ) ) {
|
295 |
+
call_user_func_array( array(
|
296 |
+
$this->xcloner_remote_storage,
|
297 |
+
"upload_backup_to_storage"
|
298 |
+
), array( $backup_file, $schedule['remote_storage'] ) );
|
299 |
+
}
|
300 |
}
|
301 |
+
|
302 |
+
if ( isset( $schedule['backup_params']->email_notification ) and $to = $schedule['backup_params']->email_notification ) {
|
303 |
+
try {
|
304 |
+
$from = "";
|
|
|
305 |
$additional['lines_total'] = $return['extra']['lines_total'];
|
306 |
+
$subject = sprintf( __( "%s - new backup generated %s" ), $schedule['name'], $return['extra']['backup_parent'] );
|
307 |
+
|
308 |
+
$this->archive_system->send_notification( $to, $from, $subject, $return['extra']['backup_parent'], $schedule, "", $additional );
|
309 |
+
|
310 |
+
} catch ( Exception $e ) {
|
311 |
+
$this->logger->error( $e->getMessage() );
|
|
|
312 |
}
|
313 |
}
|
314 |
+
|
315 |
//CHECK IF WE SHOULD DELETE BACKUP AFTER REMOTE TRANSFER IS DONE
|
316 |
+
if ( $schedule['remote_storage'] && $this->xcloner_settings->get_xcloner_option( 'xcloner_cleanup_delete_after_remote_transfer' ) ) {
|
317 |
+
$this->logger->info( sprintf( "Deleting %s from local storage matching rule xcloner_cleanup_delete_after_remote_transfer", $return['extra']['backup_parent'] ) );
|
318 |
+
$this->xcloner_file_system->delete_backup_by_name( $return['extra']['backup_parent'] );
|
319 |
+
|
|
|
320 |
}
|
321 |
+
|
322 |
$this->xcloner_file_system->remove_tmp_filesystem();
|
323 |
+
|
324 |
$this->xcloner_file_system->backup_storage_cleanup();
|
325 |
+
|
326 |
//DO TMP FILESYSTEM CLEANUP
|
327 |
$this->xcloner_file_system->cleanup_tmp_directories();
|
328 |
}
|
329 |
+
|
330 |
+
public function xcloner_scheduler_callback( $id, $schedule = "" ) {
|
331 |
+
if ( $id ) {
|
332 |
+
$schedule = $this->get_schedule_by_id( $id );
|
|
|
|
|
333 |
}
|
|
|
|
|
334 |
|
335 |
+
try {
|
336 |
+
|
337 |
+
$this->_xcloner_scheduler_callback( $id, $schedule );
|
338 |
+
|
339 |
+
} catch ( Exception $e ) {
|
340 |
+
|
341 |
//send email to site admin if email notification is not set in the scheduler
|
342 |
+
if ( ! isset( $schedule['backup_params']->email_notification ) || ! $schedule['backup_params']->email_notification ) {
|
343 |
+
$schedule['backup_params']->email_notification = get_option( 'admin_email' );
|
|
|
344 |
}
|
345 |
+
|
346 |
+
if ( isset( $schedule['backup_params']->email_notification ) && $to = $schedule['backup_params']->email_notification ) {
|
|
|
347 |
$from = "";
|
348 |
+
$this->archive_system->send_notification( $to, $from, $schedule['name'] . " - backup error", "", "", $e->getMessage() );
|
349 |
}
|
350 |
+
|
351 |
}
|
352 |
+
|
353 |
}
|
354 |
+
|
355 |
+
public function get_available_intervals() {
|
356 |
+
$schedules = wp_get_schedules();
|
|
|
357 |
$new_schedules = array();
|
358 |
+
|
359 |
+
foreach ( $schedules as $key => $row ) {
|
360 |
+
if ( in_array( $key, $this->allowed_schedules ) ) {
|
361 |
+
$new_schedules[ $key ] = $row;
|
362 |
+
$intervals[ $key ] = $row['interval'];
|
|
|
363 |
}
|
364 |
}
|
365 |
+
|
366 |
+
array_multisort( $intervals, SORT_ASC, $new_schedules );
|
367 |
+
|
368 |
return $new_schedules;
|
369 |
}
|
370 |
+
|
371 |
+
|
372 |
}
|
includes/class-xcloner-settings.php
CHANGED
@@ -1,489 +1,530 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
class Xcloner_Settings
|
4 |
-
{
|
5 |
private $logger_file = "xcloner_main_%s.log";
|
6 |
private $logger_file_hash = "xcloner%s.log";
|
7 |
-
private $hash
|
8 |
private $xcloner_sanitization;
|
9 |
private $xcloner_container;
|
10 |
-
|
11 |
-
public function __construct(Xcloner $xcloner_container, $hash = "")
|
12 |
-
{
|
13 |
$this->xcloner_container = $xcloner_container;
|
14 |
-
if(isset($hash))
|
15 |
-
$this->set_hash($hash);
|
|
|
16 |
}
|
17 |
-
|
18 |
-
private function get_xcloner_container()
|
19 |
-
{
|
20 |
return $this->xcloner_container;
|
21 |
}
|
22 |
-
|
23 |
-
public function get_logger_filename($include_hash = 0)
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
return $filename;
|
31 |
}
|
32 |
-
|
33 |
-
public function get_xcloner_start_path()
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
return $path;
|
41 |
}
|
42 |
-
|
43 |
-
public function get_xcloner_dir_path($dir)
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
return $path;
|
48 |
}
|
49 |
-
|
50 |
-
public function get_xcloner_store_path()
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
return $path;
|
58 |
}
|
59 |
-
|
60 |
-
public function get_xcloner_tmp_path_suffix()
|
61 |
-
|
62 |
-
return "xcloner".$this->get_hash();
|
63 |
}
|
64 |
-
|
65 |
-
|
66 |
-
public function get_xcloner_tmp_path($suffix = true)
|
67 |
-
|
68 |
-
if(get_option('xcloner_force_tmp_path_site_root'))
|
69 |
-
{
|
70 |
$path = $this->get_xcloner_store_path();
|
71 |
-
}else{
|
72 |
-
|
73 |
$path = sys_get_temp_dir();
|
74 |
-
if(!is_dir($path))
|
75 |
-
|
76 |
-
@
|
77 |
-
@chmod($path, 0777);
|
78 |
}
|
79 |
-
|
80 |
-
if(!is_dir($path) or !is_writeable($path))
|
81 |
-
{
|
82 |
$path = $this->get_xcloner_store_path();
|
83 |
}
|
84 |
}
|
85 |
-
|
86 |
-
if($suffix)
|
87 |
-
|
88 |
-
$path = $path.DS.".".$this->get_xcloner_tmp_path_suffix();
|
89 |
}
|
90 |
-
|
91 |
return $path;
|
92 |
}
|
93 |
-
|
94 |
-
public function get_enable_mysql_backup()
|
95 |
-
|
96 |
-
if(get_option('xcloner_enable_mysql_backup'))
|
97 |
return true;
|
98 |
-
|
99 |
-
|
|
|
100 |
}
|
101 |
-
|
102 |
-
public function get_backup_extension_name($ext = "")
|
103 |
-
|
104 |
-
|
105 |
-
{
|
106 |
-
if(get_option('xcloner_backup_compression_level'))
|
107 |
$ext = ".tgz";
|
108 |
-
else
|
109 |
$ext = ".tar";
|
110 |
-
|
111 |
-
|
|
|
|
|
112 |
}
|
113 |
-
|
114 |
-
public function get_hash()
|
115 |
-
|
116 |
-
|
117 |
-
$this->set_hash("-".$this->get_server_unique_hash(5));
|
118 |
}
|
119 |
-
|
120 |
//echo $this->hash;
|
121 |
return $this->hash;
|
122 |
}
|
123 |
-
|
124 |
-
public function generate_new_hash()
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
return $hash;
|
131 |
}
|
132 |
-
|
133 |
-
public function set_hash($hash = "")
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
$this->hash = substr( $hash, 0, 6);
|
139 |
-
|
140 |
return $this;
|
141 |
}
|
142 |
-
|
143 |
-
public function get_default_backup_name()
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
return $backup_name;
|
150 |
}
|
151 |
-
|
152 |
-
public function get_db_hostname()
|
153 |
-
{
|
154 |
global $wpdb;
|
155 |
-
|
156 |
-
if(
|
157 |
$data = $wpdb->dbhost;
|
158 |
-
|
|
|
159 |
return $data;
|
160 |
}
|
161 |
-
|
162 |
-
public function get_db_username()
|
163 |
-
{
|
164 |
global $wpdb;
|
165 |
-
|
166 |
-
if(
|
167 |
$data = $wpdb->dbuser;
|
168 |
-
|
|
|
169 |
return $data;
|
170 |
}
|
171 |
-
|
172 |
-
public function get_db_password()
|
173 |
-
{
|
174 |
global $wpdb;
|
175 |
-
|
176 |
-
if(
|
177 |
$data = $wpdb->dbpassword;
|
178 |
-
|
|
|
179 |
return $data;
|
180 |
}
|
181 |
-
|
182 |
-
public function get_db_database()
|
183 |
-
{
|
184 |
global $wpdb;
|
185 |
-
|
186 |
-
if(
|
187 |
$data = $wpdb->dbname;
|
188 |
-
|
|
|
189 |
return $data;
|
190 |
}
|
191 |
-
|
192 |
-
public function get_table_prefix()
|
193 |
-
{
|
194 |
global $wpdb;
|
195 |
-
|
196 |
return $wpdb->prefix;
|
197 |
}
|
198 |
-
|
199 |
-
public function get_xcloner_option($option)
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
return $data;
|
204 |
}
|
205 |
-
|
206 |
-
public function get_server_unique_hash($strlen = 0)
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
return $hash;
|
214 |
}
|
215 |
-
|
216 |
-
public function settings_init()
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
if( false == get_option( 'xcloner_mysql_settings_page' ) ) {
|
223 |
add_option( 'xcloner_mysql_settings_page' );
|
224 |
} // end if
|
225 |
-
|
226 |
-
|
227 |
add_option( 'xcloner_cron_settings_page' );
|
228 |
} // end if
|
229 |
-
|
230 |
-
|
231 |
add_option( 'xcloner_system_settings_page' );
|
232 |
} // end if
|
233 |
-
|
234 |
-
|
235 |
add_option( 'xcloner_cleanup_settings_page' );
|
236 |
} // end if
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
//CRON section
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
//REGISTERING THE 'GENERAL SECTION' FIELDS
|
283 |
-
register_setting('xcloner_general_settings_group', 'xcloner_backup_compression_level', array(
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
306 |
$this->get_xcloner_start_path(),
|
307 |
//'disabled'
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
|
|
|
|
|
|
|
|
321 |
//'disabled'
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
358 |
//$this->get_xcloner_store_path(),
|
359 |
//'disabled'
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
//REGISTERING THE 'MYSQL SECTION' FIELDS
|
364 |
-
register_setting('xcloner_mysql_settings_group', 'xcloner_enable_mysql_backup', array(
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
397 |
$this->get_db_hostname(),
|
398 |
'disabled'
|
399 |
-
|
400 |
-
|
401 |
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
|
|
|
|
|
|
|
|
411 |
$this->get_db_username(),
|
412 |
'disabled'
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
|
|
|
|
|
|
|
|
425 |
$this->get_db_database(),
|
426 |
'disabled'
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
487 |
/*register_setting('xcloner_system_settings_group', 'xcloner_diff_backup_recreate_period', array($this->xcloner_sanitization, "sanitize_input_as_int"));
|
488 |
add_settings_field(
|
489 |
'xcloner_diff_backup_recreate_period',
|
@@ -495,261 +536,332 @@ class Xcloner_Settings
|
|
495 |
__('Use this option to set when a full backup should be recreated if the scheduled backup type is set to \'Full Backup+Differential Backups\' ','xcloner-backup-and-restore'),
|
496 |
)
|
497 |
);*/
|
498 |
-
|
499 |
-
register_setting('xcloner_system_settings_group', 'xcloner_exclude_files_larger_than_mb', array(
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
535 |
//REGISTERING THE 'CLEANUP SECTION' FIELDS
|
536 |
-
register_setting('xcloner_cleanup_settings_group', 'xcloner_cleanup_retention_limit_days', array(
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
|
|
|
|
|
|
|
|
545 |
)
|
546 |
-
|
547 |
-
|
548 |
-
register_setting('xcloner_cleanup_settings_group', 'xcloner_cleanup_retention_limit_archives', array(
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
|
|
|
|
|
|
|
|
557 |
)
|
558 |
-
|
559 |
-
|
560 |
-
register_setting('xcloner_cleanup_settings_group', 'xcloner_cleanup_capacity_limit', array(
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
|
|
|
|
|
|
|
|
569 |
)
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
|
|
|
|
|
|
|
|
581 |
)
|
582 |
-
|
583 |
-
|
584 |
//REGISTERING THE 'CRON SECTION' FIELDS
|
585 |
-
register_setting('xcloner_cron_settings_group', 'xcloner_cron_frequency');
|
586 |
-
|
587 |
-
|
588 |
-
|
589 |
-
|
590 |
-
|
591 |
-
|
592 |
-
|
593 |
-
|
|
|
594 |
)
|
595 |
-
|
596 |
}
|
597 |
-
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
/**
|
602 |
* callback functions
|
603 |
*/
|
604 |
-
|
605 |
// section content cb
|
606 |
-
public function xcloner_settings_section_cb()
|
607 |
-
|
608 |
-
//echo '<p>WPOrg Section Introduction.</p>';
|
609 |
}
|
610 |
-
|
611 |
// text field content cb
|
612 |
-
public function do_form_text_field($params)
|
613 |
-
|
614 |
-
if(!isset($params['3']))
|
615 |
$params[3] = 0;
|
616 |
-
|
617 |
-
|
618 |
-
|
619 |
-
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
-
|
626 |
-
|
627 |
-
|
628 |
-
|
629 |
-
|
630 |
-
|
631 |
-
|
632 |
-
|
633 |
-
|
634 |
-
|
635 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
636 |
}
|
637 |
-
|
638 |
// textarea field content cb
|
639 |
-
public function do_form_textarea_field($params)
|
640 |
-
|
641 |
-
if(!isset($params['3']))
|
642 |
$params[3] = 0;
|
643 |
-
|
644 |
-
|
645 |
-
|
646 |
-
|
647 |
-
|
648 |
-
|
649 |
-
|
650 |
-
|
651 |
-
|
652 |
-
|
653 |
-
|
654 |
-
|
655 |
-
|
656 |
-
|
657 |
-
|
658 |
-
|
659 |
-
|
660 |
-
|
661 |
-
|
662 |
-
|
663 |
-
|
664 |
-
|
665 |
-
|
666 |
-
|
667 |
-
|
668 |
-
|
669 |
-
|
670 |
-
|
671 |
-
|
672 |
-
|
673 |
-
|
674 |
-
|
675 |
-
|
676 |
-
|
677 |
-
|
678 |
-
|
679 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
680 |
}
|
681 |
-
|
682 |
// number field content cb
|
683 |
-
public function do_form_number_field($params)
|
684 |
-
|
685 |
-
if(!isset($params['3']))
|
686 |
$params[3] = 0;
|
687 |
-
|
688 |
-
|
689 |
-
|
690 |
-
|
691 |
-
|
692 |
-
|
693 |
-
|
694 |
-
|
695 |
-
|
696 |
-
|
697 |
-
|
698 |
-
|
699 |
-
|
700 |
-
|
701 |
-
|
702 |
-
|
703 |
-
|
704 |
-
|
705 |
-
|
706 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
707 |
}
|
708 |
-
|
709 |
-
public function do_form_range_field($params)
|
710 |
-
|
711 |
-
if(!isset($params['4']))
|
712 |
$params[4] = 0;
|
713 |
-
|
714 |
-
|
715 |
-
$
|
716 |
-
|
717 |
-
|
718 |
-
|
719 |
-
|
720 |
-
|
721 |
-
|
722 |
-
|
723 |
-
|
724 |
-
|
725 |
-
|
726 |
-
|
727 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
728 |
}
|
729 |
-
|
730 |
-
|
731 |
-
public function do_form_switch_field($params)
|
732 |
-
|
733 |
-
if(!isset($params['2']))
|
734 |
$params[2] = 0;
|
735 |
-
|
736 |
-
$
|
737 |
-
|
738 |
-
|
739 |
-
|
740 |
-
|
741 |
-
|
742 |
-
|
743 |
-
|
744 |
-
|
745 |
-
|
746 |
-
|
747 |
-
|
748 |
-
|
749 |
-
|
750 |
-
|
751 |
-
|
752 |
-
|
753 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
754 |
}
|
755 |
}
|
1 |
<?php
|
2 |
|
3 |
+
class Xcloner_Settings {
|
|
|
4 |
private $logger_file = "xcloner_main_%s.log";
|
5 |
private $logger_file_hash = "xcloner%s.log";
|
6 |
+
private $hash;
|
7 |
private $xcloner_sanitization;
|
8 |
private $xcloner_container;
|
9 |
+
|
10 |
+
public function __construct( Xcloner $xcloner_container, $hash = "" ) {
|
|
|
11 |
$this->xcloner_container = $xcloner_container;
|
12 |
+
if ( isset( $hash ) ) {
|
13 |
+
$this->set_hash( $hash );
|
14 |
+
}
|
15 |
}
|
16 |
+
|
17 |
+
private function get_xcloner_container() {
|
|
|
18 |
return $this->xcloner_container;
|
19 |
}
|
20 |
+
|
21 |
+
public function get_logger_filename( $include_hash = 0 ) {
|
22 |
+
if ( $include_hash ) {
|
23 |
+
$filename = sprintf( $this->logger_file_hash, $this->get_hash() );
|
24 |
+
} else {
|
25 |
+
$filename = sprintf( $this->logger_file, $this->get_server_unique_hash( 5 ) );
|
26 |
+
}
|
27 |
+
|
28 |
return $filename;
|
29 |
}
|
30 |
+
|
31 |
+
public function get_xcloner_start_path() {
|
32 |
+
if ( ! get_option( 'xcloner_start_path' ) or ! is_dir( get_option( 'xcloner_start_path' ) ) ) {
|
33 |
+
$path = realpath( ABSPATH );
|
34 |
+
} else {
|
35 |
+
$path = get_option( 'xcloner_start_path' );
|
36 |
+
}
|
37 |
+
|
38 |
return $path;
|
39 |
}
|
40 |
+
|
41 |
+
public function get_xcloner_dir_path( $dir ) {
|
42 |
+
$path = self::get_xcloner_start_path() . DS . $dir;
|
43 |
+
|
|
|
44 |
return $path;
|
45 |
}
|
46 |
+
|
47 |
+
public function get_xcloner_store_path() {
|
48 |
+
if ( ! get_option( 'xcloner_store_path' ) or ! is_dir( get_option( 'xcloner_store_path' ) ) ) {
|
49 |
+
$path = realpath( XCLONER_STORAGE_PATH );
|
50 |
+
} else {
|
51 |
+
$path = get_option( 'xcloner_store_path' );
|
52 |
+
}
|
53 |
+
|
54 |
return $path;
|
55 |
}
|
56 |
+
|
57 |
+
public function get_xcloner_tmp_path_suffix() {
|
58 |
+
return "xcloner" . $this->get_hash();
|
|
|
59 |
}
|
60 |
+
|
61 |
+
|
62 |
+
public function get_xcloner_tmp_path( $suffix = true ) {
|
63 |
+
if ( get_option( 'xcloner_force_tmp_path_site_root' ) ) {
|
|
|
|
|
64 |
$path = $this->get_xcloner_store_path();
|
65 |
+
} else {
|
66 |
+
|
67 |
$path = sys_get_temp_dir();
|
68 |
+
if ( ! is_dir( $path ) ) {
|
69 |
+
@mkdir( $path );
|
70 |
+
@chmod( $path, 0777 );
|
|
|
71 |
}
|
72 |
+
|
73 |
+
if ( ! is_dir( $path ) or ! is_writeable( $path ) ) {
|
|
|
74 |
$path = $this->get_xcloner_store_path();
|
75 |
}
|
76 |
}
|
77 |
+
|
78 |
+
if ( $suffix ) {
|
79 |
+
$path = $path . DS . "." . $this->get_xcloner_tmp_path_suffix();
|
|
|
80 |
}
|
81 |
+
|
82 |
return $path;
|
83 |
}
|
84 |
+
|
85 |
+
public function get_enable_mysql_backup() {
|
86 |
+
if ( get_option( 'xcloner_enable_mysql_backup' ) ) {
|
|
|
87 |
return true;
|
88 |
+
}
|
89 |
+
|
90 |
+
return false;
|
91 |
}
|
92 |
+
|
93 |
+
public function get_backup_extension_name( $ext = "" ) {
|
94 |
+
if ( ! $ext ) {
|
95 |
+
if ( get_option( 'xcloner_backup_compression_level' ) ) {
|
|
|
|
|
96 |
$ext = ".tgz";
|
97 |
+
} else {
|
98 |
$ext = ".tar";
|
99 |
+
}
|
100 |
+
}
|
101 |
+
|
102 |
+
return ( $this->get_hash() ) . $ext;
|
103 |
}
|
104 |
+
|
105 |
+
public function get_hash() {
|
106 |
+
if ( ! $this->hash ) {
|
107 |
+
$this->set_hash( "-" . $this->get_server_unique_hash( 5 ) );
|
|
|
108 |
}
|
109 |
+
|
110 |
//echo $this->hash;
|
111 |
return $this->hash;
|
112 |
}
|
113 |
+
|
114 |
+
public function generate_new_hash() {
|
115 |
+
$hash = "-" . md5( rand() );
|
116 |
+
|
117 |
+
$this->set_hash( substr( $hash, 0, 6 ) );
|
118 |
+
|
|
|
119 |
return $hash;
|
120 |
}
|
121 |
+
|
122 |
+
public function set_hash( $hash = "" ) {
|
123 |
+
if ( substr( $hash, 0, 1 ) != "-" and strlen( $hash ) ) {
|
124 |
+
$hash = "-" . $hash;
|
125 |
+
}
|
126 |
+
|
127 |
+
$this->hash = substr( $hash, 0, 6 );
|
128 |
+
|
129 |
return $this;
|
130 |
}
|
131 |
+
|
132 |
+
public function get_default_backup_name() {
|
133 |
+
$data = parse_url( get_site_url() );
|
134 |
+
|
135 |
+
$backup_name = "backup_[domain]" . ( isset( $data['port'] ) ? "_" . $data['port'] : "" ) . "-[time]-" . ( $this->get_enable_mysql_backup() ? "sql" : "nosql" );
|
136 |
+
|
|
|
137 |
return $backup_name;
|
138 |
}
|
139 |
+
|
140 |
+
public function get_db_hostname() {
|
|
|
141 |
global $wpdb;
|
142 |
+
|
143 |
+
if ( ! $data = get_option( 'xcloner_mysql_hostname' ) ) {
|
144 |
$data = $wpdb->dbhost;
|
145 |
+
}
|
146 |
+
|
147 |
return $data;
|
148 |
}
|
149 |
+
|
150 |
+
public function get_db_username() {
|
|
|
151 |
global $wpdb;
|
152 |
+
|
153 |
+
if ( ! $data = get_option( 'xcloner_mysql_username' ) ) {
|
154 |
$data = $wpdb->dbuser;
|
155 |
+
}
|
156 |
+
|
157 |
return $data;
|
158 |
}
|
159 |
+
|
160 |
+
public function get_db_password() {
|
|
|
161 |
global $wpdb;
|
162 |
+
|
163 |
+
if ( ! $data = get_option( 'xcloner_mysql_password' ) ) {
|
164 |
$data = $wpdb->dbpassword;
|
165 |
+
}
|
166 |
+
|
167 |
return $data;
|
168 |
}
|
169 |
+
|
170 |
+
public function get_db_database() {
|
|
|
171 |
global $wpdb;
|
172 |
+
|
173 |
+
if ( ! $data = get_option( 'xcloner_mysql_database' ) ) {
|
174 |
$data = $wpdb->dbname;
|
175 |
+
}
|
176 |
+
|
177 |
return $data;
|
178 |
}
|
179 |
+
|
180 |
+
public function get_table_prefix() {
|
|
|
181 |
global $wpdb;
|
182 |
+
|
183 |
return $wpdb->prefix;
|
184 |
}
|
185 |
+
|
186 |
+
public function get_xcloner_option( $option ) {
|
187 |
+
$data = get_option( $option );
|
188 |
+
|
|
|
189 |
return $data;
|
190 |
}
|
191 |
+
|
192 |
+
public function get_server_unique_hash( $strlen = 0 ) {
|
193 |
+
$hash = md5( get_home_url() . __DIR__ );
|
194 |
+
|
195 |
+
if ( $strlen ) {
|
196 |
+
$hash = substr( $hash, 0, $strlen );
|
197 |
+
}
|
198 |
+
|
199 |
return $hash;
|
200 |
}
|
201 |
+
|
202 |
+
public function settings_init() {
|
203 |
+
global $wpdb;
|
204 |
+
$this->xcloner_sanitization = $this->get_xcloner_container()->get_xcloner_sanitization();
|
205 |
+
|
206 |
+
//ADDING MISSING OPTIONS
|
207 |
+
if ( false == get_option( 'xcloner_mysql_settings_page' ) ) {
|
|
|
208 |
add_option( 'xcloner_mysql_settings_page' );
|
209 |
} // end if
|
210 |
+
|
211 |
+
if ( false == get_option( 'xcloner_cron_settings_page' ) ) {
|
212 |
add_option( 'xcloner_cron_settings_page' );
|
213 |
} // end if
|
214 |
+
|
215 |
+
if ( false == get_option( 'xcloner_system_settings_page' ) ) {
|
216 |
add_option( 'xcloner_system_settings_page' );
|
217 |
} // end if
|
218 |
+
|
219 |
+
if ( false == get_option( 'xcloner_cleanup_settings_page' ) ) {
|
220 |
add_option( 'xcloner_cleanup_settings_page' );
|
221 |
} // end if
|
222 |
+
|
223 |
+
|
224 |
+
//ADDING SETTING SECTIONS
|
225 |
+
//GENERAL section
|
226 |
+
add_settings_section(
|
227 |
+
'xcloner_general_settings_group',
|
228 |
+
__( ' ' ),
|
229 |
+
array( $this, 'xcloner_settings_section_cb' ),
|
230 |
+
'xcloner_settings_page'
|
231 |
+
);
|
232 |
+
//MYSQL section
|
233 |
+
add_settings_section(
|
234 |
+
'xcloner_mysql_settings_group',
|
235 |
+
__( ' ' ),
|
236 |
+
array( $this, 'xcloner_settings_section_cb' ),
|
237 |
+
'xcloner_mysql_settings_page'
|
238 |
+
);
|
239 |
+
|
240 |
+
//SYSTEM section
|
241 |
+
add_settings_section(
|
242 |
+
'xcloner_system_settings_group',
|
243 |
+
__( 'These are advanced options recommended for developers!', 'xcloner-backup-and-restore' ),
|
244 |
+
array( $this, 'xcloner_settings_section_cb' ),
|
245 |
+
'xcloner_system_settings_page'
|
246 |
+
);
|
247 |
+
|
248 |
+
//CLEANUP section
|
249 |
+
add_settings_section(
|
250 |
+
'xcloner_cleanup_settings_group',
|
251 |
+
__( ' ' ),
|
252 |
+
array( $this, 'xcloner_settings_section_cb' ),
|
253 |
+
'xcloner_cleanup_settings_page'
|
254 |
+
);
|
255 |
+
|
256 |
+
|
257 |
//CRON section
|
258 |
+
add_settings_section(
|
259 |
+
'xcloner_cron_settings_group',
|
260 |
+
__( ' ' ),
|
261 |
+
array( $this, 'xcloner_settings_section_cb' ),
|
262 |
+
'xcloner_cron_settings_page'
|
263 |
+
);
|
264 |
+
|
265 |
+
|
|
|
266 |
//REGISTERING THE 'GENERAL SECTION' FIELDS
|
267 |
+
register_setting( 'xcloner_general_settings_group', 'xcloner_backup_compression_level', array(
|
268 |
+
$this->xcloner_sanitization,
|
269 |
+
"sanitize_input_as_int"
|
270 |
+
) );
|
271 |
+
add_settings_field(
|
272 |
+
'xcloner_backup_compression_level',
|
273 |
+
__( 'Backup Compression Level', 'xcloner-backup-and-restore' ),
|
274 |
+
array( $this, 'do_form_range_field' ),
|
275 |
+
'xcloner_settings_page',
|
276 |
+
'xcloner_general_settings_group',
|
277 |
+
array(
|
278 |
+
'xcloner_backup_compression_level',
|
279 |
+
__( 'Options between [0-9]. Value 0 means no compression, while 9 is maximum compression affecting cpu load', 'xcloner-backup-and-restore' ),
|
280 |
+
0,
|
281 |
+
9
|
282 |
+
)
|
283 |
+
);
|
284 |
+
|
285 |
+
register_setting( 'xcloner_general_settings_group', 'xcloner_start_path', array(
|
286 |
+
$this->xcloner_sanitization,
|
287 |
+
"sanitize_input_as_absolute_path"
|
288 |
+
) );
|
289 |
+
add_settings_field(
|
290 |
+
'xcloner_start_path',
|
291 |
+
__( 'Backup Start Location', 'xcloner-backup-and-restore' ),
|
292 |
+
array( $this, 'do_form_text_field' ),
|
293 |
+
'xcloner_settings_page',
|
294 |
+
'xcloner_general_settings_group',
|
295 |
+
array(
|
296 |
+
'xcloner_start_path',
|
297 |
+
__( 'Base path location from where XCloner can start the Backup.', 'xcloner-backup-and-restore' ),
|
298 |
$this->get_xcloner_start_path(),
|
299 |
//'disabled'
|
300 |
+
)
|
301 |
+
);
|
302 |
+
|
303 |
+
register_setting( 'xcloner_general_settings_group', 'xcloner_store_path', array(
|
304 |
+
$this->xcloner_sanitization,
|
305 |
+
"sanitize_input_as_absolute_path"
|
306 |
+
) );
|
307 |
+
add_settings_field(
|
308 |
+
'xcloner_store_path',
|
309 |
+
__( 'Backup Storage Location', 'xcloner-backup-and-restore' ),
|
310 |
+
array( $this, 'do_form_text_field' ),
|
311 |
+
'xcloner_settings_page',
|
312 |
+
'xcloner_general_settings_group',
|
313 |
+
array(
|
314 |
+
'xcloner_store_path',
|
315 |
+
__( 'Location where XCloner will store the Backup archives.', 'xcloner-backup-and-restore' ),
|
316 |
+
$this->get_xcloner_store_path(),
|
317 |
//'disabled'
|
318 |
+
)
|
319 |
+
);
|
320 |
+
|
321 |
+
register_setting( 'xcloner_general_settings_group', 'xcloner_enable_log', array(
|
322 |
+
$this->xcloner_sanitization,
|
323 |
+
"sanitize_input_as_int"
|
324 |
+
) );
|
325 |
+
add_settings_field(
|
326 |
+
'xcloner_enable_log',
|
327 |
+
__( 'Enable XCloner Backup Log', 'xcloner-backup-and-restore' ),
|
328 |
+
array( $this, 'do_form_switch_field' ),
|
329 |
+
'xcloner_settings_page',
|
330 |
+
'xcloner_general_settings_group',
|
331 |
+
array(
|
332 |
+
'xcloner_enable_log',
|
333 |
+
sprintf( __( 'Enable the XCloner Backup log. You will find it stored unde the Backup Storage Location, file %s', 'xcloner-backup-and-restore' ), $this->get_logger_filename() )
|
334 |
+
)
|
335 |
+
);
|
336 |
+
|
337 |
+
register_setting( 'xcloner_general_settings_group', 'xcloner_enable_pre_update_backup', array(
|
338 |
+
$this->xcloner_sanitization,
|
339 |
+
"sanitize_input_as_int"
|
340 |
+
) );
|
341 |
+
add_settings_field(
|
342 |
+
'xcloner_enable_pre_update_backup',
|
343 |
+
__( 'Generate Backups before Automatic WP Upgrades', 'xcloner-backup-and-restore' ),
|
344 |
+
array( $this, 'do_form_switch_field' ),
|
345 |
+
'xcloner_settings_page',
|
346 |
+
'xcloner_general_settings_group',
|
347 |
+
array(
|
348 |
+
'xcloner_enable_pre_update_backup',
|
349 |
+
sprintf( __( 'Attempt to generate a core, plugins, themes or languages files backup before the automatic update of Wordpress core, plugins, themes or languages files.', 'xcloner-backup-and-restore' ), $this->get_logger_filename() )
|
350 |
+
)
|
351 |
+
);
|
352 |
+
|
353 |
+
register_setting( 'xcloner_general_settings_group', 'xcloner_regex_exclude', array(
|
354 |
+
$this->xcloner_sanitization,
|
355 |
+
"sanitize_input_as_raw"
|
356 |
+
) );
|
357 |
+
add_settings_field(
|
358 |
+
'xcloner_regex_exclude',
|
359 |
+
__( 'Regex Exclude Files', 'xcloner-backup-and-restore' ),
|
360 |
+
array( $this, 'do_form_textarea_field' ),
|
361 |
+
'xcloner_settings_page',
|
362 |
+
'xcloner_general_settings_group',
|
363 |
+
array(
|
364 |
+
'xcloner_regex_exclude',
|
365 |
+
__( 'Regular expression match to exclude files and folders, example patterns provided below, one pattern per line', 'xcloner-backup-and-restore' ),
|
366 |
//$this->get_xcloner_store_path(),
|
367 |
//'disabled'
|
368 |
+
)
|
369 |
+
);
|
370 |
+
|
371 |
//REGISTERING THE 'MYSQL SECTION' FIELDS
|
372 |
+
register_setting( 'xcloner_mysql_settings_group', 'xcloner_enable_mysql_backup', array(
|
373 |
+
$this->xcloner_sanitization,
|
374 |
+
"sanitize_input_as_int"
|
375 |
+
) );
|
376 |
+
add_settings_field(
|
377 |
+
'xcloner_enable_mysql_backup',
|
378 |
+
__( 'Enable Mysql Backup', 'xcloner-backup-and-restore' ),
|
379 |
+
array( $this, 'do_form_switch_field' ),
|
380 |
+
'xcloner_mysql_settings_page',
|
381 |
+
'xcloner_mysql_settings_group',
|
382 |
+
array(
|
383 |
+
'xcloner_enable_mysql_backup',
|
384 |
+
__( 'Enable Mysql Backup Option. If you don\'t want to backup the database, you can disable this.', 'xcloner-backup-and-restore' )
|
385 |
+
)
|
386 |
+
);
|
387 |
+
|
388 |
+
register_setting( 'xcloner_mysql_settings_group', 'xcloner_backup_only_wp_tables' );
|
389 |
+
add_settings_field(
|
390 |
+
'xcloner_backup_only_wp_tables',
|
391 |
+
__( 'Backup only WP tables', 'xcloner-backup-and-restore' ),
|
392 |
+
array( $this, 'do_form_switch_field' ),
|
393 |
+
'xcloner_mysql_settings_page',
|
394 |
+
'xcloner_mysql_settings_group',
|
395 |
+
array(
|
396 |
+
'xcloner_backup_only_wp_tables',
|
397 |
+
sprintf( __( 'Enable this if you only want to Backup only tables starting with \'%s\' prefix', 'xcloner-backup-and-restore' ), $this->get_table_prefix() )
|
398 |
+
)
|
399 |
+
);
|
400 |
+
|
401 |
+
register_setting( 'xcloner_mysql_settings_group', 'xcloner_mysql_hostname', array(
|
402 |
+
$this->xcloner_sanitization,
|
403 |
+
"sanitize_input_as_raw"
|
404 |
+
) );
|
405 |
+
add_settings_field(
|
406 |
+
'xcloner_mysql_hostname',
|
407 |
+
__( 'Mysql Hostname', 'xcloner-backup-and-restore' ),
|
408 |
+
array( $this, 'do_form_text_field' ),
|
409 |
+
'xcloner_mysql_settings_page',
|
410 |
+
'xcloner_mysql_settings_group',
|
411 |
+
array(
|
412 |
+
'xcloner_mysql_hostname',
|
413 |
+
__( 'Wordpress mysql hostname', 'xcloner-backup-and-restore' ),
|
414 |
$this->get_db_hostname(),
|
415 |
'disabled'
|
416 |
+
)
|
417 |
+
);
|
418 |
|
419 |
+
register_setting( 'xcloner_mysql_settings_group', 'xcloner_mysql_username', array(
|
420 |
+
$this->xcloner_sanitization,
|
421 |
+
"sanitize_input_as_raw"
|
422 |
+
) );
|
423 |
+
add_settings_field(
|
424 |
+
'xcloner_mysql_username',
|
425 |
+
__( 'Mysql Username', 'xcloner-backup-and-restore' ),
|
426 |
+
array( $this, 'do_form_text_field' ),
|
427 |
+
'xcloner_mysql_settings_page',
|
428 |
+
'xcloner_mysql_settings_group',
|
429 |
+
array(
|
430 |
+
'xcloner_mysql_username',
|
431 |
+
__( 'Wordpress mysql username', 'xcloner-backup-and-restore' ),
|
432 |
$this->get_db_username(),
|
433 |
'disabled'
|
434 |
+
)
|
435 |
+
);
|
436 |
+
|
437 |
+
register_setting( 'xcloner_mysql_settings_group', 'xcloner_mysql_database', array(
|
438 |
+
$this->xcloner_sanitization,
|
439 |
+
"sanitize_input_as_raw"
|
440 |
+
) );
|
441 |
+
add_settings_field(
|
442 |
+
'xcloner_mysql_database',
|
443 |
+
__( 'Mysql Database', 'xcloner-backup-and-restore' ),
|
444 |
+
array( $this, 'do_form_text_field' ),
|
445 |
+
'xcloner_mysql_settings_page',
|
446 |
+
'xcloner_mysql_settings_group',
|
447 |
+
array(
|
448 |
+
'xcloner_mysql_database',
|
449 |
+
__( 'Wordpress mysql database', 'xcloner-backup-and-restore' ),
|
450 |
$this->get_db_database(),
|
451 |
'disabled'
|
452 |
+
)
|
453 |
+
);
|
454 |
+
|
455 |
+
//REGISTERING THE 'SYSTEM SECTION' FIELDS
|
456 |
+
register_setting( 'xcloner_system_settings_group', 'xcloner_size_limit_per_request', array(
|
457 |
+
$this->xcloner_sanitization,
|
458 |
+
"sanitize_input_as_int"
|
459 |
+
) );
|
460 |
+
add_settings_field(
|
461 |
+
'xcloner_size_limit_per_request',
|
462 |
+
__( 'Data Size Limit Per Request', 'xcloner-backup-and-restore' ),
|
463 |
+
array( $this, 'do_form_range_field' ),
|
464 |
+
'xcloner_system_settings_page',
|
465 |
+
'xcloner_system_settings_group',
|
466 |
+
array(
|
467 |
+
'xcloner_size_limit_per_request',
|
468 |
+
__( 'Use this option to set how much file data can XCloner backup in one AJAX request. Range 0-1024 MB', 'xcloner-backup-and-restore' ),
|
469 |
+
0,
|
470 |
+
1024
|
471 |
+
)
|
472 |
+
);
|
473 |
+
|
474 |
+
register_setting( 'xcloner_system_settings_group', 'xcloner_files_to_process_per_request', array(
|
475 |
+
$this->xcloner_sanitization,
|
476 |
+
"sanitize_input_as_int"
|
477 |
+
) );
|
478 |
+
add_settings_field(
|
479 |
+
'xcloner_files_to_process_per_request',
|
480 |
+
__( 'Files To Process Per Request', 'xcloner-backup-and-restore' ),
|
481 |
+
array( $this, 'do_form_range_field' ),
|
482 |
+
'xcloner_system_settings_page',
|
483 |
+
'xcloner_system_settings_group',
|
484 |
+
array(
|
485 |
+
'xcloner_files_to_process_per_request',
|
486 |
+
__( 'Use this option to set how many files XCloner should process at one time before doing another AJAX call', 'xcloner-backup-and-restore' ),
|
487 |
+
0,
|
488 |
+
1000
|
489 |
+
)
|
490 |
+
);
|
491 |
+
|
492 |
+
register_setting( 'xcloner_system_settings_group', 'xcloner_directories_to_scan_per_request', array(
|
493 |
+
$this->xcloner_sanitization,
|
494 |
+
"sanitize_input_as_int"
|
495 |
+
) );
|
496 |
+
add_settings_field(
|
497 |
+
'xcloner_directories_to_scan_per_request',
|
498 |
+
__( 'Directories To Scan Per Request', 'xcloner-backup-and-restore' ),
|
499 |
+
array( $this, 'do_form_range_field' ),
|
500 |
+
'xcloner_system_settings_page',
|
501 |
+
'xcloner_system_settings_group',
|
502 |
+
array(
|
503 |
+
'xcloner_directories_to_scan_per_request',
|
504 |
+
__( 'Use this option to set how many directories XCloner should scan at one time before doing another AJAX call', 'xcloner-backup-and-restore' ),
|
505 |
+
0,
|
506 |
+
1000
|
507 |
+
)
|
508 |
+
);
|
509 |
+
|
510 |
+
register_setting( 'xcloner_system_settings_group', 'xcloner_database_records_per_request', array(
|
511 |
+
$this->xcloner_sanitization,
|
512 |
+
"sanitize_input_as_int"
|
513 |
+
) );
|
514 |
+
add_settings_field(
|
515 |
+
'xcloner_database_records_per_request',
|
516 |
+
__( 'Database Records Per Request', 'xcloner-backup-and-restore' ),
|
517 |
+
array( $this, 'do_form_range_field' ),
|
518 |
+
'xcloner_system_settings_page',
|
519 |
+
'xcloner_system_settings_group',
|
520 |
+
array(
|
521 |
+
'xcloner_database_records_per_request',
|
522 |
+
__( 'Use this option to set how many database table records should be fetched per AJAX request, or set to 0 to fetch all. Range 0-100000 records', 'xcloner-backup-and-restore' ),
|
523 |
+
0,
|
524 |
+
100000
|
525 |
+
)
|
526 |
+
);
|
527 |
+
|
528 |
/*register_setting('xcloner_system_settings_group', 'xcloner_diff_backup_recreate_period', array($this->xcloner_sanitization, "sanitize_input_as_int"));
|
529 |
add_settings_field(
|
530 |
'xcloner_diff_backup_recreate_period',
|
536 |
__('Use this option to set when a full backup should be recreated if the scheduled backup type is set to \'Full Backup+Differential Backups\' ','xcloner-backup-and-restore'),
|
537 |
)
|
538 |
);*/
|
539 |
+
|
540 |
+
register_setting( 'xcloner_system_settings_group', 'xcloner_exclude_files_larger_than_mb', array(
|
541 |
+
$this->xcloner_sanitization,
|
542 |
+
"sanitize_input_as_int"
|
543 |
+
) );
|
544 |
+
add_settings_field(
|
545 |
+
'xcloner_exclude_files_larger_than_mb',
|
546 |
+
__( 'Exclude files larger than (MB)', 'xcloner-backup-and-restore' ),
|
547 |
+
array( $this, 'do_form_number_field' ),
|
548 |
+
'xcloner_system_settings_page',
|
549 |
+
'xcloner_system_settings_group',
|
550 |
+
array(
|
551 |
+
'xcloner_exclude_files_larger_than_mb',
|
552 |
+
__( 'Use this option to automatically exclude files larger than a certain size in MB, or set to 0 to include all. Range 0-1000 MB', 'xcloner-backup-and-restore' ),
|
553 |
+
)
|
554 |
+
);
|
555 |
+
|
556 |
+
register_setting( 'xcloner_system_settings_group', 'xcloner_split_backup_limit', array(
|
557 |
+
$this->xcloner_sanitization,
|
558 |
+
"sanitize_input_as_int"
|
559 |
+
) );
|
560 |
+
add_settings_field(
|
561 |
+
'xcloner_split_backup_limit',
|
562 |
+
__( 'Split Backup Archive Limit (MB)', 'xcloner-backup-and-restore' ),
|
563 |
+
array( $this, 'do_form_number_field' ),
|
564 |
+
'xcloner_system_settings_page',
|
565 |
+
'xcloner_system_settings_group',
|
566 |
+
array(
|
567 |
+
'xcloner_split_backup_limit',
|
568 |
+
__( 'Use this option to automatically split the backup archive into smaller parts. Range 0-10000 MB', 'xcloner-backup-and-restore' ),
|
569 |
+
)
|
570 |
+
);
|
571 |
+
|
572 |
+
register_setting( 'xcloner_system_settings_group', 'xcloner_force_tmp_path_site_root' );
|
573 |
+
add_settings_field(
|
574 |
+
'xcloner_force_tmp_path_site_root',
|
575 |
+
__( 'Force Temporary Path Within XCloner Storage', 'xcloner-backup-and-restore' ),
|
576 |
+
array( $this, 'do_form_switch_field' ),
|
577 |
+
'xcloner_system_settings_page',
|
578 |
+
'xcloner_system_settings_group',
|
579 |
+
array(
|
580 |
+
'xcloner_force_tmp_path_site_root',
|
581 |
+
sprintf( __( 'Enable this option if you want the XCloner Temporary Path to be within your XCloner Storage Location', 'xcloner-backup-and-restore' ), $this->get_table_prefix() )
|
582 |
+
)
|
583 |
+
);
|
584 |
+
|
585 |
//REGISTERING THE 'CLEANUP SECTION' FIELDS
|
586 |
+
register_setting( 'xcloner_cleanup_settings_group', 'xcloner_cleanup_retention_limit_days', array(
|
587 |
+
$this->xcloner_sanitization,
|
588 |
+
"sanitize_input_as_int"
|
589 |
+
) );
|
590 |
+
add_settings_field(
|
591 |
+
'xcloner_cleanup_retention_limit_days',
|
592 |
+
__( 'Cleanup by Date(days)', 'xcloner-backup-and-restore' ),
|
593 |
+
array( $this, 'do_form_number_field' ),
|
594 |
+
'xcloner_cleanup_settings_page',
|
595 |
+
'xcloner_cleanup_settings_group',
|
596 |
+
array(
|
597 |
+
'xcloner_cleanup_retention_limit_days',
|
598 |
+
__( 'Specify the maximum number of days a backup archive can be kept on the server. 0 disables this option', 'xcloner-backup-and-restore' )
|
599 |
)
|
600 |
+
);
|
601 |
+
|
602 |
+
register_setting( 'xcloner_cleanup_settings_group', 'xcloner_cleanup_retention_limit_archives', array(
|
603 |
+
$this->xcloner_sanitization,
|
604 |
+
"sanitize_input_as_int"
|
605 |
+
) );
|
606 |
+
add_settings_field(
|
607 |
+
'xcloner_cleanup_retention_limit_archives',
|
608 |
+
__( 'Cleanup by Quantity', 'xcloner-backup-and-restore' ),
|
609 |
+
array( $this, 'do_form_number_field' ),
|
610 |
+
'xcloner_cleanup_settings_page',
|
611 |
+
'xcloner_cleanup_settings_group',
|
612 |
+
array(
|
613 |
+
'xcloner_cleanup_retention_limit_archives',
|
614 |
+
__( 'Specify the maximum number of backup archives to keep on the server. 0 disables this option', 'xcloner-backup-and-restore' )
|
615 |
)
|
616 |
+
);
|
617 |
+
|
618 |
+
register_setting( 'xcloner_cleanup_settings_group', 'xcloner_cleanup_capacity_limit', array(
|
619 |
+
$this->xcloner_sanitization,
|
620 |
+
"sanitize_input_as_int"
|
621 |
+
) );
|
622 |
+
add_settings_field(
|
623 |
+
'xcloner_cleanup_capacity_limit',
|
624 |
+
__( 'Cleanup by Capacity(MB)', 'xcloner-backup-and-restore' ),
|
625 |
+
array( $this, 'do_form_number_field' ),
|
626 |
+
'xcloner_cleanup_settings_page',
|
627 |
+
'xcloner_cleanup_settings_group',
|
628 |
+
array(
|
629 |
+
'xcloner_cleanup_capacity_limit',
|
630 |
+
__( 'Remove oldest backups if all created backups exceed the configured limit in Megabytes. 0 disables this option', 'xcloner-backup-and-restore' )
|
631 |
)
|
632 |
+
);
|
633 |
+
|
634 |
+
register_setting( 'xcloner_cleanup_settings_group', 'xcloner_cleanup_delete_after_remote_transfer', array(
|
635 |
+
$this->xcloner_sanitization,
|
636 |
+
"sanitize_input_as_int"
|
637 |
+
) );
|
638 |
+
add_settings_field(
|
639 |
+
'xcloner_cleanup_delete_after_remote_transfer',
|
640 |
+
__( 'Delete Backup After Remote Storage Transfer', 'xcloner-backup-and-restore' ),
|
641 |
+
array( $this, 'do_form_switch_field' ),
|
642 |
+
'xcloner_cleanup_settings_page',
|
643 |
+
'xcloner_cleanup_settings_group',
|
644 |
+
array(
|
645 |
+
'xcloner_cleanup_delete_after_remote_transfer',
|
646 |
+
__( 'Remove backup created automatically from local storage after sending the backup to Remote Storage', 'xcloner-backup-and-restore' )
|
647 |
)
|
648 |
+
);
|
649 |
+
|
650 |
//REGISTERING THE 'CRON SECTION' FIELDS
|
651 |
+
register_setting( 'xcloner_cron_settings_group', 'xcloner_cron_frequency' );
|
652 |
+
add_settings_field(
|
653 |
+
'xcloner_cron_frequency',
|
654 |
+
__( 'Cron frequency', 'xcloner-backup-and-restore' ),
|
655 |
+
array( $this, 'do_form_text_field' ),
|
656 |
+
'xcloner_cron_settings_page',
|
657 |
+
'xcloner_cron_settings_group',
|
658 |
+
array(
|
659 |
+
'xcloner_cron_frequency',
|
660 |
+
__( 'Cron frequency' )
|
661 |
)
|
662 |
+
);
|
663 |
}
|
664 |
+
|
665 |
+
|
666 |
+
|
667 |
+
|
668 |
/**
|
669 |
* callback functions
|
670 |
*/
|
671 |
+
|
672 |
// section content cb
|
673 |
+
public function xcloner_settings_section_cb() {
|
674 |
+
//echo '<p>WPOrg Section Introduction.</p>';
|
|
|
675 |
}
|
676 |
+
|
677 |
// text field content cb
|
678 |
+
public function do_form_text_field( $params ) {
|
679 |
+
if ( ! isset( $params['3'] ) ) {
|
|
|
680 |
$params[3] = 0;
|
681 |
+
}
|
682 |
+
if ( ! isset( $params['2'] ) ) {
|
683 |
+
$params[2] = 0;
|
684 |
+
}
|
685 |
+
|
686 |
+
list( $fieldname, $label, $value, $disabled ) = $params;
|
687 |
+
|
688 |
+
if ( ! $value ) {
|
689 |
+
$value = get_option( $fieldname );
|
690 |
+
}
|
691 |
+
// output the field
|
692 |
+
?>
|
693 |
+
<div class="row">
|
694 |
+
<div class="input-field col s10 m10 l8">
|
695 |
+
<input class="validate" <?php echo ( $disabled ) ? "disabled" : "" ?> name="<?php echo $fieldname ?>"
|
696 |
+
id="<?php echo $fieldname ?>" type="text" class="validate"
|
697 |
+
value="<?php echo isset( $value ) ? esc_attr( $value ) : ''; ?>">
|
698 |
+
</div>
|
699 |
+
<div class="col s2 m2 ">
|
700 |
+
<a class="btn-floating tooltipped btn-small" data-position="left" data-delay="50"
|
701 |
+
data-tooltip="<?php echo $label ?>" data-tooltip-id=""><i class="material-icons">help_outline</i></a>
|
702 |
+
</div>
|
703 |
+
</div>
|
704 |
+
|
705 |
+
|
706 |
+
<?php
|
707 |
}
|
708 |
+
|
709 |
// textarea field content cb
|
710 |
+
public function do_form_textarea_field( $params ) {
|
711 |
+
if ( ! isset( $params['3'] ) ) {
|
|
|
712 |
$params[3] = 0;
|
713 |
+
}
|
714 |
+
if ( ! isset( $params['2'] ) ) {
|
715 |
+
$params[2] = 0;
|
716 |
+
}
|
717 |
+
|
718 |
+
list( $fieldname, $label, $value, $disabled ) = $params;
|
719 |
+
|
720 |
+
if ( ! $value ) {
|
721 |
+
$value = get_option( $fieldname );
|
722 |
+
}
|
723 |
+
// output the field
|
724 |
+
?>
|
725 |
+
<div class="row">
|
726 |
+
<div class="input-field col s10 m10 l8">
|
727 |
+
<textarea class="validate" <?php echo ( $disabled ) ? "disabled" : "" ?> name="<?php echo $fieldname ?>"
|
728 |
+
id="<?php echo $fieldname ?>" type="text" class="validate"
|
729 |
+
value=""><?php echo isset( $value ) ? esc_attr( $value ) : ''; ?></textarea>
|
730 |
+
</div>
|
731 |
+
<div class="col s2 m2 ">
|
732 |
+
<a class="btn-floating tooltipped btn-small" data-position="center" data-html="true" data-delay="50"
|
733 |
+
data-tooltip="<?php echo $label ?>" data-tooltip-id=""><i class="material-icons">help_outline</i></a>
|
734 |
+
</div>
|
735 |
+
<div class="col s12">
|
736 |
+
<ul class="xcloner_regex_exclude_limit">
|
737 |
+
<li>Exclude all except .php file: <span
|
738 |
+
class="regex_pattern"><?php echo htmlentities( '(.*)\.(.+)$(?<!(php))' ) ?></span></li>
|
739 |
+
<li>Exclude all except .php and .txt: <span
|
740 |
+
class="regex_pattern"> <?php echo htmlentities( '(.*)\.(.+)$(?<!(php|txt))' ) ?></span>
|
741 |
+
</li>
|
742 |
+
<li>Exclude all .avi files: <span
|
743 |
+
class="regex_pattern"> <?php echo htmlentities( '(.*)\.(.+)$(?<=(avi))' ) ?></span></li>
|
744 |
+
<li>Exclude all .jpg,.gif and .png files: <span
|
745 |
+
class="regex_pattern"> <?php echo htmlentities( '(.*)\.(.+)$(?<=(gif|png|jpg))' ) ?></span>
|
746 |
+
</li>
|
747 |
+
<li>Exclude all .svn and .git: <span
|
748 |
+
class="regex_pattern"> <?php echo htmlentities( '(.*)\.(svn|git)(.*)$' ) ?></span></li>
|
749 |
+
<li>Exclude root directory /test: <span
|
750 |
+
class="regex_pattern"> <?php echo htmlentities( '\/test(.*)$' ) ?></span> or <span
|
751 |
+
class="regex_pattern"> <?php echo htmlentities( 'test(.*)$' ) ?></span></li>
|
752 |
+
<li>Exclude the wp-admin folder: <span
|
753 |
+
class="regex_pattern"> <?php echo htmlentities( '(\/wp-admin)(.*)$' ) ?></span></li>
|
754 |
+
<li>Exclude the wp-content/uploads folder: <span
|
755 |
+
class="regex_pattern"> <?php echo htmlentities( '(\/wp-content\/uploads)(.*)$' ) ?></span>
|
756 |
+
</li>
|
757 |
+
<li>Exclude the wp-admin, wp-includes and wp-config.php: <span
|
758 |
+
class="regex_pattern"> <?php echo htmlentities( '\/(wp-admin|wp-includes|wp-config.php)(.*)$' ) ?></span>
|
759 |
+
</li>
|
760 |
+
<li>Exclude wp-content/updraft and wp/content/uploads/wp_all_backup folder :<span
|
761 |
+
class="regex_pattern">\/(wp-content\/updraft|\/wp-content\/uploads\/wp_all_backup)(.*)$</span>
|
762 |
+
</li>
|
763 |
+
<li>Exclude all cache folders from wp-content/ and it's subdirectories: <span
|
764 |
+
class="regex_pattern"> <?php echo htmlentities( '\/wp-content(.*)\/cache($|\/)(.*)' ) ?></span>
|
765 |
+
</li>
|
766 |
+
<li>Exclude wp-content/cache/ folder: <span
|
767 |
+
class="regex_pattern"> <?php echo htmlentities( '\/wp-content\/cache(.*)' ) ?></span>
|
768 |
+
</li>
|
769 |
+
<li>Exclude all error_log files: <span
|
770 |
+
class="regex_pattern"> <?php echo htmlentities( '(.*)error_log$' ) ?></span></li>
|
771 |
+
</ul>
|
772 |
+
</div>
|
773 |
+
</div>
|
774 |
+
|
775 |
+
|
776 |
+
<?php
|
777 |
}
|
778 |
+
|
779 |
// number field content cb
|
780 |
+
public function do_form_number_field( $params ) {
|
781 |
+
if ( ! isset( $params['3'] ) ) {
|
|
|
782 |
$params[3] = 0;
|
783 |
+
}
|
784 |
+
if ( ! isset( $params['2'] ) ) {
|
785 |
+
$params[2] = 0;
|
786 |
+
}
|
787 |
+
|
788 |
+
list( $fieldname, $label, $value, $disabled ) = $params;
|
789 |
+
|
790 |
+
if ( ! $value ) {
|
791 |
+
$value = get_option( $fieldname );
|
792 |
+
}
|
793 |
+
// output the field
|
794 |
+
?>
|
795 |
+
<div class="row">
|
796 |
+
<div class="input-field col s10 m5 l3">
|
797 |
+
<input class="validate" <?php echo ( $disabled ) ? "disabled" : "" ?> name="<?php echo $fieldname ?>"
|
798 |
+
id="<?php echo $fieldname ?>" type="number" class="validate"
|
799 |
+
value="<?php echo isset( $value ) ? esc_attr( $value ) : ''; ?>">
|
800 |
+
</div>
|
801 |
+
<div class="col s2 m2 ">
|
802 |
+
<a class="btn-floating tooltipped btn-small" data-html="true" data-position="center" data-delay="50"
|
803 |
+
data-tooltip="<?php echo $label ?>" data-tooltip-id=""><i class="material-icons">help_outline</i></a>
|
804 |
+
</div>
|
805 |
+
</div>
|
806 |
+
|
807 |
+
|
808 |
+
<?php
|
809 |
}
|
810 |
+
|
811 |
+
public function do_form_range_field( $params ) {
|
812 |
+
if ( ! isset( $params['4'] ) ) {
|
|
|
813 |
$params[4] = 0;
|
814 |
+
}
|
815 |
+
|
816 |
+
list( $fieldname, $label, $range_start, $range_end, $disabled ) = $params;
|
817 |
+
$value = get_option( $fieldname );
|
818 |
+
?>
|
819 |
+
<div class="row">
|
820 |
+
<div class="input-field col s10 m10 l8">
|
821 |
+
<p class="range-field">
|
822 |
+
<input <?php echo ( $disabled ) ? "disabled" : "" ?> type="range" name="<?php echo $fieldname ?>"
|
823 |
+
id="<?php echo $fieldname ?>"
|
824 |
+
min="<?php echo $range_start ?>"
|
825 |
+
max="<?php echo $range_end ?>"
|
826 |
+
value="<?php echo isset( $value ) ? esc_attr( $value ) : ''; ?>"/>
|
827 |
+
</p>
|
828 |
+
</div>
|
829 |
+
<div class="col s2 m2 ">
|
830 |
+
<a class="btn-floating tooltipped btn-small" data-html="true" data-position="center" data-delay="50"
|
831 |
+
data-tooltip="<?php echo $label ?>" data-tooltip-id=""><i class="material-icons">help_outline</i></a>
|
832 |
+
</div>
|
833 |
+
</div>
|
834 |
+
<?php
|
835 |
}
|
836 |
+
|
837 |
+
|
838 |
+
public function do_form_switch_field( $params ) {
|
839 |
+
if ( ! isset( $params['2'] ) ) {
|
|
|
840 |
$params[2] = 0;
|
841 |
+
}
|
842 |
+
list( $fieldname, $label, $disabled ) = $params;
|
843 |
+
$value = get_option( $fieldname );
|
844 |
+
?>
|
845 |
+
<div class="row">
|
846 |
+
<div class="input-field col s10 m5 l3">
|
847 |
+
<div class="switch">
|
848 |
+
<label>
|
849 |
+
Off
|
850 |
+
<input <?php echo ( $disabled ) ? "disabled" : "" ?> type="checkbox"
|
851 |
+
name="<?php echo $fieldname ?>"
|
852 |
+
id="<?php echo $fieldname ?>"
|
853 |
+
value="1" <?php echo ( $value ) ? 'checked="checked"' : ''; ?>
|
854 |
+
">
|
855 |
+
<span class="lever"></span>
|
856 |
+
On
|
857 |
+
</label>
|
858 |
+
</div>
|
859 |
+
</div>
|
860 |
+
<div class="col s2 m2">
|
861 |
+
<a class="btn-floating tooltipped btn-small" data-position="center" data-delay="50"
|
862 |
+
data-tooltip="<?php echo $label ?>" data-tooltip-id=""><i class="material-icons">help_outline</i></a>
|
863 |
+
</div>
|
864 |
+
</div>
|
865 |
+
<?php
|
866 |
}
|
867 |
}
|
includes/class-xcloner.php
CHANGED
@@ -1,16 +1,29 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
/**
|
4 |
-
*
|
5 |
*
|
6 |
-
*
|
7 |
-
*
|
8 |
*
|
9 |
-
*
|
10 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
*
|
12 |
-
* @package Xcloner
|
13 |
-
* @subpackage Xcloner/includes
|
14 |
*/
|
15 |
|
16 |
/**
|
@@ -26,6 +39,7 @@
|
|
26 |
* @package Xcloner
|
27 |
* @subpackage Xcloner/includes
|
28 |
* @author Liuta Ovidiu <info@thinkovi.com>
|
|
|
29 |
*/
|
30 |
class Xcloner {
|
31 |
|
@@ -38,7 +52,7 @@ class Xcloner {
|
|
38 |
* @var Xcloner_Loader $loader Maintains and registers all hooks for the plugin.
|
39 |
*/
|
40 |
protected $loader;
|
41 |
-
|
42 |
/**
|
43 |
* The unique identifier of this plugin.
|
44 |
*
|
@@ -47,7 +61,7 @@ class Xcloner {
|
|
47 |
* @var string $plugin_name The string used to uniquely identify this plugin.
|
48 |
*/
|
49 |
protected $plugin_name;
|
50 |
-
|
51 |
protected $plugin_admin;
|
52 |
|
53 |
/**
|
@@ -58,8 +72,8 @@ class Xcloner {
|
|
58 |
* @var string $version The current version of the plugin.
|
59 |
*/
|
60 |
protected $version;
|
61 |
-
|
62 |
-
private $xcloner_settings;
|
63 |
private $xcloner_logger;
|
64 |
private $xcloner_sanitization;
|
65 |
private $xcloner_requirements;
|
@@ -78,80 +92,80 @@ class Xcloner {
|
|
78 |
*
|
79 |
* @since 1.0.0
|
80 |
*/
|
81 |
-
public function init()
|
82 |
{
|
83 |
register_shutdown_function(array($this, 'exception_handler'));
|
84 |
-
|
85 |
$this->plugin_name = 'xcloner';
|
86 |
$this->version = '4.0.4';
|
87 |
-
|
88 |
$this->load_dependencies();
|
89 |
$this->set_locale();
|
90 |
$this->define_admin_hooks();
|
91 |
$this->define_public_hooks();
|
92 |
-
|
93 |
$this->define_admin_menu();
|
94 |
$this->define_plugin_settings();
|
95 |
-
|
96 |
$this->define_ajax_hooks();
|
97 |
$this->define_cron_hooks();
|
98 |
-
|
99 |
}
|
100 |
-
|
101 |
public function get_xcloner_settings()
|
102 |
{
|
103 |
return $this->xcloner_settings;
|
104 |
}
|
105 |
-
|
106 |
public function get_xcloner_filesystem()
|
107 |
{
|
108 |
return $this->xcloner_filesystem;
|
109 |
}
|
110 |
-
|
111 |
public function get_xcloner_logger()
|
112 |
{
|
113 |
return $this->xcloner_logger;
|
114 |
}
|
115 |
-
|
116 |
public function get_xcloner_sanitization()
|
117 |
{
|
118 |
return $this->xcloner_sanitization;
|
119 |
}
|
120 |
-
|
121 |
public function get_xcloner_requirements()
|
122 |
{
|
123 |
return $this->xcloner_requirements;
|
124 |
}
|
125 |
-
|
126 |
public function get_archive_system()
|
127 |
{
|
128 |
return $this->archive_system;
|
129 |
}
|
130 |
-
|
131 |
public function get_xcloner_database()
|
132 |
{
|
133 |
return $this->xcloner_database;
|
134 |
}
|
135 |
-
|
136 |
public function get_xcloner_scheduler()
|
137 |
{
|
138 |
return $this->xcloner_scheduler;
|
139 |
}
|
140 |
-
|
141 |
public function get_xcloner_remote_storage()
|
142 |
{
|
143 |
return $this->xcloner_remote_storage;
|
144 |
}
|
145 |
-
|
146 |
public function get_xcloner_file_transfer()
|
147 |
{
|
148 |
return $this->xcloner_file_transfer;
|
149 |
}
|
150 |
-
|
151 |
public function check_dependencies(){
|
152 |
-
|
153 |
$backup_storage_path = realpath(__DIR__.DS."..".DS."..".DS."..").DS."backups".DS;
|
154 |
-
|
155 |
define("XCLONER_STORAGE_PATH", realpath($backup_storage_path));
|
156 |
|
157 |
if(!is_dir($backup_storage_path))
|
@@ -163,25 +177,25 @@ class Xcloner {
|
|
163 |
$this->trigger_message($message, $status, $backup_storage_path);
|
164 |
return;
|
165 |
}
|
166 |
-
}
|
167 |
if(!is_writable($backup_storage_path))
|
168 |
{
|
169 |
$status = "error";
|
170 |
$message = sprintf(__("Unable to write to the Backup Storage Location Folder %s . Please fix this before starting the backup process."), $backup_storage_path);
|
171 |
$this->trigger_message($message, $status, $backup_storage_path);
|
172 |
-
|
173 |
return;
|
174 |
}
|
175 |
-
|
176 |
}
|
177 |
-
|
178 |
public function trigger_message($message, $status = "error", $message_param1 = "", $message_param2 = "", $message_param3 = "")
|
179 |
{
|
180 |
$message = sprintf(__($message), $message_param1, $message_param2, $message_param3);
|
181 |
add_action( 'xcloner_admin_notices', array($this,"trigger_message_notice"), 10, 2);
|
182 |
do_action( 'xcloner_admin_notices', $message, $status);
|
183 |
}
|
184 |
-
|
185 |
public function trigger_message_notice($message, $status = "success")
|
186 |
{
|
187 |
?>
|
@@ -225,57 +239,57 @@ class Xcloner {
|
|
225 |
* The class responsible for defining all actions that occur in the admin area.
|
226 |
*/
|
227 |
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/class-xcloner-admin.php';
|
228 |
-
|
229 |
/**
|
230 |
* The class responsible for debugging XCloner.
|
231 |
*/
|
232 |
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-xcloner-logger.php';
|
233 |
-
|
234 |
/**
|
235 |
* The class responsible for defining the admin settings area.
|
236 |
*/
|
237 |
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-xcloner-settings.php';
|
238 |
-
|
239 |
/**
|
240 |
* The class responsible for defining the Remote Storage settings area.
|
241 |
*/
|
242 |
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-xcloner-remote-storage.php';
|
243 |
-
|
244 |
/**
|
245 |
* The class responsible for implementing the database backup methods.
|
246 |
*/
|
247 |
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-xcloner-database.php';
|
248 |
-
|
249 |
/**
|
250 |
* The class responsible for sanitization of users input.
|
251 |
*/
|
252 |
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-xcloner-sanitization.php';
|
253 |
-
|
254 |
/**
|
255 |
* The class responsible for XCloner system requirements validation.
|
256 |
*/
|
257 |
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-xcloner-requirements.php';
|
258 |
-
|
259 |
/**
|
260 |
* The class responsible for XCloner backup archive creation.
|
261 |
*/
|
262 |
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-xcloner-archive.php';
|
263 |
-
|
264 |
/**
|
265 |
* The class responsible for XCloner API requests.
|
266 |
*/
|
267 |
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-xcloner-api.php';
|
268 |
-
|
269 |
/**
|
270 |
* The class responsible for the XCloner File System methods.
|
271 |
*/
|
272 |
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-xcloner-file-system.php';
|
273 |
-
|
274 |
/**
|
275 |
* The class responsible for the XCloner File Transfer methods.
|
276 |
*/
|
277 |
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-xcloner-file-transfer.php';
|
278 |
-
|
279 |
/**
|
280 |
* The class responsible for the XCloner Scheduler methods.
|
281 |
*/
|
@@ -286,7 +300,7 @@ class Xcloner {
|
|
286 |
* side of the site.
|
287 |
*/
|
288 |
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'public/class-xcloner-public.php';
|
289 |
-
|
290 |
$this->loader = new Xcloner_Loader($this);
|
291 |
|
292 |
}
|
@@ -305,7 +319,7 @@ class Xcloner {
|
|
305 |
$plugin_i18n = new Xcloner_i18n();
|
306 |
|
307 |
$this->loader->add_action( 'plugins_loaded', $plugin_i18n, 'load_plugin_textdomain' );
|
308 |
-
|
309 |
//wp_localize_script( 'ajax-script', 'my_ajax_object',
|
310 |
// array( 'ajax_url' => admin_url( 'admin-ajax.php' ) ) );
|
311 |
|
@@ -319,42 +333,44 @@ class Xcloner {
|
|
319 |
* @access private
|
320 |
*/
|
321 |
private function define_admin_hooks() {
|
322 |
-
|
323 |
$plugin_admin = new Xcloner_Admin( $this );
|
324 |
$this->plugin_admin = $plugin_admin;
|
325 |
|
326 |
$this->loader->add_action( 'admin_enqueue_scripts', $plugin_admin, 'enqueue_styles' );
|
327 |
$this->loader->add_action( 'admin_enqueue_scripts', $plugin_admin, 'enqueue_scripts' );
|
328 |
-
|
|
|
329 |
}
|
330 |
-
|
331 |
/**
|
332 |
* Register the Admin Sidebar menu
|
333 |
-
*
|
334 |
-
* @access
|
|
|
335 |
*/
|
336 |
private function define_admin_menu(){
|
337 |
-
|
338 |
add_action('admin_menu', array($this->loader, 'xcloner_backup_add_admin_menu'));
|
339 |
-
|
340 |
}
|
341 |
-
|
342 |
private function define_plugin_settings(){
|
343 |
/**
|
344 |
* register wporg_settings_init to the admin_init action hook
|
345 |
*/
|
346 |
|
347 |
$this->xcloner_settings = new XCloner_Settings($this);
|
348 |
-
|
349 |
if(defined('DOING_CRON') || isset($_POST['hash'])){
|
350 |
-
|
351 |
if(defined('DOING_CRON') || $_POST['hash'] == "generate_hash"){
|
352 |
$this->xcloner_settings->generate_new_hash();
|
353 |
}else{
|
354 |
$this->xcloner_settings->set_hash($_POST['hash']);
|
355 |
}
|
356 |
}
|
357 |
-
|
358 |
if(defined('DOING_CRON') || !isset($_POST['hash']))
|
359 |
{
|
360 |
add_action( 'shutdown', function(){
|
@@ -362,19 +378,19 @@ class Xcloner {
|
|
362 |
$this->xcloner_file_system->remove_tmp_filesystem();
|
363 |
});
|
364 |
}
|
365 |
-
|
366 |
$this->xcloner_sanitization = new Xcloner_Sanitization();
|
367 |
$this->xcloner_requirements = new Xcloner_Requirements($this);
|
368 |
-
|
369 |
add_action('admin_init', array($this->xcloner_settings, 'settings_init'));
|
370 |
-
|
371 |
//adding links to the Manage Plugins Wordpress page for XCloner
|
372 |
add_filter('plugin_action_links', array($this, 'add_plugin_action_links'), 10, 2);
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
}
|
377 |
-
|
378 |
/*
|
379 |
* type = core|plugin|theme|translation
|
380 |
*/
|
@@ -383,15 +399,15 @@ class Xcloner {
|
|
383 |
if(!$type)
|
384 |
{
|
385 |
return false;
|
386 |
-
}
|
387 |
-
|
388 |
$this->get_xcloner_logger()->info(sprintf("Doing automatic backup before %s upgrade, pre_auto_update hook.", $type));
|
389 |
-
|
390 |
-
$content_dir = str_replace(ABSPATH, "", WP_CONTENT_DIR);
|
391 |
$plugins_dir = str_replace(ABSPATH, "", WP_PLUGIN_DIR);
|
392 |
$langs_dir = $content_dir . DS . "languages";
|
393 |
$themes_dir = $content_dir . DS . "themes";
|
394 |
-
|
395 |
switch ( $type ) {
|
396 |
case 'core':
|
397 |
$exclude_files = array(
|
@@ -399,17 +415,17 @@ class Xcloner {
|
|
399 |
);
|
400 |
break;
|
401 |
case 'plugin':
|
402 |
-
|
403 |
$dir_array = explode(DS, $plugins_dir);
|
404 |
-
|
405 |
foreach($dir_array as $dir)
|
406 |
{
|
407 |
$data .= "\/".$dir;
|
408 |
$regex .= $data."$|";
|
409 |
}
|
410 |
-
|
411 |
$regex .= "\/".implode("\/", $dir_array);
|
412 |
-
|
413 |
$exclude_files = array(
|
414 |
"^(?!(".$regex."))(.*)$",
|
415 |
);
|
@@ -417,55 +433,55 @@ class Xcloner {
|
|
417 |
case 'theme':
|
418 |
|
419 |
$dir_array = explode(DS, $themes_dir);
|
420 |
-
|
421 |
foreach($dir_array as $dir)
|
422 |
{
|
423 |
$data .= "\/".$dir;
|
424 |
$regex .= $data."$|";
|
425 |
}
|
426 |
-
|
427 |
$regex .= "\/".implode("\/", $dir_array);
|
428 |
-
|
429 |
$exclude_files = array(
|
430 |
"^(?!(".$regex."))(.*)$",
|
431 |
-
);
|
432 |
break;
|
433 |
case 'translation':
|
434 |
|
435 |
$dir_array = explode(DS, $langs_dir);
|
436 |
-
|
437 |
foreach($dir_array as $dir)
|
438 |
{
|
439 |
$data .= "\/".$dir;
|
440 |
$regex .= $data."$|";
|
441 |
}
|
442 |
-
|
443 |
$regex .= "\/".implode("\/", $dir_array);
|
444 |
-
|
445 |
$exclude_files = array(
|
446 |
"^(?!(".$regex."))(.*)$",
|
447 |
-
);
|
448 |
break;
|
449 |
}
|
450 |
-
|
451 |
$schedule = array();
|
452 |
-
|
453 |
$schedule['id'] = 0;
|
454 |
$schedule['name'] = "pre_auto_update";
|
455 |
$schedule['recurrence'] = "single";
|
456 |
$schedule['excluded_files'] = json_encode($exclude_files);
|
457 |
$schedule['table_params'] = json_encode(array("#" => array($this->get_xcloner_settings()->get_db_database())));
|
458 |
-
|
459 |
$schedule['backup_params'] = new stdClass();
|
460 |
$schedule['backup_params']->email_notification = get_option('admin_email');
|
461 |
$schedule['backup_params']->backup_name = "backup_pre_auto_update_".$type."_[domain]-[time]-sql";
|
462 |
-
|
463 |
try{
|
464 |
$this->xcloner_scheduler->xcloner_scheduler_callback(0, $schedule);
|
465 |
}catch(Exception $e){
|
466 |
$this->get_xcloner_logger()->error($e->getMessage());
|
467 |
}
|
468 |
-
|
469 |
}
|
470 |
|
471 |
/**
|
@@ -483,19 +499,19 @@ class Xcloner {
|
|
483 |
$this->loader->add_action( 'wp_enqueue_scripts', $plugin_public, 'enqueue_scripts' );
|
484 |
|
485 |
}
|
486 |
-
|
487 |
public function exception_handler() {
|
488 |
-
|
489 |
$logger = new XCloner_Logger($this, "php_system");
|
490 |
$error = error_get_last();
|
491 |
-
|
492 |
if($error['type'] and $logger)
|
493 |
{
|
494 |
$logger->info($this->friendly_error_type ($error['type']).": ".var_export($error, true));
|
495 |
}
|
496 |
-
|
497 |
}
|
498 |
-
|
499 |
function friendly_error_type($type) {
|
500 |
static $levels=null;
|
501 |
if ($levels===null) {
|
@@ -507,24 +523,24 @@ class Xcloner {
|
|
507 |
}
|
508 |
return (isset($levels[$type]) ? $levels[$type] : "Error #{$type}");
|
509 |
}
|
510 |
-
|
511 |
private function define_ajax_hooks()
|
512 |
{
|
513 |
//adding the pre-update hook
|
514 |
-
|
515 |
if(is_admin() || defined('DOING_CRON'))
|
516 |
{
|
517 |
$this->xcloner_logger = new XCloner_Logger($this, "xcloner_api");
|
518 |
$this->xcloner_filesystem = new Xcloner_File_System($this);
|
519 |
-
|
520 |
//$this->xcloner_filesystem->set_diff_timestamp_start (strtotime("-15 days"));
|
521 |
-
|
522 |
$this->archive_system = new Xcloner_Archive($this);
|
523 |
$this->xcloner_database = new Xcloner_Database($this);
|
524 |
$this->xcloner_scheduler = new Xcloner_Scheduler($this);
|
525 |
$this->xcloner_remote_storage = new Xcloner_Remote_Storage($this);
|
526 |
$this->xcloner_file_transfer = new Xcloner_File_Transfer($this);
|
527 |
-
|
528 |
$xcloner_api = new Xcloner_Api($this);
|
529 |
|
530 |
add_action( 'wp_ajax_get_database_tables_action', array($xcloner_api,'get_database_tables_action') );
|
@@ -546,65 +562,65 @@ class Xcloner {
|
|
546 |
add_action( 'wp_ajax_copy_backup_remote_to_local', array($xcloner_api,'copy_backup_remote_to_local') );
|
547 |
add_action( 'wp_ajax_restore_backup', array($xcloner_api,'restore_backup') );
|
548 |
add_action( 'admin_notices', array($this, 'xcloner_error_admin_notices' ));
|
549 |
-
|
550 |
}
|
551 |
-
|
552 |
//Do a pre-update backup of targeted files
|
553 |
if($this->get_xcloner_settings()->get_xcloner_option('xcloner_enable_pre_update_backup'))
|
554 |
{
|
555 |
add_action("pre_auto_update", array($this, "pre_auto_update"), 1, 3);
|
556 |
}
|
557 |
}
|
558 |
-
|
559 |
function add_plugin_action_links($links, $file) {
|
560 |
if ($file == plugin_basename(dirname(dirname(__FILE__)) . '/xcloner.php'))
|
561 |
-
{
|
562 |
$links[] = '<a href="admin.php?page=xcloner_settings_page">'.__('Settings', 'xcloner-backup-and-restore').'</a>';
|
563 |
$links[] = '<a href="admin.php?page=xcloner_generate_backups_page">'.__('Generate Backup', 'xcloner-backup-and-restore').'</a>';
|
564 |
}
|
565 |
-
|
566 |
return $links;
|
567 |
}
|
568 |
-
|
569 |
public function xcloner_error_admin_notices() {
|
570 |
settings_errors( 'xcloner_error_message' );
|
571 |
}
|
572 |
-
|
573 |
public function define_cron_hooks()
|
574 |
{
|
575 |
//registering new schedule intervals
|
576 |
add_filter( 'cron_schedules', array($this, 'add_new_intervals'));
|
577 |
-
|
578 |
-
|
579 |
$xcloner_scheduler = $this->get_xcloner_scheduler();
|
580 |
$xcloner_scheduler->update_wp_cron_hooks();
|
581 |
-
|
582 |
}
|
583 |
-
|
584 |
-
function add_new_intervals($schedules)
|
585 |
{
|
586 |
//weekly scheduler interval
|
587 |
$schedules['weekly'] = array(
|
588 |
'interval' => 604800,
|
589 |
'display' => __('Once Weekly', 'xcloner-backup-and-restore')
|
590 |
);
|
591 |
-
|
592 |
//monthly scheduler interval
|
593 |
$schedules['monthly'] = array(
|
594 |
'interval' => 2635200,
|
595 |
'display' => __('Once Monthly', 'xcloner-backup-and-restore')
|
596 |
);
|
597 |
-
|
598 |
//monthly scheduler interval
|
599 |
$schedules['twicedaily'] = array(
|
600 |
'interval' => 43200,
|
601 |
'display' => __('Twice Daily', 'xcloner-backup-and-restore')
|
602 |
);
|
603 |
-
|
604 |
return $schedules;
|
605 |
}
|
606 |
|
607 |
-
|
608 |
/**
|
609 |
* Run the loader to execute all of the hooks with WordPress.
|
610 |
*
|
@@ -644,28 +660,28 @@ class Xcloner {
|
|
644 |
public function get_version() {
|
645 |
return $this->version;
|
646 |
}
|
647 |
-
|
648 |
function xcloner_display()
|
649 |
-
{
|
650 |
// check user capabilities
|
651 |
if (!current_user_can('manage_options')) {
|
652 |
return;
|
653 |
}
|
654 |
-
|
655 |
$page = sanitize_key($_GET['page']);
|
656 |
|
657 |
if($page)
|
658 |
{
|
659 |
$this->display($page);
|
660 |
}
|
661 |
-
|
662 |
}
|
663 |
-
|
664 |
public function display($page)
|
665 |
{
|
666 |
$plugin_admin = new Xcloner_Admin($this);
|
667 |
$this->plugin_admin = $plugin_admin;
|
668 |
-
|
669 |
call_user_func_array(array($this->plugin_admin, $page), array());
|
670 |
}
|
671 |
}
|
1 |
<?php
|
|
|
2 |
/**
|
3 |
+
* XCloner - Backup and Restore backup plugin for Wordpress
|
4 |
*
|
5 |
+
* class-xcloner.php
|
6 |
+
* @author Liuta Ovidiu <info@thinkovi.com>
|
7 |
*
|
8 |
+
* This program is free software; you can redistribute it and/or modify
|
9 |
+
* it under the terms of the GNU General Public License as published by
|
10 |
+
* the Free Software Foundation; either version 2 of the License, or
|
11 |
+
* (at your option) any later version.
|
12 |
+
*
|
13 |
+
* This program is distributed in the hope that it will be useful,
|
14 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16 |
+
* GNU General Public License for more details.
|
17 |
+
*
|
18 |
+
* You should have received a copy of the GNU General Public License
|
19 |
+
* along with this program; if not, write to the Free Software
|
20 |
+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
21 |
+
* MA 02110-1301, USA.
|
22 |
+
*
|
23 |
+
* @link https://github.com/ovidiul/XCloner-Wordpress
|
24 |
+
*
|
25 |
+
* @modified 7/31/18 3:29 PM
|
26 |
*
|
|
|
|
|
27 |
*/
|
28 |
|
29 |
/**
|
39 |
* @package Xcloner
|
40 |
* @subpackage Xcloner/includes
|
41 |
* @author Liuta Ovidiu <info@thinkovi.com>
|
42 |
+
* @link http://www.thinkovi.com
|
43 |
*/
|
44 |
class Xcloner {
|
45 |
|
52 |
* @var Xcloner_Loader $loader Maintains and registers all hooks for the plugin.
|
53 |
*/
|
54 |
protected $loader;
|
55 |
+
|
56 |
/**
|
57 |
* The unique identifier of this plugin.
|
58 |
*
|
61 |
* @var string $plugin_name The string used to uniquely identify this plugin.
|
62 |
*/
|
63 |
protected $plugin_name;
|
64 |
+
|
65 |
protected $plugin_admin;
|
66 |
|
67 |
/**
|
72 |
* @var string $version The current version of the plugin.
|
73 |
*/
|
74 |
protected $version;
|
75 |
+
|
76 |
+
private $xcloner_settings;
|
77 |
private $xcloner_logger;
|
78 |
private $xcloner_sanitization;
|
79 |
private $xcloner_requirements;
|
92 |
*
|
93 |
* @since 1.0.0
|
94 |
*/
|
95 |
+
public function init()
|
96 |
{
|
97 |
register_shutdown_function(array($this, 'exception_handler'));
|
98 |
+
|
99 |
$this->plugin_name = 'xcloner';
|
100 |
$this->version = '4.0.4';
|
101 |
+
|
102 |
$this->load_dependencies();
|
103 |
$this->set_locale();
|
104 |
$this->define_admin_hooks();
|
105 |
$this->define_public_hooks();
|
106 |
+
|
107 |
$this->define_admin_menu();
|
108 |
$this->define_plugin_settings();
|
109 |
+
|
110 |
$this->define_ajax_hooks();
|
111 |
$this->define_cron_hooks();
|
112 |
+
|
113 |
}
|
114 |
+
|
115 |
public function get_xcloner_settings()
|
116 |
{
|
117 |
return $this->xcloner_settings;
|
118 |
}
|
119 |
+
|
120 |
public function get_xcloner_filesystem()
|
121 |
{
|
122 |
return $this->xcloner_filesystem;
|
123 |
}
|
124 |
+
|
125 |
public function get_xcloner_logger()
|
126 |
{
|
127 |
return $this->xcloner_logger;
|
128 |
}
|
129 |
+
|
130 |
public function get_xcloner_sanitization()
|
131 |
{
|
132 |
return $this->xcloner_sanitization;
|
133 |
}
|
134 |
+
|
135 |
public function get_xcloner_requirements()
|
136 |
{
|
137 |
return $this->xcloner_requirements;
|
138 |
}
|
139 |
+
|
140 |
public function get_archive_system()
|
141 |
{
|
142 |
return $this->archive_system;
|
143 |
}
|
144 |
+
|
145 |
public function get_xcloner_database()
|
146 |
{
|
147 |
return $this->xcloner_database;
|
148 |
}
|
149 |
+
|
150 |
public function get_xcloner_scheduler()
|
151 |
{
|
152 |
return $this->xcloner_scheduler;
|
153 |
}
|
154 |
+
|
155 |
public function get_xcloner_remote_storage()
|
156 |
{
|
157 |
return $this->xcloner_remote_storage;
|
158 |
}
|
159 |
+
|
160 |
public function get_xcloner_file_transfer()
|
161 |
{
|
162 |
return $this->xcloner_file_transfer;
|
163 |
}
|
164 |
+
|
165 |
public function check_dependencies(){
|
166 |
+
|
167 |
$backup_storage_path = realpath(__DIR__.DS."..".DS."..".DS."..").DS."backups".DS;
|
168 |
+
|
169 |
define("XCLONER_STORAGE_PATH", realpath($backup_storage_path));
|
170 |
|
171 |
if(!is_dir($backup_storage_path))
|
177 |
$this->trigger_message($message, $status, $backup_storage_path);
|
178 |
return;
|
179 |
}
|
180 |
+
}
|
181 |
if(!is_writable($backup_storage_path))
|
182 |
{
|
183 |
$status = "error";
|
184 |
$message = sprintf(__("Unable to write to the Backup Storage Location Folder %s . Please fix this before starting the backup process."), $backup_storage_path);
|
185 |
$this->trigger_message($message, $status, $backup_storage_path);
|
186 |
+
|
187 |
return;
|
188 |
}
|
189 |
+
|
190 |
}
|
191 |
+
|
192 |
public function trigger_message($message, $status = "error", $message_param1 = "", $message_param2 = "", $message_param3 = "")
|
193 |
{
|
194 |
$message = sprintf(__($message), $message_param1, $message_param2, $message_param3);
|
195 |
add_action( 'xcloner_admin_notices', array($this,"trigger_message_notice"), 10, 2);
|
196 |
do_action( 'xcloner_admin_notices', $message, $status);
|
197 |
}
|
198 |
+
|
199 |
public function trigger_message_notice($message, $status = "success")
|
200 |
{
|
201 |
?>
|
239 |
* The class responsible for defining all actions that occur in the admin area.
|
240 |
*/
|
241 |
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/class-xcloner-admin.php';
|
242 |
+
|
243 |
/**
|
244 |
* The class responsible for debugging XCloner.
|
245 |
*/
|
246 |
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-xcloner-logger.php';
|
247 |
+
|
248 |
/**
|
249 |
* The class responsible for defining the admin settings area.
|
250 |
*/
|
251 |
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-xcloner-settings.php';
|
252 |
+
|
253 |
/**
|
254 |
* The class responsible for defining the Remote Storage settings area.
|
255 |
*/
|
256 |
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-xcloner-remote-storage.php';
|
257 |
+
|
258 |
/**
|
259 |
* The class responsible for implementing the database backup methods.
|
260 |
*/
|
261 |
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-xcloner-database.php';
|
262 |
+
|
263 |
/**
|
264 |
* The class responsible for sanitization of users input.
|
265 |
*/
|
266 |
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-xcloner-sanitization.php';
|
267 |
+
|
268 |
/**
|
269 |
* The class responsible for XCloner system requirements validation.
|
270 |
*/
|
271 |
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-xcloner-requirements.php';
|
272 |
+
|
273 |
/**
|
274 |
* The class responsible for XCloner backup archive creation.
|
275 |
*/
|
276 |
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-xcloner-archive.php';
|
277 |
+
|
278 |
/**
|
279 |
* The class responsible for XCloner API requests.
|
280 |
*/
|
281 |
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-xcloner-api.php';
|
282 |
+
|
283 |
/**
|
284 |
* The class responsible for the XCloner File System methods.
|
285 |
*/
|
286 |
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-xcloner-file-system.php';
|
287 |
+
|
288 |
/**
|
289 |
* The class responsible for the XCloner File Transfer methods.
|
290 |
*/
|
291 |
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-xcloner-file-transfer.php';
|
292 |
+
|
293 |
/**
|
294 |
* The class responsible for the XCloner Scheduler methods.
|
295 |
*/
|
300 |
* side of the site.
|
301 |
*/
|
302 |
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'public/class-xcloner-public.php';
|
303 |
+
|
304 |
$this->loader = new Xcloner_Loader($this);
|
305 |
|
306 |
}
|
319 |
$plugin_i18n = new Xcloner_i18n();
|
320 |
|
321 |
$this->loader->add_action( 'plugins_loaded', $plugin_i18n, 'load_plugin_textdomain' );
|
322 |
+
|
323 |
//wp_localize_script( 'ajax-script', 'my_ajax_object',
|
324 |
// array( 'ajax_url' => admin_url( 'admin-ajax.php' ) ) );
|
325 |
|
333 |
* @access private
|
334 |
*/
|
335 |
private function define_admin_hooks() {
|
336 |
+
|
337 |
$plugin_admin = new Xcloner_Admin( $this );
|
338 |
$this->plugin_admin = $plugin_admin;
|
339 |
|
340 |
$this->loader->add_action( 'admin_enqueue_scripts', $plugin_admin, 'enqueue_styles' );
|
341 |
$this->loader->add_action( 'admin_enqueue_scripts', $plugin_admin, 'enqueue_scripts' );
|
342 |
+
|
343 |
+
add_action( 'backup_archive_finished', array($this, 'do_action_after_backup_finished'), 10, 2);
|
344 |
}
|
345 |
+
|
346 |
/**
|
347 |
* Register the Admin Sidebar menu
|
348 |
+
*
|
349 |
+
* @access private
|
350 |
+
*
|
351 |
*/
|
352 |
private function define_admin_menu(){
|
353 |
+
|
354 |
add_action('admin_menu', array($this->loader, 'xcloner_backup_add_admin_menu'));
|
355 |
+
|
356 |
}
|
357 |
+
|
358 |
private function define_plugin_settings(){
|
359 |
/**
|
360 |
* register wporg_settings_init to the admin_init action hook
|
361 |
*/
|
362 |
|
363 |
$this->xcloner_settings = new XCloner_Settings($this);
|
364 |
+
|
365 |
if(defined('DOING_CRON') || isset($_POST['hash'])){
|
366 |
+
|
367 |
if(defined('DOING_CRON') || $_POST['hash'] == "generate_hash"){
|
368 |
$this->xcloner_settings->generate_new_hash();
|
369 |
}else{
|
370 |
$this->xcloner_settings->set_hash($_POST['hash']);
|
371 |
}
|
372 |
}
|
373 |
+
|
374 |
if(defined('DOING_CRON') || !isset($_POST['hash']))
|
375 |
{
|
376 |
add_action( 'shutdown', function(){
|
378 |
$this->xcloner_file_system->remove_tmp_filesystem();
|
379 |
});
|
380 |
}
|
381 |
+
|
382 |
$this->xcloner_sanitization = new Xcloner_Sanitization();
|
383 |
$this->xcloner_requirements = new Xcloner_Requirements($this);
|
384 |
+
|
385 |
add_action('admin_init', array($this->xcloner_settings, 'settings_init'));
|
386 |
+
|
387 |
//adding links to the Manage Plugins Wordpress page for XCloner
|
388 |
add_filter('plugin_action_links', array($this, 'add_plugin_action_links'), 10, 2);
|
389 |
+
|
390 |
+
|
391 |
+
|
392 |
}
|
393 |
+
|
394 |
/*
|
395 |
* type = core|plugin|theme|translation
|
396 |
*/
|
399 |
if(!$type)
|
400 |
{
|
401 |
return false;
|
402 |
+
}
|
403 |
+
|
404 |
$this->get_xcloner_logger()->info(sprintf("Doing automatic backup before %s upgrade, pre_auto_update hook.", $type));
|
405 |
+
|
406 |
+
$content_dir = str_replace(ABSPATH, "", WP_CONTENT_DIR);
|
407 |
$plugins_dir = str_replace(ABSPATH, "", WP_PLUGIN_DIR);
|
408 |
$langs_dir = $content_dir . DS . "languages";
|
409 |
$themes_dir = $content_dir . DS . "themes";
|
410 |
+
|
411 |
switch ( $type ) {
|
412 |
case 'core':
|
413 |
$exclude_files = array(
|
415 |
);
|
416 |
break;
|
417 |
case 'plugin':
|
418 |
+
|
419 |
$dir_array = explode(DS, $plugins_dir);
|
420 |
+
|
421 |
foreach($dir_array as $dir)
|
422 |
{
|
423 |
$data .= "\/".$dir;
|
424 |
$regex .= $data."$|";
|
425 |
}
|
426 |
+
|
427 |
$regex .= "\/".implode("\/", $dir_array);
|
428 |
+
|
429 |
$exclude_files = array(
|
430 |
"^(?!(".$regex."))(.*)$",
|
431 |
);
|
433 |
case 'theme':
|
434 |
|
435 |
$dir_array = explode(DS, $themes_dir);
|
436 |
+
|
437 |
foreach($dir_array as $dir)
|
438 |
{
|
439 |
$data .= "\/".$dir;
|
440 |
$regex .= $data."$|";
|
441 |
}
|
442 |
+
|
443 |
$regex .= "\/".implode("\/", $dir_array);
|
444 |
+
|
445 |
$exclude_files = array(
|
446 |
"^(?!(".$regex."))(.*)$",
|
447 |
+
);
|
448 |
break;
|
449 |
case 'translation':
|
450 |
|
451 |
$dir_array = explode(DS, $langs_dir);
|
452 |
+
|
453 |
foreach($dir_array as $dir)
|
454 |
{
|
455 |
$data .= "\/".$dir;
|
456 |
$regex .= $data."$|";
|
457 |
}
|
458 |
+
|
459 |
$regex .= "\/".implode("\/", $dir_array);
|
460 |
+
|
461 |
$exclude_files = array(
|
462 |
"^(?!(".$regex."))(.*)$",
|
463 |
+
);
|
464 |
break;
|
465 |
}
|
466 |
+
|
467 |
$schedule = array();
|
468 |
+
|
469 |
$schedule['id'] = 0;
|
470 |
$schedule['name'] = "pre_auto_update";
|
471 |
$schedule['recurrence'] = "single";
|
472 |
$schedule['excluded_files'] = json_encode($exclude_files);
|
473 |
$schedule['table_params'] = json_encode(array("#" => array($this->get_xcloner_settings()->get_db_database())));
|
474 |
+
|
475 |
$schedule['backup_params'] = new stdClass();
|
476 |
$schedule['backup_params']->email_notification = get_option('admin_email');
|
477 |
$schedule['backup_params']->backup_name = "backup_pre_auto_update_".$type."_[domain]-[time]-sql";
|
478 |
+
|
479 |
try{
|
480 |
$this->xcloner_scheduler->xcloner_scheduler_callback(0, $schedule);
|
481 |
}catch(Exception $e){
|
482 |
$this->get_xcloner_logger()->error($e->getMessage());
|
483 |
}
|
484 |
+
|
485 |
}
|
486 |
|
487 |
/**
|
499 |
$this->loader->add_action( 'wp_enqueue_scripts', $plugin_public, 'enqueue_scripts' );
|
500 |
|
501 |
}
|
502 |
+
|
503 |
public function exception_handler() {
|
504 |
+
|
505 |
$logger = new XCloner_Logger($this, "php_system");
|
506 |
$error = error_get_last();
|
507 |
+
|
508 |
if($error['type'] and $logger)
|
509 |
{
|
510 |
$logger->info($this->friendly_error_type ($error['type']).": ".var_export($error, true));
|
511 |
}
|
512 |
+
|
513 |
}
|
514 |
+
|
515 |
function friendly_error_type($type) {
|
516 |
static $levels=null;
|
517 |
if ($levels===null) {
|
523 |
}
|
524 |
return (isset($levels[$type]) ? $levels[$type] : "Error #{$type}");
|
525 |
}
|
526 |
+
|
527 |
private function define_ajax_hooks()
|
528 |
{
|
529 |
//adding the pre-update hook
|
530 |
+
|
531 |
if(is_admin() || defined('DOING_CRON'))
|
532 |
{
|
533 |
$this->xcloner_logger = new XCloner_Logger($this, "xcloner_api");
|
534 |
$this->xcloner_filesystem = new Xcloner_File_System($this);
|
535 |
+
|
536 |
//$this->xcloner_filesystem->set_diff_timestamp_start (strtotime("-15 days"));
|
537 |
+
|
538 |
$this->archive_system = new Xcloner_Archive($this);
|
539 |
$this->xcloner_database = new Xcloner_Database($this);
|
540 |
$this->xcloner_scheduler = new Xcloner_Scheduler($this);
|
541 |
$this->xcloner_remote_storage = new Xcloner_Remote_Storage($this);
|
542 |
$this->xcloner_file_transfer = new Xcloner_File_Transfer($this);
|
543 |
+
|
544 |
$xcloner_api = new Xcloner_Api($this);
|
545 |
|
546 |
add_action( 'wp_ajax_get_database_tables_action', array($xcloner_api,'get_database_tables_action') );
|
562 |
add_action( 'wp_ajax_copy_backup_remote_to_local', array($xcloner_api,'copy_backup_remote_to_local') );
|
563 |
add_action( 'wp_ajax_restore_backup', array($xcloner_api,'restore_backup') );
|
564 |
add_action( 'admin_notices', array($this, 'xcloner_error_admin_notices' ));
|
565 |
+
|
566 |
}
|
567 |
+
|
568 |
//Do a pre-update backup of targeted files
|
569 |
if($this->get_xcloner_settings()->get_xcloner_option('xcloner_enable_pre_update_backup'))
|
570 |
{
|
571 |
add_action("pre_auto_update", array($this, "pre_auto_update"), 1, 3);
|
572 |
}
|
573 |
}
|
574 |
+
|
575 |
function add_plugin_action_links($links, $file) {
|
576 |
if ($file == plugin_basename(dirname(dirname(__FILE__)) . '/xcloner.php'))
|
577 |
+
{
|
578 |
$links[] = '<a href="admin.php?page=xcloner_settings_page">'.__('Settings', 'xcloner-backup-and-restore').'</a>';
|
579 |
$links[] = '<a href="admin.php?page=xcloner_generate_backups_page">'.__('Generate Backup', 'xcloner-backup-and-restore').'</a>';
|
580 |
}
|
581 |
+
|
582 |
return $links;
|
583 |
}
|
584 |
+
|
585 |
public function xcloner_error_admin_notices() {
|
586 |
settings_errors( 'xcloner_error_message' );
|
587 |
}
|
588 |
+
|
589 |
public function define_cron_hooks()
|
590 |
{
|
591 |
//registering new schedule intervals
|
592 |
add_filter( 'cron_schedules', array($this, 'add_new_intervals'));
|
593 |
+
|
594 |
+
|
595 |
$xcloner_scheduler = $this->get_xcloner_scheduler();
|
596 |
$xcloner_scheduler->update_wp_cron_hooks();
|
597 |
+
|
598 |
}
|
599 |
+
|
600 |
+
function add_new_intervals($schedules)
|
601 |
{
|
602 |
//weekly scheduler interval
|
603 |
$schedules['weekly'] = array(
|
604 |
'interval' => 604800,
|
605 |
'display' => __('Once Weekly', 'xcloner-backup-and-restore')
|
606 |
);
|
607 |
+
|
608 |
//monthly scheduler interval
|
609 |
$schedules['monthly'] = array(
|
610 |
'interval' => 2635200,
|
611 |
'display' => __('Once Monthly', 'xcloner-backup-and-restore')
|
612 |
);
|
613 |
+
|
614 |
//monthly scheduler interval
|
615 |
$schedules['twicedaily'] = array(
|
616 |
'interval' => 43200,
|
617 |
'display' => __('Twice Daily', 'xcloner-backup-and-restore')
|
618 |
);
|
619 |
+
|
620 |
return $schedules;
|
621 |
}
|
622 |
|
623 |
+
|
624 |
/**
|
625 |
* Run the loader to execute all of the hooks with WordPress.
|
626 |
*
|
660 |
public function get_version() {
|
661 |
return $this->version;
|
662 |
}
|
663 |
+
|
664 |
function xcloner_display()
|
665 |
+
{
|
666 |
// check user capabilities
|
667 |
if (!current_user_can('manage_options')) {
|
668 |
return;
|
669 |
}
|
670 |
+
|
671 |
$page = sanitize_key($_GET['page']);
|
672 |
|
673 |
if($page)
|
674 |
{
|
675 |
$this->display($page);
|
676 |
}
|
677 |
+
|
678 |
}
|
679 |
+
|
680 |
public function display($page)
|
681 |
{
|
682 |
$plugin_admin = new Xcloner_Admin($this);
|
683 |
$this->plugin_admin = $plugin_admin;
|
684 |
+
|
685 |
call_user_func_array(array($this->plugin_admin, $page), array());
|
686 |
}
|
687 |
}
|
public/class-xcloner-public.php
CHANGED
@@ -27,7 +27,7 @@ class Xcloner_Public {
|
|
27 |
*
|
28 |
* @since 1.0.0
|
29 |
* @access private
|
30 |
-
* @var string
|
31 |
*/
|
32 |
private $plugin_name;
|
33 |
|
@@ -36,7 +36,7 @@ class Xcloner_Public {
|
|
36 |
*
|
37 |
* @since 1.0.0
|
38 |
* @access private
|
39 |
-
* @var string
|
40 |
*/
|
41 |
private $version;
|
42 |
|
@@ -44,13 +44,14 @@ class Xcloner_Public {
|
|
44 |
* Initialize the class and set its properties.
|
45 |
*
|
46 |
* @since 1.0.0
|
47 |
-
*
|
48 |
-
* @param string
|
|
|
49 |
*/
|
50 |
public function __construct( Xcloner $xcloner_container ) {
|
51 |
|
52 |
-
$this->plugin_name
|
53 |
-
$this->version
|
54 |
|
55 |
}
|
56 |
|
27 |
*
|
28 |
* @since 1.0.0
|
29 |
* @access private
|
30 |
+
* @var string $plugin_name The ID of this plugin.
|
31 |
*/
|
32 |
private $plugin_name;
|
33 |
|
36 |
*
|
37 |
* @since 1.0.0
|
38 |
* @access private
|
39 |
+
* @var string $version The current version of this plugin.
|
40 |
*/
|
41 |
private $version;
|
42 |
|
44 |
* Initialize the class and set its properties.
|
45 |
*
|
46 |
* @since 1.0.0
|
47 |
+
*
|
48 |
+
* @param string $plugin_name The name of the plugin.
|
49 |
+
* @param string $version The version of this plugin.
|
50 |
*/
|
51 |
public function __construct( Xcloner $xcloner_container ) {
|
52 |
|
53 |
+
$this->plugin_name = $xcloner_container->get_plugin_name();
|
54 |
+
$this->version = $xcloner_container->get_version();
|
55 |
|
56 |
}
|
57 |
|
vendor/composer/ClassLoader.php
CHANGED
@@ -374,10 +374,14 @@ class ClassLoader
|
|
374 |
|
375 |
$first = $class[0];
|
376 |
if (isset($this->prefixLengthsPsr4[$first])) {
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
|
|
|
|
|
|
|
|
381 |
return $file;
|
382 |
}
|
383 |
}
|
374 |
|
375 |
$first = $class[0];
|
376 |
if (isset($this->prefixLengthsPsr4[$first])) {
|
377 |
+
$subPath = $class;
|
378 |
+
while (false !== $lastPos = strrpos($subPath, '\\')) {
|
379 |
+
$subPath = substr($subPath, 0, $lastPos);
|
380 |
+
$search = $subPath.'\\';
|
381 |
+
if (isset($this->prefixDirsPsr4[$search])) {
|
382 |
+
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
|
383 |
+
foreach ($this->prefixDirsPsr4[$search] as $dir) {
|
384 |
+
if (file_exists($file = $dir . $pathEnd)) {
|
385 |
return $file;
|
386 |
}
|
387 |
}
|
vendor/composer/LICENSE
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
|
2 |
-
Copyright (c)
|
3 |
|
4 |
Permission is hereby granted, free of charge, to any person obtaining a copy
|
5 |
of this software and associated documentation files (the "Software"), to deal
|
1 |
|
2 |
+
Copyright (c) Nils Adermann, Jordi Boggiano
|
3 |
|
4 |
Permission is hereby granted, free of charge, to any person obtaining a copy
|
5 |
of this software and associated documentation files (the "Software"), to deal
|
vendor/composer/autoload_files.php
CHANGED
@@ -8,15 +8,16 @@ $baseDir = dirname($vendorDir);
|
|
8 |
return array(
|
9 |
'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php',
|
10 |
'a0edc8309cc5e1d60e3047b5df6b7052' => $vendorDir . '/guzzlehttp/psr7/src/functions_include.php',
|
11 |
-
'37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
|
12 |
'383eaff206634a77a1be54e64e6459c7' => $vendorDir . '/sabre/uri/lib/functions.php',
|
|
|
13 |
'b067bc7112e384b61c701452d53a14a8' => $vendorDir . '/mtdowling/jmespath.php/src/JmesPath.php',
|
14 |
-
'3569eecfeed3bcf0bad3c998a494ecb8' => $vendorDir . '/sabre/xml/lib/Deserializer/functions.php',
|
15 |
-
'93aa591bc4ca510c520999e34229ee79' => $vendorDir . '/sabre/xml/lib/Serializer/functions.php',
|
16 |
'2b9d0f43f9552984cfa82fee95491826' => $vendorDir . '/sabre/event/lib/coroutine.php',
|
17 |
'd81bab31d3feb45bfe2f283ea3c8fdf7' => $vendorDir . '/sabre/event/lib/Loop/functions.php',
|
18 |
'a1cce3d26cc15c00fcd0b3354bd72c88' => $vendorDir . '/sabre/event/lib/Promise/functions.php',
|
|
|
|
|
19 |
'8a9dc1de0ca7e01f3e08231539562f61' => $vendorDir . '/aws/aws-sdk-php/src/functions.php',
|
20 |
'ebdb698ed4152ae445614b69b5e4bb6a' => $vendorDir . '/sabre/http/lib/functions.php',
|
|
|
21 |
'decc78cc4436b1292c6c0d151b19445c' => $vendorDir . '/phpseclib/phpseclib/phpseclib/bootstrap.php',
|
22 |
);
|
8 |
return array(
|
9 |
'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php',
|
10 |
'a0edc8309cc5e1d60e3047b5df6b7052' => $vendorDir . '/guzzlehttp/psr7/src/functions_include.php',
|
|
|
11 |
'383eaff206634a77a1be54e64e6459c7' => $vendorDir . '/sabre/uri/lib/functions.php',
|
12 |
+
'37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
|
13 |
'b067bc7112e384b61c701452d53a14a8' => $vendorDir . '/mtdowling/jmespath.php/src/JmesPath.php',
|
|
|
|
|
14 |
'2b9d0f43f9552984cfa82fee95491826' => $vendorDir . '/sabre/event/lib/coroutine.php',
|
15 |
'd81bab31d3feb45bfe2f283ea3c8fdf7' => $vendorDir . '/sabre/event/lib/Loop/functions.php',
|
16 |
'a1cce3d26cc15c00fcd0b3354bd72c88' => $vendorDir . '/sabre/event/lib/Promise/functions.php',
|
17 |
+
'3569eecfeed3bcf0bad3c998a494ecb8' => $vendorDir . '/sabre/xml/lib/Deserializer/functions.php',
|
18 |
+
'93aa591bc4ca510c520999e34229ee79' => $vendorDir . '/sabre/xml/lib/Serializer/functions.php',
|
19 |
'8a9dc1de0ca7e01f3e08231539562f61' => $vendorDir . '/aws/aws-sdk-php/src/functions.php',
|
20 |
'ebdb698ed4152ae445614b69b5e4bb6a' => $vendorDir . '/sabre/http/lib/functions.php',
|
21 |
+
'5255c38a0faeba867671b61dfda6d864' => $vendorDir . '/paragonie/random_compat/lib/random.php',
|
22 |
'decc78cc4436b1292c6c0d151b19445c' => $vendorDir . '/phpseclib/phpseclib/phpseclib/bootstrap.php',
|
23 |
);
|
vendor/composer/autoload_psr4.php
CHANGED
@@ -32,7 +32,7 @@ return array(
|
|
32 |
'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'),
|
33 |
'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'),
|
34 |
'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'),
|
35 |
-
'
|
36 |
'BackblazeB2\\' => array($vendorDir . '/gliterd/backblaze-b2/src'),
|
37 |
'Aws\\' => array($vendorDir . '/aws/aws-sdk-php/src'),
|
38 |
);
|
32 |
'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'),
|
33 |
'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'),
|
34 |
'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'),
|
35 |
+
'Defuse\\Crypto\\' => array($vendorDir . '/defuse/php-encryption/src'),
|
36 |
'BackblazeB2\\' => array($vendorDir . '/gliterd/backblaze-b2/src'),
|
37 |
'Aws\\' => array($vendorDir . '/aws/aws-sdk-php/src'),
|
38 |
);
|
vendor/composer/autoload_static.php
CHANGED
@@ -9,16 +9,17 @@ class ComposerStaticInit571f9d19802717f7be61d57b40d60b28
|
|
9 |
public static $files = array (
|
10 |
'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php',
|
11 |
'a0edc8309cc5e1d60e3047b5df6b7052' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/functions_include.php',
|
12 |
-
'37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
|
13 |
'383eaff206634a77a1be54e64e6459c7' => __DIR__ . '/..' . '/sabre/uri/lib/functions.php',
|
|
|
14 |
'b067bc7112e384b61c701452d53a14a8' => __DIR__ . '/..' . '/mtdowling/jmespath.php/src/JmesPath.php',
|
15 |
-
'3569eecfeed3bcf0bad3c998a494ecb8' => __DIR__ . '/..' . '/sabre/xml/lib/Deserializer/functions.php',
|
16 |
-
'93aa591bc4ca510c520999e34229ee79' => __DIR__ . '/..' . '/sabre/xml/lib/Serializer/functions.php',
|
17 |
'2b9d0f43f9552984cfa82fee95491826' => __DIR__ . '/..' . '/sabre/event/lib/coroutine.php',
|
18 |
'd81bab31d3feb45bfe2f283ea3c8fdf7' => __DIR__ . '/..' . '/sabre/event/lib/Loop/functions.php',
|
19 |
'a1cce3d26cc15c00fcd0b3354bd72c88' => __DIR__ . '/..' . '/sabre/event/lib/Promise/functions.php',
|
|
|
|
|
20 |
'8a9dc1de0ca7e01f3e08231539562f61' => __DIR__ . '/..' . '/aws/aws-sdk-php/src/functions.php',
|
21 |
'ebdb698ed4152ae445614b69b5e4bb6a' => __DIR__ . '/..' . '/sabre/http/lib/functions.php',
|
|
|
22 |
'decc78cc4436b1292c6c0d151b19445c' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/bootstrap.php',
|
23 |
);
|
24 |
|
@@ -73,9 +74,9 @@ class ComposerStaticInit571f9d19802717f7be61d57b40d60b28
|
|
73 |
'GuzzleHttp\\Promise\\' => 19,
|
74 |
'GuzzleHttp\\' => 11,
|
75 |
),
|
76 |
-
'
|
77 |
array (
|
78 |
-
'
|
79 |
),
|
80 |
'B' =>
|
81 |
array (
|
@@ -192,9 +193,9 @@ class ComposerStaticInit571f9d19802717f7be61d57b40d60b28
|
|
192 |
array (
|
193 |
0 => __DIR__ . '/..' . '/guzzlehttp/guzzle/src',
|
194 |
),
|
195 |
-
'
|
196 |
array (
|
197 |
-
0 => __DIR__ . '/..' . '/
|
198 |
),
|
199 |
'BackblazeB2\\' =>
|
200 |
array (
|
9 |
public static $files = array (
|
10 |
'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php',
|
11 |
'a0edc8309cc5e1d60e3047b5df6b7052' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/functions_include.php',
|
|
|
12 |
'383eaff206634a77a1be54e64e6459c7' => __DIR__ . '/..' . '/sabre/uri/lib/functions.php',
|
13 |
+
'37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
|
14 |
'b067bc7112e384b61c701452d53a14a8' => __DIR__ . '/..' . '/mtdowling/jmespath.php/src/JmesPath.php',
|
|
|
|
|
15 |
'2b9d0f43f9552984cfa82fee95491826' => __DIR__ . '/..' . '/sabre/event/lib/coroutine.php',
|
16 |
'd81bab31d3feb45bfe2f283ea3c8fdf7' => __DIR__ . '/..' . '/sabre/event/lib/Loop/functions.php',
|
17 |
'a1cce3d26cc15c00fcd0b3354bd72c88' => __DIR__ . '/..' . '/sabre/event/lib/Promise/functions.php',
|
18 |
+
'3569eecfeed3bcf0bad3c998a494ecb8' => __DIR__ . '/..' . '/sabre/xml/lib/Deserializer/functions.php',
|
19 |
+
'93aa591bc4ca510c520999e34229ee79' => __DIR__ . '/..' . '/sabre/xml/lib/Serializer/functions.php',
|
20 |
'8a9dc1de0ca7e01f3e08231539562f61' => __DIR__ . '/..' . '/aws/aws-sdk-php/src/functions.php',
|
21 |
'ebdb698ed4152ae445614b69b5e4bb6a' => __DIR__ . '/..' . '/sabre/http/lib/functions.php',
|
22 |
+
'5255c38a0faeba867671b61dfda6d864' => __DIR__ . '/..' . '/paragonie/random_compat/lib/random.php',
|
23 |
'decc78cc4436b1292c6c0d151b19445c' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/bootstrap.php',
|
24 |
);
|
25 |
|
74 |
'GuzzleHttp\\Promise\\' => 19,
|
75 |
'GuzzleHttp\\' => 11,
|
76 |
),
|
77 |
+
'D' =>
|
78 |
array (
|
79 |
+
'Defuse\\Crypto\\' => 14,
|
80 |
),
|
81 |
'B' =>
|
82 |
array (
|
193 |
array (
|
194 |
0 => __DIR__ . '/..' . '/guzzlehttp/guzzle/src',
|
195 |
),
|
196 |
+
'Defuse\\Crypto\\' =>
|
197 |
array (
|
198 |
+
0 => __DIR__ . '/..' . '/defuse/php-encryption/src',
|
199 |
),
|
200 |
'BackblazeB2\\' =>
|
201 |
array (
|
vendor/composer/installed.json
CHANGED
@@ -1,135 +1,163 @@
|
|
1 |
[
|
2 |
{
|
3 |
-
"name": "
|
4 |
-
"version": "
|
5 |
-
"version_normalized": "
|
6 |
"source": {
|
7 |
"type": "git",
|
8 |
-
"url": "https://github.com/php
|
9 |
-
"reference": "
|
10 |
},
|
11 |
"dist": {
|
12 |
"type": "zip",
|
13 |
-
"url": "https://api.github.com/repos/php
|
14 |
-
"reference": "
|
15 |
"shasum": ""
|
16 |
},
|
17 |
"require": {
|
18 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
},
|
20 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
"type": "library",
|
22 |
"extra": {
|
23 |
"branch-alias": {
|
24 |
-
"dev-master": "
|
25 |
}
|
26 |
},
|
27 |
-
"installation-source": "
|
28 |
"autoload": {
|
29 |
"psr-4": {
|
30 |
-
"
|
31 |
-
}
|
|
|
|
|
|
|
32 |
},
|
33 |
"notification-url": "https://packagist.org/downloads/",
|
34 |
"license": [
|
35 |
-
"
|
36 |
],
|
37 |
"authors": [
|
38 |
{
|
39 |
-
"name": "
|
40 |
-
"homepage": "http://
|
41 |
}
|
42 |
],
|
43 |
-
"description": "
|
44 |
-
"homepage": "
|
45 |
"keywords": [
|
46 |
-
"
|
47 |
-
"
|
48 |
-
"
|
|
|
|
|
|
|
|
|
|
|
49 |
]
|
50 |
},
|
51 |
{
|
52 |
-
"name": "
|
53 |
-
"version": "
|
54 |
-
"version_normalized": "
|
55 |
"source": {
|
56 |
"type": "git",
|
57 |
-
"url": "https://github.com/
|
58 |
-
"reference": "
|
59 |
},
|
60 |
"dist": {
|
61 |
"type": "zip",
|
62 |
-
"url": "https://api.github.com/repos/
|
63 |
-
"reference": "
|
64 |
"shasum": ""
|
65 |
},
|
66 |
-
"
|
67 |
-
|
68 |
-
},
|
69 |
-
"require-dev": {
|
70 |
-
"phpunit/phpunit": "^4.0"
|
71 |
-
},
|
72 |
-
"time": "2016-12-20T10:07:11+00:00",
|
73 |
-
"type": "library",
|
74 |
"extra": {
|
75 |
-
"
|
76 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
77 |
}
|
78 |
},
|
79 |
-
"installation-source": "
|
80 |
-
"autoload": {
|
81 |
-
"psr-4": {
|
82 |
-
"GuzzleHttp\\Promise\\": "src/"
|
83 |
-
},
|
84 |
-
"files": [
|
85 |
-
"src/functions_include.php"
|
86 |
-
]
|
87 |
-
},
|
88 |
"notification-url": "https://packagist.org/downloads/",
|
89 |
"license": [
|
90 |
"MIT"
|
91 |
],
|
92 |
"authors": [
|
93 |
{
|
94 |
-
"name": "
|
95 |
-
"email": "mtdowling@gmail.com",
|
96 |
-
"homepage": "https://github.com/mtdowling"
|
97 |
}
|
98 |
],
|
99 |
-
"description": "
|
100 |
-
"
|
101 |
-
"promise"
|
102 |
-
]
|
103 |
},
|
104 |
{
|
105 |
-
"name": "
|
106 |
-
"version": "
|
107 |
-
"version_normalized": "
|
108 |
"source": {
|
109 |
"type": "git",
|
110 |
-
"url": "https://github.com/php-
|
111 |
-
"reference": "
|
112 |
},
|
113 |
"dist": {
|
114 |
"type": "zip",
|
115 |
-
"url": "https://api.github.com/repos/php-
|
116 |
-
"reference": "
|
117 |
"shasum": ""
|
118 |
},
|
119 |
"require": {
|
120 |
-
"
|
|
|
|
|
121 |
},
|
122 |
-
"
|
123 |
-
|
124 |
-
|
125 |
-
"branch-alias": {
|
126 |
-
"dev-master": "1.0.x-dev"
|
127 |
-
}
|
128 |
},
|
|
|
|
|
|
|
|
|
|
|
129 |
"installation-source": "dist",
|
130 |
"autoload": {
|
131 |
"psr-4": {
|
132 |
-
"
|
133 |
}
|
134 |
},
|
135 |
"notification-url": "https://packagist.org/downloads/",
|
@@ -138,61 +166,60 @@
|
|
138 |
],
|
139 |
"authors": [
|
140 |
{
|
141 |
-
"name": "
|
142 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
143 |
}
|
144 |
],
|
145 |
-
"description": "
|
146 |
-
"homepage": "https://github.com/php-fig/http-message",
|
147 |
"keywords": [
|
148 |
-
"
|
149 |
-
"
|
150 |
-
"
|
151 |
-
"
|
152 |
-
"
|
153 |
-
"
|
|
|
|
|
|
|
|
|
154 |
]
|
155 |
},
|
156 |
{
|
157 |
-
"name": "
|
158 |
-
"version": "
|
159 |
-
"version_normalized": "0.
|
160 |
"source": {
|
161 |
"type": "git",
|
162 |
-
"url": "https://github.com/
|
163 |
-
"reference": "
|
164 |
},
|
165 |
"dist": {
|
166 |
"type": "zip",
|
167 |
-
"url": "https://api.github.com/repos/
|
168 |
-
"reference": "
|
169 |
"shasum": ""
|
170 |
},
|
171 |
"require": {
|
172 |
-
"guzzlehttp/guzzle": "
|
173 |
"php": ">=5.5.0"
|
174 |
},
|
175 |
"require-dev": {
|
176 |
-
"
|
177 |
-
"
|
178 |
-
"
|
179 |
-
"phpmd/phpmd": "@stable",
|
180 |
-
"phpunit/phpunit": "~4.0",
|
181 |
-
"sebastian/phpcpd": "~2.0",
|
182 |
-
"squizlabs/php_codesniffer": "2.*",
|
183 |
-
"theseer/phpdox": "~0.8"
|
184 |
},
|
185 |
-
"time": "
|
186 |
"type": "library",
|
187 |
-
"
|
188 |
-
"branch-alias": {
|
189 |
-
"dev-master": "0.10.x-dev"
|
190 |
-
}
|
191 |
-
},
|
192 |
-
"installation-source": "dist",
|
193 |
"autoload": {
|
194 |
"psr-4": {
|
195 |
-
"
|
196 |
}
|
197 |
},
|
198 |
"notification-url": "https://packagist.org/downloads/",
|
@@ -201,54 +228,66 @@
|
|
201 |
],
|
202 |
"authors": [
|
203 |
{
|
204 |
-
"name": "
|
205 |
-
"email": "
|
|
|
|
|
206 |
}
|
207 |
],
|
208 |
-
"description": "
|
|
|
209 |
"keywords": [
|
210 |
-
"
|
211 |
-
"
|
212 |
-
"
|
|
|
|
|
|
|
213 |
"storage"
|
214 |
-
]
|
215 |
-
"abandoned": "microsoft/azure-storage-blob, microsoft/azure-storage-table, microsoft/azure-storage-queue, microsoft/azure-storage-file"
|
216 |
},
|
217 |
{
|
218 |
-
"name": "
|
219 |
-
"version": "
|
220 |
-
"version_normalized": "
|
221 |
"source": {
|
222 |
"type": "git",
|
223 |
-
"url": "https://github.com/
|
224 |
-
"reference": "
|
225 |
},
|
226 |
"dist": {
|
227 |
"type": "zip",
|
228 |
-
"url": "https://api.github.com/repos/
|
229 |
-
"reference": "
|
230 |
"shasum": ""
|
231 |
},
|
232 |
"require": {
|
233 |
-
"
|
234 |
-
"
|
235 |
-
"php": ">=5.5
|
236 |
},
|
237 |
"require-dev": {
|
238 |
-
"
|
239 |
-
"phpunit/phpunit": "
|
|
|
240 |
},
|
241 |
-
"
|
|
|
|
|
|
|
242 |
"type": "library",
|
243 |
"extra": {
|
244 |
"branch-alias": {
|
245 |
-
"dev-master": "
|
246 |
}
|
247 |
},
|
248 |
-
"installation-source": "
|
249 |
"autoload": {
|
|
|
|
|
|
|
250 |
"psr-4": {
|
251 |
-
"
|
252 |
}
|
253 |
},
|
254 |
"notification-url": "https://packagist.org/downloads/",
|
@@ -257,50 +296,58 @@
|
|
257 |
],
|
258 |
"authors": [
|
259 |
{
|
260 |
-
"name": "
|
261 |
-
"email": "
|
|
|
262 |
}
|
263 |
],
|
264 |
-
"description": "
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
265 |
},
|
266 |
{
|
267 |
-
"name": "
|
268 |
-
"version": "
|
269 |
-
"version_normalized": "
|
270 |
"source": {
|
271 |
"type": "git",
|
272 |
-
"url": "https://github.com/
|
273 |
-
"reference": "
|
274 |
},
|
275 |
"dist": {
|
276 |
"type": "zip",
|
277 |
-
"url": "https://api.github.com/repos/
|
278 |
-
"reference": "
|
279 |
"shasum": ""
|
280 |
},
|
281 |
"require": {
|
282 |
-
"php": ">=5.
|
283 |
},
|
284 |
"require-dev": {
|
285 |
-
"phpunit/phpunit": "
|
286 |
},
|
287 |
-
"time": "2016-12-
|
288 |
-
"bin": [
|
289 |
-
"bin/jp.php"
|
290 |
-
],
|
291 |
"type": "library",
|
292 |
"extra": {
|
293 |
"branch-alias": {
|
294 |
-
"dev-master": "
|
295 |
}
|
296 |
},
|
297 |
"installation-source": "dist",
|
298 |
"autoload": {
|
299 |
"psr-4": {
|
300 |
-
"
|
301 |
},
|
302 |
"files": [
|
303 |
-
"src/
|
304 |
]
|
305 |
},
|
306 |
"notification-url": "https://packagist.org/downloads/",
|
@@ -314,309 +361,298 @@
|
|
314 |
"homepage": "https://github.com/mtdowling"
|
315 |
}
|
316 |
],
|
317 |
-
"description": "
|
318 |
"keywords": [
|
319 |
-
"
|
320 |
-
"jsonpath"
|
321 |
]
|
322 |
},
|
323 |
{
|
324 |
-
"name": "
|
325 |
-
"version": "1.2
|
326 |
-
"version_normalized": "1.2.
|
327 |
"source": {
|
328 |
"type": "git",
|
329 |
-
"url": "https://github.com/
|
330 |
-
"reference": "
|
331 |
},
|
332 |
"dist": {
|
333 |
"type": "zip",
|
334 |
-
"url": "https://api.github.com/repos/
|
335 |
-
"reference": "
|
336 |
"shasum": ""
|
337 |
},
|
338 |
"require": {
|
339 |
-
"php": ">=5.4.
|
|
|
|
|
|
|
|
|
340 |
},
|
341 |
"require-dev": {
|
342 |
-
"phpunit/phpunit": "
|
343 |
-
"sabre/cs": "~1.0.0"
|
344 |
},
|
345 |
-
"time": "2017-
|
346 |
"type": "library",
|
347 |
-
"
|
|
|
|
|
|
|
|
|
|
|
348 |
"autoload": {
|
349 |
-
"files": [
|
350 |
-
"lib/functions.php"
|
351 |
-
],
|
352 |
"psr-4": {
|
353 |
-
"
|
354 |
-
}
|
|
|
|
|
|
|
355 |
},
|
356 |
"notification-url": "https://packagist.org/downloads/",
|
357 |
"license": [
|
358 |
-
"
|
359 |
],
|
360 |
"authors": [
|
361 |
{
|
362 |
-
"name": "
|
363 |
-
"email": "
|
364 |
-
"homepage": "
|
365 |
-
|
|
|
|
|
|
|
366 |
}
|
367 |
],
|
368 |
-
"description": "
|
369 |
-
"homepage": "http://sabre.io/uri/",
|
370 |
"keywords": [
|
371 |
-
"
|
|
|
|
|
|
|
|
|
372 |
"uri",
|
373 |
"url"
|
374 |
]
|
375 |
},
|
376 |
{
|
377 |
-
"name": "
|
378 |
-
"version": "1.
|
379 |
-
"version_normalized": "1.
|
380 |
"source": {
|
381 |
"type": "git",
|
382 |
-
"url": "https://github.com/
|
383 |
-
"reference": "
|
384 |
},
|
385 |
"dist": {
|
386 |
"type": "zip",
|
387 |
-
"url": "https://api.github.com/repos/
|
388 |
-
"reference": "
|
389 |
"shasum": ""
|
390 |
},
|
391 |
"require": {
|
392 |
-
"
|
393 |
-
|
394 |
-
|
395 |
-
"
|
396 |
-
"php": ">=5.5.5",
|
397 |
-
"sabre/uri": ">=1.0,<3.0.0"
|
398 |
},
|
399 |
"require-dev": {
|
400 |
-
"
|
401 |
-
"
|
|
|
402 |
},
|
403 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
404 |
"type": "library",
|
405 |
-
"
|
|
|
|
|
|
|
|
|
|
|
406 |
"autoload": {
|
407 |
"psr-4": {
|
408 |
-
"
|
409 |
-
}
|
410 |
-
"files": [
|
411 |
-
"lib/Deserializer/functions.php",
|
412 |
-
"lib/Serializer/functions.php"
|
413 |
-
]
|
414 |
},
|
415 |
"notification-url": "https://packagist.org/downloads/",
|
416 |
"license": [
|
417 |
-
"
|
418 |
],
|
419 |
"authors": [
|
420 |
{
|
421 |
-
"name": "
|
422 |
-
"email": "
|
423 |
-
"homepage": "http://evertpot.com/",
|
424 |
-
"role": "Developer"
|
425 |
-
},
|
426 |
-
{
|
427 |
-
"name": "Markus Staab",
|
428 |
-
"email": "markus.staab@redaxo.de",
|
429 |
-
"role": "Developer"
|
430 |
}
|
431 |
],
|
432 |
-
"description": "
|
433 |
-
"homepage": "https://sabre.io/xml/",
|
434 |
"keywords": [
|
435 |
-
"
|
436 |
-
"
|
437 |
-
"
|
438 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
439 |
]
|
440 |
},
|
441 |
{
|
442 |
-
"name": "
|
443 |
-
"version": "
|
444 |
-
"version_normalized": "
|
445 |
"source": {
|
446 |
"type": "git",
|
447 |
-
"url": "https://github.com/
|
448 |
-
"reference": "
|
449 |
},
|
450 |
"dist": {
|
451 |
"type": "zip",
|
452 |
-
"url": "https://api.github.com/repos/
|
453 |
-
"reference": "
|
454 |
"shasum": ""
|
455 |
},
|
456 |
"require": {
|
457 |
-
"php": "
|
|
|
|
|
458 |
},
|
459 |
"require-dev": {
|
460 |
-
"
|
461 |
-
"
|
462 |
},
|
463 |
-
"time": "
|
464 |
"type": "library",
|
465 |
-
"
|
|
|
|
|
|
|
|
|
|
|
466 |
"autoload": {
|
467 |
"psr-4": {
|
468 |
-
"
|
469 |
-
}
|
470 |
-
"files": [
|
471 |
-
"lib/coroutine.php",
|
472 |
-
"lib/Loop/functions.php",
|
473 |
-
"lib/Promise/functions.php"
|
474 |
-
]
|
475 |
},
|
476 |
"notification-url": "https://packagist.org/downloads/",
|
477 |
"license": [
|
478 |
-
"
|
479 |
],
|
480 |
"authors": [
|
481 |
{
|
482 |
-
"name": "
|
483 |
-
"email": "
|
484 |
-
"homepage": "http://evertpot.com/",
|
485 |
-
"role": "Developer"
|
486 |
}
|
487 |
],
|
488 |
-
"description": "
|
489 |
-
"homepage": "http://sabre.io/event/",
|
490 |
-
"keywords": [
|
491 |
-
"EventEmitter",
|
492 |
-
"async",
|
493 |
-
"events",
|
494 |
-
"hooks",
|
495 |
-
"plugin",
|
496 |
-
"promise",
|
497 |
-
"signal"
|
498 |
-
]
|
499 |
},
|
500 |
{
|
501 |
-
"name": "
|
502 |
-
"version": "
|
503 |
-
"version_normalized": "
|
504 |
"source": {
|
505 |
"type": "git",
|
506 |
-
"url": "https://github.com/
|
507 |
-
"reference": "
|
508 |
},
|
509 |
"dist": {
|
510 |
"type": "zip",
|
511 |
-
"url": "https://api.github.com/repos/
|
512 |
-
"reference": "
|
513 |
"shasum": ""
|
514 |
},
|
515 |
"require": {
|
516 |
-
"
|
517 |
-
"
|
518 |
-
"
|
519 |
-
"ext-iconv": "*",
|
520 |
-
"ext-mbstring": "*",
|
521 |
-
"ext-pcre": "*",
|
522 |
-
"ext-simplexml": "*",
|
523 |
-
"ext-spl": "*",
|
524 |
-
"lib-libxml": ">=2.7.0",
|
525 |
-
"php": ">=5.5.0",
|
526 |
-
"psr/log": "^1.0",
|
527 |
-
"sabre/event": ">=2.0.0, <4.0.0",
|
528 |
-
"sabre/http": "^4.2.1",
|
529 |
-
"sabre/uri": "^1.0.1",
|
530 |
-
"sabre/vobject": "^4.1.0",
|
531 |
-
"sabre/xml": "^1.4.0"
|
532 |
},
|
533 |
"require-dev": {
|
534 |
-
"
|
535 |
-
"
|
536 |
-
"phpunit/phpunit": "> 4.8, <6.0.0",
|
537 |
-
"sabre/cs": "^1.0.0"
|
538 |
-
},
|
539 |
-
"suggest": {
|
540 |
-
"ext-curl": "*",
|
541 |
-
"ext-pdo": "*"
|
542 |
},
|
543 |
-
"time": "
|
544 |
-
"bin": [
|
545 |
-
"bin/sabredav",
|
546 |
-
"bin/naturalselection"
|
547 |
-
],
|
548 |
"type": "library",
|
549 |
"extra": {
|
550 |
"branch-alias": {
|
551 |
-
"dev-master": "
|
552 |
}
|
553 |
},
|
554 |
"installation-source": "dist",
|
555 |
"autoload": {
|
556 |
"psr-4": {
|
557 |
-
"
|
558 |
-
"Sabre\\DAVACL\\": "lib/DAVACL/",
|
559 |
-
"Sabre\\CalDAV\\": "lib/CalDAV/",
|
560 |
-
"Sabre\\CardDAV\\": "lib/CardDAV/"
|
561 |
}
|
562 |
},
|
563 |
"notification-url": "https://packagist.org/downloads/",
|
564 |
"license": [
|
565 |
-
"
|
566 |
],
|
567 |
"authors": [
|
568 |
{
|
569 |
-
"name": "
|
570 |
-
"email": "
|
571 |
-
"homepage": "http://evertpot.com/",
|
572 |
-
"role": "Developer"
|
573 |
}
|
574 |
],
|
575 |
-
"description": "
|
576 |
-
"
|
577 |
-
"keywords": [
|
578 |
-
"CalDAV",
|
579 |
-
"CardDAV",
|
580 |
-
"WebDAV",
|
581 |
-
"framework",
|
582 |
-
"iCalendar"
|
583 |
-
]
|
584 |
},
|
585 |
{
|
586 |
-
"name": "league/flysystem-
|
587 |
-
"version": "1.0.
|
588 |
-
"version_normalized": "1.0.
|
589 |
"source": {
|
590 |
"type": "git",
|
591 |
-
"url": "https://github.com/thephpleague/flysystem-
|
592 |
-
"reference": "
|
593 |
},
|
594 |
"dist": {
|
595 |
"type": "zip",
|
596 |
-
"url": "https://api.github.com/repos/thephpleague/flysystem-
|
597 |
-
"reference": "
|
598 |
"shasum": ""
|
599 |
},
|
600 |
"require": {
|
601 |
"league/flysystem": "~1.0",
|
602 |
-
"php": ">=5.
|
603 |
-
"
|
604 |
},
|
605 |
"require-dev": {
|
606 |
-
"mockery/mockery": "
|
607 |
"phpunit/phpunit": "~4.0"
|
608 |
},
|
609 |
-
"time": "
|
610 |
"type": "library",
|
611 |
"extra": {
|
612 |
"branch-alias": {
|
613 |
"dev-master": "1.0-dev"
|
614 |
}
|
615 |
},
|
616 |
-
"installation-source": "
|
617 |
"autoload": {
|
618 |
"psr-4": {
|
619 |
-
"League\\Flysystem\\
|
620 |
}
|
621 |
},
|
622 |
"notification-url": "https://packagist.org/downloads/",
|
@@ -629,43 +665,43 @@
|
|
629 |
"email": "info@frenky.net"
|
630 |
}
|
631 |
],
|
632 |
-
"description": "Flysystem adapter for
|
633 |
},
|
634 |
{
|
635 |
-
"name": "league/flysystem-
|
636 |
-
"version": "1.0.
|
637 |
-
"version_normalized": "1.0.
|
638 |
"source": {
|
639 |
"type": "git",
|
640 |
-
"url": "https://github.com/thephpleague/flysystem-
|
641 |
-
"reference": "
|
642 |
},
|
643 |
"dist": {
|
644 |
"type": "zip",
|
645 |
-
"url": "https://api.github.com/repos/thephpleague/flysystem-
|
646 |
-
"reference": "
|
647 |
"shasum": ""
|
648 |
},
|
649 |
"require": {
|
650 |
"league/flysystem": "~1.0",
|
651 |
-
"php": ">=5.
|
652 |
-
"
|
653 |
},
|
654 |
"require-dev": {
|
655 |
-
"mockery/mockery": "0.9
|
656 |
"phpunit/phpunit": "~4.0"
|
657 |
},
|
658 |
-
"time": "
|
659 |
"type": "library",
|
660 |
"extra": {
|
661 |
"branch-alias": {
|
662 |
"dev-master": "1.0-dev"
|
663 |
}
|
664 |
},
|
665 |
-
"installation-source": "
|
666 |
"autoload": {
|
667 |
"psr-4": {
|
668 |
-
"League\\Flysystem\\
|
669 |
}
|
670 |
},
|
671 |
"notification-url": "https://packagist.org/downloads/",
|
@@ -678,47 +714,41 @@
|
|
678 |
"email": "info@frenky.net"
|
679 |
}
|
680 |
],
|
681 |
-
"description": "Flysystem adapter for
|
682 |
},
|
683 |
{
|
684 |
-
"name": "
|
685 |
-
"version": "
|
686 |
-
"version_normalized": "
|
687 |
"source": {
|
688 |
"type": "git",
|
689 |
-
"url": "https://github.com/
|
690 |
-
"reference": "
|
691 |
},
|
692 |
"dist": {
|
693 |
"type": "zip",
|
694 |
-
"url": "https://api.github.com/repos/
|
695 |
-
"reference": "
|
696 |
"shasum": ""
|
697 |
},
|
698 |
"require": {
|
699 |
-
"
|
|
|
|
|
|
|
|
|
700 |
},
|
701 |
"require-dev": {
|
702 |
-
"
|
703 |
-
"
|
704 |
-
"
|
705 |
-
"squizlabs/php_codesniffer": "~2.0"
|
706 |
-
},
|
707 |
-
"suggest": {
|
708 |
-
"ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.",
|
709 |
-
"ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.",
|
710 |
-
"ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.",
|
711 |
-
"ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations."
|
712 |
},
|
713 |
-
"time": "2018-
|
714 |
"type": "library",
|
715 |
"installation-source": "source",
|
716 |
"autoload": {
|
717 |
-
"files": [
|
718 |
-
"phpseclib/bootstrap.php"
|
719 |
-
],
|
720 |
"psr-4": {
|
721 |
-
"
|
722 |
}
|
723 |
},
|
724 |
"notification-url": "https://packagist.org/downloads/",
|
@@ -727,155 +757,130 @@
|
|
727 |
],
|
728 |
"authors": [
|
729 |
{
|
730 |
-
"name": "
|
731 |
-
"email": "
|
732 |
-
"
|
733 |
-
},
|
734 |
-
{
|
735 |
-
"name": "Patrick Monnerat",
|
736 |
-
"email": "pm@datasphere.ch",
|
737 |
-
"role": "Developer"
|
738 |
-
},
|
739 |
-
{
|
740 |
-
"name": "Andreas Fischer",
|
741 |
-
"email": "bantu@phpbb.com",
|
742 |
-
"role": "Developer"
|
743 |
-
},
|
744 |
-
{
|
745 |
-
"name": "Hans-Jürgen Petrich",
|
746 |
-
"email": "petrich@tronic-media.com",
|
747 |
-
"role": "Developer"
|
748 |
-
},
|
749 |
-
{
|
750 |
-
"name": "Graham Campbell",
|
751 |
-
"email": "graham@alt-three.com",
|
752 |
"role": "Developer"
|
753 |
}
|
754 |
],
|
755 |
-
"description": "
|
756 |
-
"homepage": "
|
757 |
"keywords": [
|
758 |
-
"
|
759 |
-
"
|
760 |
-
"
|
761 |
-
"
|
762 |
-
"
|
763 |
-
"crypto",
|
764 |
-
"cryptography",
|
765 |
-
"encryption",
|
766 |
-
"rsa",
|
767 |
-
"security",
|
768 |
-
"sftp",
|
769 |
-
"signature",
|
770 |
-
"signing",
|
771 |
-
"ssh",
|
772 |
-
"twofish",
|
773 |
-
"x.509",
|
774 |
-
"x509"
|
775 |
]
|
776 |
},
|
777 |
{
|
778 |
-
"name": "
|
779 |
-
"version": "
|
780 |
-
"version_normalized": "
|
781 |
"source": {
|
782 |
"type": "git",
|
783 |
-
"url": "https://github.com/
|
784 |
-
"reference": "
|
785 |
},
|
786 |
"dist": {
|
787 |
"type": "zip",
|
788 |
-
"url": "https://api.github.com/repos/
|
789 |
-
"reference": "
|
790 |
"shasum": ""
|
791 |
},
|
792 |
-
"
|
793 |
-
|
794 |
-
|
795 |
-
|
796 |
-
|
797 |
-
|
798 |
-
|
799 |
-
|
800 |
-
|
801 |
-
|
802 |
-
|
803 |
-
|
804 |
-
|
805 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
806 |
}
|
807 |
},
|
808 |
-
"installation-source": "source",
|
809 |
"notification-url": "https://packagist.org/downloads/",
|
810 |
"license": [
|
811 |
"MIT"
|
812 |
],
|
813 |
"authors": [
|
814 |
{
|
815 |
-
"name": "
|
|
|
816 |
}
|
817 |
],
|
818 |
-
"description": "
|
819 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
820 |
},
|
821 |
{
|
822 |
-
"name": "
|
823 |
-
"version": "
|
824 |
-
"version_normalized": "
|
825 |
"source": {
|
826 |
"type": "git",
|
827 |
-
"url": "https://github.com/
|
828 |
-
"reference": "
|
829 |
},
|
830 |
"dist": {
|
831 |
"type": "zip",
|
832 |
-
"url": "https://api.github.com/repos/
|
833 |
-
"reference": "
|
834 |
"shasum": ""
|
835 |
},
|
836 |
"require": {
|
837 |
-
"
|
838 |
},
|
839 |
-
"
|
840 |
-
"
|
841 |
},
|
842 |
-
"time": "
|
843 |
-
"type": "
|
844 |
"extra": {
|
845 |
-
"
|
846 |
-
"
|
847 |
-
"dist/jstree.js"
|
848 |
-
],
|
849 |
-
"styles": [
|
850 |
-
"dist/themes/default/style.css"
|
851 |
-
],
|
852 |
-
"images": [
|
853 |
-
"dist/themes/default/32px.png",
|
854 |
-
"dist/themes/default/40px.png",
|
855 |
-
"dist/themes/default/throbber.gif"
|
856 |
-
],
|
857 |
-
"files": [
|
858 |
-
"dist/jstree.min.js",
|
859 |
-
"dist/themes/default/style.min.css",
|
860 |
-
"dist/themes/default/32px.png",
|
861 |
-
"dist/themes/default/40px.png",
|
862 |
-
"dist/themes/default/throbber.gif"
|
863 |
-
]
|
864 |
}
|
865 |
},
|
866 |
"installation-source": "source",
|
|
|
|
|
|
|
|
|
|
|
867 |
"notification-url": "https://packagist.org/downloads/",
|
868 |
"license": [
|
869 |
-
"
|
870 |
],
|
871 |
"authors": [
|
872 |
{
|
873 |
-
"name": "
|
874 |
-
"
|
|
|
875 |
}
|
876 |
],
|
877 |
-
"description": "
|
878 |
-
"homepage": "http://
|
879 |
},
|
880 |
{
|
881 |
"name": "monolog/monolog",
|
@@ -958,44 +963,43 @@
|
|
958 |
]
|
959 |
},
|
960 |
{
|
961 |
-
"name": "
|
962 |
-
"version": "
|
963 |
-
"version_normalized": "
|
964 |
"source": {
|
965 |
"type": "git",
|
966 |
-
"url": "https://github.com/
|
967 |
-
"reference": "
|
968 |
},
|
969 |
"dist": {
|
970 |
"type": "zip",
|
971 |
-
"url": "https://api.github.com/repos/
|
972 |
-
"reference": "
|
973 |
"shasum": ""
|
974 |
},
|
975 |
"require": {
|
976 |
-
"php": ">=5.4.0"
|
977 |
-
"psr/http-message": "~1.0"
|
978 |
-
},
|
979 |
-
"provide": {
|
980 |
-
"psr/http-message-implementation": "1.0"
|
981 |
},
|
982 |
"require-dev": {
|
983 |
"phpunit/phpunit": "~4.0"
|
984 |
},
|
985 |
-
"time": "
|
|
|
|
|
|
|
986 |
"type": "library",
|
987 |
"extra": {
|
988 |
"branch-alias": {
|
989 |
-
"dev-master": "
|
990 |
}
|
991 |
},
|
992 |
-
"installation-source": "
|
993 |
"autoload": {
|
994 |
"psr-4": {
|
995 |
-
"
|
996 |
},
|
997 |
"files": [
|
998 |
-
"src/
|
999 |
]
|
1000 |
},
|
1001 |
"notification-url": "https://packagist.org/downloads/",
|
@@ -1007,66 +1011,45 @@
|
|
1007 |
"name": "Michael Dowling",
|
1008 |
"email": "mtdowling@gmail.com",
|
1009 |
"homepage": "https://github.com/mtdowling"
|
1010 |
-
},
|
1011 |
-
{
|
1012 |
-
"name": "Tobias Schultze",
|
1013 |
-
"homepage": "https://github.com/Tobion"
|
1014 |
}
|
1015 |
],
|
1016 |
-
"description": "
|
1017 |
"keywords": [
|
1018 |
-
"
|
1019 |
-
"
|
1020 |
-
"request",
|
1021 |
-
"response",
|
1022 |
-
"stream",
|
1023 |
-
"uri",
|
1024 |
-
"url"
|
1025 |
]
|
1026 |
},
|
1027 |
{
|
1028 |
-
"name": "
|
1029 |
-
"version": "
|
1030 |
-
"version_normalized": "
|
1031 |
"source": {
|
1032 |
"type": "git",
|
1033 |
-
"url": "https://github.com/
|
1034 |
-
"reference": "
|
1035 |
},
|
1036 |
"dist": {
|
1037 |
"type": "zip",
|
1038 |
-
"url": "https://api.github.com/repos/
|
1039 |
-
"reference": "
|
1040 |
"shasum": ""
|
1041 |
},
|
1042 |
"require": {
|
1043 |
-
"
|
1044 |
-
"guzzlehttp/psr7": "^1.4",
|
1045 |
-
"php": ">=5.5"
|
1046 |
},
|
1047 |
"require-dev": {
|
1048 |
-
"
|
1049 |
-
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0",
|
1050 |
-
"psr/log": "^1.0"
|
1051 |
},
|
1052 |
"suggest": {
|
1053 |
-
"
|
1054 |
},
|
1055 |
-
"time": "2018-
|
1056 |
"type": "library",
|
1057 |
-
"
|
1058 |
-
"branch-alias": {
|
1059 |
-
"dev-master": "6.3-dev"
|
1060 |
-
}
|
1061 |
-
},
|
1062 |
-
"installation-source": "source",
|
1063 |
"autoload": {
|
1064 |
"files": [
|
1065 |
-
"
|
1066 |
-
]
|
1067 |
-
"psr-4": {
|
1068 |
-
"GuzzleHttp\\": "src/"
|
1069 |
-
}
|
1070 |
},
|
1071 |
"notification-url": "https://packagist.org/downloads/",
|
1072 |
"license": [
|
@@ -1074,76 +1057,58 @@
|
|
1074 |
],
|
1075 |
"authors": [
|
1076 |
{
|
1077 |
-
"name": "
|
1078 |
-
"email": "
|
1079 |
-
"homepage": "https://
|
1080 |
}
|
1081 |
],
|
1082 |
-
"description": "
|
1083 |
-
"homepage": "http://guzzlephp.org/",
|
1084 |
"keywords": [
|
1085 |
-
"
|
1086 |
-
"
|
1087 |
-
"
|
1088 |
-
"
|
1089 |
-
"http client",
|
1090 |
-
"rest",
|
1091 |
-
"web service"
|
1092 |
]
|
1093 |
},
|
1094 |
{
|
1095 |
-
"name": "
|
1096 |
-
"version": "
|
1097 |
-
"version_normalized": "
|
1098 |
"source": {
|
1099 |
"type": "git",
|
1100 |
-
"url": "https://github.com/
|
1101 |
-
"reference": "
|
1102 |
},
|
1103 |
"dist": {
|
1104 |
"type": "zip",
|
1105 |
-
"url": "https://api.github.com/repos/
|
1106 |
-
"reference": "
|
1107 |
"shasum": ""
|
1108 |
},
|
1109 |
"require": {
|
1110 |
-
"php": ">=5.
|
1111 |
-
},
|
1112 |
-
"conflict": {
|
1113 |
-
"league/flysystem-sftp": "<1.0.6"
|
1114 |
},
|
1115 |
"require-dev": {
|
1116 |
-
"
|
1117 |
-
"
|
1118 |
-
"
|
|
|
1119 |
},
|
1120 |
"suggest": {
|
1121 |
-
"ext-
|
1122 |
-
"ext-
|
1123 |
-
"ext-
|
1124 |
-
"
|
1125 |
-
"league/flysystem-aws-s3-v3": "Allows you to use S3 storage with AWS SDK v3",
|
1126 |
-
"league/flysystem-azure": "Allows you to use Windows Azure Blob storage",
|
1127 |
-
"league/flysystem-cached-adapter": "Flysystem adapter decorator for metadata caching",
|
1128 |
-
"league/flysystem-eventable-filesystem": "Allows you to use EventableFilesystem",
|
1129 |
-
"league/flysystem-rackspace": "Allows you to use Rackspace Cloud Files",
|
1130 |
-
"league/flysystem-sftp": "Allows you to use SFTP server storage via phpseclib",
|
1131 |
-
"league/flysystem-webdav": "Allows you to use WebDAV storage",
|
1132 |
-
"league/flysystem-ziparchive": "Allows you to use ZipArchive adapter",
|
1133 |
-
"spatie/flysystem-dropbox": "Allows you to use Dropbox storage",
|
1134 |
-
"srmklive/flysystem-dropbox-v2": "Allows you to use Dropbox storage for PHP 5 applications"
|
1135 |
},
|
1136 |
-
"time": "2018-
|
1137 |
"type": "library",
|
1138 |
-
"extra": {
|
1139 |
-
"branch-alias": {
|
1140 |
-
"dev-master": "1.1-dev"
|
1141 |
-
}
|
1142 |
-
},
|
1143 |
"installation-source": "source",
|
1144 |
"autoload": {
|
|
|
|
|
|
|
1145 |
"psr-4": {
|
1146 |
-
"
|
1147 |
}
|
1148 |
},
|
1149 |
"notification-url": "https://packagist.org/downloads/",
|
@@ -1152,66 +1117,82 @@
|
|
1152 |
],
|
1153 |
"authors": [
|
1154 |
{
|
1155 |
-
"name": "
|
1156 |
-
"email": "
|
1157 |
-
|
1158 |
-
|
1159 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1160 |
"keywords": [
|
1161 |
-
"
|
1162 |
-
"
|
1163 |
-
"
|
1164 |
-
"
|
1165 |
-
"
|
1166 |
-
"
|
1167 |
-
"
|
1168 |
-
"
|
1169 |
-
"
|
1170 |
-
"
|
1171 |
-
"filesystems",
|
1172 |
-
"ftp",
|
1173 |
-
"rackspace",
|
1174 |
-
"remote",
|
1175 |
-
"s3",
|
1176 |
"sftp",
|
1177 |
-
"
|
|
|
|
|
|
|
|
|
|
|
1178 |
]
|
1179 |
},
|
1180 |
{
|
1181 |
-
"name": "
|
1182 |
-
"version": "1.0.
|
1183 |
-
"version_normalized": "1.0.
|
1184 |
"source": {
|
1185 |
"type": "git",
|
1186 |
-
"url": "https://github.com/
|
1187 |
-
"reference": "
|
1188 |
},
|
1189 |
"dist": {
|
1190 |
"type": "zip",
|
1191 |
-
"url": "https://api.github.com/repos/
|
1192 |
-
"reference": "
|
1193 |
"shasum": ""
|
1194 |
},
|
1195 |
"require": {
|
1196 |
-
"
|
1197 |
-
"league/flysystem": "^1.0.40",
|
1198 |
-
"php": ">=5.5.0"
|
1199 |
-
},
|
1200 |
-
"require-dev": {
|
1201 |
-
"henrikbjorn/phpspec-code-coverage": "~1.0.1",
|
1202 |
-
"phpspec/phpspec": "^2.0.0"
|
1203 |
},
|
1204 |
-
"time": "
|
1205 |
"type": "library",
|
1206 |
"extra": {
|
1207 |
"branch-alias": {
|
1208 |
-
"dev-master": "1.0-dev"
|
1209 |
}
|
1210 |
},
|
1211 |
-
"installation-source": "
|
1212 |
"autoload": {
|
1213 |
"psr-4": {
|
1214 |
-
"
|
1215 |
}
|
1216 |
},
|
1217 |
"notification-url": "https://packagist.org/downloads/",
|
@@ -1220,88 +1201,50 @@
|
|
1220 |
],
|
1221 |
"authors": [
|
1222 |
{
|
1223 |
-
"name": "
|
1224 |
-
"
|
1225 |
}
|
1226 |
],
|
1227 |
-
"description": "
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1228 |
},
|
1229 |
{
|
1230 |
-
"name": "
|
1231 |
-
"version": "
|
1232 |
-
"version_normalized": "1.
|
1233 |
"source": {
|
1234 |
"type": "git",
|
1235 |
-
"url": "https://github.com/
|
1236 |
-
"reference": "
|
1237 |
},
|
1238 |
"dist": {
|
1239 |
"type": "zip",
|
1240 |
-
"url": "https://api.github.com/repos/
|
1241 |
-
"reference": "
|
1242 |
"shasum": ""
|
1243 |
},
|
1244 |
"require": {
|
1245 |
"php": ">=5.3.0"
|
1246 |
},
|
1247 |
-
"
|
1248 |
-
"phpunit/phpunit": "~4.5"
|
1249 |
-
},
|
1250 |
-
"time": "2017-08-01T08:02:14+00:00",
|
1251 |
"type": "library",
|
1252 |
"extra": {
|
1253 |
"branch-alias": {
|
1254 |
-
"dev-master": "1.
|
1255 |
-
}
|
1256 |
-
},
|
1257 |
-
"installation-source": "source",
|
1258 |
-
"autoload": {
|
1259 |
-
"psr-0": {
|
1260 |
-
"org\\bovigo\\vfs\\": "src/main/php"
|
1261 |
-
}
|
1262 |
-
},
|
1263 |
-
"notification-url": "https://packagist.org/downloads/",
|
1264 |
-
"license": [
|
1265 |
-
"BSD-3-Clause"
|
1266 |
-
],
|
1267 |
-
"authors": [
|
1268 |
-
{
|
1269 |
-
"name": "Frank Kleine",
|
1270 |
-
"homepage": "http://frankkleine.de/",
|
1271 |
-
"role": "Developer"
|
1272 |
}
|
1273 |
-
],
|
1274 |
-
"description": "Virtual file system to mock the real file system in unit tests.",
|
1275 |
-
"homepage": "http://vfs.bovigo.org/"
|
1276 |
-
},
|
1277 |
-
{
|
1278 |
-
"name": "gliterd/backblaze-b2",
|
1279 |
-
"version": "0.0.3",
|
1280 |
-
"version_normalized": "0.0.3.0",
|
1281 |
-
"source": {
|
1282 |
-
"type": "git",
|
1283 |
-
"url": "https://github.com/gliterd/backblaze-b2.git",
|
1284 |
-
"reference": "eeaedb198fe10e0fb7d94ffaa9aa6ab207d7e9c6"
|
1285 |
-
},
|
1286 |
-
"dist": {
|
1287 |
-
"type": "zip",
|
1288 |
-
"url": "https://api.github.com/repos/gliterd/backblaze-b2/zipball/eeaedb198fe10e0fb7d94ffaa9aa6ab207d7e9c6",
|
1289 |
-
"reference": "eeaedb198fe10e0fb7d94ffaa9aa6ab207d7e9c6",
|
1290 |
-
"shasum": ""
|
1291 |
},
|
1292 |
-
"
|
1293 |
-
"guzzlehttp/guzzle": "^6.1",
|
1294 |
-
"php": ">=5.5.0"
|
1295 |
-
},
|
1296 |
-
"require-dev": {
|
1297 |
-
"phpunit/phpunit": "4.8.*"
|
1298 |
-
},
|
1299 |
-
"time": "2017-08-09T13:57:57+00:00",
|
1300 |
-
"type": "library",
|
1301 |
-
"installation-source": "source",
|
1302 |
"autoload": {
|
1303 |
"psr-4": {
|
1304 |
-
"
|
1305 |
}
|
1306 |
},
|
1307 |
"notification-url": "https://packagist.org/downloads/",
|
@@ -1310,131 +1253,160 @@
|
|
1310 |
],
|
1311 |
"authors": [
|
1312 |
{
|
1313 |
-
"name": "
|
1314 |
-
"
|
1315 |
-
"homepage": "https://gliterd.com",
|
1316 |
-
"role": "Developer"
|
1317 |
}
|
1318 |
],
|
1319 |
-
"description": "
|
1320 |
-
"homepage": "https://github.com/
|
1321 |
"keywords": [
|
1322 |
-
"
|
1323 |
-
"
|
1324 |
-
"
|
1325 |
-
"cloud",
|
1326 |
-
"cloud-storage",
|
1327 |
-
"filesystem",
|
1328 |
-
"storage"
|
1329 |
]
|
1330 |
},
|
1331 |
{
|
1332 |
-
"name": "
|
1333 |
-
"version": "
|
1334 |
-
"version_normalized": "
|
1335 |
"source": {
|
1336 |
"type": "git",
|
1337 |
-
"url": "https://github.com/
|
1338 |
-
"reference": "
|
1339 |
},
|
1340 |
"dist": {
|
1341 |
"type": "zip",
|
1342 |
-
"url": "https://api.github.com/repos/
|
1343 |
-
"reference": "
|
1344 |
"shasum": ""
|
1345 |
},
|
1346 |
"require": {
|
1347 |
-
"
|
1348 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1349 |
},
|
1350 |
"require-dev": {
|
1351 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1352 |
},
|
1353 |
-
"time": "
|
|
|
|
|
|
|
|
|
1354 |
"type": "library",
|
1355 |
-
"
|
|
|
|
|
|
|
|
|
|
|
1356 |
"autoload": {
|
1357 |
"psr-4": {
|
1358 |
-
"
|
|
|
|
|
|
|
1359 |
}
|
1360 |
},
|
1361 |
"notification-url": "https://packagist.org/downloads/",
|
1362 |
"license": [
|
1363 |
-
"
|
1364 |
],
|
1365 |
"authors": [
|
1366 |
{
|
1367 |
-
"name": "
|
1368 |
-
"email": "
|
1369 |
-
"homepage": "
|
|
|
1370 |
}
|
1371 |
],
|
1372 |
-
"description": "
|
1373 |
-
"homepage": "
|
1374 |
"keywords": [
|
1375 |
-
"
|
1376 |
-
"
|
1377 |
-
"
|
1378 |
-
"
|
1379 |
-
"
|
1380 |
-
"storage"
|
1381 |
]
|
1382 |
},
|
1383 |
{
|
1384 |
-
"name": "
|
1385 |
-
"version": "
|
1386 |
-
"version_normalized": "
|
1387 |
"source": {
|
1388 |
"type": "git",
|
1389 |
-
"url": "https://github.com/
|
1390 |
-
"reference": "
|
1391 |
},
|
1392 |
"dist": {
|
1393 |
"type": "zip",
|
1394 |
-
"url": "https://api.github.com/repos/
|
1395 |
-
"reference": "
|
1396 |
-
"shasum": ""
|
1397 |
-
},
|
1398 |
-
"require": {
|
1399 |
-
"
|
1400 |
-
"gliterd/backblaze-b2": "*",
|
1401 |
-
"league/flysystem": "~1.0",
|
1402 |
-
"mikey179/vfsstream": "*",
|
1403 |
-
"php": ">=5.5.0"
|
1404 |
},
|
1405 |
"require-dev": {
|
1406 |
-
"phpunit/phpunit": "
|
1407 |
-
"
|
1408 |
-
"squizlabs/php_codesniffer": "~2.3"
|
1409 |
},
|
1410 |
-
"time": "
|
1411 |
"type": "library",
|
1412 |
-
"installation-source": "
|
1413 |
"autoload": {
|
1414 |
"psr-4": {
|
1415 |
-
"
|
1416 |
-
}
|
|
|
|
|
|
|
|
|
|
|
1417 |
},
|
1418 |
"notification-url": "https://packagist.org/downloads/",
|
1419 |
"license": [
|
1420 |
-
"
|
1421 |
],
|
1422 |
"authors": [
|
1423 |
{
|
1424 |
-
"name": "
|
1425 |
-
"email": "
|
1426 |
-
"homepage": "
|
1427 |
"role": "Developer"
|
1428 |
}
|
1429 |
],
|
1430 |
-
"description": "
|
1431 |
-
"homepage": "
|
1432 |
"keywords": [
|
1433 |
-
"
|
1434 |
-
"
|
1435 |
-
"
|
1436 |
-
"
|
1437 |
-
"
|
|
|
|
|
1438 |
]
|
1439 |
},
|
1440 |
{
|
@@ -1495,6 +1467,59 @@
|
|
1495 |
"http"
|
1496 |
]
|
1497 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1498 |
{
|
1499 |
"name": "sabre/vobject",
|
1500 |
"version": "4.1.6",
|
@@ -1594,6 +1619,71 @@
|
|
1594 |
"xCard"
|
1595 |
]
|
1596 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1597 |
{
|
1598 |
"name": "splitbrain/php-archive",
|
1599 |
"version": "1.0.10",
|
@@ -1702,85 +1792,62 @@
|
|
1702 |
]
|
1703 |
},
|
1704 |
{
|
1705 |
-
"name": "
|
1706 |
-
"version": "3.
|
1707 |
-
"version_normalized": "3.
|
1708 |
"source": {
|
1709 |
"type": "git",
|
1710 |
-
"url": "https://github.com/
|
1711 |
-
"reference": "
|
1712 |
},
|
1713 |
"dist": {
|
1714 |
"type": "zip",
|
1715 |
-
"url": "https://api.github.com/repos/
|
1716 |
-
"reference": "
|
1717 |
"shasum": ""
|
1718 |
},
|
1719 |
"require": {
|
1720 |
-
"
|
1721 |
-
"ext-pcre": "*",
|
1722 |
-
"ext-simplexml": "*",
|
1723 |
-
"ext-spl": "*",
|
1724 |
-
"guzzlehttp/guzzle": "^5.3.1|^6.2.1",
|
1725 |
-
"guzzlehttp/promises": "~1.0",
|
1726 |
-
"guzzlehttp/psr7": "^1.4.1",
|
1727 |
-
"mtdowling/jmespath.php": "~2.2",
|
1728 |
-
"php": ">=5.5"
|
1729 |
-
},
|
1730 |
-
"require-dev": {
|
1731 |
-
"andrewsville/php-token-reflection": "^1.4",
|
1732 |
-
"aws/aws-php-sns-message-validator": "~1.0",
|
1733 |
-
"behat/behat": "~3.0",
|
1734 |
-
"doctrine/cache": "~1.4",
|
1735 |
-
"ext-dom": "*",
|
1736 |
-
"ext-openssl": "*",
|
1737 |
-
"nette/neon": "^2.3",
|
1738 |
-
"phpunit/phpunit": "^4.8.35|^5.4.3",
|
1739 |
-
"psr/cache": "^1.0"
|
1740 |
},
|
1741 |
"suggest": {
|
1742 |
-
"
|
1743 |
-
"doctrine/cache": "To use the DoctrineCacheAdapter",
|
1744 |
-
"ext-curl": "To send requests using cURL",
|
1745 |
-
"ext-openssl": "Allows working with CloudFront private distributions and verifying received SNS messages"
|
1746 |
},
|
1747 |
-
"time": "2018-
|
1748 |
-
"type": "
|
1749 |
"extra": {
|
1750 |
-
"
|
1751 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1752 |
}
|
1753 |
},
|
1754 |
"installation-source": "source",
|
1755 |
-
"autoload": {
|
1756 |
-
"psr-4": {
|
1757 |
-
"Aws\\": "src/"
|
1758 |
-
},
|
1759 |
-
"files": [
|
1760 |
-
"src/functions.php"
|
1761 |
-
]
|
1762 |
-
},
|
1763 |
"notification-url": "https://packagist.org/downloads/",
|
1764 |
"license": [
|
1765 |
-
"
|
1766 |
],
|
1767 |
"authors": [
|
1768 |
{
|
1769 |
-
"name": "
|
1770 |
-
"
|
1771 |
}
|
1772 |
],
|
1773 |
-
"description": "
|
1774 |
-
"homepage": "http://
|
1775 |
-
"keywords": [
|
1776 |
-
"amazon",
|
1777 |
-
"aws",
|
1778 |
-
"cloud",
|
1779 |
-
"dynamodb",
|
1780 |
-
"ec2",
|
1781 |
-
"glacier",
|
1782 |
-
"s3",
|
1783 |
-
"sdk"
|
1784 |
-
]
|
1785 |
}
|
1786 |
]
|
1 |
[
|
2 |
{
|
3 |
+
"name": "aws/aws-sdk-php",
|
4 |
+
"version": "3.56.5",
|
5 |
+
"version_normalized": "3.56.5.0",
|
6 |
"source": {
|
7 |
"type": "git",
|
8 |
+
"url": "https://github.com/aws/aws-sdk-php.git",
|
9 |
+
"reference": "d5b8f10a6e51174fab6a0222e1f0dfae2323e75d"
|
10 |
},
|
11 |
"dist": {
|
12 |
"type": "zip",
|
13 |
+
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/d5b8f10a6e51174fab6a0222e1f0dfae2323e75d",
|
14 |
+
"reference": "d5b8f10a6e51174fab6a0222e1f0dfae2323e75d",
|
15 |
"shasum": ""
|
16 |
},
|
17 |
"require": {
|
18 |
+
"ext-json": "*",
|
19 |
+
"ext-pcre": "*",
|
20 |
+
"ext-simplexml": "*",
|
21 |
+
"ext-spl": "*",
|
22 |
+
"guzzlehttp/guzzle": "^5.3.1|^6.2.1",
|
23 |
+
"guzzlehttp/promises": "~1.0",
|
24 |
+
"guzzlehttp/psr7": "^1.4.1",
|
25 |
+
"mtdowling/jmespath.php": "~2.2",
|
26 |
+
"php": ">=5.5"
|
27 |
},
|
28 |
+
"require-dev": {
|
29 |
+
"andrewsville/php-token-reflection": "^1.4",
|
30 |
+
"aws/aws-php-sns-message-validator": "~1.0",
|
31 |
+
"behat/behat": "~3.0",
|
32 |
+
"doctrine/cache": "~1.4",
|
33 |
+
"ext-dom": "*",
|
34 |
+
"ext-openssl": "*",
|
35 |
+
"nette/neon": "^2.3",
|
36 |
+
"phpunit/phpunit": "^4.8.35|^5.4.3",
|
37 |
+
"psr/cache": "^1.0"
|
38 |
+
},
|
39 |
+
"suggest": {
|
40 |
+
"aws/aws-php-sns-message-validator": "To validate incoming SNS notifications",
|
41 |
+
"doctrine/cache": "To use the DoctrineCacheAdapter",
|
42 |
+
"ext-curl": "To send requests using cURL",
|
43 |
+
"ext-openssl": "Allows working with CloudFront private distributions and verifying received SNS messages"
|
44 |
+
},
|
45 |
+
"time": "2018-05-21T20:15:18+00:00",
|
46 |
"type": "library",
|
47 |
"extra": {
|
48 |
"branch-alias": {
|
49 |
+
"dev-master": "3.0-dev"
|
50 |
}
|
51 |
},
|
52 |
+
"installation-source": "source",
|
53 |
"autoload": {
|
54 |
"psr-4": {
|
55 |
+
"Aws\\": "src/"
|
56 |
+
},
|
57 |
+
"files": [
|
58 |
+
"src/functions.php"
|
59 |
+
]
|
60 |
},
|
61 |
"notification-url": "https://packagist.org/downloads/",
|
62 |
"license": [
|
63 |
+
"Apache-2.0"
|
64 |
],
|
65 |
"authors": [
|
66 |
{
|
67 |
+
"name": "Amazon Web Services",
|
68 |
+
"homepage": "http://aws.amazon.com"
|
69 |
}
|
70 |
],
|
71 |
+
"description": "AWS SDK for PHP - Use Amazon Web Services in your PHP project",
|
72 |
+
"homepage": "http://aws.amazon.com/sdkforphp",
|
73 |
"keywords": [
|
74 |
+
"amazon",
|
75 |
+
"aws",
|
76 |
+
"cloud",
|
77 |
+
"dynamodb",
|
78 |
+
"ec2",
|
79 |
+
"glacier",
|
80 |
+
"s3",
|
81 |
+
"sdk"
|
82 |
]
|
83 |
},
|
84 |
{
|
85 |
+
"name": "components/jquery",
|
86 |
+
"version": "3.3.1",
|
87 |
+
"version_normalized": "3.3.1.0",
|
88 |
"source": {
|
89 |
"type": "git",
|
90 |
+
"url": "https://github.com/components/jquery.git",
|
91 |
+
"reference": "459648cda77875519c5da3ae1dd0ed5d170aa649"
|
92 |
},
|
93 |
"dist": {
|
94 |
"type": "zip",
|
95 |
+
"url": "https://api.github.com/repos/components/jquery/zipball/459648cda77875519c5da3ae1dd0ed5d170aa649",
|
96 |
+
"reference": "459648cda77875519c5da3ae1dd0ed5d170aa649",
|
97 |
"shasum": ""
|
98 |
},
|
99 |
+
"time": "2018-03-04T13:23:48+00:00",
|
100 |
+
"type": "component",
|
|
|
|
|
|
|
|
|
|
|
|
|
101 |
"extra": {
|
102 |
+
"component": {
|
103 |
+
"scripts": [
|
104 |
+
"jquery.js"
|
105 |
+
],
|
106 |
+
"files": [
|
107 |
+
"jquery.min.js",
|
108 |
+
"jquery.min.map",
|
109 |
+
"jquery.slim.js",
|
110 |
+
"jquery.slim.min.js",
|
111 |
+
"jquery.slim.min.map"
|
112 |
+
]
|
113 |
}
|
114 |
},
|
115 |
+
"installation-source": "source",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
116 |
"notification-url": "https://packagist.org/downloads/",
|
117 |
"license": [
|
118 |
"MIT"
|
119 |
],
|
120 |
"authors": [
|
121 |
{
|
122 |
+
"name": "JS Foundation and other contributors"
|
|
|
|
|
123 |
}
|
124 |
],
|
125 |
+
"description": "jQuery JavaScript Library",
|
126 |
+
"homepage": "http://jquery.com"
|
|
|
|
|
127 |
},
|
128 |
{
|
129 |
+
"name": "defuse/php-encryption",
|
130 |
+
"version": "v2.2.0",
|
131 |
+
"version_normalized": "2.2.0.0",
|
132 |
"source": {
|
133 |
"type": "git",
|
134 |
+
"url": "https://github.com/defuse/php-encryption.git",
|
135 |
+
"reference": "0d4d27c368ca6798bc162469e43248c363c73495"
|
136 |
},
|
137 |
"dist": {
|
138 |
"type": "zip",
|
139 |
+
"url": "https://api.github.com/repos/defuse/php-encryption/zipball/0d4d27c368ca6798bc162469e43248c363c73495",
|
140 |
+
"reference": "0d4d27c368ca6798bc162469e43248c363c73495",
|
141 |
"shasum": ""
|
142 |
},
|
143 |
"require": {
|
144 |
+
"ext-openssl": "*",
|
145 |
+
"paragonie/random_compat": "~2.0",
|
146 |
+
"php": ">=5.4.0"
|
147 |
},
|
148 |
+
"require-dev": {
|
149 |
+
"nikic/php-parser": "^2.0|^3.0|^4.0",
|
150 |
+
"phpunit/phpunit": "^4|^5"
|
|
|
|
|
|
|
151 |
},
|
152 |
+
"time": "2018-04-23T19:33:40+00:00",
|
153 |
+
"bin": [
|
154 |
+
"bin/generate-defuse-key"
|
155 |
+
],
|
156 |
+
"type": "library",
|
157 |
"installation-source": "dist",
|
158 |
"autoload": {
|
159 |
"psr-4": {
|
160 |
+
"Defuse\\Crypto\\": "src"
|
161 |
}
|
162 |
},
|
163 |
"notification-url": "https://packagist.org/downloads/",
|
166 |
],
|
167 |
"authors": [
|
168 |
{
|
169 |
+
"name": "Taylor Hornby",
|
170 |
+
"email": "taylor@defuse.ca",
|
171 |
+
"homepage": "https://defuse.ca/"
|
172 |
+
},
|
173 |
+
{
|
174 |
+
"name": "Scott Arciszewski",
|
175 |
+
"email": "info@paragonie.com",
|
176 |
+
"homepage": "https://paragonie.com"
|
177 |
}
|
178 |
],
|
179 |
+
"description": "Secure PHP Encryption Library",
|
|
|
180 |
"keywords": [
|
181 |
+
"aes",
|
182 |
+
"authenticated encryption",
|
183 |
+
"cipher",
|
184 |
+
"crypto",
|
185 |
+
"cryptography",
|
186 |
+
"encrypt",
|
187 |
+
"encryption",
|
188 |
+
"openssl",
|
189 |
+
"security",
|
190 |
+
"symmetric key cryptography"
|
191 |
]
|
192 |
},
|
193 |
{
|
194 |
+
"name": "gliterd/backblaze-b2",
|
195 |
+
"version": "1.0.4",
|
196 |
+
"version_normalized": "1.0.4.0",
|
197 |
"source": {
|
198 |
"type": "git",
|
199 |
+
"url": "https://github.com/gliterd/backblaze-b2.git",
|
200 |
+
"reference": "5427b10b93b0ba24f06f80623b502c7d1d7fcd72"
|
201 |
},
|
202 |
"dist": {
|
203 |
"type": "zip",
|
204 |
+
"url": "https://api.github.com/repos/gliterd/backblaze-b2/zipball/5427b10b93b0ba24f06f80623b502c7d1d7fcd72",
|
205 |
+
"reference": "5427b10b93b0ba24f06f80623b502c7d1d7fcd72",
|
206 |
"shasum": ""
|
207 |
},
|
208 |
"require": {
|
209 |
+
"guzzlehttp/guzzle": "^6.1",
|
210 |
"php": ">=5.5.0"
|
211 |
},
|
212 |
"require-dev": {
|
213 |
+
"phpunit/phpunit": "4.8.*",
|
214 |
+
"scrutinizer/ocular": "~1.1",
|
215 |
+
"squizlabs/php_codesniffer": "~2.3"
|
|
|
|
|
|
|
|
|
|
|
216 |
},
|
217 |
+
"time": "2018-07-03T11:52:32+00:00",
|
218 |
"type": "library",
|
219 |
+
"installation-source": "source",
|
|
|
|
|
|
|
|
|
|
|
220 |
"autoload": {
|
221 |
"psr-4": {
|
222 |
+
"BackblazeB2\\": "src/"
|
223 |
}
|
224 |
},
|
225 |
"notification-url": "https://packagist.org/downloads/",
|
228 |
],
|
229 |
"authors": [
|
230 |
{
|
231 |
+
"name": "Ramesh Mhetre",
|
232 |
+
"email": "mhetreramesh@gmail.com",
|
233 |
+
"homepage": "https://gliterd.com",
|
234 |
+
"role": "Developer"
|
235 |
}
|
236 |
],
|
237 |
+
"description": "PHP SDK for working with backblaze B2 cloud storage.",
|
238 |
+
"homepage": "https://github.com/gliterd/b2-sdk-php",
|
239 |
"keywords": [
|
240 |
+
"b2",
|
241 |
+
"backblaze",
|
242 |
+
"backup",
|
243 |
+
"cloud",
|
244 |
+
"cloud-storage",
|
245 |
+
"filesystem",
|
246 |
"storage"
|
247 |
+
]
|
|
|
248 |
},
|
249 |
{
|
250 |
+
"name": "guzzlehttp/guzzle",
|
251 |
+
"version": "6.3.3",
|
252 |
+
"version_normalized": "6.3.3.0",
|
253 |
"source": {
|
254 |
"type": "git",
|
255 |
+
"url": "https://github.com/guzzle/guzzle.git",
|
256 |
+
"reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba"
|
257 |
},
|
258 |
"dist": {
|
259 |
"type": "zip",
|
260 |
+
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/407b0cb880ace85c9b63c5f9551db498cb2d50ba",
|
261 |
+
"reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba",
|
262 |
"shasum": ""
|
263 |
},
|
264 |
"require": {
|
265 |
+
"guzzlehttp/promises": "^1.0",
|
266 |
+
"guzzlehttp/psr7": "^1.4",
|
267 |
+
"php": ">=5.5"
|
268 |
},
|
269 |
"require-dev": {
|
270 |
+
"ext-curl": "*",
|
271 |
+
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0",
|
272 |
+
"psr/log": "^1.0"
|
273 |
},
|
274 |
+
"suggest": {
|
275 |
+
"psr/log": "Required for using the Log middleware"
|
276 |
+
},
|
277 |
+
"time": "2018-04-22T15:46:56+00:00",
|
278 |
"type": "library",
|
279 |
"extra": {
|
280 |
"branch-alias": {
|
281 |
+
"dev-master": "6.3-dev"
|
282 |
}
|
283 |
},
|
284 |
+
"installation-source": "source",
|
285 |
"autoload": {
|
286 |
+
"files": [
|
287 |
+
"src/functions_include.php"
|
288 |
+
],
|
289 |
"psr-4": {
|
290 |
+
"GuzzleHttp\\": "src/"
|
291 |
}
|
292 |
},
|
293 |
"notification-url": "https://packagist.org/downloads/",
|
296 |
],
|
297 |
"authors": [
|
298 |
{
|
299 |
+
"name": "Michael Dowling",
|
300 |
+
"email": "mtdowling@gmail.com",
|
301 |
+
"homepage": "https://github.com/mtdowling"
|
302 |
}
|
303 |
],
|
304 |
+
"description": "Guzzle is a PHP HTTP client library",
|
305 |
+
"homepage": "http://guzzlephp.org/",
|
306 |
+
"keywords": [
|
307 |
+
"client",
|
308 |
+
"curl",
|
309 |
+
"framework",
|
310 |
+
"http",
|
311 |
+
"http client",
|
312 |
+
"rest",
|
313 |
+
"web service"
|
314 |
+
]
|
315 |
},
|
316 |
{
|
317 |
+
"name": "guzzlehttp/promises",
|
318 |
+
"version": "v1.3.1",
|
319 |
+
"version_normalized": "1.3.1.0",
|
320 |
"source": {
|
321 |
"type": "git",
|
322 |
+
"url": "https://github.com/guzzle/promises.git",
|
323 |
+
"reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646"
|
324 |
},
|
325 |
"dist": {
|
326 |
"type": "zip",
|
327 |
+
"url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646",
|
328 |
+
"reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646",
|
329 |
"shasum": ""
|
330 |
},
|
331 |
"require": {
|
332 |
+
"php": ">=5.5.0"
|
333 |
},
|
334 |
"require-dev": {
|
335 |
+
"phpunit/phpunit": "^4.0"
|
336 |
},
|
337 |
+
"time": "2016-12-20T10:07:11+00:00",
|
|
|
|
|
|
|
338 |
"type": "library",
|
339 |
"extra": {
|
340 |
"branch-alias": {
|
341 |
+
"dev-master": "1.4-dev"
|
342 |
}
|
343 |
},
|
344 |
"installation-source": "dist",
|
345 |
"autoload": {
|
346 |
"psr-4": {
|
347 |
+
"GuzzleHttp\\Promise\\": "src/"
|
348 |
},
|
349 |
"files": [
|
350 |
+
"src/functions_include.php"
|
351 |
]
|
352 |
},
|
353 |
"notification-url": "https://packagist.org/downloads/",
|
361 |
"homepage": "https://github.com/mtdowling"
|
362 |
}
|
363 |
],
|
364 |
+
"description": "Guzzle promises library",
|
365 |
"keywords": [
|
366 |
+
"promise"
|
|
|
367 |
]
|
368 |
},
|
369 |
{
|
370 |
+
"name": "guzzlehttp/psr7",
|
371 |
+
"version": "1.4.2",
|
372 |
+
"version_normalized": "1.4.2.0",
|
373 |
"source": {
|
374 |
"type": "git",
|
375 |
+
"url": "https://github.com/guzzle/psr7.git",
|
376 |
+
"reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c"
|
377 |
},
|
378 |
"dist": {
|
379 |
"type": "zip",
|
380 |
+
"url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c",
|
381 |
+
"reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c",
|
382 |
"shasum": ""
|
383 |
},
|
384 |
"require": {
|
385 |
+
"php": ">=5.4.0",
|
386 |
+
"psr/http-message": "~1.0"
|
387 |
+
},
|
388 |
+
"provide": {
|
389 |
+
"psr/http-message-implementation": "1.0"
|
390 |
},
|
391 |
"require-dev": {
|
392 |
+
"phpunit/phpunit": "~4.0"
|
|
|
393 |
},
|
394 |
+
"time": "2017-03-20T17:10:46+00:00",
|
395 |
"type": "library",
|
396 |
+
"extra": {
|
397 |
+
"branch-alias": {
|
398 |
+
"dev-master": "1.4-dev"
|
399 |
+
}
|
400 |
+
},
|
401 |
+
"installation-source": "source",
|
402 |
"autoload": {
|
|
|
|
|
|
|
403 |
"psr-4": {
|
404 |
+
"GuzzleHttp\\Psr7\\": "src/"
|
405 |
+
},
|
406 |
+
"files": [
|
407 |
+
"src/functions_include.php"
|
408 |
+
]
|
409 |
},
|
410 |
"notification-url": "https://packagist.org/downloads/",
|
411 |
"license": [
|
412 |
+
"MIT"
|
413 |
],
|
414 |
"authors": [
|
415 |
{
|
416 |
+
"name": "Michael Dowling",
|
417 |
+
"email": "mtdowling@gmail.com",
|
418 |
+
"homepage": "https://github.com/mtdowling"
|
419 |
+
},
|
420 |
+
{
|
421 |
+
"name": "Tobias Schultze",
|
422 |
+
"homepage": "https://github.com/Tobion"
|
423 |
}
|
424 |
],
|
425 |
+
"description": "PSR-7 message implementation that also provides common utility methods",
|
|
|
426 |
"keywords": [
|
427 |
+
"http",
|
428 |
+
"message",
|
429 |
+
"request",
|
430 |
+
"response",
|
431 |
+
"stream",
|
432 |
"uri",
|
433 |
"url"
|
434 |
]
|
435 |
},
|
436 |
{
|
437 |
+
"name": "league/flysystem",
|
438 |
+
"version": "1.0.45",
|
439 |
+
"version_normalized": "1.0.45.0",
|
440 |
"source": {
|
441 |
"type": "git",
|
442 |
+
"url": "https://github.com/thephpleague/flysystem.git",
|
443 |
+
"reference": "a99f94e63b512d75f851b181afcdf0ee9ebef7e6"
|
444 |
},
|
445 |
"dist": {
|
446 |
"type": "zip",
|
447 |
+
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/a99f94e63b512d75f851b181afcdf0ee9ebef7e6",
|
448 |
+
"reference": "a99f94e63b512d75f851b181afcdf0ee9ebef7e6",
|
449 |
"shasum": ""
|
450 |
},
|
451 |
"require": {
|
452 |
+
"php": ">=5.5.9"
|
453 |
+
},
|
454 |
+
"conflict": {
|
455 |
+
"league/flysystem-sftp": "<1.0.6"
|
|
|
|
|
456 |
},
|
457 |
"require-dev": {
|
458 |
+
"ext-fileinfo": "*",
|
459 |
+
"phpspec/phpspec": "^3.4",
|
460 |
+
"phpunit/phpunit": "^5.7"
|
461 |
},
|
462 |
+
"suggest": {
|
463 |
+
"ext-fileinfo": "Required for MimeType",
|
464 |
+
"ext-ftp": "Allows you to use FTP server storage",
|
465 |
+
"ext-openssl": "Allows you to use FTPS server storage",
|
466 |
+
"league/flysystem-aws-s3-v2": "Allows you to use S3 storage with AWS SDK v2",
|
467 |
+
"league/flysystem-aws-s3-v3": "Allows you to use S3 storage with AWS SDK v3",
|
468 |
+
"league/flysystem-azure": "Allows you to use Windows Azure Blob storage",
|
469 |
+
"league/flysystem-cached-adapter": "Flysystem adapter decorator for metadata caching",
|
470 |
+
"league/flysystem-eventable-filesystem": "Allows you to use EventableFilesystem",
|
471 |
+
"league/flysystem-rackspace": "Allows you to use Rackspace Cloud Files",
|
472 |
+
"league/flysystem-sftp": "Allows you to use SFTP server storage via phpseclib",
|
473 |
+
"league/flysystem-webdav": "Allows you to use WebDAV storage",
|
474 |
+
"league/flysystem-ziparchive": "Allows you to use ZipArchive adapter",
|
475 |
+
"spatie/flysystem-dropbox": "Allows you to use Dropbox storage",
|
476 |
+
"srmklive/flysystem-dropbox-v2": "Allows you to use Dropbox storage for PHP 5 applications"
|
477 |
+
},
|
478 |
+
"time": "2018-05-07T08:44:23+00:00",
|
479 |
"type": "library",
|
480 |
+
"extra": {
|
481 |
+
"branch-alias": {
|
482 |
+
"dev-master": "1.1-dev"
|
483 |
+
}
|
484 |
+
},
|
485 |
+
"installation-source": "source",
|
486 |
"autoload": {
|
487 |
"psr-4": {
|
488 |
+
"League\\Flysystem\\": "src/"
|
489 |
+
}
|
|
|
|
|
|
|
|
|
490 |
},
|
491 |
"notification-url": "https://packagist.org/downloads/",
|
492 |
"license": [
|
493 |
+
"MIT"
|
494 |
],
|
495 |
"authors": [
|
496 |
{
|
497 |
+
"name": "Frank de Jonge",
|
498 |
+
"email": "info@frenky.net"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
499 |
}
|
500 |
],
|
501 |
+
"description": "Filesystem abstraction: Many filesystems, one API.",
|
|
|
502 |
"keywords": [
|
503 |
+
"Cloud Files",
|
504 |
+
"WebDAV",
|
505 |
+
"abstraction",
|
506 |
+
"aws",
|
507 |
+
"cloud",
|
508 |
+
"copy.com",
|
509 |
+
"dropbox",
|
510 |
+
"file systems",
|
511 |
+
"files",
|
512 |
+
"filesystem",
|
513 |
+
"filesystems",
|
514 |
+
"ftp",
|
515 |
+
"rackspace",
|
516 |
+
"remote",
|
517 |
+
"s3",
|
518 |
+
"sftp",
|
519 |
+
"storage"
|
520 |
]
|
521 |
},
|
522 |
{
|
523 |
+
"name": "league/flysystem-aws-s3-v3",
|
524 |
+
"version": "1.0.19",
|
525 |
+
"version_normalized": "1.0.19.0",
|
526 |
"source": {
|
527 |
"type": "git",
|
528 |
+
"url": "https://github.com/thephpleague/flysystem-aws-s3-v3.git",
|
529 |
+
"reference": "f135691ef6761542af301b7c9880f140fb12dc74"
|
530 |
},
|
531 |
"dist": {
|
532 |
"type": "zip",
|
533 |
+
"url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/f135691ef6761542af301b7c9880f140fb12dc74",
|
534 |
+
"reference": "f135691ef6761542af301b7c9880f140fb12dc74",
|
535 |
"shasum": ""
|
536 |
},
|
537 |
"require": {
|
538 |
+
"aws/aws-sdk-php": "^3.0.0",
|
539 |
+
"league/flysystem": "^1.0.40",
|
540 |
+
"php": ">=5.5.0"
|
541 |
},
|
542 |
"require-dev": {
|
543 |
+
"henrikbjorn/phpspec-code-coverage": "~1.0.1",
|
544 |
+
"phpspec/phpspec": "^2.0.0"
|
545 |
},
|
546 |
+
"time": "2018-03-27T20:33:59+00:00",
|
547 |
"type": "library",
|
548 |
+
"extra": {
|
549 |
+
"branch-alias": {
|
550 |
+
"dev-master": "1.0-dev"
|
551 |
+
}
|
552 |
+
},
|
553 |
+
"installation-source": "source",
|
554 |
"autoload": {
|
555 |
"psr-4": {
|
556 |
+
"League\\Flysystem\\AwsS3v3\\": "src/"
|
557 |
+
}
|
|
|
|
|
|
|
|
|
|
|
558 |
},
|
559 |
"notification-url": "https://packagist.org/downloads/",
|
560 |
"license": [
|
561 |
+
"MIT"
|
562 |
],
|
563 |
"authors": [
|
564 |
{
|
565 |
+
"name": "Frank de Jonge",
|
566 |
+
"email": "info@frenky.net"
|
|
|
|
|
567 |
}
|
568 |
],
|
569 |
+
"description": "Flysystem adapter for the AWS S3 SDK v3.x"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
570 |
},
|
571 |
{
|
572 |
+
"name": "league/flysystem-azure",
|
573 |
+
"version": "1.0.4",
|
574 |
+
"version_normalized": "1.0.4.0",
|
575 |
"source": {
|
576 |
"type": "git",
|
577 |
+
"url": "https://github.com/thephpleague/flysystem-azure.git",
|
578 |
+
"reference": "0b9838c4f75ee41bc390357b0350e9a62e3b3a1f"
|
579 |
},
|
580 |
"dist": {
|
581 |
"type": "zip",
|
582 |
+
"url": "https://api.github.com/repos/thephpleague/flysystem-azure/zipball/0b9838c4f75ee41bc390357b0350e9a62e3b3a1f",
|
583 |
+
"reference": "0b9838c4f75ee41bc390357b0350e9a62e3b3a1f",
|
584 |
"shasum": ""
|
585 |
},
|
586 |
"require": {
|
587 |
+
"league/flysystem": "~1.0",
|
588 |
+
"microsoft/azure-storage": "~0.10.1",
|
589 |
+
"php": ">=5.5.0"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
590 |
},
|
591 |
"require-dev": {
|
592 |
+
"mockery/mockery": "~0.9",
|
593 |
+
"phpunit/phpunit": "~4.0"
|
|
|
|
|
|
|
|
|
|
|
|
|
594 |
},
|
595 |
+
"time": "2016-07-10T19:08:39+00:00",
|
|
|
|
|
|
|
|
|
596 |
"type": "library",
|
597 |
"extra": {
|
598 |
"branch-alias": {
|
599 |
+
"dev-master": "1.0-dev"
|
600 |
}
|
601 |
},
|
602 |
"installation-source": "dist",
|
603 |
"autoload": {
|
604 |
"psr-4": {
|
605 |
+
"League\\Flysystem\\Azure\\": "src/"
|
|
|
|
|
|
|
606 |
}
|
607 |
},
|
608 |
"notification-url": "https://packagist.org/downloads/",
|
609 |
"license": [
|
610 |
+
"MIT"
|
611 |
],
|
612 |
"authors": [
|
613 |
{
|
614 |
+
"name": "Frank de Jonge",
|
615 |
+
"email": "info@frenky.net"
|
|
|
|
|
616 |
}
|
617 |
],
|
618 |
+
"description": "Flysystem adapter for Windows Azure",
|
619 |
+
"abandoned": "league/flysystem-azure-blob-storage"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
620 |
},
|
621 |
{
|
622 |
+
"name": "league/flysystem-sftp",
|
623 |
+
"version": "1.0.14",
|
624 |
+
"version_normalized": "1.0.14.0",
|
625 |
"source": {
|
626 |
"type": "git",
|
627 |
+
"url": "https://github.com/thephpleague/flysystem-sftp.git",
|
628 |
+
"reference": "f28d742a3e81258417293fd9a179a350154ab8f7"
|
629 |
},
|
630 |
"dist": {
|
631 |
"type": "zip",
|
632 |
+
"url": "https://api.github.com/repos/thephpleague/flysystem-sftp/zipball/f28d742a3e81258417293fd9a179a350154ab8f7",
|
633 |
+
"reference": "f28d742a3e81258417293fd9a179a350154ab8f7",
|
634 |
"shasum": ""
|
635 |
},
|
636 |
"require": {
|
637 |
"league/flysystem": "~1.0",
|
638 |
+
"php": ">=5.4.0",
|
639 |
+
"phpseclib/phpseclib": "~2.0"
|
640 |
},
|
641 |
"require-dev": {
|
642 |
+
"mockery/mockery": "0.9.*",
|
643 |
"phpunit/phpunit": "~4.0"
|
644 |
},
|
645 |
+
"time": "2017-07-11T12:29:45+00:00",
|
646 |
"type": "library",
|
647 |
"extra": {
|
648 |
"branch-alias": {
|
649 |
"dev-master": "1.0-dev"
|
650 |
}
|
651 |
},
|
652 |
+
"installation-source": "source",
|
653 |
"autoload": {
|
654 |
"psr-4": {
|
655 |
+
"League\\Flysystem\\Sftp\\": "src/"
|
656 |
}
|
657 |
},
|
658 |
"notification-url": "https://packagist.org/downloads/",
|
665 |
"email": "info@frenky.net"
|
666 |
}
|
667 |
],
|
668 |
+
"description": "Flysystem adapter for SFTP"
|
669 |
},
|
670 |
{
|
671 |
+
"name": "league/flysystem-webdav",
|
672 |
+
"version": "1.0.5",
|
673 |
+
"version_normalized": "1.0.5.0",
|
674 |
"source": {
|
675 |
"type": "git",
|
676 |
+
"url": "https://github.com/thephpleague/flysystem-webdav.git",
|
677 |
+
"reference": "5fb6f5a45e5f2a5519a26032d98ad7d7c65f81d7"
|
678 |
},
|
679 |
"dist": {
|
680 |
"type": "zip",
|
681 |
+
"url": "https://api.github.com/repos/thephpleague/flysystem-webdav/zipball/5fb6f5a45e5f2a5519a26032d98ad7d7c65f81d7",
|
682 |
+
"reference": "5fb6f5a45e5f2a5519a26032d98ad7d7c65f81d7",
|
683 |
"shasum": ""
|
684 |
},
|
685 |
"require": {
|
686 |
"league/flysystem": "~1.0",
|
687 |
+
"php": ">=5.5.0",
|
688 |
+
"sabre/dav": "~3.1"
|
689 |
},
|
690 |
"require-dev": {
|
691 |
+
"mockery/mockery": "~0.9",
|
692 |
"phpunit/phpunit": "~4.0"
|
693 |
},
|
694 |
+
"time": "2016-12-14T11:28:55+00:00",
|
695 |
"type": "library",
|
696 |
"extra": {
|
697 |
"branch-alias": {
|
698 |
"dev-master": "1.0-dev"
|
699 |
}
|
700 |
},
|
701 |
+
"installation-source": "dist",
|
702 |
"autoload": {
|
703 |
"psr-4": {
|
704 |
+
"League\\Flysystem\\WebDAV\\": "src"
|
705 |
}
|
706 |
},
|
707 |
"notification-url": "https://packagist.org/downloads/",
|
714 |
"email": "info@frenky.net"
|
715 |
}
|
716 |
],
|
717 |
+
"description": "Flysystem adapter for WebDAV"
|
718 |
},
|
719 |
{
|
720 |
+
"name": "mhetreramesh/flysystem-backblaze",
|
721 |
+
"version": "1.1.4",
|
722 |
+
"version_normalized": "1.1.4.0",
|
723 |
"source": {
|
724 |
"type": "git",
|
725 |
+
"url": "https://github.com/gliterd/flysystem-backblaze.git",
|
726 |
+
"reference": "bce0372dfe40baa1e16b54e93c3400a568059070"
|
727 |
},
|
728 |
"dist": {
|
729 |
"type": "zip",
|
730 |
+
"url": "https://api.github.com/repos/gliterd/flysystem-backblaze/zipball/bce0372dfe40baa1e16b54e93c3400a568059070",
|
731 |
+
"reference": "bce0372dfe40baa1e16b54e93c3400a568059070",
|
732 |
"shasum": ""
|
733 |
},
|
734 |
"require": {
|
735 |
+
"gliterd/backblaze-b2": "*",
|
736 |
+
"league/flysystem": "~1.0",
|
737 |
+
"mikey179/vfsstream": "*",
|
738 |
+
"php": ">=5.6.0",
|
739 |
+
"psr/http-message-implementation": "*"
|
740 |
},
|
741 |
"require-dev": {
|
742 |
+
"phpunit/phpunit": "~4.0||~5.0",
|
743 |
+
"scrutinizer/ocular": "~1.1",
|
744 |
+
"squizlabs/php_codesniffer": "~2.3"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
745 |
},
|
746 |
+
"time": "2018-06-29T12:06:41+00:00",
|
747 |
"type": "library",
|
748 |
"installation-source": "source",
|
749 |
"autoload": {
|
|
|
|
|
|
|
750 |
"psr-4": {
|
751 |
+
"Mhetreramesh\\Flysystem\\": "src"
|
752 |
}
|
753 |
},
|
754 |
"notification-url": "https://packagist.org/downloads/",
|
757 |
],
|
758 |
"authors": [
|
759 |
{
|
760 |
+
"name": "Ramesh Mhetre",
|
761 |
+
"email": "mhetreramesh@gmail.com",
|
762 |
+
"homepage": "https://about.me/rameshmhetre",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
763 |
"role": "Developer"
|
764 |
}
|
765 |
],
|
766 |
+
"description": "Backblaze adapter for the flysystem filesystem abstraction library",
|
767 |
+
"homepage": "https://github.com/mhetreramesh/flysystem-backblaze",
|
768 |
"keywords": [
|
769 |
+
"Flysystem",
|
770 |
+
"api",
|
771 |
+
"backblaze",
|
772 |
+
"client",
|
773 |
+
"filesystem"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
774 |
]
|
775 |
},
|
776 |
{
|
777 |
+
"name": "microsoft/azure-storage",
|
778 |
+
"version": "v0.10.2",
|
779 |
+
"version_normalized": "0.10.2.0",
|
780 |
"source": {
|
781 |
"type": "git",
|
782 |
+
"url": "https://github.com/Azure/azure-storage-php.git",
|
783 |
+
"reference": "27de05b00c1858d6e1c6adbc489efa90e0342f82"
|
784 |
},
|
785 |
"dist": {
|
786 |
"type": "zip",
|
787 |
+
"url": "https://api.github.com/repos/Azure/azure-storage-php/zipball/27de05b00c1858d6e1c6adbc489efa90e0342f82",
|
788 |
+
"reference": "27de05b00c1858d6e1c6adbc489efa90e0342f82",
|
789 |
"shasum": ""
|
790 |
},
|
791 |
+
"require": {
|
792 |
+
"guzzlehttp/guzzle": "~6.0",
|
793 |
+
"php": ">=5.5.0"
|
794 |
+
},
|
795 |
+
"require-dev": {
|
796 |
+
"mikey179/vfsstream": "~1.6",
|
797 |
+
"pdepend/pdepend": "~2.2",
|
798 |
+
"phploc/phploc": "~2.1",
|
799 |
+
"phpmd/phpmd": "@stable",
|
800 |
+
"phpunit/phpunit": "~4.0",
|
801 |
+
"sebastian/phpcpd": "~2.0",
|
802 |
+
"squizlabs/php_codesniffer": "2.*",
|
803 |
+
"theseer/phpdox": "~0.8"
|
804 |
+
},
|
805 |
+
"time": "2016-08-19T08:32:57+00:00",
|
806 |
+
"type": "library",
|
807 |
+
"extra": {
|
808 |
+
"branch-alias": {
|
809 |
+
"dev-master": "0.10.x-dev"
|
810 |
+
}
|
811 |
+
},
|
812 |
+
"installation-source": "dist",
|
813 |
+
"autoload": {
|
814 |
+
"psr-4": {
|
815 |
+
"MicrosoftAzure\\Storage\\": "src/"
|
816 |
}
|
817 |
},
|
|
|
818 |
"notification-url": "https://packagist.org/downloads/",
|
819 |
"license": [
|
820 |
"MIT"
|
821 |
],
|
822 |
"authors": [
|
823 |
{
|
824 |
+
"name": "Azure Storage PHP SDK",
|
825 |
+
"email": "dmsh@microsoft.com"
|
826 |
}
|
827 |
],
|
828 |
+
"description": "This project provides a set of PHP client libraries that make it easy to access Microsoft Azure storage APIs.",
|
829 |
+
"keywords": [
|
830 |
+
"azure",
|
831 |
+
"php",
|
832 |
+
"sdk",
|
833 |
+
"storage"
|
834 |
+
],
|
835 |
+
"abandoned": "microsoft/azure-storage-blob, microsoft/azure-storage-table, microsoft/azure-storage-queue, microsoft/azure-storage-file"
|
836 |
},
|
837 |
{
|
838 |
+
"name": "mikey179/vfsStream",
|
839 |
+
"version": "v1.6.5",
|
840 |
+
"version_normalized": "1.6.5.0",
|
841 |
"source": {
|
842 |
"type": "git",
|
843 |
+
"url": "https://github.com/mikey179/vfsStream.git",
|
844 |
+
"reference": "d5fec95f541d4d71c4823bb5e30cf9b9e5b96145"
|
845 |
},
|
846 |
"dist": {
|
847 |
"type": "zip",
|
848 |
+
"url": "https://api.github.com/repos/mikey179/vfsStream/zipball/d5fec95f541d4d71c4823bb5e30cf9b9e5b96145",
|
849 |
+
"reference": "d5fec95f541d4d71c4823bb5e30cf9b9e5b96145",
|
850 |
"shasum": ""
|
851 |
},
|
852 |
"require": {
|
853 |
+
"php": ">=5.3.0"
|
854 |
},
|
855 |
+
"require-dev": {
|
856 |
+
"phpunit/phpunit": "~4.5"
|
857 |
},
|
858 |
+
"time": "2017-08-01T08:02:14+00:00",
|
859 |
+
"type": "library",
|
860 |
"extra": {
|
861 |
+
"branch-alias": {
|
862 |
+
"dev-master": "1.6.x-dev"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
863 |
}
|
864 |
},
|
865 |
"installation-source": "source",
|
866 |
+
"autoload": {
|
867 |
+
"psr-0": {
|
868 |
+
"org\\bovigo\\vfs\\": "src/main/php"
|
869 |
+
}
|
870 |
+
},
|
871 |
"notification-url": "https://packagist.org/downloads/",
|
872 |
"license": [
|
873 |
+
"BSD-3-Clause"
|
874 |
],
|
875 |
"authors": [
|
876 |
{
|
877 |
+
"name": "Frank Kleine",
|
878 |
+
"homepage": "http://frankkleine.de/",
|
879 |
+
"role": "Developer"
|
880 |
}
|
881 |
],
|
882 |
+
"description": "Virtual file system to mock the real file system in unit tests.",
|
883 |
+
"homepage": "http://vfs.bovigo.org/"
|
884 |
},
|
885 |
{
|
886 |
"name": "monolog/monolog",
|
963 |
]
|
964 |
},
|
965 |
{
|
966 |
+
"name": "mtdowling/jmespath.php",
|
967 |
+
"version": "2.4.0",
|
968 |
+
"version_normalized": "2.4.0.0",
|
969 |
"source": {
|
970 |
"type": "git",
|
971 |
+
"url": "https://github.com/jmespath/jmespath.php.git",
|
972 |
+
"reference": "adcc9531682cf87dfda21e1fd5d0e7a41d292fac"
|
973 |
},
|
974 |
"dist": {
|
975 |
"type": "zip",
|
976 |
+
"url": "https://api.github.com/repos/jmespath/jmespath.php/zipball/adcc9531682cf87dfda21e1fd5d0e7a41d292fac",
|
977 |
+
"reference": "adcc9531682cf87dfda21e1fd5d0e7a41d292fac",
|
978 |
"shasum": ""
|
979 |
},
|
980 |
"require": {
|
981 |
+
"php": ">=5.4.0"
|
|
|
|
|
|
|
|
|
982 |
},
|
983 |
"require-dev": {
|
984 |
"phpunit/phpunit": "~4.0"
|
985 |
},
|
986 |
+
"time": "2016-12-03T22:08:25+00:00",
|
987 |
+
"bin": [
|
988 |
+
"bin/jp.php"
|
989 |
+
],
|
990 |
"type": "library",
|
991 |
"extra": {
|
992 |
"branch-alias": {
|
993 |
+
"dev-master": "2.0-dev"
|
994 |
}
|
995 |
},
|
996 |
+
"installation-source": "dist",
|
997 |
"autoload": {
|
998 |
"psr-4": {
|
999 |
+
"JmesPath\\": "src/"
|
1000 |
},
|
1001 |
"files": [
|
1002 |
+
"src/JmesPath.php"
|
1003 |
]
|
1004 |
},
|
1005 |
"notification-url": "https://packagist.org/downloads/",
|
1011 |
"name": "Michael Dowling",
|
1012 |
"email": "mtdowling@gmail.com",
|
1013 |
"homepage": "https://github.com/mtdowling"
|
|
|
|
|
|
|
|
|
1014 |
}
|
1015 |
],
|
1016 |
+
"description": "Declaratively specify how to extract elements from a JSON document",
|
1017 |
"keywords": [
|
1018 |
+
"json",
|
1019 |
+
"jsonpath"
|
|
|
|
|
|
|
|
|
|
|
1020 |
]
|
1021 |
},
|
1022 |
{
|
1023 |
+
"name": "paragonie/random_compat",
|
1024 |
+
"version": "v2.0.15",
|
1025 |
+
"version_normalized": "2.0.15.0",
|
1026 |
"source": {
|
1027 |
"type": "git",
|
1028 |
+
"url": "https://github.com/paragonie/random_compat.git",
|
1029 |
+
"reference": "10bcb46e8f3d365170f6de9d05245aa066b81f09"
|
1030 |
},
|
1031 |
"dist": {
|
1032 |
"type": "zip",
|
1033 |
+
"url": "https://api.github.com/repos/paragonie/random_compat/zipball/10bcb46e8f3d365170f6de9d05245aa066b81f09",
|
1034 |
+
"reference": "10bcb46e8f3d365170f6de9d05245aa066b81f09",
|
1035 |
"shasum": ""
|
1036 |
},
|
1037 |
"require": {
|
1038 |
+
"php": ">=5.2.0"
|
|
|
|
|
1039 |
},
|
1040 |
"require-dev": {
|
1041 |
+
"phpunit/phpunit": "4.*|5.*"
|
|
|
|
|
1042 |
},
|
1043 |
"suggest": {
|
1044 |
+
"ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
|
1045 |
},
|
1046 |
+
"time": "2018-06-08T15:26:40+00:00",
|
1047 |
"type": "library",
|
1048 |
+
"installation-source": "dist",
|
|
|
|
|
|
|
|
|
|
|
1049 |
"autoload": {
|
1050 |
"files": [
|
1051 |
+
"lib/random.php"
|
1052 |
+
]
|
|
|
|
|
|
|
1053 |
},
|
1054 |
"notification-url": "https://packagist.org/downloads/",
|
1055 |
"license": [
|
1057 |
],
|
1058 |
"authors": [
|
1059 |
{
|
1060 |
+
"name": "Paragon Initiative Enterprises",
|
1061 |
+
"email": "security@paragonie.com",
|
1062 |
+
"homepage": "https://paragonie.com"
|
1063 |
}
|
1064 |
],
|
1065 |
+
"description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
|
|
|
1066 |
"keywords": [
|
1067 |
+
"csprng",
|
1068 |
+
"polyfill",
|
1069 |
+
"pseudorandom",
|
1070 |
+
"random"
|
|
|
|
|
|
|
1071 |
]
|
1072 |
},
|
1073 |
{
|
1074 |
+
"name": "phpseclib/phpseclib",
|
1075 |
+
"version": "2.0.11",
|
1076 |
+
"version_normalized": "2.0.11.0",
|
1077 |
"source": {
|
1078 |
"type": "git",
|
1079 |
+
"url": "https://github.com/phpseclib/phpseclib.git",
|
1080 |
+
"reference": "7053f06f91b3de78e143d430e55a8f7889efc08b"
|
1081 |
},
|
1082 |
"dist": {
|
1083 |
"type": "zip",
|
1084 |
+
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/7053f06f91b3de78e143d430e55a8f7889efc08b",
|
1085 |
+
"reference": "7053f06f91b3de78e143d430e55a8f7889efc08b",
|
1086 |
"shasum": ""
|
1087 |
},
|
1088 |
"require": {
|
1089 |
+
"php": ">=5.3.3"
|
|
|
|
|
|
|
1090 |
},
|
1091 |
"require-dev": {
|
1092 |
+
"phing/phing": "~2.7",
|
1093 |
+
"phpunit/phpunit": "^4.8.35|^5.7|^6.0",
|
1094 |
+
"sami/sami": "~2.0",
|
1095 |
+
"squizlabs/php_codesniffer": "~2.0"
|
1096 |
},
|
1097 |
"suggest": {
|
1098 |
+
"ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.",
|
1099 |
+
"ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.",
|
1100 |
+
"ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.",
|
1101 |
+
"ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1102 |
},
|
1103 |
+
"time": "2018-04-15T16:55:05+00:00",
|
1104 |
"type": "library",
|
|
|
|
|
|
|
|
|
|
|
1105 |
"installation-source": "source",
|
1106 |
"autoload": {
|
1107 |
+
"files": [
|
1108 |
+
"phpseclib/bootstrap.php"
|
1109 |
+
],
|
1110 |
"psr-4": {
|
1111 |
+
"phpseclib\\": "phpseclib/"
|
1112 |
}
|
1113 |
},
|
1114 |
"notification-url": "https://packagist.org/downloads/",
|
1117 |
],
|
1118 |
"authors": [
|
1119 |
{
|
1120 |
+
"name": "Jim Wigginton",
|
1121 |
+
"email": "terrafrost@php.net",
|
1122 |
+
"role": "Lead Developer"
|
1123 |
+
},
|
1124 |
+
{
|
1125 |
+
"name": "Patrick Monnerat",
|
1126 |
+
"email": "pm@datasphere.ch",
|
1127 |
+
"role": "Developer"
|
1128 |
+
},
|
1129 |
+
{
|
1130 |
+
"name": "Andreas Fischer",
|
1131 |
+
"email": "bantu@phpbb.com",
|
1132 |
+
"role": "Developer"
|
1133 |
+
},
|
1134 |
+
{
|
1135 |
+
"name": "Hans-Jürgen Petrich",
|
1136 |
+
"email": "petrich@tronic-media.com",
|
1137 |
+
"role": "Developer"
|
1138 |
+
},
|
1139 |
+
{
|
1140 |
+
"name": "Graham Campbell",
|
1141 |
+
"email": "graham@alt-three.com",
|
1142 |
+
"role": "Developer"
|
1143 |
+
}
|
1144 |
+
],
|
1145 |
+
"description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.",
|
1146 |
+
"homepage": "http://phpseclib.sourceforge.net",
|
1147 |
"keywords": [
|
1148 |
+
"BigInteger",
|
1149 |
+
"aes",
|
1150 |
+
"asn.1",
|
1151 |
+
"asn1",
|
1152 |
+
"blowfish",
|
1153 |
+
"crypto",
|
1154 |
+
"cryptography",
|
1155 |
+
"encryption",
|
1156 |
+
"rsa",
|
1157 |
+
"security",
|
|
|
|
|
|
|
|
|
|
|
1158 |
"sftp",
|
1159 |
+
"signature",
|
1160 |
+
"signing",
|
1161 |
+
"ssh",
|
1162 |
+
"twofish",
|
1163 |
+
"x.509",
|
1164 |
+
"x509"
|
1165 |
]
|
1166 |
},
|
1167 |
{
|
1168 |
+
"name": "psr/http-message",
|
1169 |
+
"version": "1.0.1",
|
1170 |
+
"version_normalized": "1.0.1.0",
|
1171 |
"source": {
|
1172 |
"type": "git",
|
1173 |
+
"url": "https://github.com/php-fig/http-message.git",
|
1174 |
+
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
|
1175 |
},
|
1176 |
"dist": {
|
1177 |
"type": "zip",
|
1178 |
+
"url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
|
1179 |
+
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
|
1180 |
"shasum": ""
|
1181 |
},
|
1182 |
"require": {
|
1183 |
+
"php": ">=5.3.0"
|
|
|
|
|
|
|
|
|
|
|
|
|
1184 |
},
|
1185 |
+
"time": "2016-08-06T14:39:51+00:00",
|
1186 |
"type": "library",
|
1187 |
"extra": {
|
1188 |
"branch-alias": {
|
1189 |
+
"dev-master": "1.0.x-dev"
|
1190 |
}
|
1191 |
},
|
1192 |
+
"installation-source": "dist",
|
1193 |
"autoload": {
|
1194 |
"psr-4": {
|
1195 |
+
"Psr\\Http\\Message\\": "src/"
|
1196 |
}
|
1197 |
},
|
1198 |
"notification-url": "https://packagist.org/downloads/",
|
1201 |
],
|
1202 |
"authors": [
|
1203 |
{
|
1204 |
+
"name": "PHP-FIG",
|
1205 |
+
"homepage": "http://www.php-fig.org/"
|
1206 |
}
|
1207 |
],
|
1208 |
+
"description": "Common interface for HTTP messages",
|
1209 |
+
"homepage": "https://github.com/php-fig/http-message",
|
1210 |
+
"keywords": [
|
1211 |
+
"http",
|
1212 |
+
"http-message",
|
1213 |
+
"psr",
|
1214 |
+
"psr-7",
|
1215 |
+
"request",
|
1216 |
+
"response"
|
1217 |
+
]
|
1218 |
},
|
1219 |
{
|
1220 |
+
"name": "psr/log",
|
1221 |
+
"version": "1.0.2",
|
1222 |
+
"version_normalized": "1.0.2.0",
|
1223 |
"source": {
|
1224 |
"type": "git",
|
1225 |
+
"url": "https://github.com/php-fig/log.git",
|
1226 |
+
"reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d"
|
1227 |
},
|
1228 |
"dist": {
|
1229 |
"type": "zip",
|
1230 |
+
"url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
|
1231 |
+
"reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
|
1232 |
"shasum": ""
|
1233 |
},
|
1234 |
"require": {
|
1235 |
"php": ">=5.3.0"
|
1236 |
},
|
1237 |
+
"time": "2016-10-10T12:19:37+00:00",
|
|
|
|
|
|
|
1238 |
"type": "library",
|
1239 |
"extra": {
|
1240 |
"branch-alias": {
|
1241 |
+
"dev-master": "1.0.x-dev"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1242 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1243 |
},
|
1244 |
+
"installation-source": "dist",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1245 |
"autoload": {
|
1246 |
"psr-4": {
|
1247 |
+
"Psr\\Log\\": "Psr/Log/"
|
1248 |
}
|
1249 |
},
|
1250 |
"notification-url": "https://packagist.org/downloads/",
|
1253 |
],
|
1254 |
"authors": [
|
1255 |
{
|
1256 |
+
"name": "PHP-FIG",
|
1257 |
+
"homepage": "http://www.php-fig.org/"
|
|
|
|
|
1258 |
}
|
1259 |
],
|
1260 |
+
"description": "Common interface for logging libraries",
|
1261 |
+
"homepage": "https://github.com/php-fig/log",
|
1262 |
"keywords": [
|
1263 |
+
"log",
|
1264 |
+
"psr",
|
1265 |
+
"psr-3"
|
|
|
|
|
|
|
|
|
1266 |
]
|
1267 |
},
|
1268 |
{
|
1269 |
+
"name": "sabre/dav",
|
1270 |
+
"version": "3.2.2",
|
1271 |
+
"version_normalized": "3.2.2.0",
|
1272 |
"source": {
|
1273 |
"type": "git",
|
1274 |
+
"url": "https://github.com/sabre-io/dav.git",
|
1275 |
+
"reference": "e987775e619728f12205606c9cc3ee565ffb1516"
|
1276 |
},
|
1277 |
"dist": {
|
1278 |
"type": "zip",
|
1279 |
+
"url": "https://api.github.com/repos/sabre-io/dav/zipball/e987775e619728f12205606c9cc3ee565ffb1516",
|
1280 |
+
"reference": "e987775e619728f12205606c9cc3ee565ffb1516",
|
1281 |
"shasum": ""
|
1282 |
},
|
1283 |
"require": {
|
1284 |
+
"ext-ctype": "*",
|
1285 |
+
"ext-date": "*",
|
1286 |
+
"ext-dom": "*",
|
1287 |
+
"ext-iconv": "*",
|
1288 |
+
"ext-mbstring": "*",
|
1289 |
+
"ext-pcre": "*",
|
1290 |
+
"ext-simplexml": "*",
|
1291 |
+
"ext-spl": "*",
|
1292 |
+
"lib-libxml": ">=2.7.0",
|
1293 |
+
"php": ">=5.5.0",
|
1294 |
+
"psr/log": "^1.0",
|
1295 |
+
"sabre/event": ">=2.0.0, <4.0.0",
|
1296 |
+
"sabre/http": "^4.2.1",
|
1297 |
+
"sabre/uri": "^1.0.1",
|
1298 |
+
"sabre/vobject": "^4.1.0",
|
1299 |
+
"sabre/xml": "^1.4.0"
|
1300 |
},
|
1301 |
"require-dev": {
|
1302 |
+
"evert/phpdoc-md": "~0.1.0",
|
1303 |
+
"monolog/monolog": "^1.18",
|
1304 |
+
"phpunit/phpunit": "> 4.8, <6.0.0",
|
1305 |
+
"sabre/cs": "^1.0.0"
|
1306 |
+
},
|
1307 |
+
"suggest": {
|
1308 |
+
"ext-curl": "*",
|
1309 |
+
"ext-pdo": "*"
|
1310 |
},
|
1311 |
+
"time": "2017-02-15T03:06:08+00:00",
|
1312 |
+
"bin": [
|
1313 |
+
"bin/sabredav",
|
1314 |
+
"bin/naturalselection"
|
1315 |
+
],
|
1316 |
"type": "library",
|
1317 |
+
"extra": {
|
1318 |
+
"branch-alias": {
|
1319 |
+
"dev-master": "3.1.0-dev"
|
1320 |
+
}
|
1321 |
+
},
|
1322 |
+
"installation-source": "dist",
|
1323 |
"autoload": {
|
1324 |
"psr-4": {
|
1325 |
+
"Sabre\\DAV\\": "lib/DAV/",
|
1326 |
+
"Sabre\\DAVACL\\": "lib/DAVACL/",
|
1327 |
+
"Sabre\\CalDAV\\": "lib/CalDAV/",
|
1328 |
+
"Sabre\\CardDAV\\": "lib/CardDAV/"
|
1329 |
}
|
1330 |
},
|
1331 |
"notification-url": "https://packagist.org/downloads/",
|
1332 |
"license": [
|
1333 |
+
"BSD-3-Clause"
|
1334 |
],
|
1335 |
"authors": [
|
1336 |
{
|
1337 |
+
"name": "Evert Pot",
|
1338 |
+
"email": "me@evertpot.com",
|
1339 |
+
"homepage": "http://evertpot.com/",
|
1340 |
+
"role": "Developer"
|
1341 |
}
|
1342 |
],
|
1343 |
+
"description": "WebDAV Framework for PHP",
|
1344 |
+
"homepage": "http://sabre.io/",
|
1345 |
"keywords": [
|
1346 |
+
"CalDAV",
|
1347 |
+
"CardDAV",
|
1348 |
+
"WebDAV",
|
1349 |
+
"framework",
|
1350 |
+
"iCalendar"
|
|
|
1351 |
]
|
1352 |
},
|
1353 |
{
|
1354 |
+
"name": "sabre/event",
|
1355 |
+
"version": "3.0.0",
|
1356 |
+
"version_normalized": "3.0.0.0",
|
1357 |
"source": {
|
1358 |
"type": "git",
|
1359 |
+
"url": "https://github.com/sabre-io/event.git",
|
1360 |
+
"reference": "831d586f5a442dceacdcf5e9c4c36a4db99a3534"
|
1361 |
},
|
1362 |
"dist": {
|
1363 |
"type": "zip",
|
1364 |
+
"url": "https://api.github.com/repos/sabre-io/event/zipball/831d586f5a442dceacdcf5e9c4c36a4db99a3534",
|
1365 |
+
"reference": "831d586f5a442dceacdcf5e9c4c36a4db99a3534",
|
1366 |
+
"shasum": ""
|
1367 |
+
},
|
1368 |
+
"require": {
|
1369 |
+
"php": ">=5.5"
|
|
|
|
|
|
|
|
|
1370 |
},
|
1371 |
"require-dev": {
|
1372 |
+
"phpunit/phpunit": "*",
|
1373 |
+
"sabre/cs": "~0.0.4"
|
|
|
1374 |
},
|
1375 |
+
"time": "2015-11-05T20:14:39+00:00",
|
1376 |
"type": "library",
|
1377 |
+
"installation-source": "dist",
|
1378 |
"autoload": {
|
1379 |
"psr-4": {
|
1380 |
+
"Sabre\\Event\\": "lib/"
|
1381 |
+
},
|
1382 |
+
"files": [
|
1383 |
+
"lib/coroutine.php",
|
1384 |
+
"lib/Loop/functions.php",
|
1385 |
+
"lib/Promise/functions.php"
|
1386 |
+
]
|
1387 |
},
|
1388 |
"notification-url": "https://packagist.org/downloads/",
|
1389 |
"license": [
|
1390 |
+
"BSD-3-Clause"
|
1391 |
],
|
1392 |
"authors": [
|
1393 |
{
|
1394 |
+
"name": "Evert Pot",
|
1395 |
+
"email": "me@evertpot.com",
|
1396 |
+
"homepage": "http://evertpot.com/",
|
1397 |
"role": "Developer"
|
1398 |
}
|
1399 |
],
|
1400 |
+
"description": "sabre/event is a library for lightweight event-based programming",
|
1401 |
+
"homepage": "http://sabre.io/event/",
|
1402 |
"keywords": [
|
1403 |
+
"EventEmitter",
|
1404 |
+
"async",
|
1405 |
+
"events",
|
1406 |
+
"hooks",
|
1407 |
+
"plugin",
|
1408 |
+
"promise",
|
1409 |
+
"signal"
|
1410 |
]
|
1411 |
},
|
1412 |
{
|
1467 |
"http"
|
1468 |
]
|
1469 |
},
|
1470 |
+
{
|
1471 |
+
"name": "sabre/uri",
|
1472 |
+
"version": "1.2.1",
|
1473 |
+
"version_normalized": "1.2.1.0",
|
1474 |
+
"source": {
|
1475 |
+
"type": "git",
|
1476 |
+
"url": "https://github.com/sabre-io/uri.git",
|
1477 |
+
"reference": "ada354d83579565949d80b2e15593c2371225e61"
|
1478 |
+
},
|
1479 |
+
"dist": {
|
1480 |
+
"type": "zip",
|
1481 |
+
"url": "https://api.github.com/repos/sabre-io/uri/zipball/ada354d83579565949d80b2e15593c2371225e61",
|
1482 |
+
"reference": "ada354d83579565949d80b2e15593c2371225e61",
|
1483 |
+
"shasum": ""
|
1484 |
+
},
|
1485 |
+
"require": {
|
1486 |
+
"php": ">=5.4.7"
|
1487 |
+
},
|
1488 |
+
"require-dev": {
|
1489 |
+
"phpunit/phpunit": ">=4.0,<6.0",
|
1490 |
+
"sabre/cs": "~1.0.0"
|
1491 |
+
},
|
1492 |
+
"time": "2017-02-20T19:59:28+00:00",
|
1493 |
+
"type": "library",
|
1494 |
+
"installation-source": "dist",
|
1495 |
+
"autoload": {
|
1496 |
+
"files": [
|
1497 |
+
"lib/functions.php"
|
1498 |
+
],
|
1499 |
+
"psr-4": {
|
1500 |
+
"Sabre\\Uri\\": "lib/"
|
1501 |
+
}
|
1502 |
+
},
|
1503 |
+
"notification-url": "https://packagist.org/downloads/",
|
1504 |
+
"license": [
|
1505 |
+
"BSD-3-Clause"
|
1506 |
+
],
|
1507 |
+
"authors": [
|
1508 |
+
{
|
1509 |
+
"name": "Evert Pot",
|
1510 |
+
"email": "me@evertpot.com",
|
1511 |
+
"homepage": "http://evertpot.com/",
|
1512 |
+
"role": "Developer"
|
1513 |
+
}
|
1514 |
+
],
|
1515 |
+
"description": "Functions for making sense out of URIs.",
|
1516 |
+
"homepage": "http://sabre.io/uri/",
|
1517 |
+
"keywords": [
|
1518 |
+
"rfc3986",
|
1519 |
+
"uri",
|
1520 |
+
"url"
|
1521 |
+
]
|
1522 |
+
},
|
1523 |
{
|
1524 |
"name": "sabre/vobject",
|
1525 |
"version": "4.1.6",
|
1619 |
"xCard"
|
1620 |
]
|
1621 |
},
|
1622 |
+
{
|
1623 |
+
"name": "sabre/xml",
|
1624 |
+
"version": "1.5.0",
|
1625 |
+
"version_normalized": "1.5.0.0",
|
1626 |
+
"source": {
|
1627 |
+
"type": "git",
|
1628 |
+
"url": "https://github.com/sabre-io/xml.git",
|
1629 |
+
"reference": "59b20e5bbace9912607481634f97d05a776ffca7"
|
1630 |
+
},
|
1631 |
+
"dist": {
|
1632 |
+
"type": "zip",
|
1633 |
+
"url": "https://api.github.com/repos/sabre-io/xml/zipball/59b20e5bbace9912607481634f97d05a776ffca7",
|
1634 |
+
"reference": "59b20e5bbace9912607481634f97d05a776ffca7",
|
1635 |
+
"shasum": ""
|
1636 |
+
},
|
1637 |
+
"require": {
|
1638 |
+
"ext-dom": "*",
|
1639 |
+
"ext-xmlreader": "*",
|
1640 |
+
"ext-xmlwriter": "*",
|
1641 |
+
"lib-libxml": ">=2.6.20",
|
1642 |
+
"php": ">=5.5.5",
|
1643 |
+
"sabre/uri": ">=1.0,<3.0.0"
|
1644 |
+
},
|
1645 |
+
"require-dev": {
|
1646 |
+
"phpunit/phpunit": "*",
|
1647 |
+
"sabre/cs": "~1.0.0"
|
1648 |
+
},
|
1649 |
+
"time": "2016-10-09T22:57:52+00:00",
|
1650 |
+
"type": "library",
|
1651 |
+
"installation-source": "dist",
|
1652 |
+
"autoload": {
|
1653 |
+
"psr-4": {
|
1654 |
+
"Sabre\\Xml\\": "lib/"
|
1655 |
+
},
|
1656 |
+
"files": [
|
1657 |
+
"lib/Deserializer/functions.php",
|
1658 |
+
"lib/Serializer/functions.php"
|
1659 |
+
]
|
1660 |
+
},
|
1661 |
+
"notification-url": "https://packagist.org/downloads/",
|
1662 |
+
"license": [
|
1663 |
+
"BSD-3-Clause"
|
1664 |
+
],
|
1665 |
+
"authors": [
|
1666 |
+
{
|
1667 |
+
"name": "Evert Pot",
|
1668 |
+
"email": "me@evertpot.com",
|
1669 |
+
"homepage": "http://evertpot.com/",
|
1670 |
+
"role": "Developer"
|
1671 |
+
},
|
1672 |
+
{
|
1673 |
+
"name": "Markus Staab",
|
1674 |
+
"email": "markus.staab@redaxo.de",
|
1675 |
+
"role": "Developer"
|
1676 |
+
}
|
1677 |
+
],
|
1678 |
+
"description": "sabre/xml is an XML library that you may not hate.",
|
1679 |
+
"homepage": "https://sabre.io/xml/",
|
1680 |
+
"keywords": [
|
1681 |
+
"XMLReader",
|
1682 |
+
"XMLWriter",
|
1683 |
+
"dom",
|
1684 |
+
"xml"
|
1685 |
+
]
|
1686 |
+
},
|
1687 |
{
|
1688 |
"name": "splitbrain/php-archive",
|
1689 |
"version": "1.0.10",
|
1792 |
]
|
1793 |
},
|
1794 |
{
|
1795 |
+
"name": "vakata/jstree",
|
1796 |
+
"version": "3.3.5",
|
1797 |
+
"version_normalized": "3.3.5.0",
|
1798 |
"source": {
|
1799 |
"type": "git",
|
1800 |
+
"url": "https://github.com/vakata/jstree.git",
|
1801 |
+
"reference": "0097fab41981daf36c234b73b683166daabd5f28"
|
1802 |
},
|
1803 |
"dist": {
|
1804 |
"type": "zip",
|
1805 |
+
"url": "https://api.github.com/repos/vakata/jstree/zipball/0097fab41981daf36c234b73b683166daabd5f28",
|
1806 |
+
"reference": "0097fab41981daf36c234b73b683166daabd5f28",
|
1807 |
"shasum": ""
|
1808 |
},
|
1809 |
"require": {
|
1810 |
+
"components/jquery": ">=1.9.1"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1811 |
},
|
1812 |
"suggest": {
|
1813 |
+
"robloach/component-installer": "Allows installation of Components via Composer"
|
|
|
|
|
|
|
1814 |
},
|
1815 |
+
"time": "2018-01-02T08:13:23+00:00",
|
1816 |
+
"type": "component",
|
1817 |
"extra": {
|
1818 |
+
"component": {
|
1819 |
+
"scripts": [
|
1820 |
+
"dist/jstree.js"
|
1821 |
+
],
|
1822 |
+
"styles": [
|
1823 |
+
"dist/themes/default/style.css"
|
1824 |
+
],
|
1825 |
+
"images": [
|
1826 |
+
"dist/themes/default/32px.png",
|
1827 |
+
"dist/themes/default/40px.png",
|
1828 |
+
"dist/themes/default/throbber.gif"
|
1829 |
+
],
|
1830 |
+
"files": [
|
1831 |
+
"dist/jstree.min.js",
|
1832 |
+
"dist/themes/default/style.min.css",
|
1833 |
+
"dist/themes/default/32px.png",
|
1834 |
+
"dist/themes/default/40px.png",
|
1835 |
+
"dist/themes/default/throbber.gif"
|
1836 |
+
]
|
1837 |
}
|
1838 |
},
|
1839 |
"installation-source": "source",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1840 |
"notification-url": "https://packagist.org/downloads/",
|
1841 |
"license": [
|
1842 |
+
"MIT"
|
1843 |
],
|
1844 |
"authors": [
|
1845 |
{
|
1846 |
+
"name": "Ivan Bozhanov",
|
1847 |
+
"email": "jstree@jstree.com"
|
1848 |
}
|
1849 |
],
|
1850 |
+
"description": "jsTree is jquery plugin, that provides interactive trees.",
|
1851 |
+
"homepage": "http://jstree.com"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1852 |
}
|
1853 |
]
|
vendor/defuse/php-encryption/.gitignore
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
*~
|
2 |
+
/test/unit/File/big-generated-file
|
3 |
+
/composer.lock
|
4 |
+
/vendor
|
5 |
+
defuse-crypto.phar
|
6 |
+
defuse-crypto.phar.sig
|
7 |
+
composer.phar
|
8 |
+
box.phar
|
9 |
+
phpunit.phar
|
10 |
+
phpunit.phar.asc
|
11 |
+
test/unit/File/tmp
|
vendor/defuse/php-encryption/.php_cs
ADDED
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
$config = Symfony\CS\Config\Config::create()
|
4 |
+
->level(Symfony\CS\FixerInterface::PSR2_LEVEL)
|
5 |
+
->fixers([
|
6 |
+
'blankline_after_open_tag',
|
7 |
+
'empty_return',
|
8 |
+
'extra_empty_lines',
|
9 |
+
'function_typehint_space',
|
10 |
+
'join_function',
|
11 |
+
'method_argument_default_value',
|
12 |
+
'multiline_array_trailing_comma',
|
13 |
+
'no_blank_lines_after_class_opening',
|
14 |
+
'no_empty_lines_after_phpdocs',
|
15 |
+
'phpdoc_indent',
|
16 |
+
'phpdoc_no_access',
|
17 |
+
'phpdoc_no_empty_return',
|
18 |
+
'phpdoc_no_package',
|
19 |
+
'phpdoc_params',
|
20 |
+
'phpdoc_scalar',
|
21 |
+
'phpdoc_separation',
|
22 |
+
'phpdoc_trim',
|
23 |
+
'phpdoc_type_to_var',
|
24 |
+
'phpdoc_types',
|
25 |
+
'phpdoc_var_without_name',
|
26 |
+
'remove_leading_slash_use',
|
27 |
+
'remove_lines_between_uses',
|
28 |
+
'short_bool_cast',
|
29 |
+
'single_quote',
|
30 |
+
'spaces_after_semicolon',
|
31 |
+
'spaces_before_semicolon',
|
32 |
+
'spaces_cast',
|
33 |
+
'standardize_not_equal',
|
34 |
+
'ternary_spaces',
|
35 |
+
'trim_array_spaces',
|
36 |
+
'unneeded_control_parentheses',
|
37 |
+
'unused_use',
|
38 |
+
'whitespacy_lines',
|
39 |
+
'align_double_arrow',
|
40 |
+
'concat_with_spaces',
|
41 |
+
'logical_not_operators_with_successor_space',
|
42 |
+
'multiline_spaces_before_semicolon',
|
43 |
+
'newline_after_open_tag',
|
44 |
+
'ordered_use',
|
45 |
+
'php_unit_construct',
|
46 |
+
'phpdoc_order',
|
47 |
+
'short_array_syntax',
|
48 |
+
]);
|
49 |
+
|
50 |
+
if (null === $input->getArgument('path')) {
|
51 |
+
$config
|
52 |
+
->finder(
|
53 |
+
Symfony\CS\Finder\DefaultFinder::create()
|
54 |
+
->in('src')
|
55 |
+
->in('test')
|
56 |
+
->exclude('vendor')
|
57 |
+
);
|
58 |
+
}
|
59 |
+
|
60 |
+
return $config;
|
vendor/defuse/php-encryption/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
The MIT License (MIT)
|
2 |
+
|
3 |
+
Copyright (c) 2016 Taylor Hornby <https://defuse.ca> and Paragon Initiative
|
4 |
+
Enterprises <https://paragonie.com>.
|
5 |
+
|
6 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
7 |
+
this software and associated documentation files (the "Software"), to deal in
|
8 |
+
the Software without restriction, including without limitation the rights to
|
9 |
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
10 |
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
11 |
+
subject to the following conditions:
|
12 |
+
|
13 |
+
The above copyright notice and this permission notice shall be included in all
|
14 |
+
copies or substantial portions of the Software.
|
15 |
+
|
16 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
18 |
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
19 |
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
20 |
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
21 |
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
vendor/defuse/php-encryption/README.md
ADDED
@@ -0,0 +1,102 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
php-encryption
|
2 |
+
===============
|
3 |
+
|
4 |
+
[![Build Status](https://travis-ci.org/defuse/php-encryption.svg?branch=master)](https://travis-ci.org/defuse/php-encryption)
|
5 |
+
[![codecov](https://codecov.io/gh/defuse/php-encryption/branch/master/graph/badge.svg)](https://codecov.io/gh/defuse/php-encryption)
|
6 |
+
[![Latest Stable Version](https://poser.pugx.org/defuse/php-encryption/v/stable)](https://packagist.org/packages/defuse/php-encryption)
|
7 |
+
[![Latest Unstable Version](https://poser.pugx.org/defuse/php-encryption/v/unstable)](https://packagist.org/packages/defuse/php-encryption)
|
8 |
+
[![License](https://poser.pugx.org/defuse/php-encryption/license)](https://packagist.org/packages/defuse/php-encryption)
|
9 |
+
[![Downloads](https://img.shields.io/packagist/dt/defuse/php-encryption.svg)](https://packagist.org/packages/defuse/php-encryption)
|
10 |
+
|
11 |
+
This is a library for encrypting data with a key or password in PHP. **It
|
12 |
+
requires PHP 5.6 or newer and OpenSSL 1.0.1 or newer.** The current version is
|
13 |
+
v2.2.0, which is expected to remain stable and supported by its authors with
|
14 |
+
security and bugfixes until at least January 1st, 2020.
|
15 |
+
|
16 |
+
The library is a joint effort between [Taylor Hornby](https://defuse.ca/) and
|
17 |
+
[Scott Arciszewski](https://paragonie.com/blog/author/scott-arcizewski) as well
|
18 |
+
as numerous open-source contributors.
|
19 |
+
|
20 |
+
What separates this library from other PHP encryption libraries is, firstly,
|
21 |
+
that it is secure. The authors used to encounter insecure PHP encryption code on
|
22 |
+
a daily basis, so they created this library to bring more security to the
|
23 |
+
ecosystem. Secondly, this library is "difficult to misuse." Like
|
24 |
+
[libsodium](https://github.com/jedisct1/libsodium), its API is designed to be
|
25 |
+
easy to use in a secure way and hard to use in an insecure way.
|
26 |
+
|
27 |
+
|
28 |
+
Dependencies
|
29 |
+
------------
|
30 |
+
|
31 |
+
This library requires no special dependencies except for PHP 5.6 or newer with
|
32 |
+
the OpenSSL extensions (version 1.0.1 or later) enabled (this is the default).
|
33 |
+
It uses [random\_compat](https://github.com/paragonie/random_compat), which is
|
34 |
+
bundled in with this library so that your users will not need to follow any
|
35 |
+
special installation steps.
|
36 |
+
|
37 |
+
Getting Started
|
38 |
+
----------------
|
39 |
+
|
40 |
+
Start with the [**Tutorial**](docs/Tutorial.md). You can find instructions for
|
41 |
+
obtaining this library's code securely in the [Installing and
|
42 |
+
Verifying](docs/InstallingAndVerifying.md) documentation.
|
43 |
+
|
44 |
+
After you've read the tutorial and got the code, refer to the formal
|
45 |
+
documentation for each of the classes this library provides:
|
46 |
+
|
47 |
+
- [Crypto](docs/classes/Crypto.md)
|
48 |
+
- [File](docs/classes/File.md)
|
49 |
+
- [Key](docs/classes/Key.md)
|
50 |
+
- [KeyProtectedByPassword](docs/classes/KeyProtectedByPassword.md)
|
51 |
+
|
52 |
+
If you encounter difficulties, see the [FAQ](docs/FAQ.md) answers. The fixes to
|
53 |
+
the most commonly-reported problems are explained there.
|
54 |
+
|
55 |
+
If you're a cryptographer and want to understand the nitty-gritty details of how
|
56 |
+
this library works, look at the [Cryptography Details](docs/CryptoDetails.md)
|
57 |
+
documentation.
|
58 |
+
|
59 |
+
If you're interested in contributing to this library, see the [Internal
|
60 |
+
Developer Documentation](docs/InternalDeveloperDocs.md).
|
61 |
+
|
62 |
+
Other Language Support
|
63 |
+
----------------------
|
64 |
+
|
65 |
+
This library is intended for server-side PHP software that needs to encrypt data at rest.
|
66 |
+
If you are building software that needs to encrypt client-side, or building a system that
|
67 |
+
requires cross-platform encryption/decryption support, we strongly recommend using
|
68 |
+
[libsodium](https://download.libsodium.org/doc/bindings_for_other_languages) instead.
|
69 |
+
|
70 |
+
Examples
|
71 |
+
---------
|
72 |
+
|
73 |
+
If the documentation is not enough for you to understand how to use this
|
74 |
+
library, then you can look at an example project that uses this library:
|
75 |
+
|
76 |
+
- [encutil](https://github.com/defuse/encutil)
|
77 |
+
- [fileencrypt](https://github.com/tsusanka/fileencrypt)
|
78 |
+
|
79 |
+
Security Audit Status
|
80 |
+
---------------------
|
81 |
+
|
82 |
+
This code has not been subjected to a formal, paid, security audit. However, it
|
83 |
+
has received lots of review from members of the PHP security community, and the
|
84 |
+
authors are experienced with cryptography. In all likelihood, you are safer
|
85 |
+
using this library than almost any other encryption library for PHP.
|
86 |
+
|
87 |
+
If you use this library as a part of your business and would like to help fund
|
88 |
+
a formal audit, please [contact Taylor Hornby](https://defuse.ca/contact.htm).
|
89 |
+
|
90 |
+
Public Keys
|
91 |
+
------------
|
92 |
+
|
93 |
+
The GnuPG public key used to sign releases is available in
|
94 |
+
[dist/signingkey.asc](https://github.com/defuse/php-encryption/raw/master/dist/signingkey.asc). Its fingerprint is:
|
95 |
+
|
96 |
+
```
|
97 |
+
2FA6 1D8D 99B9 2658 6BAC 3D53 385E E055 A129 1538
|
98 |
+
```
|
99 |
+
|
100 |
+
You can verify it against Taylor Hornby's [contact
|
101 |
+
page](https://defuse.ca/contact.htm) and
|
102 |
+
[twitter](https://twitter.com/DefuseSec/status/723741424253059074).
|
vendor/defuse/php-encryption/bin/generate-defuse-key
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/env php
|
2 |
+
<?php
|
3 |
+
|
4 |
+
use Defuse\Crypto\Key;
|
5 |
+
|
6 |
+
foreach ([__DIR__ . '/../../../autoload.php', __DIR__ . '/../vendor/autoload.php'] as $file) {
|
7 |
+
if (file_exists($file)) {
|
8 |
+
require $file;
|
9 |
+
break;
|
10 |
+
}
|
11 |
+
}
|
12 |
+
|
13 |
+
$key = Key::createNewRandomKey();
|
14 |
+
echo $key->saveToAsciiSafeString(), "\n";
|
vendor/defuse/php-encryption/composer.json
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"name": "defuse/php-encryption",
|
3 |
+
"description": "Secure PHP Encryption Library",
|
4 |
+
"license": "MIT",
|
5 |
+
"keywords": ["security", "encryption", "AES", "openssl", "cipher", "cryptography", "symmetric key cryptography", "crypto", "encrypt", "authenticated encryption"],
|
6 |
+
"authors": [
|
7 |
+
{
|
8 |
+
"name": "Taylor Hornby",
|
9 |
+
"email": "taylor@defuse.ca",
|
10 |
+
"homepage": "https://defuse.ca/"
|
11 |
+
},
|
12 |
+
{
|
13 |
+
"name": "Scott Arciszewski",
|
14 |
+
"email": "info@paragonie.com",
|
15 |
+
"homepage": "https://paragonie.com"
|
16 |
+
}
|
17 |
+
],
|
18 |
+
"autoload": {
|
19 |
+
"psr-4": {
|
20 |
+
"Defuse\\Crypto\\": "src"
|
21 |
+
}
|
22 |
+
},
|
23 |
+
"require": {
|
24 |
+
"paragonie/random_compat": "~2.0",
|
25 |
+
"ext-openssl": "*",
|
26 |
+
"php": ">=5.4.0"
|
27 |
+
},
|
28 |
+
"require-dev": {
|
29 |
+
"phpunit/phpunit": "^4|^5",
|
30 |
+
"nikic/php-parser": "^2.0|^3.0|^4.0"
|
31 |
+
},
|
32 |
+
"bin": [
|
33 |
+
"bin/generate-defuse-key"
|
34 |
+
]
|
35 |
+
}
|
vendor/defuse/php-encryption/dist/Makefile
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# This builds defuse-crypto.phar. To run this Makefile, `box` and `composer`
|
2 |
+
# must be installed and in your $PATH. Run it from inside the dist/ directory.
|
3 |
+
|
4 |
+
box := $(shell which box)
|
5 |
+
composer := "composer"
|
6 |
+
|
7 |
+
.PHONY: all
|
8 |
+
all: build-phar
|
9 |
+
|
10 |
+
.PHONY: sign-phar
|
11 |
+
sign-phar:
|
12 |
+
gpg -u 7B4B2D98 --armor --output defuse-crypto.phar.sig --detach-sig defuse-crypto.phar
|
13 |
+
|
14 |
+
# ensure we run in clean tree. export git tree and run there.
|
15 |
+
.PHONY: build-phar
|
16 |
+
build-phar:
|
17 |
+
@echo "Creating .phar from revision $(shell git rev-parse HEAD)."
|
18 |
+
rm -rf worktree
|
19 |
+
install -d worktree
|
20 |
+
(cd $(CURDIR)/..; git archive HEAD) | tar -x -C worktree
|
21 |
+
$(MAKE) -f $(CURDIR)/Makefile -C worktree defuse-crypto.phar
|
22 |
+
mv worktree/*.phar .
|
23 |
+
rm -rf worktree
|
24 |
+
|
25 |
+
.PHONY: clean
|
26 |
+
clean:
|
27 |
+
rm -vf defuse-crypto.phar defuse-crypto.phar.sig
|
28 |
+
|
29 |
+
# Inside workdir/:
|
30 |
+
|
31 |
+
defuse-crypto.phar: dist/box.json composer.lock
|
32 |
+
cp dist/box.json .
|
33 |
+
php -d phar.readonly=0 $(box) build -c box.json -v
|
34 |
+
|
35 |
+
composer.lock:
|
36 |
+
$(composer) install --no-dev
|
37 |
+
|
vendor/defuse/php-encryption/dist/box.json
ADDED
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"chmod": "0755",
|
3 |
+
"finder": [
|
4 |
+
{
|
5 |
+
"in": "src",
|
6 |
+
"name": "*.php"
|
7 |
+
},
|
8 |
+
{
|
9 |
+
"in": "vendor/composer",
|
10 |
+
"name": "*.php"
|
11 |
+
},
|
12 |
+
{
|
13 |
+
"in": "vendor/paragonie",
|
14 |
+
"name": "*.php",
|
15 |
+
"exclude": "other"
|
16 |
+
}
|
17 |
+
],
|
18 |
+
"compactors": [
|
19 |
+
"Herrera\\Box\\Compactor\\Php"
|
20 |
+
],
|
21 |
+
"main": "vendor/autoload.php",
|
22 |
+
"output": "defuse-crypto.phar",
|
23 |
+
"shebang": false,
|
24 |
+
"stub": true
|
25 |
+
}
|
vendor/defuse/php-encryption/dist/signingkey.asc
ADDED
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
2 |
+
Version: GnuPG v2
|
3 |
+
|
4 |
+
mQINBFarvO4BEACdQBaLt6SUBx1cB5liUu1qo+YwVLh9bxTregQtmEREMdTVqXYt
|
5 |
+
e5b79uL4pQp2GlKHcEyRURS+6rIIruM0oh9ZYGTJYPAkCDzJxaU2awZeFbfBvpCm
|
6 |
+
iF66/O4ZJI4mlT8dFKmxBJxDhfeOR2UmmhDiEsJK9FxBKUzvo/dWrX2pBzf8Y122
|
7 |
+
iIaVraSo+tymaf7vriaIf/NnSKhDw8dtQYGM4NMrxxsPTfbCF8XiboDgTkoD2A+6
|
8 |
+
NpOJYxA4Veedsf2TP9YLhljH4m5yYlfjjqBzbBCPWuE6Hhy5Xze9mncgDr7LKenm
|
9 |
+
Ctf2NxW6y4O3RCI+9eLlBfFWB+KuGV87/b5daetX7NNLbjID8z2rqEa+d6wu5xA5
|
10 |
+
Ta2uiVkAOEovr3XnkayZ9zth+Za7w7Ai0ln0N/LVMkM+Gu4z/pJv6HjmTGDM2wJb
|
11 |
+
fs+UOM0TFdg+N81Do67XT2M4o0MeHyUqsIiWpYa2Qf1PNmqTQNJnRk8uZZ9I96Nh
|
12 |
+
eCgNuCbhsQiYBMicox+xmuWAlGAfA06y0kCtmqGhiBGArdJlWvUqPqGiZ4Hln9z0
|
13 |
+
FJmXDOh0Q/FIPxcDg8mKRRbx+lOP389PLsPpj4b2B/4PEgfpCCOwuKpLotATZxC1
|
14 |
+
9JwFk0Y/cvUUkq4a+nAJBNtBbtRJkEesuuUnRq6XexmnE3uUucDcV0XCSwARAQAB
|
15 |
+
tCBUYXlsb3IgSG9ybmJ5IDx0YXlsb3JAZGVmdXNlLmNhPokCPQQTAQgAJwUCVqu8
|
16 |
+
7gIbAwUJB4TOAAULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAKCRA4XuBVoSkVOJbx
|
17 |
+
EACG0F9blPMAsK05EWyNnnS4mw25zPfbaqqEvYbquAeM0nBpRDm7sRn2MNR0AL4g
|
18 |
+
7XrtxE/4qYkdEl6f2wFCQeRhZgxE3w22llredzLme11Hic8hn4i7ysdIw0r9dMMR
|
19 |
+
kjgR5UcWpv8iU847czyK09PkKW2EaLRbX2qbA7rNU5qCFKeD4Sy4bBTteISeVsHo
|
20 |
+
Vr9o1/bRrMhgZ++ts8hYf0LmujIf5cxp+qcdKwCXSnS/gmmXaKRMCPv/Wdlq9bt6
|
21 |
+
LX9jZB9lXBdGxcBJeFOsTG+QRDiVjg3d6i3o3TAKV87ALBI4v2ADEYtN8lviHo3/
|
22 |
+
SovVKv6zrUsZHxhoGiLTiksNrYsKMmiMxdJCoOazmtUPnZ4UOtT8NdqMPoKvdoRz
|
23 |
+
f4rhZ+f5jSVD9OuX2PDmfyq21Rdiym7Vcgr+uTIFJ3ShRHjWb/ytCwoB2FeGY6+G
|
24 |
+
AKY58bTQvUIqEJvSov/+TAqZ4BfOuSdTLcHglV1OdUu2SFZvU2gmyVp0l5elGv5t
|
25 |
+
FyUlBJUkQT9MtvsdLOR7vQi8QapV+9LWpqwvaj9hyEJz848DQ2sdYTphUytFHv7H
|
26 |
+
k58DAtVhTrVjHyeefjiYtMl6vSAgTjy5LWAUpo5TfhdGrAi0Tdd/GD7amHoWoDy8
|
27 |
+
EKXKq2xPLo3JOdkWYQUi5NErzEskfsSzpCOgyDJmGetWK7kCDQRWq7zuARAAu7/i
|
28 |
+
cm8cjgLhHEX/bgfwOT2hLOLSjjve0O8YFSuJO9XqIHXqmfVOrqWtfG0Mh4bwlfqc
|
29 |
+
MAvBfF5NSSPfAE4ftBAQ1e5jEv8hJeqICpq3IHTFX4etBs49NfNkyveQl/amVTu1
|
30 |
+
+/O5J4CuIcsEf3y0Xuu38n7EB3SfMQCWLcOR1NyZoX3bI+CGRpOVVoFse3ljSWL4
|
31 |
+
LhLVl0WiEMXULsussEoN+c6x9KCyAi/jFOrxrTrFC//sZesKj6KucoqKGfwMWrrv
|
32 |
+
IeRT9Ga8Wn5MJnQu0aWg+zVVYqTedXZLNLODgQIInFnXO0seBXy15yDok1y5bkx2
|
33 |
+
sinKg4+mueYaGUpoUti0hM3J3yaC34i6Cwa8MQoLNw1JIS/oNtKjpMxyV10w8aoc
|
34 |
+
PHRK3n7UYp10mJHx7aM+lldSKvVS1NTQmI4vloNLwMp324H5ANDFAlRUz7mysVnu
|
35 |
+
DEEvigPSPxs5ZYENu/i7pCQC5qHfhrlBrQwTjhegr0pQPcumy2fO5SGC9l/5B7ev
|
36 |
+
bqQSZmDeWWoTvh2w2wl5/RWAsgZKx6rDtkCqYx7sSBY17uorrxP24LP4zhq7NxRV
|
37 |
+
nfdsLogbCFNVQ66u7qvq5zFccdFtg9h1HQWdS7wbnKSBGZoo5gl6js7GGtxfGbb0
|
38 |
+
oQ9kp6eciF4U92r6POhVgbRe4CfPo50nqgZBddkAEQEAAYkCJQQYAQgADwUCVqu8
|
39 |
+
7gIbDAUJB4TOAAAKCRA4XuBVoSkVOFJ8D/9J8IJ4XWUU3FYIaHJ3XeSoxDmTi7d5
|
40 |
+
WmNdf1lmwz82MQjG4uw17oCbvQzmj4/a/CM1Ly4v0WwBhUf9aiNErD0ByHASFnuc
|
41 |
+
tlQBLVJdk0vRyD0fZakGg64qCA76hiySjMhlGHkQFyP2mDORc2GNu/OqFGm79pXT
|
42 |
+
ZUplXxd431E603/agM5xJrweutMMpP1nBFTSEMJvbMNzDVN8I1A1CH4zVmAVxOUk
|
43 |
+
sQ5L5rXW+KeXWyiMF24+l2CMnkQ2CxfHpkcpfPJs1Cbt+TIBSSofIqK8QJXrb/2f
|
44 |
+
Zpl/ftqW7Xe86rJFrB/Y/77LDWx10rqWEvfCqrBxrMj7ONAQfbKQF/IjAwDN17Wf
|
45 |
+
1K74rqKnRu+KHCyNM89s1iDbQC9kzZfzYt4AEOvAH/ZQDMZffzPSbnfkBerExFpa
|
46 |
+
93XMuiR66jiBsf9IXIQeydpJD4Ogl2sSUSxFEJxJ/bBSxPxC5w7/BVMA7Am1y8Zo
|
47 |
+
3hrpqnX2PBzxG7L0FZ6fYkfR3p8JS7vI6nByBf2IDv8W32wn43olPf+u6uobHLvt
|
48 |
+
ttapOjwPAhPDalRuxs9U6WSg06QJkT/0F8TFUPWpsFmKTl+G4Ty7PHWsjeeNHJCL
|
49 |
+
7/5RQboFY3k8Jy3/sIofABO6Un9LJivDuu9PxqA0IgvaS6Mja8JdCCk9Nyk4vHB7
|
50 |
+
IEgAL/CYqrk38w==
|
51 |
+
=lmD7
|
52 |
+
-----END PGP PUBLIC KEY BLOCK-----
|
vendor/defuse/php-encryption/docs/CryptoDetails.md
ADDED
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Cryptography Details
|
2 |
+
=====================
|
3 |
+
|
4 |
+
Here is a high-level description of how this library works. Any discrepancy
|
5 |
+
between this documentation and the actual implementation will be considered
|
6 |
+
a security bug.
|
7 |
+
|
8 |
+
Let's start with the following definitions:
|
9 |
+
|
10 |
+
- HKDF-SHA256(*k*, *n*, *info*, *s*) is the key derivation function specified in
|
11 |
+
RFC 5869 (using the SHA256 hash function). The parameters are:
|
12 |
+
- *k*: The initial keying material.
|
13 |
+
- *n*: The number of output bytes.
|
14 |
+
- *info*: The info string.
|
15 |
+
- *s*: The salt.
|
16 |
+
- AES-256-CTR(*m*, *k*, *iv*) is AES-256 encryption in CTR mode. The parameters
|
17 |
+
are:
|
18 |
+
- *m*: An arbitrary-length (possibly zero-length) message.
|
19 |
+
- *k*: A 32-byte key.
|
20 |
+
- *iv*: A 16-byte initialization vector (nonce).
|
21 |
+
- PBKDF2-SHA256(*p*, *s*, *i*, *n*) is the password-based key derivation
|
22 |
+
function defined in RFC 2898 (using the SHA256 hash function). The parameters
|
23 |
+
are:
|
24 |
+
- *p*: The password string.
|
25 |
+
- *s*: The salt string.
|
26 |
+
- *i*: The iteration count.
|
27 |
+
- *n*: The output length in bytes.
|
28 |
+
- VERSION is the string `"\xDE\xF5\x02\x00"`.
|
29 |
+
- AUTHINFO is the string `"DefusePHP|V2|KeyForAuthentication"`.
|
30 |
+
- ENCRINFO is the string `"DefusePHP|V2|KeyForEncryption"`.
|
31 |
+
|
32 |
+
To encrypt a message *m* using a 32-byte key *k*, the following steps are taken:
|
33 |
+
|
34 |
+
1. Generate a random 32-byte string *salt*.
|
35 |
+
2. Derive the 32-byte authentication key *akey* = HKDF-SHA256(*k*, 32, AUTHINFO, *salt*).
|
36 |
+
3. Derive the 32-byte encryption key *ekey* = HKDF-SHA256(*k*, 32, ENCRINFO, *salt*).
|
37 |
+
4. Generate a random 16-byte initialization vector *iv*.
|
38 |
+
5. Compute *c* = AES-256-CTR(*m*, *ekey*, *iv*).
|
39 |
+
6. Combine *ctxt* = VERSION || *salt* || *iv* || *c*.
|
40 |
+
7. Compute *h* = HMAC-SHA256(*ctxt*, *akey*).
|
41 |
+
8. Output *ctxt* || *h*.
|
42 |
+
|
43 |
+
Decryption is roughly the reverse process (see the code for details, since the
|
44 |
+
security of the decryption routine is highly implementation-dependent).
|
45 |
+
|
46 |
+
For encryption using a password *p*, steps 1-3 above are replaced by:
|
47 |
+
|
48 |
+
1. Generate a random 32-byte string *salt*.
|
49 |
+
2. Compute *k* = PBKDF2-SHA256(SHA256(*p*), *salt*, 100000, 32).
|
50 |
+
3. Derive the 32-byte authentication key *akey* = HKDF-SHA256(*k*, 32, AUTHINFO, *salt*)
|
51 |
+
4. Derive the 32-byte encryption key *ekey* = HKDF-SHA256(*k*, 32, ENCRINFO, *salt*)
|
52 |
+
|
53 |
+
The remainder of the process is the same. Notice the reuse of the same *salt*
|
54 |
+
for PBKDF2-SHA256 and HKDF-SHA256. The prehashing of the password in step 2 is
|
55 |
+
done to prevent a [DoS attack using long
|
56 |
+
passwords](https://github.com/defuse/php-encryption/issues/230).
|
57 |
+
|
58 |
+
For `KeyProtectedByPassword`, the serialized key is encrypted according to the
|
59 |
+
password encryption defined above. However, the actual password used for
|
60 |
+
encryption is the SHA256 hash of the password the user provided. This is done in
|
61 |
+
order to provide domain separation between the message encryption in the user's
|
62 |
+
application and the internal key encryption done by this library. It fixes
|
63 |
+
a [key replacement chosen-protocol
|
64 |
+
attack](https://github.com/defuse/php-encryption/issues/240).
|
vendor/defuse/php-encryption/docs/FAQ.md
ADDED
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Frequently Asked Questions
|
2 |
+
===========================
|
3 |
+
|
4 |
+
How do I use this library to encrypt passwords?
|
5 |
+
------------------------------------------------
|
6 |
+
|
7 |
+
Passwords should not be encrypted, they should be hashed with a *slow* password
|
8 |
+
hashing function that's designed to slow down password guessing attacks. See
|
9 |
+
[How to Safely Store Your Users' Passwords in
|
10 |
+
2016](https://paragonie.com/blog/2016/02/how-safely-store-password-in-2016).
|
11 |
+
|
12 |
+
How do I give it the same key every time instead of a new random key?
|
13 |
+
----------------------------------------------------------------------
|
14 |
+
|
15 |
+
A `Key` object can be saved to a string by calling its `saveToAsciiSafeString()`
|
16 |
+
method. You will have to save that string somewhere safe, and then load it back
|
17 |
+
into a `Key` object using `Key`'s `loadFromAsciiSafeString` static method.
|
18 |
+
|
19 |
+
Where you store the string depends on your application. For example if you are
|
20 |
+
using `KeyProtectedByPassword` to encrypt files with a user's login password,
|
21 |
+
then you should not store the `Key` at all. If you are protecting sensitive data
|
22 |
+
on a server that may be compromised, then you should store it in a hardware
|
23 |
+
security module. When in doubt, consult a security expert.
|
24 |
+
|
25 |
+
Why is an EnvironmentIsBrokenException getting thrown?
|
26 |
+
-------------------------------------------------------
|
27 |
+
|
28 |
+
Either you've encountered a bug in this library, or your system doesn't support
|
29 |
+
the use of this library. For example, if your system does not have a secure
|
30 |
+
random number generator, this library will refuse to run, by throwing that
|
31 |
+
exception, instead of falling back to an insecure random number generator.
|
32 |
+
|
33 |
+
Why am I getting a BadFormatException when loading a Key from a string?
|
34 |
+
------------------------------------------------------------------------
|
35 |
+
|
36 |
+
If you're getting this exception, then the string you're giving to
|
37 |
+
`loadFromAsciiSafeString()` is *not* the same as the string you got from
|
38 |
+
`saveToAsciiSafeString()`. Perhaps your database column isn't wide enough and
|
39 |
+
it's truncating the string as you insert it?
|
40 |
+
|
41 |
+
Does encrypting hide the length of the plaintext?
|
42 |
+
--------------------------------------------------
|
43 |
+
|
44 |
+
Encryption does not, and is not intended to, hide the length of the data being
|
45 |
+
encrypted. For example, it is not safe to encrypt a field in which only a small
|
46 |
+
number of different-length values are possible (e.g. "male" or "female") since
|
47 |
+
it would be possible to tell what the plaintext is by looking at the length of
|
48 |
+
the ciphertext. In order to do this safely, it is your responsibility to, before
|
49 |
+
encrypting, pad the data out to the length of the longest string that will ever
|
50 |
+
be encrypted. This way, all plaintexts are the same length, and no information
|
51 |
+
about the plaintext can be gleaned from the length of the ciphertext.
|
vendor/defuse/php-encryption/docs/InstallingAndVerifying.md
ADDED
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Getting The Code
|
2 |
+
=================
|
3 |
+
|
4 |
+
There are two ways to use this library in your applications. You can either:
|
5 |
+
|
6 |
+
1. Use [Composer](https://getcomposer.org/), or
|
7 |
+
2. `require_once` a single `.phar` file in your application.
|
8 |
+
|
9 |
+
If you are not using either option (for example, because you're using Git submodules), you may need to write your own autoloader ([example](https://gist.github.com/paragonie-scott/949daee819bb7f19c50e5e103170b400)).
|
10 |
+
|
11 |
+
Option 1: Using Composer
|
12 |
+
-------------------------
|
13 |
+
|
14 |
+
Run this inside the directory of your composer-enabled project:
|
15 |
+
|
16 |
+
```sh
|
17 |
+
composer require defuse/php-encryption
|
18 |
+
```
|
19 |
+
|
20 |
+
Unfortunately, composer doesn't provide a way for you to verify that the code
|
21 |
+
you're getting was signed by this library's authors. If you want a more secure
|
22 |
+
option, use the `.phar` method described below.
|
23 |
+
|
24 |
+
Option 2: Including a PHAR
|
25 |
+
----------------------------
|
26 |
+
|
27 |
+
The `.phar` option lets you include this library into your project simply by
|
28 |
+
calling `require_once` on a single file. Download `defuse-crypto.phar` and
|
29 |
+
`defuse-crypto.phar.sig` from this project's
|
30 |
+
[releases](https://github.com/defuse/php-encryption/releases) page.
|
31 |
+
|
32 |
+
You should verify the integrity of the `.phar`. The `defuse-crypto.phar.sig`
|
33 |
+
contains the signature of `defuse-crypto.phar`. It is signed with Taylor
|
34 |
+
Hornby's PGP key. You can find Taylor's public key in `dist/signingkey.asc`. You
|
35 |
+
can verify the public key's fingerprint against the Taylor Hornby's [contact
|
36 |
+
page](https://defuse.ca/contact.htm) and
|
37 |
+
[twitter](https://twitter.com/DefuseSec/status/723741424253059074).
|
38 |
+
|
39 |
+
Once you have verified the signature, it is safe to use the `.phar`. Place it
|
40 |
+
somewhere in your file system, e.g. `/var/www/lib/defuse-crypto.phar`, and then
|
41 |
+
pass that path to `require_once`.
|
42 |
+
|
43 |
+
```php
|
44 |
+
<?php
|
45 |
+
|
46 |
+
require_once('/var/www/lib/defuse-crypto.phar');
|
47 |
+
|
48 |
+
// ... the Crypto, File, Key, and KeyProtectedByPassword classes are now
|
49 |
+
// available ...
|
50 |
+
|
51 |
+
// ...
|
52 |
+
```
|
53 |
+
|
vendor/defuse/php-encryption/docs/InternalDeveloperDocs.md
ADDED
@@ -0,0 +1,166 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Information for the Developers of php-encryption
|
2 |
+
=================================================
|
3 |
+
|
4 |
+
Status
|
5 |
+
-------
|
6 |
+
|
7 |
+
This library is currently frozen under a long-term support release. We do not
|
8 |
+
plan to add any new features. We will maintain the library by fixing any bugs
|
9 |
+
that are reported, or security vulnerabilities that are found.
|
10 |
+
|
11 |
+
Development Environment
|
12 |
+
------------------------
|
13 |
+
|
14 |
+
Development is done on Linux. To run the tests, you will need to have the
|
15 |
+
following tools installed:
|
16 |
+
|
17 |
+
- `php` (with OpenSSL enabled, if you're compiling from source).
|
18 |
+
- `gpg`
|
19 |
+
- `composer`
|
20 |
+
|
21 |
+
Running the Tests
|
22 |
+
------------------
|
23 |
+
|
24 |
+
First do `composer install` and then you can run the tests by running
|
25 |
+
`./test.sh`. This will download a PHPUnit PHAR, verify its cryptographic
|
26 |
+
signatures, and then use it to run the tests in `test/unit`.
|
27 |
+
|
28 |
+
Getting and Using Psalm
|
29 |
+
-----------------------
|
30 |
+
|
31 |
+
[Psalm](https://github.com/vimeo/psalm) is a static analysis suite for PHP projects.
|
32 |
+
We use Psalm to ensure type safety throughout our library.
|
33 |
+
|
34 |
+
To install Psalm, you just need to run one command:
|
35 |
+
|
36 |
+
composer require --dev "vimeo/psalm:dev-master"
|
37 |
+
|
38 |
+
To verify that your code changes are still strictly type-safe, run the following
|
39 |
+
command:
|
40 |
+
|
41 |
+
vendor/bin/psalm
|
42 |
+
|
43 |
+
Reporting Bugs
|
44 |
+
---------------
|
45 |
+
|
46 |
+
Please report bugs, even critical security vulnerabilities, by opening an issue
|
47 |
+
on GitHub. We recommend disclosing security vulnerabilities found in this
|
48 |
+
library *publicly* as soon as possible.
|
49 |
+
|
50 |
+
Philosophy
|
51 |
+
-----------
|
52 |
+
|
53 |
+
This library is developed around several core values:
|
54 |
+
|
55 |
+
- Rule #1: Security is prioritized over everything else.
|
56 |
+
|
57 |
+
> Whenever there is a conflict between security and some other property,
|
58 |
+
> security will be favored. For example, the library has runtime tests,
|
59 |
+
> which make it slower, but will hopefully stop it from encrypting stuff
|
60 |
+
> if the platform it's running on is broken.
|
61 |
+
|
62 |
+
- Rule #2: It should be difficult to misuse the library.
|
63 |
+
|
64 |
+
> We assume the developers using this library have no experience with
|
65 |
+
> cryptography. We only assume that they know that the "key" is something
|
66 |
+
> you need to encrypt and decrypt the messages, and that it must be kept
|
67 |
+
> secret. Whenever possible, the library should refuse to encrypt or decrypt
|
68 |
+
> messages when it is not being used correctly.
|
69 |
+
|
70 |
+
- Rule #3: The library aims only to be compatible with itself.
|
71 |
+
|
72 |
+
> Other PHP encryption libraries try to support every possible type of
|
73 |
+
> encryption, even the insecure ones (e.g. ECB mode). Because there are so
|
74 |
+
> many options, inexperienced developers must decide whether to use "CBC
|
75 |
+
> mode" or "ECB mode" when both are meaningless terms to them. This
|
76 |
+
> inevitably leads to vulnerabilities.
|
77 |
+
|
78 |
+
> This library will only support one secure mode. A developer using this
|
79 |
+
> library will call "encrypt" and "decrypt" methods without worrying about
|
80 |
+
> how they are implemented.
|
81 |
+
|
82 |
+
- Rule #4: The library should require no special installation.
|
83 |
+
|
84 |
+
> Some PHP encryption libraries, like libsodium-php, are not straightforward
|
85 |
+
> to install and cannot packaged with "just download and extract"
|
86 |
+
> applications. This library will always be just a handful of PHP files that
|
87 |
+
> you can copy to your source tree and require().
|
88 |
+
|
89 |
+
Publishing Releases
|
90 |
+
--------------------
|
91 |
+
|
92 |
+
To make a release, you will need to install [composer](https://getcomposer.org/)
|
93 |
+
and [box](https://github.com/box-project/box2) on your system. They will need to
|
94 |
+
be available in your `$PATH` so that running the commands `composer` and `box`
|
95 |
+
in your terminal run them, respectively. You will also need the private key for
|
96 |
+
signing (ID: 7B4B2D98) available.
|
97 |
+
|
98 |
+
Once you have those tools installed and the key available follow these steps:
|
99 |
+
|
100 |
+
**Remember to set the version number in `composer.json`!**
|
101 |
+
|
102 |
+
Make a fresh clone of the repository:
|
103 |
+
|
104 |
+
```
|
105 |
+
git clone <url>
|
106 |
+
```
|
107 |
+
|
108 |
+
Check out the branch you want to release:
|
109 |
+
|
110 |
+
```
|
111 |
+
git checkout <branchname>
|
112 |
+
```
|
113 |
+
|
114 |
+
Check that the version number in composer.json is correct:
|
115 |
+
|
116 |
+
```
|
117 |
+
cat composer.json
|
118 |
+
```
|
119 |
+
|
120 |
+
Check that the version number and support lifetime in README.md are correct:
|
121 |
+
|
122 |
+
```
|
123 |
+
cat README.md
|
124 |
+
```
|
125 |
+
|
126 |
+
Run the tests:
|
127 |
+
|
128 |
+
```
|
129 |
+
composer install
|
130 |
+
./test.sh
|
131 |
+
```
|
132 |
+
|
133 |
+
Generate the `.phar`:
|
134 |
+
|
135 |
+
```
|
136 |
+
cd dist
|
137 |
+
make build-phar
|
138 |
+
```
|
139 |
+
|
140 |
+
Test the `.phar`:
|
141 |
+
|
142 |
+
```
|
143 |
+
cd ../
|
144 |
+
./test.sh dist/defuse-crypto.phar
|
145 |
+
```
|
146 |
+
|
147 |
+
Sign the `.phar`:
|
148 |
+
|
149 |
+
```
|
150 |
+
cd dist
|
151 |
+
make sign-phar
|
152 |
+
```
|
153 |
+
|
154 |
+
Tag the release:
|
155 |
+
|
156 |
+
```
|
157 |
+
git -c user.signingkey=7B4B2D98 tag -s "<TAG NAME>" -m "<TAG MESSAGE>"
|
158 |
+
```
|
159 |
+
|
160 |
+
`<TAG NAME>` should be in the format `v2.0.0` and `<TAG MESSAGE>` should look
|
161 |
+
like "Release of v2.0.0."
|
162 |
+
|
163 |
+
Push the tag to github, then use the
|
164 |
+
[releases](https://github.com/defuse/php-encryption/releases) page to draft
|
165 |
+
a new release for that tag. Upload the `.phar` and the `.phar.sig` file to be
|
166 |
+
included as part of that release.
|
vendor/defuse/php-encryption/docs/Tutorial.md
ADDED
@@ -0,0 +1,314 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Tutorial
|
2 |
+
=========
|
3 |
+
|
4 |
+
Hello! If you're reading this file, it's because you want to add encryption to
|
5 |
+
one of your PHP projects. My job, as the person writing this documentation, is
|
6 |
+
to help you make sure you're doing the right thing and then show you how to use
|
7 |
+
this library to do it. To help me help you, please read the documentation
|
8 |
+
*carefully* and *deliberately*.
|
9 |
+
|
10 |
+
A Word of Caution
|
11 |
+
------------------
|
12 |
+
|
13 |
+
Encryption is not magic dust you can sprinkle on a system to make it more
|
14 |
+
secure. The way encryption is integrated into a system's design needs to be
|
15 |
+
carefully thought out. Sometimes, encryption is the wrong thing to use. Other
|
16 |
+
times, encryption needs to be used in a very specific way in order for it to
|
17 |
+
work as intended. Even if you are sure of what you are doing, we strongly
|
18 |
+
recommend seeking advice from an expert.
|
19 |
+
|
20 |
+
The first step is to think about your application's threat model. Ask yourself
|
21 |
+
the following questions. Who will want to attack my application, and what will
|
22 |
+
they get out of it? Are they trying to steal some information? Trying to alter
|
23 |
+
or destroy some information? Or just trying to make the system go down so people
|
24 |
+
can't access it? Then ask yourself how encryption can help combat those threats.
|
25 |
+
If you're going to add encryption to your application, you should have a very
|
26 |
+
clear idea of exactly which kinds of attacks it's helping to secure your
|
27 |
+
application against. Once you have your threat model, think about what kinds of
|
28 |
+
attacks it *does not* cover, and whether or not you should improve your threat
|
29 |
+
model to include those attacks.
|
30 |
+
|
31 |
+
**This isn't for storing user login passwords:** The most common use of
|
32 |
+
cryptography in web applications is to protect the users' login passwords. If
|
33 |
+
you're trying to use this library to "encrypt" your users' passwords, you're in
|
34 |
+
the wrong place. Passwords shouldn't be *encrypted*, they should be *hashed*
|
35 |
+
with a slow computation-heavy function that makes password guessing attacks more
|
36 |
+
expensive. See [How to Safely Store Your Users' Passwords in
|
37 |
+
2016](https://paragonie.com/blog/2016/02/how-safely-store-password-in-2016).
|
38 |
+
|
39 |
+
**This isn't for encrypting network communication:** Likewise, if you're trying
|
40 |
+
to encrypt messages sent between two parties over the Internet, you don't want
|
41 |
+
to be using this library. For that, set up a TLS connection between the two
|
42 |
+
points, or, if it's a chat app, use the [Signal
|
43 |
+
Protocol](https://whispersystems.org/blog/advanced-ratcheting/).
|
44 |
+
|
45 |
+
What this library provides is symmetric encryption for "data at rest." This
|
46 |
+
means it is not suitable for use in building protocols where "data is in motion"
|
47 |
+
(i.e. moving over a network) except in limited set of cases.
|
48 |
+
|
49 |
+
Please note that **encryption does not, and is not intended to, hide the
|
50 |
+
*length* of the data being encrypted.** For example, it is not safe to encrypt
|
51 |
+
a field in which only a small number of different-length values are possible
|
52 |
+
(e.g. "male" or "female") since it would be possible to tell what the plaintext
|
53 |
+
is by looking at the length of the ciphertext. In order to do this safely, it is
|
54 |
+
your responsibility to, before encrypting, pad the data out to the length of the
|
55 |
+
longest string that will ever be encrypted. This way, all plaintexts are the
|
56 |
+
same length, and no information about the plaintext can be gleaned from the
|
57 |
+
length of the ciphertext.
|
58 |
+
|
59 |
+
Getting the Code
|
60 |
+
-----------------
|
61 |
+
|
62 |
+
There are several different ways to obtain this library's code and to add it to
|
63 |
+
your project. Even if you've already cloned the code from GitHub, you should
|
64 |
+
take steps to verify the cryptographic signatures to make sure the code you got
|
65 |
+
was not intercepted and modified by an attacker.
|
66 |
+
|
67 |
+
Please head over to the [**Installing and
|
68 |
+
Verifying**](InstallingAndVerifying.md) documentation to get the code, and then
|
69 |
+
come back here to continue the tutorial.
|
70 |
+
|
71 |
+
Using the Library
|
72 |
+
------------------
|
73 |
+
|
74 |
+
I'm going to assume you know what symmetric encryption is, and the difference
|
75 |
+
between symmetric and asymmetric encryption. If you don't, I recommend taking
|
76 |
+
[Dan Boneh's Cryptography I course](https://www.coursera.org/learn/crypto/) on
|
77 |
+
Coursera.
|
78 |
+
|
79 |
+
To give you a quick introduction to the library, I'm going to explain how it
|
80 |
+
would be used in two sterotypical scenarios. Hopefully, one of these sterotypes
|
81 |
+
is close enough to what you want to do that you'll be able to figure out what
|
82 |
+
needs to be different on your own.
|
83 |
+
|
84 |
+
### Formal Documentation
|
85 |
+
|
86 |
+
While this tutorial should get you up and running fast, it's important to
|
87 |
+
understand how this library behaves. Please make sure to read the formal
|
88 |
+
documentation of all of the functions you're using, since there are some
|
89 |
+
important security warnings there.
|
90 |
+
|
91 |
+
The following classes are available for you to use:
|
92 |
+
|
93 |
+
- [Crypto](classes/Crypto.md): Encrypting and decrypting strings.
|
94 |
+
- [File](classes/File.md): Encrypting and decrypting files.
|
95 |
+
- [Key](classes/Key.md): Represents a secret encryption key.
|
96 |
+
- [KeyProtectedByPassword](classes/KeyProtectedByPassword.md): Represents
|
97 |
+
a secret encryption key that needs to be "unlocked" by a password before it
|
98 |
+
can be used.
|
99 |
+
|
100 |
+
### Scenario #1: Keep data secret from the database administrator
|
101 |
+
|
102 |
+
In this scenario, our threat model is as follows. Alice is a server
|
103 |
+
administrator responsible for managing a trusted web server. Eve is a database
|
104 |
+
administrator responsible for managing a database server. Dave is a web
|
105 |
+
developer working on code that will eventually run on the trusted web server.
|
106 |
+
|
107 |
+
Let's say Alice and Dave trust each other, and Alice is going to host Dave's
|
108 |
+
application on her server. But both Alice and Dave don't trust Eve. They know
|
109 |
+
Eve is a good database administrator, but she might have incentive to steal the
|
110 |
+
data from the database. They want to keep some of the web application's data
|
111 |
+
secret from Eve.
|
112 |
+
|
113 |
+
In order to do that, Alice will use the included `generate-defuse-key` script
|
114 |
+
which generates a random encryption key and prints it to standard output:
|
115 |
+
|
116 |
+
```sh
|
117 |
+
$ composer require defuse/php-encryption
|
118 |
+
$ vendor/bin/generate-defuse-key
|
119 |
+
```
|
120 |
+
|
121 |
+
Alice will run this script once and save the output to a configuration file, say
|
122 |
+
in `/etc/daveapp-secret-key.txt` and set the file permissions so that only the
|
123 |
+
user that the website PHP scripts run as can access it.
|
124 |
+
|
125 |
+
Dave will write his code to load the key from the configuration file:
|
126 |
+
|
127 |
+
```php
|
128 |
+
<?php
|
129 |
+
use Defuse\Crypto\Key;
|
130 |
+
|
131 |
+
function loadEncryptionKeyFromConfig()
|
132 |
+
{
|
133 |
+
$keyAscii = // ... load the contents of /etc/daveapp-secret-key.txt
|
134 |
+
return Key::loadFromAsciiSafeString($keyAscii);
|
135 |
+
}
|
136 |
+
```
|
137 |
+
|
138 |
+
Then, whenever Dave wants to save a secret value to the database, he will first
|
139 |
+
encrypt it:
|
140 |
+
|
141 |
+
```php
|
142 |
+
<?php
|
143 |
+
use Defuse\Crypto\Crypto;
|
144 |
+
|
145 |
+
// ...
|
146 |
+
$key = loadEncryptionKeyFromConfig();
|
147 |
+
// ...
|
148 |
+
$ciphertext = Crypto::encrypt($secret_data, $key);
|
149 |
+
// ... save $ciphertext into the database ...
|
150 |
+
```
|
151 |
+
|
152 |
+
Whenever Dave wants to get the value back from the database, he must decrypt it
|
153 |
+
using the same key:
|
154 |
+
|
155 |
+
```php
|
156 |
+
<?php
|
157 |
+
use Defuse\Crypto\Crypto;
|
158 |
+
|
159 |
+
// ...
|
160 |
+
$key = loadEncryptionKeyFromConfig();
|
161 |
+
// ...
|
162 |
+
$ciphertext = // ... load $ciphertext from the database
|
163 |
+
try {
|
164 |
+
$secret_data = Crypto::decrypt($ciphertext, $key);
|
165 |
+
} catch (\Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
|
166 |
+
// An attack! Either the wrong key was loaded, or the ciphertext has
|
167 |
+
// changed since it was created -- either corrupted in the database or
|
168 |
+
// intentionally modified by Eve trying to carry out an attack.
|
169 |
+
|
170 |
+
// ... handle this case in a way that's suitable to your application ...
|
171 |
+
}
|
172 |
+
```
|
173 |
+
|
174 |
+
Note that if anyone ever steals the key from Alice's server, they can decrypt
|
175 |
+
all of the ciphertexts that are stored in the database. As part of our threat
|
176 |
+
model, we are assuming Alice's server administration skills and Dave's secure
|
177 |
+
coding skills are good enough to stop Eve from being able to steal the key.
|
178 |
+
Under those assumptions, this solution will prevent Eve from seeing data that's
|
179 |
+
stored in the database.
|
180 |
+
|
181 |
+
However, notice that our threat model says nothing about what could happen if
|
182 |
+
Eve wants to *modify* the data. With this solution, Eve will not be able to
|
183 |
+
alter any individual ciphertext (because each ciphertext has its own
|
184 |
+
cryptographic integrity check), but Eve *will* be able to swap ciphertexts for
|
185 |
+
one another, and revert ciphertexts to what they used to be at previous times.
|
186 |
+
If we needed to defend against such attacks, we would have to re-design our
|
187 |
+
threat model and come up with a different solution.
|
188 |
+
|
189 |
+
### Scenario #2: Encrypting account data with the user's login password
|
190 |
+
|
191 |
+
This scenario is like Scenario 1, but subtly different. The threat model is as
|
192 |
+
follows. We have Alice, a server administrator, and Dave, the developer. Alice
|
193 |
+
and Dave trust each other, and Alice wants to host Dave's web application,
|
194 |
+
including its database, on her server. Alice is worried about her server getting
|
195 |
+
hacked. The application will store the users' credit card numbers, and Alice
|
196 |
+
wants to protect them in case the server gets hacked.
|
197 |
+
|
198 |
+
We can model the situation like this: after the server gets hacked, the attacker
|
199 |
+
will have read and write access to all data on it until the attack is detected
|
200 |
+
and Alice rebuilds the server. We'll call the time the attacker has access to
|
201 |
+
the server the *exposure window.* One idea to minimize loss is to encrypt the
|
202 |
+
users' credit card numbers using a key made from their login password. Then, as
|
203 |
+
long as the users all have strong passwords, and they are never logged in during
|
204 |
+
the exposure window, their credit cards will be protected from the attacker.
|
205 |
+
|
206 |
+
To implement this, Dave will use the `KeyProtectedByPassword` class. When a new
|
207 |
+
user account is created, Dave will save a new key to their account, one that's
|
208 |
+
protected by their login password:
|
209 |
+
|
210 |
+
```php
|
211 |
+
<?php
|
212 |
+
use Defuse\Crypto\KeyProtectedByPassword;
|
213 |
+
|
214 |
+
function CreateUserAccount($username, $password)
|
215 |
+
{
|
216 |
+
// ... other user account creation stuff, including password hashing
|
217 |
+
|
218 |
+
$protected_key = KeyProtectedByPassword::createRandomPasswordProtectedKey($password);
|
219 |
+
$protected_key_encoded = $protected_key->saveToAsciiSafeString();
|
220 |
+
// ... save $protected_key_encoded into the user's account record
|
221 |
+
}
|
222 |
+
```
|
223 |
+
|
224 |
+
**WARNING:** Because of the way `KeyProtectedByPassword` is implemented, knowing
|
225 |
+
`SHA256($password)` is enough to decrypt a `KeyProtectedByPassword`. To be
|
226 |
+
secure, your application MUST NOT EVER compute `SHA256($password)` and use or
|
227 |
+
store it for any reason. You must also make sure that other libraries your
|
228 |
+
application is using don't compute it either.
|
229 |
+
|
230 |
+
Then, when the user logs in, Dave's code will load the protected key from the
|
231 |
+
user's account record, unlock it to get a `Key` object, and save the `Key`
|
232 |
+
object somewhere safe (like temporary memory-backed session storage). Note that
|
233 |
+
wherever Dave's code saves the key, it must be destroyed once the user logs out,
|
234 |
+
or else the attacker might be able to find users' keys even if they were never
|
235 |
+
logged in during the attack.
|
236 |
+
|
237 |
+
```php
|
238 |
+
<?php
|
239 |
+
use Defuse\Crypto\KeyProtectedByPassword;
|
240 |
+
|
241 |
+
// ... authenticate the user using a good password hashing scheme
|
242 |
+
// keep the user's password in $password
|
243 |
+
|
244 |
+
$protected_key_encoded = // ... load it from the user's account record
|
245 |
+
$protected_key = KeyProtectedByPassword::loadFromAsciiSafeString($protected_key_encoded);
|
246 |
+
$user_key = $protected_key->unlockKey($password);
|
247 |
+
$user_key_encoded = $user_key->saveToAsciiSafeString();
|
248 |
+
// ... save $user_key_encoded in the session
|
249 |
+
```
|
250 |
+
|
251 |
+
```php
|
252 |
+
<?php
|
253 |
+
// ... when the user is logging out ...
|
254 |
+
// ... securely wipe the saved $user_key_encoded from the system ...
|
255 |
+
```
|
256 |
+
|
257 |
+
When a user adds their credit card number, Dave's code will get the key from the
|
258 |
+
session and use it to encrypt the credit card number:
|
259 |
+
|
260 |
+
```php
|
261 |
+
<?php
|
262 |
+
use Defuse\Crypto\Crypto;
|
263 |
+
use Defuse\Crypto\Key;
|
264 |
+
|
265 |
+
// ...
|
266 |
+
|
267 |
+
$user_key_encoded = // ... get it out of the session ...
|
268 |
+
$user_key = Key::loadFromAsciiSafeString($user_key_encoded);
|
269 |
+
|
270 |
+
// ...
|
271 |
+
|
272 |
+
$credit_card_number = // ... get credit card number from the user
|
273 |
+
$encrypted_card_number = Crypto::encrypt($credit_card_number, $user_key);
|
274 |
+
// ... save $encrypted_card_number in the database
|
275 |
+
```
|
276 |
+
|
277 |
+
When the application needs to use the credit card number, it will decrypt it:
|
278 |
+
|
279 |
+
```php
|
280 |
+
<?php
|
281 |
+
use Defuse\Crypto\Crypto;
|
282 |
+
use Defuse\Crypto\Key;
|
283 |
+
|
284 |
+
// ...
|
285 |
+
|
286 |
+
$user_key_encoded = // ... get it out of the session
|
287 |
+
$user_key = Key::loadFromAsciiSafeString($user_key_encoded);
|
288 |
+
|
289 |
+
// ...
|
290 |
+
|
291 |
+
$encrypted_card_number = // ... load it from the database ...
|
292 |
+
try {
|
293 |
+
$credit_card_number = Crypto::decrypt($encrypted_card_number, $user_key);
|
294 |
+
} catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
|
295 |
+
// Either there's a bug in our code, we're trying to decrypt with the
|
296 |
+
// wrong key, or the encrypted credit card number was corrupted in the
|
297 |
+
// database.
|
298 |
+
|
299 |
+
// ... handle this case ...
|
300 |
+
}
|
301 |
+
```
|
302 |
+
|
303 |
+
With all caveats carefully heeded, this solution limits credit card number
|
304 |
+
exposure in the case where Alice's server gets hacked for a short amount of
|
305 |
+
time. Remember to think about the attacks that *aren't* included in our threat
|
306 |
+
model. The attacker is still free to do all sorts of harmful things like
|
307 |
+
modifying the server's data which may go undetected if Alice doesn't have secure
|
308 |
+
backups to compare against.
|
309 |
+
|
310 |
+
Getting Help
|
311 |
+
-------------
|
312 |
+
|
313 |
+
If you're having difficulty using the library, see if your problem is already
|
314 |
+
solved by an answer in the [FAQ](FAQ.md).
|
vendor/defuse/php-encryption/docs/UpgradingFromV1.2.md
ADDED
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Upgrading From Version 1.2
|
2 |
+
===========================
|
3 |
+
|
4 |
+
With version 2.0.0 of this library came major changes to the ciphertext format,
|
5 |
+
algorithms used for encryption, and API.
|
6 |
+
|
7 |
+
In version 1.2, keys were represented by 16-byte string variables. In version
|
8 |
+
2.0.0, keys are represented by objects, instances of the `Key` class. This
|
9 |
+
change was made in order to make it harder to misuse the API. For example, in
|
10 |
+
version 1.2, you could pass in *any* 16-byte string, but in version 2.0.0 you
|
11 |
+
need a `Key` object, which you can only get if you're "doing the right thing."
|
12 |
+
|
13 |
+
This means that for all of your old version 1.2 keys, you'll have to:
|
14 |
+
|
15 |
+
1. Generate a new version 2.0.0 key.
|
16 |
+
2. For all of the ciphertexts encrypted under the old key:
|
17 |
+
1. Decrypt the ciphertext using the old version 1.2 key.
|
18 |
+
2. Re-encrypt it using the new version 2.0.0 key.
|
19 |
+
|
20 |
+
Use the special `Crypto::legacyDecrypt()` method to decrypt the old ciphertexts
|
21 |
+
using the old key and then re-encrypt them using `Crypto::encrypt()` with the
|
22 |
+
new key. Your code will look something like the following. To avoid data loss,
|
23 |
+
securely back up your keys and data before running your upgrade code.
|
24 |
+
|
25 |
+
```php
|
26 |
+
<?php
|
27 |
+
|
28 |
+
// ...
|
29 |
+
|
30 |
+
$legacy_ciphertext = // ... get the ciphertext you want to upgrade ...
|
31 |
+
$legacy_key = // ... get the key to decrypt this ciphertext ...
|
32 |
+
|
33 |
+
// Generate the new key that we'll re-encrypt the ciphertext with.
|
34 |
+
$new_key = Key::createNewRandomKey();
|
35 |
+
// ... save it somewhere ...
|
36 |
+
|
37 |
+
// Decrypt it.
|
38 |
+
try {
|
39 |
+
$plaintext = Crypto::legacyDecrypt($legacy_ciphertext, $legacy_key);
|
40 |
+
} catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex)
|
41 |
+
{
|
42 |
+
// ... TODO: handle this case appropriately ...
|
43 |
+
}
|
44 |
+
|
45 |
+
// Re-encrypt it.
|
46 |
+
$new_ciphertext = Crypto::encrypt($plaintext, $new_key);
|
47 |
+
|
48 |
+
// ... replace the old $legacy_ciphertext with the new $new_ciphertext
|
49 |
+
|
50 |
+
// ...
|
51 |
+
```
|
vendor/defuse/php-encryption/docs/classes/Crypto.md
ADDED
@@ -0,0 +1,280 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Class: Defuse\Crypto\Crypto
|
2 |
+
============================
|
3 |
+
|
4 |
+
The `Crypto` class provides encryption and decryption of strings either using
|
5 |
+
a secret key or secret password. For encryption and decryption of large files,
|
6 |
+
see the `File` class.
|
7 |
+
|
8 |
+
This code for this class is in `src/Crypto.php`.
|
9 |
+
|
10 |
+
Instance Methods
|
11 |
+
-----------------
|
12 |
+
|
13 |
+
This class has no instance methods.
|
14 |
+
|
15 |
+
Static Methods
|
16 |
+
---------------
|
17 |
+
|
18 |
+
### Crypto::encrypt($plaintext, Key $key, $raw\_binary = false)
|
19 |
+
|
20 |
+
**Description:**
|
21 |
+
|
22 |
+
Encrypts a plaintext string using a secret key.
|
23 |
+
|
24 |
+
**Parameters:**
|
25 |
+
|
26 |
+
1. `$plaintext` is the string to encrypt.
|
27 |
+
2. `$key` is an instance of `Key` containing the secret key for encryption.
|
28 |
+
3. `$raw_binary` determines whether the output will be a byte string (true) or
|
29 |
+
hex encoded (false, the default).
|
30 |
+
|
31 |
+
**Return value:**
|
32 |
+
|
33 |
+
Returns a ciphertext string representing `$plaintext` encrypted with the key
|
34 |
+
`$key`. Knowledge of `$key` is required in order to decrypt the ciphertext and
|
35 |
+
recover the plaintext.
|
36 |
+
|
37 |
+
**Exceptions:**
|
38 |
+
|
39 |
+
- `Defuse\Crypto\Exception\EnvironmentIsBrokenException` is thrown either when
|
40 |
+
the platform the code is running on cannot safely perform encryption for some
|
41 |
+
reason (e.g. it lacks a secure random number generator), or the runtime tests
|
42 |
+
detected a bug in this library.
|
43 |
+
|
44 |
+
- `\TypeError` is thrown if the parameters are not of the expected types.
|
45 |
+
|
46 |
+
**Side-effects and performance:**
|
47 |
+
|
48 |
+
This method runs a small and very fast set of self-tests if it is the very first
|
49 |
+
time one of the `Crypto` methods has been called. The performance overhead is
|
50 |
+
negligible and can be safely ignored in all applications.
|
51 |
+
|
52 |
+
**Cautions:**
|
53 |
+
|
54 |
+
The ciphertext returned by this method is decryptable by anyone with knowledge
|
55 |
+
of the key `$key`. It is the caller's responsibility to keep `$key` secret.
|
56 |
+
Where `$key` should be stored is up to the caller and depends on the threat
|
57 |
+
model the caller is designing their application under. If you are unsure where
|
58 |
+
to store `$key`, consult with a professional cryptographer to get help designing
|
59 |
+
your application.
|
60 |
+
|
61 |
+
Please note that **encryption does not, and is not intended to, hide the
|
62 |
+
*length* of the data being encrypted.** For example, it is not safe to encrypt
|
63 |
+
a field in which only a small number of different-length values are possible
|
64 |
+
(e.g. "male" or "female") since it would be possible to tell what the plaintext
|
65 |
+
is by looking at the length of the ciphertext. In order to do this safely, it is
|
66 |
+
your responsibility to, before encrypting, pad the data out to the length of the
|
67 |
+
longest string that will ever be encrypted. This way, all plaintexts are the
|
68 |
+
same length, and no information about the plaintext can be gleaned from the
|
69 |
+
length of the ciphertext.
|
70 |
+
|
71 |
+
### Crypto::decrypt($ciphertext, Key $key, $raw\_binary = false)
|
72 |
+
|
73 |
+
**Description:**
|
74 |
+
|
75 |
+
Decrypts a ciphertext string using a secret key.
|
76 |
+
|
77 |
+
**Parameters:**
|
78 |
+
|
79 |
+
1. `$ciphertext` is the ciphertext to be decrypted.
|
80 |
+
2. `$key` is an instance of `Key` containing the secret key for decryption.
|
81 |
+
3. `$raw_binary` must have the same value as the `$raw_binary` given to the
|
82 |
+
call to `encrypt()` that generated `$ciphertext`.
|
83 |
+
|
84 |
+
**Return value:**
|
85 |
+
|
86 |
+
If the decryption succeeds, returns a string containing the same value as the
|
87 |
+
string that was passed to `encrypt()` when `$ciphertext` was produced. Upon
|
88 |
+
a successful return, the caller can be assured that `$ciphertext` could not have
|
89 |
+
been produced except by someone with knowledge of `$key`.
|
90 |
+
|
91 |
+
**Exceptions:**
|
92 |
+
|
93 |
+
- `Defuse\Crypto\Exception\EnvironmentIsBrokenException` is thrown either when
|
94 |
+
the platform the code is running on cannot safely perform encryption for some
|
95 |
+
reason (e.g. it lacks a secure random number generator), or the runtime tests
|
96 |
+
detected a bug in this library.
|
97 |
+
|
98 |
+
- `Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException` is thrown if
|
99 |
+
the `$key` is not the correct key for the given ciphertext, or if the
|
100 |
+
ciphertext has been modified (possibly maliciously). There is no way to
|
101 |
+
distinguish between these two cases.
|
102 |
+
|
103 |
+
- `\TypeError` is thrown if the parameters are not of the expected types.
|
104 |
+
|
105 |
+
**Side-effects and performance:**
|
106 |
+
|
107 |
+
This method runs a small and very fast set of self-tests if it is the very first
|
108 |
+
time one of the `Crypto` methods has been called. The performance overhead is
|
109 |
+
negligible and can be safely ignored in all applications.
|
110 |
+
|
111 |
+
**Cautions:**
|
112 |
+
|
113 |
+
It is impossible in principle to distinguish between the case where you attempt
|
114 |
+
to decrypt with the wrong key and the case where you attempt to decrypt
|
115 |
+
a modified (corrupted) ciphertext. It is up to the caller how to best deal with
|
116 |
+
this ambiguity, as it depends on the application this library is being used in.
|
117 |
+
If in doubt, consult with a professional cryptographer.
|
118 |
+
|
119 |
+
### Crypto::encryptWithPassword($plaintext, $password, $raw\_binary = false)
|
120 |
+
|
121 |
+
**Description:**
|
122 |
+
|
123 |
+
Encrypts a plaintext string using a secret password.
|
124 |
+
|
125 |
+
**Parameters:**
|
126 |
+
|
127 |
+
1. `$plaintext` is the string to encrypt.
|
128 |
+
2. `$password` is a string containing the secret password used for encryption.
|
129 |
+
3. `$raw_binary` determines whether the output will be a byte string (true) or
|
130 |
+
hex encoded (false, the default).
|
131 |
+
|
132 |
+
**Return value:**
|
133 |
+
|
134 |
+
Returns a ciphertext string representing `$plaintext` encrypted with a key
|
135 |
+
derived from `$password`. Knowledge of `$password` is required in order to
|
136 |
+
decrypt the ciphertext and recover the plaintext.
|
137 |
+
|
138 |
+
**Exceptions:**
|
139 |
+
|
140 |
+
- `Defuse\Crypto\Exception\EnvironmentIsBrokenException` is thrown either when
|
141 |
+
the platform the code is running on cannot safely perform encryption for some
|
142 |
+
reason (e.g. it lacks a secure random number generator), or the runtime tests
|
143 |
+
detected a bug in this library.
|
144 |
+
|
145 |
+
- `\TypeError` is thrown if the parameters are not of the expected types.
|
146 |
+
|
147 |
+
**Side-effects and performance:**
|
148 |
+
|
149 |
+
This method is intentionally slow, using a lot of CPU resources for a fraction
|
150 |
+
of a second. It applies key stretching to the password in order to make password
|
151 |
+
guessing attacks more computationally expensive. If you need a faster way to
|
152 |
+
encrypt multiple ciphertexts under the same password, see the
|
153 |
+
`KeyProtectedByPassword` class.
|
154 |
+
|
155 |
+
This method runs a small and very fast set of self-tests if it is the very first
|
156 |
+
time one of the `Crypto` methods has been called. The performance overhead is
|
157 |
+
negligible and can be safely ignored in all applications.
|
158 |
+
|
159 |
+
**Cautions:**
|
160 |
+
|
161 |
+
PHP stack traces display (portions of) the arguments passed to methods on the
|
162 |
+
call stack. If an exception is thrown inside this call, and it is uncaught, the
|
163 |
+
value of `$password` may be leaked out to an attacker through the stack trace.
|
164 |
+
We recommend configuring PHP to never output stack traces (either displaying
|
165 |
+
them to the user or saving them to log files).
|
166 |
+
|
167 |
+
### Crypto::decryptWithPassword($ciphertext, $password, $raw\_binary = false)
|
168 |
+
|
169 |
+
**Description:**
|
170 |
+
|
171 |
+
Decrypts a ciphertext string using a secret password.
|
172 |
+
|
173 |
+
**Parameters:**
|
174 |
+
|
175 |
+
1. `$ciphertext` is the ciphertext to be decrypted.
|
176 |
+
2. `$password` is a string containing the secret password used for decryption.
|
177 |
+
3. `$raw_binary` must have the same value as the `$raw_binary` given to the
|
178 |
+
call to `encryptWithPassword()` that generated `$ciphertext`.
|
179 |
+
|
180 |
+
**Return value:**
|
181 |
+
|
182 |
+
If the decryption succeeds, returns a string containing the same value as the
|
183 |
+
string that was passed to `encryptWithPassword()` when `$ciphertext` was
|
184 |
+
produced. Upon a successful return, the caller can be assured that `$ciphertext`
|
185 |
+
could not have been produced except by someone with knowledge of `$password`.
|
186 |
+
|
187 |
+
**Exceptions:**
|
188 |
+
|
189 |
+
- `Defuse\Crypto\Exception\EnvironmentIsBrokenException` is thrown either when
|
190 |
+
the platform the code is running on cannot safely perform encryption for some
|
191 |
+
reason (e.g. it lacks a secure random number generator), or the runtime tests
|
192 |
+
detected a bug in this library.
|
193 |
+
|
194 |
+
- `Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException` is thrown if
|
195 |
+
the `$password` is not the correct password for the given ciphertext, or if
|
196 |
+
the ciphertext has been modified (possibly maliciously). There is no way to
|
197 |
+
distinguish between these two cases.
|
198 |
+
|
199 |
+
- `\TypeError` is thrown if the parameters are not of the expected types.
|
200 |
+
|
201 |
+
**Side-effects:**
|
202 |
+
|
203 |
+
This method is intentionally slow. It applies key stretching to the password in
|
204 |
+
order to make password guessing attacks more computationally expensive. If you
|
205 |
+
need a faster way to encrypt multiple ciphertexts under the same password, see
|
206 |
+
the `KeyProtectedByPassword` class.
|
207 |
+
|
208 |
+
This method runs a small and very fast set of self-tests if it is the very first
|
209 |
+
time one of the `Crypto` methods has been called. The performance overhead is
|
210 |
+
negligible and can be safely ignored in all applications.
|
211 |
+
|
212 |
+
**Cautions:**
|
213 |
+
|
214 |
+
PHP stack traces display (portions of) the arguments passed to methods on the
|
215 |
+
call stack. If an exception is thrown inside this call, and it is uncaught, the
|
216 |
+
value of `$password` may be leaked out to an attacker through the stack trace.
|
217 |
+
We recommend configuring PHP to never output stack traces (either displaying
|
218 |
+
them to the user or saving them to log files).
|
219 |
+
|
220 |
+
It is impossible in principle to distinguish between the case where you attempt
|
221 |
+
to decrypt with the wrong password and the case where you attempt to decrypt
|
222 |
+
a modified (corrupted) ciphertext. It is up to the caller how to best deal with
|
223 |
+
this ambiguity, as it depends on the application this library is being used in.
|
224 |
+
If in doubt, consult with a professional cryptographer.
|
225 |
+
|
226 |
+
### Crypto::legacyDecrypt($ciphertext, $key)
|
227 |
+
|
228 |
+
**Description:**
|
229 |
+
|
230 |
+
Decrypts a ciphertext produced by version 1 of this library so that the
|
231 |
+
plaintext can be re-encrypted into a version 2 ciphertext. See [Upgrading from
|
232 |
+
v1.2](../UpgradingFromV1.2.md).
|
233 |
+
|
234 |
+
**Parameters:**
|
235 |
+
|
236 |
+
1. `$ciphertext` is a ciphertext produced by version 1.x of this library.
|
237 |
+
2. `$key` is a 16-byte string (*not* a Key object) containing the key that was
|
238 |
+
used with version 1.x of this library to produce `$ciphertext`.
|
239 |
+
|
240 |
+
**Return value:**
|
241 |
+
|
242 |
+
If the decryption succeeds, returns the string that was encrypted to make
|
243 |
+
`$ciphertext` by version 1.x of this library. Upon a successful return, the
|
244 |
+
caller can be assured that `$ciphertext` could not have been produced except by
|
245 |
+
someone with knowledge of `$key`.
|
246 |
+
|
247 |
+
**Exceptions:**
|
248 |
+
|
249 |
+
- `Defuse\Crypto\Exception\EnvironmentIsBrokenException` is thrown either when
|
250 |
+
the platform the code is running on cannot safely perform encryption for some
|
251 |
+
reason (e.g. it lacks a secure random number generator), or the runtime tests
|
252 |
+
detected a bug in this library.
|
253 |
+
|
254 |
+
- `Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException` is thrown if
|
255 |
+
the `$key` is not the correct key for the given ciphertext, or if the
|
256 |
+
ciphertext has been modified (possibly maliciously). There is no way to
|
257 |
+
distinguish between these two cases.
|
258 |
+
|
259 |
+
- `\TypeError` is thrown if the parameters are not of the expected types.
|
260 |
+
|
261 |
+
**Side-effects:**
|
262 |
+
|
263 |
+
This method runs a small and very fast set of self-tests if it is the very first
|
264 |
+
time one of the `Crypto` methods has been called. The performance overhead is
|
265 |
+
negligible and can be safely ignored in all applications.
|
266 |
+
|
267 |
+
**Cautions:**
|
268 |
+
|
269 |
+
PHP stack traces display (portions of) the arguments passed to methods on the
|
270 |
+
call stack. If an exception is thrown inside this call, and it is uncaught, the
|
271 |
+
value of `$key` may be leaked out to an attacker through the stack trace. We
|
272 |
+
recommend configuring PHP to never output stack traces (either displaying them
|
273 |
+
to the user or saving them to log files).
|
274 |
+
|
275 |
+
It is impossible in principle to distinguish between the case where you attempt
|
276 |
+
to decrypt with the wrong key and the case where you attempt to decrypt
|
277 |
+
a modified (corrupted) ciphertext. It is up to the caller how to best deal with
|
278 |
+
this ambiguity, as it depends on the application this library is being used in.
|
279 |
+
If in doubt, consult with a professional cryptographer.
|
280 |
+
|
vendor/defuse/php-encryption/docs/classes/File.md
ADDED
@@ -0,0 +1,486 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Class: Defuse\Crypto\File
|
2 |
+
==========================
|
3 |
+
|
4 |
+
Instance Methods
|
5 |
+
-----------------
|
6 |
+
|
7 |
+
This class has no instance methods.
|
8 |
+
|
9 |
+
Static Methods
|
10 |
+
---------------
|
11 |
+
|
12 |
+
### File::encryptFile($inputFilename, $outputFilename, Key $key)
|
13 |
+
|
14 |
+
**Description:**
|
15 |
+
|
16 |
+
Encrypts a file using a secret key.
|
17 |
+
|
18 |
+
**Parameters:**
|
19 |
+
|
20 |
+
1. `$inputFilename` is the path to a file containing the plaintext to encrypt.
|
21 |
+
2. `$outputFilename` is the path to save the ciphertext file.
|
22 |
+
3. `$key` is an instance of `Key` containing the secret key for encryption.
|
23 |
+
|
24 |
+
**Behavior:**
|
25 |
+
|
26 |
+
Encrypts the contents of the input file, writing the result to the output file.
|
27 |
+
If the output file already exists, it is overwritten.
|
28 |
+
|
29 |
+
**Return value:**
|
30 |
+
|
31 |
+
Does not return a value.
|
32 |
+
|
33 |
+
**Exceptions:**
|
34 |
+
|
35 |
+
- `Defuse\Crypto\Exception\IOException` is thrown if there is an I/O error.
|
36 |
+
|
37 |
+
- `Defuse\Crypto\Exception\EnvironmentIsBrokenException` is thrown either when
|
38 |
+
the platform the code is running on cannot safely perform encryption for some
|
39 |
+
reason (e.g. it lacks a secure random number generator), or the runtime tests
|
40 |
+
detected a bug in this library.
|
41 |
+
|
42 |
+
**Side-effects and performance:**
|
43 |
+
|
44 |
+
None.
|
45 |
+
|
46 |
+
**Cautions:**
|
47 |
+
|
48 |
+
The ciphertext output by this method is decryptable by anyone with knowledge of
|
49 |
+
the key `$key`. It is the caller's responsibility to keep `$key` secret. Where
|
50 |
+
`$key` should be stored is up to the caller and depends on the threat model the
|
51 |
+
caller is designing their application under. If you are unsure where to store
|
52 |
+
`$key`, consult with a professional cryptographer to get help designing your
|
53 |
+
application.
|
54 |
+
|
55 |
+
Please note that **encryption does not, and is not intended to, hide the
|
56 |
+
*length* of the data being encrypted.** For example, it is not safe to encrypt
|
57 |
+
a field in which only a small number of different-length values are possible
|
58 |
+
(e.g. "male" or "female") since it would be possible to tell what the plaintext
|
59 |
+
is by looking at the length of the ciphertext. In order to do this safely, it is
|
60 |
+
your responsibility to, before encrypting, pad the data out to the length of the
|
61 |
+
longest string that will ever be encrypted. This way, all plaintexts are the
|
62 |
+
same length, and no information about the plaintext can be gleaned from the
|
63 |
+
length of the ciphertext.
|
64 |
+
|
65 |
+
### File::decryptFile($inputFilename, $outputFilename, Key $key)
|
66 |
+
|
67 |
+
**Description:**
|
68 |
+
|
69 |
+
Decrypts a file using a secret key.
|
70 |
+
|
71 |
+
**Parameters:**
|
72 |
+
|
73 |
+
1. `$inputFilename` is the path to a file containing the ciphertext to decrypt.
|
74 |
+
2. `$outputFilename` is the path to save the decrypted plaintext file.
|
75 |
+
3. `$key` is an instance of `Key` containing the secret key for decryption.
|
76 |
+
|
77 |
+
**Behavior:**
|
78 |
+
|
79 |
+
Decrypts the contents of the input file, writing the result to the output file.
|
80 |
+
If the output file already exists, it is overwritten.
|
81 |
+
|
82 |
+
**Return value:**
|
83 |
+
|
84 |
+
Does not return a value.
|
85 |
+
|
86 |
+
**Exceptions:**
|
87 |
+
|
88 |
+
- `Defuse\Crypto\Exception\IOException` is thrown if there is an I/O error.
|
89 |
+
|
90 |
+
- `Defuse\Crypto\Exception\EnvironmentIsBrokenException` is thrown either when
|
91 |
+
the platform the code is running on cannot safely perform encryption for some
|
92 |
+
reason (e.g. it lacks a secure random number generator), or the runtime tests
|
93 |
+
detected a bug in this library.
|
94 |
+
|
95 |
+
- `Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException` is thrown if
|
96 |
+
the `$key` is not the correct key for the given ciphertext, or if the
|
97 |
+
ciphertext has been modified (possibly maliciously). There is no way to
|
98 |
+
distinguish between these two cases.
|
99 |
+
|
100 |
+
**Side-effects and performance:**
|
101 |
+
|
102 |
+
The input ciphertext is processed in two passes. The first pass verifies the
|
103 |
+
integrity and the second pass performs the actual decryption of the file and
|
104 |
+
writing to the output file. This is done in a streaming manner so that only
|
105 |
+
a small part of the file is ever loaded into memory at a time.
|
106 |
+
|
107 |
+
**Cautions:**
|
108 |
+
|
109 |
+
Be aware that when `Defuse\Crypto\WrongKeyOrModifiedCiphertextException` is
|
110 |
+
thrown, some partial plaintext data may have been written to the output. Any
|
111 |
+
plaintext data that is output is guaranteed to be a prefix of the original
|
112 |
+
plaintext (i.e. at worst it was truncated). This can only happen if an attacker
|
113 |
+
modifies the input between the first pass (integrity check) and the second pass
|
114 |
+
(decryption) over the file.
|
115 |
+
|
116 |
+
It is impossible in principle to distinguish between the case where you attempt
|
117 |
+
to decrypt with the wrong key and the case where you attempt to decrypt
|
118 |
+
a modified (corrupted) ciphertext. It is up to the caller how to best deal with
|
119 |
+
this ambiguity, as it depends on the application this library is being used in.
|
120 |
+
If in doubt, consult with a professional cryptographer.
|
121 |
+
|
122 |
+
### File::encryptFileWithPassword($inputFilename, $outputFilename, $password)
|
123 |
+
|
124 |
+
**Description:**
|
125 |
+
|
126 |
+
Encrypts a file with a password.
|
127 |
+
|
128 |
+
**Parameters:**
|
129 |
+
|
130 |
+
1. `$inputFilename` is the path to a file containing the plaintext to encrypt.
|
131 |
+
2. `$outputFilename` is the path to save the ciphertext file.
|
132 |
+
3. `$password` is the password used for decryption.
|
133 |
+
|
134 |
+
**Behavior:**
|
135 |
+
|
136 |
+
Encrypts the contents of the input file, writing the result to the output file.
|
137 |
+
If the output file already exists, it is overwritten.
|
138 |
+
|
139 |
+
**Return value:**
|
140 |
+
|
141 |
+
Does not return a value.
|
142 |
+
|
143 |
+
**Exceptions:**
|
144 |
+
|
145 |
+
- `Defuse\Crypto\Exception\IOException` is thrown if there is an I/O error.
|
146 |
+
|
147 |
+
- `Defuse\Crypto\Exception\EnvironmentIsBrokenException` is thrown either when
|
148 |
+
the platform the code is running on cannot safely perform encryption for some
|
149 |
+
reason (e.g. it lacks a secure random number generator), or the runtime tests
|
150 |
+
detected a bug in this library.
|
151 |
+
|
152 |
+
**Side-effects and performance:**
|
153 |
+
|
154 |
+
This method is intentionally slow, using a lot of CPU resources for a fraction
|
155 |
+
of a second. It applies key stretching to the password in order to make password
|
156 |
+
guessing attacks more computationally expensive. If you need a faster way to
|
157 |
+
encrypt multiple ciphertexts under the same password, see the
|
158 |
+
`KeyProtectedByPassword` class.
|
159 |
+
|
160 |
+
**Cautions:**
|
161 |
+
|
162 |
+
PHP stack traces display (portions of) the arguments passed to methods on the
|
163 |
+
call stack. If an exception is thrown inside this call, and it is uncaught, the
|
164 |
+
value of `$password` may be leaked out to an attacker through the stack trace.
|
165 |
+
We recommend configuring PHP to never output stack traces (either displaying
|
166 |
+
them to the user or saving them to log files).
|
167 |
+
|
168 |
+
Please note that **encryption does not, and is not intended to, hide the
|
169 |
+
*length* of the data being encrypted.** For example, it is not safe to encrypt
|
170 |
+
a field in which only a small number of different-length values are possible
|
171 |
+
(e.g. "male" or "female") since it would be possible to tell what the plaintext
|
172 |
+
is by looking at the length of the ciphertext. In order to do this safely, it is
|
173 |
+
your responsibility to, before encrypting, pad the data out to the length of the
|
174 |
+
longest string that will ever be encrypted. This way, all plaintexts are the
|
175 |
+
same length, and no information about the plaintext can be gleaned from the
|
176 |
+
length of the ciphertext.
|
177 |
+
|
178 |
+
### File::decryptFileWithPassword($inputFilename, $outputFilename, $password)
|
179 |
+
|
180 |
+
**Description:**
|
181 |
+
|
182 |
+
Decrypts a file with a password.
|
183 |
+
|
184 |
+
**Parameters:**
|
185 |
+
|
186 |
+
1. `$inputFilename` is the path to a file containing the ciphertext to decrypt.
|
187 |
+
2. `$outputFilename` is the path to save the decrypted plaintext file.
|
188 |
+
3. `$password` is the password used for decryption.
|
189 |
+
|
190 |
+
**Behavior:**
|
191 |
+
|
192 |
+
Decrypts the contents of the input file, writing the result to the output file.
|
193 |
+
If the output file already exists, it is overwritten.
|
194 |
+
|
195 |
+
**Return value:**
|
196 |
+
|
197 |
+
Does not return a value.
|
198 |
+
|
199 |
+
**Exceptions:**
|
200 |
+
|
201 |
+
- `Defuse\Crypto\Exception\IOException` is thrown if there is an I/O error.
|
202 |
+
|
203 |
+
- `Defuse\Crypto\Exception\EnvironmentIsBrokenException` is thrown either when
|
204 |
+
the platform the code is running on cannot safely perform encryption for some
|
205 |
+
reason (e.g. it lacks a secure random number generator), or the runtime tests
|
206 |
+
detected a bug in this library.
|
207 |
+
|
208 |
+
- `Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException` is thrown if
|
209 |
+
the `$password` is not the correct key for the given ciphertext, or if the
|
210 |
+
ciphertext has been modified (possibly maliciously). There is no way to
|
211 |
+
distinguish between these two cases.
|
212 |
+
|
213 |
+
**Side-effects and performance:**
|
214 |
+
|
215 |
+
This method is intentionally slow, using a lot of CPU resources for a fraction
|
216 |
+
of a second. It applies key stretching to the password in order to make password
|
217 |
+
guessing attacks more computationally expensive. If you need a faster way to
|
218 |
+
encrypt multiple ciphertexts under the same password, see the
|
219 |
+
`KeyProtectedByPassword` class.
|
220 |
+
|
221 |
+
The input ciphertext is processed in two passes. The first pass verifies the
|
222 |
+
integrity and the second pass performs the actual decryption of the file and
|
223 |
+
writing to the output file. This is done in a streaming manner so that only
|
224 |
+
a small part of the file is ever loaded into memory at a time.
|
225 |
+
|
226 |
+
**Cautions:**
|
227 |
+
|
228 |
+
PHP stack traces display (portions of) the arguments passed to methods on the
|
229 |
+
call stack. If an exception is thrown inside this call, and it is uncaught, the
|
230 |
+
value of `$password` may be leaked out to an attacker through the stack trace.
|
231 |
+
We recommend configuring PHP to never output stack traces (either displaying
|
232 |
+
them to the user or saving them to log files).
|
233 |
+
|
234 |
+
Be aware that when `Defuse\Crypto\WrongKeyOrModifiedCiphertextException` is
|
235 |
+
thrown, some partial plaintext data may have been written to the output. Any
|
236 |
+
plaintext data that is output is guaranteed to be a prefix of the original
|
237 |
+
plaintext (i.e. at worst it was truncated). This can only happen if an attacker
|
238 |
+
modifies the input between the first pass (integrity check) and the second pass
|
239 |
+
(decryption) over the file.
|
240 |
+
|
241 |
+
It is impossible in principle to distinguish between the case where you attempt
|
242 |
+
to decrypt with the wrong password and the case where you attempt to decrypt
|
243 |
+
a modified (corrupted) ciphertext. It is up to the caller how to best deal with
|
244 |
+
this ambiguity, as it depends on the application this library is being used in.
|
245 |
+
If in doubt, consult with a professional cryptographer.
|
246 |
+
|
247 |
+
### File::encryptResource($inputHandle, $outputHandle, Key $key)
|
248 |
+
|
249 |
+
**Description:**
|
250 |
+
|
251 |
+
Encrypts a resource (stream) with a secret key.
|
252 |
+
|
253 |
+
**Parameters:**
|
254 |
+
|
255 |
+
1. `$inputHandle` is a handle to a resource (like a file pointer) containing the
|
256 |
+
plaintext to encrypt.
|
257 |
+
2. `$outputHandle` is a handle to a resource (like a file pointer) that the
|
258 |
+
ciphertext will be written to.
|
259 |
+
3. `$key` is an instance of `Key` containing the secret key for encryption.
|
260 |
+
|
261 |
+
**Behavior:**
|
262 |
+
|
263 |
+
Encrypts the data read from the input stream and writes it to the output stream.
|
264 |
+
|
265 |
+
**Return value:**
|
266 |
+
|
267 |
+
Does not return a value.
|
268 |
+
|
269 |
+
**Exceptions:**
|
270 |
+
|
271 |
+
- `Defuse\Crypto\Exception\IOException` is thrown if there is an I/O error.
|
272 |
+
|
273 |
+
- `Defuse\Crypto\Exception\EnvironmentIsBrokenException` is thrown either when
|
274 |
+
the platform the code is running on cannot safely perform encryption for some
|
275 |
+
reason (e.g. it lacks a secure random number generator), or the runtime tests
|
276 |
+
detected a bug in this library.
|
277 |
+
|
278 |
+
**Side-effects and performance:**
|
279 |
+
|
280 |
+
None.
|
281 |
+
|
282 |
+
**Cautions:**
|
283 |
+
|
284 |
+
The ciphertext output by this method is decryptable by anyone with knowledge of
|
285 |
+
the key `$key`. It is the caller's responsibility to keep `$key` secret. Where
|
286 |
+
`$key` should be stored is up to the caller and depends on the threat model the
|
287 |
+
caller is designing their application under. If you are unsure where to store
|
288 |
+
`$key`, consult with a professional cryptographer to get help designing your
|
289 |
+
application.
|
290 |
+
|
291 |
+
Please note that **encryption does not, and is not intended to, hide the
|
292 |
+
*length* of the data being encrypted.** For example, it is not safe to encrypt
|
293 |
+
a field in which only a small number of different-length values are possible
|
294 |
+
(e.g. "male" or "female") since it would be possible to tell what the plaintext
|
295 |
+
is by looking at the length of the ciphertext. In order to do this safely, it is
|
296 |
+
your responsibility to, before encrypting, pad the data out to the length of the
|
297 |
+
longest string that will ever be encrypted. This way, all plaintexts are the
|
298 |
+
same length, and no information about the plaintext can be gleaned from the
|
299 |
+
length of the ciphertext.
|
300 |
+
|
301 |
+
### File::decryptResource($inputHandle, $outputHandle, Key $key)
|
302 |
+
|
303 |
+
**Description:**
|
304 |
+
|
305 |
+
Decrypts a resource (stream) with a secret key.
|
306 |
+
|
307 |
+
**Parameters:**
|
308 |
+
|
309 |
+
1. `$inputHandle` is a handle to a file-backed resource containing the
|
310 |
+
ciphertext to decrypt. It must be a file not a network stream or standard
|
311 |
+
input.
|
312 |
+
2. `$outputHandle` is a handle to a resource (like a file pointer) that the
|
313 |
+
plaintext will be written to.
|
314 |
+
3. `$key` is an instance of `Key` containing the secret key for decryption.
|
315 |
+
|
316 |
+
**Behavior:**
|
317 |
+
|
318 |
+
Decrypts the data read from the input stream and writes it to the output stream.
|
319 |
+
|
320 |
+
**Return value:**
|
321 |
+
|
322 |
+
Does not return a value.
|
323 |
+
|
324 |
+
**Exceptions:**
|
325 |
+
|
326 |
+
- `Defuse\Crypto\Exception\IOException` is thrown if there is an I/O error.
|
327 |
+
|
328 |
+
- `Defuse\Crypto\Exception\EnvironmentIsBrokenException` is thrown either when
|
329 |
+
the platform the code is running on cannot safely perform encryption for some
|
330 |
+
reason (e.g. it lacks a secure random number generator), or the runtime tests
|
331 |
+
detected a bug in this library.
|
332 |
+
|
333 |
+
- `Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException` is thrown if
|
334 |
+
the `$key` is not the correct key for the given ciphertext, or if the
|
335 |
+
ciphertext has been modified (possibly maliciously). There is no way to
|
336 |
+
distinguish between these two cases.
|
337 |
+
|
338 |
+
**Side-effects and performance:**
|
339 |
+
|
340 |
+
The input ciphertext is processed in two passes. The first pass verifies the
|
341 |
+
integrity and the second pass performs the actual decryption of the file and
|
342 |
+
writing to the output file. This is done in a streaming manner so that only
|
343 |
+
a small part of the file is ever loaded into memory at a time.
|
344 |
+
|
345 |
+
**Cautions:**
|
346 |
+
|
347 |
+
Be aware that when `Defuse\Crypto\WrongKeyOrModifiedCiphertextException` is
|
348 |
+
thrown, some partial plaintext data may have been written to the output. Any
|
349 |
+
plaintext data that is output is guaranteed to be a prefix of the original
|
350 |
+
plaintext (i.e. at worst it was truncated). This can only happen if an attacker
|
351 |
+
modifies the input between the first pass (integrity check) and the second pass
|
352 |
+
(decryption) over the file.
|
353 |
+
|
354 |
+
It is impossible in principle to distinguish between the case where you attempt
|
355 |
+
to decrypt with the wrong key and the case where you attempt to decrypt
|
356 |
+
a modified (corrupted) ciphertext. It is up to the caller how to best deal with
|
357 |
+
this ambiguity, as it depends on the application this library is being used in.
|
358 |
+
If in doubt, consult with a professional cryptographer.
|
359 |
+
|
360 |
+
### File::encryptResourceWithPassword($inputHandle, $outputHandle, $password)
|
361 |
+
|
362 |
+
**Description:**
|
363 |
+
|
364 |
+
Encrypts a resource (stream) with a password.
|
365 |
+
|
366 |
+
**Parameters:**
|
367 |
+
|
368 |
+
1. `$inputHandle` is a handle to a resource (like a file pointer) containing the
|
369 |
+
plaintext to encrypt.
|
370 |
+
2. `$outputHandle` is a handle to a resource (like a file pointer) that the
|
371 |
+
ciphertext will be written to.
|
372 |
+
3. `$password` is the password used for encryption.
|
373 |
+
|
374 |
+
**Behavior:**
|
375 |
+
|
376 |
+
Encrypts the data read from the input stream and writes it to the output stream.
|
377 |
+
|
378 |
+
**Return value:**
|
379 |
+
|
380 |
+
Does not return a value.
|
381 |
+
|
382 |
+
**Exceptions:**
|
383 |
+
|
384 |
+
- `Defuse\Crypto\Exception\IOException` is thrown if there is an I/O error.
|
385 |
+
|
386 |
+
- `Defuse\Crypto\Exception\EnvironmentIsBrokenException` is thrown either when
|
387 |
+
the platform the code is running on cannot safely perform encryption for some
|
388 |
+
reason (e.g. it lacks a secure random number generator), or the runtime tests
|
389 |
+
detected a bug in this library.
|
390 |
+
|
391 |
+
**Side-effects and performance:**
|
392 |
+
|
393 |
+
This method is intentionally slow, using a lot of CPU resources for a fraction
|
394 |
+
of a second. It applies key stretching to the password in order to make password
|
395 |
+
guessing attacks more computationally expensive. If you need a faster way to
|
396 |
+
encrypt multiple ciphertexts under the same password, see the
|
397 |
+
`KeyProtectedByPassword` class.
|
398 |
+
|
399 |
+
**Cautions:**
|
400 |
+
|
401 |
+
PHP stack traces display (portions of) the arguments passed to methods on the
|
402 |
+
call stack. If an exception is thrown inside this call, and it is uncaught, the
|
403 |
+
value of `$password` may be leaked out to an attacker through the stack trace.
|
404 |
+
We recommend configuring PHP to never output stack traces (either displaying
|
405 |
+
them to the user or saving them to log files).
|
406 |
+
|
407 |
+
Please note that **encryption does not, and is not intended to, hide the
|
408 |
+
*length* of the data being encrypted.** For example, it is not safe to encrypt
|
409 |
+
a field in which only a small number of different-length values are possible
|
410 |
+
(e.g. "male" or "female") since it would be possible to tell what the plaintext
|
411 |
+
is by looking at the length of the ciphertext. In order to do this safely, it is
|
412 |
+
your responsibility to, before encrypting, pad the data out to the length of the
|
413 |
+
longest string that will ever be encrypted. This way, all plaintexts are the
|
414 |
+
same length, and no information about the plaintext can be gleaned from the
|
415 |
+
length of the ciphertext.
|
416 |
+
|
417 |
+
### File::decryptResourceWithPassword($inputHandle, $outputHandle, $password)
|
418 |
+
|
419 |
+
**Description:**
|
420 |
+
|
421 |
+
Decrypts a resource (stream) with a password.
|
422 |
+
|
423 |
+
**Parameters:**
|
424 |
+
|
425 |
+
1. `$inputHandle` is a handle to a file-backed resource containing the
|
426 |
+
ciphertext to decrypt. It must be a file not a network stream or standard
|
427 |
+
input.
|
428 |
+
2. `$outputHandle` is a handle to a resource (like a file pointer) that the
|
429 |
+
plaintext will be written to.
|
430 |
+
3. `$password` is the password used for decryption.
|
431 |
+
|
432 |
+
**Behavior:**
|
433 |
+
|
434 |
+
Decrypts the data read from the input stream and writes it to the output stream.
|
435 |
+
|
436 |
+
**Return value:**
|
437 |
+
|
438 |
+
Does not return a value.
|
439 |
+
|
440 |
+
**Exceptions:**
|
441 |
+
|
442 |
+
- `Defuse\Crypto\Exception\IOException` is thrown if there is an I/O error.
|
443 |
+
|
444 |
+
- `Defuse\Crypto\Exception\EnvironmentIsBrokenException` is thrown either when
|
445 |
+
the platform the code is running on cannot safely perform encryption for some
|
446 |
+
reason (e.g. it lacks a secure random number generator), or the runtime tests
|
447 |
+
detected a bug in this library.
|
448 |
+
|
449 |
+
- `Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException` is thrown if
|
450 |
+
the `$password` is not the correct key for the given ciphertext, or if the
|
451 |
+
ciphertext has been modified (possibly maliciously). There is no way to
|
452 |
+
distinguish between these two cases.
|
453 |
+
|
454 |
+
**Side-effects and performance:**
|
455 |
+
|
456 |
+
This method is intentionally slow, using a lot of CPU resources for a fraction
|
457 |
+
of a second. It applies key stretching to the password in order to make password
|
458 |
+
guessing attacks more computationally expensive. If you need a faster way to
|
459 |
+
encrypt multiple ciphertexts under the same password, see the
|
460 |
+
`KeyProtectedByPassword` class.
|
461 |
+
|
462 |
+
The input ciphertext is processed in two passes. The first pass verifies the
|
463 |
+
integrity and the second pass performs the actual decryption of the file and
|
464 |
+
writing to the output file. This is done in a streaming manner so that only
|
465 |
+
a small part of the file is ever loaded into memory at a time.
|
466 |
+
|
467 |
+
**Cautions:**
|
468 |
+
|
469 |
+
PHP stack traces display (portions of) the arguments passed to methods on the
|
470 |
+
call stack. If an exception is thrown inside this call, and it is uncaught, the
|
471 |
+
value of `$password` may be leaked out to an attacker through the stack trace.
|
472 |
+
We recommend configuring PHP to never output stack traces (either displaying
|
473 |
+
them to the user or saving them to log files).
|
474 |
+
|
475 |
+
Be aware that when `Defuse\Crypto\WrongKeyOrModifiedCiphertextException` is
|
476 |
+
thrown, some partial plaintext data may have been written to the output. Any
|
477 |
+
plaintext data that is output is guaranteed to be a prefix of the original
|
478 |
+
plaintext (i.e. at worst it was truncated). This can only happen if an attacker
|
479 |
+
modifies the input between the first pass (integrity check) and the second pass
|
480 |
+
(decryption) over the file.
|
481 |
+
|
482 |
+
It is impossible in principle to distinguish between the case where you attempt
|
483 |
+
to decrypt with the wrong password and the case where you attempt to decrypt
|
484 |
+
a modified (corrupted) ciphertext. It is up to the caller how to best deal with
|
485 |
+
this ambiguity, as it depends on the application this library is being used in.
|
486 |
+
If in doubt, consult with a professional cryptographer.
|
vendor/defuse/php-encryption/docs/classes/Key.md
ADDED
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Class: Defuse\Crypto\Key
|
2 |
+
=========================
|
3 |
+
|
4 |
+
The `Key` class represents a secret key used for encrypting and decrypting. Once
|
5 |
+
you have a `Key` instance, you can use it with the `Crypto` class to encrypt and
|
6 |
+
decrypt strings and with the `File` class to encrypt and decrypt files.
|
7 |
+
|
8 |
+
Instance Methods
|
9 |
+
-----------------
|
10 |
+
|
11 |
+
### saveToAsciiSafeString()
|
12 |
+
|
13 |
+
**Description:**
|
14 |
+
|
15 |
+
Saves the encryption key to a string of printable ASCII characters, which can be
|
16 |
+
loaded again into a `Key` instance using `Key::loadFromAsciiSafeString()`.
|
17 |
+
|
18 |
+
**Parameters:**
|
19 |
+
|
20 |
+
This method does not take any parameters.
|
21 |
+
|
22 |
+
**Return value:**
|
23 |
+
|
24 |
+
Returns a string of printable ASCII characters representing this `Key` instance,
|
25 |
+
which can be loaded back into an instance of `Key` using
|
26 |
+
`Key::loadFromAsciiSafeString()`.
|
27 |
+
|
28 |
+
**Exceptions:**
|
29 |
+
|
30 |
+
- `Defuse\Crypto\Exception\EnvironmentIsBrokenException` is thrown either when
|
31 |
+
the platform the code is running on cannot safely perform encryption for some
|
32 |
+
reason (e.g. it lacks a secure random number generator), or the runtime tests
|
33 |
+
detected a bug in this library.
|
34 |
+
|
35 |
+
**Side-effects and performance:**
|
36 |
+
|
37 |
+
None.
|
38 |
+
|
39 |
+
**Cautions:**
|
40 |
+
|
41 |
+
This method currently returns a hexadecimal string. You should not rely on this
|
42 |
+
behavior. For example, it may be improved in the future to return a base64
|
43 |
+
string.
|
44 |
+
|
45 |
+
Static Methods
|
46 |
+
---------------
|
47 |
+
|
48 |
+
### Key::createNewRandomKey()
|
49 |
+
|
50 |
+
**Description:**
|
51 |
+
|
52 |
+
Generates a new random key and returns an instance of `Key`.
|
53 |
+
|
54 |
+
**Parameters:**
|
55 |
+
|
56 |
+
This method does not take any parameters.
|
57 |
+
|
58 |
+
**Return value:**
|
59 |
+
|
60 |
+
Returns an instance of `Key` containing a randomly-generated encryption key.
|
61 |
+
|
62 |
+
**Exceptions:**
|
63 |
+
|
64 |
+
- `Defuse\Crypto\Exception\EnvironmentIsBrokenException` is thrown either when
|
65 |
+
the platform the code is running on cannot safely perform encryption for some
|
66 |
+
reason (e.g. it lacks a secure random number generator), or the runtime tests
|
67 |
+
detected a bug in this library.
|
68 |
+
|
69 |
+
**Side-effects and performance:**
|
70 |
+
|
71 |
+
None.
|
72 |
+
|
73 |
+
**Cautions:**
|
74 |
+
|
75 |
+
None.
|
76 |
+
|
77 |
+
### Key::loadFromAsciiSafeString($saved\_key\_string, $do\_not\_trim = false)
|
78 |
+
|
79 |
+
**Description:**
|
80 |
+
|
81 |
+
Loads an instance of `Key` that was saved to a string by
|
82 |
+
`saveToAsciiSafeString()`.
|
83 |
+
|
84 |
+
By default, this function will call `Encoding::trimTrailingWhitespace()`
|
85 |
+
to remove trailing CR, LF, NUL, TAB, and SPACE characters, which are commonly
|
86 |
+
appended to files when working with text editors.
|
87 |
+
|
88 |
+
**Parameters:**
|
89 |
+
|
90 |
+
1. `$saved_key_string` is the string returned from `saveToAsciiSafeString()`
|
91 |
+
when the original `Key` instance was saved.
|
92 |
+
2. `$do_not_trim` should be set to `TRUE` if you do not wish for the library
|
93 |
+
to automatically strip trailing whitespace from the string.
|
94 |
+
|
95 |
+
**Return value:**
|
96 |
+
|
97 |
+
Returns an instance of `Key` representing the same encryption key as the one
|
98 |
+
that was represented by the `Key` instance that got saved into
|
99 |
+
`$saved_key_string` by a call to `saveToAsciiSafeString()`.
|
100 |
+
|
101 |
+
**Exceptions:**
|
102 |
+
|
103 |
+
- `Defuse\Crypto\Exception\EnvironmentIsBrokenException` is thrown either when
|
104 |
+
the platform the code is running on cannot safely perform encryption for some
|
105 |
+
reason (e.g. it lacks a secure random number generator), or the runtime tests
|
106 |
+
detected a bug in this library.
|
107 |
+
|
108 |
+
- `Defuse\Crypto\Exception\BadFormatException` is thrown whenever
|
109 |
+
`$saved_key_string` does not represent a valid `Key` instance.
|
110 |
+
|
111 |
+
**Side-effects and performance:**
|
112 |
+
|
113 |
+
None.
|
114 |
+
|
115 |
+
**Cautions:**
|
116 |
+
|
117 |
+
None.
|
vendor/defuse/php-encryption/docs/classes/KeyProtectedByPassword.md
ADDED
@@ -0,0 +1,259 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Class: Defuse\Crypto\KeyProtectedByPassword
|
2 |
+
============================================
|
3 |
+
|
4 |
+
The `KeyProtectedByPassword` class represents a key that is "locked" with
|
5 |
+
a password. In order to obtain an instance of `Key` that you can use for
|
6 |
+
encrypting and decrypting, a `KeyProtectedByPassword` must first be "unlocked"
|
7 |
+
by providing the correct password.
|
8 |
+
|
9 |
+
`KeyProtectedByPassword` provides an alternative to using the
|
10 |
+
`encryptWithPassword()`, `decryptWithPassword()`, `encryptFileWithPassword()`,
|
11 |
+
and `decryptFileWithPassword()` methods with several advantages:
|
12 |
+
|
13 |
+
- The slow and computationally-expensive key stretching is run only once when
|
14 |
+
you unlock a `KeyProtectedByPassword` to obtain the `Key`.
|
15 |
+
- You do not have to keep the original password in memory to encrypt and decrypt
|
16 |
+
things. After you've obtained the `Key` from a `KeyProtectedByPassword`, the
|
17 |
+
password is no longer necessary.
|
18 |
+
|
19 |
+
Instance Methods
|
20 |
+
-----------------
|
21 |
+
|
22 |
+
### saveToAsciiSafeString()
|
23 |
+
|
24 |
+
**Description:**
|
25 |
+
|
26 |
+
Saves the protected key to a string of printable ASCII characters, which can be
|
27 |
+
loaded again into a `KeyProtectedByPassword` instance using
|
28 |
+
`KeyProtectedByPassword::loadFromAsciiSafeString()`.
|
29 |
+
|
30 |
+
**Parameters:**
|
31 |
+
|
32 |
+
This method does not take any parameters.
|
33 |
+
|
34 |
+
**Return value:**
|
35 |
+
|
36 |
+
Returns a string of printable ASCII characters representing this
|
37 |
+
`KeyProtectedByPassword` instance, which can be loaded back into an instance of
|
38 |
+
`KeyProtectedByPassword` using
|
39 |
+
`KeyProtectedByPassword::loadFromAsciiSafeString()`.
|
40 |
+
|
41 |
+
**Exceptions:**
|
42 |
+
|
43 |
+
- `Defuse\Crypto\Exception\EnvironmentIsBrokenException` is thrown either when
|
44 |
+
the platform the code is running on cannot safely perform encryption for some
|
45 |
+
reason (e.g. it lacks a secure random number generator), or the runtime tests
|
46 |
+
detected a bug in this library.
|
47 |
+
|
48 |
+
**Side-effects and performance:**
|
49 |
+
|
50 |
+
None.
|
51 |
+
|
52 |
+
**Cautions:**
|
53 |
+
|
54 |
+
This method currently returns a hexadecimal string. You should not rely on this
|
55 |
+
behavior. For example, it may be improved in the future to return a base64
|
56 |
+
string.
|
57 |
+
|
58 |
+
### unlockKey($password)
|
59 |
+
|
60 |
+
**Description:**
|
61 |
+
|
62 |
+
Unlocks the password-protected key, obtaining a `Key` which can be used for
|
63 |
+
encryption and decryption.
|
64 |
+
|
65 |
+
**Parameters:**
|
66 |
+
|
67 |
+
1. `$password` is the password required to unlock this `KeyProtectedByPassword`
|
68 |
+
to obtain the `Key`.
|
69 |
+
|
70 |
+
**Return value:**
|
71 |
+
|
72 |
+
If `$password` is the correct password, then this method returns an instance of
|
73 |
+
the `Key` class.
|
74 |
+
|
75 |
+
**Exceptions:**
|
76 |
+
|
77 |
+
- `Defuse\Crypto\Exception\EnvironmentIsBrokenException` is thrown either when
|
78 |
+
the platform the code is running on cannot safely perform encryption for some
|
79 |
+
reason (e.g. it lacks a secure random number generator), or the runtime tests
|
80 |
+
detected a bug in this library.
|
81 |
+
|
82 |
+
- `Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException` is thrown if
|
83 |
+
either the given `$password` is not the correct password for this
|
84 |
+
`KeyProtectedByPassword` or the ciphertext stored internally by this object
|
85 |
+
has been modified, i.e. it was accidentally corrupted or intentionally
|
86 |
+
corrupted by an attacker. There is no way for the caller to distinguish
|
87 |
+
between these two cases.
|
88 |
+
|
89 |
+
**Side-effects and performance:**
|
90 |
+
|
91 |
+
This method runs a small and very fast set of self-tests if it is the very first
|
92 |
+
time this method or one of the `Crypto` methods has been called. The performance
|
93 |
+
overhead is negligible and can be safely ignored in all applications.
|
94 |
+
|
95 |
+
**Cautions:**
|
96 |
+
|
97 |
+
PHP stack traces display (portions of) the arguments passed to methods on the
|
98 |
+
call stack. If an exception is thrown inside this call, and it is uncaught, the
|
99 |
+
value of `$password` may be leaked out to an attacker through the stack trace.
|
100 |
+
We recommend configuring PHP to never output stack traces (either displaying
|
101 |
+
them to the user or saving them to log files).
|
102 |
+
|
103 |
+
It is impossible in principle to distinguish between the case where you attempt
|
104 |
+
to unlock with the wrong password and the case where you attempt to unlock
|
105 |
+
a modified (corrupted) `KeyProtectedByPassword`. It is up to the caller how to
|
106 |
+
best deal with this ambiguity, as it depends on the application this library is
|
107 |
+
being used in. If in doubt, consult with a professional cryptographer.
|
108 |
+
|
109 |
+
### changePassword($current\_password, $new\_password)
|
110 |
+
|
111 |
+
**Description:**
|
112 |
+
|
113 |
+
Changes the password, so that calling `unlockKey` on this object in the future
|
114 |
+
will require you to pass `$new\_password` instead of the old password. It is
|
115 |
+
your responsibility to overwrite all stored copies of this
|
116 |
+
`KeyProtectedByPassword`. Any copies you leave lying around can still be
|
117 |
+
decrypted with the old password.
|
118 |
+
|
119 |
+
**Parameters:**
|
120 |
+
|
121 |
+
1. `$current\_password` is the password that this `KeyProtectedByPassword` is
|
122 |
+
currently protected with.
|
123 |
+
2. `$new\_password` is the new password, which the `KeyProtectedByPassword` will
|
124 |
+
be protected with once this operation completes.
|
125 |
+
|
126 |
+
**Return value:**
|
127 |
+
|
128 |
+
If `$current\_password` is the correct password, then this method updates itself
|
129 |
+
to be protected with the new password, and also returns itself.
|
130 |
+
|
131 |
+
**Exceptions:**
|
132 |
+
|
133 |
+
- `Defuse\Crypto\Exception\EnvironmentIsBrokenException` is thrown either when
|
134 |
+
the platform the code is running on cannot safely perform encryption for some
|
135 |
+
reason (e.g. it lacks a secure random number generator), or the runtime tests
|
136 |
+
detected a bug in this library.
|
137 |
+
|
138 |
+
- `Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException` is thrown if
|
139 |
+
either the given `$current\_password` is not the correct password for this
|
140 |
+
`KeyProtectedByPassword` or the ciphertext stored internally by this object
|
141 |
+
has been modified, i.e. it was accidentally corrupted or intentionally
|
142 |
+
corrupted by an attacker. There is no way for the caller to distinguish
|
143 |
+
between these two cases.
|
144 |
+
|
145 |
+
**Side-effects and performance:**
|
146 |
+
|
147 |
+
This method runs a small and very fast set of self-tests if it is the very first
|
148 |
+
time this method or one of the `Crypto` methods has been called. The performance
|
149 |
+
overhead is negligible and can be safely ignored in all applications.
|
150 |
+
|
151 |
+
**Cautions:**
|
152 |
+
|
153 |
+
PHP stack traces display (portions of) the arguments passed to methods on the
|
154 |
+
call stack. If an exception is thrown inside this call, and it is uncaught, the
|
155 |
+
value of `$password` may be leaked out to an attacker through the stack trace.
|
156 |
+
We recommend configuring PHP to never output stack traces (either displaying
|
157 |
+
them to the user or saving them to log files).
|
158 |
+
|
159 |
+
It is impossible in principle to distinguish between the case where you attempt
|
160 |
+
to unlock with the wrong password and the case where you attempt to unlock
|
161 |
+
a modified (corrupted) `KeyProtectedByPassword`. It is up to the caller how to
|
162 |
+
best deal with this ambiguity, as it depends on the application this library is
|
163 |
+
being used in. If in doubt, consult with a professional cryptographer.
|
164 |
+
|
165 |
+
**WARNING:** Because of the way `KeyProtectedByPassword` is implemented, knowing
|
166 |
+
`SHA256($password)` is enough to decrypt a `KeyProtectedByPassword`. To be
|
167 |
+
secure, your application MUST NOT EVER compute `SHA256($password)` and use or
|
168 |
+
store it for any reason. You must also make sure that other libraries your
|
169 |
+
application is using don't compute it either.
|
170 |
+
|
171 |
+
Static Methods
|
172 |
+
---------------
|
173 |
+
|
174 |
+
### KeyProtectedByPassword::createRandomPasswordProtectedKey($password)
|
175 |
+
|
176 |
+
**Description:**
|
177 |
+
|
178 |
+
Generates a new random key that's protected by the string `$password` and
|
179 |
+
returns an instance of `KeyProtectedByPassword`.
|
180 |
+
|
181 |
+
**Parameters:**
|
182 |
+
|
183 |
+
1. `$password` is the password used to protect the random key.
|
184 |
+
|
185 |
+
**Return value:**
|
186 |
+
|
187 |
+
Returns an instance of `KeyProtectedByPassword` containing a randomly-generated
|
188 |
+
encryption key that's protected by the password `$password`.
|
189 |
+
|
190 |
+
**Exceptions:**
|
191 |
+
|
192 |
+
- `Defuse\Crypto\Exception\EnvironmentIsBrokenException` is thrown either when
|
193 |
+
the platform the code is running on cannot safely perform encryption for some
|
194 |
+
reason (e.g. it lacks a secure random number generator), or the runtime tests
|
195 |
+
detected a bug in this library.
|
196 |
+
|
197 |
+
**Side-effects and performance:**
|
198 |
+
|
199 |
+
This method runs a small and very fast set of self-tests if it is the very first
|
200 |
+
time this method or one of the `Crypto` methods has been called. The performance
|
201 |
+
overhead is negligible and can be safely ignored in all applications.
|
202 |
+
|
203 |
+
**Cautions:**
|
204 |
+
|
205 |
+
PHP stack traces display (portions of) the arguments passed to methods on the
|
206 |
+
call stack. If an exception is thrown inside this call, and it is uncaught, the
|
207 |
+
value of `$password` may be leaked out to an attacker through the stack trace.
|
208 |
+
We recommend configuring PHP to never output stack traces (either displaying
|
209 |
+
them to the user or saving them to log files).
|
210 |
+
|
211 |
+
Be aware that if you protecting multiple keys with the same password, an
|
212 |
+
attacker with write access to your system will be able to swap the protected
|
213 |
+
keys around so that the wrong key gets used next time it is unlocked. This could
|
214 |
+
lead to data being encrypted with the wrong key, perhaps one that the attacker
|
215 |
+
knows.
|
216 |
+
|
217 |
+
**WARNING:** Because of the way `KeyProtectedByPassword` is implemented, knowing
|
218 |
+
`SHA256($password)` is enough to decrypt a `KeyProtectedByPassword`. To be
|
219 |
+
secure, your application MUST NOT EVER compute `SHA256($password)` and use or
|
220 |
+
store it for any reason. You must also make sure that other libraries your
|
221 |
+
application is using don't compute it either.
|
222 |
+
|
223 |
+
### KeyProtectedByPassword::loadFromAsciiSafeString($saved\_key\_string)
|
224 |
+
|
225 |
+
**Description:**
|
226 |
+
|
227 |
+
Loads an instance of `KeyProtectedByPassword` that was saved to a string by
|
228 |
+
`saveToAsciiSafeString()`.
|
229 |
+
|
230 |
+
**Parameters:**
|
231 |
+
|
232 |
+
1. `$saved_key_string` is the string returned from `saveToAsciiSafeString()`
|
233 |
+
when the original `KeyProtectedByPassword` instance was saved.
|
234 |
+
|
235 |
+
**Return value:**
|
236 |
+
|
237 |
+
Returns an instance of `KeyProtectedByPassword` representing the same
|
238 |
+
password-protected key as the one that was represented by the
|
239 |
+
`KeyProtectedByPassword` instance that got saved into `$saved_key_string` by
|
240 |
+
a call to `saveToAsciiSafeString()`.
|
241 |
+
|
242 |
+
**Exceptions:**
|
243 |
+
|
244 |
+
- `Defuse\Crypto\Exception\EnvironmentIsBrokenException` is thrown either when
|
245 |
+
the platform the code is running on cannot safely perform encryption for some
|
246 |
+
reason (e.g. it lacks a secure random number generator), or the runtime tests
|
247 |
+
detected a bug in this library.
|
248 |
+
|
249 |
+
- `Defuse\Crypto\Exception\BadFormatException` is thrown whenever
|
250 |
+
`$saved_key_string` does not represent a valid `KeyProtectedByPassword`
|
251 |
+
instance.
|
252 |
+
|
253 |
+
**Side-effects and performance:**
|
254 |
+
|
255 |
+
None.
|
256 |
+
|
257 |
+
**Cautions:**
|
258 |
+
|
259 |
+
None.
|
vendor/defuse/php-encryption/psalm.xml
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<psalm
|
3 |
+
useDocblockTypes="true"
|
4 |
+
>
|
5 |
+
<projectFiles>
|
6 |
+
<directory name="src" />
|
7 |
+
</projectFiles>
|
8 |
+
<issueHandlers>
|
9 |
+
<DocblockTypeContradiction errorLevel="info" />
|
10 |
+
<RedundantConditionGivenDocblockType errorLevel="info" />
|
11 |
+
</issueHandlers>
|
12 |
+
</psalm>
|
vendor/defuse/php-encryption/src/Core.php
ADDED
@@ -0,0 +1,448 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Defuse\Crypto;
|
4 |
+
|
5 |
+
use Defuse\Crypto\Exception as Ex;
|
6 |
+
|
7 |
+
final class Core
|
8 |
+
{
|
9 |
+
const HEADER_VERSION_SIZE = 4;
|
10 |
+
const MINIMUM_CIPHERTEXT_SIZE = 84;
|
11 |
+
|
12 |
+
const CURRENT_VERSION = "\xDE\xF5\x02\x00";
|
13 |
+
|
14 |
+
const CIPHER_METHOD = 'aes-256-ctr';
|
15 |
+
const BLOCK_BYTE_SIZE = 16;
|
16 |
+
const KEY_BYTE_SIZE = 32;
|
17 |
+
const SALT_BYTE_SIZE = 32;
|
18 |
+
const MAC_BYTE_SIZE = 32;
|
19 |
+
const HASH_FUNCTION_NAME = 'sha256';
|
20 |
+
const ENCRYPTION_INFO_STRING = 'DefusePHP|V2|KeyForEncryption';
|
21 |
+
const AUTHENTICATION_INFO_STRING = 'DefusePHP|V2|KeyForAuthentication';
|
22 |
+
const BUFFER_BYTE_SIZE = 1048576;
|
23 |
+
|
24 |
+
const LEGACY_CIPHER_METHOD = 'aes-128-cbc';
|
25 |
+
const LEGACY_BLOCK_BYTE_SIZE = 16;
|
26 |
+
const LEGACY_KEY_BYTE_SIZE = 16;
|
27 |
+
const LEGACY_HASH_FUNCTION_NAME = 'sha256';
|
28 |
+
const LEGACY_MAC_BYTE_SIZE = 32;
|
29 |
+
const LEGACY_ENCRYPTION_INFO_STRING = 'DefusePHP|KeyForEncryption';
|
30 |
+
const LEGACY_AUTHENTICATION_INFO_STRING = 'DefusePHP|KeyForAuthentication';
|
31 |
+
|
32 |
+
/*
|
33 |
+
* V2.0 Format: VERSION (4 bytes) || SALT (32 bytes) || IV (16 bytes) ||
|
34 |
+
* CIPHERTEXT (varies) || HMAC (32 bytes)
|
35 |
+
*
|
36 |
+
* V1.0 Format: HMAC (32 bytes) || IV (16 bytes) || CIPHERTEXT (varies).
|
37 |
+
*/
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Adds an integer to a block-sized counter.
|
41 |
+
*
|
42 |
+
* @param string $ctr
|
43 |
+
* @param int $inc
|
44 |
+
*
|
45 |
+
* @throws Ex\EnvironmentIsBrokenException
|
46 |
+
*
|
47 |
+
* @return string
|
48 |
+
*
|
49 |
+
* @psalm-suppress RedundantCondition - It's valid to use is_int to check for overflow.
|
50 |
+
*/
|
51 |
+
public static function incrementCounter($ctr, $inc)
|
52 |
+
{
|
53 |
+
Core::ensureTrue(
|
54 |
+
Core::ourStrlen($ctr) === Core::BLOCK_BYTE_SIZE,
|
55 |
+
'Trying to increment a nonce of the wrong size.'
|
56 |
+
);
|
57 |
+
|
58 |
+
Core::ensureTrue(
|
59 |
+
\is_int($inc),
|
60 |
+
'Trying to increment nonce by a non-integer.'
|
61 |
+
);
|
62 |
+
|
63 |
+
// The caller is probably re-using CTR-mode keystream if they increment by 0.
|
64 |
+
Core::ensureTrue(
|
65 |
+
$inc > 0,
|
66 |
+
'Trying to increment a nonce by a nonpositive amount'
|
67 |
+
);
|
68 |
+
|
69 |
+
Core::ensureTrue(
|
70 |
+
$inc <= PHP_INT_MAX - 255,
|
71 |
+
'Integer overflow may occur'
|
72 |
+
);
|
73 |
+
|
74 |
+
/*
|
75 |
+
* We start at the rightmost byte (big-endian)
|
76 |
+
* So, too, does OpenSSL: http://stackoverflow.com/a/3146214/2224584
|
77 |
+
*/
|
78 |
+
for ($i = Core::BLOCK_BYTE_SIZE - 1; $i >= 0; --$i) {
|
79 |
+
$sum = \ord($ctr[$i]) + $inc;
|
80 |
+
|
81 |
+
/* Detect integer overflow and fail. */
|
82 |
+
Core::ensureTrue(\is_int($sum), 'Integer overflow in CTR mode nonce increment');
|
83 |
+
|
84 |
+
$ctr[$i] = \pack('C', $sum & 0xFF);
|
85 |
+
$inc = $sum >> 8;
|
86 |
+
}
|
87 |
+
return $ctr;
|
88 |
+
}
|
89 |
+
|
90 |
+
/**
|
91 |
+
* Returns a random byte string of the specified length.
|
92 |
+
*
|
93 |
+
* @param int $octets
|
94 |
+
*
|
95 |
+
* @throws Ex\EnvironmentIsBrokenException
|
96 |
+
*
|
97 |
+
* @return string
|
98 |
+
*/
|
99 |
+
public static function secureRandom($octets)
|
100 |
+
{
|
101 |
+
self::ensureFunctionExists('random_bytes');
|
102 |
+
try {
|
103 |
+
return \random_bytes($octets);
|
104 |
+
} catch (\Exception $ex) {
|
105 |
+
throw new Ex\EnvironmentIsBrokenException(
|
106 |
+
'Your system does not have a secure random number generator.'
|
107 |
+
);
|
108 |
+
}
|
109 |
+
}
|
110 |
+
|
111 |
+
/**
|
112 |
+
* Computes the HKDF key derivation function specified in
|
113 |
+
* http://tools.ietf.org/html/rfc5869.
|
114 |
+
*
|
115 |
+
* @param string $hash Hash Function
|
116 |
+
* @param string $ikm Initial Keying Material
|
117 |
+
* @param int $length How many bytes?
|
118 |
+
* @param string $info What sort of key are we deriving?
|
119 |
+
* @param string $salt
|
120 |
+
*
|
121 |
+
* @throws Ex\EnvironmentIsBrokenException
|
122 |
+
* @psalm-suppress UndefinedFunction - We're checking if the function exists first.
|
123 |
+
*
|
124 |
+
* @return string
|
125 |
+
*/
|
126 |
+
public static function HKDF($hash, $ikm, $length, $info = '', $salt = null)
|
127 |
+
{
|
128 |
+
static $nativeHKDF = null;
|
129 |
+
if ($nativeHKDF === null) {
|
130 |
+
$nativeHKDF = \is_callable('\\hash_hkdf');
|
131 |
+
}
|
132 |
+
if ($nativeHKDF) {
|
133 |
+
if (\is_null($salt)) {
|
134 |
+
$salt = '';
|
135 |
+
}
|
136 |
+
return \hash_hkdf($hash, $ikm, $length, $info, $salt);
|
137 |
+
}
|
138 |
+
|
139 |
+
$digest_length = Core::ourStrlen(\hash_hmac($hash, '', '', true));
|
140 |
+
|
141 |
+
// Sanity-check the desired output length.
|
142 |
+
Core::ensureTrue(
|
143 |
+
!empty($length) && \is_int($length) && $length >= 0 && $length <= 255 * $digest_length,
|
144 |
+
'Bad output length requested of HDKF.'
|
145 |
+
);
|
146 |
+
|
147 |
+
// "if [salt] not provided, is set to a string of HashLen zeroes."
|
148 |
+
if (\is_null($salt)) {
|
149 |
+
$salt = \str_repeat("\x00", $digest_length);
|
150 |
+
}
|
151 |
+
|
152 |
+
// HKDF-Extract:
|
153 |
+
// PRK = HMAC-Hash(salt, IKM)
|
154 |
+
// The salt is the HMAC key.
|
155 |
+
$prk = \hash_hmac($hash, $ikm, $salt, true);
|
156 |
+
|
157 |
+
// HKDF-Expand:
|
158 |
+
|
159 |
+
// This check is useless, but it serves as a reminder to the spec.
|
160 |
+
Core::ensureTrue(Core::ourStrlen($prk) >= $digest_length);
|
161 |
+
|
162 |
+
// T(0) = ''
|
163 |
+
$t = '';
|
164 |
+
$last_block = '';
|
165 |
+
for ($block_index = 1; Core::ourStrlen($t) < $length; ++$block_index) {
|
166 |
+
// T(i) = HMAC-Hash(PRK, T(i-1) | info | 0x??)
|
167 |
+
$last_block = \hash_hmac(
|
168 |
+
$hash,
|
169 |
+
$last_block . $info . \chr($block_index),
|
170 |
+
$prk,
|
171 |
+
true
|
172 |
+
);
|
173 |
+
// T = T(1) | T(2) | T(3) | ... | T(N)
|
174 |
+
$t .= $last_block;
|
175 |
+
}
|
176 |
+
|
177 |
+
// ORM = first L octets of T
|
178 |
+
/** @var string $orm */
|
179 |
+
$orm = Core::ourSubstr($t, 0, $length);
|
180 |
+
Core::ensureTrue(\is_string($orm));
|
181 |
+
return $orm;
|
182 |
+
}
|
183 |
+
|
184 |
+
/**
|
185 |
+
* Checks if two equal-length strings are the same without leaking
|
186 |
+
* information through side channels.
|
187 |
+
*
|
188 |
+
* @param string $expected
|
189 |
+
* @param string $given
|
190 |
+
*
|
191 |
+
* @throws Ex\EnvironmentIsBrokenException
|
192 |
+
*
|
193 |
+
* @return bool
|
194 |
+
*/
|
195 |
+
public static function hashEquals($expected, $given)
|
196 |
+
{
|
197 |
+
static $native = null;
|
198 |
+
if ($native === null) {
|
199 |
+
$native = \function_exists('hash_equals');
|
200 |
+
}
|
201 |
+
if ($native) {
|
202 |
+
return \hash_equals($expected, $given);
|
203 |
+
}
|
204 |
+
|
205 |
+
// We can't just compare the strings with '==', since it would make
|
206 |
+
// timing attacks possible. We could use the XOR-OR constant-time
|
207 |
+
// comparison algorithm, but that may not be a reliable defense in an
|
208 |
+
// interpreted language. So we use the approach of HMACing both strings
|
209 |
+
// with a random key and comparing the HMACs.
|
210 |
+
|
211 |
+
// We're not attempting to make variable-length string comparison
|
212 |
+
// secure, as that's very difficult. Make sure the strings are the same
|
213 |
+
// length.
|
214 |
+
Core::ensureTrue(Core::ourStrlen($expected) === Core::ourStrlen($given));
|
215 |
+
|
216 |
+
$blind = Core::secureRandom(32);
|
217 |
+
$message_compare = \hash_hmac(Core::HASH_FUNCTION_NAME, $given, $blind);
|
218 |
+
$correct_compare = \hash_hmac(Core::HASH_FUNCTION_NAME, $expected, $blind);
|
219 |
+
return $correct_compare === $message_compare;
|
220 |
+
}
|
221 |
+
/**
|
222 |
+
* Throws an exception if the constant doesn't exist.
|
223 |
+
*
|
224 |
+
* @param string $name
|
225 |
+
* @return void
|
226 |
+
*
|
227 |
+
* @throws Ex\EnvironmentIsBrokenException
|
228 |
+
*/
|
229 |
+
public static function ensureConstantExists($name)
|
230 |
+
{
|
231 |
+
Core::ensureTrue(\defined($name));
|
232 |
+
}
|
233 |
+
|
234 |
+
/**
|
235 |
+
* Throws an exception if the function doesn't exist.
|
236 |
+
*
|
237 |
+
* @param string $name
|
238 |
+
* @return void
|
239 |
+
*
|
240 |
+
* @throws Ex\EnvironmentIsBrokenException
|
241 |
+
*/
|
242 |
+
public static function ensureFunctionExists($name)
|
243 |
+
{
|
244 |
+
Core::ensureTrue(\function_exists($name));
|
245 |
+
}
|
246 |
+
|
247 |
+
/**
|
248 |
+
* Throws an exception if the condition is false.
|
249 |
+
*
|
250 |
+
* @param bool $condition
|
251 |
+
* @param string $message
|
252 |
+
* @return void
|
253 |
+
*
|
254 |
+
* @throws Ex\EnvironmentIsBrokenException
|
255 |
+
*/
|
256 |
+
public static function ensureTrue($condition, $message = '')
|
257 |
+
{
|
258 |
+
if (!$condition) {
|
259 |
+
throw new Ex\EnvironmentIsBrokenException($message);
|
260 |
+
}
|
261 |
+
}
|
262 |
+
|
263 |
+
/*
|
264 |
+
* We need these strlen() and substr() functions because when
|
265 |
+
* 'mbstring.func_overload' is set in php.ini, the standard strlen() and
|
266 |
+
* substr() are replaced by mb_strlen() and mb_substr().
|
267 |
+
*/
|
268 |
+
|
269 |
+
/**
|
270 |
+
* Computes the length of a string in bytes.
|
271 |
+
*
|
272 |
+
* @param string $str
|
273 |
+
*
|
274 |
+
* @throws Ex\EnvironmentIsBrokenException
|
275 |
+
*
|
276 |
+
* @return int
|
277 |
+
*/
|
278 |
+
public static function ourStrlen($str)
|
279 |
+
{
|
280 |
+
static $exists = null;
|
281 |
+
if ($exists === null) {
|
282 |
+
$exists = \extension_loaded('mbstring') && \ini_get('mbstring.func_overload') !== false && (int)\ini_get('mbstring.func_overload') & MB_OVERLOAD_STRING;
|
283 |
+
}
|
284 |
+
if ($exists) {
|
285 |
+
$length = \mb_strlen($str, '8bit');
|
286 |
+
Core::ensureTrue($length !== false);
|
287 |
+
return $length;
|
288 |
+
} else {
|
289 |
+
return \strlen($str);
|
290 |
+
}
|
291 |
+
}
|
292 |
+
|
293 |
+
/**
|
294 |
+
* Behaves roughly like the function substr() in PHP 7 does.
|
295 |
+
*
|
296 |
+
* @param string $str
|
297 |
+
* @param int $start
|
298 |
+
* @param int $length
|
299 |
+
*
|
300 |
+
* @throws Ex\EnvironmentIsBrokenException
|
301 |
+
*
|
302 |
+
* @return string|bool
|
303 |
+
*/
|
304 |
+
public static function ourSubstr($str, $start, $length = null)
|
305 |
+
{
|
306 |
+
static $exists = null;
|
307 |
+
if ($exists === null) {
|
308 |
+
$exists = \extension_loaded('mbstring') && \ini_get('mbstring.func_overload') !== false && (int)\ini_get('mbstring.func_overload') & MB_OVERLOAD_STRING;
|
309 |
+
}
|
310 |
+
|
311 |
+
// This is required to make mb_substr behavior identical to substr.
|
312 |
+
// Without this, mb_substr() would return false, contra to what the
|
313 |
+
// PHP documentation says (it doesn't say it can return false.)
|
314 |
+
$input_len = Core::ourStrlen($str);
|
315 |
+
if ($start === $input_len && !$length) {
|
316 |
+
return '';
|
317 |
+
}
|
318 |
+
|
319 |
+
if ($start > $input_len) {
|
320 |
+
return false;
|
321 |
+
}
|
322 |
+
|
323 |
+
// mb_substr($str, 0, NULL, '8bit') returns an empty string on PHP 5.3,
|
324 |
+
// so we have to find the length ourselves. Also, substr() doesn't
|
325 |
+
// accept null for the length.
|
326 |
+
if (! isset($length)) {
|
327 |
+
if ($start >= 0) {
|
328 |
+
$length = $input_len - $start;
|
329 |
+
} else {
|
330 |
+
$length = -$start;
|
331 |
+
}
|
332 |
+
}
|
333 |
+
|
334 |
+
if ($length < 0) {
|
335 |
+
throw new \InvalidArgumentException(
|
336 |
+
"Negative lengths are not supported with ourSubstr."
|
337 |
+
);
|
338 |
+
}
|
339 |
+
|
340 |
+
if ($exists) {
|
341 |
+
$substr = \mb_substr($str, $start, $length, '8bit');
|
342 |
+
// At this point there are two cases where mb_substr can
|
343 |
+
// legitimately return an empty string. Either $length is 0, or
|
344 |
+
// $start is equal to the length of the string (both mb_substr and
|
345 |
+
// substr return an empty string when this happens). It should never
|
346 |
+
// ever return a string that's longer than $length.
|
347 |
+
if (Core::ourStrlen($substr) > $length || (Core::ourStrlen($substr) === 0 && $length !== 0 && $start !== $input_len)) {
|
348 |
+
throw new Ex\EnvironmentIsBrokenException(
|
349 |
+
'Your version of PHP has bug #66797. Its implementation of
|
350 |
+
mb_substr() is incorrect. See the details here:
|
351 |
+
https://bugs.php.net/bug.php?id=66797'
|
352 |
+
);
|
353 |
+
}
|
354 |
+
return $substr;
|
355 |
+
}
|
356 |
+
|
357 |
+
return \substr($str, $start, $length);
|
358 |
+
}
|
359 |
+
|
360 |
+
/**
|
361 |
+
* Computes the PBKDF2 password-based key derivation function.
|
362 |
+
*
|
363 |
+
* The PBKDF2 function is defined in RFC 2898. Test vectors can be found in
|
364 |
+
* RFC 6070. This implementation of PBKDF2 was originally created by Taylor
|
365 |
+
* Hornby, with improvements from http://www.variations-of-shadow.com/.
|
366 |
+
*
|
367 |
+
* @param string $algorithm The hash algorithm to use. Recommended: SHA256
|
368 |
+
* @param string $password The password.
|
369 |
+
* @param string $salt A salt that is unique to the password.
|
370 |
+
* @param int $count Iteration count. Higher is better, but slower. Recommended: At least 1000.
|
371 |
+
* @param int $key_length The length of the derived key in bytes.
|
372 |
+
* @param bool $raw_output If true, the key is returned in raw binary format. Hex encoded otherwise.
|
373 |
+
*
|
374 |
+
* @throws Ex\EnvironmentIsBrokenException
|
375 |
+
*
|
376 |
+
* @return string A $key_length-byte key derived from the password and salt.
|
377 |
+
*/
|
378 |
+
public static function pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output = false)
|
379 |
+
{
|
380 |
+
// Type checks:
|
381 |
+
if (! \is_string($algorithm)) {
|
382 |
+
throw new \InvalidArgumentException(
|
383 |
+
'pbkdf2(): algorithm must be a string'
|
384 |
+
);
|
385 |
+
}
|
386 |
+
if (! \is_string($password)) {
|
387 |
+
throw new \InvalidArgumentException(
|
388 |
+
'pbkdf2(): password must be a string'
|
389 |
+
);
|
390 |
+
}
|
391 |
+
if (! \is_string($salt)) {
|
392 |
+
throw new \InvalidArgumentException(
|
393 |
+
'pbkdf2(): salt must be a string'
|
394 |
+
);
|
395 |
+
}
|
396 |
+
// Coerce strings to integers with no information loss or overflow
|
397 |
+
$count += 0;
|
398 |
+
$key_length += 0;
|
399 |
+
|
400 |
+
$algorithm = \strtolower($algorithm);
|
401 |
+
Core::ensureTrue(
|
402 |
+
\in_array($algorithm, \hash_algos(), true),
|
403 |
+
'Invalid or unsupported hash algorithm.'
|
404 |
+
);
|
405 |
+
|
406 |
+
// Whitelist, or we could end up with people using CRC32.
|
407 |
+
$ok_algorithms = [
|
408 |
+
'sha1', 'sha224', 'sha256', 'sha384', 'sha512',
|
409 |
+
'ripemd160', 'ripemd256', 'ripemd320', 'whirlpool',
|
410 |
+
];
|
411 |
+
Core::ensureTrue(
|
412 |
+
\in_array($algorithm, $ok_algorithms, true),
|
413 |
+
'Algorithm is not a secure cryptographic hash function.'
|
414 |
+
);
|
415 |
+
|
416 |
+
Core::ensureTrue($count > 0 && $key_length > 0, 'Invalid PBKDF2 parameters.');
|
417 |
+
|
418 |
+
if (\function_exists('hash_pbkdf2')) {
|
419 |
+
// The output length is in NIBBLES (4-bits) if $raw_output is false!
|
420 |
+
if (! $raw_output) {
|
421 |
+
$key_length = $key_length * 2;
|
422 |
+
}
|
423 |
+
return \hash_pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output);
|
424 |
+
}
|
425 |
+
|
426 |
+
$hash_length = Core::ourStrlen(\hash($algorithm, '', true));
|
427 |
+
$block_count = \ceil($key_length / $hash_length);
|
428 |
+
|
429 |
+
$output = '';
|
430 |
+
for ($i = 1; $i <= $block_count; $i++) {
|
431 |
+
// $i encoded as 4 bytes, big endian.
|
432 |
+
$last = $salt . \pack('N', $i);
|
433 |
+
// first iteration
|
434 |
+
$last = $xorsum = \hash_hmac($algorithm, $last, $password, true);
|
435 |
+
// perform the other $count - 1 iterations
|
436 |
+
for ($j = 1; $j < $count; $j++) {
|
437 |
+
$xorsum ^= ($last = \hash_hmac($algorithm, $last, $password, true));
|
438 |
+
}
|
439 |
+
$output .= $xorsum;
|
440 |
+
}
|
441 |
+
|
442 |
+
if ($raw_output) {
|
443 |
+
return (string) Core::ourSubstr($output, 0, $key_length);
|
444 |
+
} else {
|
445 |
+
return Encoding::binToHex((string) Core::ourSubstr($output, 0, $key_length));
|
446 |
+
}
|
447 |
+
}
|
448 |
+
}
|
vendor/defuse/php-encryption/src/Crypto.php
ADDED
@@ -0,0 +1,445 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Defuse\Crypto;
|
4 |
+
|
5 |
+
use Defuse\Crypto\Exception as Ex;
|
6 |
+
|
7 |
+
class Crypto
|
8 |
+
{
|
9 |
+
/**
|
10 |
+
* Encrypts a string with a Key.
|
11 |
+
*
|
12 |
+
* @param string $plaintext
|
13 |
+
* @param Key $key
|
14 |
+
* @param bool $raw_binary
|
15 |
+
*
|
16 |
+
* @throws Ex\EnvironmentIsBrokenException
|
17 |
+
* @throws \TypeError
|
18 |
+
*
|
19 |
+
* @return string
|
20 |
+
*/
|
21 |
+
public static function encrypt($plaintext, $key, $raw_binary = false)
|
22 |
+
{
|
23 |
+
if (!\is_string($plaintext)) {
|
24 |
+
throw new \TypeError(
|
25 |
+
'String expected for argument 1. ' . \ucfirst(\gettype($plaintext)) . ' given instead.'
|
26 |
+
);
|
27 |
+
}
|
28 |
+
if (!($key instanceof Key)) {
|
29 |
+
throw new \TypeError(
|
30 |
+
'Key expected for argument 2. ' . \ucfirst(\gettype($key)) . ' given instead.'
|
31 |
+
);
|
32 |
+
}
|
33 |
+
if (!\is_bool($raw_binary)) {
|
34 |
+
throw new \TypeError(
|
35 |
+
'Boolean expected for argument 3. ' . \ucfirst(\gettype($raw_binary)) . ' given instead.'
|
36 |
+
);
|
37 |
+
}
|
38 |
+
return self::encryptInternal(
|
39 |
+
$plaintext,
|
40 |
+
KeyOrPassword::createFromKey($key),
|
41 |
+
$raw_binary
|
42 |
+
);
|
43 |
+
}
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Encrypts a string with a password, using a slow key derivation function
|
47 |
+
* to make password cracking more expensive.
|
48 |
+
*
|
49 |
+
* @param string $plaintext
|
50 |
+
* @param string $password
|
51 |
+
* @param bool $raw_binary
|
52 |
+
*
|
53 |
+
* @throws Ex\EnvironmentIsBrokenException
|
54 |
+
* @throws \TypeError
|
55 |
+
*
|
56 |
+
* @return string
|
57 |
+
*/
|
58 |
+
public static function encryptWithPassword($plaintext, $password, $raw_binary = false)
|
59 |
+
{
|
60 |
+
if (!\is_string($plaintext)) {
|
61 |
+
throw new \TypeError(
|
62 |
+
'String expected for argument 1. ' . \ucfirst(\gettype($plaintext)) . ' given instead.'
|
63 |
+
);
|
64 |
+
}
|
65 |
+
if (!\is_string($password)) {
|
66 |
+
throw new \TypeError(
|
67 |
+
'String expected for argument 2. ' . \ucfirst(\gettype($password)) . ' given instead.'
|
68 |
+
);
|
69 |
+
}
|
70 |
+
if (!\is_bool($raw_binary)) {
|
71 |
+
throw new \TypeError(
|
72 |
+
'Boolean expected for argument 3. ' . \ucfirst(\gettype($raw_binary)) . ' given instead.'
|
73 |
+
);
|
74 |
+
}
|
75 |
+
return self::encryptInternal(
|
76 |
+
$plaintext,
|
77 |
+
KeyOrPassword::createFromPassword($password),
|
78 |
+
$raw_binary
|
79 |
+
);
|
80 |
+
}
|
81 |
+
|
82 |
+
/**
|
83 |
+
* Decrypts a ciphertext to a string with a Key.
|
84 |
+
*
|
85 |
+
* @param string $ciphertext
|
86 |
+
* @param Key $key
|
87 |
+
* @param bool $raw_binary
|
88 |
+
*
|
89 |
+
* @throws \TypeError
|
90 |
+
* @throws Ex\EnvironmentIsBrokenException
|
91 |
+
* @throws Ex\WrongKeyOrModifiedCiphertextException
|
92 |
+
*
|
93 |
+
* @return string
|
94 |
+
*/
|
95 |
+
public static function decrypt($ciphertext, $key, $raw_binary = false)
|
96 |
+
{
|
97 |
+
if (!\is_string($ciphertext)) {
|
98 |
+
throw new \TypeError(
|
99 |
+
'String expected for argument 1. ' . \ucfirst(\gettype($ciphertext)) . ' given instead.'
|
100 |
+
);
|
101 |
+
}
|
102 |
+
if (!($key instanceof Key)) {
|
103 |
+
throw new \TypeError(
|
104 |
+
'Key expected for argument 2. ' . \ucfirst(\gettype($key)) . ' given instead.'
|
105 |
+
);
|
106 |
+
}
|
107 |
+
if (!\is_bool($raw_binary)) {
|
108 |
+
throw new \TypeError(
|
109 |
+
'Boolean expected for argument 3. ' . \ucfirst(\gettype($raw_binary)) . ' given instead.'
|
110 |
+
);
|
111 |
+
}
|
112 |
+
return self::decryptInternal(
|
113 |
+
$ciphertext,
|
114 |
+
KeyOrPassword::createFromKey($key),
|
115 |
+
$raw_binary
|
116 |
+
);
|
117 |
+
}
|
118 |
+
|
119 |
+
/**
|
120 |
+
* Decrypts a ciphertext to a string with a password, using a slow key
|
121 |
+
* derivation function to make password cracking more expensive.
|
122 |
+
*
|
123 |
+
* @param string $ciphertext
|
124 |
+
* @param string $password
|
125 |
+
* @param bool $raw_binary
|
126 |
+
*
|
127 |
+
* @throws Ex\EnvironmentIsBrokenException
|
128 |
+
* @throws Ex\WrongKeyOrModifiedCiphertextException
|
129 |
+
* @throws \TypeError
|
130 |
+
*
|
131 |
+
* @return string
|
132 |
+
*/
|
133 |
+
public static function decryptWithPassword($ciphertext, $password, $raw_binary = false)
|
134 |
+
{
|
135 |
+
if (!\is_string($ciphertext)) {
|
136 |
+
throw new \TypeError(
|
137 |
+
'String expected for argument 1. ' . \ucfirst(\gettype($ciphertext)) . ' given instead.'
|
138 |
+
);
|
139 |
+
}
|
140 |
+
if (!\is_string($password)) {
|
141 |
+
throw new \TypeError(
|
142 |
+
'String expected for argument 2. ' . \ucfirst(\gettype($password)) . ' given instead.'
|
143 |
+
);
|
144 |
+
}
|
145 |
+
if (!\is_bool($raw_binary)) {
|
146 |
+
throw new \TypeError(
|
147 |
+
'Boolean expected for argument 3. ' . \ucfirst(\gettype($raw_binary)) . ' given instead.'
|
148 |
+
);
|
149 |
+
}
|
150 |
+
return self::decryptInternal(
|
151 |
+
$ciphertext,
|
152 |
+
KeyOrPassword::createFromPassword($password),
|
153 |
+
$raw_binary
|
154 |
+
);
|
155 |
+
}
|
156 |
+
|
157 |
+
/**
|
158 |
+
* Decrypts a legacy ciphertext produced by version 1 of this library.
|
159 |
+
*
|
160 |
+
* @param string $ciphertext
|
161 |
+
* @param string $key
|
162 |
+
*
|
163 |
+
* @throws Ex\EnvironmentIsBrokenException
|
164 |
+
* @throws Ex\WrongKeyOrModifiedCiphertextException
|
165 |
+
* @throws \TypeError
|
166 |
+
*
|
167 |
+
* @return string
|
168 |
+
*/
|
169 |
+
public static function legacyDecrypt($ciphertext, $key)
|
170 |
+
{
|
171 |
+
if (!\is_string($ciphertext)) {
|
172 |
+
throw new \TypeError(
|
173 |
+
'String expected for argument 1. ' . \ucfirst(\gettype($ciphertext)) . ' given instead.'
|
174 |
+
);
|
175 |
+
}
|
176 |
+
if (!\is_string($key)) {
|
177 |
+
throw new \TypeError(
|
178 |
+
'String expected for argument 2. ' . \ucfirst(\gettype($key)) . ' given instead.'
|
179 |
+
);
|
180 |
+
}
|
181 |
+
|
182 |
+
RuntimeTests::runtimeTest();
|
183 |
+
|
184 |
+
// Extract the HMAC from the front of the ciphertext.
|
185 |
+
if (Core::ourStrlen($ciphertext) <= Core::LEGACY_MAC_BYTE_SIZE) {
|
186 |
+
throw new Ex\WrongKeyOrModifiedCiphertextException(
|
187 |
+
'Ciphertext is too short.'
|
188 |
+
);
|
189 |
+
}
|
190 |
+
/**
|
191 |
+
* @var string
|
192 |
+
*/
|
193 |
+
$hmac = Core::ourSubstr($ciphertext, 0, Core::LEGACY_MAC_BYTE_SIZE);
|
194 |
+
Core::ensureTrue(\is_string($hmac));
|
195 |
+
/**
|
196 |
+
* @var string
|
197 |
+
*/
|
198 |
+
$messageCiphertext = Core::ourSubstr($ciphertext, Core::LEGACY_MAC_BYTE_SIZE);
|
199 |
+
Core::ensureTrue(\is_string($messageCiphertext));
|
200 |
+
|
201 |
+
// Regenerate the same authentication sub-key.
|
202 |
+
$akey = Core::HKDF(
|
203 |
+
Core::LEGACY_HASH_FUNCTION_NAME,
|
204 |
+
$key,
|
205 |
+
Core::LEGACY_KEY_BYTE_SIZE,
|
206 |
+
Core::LEGACY_AUTHENTICATION_INFO_STRING,
|
207 |
+
null
|
208 |
+
);
|
209 |
+
|
210 |
+
if (self::verifyHMAC($hmac, $messageCiphertext, $akey)) {
|
211 |
+
// Regenerate the same encryption sub-key.
|
212 |
+
$ekey = Core::HKDF(
|
213 |
+
Core::LEGACY_HASH_FUNCTION_NAME,
|
214 |
+
$key,
|
215 |
+
Core::LEGACY_KEY_BYTE_SIZE,
|
216 |
+
Core::LEGACY_ENCRYPTION_INFO_STRING,
|
217 |
+
null
|
218 |
+
);
|
219 |
+
|
220 |
+
// Extract the IV from the ciphertext.
|
221 |
+
if (Core::ourStrlen($messageCiphertext) <= Core::LEGACY_BLOCK_BYTE_SIZE) {
|
222 |
+
throw new Ex\WrongKeyOrModifiedCiphertextException(
|
223 |
+
'Ciphertext is too short.'
|
224 |
+
);
|
225 |
+
}
|
226 |
+
/**
|
227 |
+
* @var string
|
228 |
+
*/
|
229 |
+
$iv = Core::ourSubstr($messageCiphertext, 0, Core::LEGACY_BLOCK_BYTE_SIZE);
|
230 |
+
Core::ensureTrue(\is_string($iv));
|
231 |
+
|
232 |
+
/**
|
233 |
+
* @var string
|
234 |
+
*/
|
235 |
+
$actualCiphertext = Core::ourSubstr($messageCiphertext, Core::LEGACY_BLOCK_BYTE_SIZE);
|
236 |
+
Core::ensureTrue(\is_string($actualCiphertext));
|
237 |
+
|
238 |
+
// Do the decryption.
|
239 |
+
$plaintext = self::plainDecrypt($actualCiphertext, $ekey, $iv, Core::LEGACY_CIPHER_METHOD);
|
240 |
+
return $plaintext;
|
241 |
+
} else {
|
242 |
+
throw new Ex\WrongKeyOrModifiedCiphertextException(
|
243 |
+
'Integrity check failed.'
|
244 |
+
);
|
245 |
+
}
|
246 |
+
}
|
247 |
+
|
248 |
+
/**
|
249 |
+
* Encrypts a string with either a key or a password.
|
250 |
+
*
|
251 |
+
* @param string $plaintext
|
252 |
+
* @param KeyOrPassword $secret
|
253 |
+
* @param bool $raw_binary
|
254 |
+
*
|
255 |
+
* @return string
|
256 |
+
*/
|
257 |
+
private static function encryptInternal($plaintext, KeyOrPassword $secret, $raw_binary)
|
258 |
+
{
|
259 |
+
RuntimeTests::runtimeTest();
|
260 |
+
|
261 |
+
$salt = Core::secureRandom(Core::SALT_BYTE_SIZE);
|
262 |
+
$keys = $secret->deriveKeys($salt);
|
263 |
+
$ekey = $keys->getEncryptionKey();
|
264 |
+
$akey = $keys->getAuthenticationKey();
|
265 |
+
$iv = Core::secureRandom(Core::BLOCK_BYTE_SIZE);
|
266 |
+
|
267 |
+
$ciphertext = Core::CURRENT_VERSION . $salt . $iv . self::plainEncrypt($plaintext, $ekey, $iv);
|
268 |
+
$auth = \hash_hmac(Core::HASH_FUNCTION_NAME, $ciphertext, $akey, true);
|
269 |
+
$ciphertext = $ciphertext . $auth;
|
270 |
+
|
271 |
+
if ($raw_binary) {
|
272 |
+
return $ciphertext;
|
273 |
+
}
|
274 |
+
return Encoding::binToHex($ciphertext);
|
275 |
+
}
|
276 |
+
|
277 |
+
/**
|
278 |
+
* Decrypts a ciphertext to a string with either a key or a password.
|
279 |
+
*
|
280 |
+
* @param string $ciphertext
|
281 |
+
* @param KeyOrPassword $secret
|
282 |
+
* @param bool $raw_binary
|
283 |
+
*
|
284 |
+
* @throws Ex\EnvironmentIsBrokenException
|
285 |
+
* @throws Ex\WrongKeyOrModifiedCiphertextException
|
286 |
+
*
|
287 |
+
* @return string
|
288 |
+
*/
|
289 |
+
private static function decryptInternal($ciphertext, KeyOrPassword $secret, $raw_binary)
|
290 |
+
{
|
291 |
+
RuntimeTests::runtimeTest();
|
292 |
+
|
293 |
+
if (! $raw_binary) {
|
294 |
+
try {
|
295 |
+
$ciphertext = Encoding::hexToBin($ciphertext);
|
296 |
+
} catch (Ex\BadFormatException $ex) {
|
297 |
+
throw new Ex\WrongKeyOrModifiedCiphertextException(
|
298 |
+
'Ciphertext has invalid hex encoding.'
|
299 |
+
);
|
300 |
+
}
|
301 |
+
}
|
302 |
+
|
303 |
+
if (Core::ourStrlen($ciphertext) < Core::MINIMUM_CIPHERTEXT_SIZE) {
|
304 |
+
throw new Ex\WrongKeyOrModifiedCiphertextException(
|
305 |
+
'Ciphertext is too short.'
|
306 |
+
);
|
307 |
+
}
|
308 |
+
|
309 |
+
// Get and check the version header.
|
310 |
+
/** @var string $header */
|
311 |
+
$header = Core::ourSubstr($ciphertext, 0, Core::HEADER_VERSION_SIZE);
|
312 |
+
if ($header !== Core::CURRENT_VERSION) {
|
313 |
+
throw new Ex\WrongKeyOrModifiedCiphertextException(
|
314 |
+
'Bad version header.'
|
315 |
+
);
|
316 |
+
}
|
317 |
+
|
318 |
+
// Get the salt.
|
319 |
+
/** @var string $salt */
|
320 |
+
$salt = Core::ourSubstr(
|
321 |
+
$ciphertext,
|
322 |
+
Core::HEADER_VERSION_SIZE,
|
323 |
+
Core::SALT_BYTE_SIZE
|
324 |
+
);
|
325 |
+
Core::ensureTrue(\is_string($salt));
|
326 |
+
|
327 |
+
// Get the IV.
|
328 |
+
/** @var string $iv */
|
329 |
+
$iv = Core::ourSubstr(
|
330 |
+
$ciphertext,
|
331 |
+
Core::HEADER_VERSION_SIZE + Core::SALT_BYTE_SIZE,
|
332 |
+
Core::BLOCK_BYTE_SIZE
|
333 |
+
);
|
334 |
+
Core::ensureTrue(\is_string($iv));
|
335 |
+
|
336 |
+
// Get the HMAC.
|
337 |
+
/** @var string $hmac */
|
338 |
+
$hmac = Core::ourSubstr(
|
339 |
+
$ciphertext,
|
340 |
+
Core::ourStrlen($ciphertext) - Core::MAC_BYTE_SIZE,
|
341 |
+
Core::MAC_BYTE_SIZE
|
342 |
+
);
|
343 |
+
Core::ensureTrue(\is_string($hmac));
|
344 |
+
|
345 |
+
// Get the actual encrypted ciphertext.
|
346 |
+
/** @var string $encrypted */
|
347 |
+
$encrypted = Core::ourSubstr(
|
348 |
+
$ciphertext,
|
349 |
+
Core::HEADER_VERSION_SIZE + Core::SALT_BYTE_SIZE +
|
350 |
+
Core::BLOCK_BYTE_SIZE,
|
351 |
+
Core::ourStrlen($ciphertext) - Core::MAC_BYTE_SIZE - Core::SALT_BYTE_SIZE -
|
352 |
+
Core::BLOCK_BYTE_SIZE - Core::HEADER_VERSION_SIZE
|
353 |
+
);
|
354 |
+
Core::ensureTrue(\is_string($encrypted));
|
355 |
+
|
356 |
+
// Derive the separate encryption and authentication keys from the key
|
357 |
+
// or password, whichever it is.
|
358 |
+
$keys = $secret->deriveKeys($salt);
|
359 |
+
|
360 |
+
if (self::verifyHMAC($hmac, $header . $salt . $iv . $encrypted, $keys->getAuthenticationKey())) {
|
361 |
+
$plaintext = self::plainDecrypt($encrypted, $keys->getEncryptionKey(), $iv, Core::CIPHER_METHOD);
|
362 |
+
return $plaintext;
|
363 |
+
} else {
|
364 |
+
throw new Ex\WrongKeyOrModifiedCiphertextException(
|
365 |
+
'Integrity check failed.'
|
366 |
+
);
|
367 |
+
}
|
368 |
+
}
|
369 |
+
|
370 |
+
/**
|
371 |
+
* Raw unauthenticated encryption (insecure on its own).
|
372 |
+
*
|
373 |
+
* @param string $plaintext
|
374 |
+
* @param string $key
|
375 |
+
* @param string $iv
|
376 |
+
*
|
377 |
+
* @throws Ex\EnvironmentIsBrokenException
|
378 |
+
*
|
379 |
+
* @return string
|
380 |
+
*/
|
381 |
+
protected static function plainEncrypt($plaintext, $key, $iv)
|
382 |
+
{
|
383 |
+
Core::ensureConstantExists('OPENSSL_RAW_DATA');
|
384 |
+
Core::ensureFunctionExists('openssl_encrypt');
|
385 |
+
/** @var string $ciphertext */
|
386 |
+
$ciphertext = \openssl_encrypt(
|
387 |
+
$plaintext,
|
388 |
+
Core::CIPHER_METHOD,
|
389 |
+
$key,
|
390 |
+
OPENSSL_RAW_DATA,
|
391 |
+
$iv
|
392 |
+
);
|
393 |
+
|
394 |
+
Core::ensureTrue(\is_string($ciphertext), 'openssl_encrypt() failed');
|
395 |
+
|
396 |
+
return $ciphertext;
|
397 |
+
}
|
398 |
+
|
399 |
+
/**
|
400 |
+
* Raw unauthenticated decryption (insecure on its own).
|
401 |
+
*
|
402 |
+
* @param string $ciphertext
|
403 |
+
* @param string $key
|
404 |
+
* @param string $iv
|
405 |
+
* @param string $cipherMethod
|
406 |
+
*
|
407 |
+
* @throws Ex\EnvironmentIsBrokenException
|
408 |
+
*
|
409 |
+
* @return string
|
410 |
+
*/
|
411 |
+
protected static function plainDecrypt($ciphertext, $key, $iv, $cipherMethod)
|
412 |
+
{
|
413 |
+
Core::ensureConstantExists('OPENSSL_RAW_DATA');
|
414 |
+
Core::ensureFunctionExists('openssl_decrypt');
|
415 |
+
|
416 |
+
/** @var string $plaintext */
|
417 |
+
$plaintext = \openssl_decrypt(
|
418 |
+
$ciphertext,
|
419 |
+
$cipherMethod,
|
420 |
+
$key,
|
421 |
+
OPENSSL_RAW_DATA,
|
422 |
+
$iv
|
423 |
+
);
|
424 |
+
Core::ensureTrue(\is_string($plaintext), 'openssl_decrypt() failed.');
|
425 |
+
|
426 |
+
return $plaintext;
|
427 |
+
}
|
428 |
+
|
429 |
+
/**
|
430 |
+
* Verifies an HMAC without leaking information through side-channels.
|
431 |
+
*
|
432 |
+
* @param string $expected_hmac
|
433 |
+
* @param string $message
|
434 |
+
* @param string $key
|
435 |
+
*
|
436 |
+
* @throws Ex\EnvironmentIsBrokenException
|
437 |
+
*
|
438 |
+
* @return bool
|
439 |
+
*/
|
440 |
+
protected static function verifyHMAC($expected_hmac, $message, $key)
|
441 |
+
{
|
442 |
+
$message_hmac = \hash_hmac(Core::HASH_FUNCTION_NAME, $message, $key, true);
|
443 |
+
return Core::hashEquals($message_hmac, $expected_hmac);
|
444 |
+
}
|
445 |
+
}
|
vendor/defuse/php-encryption/src/DerivedKeys.php
ADDED
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Defuse\Crypto;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Class DerivedKeys
|
7 |
+
* @package Defuse\Crypto
|
8 |
+
*/
|
9 |
+
final class DerivedKeys
|
10 |
+
{
|
11 |
+
/**
|
12 |
+
* @var string
|
13 |
+
*/
|
14 |
+
private $akey = '';
|
15 |
+
|
16 |
+
/**
|
17 |
+
* @var string
|
18 |
+
*/
|
19 |
+
private $ekey = '';
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Returns the authentication key.
|
23 |
+
* @return string
|
24 |
+
*/
|
25 |
+
public function getAuthenticationKey()
|
26 |
+
{
|
27 |
+
return $this->akey;
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Returns the encryption key.
|
32 |
+
* @return string
|
33 |
+
*/
|
34 |
+
public function getEncryptionKey()
|
35 |
+
{
|
36 |
+
return $this->ekey;
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Constructor for DerivedKeys.
|
41 |
+
*
|
42 |
+
* @param string $akey
|
43 |
+
* @param string $ekey
|
44 |
+
*/
|
45 |
+
public function __construct($akey, $ekey)
|
46 |
+
{
|
47 |
+
$this->akey = $akey;
|
48 |
+
$this->ekey = $ekey;
|
49 |
+
}
|
50 |
+
}
|
vendor/defuse/php-encryption/src/Encoding.php
ADDED
@@ -0,0 +1,268 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Defuse\Crypto;
|
4 |
+
|
5 |
+
use Defuse\Crypto\Exception as Ex;
|
6 |
+
|
7 |
+
final class Encoding
|
8 |
+
{
|
9 |
+
const CHECKSUM_BYTE_SIZE = 32;
|
10 |
+
const CHECKSUM_HASH_ALGO = 'sha256';
|
11 |
+
const SERIALIZE_HEADER_BYTES = 4;
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Converts a byte string to a hexadecimal string without leaking
|
15 |
+
* information through side channels.
|
16 |
+
*
|
17 |
+
* @param string $byte_string
|
18 |
+
*
|
19 |
+
* @throws Ex\EnvironmentIsBrokenException
|
20 |
+
*
|
21 |
+
* @return string
|
22 |
+
*/
|
23 |
+
public static function binToHex($byte_string)
|
24 |
+
{
|
25 |
+
$hex = '';
|
26 |
+
$len = Core::ourStrlen($byte_string);
|
27 |
+
for ($i = 0; $i < $len; ++$i) {
|
28 |
+
$c = \ord($byte_string[$i]) & 0xf;
|
29 |
+
$b = \ord($byte_string[$i]) >> 4;
|
30 |
+
$hex .= \pack(
|
31 |
+
'CC',
|
32 |
+
87 + $b + ((($b - 10) >> 8) & ~38),
|
33 |
+
87 + $c + ((($c - 10) >> 8) & ~38)
|
34 |
+
);
|
35 |
+
}
|
36 |
+
return $hex;
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Converts a hexadecimal string into a byte string without leaking
|
41 |
+
* information through side channels.
|
42 |
+
*
|
43 |
+
* @param string $hex_string
|
44 |
+
*
|
45 |
+
* @throws Ex\BadFormatException
|
46 |
+
* @throws Ex\EnvironmentIsBrokenException
|
47 |
+
*
|
48 |
+
* @return string
|
49 |
+
*/
|
50 |
+
public static function hexToBin($hex_string)
|
51 |
+
{
|
52 |
+
$hex_pos = 0;
|
53 |
+
$bin = '';
|
54 |
+
$hex_len = Core::ourStrlen($hex_string);
|
55 |
+
$state = 0;
|
56 |
+
$c_acc = 0;
|
57 |
+
|
58 |
+
while ($hex_pos < $hex_len) {
|
59 |
+
$c = \ord($hex_string[$hex_pos]);
|
60 |
+
$c_num = $c ^ 48;
|
61 |
+
$c_num0 = ($c_num - 10) >> 8;
|
62 |
+
$c_alpha = ($c & ~32) - 55;
|
63 |
+
$c_alpha0 = (($c_alpha - 10) ^ ($c_alpha - 16)) >> 8;
|
64 |
+
if (($c_num0 | $c_alpha0) === 0) {
|
65 |
+
throw new Ex\BadFormatException(
|
66 |
+
'Encoding::hexToBin() input is not a hex string.'
|
67 |
+
);
|
68 |
+
}
|
69 |
+
$c_val = ($c_num0 & $c_num) | ($c_alpha & $c_alpha0);
|
70 |
+
if ($state === 0) {
|
71 |
+
$c_acc = $c_val * 16;
|
72 |
+
} else {
|
73 |
+
$bin .= \pack('C', $c_acc | $c_val);
|
74 |
+
}
|
75 |
+
$state ^= 1;
|
76 |
+
++$hex_pos;
|
77 |
+
}
|
78 |
+
return $bin;
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Remove trialing whitespace without table look-ups or branches.
|
83 |
+
*
|
84 |
+
* Calling this function may leak the length of the string as well as the
|
85 |
+
* number of trailing whitespace characters through side-channels.
|
86 |
+
*
|
87 |
+
* @param string $string
|
88 |
+
* @return string
|
89 |
+
*/
|
90 |
+
public static function trimTrailingWhitespace($string = '')
|
91 |
+
{
|
92 |
+
$length = Core::ourStrlen($string);
|
93 |
+
if ($length < 1) {
|
94 |
+
return '';
|
95 |
+
}
|
96 |
+
do {
|
97 |
+
$prevLength = $length;
|
98 |
+
$last = $length - 1;
|
99 |
+
$chr = \ord($string[$last]);
|
100 |
+
|
101 |
+
/* Null Byte (0x00), a.k.a. \0 */
|
102 |
+
// if ($chr === 0x00) $length -= 1;
|
103 |
+
$sub = (($chr - 1) >> 8 ) & 1;
|
104 |
+
$length -= $sub;
|
105 |
+
$last -= $sub;
|
106 |
+
|
107 |
+
/* Horizontal Tab (0x09) a.k.a. \t */
|
108 |
+
$chr = \ord($string[$last]);
|
109 |
+
// if ($chr === 0x09) $length -= 1;
|
110 |
+
$sub = (((0x08 - $chr) & ($chr - 0x0a)) >> 8) & 1;
|
111 |
+
$length -= $sub;
|
112 |
+
$last -= $sub;
|
113 |
+
|
114 |
+
/* New Line (0x0a), a.k.a. \n */
|
115 |
+
$chr = \ord($string[$last]);
|
116 |
+
// if ($chr === 0x0a) $length -= 1;
|
117 |
+
$sub = (((0x09 - $chr) & ($chr - 0x0b)) >> 8) & 1;
|
118 |
+
$length -= $sub;
|
119 |
+
$last -= $sub;
|
120 |
+
|
121 |
+
/* Carriage Return (0x0D), a.k.a. \r */
|
122 |
+
$chr = \ord($string[$last]);
|
123 |
+
// if ($chr === 0x0d) $length -= 1;
|
124 |
+
$sub = (((0x0c - $chr) & ($chr - 0x0e)) >> 8) & 1;
|
125 |
+
$length -= $sub;
|
126 |
+
$last -= $sub;
|
127 |
+
|
128 |
+
/* Space */
|
129 |
+
$chr = \ord($string[$last]);
|
130 |
+
// if ($chr === 0x20) $length -= 1;
|
131 |
+
$sub = (((0x1f - $chr) & ($chr - 0x21)) >> 8) & 1;
|
132 |
+
$length -= $sub;
|
133 |
+
} while ($prevLength !== $length && $length > 0);
|
134 |
+
return (string) Core::ourSubstr($string, 0, $length);
|
135 |
+
}
|
136 |
+
|
137 |
+
/*
|
138 |
+
* SECURITY NOTE ON APPLYING CHECKSUMS TO SECRETS:
|
139 |
+
*
|
140 |
+
* The checksum introduces a potential security weakness. For example,
|
141 |
+
* suppose we apply a checksum to a key, and that an adversary has an
|
142 |
+
* exploit against the process containing the key, such that they can
|
143 |
+
* overwrite an arbitrary byte of memory and then cause the checksum to
|
144 |
+
* be verified and learn the result.
|
145 |
+
*
|
146 |
+
* In this scenario, the adversary can extract the key one byte at
|
147 |
+
* a time by overwriting it with their guess of its value and then
|
148 |
+
* asking if the checksum matches. If it does, their guess was right.
|
149 |
+
* This kind of attack may be more easy to implement and more reliable
|
150 |
+
* than a remote code execution attack.
|
151 |
+
*
|
152 |
+
* This attack also applies to authenticated encryption as a whole, in
|
153 |
+
* the situation where the adversary can overwrite a byte of the key
|
154 |
+
* and then cause a valid ciphertext to be decrypted, and then
|
155 |
+
* determine whether the MAC check passed or failed.
|
156 |
+
*
|
157 |
+
* By using the full SHA256 hash instead of truncating it, I'm ensuring
|
158 |
+
* that both ways of going about the attack are equivalently difficult.
|
159 |
+
* A shorter checksum of say 32 bits might be more useful to the
|
160 |
+
* adversary as an oracle in case their writes are coarser grained.
|
161 |
+
*
|
162 |
+
* Because the scenario assumes a serious vulnerability, we don't try
|
163 |
+
* to prevent attacks of this style.
|
164 |
+
*/
|
165 |
+
|
166 |
+
/**
|
167 |
+
* INTERNAL USE ONLY: Applies a version header, applies a checksum, and
|
168 |
+
* then encodes a byte string into a range of printable ASCII characters.
|
169 |
+
*
|
170 |
+
* @param string $header
|
171 |
+
* @param string $bytes
|
172 |
+
*
|
173 |
+
* @throws Ex\EnvironmentIsBrokenException
|
174 |
+
*
|
175 |
+
* @return string
|
176 |
+
*/
|
177 |
+
public static function saveBytesToChecksummedAsciiSafeString($header, $bytes)
|
178 |
+
{
|
179 |
+
// Headers must be a constant length to prevent one type's header from
|
180 |
+
// being a prefix of another type's header, leading to ambiguity.
|
181 |
+
Core::ensureTrue(
|
182 |
+
Core::ourStrlen($header) === self::SERIALIZE_HEADER_BYTES,
|
183 |
+
'Header must be ' . self::SERIALIZE_HEADER_BYTES . ' bytes.'
|
184 |
+
);
|
185 |
+
|
186 |
+
return Encoding::binToHex(
|
187 |
+
$header .
|
188 |
+
$bytes .
|
189 |
+
\hash(
|
190 |
+
self::CHECKSUM_HASH_ALGO,
|
191 |
+
$header . $bytes,
|
192 |
+
true
|
193 |
+
)
|
194 |
+
);
|
195 |
+
}
|
196 |
+
|
197 |
+
/**
|
198 |
+
* INTERNAL USE ONLY: Decodes, verifies the header and checksum, and returns
|
199 |
+
* the encoded byte string.
|
200 |
+
*
|
201 |
+
* @param string $expected_header
|
202 |
+
* @param string $string
|
203 |
+
*
|
204 |
+
* @throws Ex\EnvironmentIsBrokenException
|
205 |
+
* @throws Ex\BadFormatException
|
206 |
+
*
|
207 |
+
* @return string
|
208 |
+
*/
|
209 |
+
public static function loadBytesFromChecksummedAsciiSafeString($expected_header, $string)
|
210 |
+
{
|
211 |
+
// Headers must be a constant length to prevent one type's header from
|
212 |
+
// being a prefix of another type's header, leading to ambiguity.
|
213 |
+
Core::ensureTrue(
|
214 |
+
Core::ourStrlen($expected_header) === self::SERIALIZE_HEADER_BYTES,
|
215 |
+
'Header must be 4 bytes.'
|
216 |
+
);
|
217 |
+
|
218 |
+
/* If you get an exception here when attempting to load from a file, first pass your
|
219 |
+
key to Encoding::trimTrailingWhitespace() to remove newline characters, etc. */
|
220 |
+
$bytes = Encoding::hexToBin($string);
|
221 |
+
|
222 |
+
/* Make sure we have enough bytes to get the version header and checksum. */
|
223 |
+
if (Core::ourStrlen($bytes) < self::SERIALIZE_HEADER_BYTES + self::CHECKSUM_BYTE_SIZE) {
|
224 |
+
throw new Ex\BadFormatException(
|
225 |
+
'Encoded data is shorter than expected.'
|
226 |
+
);
|
227 |
+
}
|
228 |
+
|
229 |
+
/* Grab the version header. */
|
230 |
+
$actual_header = (string) Core::ourSubstr($bytes, 0, self::SERIALIZE_HEADER_BYTES);
|
231 |
+
|
232 |
+
if ($actual_header !== $expected_header) {
|
233 |
+
throw new Ex\BadFormatException(
|
234 |
+
'Invalid header.'
|
235 |
+
);
|
236 |
+
}
|
237 |
+
|
238 |
+
/* Grab the bytes that are part of the checksum. */
|
239 |
+
$checked_bytes = (string) Core::ourSubstr(
|
240 |
+
$bytes,
|
241 |
+
0,
|
242 |
+
Core::ourStrlen($bytes) - self::CHECKSUM_BYTE_SIZE
|
243 |
+
);
|
244 |
+
|
245 |
+
/* Grab the included checksum. */
|
246 |
+
$checksum_a = (string) Core::ourSubstr(
|
247 |
+
$bytes,
|
248 |
+
Core::ourStrlen($bytes) - self::CHECKSUM_BYTE_SIZE,
|
249 |
+
self::CHECKSUM_BYTE_SIZE
|
250 |
+
);
|
251 |
+
|
252 |
+
/* Re-compute the checksum. */
|
253 |
+
$checksum_b = \hash(self::CHECKSUM_HASH_ALGO, $checked_bytes, true);
|
254 |
+
|
255 |
+
/* Check if the checksum matches. */
|
256 |
+
if (! Core::hashEquals($checksum_a, $checksum_b)) {
|
257 |
+
throw new Ex\BadFormatException(
|
258 |
+
"Data is corrupted, the checksum doesn't match"
|
259 |
+
);
|
260 |
+
}
|
261 |
+
|
262 |
+
return (string) Core::ourSubstr(
|
263 |
+
$bytes,
|
264 |
+
self::SERIALIZE_HEADER_BYTES,
|
265 |
+
Core::ourStrlen($bytes) - self::SERIALIZE_HEADER_BYTES - self::CHECKSUM_BYTE_SIZE
|
266 |
+
);
|
267 |
+
}
|
268 |
+
}
|
vendor/defuse/php-encryption/src/Exception/BadFormatException.php
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Defuse\Crypto\Exception;
|
4 |
+
|
5 |
+
class BadFormatException extends \Defuse\Crypto\Exception\CryptoException
|
6 |
+
{
|
7 |
+
}
|
vendor/defuse/php-encryption/src/Exception/CryptoException.php
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Defuse\Crypto\Exception;
|
4 |
+
|
5 |
+
class CryptoException extends \Exception
|
6 |
+
{
|
7 |
+
}
|
vendor/defuse/php-encryption/src/Exception/EnvironmentIsBrokenException.php
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Defuse\Crypto\Exception;
|
4 |
+
|
5 |
+
class EnvironmentIsBrokenException extends \Defuse\Crypto\Exception\CryptoException
|
6 |
+
{
|
7 |
+
}
|
vendor/defuse/php-encryption/src/Exception/IOException.php
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Defuse\Crypto\Exception;
|
4 |
+
|
5 |
+
class IOException extends \Defuse\Crypto\Exception\CryptoException
|
6 |
+
{
|
7 |
+
}
|
vendor/defuse/php-encryption/src/Exception/WrongKeyOrModifiedCiphertextException.php
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Defuse\Crypto\Exception;
|
4 |
+
|
5 |
+
class WrongKeyOrModifiedCiphertextException extends \Defuse\Crypto\Exception\CryptoException
|
6 |
+
{
|
7 |
+
}
|
vendor/defuse/php-encryption/src/File.php
ADDED
@@ -0,0 +1,762 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Defuse\Crypto;
|
4 |
+
|
5 |
+
use Defuse\Crypto\Exception as Ex;
|
6 |
+
|
7 |
+
final class File
|
8 |
+
{
|
9 |
+
/**
|
10 |
+
* Encrypts the input file, saving the ciphertext to the output file.
|
11 |
+
*
|
12 |
+
* @param string $inputFilename
|
13 |
+
* @param string $outputFilename
|
14 |
+
* @param Key $key
|
15 |
+
* @return void
|
16 |
+
*
|
17 |
+
* @throws Ex\EnvironmentIsBrokenException
|
18 |
+
* @throws Ex\IOException
|
19 |
+
*/
|
20 |
+
public static function encryptFile($inputFilename, $outputFilename, Key $key)
|
21 |
+
{
|
22 |
+
self::encryptFileInternal(
|
23 |
+
$inputFilename,
|
24 |
+
$outputFilename,
|
25 |
+
KeyOrPassword::createFromKey($key)
|
26 |
+
);
|
27 |
+
}
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Encrypts a file with a password, using a slow key derivation function to
|
31 |
+
* make password cracking more expensive.
|
32 |
+
*
|
33 |
+
* @param string $inputFilename
|
34 |
+
* @param string $outputFilename
|
35 |
+
* @param string $password
|
36 |
+
* @return void
|
37 |
+
*
|
38 |
+
* @throws Ex\EnvironmentIsBrokenException
|
39 |
+
* @throws Ex\IOException
|
40 |
+
*/
|
41 |
+
public static function encryptFileWithPassword($inputFilename, $outputFilename, $password)
|
42 |
+
{
|
43 |
+
self::encryptFileInternal(
|
44 |
+
$inputFilename,
|
45 |
+
$outputFilename,
|
46 |
+
KeyOrPassword::createFromPassword($password)
|
47 |
+
);
|
48 |
+
}
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Decrypts the input file, saving the plaintext to the output file.
|
52 |
+
*
|
53 |
+
* @param string $inputFilename
|
54 |
+
* @param string $outputFilename
|
55 |
+
* @param Key $key
|
56 |
+
* @return void
|
57 |
+
*
|
58 |
+
* @throws Ex\EnvironmentIsBrokenException
|
59 |
+
* @throws Ex\IOException
|
60 |
+
* @throws Ex\WrongKeyOrModifiedCiphertextException
|
61 |
+
*/
|
62 |
+
public static function decryptFile($inputFilename, $outputFilename, Key $key)
|
63 |
+
{
|
64 |
+
self::decryptFileInternal(
|
65 |
+
$inputFilename,
|
66 |
+
$outputFilename,
|
67 |
+
KeyOrPassword::createFromKey($key)
|
68 |
+
);
|
69 |
+
}
|
70 |
+
|
71 |
+
/**
|
72 |
+
* Decrypts a file with a password, using a slow key derivation function to
|
73 |
+
* make password cracking more expensive.
|
74 |
+
*
|
75 |
+
* @param string $inputFilename
|
76 |
+
* @param string $outputFilename
|
77 |
+
* @param string $password
|
78 |
+
* @return void
|
79 |
+
*
|
80 |
+
* @throws Ex\EnvironmentIsBrokenException
|
81 |
+
* @throws Ex\IOException
|
82 |
+
* @throws Ex\WrongKeyOrModifiedCiphertextException
|
83 |
+
*/
|
84 |
+
public static function decryptFileWithPassword($inputFilename, $outputFilename, $password)
|
85 |
+
{
|
86 |
+
self::decryptFileInternal(
|
87 |
+
$inputFilename,
|
88 |
+
$outputFilename,
|
89 |
+
KeyOrPassword::createFromPassword($password)
|
90 |
+
);
|
91 |
+
}
|
92 |
+
|
93 |
+
/**
|
94 |
+
* Takes two resource handles and encrypts the contents of the first,
|
95 |
+
* writing the ciphertext into the second.
|
96 |
+
*
|
97 |
+
* @param resource $inputHandle
|
98 |
+
* @param resource $outputHandle
|
99 |
+
* @param Key $key
|
100 |
+
* @return void
|
101 |
+
*
|
102 |
+
* @throws Ex\EnvironmentIsBrokenException
|
103 |
+
* @throws Ex\WrongKeyOrModifiedCiphertextException
|
104 |
+
*/
|
105 |
+
public static function encryptResource($inputHandle, $outputHandle, Key $key)
|
106 |
+
{
|
107 |
+
self::encryptResourceInternal(
|
108 |
+
$inputHandle,
|
109 |
+
$outputHandle,
|
110 |
+
KeyOrPassword::createFromKey($key)
|
111 |
+
);
|
112 |
+
}
|
113 |
+
|
114 |
+
/**
|
115 |
+
* Encrypts the contents of one resource handle into another with a
|
116 |
+
* password, using a slow key derivation function to make password cracking
|
117 |
+
* more expensive.
|
118 |
+
*
|
119 |
+
* @param resource $inputHandle
|
120 |
+
* @param resource $outputHandle
|
121 |
+
* @param string $password
|
122 |
+
* @return void
|
123 |
+
*
|
124 |
+
* @throws Ex\EnvironmentIsBrokenException
|
125 |
+
* @throws Ex\IOException
|
126 |
+
* @throws Ex\WrongKeyOrModifiedCiphertextException
|
127 |
+
*/
|
128 |
+
public static function encryptResourceWithPassword($inputHandle, $outputHandle, $password)
|
129 |
+
{
|
130 |
+
self::encryptResourceInternal(
|
131 |
+
$inputHandle,
|
132 |
+
$outputHandle,
|
133 |
+
KeyOrPassword::createFromPassword($password)
|
134 |
+
);
|
135 |
+
}
|
136 |
+
|
137 |
+
/**
|
138 |
+
* Takes two resource handles and decrypts the contents of the first,
|
139 |
+
* writing the plaintext into the second.
|
140 |
+
*
|
141 |
+
* @param resource $inputHandle
|
142 |
+
* @param resource $outputHandle
|
143 |
+
* @param Key $key
|
144 |
+
* @return void
|
145 |
+
*
|
146 |
+
* @throws Ex\EnvironmentIsBrokenException
|
147 |
+
* @throws Ex\IOException
|
148 |
+
* @throws Ex\WrongKeyOrModifiedCiphertextException
|
149 |
+
*/
|
150 |
+
public static function decryptResource($inputHandle, $outputHandle, Key $key)
|
151 |
+
{
|
152 |
+
self::decryptResourceInternal(
|
153 |
+
$inputHandle,
|
154 |
+
$outputHandle,
|
155 |
+
KeyOrPassword::createFromKey($key)
|
156 |
+
);
|
157 |
+
}
|
158 |
+
|
159 |
+
/**
|
160 |
+
* Decrypts the contents of one resource into another with a password, using
|
161 |
+
* a slow key derivation function to make password cracking more expensive.
|
162 |
+
*
|
163 |
+
* @param resource $inputHandle
|
164 |
+
* @param resource $outputHandle
|
165 |
+
* @param string $password
|
166 |
+
* @return void
|
167 |
+
*
|
168 |
+
* @throws Ex\EnvironmentIsBrokenException
|
169 |
+
* @throws Ex\IOException
|
170 |
+
* @throws Ex\WrongKeyOrModifiedCiphertextException
|
171 |
+
*/
|
172 |
+
public static function decryptResourceWithPassword($inputHandle, $outputHandle, $password)
|
173 |
+
{
|
174 |
+
self::decryptResourceInternal(
|
175 |
+
$inputHandle,
|
176 |
+
$outputHandle,
|
177 |
+
KeyOrPassword::createFromPassword($password)
|
178 |
+
);
|
179 |
+
}
|
180 |
+
|
181 |
+
/**
|
182 |
+
* Encrypts a file with either a key or a password.
|
183 |
+
*
|
184 |
+
* @param string $inputFilename
|
185 |
+
* @param string $outputFilename
|
186 |
+
* @param KeyOrPassword $secret
|
187 |
+
* @return void
|
188 |
+
*
|
189 |
+
* @throws Ex\CryptoException
|
190 |
+
* @throws Ex\IOException
|
191 |
+
*/
|
192 |
+
private static function encryptFileInternal($inputFilename, $outputFilename, KeyOrPassword $secret)
|
193 |
+
{
|
194 |
+
/* Open the input file. */
|
195 |
+
$if = @\fopen($inputFilename, 'rb');
|
196 |
+
if ($if === false) {
|
197 |
+
throw new Ex\IOException(
|
198 |
+
'Cannot open input file for encrypting: ' .
|
199 |
+
self::getLastErrorMessage()
|
200 |
+
);
|
201 |
+
}
|
202 |
+
if (\is_callable('\\stream_set_read_buffer')) {
|
203 |
+
/* This call can fail, but the only consequence is performance. */
|
204 |
+
\stream_set_read_buffer($if, 0);
|
205 |
+
}
|
206 |
+
|
207 |
+
/* Open the output file. */
|
208 |
+
$of = @\fopen($outputFilename, 'wb');
|
209 |
+
if ($of === false) {
|
210 |
+
\fclose($if);
|
211 |
+
throw new Ex\IOException(
|
212 |
+
'Cannot open output file for encrypting: ' .
|
213 |
+
self::getLastErrorMessage()
|
214 |
+
);
|
215 |
+
}
|
216 |
+
if (\is_callable('\\stream_set_write_buffer')) {
|
217 |
+
/* This call can fail, but the only consequence is performance. */
|
218 |
+
\stream_set_write_buffer($of, 0);
|
219 |
+
}
|
220 |
+
|
221 |
+
/* Perform the encryption. */
|
222 |
+
try {
|
223 |
+
self::encryptResourceInternal($if, $of, $secret);
|
224 |
+
} catch (Ex\CryptoException $ex) {
|
225 |
+
\fclose($if);
|
226 |
+
\fclose($of);
|
227 |
+
throw $ex;
|
228 |
+
}
|
229 |
+
|
230 |
+
/* Close the input file. */
|
231 |
+
if (\fclose($if) === false) {
|
232 |
+
\fclose($of);
|
233 |
+
throw new Ex\IOException(
|
234 |
+
'Cannot close input file after encrypting'
|
235 |
+
);
|
236 |
+
}
|
237 |
+
|
238 |
+
/* Close the output file. */
|
239 |
+
if (\fclose($of) === false) {
|
240 |
+
throw new Ex\IOException(
|
241 |
+
'Cannot close output file after encrypting'
|
242 |
+
);
|
243 |
+
}
|
244 |
+
}
|
245 |
+
|
246 |
+
/**
|
247 |
+
* Decrypts a file with either a key or a password.
|
248 |
+
*
|
249 |
+
* @param string $inputFilename
|
250 |
+
* @param string $outputFilename
|
251 |
+
* @param KeyOrPassword $secret
|
252 |
+
* @return void
|
253 |
+
*
|
254 |
+
* @throws Ex\CryptoException
|
255 |
+
* @throws Ex\IOException
|
256 |
+
*/
|
257 |
+
private static function decryptFileInternal($inputFilename, $outputFilename, KeyOrPassword $secret)
|
258 |
+
{
|
259 |
+
/* Open the input file. */
|
260 |
+
$if = @\fopen($inputFilename, 'rb');
|
261 |
+
if ($if === false) {
|
262 |
+
throw new Ex\IOException(
|
263 |
+
'Cannot open input file for decrypting: ' .
|
264 |
+
self::getLastErrorMessage()
|
265 |
+
);
|
266 |
+
}
|
267 |
+
|
268 |
+
if (\is_callable('\\stream_set_read_buffer')) {
|
269 |
+
/* This call can fail, but the only consequence is performance. */
|
270 |
+
\stream_set_read_buffer($if, 0);
|
271 |
+
}
|
272 |
+
|
273 |
+
/* Open the output file. */
|
274 |
+
$of = @\fopen($outputFilename, 'wb');
|
275 |
+
if ($of === false) {
|
276 |
+
\fclose($if);
|
277 |
+
throw new Ex\IOException(
|
278 |
+
'Cannot open output file for decrypting: ' .
|
279 |
+
self::getLastErrorMessage()
|
280 |
+
);
|
281 |
+
}
|
282 |
+
|
283 |
+
if (\is_callable('\\stream_set_write_buffer')) {
|
284 |
+
/* This call can fail, but the only consequence is performance. */
|
285 |
+
\stream_set_write_buffer($of, 0);
|
286 |
+
}
|
287 |
+
|
288 |
+
/* Perform the decryption. */
|
289 |
+
try {
|
290 |
+
self::decryptResourceInternal($if, $of, $secret);
|
291 |
+
} catch (Ex\CryptoException $ex) {
|
292 |
+
\fclose($if);
|
293 |
+
\fclose($of);
|
294 |
+
throw $ex;
|
295 |
+
}
|
296 |
+
|
297 |
+
/* Close the input file. */
|
298 |
+
if (\fclose($if) === false) {
|
299 |
+
\fclose($of);
|
300 |
+
throw new Ex\IOException(
|
301 |
+
'Cannot close input file after decrypting'
|
302 |
+
);
|
303 |
+
}
|
304 |
+
|
305 |
+
/* Close the output file. */
|
306 |
+
if (\fclose($of) === false) {
|
307 |
+
throw new Ex\IOException(
|
308 |
+
'Cannot close output file after decrypting'
|
309 |
+
);
|
310 |
+
}
|
311 |
+
}
|
312 |
+
|
313 |
+
/**
|
314 |
+
* Encrypts a resource with either a key or a password.
|
315 |
+
*
|
316 |
+
* @param resource $inputHandle
|
317 |
+
* @param resource $outputHandle
|
318 |
+
* @param KeyOrPassword $secret
|
319 |
+
* @return void
|
320 |
+
*
|
321 |
+
* @throws Ex\EnvironmentIsBrokenException
|
322 |
+
* @throws Ex\IOException
|
323 |
+
*/
|
324 |
+
private static function encryptResourceInternal($inputHandle, $outputHandle, KeyOrPassword $secret)
|
325 |
+
{
|
326 |
+
if (! \is_resource($inputHandle)) {
|
327 |
+
throw new Ex\IOException(
|
328 |
+
'Input handle must be a resource!'
|
329 |
+
);
|
330 |
+
}
|
331 |
+
if (! \is_resource($outputHandle)) {
|
332 |
+
throw new Ex\IOException(
|
333 |
+
'Output handle must be a resource!'
|
334 |
+
);
|
335 |
+
}
|
336 |
+
|
337 |
+
$inputStat = \fstat($inputHandle);
|
338 |
+
$inputSize = $inputStat['size'];
|
339 |
+
|
340 |
+
$file_salt = Core::secureRandom(Core::SALT_BYTE_SIZE);
|
341 |
+
$keys = $secret->deriveKeys($file_salt);
|
342 |
+
$ekey = $keys->getEncryptionKey();
|
343 |
+
$akey = $keys->getAuthenticationKey();
|
344 |
+
|
345 |
+
$ivsize = Core::BLOCK_BYTE_SIZE;
|
346 |
+
$iv = Core::secureRandom($ivsize);
|
347 |
+
|
348 |
+
/* Initialize a streaming HMAC state. */
|
349 |
+
/** @var resource $hmac */
|
350 |
+
$hmac = \hash_init(Core::HASH_FUNCTION_NAME, HASH_HMAC, $akey);
|
351 |
+
Core::ensureTrue(
|
352 |
+
\is_resource($hmac) || \is_object($hmac),
|
353 |
+
'Cannot initialize a hash context'
|
354 |
+
);
|
355 |
+
|
356 |
+
/* Write the header, salt, and IV. */
|
357 |
+
self::writeBytes(
|
358 |
+
$outputHandle,
|
359 |
+
Core::CURRENT_VERSION . $file_salt . $iv,
|
360 |
+
Core::HEADER_VERSION_SIZE + Core::SALT_BYTE_SIZE + $ivsize
|
361 |
+
);
|
362 |
+
|
363 |
+
/* Add the header, salt, and IV to the HMAC. */
|
364 |
+
\hash_update($hmac, Core::CURRENT_VERSION);
|
365 |
+
\hash_update($hmac, $file_salt);
|
366 |
+
\hash_update($hmac, $iv);
|
367 |
+
|
368 |
+
/* $thisIv will be incremented after each call to the encryption. */
|
369 |
+
$thisIv = $iv;
|
370 |
+
|
371 |
+
/* How many blocks do we encrypt at a time? We increment by this value. */
|
372 |
+
$inc = (int) (Core::BUFFER_BYTE_SIZE / Core::BLOCK_BYTE_SIZE);
|
373 |
+
|
374 |
+
/* Loop until we reach the end of the input file. */
|
375 |
+
$at_file_end = false;
|
376 |
+
while (! (\feof($inputHandle) || $at_file_end)) {
|
377 |
+
/* Find out if we can read a full buffer, or only a partial one. */
|
378 |
+
/** @var int */
|
379 |
+
$pos = \ftell($inputHandle);
|
380 |
+
if (!\is_int($pos)) {
|
381 |
+
throw new Ex\IOException(
|
382 |
+
'Could not get current position in input file during encryption'
|
383 |
+
);
|
384 |
+
}
|
385 |
+
if ($pos + Core::BUFFER_BYTE_SIZE >= $inputSize) {
|
386 |
+
/* We're at the end of the file, so we need to break out of the loop. */
|
387 |
+
$at_file_end = true;
|
388 |
+
$read = self::readBytes(
|
389 |
+
$inputHandle,
|
390 |
+
$inputSize - $pos
|
391 |
+
);
|
392 |
+
} else {
|
393 |
+
$read = self::readBytes(
|
394 |
+
$inputHandle,
|
395 |
+
Core::BUFFER_BYTE_SIZE
|
396 |
+
);
|
397 |
+
}
|
398 |
+
|
399 |
+
/* Encrypt this buffer. */
|
400 |
+
/** @var string */
|
401 |
+
$encrypted = \openssl_encrypt(
|
402 |
+
$read,
|
403 |
+
Core::CIPHER_METHOD,
|
404 |
+
$ekey,
|
405 |
+
OPENSSL_RAW_DATA,
|
406 |
+
$thisIv
|
407 |
+
);
|
408 |
+
|
409 |
+
Core::ensureTrue(\is_string($encrypted), 'OpenSSL encryption error');
|
410 |
+
|
411 |
+
/* Write this buffer's ciphertext. */
|
412 |
+
self::writeBytes($outputHandle, $encrypted, Core::ourStrlen($encrypted));
|
413 |
+
/* Add this buffer's ciphertext to the HMAC. */
|
414 |
+
\hash_update($hmac, $encrypted);
|
415 |
+
|
416 |
+
/* Increment the counter by the number of blocks in a buffer. */
|
417 |
+
$thisIv = Core::incrementCounter($thisIv, $inc);
|
418 |
+
/* WARNING: Usually, unless the file is a multiple of the buffer
|
419 |
+
* size, $thisIv will contain an incorrect value here on the last
|
420 |
+
* iteration of this loop. */
|
421 |
+
}
|
422 |
+
|
423 |
+
/* Get the HMAC and append it to the ciphertext. */
|
424 |
+
$final_mac = \hash_final($hmac, true);
|
425 |
+
self::writeBytes($outputHandle, $final_mac, Core::MAC_BYTE_SIZE);
|
426 |
+
}
|
427 |
+
|
428 |
+
/**
|
429 |
+
* Decrypts a file-backed resource with either a key or a password.
|
430 |
+
*
|
431 |
+
* @param resource $inputHandle
|
432 |
+
* @param resource $outputHandle
|
433 |
+
* @param KeyOrPassword $secret
|
434 |
+
* @return void
|
435 |
+
*
|
436 |
+
* @throws Ex\EnvironmentIsBrokenException
|
437 |
+
* @throws Ex\IOException
|
438 |
+
* @throws Ex\WrongKeyOrModifiedCiphertextException
|
439 |
+
*/
|
440 |
+
public static function decryptResourceInternal($inputHandle, $outputHandle, KeyOrPassword $secret)
|
441 |
+
{
|
442 |
+
if (! \is_resource($inputHandle)) {
|
443 |
+
throw new Ex\IOException(
|
444 |
+
'Input handle must be a resource!'
|
445 |
+
);
|
446 |
+
}
|
447 |
+
if (! \is_resource($outputHandle)) {
|
448 |
+
throw new Ex\IOException(
|
449 |
+
'Output handle must be a resource!'
|
450 |
+
);
|
451 |
+
}
|
452 |
+
|
453 |
+
/* Make sure the file is big enough for all the reads we need to do. */
|
454 |
+
$stat = \fstat($inputHandle);
|
455 |
+
if ($stat['size'] < Core::MINIMUM_CIPHERTEXT_SIZE) {
|
456 |
+
throw new Ex\WrongKeyOrModifiedCiphertextException(
|
457 |
+
'Input file is too small to have been created by this library.'
|
458 |
+
);
|
459 |
+
}
|
460 |
+
|
461 |
+
/* Check the version header. */
|
462 |
+
$header = self::readBytes($inputHandle, Core::HEADER_VERSION_SIZE);
|
463 |
+
if ($header !== Core::CURRENT_VERSION) {
|
464 |
+
throw new Ex\WrongKeyOrModifiedCiphertextException(
|
465 |
+
'Bad version header.'
|
466 |
+
);
|
467 |
+
}
|
468 |
+
|
469 |
+
/* Get the salt. */
|
470 |
+
$file_salt = self::readBytes($inputHandle, Core::SALT_BYTE_SIZE);
|
471 |
+
|
472 |
+
/* Get the IV. */
|
473 |
+
$ivsize = Core::BLOCK_BYTE_SIZE;
|
474 |
+
$iv = self::readBytes($inputHandle, $ivsize);
|
475 |
+
|
476 |
+
/* Derive the authentication and encryption keys. */
|
477 |
+
$keys = $secret->deriveKeys($file_salt);
|
478 |
+
$ekey = $keys->getEncryptionKey();
|
479 |
+
$akey = $keys->getAuthenticationKey();
|
480 |
+
|
481 |
+
/* We'll store the MAC of each buffer-sized chunk as we verify the
|
482 |
+
* actual MAC, so that we can check them again when decrypting. */
|
483 |
+
$macs = [];
|
484 |
+
|
485 |
+
/* $thisIv will be incremented after each call to the decryption. */
|
486 |
+
$thisIv = $iv;
|
487 |
+
|
488 |
+
/* How many blocks do we encrypt at a time? We increment by this value. */
|
489 |
+
$inc = (int) (Core::BUFFER_BYTE_SIZE / Core::BLOCK_BYTE_SIZE);
|
490 |
+
|
491 |
+
/* Get the HMAC. */
|
492 |
+
if (\fseek($inputHandle, (-1 * Core::MAC_BYTE_SIZE), SEEK_END) === false) {
|
493 |
+
throw new Ex\IOException(
|
494 |
+
'Cannot seek to beginning of MAC within input file'
|
495 |
+
);
|
496 |
+
}
|
497 |
+
|
498 |
+
/* Get the position of the last byte in the actual ciphertext. */
|
499 |
+
/** @var int $cipher_end */
|
500 |
+
$cipher_end = \ftell($inputHandle);
|
501 |
+
if (!\is_int($cipher_end)) {
|
502 |
+
throw new Ex\IOException(
|
503 |
+
'Cannot read input file'
|
504 |
+
);
|
505 |
+
}
|
506 |
+
/* We have the position of the first byte of the HMAC. Go back by one. */
|
507 |
+
--$cipher_end;
|
508 |
+
|
509 |
+
/* Read the HMAC. */
|
510 |
+
/** @var string $stored_mac */
|
511 |
+
$stored_mac = self::readBytes($inputHandle, Core::MAC_BYTE_SIZE);
|
512 |
+
|
513 |
+
/* Initialize a streaming HMAC state. */
|
514 |
+
/** @var resource $hmac */
|
515 |
+
$hmac = \hash_init(Core::HASH_FUNCTION_NAME, HASH_HMAC, $akey);
|
516 |
+
Core::ensureTrue(\is_resource($hmac) || \is_object($hmac), 'Cannot initialize a hash context');
|
517 |
+
|
518 |
+
/* Reset file pointer to the beginning of the file after the header */
|
519 |
+
if (\fseek($inputHandle, Core::HEADER_VERSION_SIZE, SEEK_SET) === false) {
|
520 |
+
throw new Ex\IOException(
|
521 |
+
'Cannot read seek within input file'
|
522 |
+
);
|
523 |
+
}
|
524 |
+
|
525 |
+
/* Seek to the start of the actual ciphertext. */
|
526 |
+
if (\fseek($inputHandle, Core::SALT_BYTE_SIZE + $ivsize, SEEK_CUR) === false) {
|
527 |
+
throw new Ex\IOException(
|
528 |
+
'Cannot seek input file to beginning of ciphertext'
|
529 |
+
);
|
530 |
+
}
|
531 |
+
|
532 |
+
/* PASS #1: Calculating the HMAC. */
|
533 |
+
|
534 |
+
\hash_update($hmac, $header);
|
535 |
+
\hash_update($hmac, $file_salt);
|
536 |
+
\hash_update($hmac, $iv);
|
537 |
+
/** @var resource $hmac2 */
|
538 |
+
$hmac2 = \hash_copy($hmac);
|
539 |
+
|
540 |
+
$break = false;
|
541 |
+
while (! $break) {
|
542 |
+
/** @var int $pos */
|
543 |
+
$pos = \ftell($inputHandle);
|
544 |
+
if (!\is_int($pos)) {
|
545 |
+
throw new Ex\IOException(
|
546 |
+
'Could not get current position in input file during decryption'
|
547 |
+
);
|
548 |
+
}
|
549 |
+
|
550 |
+
/* Read the next buffer-sized chunk (or less). */
|
551 |
+
if ($pos + Core::BUFFER_BYTE_SIZE >= $cipher_end) {
|
552 |
+
$break = true;
|
553 |
+
$read = self::readBytes(
|
554 |
+
$inputHandle,
|
555 |
+
$cipher_end - $pos + 1
|
556 |
+
);
|
557 |
+
} else {
|
558 |
+
$read = self::readBytes(
|
559 |
+
$inputHandle,
|
560 |
+
Core::BUFFER_BYTE_SIZE
|
561 |
+
);
|
562 |
+
}
|
563 |
+
|
564 |
+
/* Update the HMAC. */
|
565 |
+
\hash_update($hmac, $read);
|
566 |
+
|
567 |
+
/* Remember this buffer-sized chunk's HMAC. */
|
568 |
+
/** @var resource $chunk_mac */
|
569 |
+
$chunk_mac = \hash_copy($hmac);
|
570 |
+
Core::ensureTrue(\is_resource($chunk_mac) || \is_object($chunk_mac), 'Cannot duplicate a hash context');
|
571 |
+
$macs []= \hash_final($chunk_mac);
|
572 |
+
}
|
573 |
+
|
574 |
+
/* Get the final HMAC, which should match the stored one. */
|
575 |
+
/** @var string $final_mac */
|
576 |
+
$final_mac = \hash_final($hmac, true);
|
577 |
+
|
578 |
+
/* Verify the HMAC. */
|
579 |
+
if (! Core::hashEquals($final_mac, $stored_mac)) {
|
580 |
+
throw new Ex\WrongKeyOrModifiedCiphertextException(
|
581 |
+
'Integrity check failed.'
|
582 |
+
);
|
583 |
+
}
|
584 |
+
|
585 |
+
/* PASS #2: Decrypt and write output. */
|
586 |
+
|
587 |
+
/* Rewind to the start of the actual ciphertext. */
|
588 |
+
if (\fseek($inputHandle, Core::SALT_BYTE_SIZE + $ivsize + Core::HEADER_VERSION_SIZE, SEEK_SET) === false) {
|
589 |
+
throw new Ex\IOException(
|
590 |
+
'Could not move the input file pointer during decryption'
|
591 |
+
);
|
592 |
+
}
|
593 |
+
|
594 |
+
$at_file_end = false;
|
595 |
+
while (! $at_file_end) {
|
596 |
+
/** @var int $pos */
|
597 |
+
$pos = \ftell($inputHandle);
|
598 |
+
if (!\is_int($pos)) {
|
599 |
+
throw new Ex\IOException(
|
600 |
+
'Could not get current position in input file during decryption'
|
601 |
+
);
|
602 |
+
}
|
603 |
+
|
604 |
+
/* Read the next buffer-sized chunk (or less). */
|
605 |
+
if ($pos + Core::BUFFER_BYTE_SIZE >= $cipher_end) {
|
606 |
+
$at_file_end = true;
|
607 |
+
$read = self::readBytes(
|
608 |
+
$inputHandle,
|
609 |
+
$cipher_end - $pos + 1
|
610 |
+
);
|
611 |
+
} else {
|
612 |
+
$read = self::readBytes(
|
613 |
+
$inputHandle,
|
614 |
+
Core::BUFFER_BYTE_SIZE
|
615 |
+
);
|
616 |
+
}
|
617 |
+
|
618 |
+
/* Recalculate the MAC (so far) and compare it with the one we
|
619 |
+
* remembered from pass #1 to ensure attackers didn't change the
|
620 |
+
* ciphertext after MAC verification. */
|
621 |
+
\hash_update($hmac2, $read);
|
622 |
+
/** @var resource $calc_mac */
|
623 |
+
$calc_mac = \hash_copy($hmac2);
|
624 |
+
Core::ensureTrue(\is_resource($calc_mac) || \is_object($calc_mac), 'Cannot duplicate a hash context');
|
625 |
+
$calc = \hash_final($calc_mac);
|
626 |
+
|
627 |
+
if (empty($macs)) {
|
628 |
+
throw new Ex\WrongKeyOrModifiedCiphertextException(
|
629 |
+
'File was modified after MAC verification'
|
630 |
+
);
|
631 |
+
} elseif (! Core::hashEquals(\array_shift($macs), $calc)) {
|
632 |
+
throw new Ex\WrongKeyOrModifiedCiphertextException(
|
633 |
+
'File was modified after MAC verification'
|
634 |
+
);
|
635 |
+
}
|
636 |
+
|
637 |
+
/* Decrypt this buffer-sized chunk. */
|
638 |
+
/** @var string $decrypted */
|
639 |
+
$decrypted = \openssl_decrypt(
|
640 |
+
$read,
|
641 |
+
Core::CIPHER_METHOD,
|
642 |
+
$ekey,
|
643 |
+
OPENSSL_RAW_DATA,
|
644 |
+
$thisIv
|
645 |
+
);
|
646 |
+
Core::ensureTrue(\is_string($decrypted), 'OpenSSL decryption error');
|
647 |
+
|
648 |
+
/* Write the plaintext to the output file. */
|
649 |
+
self::writeBytes(
|
650 |
+
$outputHandle,
|
651 |
+
$decrypted,
|
652 |
+
Core::ourStrlen($decrypted)
|
653 |
+
);
|
654 |
+
|
655 |
+
/* Increment the IV by the amount of blocks in a buffer. */
|
656 |
+
/** @var string $thisIv */
|
657 |
+
$thisIv = Core::incrementCounter($thisIv, $inc);
|
658 |
+
/* WARNING: Usually, unless the file is a multiple of the buffer
|
659 |
+
* size, $thisIv will contain an incorrect value here on the last
|
660 |
+
* iteration of this loop. */
|
661 |
+
}
|
662 |
+
}
|
663 |
+
|
664 |
+
/**
|
665 |
+
* Read from a stream; prevent partial reads.
|
666 |
+
*
|
667 |
+
* @param resource $stream
|
668 |
+
* @param int $num_bytes
|
669 |
+
* @return string
|
670 |
+
*
|
671 |
+
* @throws Ex\IOException
|
672 |
+
* @throws Ex\EnvironmentIsBrokenException
|
673 |
+
*
|
674 |
+
* @return string
|
675 |
+
*/
|
676 |
+
public static function readBytes($stream, $num_bytes)
|
677 |
+
{
|
678 |
+
Core::ensureTrue($num_bytes >= 0, 'Tried to read less than 0 bytes');
|
679 |
+
|
680 |
+
if ($num_bytes === 0) {
|
681 |
+
return '';
|
682 |
+
}
|
683 |
+
|
684 |
+
$buf = '';
|
685 |
+
$remaining = $num_bytes;
|
686 |
+
while ($remaining > 0 && ! \feof($stream)) {
|
687 |
+
/** @var string $read */
|
688 |
+
$read = \fread($stream, $remaining);
|
689 |
+
if (!\is_string($read)) {
|
690 |
+
throw new Ex\IOException(
|
691 |
+
'Could not read from the file'
|
692 |
+
);
|
693 |
+
}
|
694 |
+
$buf .= $read;
|
695 |
+
$remaining -= Core::ourStrlen($read);
|
696 |
+
}
|
697 |
+
if (Core::ourStrlen($buf) !== $num_bytes) {
|
698 |
+
throw new Ex\IOException(
|
699 |
+
'Tried to read past the end of the file'
|
700 |
+
);
|
701 |
+
}
|
702 |
+
return $buf;
|
703 |
+
}
|
704 |
+
|
705 |
+
/**
|
706 |
+
* Write to a stream; prevents partial writes.
|
707 |
+
*
|
708 |
+
* @param resource $stream
|
709 |
+
* @param string $buf
|
710 |
+
* @param int $num_bytes
|
711 |
+
* @return int
|
712 |
+
*
|
713 |
+
* @throws Ex\IOException
|
714 |
+
*
|
715 |
+
* @return string
|
716 |
+
*/
|
717 |
+
public static function writeBytes($stream, $buf, $num_bytes = null)
|
718 |
+
{
|
719 |
+
$bufSize = Core::ourStrlen($buf);
|
720 |
+
if ($num_bytes === null) {
|
721 |
+
$num_bytes = $bufSize;
|
722 |
+
}
|
723 |
+
if ($num_bytes > $bufSize) {
|
724 |
+
throw new Ex\IOException(
|
725 |
+
'Trying to write more bytes than the buffer contains.'
|
726 |
+
);
|
727 |
+
}
|
728 |
+
if ($num_bytes < 0) {
|
729 |
+
throw new Ex\IOException(
|
730 |
+
'Tried to write less than 0 bytes'
|
731 |
+
);
|
732 |
+
}
|
733 |
+
$remaining = $num_bytes;
|
734 |
+
while ($remaining > 0) {
|
735 |
+
/** @var int $written */
|
736 |
+
$written = \fwrite($stream, $buf, $remaining);
|
737 |
+
if (!\is_int($written)) {
|
738 |
+
throw new Ex\IOException(
|
739 |
+
'Could not write to the file'
|
740 |
+
);
|
741 |
+
}
|
742 |
+
$buf = (string) Core::ourSubstr($buf, $written, null);
|
743 |
+
$remaining -= $written;
|
744 |
+
}
|
745 |
+
return $num_bytes;
|
746 |
+
}
|
747 |
+
|
748 |
+
/**
|
749 |
+
* Returns the last PHP error's or warning's message string.
|
750 |
+
*
|
751 |
+
* @return string
|
752 |
+
*/
|
753 |
+
private static function getLastErrorMessage()
|
754 |
+
{
|
755 |
+
$error = error_get_last();
|
756 |
+
if ($error === null) {
|
757 |
+
return '[no PHP error]';
|
758 |
+
} else {
|
759 |
+
return $error['message'];
|
760 |
+
}
|
761 |
+
}
|
762 |
+
}
|
vendor/defuse/php-encryption/src/Key.php
ADDED
@@ -0,0 +1,94 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Defuse\Crypto;
|
4 |
+
|
5 |
+
use Defuse\Crypto\Exception as Ex;
|
6 |
+
|
7 |
+
final class Key
|
8 |
+
{
|
9 |
+
const KEY_CURRENT_VERSION = "\xDE\xF0\x00\x00";
|
10 |
+
const KEY_BYTE_SIZE = 32;
|
11 |
+
|
12 |
+
/**
|
13 |
+
* @var string
|
14 |
+
*/
|
15 |
+
private $key_bytes;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Creates new random key.
|
19 |
+
*
|
20 |
+
* @throws Ex\EnvironmentIsBrokenException
|
21 |
+
*
|
22 |
+
* @return Key
|
23 |
+
*/
|
24 |
+
public static function createNewRandomKey()
|
25 |
+
{
|
26 |
+
return new Key(Core::secureRandom(self::KEY_BYTE_SIZE));
|
27 |
+
}
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Loads a Key from its encoded form.
|
31 |
+
*
|
32 |
+
* By default, this function will call Encoding::trimTrailingWhitespace()
|
33 |
+
* to remove trailing CR, LF, NUL, TAB, and SPACE characters, which are
|
34 |
+
* commonly appended to files when working with text editors.
|
35 |
+
*
|
36 |
+
* @param string $saved_key_string
|
37 |
+
* @param bool $do_not_trim (default: false)
|
38 |
+
*
|
39 |
+
* @throws Ex\BadFormatException
|
40 |
+
* @throws Ex\EnvironmentIsBrokenException
|
41 |
+
*
|
42 |
+
* @return Key
|
43 |
+
*/
|
44 |
+
public static function loadFromAsciiSafeString($saved_key_string, $do_not_trim = false)
|
45 |
+
{
|
46 |
+
if (!$do_not_trim) {
|
47 |
+
$saved_key_string = Encoding::trimTrailingWhitespace($saved_key_string);
|
48 |
+
}
|
49 |
+
$key_bytes = Encoding::loadBytesFromChecksummedAsciiSafeString(self::KEY_CURRENT_VERSION, $saved_key_string);
|
50 |
+
return new Key($key_bytes);
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Encodes the Key into a string of printable ASCII characters.
|
55 |
+
*
|
56 |
+
* @throws Ex\EnvironmentIsBrokenException
|
57 |
+
*
|
58 |
+
* @return string
|
59 |
+
*/
|
60 |
+
public function saveToAsciiSafeString()
|
61 |
+
{
|
62 |
+
return Encoding::saveBytesToChecksummedAsciiSafeString(
|
63 |
+
self::KEY_CURRENT_VERSION,
|
64 |
+
$this->key_bytes
|
65 |
+
);
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Gets the raw bytes of the key.
|
70 |
+
*
|
71 |
+
* @return string
|
72 |
+
*/
|
73 |
+
public function getRawBytes()
|
74 |
+
{
|
75 |
+
return $this->key_bytes;
|
76 |
+
}
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Constructs a new Key object from a string of raw bytes.
|
80 |
+
*
|
81 |
+
* @param string $bytes
|
82 |
+
*
|
83 |
+
* @throws Ex\EnvironmentIsBrokenException
|
84 |
+
*/
|
85 |
+
private function __construct($bytes)
|
86 |
+
{
|
87 |
+
Core::ensureTrue(
|
88 |
+
Core::ourStrlen($bytes) === self::KEY_BYTE_SIZE,
|
89 |
+
'Bad key length.'
|
90 |
+
);
|
91 |
+
$this->key_bytes = $bytes;
|
92 |
+
}
|
93 |
+
|
94 |
+
}
|
vendor/defuse/php-encryption/src/KeyOrPassword.php
ADDED
@@ -0,0 +1,149 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Defuse\Crypto;
|
4 |
+
|
5 |
+
use Defuse\Crypto\Exception as Ex;
|
6 |
+
|
7 |
+
final class KeyOrPassword
|
8 |
+
{
|
9 |
+
const PBKDF2_ITERATIONS = 100000;
|
10 |
+
const SECRET_TYPE_KEY = 1;
|
11 |
+
const SECRET_TYPE_PASSWORD = 2;
|
12 |
+
|
13 |
+
/**
|
14 |
+
* @var int
|
15 |
+
*/
|
16 |
+
private $secret_type = 0;
|
17 |
+
|
18 |
+
/**
|
19 |
+
* @var Key|string
|
20 |
+
*/
|
21 |
+
private $secret;
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Initializes an instance of KeyOrPassword from a key.
|
25 |
+
*
|
26 |
+
* @param Key $key
|
27 |
+
*
|
28 |
+
* @return KeyOrPassword
|
29 |
+
*/
|
30 |
+
public static function createFromKey(Key $key)
|
31 |
+
{
|
32 |
+
return new KeyOrPassword(self::SECRET_TYPE_KEY, $key);
|
33 |
+
}
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Initializes an instance of KeyOrPassword from a password.
|
37 |
+
*
|
38 |
+
* @param string $password
|
39 |
+
*
|
40 |
+
* @return KeyOrPassword
|
41 |
+
*/
|
42 |
+
public static function createFromPassword($password)
|
43 |
+
{
|
44 |
+
return new KeyOrPassword(self::SECRET_TYPE_PASSWORD, $password);
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Derives authentication and encryption keys from the secret, using a slow
|
49 |
+
* key derivation function if the secret is a password.
|
50 |
+
*
|
51 |
+
* @param string $salt
|
52 |
+
*
|
53 |
+
* @throws Ex\CryptoException
|
54 |
+
* @throws Ex\EnvironmentIsBrokenException
|
55 |
+
*
|
56 |
+
* @return DerivedKeys
|
57 |
+
*/
|
58 |
+
public function deriveKeys($salt)
|
59 |
+
{
|
60 |
+
Core::ensureTrue(
|
61 |
+
Core::ourStrlen($salt) === Core::SALT_BYTE_SIZE,
|
62 |
+
'Bad salt.'
|
63 |
+
);
|
64 |
+
|
65 |
+
if ($this->secret_type === self::SECRET_TYPE_KEY) {
|
66 |
+
Core::ensureTrue($this->secret instanceof Key);
|
67 |
+
/**
|
68 |
+
* @psalm-suppress PossiblyInvalidMethodCall
|
69 |
+
*/
|
70 |
+
$akey = Core::HKDF(
|
71 |
+
Core::HASH_FUNCTION_NAME,
|
72 |
+
$this->secret->getRawBytes(),
|
73 |
+
Core::KEY_BYTE_SIZE,
|
74 |
+
Core::AUTHENTICATION_INFO_STRING,
|
75 |
+
$salt
|
76 |
+
);
|
77 |
+
/**
|
78 |
+
* @psalm-suppress PossiblyInvalidMethodCall
|
79 |
+
*/
|
80 |
+
$ekey = Core::HKDF(
|
81 |
+
Core::HASH_FUNCTION_NAME,
|
82 |
+
$this->secret->getRawBytes(),
|
83 |
+
Core::KEY_BYTE_SIZE,
|
84 |
+
Core::ENCRYPTION_INFO_STRING,
|
85 |
+
$salt
|
86 |
+
);
|
87 |
+
return new DerivedKeys($akey, $ekey);
|
88 |
+
} elseif ($this->secret_type === self::SECRET_TYPE_PASSWORD) {
|
89 |
+
Core::ensureTrue(\is_string($this->secret));
|
90 |
+
/* Our PBKDF2 polyfill is vulnerable to a DoS attack documented in
|
91 |
+
* GitHub issue #230. The fix is to pre-hash the password to ensure
|
92 |
+
* it is short. We do the prehashing here instead of in pbkdf2() so
|
93 |
+
* that pbkdf2() still computes the function as defined by the
|
94 |
+
* standard. */
|
95 |
+
|
96 |
+
/**
|
97 |
+
* @psalm-suppress PossiblyInvalidArgument
|
98 |
+
*/
|
99 |
+
$prehash = \hash(Core::HASH_FUNCTION_NAME, $this->secret, true);
|
100 |
+
|
101 |
+
$prekey = Core::pbkdf2(
|
102 |
+
Core::HASH_FUNCTION_NAME,
|
103 |
+
$prehash,
|
104 |
+
$salt,
|
105 |
+
self::PBKDF2_ITERATIONS,
|
106 |
+
Core::KEY_BYTE_SIZE,
|
107 |
+
true
|
108 |
+
);
|
109 |
+
$akey = Core::HKDF(
|
110 |
+
Core::HASH_FUNCTION_NAME,
|
111 |
+
$prekey,
|
112 |
+
Core::KEY_BYTE_SIZE,
|
113 |
+
Core::AUTHENTICATION_INFO_STRING,
|
114 |
+
$salt
|
115 |
+
);
|
116 |
+
/* Note the cryptographic re-use of $salt here. */
|
117 |
+
$ekey = Core::HKDF(
|
118 |
+
Core::HASH_FUNCTION_NAME,
|
119 |
+
$prekey,
|
120 |
+
Core::KEY_BYTE_SIZE,
|
121 |
+
Core::ENCRYPTION_INFO_STRING,
|
122 |
+
$salt
|
123 |
+
);
|
124 |
+
return new DerivedKeys($akey, $ekey);
|
125 |
+
} else {
|
126 |
+
throw new Ex\EnvironmentIsBrokenException('Bad secret type.');
|
127 |
+
}
|
128 |
+
}
|
129 |
+
|
130 |
+
/**
|
131 |
+
* Constructor for KeyOrPassword.
|
132 |
+
*
|
133 |
+
* @param int $secret_type
|
134 |
+
* @param mixed $secret (either a Key or a password string)
|
135 |
+
*/
|
136 |
+
private function __construct($secret_type, $secret)
|
137 |
+
{
|
138 |
+
// The constructor is private, so these should never throw.
|
139 |
+
if ($secret_type === self::SECRET_TYPE_KEY) {
|
140 |
+
Core::ensureTrue($secret instanceof Key);
|
141 |
+
} elseif ($secret_type === self::SECRET_TYPE_PASSWORD) {
|
142 |
+
Core::ensureTrue(\is_string($secret));
|
143 |
+
} else {
|
144 |
+
throw new Ex\EnvironmentIsBrokenException('Bad secret type.');
|
145 |
+
}
|
146 |
+
$this->secret_type = $secret_type;
|
147 |
+
$this->secret = $secret;
|
148 |
+
}
|
149 |
+
}
|
vendor/defuse/php-encryption/src/KeyProtectedByPassword.php
ADDED
@@ -0,0 +1,145 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Defuse\Crypto;
|
4 |
+
|
5 |
+
use Defuse\Crypto\Exception as Ex;
|
6 |
+
|
7 |
+
final class KeyProtectedByPassword
|
8 |
+
{
|
9 |
+
const PASSWORD_KEY_CURRENT_VERSION = "\xDE\xF1\x00\x00";
|
10 |
+
|
11 |
+
/**
|
12 |
+
* @var string
|
13 |
+
*/
|
14 |
+
private $encrypted_key = '';
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Creates a random key protected by the provided password.
|
18 |
+
*
|
19 |
+
* @param string $password
|
20 |
+
*
|
21 |
+
* @throws Ex\EnvironmentIsBrokenException
|
22 |
+
*
|
23 |
+
* @return KeyProtectedByPassword
|
24 |
+
*/
|
25 |
+
public static function createRandomPasswordProtectedKey($password)
|
26 |
+
{
|
27 |
+
$inner_key = Key::createNewRandomKey();
|
28 |
+
/* The password is hashed as a form of poor-man's domain separation
|
29 |
+
* between this use of encryptWithPassword() and other uses of
|
30 |
+
* encryptWithPassword() that the user may also be using as part of the
|
31 |
+
* same protocol. */
|
32 |
+
$encrypted_key = Crypto::encryptWithPassword(
|
33 |
+
$inner_key->saveToAsciiSafeString(),
|
34 |
+
\hash(Core::HASH_FUNCTION_NAME, $password, true),
|
35 |
+
true
|
36 |
+
);
|
37 |
+
|
38 |
+
return new KeyProtectedByPassword($encrypted_key);
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Loads a KeyProtectedByPassword from its encoded form.
|
43 |
+
*
|
44 |
+
* @param string $saved_key_string
|
45 |
+
*
|
46 |
+
* @throws Ex\BadFormatException
|
47 |
+
*
|
48 |
+
* @return KeyProtectedByPassword
|
49 |
+
*/
|
50 |
+
public static function loadFromAsciiSafeString($saved_key_string)
|
51 |
+
{
|
52 |
+
$encrypted_key = Encoding::loadBytesFromChecksummedAsciiSafeString(
|
53 |
+
self::PASSWORD_KEY_CURRENT_VERSION,
|
54 |
+
$saved_key_string
|
55 |
+
);
|
56 |
+
return new KeyProtectedByPassword($encrypted_key);
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Encodes the KeyProtectedByPassword into a string of printable ASCII
|
61 |
+
* characters.
|
62 |
+
*
|
63 |
+
* @throws Ex\EnvironmentIsBrokenException
|
64 |
+
*
|
65 |
+
* @return string
|
66 |
+
*/
|
67 |
+
public function saveToAsciiSafeString()
|
68 |
+
{
|
69 |
+
return Encoding::saveBytesToChecksummedAsciiSafeString(
|
70 |
+
self::PASSWORD_KEY_CURRENT_VERSION,
|
71 |
+
$this->encrypted_key
|
72 |
+
);
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Decrypts the protected key, returning an unprotected Key object that can
|
77 |
+
* be used for encryption and decryption.
|
78 |
+
*
|
79 |
+
* @throws Ex\EnvironmentIsBrokenException
|
80 |
+
* @throws Ex\WrongKeyOrModifiedCiphertextException
|
81 |
+
*
|
82 |
+
* @param string $password
|
83 |
+
* @return Key
|
84 |
+
*/
|
85 |
+
public function unlockKey($password)
|
86 |
+
{
|
87 |
+
try {
|
88 |
+
$inner_key_encoded = Crypto::decryptWithPassword(
|
89 |
+
$this->encrypted_key,
|
90 |
+
\hash(Core::HASH_FUNCTION_NAME, $password, true),
|
91 |
+
true
|
92 |
+
);
|
93 |
+
return Key::loadFromAsciiSafeString($inner_key_encoded);
|
94 |
+
} catch (Ex\BadFormatException $ex) {
|
95 |
+
/* This should never happen unless an attacker replaced the
|
96 |
+
* encrypted key ciphertext with some other ciphertext that was
|
97 |
+
* encrypted with the same password. We transform the exception type
|
98 |
+
* here in order to make the API simpler, avoiding the need to
|
99 |
+
* document that this method might throw an Ex\BadFormatException. */
|
100 |
+
throw new Ex\WrongKeyOrModifiedCiphertextException(
|
101 |
+
"The decrypted key was found to be in an invalid format. " .
|
102 |
+
"This very likely indicates it was modified by an attacker."
|
103 |
+
);
|
104 |
+
}
|
105 |
+
}
|
106 |
+
|
107 |
+
/**
|
108 |
+
* Changes the password.
|
109 |
+
*
|
110 |
+
* @param string $current_password
|
111 |
+
* @param string $new_password
|
112 |
+
*
|
113 |
+
* @throws Ex\EnvironmentIsBrokenException
|
114 |
+
* @throws Ex\WrongKeyOrModifiedCiphertextException
|
115 |
+
*
|
116 |
+
* @return KeyProtectedByPassword
|
117 |
+
*/
|
118 |
+
public function changePassword($current_password, $new_password)
|
119 |
+
{
|
120 |
+
$inner_key = $this->unlockKey($current_password);
|
121 |
+
/* The password is hashed as a form of poor-man's domain separation
|
122 |
+
* between this use of encryptWithPassword() and other uses of
|
123 |
+
* encryptWithPassword() that the user may also be using as part of the
|
124 |
+
* same protocol. */
|
125 |
+
$encrypted_key = Crypto::encryptWithPassword(
|
126 |
+
$inner_key->saveToAsciiSafeString(),
|
127 |
+
\hash(Core::HASH_FUNCTION_NAME, $new_password, true),
|
128 |
+
true
|
129 |
+
);
|
130 |
+
|
131 |
+
$this->encrypted_key = $encrypted_key;
|
132 |
+
|
133 |
+
return $this;
|
134 |
+
}
|
135 |
+
|
136 |
+
/**
|
137 |
+
* Constructor for KeyProtectedByPassword.
|
138 |
+
*
|
139 |
+
* @param string $encrypted_key
|
140 |
+
*/
|
141 |
+
private function __construct($encrypted_key)
|
142 |
+
{
|
143 |
+
$this->encrypted_key = $encrypted_key;
|
144 |
+
}
|
145 |
+
}
|
vendor/defuse/php-encryption/src/RuntimeTests.php
ADDED
@@ -0,0 +1,228 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Defuse\Crypto;
|
4 |
+
|
5 |
+
use Defuse\Crypto\Exception as Ex;
|
6 |
+
|
7 |
+
/*
|
8 |
+
* We're using static class inheritance to get access to protected methods
|
9 |
+
* inside Crypto. To make it easy to know where the method we're calling can be
|
10 |
+
* found, within this file, prefix calls with `Crypto::` or `RuntimeTests::`,
|
11 |
+
* and don't use `self::`.
|
12 |
+
*/
|
13 |
+
|
14 |
+
class RuntimeTests extends Crypto
|
15 |
+
{
|
16 |
+
/**
|
17 |
+
* Runs the runtime tests.
|
18 |
+
*
|
19 |
+
* @throws Ex\EnvironmentIsBrokenException
|
20 |
+
* @return void
|
21 |
+
*/
|
22 |
+
public static function runtimeTest()
|
23 |
+
{
|
24 |
+
// 0: Tests haven't been run yet.
|
25 |
+
// 1: Tests have passed.
|
26 |
+
// 2: Tests are running right now.
|
27 |
+
// 3: Tests have failed.
|
28 |
+
static $test_state = 0;
|
29 |
+
|
30 |
+
if ($test_state === 1 || $test_state === 2) {
|
31 |
+
return;
|
32 |
+
}
|
33 |
+
|
34 |
+
if ($test_state === 3) {
|
35 |
+
/* If an intermittent problem caused a test to fail previously, we
|
36 |
+
* want that to be indicated to the user with every call to this
|
37 |
+
* library. This way, if the user first does something they really
|
38 |
+
* don't care about, and just ignores all exceptions, they won't get
|
39 |
+
* screwed when they then start to use the library for something
|
40 |
+
* they do care about. */
|
41 |
+
throw new Ex\EnvironmentIsBrokenException('Tests failed previously.');
|
42 |
+
}
|
43 |
+
|
44 |
+
try {
|
45 |
+
$test_state = 2;
|
46 |
+
|
47 |
+
Core::ensureFunctionExists('openssl_get_cipher_methods');
|
48 |
+
if (\in_array(Core::CIPHER_METHOD, \openssl_get_cipher_methods()) === false) {
|
49 |
+
throw new Ex\EnvironmentIsBrokenException(
|
50 |
+
'Cipher method not supported. This is normally caused by an outdated ' .
|
51 |
+
'version of OpenSSL (and/or OpenSSL compiled for FIPS compliance). ' .
|
52 |
+
'Please upgrade to a newer version of OpenSSL that supports ' .
|
53 |
+
Core::CIPHER_METHOD . ' to use this library.'
|
54 |
+
);
|
55 |
+
}
|
56 |
+
|
57 |
+
RuntimeTests::AESTestVector();
|
58 |
+
RuntimeTests::HMACTestVector();
|
59 |
+
RuntimeTests::HKDFTestVector();
|
60 |
+
|
61 |
+
RuntimeTests::testEncryptDecrypt();
|
62 |
+
Core::ensureTrue(Core::ourStrlen(Key::createNewRandomKey()->getRawBytes()) === Core::KEY_BYTE_SIZE);
|
63 |
+
|
64 |
+
Core::ensureTrue(Core::ENCRYPTION_INFO_STRING !== Core::AUTHENTICATION_INFO_STRING);
|
65 |
+
} catch (Ex\EnvironmentIsBrokenException $ex) {
|
66 |
+
// Do this, otherwise it will stay in the "tests are running" state.
|
67 |
+
$test_state = 3;
|
68 |
+
throw $ex;
|
69 |
+
}
|
70 |
+
|
71 |
+
// Change this to '0' make the tests always re-run (for benchmarking).
|
72 |
+
$test_state = 1;
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* High-level tests of Crypto operations.
|
77 |
+
*
|
78 |
+
* @throws Ex\EnvironmentIsBrokenException
|
79 |
+
* @return void
|
80 |
+
*/
|
81 |
+
private static function testEncryptDecrypt()
|
82 |
+
{
|
83 |
+
$key = Key::createNewRandomKey();
|
84 |
+
$data = "EnCrYpT EvErYThInG\x00\x00";
|
85 |
+
|
86 |
+
// Make sure encrypting then decrypting doesn't change the message.
|
87 |
+
$ciphertext = Crypto::encrypt($data, $key, true);
|
88 |
+
try {
|
89 |
+
$decrypted = Crypto::decrypt($ciphertext, $key, true);
|
90 |
+
} catch (Ex\WrongKeyOrModifiedCiphertextException $ex) {
|
91 |
+
// It's important to catch this and change it into a
|
92 |
+
// Ex\EnvironmentIsBrokenException, otherwise a test failure could trick
|
93 |
+
// the user into thinking it's just an invalid ciphertext!
|
94 |
+
throw new Ex\EnvironmentIsBrokenException();
|
95 |
+
}
|
96 |
+
Core::ensureTrue($decrypted === $data);
|
97 |
+
|
98 |
+
// Modifying the ciphertext: Appending a string.
|
99 |
+
try {
|
100 |
+
Crypto::decrypt($ciphertext . 'a', $key, true);
|
101 |
+
throw new Ex\EnvironmentIsBrokenException();
|
102 |
+
} catch (Ex\WrongKeyOrModifiedCiphertextException $e) { /* expected */
|
103 |
+
}
|
104 |
+
|
105 |
+
// Modifying the ciphertext: Changing an HMAC byte.
|
106 |
+
$indices_to_change = [
|
107 |
+
0, // The header.
|
108 |
+
Core::HEADER_VERSION_SIZE + 1, // the salt
|
109 |
+
Core::HEADER_VERSION_SIZE + Core::SALT_BYTE_SIZE + 1, // the IV
|
110 |
+
Core::HEADER_VERSION_SIZE + Core::SALT_BYTE_SIZE + Core::BLOCK_BYTE_SIZE + 1, // the ciphertext
|
111 |
+
];
|
112 |
+
|
113 |
+
foreach ($indices_to_change as $index) {
|
114 |
+
try {
|
115 |
+
$ciphertext[$index] = \chr((\ord($ciphertext[$index]) + 1) % 256);
|
116 |
+
Crypto::decrypt($ciphertext, $key, true);
|
117 |
+
throw new Ex\EnvironmentIsBrokenException();
|
118 |
+
} catch (Ex\WrongKeyOrModifiedCiphertextException $e) { /* expected */
|
119 |
+
}
|
120 |
+
}
|
121 |
+
|
122 |
+
// Decrypting with the wrong key.
|
123 |
+
$key = Key::createNewRandomKey();
|
124 |
+
$data = 'abcdef';
|
125 |
+
$ciphertext = Crypto::encrypt($data, $key, true);
|
126 |
+
$wrong_key = Key::createNewRandomKey();
|
127 |
+
try {
|
128 |
+
Crypto::decrypt($ciphertext, $wrong_key, true);
|
129 |
+
throw new Ex\EnvironmentIsBrokenException();
|
130 |
+
} catch (Ex\WrongKeyOrModifiedCiphertextException $e) { /* expected */
|
131 |
+
}
|
132 |
+
|
133 |
+
// Ciphertext too small.
|
134 |
+
$key = Key::createNewRandomKey();
|
135 |
+
$ciphertext = \str_repeat('A', Core::MINIMUM_CIPHERTEXT_SIZE - 1);
|
136 |
+
try {
|
137 |
+
Crypto::decrypt($ciphertext, $key, true);
|
138 |
+
throw new Ex\EnvironmentIsBrokenException();
|
139 |
+
} catch (Ex\WrongKeyOrModifiedCiphertextException $e) { /* expected */
|
140 |
+
}
|
141 |
+
}
|
142 |
+
|
143 |
+
/**
|
144 |
+
* Test HKDF against test vectors.
|
145 |
+
*
|
146 |
+
* @throws Ex\EnvironmentIsBrokenException
|
147 |
+
* @return void
|
148 |
+
*/
|
149 |
+
private static function HKDFTestVector()
|
150 |
+
{
|
151 |
+
// HKDF test vectors from RFC 5869
|
152 |
+
|
153 |
+
// Test Case 1
|
154 |
+
$ikm = \str_repeat("\x0b", 22);
|
155 |
+
$salt = Encoding::hexToBin('000102030405060708090a0b0c');
|
156 |
+
$info = Encoding::hexToBin('f0f1f2f3f4f5f6f7f8f9');
|
157 |
+
$length = 42;
|
158 |
+
$okm = Encoding::hexToBin(
|
159 |
+
'3cb25f25faacd57a90434f64d0362f2a' .
|
160 |
+
'2d2d0a90cf1a5a4c5db02d56ecc4c5bf' .
|
161 |
+
'34007208d5b887185865'
|
162 |
+
);
|
163 |
+
$computed_okm = Core::HKDF('sha256', $ikm, $length, $info, $salt);
|
164 |
+
Core::ensureTrue($computed_okm === $okm);
|
165 |
+
|
166 |
+
// Test Case 7
|
167 |
+
$ikm = \str_repeat("\x0c", 22);
|
168 |
+
$length = 42;
|
169 |
+
$okm = Encoding::hexToBin(
|
170 |
+
'2c91117204d745f3500d636a62f64f0a' .
|
171 |
+
'b3bae548aa53d423b0d1f27ebba6f5e5' .
|
172 |
+
'673a081d70cce7acfc48'
|
173 |
+
);
|
174 |
+
$computed_okm = Core::HKDF('sha1', $ikm, $length, '', null);
|
175 |
+
Core::ensureTrue($computed_okm === $okm);
|
176 |
+
}
|
177 |
+
|
178 |
+
/**
|
179 |
+
* Test HMAC against test vectors.
|
180 |
+
*
|
181 |
+
* @throws Ex\EnvironmentIsBrokenException
|
182 |
+
* @return void
|
183 |
+
*/
|
184 |
+
private static function HMACTestVector()
|
185 |
+
{
|
186 |
+
// HMAC test vector From RFC 4231 (Test Case 1)
|
187 |
+
$key = \str_repeat("\x0b", 20);
|
188 |
+
$data = 'Hi There';
|
189 |
+
$correct = 'b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7';
|
190 |
+
Core::ensureTrue(
|
191 |
+
\hash_hmac(Core::HASH_FUNCTION_NAME, $data, $key) === $correct
|
192 |
+
);
|
193 |
+
}
|
194 |
+
|
195 |
+
/**
|
196 |
+
* Test AES against test vectors.
|
197 |
+
*
|
198 |
+
* @throws Ex\EnvironmentIsBrokenException
|
199 |
+
* @return void
|
200 |
+
*/
|
201 |
+
private static function AESTestVector()
|
202 |
+
{
|
203 |
+
// AES CTR mode test vector from NIST SP 800-38A
|
204 |
+
$key = Encoding::hexToBin(
|
205 |
+
'603deb1015ca71be2b73aef0857d7781' .
|
206 |
+
'1f352c073b6108d72d9810a30914dff4'
|
207 |
+
);
|
208 |
+
$iv = Encoding::hexToBin('f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff');
|
209 |
+
$plaintext = Encoding::hexToBin(
|
210 |
+
'6bc1bee22e409f96e93d7e117393172a' .
|
211 |
+
'ae2d8a571e03ac9c9eb76fac45af8e51' .
|
212 |
+
'30c81c46a35ce411e5fbc1191a0a52ef' .
|
213 |
+
'f69f2445df4f9b17ad2b417be66c3710'
|
214 |
+
);
|
215 |
+
$ciphertext = Encoding::hexToBin(
|
216 |
+
'601ec313775789a5b7a7f504bbf3d228' .
|
217 |
+
'f443e3ca4d62b59aca84e990cacaf5c5' .
|
218 |
+
'2b0930daa23de94ce87017ba2d84988d' .
|
219 |
+
'dfc9c58db67aada613c2dd08457941a6'
|
220 |
+
);
|
221 |
+
|
222 |
+
$computed_ciphertext = Crypto::plainEncrypt($plaintext, $key, $iv);
|
223 |
+
Core::ensureTrue($computed_ciphertext === $ciphertext);
|
224 |
+
|
225 |
+
$computed_plaintext = Crypto::plainDecrypt($ciphertext, $key, $iv, Core::CIPHER_METHOD);
|
226 |
+
Core::ensureTrue($computed_plaintext === $plaintext);
|
227 |
+
}
|
228 |
+
}
|
vendor/gliterd/backblaze-b2/CHANGELOG.md
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Changelog
|
2 |
+
|
3 |
+
All Notable changes to `gliterd/backblaze-b2` will be documented in this file.
|
4 |
+
|
5 |
+
Updates should follow the [Keep a CHANGELOG](http://keepachangelog.com/) principles.
|
6 |
+
|
7 |
+
## NEXT - YYYY-MM-DD
|
8 |
+
|
9 |
+
### Added
|
10 |
+
- Nothing
|
11 |
+
|
12 |
+
### Deprecated
|
13 |
+
- Nothing
|
14 |
+
|
15 |
+
### Fixed
|
16 |
+
- Nothing
|
17 |
+
|
18 |
+
### Removed
|
19 |
+
- Nothing
|
20 |
+
|
21 |
+
### Security
|
22 |
+
- Nothing
|
vendor/gliterd/backblaze-b2/CONDUCT.md
ADDED
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Contributor Code of Conduct
|
2 |
+
|
3 |
+
## Our Pledge
|
4 |
+
|
5 |
+
In the interest of fostering an open and welcoming environment, we as
|
6 |
+
contributors and maintainers pledge to making participation in our project and
|
7 |
+
our community a harassment-free experience for everyone, regardless of age, body
|
8 |
+
size, disability, ethnicity, gender identity and expression, level of experience,
|
9 |
+
nationality, personal appearance, race, religion, or sexual identity and
|
10 |
+
orientation.
|
11 |
+
|
12 |
+
## Our Standards
|
13 |
+
|
14 |
+
Examples of behavior that contributes to creating a positive environment
|
15 |
+
include:
|
16 |
+
|
17 |
+
* Using welcoming and inclusive language
|
18 |
+
* Being respectful of differing viewpoints and experiences
|
19 |
+
* Gracefully accepting constructive criticism
|
20 |
+
* Focusing on what is best for the community
|
21 |
+
* Showing empathy towards other community members
|
22 |
+
|
23 |
+
Examples of unacceptable behavior by participants include:
|
24 |
+
|
25 |
+
* The use of sexualized language or imagery and unwelcome sexual attention or
|
26 |
+
advances
|
27 |
+
* Trolling, insulting/derogatory comments, and personal or political attacks
|
28 |
+
* Public or private harassment
|
29 |
+
* Publishing others' private information, such as a physical or electronic
|
30 |
+
address, without explicit permission
|
31 |
+
* Other conduct which could reasonably be considered inappropriate in a
|
32 |
+
professional setting
|
33 |
+
|
34 |
+
## Our Responsibilities
|
35 |
+
|
36 |
+
Project maintainers are responsible for clarifying the standards of acceptable
|
37 |
+
behavior and are expected to take appropriate and fair corrective action in
|
38 |
+
response to any instances of unacceptable behavior.
|
39 |
+
|
40 |
+
Project maintainers have the right and responsibility to remove, edit, or
|
41 |
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
42 |
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
43 |
+
permanently any contributor for other behaviors that they deem inappropriate,
|
44 |
+
threatening, offensive, or harmful.
|
45 |
+
|
46 |
+
## Scope
|
47 |
+
|
48 |
+
This Code of Conduct applies both within project spaces and in public spaces
|
49 |
+
when an individual is representing the project or its community. Examples of
|
50 |
+
representing a project or community include using an official project e-mail
|
51 |
+
address, posting via an official social media account, or acting as an appointed
|
52 |
+
representative at an online or offline event. Representation of a project may be
|
53 |
+
further defined and clarified by project maintainers.
|
54 |
+
|
55 |
+
## Enforcement
|
56 |
+
|
57 |
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
58 |
+
reported by contacting the project team at `contact@yeello.com`. All
|
59 |
+
complaints will be reviewed and investigated and will result in a response that
|
60 |
+
is deemed necessary and appropriate to the circumstances. The project team is
|
61 |
+
obligated to maintain confidentiality with regard to the reporter of an incident.
|
62 |
+
Further details of specific enforcement policies may be posted separately.
|
63 |
+
|
64 |
+
Project maintainers who do not follow or enforce the Code of Conduct in good
|
65 |
+
faith may face temporary or permanent repercussions as determined by other
|
66 |
+
members of the project's leadership.
|
67 |
+
|
68 |
+
## Attribution
|
69 |
+
|
70 |
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
71 |
+
available at [http://contributor-covenant.org/version/1/4][version]
|
72 |
+
|
73 |
+
[homepage]: http://contributor-covenant.org
|
74 |
+
[version]: http://contributor-covenant.org/version/1/4/
|
vendor/gliterd/backblaze-b2/CONTRIBUTING.md
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Contributing
|
2 |
+
|
3 |
+
Contributions are **welcome** and will be fully **credited**.
|
4 |
+
|
5 |
+
We accept contributions via Pull Requests on [Github](https://github.com/mhetreramesh/flysystem-backblaze).
|
6 |
+
|
7 |
+
|
8 |
+
## Pull Requests
|
9 |
+
|
10 |
+
- **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](http://pear.php.net/package/PHP_CodeSniffer).
|
11 |
+
|
12 |
+
- **Add tests!** - Your patch won't be accepted if it doesn't have tests.
|
13 |
+
|
14 |
+
- **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date.
|
15 |
+
|
16 |
+
- **Consider our release cycle** - We try to follow [SemVer v2.0.0](http://semver.org/). Randomly breaking public APIs is not an option.
|
17 |
+
|
18 |
+
- **Create feature branches** - Don't ask us to pull from your master branch.
|
19 |
+
|
20 |
+
- **One pull request per feature** - If you want to do more than one thing, send multiple pull requests.
|
21 |
+
|
22 |
+
- **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please [squash them](http://www.git-scm.com/book/en/v2/Git-Tools-Rewriting-History#Changing-Multiple-Commit-Messages) before submitting.
|
23 |
+
|
24 |
+
|
25 |
+
## Running Tests
|
26 |
+
|
27 |
+
``` bash
|
28 |
+
$ composer test
|
29 |
+
```
|
30 |
+
|
31 |
+
|
32 |
+
**Happy coding**!
|
vendor/gliterd/backblaze-b2/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
MIT License
|
2 |
+
|
3 |
+
Copyright (c) 2017 Gliterd Software
|
4 |
+
|
5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6 |
+
of this software and associated documentation files (the "Software"), to deal
|
7 |
+
in the Software without restriction, including without limitation the rights
|
8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9 |
+
copies of the Software, and to permit persons to whom the Software is
|
10 |
+
furnished to do so, subject to the following conditions:
|
11 |
+
|
12 |
+
The above copyright notice and this permission notice shall be included in all
|
13 |
+
copies or substantial portions of the Software.
|
14 |
+
|
15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21 |
+
SOFTWARE.
|
vendor/gliterd/backblaze-b2/README.md
ADDED
@@ -0,0 +1,141 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
## Backblaze B2 for PHP
|
2 |
+
|
3 |
+
[![Author](http://img.shields.io/badge/author-@mhetreramesh-blue.svg?style=flat-square)](https://twitter.com/mhetreramesh)
|
4 |
+
[![Latest Version on Packagist](https://img.shields.io/packagist/v/gliterd/backblaze-b2.svg?style=flat-square)](https://packagist.org/packages/gliterd/backblaze-b2)
|
5 |
+
[![Software License][ico-license]](LICENSE.md)
|
6 |
+
[![Build Status](https://img.shields.io/travis/gliterd/backblaze-b2/master.svg?style=flat-square)](https://travis-ci.org/gliterd/backblaze-b2)
|
7 |
+
[![Coverage Status][ico-scrutinizer]][link-scrutinizer]
|
8 |
+
[![Quality Score][ico-code-quality]][link-code-quality]
|
9 |
+
[![Total Downloads](https://img.shields.io/packagist/dt/gliterd/backblaze-b2.svg?style=flat-square)](https://packagist.org/packages/gliterd/backblaze-b2)
|
10 |
+
|
11 |
+
`backblaze-b2` is the SDK for working with Backblaze's B2 storage service.
|
12 |
+
|
13 |
+
## Install
|
14 |
+
|
15 |
+
Via Composer
|
16 |
+
|
17 |
+
``` bash
|
18 |
+
$ composer require gliterd/backblaze-b2
|
19 |
+
```
|
20 |
+
|
21 |
+
## Usage
|
22 |
+
|
23 |
+
``` php
|
24 |
+
use BackblazeB2\Client;
|
25 |
+
use BackblazeB2\Bucket;
|
26 |
+
|
27 |
+
$client = new Client('accountId', 'applicationKey');
|
28 |
+
```
|
29 |
+
#### Returns a bucket details
|
30 |
+
``` php
|
31 |
+
$bucket = $client->createBucket([
|
32 |
+
'BucketName' => 'my-special-bucket',
|
33 |
+
'BucketType' => Bucket::TYPE_PRIVATE // or TYPE_PUBLIC
|
34 |
+
]);
|
35 |
+
```
|
36 |
+
|
37 |
+
#### Change the bucket Type
|
38 |
+
``` php
|
39 |
+
$updatedBucket = $client->updateBucket([
|
40 |
+
'BucketId' => $bucket->getId(),
|
41 |
+
'BucketType' => Bucket::TYPE_PUBLIC
|
42 |
+
]);
|
43 |
+
```
|
44 |
+
|
45 |
+
#### List all buckets
|
46 |
+
``` php
|
47 |
+
$buckets = $client->listBuckets();
|
48 |
+
```
|
49 |
+
#### Delete a bucket
|
50 |
+
``` php
|
51 |
+
$client->deleteBucket([
|
52 |
+
'BucketId' => 'YOUR_BUCKET_ID'
|
53 |
+
]);
|
54 |
+
```
|
55 |
+
|
56 |
+
#### File Upload
|
57 |
+
``` php
|
58 |
+
$file = $client->upload([
|
59 |
+
'BucketName' => 'my-special-bucket',
|
60 |
+
'FileName' => 'path/to/upload/to',
|
61 |
+
'Body' => 'I am the file content'
|
62 |
+
|
63 |
+
// The file content can also be provided via a resource.
|
64 |
+
// 'Body' => fopen('/path/to/input', 'r')
|
65 |
+
]);
|
66 |
+
```
|
67 |
+
|
68 |
+
#### File Download
|
69 |
+
``` php
|
70 |
+
$fileContent = $client->download([
|
71 |
+
'FileId' => $file->getId()
|
72 |
+
|
73 |
+
// Can also identify the file via bucket and path:
|
74 |
+
// 'BucketName' => 'my-special-bucket',
|
75 |
+
// 'FileName' => 'path/to/file'
|
76 |
+
|
77 |
+
// Can also save directly to a location on disk. This will cause download() to not return file content.
|
78 |
+
// 'SaveAs' => '/path/to/save/location'
|
79 |
+
]);
|
80 |
+
```
|
81 |
+
|
82 |
+
#### File Delete
|
83 |
+
``` php
|
84 |
+
$fileDelete = $client->deleteFile([
|
85 |
+
'FileId' => $file->getId()
|
86 |
+
|
87 |
+
// Can also identify the file via bucket and path:
|
88 |
+
// 'BucketName' => 'my-special-bucket',
|
89 |
+
// 'FileName' => 'path/to/file'
|
90 |
+
]);
|
91 |
+
```
|
92 |
+
|
93 |
+
#### List all files
|
94 |
+
``` php
|
95 |
+
$fileList = $client->listFiles([
|
96 |
+
'BucketId' => 'YOUR_BUCKET_ID'
|
97 |
+
]);
|
98 |
+
```
|
99 |
+
|
100 |
+
|
101 |
+
## Change log
|
102 |
+
|
103 |
+
Please see [CHANGELOG](CHANGELOG.md) for more information what has changed recently.
|
104 |
+
|
105 |
+
## Testing
|
106 |
+
|
107 |
+
```bash
|
108 |
+
$ vendor/bin/phpunit
|
109 |
+
```
|
110 |
+
|
111 |
+
|
112 |
+
## Contributing
|
113 |
+
|
114 |
+
Please see [CONTRIBUTING](CONTRIBUTING.md) and [CONDUCT](CONDUCT.md) for details.
|
115 |
+
|
116 |
+
## Security
|
117 |
+
|
118 |
+
If you discover any security related issues, please email mhetreramesh@gmail.com instead of using the issue tracker.
|
119 |
+
|
120 |
+
## Credits
|
121 |
+
|
122 |
+
- [All Contributors][link-contributors]
|
123 |
+
|
124 |
+
## License
|
125 |
+
|
126 |
+
The MIT License (MIT). Please see [License File](LICENSE.md) for more information.
|
127 |
+
|
128 |
+
[ico-version]: https://img.shields.io/packagist/v/gliterd/backblaze-b2.svg?style=flat-square
|
129 |
+
[ico-license]: https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square
|
130 |
+
[ico-travis]: https://img.shields.io/travis/gliterd/backblaze-b2/master.svg?style=flat-square
|
131 |
+
[ico-scrutinizer]: https://img.shields.io/scrutinizer/coverage/g/gliterd/backblaze-b2.svg?style=flat-square
|
132 |
+
[ico-code-quality]: https://img.shields.io/scrutinizer/g/gliterd/backblaze-b2.svg?style=flat-square
|
133 |
+
[ico-downloads]: https://img.shields.io/packagist/dt/gliterd/backblaze-b2.svg?style=flat-square
|
134 |
+
|
135 |
+
[link-packagist]: https://packagist.org/packages/gliterd/backblaze-b2
|
136 |
+
[link-travis]: https://travis-ci.org/gliterd/backblaze-b2
|
137 |
+
[link-scrutinizer]: https://scrutinizer-ci.com/g/gliterd/backblaze-b2/code-structure
|
138 |
+
[link-code-quality]: https://scrutinizer-ci.com/g/gliterd/backblaze-b2
|
139 |
+
[link-downloads]: https://packagist.org/packages/gliterd/backblaze-b2
|
140 |
+
[link-author]: https://github.com/gliterd
|
141 |
+
[link-contributors]: ../../contributors
|
vendor/gliterd/backblaze-b2/composer.json
ADDED
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"name": "gliterd/backblaze-b2",
|
3 |
+
"type": "library",
|
4 |
+
"description": "PHP SDK for working with backblaze B2 cloud storage.",
|
5 |
+
"keywords": ["cloud-storage", "b2", "storage", "backblaze", "cloud", "filesystem", "backup"],
|
6 |
+
"homepage": "https://github.com/gliterd/b2-sdk-php",
|
7 |
+
"license": "MIT",
|
8 |
+
"authors": [
|
9 |
+
{
|
10 |
+
"name": "Ramesh Mhetre",
|
11 |
+
"email": "mhetreramesh@gmail.com",
|
12 |
+
"homepage": "https://gliterd.com",
|
13 |
+
"role": "Developer"
|
14 |
+
}
|
15 |
+
],
|
16 |
+
"require": {
|
17 |
+
"php": ">=5.5.0",
|
18 |
+
"guzzlehttp/guzzle": "^6.1"
|
19 |
+
},
|
20 |
+
"require-dev": {
|
21 |
+
"phpunit/phpunit": "4.8.*",
|
22 |
+
"scrutinizer/ocular": "~1.1",
|
23 |
+
"squizlabs/php_codesniffer": "~2.3"
|
24 |
+
},
|
25 |
+
"autoload": {
|
26 |
+
"psr-4": {
|
27 |
+
"BackblazeB2\\": "src/"
|
28 |
+
}
|
29 |
+
},
|
30 |
+
"autoload-dev": {
|
31 |
+
"psr-4": {
|
32 |
+
"BackblazeB2\\Tests\\": "tests/"
|
33 |
+
}
|
34 |
+
},
|
35 |
+
"scripts": {
|
36 |
+
"test": "phpunit",
|
37 |
+
"format": "phpcbf --standard=psr2 src/"
|
38 |
+
},
|
39 |
+
"config": {
|
40 |
+
"sort-packages": true
|
41 |
+
}
|
42 |
+
}
|
vendor/gliterd/backblaze-b2/phpunit.hhvm.xml
ADDED
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
+
<phpunit backupGlobals="false"
|
3 |
+
backupStaticAttributes="false"
|
4 |
+
bootstrap="./phpunit.php"
|
5 |
+
colors="true"
|
6 |
+
convertErrorsToExceptions="true"
|
7 |
+
convertNoticesToExceptions="true"
|
8 |
+
convertWarningsToExceptions="true"
|
9 |
+
processIsolation="false"
|
10 |
+
stopOnFailure="false"
|
11 |
+
syntaxCheck="true"
|
12 |
+
verbose="true"
|
13 |
+
>
|
14 |
+
<testsuites>
|
15 |
+
<testsuite name="backblaze-b2">
|
16 |
+
<directory suffix=".php">./tests/</directory>
|
17 |
+
</testsuite>
|
18 |
+
</testsuites>
|
19 |
+
<filter>
|
20 |
+
<whitelist>
|
21 |
+
<directory suffix=".php">./src/</directory>
|
22 |
+
</whitelist>
|
23 |
+
</filter>
|
24 |
+
</phpunit>
|
vendor/gliterd/backblaze-b2/phpunit.php
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
require __DIR__.'/vendor/autoload.php';
|
vendor/gliterd/backblaze-b2/phpunit.xml
ADDED
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
+
<phpunit backupGlobals="false"
|
3 |
+
backupStaticAttributes="false"
|
4 |
+
bootstrap="./phpunit.php"
|
5 |
+
colors="true"
|
6 |
+
convertErrorsToExceptions="true"
|
7 |
+
convertNoticesToExceptions="true"
|
8 |
+
convertWarningsToExceptions="true"
|
9 |
+
processIsolation="false"
|
10 |
+
stopOnFailure="false"
|
11 |
+
syntaxCheck="true"
|
12 |
+
verbose="true"
|
13 |
+
>
|
14 |
+
<testsuites>
|
15 |
+
<testsuite name="backblaze-b2">
|
16 |
+
<directory suffix=".php">./tests/</directory>
|
17 |
+
</testsuite>
|
18 |
+
</testsuites>
|
19 |
+
<filter>
|
20 |
+
<whitelist>
|
21 |
+
<directory suffix=".php">./src/</directory>
|
22 |
+
</whitelist>
|
23 |
+
</filter>
|
24 |
+
<logging>
|
25 |
+
<log type="coverage-text" target="php://stdout" showUncoveredFiles="true"/>
|
26 |
+
<log type="coverage-html" target="coverage" showUncoveredFiles="true"/>
|
27 |
+
<log type="coverage-clover" target="coverage.xml" showUncoveredFiles="true"/>
|
28 |
+
</logging>
|
29 |
+
</phpunit>
|
vendor/gliterd/backblaze-b2/src/Bucket.php
ADDED
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace BackblazeB2;
|
4 |
+
|
5 |
+
class Bucket
|
6 |
+
{
|
7 |
+
const TYPE_PUBLIC = 'allPublic';
|
8 |
+
const TYPE_PRIVATE = 'allPrivate';
|
9 |
+
|
10 |
+
protected $id;
|
11 |
+
protected $name;
|
12 |
+
protected $type;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Bucket constructor.
|
16 |
+
*
|
17 |
+
* @param $id
|
18 |
+
* @param $name
|
19 |
+
* @param $type
|
20 |
+
*/
|
21 |
+
public function __construct($id, $name, $type)
|
22 |
+
{
|
23 |
+
$this->id = $id;
|
24 |
+
$this->name = $name;
|
25 |
+
$this->type = $type;
|
26 |
+
}
|
27 |
+
|
28 |
+
public function getId()
|
29 |
+
{
|
30 |
+
return $this->id;
|
31 |
+
}
|
32 |
+
|
33 |
+
public function getName()
|
34 |
+
{
|
35 |
+
return $this->name;
|
36 |
+
}
|
37 |
+
|
38 |
+
public function getType()
|
39 |
+
{
|
40 |
+
return $this->type;
|
41 |
+
}
|
42 |
+
}
|
vendor/gliterd/backblaze-b2/src/Client.php
ADDED
@@ -0,0 +1,479 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace BackblazeB2;
|
4 |
+
|
5 |
+
use BackblazeB2\Exceptions\NotFoundException;
|
6 |
+
use BackblazeB2\Exceptions\ValidationException;
|
7 |
+
use BackblazeB2\Http\Client as HttpClient;
|
8 |
+
|
9 |
+
class Client
|
10 |
+
{
|
11 |
+
protected $accountId;
|
12 |
+
protected $applicationKey;
|
13 |
+
|
14 |
+
protected $authToken;
|
15 |
+
protected $apiUrl;
|
16 |
+
protected $downloadUrl;
|
17 |
+
|
18 |
+
protected $client;
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Client constructor. Accepts the account ID, application key and an optional array of options.
|
22 |
+
*
|
23 |
+
* @param $accountId
|
24 |
+
* @param $applicationKey
|
25 |
+
* @param array $options
|
26 |
+
*/
|
27 |
+
public function __construct($accountId, $applicationKey, array $options = [])
|
28 |
+
{
|
29 |
+
$this->accountId = $accountId;
|
30 |
+
$this->applicationKey = $applicationKey;
|
31 |
+
|
32 |
+
if (isset($options['client'])) {
|
33 |
+
$this->client = $options['client'];
|
34 |
+
} else {
|
35 |
+
$this->client = new HttpClient(['exceptions' => false]);
|
36 |
+
}
|
37 |
+
|
38 |
+
$this->authorizeAccount();
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Create a bucket with the given name and type.
|
43 |
+
*
|
44 |
+
* @param array $options
|
45 |
+
*
|
46 |
+
* @throws ValidationException
|
47 |
+
*
|
48 |
+
* @return Bucket
|
49 |
+
*/
|
50 |
+
public function createBucket(array $options)
|
51 |
+
{
|
52 |
+
if (!in_array($options['BucketType'], [Bucket::TYPE_PUBLIC, Bucket::TYPE_PRIVATE])) {
|
53 |
+
throw new ValidationException(
|
54 |
+
sprintf('Bucket type must be %s or %s', Bucket::TYPE_PRIVATE, Bucket::TYPE_PUBLIC)
|
55 |
+
);
|
56 |
+
}
|
57 |
+
|
58 |
+
$response = $this->client->request('POST', $this->apiUrl.'/b2_create_bucket', [
|
59 |
+
'headers' => [
|
60 |
+
'Authorization' => $this->authToken,
|
61 |
+
],
|
62 |
+
'json' => [
|
63 |
+
'accountId' => $this->accountId,
|
64 |
+
'bucketName' => $options['BucketName'],
|
65 |
+
'bucketType' => $options['BucketType'],
|
66 |
+
],
|
67 |
+
]);
|
68 |
+
|
69 |
+
return new Bucket($response['bucketId'], $response['bucketName'], $response['bucketType']);
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Updates the type attribute of a bucket by the given ID.
|
74 |
+
*
|
75 |
+
* @param array $options
|
76 |
+
*
|
77 |
+
* @throws ValidationException
|
78 |
+
*
|
79 |
+
* @return Bucket
|
80 |
+
*/
|
81 |
+
public function updateBucket(array $options)
|
82 |
+
{
|
83 |
+
if (!in_array($options['BucketType'], [Bucket::TYPE_PUBLIC, Bucket::TYPE_PRIVATE])) {
|
84 |
+
throw new ValidationException(
|
85 |
+
sprintf('Bucket type must be %s or %s', Bucket::TYPE_PRIVATE, Bucket::TYPE_PUBLIC)
|
86 |
+
);
|
87 |
+
}
|
88 |
+
|
89 |
+
if (!isset($options['BucketId']) && isset($options['BucketName'])) {
|
90 |
+
$options['BucketId'] = $this->getBucketIdFromName($options['BucketName']);
|
91 |
+
}
|
92 |
+
|
93 |
+
$response = $this->client->request('POST', $this->apiUrl.'/b2_update_bucket', [
|
94 |
+
'headers' => [
|
95 |
+
'Authorization' => $this->authToken,
|
96 |
+
],
|
97 |
+
'json' => [
|
98 |
+
'accountId' => $this->accountId,
|
99 |
+
'bucketId' => $options['BucketId'],
|
100 |
+
'bucketType' => $options['BucketType'],
|
101 |
+
],
|
102 |
+
]);
|
103 |
+
|
104 |
+
return new Bucket($response['bucketId'], $response['bucketName'], $response['bucketType']);
|
105 |
+
}
|
106 |
+
|
107 |
+
/**
|
108 |
+
* Returns a list of bucket objects representing the buckets on the account.
|
109 |
+
*
|
110 |
+
* @return array
|
111 |
+
*/
|
112 |
+
public function listBuckets()
|
113 |
+
{
|
114 |
+
$buckets = [];
|
115 |
+
|
116 |
+
$response = $this->client->request('POST', $this->apiUrl.'/b2_list_buckets', [
|
117 |
+
'headers' => [
|
118 |
+
'Authorization' => $this->authToken,
|
119 |
+
],
|
120 |
+
'json' => [
|
121 |
+
'accountId' => $this->accountId,
|
122 |
+
],
|
123 |
+
]);
|
124 |
+
|
125 |
+
foreach ($response['buckets'] as $bucket) {
|
126 |
+
$buckets[] = new Bucket($bucket['bucketId'], $bucket['bucketName'], $bucket['bucketType']);
|
127 |
+
}
|
128 |
+
|
129 |
+
return $buckets;
|
130 |
+
}
|
131 |
+
|
132 |
+
/**
|
133 |
+
* Deletes the bucket identified by its ID.
|
134 |
+
*
|
135 |
+
* @param array $options
|
136 |
+
*
|
137 |
+
* @return bool
|
138 |
+
*/
|
139 |
+
public function deleteBucket(array $options)
|
140 |
+
{
|
141 |
+
if (!isset($options['BucketId']) && isset($options['BucketName'])) {
|
142 |
+
$options['BucketId'] = $this->getBucketIdFromName($options['BucketName']);
|
143 |
+
}
|
144 |
+
|
145 |
+
$this->client->request('POST', $this->apiUrl.'/b2_delete_bucket', [
|
146 |
+
'headers' => [
|
147 |
+
'Authorization' => $this->authToken,
|
148 |
+
],
|
149 |
+
'json' => [
|
150 |
+
'accountId' => $this->accountId,
|
151 |
+
'bucketId' => $options['BucketId'],
|
152 |
+
],
|
153 |
+
]);
|
154 |
+
|
155 |
+
return true;
|
156 |
+
}
|
157 |
+
|
158 |
+
/**
|
159 |
+
* Uploads a file to a bucket and returns a File object.
|
160 |
+
*
|
161 |
+
* @param array $options
|
162 |
+
*
|
163 |
+
* @return File
|
164 |
+
*/
|
165 |
+
public function upload(array $options)
|
166 |
+
{
|
167 |
+
// Clean the path if it starts with /.
|
168 |
+
if (substr($options['FileName'], 0, 1) === '/') {
|
169 |
+
$options['FileName'] = ltrim($options['FileName'], '/');
|
170 |
+
}
|
171 |
+
|
172 |
+
if (!isset($options['BucketId']) && isset($options['BucketName'])) {
|
173 |
+
$options['BucketId'] = $this->getBucketIdFromName($options['BucketName']);
|
174 |
+
}
|
175 |
+
|
176 |
+
// Retrieve the URL that we should be uploading to.
|
177 |
+
$response = $this->client->request('POST', $this->apiUrl.'/b2_get_upload_url', [
|
178 |
+
'headers' => [
|
179 |
+
'Authorization' => $this->authToken,
|
180 |
+
],
|
181 |
+
'json' => [
|
182 |
+
'bucketId' => $options['BucketId'],
|
183 |
+
],
|
184 |
+
]);
|
185 |
+
|
186 |
+
$uploadEndpoint = $response['uploadUrl'];
|
187 |
+
$uploadAuthToken = $response['authorizationToken'];
|
188 |
+
|
189 |
+
if (is_resource($options['Body'])) {
|
190 |
+
// We need to calculate the file's hash incrementally from the stream.
|
191 |
+
$context = hash_init('sha1');
|
192 |
+
hash_update_stream($context, $options['Body']);
|
193 |
+
$hash = hash_final($context);
|
194 |
+
|
195 |
+
// Similarly, we have to use fstat to get the size of the stream.
|
196 |
+
$size = fstat($options['Body'])['size'];
|
197 |
+
|
198 |
+
// Rewind the stream before passing it to the HTTP client.
|
199 |
+
rewind($options['Body']);
|
200 |
+
} else {
|
201 |
+
// We've been given a simple string body, it's super simple to calculate the hash and size.
|
202 |
+
$hash = sha1($options['Body']);
|
203 |
+
$size = mb_strlen($options['Body']);
|
204 |
+
}
|
205 |
+
|
206 |
+
if (!isset($options['FileLastModified'])) {
|
207 |
+
$options['FileLastModified'] = round(microtime(true) * 1000);
|
208 |
+
}
|
209 |
+
|
210 |
+
if (!isset($options['FileContentType'])) {
|
211 |
+
$options['FileContentType'] = 'b2/x-auto';
|
212 |
+
}
|
213 |
+
|
214 |
+
$response = $this->client->request('POST', $uploadEndpoint, [
|
215 |
+
'headers' => [
|
216 |
+
'Authorization' => $uploadAuthToken,
|
217 |
+
'Content-Type' => $options['FileContentType'],
|
218 |
+
'Content-Length' => $size,
|
219 |
+
'X-Bz-File-Name' => $options['FileName'],
|
220 |
+
'X-Bz-Content-Sha1' => $hash,
|
221 |
+
'X-Bz-Info-src_last_modified_millis' => $options['FileLastModified'],
|
222 |
+
],
|
223 |
+
'body' => $options['Body'],
|
224 |
+
]);
|
225 |
+
|
226 |
+
return new File(
|
227 |
+
$response['fileId'],
|
228 |
+
$response['fileName'],
|
229 |
+
$response['contentSha1'],
|
230 |
+
$response['contentLength'],
|
231 |
+
$response['contentType'],
|
232 |
+
$response['fileInfo']
|
233 |
+
);
|
234 |
+
}
|
235 |
+
|
236 |
+
/**
|
237 |
+
* Download a file from a B2 bucket.
|
238 |
+
*
|
239 |
+
* @param array $options
|
240 |
+
*
|
241 |
+
* @return bool|mixed|string
|
242 |
+
*/
|
243 |
+
public function download(array $options)
|
244 |
+
{
|
245 |
+
$requestUrl = null;
|
246 |
+
$requestOptions = [
|
247 |
+
'headers' => [
|
248 |
+
'Authorization' => $this->authToken,
|
249 |
+
],
|
250 |
+
'sink' => isset($options['SaveAs']) ? $options['SaveAs'] : null,
|
251 |
+
];
|
252 |
+
|
253 |
+
if (isset($options['FileId'])) {
|
254 |
+
$requestOptions['query'] = ['fileId' => $options['FileId']];
|
255 |
+
$requestUrl = $this->downloadUrl.'/b2api/v1/b2_download_file_by_id';
|
256 |
+
} else {
|
257 |
+
if (!isset($options['BucketName']) && isset($options['BucketId'])) {
|
258 |
+
$options['BucketName'] = $this->getBucketNameFromId($options['BucketId']);
|
259 |
+
}
|
260 |
+
|
261 |
+
$requestUrl = sprintf('%s/file/%s/%s', $this->downloadUrl, $options['BucketName'], $options['FileName']);
|
262 |
+
}
|
263 |
+
|
264 |
+
$response = $this->client->request('GET', $requestUrl, $requestOptions, false);
|
265 |
+
|
266 |
+
return isset($options['SaveAs']) ? true : $response;
|
267 |
+
}
|
268 |
+
|
269 |
+
/**
|
270 |
+
* Retrieve a collection of File objects representing the files stored inside a bucket.
|
271 |
+
*
|
272 |
+
* @param array $options
|
273 |
+
*
|
274 |
+
* @return array
|
275 |
+
*/
|
276 |
+
public function listFiles(array $options)
|
277 |
+
{
|
278 |
+
// if FileName is set, we only attempt to retrieve information about that single file.
|
279 |
+
$fileName = !empty($options['FileName']) ? $options['FileName'] : null;
|
280 |
+
|
281 |
+
$nextFileName = null;
|
282 |
+
$maxFileCount = 1000;
|
283 |
+
$files = [];
|
284 |
+
|
285 |
+
if (!isset($options['BucketId']) && isset($options['BucketName'])) {
|
286 |
+
$options['BucketId'] = $this->getBucketIdFromName($options['BucketName']);
|
287 |
+
}
|
288 |
+
|
289 |
+
if ($fileName) {
|
290 |
+
$nextFileName = $fileName;
|
291 |
+
$maxFileCount = 1;
|
292 |
+
}
|
293 |
+
|
294 |
+
// B2 returns, at most, 1000 files per "page". Loop through the pages and compile an array of File objects.
|
295 |
+
while (true) {
|
296 |
+
$response = $this->client->request('POST', $this->apiUrl.'/b2_list_file_names', [
|
297 |
+
'headers' => [
|
298 |
+
'Authorization' => $this->authToken,
|
299 |
+
],
|
300 |
+
'json' => [
|
301 |
+
'bucketId' => $options['BucketId'],
|
302 |
+
'startFileName' => $nextFileName,
|
303 |
+
'maxFileCount' => $maxFileCount,
|
304 |
+
],
|
305 |
+
]);
|
306 |
+
|
307 |
+
foreach ($response['files'] as $file) {
|
308 |
+
// if we have a file name set, only retrieve information if the file name matches
|
309 |
+
if (!$fileName || ($fileName === $file['fileName'])) {
|
310 |
+
$files[] = new File($file['fileId'], $file['fileName'], null, $file['size']);
|
311 |
+
}
|
312 |
+
}
|
313 |
+
|
314 |
+
if ($fileName || $response['nextFileName'] === null) {
|
315 |
+
// We've got all the files - break out of loop.
|
316 |
+
break;
|
317 |
+
}
|
318 |
+
|
319 |
+
$nextFileName = $response['nextFileName'];
|
320 |
+
}
|
321 |
+
|
322 |
+
return $files;
|
323 |
+
}
|
324 |
+
|
325 |
+
/**
|
326 |
+
* Test whether a file exists in B2 for the given bucket.
|
327 |
+
*
|
328 |
+
* @param array $options
|
329 |
+
*
|
330 |
+
* @return bool
|
331 |
+
*/
|
332 |
+
public function fileExists(array $options)
|
333 |
+
{
|
334 |
+
$files = $this->listFiles($options);
|
335 |
+
|
336 |
+
return !empty($files);
|
337 |
+
}
|
338 |
+
|
339 |
+
/**
|
340 |
+
* Returns a single File object representing a file stored on B2.
|
341 |
+
*
|
342 |
+
* @param array $options
|
343 |
+
*
|
344 |
+
* @throws NotFoundException If no file id was provided and BucketName + FileName does not resolve to a file, a NotFoundException is thrown.
|
345 |
+
*
|
346 |
+
* @return File
|
347 |
+
*/
|
348 |
+
public function getFile(array $options)
|
349 |
+
{
|
350 |
+
if (!isset($options['FileId']) && isset($options['BucketName']) && isset($options['FileName'])) {
|
351 |
+
$options['FileId'] = $this->getFileIdFromBucketAndFileName($options['BucketName'], $options['FileName']);
|
352 |
+
|
353 |
+
if (!$options['FileId']) {
|
354 |
+
throw new NotFoundException();
|
355 |
+
}
|
356 |
+
}
|
357 |
+
|
358 |
+
$response = $this->client->request('POST', $this->apiUrl.'/b2_get_file_info', [
|
359 |
+
'headers' => [
|
360 |
+
'Authorization' => $this->authToken,
|
361 |
+
],
|
362 |
+
'json' => [
|
363 |
+
'fileId' => $options['FileId'],
|
364 |
+
],
|
365 |
+
]);
|
366 |
+
|
367 |
+
return new File(
|
368 |
+
$response['fileId'],
|
369 |
+
$response['fileName'],
|
370 |
+
$response['contentSha1'],
|
371 |
+
$response['contentLength'],
|
372 |
+
$response['contentType'],
|
373 |
+
$response['fileInfo'],
|
374 |
+
$response['bucketId'],
|
375 |
+
$response['action'],
|
376 |
+
$response['uploadTimestamp']
|
377 |
+
);
|
378 |
+
}
|
379 |
+
|
380 |
+
/**
|
381 |
+
* Deletes the file identified by ID from Backblaze B2.
|
382 |
+
*
|
383 |
+
* @param array $options
|
384 |
+
*
|
385 |
+
* @return bool
|
386 |
+
*/
|
387 |
+
public function deleteFile(array $options)
|
388 |
+
{
|
389 |
+
if (!isset($options['FileName'])) {
|
390 |
+
$file = $this->getFile($options);
|
391 |
+
|
392 |
+
$options['FileName'] = $file->getName();
|
393 |
+
}
|
394 |
+
|
395 |
+
if (!isset($options['FileId']) && isset($options['BucketName']) && isset($options['FileName'])) {
|
396 |
+
$file = $this->getFile($options);
|
397 |
+
|
398 |
+
$options['FileId'] = $file->getId();
|
399 |
+
}
|
400 |
+
|
401 |
+
$this->client->request('POST', $this->apiUrl.'/b2_delete_file_version', [
|
402 |
+
'headers' => [
|
403 |
+
'Authorization' => $this->authToken,
|
404 |
+
],
|
405 |
+
'json' => [
|
406 |
+
'fileName' => $options['FileName'],
|
407 |
+
'fileId' => $options['FileId'],
|
408 |
+
],
|
409 |
+
]);
|
410 |
+
|
411 |
+
return true;
|
412 |
+
}
|
413 |
+
|
414 |
+
/**
|
415 |
+
* Authorize the B2 account in order to get an auth token and API/download URLs.
|
416 |
+
*
|
417 |
+
* @throws \Exception
|
418 |
+
*/
|
419 |
+
protected function authorizeAccount()
|
420 |
+
{
|
421 |
+
$response = $this->client->request('GET', 'https://api.backblazeb2.com/b2api/v1/b2_authorize_account', [
|
422 |
+
'auth' => [$this->accountId, $this->applicationKey],
|
423 |
+
]);
|
424 |
+
|
425 |
+
$this->authToken = $response['authorizationToken'];
|
426 |
+
$this->apiUrl = $response['apiUrl'].'/b2api/v1';
|
427 |
+
$this->downloadUrl = $response['downloadUrl'];
|
428 |
+
}
|
429 |
+
|
430 |
+
/**
|
431 |
+
* Maps the provided bucket name to the appropriate bucket ID.
|
432 |
+
*
|
433 |
+
* @param $name
|
434 |
+
*
|
435 |
+
* @return null
|
436 |
+
*/
|
437 |
+
protected function getBucketIdFromName($name)
|
438 |
+
{
|
439 |
+
$buckets = $this->listBuckets();
|
440 |
+
|
441 |
+
foreach ($buckets as $bucket) {
|
442 |
+
if ($bucket->getName() === $name) {
|
443 |
+
return $bucket->getId();
|
444 |
+
}
|
445 |
+
}
|
446 |
+
}
|
447 |
+
|
448 |
+
/**
|
449 |
+
* Maps the provided bucket ID to the appropriate bucket name.
|
450 |
+
*
|
451 |
+
* @param $id
|
452 |
+
*
|
453 |
+
* @return null
|
454 |
+
*/
|
455 |
+
protected function getBucketNameFromId($id)
|
456 |
+
{
|
457 |
+
$buckets = $this->listBuckets();
|
458 |
+
|
459 |
+
foreach ($buckets as $bucket) {
|
460 |
+
if ($bucket->getId() === $id) {
|
461 |
+
return $bucket->getName();
|
462 |
+
}
|
463 |
+
}
|
464 |
+
}
|
465 |
+
|
466 |
+
protected function getFileIdFromBucketAndFileName($bucketName, $fileName)
|
467 |
+
{
|
468 |
+
$files = $this->listFiles([
|
469 |
+
'BucketName' => $bucketName,
|
470 |
+
'FileName' => $fileName,
|
471 |
+
]);
|
472 |
+
|
473 |
+
foreach ($files as $file) {
|
474 |
+
if ($file->getName() === $fileName) {
|
475 |
+
return $file->getId();
|
476 |
+
}
|
477 |
+
}
|
478 |
+
}
|
479 |
+
}
|
vendor/gliterd/backblaze-b2/src/ErrorHandler.php
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace BackblazeB2;
|
4 |
+
|
5 |
+
use BackblazeB2\Exceptions\B2Exception;
|
6 |
+
use BackblazeB2\Exceptions\BadJsonException;
|
7 |
+
use BackblazeB2\Exceptions\BadValueException;
|
8 |
+
use BackblazeB2\Exceptions\BucketAlreadyExistsException;
|
9 |
+
use BackblazeB2\Exceptions\BucketNotEmptyException;
|
10 |
+
use BackblazeB2\Exceptions\FileNotPresentException;
|
11 |
+
use BackblazeB2\Exceptions\NotFoundException;
|
12 |
+
use GuzzleHttp\Psr7\Response;
|
13 |
+
|
14 |
+
class ErrorHandler
|
15 |
+
{
|
16 |
+
protected static $mappings = [
|
17 |
+
'bad_json' => BadJsonException::class,
|
18 |
+
'bad_value' => BadValueException::class,
|
19 |
+
'duplicate_bucket_name' => BucketAlreadyExistsException::class,
|
20 |
+
'not_found' => NotFoundException::class,
|
21 |
+
'file_not_present' => FileNotPresentException::class,
|
22 |
+
'cannot_delete_non_empty_bucket' => BucketNotEmptyException::class,
|
23 |
+
];
|
24 |
+
|
25 |
+
public static function handleErrorResponse(Response $response)
|
26 |
+
{
|
27 |
+
$responseJson = json_decode($response->getBody(), true);
|
28 |
+
|
29 |
+
if (isset(self::$mappings[$responseJson['code']])) {
|
30 |
+
$exceptionClass = self::$mappings[$responseJson['code']];
|
31 |
+
} else {
|
32 |
+
// We don't have an exception mapped to this response error, throw generic exception
|
33 |
+
$exceptionClass = B2Exception::class;
|
34 |
+
}
|
35 |
+
|
36 |
+
throw new $exceptionClass('Received error from B2: '.$responseJson['message']);
|
37 |
+
}
|
38 |
+
}
|
vendor/gliterd/backblaze-b2/src/Exceptions/B2Exception.php
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace BackblazeB2\Exceptions;
|
4 |
+
|
5 |
+
class B2Exception extends \Exception
|
6 |
+
{
|
7 |
+
}
|
vendor/gliterd/backblaze-b2/src/Exceptions/BadJsonException.php
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace BackblazeB2\Exceptions;
|
4 |
+
|
5 |
+
class BadJsonException extends \Exception
|
6 |
+
{
|
7 |
+
}
|
vendor/gliterd/backblaze-b2/src/Exceptions/BadValueException.php
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace BackblazeB2\Exceptions;
|
4 |
+
|
5 |
+
class BadValueException extends \Exception
|
6 |
+
{
|
7 |
+
}
|
vendor/gliterd/backblaze-b2/src/Exceptions/BucketAlreadyExistsException.php
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace BackblazeB2\Exceptions;
|
4 |
+
|
5 |
+
class BucketAlreadyExistsException extends \Exception
|
6 |
+
{
|
7 |
+
}
|
vendor/gliterd/backblaze-b2/src/Exceptions/BucketNotEmptyException.php
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace BackblazeB2\Exceptions;
|
4 |
+
|
5 |
+
class BucketNotEmptyException extends \Exception
|
6 |
+
{
|
7 |
+
}
|
vendor/gliterd/backblaze-b2/src/Exceptions/FileNotPresentException.php
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace BackblazeB2\Exceptions;
|
4 |
+
|
5 |
+
class FileNotPresentException extends \Exception
|
6 |
+
{
|
7 |
+
}
|
vendor/gliterd/backblaze-b2/src/Exceptions/NotFoundException.php
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace BackblazeB2\Exceptions;
|
4 |
+
|
5 |
+
class NotFoundException extends \Exception
|
6 |
+
{
|
7 |
+
}
|
vendor/gliterd/backblaze-b2/src/Exceptions/ValidationException.php
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace BackblazeB2\Exceptions;
|
4 |
+
|
5 |
+
class ValidationException extends \Exception
|
6 |
+
{
|
7 |
+
}
|
vendor/gliterd/backblaze-b2/src/File.php
ADDED
@@ -0,0 +1,114 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace BackblazeB2;
|
4 |
+
|
5 |
+
class File
|
6 |
+
{
|
7 |
+
protected $id;
|
8 |
+
protected $name;
|
9 |
+
protected $hash;
|
10 |
+
protected $size;
|
11 |
+
protected $type;
|
12 |
+
protected $info;
|
13 |
+
protected $bucketId;
|
14 |
+
protected $action;
|
15 |
+
protected $uploadTimestamp;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* File constructor.
|
19 |
+
*
|
20 |
+
* @param $id
|
21 |
+
* @param $name
|
22 |
+
* @param $hash
|
23 |
+
* @param $size
|
24 |
+
* @param $type
|
25 |
+
* @param $info
|
26 |
+
* @param $bucketId
|
27 |
+
* @param $action
|
28 |
+
* @param $uploadTimestamp
|
29 |
+
*/
|
30 |
+
public function __construct($id, $name, $hash = null, $size = null, $type = null, $info = null, $bucketId = null, $action = null, $uploadTimestamp = null)
|
31 |
+
{
|
32 |
+
$this->id = $id;
|
33 |
+
$this->name = $name;
|
34 |
+
$this->hash = $hash;
|
35 |
+
$this->size = $size;
|
36 |
+
$this->type = $type;
|
37 |
+
$this->info = $info;
|
38 |
+
$this->bucketId = $bucketId;
|
39 |
+
$this->action = $action;
|
40 |
+
$this->uploadTimestamp = $uploadTimestamp;
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* @return string
|
45 |
+
*/
|
46 |
+
public function getId()
|
47 |
+
{
|
48 |
+
return $this->id;
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* @return string
|
53 |
+
*/
|
54 |
+
public function getName()
|
55 |
+
{
|
56 |
+
return $this->name;
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* @return string
|
61 |
+
*/
|
62 |
+
public function getHash()
|
63 |
+
{
|
64 |
+
return $this->hash;
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* @return int
|
69 |
+
*/
|
70 |
+
public function getSize()
|
71 |
+
{
|
72 |
+
return $this->size;
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* @return string
|
77 |
+
*/
|
78 |
+
public function getType()
|
79 |
+
{
|
80 |
+
return $this->type;
|
81 |
+
}
|
82 |
+
|
83 |
+
/**
|
84 |
+
* @return array
|
85 |
+
*/
|
86 |
+
public function getInfo()
|
87 |
+
{
|
88 |
+
return $this->info;
|
89 |
+
}
|
90 |
+
|
91 |
+
/**
|
92 |
+
* @return string
|
93 |
+
*/
|
94 |
+
public function getBucketId()
|
95 |
+
{
|
96 |
+
return $this->bucketId;
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* @return string
|
101 |
+
*/
|
102 |
+
public function getAction()
|
103 |
+
{
|
104 |
+
return $this->action;
|
105 |
+
}
|
106 |
+
|
107 |
+
/**
|
108 |
+
* @return string
|
109 |
+
*/
|
110 |
+
public function getUploadTimestamp()
|
111 |
+
{
|
112 |
+
return $this->uploadTimestamp;
|
113 |
+
}
|
114 |
+
}
|
vendor/gliterd/backblaze-b2/src/Http/Client.php
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace BackblazeB2\Http;
|
4 |
+
|
5 |
+
use BackblazeB2\ErrorHandler;
|
6 |
+
use GuzzleHttp\Client as GuzzleClient;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Client wrapper around Guzzle.
|
10 |
+
*/
|
11 |
+
class Client extends GuzzleClient
|
12 |
+
{
|
13 |
+
/**
|
14 |
+
* Sends a response to the B2 API, automatically handling decoding JSON and errors.
|
15 |
+
*
|
16 |
+
* @param string $method
|
17 |
+
* @param null $uri
|
18 |
+
* @param array $options
|
19 |
+
* @param bool $asJson
|
20 |
+
*
|
21 |
+
* @return mixed|string
|
22 |
+
*/
|
23 |
+
public function request($method, $uri = null, array $options = [], $asJson = true)
|
24 |
+
{
|
25 |
+
$response = parent::request($method, $uri, $options);
|
26 |
+
|
27 |
+
if ($response->getStatusCode() !== 200) {
|
28 |
+
ErrorHandler::handleErrorResponse($response);
|
29 |
+
}
|
30 |
+
|
31 |
+
if ($asJson) {
|
32 |
+
return json_decode($response->getBody(), true);
|
33 |
+
}
|
34 |
+
|
35 |
+
return $response->getBody()->getContents();
|
36 |
+
}
|
37 |
+
}
|
vendor/gliterd/backblaze-b2/tests/ClientTest.php
ADDED
@@ -0,0 +1,529 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace BackblazeB2\Tests;
|
4 |
+
|
5 |
+
use BackblazeB2\Bucket;
|
6 |
+
use BackblazeB2\Client;
|
7 |
+
use BackblazeB2\Exceptions\BadJsonException;
|
8 |
+
use BackblazeB2\Exceptions\BadValueException;
|
9 |
+
use BackblazeB2\Exceptions\BucketAlreadyExistsException;
|
10 |
+
use BackblazeB2\Exceptions\BucketNotEmptyException;
|
11 |
+
use BackblazeB2\Exceptions\NotFoundException;
|
12 |
+
use BackblazeB2\Exceptions\ValidationException;
|
13 |
+
use BackblazeB2\File;
|
14 |
+
use GuzzleHttp\Middleware;
|
15 |
+
use GuzzleHttp\Psr7\Stream;
|
16 |
+
|
17 |
+
class ClientTest extends \PHPUnit_Framework_TestCase
|
18 |
+
{
|
19 |
+
use TestHelper;
|
20 |
+
|
21 |
+
public function testCreatePublicBucket()
|
22 |
+
{
|
23 |
+
$guzzle = $this->buildGuzzleFromResponses([
|
24 |
+
$this->buildResponseFromStub(200, [], 'authorize_account.json'),
|
25 |
+
$this->buildResponseFromStub(200, [], 'create_bucket_public.json'),
|
26 |
+
]);
|
27 |
+
|
28 |
+
$client = new Client('testId', 'testKey', ['client' => $guzzle]);
|
29 |
+
|
30 |
+
// Test that we get a public bucket back after creation
|
31 |
+
$bucket = $client->createBucket([
|
32 |
+
'BucketName' => 'Test bucket',
|
33 |
+
'BucketType' => Bucket::TYPE_PUBLIC,
|
34 |
+
]);
|
35 |
+
$this->assertInstanceOf(Bucket::class, $bucket);
|
36 |
+
$this->assertEquals('Test bucket', $bucket->getName());
|
37 |
+
$this->assertEquals(Bucket::TYPE_PUBLIC, $bucket->getType());
|
38 |
+
}
|
39 |
+
|
40 |
+
public function testCreatePrivateBucket()
|
41 |
+
{
|
42 |
+
$guzzle = $this->buildGuzzleFromResponses([
|
43 |
+
$this->buildResponseFromStub(200, [], 'authorize_account.json'),
|
44 |
+
$this->buildResponseFromStub(200, [], 'create_bucket_private.json'),
|
45 |
+
]);
|
46 |
+
|
47 |
+
$client = new Client('testId', 'testKey', ['client' => $guzzle]);
|
48 |
+
|
49 |
+
// Test that we get a private bucket back after creation
|
50 |
+
$bucket = $client->createBucket([
|
51 |
+
'BucketName' => 'Test bucket',
|
52 |
+
'BucketType' => Bucket::TYPE_PRIVATE,
|
53 |
+
]);
|
54 |
+
$this->assertInstanceOf(Bucket::class, $bucket);
|
55 |
+
$this->assertEquals('Test bucket', $bucket->getName());
|
56 |
+
$this->assertEquals(Bucket::TYPE_PRIVATE, $bucket->getType());
|
57 |
+
}
|
58 |
+
|
59 |
+
public function testBucketAlreadyExistsExceptionThrown()
|
60 |
+
{
|
61 |
+
$this->setExpectedException(BucketAlreadyExistsException::class);
|
62 |
+
|
63 |
+
$guzzle = $this->buildGuzzleFromResponses([
|
64 |
+
$this->buildResponseFromStub(200, [], 'authorize_account.json'),
|
65 |
+
$this->buildResponseFromStub(400, [], 'create_bucket_exists.json'),
|
66 |
+
]);
|
67 |
+
|
68 |
+
$client = new Client('testId', 'testKey', ['client' => $guzzle]);
|
69 |
+
$client->createBucket([
|
70 |
+
'BucketName' => 'I already exist',
|
71 |
+
'BucketType' => Bucket::TYPE_PRIVATE,
|
72 |
+
]);
|
73 |
+
}
|
74 |
+
|
75 |
+
public function testInvalidBucketTypeThrowsException()
|
76 |
+
{
|
77 |
+
$this->setExpectedException(ValidationException::class);
|
78 |
+
|
79 |
+
$guzzle = $this->buildGuzzleFromResponses([
|
80 |
+
$this->buildResponseFromStub(200, [], 'authorize_account.json'),
|
81 |
+
]);
|
82 |
+
|
83 |
+
$client = new Client('testId', 'testKey', ['client' => $guzzle]);
|
84 |
+
$client->createBucket([
|
85 |
+
'BucketName' => 'Test bucket',
|
86 |
+
'BucketType' => 'i am not valid',
|
87 |
+
]);
|
88 |
+
}
|
89 |
+
|
90 |
+
public function testUpdateBucketToPrivate()
|
91 |
+
{
|
92 |
+
$guzzle = $this->buildGuzzleFromResponses([
|
93 |
+
$this->buildResponseFromStub(200, [], 'authorize_account.json'),
|
94 |
+
$this->buildResponseFromStub(200, [], 'update_bucket_to_private.json'),
|
95 |
+
]);
|
96 |
+
|
97 |
+
$client = new Client('testId', 'testKey', ['client' => $guzzle]);
|
98 |
+
|
99 |
+
$bucket = $client->updateBucket([
|
100 |
+
'BucketId' => 'bucketId',
|
101 |
+
'BucketType' => Bucket::TYPE_PRIVATE,
|
102 |
+
]);
|
103 |
+
|
104 |
+
$this->assertInstanceOf(Bucket::class, $bucket);
|
105 |
+
$this->assertEquals('bucketId', $bucket->getId());
|
106 |
+
$this->assertEquals(Bucket::TYPE_PRIVATE, $bucket->getType());
|
107 |
+
}
|
108 |
+
|
109 |
+
public function testUpdateBucketToPublic()
|
110 |
+
{
|
111 |
+
$guzzle = $this->buildGuzzleFromResponses([
|
112 |
+
$this->buildResponseFromStub(200, [], 'authorize_account.json'),
|
113 |
+
|