| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555 |
- <?php
- if ( ! defined( 'ABSPATH' ) ) {
- die( '-1' );
- }
- /**
- * WPBakery WPBakery Page Builder Plugin
- *
- * @package WPBakeryPageBuilder
- *
- */
- /**
- * Manage license
- *
- * Activation/deactivation is done via support portal and does not use Envato username and
- * api_key anymore
- */
- class Vc_License {
- /**
- * Option name where license key is stored
- *
- * @var string
- */
- protected static $license_key_option = 'js_composer_purchase_code';
- /**
- * Option name where license key token is stored
- *
- * @var string
- */
- protected static $license_key_token_option = 'license_key_token';
- /**
- * @var string
- */
- protected static $support_host = 'https://support.wpbakery.com';
- /**
- * @var string
- */
- public $error = null;
- public function init() {
- if ( 'vc-updater' === vc_get_param( 'page' ) ) {
- $activate = vc_get_param( 'activate' );
- $deactivate = vc_get_param( 'deactivate' );
- if ( $activate ) {
- $this->finishActivationDeactivation( true, $activate );
- } elseif ( $deactivate ) {
- $this->finishActivationDeactivation( false, $deactivate );
- }
- }
- add_action( 'wp_ajax_vc_get_activation_url', array(
- $this,
- 'startActivationResponse',
- ) );
- add_action( 'wp_ajax_vc_get_deactivation_url', array(
- $this,
- 'startDeactivationResponse',
- ) );
- add_action( 'wp_ajax_nopriv_vc_check_license_key', array(
- vc_license(),
- 'checkLicenseKeyFromRemote',
- ) );
- }
- /**
- * Output notice
- *
- * @param string $message
- * @param bool $success
- */
- public function outputNotice( $message, $success = true ) {
- echo sprintf( '<div class="%s"><p>%s</p></div>', (bool) $success ? 'updated' : 'error', esc_html( $message ) );
- }
- /**
- * Show error
- *
- * @param string $error
- */
- public function showError( $error ) {
- $this->error = $error;
- add_action( 'admin_notices', array(
- $this,
- 'outputLastError',
- ) );
- }
- /**
- * Output last error
- */
- public function outputLastError() {
- $this->outputNotice( $this->error, false );
- }
- /**
- * Output successful activation message
- */
- public function outputActivatedSuccess() {
- $this->outputNotice( esc_html__( 'WPBakery Page Builder successfully activated.', 'js_composer' ), true );
- }
- /**
- * Output successful deactivation message
- */
- public function outputDeactivatedSuccess() {
- $this->outputNotice( esc_html__( 'WPBakery Page Builder successfully deactivated.', 'js_composer' ), true );
- }
- /**
- * Finish pending activation/deactivation
- *
- * 1) Make API call to support portal
- * 2) Receive success status and license key
- * 3) Set new license key
- *
- * @param bool $activation
- * @param string $user_token
- *
- * @return bool
- */
- public function finishActivationDeactivation( $activation, $user_token ) {
- if ( ! $this->isValidToken( $user_token ) ) {
- $this->showError( esc_html__( 'Token is not valid or has expired', 'js_composer' ) );
- return false;
- }
- if ( $activation ) {
- $url = self::$support_host . '/finish-license-activation';
- } else {
- $url = self::$support_host . '/finish-license-deactivation';
- }
- $params = array(
- 'body' => array( 'token' => $user_token ),
- 'timeout' => 30,
- );
- // FIX SSL SNI
- $filter_add = true;
- if ( function_exists( 'curl_version' ) ) {
- $version = curl_version();
- if ( version_compare( $version['version'], '7.18', '>=' ) ) {
- $filter_add = false;
- }
- }
- if ( $filter_add ) {
- add_filter( 'https_ssl_verify', '__return_false' );
- }
- $response = wp_remote_post( $url, $params );
- if ( $filter_add ) {
- remove_filter( 'https_ssl_verify', '__return_false' );
- }
- if ( is_wp_error( $response ) ) {
- $this->showError( sprintf( esc_html__( '%s. Please try again.', 'js_composer' ), $response->get_error_message() ) );
- return false;
- }
- if ( 200 !== $response['response']['code'] ) {
- $this->showError( sprintf( esc_html__( 'Server did not respond with OK: %s', 'js_composer' ), $response['response']['code'] ) );
- return false;
- }
- $json = json_decode( $response['body'], true );
- if ( ! $json || ! isset( $json['status'] ) ) {
- $this->showError( esc_html__( 'Invalid response structure. Please contact us for support.', 'js_composer' ) );
- return false;
- }
- if ( ! $json['status'] ) {
- $this->showError( esc_html__( 'Something went wrong. Please contact us for support.', 'js_composer' ) );
- return false;
- }
- if ( $activation ) {
- if ( ! isset( $json['license_key'] ) || ! $this->isValidFormat( $json['license_key'] ) ) {
- $this->showError( esc_html__( 'Invalid response structure. Please contact us for support.', 'js_composer' ) );
- return false;
- }
- $this->setLicenseKey( $json['license_key'] );
- add_action( 'admin_notices', array(
- $this,
- 'outputActivatedSuccess',
- ) );
- } else {
- $this->setLicenseKey( '' );
- add_action( 'admin_notices', array(
- $this,
- 'outputDeactivatedSuccess',
- ) );
- }
- $this->setLicenseKeyToken( '' );
- return true;
- }
- /**
- * @return boolean
- */
- public function isActivated() {
- return (bool) $this->getLicenseKey();
- }
- /**
- * Check license key from remote
- *
- * Function is used by support portal to check if VC w/ specific license is still installed
- */
- public function checkLicenseKeyFromRemote() {
- $license_key = vc_request_param( 'license_key' );
- if ( ! $this->isValid( $license_key ) ) {
- $response = array(
- 'status' => false,
- 'error' => esc_html__( 'Invalid license key', 'js_composer' ),
- );
- } else {
- $response = array( 'status' => true );
- }
- die( wp_json_encode( $response ) );
- }
- /**
- * Generate action URL
- *
- * @return string
- */
- public function generateActivationUrl() {
- $token = sha1( $this->newLicenseKeyToken() );
- $url = esc_url( self::getSiteUrl() );
- $redirect = esc_url( vc_updater()->getUpdaterUrl() );
- return sprintf( '%s/activate-license?token=%s&url=%s&redirect=%s', self::$support_host, $token, $url, $redirect );
- }
- /**
- * Generate action URL
- *
- * @return string
- */
- public function generateDeactivationUrl() {
- $license_key = $this->getLicenseKey();
- $token = sha1( $this->newLicenseKeyToken() );
- $url = esc_url( self::getSiteUrl() );
- $redirect = esc_url( vc_updater()->getUpdaterUrl() );
- return sprintf( '%s/deactivate-license?license_key=%s&token=%s&url=%s&redirect=%s', self::$support_host, $license_key, $token, $url, $redirect );
- }
- /**
- * Start activation process and output redirect URL as JSON
- */
- public function startActivationResponse() {
- vc_user_access()->checkAdminNonce()->validateDie()->wpAny( 'manage_options' )->validateDie()->part( 'settings' )->can( 'vc-updater-tab' )->validateDie();
- $response = array(
- 'status' => true,
- 'url' => $this->generateActivationUrl(),
- );
- die( wp_json_encode( $response ) );
- }
- /**
- * Start deactivation process and output redirect URL as JSON
- */
- public function startDeactivationResponse() {
- vc_user_access()->checkAdminNonce()->validateDie( 'Failed nonce check' )->wpAny( 'manage_options' )->validateDie( 'Failed access check' )->part( 'settings' )->can( 'vc-updater-tab' )
- ->validateDie( 'Failed access check #2' );
- $response = array(
- 'status' => true,
- 'url' => $this->generateDeactivationUrl(),
- );
- die( wp_json_encode( $response ) );
- }
- /**
- * Set license key
- *
- * @param string $license_key
- */
- public function setLicenseKey( $license_key ) {
- if ( vc_is_network_plugin() ) {
- update_site_option( 'wpb_js_' . self::$license_key_option, $license_key );
- } else {
- vc_settings()->set( self::$license_key_option, $license_key );
- }
- }
- /**
- * Get license key
- *
- * @return string
- */
- public function getLicenseKey() {
- if ( vc_is_network_plugin() ) {
- $value = get_site_option( 'wpb_js_' . self::$license_key_option );
- } else {
- $value = vc_settings()->get( self::$license_key_option );
- }
- return $value;
- }
- /**
- * Check if specified license key is valid
- *
- * @param string $license_key
- *
- * @return bool
- */
- public function isValid( $license_key ) {
- return $license_key === $this->getLicenseKey();
- }
- /**
- * Set up license activation notice if needed
- *
- * Don't show notice on dev environment
- */
- public function setupReminder() {
- if ( self::isDevEnvironment() ) {
- return;
- }
- $version1 = isset( $_COOKIE['vchideactivationmsg_vc11'] ) ? sanitize_text_field( wp_unslash( $_COOKIE['vchideactivationmsg_vc11'] ) ) : '';
- if ( ! $this->isActivated() && ( empty( $version1 ) || version_compare( $version1, WPB_VC_VERSION, '<' ) ) && ! ( vc_is_network_plugin() && is_network_admin() ) ) {
- add_action( 'admin_notices', array(
- $this,
- 'adminNoticeLicenseActivation',
- ) );
- }
- }
- /**
- * Check if current enviroment is dev
- *
- * Environment is considered dev if host is:
- * - ip address
- * - tld is local, dev, wp, test, example, localhost or invalid
- * - no tld (localhost, custom hosts)
- *
- * @param string $host Hostname to check. If null, use HTTP_HOST
- *
- * @return boolean
- */
- public static function isDevEnvironment( $host = null ) {
- if ( ! $host ) {
- $host = self::getSiteUrl();
- }
- $chunks = explode( '.', $host );
- if ( 1 === count( $chunks ) ) {
- return true;
- }
- if ( in_array( end( $chunks ), array(
- 'local',
- 'dev',
- 'wp',
- 'test',
- 'example',
- 'localhost',
- 'invalid',
- ), true ) ) {
- return true;
- }
- if ( preg_match( '/^[0-9\.]+$/', $host ) ) {
- return true;
- }
- return false;
- }
- public function adminNoticeLicenseActivation() {
- if ( vc_is_network_plugin() ) {
- update_site_option( 'wpb_js_composer_license_activation_notified', 'yes' );
- } else {
- vc_settings()->set( 'composer_license_activation_notified', 'yes' );
- }
- $redirect = esc_url( vc_updater()->getUpdaterUrl() );
- $first_tag = 'style';
- $second_tag = 'script';
- // @codingStandardsIgnoreStart
- ?>
- <<?php echo esc_attr( $first_tag ); ?>>
- .vc_license-activation-notice {
- position: relative;
- }
- </<?php echo esc_attr( $first_tag ); ?>>
- <<?php echo esc_attr( $second_tag ); ?>>
- (function ( $ ) {
- var setCookie = function ( c_name, value, exdays ) {
- var exdate = new Date();
- exdate.setDate( exdate.getDate() + exdays );
- var c_value = encodeURIComponent( value ) + ((null === exdays) ? "" : "; expires=" + exdate.toUTCString());
- document.cookie = c_name + "=" + c_value;
- };
- $( document ).off( 'click.vc-notice-dismiss' ).on( 'click.vc-notice-dismiss',
- '.vc-notice-dismiss',
- function ( e ) {
- e.preventDefault();
- var $el = $( this ).closest(
- '#vc_license-activation-notice' );
- $el.fadeTo( 100, 0, function () {
- $el.slideUp( 100, function () {
- $el.remove();
- } );
- } );
- setCookie( 'vchideactivationmsg_vc11',
- '<?php echo esc_attr( WPB_VC_VERSION ); ?>',
- 30 );
- } );
- })( window.jQuery );
- </<?php echo esc_attr( $second_tag ); ?>>
- <?php
- echo '<div class="updated vc_license-activation-notice" id="vc_license-activation-notice"><p>' . sprintf( esc_html__( 'Hola! Would you like to receive automatic updates and unlock premium support? Please %sactivate your copy%s of WPBakery Page Builder.', 'js_composer' ), '<a href="' . esc_url( wp_nonce_url( $redirect ) ) . '">', '</a>' ) . '</p>' . '<button type="button" class="notice-dismiss vc-notice-dismiss"><span class="screen-reader-text">' . esc_html__( 'Dismiss this notice.', 'js_composer' ) . '</span></button></div>';
- // @codingStandardsIgnoreEnd
- }
- /**
- * Get license key token
- *
- * @return string
- */
- public function getLicenseKeyToken() {
- $value = vc_is_network_plugin() ? get_site_option( self::$license_key_token_option ) : get_option( self::$license_key_token_option );
- return $value;
- }
- /**
- * Set license key token
- *
- * @param string $token
- *
- * @return string
- */
- public function setLicenseKeyToken( $token ) {
- if ( vc_is_network_plugin() ) {
- $value = update_site_option( self::$license_key_token_option, $token );
- } else {
- $value = update_option( self::$license_key_token_option, $token );
- }
- return $value;
- }
- /**
- * Return new license key token
- *
- * Token is used to change license key from remote location
- *
- * Format is: timestamp|20-random-characters
- *
- * @return string
- */
- public function generateLicenseKeyToken() {
- $token = current_time( 'timestamp' ) . '|' . vc_random_string( 20 );
- return $token;
- }
- /**
- * Generate and set new license key token
- *
- * @return string
- */
- public function newLicenseKeyToken() {
- $token = $this->generateLicenseKeyToken();
- $this->setLicenseKeyToken( $token );
- return $token;
- }
- /**
- * Check if specified license key token is valid
- *
- * @param string $token_to_check SHA1 hashed token
- * @param int $ttl_in_seconds Time to live in seconds. Default = 20min
- *
- * @return boolean
- */
- public function isValidToken( $token_to_check, $ttl_in_seconds = 1200 ) {
- $token = $this->getLicenseKeyToken();
- if ( ! $token_to_check || sha1( $token ) !== $token_to_check ) {
- return false;
- }
- $chunks = explode( '|', $token );
- if ( intval( $chunks[0] ) < ( current_time( 'timestamp' ) - $ttl_in_seconds ) ) {
- return false;
- }
- return true;
- }
- /**
- * Check if license key format is valid
- *
- * license key is version 4 UUID, that have form xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
- * where x is any hexadecimal digit and y is one of 8, 9, A, or B.
- *
- * @param string $license_key
- *
- * @return boolean
- */
- public function isValidFormat( $license_key ) {
- $pattern = '/^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i';
- return (bool) preg_match( $pattern, $license_key );
- }
- /**
- * @return string|void
- */
- /**
- * @return string|void
- */
- public static function getSiteUrl() {
- if ( vc_is_network_plugin() ) {
- return network_site_url();
- } else {
- return site_url();
- }
- }
- }
|