File: /home/frenchy/www/_trash/wp-content/plugins/wp-sync-db/class/wpsdb-base.php
<?php
class WPSDB_Base {
protected $settings;
protected $plugin_file_path;
protected $plugin_dir_path;
protected $plugin_slug;
protected $plugin_folder_name;
protected $plugin_basename;
protected $plugin_base;
protected $plugin_version;
protected $template_dir;
protected $plugin_title;
protected $transient_timeout;
protected $transient_retry_timeout;
protected $multipart_boundary = 'bWH4JVmYCnf6GfXacrcc';
protected $attempting_to_connect_to;
protected $error;
protected $temp_prefix = '_mig_';
protected $invalid_content_verification_error;
protected $addons;
protected $doing_cli_migration = false;
function __construct( $plugin_file_path ) {
$this->settings = get_option( 'wpsdb_settings' );
$this->addons = array(
'wp-sync-db-media-files/wp-sync-db-media-files.php' => array(
'name' => 'Media Files',
'required_version' => '1.1.4b1',
),
'wp-sync-db-cli/wp-sync-db-cli.php' => array(
'name' => 'CLI',
'required_version' => '1.0b1',
)
);
$this->invalid_content_verification_error = __( 'Invalid content verification signature, please verify the connection information on the remote site and try again.', 'wp-sync-db' );
$this->transient_timeout = 60 * 60 * 12;
$this->transient_retry_timeout = 60 * 60 * 2;
$this->plugin_file_path = $plugin_file_path;
$this->plugin_dir_path = plugin_dir_path( $plugin_file_path );
$this->plugin_folder_name = basename( $this->plugin_dir_path );
$this->plugin_basename = plugin_basename( $plugin_file_path );
$this->template_dir = $this->plugin_dir_path . 'template' . DS;
$this->plugin_title = ucwords( str_ireplace( '-', ' ', basename( $plugin_file_path ) ) );
$this->plugin_title = str_ireplace( array( 'db', 'wp', '.php' ), array( 'DB', 'WP', '' ), $this->plugin_title );
if ( is_multisite() ) {
$this->plugin_base = 'settings.php?page=wp-sync-db';
}
else {
$this->plugin_base = 'tools.php?page=wp-sync-db';
}
// allow devs to change the temporary prefix applied to the tables
$this->temp_prefix = apply_filters( 'wpsdb_temporary_prefix', $this->temp_prefix );
}
function template( $template ) {
include $this->template_dir . $template . '.php';
}
function open_ssl_enabled() {
if ( defined( 'OPENSSL_VERSION_TEXT' ) ) {
return true;
}
else {
return false;
}
}
function set_time_limit() {
if ( !function_exists( 'ini_get' ) || !ini_get( 'safe_mode' ) ) {
@set_time_limit( 0 );
}
}
function remote_post( $url, $data, $scope, $args = array(), $expecting_serial = false ) {
$this->set_time_limit();
if( function_exists( 'fsockopen' ) && strpos( $url, 'https://' ) === 0 && $scope == 'ajax_verify_connection_to_remote_site' ) {
$url_parts = parse_url( $url );
$host = $url_parts['host'];
if( $pf = @fsockopen( $host, 443, $err, $err_string, 1 ) ) {
// worked
fclose( $pf );
}
else {
// failed
$url = substr_replace( $url, 'http', 0, 5 );
}
}
$sslverify = ( $this->settings['verify_ssl'] == 1 ? true : false );
$default_remote_post_timeout = apply_filters( 'wpsdb_default_remote_post_timeout', 60 * 20 );
$args = wp_parse_args( $args, array(
'timeout' => $default_remote_post_timeout,
'blocking' => true,
'sslverify' => $sslverify,
) );
$args['method'] = 'POST';
if( ! isset( $args['body'] ) ) {
$args['body'] = $this->array_to_multipart( $data );
}
$args['headers']['Content-Type'] = 'multipart/form-data; boundary=' . $this->multipart_boundary;
$args['headers']['Referer'] = network_admin_url( 'admin-ajax.php' );
$this->attempting_to_connect_to = $url;
$response = wp_remote_post( $url, $args );
if ( ! is_wp_error( $response ) ) {
$response['body'] = trim( $response['body'], "\xef\xbb\xbf" );
}
if ( is_wp_error( $response ) ) {
if( strpos( $url, 'https://' ) === 0 && $scope == 'ajax_verify_connection_to_remote_site' ) {
return $this->retry_remote_post( $url, $data, $scope, $args, $expecting_serial );
}
else if( isset( $response->errors['http_request_failed'][0] ) && strstr( $response->errors['http_request_failed'][0], 'timed out' ) ) {
$this->error = sprintf( __( 'The connection to the remote server has timed out, no changes have been committed. (#134 - scope: %s)', 'wp-sync-db' ), $scope );
}
else if ( isset( $response->errors['http_request_failed'][0] ) && ( strstr( $response->errors['http_request_failed'][0], 'Could not resolve host' ) || strstr( $response->errors['http_request_failed'][0], 'couldn\'t connect to host' ) ) ) {
$this->error = sprintf( __( 'We could not find: %s. Are you sure this is the correct URL?', 'wp-sync-db' ), $_POST['url'] );
$url_bits = parse_url( $_POST['url'] );
if( strstr( $_POST['url'], 'dev.' ) || strstr( $_POST['url'], '.dev' ) || ! strstr( $url_bits['host'], '.' ) ) {
$this->error .= '<br />';
if( $_POST['intent'] == 'pull' ) {
$this->error .= __( 'It appears that you might be trying to pull from a local environment. This will not work if <u>this</u> website happens to be located on a remote server, it would be impossible for this server to contact your local environment.', 'wp-sync-db' );
}
else {
$this->error .= __( 'It appears that you might be trying to push to a local environment. This will not work if <u>this</u> website happens to be located on a remote server, it would be impossible for this server to contact your local environment.', 'wp-sync-db' );
}
}
}
else {
$this->error = sprintf( __( 'The connection failed, an unexpected error occurred, please contact support. (#121 - scope: %s)', 'wp-sync-db' ), $scope );
}
$this->log_error( $this->error, $response );
return false;
}
elseif ( (int) $response['response']['code'] < 200 || (int) $response['response']['code'] > 399 ) {
if( strpos( $url, 'https://' ) === 0 && $scope == 'ajax_verify_connection_to_remote_site' ) {
return $this->retry_remote_post( $url, $data, $scope, $args, $expecting_serial );
}
else if( $response['response']['code'] == '401' ) {
$this->error = __( 'The remote site is protected with Basic Authentication. Please enter the username and password above to continue. (401 Unauthorized)', 'wp-sync-db' );
$this->log_error( $this->error, $response );
return false;
}
else {
$this->error = sprintf( __( 'Unable to connect to the remote server, please check the connection details - %1$s %2$s (#129 - scope: %3$s)', 'wp-sync-db' ), $response['response']['code'], $response['response']['message'], $scope );
$this->log_error( $this->error, $response );
return false;
}
}
elseif ( $expecting_serial && is_serialized( $response['body'] ) == false ) {
if( strpos( $url, 'https://' ) === 0 && $scope == 'ajax_verify_connection_to_remote_site' ) {
return $this->retry_remote_post( $url, $data, $scope, $args, $expecting_serial );
}
$this->error = __( 'There was a problem with the AJAX request, we were expecting a serialized response, instead we received:<br />', 'wp-sync-db' ) . htmlentities( $response['body'] );
$this->log_error( $this->error, $response );
return false;
}
elseif ( $response['body'] === '0' ) {
if( strpos( $url, 'https://' ) === 0 && $scope == 'ajax_verify_connection_to_remote_site' ) {
return $this->retry_remote_post( $url, $data, $scope, $args, $expecting_serial );
}
$this->error = sprintf( __( 'WP Sync DB does not seem to be installed or active on the remote site. (#131 - scope: %s)', 'wp-sync-db' ), $scope );
$this->log_error( $this->error, $response );
return false;
}
elseif ( $expecting_serial && is_serialized( $response['body'] ) == true && $scope == 'ajax_verify_connection_to_remote_site' ) {
$unserialized_response = unserialize( $response['body'] );
if ( isset( $unserialized_response['error'] ) && '1' == $unserialized_response['error'] && strpos( $url, 'https://' ) === 0 ) {
return $this->retry_remote_post( $url, $data, $scope, $args, $expecting_serial );
}
}
return $response['body'];
}
function retry_remote_post( $url, $data, $scope, $args = array(), $expecting_serial = false ) {
$url = substr_replace( $url, 'http', 0, 5 );
if( $response = $this->remote_post( $url, $data, $scope, $args, $expecting_serial ) ) {
return $response;
}
return false;
}
function array_to_multipart( $data ) {
if ( !$data || !is_array( $data ) ) {
return $data;
}
$result = '';
foreach ( $data as $key => $value ) {
$result .= '--' . $this->multipart_boundary . "\r\n" .
sprintf( 'Content-Disposition: form-data; name="%s"', $key );
if ( 'chunk' == $key ) {
if ( $data['chunk_gzipped'] ) {
$result .= "; filename=\"chunk.txt.gz\"\r\nContent-Type: application/x-gzip";
}
else {
$result .= "; filename=\"chunk.txt\"\r\nContent-Type: text/plain;";
}
}
else {
$result .= "\r\nContent-Type: text/plain; charset=" . get_option( 'blog_charset' );
}
$result .= "\r\n\r\n" . $value . "\r\n";
}
$result .= "--" . $this->multipart_boundary . "--\r\n";
return $result;
}
function file_to_multipart( $file ) {
$result = '';
if( false == file_exists( $file ) ) return false;
$filetype = wp_check_filetype( $file );
$contents = file_get_contents( $file );
$result .= '--' . $this->multipart_boundary . "\r\n" .
sprintf( 'Content-Disposition: form-data; name="media[]"; filename="%s"', basename( $file ) );
$result .= sprintf( "\r\nContent-Type: %s", $filetype['type'] );
$result .= "\r\n\r\n" . $contents . "\r\n";
$result .= "--" . $this->multipart_boundary . "--\r\n";
return $result;
}
function log_error( $wpsdb_error, $additional_error_var = false ){
$error_header = "********************************************\n****** Log date: " . date( 'Y/m/d H:i:s' ) . " ******\n********************************************\n\n";
$error = $error_header . "WPSDB Error: " . $wpsdb_error . "\n\n";
if( ! empty( $this->attempting_to_connect_to ) ) {
$error .= "Attempted to connect to: " . $this->attempting_to_connect_to . "\n\n";
}
if( $additional_error_var !== false ){
$error .= print_r( $additional_error_var, true ) . "\n\n";
}
$log = get_option( 'wpsdb_error_log' );
if( $log ) {
$log = $log . $error;
}
else {
$log = $error;
}
update_option( 'wpsdb_error_log', $log );
}
function display_errors() {
if ( ! empty( $this->error ) ) {
echo $this->error;
$this->error = '';
return true;
}
return false;
}
function filter_post_elements( $post_array, $accepted_elements ) {
if ( isset( $post_array['form_data'] ) ) {
$post_array['form_data'] = stripslashes( $post_array['form_data'] );
}
$accepted_elements[] = 'sig';
return array_intersect_key( $post_array, array_flip( $accepted_elements ) );
}
function create_signature( $data, $key ) {
if ( isset( $data['sig'] ) ) {
unset( $data['sig'] );
}
$flat_data = implode( '', $data );
return base64_encode( hash_hmac( 'sha1', $flat_data, $key, true ) );
}
function verify_signature( $data, $key ) {
if( empty( $data['sig'] ) ) {
return false;
}
if ( isset( $data['nonce'] ) ) {
unset( $data['nonce'] );
}
$temp = $data;
$computed_signature = $this->create_signature( $temp, $key );
return $computed_signature === $data['sig'];
}
function diverse_array( $vector ) {
$result = array();
foreach( $vector as $key1 => $value1 )
foreach( $value1 as $key2 => $value2 )
$result[$key2][$key1] = $value2;
return $result;
}
function set_time_limit_available() {
if ( ! function_exists( 'set_time_limit' ) || ! function_exists( 'ini_get' ) ) return false;
$current_max_execution_time = ini_get( 'max_execution_time' );
$proposed_max_execution_time = ( $current_max_execution_time == 30 ) ? 31 : 30;
@set_time_limit( $proposed_max_execution_time );
$current_max_execution_time = ini_get( 'max_execution_time' );
return ( $proposed_max_execution_time == $current_max_execution_time );
}
function get_plugin_name( $plugin = false ) {
if ( !is_admin() ) return false;
$plugin_basename = ( false !== $plugin ? $plugin : $this->plugin_basename );
$plugins = get_plugins();
if ( !isset( $plugins[$plugin_basename]['Name'] ) ) {
return false;
}
return $plugins[$plugin_basename]['Name'];
}
function get_class_props() {
return get_object_vars( $this );
}
// Get only the table beginning with our DB prefix or temporary prefix, also skip views
function get_tables( $scope = 'regular' ) {
global $wpdb;
$prefix = ( $scope == 'temp' ? $this->temp_prefix : $wpdb->prefix );
$tables = $wpdb->get_results( 'SHOW FULL TABLES', ARRAY_N );
foreach ( $tables as $table ) {
if ( ( ( $scope == 'temp' || $scope == 'prefix' ) && 0 !== strpos( $table[0], $prefix ) ) || $table[1] == 'VIEW' ) {
continue;
}
$clean_tables[] = $table[0];
}
return apply_filters( 'wpsdb_tables', $clean_tables, $scope );
}
function plugins_dir() {
$path = untrailingslashit( $this->plugin_dir_path );
return substr( $path, 0, strrpos( $path, DS ) ) . DS;
}
function is_addon_outdated( $addon_basename ) {
$addon_slug = current( explode( '/', $addon_basename ) );
// If pre-1.1.2 version of Media Files addon, then it is outdated
if ( ! isset( $GLOBALS['wpsdb_meta'][$addon_slug]['version'] ) ) return true;
$installed_version = $GLOBALS['wpsdb_meta'][$addon_slug]['version'];
$required_version = $this->addons[$addon_basename]['required_version'];
return version_compare( $installed_version, $required_version, '<' );
}
function get_plugin_file_path() {
return $this->plugin_file_path;
}
function set_cli_migration() {
$this->doing_cli_migration = true;
}
function end_ajax( $return = false ) {
if( defined( 'DOING_WPSDB_TESTS' ) || $this->doing_cli_migration ) {
return ( false === $return ) ? NULL : $return;
}
echo ( false === $return ) ? '' : $return;
exit;
}
function check_ajax_referer( $action ) {
if ( defined( 'DOING_WPSDB_TESTS' ) || $this->doing_cli_migration ) return;
$result = check_ajax_referer( $action, 'nonce', false );
if ( false === $result ) {
$return = array( 'wpsdb_error' => 1, 'body' => sprintf( __( 'Invalid nonce for: %s', 'wp-sync-db' ), $action ) );
$this->end_ajax( json_encode( $return ) );
}
$cap = ( is_multisite() ) ? 'manage_network_options' : 'export';
$cap = apply_filters( 'wpsdb_ajax_cap', $cap );
if ( !current_user_can( $cap ) ) {
$return = array( 'wpsdb_error' => 1, 'body' => sprintf( __( 'Access denied for: %s', 'wp-sync-db' ), $action ) );
$this->end_ajax( json_encode( $return ) );
}
}
}