diff --git a/src/mibew/js/compiled/chat/model_views/controls/redirect.js b/src/mibew/js/compiled/chat/model_views/controls/redirect.js index 4116ff2b..57c97c89 100644 --- a/src/mibew/js/compiled/chat/model_views/controls/redirect.js +++ b/src/mibew/js/compiled/chat/model_views/controls/redirect.js @@ -5,5 +5,5 @@ You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 */ -(function(a,d,e){a.Views.RedirectControl=a.Views.Control.extend({template:d.templates.chat_controls_redirect,events:e.extend({},a.Views.Control.prototype.events,{click:"redirect"}),initialize:function(){a.Objects.Models.user.on("change",this.render,this)},serializeData:function(){var b=this.model.toJSON();b.user=a.Objects.Models.user.toJSON();return b},redirect:function(){var b=a.Objects.Models.user;if(b.get("isAgent")&&b.get("canPost")&&(b=this.model.get("link"))){var c=a.Objects.Models.page.get("style"); -window.location.href=b.replace(/\&\;/g,"&")+(c?"&style="+c:"")}}})})(Mibew,Handlebars,_); +(function(b,e,f){b.Views.RedirectControl=b.Views.Control.extend({template:e.templates.chat_controls_redirect,events:f.extend({},b.Views.Control.prototype.events,{click:"redirect"}),initialize:function(){b.Objects.Models.user.on("change",this.render,this)},serializeData:function(){var a=this.model.toJSON();a.user=b.Objects.Models.user.toJSON();return a},redirect:function(){var a=b.Objects.Models.user;if(a.get("isAgent")&&a.get("canPost")&&(a=this.model.get("link"))){var c=b.Objects.Models.page.get("style"), +d="";c&&(d=(-1===a.indexOf("?")?"?":"&")+"style="+c);window.location.href=a.replace(/\&\;/g,"&")+d}}})})(Mibew,Handlebars,_); diff --git a/src/mibew/js/compiled/chat_app.js b/src/mibew/js/compiled/chat_app.js index fa6974ec..7be91ff7 100644 --- a/src/mibew/js/compiled/chat_app.js +++ b/src/mibew/js/compiled/chat_app.js @@ -208,8 +208,8 @@ changeGroupDescription:function(){var a=this.ui.groupSelect.prop("selectedIndex" You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 */ -(function(a,d,e){a.Views.RedirectControl=a.Views.Control.extend({template:d.templates.chat_controls_redirect,events:e.extend({},a.Views.Control.prototype.events,{click:"redirect"}),initialize:function(){a.Objects.Models.user.on("change",this.render,this)},serializeData:function(){var b=this.model.toJSON();b.user=a.Objects.Models.user.toJSON();return b},redirect:function(){var b=a.Objects.Models.user;if(b.get("isAgent")&&b.get("canPost")&&(b=this.model.get("link"))){var c=a.Objects.Models.page.get("style"); -window.location.href=b.replace(/\&\;/g,"&")+(c?"&style="+c:"")}}})})(Mibew,Handlebars,_); +(function(b,e,f){b.Views.RedirectControl=b.Views.Control.extend({template:e.templates.chat_controls_redirect,events:f.extend({},b.Views.Control.prototype.events,{click:"redirect"}),initialize:function(){b.Objects.Models.user.on("change",this.render,this)},serializeData:function(){var a=this.model.toJSON();a.user=b.Objects.Models.user.toJSON();return a},redirect:function(){var a=b.Objects.Models.user;if(a.get("isAgent")&&a.get("canPost")&&(a=this.model.get("link"))){var c=b.Objects.Models.page.get("style"), +d="";c&&(d=(-1===a.indexOf("?")?"?":"&")+"style="+c);window.location.href=a.replace(/\&\;/g,"&")+d}}})})(Mibew,Handlebars,_); /* Copyright 2005-2014 the original author or authors. Licensed under the Apache License, Version 2.0 (the "License"). diff --git a/src/mibew/js/source/chat/model_views/controls/redirect.js b/src/mibew/js/source/chat/model_views/controls/redirect.js index 9364cc18..1e552890 100644 --- a/src/mibew/js/source/chat/model_views/controls/redirect.js +++ b/src/mibew/js/source/chat/model_views/controls/redirect.js @@ -62,8 +62,13 @@ if (link) { // Redirect browser to user redirection page var style = Mibew.Objects.Models.page.get('style'); + var styleArg = ''; + if (style) { + styleArg = ((link.indexOf('?') === -1) ? '?' : '&') + + 'style=' + style; + } window.location.href = link.replace(/\&\;/g, '&') - + (style ? ('&style=' + style) : ''); + + styleArg; } } } diff --git a/src/mibew/libs/chat.php b/src/mibew/libs/chat.php index 023481e1..762a3a87 100644 --- a/src/mibew/libs/chat.php +++ b/src/mibew/libs/chat.php @@ -613,10 +613,8 @@ function setup_chatview_for_operator(Thread $thread, $operator) $data['chat']['messageForm']['predefinedAnswers'] = $predefined_answers; } // Set link to user redirection page - $params = "thread=" . $thread->id . "&token=" . $thread->lastToken; - $data['chat']['links']['redirect'] = MIBEW_WEB_ROOT . "/operator/chat?" - . $params - . "&redirect=1"; + $data['chat']['links']['redirect'] = MIBEW_WEB_ROOT . "/operator/chat/" + . $thread->id . '/' . $thread->lastToken . '/redirection-links'; $data['namePostfix'] = ""; diff --git a/src/mibew/libs/classes/Mibew/Controller/Chat/Operator/ChatController.php b/src/mibew/libs/classes/Mibew/Controller/Chat/Operator/ChatController.php index b25ed344..b106c462 100644 --- a/src/mibew/libs/classes/Mibew/Controller/Chat/Operator/ChatController.php +++ b/src/mibew/libs/classes/Mibew/Controller/Chat/Operator/ChatController.php @@ -76,21 +76,11 @@ class ChatController extends AbstractController $page = setup_chatview_for_operator($thread, $operator); - if ($request->query->get('redirect')) { - $page = array_merge_recursive( - $page, - setup_redirect_links($thread_id, $operator, $token) - ); + // Build js application options + $page['chatOptions'] = json_encode($page['chat']); - // Render the page with redirection links. - return $this->render('redirect', $page); - } else { - // Build js application options - $page['chatOptions'] = json_encode($page['chat']); - - // Render the page with chat. - return $this->render('chat', $page); - } + // Render the page with chat. + return $this->render('chat', $page); } /** diff --git a/src/mibew/libs/classes/Mibew/Controller/Chat/Operator/RedirectController.php b/src/mibew/libs/classes/Mibew/Controller/Chat/Operator/RedirectController.php index d436ac8d..abc2ea69 100644 --- a/src/mibew/libs/classes/Mibew/Controller/Chat/Operator/RedirectController.php +++ b/src/mibew/libs/classes/Mibew/Controller/Chat/Operator/RedirectController.php @@ -20,6 +20,7 @@ namespace Mibew\Controller\Chat\Operator; use Mibew\Controller\Chat\AbstractController; use Mibew\Database; use Mibew\Http\Exception\BadRequestException; +use Mibew\Http\Exception\NotFoundException; use Mibew\Thread; use Symfony\Component\HttpFoundation\Request; @@ -29,31 +30,64 @@ use Symfony\Component\HttpFoundation\Request; class RedirectController extends AbstractController { /** - * Process chat's redirections. + * Renders a page with redirections links. * * @param Request $request Incoming request. * @return string|\Symfony\Component\HttpFoundation\RedirectResponse Rendered * page content or a redirect response. - * @throws BadRequestException If the thread cannot be loaded by some - * reasons. + * @throws NotFoundException If the thread with specified ID and token is + * not found. */ - public function indexAction(Request $request) + public function showRedirectionLinksAction(Request $request) { - // Get and validate thread id - $thread_id = $request->query->get('thread'); - if (!preg_match("/^\d{1,10}$/", $thread_id)) { - throw new BadRequestException('Wrong value of "thread" argument.'); + // Check if we should force the user to use SSL + $ssl_redirect = $this->sslRedirect($request); + if ($ssl_redirect !== false) { + return $ssl_redirect; } - // Get and validate token - $token = $request->query->get('token'); - if (!preg_match("/^\d{1,10}$/", $token)) { - throw new BadRequestException('Wrong value of "token" argument.'); - } + $operator = $this->getOperator(); + $thread_id = $request->attributes->get('thread_id'); + $token = $request->attributes->get('token'); $thread = Thread::load($thread_id, $token); if (!$thread) { - throw new BadRequestException('Wrong thread.'); + throw new NotFoundException('The thread is not found.'); + } + + if ($thread->agentId != $operator['operatorid']) { + $page = array('errors' => array('Can redirect only own threads.')); + + return $this->render('error', $page); + } + + $page = array_merge_recursive( + setup_chatview_for_operator($thread, $operator), + setup_redirect_links($this->getRouter()->getGenerator(), $thread_id, $operator, $token) + ); + + // Render the page with redirection links. + return $this->render('redirect', $page); + } + + /** + * Process chat thread redirection. + * + * @param Request $request Incoming request. + * @return string|\Symfony\Component\HttpFoundation\RedirectResponse Rendered + * page content or a redirect response. + * @throws NotFoundException If the thread with specified ID and token is + * not found. + * @throws BadRequestException If one or more arguments have a wrong format. + */ + public function redirectAction(Request $request) + { + $thread_id = $request->attributes->get('thread_id'); + $token = $request->attributes->get('token'); + + $thread = Thread::load($thread_id, $token); + if (!$thread) { + throw new NotFoundException('The thread is not found.'); } $page = array( @@ -109,6 +143,13 @@ class RedirectController extends AbstractController } } + /** + * Redirects a chat thread to the group with the specified ID. + * + * @param \Mibew\Thread $thread Chat thread to redirect. + * @param int $group_id ID of the target group. + * @return boolean True if the thread was redirected and false on failure. + */ protected function redirectToGroup(Thread $thread, $group_id) { if ($thread->state != Thread::STATE_CHATTING) { @@ -138,6 +179,13 @@ class RedirectController extends AbstractController return true; } + /** + * Redirects a chat thread to the operator with the specified ID. + * + * @param \Mibew\Thread $thread Chat thread to redirect. + * @param int $group_id ID of the target operator. + * @return boolean True if the thread was redirected and false on failure. + */ protected function redirectToOperator(Thread $thread, $operator_id) { if ($thread->state != Thread::STATE_CHATTING) { diff --git a/src/mibew/libs/operator.php b/src/mibew/libs/operator.php index 3dd5563a..8771d1bb 100644 --- a/src/mibew/libs/operator.php +++ b/src/mibew/libs/operator.php @@ -19,6 +19,7 @@ use Mibew\Database; use Mibew\EventDispatcher; use Mibew\Settings; +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; /** * Name of the cookie to remember an operator @@ -603,7 +604,7 @@ function get_logged_in() : false; } -function setup_redirect_links($threadid, $operator, $token) +function setup_redirect_links(UrlGeneratorInterface $url_generator, $threadid, $operator, $token) { $result = array(); @@ -637,7 +638,7 @@ function setup_redirect_links($threadid, $operator, $token) $groups = array_slice($groups, $p['start'], $p['end'] - $p['start']); $agent_list = ""; - $params = array('thread' => $threadid, 'token' => $token); + $params = array('thread_id' => $threadid, 'token' => $token); foreach ($operators as $agent) { $params['nextAgent'] = $agent['operatorid']; $status = $agent['time'] < Settings::get('online_timeout') @@ -645,7 +646,7 @@ function setup_redirect_links($threadid, $operator, $token) ? getlocal("char.redirect.operator.online_suff") : getlocal("char.redirect.operator.away_suff")) : ""; - $agent_list .= "