Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"description": "Wordpress plugin for tawk.to",
"type": "project",
"license": "GPL-3.0",
"version": "0.9.0",
"version": "0.9.1",
"require": {
"tawk/url-utils": "2.0.1"
},
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "tawk-wordpress",
"version": "0.9.0",
"version": "0.9.1",
"description": "tawk.to wordpress plugin",
"main": "index.js",
"directories": {
Expand Down
8 changes: 6 additions & 2 deletions tawkto/readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Tags: tawk.to,tawk,free live chat,ai chat,chat widget
Requires at least: 2.7
Requires PHP: 5.6
Tested up to: 6.7
Stable tag: 0.9.0
Stable tag: 0.9.1
License: GPLv3
License URI: https://www.gnu.org/licenses/gpl-3.0.html

Expand Down Expand Up @@ -71,7 +71,11 @@ Note: You will need a free tawk.to account: [Create one for free here!](https://

== Changelog ==

= 0.9.0
= 0.9.1 =
* Add configuration versioning
* Improve security for Secure Mode

= 0.9.0 =
* Add support for Secure Mode

= 0.8.7 =
Expand Down
144 changes: 104 additions & 40 deletions tawkto/tawkto.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* Plugin Name: Tawk.to Live Chat
* Plugin URI: https://www.tawk.to
* Description: Embeds Tawk.to live chat widget to your site
* Version: 0.9.0
* Version: 0.9.1
* Author: Tawkto
* Text Domain: tawk-to-live-chat
* License: GPLv3
Expand All @@ -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 @@ -132,6 +132,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 +327,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 +428,20 @@ 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' );
}
$fields['js_api_key'] = trim( $fields['js_api_key'] );

if ( 40 !== strlen( $fields['js_api_key'] ) ) {
self::show_tawk_options_error( '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,12 +534,12 @@ 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 );

if ( false === $decoded_data ) {
return '';
return null;
}

$iv = substr( $decoded_data, 0, self::CIPHER_IV_LENGTH );
Expand All @@ -538,35 +548,12 @@ private static function get_decrypted_data( $data ) {
$decrypted_data = openssl_decrypt( $encrypted_data, self::CIPHER, SECURE_AUTH_KEY, 0, $iv );

if ( false === $decrypted_data ) {
return '';
return null;
}

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 +586,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 +601,41 @@ 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() {
$privacy = get_option( TawkTo_Settings::TAWK_PRIVACY_OPTIONS );

if ( empty( $privacy['enable_visitor_recognition'] ) ) {
return;
}

$security = get_option( TawkTo_Settings::TAWK_SECURITY_OPTIONS );

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

if ( session_status() === PHP_SESSION_NONE ) {
session_start();

// If user is not logged in, remove the visitor session and close the session.
// Session cannot be updated if it is not started.
if ( ! is_user_logged_in() ) {
if ( isset( $_SESSION[ self::TAWK_VISITOR_SESSION ] ) ) {
unset( $_SESSION[ self::TAWK_VISITOR_SESSION ] );
}
session_write_close();
}
}
}

/**
Expand Down Expand Up @@ -658,9 +681,8 @@ public static function deactivate() {
delete_option( TawkTo_Settings::TAWK_VISIBILITY_OPTIONS );
delete_option( TawkTo_Settings::TAWK_PRIVACY_OPTIONS );
delete_option( TawkTo_Settings::TAWK_SECURITY_OPTIONS );
delete_option( TawkTo_Settings::TAWK_CONFIG_VERSION );
delete_option( self::PLUGIN_VERSION_VARIABLE );

delete_transient( TawkTo_Settings::TAWK_API_KEY );
}

/**
Expand All @@ -683,16 +705,58 @@ 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 ( null !== $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 ) {
$security = get_option( TawkTo_Settings::TAWK_SECURITY_OPTIONS );

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

$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 ( isset( $current_session['hash'] ) &&
$current_session['email'] === $email &&
$current_session['config_version'] === $config_version ) {
return $current_session['hash'];
}
}

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

if ( null === $key ) {
return null;
}

$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
4 changes: 2 additions & 2 deletions tawkto/templates/widget.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

?>

<!--Start of Tawk.to Script (0.9.0)-->
<!--Start of Tawk.to Script (0.9.1)-->
<script id="tawk-script" type="text/javascript">
var Tawk_API = Tawk_API || {};
<?php if ( isset( $customer_details ) && $enable_visitor_recognition ) : ?>
Expand All @@ -24,5 +24,5 @@
s0.parentNode.insertBefore( s1, s0 );
})();
</script>
<!--End of Tawk.to Script (0.9.0)-->
<!--End of Tawk.to Script (0.9.1)-->