load_textdomain();
$this->wpo_update_api = apply_filters( 'wpovernight_api_url', 'https://wpovernight.com/license-api/' );
$this->plugin_item_name = $_item_name;
$this->plugin_file = $_file;
$this->plugin_basename = plugin_basename( $_file );
$this->plugin_slug = dirname( $this->plugin_basename );
$this->plugin_license_slug = $_license_slug;
$this->plugin_version = $_version;
$this->plugin_author = $_author;
$this->license_keys_option_name = 'wpocore_settings';
$this->license_key = $this->get_license_key();
if( ! class_exists( '\\WPO\\EDD_SL_Plugin_Updater' ) ) {
// load the EDD updater class
include( dirname( __FILE__ ) . '/EDD_SL_Plugin_Updater.php' );
}
add_filter( 'edd_sl_plugin_updater_api_params', array( $this, 'set_url_for_version_request' ), 10, 3 );
$this->load_edd_updater();
add_action( 'admin_init', array( $this, 'disable_subsite_update_notifications' ) );
add_action( 'wp_ajax_wpo_updater_licence_key_action_'.$this->plugin_license_slug, array( $this, 'ajax_remote_license_actions' ) );
add_filter( 'http_response', array( $this, 'unauthorized_response'), 10, 3 );
add_filter( 'network_admin_plugin_action_links_' . $this->plugin_basename, array( $this, 'add_license_activation_link' ), 10, 4 );
add_filter( 'plugin_action_links_' . $this->plugin_basename, array( $this, 'add_license_activation_link' ), 10, 4 );
add_action( 'after_plugin_row_' . $this->plugin_basename, array( $this, 'plugin_license_field' ), 10, 3 );
add_action( 'admin_enqueue_scripts', array( $this, 'scripts_styles' ) );
}
public function load_textdomain() {
load_plugin_textdomain( 'wpo-updater', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' );
}
public function scripts_styles( $hook ) {
if ( $hook === 'plugins.php' && ! wp_script_is( 'wpo-update-helper', 'enqueued' ) ) {
wp_enqueue_style(
'wpo-update-helper',
plugin_dir_url( __FILE__ ) . 'assets/style.css',
array(),
$this->version
);
wp_enqueue_script(
'wpo-update-helper',
plugin_dir_url( __FILE__ ) . 'assets/script.js',
array( 'jquery' ),
$this->version
);
wp_localize_script(
'wpo-update-helper',
'wpo_update_helper',
array(
'ajaxurl' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( 'wpo_update_helper' ),
)
);
}
}
public function add_license_activation_link( $actions, $plugin_file = '', $plugin_data = array(), $context = '' ) {
if ( $this->should_show_license_manager() ) {
$actions['wpo_license'] = sprintf(
'%3$s',
esc_attr( $this->plugin_license_slug ),
esc_attr( $this->plugin_slug ),
esc_html__( 'Manage license', 'wpo-updater' )
);
}
return $actions;
}
public function plugin_license_field( $file, $plugin, $status = '' ) {
if ( ! $this->should_show_license_manager() ) {
return;
}
?>
license_key ) ) {
$this->plugin_license_field_content();
} else {
?>
|
plugin_basename ) ) {
// multisite & network active: show only on network admin
$show = is_network_admin();
} else {
// single site OR multisite and not active on network: only show on the subsite
$show = ! is_network_admin();
}
return apply_filters( 'wpo_updater_show_license_manager', $show, $this->plugin_slug );
}
public function plugin_license_field_content( $action_args = array() ) {
$name = "wpocore_settings[{$this->plugin_license_slug}]";
if ( array_key_exists( 'license_key', $action_args ) ) {
$this->license_key = $action_args['license_key'];
}
if ( empty( $action_args ) ) {
if ( ! empty( $this->license_key ) ) {
$action_args = array(
'edd_action' => 'check_license',
'license_key' => trim( $this->license_key ),
);
} else {
$action_args = array();
}
}
$status = $this->remote_license_actions( $action_args );
if ( is_object( $status ) && isset( $status->license ) ) {
$activation_status = $status->license;
} elseif ( is_string( $status ) ) {
$activation_status = $status;
} else {
$activation_status = '';
}
if ( empty( $this->license_key ) ) {
$notice_class = 'notice-warning notice-alt';
} else {
$notice_class = 'notice-alt';
}
// allow setting license field to password
if ( apply_filters( 'wpo_update_helper_shield_license_field', false ) ) {
$license_field_type = 'password';
} else {
$license_field_type = 'text';
}
?>
license_key ) ): ?>
license_state_message ) ? esc_html( $status->license_state_message ) : ''; ?>
action_message ) ): ?>
action_message ); ?>
license_info ) ? wp_kses_post( $status->license_info ) : ''; ?>
license_key ) ) {
return false;
} else {
return true;
}
}
/**
* Load the EDD Updater class
*/
public function load_edd_updater() {
// setup the updater
if ( ! empty( $this->license_key ) ) {
$this->edd_updater = new \WPO\EDD_SL_Plugin_Updater( $this->wpo_update_api, $this->plugin_file, array(
'version' => $this->plugin_version, // current version number
'license' => $this->license_key, // license key (used get_option above to retrieve from DB)
'item_name' => $this->plugin_item_name, // name of this plugin
'author' => $this->plugin_author // author of this plugin
)
);
}
}
/**
* Don't show update notifications on subsites when plugin is network activated
*/
public function disable_subsite_update_notifications() {
if ( is_multisite() && ! is_network_admin() && is_plugin_active_for_network( $this->plugin_basename ) && ! empty( $this->edd_updater ) && method_exists( $this->edd_updater, 'show_update_notification' ) ) {
remove_action( 'after_plugin_row', array( $this->edd_updater, 'show_update_notification' ) );
}
}
public function ajax_remote_license_actions() {
check_ajax_referer( "wpo_update_helper", 'security' );
if ( empty( $_POST['remote_edd_action'] ) ) {
return;
}
if ($_POST['remote_edd_action'] == 'show_license') {
$args = array(
'edd_action' => 'check_license',
'license_key' => trim( $this->license_key ),
);
} else {
$args = array(
'edd_action' => $_POST['remote_edd_action'],
'license_key' => trim( $_POST['license_key'] ),
);
}
ob_start();
$this->plugin_license_field_content( $args );
$html = ob_get_clean();
wp_send_json( array('html' => $html ) );
}
/************************************
* Activate/deactivate license key
*************************************/
public function remote_license_actions( $args ) {
if ( empty( $args['edd_action'] ) ) {
return;
}
// retrieve the license from the database
$this->save_license_key( $args['license_key'] );
if ( empty( $args['license_key'] ) ) {
$response = array(
'action_message' => __( 'Please enter a license key.', 'wpo-updater' ),
'license_info' => '',
'license_state' => 'incomplete',
'license_state_message' => __( 'invalid', 'wpo-updater' ),
);
return (object) $response;
}
// data to send in our API request
$api_params = array(
'edd_action' => $args['edd_action'],
'license' => $args['license_key'],
'item_name' => urlencode( $this->plugin_item_name ), // the name of our product in EDD
'url' => $this->get_home_url(), // License server has a fallback to the User-Agent, but this could have been filtered so we can't rely on it
);
$response = $this->edd_api_action( $api_params );
if ( isset( $response->wp_error ) ) {
/* translators: 1. error message, 2. error code, 3. host IP */
$message = sprintf( __( 'API Error: %1$s (%2$s), IP: %3$s', 'wpo-updater' ), $response->wp_error, $response->error_code, $this->get_host_ip() );
$response->action_message = $message;
$response->license_state = 'incomplete';
$response->license_state_message = __( 'unknown', 'wpo-updater' );
$response->license_info = '-';
return $response;
}
if ( isset( $response->expires ) ) {
if ( $response->expires == 'lifetime' ) {
$exp_date = __( 'Forever', 'wpo-updater' );
} else {
$exp_date = date_i18n( get_option( 'date_format' ), strtotime( $response->expires ) );
}
}
switch ( $response->license ) {
case 'valid':
if ( $args['edd_action'] == 'activate_licese' ) {
$response->action_message = __( 'Activated your license for this site.', 'wpo-updater' );
}
$response->license_state = 'valid';
$response->license_state_message = __( 'valid', 'wpo-updater' );
/* translators: 1. expiration date, 2. active sites count, 3. license limit count */
$response->license_info = sprintf( __( 'This license is valid until: %1$s (Active sites: %2$s / %3$s)', 'wpo-updater' ), $exp_date, $response->site_count, $response->license_limit );
break;
case 'deactivated':
// get activation count & limit
$api_params = array(
'edd_action'=> 'check_license',
'license' => $args['license_key'],
'item_name' => urlencode( $this->plugin_item_name ), // the name of our product in EDD
);
$check_response = $this->edd_api_action( $api_params );
$exp_date = date_i18n( get_option( 'date_format' ), strtotime( $check_response->expires ) );
$license_limit = $check_response->license_limit;
$site_count = $check_response->site_count;
$response->action_message = __( 'Deactivated your license for this site.', 'wpo-updater' );
$response->license_state = 'invalid';
$response->license_state_message = __( 'deactivated', 'wpo-updater' );
$response->license_info = sprintf( __( 'This license is valid until: %1$s (Active sites: %2$s / %3$s)', 'wpo-updater' ), $exp_date, $site_count, $license_limit );
break;
case 'expired':
$response->license_state = 'invalid';
$response->license_state_message = __( 'expired', 'wpo-updater' );
$response->license_info = __( 'This license was valid until: ' . $exp_date, 'wpo-updater' );
break;
case 'inactive':
case 'site_inactive':
$response->license_state = 'valid';
$response->license_state_message = __( 'valid', 'wpo-updater' );
$response->license_info = sprintf( __( 'This license is valid until: %1$s (Active sites: %2$s / %3$s)', 'wpo-updater' ), $exp_date, $response->site_count, $response->license_limit );
break;
case 'failed':
$response->action_message = __( 'Deactivated your license for this site.', 'wpo-updater' );
$response->license_state = 'invalid';
$response->license_state_message = __( 'invalid', 'wpo-updater' );
$response->license_info = '';
break;
case 'invalid':
$error = ! empty( $response->error ) ? $response->error : '';
if ( $error == 'missing' ) {
$response->action_message = __( 'Your license key was incorrect.', 'wpo-updater' );
$response->license_state = 'incomplete';
$response->license_state_message = __( 'invalid', 'wpo-updater' );
$response->license_info = __( 'Please enter the correct license key.', 'wpo-updater' );
} elseif ( $error == 'expired' ) {
$response->action_message = __( 'Your license key is expired.', 'wpo-updater' );
$response->license_state = 'incomplete';
$response->license_state_message = __( 'expired', 'wpo-updater' );
/* translators: expiration date */
$response->license_info = sprintf( __( 'This license was valid until: %s', 'wpo-updater' ), $exp_date );
} elseif ($error == 'no_activations_left') {
/* translators: tags */
$response->action_message = sprintf( __( 'No Activations Left — Please visit %1$sMy Account%2$s to upgrade your license or deactivate a previous activation.', 'wpo-updater' ), '', '' );
$response->license_state = 'incomplete';
$response->license_state_message = __( 'invalid', 'wpo-updater' );
$response->license_info = '';
} else {
$response->action_message = __( 'Please enter the correct license key.', 'wpo-updater' );
$response->license_info = '';
$response->license_state = 'incomplete';
$response->license_state_message = __( 'invalid', 'wpo-updater' );
}
break;
default:
break;
}
return $response;
}
public function edd_api_action( $api_params ) {
// Call the WPO API.
$response = wp_remote_get( esc_url_raw( add_query_arg( $api_params, $this->wpo_update_api ) ), array( 'timeout' => 15, 'sslverify' => true ) );
// make sure the response came back okay
if ( is_wp_error( $response ) ) {
$error_response = new stdClass();
$error_response->wp_error = $response->get_error_message();
$error_response->error_code = $response->get_error_code();
return $error_response;
}
if ( wp_remote_retrieve_response_code( $response ) !== 200 ) {
$error_response = new stdClass();
$error_body = wp_remote_retrieve_body( $response );
if ( strpos( $error_body, 'Wordfence' ) !== false ) {
$error_response->wp_error = __( 'Your site host is blocked by the Wordfence network, please contact support@wpovernight.com with this error message.', 'wpo-updater' );
} else {
$error_response->wp_error = esc_html( sanitize_text_field( strip_tags( $error_body ) ) );
}
$error_response->error_code = wp_remote_retrieve_response_code( $response );
return $error_response;
}
// decode the license data
$response = json_decode( wp_remote_retrieve_body( $response ) );
return $response;
}
public function unauthorized_response( $response, $args, $url ) {
if ( ! is_wp_error( $response ) && is_array( $response ) && isset( $response['response'] ) && is_array( $response['response'] ) ) {
if ( isset( $response['response']['code'] ) && $response['response']['code'] == 401 ) {
// we have a 401 response, check if it's ours
$license_server = 'https://wpovernight.com';
if ( strpos( $url, $license_server ) !== false && strpos( $url, 'package_download' ) !== false ) {
// this is our request
// extract values from token
$url_parts = parse_url( $url );
$paths = array_values( explode( '/', $url_parts['path'] ) );
$token = end( $paths );
$values = explode( ':', base64_decode( $token ) );
if ( count( $values ) !== 6 ) {
$response['response']['message'] = __( 'Invalid token supplied', 'wpo-updater' );
return $response;
}
$expires = $values[0];
$license_key = $values[1];
$download_id = (int) $values[2];
$url = str_replace( '@', ':', $values[4] );
$download_beta = (bool) $values[5];
// Check_license response with the above vars
// data to send in our API request
$api_params = array(
'edd_action' => 'check_license',
'url' => $url,
'license' => $license_key,
'item_id' => $download_id,
);
if ( $check_response = $this->edd_api_action( $api_params ) ) {
if ( isset( $check_response->license ) ) {
switch( $check_response->license ) {
case 'expired':
$message = __( 'Your license has expired, please renew it to install this update.', 'wpo-updater' );
break;
case 'inactive':
case 'site_inactive':
/* translators: site URL */
$message = sprintf( __( 'Your license has not been activated for this site (%s), please activate it first.', 'wpo-updater' ), str_replace( array('http://','https://'), '', $url ) );
break;
case 'disabled':
$message = __( 'Your license has been disabled.', 'wpo-updater' );
break;
case 'valid':
$message = "";
break;
default:
$message = __( 'Your license could not be validated.', 'wpo-updater' );
break;
}
} elseif ( isset( $check_response->wp_error ) ) {
$message = sprintf( __( 'API Error: %1$s (%2$s), IP: %3$s', 'wpo-updater' ), $check_response->wp_error, $check_response->error_code, $this->get_host_ip() );
}
} else {
$message = __( 'License key expired or not activated for URL', 'wpo-updater' );
}
$response['response']['message'] = esc_html( $message );
return $response;
}
}
}
return $response;
}
public function get_host_ip() {
$response = wp_remote_get( 'https://icanhazip.com', array( 'timeout' => 15, 'sslverify' => true ) );
if ( is_wp_error( $response ) || wp_remote_retrieve_response_code( $response ) !== 200 ) {
$ip = __( 'unknown', 'wpo-updater' );
} else {
$ip = wp_remote_retrieve_body( $response );
// get v4 if we only have v6
if ( strpos( $ip, ':' ) !== false ) {
$response = wp_remote_get( 'https://ipv4.icanhazip.com', array( 'timeout' => 15, 'sslverify' => true ) );
if ( !is_wp_error( $response ) && wp_remote_retrieve_response_code( $response ) == 200 ) {
$ipv4 = wp_remote_retrieve_body( $response );
$ip = "{$ip} / {$ipv4}";
}
}
}
return $ip;
}
/**
* Sets the URL parameter sent in the API request that gets the current version information,
* so that it matches what we pass during activation
*
* @since 2.1.2
* @param array $api_params The array of data sent in the request.
* @param array $api_data The array of data set up in the class constructor.
* @param string $plugin_file The full path and filename of the file.
*
* @return array $api_params
*/
public function set_url_for_version_request( $api_params, $api_data, $plugin_file ) {
if ( $plugin_file === $this->plugin_file ) {
$api_params['url'] = $this->get_home_url();
}
return $api_params;
}
/**
* Gets the "Site Address (URL)", using the default language in case WPML is installed
*
* @since 2.1.2
* @return string
*/
public function get_home_url() {
global $sitepress;
if ( is_callable( array( $sitepress, 'language_url' ) ) && is_callable( array( $sitepress, 'get_default_language' ) ) ) {
// this is the same function that is used when using the wpml_home_url filter,
// except that filter always passes $sitepress->get_current_language()
$home_url = $sitepress->language_url( $sitepress->get_default_language() );
} else {
$home_url = home_url();
}
return $home_url;
}
/**
* Get the license key
*
* @since 2.1.3
* @return string
*/
public function get_license_key() {
if ( ! function_exists( 'is_plugin_active_for_network' ) ) {
include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
}
if ( is_multisite() && is_plugin_active_for_network( $this->plugin_basename ) ) {
$wpo_license_keys = get_blog_option( get_main_site_id(), $this->license_keys_option_name, array() );
} elseif ( is_multisite() && ! is_plugin_active_for_network( $this->plugin_basename ) ) {
$wpo_license_keys = get_blog_option( get_current_blog_id(), $this->license_keys_option_name, array() );
} else {
$wpo_license_keys = get_option( $this->license_keys_option_name, array() );
}
$license_key = isset( $wpo_license_keys[$this->plugin_license_slug] ) ? $wpo_license_keys[$this->plugin_license_slug] : '';
return $license_key;
}
/**
* Save the license key
*
* @since 2.1.3
* @param string $license_key The plugin license key.
* @return void
*/
public function save_license_key( $license_key ) {
if ( ! function_exists( 'is_plugin_active_for_network' ) ) {
include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
}
if ( is_multisite() && is_plugin_active_for_network( $this->plugin_basename ) ) {
$wpo_license_keys = get_blog_option( get_main_site_id(), $this->license_keys_option_name, array() );
$wpo_license_keys[$this->plugin_license_slug] = $license_key;
update_blog_option( get_main_site_id(), $this->license_keys_option_name, $wpo_license_keys );
} elseif ( is_multisite() && ! is_plugin_active_for_network( $this->plugin_basename ) ) {
$wpo_license_keys = get_blog_option( get_current_blog_id(), $this->license_keys_option_name, array() );
$wpo_license_keys[$this->plugin_license_slug] = $license_key;
update_blog_option( get_current_blog_id(), $this->license_keys_option_name, $wpo_license_keys );
} else {
$wpo_license_keys = get_option( $this->license_keys_option_name, array() );
$wpo_license_keys[$this->plugin_license_slug] = $license_key;
update_option( $this->license_keys_option_name, $wpo_license_keys );
}
}
}