mirror of
https://github.com/Mibew/mibew.git
synced 2024-11-15 00:24:12 +03:00
Merge branch 'cookies' into test
This commit is contained in:
commit
a37ea34670
@ -30,7 +30,7 @@
|
||||
"require": {
|
||||
"mibew/handlebars.php": "~0.10.5",
|
||||
"mibew/handlebars.php-helpers": "1.*",
|
||||
"symfony/http-foundation": "~2.8.52",
|
||||
"symfony/http-foundation": "~3.2",
|
||||
"symfony/routing": "2.6.*",
|
||||
"symfony/config": "2.6.*",
|
||||
"symfony/yaml": "^5.2",
|
||||
|
@ -102,6 +102,11 @@ chat_user_start:
|
||||
defaults:
|
||||
_controller: Mibew\Controller\Chat\UserChatController::startAction
|
||||
|
||||
chat_user_cookie_set_permission:
|
||||
path: /chat/cookies-set-permission
|
||||
defaults:
|
||||
_controller: Mibew\Controller\Chat\UserChatController::cookieSetPermissionAction
|
||||
|
||||
# Pages that are available for all users
|
||||
button:
|
||||
path: /b
|
||||
|
@ -301,6 +301,12 @@ var Mibew = Mibew || {};
|
||||
// Call parent constructor.
|
||||
BasePopup.call(this, options);
|
||||
|
||||
/**
|
||||
* Store options in case we need some of them later.
|
||||
* @type {Object}
|
||||
*/
|
||||
this.options = options;
|
||||
|
||||
/**
|
||||
* Wrapper for popup iframe DOM Element.
|
||||
* @type {Node}
|
||||
@ -331,6 +337,12 @@ var Mibew = Mibew || {};
|
||||
*/
|
||||
this.isMinified = false;
|
||||
|
||||
/**
|
||||
* Indicates if cookies are blocked.
|
||||
* @type {Boolean}
|
||||
*/
|
||||
this.cookiesBlocked = false;
|
||||
|
||||
// Load default styles. These styles hide the popup while real styles
|
||||
// are loading.
|
||||
this.attachDefaultStyles();
|
||||
@ -344,6 +356,18 @@ var Mibew = Mibew || {};
|
||||
// new page is visited.
|
||||
this.safeOpen(openedChatUrl);
|
||||
}
|
||||
|
||||
// Check if it's possible to set cookies at all
|
||||
var rnd = Math.random();
|
||||
Mibew.Utils.createCookie('mibewCheckToken', rnd);
|
||||
var checkCookiesBlock = Mibew.Utils.loadScript(options.url.split('?')[0] + '/cookies-set-permission' + '?rnd=' + rnd);
|
||||
checkCookiesBlock.popup = this;
|
||||
checkCookiesBlock.onload = function() {
|
||||
this.popup.cookiesBlocked = false;
|
||||
};
|
||||
checkCookiesBlock.onerror = function() {
|
||||
this.popup.cookiesBlocked = true;
|
||||
};
|
||||
};
|
||||
|
||||
// Set correct prototype chain for IFrame popup.
|
||||
@ -394,6 +418,14 @@ var Mibew = Mibew || {};
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.cookiesBlocked) {
|
||||
// Last resort. Replace this iframe-based popup with window-based popup
|
||||
// and try to open a chat in a separate window.
|
||||
Mibew.Objects.ChatPopups[this.id] = new Mibew.ChatPopup.Window(this.options);
|
||||
Mibew.Objects.ChatPopups[this.id].open(url);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.wrapperDiv) {
|
||||
// Create new iframe and its wrapper.
|
||||
// There is a bug in IE <= 7 that make "name" attribute unchangeble
|
||||
@ -513,6 +545,10 @@ var Mibew = Mibew || {};
|
||||
* value is omitted, the chat initialization URL will be loaded.
|
||||
*/
|
||||
Mibew.ChatPopup.Window.prototype.open = function(url) {
|
||||
// Windows is already opened, nothing to do.
|
||||
if (this.window != null && !this.window.closed) {
|
||||
return;
|
||||
}
|
||||
this.window = window.open(
|
||||
url || this.buildChatUrl(),
|
||||
'mibewChat' + this.id,
|
||||
|
@ -78,6 +78,12 @@ var Mibew = Mibew || {};
|
||||
*/
|
||||
this.visitorCookieName = options.visitorCookieName;
|
||||
|
||||
/**
|
||||
* Name of tracking cookie
|
||||
* @type String
|
||||
*/
|
||||
this.cookiesBlocked = false;
|
||||
|
||||
/**
|
||||
* URL of file with additional CSS rules for invitation
|
||||
* @type String
|
||||
@ -112,7 +118,14 @@ var Mibew = Mibew || {};
|
||||
// Prepare GET params list
|
||||
this.dataToSend.entry = escape(document.referrer),
|
||||
this.dataToSend.locale = this.locale;
|
||||
// Random value should be set both as a GET param and as a cookie,
|
||||
// so it will be possible to find out whether cookies are blocked
|
||||
// Also it will prevent response from being cached at any level
|
||||
this.dataToSend.rnd = Math.random();
|
||||
Mibew.Utils.createCookie(
|
||||
'mibewRndValue',
|
||||
this.dataToSend.rnd
|
||||
);
|
||||
if (userId !== false) {
|
||||
this.dataToSend.user_id = userId;
|
||||
} else {
|
||||
@ -330,6 +343,12 @@ var Mibew = Mibew || {};
|
||||
* - 'acceptCaption': String, caption for accept button.
|
||||
*/
|
||||
Mibew.Invitation.create = function (options) {
|
||||
|
||||
// Cookies are blocked, invitation will behave badly
|
||||
if (Mibew.Objects.widget.cookiesBlocked) {
|
||||
return;
|
||||
}
|
||||
|
||||
var operatorName = options.operatorName;
|
||||
var avatarUrl = options.avatarUrl;
|
||||
var threadUrl = options.threadUrl;
|
||||
@ -487,6 +506,14 @@ var Mibew = Mibew || {};
|
||||
*/
|
||||
Mibew.APIFunctions = {};
|
||||
|
||||
/**
|
||||
* Update cookies status. API function
|
||||
* @param {Object} response Data object from server
|
||||
*/
|
||||
Mibew.APIFunctions.updateCookiesBlockStatus = function(response) {
|
||||
Mibew.Objects.widget.cookiesBlocked = response.cookiesBlocked;
|
||||
};
|
||||
|
||||
/**
|
||||
* Update user id. API function
|
||||
* @param {Object} response Data object from server
|
||||
|
@ -563,6 +563,8 @@ function setup_chatview_for_operator(
|
||||
*/
|
||||
function visitor_from_request()
|
||||
{
|
||||
$tmp_request = Request::createFromGlobals();
|
||||
|
||||
$default_name = getlocal("Guest");
|
||||
$user_name = $default_name;
|
||||
if (isset($_COOKIE[USERNAME_COOKIE_NAME])) {
|
||||
@ -573,17 +575,32 @@ function visitor_from_request()
|
||||
}
|
||||
|
||||
if ($user_name == $default_name) {
|
||||
$temp = Request::createFromGlobals()->query->get('name');
|
||||
$temp = $tmp_request->query->get('name');
|
||||
$user_name = (isset($temp) && ($temp !== '')) ? $temp : $user_name;
|
||||
}
|
||||
|
||||
if (isset($_COOKIE[USERID_COOKIE_NAME])) {
|
||||
$user_id = $_COOKIE[USERID_COOKIE_NAME];
|
||||
} else {
|
||||
$user_id = uniqid('', true);
|
||||
setcookie(USERID_COOKIE_NAME, $user_id, time() + 60 * 60 * 24 * 365);
|
||||
// Check whether user id already exists in absence of the appropriate cookie:
|
||||
// some browsers could have weird behaviour
|
||||
$temp = $tmp_request->query->get('user_id');
|
||||
$user_id = (isset($temp)) ? $temp : uniqid('', true);
|
||||
|
||||
$cookie_properties = array( 'expires' => time() + 60 * 60 * 24 * 365 );
|
||||
if (version_compare(phpversion(), '7.3.0', '<')) {
|
||||
setcookie(USERID_COOKIE_NAME, $user_id, $cookie_properties['expires']);
|
||||
} else {
|
||||
if ($tmp_request->isSecure()) {
|
||||
$cookie_properties['samesite'] = 'None';
|
||||
$cookie_properties['secure'] = true;
|
||||
}
|
||||
setcookie(USERID_COOKIE_NAME, $user_id, $cookie_properties);
|
||||
}
|
||||
}
|
||||
|
||||
unset($tmp_request);
|
||||
|
||||
return array('id' => $user_id, 'name' => $user_name);
|
||||
}
|
||||
|
||||
|
@ -361,7 +361,9 @@ class Application implements
|
||||
$response->headers->setCookie(CookieFactory::fromRequest($request)->createCookie(
|
||||
LOCALE_COOKIE_NAME,
|
||||
get_current_locale(),
|
||||
time() + 60 * 60 * 24 * 1000
|
||||
time() + 60 * 60 * 24 * 1000,
|
||||
true,
|
||||
false
|
||||
));
|
||||
|
||||
$response->prepare($request);
|
||||
|
@ -299,4 +299,29 @@ class UserChatController extends AbstractController
|
||||
// Expand page
|
||||
return $this->render('chat', $page);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check possibility to set cookie on the client side: it's crusial for chat to work,
|
||||
* since otherwise there will be no session.
|
||||
*
|
||||
* @param Request $request Incoming request.
|
||||
* @return string Empty string.
|
||||
* @throws AccessDeniedException if the thread with specified ID and token is
|
||||
* not found.
|
||||
*/
|
||||
public function cookieSetPermissionAction(Request $request)
|
||||
{
|
||||
$blocked = true;
|
||||
$token1 = $request->query->get('rnd');
|
||||
if ($request->cookies->has('mibewCheckToken')) {
|
||||
$token2 = $request->cookies->get('mibewCheckToken');
|
||||
if ($token1 === $token2) {
|
||||
$blocked = false;
|
||||
}
|
||||
}
|
||||
if ($blocked) {
|
||||
throw new NotFoundException('Cookies are blocked.');
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
@ -51,8 +51,27 @@ class WidgetController extends AbstractController
|
||||
'data' => array(),
|
||||
);
|
||||
|
||||
// Check whether third parties cookies are blocked
|
||||
// It will be impossible to chat if they are
|
||||
$cookies_blocked = false;
|
||||
$rnd_value1 = $request->query->get('rnd', false);
|
||||
if ($request->cookies->has('mibewRndValue')) {
|
||||
$rnd_value2 = $request->cookies->get('mibewRndValue');
|
||||
if ($rnd_value1 !== $rnd_value2) {
|
||||
$cookies_blocked = true;
|
||||
}
|
||||
} else {
|
||||
$cookies_blocked = true;
|
||||
}
|
||||
|
||||
// Update status on blocked cookie
|
||||
$response_data['handlers'][] = 'updateCookiesBlockStatus';
|
||||
$response_data['dependencies']['updateCookiesBlockStatus'] = array();
|
||||
$response_data['data']['cookiesBlocked'] = $cookies_blocked;
|
||||
|
||||
$tracking_allowed = (Settings::get('enabletracking') == '1')
|
||||
&& (Settings::get('trackoperators') == '1' || !$this->getOperator());
|
||||
&& (Settings::get('trackoperators') == '1' || !$this->getOperator())
|
||||
&& !$cookies_blocked;
|
||||
|
||||
if ($tracking_allowed) {
|
||||
$entry = $request->query->get('entry', '');
|
||||
|
@ -83,11 +83,14 @@ class CookieFactory
|
||||
* @param string $name The name of the cookie.
|
||||
* @param string $value The value of the cookie.
|
||||
* @param int|string|\DateTime $expire The time the cookie expires.
|
||||
* @param bool $httpOnly Whether the cookie will be made accessible only
|
||||
* @param bool $http_only Whether the cookie will be made accessible only
|
||||
* through the HTTP protocol.
|
||||
* @param bool $same_site Whether the cookie should be used only on the
|
||||
* original site. Otherwise (but only if it's already marked as secure)
|
||||
* it will be marked as SameSite=None
|
||||
* @return Cookie
|
||||
*/
|
||||
public function createCookie($name, $value = null, $expire = 0, $http_only = true)
|
||||
public function createCookie($name, $value = null, $expire = 0, $http_only = true, $same_site = true)
|
||||
{
|
||||
return new Cookie(
|
||||
$name,
|
||||
@ -96,7 +99,9 @@ class CookieFactory
|
||||
$this->getPath(),
|
||||
$this->getDomain(),
|
||||
$this->isSecure(),
|
||||
$http_only
|
||||
$http_only,
|
||||
true,
|
||||
!$same_site && $this->isSecure() ? 'None' : false
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -240,6 +240,9 @@ abstract class AbstractProcessor
|
||||
return $this->buildSyncResponses($this->responses);
|
||||
}
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
// Looks like a try to use chat with blocked cookies or something, return 403
|
||||
return new Response('Update forbidden', Response::HTTP_FORBIDDEN);
|
||||
} catch (\Exception $e) {
|
||||
// Something went wrong. Trigger error event
|
||||
$vars = array('exception' => $e);
|
||||
|
@ -553,7 +553,17 @@ class ThreadProcessor extends ClientSideProcessor implements
|
||||
$thread->renameUser($args['name']);
|
||||
// Update user name in cookies
|
||||
$data = strtr(base64_encode($args['name']), '+/=', '-_,');
|
||||
setcookie(USERNAME_COOKIE_NAME, $data, time() + 60 * 60 * 24 * 365);
|
||||
|
||||
$cookie_properties = array( 'expires' => time() + 60 * 60 * 24 * 365 );
|
||||
if (version_compare(phpversion(), '7.3.0', '<')) {
|
||||
setcookie(USERNAME_COOKIE_NAME, $data, $cookie_properties['expires']);
|
||||
} else {
|
||||
if ($this->currentRequest && $this->currentRequest->isSecure()) {
|
||||
$cookie_properties['samesite'] = 'None';
|
||||
$cookie_properties['secure'] = true;
|
||||
}
|
||||
setcookie(USERNAME_COOKIE_NAME, $data, $cookie_properties);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -55,6 +55,7 @@ $tmp_request = \Symfony\Component\HttpFoundation\Request::createFromGlobals();
|
||||
@ini_set('session.cookie_httponly', true);
|
||||
if ($tmp_request->isSecure()) {
|
||||
@ini_set('session.cookie_secure', true);
|
||||
@ini_set('session.cookie_samesite', 'None');
|
||||
}
|
||||
@ini_set('session.cookie_path', $tmp_request->getBasePath() . "/");
|
||||
@ini_set('session.name', 'MibewSessionID');
|
||||
@ -62,14 +63,8 @@ if ($tmp_request->isSecure()) {
|
||||
// Remove temporary request to keep global scope clean.
|
||||
unset($tmp_request);
|
||||
|
||||
if (version_compare(phpversion(), '5.4.0', '<')) {
|
||||
if (session_id() == '') {
|
||||
session_start();
|
||||
}
|
||||
} else {
|
||||
if (session_status() == PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
if (session_status() == PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
if (function_exists("date_default_timezone_set")) {
|
||||
|
Loading…
Reference in New Issue
Block a user