Version Description
- Improve database export process
- Simplify export and import cron
- Fix an issue with export and import progress status
Download this release
Release Info
Developer | bangelov |
Plugin | All-in-One WP Migration |
Version | 5.50 |
Comparing to | |
See all releases |
Code changes from version 5.49 to 5.50
- all-in-one-wp-migration.php +1 -1
- constants.php +6 -2
- lib/controller/class-ai1wm-export-controller.php +1 -1
- lib/controller/class-ai1wm-import-controller.php +1 -1
- lib/controller/class-ai1wm-resolve-controller.php +2 -2
- lib/model/class-ai1wm-extensions.php +1 -1
- lib/model/class-ai1wm-http.php +38 -56
- lib/model/class-ai1wm-status.php +0 -4
- lib/model/class-ai1wm-streams.php +0 -422
- lib/model/export/class-ai1wm-export-database.php +4 -14
- lib/model/http/class-ai1wm-http-curl.php +49 -0
- lib/model/http/class-ai1wm-http-factory.php +36 -0
- lib/model/http/class-ai1wm-http-stream.php +90 -0
- lib/vendor/servmask/database/class-ai1wm-database-utility.php +23 -25
- lib/vendor/servmask/database/class-ai1wm-database.php +41 -48
- loader.php +12 -3
- readme.txt +6 -1
all-in-one-wp-migration.php
CHANGED
@@ -5,7 +5,7 @@
|
|
5 |
* Description: Migration tool for all your blog data. Import or Export your blog content with a single click.
|
6 |
* Author: ServMask
|
7 |
* Author URI: https://servmask.com/
|
8 |
-
* Version: 5.
|
9 |
* Text Domain: all-in-one-wp-migration
|
10 |
* Domain Path: /languages
|
11 |
* Network: True
|
5 |
* Description: Migration tool for all your blog data. Import or Export your blog content with a single click.
|
6 |
* Author: ServMask
|
7 |
* Author URI: https://servmask.com/
|
8 |
+
* Version: 5.50
|
9 |
* Text Domain: all-in-one-wp-migration
|
10 |
* Domain Path: /languages
|
11 |
* Network: True
|
constants.php
CHANGED
@@ -27,7 +27,6 @@ $local = array(
|
|
27 |
'iliev.local',
|
28 |
'develop.servmask.com',
|
29 |
'Borislav-MacBook-Pro.local',
|
30 |
-
'Simeon-PC',
|
31 |
);
|
32 |
|
33 |
if ( function_exists( 'gethostname' ) && in_array( gethostname(), $local ) ) {
|
@@ -39,7 +38,7 @@ if ( function_exists( 'gethostname' ) && in_array( gethostname(), $local ) ) {
|
|
39 |
// ==================
|
40 |
// = Plugin Version =
|
41 |
// ==================
|
42 |
-
define( 'AI1WM_VERSION', '5.
|
43 |
|
44 |
// ===============
|
45 |
// = Plugin Name =
|
@@ -91,6 +90,11 @@ define( 'AI1WM_EXPORT_PATH', AI1WM_MODEL_PATH . DIRECTORY_SEPARATOR . 'export' )
|
|
91 |
// ===============
|
92 |
define( 'AI1WM_IMPORT_PATH', AI1WM_MODEL_PATH . DIRECTORY_SEPARATOR . 'import' );
|
93 |
|
|
|
|
|
|
|
|
|
|
|
94 |
// =============
|
95 |
// = View Path =
|
96 |
// =============
|
27 |
'iliev.local',
|
28 |
'develop.servmask.com',
|
29 |
'Borislav-MacBook-Pro.local',
|
|
|
30 |
);
|
31 |
|
32 |
if ( function_exists( 'gethostname' ) && in_array( gethostname(), $local ) ) {
|
38 |
// ==================
|
39 |
// = Plugin Version =
|
40 |
// ==================
|
41 |
+
define( 'AI1WM_VERSION', '5.50' );
|
42 |
|
43 |
// ===============
|
44 |
// = Plugin Name =
|
90 |
// ===============
|
91 |
define( 'AI1WM_IMPORT_PATH', AI1WM_MODEL_PATH . DIRECTORY_SEPARATOR . 'import' );
|
92 |
|
93 |
+
// =============
|
94 |
+
// = Http Path =
|
95 |
+
// =============
|
96 |
+
define( 'AI1WM_HTTP_PATH', AI1WM_MODEL_PATH . DIRECTORY_SEPARATOR . 'http' );
|
97 |
+
|
98 |
// =============
|
99 |
// = View Path =
|
100 |
// =============
|
lib/controller/class-ai1wm-export-controller.php
CHANGED
@@ -87,7 +87,7 @@ class Ai1wm_Export_Controller {
|
|
87 |
|
88 |
// Do request
|
89 |
if ( $completed === false || ( $next = next( $filters ) ) && ( $params['priority'] = key( $filters ) ) ) {
|
90 |
-
return Ai1wm_Http::
|
91 |
}
|
92 |
}
|
93 |
|
87 |
|
88 |
// Do request
|
89 |
if ( $completed === false || ( $next = next( $filters ) ) && ( $params['priority'] = key( $filters ) ) ) {
|
90 |
+
return Ai1wm_Http::get( admin_url( 'admin-ajax.php?action=ai1wm_export' ), $params );
|
91 |
}
|
92 |
}
|
93 |
|
lib/controller/class-ai1wm-import-controller.php
CHANGED
@@ -93,7 +93,7 @@ class Ai1wm_Import_Controller {
|
|
93 |
|
94 |
// Do request
|
95 |
if ( $completed === false || ( $next = next( $filters ) ) && ( $params['priority'] = key( $filters ) ) ) {
|
96 |
-
return Ai1wm_Http::
|
97 |
}
|
98 |
}
|
99 |
|
93 |
|
94 |
// Do request
|
95 |
if ( $completed === false || ( $next = next( $filters ) ) && ( $params['priority'] = key( $filters ) ) ) {
|
96 |
+
return Ai1wm_Http::get( admin_url( 'admin-ajax.php?action=ai1wm_import' ), $params );
|
97 |
}
|
98 |
}
|
99 |
|
lib/controller/class-ai1wm-resolve-controller.php
CHANGED
@@ -58,9 +58,9 @@ class Ai1wm_Resolve_Controller {
|
|
58 |
// Set transport layer
|
59 |
if ( isset( $params['url_transport'] ) && ( $transport = $params['url_transport'] ) ) {
|
60 |
if ( $transport === 'curl' ) {
|
61 |
-
update_option( AI1WM_URL_TRANSPORT,
|
62 |
} else {
|
63 |
-
update_option( AI1WM_URL_TRANSPORT,
|
64 |
}
|
65 |
}
|
66 |
}
|
58 |
// Set transport layer
|
59 |
if ( isset( $params['url_transport'] ) && ( $transport = $params['url_transport'] ) ) {
|
60 |
if ( $transport === 'curl' ) {
|
61 |
+
update_option( AI1WM_URL_TRANSPORT, 'curl' );
|
62 |
} else {
|
63 |
+
update_option( AI1WM_URL_TRANSPORT, 'stream' );
|
64 |
}
|
65 |
}
|
66 |
}
|
lib/model/class-ai1wm-extensions.php
CHANGED
@@ -76,7 +76,7 @@ class Ai1wm_Extensions {
|
|
76 |
'about' => AI1WMME_PLUGIN_ABOUT,
|
77 |
'basename' => AI1WMME_PLUGIN_BASENAME,
|
78 |
'version' => AI1WMME_VERSION,
|
79 |
-
'requires' => '3.
|
80 |
'short' => AI1WMME_PLUGIN_SHORT,
|
81 |
);
|
82 |
}
|
76 |
'about' => AI1WMME_PLUGIN_ABOUT,
|
77 |
'basename' => AI1WMME_PLUGIN_BASENAME,
|
78 |
'version' => AI1WMME_VERSION,
|
79 |
+
'requires' => '3.23',
|
80 |
'short' => AI1WMME_PLUGIN_SHORT,
|
81 |
);
|
82 |
}
|
lib/model/class-ai1wm-http.php
CHANGED
@@ -25,9 +25,7 @@
|
|
25 |
|
26 |
class Ai1wm_Http {
|
27 |
|
28 |
-
public static $
|
29 |
-
|
30 |
-
public static function post( $url, $params = array() ) {
|
31 |
|
32 |
// Check the status, maybe we need to stop it
|
33 |
if ( ! is_file( ai1wm_export_path( $params ) ) && ! is_file( ai1wm_import_path( $params ) ) ) {
|
@@ -37,8 +35,11 @@ class Ai1wm_Http {
|
|
37 |
// Get IP address
|
38 |
$ip = get_option( AI1WM_URL_IP );
|
39 |
|
|
|
|
|
|
|
40 |
// HTTP request
|
41 |
-
Ai1wm_Http::request( $url, $ip, $params );
|
42 |
}
|
43 |
|
44 |
public static function resolve( $url ) {
|
@@ -50,36 +51,35 @@ class Ai1wm_Http {
|
|
50 |
// Set secret
|
51 |
$secret_key = get_option( AI1WM_SECRET_KEY );
|
52 |
|
53 |
-
// Set
|
54 |
-
$scheme = parse_url( $url, PHP_URL_SCHEME );
|
55 |
-
|
56 |
-
// Set host name
|
57 |
$host = parse_url( $url, PHP_URL_HOST );
|
58 |
|
59 |
// Set server IP address
|
60 |
if ( ! empty( $_SERVER['SERVER_ADDR'] ) ) {
|
61 |
-
$
|
62 |
} else if ( ! empty( $_SERVER['LOCAL_ADDR'] ) ) {
|
63 |
-
$
|
64 |
} else {
|
65 |
-
$
|
66 |
}
|
67 |
|
68 |
-
// Set
|
69 |
-
$
|
70 |
|
71 |
// HTTP resolve
|
72 |
-
foreach ( array( '
|
73 |
-
foreach ( array( $
|
74 |
|
75 |
-
|
76 |
-
|
|
|
|
|
77 |
|
78 |
// HTTP request
|
79 |
-
Ai1wm_Http::request( $url, $ip, array(
|
80 |
'secret_key' => $secret_key,
|
81 |
'url_ip' => $ip,
|
82 |
-
'url_transport' => $transport
|
83 |
) );
|
84 |
|
85 |
// HTTP response
|
@@ -104,54 +104,36 @@ class Ai1wm_Http {
|
|
104 |
) );
|
105 |
}
|
106 |
|
107 |
-
public static function request( $url, $ip, $params = array() ) {
|
108 |
-
|
109 |
-
// Set request order
|
110 |
-
add_filter( 'http_api_transports', 'Ai1wm_Http::transports', 100 );
|
111 |
-
|
112 |
-
// Set host name
|
113 |
$host = parse_url( $url, PHP_URL_HOST );
|
114 |
|
|
|
|
|
|
|
115 |
// Set accept header
|
116 |
-
$headers = array(
|
117 |
|
118 |
-
//
|
119 |
-
if (
|
120 |
-
$
|
121 |
}
|
122 |
|
123 |
-
//
|
124 |
-
if ( ( $port
|
125 |
-
$headers[
|
126 |
} else {
|
127 |
-
$headers[
|
128 |
-
}
|
129 |
-
|
130 |
-
// Add IPv6 support
|
131 |
-
if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ) ) {
|
132 |
-
$ip = "[$ip]";
|
133 |
}
|
134 |
|
135 |
-
//
|
136 |
-
if (
|
137 |
-
$
|
|
|
|
|
138 |
}
|
139 |
|
140 |
// HTTP request
|
141 |
-
|
142 |
-
wp_remote_post(
|
143 |
-
$url,
|
144 |
-
array(
|
145 |
-
'timeout' => apply_filters( 'ai1wm_http_timeout', 5 ),
|
146 |
-
'blocking' => false,
|
147 |
-
'sslverify' => false,
|
148 |
-
'headers' => $headers,
|
149 |
-
'body' => $params,
|
150 |
-
)
|
151 |
-
);
|
152 |
-
}
|
153 |
-
|
154 |
-
public static function transports( $transports ) {
|
155 |
-
return get_option( AI1WM_URL_TRANSPORT, Ai1wm_Http::$transports );
|
156 |
}
|
157 |
}
|
25 |
|
26 |
class Ai1wm_Http {
|
27 |
|
28 |
+
public static function get( $url, $params = array() ) {
|
|
|
|
|
29 |
|
30 |
// Check the status, maybe we need to stop it
|
31 |
if ( ! is_file( ai1wm_export_path( $params ) ) && ! is_file( ai1wm_import_path( $params ) ) ) {
|
35 |
// Get IP address
|
36 |
$ip = get_option( AI1WM_URL_IP );
|
37 |
|
38 |
+
// Get transport
|
39 |
+
$transport = get_option( AI1WM_URL_TRANSPORT );
|
40 |
+
|
41 |
// HTTP request
|
42 |
+
Ai1wm_Http::request( $url, $ip, $transport, $params );
|
43 |
}
|
44 |
|
45 |
public static function resolve( $url ) {
|
51 |
// Set secret
|
52 |
$secret_key = get_option( AI1WM_SECRET_KEY );
|
53 |
|
54 |
+
// Set host
|
|
|
|
|
|
|
55 |
$host = parse_url( $url, PHP_URL_HOST );
|
56 |
|
57 |
// Set server IP address
|
58 |
if ( ! empty( $_SERVER['SERVER_ADDR'] ) ) {
|
59 |
+
$server = $_SERVER['SERVER_ADDR'];
|
60 |
} else if ( ! empty( $_SERVER['LOCAL_ADDR'] ) ) {
|
61 |
+
$server = $_SERVER['LOCAL_ADDR'];
|
62 |
} else {
|
63 |
+
$server = '127.0.0.1';
|
64 |
}
|
65 |
|
66 |
+
// Set local IP address
|
67 |
+
$local = gethostbyname( $host );
|
68 |
|
69 |
// HTTP resolve
|
70 |
+
foreach ( array( 'stream', 'curl' ) as $transport ) {
|
71 |
+
foreach ( array( $server, $local, $host ) as $ip ) {
|
72 |
|
73 |
+
// Add IPv6 support
|
74 |
+
if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ) ) {
|
75 |
+
$ip = "[$ip]";
|
76 |
+
}
|
77 |
|
78 |
// HTTP request
|
79 |
+
Ai1wm_Http::request( $url, $ip, $transport, array(
|
80 |
'secret_key' => $secret_key,
|
81 |
'url_ip' => $ip,
|
82 |
+
'url_transport' => $transport,
|
83 |
) );
|
84 |
|
85 |
// HTTP response
|
104 |
) );
|
105 |
}
|
106 |
|
107 |
+
public static function request( $url, $ip, $transport, $params = array() ) {
|
108 |
+
// Set host
|
|
|
|
|
|
|
|
|
109 |
$host = parse_url( $url, PHP_URL_HOST );
|
110 |
|
111 |
+
// Set port
|
112 |
+
$port = parse_url( $url, PHP_URL_PORT );
|
113 |
+
|
114 |
// Set accept header
|
115 |
+
$headers = array( "Accept: */*" );
|
116 |
|
117 |
+
// Set URL
|
118 |
+
if ( ! empty( $ip ) ) {
|
119 |
+
$url = str_replace( "//{$host}", "//{$ip}", $url );
|
120 |
}
|
121 |
|
122 |
+
// Set host header
|
123 |
+
if ( ! empty( $port ) ) {
|
124 |
+
$headers[] = "Host: {$host}:{$port}";
|
125 |
} else {
|
126 |
+
$headers[] = "Host: {$host}";
|
|
|
|
|
|
|
|
|
|
|
127 |
}
|
128 |
|
129 |
+
// Add authorization header
|
130 |
+
if ( ( $user = get_option( AI1WM_AUTH_USER ) ) && ( $password = get_option( AI1WM_AUTH_PASSWORD ) ) ) {
|
131 |
+
if ( ( $hash = base64_encode( "{$user}:{$password}" ) ) ) {
|
132 |
+
$headers[] = "Authorization: Basic {$hash}";
|
133 |
+
}
|
134 |
}
|
135 |
|
136 |
// HTTP request
|
137 |
+
Ai1wm_Http_Factory::create( $transport )->get( add_query_arg( $params, $url ), $headers );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
138 |
}
|
139 |
}
|
lib/model/class-ai1wm-status.php
CHANGED
@@ -58,8 +58,4 @@ class Ai1wm_Status {
|
|
58 |
update_option( AI1WM_STATUS, $data );
|
59 |
}
|
60 |
}
|
61 |
-
|
62 |
-
public static function flush() {
|
63 |
-
delete_option( AI1WM_STATUS );
|
64 |
-
}
|
65 |
}
|
58 |
update_option( AI1WM_STATUS, $data );
|
59 |
}
|
60 |
}
|
|
|
|
|
|
|
|
|
61 |
}
|
lib/model/class-ai1wm-streams.php
DELETED
@@ -1,422 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Simple and uniform HTTP request API.
|
4 |
-
*
|
5 |
-
* Standardizes the HTTP requests for WordPress. Handles cookies, gzip encoding and decoding, chunk
|
6 |
-
* decoding, if HTTP 1.1 and various other difficult HTTP protocol implementations.
|
7 |
-
*
|
8 |
-
* @link https://core.trac.wordpress.org/ticket/4779 HTTP API Proposal
|
9 |
-
*
|
10 |
-
* @package WordPress
|
11 |
-
* @subpackage HTTP
|
12 |
-
* @since 2.7.0
|
13 |
-
*/
|
14 |
-
|
15 |
-
/**
|
16 |
-
* HTTP request method uses PHP Streams to retrieve the url.
|
17 |
-
*
|
18 |
-
* @since 2.7.0
|
19 |
-
* @since 3.7.0 Combined with the fsockopen transport and switched to stream_socket_client().
|
20 |
-
*/
|
21 |
-
class WP_Http_Ai1wm {
|
22 |
-
/**
|
23 |
-
* Send a HTTP request to a URI using PHP Streams.
|
24 |
-
*
|
25 |
-
* @see WP_Http::request For default options descriptions.
|
26 |
-
*
|
27 |
-
* @since 2.7.0
|
28 |
-
* @since 3.7.0 Combined with the fsockopen transport and switched to stream_socket_client().
|
29 |
-
*
|
30 |
-
* @access public
|
31 |
-
* @param string $url The request URL.
|
32 |
-
* @param string|array $args Optional. Override the defaults.
|
33 |
-
* @return array|WP_Error Array containing 'headers', 'body', 'response', 'cookies', 'filename'. A WP_Error instance upon error
|
34 |
-
*/
|
35 |
-
public function request($url, $args = array()) {
|
36 |
-
$defaults = array(
|
37 |
-
'method' => 'GET', 'timeout' => 5,
|
38 |
-
'redirection' => 5, 'httpversion' => '1.0',
|
39 |
-
'blocking' => true,
|
40 |
-
'headers' => array(), 'body' => null, 'cookies' => array()
|
41 |
-
);
|
42 |
-
|
43 |
-
$r = wp_parse_args( $args, $defaults );
|
44 |
-
|
45 |
-
if ( isset( $r['headers']['User-Agent'] ) ) {
|
46 |
-
$r['user-agent'] = $r['headers']['User-Agent'];
|
47 |
-
unset( $r['headers']['User-Agent'] );
|
48 |
-
} elseif ( isset( $r['headers']['user-agent'] ) ) {
|
49 |
-
$r['user-agent'] = $r['headers']['user-agent'];
|
50 |
-
unset( $r['headers']['user-agent'] );
|
51 |
-
}
|
52 |
-
|
53 |
-
// Construct Cookie: header if any cookies are set.
|
54 |
-
WP_Http::buildCookieHeader( $r );
|
55 |
-
|
56 |
-
$arrURL = parse_url($url);
|
57 |
-
|
58 |
-
$connect_host = $arrURL['host'];
|
59 |
-
|
60 |
-
$secure_transport = ( $arrURL['scheme'] == 'ssl' || $arrURL['scheme'] == 'https' );
|
61 |
-
if ( ! isset( $arrURL['port'] ) ) {
|
62 |
-
if ( $arrURL['scheme'] == 'ssl' || $arrURL['scheme'] == 'https' ) {
|
63 |
-
$arrURL['port'] = 443;
|
64 |
-
$secure_transport = true;
|
65 |
-
} else {
|
66 |
-
$arrURL['port'] = 80;
|
67 |
-
}
|
68 |
-
}
|
69 |
-
|
70 |
-
// Always pass a Path, defaulting to the root in cases such as http://example.com
|
71 |
-
if ( ! isset( $arrURL['path'] ) ) {
|
72 |
-
$arrURL['path'] = '/';
|
73 |
-
}
|
74 |
-
|
75 |
-
if ( isset( $r['headers']['Host'] ) || isset( $r['headers']['host'] ) ) {
|
76 |
-
if ( isset( $r['headers']['Host'] ) )
|
77 |
-
$arrURL['host'] = preg_replace( '/:\d+$/', '', $r['headers']['Host'] );
|
78 |
-
else
|
79 |
-
$arrURL['host'] = preg_replace( '/:\d+$/', '', $r['headers']['host'] );
|
80 |
-
unset( $r['headers']['Host'], $r['headers']['host'] );
|
81 |
-
}
|
82 |
-
|
83 |
-
/*
|
84 |
-
* Certain versions of PHP have issues with 'localhost' and IPv6, It attempts to connect
|
85 |
-
* to ::1, which fails when the server is not set up for it. For compatibility, always
|
86 |
-
* connect to the IPv4 address.
|
87 |
-
*/
|
88 |
-
if ( 'localhost' == strtolower( $connect_host ) )
|
89 |
-
$connect_host = '127.0.0.1';
|
90 |
-
|
91 |
-
$connect_host = $secure_transport ? 'ssl://' . $connect_host : 'tcp://' . $connect_host;
|
92 |
-
|
93 |
-
$is_local = isset( $r['local'] ) && $r['local'];
|
94 |
-
$ssl_verify = isset( $r['sslverify'] ) && $r['sslverify'];
|
95 |
-
if ( $is_local ) {
|
96 |
-
/**
|
97 |
-
* Filter whether SSL should be verified for local requests.
|
98 |
-
*
|
99 |
-
* @since 2.8.0
|
100 |
-
*
|
101 |
-
* @param bool $ssl_verify Whether to verify the SSL connection. Default true.
|
102 |
-
*/
|
103 |
-
$ssl_verify = apply_filters( 'https_local_ssl_verify', $ssl_verify );
|
104 |
-
} elseif ( ! $is_local ) {
|
105 |
-
/**
|
106 |
-
* Filter whether SSL should be verified for non-local requests.
|
107 |
-
*
|
108 |
-
* @since 2.8.0
|
109 |
-
*
|
110 |
-
* @param bool $ssl_verify Whether to verify the SSL connection. Default true.
|
111 |
-
*/
|
112 |
-
$ssl_verify = apply_filters( 'https_ssl_verify', $ssl_verify );
|
113 |
-
}
|
114 |
-
|
115 |
-
$proxy = new WP_HTTP_Proxy();
|
116 |
-
|
117 |
-
$context = stream_context_create( array(
|
118 |
-
'ssl' => array(
|
119 |
-
'verify_peer' => $ssl_verify,
|
120 |
-
'verify_peer_name' => $ssl_verify,
|
121 |
-
//'CN_match' => $arrURL['host'], // This is handled by self::verify_ssl_certificate()
|
122 |
-
'capture_peer_cert' => $ssl_verify,
|
123 |
-
'SNI_enabled' => true,
|
124 |
-
'cafile' => $r['sslcertificates'],
|
125 |
-
'allow_self_signed' => ! $ssl_verify,
|
126 |
-
)
|
127 |
-
) );
|
128 |
-
|
129 |
-
$timeout = (int) floor( $r['timeout'] );
|
130 |
-
$utimeout = $timeout == $r['timeout'] ? 0 : 1000000 * $r['timeout'] % 1000000;
|
131 |
-
$connect_timeout = max( $timeout, 1 );
|
132 |
-
|
133 |
-
// Store error number.
|
134 |
-
$connection_error = null;
|
135 |
-
|
136 |
-
// Store error string.
|
137 |
-
$connection_error_str = null;
|
138 |
-
|
139 |
-
if ( !WP_DEBUG ) {
|
140 |
-
// In the event that the SSL connection fails, silence the many PHP Warnings.
|
141 |
-
if ( $secure_transport )
|
142 |
-
$error_reporting = error_reporting(0);
|
143 |
-
|
144 |
-
if ( $proxy->is_enabled() && $proxy->send_through_proxy( $url ) )
|
145 |
-
$handle = @stream_socket_client( 'tcp://' . $proxy->host() . ':' . $proxy->port(), $connection_error, $connection_error_str, $connect_timeout, STREAM_CLIENT_CONNECT | STREAM_CLIENT_ASYNC_CONNECT, $context );
|
146 |
-
else
|
147 |
-
$handle = @stream_socket_client( $connect_host . ':' . $arrURL['port'], $connection_error, $connection_error_str, $connect_timeout, STREAM_CLIENT_CONNECT | STREAM_CLIENT_ASYNC_CONNECT, $context );
|
148 |
-
|
149 |
-
if ( $secure_transport )
|
150 |
-
error_reporting( $error_reporting );
|
151 |
-
|
152 |
-
} else {
|
153 |
-
if ( $proxy->is_enabled() && $proxy->send_through_proxy( $url ) )
|
154 |
-
$handle = stream_socket_client( 'tcp://' . $proxy->host() . ':' . $proxy->port(), $connection_error, $connection_error_str, $connect_timeout, STREAM_CLIENT_CONNECT | STREAM_CLIENT_ASYNC_CONNECT, $context );
|
155 |
-
else
|
156 |
-
$handle = stream_socket_client( $connect_host . ':' . $arrURL['port'], $connection_error, $connection_error_str, $connect_timeout, STREAM_CLIENT_CONNECT | STREAM_CLIENT_ASYNC_CONNECT, $context );
|
157 |
-
}
|
158 |
-
|
159 |
-
if ( false === $handle ) {
|
160 |
-
// SSL connection failed due to expired/invalid cert, or, OpenSSL configuration is broken.
|
161 |
-
if ( $secure_transport && 0 === $connection_error && '' === $connection_error_str )
|
162 |
-
return new WP_Error( 'http_request_failed', __( 'The SSL certificate for the host could not be verified.' ) );
|
163 |
-
|
164 |
-
return new WP_Error('http_request_failed', $connection_error . ': ' . $connection_error_str );
|
165 |
-
}
|
166 |
-
|
167 |
-
// Verify that the SSL certificate is valid for this request.
|
168 |
-
if ( $secure_transport && $ssl_verify && ! $proxy->is_enabled() ) {
|
169 |
-
if ( ! self::verify_ssl_certificate( $handle, $arrURL['host'] ) )
|
170 |
-
return new WP_Error( 'http_request_failed', __( 'The SSL certificate for the host could not be verified.' ) );
|
171 |
-
}
|
172 |
-
|
173 |
-
// Set connection sleep
|
174 |
-
usleep( 500000 );
|
175 |
-
|
176 |
-
// Set stream timeout
|
177 |
-
stream_set_timeout( $handle, $timeout, $utimeout );
|
178 |
-
|
179 |
-
if ( $proxy->is_enabled() && $proxy->send_through_proxy( $url ) ) //Some proxies require full URL in this field.
|
180 |
-
$requestPath = $url;
|
181 |
-
else
|
182 |
-
$requestPath = $arrURL['path'] . ( isset($arrURL['query']) ? '?' . $arrURL['query'] : '' );
|
183 |
-
|
184 |
-
$strHeaders = strtoupper($r['method']) . ' ' . $requestPath . ' HTTP/' . $r['httpversion'] . "\r\n";
|
185 |
-
|
186 |
-
$include_port_in_host_header = (
|
187 |
-
( $proxy->is_enabled() && $proxy->send_through_proxy( $url ) ) ||
|
188 |
-
( 'http' == $arrURL['scheme'] && 80 != $arrURL['port'] ) ||
|
189 |
-
( 'https' == $arrURL['scheme'] && 443 != $arrURL['port'] )
|
190 |
-
);
|
191 |
-
|
192 |
-
if ( $include_port_in_host_header ) {
|
193 |
-
$strHeaders .= 'Host: ' . $arrURL['host'] . ':' . $arrURL['port'] . "\r\n";
|
194 |
-
} else {
|
195 |
-
$strHeaders .= 'Host: ' . $arrURL['host'] . "\r\n";
|
196 |
-
}
|
197 |
-
|
198 |
-
if ( isset($r['user-agent']) )
|
199 |
-
$strHeaders .= 'User-agent: ' . $r['user-agent'] . "\r\n";
|
200 |
-
|
201 |
-
if ( is_array($r['headers']) ) {
|
202 |
-
foreach ( (array) $r['headers'] as $header => $headerValue )
|
203 |
-
$strHeaders .= $header . ': ' . $headerValue . "\r\n";
|
204 |
-
} else {
|
205 |
-
$strHeaders .= $r['headers'];
|
206 |
-
}
|
207 |
-
|
208 |
-
if ( $proxy->use_authentication() )
|
209 |
-
$strHeaders .= $proxy->authentication_header() . "\r\n";
|
210 |
-
|
211 |
-
$strHeaders .= "\r\n";
|
212 |
-
|
213 |
-
if ( ! is_null($r['body']) )
|
214 |
-
$strHeaders .= $r['body'];
|
215 |
-
|
216 |
-
fwrite($handle, $strHeaders);
|
217 |
-
|
218 |
-
if ( ! $r['blocking'] ) {
|
219 |
-
stream_set_blocking( $handle, 0 );
|
220 |
-
fclose( $handle );
|
221 |
-
return array( 'headers' => array(), 'body' => '', 'response' => array('code' => false, 'message' => false), 'cookies' => array() );
|
222 |
-
}
|
223 |
-
|
224 |
-
$strResponse = '';
|
225 |
-
$bodyStarted = false;
|
226 |
-
$keep_reading = true;
|
227 |
-
$block_size = 4096;
|
228 |
-
if ( isset( $r['limit_response_size'] ) )
|
229 |
-
$block_size = min( $block_size, $r['limit_response_size'] );
|
230 |
-
|
231 |
-
// If streaming to a file setup the file handle.
|
232 |
-
if ( $r['stream'] ) {
|
233 |
-
if ( ! WP_DEBUG )
|
234 |
-
$stream_handle = @fopen( $r['filename'], 'w+' );
|
235 |
-
else
|
236 |
-
$stream_handle = fopen( $r['filename'], 'w+' );
|
237 |
-
if ( ! $stream_handle )
|
238 |
-
return new WP_Error( 'http_request_failed', sprintf( __( 'Could not open handle for fopen() to %s' ), $r['filename'] ) );
|
239 |
-
|
240 |
-
$bytes_written = 0;
|
241 |
-
while ( ! feof($handle) && $keep_reading ) {
|
242 |
-
$block = fread( $handle, $block_size );
|
243 |
-
if ( ! $bodyStarted ) {
|
244 |
-
$strResponse .= $block;
|
245 |
-
if ( strpos( $strResponse, "\r\n\r\n" ) ) {
|
246 |
-
$process = WP_Http::processResponse( $strResponse );
|
247 |
-
$bodyStarted = true;
|
248 |
-
$block = $process['body'];
|
249 |
-
unset( $strResponse );
|
250 |
-
$process['body'] = '';
|
251 |
-
}
|
252 |
-
}
|
253 |
-
|
254 |
-
$this_block_size = strlen( $block );
|
255 |
-
|
256 |
-
if ( isset( $r['limit_response_size'] ) && ( $bytes_written + $this_block_size ) > $r['limit_response_size'] ) {
|
257 |
-
$this_block_size = ( $r['limit_response_size'] - $bytes_written );
|
258 |
-
$block = substr( $block, 0, $this_block_size );
|
259 |
-
}
|
260 |
-
|
261 |
-
$bytes_written_to_file = fwrite( $stream_handle, $block );
|
262 |
-
|
263 |
-
if ( $bytes_written_to_file != $this_block_size ) {
|
264 |
-
fclose( $handle );
|
265 |
-
fclose( $stream_handle );
|
266 |
-
return new WP_Error( 'http_request_failed', __( 'Failed to write request to temporary file.' ) );
|
267 |
-
}
|
268 |
-
|
269 |
-
$bytes_written += $bytes_written_to_file;
|
270 |
-
|
271 |
-
$keep_reading = !isset( $r['limit_response_size'] ) || $bytes_written < $r['limit_response_size'];
|
272 |
-
}
|
273 |
-
|
274 |
-
fclose( $stream_handle );
|
275 |
-
|
276 |
-
} else {
|
277 |
-
$header_length = 0;
|
278 |
-
while ( ! feof( $handle ) && $keep_reading ) {
|
279 |
-
$block = fread( $handle, $block_size );
|
280 |
-
$strResponse .= $block;
|
281 |
-
if ( ! $bodyStarted && strpos( $strResponse, "\r\n\r\n" ) ) {
|
282 |
-
$header_length = strpos( $strResponse, "\r\n\r\n" ) + 4;
|
283 |
-
$bodyStarted = true;
|
284 |
-
}
|
285 |
-
$keep_reading = ( ! $bodyStarted || !isset( $r['limit_response_size'] ) || strlen( $strResponse ) < ( $header_length + $r['limit_response_size'] ) );
|
286 |
-
}
|
287 |
-
|
288 |
-
$process = WP_Http::processResponse( $strResponse );
|
289 |
-
unset( $strResponse );
|
290 |
-
|
291 |
-
}
|
292 |
-
|
293 |
-
fclose( $handle );
|
294 |
-
|
295 |
-
$arrHeaders = WP_Http::processHeaders( $process['headers'], $url );
|
296 |
-
|
297 |
-
$response = array(
|
298 |
-
'headers' => $arrHeaders['headers'],
|
299 |
-
// Not yet processed.
|
300 |
-
'body' => null,
|
301 |
-
'response' => $arrHeaders['response'],
|
302 |
-
'cookies' => $arrHeaders['cookies'],
|
303 |
-
'filename' => $r['filename']
|
304 |
-
);
|
305 |
-
|
306 |
-
// Handle redirects.
|
307 |
-
if ( false !== ( $redirect_response = WP_HTTP::handle_redirects( $url, $r, $response ) ) )
|
308 |
-
return $redirect_response;
|
309 |
-
|
310 |
-
// If the body was chunk encoded, then decode it.
|
311 |
-
if ( ! empty( $process['body'] ) && isset( $arrHeaders['headers']['transfer-encoding'] ) && 'chunked' == $arrHeaders['headers']['transfer-encoding'] )
|
312 |
-
$process['body'] = WP_Http::chunkTransferDecode($process['body']);
|
313 |
-
|
314 |
-
if ( true === $r['decompress'] && true === WP_Http_Encoding::should_decode($arrHeaders['headers']) )
|
315 |
-
$process['body'] = WP_Http_Encoding::decompress( $process['body'] );
|
316 |
-
|
317 |
-
if ( isset( $r['limit_response_size'] ) && strlen( $process['body'] ) > $r['limit_response_size'] )
|
318 |
-
$process['body'] = substr( $process['body'], 0, $r['limit_response_size'] );
|
319 |
-
|
320 |
-
$response['body'] = $process['body'];
|
321 |
-
|
322 |
-
return $response;
|
323 |
-
}
|
324 |
-
|
325 |
-
/**
|
326 |
-
* Verifies the received SSL certificate against it's Common Names and subjectAltName fields
|
327 |
-
*
|
328 |
-
* PHP's SSL verifications only verify that it's a valid Certificate, it doesn't verify if
|
329 |
-
* the certificate is valid for the hostname which was requested.
|
330 |
-
* This function verifies the requested hostname against certificate's subjectAltName field,
|
331 |
-
* if that is empty, or contains no DNS entries, a fallback to the Common Name field is used.
|
332 |
-
*
|
333 |
-
* IP Address support is included if the request is being made to an IP address.
|
334 |
-
*
|
335 |
-
* @since 3.7.0
|
336 |
-
* @static
|
337 |
-
*
|
338 |
-
* @param stream $stream The PHP Stream which the SSL request is being made over
|
339 |
-
* @param string $host The hostname being requested
|
340 |
-
* @return bool If the cerficiate presented in $stream is valid for $host
|
341 |
-
*/
|
342 |
-
public static function verify_ssl_certificate( $stream, $host ) {
|
343 |
-
$context_options = stream_context_get_options( $stream );
|
344 |
-
|
345 |
-
if ( empty( $context_options['ssl']['peer_certificate'] ) )
|
346 |
-
return false;
|
347 |
-
|
348 |
-
$cert = openssl_x509_parse( $context_options['ssl']['peer_certificate'] );
|
349 |
-
if ( ! $cert )
|
350 |
-
return false;
|
351 |
-
|
352 |
-
/*
|
353 |
-
* If the request is being made to an IP address, we'll validate against IP fields
|
354 |
-
* in the cert (if they exist)
|
355 |
-
*/
|
356 |
-
$host_type = ( WP_HTTP::is_ip_address( $host ) ? 'ip' : 'dns' );
|
357 |
-
|
358 |
-
$certificate_hostnames = array();
|
359 |
-
if ( ! empty( $cert['extensions']['subjectAltName'] ) ) {
|
360 |
-
$match_against = preg_split( '/,\s*/', $cert['extensions']['subjectAltName'] );
|
361 |
-
foreach ( $match_against as $match ) {
|
362 |
-
list( $match_type, $match_host ) = explode( ':', $match );
|
363 |
-
if ( $host_type == strtolower( trim( $match_type ) ) ) // IP: or DNS:
|
364 |
-
$certificate_hostnames[] = strtolower( trim( $match_host ) );
|
365 |
-
}
|
366 |
-
} elseif ( !empty( $cert['subject']['CN'] ) ) {
|
367 |
-
// Only use the CN when the certificate includes no subjectAltName extension.
|
368 |
-
$certificate_hostnames[] = strtolower( $cert['subject']['CN'] );
|
369 |
-
}
|
370 |
-
|
371 |
-
// Exact hostname/IP matches.
|
372 |
-
if ( in_array( strtolower( $host ), $certificate_hostnames ) )
|
373 |
-
return true;
|
374 |
-
|
375 |
-
// IP's can't be wildcards, Stop processing.
|
376 |
-
if ( 'ip' == $host_type )
|
377 |
-
return false;
|
378 |
-
|
379 |
-
// Test to see if the domain is at least 2 deep for wildcard support.
|
380 |
-
if ( substr_count( $host, '.' ) < 2 )
|
381 |
-
return false;
|
382 |
-
|
383 |
-
// Wildcard subdomains certs (*.example.com) are valid for a.example.com but not a.b.example.com.
|
384 |
-
$wildcard_host = preg_replace( '/^[^.]+\./', '*.', $host );
|
385 |
-
|
386 |
-
return in_array( strtolower( $wildcard_host ), $certificate_hostnames );
|
387 |
-
}
|
388 |
-
|
389 |
-
/**
|
390 |
-
* Whether this class can be used for retrieving a URL.
|
391 |
-
*
|
392 |
-
* @static
|
393 |
-
* @access public
|
394 |
-
* @since 2.7.0
|
395 |
-
* @since 3.7.0 Combined with the fsockopen transport and switched to stream_socket_client().
|
396 |
-
*
|
397 |
-
* @return bool False means this class can not be used, true means it can.
|
398 |
-
*/
|
399 |
-
public static function test( $args = array() ) {
|
400 |
-
if ( ! function_exists( 'stream_socket_client' ) )
|
401 |
-
return false;
|
402 |
-
|
403 |
-
$is_ssl = isset( $args['ssl'] ) && $args['ssl'];
|
404 |
-
|
405 |
-
if ( $is_ssl ) {
|
406 |
-
if ( ! extension_loaded( 'openssl' ) )
|
407 |
-
return false;
|
408 |
-
if ( ! function_exists( 'openssl_x509_parse' ) )
|
409 |
-
return false;
|
410 |
-
}
|
411 |
-
|
412 |
-
/**
|
413 |
-
* Filter whether streams can be used as a transport for retrieving a URL.
|
414 |
-
*
|
415 |
-
* @since 2.7.0
|
416 |
-
*
|
417 |
-
* @param bool $use_class Whether the class can be used. Default true.
|
418 |
-
* @param array $args Request arguments.
|
419 |
-
*/
|
420 |
-
return apply_filters( 'use_streams_transport', true, $args );
|
421 |
-
}
|
422 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/model/export/class-ai1wm-export-database.php
CHANGED
@@ -104,6 +104,9 @@ class Ai1wm_Export_Database {
|
|
104 |
->set_table_prefix_columns( ai1wm_table_prefix() . 'options', array( 'option_name' ) )
|
105 |
->set_table_prefix_columns( ai1wm_table_prefix() . 'usermeta', array( 'meta_key' ) );
|
106 |
|
|
|
|
|
|
|
107 |
// Set current table index
|
108 |
if ( isset( $params['current_table_index'] ) ) {
|
109 |
$current_table_index = (int) $params['current_table_index'];
|
@@ -111,18 +114,8 @@ class Ai1wm_Export_Database {
|
|
111 |
$current_table_index = 0;
|
112 |
}
|
113 |
|
114 |
-
// Set current table offset
|
115 |
-
if ( isset( $params['current_table_offset'] ) ) {
|
116 |
-
$current_table_offset = (int) $params['current_table_offset'];
|
117 |
-
} else {
|
118 |
-
$current_table_offset = 0;
|
119 |
-
}
|
120 |
-
|
121 |
-
// Flush status
|
122 |
-
Ai1wm_Status::flush();
|
123 |
-
|
124 |
// Export database
|
125 |
-
$completed = $client->export( ai1wm_database_path( $params ), $current_table_index,
|
126 |
|
127 |
// Export completed
|
128 |
if ( $completed ) {
|
@@ -140,9 +133,6 @@ class Ai1wm_Export_Database {
|
|
140 |
// Set current table index
|
141 |
$params['current_table_index'] = $current_table_index;
|
142 |
|
143 |
-
// Set current table offset
|
144 |
-
$params['current_table_offset'] = $current_table_offset;
|
145 |
-
|
146 |
// Set completed flag
|
147 |
$params['completed'] = $completed;
|
148 |
|
104 |
->set_table_prefix_columns( ai1wm_table_prefix() . 'options', array( 'option_name' ) )
|
105 |
->set_table_prefix_columns( ai1wm_table_prefix() . 'usermeta', array( 'meta_key' ) );
|
106 |
|
107 |
+
// Status options
|
108 |
+
$client->set_table_query_clauses( ai1wm_table_prefix() . 'options', sprintf( " WHERE option_name != '%s' ", AI1WM_STATUS ) );
|
109 |
+
|
110 |
// Set current table index
|
111 |
if ( isset( $params['current_table_index'] ) ) {
|
112 |
$current_table_index = (int) $params['current_table_index'];
|
114 |
$current_table_index = 0;
|
115 |
}
|
116 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
117 |
// Export database
|
118 |
+
$completed = $client->export( ai1wm_database_path( $params ), $current_table_index, 10 );
|
119 |
|
120 |
// Export completed
|
121 |
if ( $completed ) {
|
133 |
// Set current table index
|
134 |
$params['current_table_index'] = $current_table_index;
|
135 |
|
|
|
|
|
|
|
136 |
// Set completed flag
|
137 |
$params['completed'] = $completed;
|
138 |
|
lib/model/http/class-ai1wm-http-curl.php
ADDED
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (C) 2014-2016 ServMask Inc.
|
4 |
+
*
|
5 |
+
* This program is free software: you can redistribute it and/or modify
|
6 |
+
* it under the terms of the GNU General Public License as published by
|
7 |
+
* the Free Software Foundation, either version 3 of the License, or
|
8 |
+
* (at your option) any later version.
|
9 |
+
*
|
10 |
+
* This program is distributed in the hope that it will be useful,
|
11 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
+
* GNU General Public License for more details.
|
14 |
+
*
|
15 |
+
* You should have received a copy of the GNU General Public License
|
16 |
+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17 |
+
*
|
18 |
+
* ███████╗███████╗██████╗ ██╗ ██╗███╗ ███╗ █████╗ ███████╗██╗ ██╗
|
19 |
+
* ██╔════╝██╔════╝██╔══██╗██║ ██║████╗ ████║██╔══██╗██╔════╝██║ ██╔╝
|
20 |
+
* ███████╗█████╗ ██████╔╝██║ ██║██╔████╔██║███████║███████╗█████╔╝
|
21 |
+
* ╚════██║██╔══╝ ██╔══██╗╚██╗ ██╔╝██║╚██╔╝██║██╔══██║╚════██║██╔═██╗
|
22 |
+
* ███████║███████╗██║ ██║ ╚████╔╝ ██║ ╚═╝ ██║██║ ██║███████║██║ ██╗
|
23 |
+
* ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝
|
24 |
+
*/
|
25 |
+
|
26 |
+
class Ai1wm_Http_Curl {
|
27 |
+
|
28 |
+
public function get( $url, $headers = array() ) {
|
29 |
+
// Set cURL client
|
30 |
+
$handle = curl_init();
|
31 |
+
|
32 |
+
// Set cURL options
|
33 |
+
curl_setopt( $handle, CURLOPT_CONNECTTIMEOUT, 5 );
|
34 |
+
curl_setopt( $handle, CURLOPT_TIMEOUT, 5 );
|
35 |
+
curl_setopt( $handle, CURLOPT_URL, $url ) ;
|
36 |
+
curl_setopt( $handle, CURLOPT_FOLLOWLOCATION, true );
|
37 |
+
curl_setopt( $handle, CURLOPT_RETURNTRANSFER, true );
|
38 |
+
curl_setopt( $handle, CURLOPT_SSL_VERIFYHOST, false );
|
39 |
+
curl_setopt( $handle, CURLOPT_SSL_VERIFYPEER, false );
|
40 |
+
curl_setopt( $handle, CURLOPT_HEADER, false );
|
41 |
+
curl_setopt( $handle, CURLOPT_HTTPHEADER, $headers );
|
42 |
+
|
43 |
+
// Send data to server
|
44 |
+
curl_exec( $handle );
|
45 |
+
|
46 |
+
// Close cURL handle
|
47 |
+
curl_close( $handle );
|
48 |
+
}
|
49 |
+
}
|
lib/model/http/class-ai1wm-http-factory.php
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (C) 2014-2016 ServMask Inc.
|
4 |
+
*
|
5 |
+
* This program is free software: you can redistribute it and/or modify
|
6 |
+
* it under the terms of the GNU General Public License as published by
|
7 |
+
* the Free Software Foundation, either version 3 of the License, or
|
8 |
+
* (at your option) any later version.
|
9 |
+
*
|
10 |
+
* This program is distributed in the hope that it will be useful,
|
11 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
+
* GNU General Public License for more details.
|
14 |
+
*
|
15 |
+
* You should have received a copy of the GNU General Public License
|
16 |
+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17 |
+
*
|
18 |
+
* ███████╗███████╗██████╗ ██╗ ██╗███╗ ███╗ █████╗ ███████╗██╗ ██╗
|
19 |
+
* ██╔════╝██╔════╝██╔══██╗██║ ██║████╗ ████║██╔══██╗██╔════╝██║ ██╔╝
|
20 |
+
* ███████╗█████╗ ██████╔╝██║ ██║██╔████╔██║███████║███████╗█████╔╝
|
21 |
+
* ╚════██║██╔══╝ ██╔══██╗╚██╗ ██╔╝██║╚██╔╝██║██╔══██║╚════██║██╔═██╗
|
22 |
+
* ███████║███████╗██║ ██║ ╚████╔╝ ██║ ╚═╝ ██║██║ ██║███████║██║ ██╗
|
23 |
+
* ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝
|
24 |
+
*/
|
25 |
+
|
26 |
+
class Ai1wm_Http_Factory {
|
27 |
+
|
28 |
+
public static function create( $type ) {
|
29 |
+
if ( $type === 'curl' ) {
|
30 |
+
return new Ai1wm_Http_Curl;
|
31 |
+
}
|
32 |
+
|
33 |
+
return new Ai1wm_Http_Stream;
|
34 |
+
}
|
35 |
+
|
36 |
+
}
|
lib/model/http/class-ai1wm-http-stream.php
ADDED
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (C) 2014-2016 ServMask Inc.
|
4 |
+
*
|
5 |
+
* This program is free software: you can redistribute it and/or modify
|
6 |
+
* it under the terms of the GNU General Public License as published by
|
7 |
+
* the Free Software Foundation, either version 3 of the License, or
|
8 |
+
* (at your option) any later version.
|
9 |
+
*
|
10 |
+
* This program is distributed in the hope that it will be useful,
|
11 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
+
* GNU General Public License for more details.
|
14 |
+
*
|
15 |
+
* You should have received a copy of the GNU General Public License
|
16 |
+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17 |
+
*
|
18 |
+
* ███████╗███████╗██████╗ ██╗ ██╗███╗ ███╗ █████╗ ███████╗██╗ ██╗
|
19 |
+
* ██╔════╝██╔════╝██╔══██╗██║ ██║████╗ ████║██╔══██╗██╔════╝██║ ██╔╝
|
20 |
+
* ███████╗█████╗ ██████╔╝██║ ██║██╔████╔██║███████║███████╗█████╔╝
|
21 |
+
* ╚════██║██╔══╝ ██╔══██╗╚██╗ ██╔╝██║╚██╔╝██║██╔══██║╚════██║██╔═██╗
|
22 |
+
* ███████║███████╗██║ ██║ ╚████╔╝ ██║ ╚═╝ ██║██║ ██║███████║██║ ██╗
|
23 |
+
* ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝
|
24 |
+
*/
|
25 |
+
|
26 |
+
class Ai1wm_Http_Stream {
|
27 |
+
|
28 |
+
public function get( $url, $headers = array() ) {
|
29 |
+
// Set host
|
30 |
+
$host = parse_url( $url, PHP_URL_HOST );
|
31 |
+
|
32 |
+
// Set port
|
33 |
+
$port = parse_url( $url, PHP_URL_PORT );
|
34 |
+
|
35 |
+
// Set path
|
36 |
+
$path = parse_url( $url, PHP_URL_PATH );
|
37 |
+
|
38 |
+
// Set query
|
39 |
+
$query = parse_url( $url, PHP_URL_QUERY );
|
40 |
+
|
41 |
+
// Set port
|
42 |
+
if ( empty( $port ) ) {
|
43 |
+
if ( parse_url( $url, PHP_URL_SCHEME ) === 'https' ) {
|
44 |
+
$port = 443;
|
45 |
+
} else {
|
46 |
+
$port = 80;
|
47 |
+
}
|
48 |
+
}
|
49 |
+
|
50 |
+
// Set stream context
|
51 |
+
$context = stream_context_create( array(
|
52 |
+
'ssl' => array(
|
53 |
+
'verify_peer' => false,
|
54 |
+
'verify_peer_name' => false,
|
55 |
+
'capture_peer_cert' => false,
|
56 |
+
'allow_self_signed' => true,
|
57 |
+
)
|
58 |
+
) );
|
59 |
+
|
60 |
+
// Set stream client
|
61 |
+
if ( parse_url( $url, PHP_URL_SCHEME ) === 'https' ) {
|
62 |
+
$handle = stream_socket_client( "ssl://{$host}:{$port}", $errno, $errstr, 5, STREAM_CLIENT_CONNECT, $context );
|
63 |
+
} else {
|
64 |
+
$handle = stream_socket_client( "tcp://{$host}:{$port}", $errno, $errstr, 5, STREAM_CLIENT_CONNECT, $context );
|
65 |
+
}
|
66 |
+
|
67 |
+
// Ensure the stream is ready to write to
|
68 |
+
$no_streams = array();
|
69 |
+
$write_streams = array( $handle );
|
70 |
+
stream_select( $no_streams, $write_streams, $no_streams, 0, 200000 );
|
71 |
+
|
72 |
+
// Prepare headers
|
73 |
+
$headers = implode( "\r\n", $headers );
|
74 |
+
|
75 |
+
// Prepare request
|
76 |
+
$request = "GET {$path}?{$query} HTTP/1.0\r\n{$headers}\r\n\r\n";
|
77 |
+
|
78 |
+
// Send data to server
|
79 |
+
if ( ( $length = fwrite( $handle, $request ) ) !== strlen( $request ) ) {
|
80 |
+
trigger_error( sprintf( 'fwrite wrote only %d instead of %d' , $length, strlen( $request ) ) );
|
81 |
+
}
|
82 |
+
|
83 |
+
// Set non blocking
|
84 |
+
stream_set_blocking( $handle, 0 );
|
85 |
+
|
86 |
+
// Close stream handle
|
87 |
+
fclose( $handle );
|
88 |
+
}
|
89 |
+
|
90 |
+
}
|
lib/vendor/servmask/database/class-ai1wm-database-utility.php
CHANGED
@@ -53,37 +53,35 @@ class Ai1wm_Database_Utility {
|
|
53 |
try {
|
54 |
|
55 |
// Some unserialized data cannot be re-serialized eg. SimpleXMLElements
|
56 |
-
if ( $data ) {
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
}
|
64 |
-
|
65 |
-
$data = $tmp;
|
66 |
-
unset( $tmp );
|
67 |
-
} elseif ( is_object( $data ) ) {
|
68 |
-
$tmp = $data;
|
69 |
-
$props = get_object_vars( $data );
|
70 |
-
foreach ( $props as $key => $value ) {
|
71 |
-
$tmp->$key = self::replace_serialized_values( $from, $to, $value, false );
|
72 |
-
}
|
73 |
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
|
|
80 |
}
|
81 |
|
82 |
-
|
83 |
-
|
|
|
|
|
|
|
84 |
}
|
85 |
}
|
86 |
|
|
|
|
|
|
|
|
|
87 |
} catch ( Exception $e ) {
|
88 |
// pass
|
89 |
}
|
53 |
try {
|
54 |
|
55 |
// Some unserialized data cannot be re-serialized eg. SimpleXMLElements
|
56 |
+
if ( is_serialized( $data ) && ( $unserialized = @unserialize( $data ) ) !== false ) {
|
57 |
+
$data = self::replace_serialized_values( $from, $to, $unserialized, true );
|
58 |
+
} else if ( is_array( $data ) ) {
|
59 |
+
$tmp = array();
|
60 |
+
foreach ( $data as $key => $value ) {
|
61 |
+
$tmp[$key] = self::replace_serialized_values( $from, $to, $value, false );
|
62 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
63 |
|
64 |
+
$data = $tmp;
|
65 |
+
unset( $tmp );
|
66 |
+
} elseif ( is_object( $data ) ) {
|
67 |
+
$tmp = $data;
|
68 |
+
$props = get_object_vars( $data );
|
69 |
+
foreach ( $props as $key => $value ) {
|
70 |
+
$tmp->$key = self::replace_serialized_values( $from, $to, $value, false );
|
71 |
}
|
72 |
|
73 |
+
$data = $tmp;
|
74 |
+
unset( $tmp );
|
75 |
+
} else {
|
76 |
+
if ( is_string( $data ) ) {
|
77 |
+
$data = str_ireplace( $from, $to, $data );
|
78 |
}
|
79 |
}
|
80 |
|
81 |
+
if ( $serialized ) {
|
82 |
+
return serialize( $data );
|
83 |
+
}
|
84 |
+
|
85 |
} catch ( Exception $e ) {
|
86 |
// pass
|
87 |
}
|
lib/vendor/servmask/database/class-ai1wm-database.php
CHANGED
@@ -364,11 +364,10 @@ abstract class Ai1wm_Database {
|
|
364 |
*
|
365 |
* @param string $file_name Name of file
|
366 |
* @param string $current_table_index Current table index
|
367 |
-
* @param int $current_table_offset Current table offset
|
368 |
* @param int $timeout Process timeout
|
369 |
* @return bool
|
370 |
*/
|
371 |
-
public function export( $file_name, &$current_table_index = 0,
|
372 |
|
373 |
// Set file handler
|
374 |
$file_handler = fopen( $file_name, 'ab' );
|
@@ -393,7 +392,7 @@ abstract class Ai1wm_Database {
|
|
393 |
$tables = $this->get_tables();
|
394 |
|
395 |
// Export tables
|
396 |
-
for ( ; $current_table_index < count( $tables );
|
397 |
|
398 |
// Get table name
|
399 |
$table_name = $tables[ $current_table_index ];
|
@@ -401,47 +400,45 @@ abstract class Ai1wm_Database {
|
|
401 |
// Replace table name prefixes
|
402 |
$new_table_name = $this->replace_table_prefixes( $table_name, 0 );
|
403 |
|
404 |
-
//
|
405 |
-
|
|
|
406 |
|
407 |
-
|
408 |
-
|
409 |
-
$table = $this->fetch_assoc( $structure );
|
410 |
|
411 |
-
|
412 |
-
|
413 |
|
414 |
-
//
|
415 |
-
|
416 |
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
if ( fwrite( $file_handler, $drop_table ) === false ) {
|
422 |
-
throw new Exception( 'Unable to write database table statement' );
|
423 |
-
}
|
424 |
|
425 |
-
|
426 |
-
|
427 |
|
428 |
-
|
429 |
-
|
430 |
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
}
|
440 |
}
|
441 |
}
|
442 |
|
|
|
|
|
443 |
// Set query
|
444 |
-
$query = sprintf( "SELECT * FROM `$table_name` %s
|
445 |
|
446 |
// Apply additional table prefix columns
|
447 |
$columns = $this->get_table_prefix_columns( $table_name );
|
@@ -488,30 +485,26 @@ abstract class Ai1wm_Database {
|
|
488 |
throw new Exception( 'Unable to write database end of transaction' );
|
489 |
}
|
490 |
}
|
|
|
491 |
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
break;
|
497 |
-
}
|
498 |
}
|
499 |
}
|
500 |
|
|
|
|
|
501 |
// Close result cursor
|
502 |
$this->free_result( $result );
|
503 |
|
504 |
-
//
|
505 |
-
if ( $
|
506 |
-
if (
|
507 |
-
|
508 |
-
|
509 |
-
}
|
510 |
}
|
511 |
-
|
512 |
-
$current_table_offset = 0;
|
513 |
-
} else {
|
514 |
-
break;
|
515 |
}
|
516 |
}
|
517 |
|
364 |
*
|
365 |
* @param string $file_name Name of file
|
366 |
* @param string $current_table_index Current table index
|
|
|
367 |
* @param int $timeout Process timeout
|
368 |
* @return bool
|
369 |
*/
|
370 |
+
public function export( $file_name, &$current_table_index = 0, $timeout = 0 ) {
|
371 |
|
372 |
// Set file handler
|
373 |
$file_handler = fopen( $file_name, 'ab' );
|
392 |
$tables = $this->get_tables();
|
393 |
|
394 |
// Export tables
|
395 |
+
for ( ; $current_table_index < count( $tables ); ) {
|
396 |
|
397 |
// Get table name
|
398 |
$table_name = $tables[ $current_table_index ];
|
400 |
// Replace table name prefixes
|
401 |
$new_table_name = $this->replace_table_prefixes( $table_name, 0 );
|
402 |
|
403 |
+
// Get table structure
|
404 |
+
$structure = $this->query( "SHOW CREATE TABLE `$table_name`" );
|
405 |
+
$table = $this->fetch_assoc( $structure );
|
406 |
|
407 |
+
// Close structure cursor
|
408 |
+
$this->free_result( $structure );
|
|
|
409 |
|
410 |
+
// Get create table
|
411 |
+
if ( isset( $table['Create Table'] ) ) {
|
412 |
|
413 |
+
// Write table drop statement
|
414 |
+
$drop_table = "\nDROP TABLE IF EXISTS `$new_table_name`;\n";
|
415 |
|
416 |
+
// Write table statement
|
417 |
+
if ( fwrite( $file_handler, $drop_table ) === false ) {
|
418 |
+
throw new Exception( 'Unable to write database table statement' );
|
419 |
+
}
|
|
|
|
|
|
|
420 |
|
421 |
+
// Replace create table prefixes
|
422 |
+
$create_table = $this->replace_table_prefixes( $table['Create Table'], 14 );
|
423 |
|
424 |
+
// Strip table constraints
|
425 |
+
$create_table = $this->strip_table_constraints( $create_table );
|
426 |
|
427 |
+
// Write table structure
|
428 |
+
if ( fwrite( $file_handler, $create_table ) === false ) {
|
429 |
+
throw new Exception( 'Unable to write database table structure' );
|
430 |
+
}
|
431 |
|
432 |
+
// Write end of statement
|
433 |
+
if ( fwrite( $file_handler, ";\n\n" ) === false ) {
|
434 |
+
throw new Exception( 'Unable to write database end of statement' );
|
|
|
435 |
}
|
436 |
}
|
437 |
|
438 |
+
$current_table_offset = 0;
|
439 |
+
|
440 |
// Set query
|
441 |
+
$query = sprintf( "SELECT * FROM `$table_name` %s", $this->get_table_query_clauses( $table_name ) );
|
442 |
|
443 |
// Apply additional table prefix columns
|
444 |
$columns = $this->get_table_prefix_columns( $table_name );
|
485 |
throw new Exception( 'Unable to write database end of transaction' );
|
486 |
}
|
487 |
}
|
488 |
+
}
|
489 |
|
490 |
+
// Write end of transaction
|
491 |
+
if ( $current_table_offset % Ai1wm_Database::QUERIES_PER_TRANSACTION !== 0 ) {
|
492 |
+
if ( fwrite( $file_handler, "COMMIT;\n" ) === false ) {
|
493 |
+
throw new Exception( 'Unable to write database end of transaction' );
|
|
|
|
|
494 |
}
|
495 |
}
|
496 |
|
497 |
+
$current_table_index += 1;
|
498 |
+
|
499 |
// Close result cursor
|
500 |
$this->free_result( $result );
|
501 |
|
502 |
+
// Time elapsed
|
503 |
+
if ( $timeout ) {
|
504 |
+
if ( ( microtime( true ) - $start ) > $timeout ) {
|
505 |
+
$completed = false;
|
506 |
+
break;
|
|
|
507 |
}
|
|
|
|
|
|
|
|
|
508 |
}
|
509 |
}
|
510 |
|
loader.php
CHANGED
@@ -262,6 +262,18 @@ require_once AI1WM_IMPORT_PATH .
|
|
262 |
DIRECTORY_SEPARATOR .
|
263 |
'class-ai1wm-import-clean.php';
|
264 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
265 |
require_once AI1WM_MODEL_PATH .
|
266 |
DIRECTORY_SEPARATOR .
|
267 |
'class-ai1wm-deprecated.php';
|
@@ -314,6 +326,3 @@ require_once AI1WM_MODEL_PATH .
|
|
314 |
DIRECTORY_SEPARATOR .
|
315 |
'class-ai1wm-http.php';
|
316 |
|
317 |
-
require_once AI1WM_MODEL_PATH .
|
318 |
-
DIRECTORY_SEPARATOR .
|
319 |
-
'class-ai1wm-streams.php';
|
262 |
DIRECTORY_SEPARATOR .
|
263 |
'class-ai1wm-import-clean.php';
|
264 |
|
265 |
+
require_once AI1WM_HTTP_PATH .
|
266 |
+
DIRECTORY_SEPARATOR .
|
267 |
+
'class-ai1wm-http-stream.php';
|
268 |
+
|
269 |
+
require_once AI1WM_HTTP_PATH .
|
270 |
+
DIRECTORY_SEPARATOR .
|
271 |
+
'class-ai1wm-http-curl.php';
|
272 |
+
|
273 |
+
require_once AI1WM_HTTP_PATH .
|
274 |
+
DIRECTORY_SEPARATOR .
|
275 |
+
'class-ai1wm-http-factory.php';
|
276 |
+
|
277 |
require_once AI1WM_MODEL_PATH .
|
278 |
DIRECTORY_SEPARATOR .
|
279 |
'class-ai1wm-deprecated.php';
|
326 |
DIRECTORY_SEPARATOR .
|
327 |
'class-ai1wm-http.php';
|
328 |
|
|
|
|
|
|
readme.txt
CHANGED
@@ -3,7 +3,7 @@ Contributors: yani.iliev, bangelov, pimjitsawang
|
|
3 |
Tags: db migration, migration, wordpress migration, db backup, db restore, website backup, website restore, website migration, website deploy, wordpress deploy, db backup, database export, database serialization, database find replace
|
4 |
Requires at least: 3.3
|
5 |
Tested up to: 4.6
|
6 |
-
Stable tag: 5.
|
7 |
License: GPLv2 or later
|
8 |
|
9 |
All-in-One WP Migration is the only tool that you will ever need to migrate a WordPress site.
|
@@ -78,6 +78,11 @@ All in One WP Plugin is the first plugin to offer true mobile experience on Word
|
|
78 |
3. Plugin Menu
|
79 |
|
80 |
== Changelog ==
|
|
|
|
|
|
|
|
|
|
|
81 |
= 5.49 =
|
82 |
* Test plugin up to WordPress 4.6
|
83 |
|
3 |
Tags: db migration, migration, wordpress migration, db backup, db restore, website backup, website restore, website migration, website deploy, wordpress deploy, db backup, database export, database serialization, database find replace
|
4 |
Requires at least: 3.3
|
5 |
Tested up to: 4.6
|
6 |
+
Stable tag: 5.50
|
7 |
License: GPLv2 or later
|
8 |
|
9 |
All-in-One WP Migration is the only tool that you will ever need to migrate a WordPress site.
|
78 |
3. Plugin Menu
|
79 |
|
80 |
== Changelog ==
|
81 |
+
= 5.50 =
|
82 |
+
* Improve database export process
|
83 |
+
* Simplify export and import cron
|
84 |
+
* Fix an issue with export and import progress status
|
85 |
+
|
86 |
= 5.49 =
|
87 |
* Test plugin up to WordPress 4.6
|
88 |
|