Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions tawkto/includes/default_config.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?php

return array(
'visibility' => array(
'visibility' => array(
'always_display' => 1,
'show_onfrontpage' => 0,
'show_oncategory' => 0,
Expand All @@ -16,10 +16,11 @@
'display_on_productpage' => 0,
'display_on_producttag' => 0,
),
'privacy' => array(
'privacy' => array(
'enable_visitor_recognition' => 1,
),
'security' => array(
'security' => array(
'js_api_key' => '',
),
'config_version' => 0,
);
112 changes: 75 additions & 37 deletions tawkto/tawkto.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ class TawkTo_Settings {
const TAWK_VISIBILITY_OPTIONS = 'tawkto-visibility-options';
const TAWK_PRIVACY_OPTIONS = 'tawkto-privacy-options';
const TAWK_SECURITY_OPTIONS = 'tawkto-security-options';
const TAWK_CONFIG_VERSION = 'tawkto-config-version';
const TAWK_ACTION_SET_WIDGET = 'tawkto-set-widget';
const TAWK_ACTION_REMOVE_WIDGET = 'tawkto-remove-widget';
const CIPHER = 'AES-256-CBC';
const CIPHER_IV_LENGTH = 16;
const NO_CHANGE = 'nochange';
const TAWK_API_KEY = 'tawkto-js-api-key';

/**
* @var $plugin_ver Plugin version
Expand Down Expand Up @@ -92,6 +92,10 @@ public static function init_options() {
if ( ! get_option( self::TAWK_SECURITY_OPTIONS, false ) ) {
update_option( self::TAWK_SECURITY_OPTIONS, $options['security'] );
}

if ( ! get_option( self::TAWK_CONFIG_VERSION, false ) ) {
update_option( self::TAWK_CONFIG_VERSION, $options['config_version'] );
}
}

/**
Expand Down Expand Up @@ -132,6 +136,7 @@ public function admin_init() {
register_setting( 'tawk_options', self::TAWK_VISIBILITY_OPTIONS, array( &$this, 'validate_visibility_options' ) );
register_setting( 'tawk_options', self::TAWK_PRIVACY_OPTIONS, array( &$this, 'validate_privacy_options' ) );
register_setting( 'tawk_options', self::TAWK_SECURITY_OPTIONS, array( &$this, 'validate_security_options' ) );
register_setting( 'tawk_options', self::TAWK_CONFIG_VERSION, array( &$this, 'update_config_version' ) );
}

/**
Expand Down Expand Up @@ -326,6 +331,15 @@ public function validate_security_options( $input ) {
return $security;
}

/**
* Updates the config version
*
* @return int
*/
public function update_config_version() {
return get_option( self::TAWK_CONFIG_VERSION, 0 ) + 1;
}

/**
* Adds the tawk.to plugin settings in the admin menu.
*/
Expand Down Expand Up @@ -418,20 +432,18 @@ private static function validate_js_api_key( &$fields ) {
return;
}

delete_transient( self::TAWK_API_KEY );

if ( '' === $fields['js_api_key'] ) {
return;
}

try {
if ( 40 !== strlen( $fields['js_api_key'] ) ) {
throw new Exception( 'Invalid key. Please provide value with 40 characters' );
}
if ( 40 !== strlen( $fields['js_api_key'] ) ) {
throw new Exception( 'Invalid API key.' );
}

try {
$fields['js_api_key'] = self::get_encrypted_data( $fields['js_api_key'] );
} catch ( Exception $e ) {
self::show_tawk_options_error( 'Javascript API Key: ' . $e->getMessage() );
self::show_tawk_options_error( 'Error saving Javascript API Key.' );

unset( $fields['js_api_key'] );
}
Expand Down Expand Up @@ -524,7 +536,7 @@ private static function get_encrypted_data( $data ) {
* @param string $data - Data to be decrypted.
* @return string
*/
private static function get_decrypted_data( $data ) {
public static function get_decrypted_data( $data ) {
// phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode
$decoded_data = base64_decode( $data );

Expand All @@ -544,29 +556,6 @@ private static function get_decrypted_data( $data ) {
return $decrypted_data;
}

/**
* Retrieves JS API Key
*
* @return string
*/
public static function get_js_api_key() {
if ( ! empty( get_transient( self::TAWK_API_KEY ) ) ) {
return get_transient( self::TAWK_API_KEY );
}

$security = get_option( self::TAWK_SECURITY_OPTIONS );

if ( ! isset( $security['js_api_key'] ) ) {
return '';
}

$key = self::get_decrypted_data( $security['js_api_key'] );

set_transient( self::TAWK_API_KEY, $key, 60 * 60 );

return $key;
}

/**
* Adds settings error
*
Expand Down Expand Up @@ -599,6 +588,7 @@ private static function show_tawk_options_error( $message ) {
*/
class TawkTo {
const PLUGIN_VERSION_VARIABLE = 'tawkto-version';
const TAWK_VISITOR_SESSION = 'tawkto-visitor-session';

/**
* @var $plugin_version Plugin version
Expand All @@ -613,6 +603,19 @@ class TawkTo {
public function __construct() {
$tawkto_settings = new TawkTo_Settings();
add_shortcode( 'tawkto', array( $this, 'shortcode_print_embed_code' ) );

add_action( 'init', array( $this, 'start_session' ) );
}

/**
* Starts user session
*
* @return void
*/
public function start_session() {
if ( session_status() === PHP_SESSION_NONE ) {
session_start();
}
}

/**
Expand Down Expand Up @@ -659,8 +662,6 @@ public static function deactivate() {
delete_option( TawkTo_Settings::TAWK_PRIVACY_OPTIONS );
delete_option( TawkTo_Settings::TAWK_SECURITY_OPTIONS );
delete_option( self::PLUGIN_VERSION_VARIABLE );

delete_transient( TawkTo_Settings::TAWK_API_KEY );
}

/**
Expand All @@ -683,16 +684,53 @@ public function get_current_customer_details() {
'email' => $current_user->user_email,
);

$js_api_key = TawkTo_Settings::get_js_api_key();
if ( ! empty( $user_info['email'] ) && ! empty( $js_api_key ) ) {
$user_info['hash'] = hash_hmac( 'sha256', $user_info['email'], $js_api_key );
$hash = self::get_visitor_hash( $user_info['email'] );
if ( ! empty( $user_info['email'] ) && ! empty( $hash ) ) {
$user_info['hash'] = $hash;
}

return wp_json_encode( $user_info );
}
return null;
}

/**
* Retrieves visitor hash
*
* @param string $email - Visitor email address.
* @return string
*/
public static function get_visitor_hash( $email ) {
$config_version = get_option( TawkTo_Settings::TAWK_CONFIG_VERSION, 0 );

if ( isset( $_SESSION[ self::TAWK_VISITOR_SESSION ] ) ) {
$current_session = $_SESSION[ self::TAWK_VISITOR_SESSION ];

if ( $current_session['email'] === $email &&
$current_session['config_version'] === $config_version ) {
return $current_session['hash'];
}
}

$security = get_option( TawkTo_Settings::TAWK_SECURITY_OPTIONS );

if ( empty( $security['js_api_key'] ) ) {
return '';
}

$key = TawkTo_Settings::get_decrypted_data( $security['js_api_key'] );

$hash = hash_hmac( 'sha256', $email, $key );

$_SESSION[ self::TAWK_VISITOR_SESSION ] = array(
'hash' => $hash,
'email' => $email,
'config_version' => $config_version,
);

return $hash;
}

/**
* Creates the embed code
*/
Expand Down