mirror of
				https://github.com/Mibew/mibew.git
				synced 2025-10-31 18:41:10 +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