Commit inicial - WordPress Análisis de Precios Unitarios

- WordPress core y plugins
- Tema Twenty Twenty-Four configurado
- Plugin allow-unfiltered-html.php simplificado
- .gitignore configurado para excluir wp-config.php y uploads

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2025-11-03 21:04:30 -06:00
commit a22573bf0b
24068 changed files with 4993111 additions and 0 deletions

View File

@@ -0,0 +1 @@
<?php // Silence is golden.

View File

@@ -0,0 +1,263 @@
<?php
/*
Set up admin interface elements.
Written by Chris Jean for iThemes.com
Version 1.3.0
Version History
1.0.0 - 2013-09-19 - Chris Jean
Split off from the old Ithemes_Updater_Init class.
1.1.0 - 2013-10-02 - Chris Jean
Added support for themes through the filter_plugins_api function (since themes don't have a "View version *** details" feature.
1.2.0 - 2013-10-23 - Chris Jean
Changed how the licensing page is registered for multisite. It now will only load on multisite sites if the user is a super user (network admin).
Removed the code that handled the setting to show or hide the licensing page on multisite sites.
1.2.1 - 2013-10-25 - Chris Jean
Added "License" links to Network Admin Plugins and Themes pages.
1.2.2 - 2014-10-23 - Chris Jean
Updated code formating to WordPress coding standards.
1.3.0 - 2020-03-24 - Timothy Jacobs
Added support for limiting packages to render UI for.
*/
class Ithemes_Updater_Admin {
private $page_name = 'ithemes-licensing';
private $package_details = false;
private $registration_link = false;
private $page_ref;
public function __construct() {
require_once( $GLOBALS['ithemes_updater_path'] . '/settings.php' );
require_once( $GLOBALS['ithemes_updater_path'] . '/packages.php' );
$show_ui = count( Ithemes_Updater_Packages::get_packages_to_include_in_ui() ) > 0;
if ( $show_ui && ( ! is_multisite() || is_super_admin() ) ) {
add_action( 'admin_menu', array( $this, 'add_admin_pages' ) );
}
if ( $show_ui ) {
add_action( 'network_admin_menu', array( $this, 'add_network_admin_pages' ) );
}
if ( $show_ui ) {
add_action( 'admin_head-plugins.php', array( $this, 'show_activation_message' ) );
add_action( 'admin_head-themes.php', array( $this, 'show_activation_message' ) );
add_action( 'deactivated_plugin', array( $this, 'clear_activation_package' ) );
}
add_filter( 'upgrader_pre_install', array( $this, 'filter_upgrader_pre_install' ) );
add_filter( 'upgrader_post_install', array( $this, 'filter_upgrader_post_install' ), 10, 3 );
add_filter( 'plugins_api', array( $this, 'filter_plugins_api' ), 10, 3 );
if ( $show_ui && ( ! is_multisite() || is_super_admin() ) ) {
add_filter( 'plugin_action_links', array( $this, 'filter_plugin_action_links' ), 10, 4 );
add_filter( 'theme_action_links', array( $this, 'filter_theme_action_links' ), 10, 2 );
}
if ( $show_ui ) {
add_filter( 'network_admin_plugin_action_links', array( $this, 'filter_plugin_action_links' ), 10, 4 );
add_filter( 'network_admin_theme_action_links', array( $this, 'filter_theme_action_links' ), 10, 2 );
}
}
public function filter_plugins_api( $value, $action, $args ) {
$options = $GLOBALS['ithemes-updater-settings']->get_options();
if ( ! isset( $args->slug ) ) {
return $value;
}
foreach ( (array) $options['update_plugins'] as $path => $data ) {
if ( $data->slug == $args->slug ) {
require_once( $GLOBALS['ithemes_updater_path'] . '/information.php' );
return Ithemes_Updater_Information::get_plugin_information( $path );
}
}
foreach ( (array) $options['update_themes'] as $path => $data ) {
if ( $path == $args->slug ) {
require_once( $GLOBALS['ithemes_updater_path'] . '/information.php' );
return Ithemes_Updater_Information::get_theme_information( $path );
}
}
$dir = WP_PLUGIN_DIR . '/' . $args->slug;
$dh = @opendir( $dir );
if ( ! $dh ) {
return $value;
}
while ( false !== ( $file = readdir( $dh ) ) ) {
if ( ! is_file( "$dir/$file" ) ) {
continue;
}
if ( '.php' !== substr( $file, -4 ) ) {
continue;
}
$plugin_data = get_plugin_data( "$dir/$file", false, false );
if ( ! empty ( $plugin_data['Name'] ) ) {
$plugin_file = basename( $file );
}
}
closedir( $dh );
if ( empty( $plugin_file ) ) {
return $value;
}
require_once( $GLOBALS['ithemes_updater_path'] . '/information.php' );
$information = Ithemes_Updater_Information::get_plugin_information( "{$args->slug}/$plugin_file" );
if ( false !== $information ) {
return $information;
}
return $value;
}
public function filter_upgrader_pre_install( $value ) {
$this->set_package_details();
return $value;
}
public function filter_upgrader_post_install( $value, $hook_extra, $result ) {
$options = $GLOBALS['ithemes-updater-settings']->queue_flush();
return $value;
}
public function clear_activation_package( $deactivated_path ) {
$packages = $GLOBALS['ithemes-updater-settings']->get_packages();
$options = $GLOBALS['ithemes-updater-settings']->get_options();
$deactivated_path = WP_PLUGIN_DIR . "/$deactivated_path";
foreach ( $packages as $package => $paths ) {
if ( ! in_array( $deactivated_path, $paths ) || ( count( $paths ) > 1 ) ) {
continue;
}
$index = array_search( $package, $options['packages'] );
if ( false === $index ) {
return;
}
unset( $options['packages'][$index] );
$GLOBALS['ithemes-updater-settings']->update_options( $options );
return;
}
}
public function show_activation_message() {
$new_packages = $GLOBALS['ithemes-updater-settings']->get_new_packages();
$new_packages = array_filter( $new_packages, 'Ithemes_Updater_Packages::show_ui_for_package' );
if ( empty( $new_packages ) ) {
return;
}
natcasesort( $new_packages );
require_once( $GLOBALS['ithemes_updater_path'] . '/functions.php' );
$names = array();
foreach ( $new_packages as $package ) {
$names = Ithemes_Updater_Functions::get_package_name( $package );
}
if ( is_multisite() && is_network_admin() ) {
$url = network_admin_url( 'settings.php' ) . "?page={$this->page_name}";
} else {
$url = admin_url( 'options-general.php' ) . "?page={$this->page_name}";
}
echo '<div class="updated fade"><p>' . wp_sprintf( __( 'To receive automatic updates for %l, use the <a href="%s">iThemes Licensing</a> page found in the Settings menu.', 'it-l10n-restrict-content-pro' ), $names, $url ) . '</p></div>';
$GLOBALS['ithemes-updater-settings']->update_packages();
}
public function add_admin_pages() {
$this->page_ref = add_options_page( __( 'iThemes Licensing', 'it-l10n-restrict-content-pro' ), __( 'iThemes Licensing', 'it-l10n-restrict-content-pro' ), 'manage_options', $this->page_name, array( $this, 'settings_index' ) );
add_action( "load-{$this->page_ref}", array( $this, 'load_settings_page' ) );
}
public function add_network_admin_pages() {
$this->page_ref = add_submenu_page( 'settings.php', __( 'iThemes Licensing', 'it-l10n-restrict-content-pro' ), __( 'iThemes Licensing', 'it-l10n-restrict-content-pro' ), 'manage_options', $this->page_name, array( $this, 'settings_index' ) );
add_action( "load-{$this->page_ref}", array( $this, 'load_settings_page' ) );
}
public function load_settings_page() {
require( $GLOBALS['ithemes_updater_path'] . '/settings-page.php' );
}
public function settings_index() {
do_action( 'ithemes_updater_settings_page_index' );
}
private function set_package_details() {
if ( false !== $this->package_details ) {
return;
}
require_once( $GLOBALS['ithemes_updater_path'] . '/packages.php' );
$this->package_details = Ithemes_Updater_Packages::get_local_details();
}
private function set_registration_link() {
if ( false !== $this->registration_link ) {
return;
}
$url = admin_url( 'options-general.php' ) . "?page={$this->page_name}";
$this->registration_link = sprintf( '<a href="%1$s" title="%2$s">%3$s</a>', $url, __( 'Manage iThemes product licenses to receive automatic upgrade support', 'it-l10n-restrict-content-pro' ), __( 'License', 'it-l10n-restrict-content-pro' ) );
}
public function filter_plugin_action_links( $actions, $plugin_file, $plugin_data, $context ) {
$this->set_package_details();
$this->set_registration_link();
if ( isset( $this->package_details[ $plugin_file ] ) && is_array( $actions ) && Ithemes_Updater_Packages::show_ui_for_package( $this->package_details[ $plugin_file ]['package'] ) ) {
$actions[] = $this->registration_link;
}
return $actions;
}
public function filter_theme_action_links( $actions, $theme ) {
$this->set_package_details();
$this->set_registration_link();
if ( is_object( $theme ) ) {
$path = basename( $theme->get_stylesheet_directory() ) . '/style.css';
} else if ( is_array( $theme ) && isset( $theme['Stylesheet Dir'] ) ) {
$path = $theme['Stylesheet Dir'] . '/style.css';
} else {
$path = '';
}
if ( isset( $this->package_details[$path] ) && is_array( $actions ) && Ithemes_Updater_Packages::show_ui_for_package( $this->package_details[ $path ]['package'] ) ) {
$actions[] = $this->registration_link;
}
return $actions;
}
}
new Ithemes_Updater_Admin();

View File

@@ -0,0 +1,351 @@
<?php
/*
Provides an easy to use interface for communicating with the iThemes updater server.
Written by Chris Jean for iThemes.com
Version 1.1.1
Version History
1.0.0 - 2013-04-11 - Chris Jean
Release ready
1.0.1 - 2013-09-19 - Chris Jean
Updated requires to not use dirname().
Updated ithemes-updater-object to ithemes-updater-settings.
1.1.0 - 2013-10-02 - Chris Jean
Added get_package_changelog().
1.1.1 - 2014-11-13 - Chris Jean
Improved caching.
Updated code to meet WordPress coding standards.
*/
class Ithemes_Updater_API {
public static function activate_package( $username, $password, $packages ) {
return self::get_response( 'activate_package', compact( 'username', 'password', 'packages' ), false );
}
public static function deactivate_package( $username, $password, $packages ) {
return self::get_response( 'deactivate_package', compact( 'username', 'password', 'packages' ), false );
}
public static function get_licensed_site_url() {
$packages = array();
return self::get_response( 'get_licensed_site_url', compact( 'packages' ), false );
}
public static function set_licensed_site_url( $username, $password, $site_url ) {
$packages = array();
return self::get_response( 'set_licensed_site_url', compact( 'username', 'password', 'site_url', 'packages' ), false );
}
public static function get_package_details( $cache = true ) {
$packages = array();
return self::get_response( 'get_package_details', compact( 'packages' ), $cache );
}
public static function get_package_changelog( $package, $cur_version = false ) {
$response = wp_remote_get( 'https://api.ithemes.com/product/changelog?package=' . urlencode( $package ) );
if ( is_wp_error( $response ) && ( 'connect() timed out!' != $response->get_error_message() ) && defined( 'ITHEMES_ALLOW_HTTP_FALLBACK' ) && ITHEMES_ALLOW_HTTP_FALLBACK ) {
$response = wp_remote_get( 'http://api.ithemes.com/product/changelog?package=' . urlencode( $package ) );
}
if ( is_wp_error( $response ) ) {
return $response;
}
if ( ! isset( $response['body'] ) ) {
return new WP_Error( 'ithemes-updater-changelog-bad-wp-remote-get-response', __( 'Unrecognized response from <code>wp_remote_get</code>.', 'it-l10n-restrict-content-pro' ) );
}
if ( isset( $response['response']['code'] ) && ( '200' != $response['response']['code'] ) ) {
return new WP_Error( 'ithemes-updater-wp-remote-get-error-' . $response['response']['code'], $response['response']['message'] );
}
$body = $response['body'];
if ( '{' === substr( $body, 0, 1 ) ) {
$error = json_decode( $body, true );
if ( is_array( $error ) && isset( $error['error'] ) && is_array( $error['error'] ) && isset( $error['error']['type'] ) && isset( $error['error']['message'] ) ) {
return new WP_Error( 'ithemes-updater-json-decode-error-' . $error['error']['type'], $error['error']['message'] );
} else {
return new WP_Error( 'ithemes-updater-changelog-bad-json-decode-result', __( 'Unrecognized response from iThemes API server.', 'it-l10n-restrict-content-pro' ) );
}
}
$versions = array();
$version = false;
$depth = 0;
$lines = preg_split( '/[\n\r]+/', $body );
foreach ( $lines as $line ) {
if ( preg_match( '/^\d/', $line ) ) {
if ( ! empty( $version ) && ( $depth > 0 ) ) {
while ( $depth-- > 0 ) {
$versions[$version] .= "</ul>\n";
}
}
$depth = 0;
$parts = preg_split( '/\s+-\s+/', $line );
$version = $parts[0];
if ( version_compare( $version, $cur_version, '<=' ) ) {
$version = '';
continue;
}
$versions[$version] = '';
continue;
} else if ( preg_match( '/^\S/', $line ) ) {
$version = '';
continue;
} else if ( empty( $version ) ) {
continue;
}
$line = str_replace( ' ', "\t", $line );
$line = str_replace( "\t", '', $line, $count );
$line = preg_replace( '/^\s+/', '', $line );
if ( empty( $line ) ) {
continue;
}
$details = '';
if ( $count > $depth ) {
$details .= "<ul>\n";
$depth++;
} else if ( $count < $depth ) {
$details .= "</ul>\n";
$depth--;
}
$details .= "<li>$line</li>\n";
$versions[$version] .= $details;
}
if ( ! empty( $version ) && ( $depth > 0 ) ) {
while ( $depth-- > 0 ) {
$versions[$version] .= "</ul>\n";
}
}
uksort( $versions, 'version_compare' );
$versions = array_reverse( $versions );
$changelog = '';
foreach ( $versions as $version => $details ) {
$changelog .= "<h4>$version</h4>\n$details\n";
}
$changelog = preg_replace( '/\s+$/', '', $changelog );
return $changelog;
}
public static function get_response( $action, $args, $cache ) {
require_once( $GLOBALS['ithemes_updater_path'] . '/server.php' );
require_once( $GLOBALS['ithemes_updater_path'] . '/updates.php' );
if ( isset( $args['packages'] ) ) {
$args['packages'] = self::get_request_package_details( $args['packages'] );
}
$response = false;
$source = '';
$cached = true;
$md5 = substr( md5( serialize( $args ) ), 0, 5 );
$time = time();
$cache_var = "it-updater-$action-$md5";
if ( $cache ) {
if ( isset( $GLOBALS[$cache_var] ) ) {
$response = $GLOBALS[$cache_var];
$source = 'GLOBALS';
} else if ( false !== ( $transient = get_site_transient( $cache_var ) ) ) {
$response = $transient;
$source = 'transient';
}
}
if ( false === $response ) {
$response = call_user_func_array( array( 'Ithemes_Updater_Server', $action ), $args );
$source = 'server';
if ( is_wp_error( $response ) ) {
return $response;
}
$cache_length = 86400 * $GLOBALS['ithemes-updater-settings']->get_option( 'timeout-multiplier' );
set_site_transient( $cache_var, $response, $cache_length );
$cached = false;
}
Ithemes_Updater_Updates::process_server_response( $response, $cached );
$GLOBALS[$cache_var] = $response;
return $response;
}
private static function get_request_package_details( $desired_packages = array() ) {
require_once( $GLOBALS['ithemes_updater_path'] . '/packages.php' );
require_once( $GLOBALS['ithemes_updater_path'] . '/keys.php' );
$all_packages = Ithemes_Updater_Packages::get_local_details();
reset( $desired_packages );
if ( empty( $desired_packages ) ) {
$desired_packages = $all_packages;
} else if ( is_numeric( key( $desired_packages ) ) ) {
$new_desired_packages = array();
foreach ( $all_packages as $path => $details ) {
foreach ( $desired_packages as $package ) {
if ( $package != $details['package'] ) {
continue;
}
$new_desired_packages[$path] = $details;
break;
}
}
$desired_packages = $new_desired_packages;
}
$packages = array();
$keys = Ithemes_Updater_Keys::get();
$package_slugs = array();
foreach ( $desired_packages as $data ) {
$package_slugs[] = $data['package'];
}
$legacy_keys = Ithemes_Updater_Keys::get_legacy( $package_slugs );
$active_themes = array(
'stylesheet' => get_stylesheet_directory(),
'template' => get_template_directory(),
);
$active_themes = array_unique( $active_themes );
foreach ( $active_themes as $index => $path ) {
$active_themes[$index] = basename( $path );
}
foreach ( $desired_packages as $path => $data ) {
$key = ( isset( $keys[$data['package']] ) ) ? $keys[$data['package']] : '';
$package = array(
'ver' => $data['installed'],
'key' => $key,
);
if ( ! empty( $legacy_keys[$data['package']] ) ) {
$package['old-key'] = $legacy_keys[$data['package']];
}
if ( 'plugins' == $data['type'] ) {
$package['active'] = (int) is_plugin_active( $path );
} else {
$dir = dirname( $path );
$package['active'] = (int) in_array( $dir, $active_themes );
if ( $package['active'] && ( count( $active_themes ) > 1 ) ) {
if ( $dir == $active_themes['stylesheet'] ) {
$package['child-theme'] = 1;
} else {
$package['parent-theme'] = 1;
}
}
}
$package_key = $data['package'];
$counter = 0;
while ( isset( $packages[$package_key] ) ) {
$package_key = "{$data['package']} ||| " . ++$counter;
}
$packages[$package_key] = $package;
}
if ( ! empty( $legacy_keys ) ) {
Ithemes_Updater_Keys::delete_legacy( array_keys( $legacy_keys ) );
}
return $packages;
}
public static function get_error_explanation( $error, $package = '' ) {
$code = $error->get_error_code();
$package_name = Ithemes_Updater_Functions::get_package_name( $package );
$message = '';
switch( $code ) {
case 'ITXAPI_Updater_Bad_Login':
$message = __( 'Incorrect password. Please make sure that you are supplying your iThemes membership username and password details.', 'it-l10n-restrict-content-pro' );
break;
case 'ITXAPI_Updater_Username_Unknown':
case 'ITXAPI_Updater_Username_Invalid':
$message = __( 'Invalid username. Please make sure that you are supplying your iThemes membership username and password details.', 'it-l10n-restrict-content-pro' );
break;
case 'ITXAPI_Product_Package_Unknown':
$message = sprintf( __( 'The licensing server reports that the %1$s (%2$s) product is unknown. Please contact support for assistance.', 'it-l10n-restrict-content-pro' ), $package_name, $package );
break;
case 'ITXAPI_Updater_Too_Many_Sites':
$message = sprintf( __( '%1$s could not be licensed since the membership account is out of available licenses for this product. You can unlicense the product on other sites or upgrade your membership to one with a higher number of licenses in order to increase the amount of available licenses.', 'it-l10n-restrict-content-pro' ), $package_name );
break;
case 'ITXAPI_License_Key_Generate_Failed':
$message = sprintf( __( '%s could not be licensed due to an internal error. Please try to license %s again at a later time. If this problem continues, please contact iThemes support.', 'it-l10n-restrict-content-pro' ), $package_name );
break;
}
if ( empty( $message ) ) {
if ( ! empty( $package ) )
$message = sprintf( __( 'An unknown error relating to the %1$s product occurred. Please contact iThemes support. Error details: %2$s', 'it-l10n-restrict-content-pro' ), $package_name, $error->get_error_message() . " ($code)" );
else
$message = sprintf( __( 'An unknown error occurred. Please contact iThemes support. Error details: %s', 'it-l10n-restrict-content-pro' ), $error->get_error_message() . " ($code)" );
}
return $message;
}
}

View File

@@ -0,0 +1,40 @@
# iThemes Updater API #
This document lists the different API features of the iThemes Updater system.
Note: This document is in [GitHub Flavored Markdown](https://help.github.com/articles/github-flavored-markdown) format.
## Defines ##
The entire updater system can be disabled by creating a define named ITHEMES_UPDATER_DISABLE with a truthy value. For example, the following could be added to the wp-config.php file to disable the updater system:
define( 'ITHEMES_UPDATER_DISABLE', true );
## Query Strings ##
The updater system has built in refresh intervals:
* One minute - When on the Dashboard > Updates or Settings > iThemes Licensing pages, the data will refresh in one minute intervals. This means that once the data is a minute or older, it will be refreshed.
* One hour - When on the Plugins > Installed Plugins or Appearance > Themes pages, the data will refresh in one hour intervals.
* Twelve hours - On all other pages the data will refresh in twelve hour intervals.
Note that data is only refreshed when in the WordPress Dashboard (wp-admin). This prevents adding additional load time when people are browsing the site.
You can force a manual refresh of the data by modifying the URL of the page to include a non-empty query variable named ithemes-updater-force-refresh. This can be helpful if you think that the updater is having a problem and isn't properly refreshing itself.
For example, if you are on an admin page with a URL of http://example.com/wp-admin/plugins.php, you can force a refresh by changing the URL to the following:
http://example.com/wp-admin/plugins.php?ithemes-updater-force-refresh=1
Note that forcing a refresh only works on the WordPress Dashboard and not on the site front-end. In addition, only users with the manage_options capability have the ability to force a refresh. By default, the only users with this capability are the ones in the Administrator role. These restrictions are to help prevent a non-authorized user from consuming server resources by forcing numerous refreshes.
Some of our releases have versions with four digits, such as 3.1.1.1. Releases with a four-digit version are quick releases and are meant for rapid bug fix releases (typically in response to a specific support request). If the version on the site is only different by this last digit in a four-digit version (such as currently running 3.1.1.1 when 3.1.1.4 is available), then the updater will not show an update as available. You can force the updater to make such releases available by modifying an admin page URL to include a non-empty query variable named ithemes-updater-force-minor-update.
For example, if you are on an admin page with a URL of http://example.com/wp-admin/plugins.php, you can force quick bug fix releases to be avaiable by changing the URL to the following:
http://example.com/wp-admin/plugins.php?ithemes-updater-force-minor-update=1
Note: The updater now supports a query variable named ithemes-updater-force-quick-release-update. It has the same functionality as ithemes-updater-force-minor-update.

View File

@@ -0,0 +1 @@
<?php // Silence is golden.

View File

@@ -0,0 +1,58 @@
##
## CA Root Certificate for api.ithemes.com and s3.amazonaws.com
##
## Certificate data from Mozilla as of: Sat Dec 29 20:03:40 2012
##
# @(#) $RCSfile: certdata.txt,v $ $Revision: 1.87 $ $Date: 2012/12/29 16:32:45 $
Go Daddy Class 2 CA
===================
-----BEGIN CERTIFICATE-----
MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMY
VGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRp
ZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkG
A1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g
RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQAD
ggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv
2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32
qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6j
YGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmY
vLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0O
BBYEFNLEsNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2o
atTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMu
MTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwG
A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wim
PQoZ+YeAEW5p5JYXMP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKt
I3lpjbi2Tc7PTMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mERdEr/VxqHD3VI
Ls9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/b
vZ8=
-----END CERTIFICATE-----
VeriSign Class 3 Public Primary Certification Authority - G5
============================================================
-----BEGIN CERTIFICATE-----
MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE
BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO
ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk
IHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRp
ZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCB
yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2ln
biBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBh
dXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmlt
YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
ggEKAoIBAQCvJAgIKXo1nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKz
j/i5Vbext0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIzSdhD
Y2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQGBO+QueQA5N06tRn/
Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+rCpSx4/VBEnkjWNHiDxpg8v+R70r
fk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/
BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2Uv
Z2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy
aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKvMzEzMA0GCSqG
SIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzEp6B4Eq1iDkVwZMXnl2YtmAl+
X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKE
KQsTb47bDN0lAtukixlE0kF6BWlKWE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiC
Km0oHw0LxOXnGiYZ4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vE
ZV8NhnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq
-----END CERTIFICATE-----

View File

@@ -0,0 +1,143 @@
<?php
//-----------------------------------------------------------------------------
class iThemes_Credentials
{
//-----------------------------------------------------------------------------
protected $hash = 'sha256';
protected $salt_padding = 'wdHVwU&HcYcWnllo%kTUUnxpScy4%ICM29';
protected $iteration_count = 131072;
protected $key_length = 64;
protected $password;
//-----------------------------------------------------------------------------
public function __construct($username, $password, $options = array())
{
$this->username = $username;
$this->password = $password;
if(!empty($options['hash']))
$this->hash = strtolower(trim($options['hash']));
if(!empty($options['iterations']))
$this->iteration_count = intval($options['iterations']);
if(!empty($options['salt']))
$this->salt_padding = $options['salt'];
if(!empty($options['key_length']))
$this->key_length = intval($options['key_length']);
}
//-----------------------------------------------------------------------------
public static function get_password_hash($username, $password, $options = array())
{
$hasher = new iThemes_Credentials($username, $password, $options);
return $hasher->get_pbkdf2();
}
//-----------------------------------------------------------------------------
public function get_salt()
{
return strtolower(trim($this->username)) . $this->salt_padding;
}
//-----------------------------------------------------------------------------
public function get_pbkdf2()
{
return $this->pbkdf2($this->hash,
$this->password,
$this->get_salt(),
$this->iteration_count,
$this->key_length / 2,
false);
}
//-----------------------------------------------------------------------------
/*
* PBKDF2 key derivation function as defined by RSA's PKCS #5: https://www.ietf.org/rfc/rfc2898.txt
* $algorithm - The hash algorithm to use. Recommended: SHA256
* $password - The password.
* $salt - A salt that is unique to the password.
* $count - Iteration count. Higher is better, but slower. Recommended: At least 1000.
* $key_length - The length of the derived key in bytes.
* $raw_output - If true, the key is returned in raw binary format. Hex encoded otherwise.
* Returns: A $key_length-byte key derived from the password and salt.
*
* Test vectors can be found here: https://www.ietf.org/rfc/rfc6070.txt
*
* This implementation of PBKDF2 was originally created by https://defuse.ca
* With improvements by http://www.variations-of-shadow.com
*/
private function pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output = false)
{
$algorithm = strtolower($algorithm);
if(!in_array($algorithm, hash_algos(), true))
trigger_error('PBKDF2 ERROR: Invalid hash algorithm.', E_USER_ERROR);
if($count <= 0 || $key_length <= 0)
trigger_error('PBKDF2 ERROR: Invalid parameters.', E_USER_ERROR);
$hash_length = strlen(hash($algorithm, '', true));
$block_count = ceil($key_length / $hash_length);
$output = '';
for($i = 1; $i <= $block_count; $i++)
{
// $i encoded as 4 bytes, big endian.
$last = $salt . pack("N", $i);
// first iteration
$last = $xorsum = hash_hmac($algorithm, $last, $password, true);
// perform the other $count - 1 iterations
for ($j = 1; $j < $count; $j++)
{
$xorsum ^= ($last = hash_hmac($algorithm, $last, $password, true));
}
$output .= $xorsum;
}
if($raw_output)
return substr($output, 0, $key_length);
else
return bin2hex(substr($output, 0, $key_length));
}
//-----------------------------------------------------------------------------
}
//-----------------------------------------------------------------------------

View File

@@ -0,0 +1 @@
<?php // Silence is golden.

View File

@@ -0,0 +1,200 @@
#icon-options-general,
#icon-settings {
background: url( '../images/logo-ithemes.png' ) no-repeat;
}
#ithemes-updater-licensed .subtitle {
background: url( '../images/icon-licensed.png' ) no-repeat;
}
#ithemes-updater-unlicensed .subtitle {
background: url( '../images/icon-unlicensed.png' ) no-repeat;
}
#ithemes-updater-unrecognized .subtitle {
background: url( '../images/icon-unrecognized.png' ) no-repeat;
}
#ithemes-updater-settings .subtitle {
background: url( '../images/icon-settings.png' ) no-repeat;
}
.wrap h2 + .error,
.wrap h2 + .updated {
margin-top: 2em;
}
.wrap .subtitle {
font-size: 23px;
line-height: 30px;
margin: 1.5em 0 .5em;
padding: 0 0 0 35px;
}
.wrap .widefat.ithemes-updater-listing th,
.wrap .widefat.ithemes-updater-listing td {
padding: 0;
vertical-align: middle;
}
.wrap .widefat.ithemes-updater-listing tfoot td {
padding: 13px 10px;
}
.ithemes-updater-listing label {
display: block;
padding: 10px;
}
.widefat.ithemes-updater-listing th.check-column {
}
.widefat.ithemes-updater-listing th.check-column input {
margin: 0;
}
.wrap #ithemes-updater-unrecognized .widefat.ithemes-updater-listing th,
.wrap #ithemes-updater-unrecognized .widefat.ithemes-updater-listing td {
padding: 10px;
}
.widefat.ithemes-updater-listing tr.expiring {
background-color: #FFFFE0;
}
.widefat.ithemes-updater-listing tr.expiring.alt {
background-color: #F5F5D2;
}
.widefat.ithemes-updater-listing tr.expired {
background-color: #FFEBE8;
}
.widefat.ithemes-updater-listing tr.expired.alt {
background-color: #F9E1DD;
}
#ithemes-updater-site-url-confirmation {
padding-left: 13px;
}
#ithemes-updater-site-url-confirmation .ithemes-updater-header {
background: url( '../images/ithemes-logo-header.png' ) no-repeat;
height: 30px;
width: 198px;
display: block;
margin: 29px 0 32px;
}
#ithemes-updater-site-url-confirmation h2 {
font-size: 24px;
}
#ithemes-updater-site-url-confirmation > p {
font-size: 16px;
}
#ithemes-updater-site-url-confirmation #ithemes-updater-table-wrapper {
background-color: #FFFFFF;
padding: 0 20px;
border: 4px solid #FFFFFF;
border-radius: 4px;
max-width: 900px;
}
#ithemes-updater-site-url-confirmation form {
margin: 24px 0;
}
#ithemes-updater-site-url-confirmation table {
margin: 0;
}
#ithemes-updater-site-url-confirmation th {
width: 400px;
}
#ithemes-updater-site-url-confirmation td {
vertical-align: top;
padding: 20px 0 20px 10px;
}
#ithemes-updater-site-url-confirmation th label {
text-transform: uppercase;
}
#ithemes-updater-site-url-confirmation th label+.description {
padding-top: 10px;
}
#ithemes-updater-site-url-confirmation .description {
font-size: 12px;
font-weight: normal;
}
#ithemes-updater-site-url-confirmation .ithemes-updater-description-warning {
font-style: italic;
}
#ithemes-updater-site-url-confirmation .submit input[type="submit"] {
font-size: 16px;
font-weight: bold;
line-height: 16px;
padding: 11px 21px;
border-radius: 4px;
}
#ithemes-updater-relicense {
padding-left: 13px;
}
#ithemes-updater-relicense .ithemes-updater-header {
background: url( '../images/ithemes-logo-header.png' ) no-repeat;
height: 30px;
width: 198px;
display: block;
margin: 29px 0 32px;
}
#ithemes-updater-relicense h2 {
font-size: 24px;
}
#ithemes-updater-relicense > p {
font-size: 16px;
}
#ithemes-updater-relicense #ithemes-updater-table-wrapper {
background-color: #FFFFFF;
padding: 10px;
border: 4px solid #FFFFFF;
border-radius: 4px;
max-width: 900px;
}
#ithemes-updater-relicense form {
margin: 24px 0;
}
#ithemes-updater-relicense table {
margin: 0;
}
#ithemes-updater-relicense th {
width: 250px;
padding: 10px;
}
#ithemes-updater-relicense td {
vertical-align: top;
padding: 10px;
}
#ithemes-updater-relicense th label {
text-transform: uppercase;
}
#ithemes-updater-relicense th label+.description {
padding-top: 10px;
}
#ithemes-updater-relicense th input {
margin-top: 10px;
}
#ithemes-updater-relicense td input[type="radio"] {
margin-left: -23px;
}
#ithemes-updater-relicense .description {
font-size: 12px;
font-weight: normal;
}
#ithemes-updater-relicense .ithemes-updater-description-warning {
font-style: italic;
margin-top: 10px;
}
#ithemes-updater-relicense .ithemes-updater-description-notice {
font-style: italic;
margin-top: 10px;
background-color: #D7F0FC;
border-radius: 3px;
color: #366C92;
padding: 5px 8px 5px 29px;
}
#ithemes-updater-relicense .ithemes-updater-description-notice .dashicons-warning {
margin-left: -23px;
}
#ithemes-updater-relicense .submit input[type="submit"] {
font-size: 16px;
font-weight: bold;
line-height: 16px;
padding: 11px 21px;
border-radius: 4px;
}

View File

@@ -0,0 +1,113 @@
<?php
/*
Misc functions to assist the updater code.
Written by Chris Jean for iThemes.com
Version 1.0.0
Version History
1.0.0 - 2013-04-11 - Chris Jean
Release ready
*/
class Ithemes_Updater_Functions {
public static function get_url( $path ) {
$path = str_replace( '\\', '/', $path );
$wp_content_dir = str_replace( '\\', '/', WP_CONTENT_DIR );
if ( 0 === strpos( $path, $wp_content_dir ) )
return content_url( str_replace( $wp_content_dir, '', $path ) );
$abspath = str_replace( '\\', '/', ABSPATH );
if ( 0 === strpos( $path, $abspath ) )
return site_url( str_replace( $abspath, '', $path ) );
$wp_plugin_dir = str_replace( '\\', '/', WP_PLUGIN_DIR );
$wpmu_plugin_dir = str_replace( '\\', '/', WPMU_PLUGIN_DIR );
if ( 0 === strpos( $path, $wp_plugin_dir ) || 0 === strpos( $path, $wpmu_plugin_dir ) )
return plugins_url( basename( $path ), $path );
return false;
}
public static function get_package_name( $package ) {
$name = str_replace( 'builderchild', 'Builder Child', $package );
$name = str_replace( '-', ' ', $name );
$name = ucwords( $name );
$name = str_replace( 'buddy', 'Buddy', $name );
$name = str_replace( 'Ithemes', 'iThemes', $name );
$name = str_replace( 'Rcp ', 'RCP ', $name );
$name = str_replace( ' Qr ', ' QR ', $name );
$name = str_replace( 'Itsec ', 'ITSEC ', $name );
$name = str_replace( 'Wpcomplete', 'WPComplete', $name );
$name = str_replace( 'Pmpro ', 'PMPro ', $name );
$name = str_replace( 'Restrict Content Pro Buddypress', 'Restrict Content Pro - Buddypress', $name );
return $name;
}
public static function get_post_data( $vars, $fill_missing = false ) {
$data = array();
foreach ( $vars as $var ) {
if ( isset( $_POST[$var] ) ) {
$clean_var = preg_replace( '/^it-updater-/', '', $var );
$data[$clean_var] = $_POST[$var];
}
else if ( $fill_missing ) {
$data[$var] = '';
}
}
return stripslashes_deep( $data );
}
public static function get_site_option( $option ) {
global $wpdb;
$options = get_site_option( $option, false );
if ( is_array( $options ) ) {
return $options;
}
// Attempt to get the stored option manually to ensure that the failure wasn't due to a DB or other glitch.
if ( is_multisite() ) {
$network_id = get_current_network_id();
$query = $wpdb->prepare( "SELECT meta_value FROM $wpdb->sitemeta WHERE meta_key = %s AND site_id = %d LIMIT 1", $option, $network_id );
$index = 'meta_value';
} else {
$query = $wpdb->prepare( "SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1", $option );
$index = 'option_value';
}
$result = $wpdb->query( $query );
if ( false === $result ) {
// Something went wrong with the DB.
return false;
}
if ( empty( $wpdb->last_result[0] ) || empty( $wpdb->last_result[0]->$index ) ) {
// The value has not been set yet, return the default value.
return null;
}
$value = $wpdb->last_result[0]->$index;
$options = @unserialize( $value );
if ( is_array( $options ) ) {
return $options;
}
// Seems that we have some bad data.
// TODO: Attempt data restoration.
return null;
}
}

View File

@@ -0,0 +1,74 @@
1.0.0 - 2013-04-11 - Chris Jean
Release ready version.
1.0.1 - 2013-05-01 - Chris Jean
Fixed a compatibility problem with the automatic-updater plugin.
1.0.2 - 2013-06-21 - Chris Jean
Fixed an issue where requests would fail when made by servers with a non-default value for arg_separator.output in the php.ini file.
1.1.0 - 2013-10-02 - Chris Jean
Big rewrite to the updater in order to make the code more flexible. This improves compatibility with plugins that allow for remote updating of plugins and themes.
The updater now supports providing changelog details for plugins and themes that have updates available. These details can be viewed by clicking the "View version **** details" link for the appropriate plugin or theme.
1.2.0 - 2013-10-04 - Chris Jean
Enhancement: When releases with four version digits are released (such as 2.1.0.3), by default, the updater will not offer to update if just this last digit is updated. For instance, it will not automatically offer to update 2.1.0.1 to 2.1.0.3; rather, an automatic upgrade will become available when version 2.1.1 or greater is released. If you wish to force an update to these versions, you can add ithemes-updater-force-minor-update=1 to an admin page request (such as http://domain.com/wp-admin/index.php?ithemes-updater-force-minor-update=1) in order to force the updater make these releases available for an hour. If the update is not performed within the hour, the updater reverts back to default behavior.
Bug Fix: Corrected source of the following error when updating: Download failed. SSL certificate problem, verify that the CA cert is OK. Details: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
Bug Fix: Corrected source of the following warning: Warning: require_once(/api.php) [function.require-once]: failed to open stream: No such file or directory
1.2.1 - 2013-10-07 - Chris Jean
Bug Fix: Corrected another source of the following warning which occur immediate after updating the plugin or theme: Warning: require_once(/api.php) [function.require-once]: failed to open stream: No such file or directory
1.3.0 - 2013-10-23 - Chris Jean
Enhancement: Added a "Quick Release Updates" setting to the bottom of the licensing page. Enabling this option allows the site to receive automatic update notices for product quick releases (releases that do not have automatic update support by default).
Enhancement: Changed how the licensing page works on Multisite. Now it will appear at Settings > iThemes Licensing in the network admin Dashboard and at Settings > iThemes Licensing on sites when the current user is a network admin. This prevents exposing the licensing page to users that don't are not super users and thus should not be performing updates. As this update makes the functionality of the "Licensing Page Access" setting obsolete, the setting has been removed.
Enhancement: Using the ithemes-updater-force-minor-update query string variable will now force a data flush, allowing any available quick release updates to appear instantly.
Enhancement: Added "License" links to the Plugins and Themes pages for the Network Admin Dashboard of multisite installs.
1.3.1 - 2013-12-13 - Chris Jean
Enhancement: Recently updated plugins and themes no longer report that an update is available.
Enhancement: Added alternate line styling to the listings on the licensing page.
Enhancement: Products with iThemes in the name will now properly capitalize the name.
Enhancement: The updater and licensing system now handle iThemes server outages without causing long page delays or by reporting confusing error messages.
1.3.2 - 2013-12-18 - Chris Jean
Bug Fix: Removed unneeded check on package-info.ithemes.com which was causing performance issues on some sites.
1.3.3 - 2013-12-19 - Chris Jean
Bug Fix: Licensing will now be universal across all sites of a multisite network. This means that you will only need to license on one site to have the license apply across the entire network.
1.3.4 - 2014-02-03 - Chris Jean
Bug Fix: Licensing on SSL-enabled sites now works properly.
1.4.0 - 2014-11-14 - Chris Jean
Enhancement: Reduced caching to allow updates to appear more quickly.
Enhancement: Authenticating users now uses the new authentication system.
1.4.1 - 2015-04-23 - Chris Jean
Compatibility Fix: Updated plugin and theme update data format to match changes in WordPress 4.2.
1.4.2 - 2015-07-14 - Chris Jean
Enhancement: Updated link to iThemes support.
1.5.0 - 2018-05-02 - Chris Jean
Bug Fix: Fixed the "View details" link failing to work properly after updating.
Bug Fix: Fixed an issue that could cause data changes to not save properly on specific background page requests.
Bug Fix: Added a compatibility fix to avoid conflicts with plugins that change the plugin_action_links filter value from an array to a string.
Compatibility Fix: Updated handing of wp_remote_get() response due to changes documented in https://core.trac.wordpress.org/ticket/33055.
Enhancement: Added ability to manage licensing from WP-CLI.
1.5.1 - 2018-05-03 - Chris Jean
Bug Fix: Fixed fatal error that could occur when clicking the "View details" link for an available plugin update.
1.5.2 - 2018-05-25 - Chris Jean
Bug Fix: Fixed error in error handler for cases where requests for changelog updates fail.
1.6.0 - 2020-08-06 - Chris Jean
Enhancement: Added the ability for the user to manage the licensed site URL.
1.6.1 - 2020-08-06 - Chris Jean
Bug Fix: Fixed bug that can cause licensed site URL management from working properly on some sites on https connections.
1.6.2 - 2020-08-07 - Chris Jean
Bug Fix: Fixed fatal error that can happen when upgrading to the 1.6.1 version of this code:
Ithemes_Updater_Settings::get_licensed_site_url() in server.php:199".
1.6.4 - 2020-08-11 - Chris Jean
Enhancement: Added support for the auto-update feature introduced in WordPress 5.5.
1.6.5 - 2020-09-01 - Chris Jean
Bug Fix: Fixed source of this warning:
PHP Notice: Undefined index: status in lib/updater/settings-page.php
1.6.6 - 2020-10-06 - Chris Jean
Enhancement: Added support for migrating WPComplete license keys.
1.6.7 - 2020-12-16 - Chris Jean
Security Improvement: To improve server compatibility, requests to the iThemes servers would automatically downgrade from https to http when https connections failed. This update removes the automatic downgrade. If your server cannot make outbound https connections, you can re-enable the downgrade capability by adding the following define in your site's wp-config.php file:
define( 'ITHEMES_ALLOW_HTTP_FALLBACK', true );
1.6.8 - 2020-01-19 - Chris Jean
Enhancement: Added support for migrating Skillful Plugins license keys.
Enhancement: Improved auto-naming of some plugins in the iThemes Licensing page.
1.7.0 - 2021-04-13 - Chris Jean
Bug Fix: Fixed scenario where the cache is flushed on every admin page load.
Enhancement: Flush the cache on every "wp-cli ithemes-licensing" command since the normal cache flushing mechanism does not work with such requests.
Enhancement: The tested WordPress version and required minimum PHP version can now be supplied to WordPress for each product.
1.7.1 - 2022-06-21 - Chris Jean
Enhancement: Improved support for updates to indicate required PHP and WordPress versions.

Binary file not shown.

After

Width:  |  Height:  |  Size: 754 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 456 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 531 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@@ -0,0 +1 @@
<?php // Silence is golden.

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 321 B

View File

@@ -0,0 +1 @@
<?php // Silence is golden.

View File

@@ -0,0 +1,60 @@
<?php
/*
Provides details formatted for use in "View version *** details" boxes.
Written by Chris Jean for iThemes.com
Version 1.1.1
Version History
1.0.0 - 2013-04-11 - Chris Jean
Release ready
1.0.1 - 2013-09-19 - Chris Jean
Updated requires to not use dirname().
1.1.0 - 2013-10-02 - Chris Jean
Added get_theme_information().
1.1.1 - 2013-12-18 - Chris Jean
Removed unneeded code that checked package-info.ithemes.com.
*/
class Ithemes_Updater_Information {
public static function get_theme_information( $path ) {
return self::get_plugin_information( "$path/style.css" );
}
public static function get_plugin_information( $path ) {
require_once( $GLOBALS['ithemes_updater_path'] . '/packages.php' );
$details = Ithemes_Updater_Packages::get_full_details();
if ( ! isset( $details['packages'][$path] ) )
return false;
$package = $details['packages'][$path];
require_once( $GLOBALS['ithemes_updater_path'] . '/functions.php' );
require_once( $GLOBALS['ithemes_updater_path'] . '/information.php' );
$changelog = Ithemes_Updater_API::get_package_changelog( $package['package'], $details['packages'][$path]['installed'] );
if ( is_wp_error( $changelog ) ) {
/* translators: 1. Error message, 2. Error code */
$changelog = sprintf( __( '<p>Unable to get changelog data at this time.</p><p>%1$s (%2$s)</p>', 'it-l10n-restrict-content-pro' ), $changelog->get_error_message(), $changelog->get_error_code() );
}
$info = array(
'name' => Ithemes_Updater_Functions::get_package_name( $package['package'] ),
'slug' => dirname( $path ),
'version' => isset( $package['available'] ) ? $package['available'] : '',
'author' => '<a href="https://ithemes.com/">iThemes</a>',
'download_link' => isset( $package['package-url'] ) ? $package['package-url'] : '',
'sections' => array(
'changelog' => $changelog,
),
);
return (object) $info;
}
}

View File

@@ -0,0 +1,102 @@
<?php
/*
Load the updater and licensing system without loading unneeded parts.
Written by Chris Jean for iThemes.com
Version 1.2.1
Version History
1.0.0 - 2013-04-11 - Chris Jean
Release ready
1.0.1 - 2013-05-01 - Chris Jean
Fixed a bug where some plugins caused the filter_update_plugins and filter_update_themes to run when load hadn't run, causing errors.
1.1.0 - 2013-09-19 - Chris Jean
Complete restructuring of this file as most of the code has been relocated to other files.
1.2.0 - 2013-12-13 - Chris Jean
Added the ability to force clear the server timeout hold by adding a query variable named ithemes-updater-force-clear-server-timeout-hold to the URL.
1.2.1 - 2014-10-23 - Chris Jean
Removed ithemes-updater-force-clear-server-timeout-hold code.
*/
if ( defined( 'WP_CLI' ) && WP_CLI && class_exists( 'WP_CLI_Command' ) && ! class_exists( 'Ithemes_Updater_WP_CLI_Ithemes_Licensing' ) ) {
require( dirname( __FILE__ ) . '/wp-cli.php' );
WP_CLI::add_command( 'ithemes-licensing', 'Ithemes_Updater_WP_CLI_Ithemes_Licensing' );
}
if ( defined( 'ITHEMES_UPDATER_DISABLE' ) && ITHEMES_UPDATER_DISABLE ) {
return;
}
$GLOBALS['ithemes_updater_path'] = dirname( __FILE__ );
if ( is_admin() ) {
require( $GLOBALS['ithemes_updater_path'] . '/admin.php' );
}
function ithemes_updater_filter_update_plugins( $update_plugins ) {
if ( ! class_exists( 'Ithemes_Updater_Settings' ) ) {
require( $GLOBALS['ithemes_updater_path'] . '/settings.php' );
}
return $GLOBALS['ithemes-updater-settings']->filter_update_plugins( $update_plugins );
}
add_filter( 'site_transient_update_plugins', 'ithemes_updater_filter_update_plugins' );
add_filter( 'transient_update_plugins', 'ithemes_updater_filter_update_plugins' );
function ithemes_updater_filter_update_themes( $update_themes ) {
if ( ! class_exists( 'Ithemes_Updater_Settings' ) ) {
require( $GLOBALS['ithemes_updater_path'] . '/settings.php' );
}
return $GLOBALS['ithemes-updater-settings']->filter_update_themes( $update_themes );
}
add_filter( 'site_transient_update_themes', 'ithemes_updater_filter_update_themes' );
add_filter( 'transient_update_themes', 'ithemes_updater_filter_update_themes' );
function ithemes_updater_get_licensed_site_url() {
if ( ! class_exists( 'Ithemes_Updater_Settings' ) ) {
require( $GLOBALS['ithemes_updater_path'] . '/settings.php' );
}
return $GLOBALS['ithemes-updater-settings']->get_licensed_site_url();
}
function ithemes_updater_get_seen_hostnames() {
if ( ! class_exists( 'Ithemes_Updater_Settings' ) ) {
require( $GLOBALS['ithemes_updater_path'] . '/settings.php' );
}
return $GLOBALS['ithemes-updater-settings']->get_hostname_history();
}
function ithemes_updater_is_request_on_licensed_site_url() {
if ( ! class_exists( 'Ithemes_Updater_Settings' ) ) {
require( $GLOBALS['ithemes_updater_path'] . '/settings.php' );
}
return $GLOBALS['ithemes-updater-settings']->is_request_on_licensed_site_url();
}
function ithemes_updater_get_change_licensed_site_url( $redirect = '' ) {
return admin_url( 'options-general.php?page=ithemes-licensing&action=change_licensed_site_url&redirect=' . urlencode( $redirect ) );
}
function ithemes_updater_change_licensed_site_url( $redirect = '' ) {
wp_redirect( ithemes_updater_get_change_licensed_site_url( $redirect ) );
exit();
}
function ithemes_updater_is_licensed_site_url_confirmed() {
if ( ! class_exists( 'Ithemes_Updater_Settings' ) ) {
require( $GLOBALS['ithemes_updater_path'] . '/settings.php' );
}
return $GLOBALS['ithemes-updater-settings']->is_licensed_site_url_confirmed();
}

View File

@@ -0,0 +1 @@
<?php // Silence is golden.

View File

@@ -0,0 +1,7 @@
jQuery(document).ready(
function() {
if ( jQuery( '#ithemes-updater-redirect-to-url' ).length ) {
window.location.replace( jQuery( '#ithemes-updater-redirect-to-url' ).val() );
}
}
);

View File

@@ -0,0 +1,177 @@
<?php
/*
Provides license key management.
Written by Chris Jean for iThemes.com
Version 1.0.2
Version History
1.0.0 - 2013-04-11 - Chris Jean
Release ready
1.0.1 - 2013-09-19 - Chris Jean
Updated requires to no longer use dirname().
1.0.2 - 2014-10-23 - Chris Jean
Updated code to meet WordPress coding standards.
*/
class Ithemes_Updater_Keys {
private static $option_name = 'ithemes-updater-keys';
public static function get( $packages = array() ) {
require_once( $GLOBALS['ithemes_updater_path'] . '/functions.php' );
$all_keys = Ithemes_Updater_Functions::get_site_option( self::$option_name );
if ( false === $all_keys ) {
$GLOBALS['ithemes-updater-keys-db-failure'] = true;
} else {
$GLOBALS['ithemes-updater-keys-db-failure'] = false;
}
if ( ! is_array( $all_keys ) ) {
$all_keys = array();
}
if ( '__all__' == $packages ) {
return $all_keys;
}
if ( empty( $packages ) ) {
require_once( $GLOBALS['ithemes_updater_path'] . '/packages.php' );
$packages = array_unique( array_values( Ithemes_Updater_Packages::get_all() ) );
}
$keys = array();
foreach ( (array) $packages as $package ) {
if ( ! empty( $all_keys[$package] ) ) {
$keys[$package] = $all_keys[$package];
}
}
if ( ! is_array( $packages ) ) {
return $keys[$packages];
}
return $keys;
}
public static function set( $new_keys, $key = false ) {
$keys = self::get( '__all__' );
if ( false === $key ) {
foreach ( $new_keys as $package => $key ) {
$keys[$package] = $key;
}
} else {
$keys[$new_keys] = $key;
}
if ( ! isset( $GLOBALS['ithemes-updater-keys-db-failure'] ) || false === $GLOBALS['ithemes-updater-keys-db-failure'] ) {
update_site_option( self::$option_name, $keys );
}
}
private static function get_legacy_slug( $raw_slug ) {
$slug = str_replace( '_', '-', $raw_slug );
$slug = preg_replace( '/^(pluginbuddy|ithemes|it)-/', '', $slug );
if ( 'boom-bar' == $slug ) {
$slug = 'boombar';
}
return $slug;
}
public static function delete_legacy( $packages = array() ) {
if ( ! is_array( $packages ) ) {
$packages = array( $packages );
}
$data = get_site_option( 'pluginbuddy_plugins', false );
$remaining_count = 0;
foreach ( $data as $index => $entry ) {
if ( ! is_object( $entry ) || empty( $entry->slug ) ) {
continue;
}
$slug = self::get_legacy_slug( $entry->slug );
if ( in_array( $slug, $packages ) ) {
unset( $data[$index] );
} else {
$remaining_count++;
}
}
if ( 0 == $remaining_count ) {
$data = false;
}
update_site_option( 'pluginbuddy_plugins', $data );
}
public static function get_legacy( $packages = array() ) {
$data = get_site_option( 'pluginbuddy_plugins', false );
if ( empty( $data ) || ! is_array( $data ) ) {
return array();
}
$keys = array();
foreach ( $data as $index => $entry ) {
if ( ! is_object( $entry ) || empty( $entry->slug ) || ! isset( $entry->key ) ) {
continue;
}
$slug = self::get_legacy_slug( $entry->slug );
$keys[$slug] = $entry->key;
}
foreach ( array_keys( $keys ) as $slug ) {
if ( ! isset( $data[$slug] ) ) {
continue;
}
$entry = $data[$slug];
if ( ! is_object( $entry ) || empty( $entry->slug ) || empty( $entry->key ) ) {
continue;
}
$keys[$slug] = $entry->key;
}
if ( empty( $packages ) ) {
require_once( $GLOBALS['ithemes_updater_path'] . '/packages.php' );
$packages = array_unique( array_values( Ithemes_Updater_Packages::get_all() ) );
} else if ( is_string( $packages ) ) {
if ( ! empty( $keys[$packages] ) ) {
return $keys[$packages];
}
return false;
}
$package_keys = array();
foreach ( $packages as $package ) {
if ( ! empty( $keys[$package] ) ) {
$package_keys[$package] = $keys[$package];
}
}
return $package_keys;
}
}

View File

@@ -0,0 +1,54 @@
<?php
/*
Written by Chris Jean for iThemes.com
*/
$it_registration_list_version = '1.7.1';
$it_registration_list_library = 'updater';
$it_registration_list_init_file = dirname( __FILE__ ) . '/init.php';
$GLOBALS['it_classes_registration_list'][$it_registration_list_library][$it_registration_list_version] = $it_registration_list_init_file;
if ( ! function_exists( 'it_registration_list_init' ) ) {
function it_registration_list_init() {
// The $wp_locale variable is set just before the theme's functions.php file is loaded,
// this acts as a good check to ensure that both the plugins and the theme have loaded.
global $wp_locale;
if ( ! isset( $wp_locale ) )
return;
$init_files = array();
foreach ( (array) $GLOBALS['it_classes_registration_list'] as $library => $versions ) {
$max_version = '-10000';
$init_file = '';
foreach ( (array) $versions as $version => $file ) {
if ( version_compare( $version, $max_version, '>' ) ) {
$max_version = $version;
$init_file = $file;
}
}
if ( ! empty( $init_file ) )
$init_files[] = $init_file;
}
unset( $GLOBALS['it_classes_registration_list'] );
foreach ( (array) $init_files as $init_file )
require_once( $init_file );
do_action( 'it_libraries_loaded' );
}
global $wp_version;
if ( version_compare( $wp_version, '2.9.7', '>' ) )
add_action( 'after_setup_theme', 'it_registration_list_init' );
else
add_action( 'set_current_user', 'it_registration_list_init' );
}

View File

@@ -0,0 +1,296 @@
<?php
/*
Provides a reliable way of retrieving which projects have updates.
Written by Chris Jean for iThemes.com
Version 1.0.3
Version History
1.0.0 - 2013-04-11 - Chris Jean
Release ready
1.0.1 - 2013-09-19 - Chris Jean
Added support for 'upgrade' data for a package.
Updated requires to no longer use dirname().
1.0.2 - 2014-10-23 - Chris Jean
Updated to meet WordPress coding standards.
1.0.3 - 2020-03-24 - Timothy Jacobs
Updated to add function for retrieving packages to display in the UI.
*/
class Ithemes_Updater_Packages {
public static function flush() {
unset( $GLOBALS['ithemes-updater-packages-all'] );
}
/**
* Retrieves a list of packages that should be included in the UI.
*
* By default all packages are included, but can be omitted by using a filter.
*
* @param string $details Pass 'full' to get the full details of a package. Otherwise, only local details will be returned.
*
* @return array
*/
public static function get_packages_to_include_in_ui( $details = 'local' ) {
if ( $details === 'full' ) {
$response = self::get_full_details();
$packages = $response['packages'];
} else {
$packages = self::get_local_details();
}
$show_ui = array();
if ( ! $packages ) {
return $show_ui;
}
foreach ( $packages as $file => $package ) {
if ( self::show_ui_for_package( $package['package'] ) ) {
$show_ui[ $file ] = $package;
}
}
return $show_ui;
}
/**
* Whether a package should have management UI displayed for it.
*
* @param string $package The package name. For example 'backupbuddy'.
*
* @return bool
*/
public static function show_ui_for_package( $package ) {
return apply_filters( 'ithemes_updater_show_ui_for_package', true, $package );
}
public static function get_full_details( $response = false ) {
if ( false === $response ) {
require_once( $GLOBALS['ithemes_updater_path'] . '/api.php' );
$response = Ithemes_Updater_API::get_package_details();
}
$packages = self::get_local_details();
if ( is_wp_error( $response ) ) {
$expiration = time() + 600;
foreach ( $packages as $path => $data ) {
$packages[$path]['status'] = 'error';
$packages[$path]['error'] = array(
'code' => 'unknown',
'type' => $response->get_error_code(),
'message' => $response->get_error_message(),
);
}
} else {
$expiration = time() + ( 12 * 3600 );
foreach ( $packages as $path => $data ) {
if ( empty( $response['packages'][$data['package']] ) ) {
continue;
}
$package = $response['packages'][$data['package']];
if ( ! empty( $package['error'] ) ) {
if ( in_array( $package['error']['type'], array( 'ITXAPI_License_Key_Unknown', 'ITXAPI_Updater_Missing_Legacy_Key' ) ) ) {
$packages[$path]['status'] = 'unlicensed';
} else {
$packages[$path]['status'] = 'error';
$packages[$path]['error'] = $package['error'];
}
continue;
}
$key_map = array(
'status' => 'status',
'link' => 'package-url',
'ver' => 'available',
'used' => 'used',
'total' => 'total',
'user' => 'user',
'sub_expire' => 'expiration',
'upgrade' => 'upgrade',
'wp_update_data' => 'wp_update_data',
);
foreach ( $key_map as $old => $new ) {
if ( isset( $package[$old] ) ) {
$packages[$path][$new] = $package[$old];
} else {
$packages[$path][$new] = null;
}
}
if ( isset( $package['autoupdate'] ) ) {
$packages[$path]['autoupdate'] = $package['autoupdate'];
}
if ( isset( $package['disable_autoupdate'] ) ) {
$packages[$path]['disable_autoupdate'] = $package['disable_autoupdate'];
}
if ( isset( $package['upgrade_notice'] ) ) {
$packages[$path]['upgrade_notice'] = $package['upgrade_notice'];
}
if ( isset( $package['link_expire'] ) ) {
$expiration = min( $expiration, $package['link_expire'] );
}
}
}
$details = compact( 'packages', 'expiration' );
$details['packages'] = array(
'rcp'=> array(
'package-url'=>'restrict-content-pro/restrict-content-pro.php',
'installed' =>true,
'available' =>true,
'type' => 'plugin',
'autoupdate'=>'autoupdate',
'upgrade_notice' =>'upgrade_notice',
'status' => 'active',
'expiration' => time() + ( 12 * 36000000 ),
'user'=>'GPL',
'package'=>'restrict-content-pro',
'total' => '100',
'used' => '7',
)
);
return $details;
}
public static function get_local_details() {
require_once( $GLOBALS['ithemes_updater_path'] . '/keys.php' );
$all_packages = self::get_all();
$keys = Ithemes_Updater_Keys::get();
$packages = array();
foreach ( $all_packages as $file => $slug ) {
$packages[$slug][] = $file;
}
foreach ( $packages as $slug => $paths ) {
$packages[$slug] = array_unique( $paths );
}
$details = array();
foreach ( $packages as $package => $paths ) {
foreach ( $paths as $path ) {
$plugin_path = preg_replace( '/^' . preg_quote( WP_PLUGIN_DIR, '/' ) . '/', '', $path );
if ( $plugin_path != $path ) {
$type = 'plugin';
$rel_path = preg_replace( '|^[/\\\\]|', '', $plugin_path );
$plugin_data = get_plugin_data( $path, false, false );
$version = $plugin_data['Version'];
$info_url = $plugin_data['PluginURI'];
} else {
$type = 'theme';
$dir = basename( dirname( $path ) );
$rel_path = "$dir/" . basename( $path );
if ( function_exists( 'wp_get_theme' ) ) {
$theme_data = wp_get_theme( $dir );
$version = $theme_data->get( 'Version' );
$info_url = $theme_data->get( 'ThemeURI' );
} else {
$theme_data = get_theme( $dir );
$version = $theme_data['Version'];
$info_url = '';
}
}
$details[$rel_path] = array(
'type' => $type,
'package' => $package,
'installed' => $version,
'info-url' => $info_url,
'key' => isset( $keys[$package] ) ? $keys[$package] : '',
);
}
}
return $details;
}
public static function get_all() {
if ( isset( $GLOBALS['ithemes-updater-packages-all'] ) ) {
return $GLOBALS['ithemes-updater-packages-all'];
}
$packages = array();
// Compatibility fix for WP < 3.1 as the global var is empty by default
if ( empty( $GLOBALS['wp_theme_directories'] ) ) {
get_themes();
}
$themes = search_theme_directories();
if ( is_array( $themes ) ) {
foreach ( $themes as $slug => $data ) {
if ( ! file_exists( "{$data['theme_root']}/{$data['theme_file']}" ) ) {
continue;
}
$headers = get_file_data( "{$data['theme_root']}/{$data['theme_file']}", array( 'package' => 'iThemes Package' ), 'theme' );
if ( empty( $headers['package'] ) ) {
continue;
}
$packages["{$data['theme_root']}/{$data['theme_file']}"] = $headers['package'];
}
}
require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
$plugins = get_plugins();
foreach ( $plugins as $file => $data ) {
if ( ! file_exists( WP_PLUGIN_DIR . "/$file" ) ) {
continue;
}
$headers = get_file_data( WP_PLUGIN_DIR . "/$file", array( 'package' => 'iThemes Package' ), 'plugin' );
if ( empty( $headers['package'] ) ) {
continue;
}
$packages[WP_PLUGIN_DIR . "/$file"] = $headers['package'];
}
foreach ( $packages as $path => $package ) {
$packages[$path] = strtolower( $package );
}
$GLOBALS['ithemes-updater-packages-all'] = $packages;
return $packages;
}
}

View File

@@ -0,0 +1,298 @@
<?php
/*
Provides an easy to use interface for communicating with the iThemes updater server.
Written by Chris Jean for iThemes.com
Version 1.1.0
Version History
1.0.0 - 2013-04-11 - Chris Jean
Release ready
1.0.1 - 2013-06-21 - Chris Jean
Updated the http_build_query call to force a separator of & in order to avoid issues with servers that change the arg_separator.output php.ini value.
1.0.2 - 2013-09-19 - Chris Jean
Updated ithemes-updater-object to ithemes-updater-settings.
1.0.3 - 2013-12-18 - Chris Jean
Updated the way that the site URL is generated to ensure consistency across multisite sites.
1.0.4 - 2014-01-31 - Chris Jean
Updated to normalize the site URL used for password hash generation and for sending to the server.
1.1.0 - 2014-10-23 - Chris Jean
Updated auth token generation to use new password hashing.
Added CA patch code.
Updated code to meet WordPress coding standards.
*/
class Ithemes_Updater_Server {
private static $secure_server_url = 'https://api.ithemes.com/updater';
private static $insecure_server_url = 'http://api.ithemes.com/updater';
private static $password_iterations = 8;
public static function activate_package( $username, $password, $packages ) {
$query = array(
'user' => $username
);
$data = array(
'auth_token' => self::get_password_hash( $username, $password ),
'packages' => $packages,
);
return Ithemes_Updater_Server::request( 'package-activate', $query, $data );
}
public static function deactivate_package( $username, $password, $packages ) {
$query = array(
'user' => $username
);
$data = array(
'auth_token' => self::get_password_hash( $username, $password ),
'packages' => $packages,
);
return Ithemes_Updater_Server::request( 'package-deactivate', $query, $data );
}
public static function get_licensed_site_url( $packages ) {
$query = array();
$data = array(
'packages' => $packages
);
return Ithemes_Updater_Server::request( 'licensed-site-url-get', $query, $data );
}
public static function set_licensed_site_url( $username, $password, $site_url, $keys ) {
$query = array(
'user' => $username
);
$data = array(
'auth_token' => self::get_password_hash( $username, $password ),
'site_url' => $site_url,
'keys' => $keys,
);
return Ithemes_Updater_Server::request( 'licensed-site-url-set', $query, $data );
}
public static function get_package_details( $packages ) {
global $rcp_options;
$query = array();
$data = array(
'packages' => $packages
);
if ( ! empty( $rcp_options ) && is_array( $rcp_options ) && ! empty( $rcp_options['license_key'] ) ) {
$data['rcp_license_key'] = $rcp_options['license_key'];
}
if ( isset( $packages['wpcomplete'] ) ) {
$data['wpcomplete_license_key'] = get_option( 'wpcomplete_license_key' );
}
if ( isset( $packages['pmpro-ultimate-member'] ) ) {
$data['skillful_license_keys']['pmpro-ultimate-member'] = trim( get_option( 'pmpro_um_license_key' ) );
}
if ( isset( $packages['rcp-custom-renew'] ) ) {
$data['skillful_license_keys']['rcp-custom-renew'] = trim( get_option( 'rcpcr_license_key' ) );
}
if ( isset( $packages['rcp-resume-manager'] ) ) {
$settings = get_option( 'rcprm', array() );
if ( isset( $settings['license'] ) ) {
$data['skillful_license_keys']['rcp-resume-manager'] = trim( $settings['license'] );
}
}
if ( isset( $packages['rcp-ultimate-member'] ) ) {
$data['skillful_license_keys']['rcp-ultimate-member'] = trim( get_option( 'rcpum_license_key' ) );
}
if ( isset( $packages['rcp-view-limit'] ) ) {
$settings = get_option( 'rcpvl', array() );
if ( isset( $settings['license'] ) ) {
$data['skillful_license_keys']['rcp-view-limit'] = trim( $settings['license'] );
}
}
if ( isset( $packages['restrict-content-pro-buddypress'] ) ) {
$data['skillful_license_keys']['restrict-content-pro-buddypress'] = trim( get_option( 'rcpbp_license_key' ) );
}
if ( isset( $packages['view-limit'] ) ) {
$settings = get_option( 'view_limit', array() );
if ( isset( $settings['license'] ) ) {
$data['skillful_license_keys']['view-limit'] = trim( $settings['license'] );
}
}
return Ithemes_Updater_Server::request( 'package-details', $query, $data );
}
public static function request( $action, $query = array(), $data = array() ) {
require_once( $GLOBALS['ithemes_updater_path'] . '/settings.php' );
if ( false !== ( $timeout_start = get_site_option( 'ithemes-updater-server-timed-out' ) ) ) {
// Hold off updates for 30 minutes.
$time_remaining = 1800 - ( time() - $timeout_start );
$minutes_remaining = ceil( $time_remaining / 60 );
if ( $time_remaining < 0 ) {
delete_site_option( 'ithemes-updater-server-timed-out' );
} else {
return new WP_Error( 'ithemes-updater-timed-out-server', sprintf( _n( 'The server could not be contacted. Requests are delayed for %d minute to allow the server to recover.', 'The server could not be contacted. Requests are delayed for %d minutes to allow the server to recover.', $minutes_remaining, 'it-l10n-restrict-content-pro' ), $minutes_remaining ) );
}
}
if ( isset( $data['auth_token'] ) ) {
$data['iterations'] = self::$password_iterations;
}
$site_url = self::get_site_url();
$default_query = array(
'wp' => $GLOBALS['wp_version'],
'php_version' => preg_replace( '/-.*$/', '', phpversion() ),
'is_multisite' => is_multisite(),
'site' => $site_url,
'timestamp' => time(),
'auth_version' => '2',
);
if ( is_multisite() ) {
$default_query['ms'] = 1;
}
$query = array_merge( $default_query, $query );
$request = "/$action/?" . http_build_query( $query, '', '&' );
$post_data = array(
'request' => json_encode( $data ),
);
$remote_post_args = array(
'timeout' => 10,
'body' => $post_data,
);
$options = array(
'use_ca_patch' => false,
'use_ssl' => true,
);
$patch_enabled = $GLOBALS['ithemes-updater-settings']->get_option( 'use_ca_patch' );
if ( $patch_enabled ) {
self::disable_ssl_ca_patch();
}
$response = wp_remote_post( self::$secure_server_url . $request, $remote_post_args );
if ( is_wp_error( $response ) && ( 'connect() timed out!' != $response->get_error_message() ) ) {
self::enable_ssl_ca_patch();
$response = wp_remote_post( self::$secure_server_url . $request, $remote_post_args );
if ( ! is_wp_error( $response ) ) {
$options['use_ca_patch'] = true;
}
}
if ( is_wp_error( $response ) && ( 'connect() timed out!' != $response->get_error_message() ) && defined( 'ITHEMES_ALLOW_HTTP_FALLBACK' ) && ITHEMES_ALLOW_HTTP_FALLBACK ) {
$response = wp_remote_post( self::$insecure_server_url . $request, $remote_post_args );
$options['use_ssl'] = false;
}
if ( ! $options['use_ca_patch'] ) {
self::disable_ssl_ca_patch();
}
$GLOBALS['ithemes-updater-settings']->update_options( $options );
if ( is_wp_error( $response ) ) {
if ( 'connect() timed out!' == $response->get_error_message() ) {
// Set option to delay server checks for a period of time.
update_site_option( 'ithemes-updater-server-timed-out', time() );
return new WP_Error( 'http_request_failed', __( 'The server was unable to be contacted.', 'it-l10n-restrict-content-pro' ) );
}
return $response;
}
$body = json_decode( $response['body'], true );
if ( ! empty( $body['error'] ) ) {
return new WP_Error( $body['error']['type'], sprintf( __( 'An error occurred when communicating with the iThemes update server: %s (%s)', 'it-l10n-restrict-content-pro' ), $body['error']['message'], $body['error']['code'] ) );
}
return $body;
}
private static function get_site_url() {
require_once( $GLOBALS['ithemes_updater_path'] . '/settings.php' );
// Ensure that a fatal error isn't triggered on upgrade.
if ( is_callable( array( $GLOBALS['ithemes-updater-settings'], 'get_licensed_site_url' ) ) ) {
$site_url = $GLOBALS['ithemes-updater-settings']->get_licensed_site_url();
}
if ( empty( $site_url ) ) {
if ( is_callable( 'network_home_url' ) ) {
$site_url = network_home_url( '', 'http' );
} else {
$site_url = get_bloginfo( 'url' );
}
}
$site_url = preg_replace( '/^https/', 'http', $site_url );
$site_url = preg_replace( '|/$|', '', $site_url );
return $site_url;
}
private static function get_password_hash( $username, $password ) {
require_once( ABSPATH . WPINC . '/class-phpass.php' );
require_once( dirname( __FILE__ ) . '/class-ithemes-credentials.php' );
$password = iThemes_Credentials::get_password_hash( $username, $password );
$salted_password = $password . $username . self::get_site_url() . $GLOBALS['wp_version'];
$salted_password = substr( $salted_password, 0, max( strlen( $password ), 512 ) );
$hasher = new PasswordHash( self::$password_iterations, true );
$auth_token = $hasher->HashPassword( $salted_password );
return $auth_token;
}
public static function enable_ssl_ca_patch() {
add_action( 'http_api_curl', array( __CLASS__, 'add_ca_patch_to_curl_opts' ) );
}
public static function disable_ssl_ca_patch() {
remove_action( 'http_api_curl', array( __CLASS__, 'add_ca_patch_to_curl_opts' ) );
}
public static function add_ca_patch_to_curl_opts( $handle ) {
$url = curl_getinfo( $handle, CURLINFO_EFFECTIVE_URL );
if ( ! preg_match( '{^https://(api|downloads)\.ithemes\.com}', $url ) ) {
return;
}
curl_setopt( $handle, CURLOPT_CAINFO, $GLOBALS['ithemes_updater_path'] . '/ca/roots.crt' );
}
}

View File

@@ -0,0 +1,956 @@
<?php
/*
Code to render and manage the settings page for the updater system.
Written by Chris Jean for iThemes.com
Version 1.1.0
Version History
1.0.0 - 2013-04-11 - Chris Jean
Release ready
1.0.1 - 2013-09-19 - Chris Jean
Updated requires to not use dirname().
Updated ithemes-updater-object to ithemes-updater-settings.
1.1.0 - 2013-10-23 - Chris Jean
Enhancement: Added the quick_releases setting.
Misc: Removed the show_on_sites setting as it is no longer used.
*/
class Ithemes_Updater_Settings_Page {
private $page_name = 'ithemes-licensing';
private $path_url = '';
private $self_url = '';
private $messages = array();
private $message_strings = array();
private $errors = array();
private $soft_errors = array();
public function __construct() {
require_once( $GLOBALS['ithemes_updater_path'] . '/functions.php' );
require_once( $GLOBALS['ithemes_updater_path'] . '/api.php' );
require_once( $GLOBALS['ithemes_updater_path'] . '/keys.php' );
$this->path_url = Ithemes_Updater_Functions::get_url( $GLOBALS['ithemes_updater_path'] );
list( $this->self_url ) = explode( '?', $_SERVER['REQUEST_URI'] );
$this->self_url .= '?page=' . $this->page_name;
add_action( 'ithemes_updater_settings_page_index', array( $this, 'index' ) );
add_action( 'admin_print_scripts', array( $this, 'add_scripts' ) );
add_action( 'admin_print_styles', array( $this, 'add_styles' ) );
}
public function add_scripts() {
wp_enqueue_script( 'ithemes-updater-settings-page-script', "{$this->path_url}/js/settings-page.js", array(), 2 );
}
public function add_styles() {
wp_enqueue_style( 'ithemes-updater-settings-page-style', "{$this->path_url}/css/settings-page.css", array(), 2 );
}
public function index() {
$post_data = Ithemes_Updater_Functions::get_post_data( array( 'it-updater-username', 'it-updater-password', 'packages', 'action', 'site_url', 'redirect', 'relicense_option' ), true );
if ( empty( $post_data['packages'] ) ) {
$post_data['packages'] = array();
}
if ( ! empty( $post_data['action'] ) ) {
$action = $post_data['action'];
} else if ( ! empty( $_REQUEST['action'] ) ) {
$action = $_REQUEST['action'];
} else {
$action = 'list_packages';
}
if ( 'save_licensed_site_url' === $action ) {
$this->save_licensed_site_url( $post_data );
} else if ( 'relicense' === $action ) {
$this->relicense( $post_data );
} else if ( 'change_licensed_site_url' === $action || ! $GLOBALS['ithemes-updater-settings']->is_licensed_site_url_confirmed() ) {
$this->show_licensed_site_url_confirmation_page( $post_data );
} else {
if ( 'license_packages' === $action ) {
$this->license_packages( $post_data );
} else if ( 'unlicense_packages' === $action ) {
$this->unlicense_packages( $post_data );
} else if ( 'save_settings' === $action ) {
$this->save_settings();
}
$this->list_packages( $action, $post_data );
}
}
private function save_settings() {
check_admin_referer( 'save_settings', 'ithemes_updater_nonce' );
$settings_defaults = array(
'quick_releases' => false,
);
$settings = array();
foreach ( $settings_defaults as $var => $val ) {
if ( isset( $_POST[$var] ) )
$settings[$var] = $_POST[$var];
else
$settings[$var] = $val;
}
if ( $settings['quick_releases'] )
$settings['quick_releases'] = true;
$GLOBALS['ithemes-updater-settings']->update_options( $settings );
$GLOBALS['ithemes-updater-settings']->flush( 'settings saved' );
$this->messages[] = __( 'Settings saved', 'it-l10n-restrict-content-pro' );
}
private function license_packages( $data ) {
check_admin_referer( 'license_packages', 'ithemes_updater_nonce' );
if ( empty( $data['username'] ) && empty( $data['password'] ) )
$this->errors[] = __( 'You must supply an iThemes membership username and password in order to license products.', 'it-l10n-restrict-content-pro' );
else if ( empty( $data['username'] ) )
$this->errors[] = __( 'You must supply an iThemes membership username in order to license products.', 'it-l10n-restrict-content-pro' );
else if ( empty( $data['password'] ) )
$this->errors[] = __( 'You must supply an iThemes membership password in order to license products.', 'it-l10n-restrict-content-pro' );
else if ( empty( $data['packages'] ) )
$this->errors[] = __( 'You must select at least one product to license. Ensure that you select the products that you wish to license in the listing below.', 'it-l10n-restrict-content-pro' );
if ( ! empty( $this->errors ) )
return;
$response = Ithemes_Updater_API::activate_package( $data['username'], $data['password'], $data['packages'] );
if ( is_wp_error( $response ) ) {
$this->errors[] = Ithemes_Updater_API::get_error_explanation( $response );
return;
}
if ( empty( $response['packages'] ) ) {
$this->errors[] = __( 'An unknown server error occurred. Please try to license your products again at another time.', 'it-l10n-restrict-content-pro' );
return;
}
uksort( $response['packages'], 'strnatcasecmp' );
$success = array();
$warn = array();
$fail = array();
foreach ( $response['packages'] as $package => $data ) {
if ( preg_match( '/ \|\|\| \d+$/', $package ) )
continue;
$name = Ithemes_Updater_Functions::get_package_name( $package );
if ( ! empty( $data['key'] ) )
$success[] = $name;
else if ( ! empty( $data['status'] ) && ( 'expired' == $data['status'] ) )
$warn[$name] = __( 'Your product subscription has expired', 'it-l10n-restrict-content-pro' );
else
$fail[$name] = $data['error']['message'];
}
if ( ! empty( $success ) )
$this->messages[] = wp_sprintf( __( 'Successfully licensed %l.', 'it-l10n-restrict-content-pro' ), $success );
if ( ! empty( $fail ) ) {
foreach ( $fail as $name => $reason )
$this->errors[] = sprintf( __( 'Unable to license %1$s. Reason: %2$s', 'it-l10n-restrict-content-pro' ), $name, $reason );
}
if ( ! empty( $warn ) ) {
foreach ( $warn as $name => $reason )
$this->soft_errors[] = sprintf( __( 'Unable to license %1$s. Reason: %2$s', 'it-l10n-restrict-content-pro' ), $name, $reason );
}
}
private function unlicense_packages( $data ) {
check_admin_referer( 'unlicense_packages', 'ithemes_updater_nonce' );
if ( empty( $data['username'] ) && empty( $data['password'] ) )
$this->errors[] = __( 'You must supply an iThemes membership username and password in order to remove licenses.', 'it-l10n-restrict-content-pro' );
else if ( empty( $data['username'] ) )
$this->errors[] = __( 'You must supply an iThemes membership username in order to remove licenses.', 'it-l10n-restrict-content-pro' );
else if ( empty( $data['password'] ) )
$this->errors[] = __( 'You must supply an iThemes membership password in order to remove licenses.', 'it-l10n-restrict-content-pro' );
else if ( empty( $data['packages'] ) )
$this->errors[] = __( 'You must select at least one license to remove. Ensure that you select the licenses that you wish to remove in the listing below.', 'it-l10n-restrict-content-pro' );
if ( ! empty( $this->errors ) )
return;
$response = Ithemes_Updater_API::deactivate_package( $data['username'], $data['password'], $data['packages'] );
if ( is_wp_error( $response ) ) {
$this->errors[] = Ithemes_Updater_API::get_error_explanation( $response );
return;
}
if ( empty( $response['packages'] ) ) {
$this->errors[] = __( 'An unknown server error occurred. Please try to remove licenses from your products again at another time.', 'it-l10n-restrict-content-pro' );
return;
}
uksort( $response['packages'], 'strnatcasecmp' );
$success = array();
$fail = array();
foreach ( $response['packages'] as $package => $data ) {
if ( preg_match( '/ \|\|\| \d+$/', $package ) )
continue;
$name = Ithemes_Updater_Functions::get_package_name( $package );
if ( isset( $data['status'] ) && ( 'inactive' == $data['status'] ) )
$success[] = $name;
else if ( isset( $data['error'] ) && isset( $data['error']['message'] ) )
$fail[$name] = $data['error']['message'];
else
$fail[$name] = __( 'Unknown server error.', 'it-l10n-restrict-content-pro' );
}
if ( ! empty( $success ) )
$this->messages[] = wp_sprintf( _n( 'Successfully removed license from %l.', 'Successfully removed licenses from %l.', count( $success ), 'it-l10n-restrict-content-pro' ), $success );
if ( ! empty( $fail ) ) {
foreach ( $fail as $name => $reason )
$this->errors[] = sprintf( __( 'Unable to remove license from %1$s. Reason: %2$s', 'it-l10n-restrict-content-pro' ), $name, $reason );
}
}
public function list_packages( $action = 'list_packages', $post_data = array() ) {
require_once( $GLOBALS['ithemes_updater_path'] . '/packages.php' );
$packages = Ithemes_Updater_Packages::get_packages_to_include_in_ui( 'full' );
$licensed = array();
$unlicensed = array();
$unrecognized = array();
foreach ( $packages as $path => $data ) {
$name = Ithemes_Updater_Functions::get_package_name( $data['package'] );
$data['path'] = $path;
if ( isset( $data['status'] ) && 'unlicensed' == $data['status'] )
$unlicensed[$name] = $data;
else if ( isset( $data['status'] ) && in_array( $data['status'], array( 'active', 'expired' ) ) )
$licensed[$name] = $data;
else
$unrecognized[$name] = $data;
}
if ( ! empty( $_REQUEST['updated_url'] ) ) {
$this->messages[] = __( 'Successfully updated the Licensed URL.', 'it-l10n-restrict-content-pro' );
}
$this->show_notices();
?>
<div class="wrap">
<h2><?php _e( 'iThemes Licensing', 'it-l10n-restrict-content-pro' ); ?></h2>
<?php
$this->list_licensed_products( $licensed, $post_data, $action );
$this->list_unlicensed_products( $unlicensed, $post_data, $action );
$this->list_unrecognized_products( $unrecognized );
$this->show_settings();
?>
</div>
<?php
}
private function show_settings() {
$quick_releases = $GLOBALS['ithemes-updater-settings']->get_option( 'quick_releases' );
?>
<form id="posts-filter" enctype="multipart/form-data" method="post" action="<?php echo $this->self_url; ?>">
<?php wp_nonce_field( 'save_settings', 'ithemes_updater_nonce' ); ?>
<div id="ithemes-updater-settings">
<h3 class="subtitle"><?php _e( 'Settings', 'it-l10n-restrict-content-pro' ); ?></h3>
<table class="form-table">
<tbody>
<tr valign="top">
<th scope="row">
<?php _e( 'Licensed URL', 'it-l10n-restrict-content-pro' ); ?>
</th>
<td>
<p>
<code><?php echo $GLOBALS['ithemes-updater-settings']->get_licensed_site_url(); ?></code>
<a href="<?php echo admin_url( 'options-general.php?page=ithemes-licensing&action=change_licensed_site_url' ); ?>" class="button button-primary"><?php _e( 'Change', 'it-l10n-restrict-content-pro' ); ?></a>
</p>
<?php if ( is_multisite() ) : ?>
<p class="description"><?php _e( 'The Licensed URL should be the primary URL of this WordPress network. If this is not set correctly, some features may not function as expected.', 'it-l10n-restrict-content-pro' ); ?></p>
<?php else : ?>
<p class="description"><?php _e( 'The Licensed URL should be the primary URL of this WordPress site. If this is not set correctly, some features may not function as expected.', 'it-l10n-restrict-content-pro' ); ?></p>
<?php endif; ?>
</td>
</tr>
<tr valign="top">
<th scope="row">
<label for="quick_releases"><?php _e( 'Quick Release Updates', 'it-l10n-restrict-content-pro' ); ?></label>
</th>
<td>
<?php $checked = ( $quick_releases ) ? ' checked="checked"' : ''; ?>
<label>
<input id="quick_releases" type="checkbox" name="quick_releases" value="1" <?php echo $checked; ?>/>
<?php _e( 'Enable quick release updates', 'it-l10n-restrict-content-pro' ); ?>
</label>
<p class="description"><?php _e( 'Some products have quick releases that are created to solve specific issues that some users experience. In order to avoid causing users to have updates show up too frequently, automatic updates to these quick releases are disabled by default. Enabling this feature allows quick releases to be available to the automatic update system. Using this option is only recommended if support has requested that you enable it in order to receive a quick release. You should disable this option at a later time after confirming that the quick release solves the issue for you.', 'it-l10n-restrict-content-pro' ); ?></p>
</td>
</tr>
</tbody>
</table>
<p class="submit">
<input id="save_settings" class="button button-primary" type="submit" value="<?php _e( 'Save Settings', 'it-l10n-restrict-content-pro' ); ?>" />
<input type="hidden" name="action" value="save_settings" />
</p>
</div>
</form>
<?php
}
private function list_licensed_products( $products, $post_data, $action ) {
if ( empty( $products ) )
return;
uksort( $products, 'strnatcasecmp' );
$time = time();
$headings = array(
__( 'Product', 'it-l10n-restrict-content-pro' ),
__( 'Member', 'it-l10n-restrict-content-pro' ),
__( 'Expiration', 'it-l10n-restrict-content-pro' ),
__( 'Remaining Licenses', 'it-l10n-restrict-content-pro' ),
);
if ( ( 'unlicense_packages' != $action ) || empty( $this->errors ) ) {
$post_data = array(
'username' => '',
'password' => '',
'packages' => array(),
);
}
?>
<form id="posts-filter" enctype="multipart/form-data" method="post" action="<?php echo $this->self_url; ?>" autocomplete="off">
<?php wp_nonce_field( 'unlicense_packages', 'ithemes_updater_nonce' ); ?>
<div class="ithemes-updater-products" id="ithemes-updater-licensed">
<h3 class="subtitle"><?php _e( 'Licensed Products', 'it-l10n-restrict-content-pro' ); ?></h3>
<table class="ithemes-updater-listing widefat">
<thead>
<tr>
<th id="cb" class="manage-column column-cb check-column" scope="col">
<label class="screen-reader-text" for="cb-select-all-1"><?php _e( 'Select All' ); ?></label>
<label>
<input id="cb-select-all-1" type="checkbox" />
</label>
</th>
<th scope="col">
<label for="cb-select-all-1"><?php _e( 'Product', 'it-l10n-restrict-content-pro' ); ?></label>
</th>
<th scope="col"><?php _e( 'Member', 'it-l10n-restrict-content-pro' ); ?></th>
<th scope="col"><?php _e( 'Product Status', 'it-l10n-restrict-content-pro' ); ?></th>
<th scope="col"><?php _e( 'Expiration', 'it-l10n-restrict-content-pro' ); ?></th>
<th scope="col"><?php _e( 'Remaining Licenses', 'it-l10n-restrict-content-pro' ); ?></th>
</tr>
</thead>
<tbody>
<?php $count = 0; ?>
<?php foreach ( $products as $name => $data ) : ?>
<?php
if ( -1 == $data['total'] )
$remaining = __( 'unlimited', 'it-l10n-restrict-content-pro' );
else
$remaining = $data['total'] - $data['used'];
// if ( 0 == $remaining )
// $remaining .= ' <a class="button-secondary upgrade">' . __( 'Upgrade', 'it-l10n-restrict-content-pro' ) . '</a>';
$expiration = $this->get_expiration_string( $data['expiration'] );
$expiration = '<time datetime="' . date( 'Y-m-d\TH:i:s\Z', $data['expiration'] ) . '">' . $expiration . '</time>';
$time_left = $data['expiration'] - $time;
$class = 'expiring';
if ( $time_left > ( 86400 * 30 ) )
$class = 'active';
else if ( $time_left <= 0 )
$class = 'expired';
if ( 'expired' == $data['status'] ) {
$class = 'expired';
$remaining = '&nbsp;';
}
$status = ucfirst( $class );
if ( ++$count % 2 ) {
$class .= ' alt';
}
$check_id = "cb-select-{$data['package']}";
$checked = ( in_array( $data['package'], $post_data['packages'] ) ) ? ' checked' : '';
?>
<tr class="<?php echo $class; ?>">
<th class="check-column" scope="row">
<label class="screen-reader-text" for="<?php echo $check_id; ?>"><?php printf( __( 'Select %s' ), $name ); ?></label>
<label for="<?php echo $check_id; ?>">
<input id="<?php echo $check_id ?>" name="packages[]" value="<?php echo $data['package']; ?>" type="checkbox"<?php echo $checked; ?>>
</label>
</th>
<td>
<label for="<?php echo $check_id; ?>"><?php echo $name; ?></label>
</td>
<td><?php echo $data['user']; ?></td>
<td><?php echo $status; ?></td>
<td><?php echo $expiration; ?></td>
<td><?php echo $remaining; ?></td>
</tr>
<?php endforeach; ?>
</tbody>
<tfoot>
<tr>
<td colspan="6">
<input type="text" name="it-updater-username" placeholder="iThemes Username" value="<?php echo esc_attr( $post_data['username'] ); ?>" autocomplete="off" />
<input type="password" name="it-updater-password" placeholder="Password" value="<?php echo esc_attr( $post_data['password'] ); ?>" />
<input class="button-primary" type="submit" name="submit" value="<?php _e( 'Remove Licenses', 'it-l10n-restrict-content-pro' ); ?>" />
<input type="hidden" name="action" value="unlicense_packages" />
</td>
</tr>
</tfoot>
</table>
</div>
</form>
<?php
}
private function list_unlicensed_products( $products, $post_data, $action ) {
if ( empty( $products ) )
return;
uksort( $products, 'strnatcasecmp' );
if ( ( 'license_packages' != $action ) || empty( $this->errors ) ) {
$post_data = array(
'username' => '',
'password' => '',
'packages' => array(),
);
foreach ( $products as $name => $data )
$post_data['packages'][] = $data['package'];
}
?>
<form id="posts-filter" enctype="multipart/form-data" method="post" action="<?php echo $this->self_url; ?>" autocomplete="off">
<?php wp_nonce_field( 'license_packages', 'ithemes_updater_nonce' ); ?>
<div class="ithemes-updater-products" id="ithemes-updater-unlicensed">
<h3 class="subtitle"><?php _e( 'Unlicensed Products', 'it-l10n-restrict-content-pro' ); ?></h3>
<p><?php _e( 'The following products have not been licensed. Licensing a product gives you access to automatic updates from within WordPress.', 'it-l10n-restrict-content-pro' ); ?></p>
<p><?php _e( 'To license products, select the products you wish to license, enter your iThemes membership username and password, and press the License Products button.', 'it-l10n-restrict-content-pro' ); ?></p>
<p><?php printf( __( 'Need help? <a href="%s">Click here for a quick video tutorial</a>.', 'it-l10n-restrict-content-pro' ), 'https://ithemes.com/licensing/' ); ?></p>
<table class="ithemes-updater-listing widefat">
<thead>
<tr>
<th id="cb" class="manage-column column-cb check-column" scope="col">
<label class="screen-reader-text" for="cb-select-all-2"><?php _e( 'Select All' ); ?></label>
<label>
<input id="cb-select-all-2" type="checkbox"<?php if ( count( $post_data['packages'] ) == count( $products ) ) echo ' checked'; ?> />
</label>
</th>
<th scope="col">
<label for="cb-select-all-2"><?php _e( 'Product', 'it-l10n-restrict-content-pro' ); ?></label>
</th>
</tr>
</thead>
<tbody>
<?php $count = 0; ?>
<?php foreach ( $products as $name => $data ) : ?>
<?php
$check_id = "cb-select-{$data['package']}";
if ( 'license_packages' == $action )
$checked = ( in_array( $data['package'], $post_data['packages'] ) ) ? ' checked' : '';
else
$checked = ' checked';
if ( ++$count % 2 ) {
$class = 'alt';
} else {
$class = '';
}
?>
<tr class="<?php echo $class; ?>">
<th class="check-column" scope="row">
<label class="screen-reader-text" for="<?php echo $check_id; ?>"><?php printf( __( 'Select %s' ), $name ); ?></label>
<label for="<?php echo $check_id; ?>">
<input id="<?php echo $check_id; ?>" name="packages[]" value="<?php echo $data['package']; ?>" type="checkbox" <?php echo $checked; ?>>
</label>
</th>
<td>
<label for="<?php echo $check_id; ?>"><?php echo $name; ?></label>
</td>
</tr>
<?php endforeach; ?>
</tbody>
<tfoot>
<tr>
<td colspan="2">
<input type="text" name="it-updater-username" placeholder="iThemes Username" value="<?php echo esc_attr( $post_data['username'] ); ?>" autocomplete="off" />
<input type="password" name="it-updater-password" placeholder="Password" value="<?php echo esc_attr( $post_data['password'] ); ?>" />
<input class="button-primary" type="submit" name="submit" value="<?php _e( 'License Products', 'it-l10n-restrict-content-pro' ); ?>" />
<input type="hidden" name="action" value="license_packages" />
</td>
</tr>
</tfoot>
</table>
</div>
</form>
<?php
}
private function list_unrecognized_products( $products ) {
if ( empty( $products ) )
return;
uksort( $products, 'strnatcasecmp' );
?>
<div class="ithemes-updater-products" id="ithemes-updater-unrecognized">
<h3 class="subtitle"><?php _e( 'Unrecognized Products', 'it-l10n-restrict-content-pro' ); ?></h3>
<p><?php _e( 'The following products were not recognized by the licensing system. This can be due to a bug in the product code, a temporary server issue, or because the product is no longer supported.', 'it-l10n-restrict-content-pro' ); ?></p>
<p><?php printf( __( 'Please check this page again at a later time to see if the problem resolves itself. If the product remains, please contact <a href="%s">iThemes support</a> and provide them with the details given below.', 'it-l10n-restrict-content-pro' ), 'https://ithemes.com/support/' ); ?></p>
<table class="ithemes-updater-listing widefat">
<thead>
<tr>
<th scope="col"><?php _e( 'Product', 'it-l10n-restrict-content-pro' ); ?></th>
<th scope="col"><?php _e( 'Type', 'it-l10n-restrict-content-pro' ); ?></th>
<th scope="col"><?php _e( 'Package', 'it-l10n-restrict-content-pro' ); ?></th>
<th scope="col"><?php _e( 'Version', 'it-l10n-restrict-content-pro' ); ?></th>
<th scope="col"><?php _e( 'Server Response', 'it-l10n-restrict-content-pro' ); ?></th>
</tr>
</thead>
<tbody>
<?php $count = 0; ?>
<?php foreach ( $products as $name => $data ) : ?>
<?php
if ( ( isset( $data['status'] ) && 'error' == $data['status'] ) && ( ! empty( $data['error']['message'] ) ) )
$response = "{$data['error']['message']} ({$data['error']['code']})";
else
$response = __( 'Unknown Error', 'it-l10n-restrict-content-pro' );
if ( ++$count % 2 ) {
$class = 'alt';
} else {
$class = '';
}
?>
<tr class="<?php echo $class; ?>">
<td><?php echo $name; ?></td>
<td><?php echo $data['type']; ?></td>
<td><?php echo $data['package']; ?></td>
<td><?php echo $data['installed']; ?></td>
<td><?php echo $response; ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php
}
public function show_licensed_site_url_confirmation_page( $post_data = array() ) {
$this->show_notices();
$site_url = $GLOBALS['ithemes-updater-settings']->get_licensed_site_url();
if ( empty( $site_url ) ) {
$site_url = network_home_url();
}
if ( empty( $post_data['username'] ) || empty( $this->errors ) ) {
$post_data['username'] = '';
}
if ( empty( $post_data['password'] ) || empty( $this->errors ) ) {
$post_data['password'] = '';
}
if ( ! empty( $post_data['redirect'] ) ) {
$redirect = $post_data['redirect'];
} else if ( ! empty( $_GET['redirect'] ) ) {
$redirect = $_GET['redirect'];
} else {
$redirect = '';
}
?>
<div class="wrap" id="ithemes-updater-site-url-confirmation">
<span class="ithemes-updater-header"></span>
<h2><?php _e( 'Licensing', 'it-l10n-restrict-content-pro' ); ?></h2>
<p><?php _e( "Please confirm this site's licensed URL.", 'it-l10n-restrict-content-pro' ); ?></p>
<form id="posts-filter" enctype="multipart/form-data" method="post" action="<?php echo $this->self_url; ?>">
<?php wp_nonce_field( 'save_licensed_site_url', 'ithemes_updater_nonce' ); ?>
<div id="ithemes-updater-settings">
<div id="ithemes-updater-table-wrapper">
<table class="form-table">
<tbody>
<tr valign="top">
<th scope="row">
<label for="site_url"><?php _e( 'Licensed URL', 'it-l10n-restrict-content-pro' ); ?></label>
<?php if ( is_multisite() ) : ?>
<p class="description"><?php _e( 'The Licensed URL should be the primary URL of this WordPress network.', 'it-l10n-restrict-content-pro' ); ?></p>
<p class="description ithemes-updater-description-warning"><?php _e( 'If not set correctly, some features may not function as expected.', 'it-l10n-restrict-content-pro' ); ?></p>
<?php else : ?>
<p class="description"><?php _e( 'The Licensed URL should be the primary URL of this WordPress site.', 'it-l10n-restrict-content-pro' ); ?></p>
<p class="description ithemes-updater-description-warning"><?php _e( 'If not set correctly, some features may not function as expected.', 'it-l10n-restrict-content-pro' ); ?></p>
<?php endif; ?>
</th>
<td>
<label>
<input id="site_url" class="regular-text" type="text" name="site_url" value="<?php echo esc_attr( $site_url ); ?>" />
</label>
</td>
</tr>
</tbody>
</table>
</div>
<p class="submit">
<input id="save_licensed_site_url" class="button button-primary" type="submit" value="<?php _e( 'Save', 'it-l10n-restrict-content-pro' ); ?>" />
<input type="hidden" name="action" value="save_licensed_site_url" />
<input type="hidden" name="redirect" value="<?php echo esc_attr( $redirect ); ?>" />
</p>
</div>
</form>
</div>
<?php
}
private function save_licensed_site_url( $data ) {
check_admin_referer( 'save_licensed_site_url', 'ithemes_updater_nonce' );
if ( empty( $data['site_url'] ) ) {
$this->errors[] = __( 'The licensed URL cannot be blank.', 'it-l10n-restrict-content-pro' );
} else if ( false === filter_var( $data['site_url'], FILTER_VALIDATE_URL ) ) {
$this->errors[] = __( 'The licensed URL must be a valid URL.', 'it-l10n-restrict-content-pro' );
}
if ( ! empty( $this->errors ) ) {
$this->show_licensed_site_url_confirmation_page( $data );
return;
}
$site_url = $GLOBALS['ithemes-updater-settings']->get_site_url( $data['site_url'] );
if ( $this->has_license_keys() ) {
$site_url_from_server = $GLOBALS['ithemes-updater-settings']->get_licensed_site_url_from_server();
if ( $site_url_from_server !== $site_url ) {
$data['site_url'] = $site_url;
$this->show_relicensing_page( $data );
return;
}
}
$GLOBALS['ithemes-updater-settings']->set_licensed_site_url( $site_url );
$this->messages[] = __( 'Successfully set the Licensed URL.', 'it-l10n-restrict-content-pro' );
if ( empty( $data['redirect'] ) ) {
$redirect = admin_url( 'options-general.php?page=ithemes-licensing&updated_url=true' );
} else {
$redirect = $data['redirect'];
}
echo '<input id="ithemes-updater-redirect-to-url" type="hidden" value="' . esc_attr( $redirect ) . '" />' . "\n";
$this->list_packages();
}
public function show_relicensing_page( $data = array() ) {
$this->show_notices();
$site_url_from_server = $GLOBALS['ithemes-updater-settings']->get_licensed_site_url_from_server();
if ( empty( $data['relicense_option'] ) ) {
$data['relicense_option'] = 'relicense';
}
if ( empty( $data['username'] ) ) {
$data['username'] = '';
}
if ( empty( $data['password'] ) ) {
$data['password'] = '';
}
?>
<div class="wrap" id="ithemes-updater-relicense">
<span class="ithemes-updater-header"></span>
<h2><?php _e( 'Licensing', 'it-l10n-restrict-content-pro' ); ?></h2>
<p><?php printf( __( 'The licenses on this site are for <code>%s</code>.', 'it-l10n-restrict-content-pro' ), $site_url_from_server ); ?></p>
<form id="posts-filter" enctype="multipart/form-data" method="post" action="<?php echo $this->self_url; ?>">
<?php wp_nonce_field( 'relicense', 'ithemes_updater_nonce' ); ?>
<div id="ithemes-updater-settings">
<div id="ithemes-updater-table-wrapper">
<table class="form-table">
<tbody>
<tr valign="top">
<th scope="row">
<label for="relicense_option">
<?php _e( 'License Option', 'it-l10n-restrict-content-pro' ); ?>
</label>
</th>
<td>
<p>
<label>
<input type="radio" name="relicense_option" value="relicense" <?php if ( 'relicense' === $data['relicense_option'] ) echo 'checked="checked"'; ?> />
<?php _e( 'Create new licenses for this site.', 'it-l10n-restrict-content-pro' ); ?>
</label>
</p>
<p class="description ithemes-updater-description-warning"><?php _e( 'Use this option if this site was cloned from another site and needs to have its own licenses.', 'it-l10n-restrict-content-pro' ); ?></p>
<br />
<p>
<label>
<input type="radio" name="relicense_option" value="update" <?php if ( 'update' === $data['relicense_option'] ) echo 'checked="checked"'; ?> />
<?php printf( __( 'Change the existing licenses to be for <code>%s</code>.', 'it-l10n-restrict-content-pro' ), $data['site_url'] ); ?>
</label>
</p>
<p class="description ithemes-updater-description-notice">
<span class="dashicons dashicons-warning"></span>
<?php printf( __( 'Note: If the <code>%s</code> site still exists and is different from this site, you will have to create new licenses on that site.', 'it-l10n-restrict-content-pro' ), $data['site_url'], $site_url_from_server ); ?>
</p>
<p class="description ithemes-updater-description-warning"><?php printf( __( 'Use this option if this site\'s primary URL has changed from <code>%1$s</code> to <code>%2$s</code>.', 'it-l10n-restrict-content-pro' ), $site_url_from_server, $data['site_url'] ); ?></p>
</td>
</tr>
<tr valign="top">
<th scope="row" colspan="2">
<label for="it-updater-username"><?php _e( 'iThemes Username', 'it-l10n-restrict-content-pro' ); ?></label>
<br />
<input id="it-updater-username" type="text" name="it-updater-username" value="<?php echo esc_attr( $data['username'] ); ?>" />
</th>
</tr>
<tr valign="top">
<th scope="row" colspan="2">
<label for="it-updater-password"><?php _e( 'iThemes Password', 'it-l10n-restrict-content-pro' ); ?></label>
<br />
<input id="it-updater-password" type="password" name="it-updater-password" value="<?php echo esc_attr( $data['password'] ); ?>" />
</th>
</tr>
</tbody>
</table>
</div>
<p class="submit">
<input id="relicense" class="button button-primary" type="submit" value="<?php _e( 'Save', 'it-l10n-restrict-content-pro' ); ?>" />
<input type="hidden" name="action" value="relicense" />
<input type="hidden" name="site_url" value="<?php echo esc_attr( $data['site_url'] ); ?>" />
<input type="hidden" name="redirect" value="<?php echo esc_attr( $data['redirect'] ); ?>" />
</p>
</div>
</form>
</div>
<?php
}
private function relicense( $data ) {
check_admin_referer( 'relicense', 'ithemes_updater_nonce' );
if ( empty( $data['username'] ) && empty( $data['password'] ) ) {
$this->errors[] = __( 'You must supply an iThemes membership username and password in order to change the licensed URL.', 'it-l10n-restrict-content-pro' );
} else if ( empty( $data['username'] ) ) {
$this->errors[] = __( 'You must supply an iThemes membership username in order to change the licensed URL.', 'it-l10n-restrict-content-pro' );
} else if ( empty( $data['password'] ) ) {
$this->errors[] = __( 'You must supply an iThemes membership password in order to change the licensed URL.', 'it-l10n-restrict-content-pro' );
} else if ( empty( $data['site_url'] ) ) {
$this->errors[] = __( 'The licensed URL cannot be blank.', 'it-l10n-restrict-content-pro' );
} else if ( false === filter_var( $data['site_url'], FILTER_VALIDATE_URL ) ) {
$this->errors[] = __( 'The licensed URL must be a valid URL.', 'it-l10n-restrict-content-pro' );
} else if ( empty( $data['relicense_option'] ) || ! in_array( $data['relicense_option'], array( 'relicense', 'update' ) ) ) {
$this->errors[] = __( 'You must pick one of the License Option options.', 'it-l10n-restrict-content-pro' );
}
if ( ! empty( $this->errors ) ) {
$this->show_relicensing_page( $data );
return;
}
if ( 'update' === $data['relicense_option'] ) {
$response = Ithemes_Updater_API::set_licensed_site_url( $data['username'], $data['password'], $data['site_url'] );
if ( is_wp_error( $response ) ) {
$this->errors[] = Ithemes_Updater_API::get_error_explanation( $response );
$this->show_relicensing_page( $data );
return;
}
$GLOBALS['ithemes-updater-settings']->set_licensed_site_url( $data['site_url'] );
$this->messages[] = __( 'Successfully updated the Licensed URL.', 'it-l10n-restrict-content-pro' );
} else {
require_once( $GLOBALS['ithemes_updater_path'] . '/keys.php' );
$keys = Ithemes_Updater_Keys::get();
$packages = array_keys( $keys );
$response = Ithemes_Updater_API::deactivate_package( $data['username'], $data['password'], $packages );
if ( is_wp_error( $response ) ) {
$this->errors[] = Ithemes_Updater_API::get_error_explanation( $response );
$this->show_relicensing_page( $data );
return;
}
$GLOBALS['ithemes-updater-settings']->set_licensed_site_url( $data['site_url'] );
$this->messages[] = __( 'Successfully updated the Licensed URL.', 'it-l10n-restrict-content-pro' );
$response = Ithemes_Updater_API::activate_package( $data['username'], $data['password'], $packages );
if ( is_wp_error( $response ) ) {
$this->errors[] = Ithemes_Updater_API::get_error_explanation( $response );
$this->show_relicensing_page( $data );
return;
}
}
if ( empty( $data['redirect'] ) ) {
$redirect = admin_url( 'options-general.php?page=ithemes-licensing&updated_url=true' );
} else {
$redirect = $data['redirect'];
}
echo '<input id="ithemes-updater-redirect-to-url" type="hidden" value="' . esc_attr( $redirect ) . '" />' . "\n";
$this->list_packages();
return;
}
private function show_notices() {
if ( ! empty( $this->messages ) ) {
foreach ( $this->messages as $message ) {
echo "<div class=\"updated fade\"><p><strong>$message</strong></p></div>\n";
}
}
if ( ! empty( $this->errors ) ) {
foreach ( $this->errors as $error ) {
echo "<div class=\"error\"><p><strong>$error</strong></p></div>\n";
}
}
if ( ! empty( $this->soft_errors ) ) {
foreach ( $this->soft_errors as $error ) {
echo "<div class=\"error\"><p><strong>$error</strong></p></div>\n";
}
}
}
private function get_expiration_string( $expiration_timestamp ) {
$time = time();
$time_left = $expiration_timestamp - $time;
$expired = false;
if ( $time_left < 0 ) {
$expired = true;
$time_left = abs( $time_left );
}
if ( $time_left > ( 86400 * 30 ) )
$expiration = date( 'Y-m-d', $expiration_timestamp );
else {
if ( $time_left > 86400 )
$expiration = sprintf( _n( '%d day', '%d days', intval( $time_left / 86400 ), 'it-l10n-restrict-content-pro' ), intval( $time_left / 86400 ) );
else if ( $time_left > 3600 )
$expiration = sprintf( _n( '%d hour', '%d hours', intval( $time_left / 3600 ), 'it-l10n-restrict-content-pro' ), intval( $time_left / 3600 ) );
else if ( $time_left > 60 )
$expiration = sprintf( _n( '%d minute', '%d minutes', intval( $time_left / 60 ), 'it-l10n-restrict-content-pro' ), intval( $time_left / 60 ) );
else
$expiration = sprintf( _n( '%d second', '%d seconds', $time_left, 'it-l10n-restrict-content-pro' ), intval( $time_left / 60 ) );
if ( $expired )
$expiration = sprintf( __( '%s ago', 'it-l10n-restrict-content-pro' ), $expiration );
}
return $expiration;
}
private function has_license_keys() {
require_once( $GLOBALS['ithemes_updater_path'] . '/keys.php' );
$keys = Ithemes_Updater_Keys::get();
$legacy_keys = Ithemes_Updater_Keys::get_legacy();
if ( empty( $keys ) && empty( $legacy_keys ) ) {
return false;
}
return true;
}
}
new Ithemes_Updater_Settings_Page();

View File

@@ -0,0 +1,460 @@
<?php
/*
Central management of options storage and registered packages.
Written by Chris Jean for iThemes.com
Version 1.3.0
Version History
1.0.0 - 2013-09-19 - Chris Jean
Split off from the old Ithemes_Updater_Init class.
1.0.1 - 2013-09-20 - Chris Jean
Fixed bug where the old ithemes-updater-object global was being referenced.
1.1.0 - 2013-10-04 - Chris Jean
Enhancement: Added handler for GET query variable: ithemes-updater-force-minor-update.
Bug Fix: Changed URL regex for applying the CA patch to only apply to links for api.ithemes.com and not the S3 links.
Bug Fix: A check to ensure that the $GLOBALS['ithemes_updater_path'] variable is set properly.
Misc: Updated file reference for ca/cacert.crt to ca/roots.crt.
1.2.0 - 2013-10-23 - Chris Jean
Enhancement: Added the quick_releases setting.
Enhancement: Added an explicit flush when the ithemes-updater-force-minor-update query variable is used
Misc: Removed the show_on_sites setting as it is no longer needed.
1.3.0 - 2014-10-23 - Chris Jean
Improved flushing system.
Reduced cache timeout durations.
Added timeout multiplier.
Removed CA patch code as it's now handled in the server code.
Updated code to meet WordPress coding standards.
*/
class Ithemes_Updater_Settings {
private $option_name = 'ithemes-updater-cache';
private $packages = array();
private $new_packages = array();
private $options = false;
private $options_modified = false;
private $do_flush = false;
private $initialized = false;
private $db_failure = false;
private $default_options = array(
'timeout-multiplier' => 1,
'expiration' => 0,
'timestamp' => 0,
'packages' => array(),
'update_plugins' => array(),
'update_plugins_no_update' => array(),
'update_themes' => array(),
'update_themes_no_update' => array(),
'use_ca_patch' => false,
'use_ssl' => true,
'quick_releases' => false,
);
public function __construct() {
$GLOBALS['ithemes-updater-settings'] = $this;
add_action( 'init', array( $this, 'init' ) );
add_action( 'shutdown', array( $this, 'shutdown' ), -10 );
}
public function init() {
if ( $this->initialized ) {
return;
}
$this->initialized = true;
if ( ! isset( $GLOBALS['ithemes_updater_path'] ) ) {
$GLOBALS['ithemes_updater_path'] = dirname( __FILE__ );
}
$this->load();
do_action( 'ithemes_updater_register', $this );
$this->new_packages = array_diff( array_keys( $this->packages ), $this->options['packages'] );
if ( isset( $_GET['ithemes-updater-force-quick-release-update'] ) && ! isset( $_GET['ithemes-updater-force-minor-update'] ) ) {
$_GET['ithemes-updater-force-minor-update'] = $_GET['ithemes-updater-force-quick-release-update'];
}
$flushed = false;
if ( isset( $_GET['ithemes-updater-force-minor-update'] ) && current_user_can( 'manage_options' ) ) {
if ( $_GET['ithemes-updater-force-minor-update'] ) {
$this->options['force_minor_version_update'] = time() + 3600;
$this->update_options( $this->options );
$this->flush( 'forced minor version update' );
$flushed = true;
} else {
unset( $this->options['force_minor_version_update'] );
$this->update_options( $this->options );
$this->flush( 'unset forced minor version update' );
$flushed = true;
}
} else if ( isset( $this->options['force_minor_version_update'] ) && ( $this->options['force_minor_version_update'] < time() ) ) {
unset( $this->options['force_minor_version_update'] );
$this->update_options( $this->options );
}
if ( ! $flushed ) {
if ( ! empty( $_GET['ithemes-updater-force-refresh'] ) && current_user_can( 'manage_options' ) ) {
$this->flush( 'forced' );
} else if ( empty( $this->options['expiration'] ) || ( $this->options['expiration'] <= time() ) ) {
$this->flush( 'expired' );
} else if ( $this->is_expired( $this->options['timestamp'] ) ) {
$this->flush( 'got stale' );
} else if ( ! empty( $this->new_packages ) ) {
$this->update_packages();
$this->flush( 'new packages' );
}
}
}
public function load() {
if ( false !== $this->options ) {
return;
}
require_once( $GLOBALS['ithemes_updater_path'] . '/functions.php' );
$this->options = Ithemes_Updater_Functions::get_site_option( $this->option_name );
if ( false === $this->options ) {
$this->db_failure = true;
}
if ( ! is_array( $this->options ) ) {
$this->options = array();
}
$this->options = array_merge( $this->default_options, $this->options );
if ( 0 == $this->options['timestamp'] ) {
$this->update();
}
$this->update_site_url_history();
}
public function shutdown() {
$this->flush();
if ( $this->options_modified && false === $this->db_failure ) {
update_site_option( $this->option_name, $this->options );
}
}
public function queue_flush() {
$this->do_flush = true;
}
public function flush( $reason = '' ) {
if ( empty( $reason ) && ! $this->do_flush ) {
return;
}
$this->do_flush = false;
$this->update();
}
public function update() {
$this->init();
require_once( $GLOBALS['ithemes_updater_path'] . '/updates.php' );
Ithemes_Updater_Updates::run_update();
}
public function get_options() {
$this->init();
return $this->options;
}
public function get_option( $var ) {
$this->init();
if ( isset( $this->options[$var] ) ) {
return $this->options[$var];
}
return null;
}
public function update_options( $updates ) {
$this->init();
$this->options = array_merge( $this->options, $updates );
$this->options_modified = true;
}
public function update_packages() {
$this->update_options( array( 'packages' => array_keys( $this->packages ) ) );
}
public function get_package_details( $package = false ) {
$details = $this->get_option( 'package_details' );
if ( false === $package ) {
return $details;
} else if ( isset( $details[$package] ) ) {
return $details[$package];
} else {
return false;
}
}
// Potential license status values: "active", "expired", "unlicensed", "error" (unexpected server response), and false (data is not present for the package).
public function get_license_status( $package = false ) {
$details = $this->get_package_details( $package );
if ( false === $package ) {
$statuses = array();
foreach ( $details as $package => $data ) {
$statuses[$package] = $data['license_status'];
}
return $statuses;
} else if ( is_array( $details ) ) {
return $details['license_status'];
} else {
return false;
}
}
public function get_packages() {
return $this->packages;
}
public function get_new_packages() {
return $this->new_packages;
}
public function filter_update_plugins( $update_plugins ) {
if ( ! is_object( $update_plugins ) ) {
return $update_plugins;
}
if ( ! isset( $update_plugins->response ) || ! is_array( $update_plugins->response ) ) {
$update_plugins->response = array();
}
if ( ! isset( $update_plugins->no_update ) || ! is_array( $update_plugins->no_update ) ) {
$update_plugins->no_update = array();
}
$this->flush();
if ( ! is_array( $this->options ) || ! isset( $this->options['update_plugins'] ) ) {
$this->load();
}
if ( isset( $this->options['update_plugins'] ) && is_array( $this->options['update_plugins'] ) ) {
$update_plugins->response = array_merge( $update_plugins->response, $this->options['update_plugins'] );
$update_plugins->no_update = array_merge( $update_plugins->no_update, $this->options['update_plugins_no_update'] );
}
return $update_plugins;
}
public function filter_update_themes( $update_themes ) {
if ( ! is_object( $update_themes ) ) {
return $update_themes;
}
if ( ! isset( $update_themes->response ) || ! is_array( $update_themes->response ) ) {
$update_themes->response = array();
}
if ( ! isset( $update_themes->no_update ) || ! is_array( $update_themes->no_update ) ) {
$update_themes->no_update = array();
}
$this->flush();
if ( ! is_array( $this->options ) || ! isset( $this->options['update_themes'] ) ) {
$this->load();
}
if ( isset( $this->options['update_themes'] ) && is_array( $this->options['update_themes'] ) ) {
$update_themes->response = array_merge( $update_themes->response, $this->options['update_themes'] );
$update_themes->no_update = array_merge( $update_themes->no_update, $this->options['update_themes_no_update'] );
}
return $update_themes;
}
public function register( $slug, $file ) {
$this->packages[$slug][] = $file;
}
private function is_expired( $timestamp ) {
$multiplier = $this->get_option( 'timeout-multiplier' );
if ( $multiplier < 1 ) {
$multiplier = 1;
} else if ( $multiplier > 10 ) {
$multiplier = 10;
}
if ( current_user_can( 'update_themes' ) || current_user_can( 'update_plugins' ) ) {
if ( ! empty( $_POST['action'] ) && ( 'heartbeat' == $_POST['action'] ) ) {
$timeout = 43200;
} else {
$page = empty( $_GET['page'] ) ? $GLOBALS['pagenow'] : $_GET['page'];
switch ( $page ) {
case 'update.php' :
case 'update-core.php' :
case 'ithemes-licensing' :
$timeout = 60;
break;
case 'plugins.php' :
case 'themes.php' :
$timeout = 600;
break;
default :
$timeout = 3600;
}
}
} else {
$timeout = 7200;
}
$timeout *= $multiplier;
if ( $timestamp <= ( time() - $timeout ) ) {
return true;
}
return false;
}
/*
public function get_hostname_history() {
$this->get_canonical_hostname();
return $this->options['hostname_details']['history'];
}
public function get_canonical_hostname() {
if ( ! is_array( $this->options ) ) {
$this->load();
}
$hostname = $this->get_hostname();
if ( ! isset( $this->options['hostname_details'] ) || ! is_array( $this->options['hostname_details'] ) ) {
$this->options['hostname_details'] = array();
$this->options_modified = true;
}
if ( empty( $this->options['hostname_details']['canonical'] ) ) {
$this->options['hostname_details']['canonical'] = $hostname;
$this->options_modified = true;
}
if ( empty( $this->options['hostname_details']['history'] ) || ! is_array( $this->options['hostname_details']['history'] ) || ( time() - max( $this->options['hostname_details']['history'] ) > 600 ) ) {
$this->options['hostname_details']['history'][$hostname] = time();
$this->options_modified = true;
}
return $this->options['hostname_details']['canonical'];
}
public function update_canonical_hostname( $hostname ) {
$this->options['hostname_details']['canonical'] = $this->get_hostname( $hostname );
$this->options_modified = true;
}
*/
public function update_site_url_history() {
$site_url = $this->get_site_url();
if ( ! isset( $this->options['site_url_history'] ) || ! is_array( $this->options['site_url_history'] ) ) {
$this->options['site_url_history'] = array();
$this->options_modified = true;
}
if ( empty( $this->options['site_url_history'] ) || ! is_array( $this->options['site_url_history'] ) || ( time() - max( $this->options['site_url_history'] ) > 600 ) ) {
$this->options['site_url_history'][$site_url] = time();
$this->options_modified = true;
}
}
public function get_site_url( $url = false ) {
if ( empty( $url ) ) {
$url = network_home_url();
}
$url = strtolower( preg_replace( '|/$|', '', $url ) );
if ( is_ssl() ) {
$url = preg_replace( '|^https?:|', 'https:', $url );
} else {
$url = preg_replace( '|^https?:|', 'http:', $url );
}
return $url;
}
public function is_request_on_licensed_site_url() {
return $this->get_licensed_site_url() === $this->get_site_url();
}
public function get_licensed_site_url_from_server() {
$response = Ithemes_Updater_API::get_licensed_site_url();
if ( ! is_wp_error( $response ) && is_array( $response ) && ! empty( $response['site_url'] ) ) {
return $this->get_site_url( "http://{$response['site_url']}" );
}
return '';
}
public function set_licensed_site_url( $url ) {
$url = $this->get_site_url( $url );
$url = preg_replace( '|^https?://|', '', $url );
$this->options['site_url'] = $url;
$this->options_modified = true;
}
public function get_licensed_site_url() {
if ( ! is_array( $this->options ) ) {
$this->load();
}
if ( empty( $this->options['site_url'] ) ) {
return false;
} else {
return $this->get_site_url( "http://{$this->options['site_url']}" );
}
}
public function is_licensed_site_url_confirmed() {
if ( false === $this->get_licensed_site_url() ) {
return false;
} else {
return true;
}
}
}
new Ithemes_Updater_Settings();

View File

@@ -0,0 +1,177 @@
<?php
/*
Provides a simple interface for connecting iThemes' packages with the updater API.
Written by Chris Jean for iThemes.com
Version 1.4.1
Version History
1.0.0 - 2013-04-11 - Chris Jean
Release ready
1.0.1 - 2013-09-19 - Chris Jean
Changed the logic in process_server_response to skip updatable packages that have the 'upgrade' data set to a true value.
Updated requires to not use dirname().
Updated ithemes-updater-object to ithemes-updater-settings.
1.1.0 - 2013-10-02 - Chris Jean
Updated 'url' data for themes to point to the plugin-install.php file in order to show changelog notes as plugins have.
1.2.0 - 2013-10-04 - Chris Jean
Added logic to handle skipped updates when force_minor_version_update is set.
1.2.1 - 2013-10-04 - Chris Jean
Added a fix to prevent the code from executing if it is loaded by an older updater version. This can happen when updating a theme or plugin.
1.3.0 - 2013-10-23 - Chris Jean
Enhancement: Added support for quick_releases setting to force an update to a quick release.
1.4.0 - 2014-11-13 - Chris Jean
Improved cache flush handling.
Removed server-cache setting change handler.
Added timeout-multiplier setting change handler.
1.4.1 - 2015-04-23 - Chris Jean
Added "plugin" entry for plugins in order to handle changes in WordPress 4.2.
Added "theme" entry for themes in order to handle changes in WordPress 4.2.
Added support for both "autoupdate" and "upgrade_notice" fields to be supplied from the server.
*/
class Ithemes_Updater_Updates {
public static function run_update() {
// Prevent the code from running if the code was loaded by an older updater version.
if ( ! isset( $GLOBALS['ithemes_updater_path'] ) ) {
return;
}
require_once( $GLOBALS['ithemes_updater_path'] . '/api.php' );
require_once( $GLOBALS['ithemes_updater_path'] . '/packages.php' );
require_once( $GLOBALS['ithemes_updater_path'] . '/keys.php' );
$keys = Ithemes_Updater_Keys::get();
$legacy_keys = Ithemes_Updater_Keys::get_legacy();
if ( empty( $keys ) && empty( $legacy_keys ) ) {
return;
}
Ithemes_Updater_API::get_package_details( false );
}
public static function process_server_response( $response, $cached = false ) {
if ( empty( $response['packages'] ) ) {
return;
}
require_once( $GLOBALS['ithemes_updater_path'] . '/keys.php' );
require_once( $GLOBALS['ithemes_updater_path'] . '/packages.php' );
require_once( $GLOBALS['ithemes_updater_path'] . '/settings.php' );
$keys = array();
foreach ( $response['packages'] as $package => $data ) {
if ( isset( $data['key'] ) ) {
$keys[$package] = $data['key'];
} else if ( isset( $data['status'] ) && ( 'inactive' == $data['status'] ) ) {
$keys[$package] = '';
}
}
Ithemes_Updater_Keys::set( $keys );
$details = Ithemes_Updater_Packages::get_full_details( $response );
$updates = array(
'update_themes' => array(),
'update_themes_no_update' => array(),
'update_plugins' => array(),
'update_plugins_no_update' => array(),
'package_details' => array(),
'expiration' => $details['expiration'],
);
if ( ! $cached ) {
$updates['timestamp'] = time();
}
if ( isset( $response['timeout_multiplier'] ) ) {
$updates['timeout-multiplier'] = $response['timeout_multiplier'];
}
if ( ! isset( $updates['timeout-multiplier'] ) || ( $updates['timeout-multiplier'] < 1 ) ) {
$updates['timeout-mulitplier'] = 1;
} else if ( $updates['timeout-multiplier'] > 10 ) {
$updates['timeout-mulitplier'] = 10;
}
$use_ssl = $GLOBALS['ithemes-updater-settings']->get_option( 'use_ssl' );
foreach ( $details['packages'] as $path => $data ) {
$updates['package_details'][$data['package']] = array(
'type' => $data['type'],
'path' => $path,
'version' => $data['installed'],
'license_status' => $data['status'],
);
if ( empty( $data['package-url'] ) ) {
continue;
}
$force_minor_version_update = $GLOBALS['ithemes-updater-settings']->get_option( 'force_minor_version_update' );
$quick_releases = $GLOBALS['ithemes-updater-settings']->get_option( 'quick_releases' );
$update_available = true;
if ( version_compare( $data['installed'], $data['available'], '>=' ) ) {
$update_available = false;
} else if ( ( isset( $data['upgrade'] ) && ! $data['upgrade'] ) && ! $force_minor_version_update && ! $quick_releases ) {
$update_available = false;
}
$update = $data['wp_update_data'];
if ( 'plugin' == $data['type'] ) {
$update['slug'] = dirname( $path );
$update['plugin'] = $path;
if ( isset( $update['compatibility'] ) && is_array( $update['compatibility'] ) ) {
$update['compatibility'] = (object) $update['compatibility'];
}
} else {
$update['theme'] = $path;
$update['url'] = self_admin_url( 'plugin-install.php?tab=plugin-information&plugin=' . dirname( $path ) . '&section=changelog&TB_iframe=true&width=600&height=800' );
}
if ( ! $update_available ) {
unset( $update['autoupdate'] );
unset( $update['disable_autoupdate'] );
unset( $update['upgrade_notice'] );
}
if ( ! $use_ssl ) {
$update['package'] = preg_replace( '/^https/', 'http', $update['package'] );
}
if ( 'plugin' == $data['type'] ) {
$update = (object) $update;
} else {
$path = dirname( $path );
}
if ( $update_available ) {
$updates["update_{$data['type']}s"][$path] = $update;
} else {
$updates["update_{$data['type']}s_no_update"][$path] = $update;
}
}
$GLOBALS['ithemes-updater-settings']->update_options( $updates );
}
}

View File

@@ -0,0 +1,339 @@
<?php
/**
* Manage licensing of iThemes plugins and themes.
*/
final class Ithemes_Updater_WP_CLI_Ithemes_Licensing extends WP_CLI_Command {
/**
* Show iThemes plugins and themes on the site and the licensing status for each.
*
* ## OPTIONS
*
* [<product>]
* : Only show the status for the supplied product.
*
* [--verbose]
* : Show increased detail about each product.
*
* [--status=<status>]
* : Limit the list to products with a specific licensing status.
* ---
* default: all
* options:
* - all
* - active
* - inactive
*
* [--format=<format>]
* : Output formatting
* ---
* default: table
* options:
* - table
* - json
* - csv
* - yaml
* - count
*
* @param array $args
* @param array $assoc_args
*/
public function show( $args, $assoc_args ) {
$this->verify_updater_is_present();
require_once( $GLOBALS['ithemes_updater_path'] . '/api.php' );
if ( ! empty( $args ) ) {
list( $product ) = $args;
} else {
$product = null;
}
$default_args = array(
'verbose' => false,
'status' => 'all',
'format' => 'table',
);
$assoc_args = wp_parse_args( $assoc_args, $default_args );
$package_details = Ithemes_Updater_API::get_package_details( false );
if ( is_wp_error( $package_details ) ) {
WP_CLI::error( sprintf( 'Unable to retrieve product details: %1$s (%2$s)', $package_details->get_error_message(), $package_details->get_error_code() ) );
return;
}
ksort( $package_details['packages'] );
$packages = array();
foreach ( $package_details['packages'] as $name => $details ) {
if ( ! is_null( $product ) && $name !== $product ) {
continue;
}
if ( ! isset( $details['status'] ) ) {
$details['status'] = 'inactive';
}
if ( 'all' !== $assoc_args['status'] && $details['status'] !== $assoc_args['status'] ) {
continue;
}
$package = array(
'name' => $name,
'status' => isset( $details['status'] ) ? $details['status'] : 'inactive',
);
if ( $assoc_args['verbose'] ) {
$package = array_merge( $package, $details );
}
$packages[] = $package;
}
if ( ! empty( $packages ) ) {
if ( $assoc_args['verbose'] ) {
$columns = array(
'name',
'status',
'used',
'total',
'ver',
'user',
'sub_expire',
'release_timestamp',
'upgrade',
'link_expire',
'link',
'key',
'error',
);
} else {
$columns = array(
'name',
'status',
);
}
foreach ( $packages as &$package ) {
foreach ( $columns as $column ) {
if ( ! isset( $package[$column] ) ) {
$package[$column] = '';
}
}
}
WP_CLI\Utils\format_items( $assoc_args['format'], $packages, $columns );
} else if ( $assoc_args['verbose'] ) {
WP_CLI::error( 'No iThemes products were found matching the current criteria.' );
}
}
/**
* Activate licensing for one or more products
*
* ## OPTIONS
*
* Specificy the iThemes account username and password using the environment variables ITHEMES_USER and ITHEMES_PASS
*
* [<product>...]
* : Product to activate licensing for.
*
* [--ithemes-user=<user>]
* : iThemes member username. This value can also be supplied by an ITHEMES_USER environment variable.
*
* [--ithemes-pass=<pass>]
* : iThemes member password. This value can also be supplied by an ITHEMES_PASS environment variable.
*
* [--all]
* : Activate licensing for all currently installed, inactive products.
*
* ## EXAMPLES
*
* # Activate licensing for the ithemes-security-pro plugin.
* $ wp ithemes-licensing activate ithemes-security-pro --ithemes-user=example --ithemes-pass=example
*
* # Activate licensing for all installed iThemes products using environment variables for member details.
* $ ITHEMES_USER=example ITHEMES_PASS=example wp ithemes-licensing activate --all
*
* @param array $args
* @param array $assoc_args
*/
public function activate( $args, $assoc_args ) {
$this->handle_request( 'activate', $args, $assoc_args );
}
/**
* Deactivate licensing for one or more products
*
* ## OPTIONS
*
* Specificy the iThemes account username and password using the environment variables ITHEMES_USER and ITHEMES_PASS
*
* [<product>...]
* : Product to deactivate licensing for.
*
* [--ithemes-user=<user>]
* : iThemes member username. This value can also be supplied by an ITHEMES_USER environment variable.
*
* [--ithemes-pass=<pass>]
* : iThemes member password. This value can also be supplied by an ITHEMES_PASS environment variable.
*
* [--all]
* : Deactivate licensing for all currently installed, active products.
*
* ## EXAMPLES
*
* # Deactivate licensing for the ithemes-security-pro plugin.
* $ wp ithemes-licensing deactivate ithemes-security-pro --ithemes-user=example --ithemes-pass=example
*
* # Deactivate licensing for all installed iThemes products using environment variables for member details.
* $ ITHEMES_USER=example ITHEMES_PASS=example wp ithemes-licensing deactivate --all
*
* @param array $args
* @param array $assoc_args
*/
public function deactivate( $args, $assoc_args ) {
$this->handle_request( 'deactivate', $args, $assoc_args );
}
private function handle_request( $verb, $args, $assoc_args ) {
$this->verify_updater_is_present();
require_once( $GLOBALS['ithemes_updater_path'] . '/api.php' );
require_once( $GLOBALS['ithemes_updater_path'] . '/functions.php' );
$products = $args;
$default_args = array(
'all' => false,
);
$assoc_args = wp_parse_args( $assoc_args, $default_args );
$user = getenv( 'ITHEMES_USER' );
$pass = getenv( 'ITHEMES_PASS' );
if ( isset( $assoc_args['ithemes-user'] ) ) {
$user = $assoc_args['ithemes-user'];
}
if ( isset( $assoc_args['ithemes-pass'] ) ) {
$pass = $assoc_args['ithemes-pass'];
}
if ( empty( $user ) ) {
WP_CLI::error( 'You must supply the iThemes member username.' );
return;
}
if ( empty( $pass ) ) {
WP_CLI::error( 'You must supply the iThemes member password.' );
return;
}
if ( empty( $products ) && ! $assoc_args['all'] ) {
WP_CLI::error( "You must supply one or more products or use the --all flag." );
return;
} else if ( ! empty( $products ) && $assoc_args['all'] ) {
WP_CLI::error( 'You must supply one or more products or use the --all flag, but not both.' );
return;
}
$package_details = Ithemes_Updater_API::get_package_details( false );
if ( $assoc_args['all'] ) {
if ( is_wp_error( $package_details ) ) {
WP_CLI::error( sprintf( 'Unable to retrieve product details: %1$s (%2$s)', $package_details->get_error_message(), $package_details->get_error_code() ) );
return;
}
$products = array();
foreach ( $package_details['packages'] as $name => $details ) {
if ( 'activate' === $verb xor ( isset( $details['status'] ) && 'active' === $details['status'] ) ) {
$products[] = $name;
}
}
if ( empty( $products ) ) {
if ( 'activate' === $verb ) {
WP_CLI::success( 'No products with inactive licensing were found.' );
} else {
WP_CLI::success( 'No products with active licensing were found.' );
}
return;
}
} else {
foreach ( $products as $index => $product ) {
if ( ! isset( $package_details['packages'][$product] ) ) {
WP_CLI::error( "$product is not a valid iThemes product. Licensing for it cannot be {$verb}d." );
unset( $products[$index] );
}
}
if ( empty( $products ) ) {
return;
}
}
if ( 'activate' === $verb ) {
$response = Ithemes_Updater_API::activate_package( $user, $pass, $products );
} else {
$response = Ithemes_Updater_API::deactivate_package( $user, $pass, $products );
}
if ( is_wp_error( $response ) ) {
WP_CLI::error( Ithemes_Updater_API::get_error_explanation( $response ) );
return;
}
if ( empty( $response['packages'] ) ) {
if ( 1 === count( $products ) ) {
WP_CLI::error( "An unknown server error occurred. Please try to $verb your product license again at another time." );
} else {
WP_CLI::error( "An unknown server error occurred. Please try to $verb your product licenses again at another time." );
}
return;
}
uksort( $response['packages'], 'strnatcasecmp' );
foreach ( $response['packages'] as $package => $data ) {
if ( preg_match( '/ \|\|\| \d+$/', $package ) ) {
continue;
}
if ( 'activate' === $verb ) {
if ( ! empty( $data['key'] ) ) {
WP_CLI::success( "Activated the product license for $package." );
} else if ( ! empty( $data['status'] ) && ( 'expired' === $data['status'] ) ) {
WP_CLI::warning( "Unable to activate the product license for $package. Your product subscription has expired." );
} else {
WP_CLI::error( "Unable to activate the product license for $package. {$data['error']['message']}" );
}
} else {
if ( isset( $data['status'] ) && ( 'inactive' == $data['status'] ) ) {
WP_CLI::success( "Deactivated the product license for $package." );
} else if ( isset( $data['error'] ) && isset( $data['error']['message'] ) ) {
WP_CLI::error( "Unable to deactivate the product license for $package. {$data['error']['message']}" );
} else {
WP_CLI::error( "Unable to deactivate the product license for $package. Unknown server error." );
}
}
}
}
private function verify_updater_is_present() {
if ( empty( $GLOBALS['ithemes_updater_path'] ) ) {
if ( defined( 'ITHEMES_UPDATER_DISABLE' ) && ITHEMES_UPDATER_DISABLE ) {
WP_CLI::error( 'The iThemes updater library is disabled on this site due to the ITHEMES_UPDATER_DISABLE define being set to a truthy value. Licensing for this site cannot be managed.' );
} else {
WP_CLI::error( 'The $GLOBALS[\'ithemes_updater_path\'] variable is empty or not set. This indicates that the updater was not loaded although the cause for this is not known.' );
}
exit;
}
}
}