From ad2e26a1c3e8de8de3a538c58013ae1a4d9de499 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Mon, 21 Sep 2015 17:44:00 +0100 Subject: [PATCH 1/7] IN-1956 Update Transifex project link --- airtime_mvc/application/configs/constants.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/airtime_mvc/application/configs/constants.php b/airtime_mvc/application/configs/constants.php index 6fec39088..ff166b982 100644 --- a/airtime_mvc/application/configs/constants.php +++ b/airtime_mvc/application/configs/constants.php @@ -17,7 +17,7 @@ define('WHOS_USING_URL' , 'http://sourcefabric.org/en/airtime/whosus define('TERMS_AND_CONDITIONS_URL' , 'http://www.sourcefabric.org/en/about/policy/'); define('PRIVACY_POLICY_URL' , 'http://www.sourcefabric.org/en/about/policy/'); define('USER_MANUAL_URL' , 'http://sourcefabric.booktype.pro/airtime-pro-for-broadcasters'); -define('AIRTIME_TRANSIFEX_URL' , 'https://www.transifex.com/projects/p/airtime/'); +define('AIRTIME_TRANSIFEX_URL' , 'https://www.transifex.com/sourcefabric/airtime/'); define('WHMCS_PASSWORD_RESET_URL' , 'https://account.sourcefabric.com/pwreset.php'); define('LICENSE_VERSION' , 'GNU AGPL v.3'); From a86e3ed4a8f3dba26bcb044c1863e8d9c23cbf38 Mon Sep 17 00:00:00 2001 From: Albert Santoni Date: Wed, 23 Sep 2015 18:21:30 -0400 Subject: [PATCH 2/7] Improvements to the preferences screen --- airtime_mvc/application/common/SecurityHelper.php | 13 +++++++++++++ .../controllers/PreferenceController.php | 12 ++++++++++++ .../public/js/airtime/preferences/preferences.js | 11 +++++++---- 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/airtime_mvc/application/common/SecurityHelper.php b/airtime_mvc/application/common/SecurityHelper.php index 95353407e..baf4ca46b 100644 --- a/airtime_mvc/application/common/SecurityHelper.php +++ b/airtime_mvc/application/common/SecurityHelper.php @@ -12,4 +12,17 @@ class SecurityHelper { } return $arr; } + + public static function verifyAjaxCSRFToken($observedToken) { + $current_namespace = new Zend_Session_Namespace('csrf_namespace'); + $observed_csrf_token = $observedToken; + $expected_csrf_token = $current_namespace->authtoken; + + if ($observed_csrf_token == $expected_csrf_token){ + return true; + }else{ + return false; + } + + } } \ No newline at end of file diff --git a/airtime_mvc/application/controllers/PreferenceController.php b/airtime_mvc/application/controllers/PreferenceController.php index 7eee7afbe..478d1d332 100644 --- a/airtime_mvc/application/controllers/PreferenceController.php +++ b/airtime_mvc/application/controllers/PreferenceController.php @@ -134,6 +134,12 @@ class PreferenceController extends Zend_Controller_Action // Remove reliance on .phtml files to render requests $this->_helper->viewRenderer->setNoRender(true); + if (!SecurityHelper::verifyAjaxCSRFToken($this->_getParam('csrf_token'))) { + Logging::error(__FILE__ . ': Invalid CSRF token'); + $this->_helper->json->sendJson(array("jsonrpc" => "2.0", "valid" => false, "error" => "CSRF token did not match.")); + return; + } + Application_Model_Preference::SetStationLogo(""); } @@ -479,6 +485,12 @@ class PreferenceController extends Zend_Controller_Action { $this->view->layout()->disableLayout(); $this->_helper->viewRenderer->setNoRender(true); + + if (!SecurityHelper::verifyAjaxCSRFToken($this->_getParam('csrf_token'))) { + Logging::error(__FILE__ . ': Invalid CSRF token'); + $this->_helper->json->sendJson(array("jsonrpc" => "2.0", "valid" => false, "error" => "CSRF token did not match.")); + return; + } // Only admin users should get here through ACL permissioning // Only allow POST requests diff --git a/airtime_mvc/public/js/airtime/preferences/preferences.js b/airtime_mvc/public/js/airtime/preferences/preferences.js index 91a9bef3a..a03f0094e 100644 --- a/airtime_mvc/public/js/airtime/preferences/preferences.js +++ b/airtime_mvc/public/js/airtime/preferences/preferences.js @@ -114,15 +114,18 @@ function setMsAuthenticationFieldsReadonly(ele) { } function removeLogo() { - $.post(baseUrl+'Preference/remove-logo', function(json){}); - location.reload(); + $.post(baseUrl+'preference/remove-logo', {'csrf_token' : $('#csrf').val()}, function(json){ + // Reload without resubmitting the form + location.href = location.href.replace(location.hash,""); + }); } function deleteAllFiles() { var resp = confirm($.i18n._("Are you sure you want to delete all the tracks in your library?")) if (resp) { - $.post(baseUrl+'Preference/delete-all-files', function(json){}); - location.reload(); + $.post(baseUrl+'preference/delete-all-files', {'csrf_token' : $('#csrf').val()}, function(json){ + location.reload(); + }); } } From c03e9cbe9ae3b88cce7678e8b4fee2d99caaec6e Mon Sep 17 00:00:00 2001 From: Albert Santoni Date: Fri, 25 Sep 2015 10:41:51 -0400 Subject: [PATCH 3/7] SAAS-1085: Optimization - Don't start sessions unless we actually need them. --- airtime_mvc/application/Bootstrap.php | 167 +------------ .../application/common/SecurityHelper.php | 9 +- .../application/common/TaskManager.php | 3 + .../application/controllers/ApiController.php | 29 ++- .../controllers/BillingController.php | 10 +- .../controllers/LoginController.php | 34 ++- .../controllers/PreferenceController.php | 4 +- .../controllers/plugins/Acl_plugin.php | 15 +- .../plugins/ConversionTracking.php | 4 + .../plugins/PageLayoutInitPlugin.php | 232 ++++++++++++++++++ .../application/forms/BillingClient.php | 4 + .../forms/BillingUpgradeDowngrade.php | 4 + airtime_mvc/application/models/Preference.php | 16 +- 13 files changed, 334 insertions(+), 197 deletions(-) create mode 100644 airtime_mvc/application/controllers/plugins/PageLayoutInitPlugin.php diff --git a/airtime_mvc/application/Bootstrap.php b/airtime_mvc/application/Bootstrap.php index 97719079a..274d38981 100644 --- a/airtime_mvc/application/Bootstrap.php +++ b/airtime_mvc/application/Bootstrap.php @@ -35,6 +35,7 @@ require_once __DIR__.'/services/CeleryService.php'; require_once __DIR__.'/services/SoundcloudService.php'; require_once __DIR__.'/forms/helpers/ValidationTypes.php'; require_once __DIR__.'/forms/helpers/CustomDecorators.php'; +require_once __DIR__.'/controllers/plugins/PageLayoutInitPlugin.php'; require_once __DIR__.'/controllers/plugins/RabbitMqPlugin.php'; require_once __DIR__.'/controllers/plugins/Maintenance.php'; require_once __DIR__.'/controllers/plugins/ConversionTracking.php'; @@ -52,20 +53,21 @@ if (array_key_exists("REQUEST_URI", $_SERVER) && (stripos($_SERVER["REQUEST_URI" die(); } +Zend_Session::setOptions(array('strict' => true)); + + Config::setAirtimeVersion(); require_once (CONFIG_PATH . 'navigation.php'); Zend_Validate::setDefaultNamespaces("Zend"); -Application_Model_Auth::pinSessionToClient(Zend_Auth::getInstance()); - $front = Zend_Controller_Front::getInstance(); $front->registerPlugin(new RabbitMqPlugin()); $front->registerPlugin(new Zend_Controller_Plugin_ConversionTracking()); $front->throwExceptions(false); -//localization configuration -Application_Model_Locale::configureLocalization(); + + /* The bootstrap class should only be used to initialize actions that return a view. Actions that return JSON will not use the bootstrap class! */ @@ -78,55 +80,7 @@ class Bootstrap extends Zend_Application_Bootstrap_Bootstrap $view->doctype('XHTML1_STRICT'); } - protected function _initGlobals() - { - $view = $this->getResource('view'); - $baseUrl = Application_Common_OsPath::getBaseDir(); - $view->headScript()->appendScript("var baseUrl = '$baseUrl';"); - $this->_initTranslationGlobals($view); - - $user = Application_Model_User::GetCurrentUser(); - if (!is_null($user)) { - $userType = $user->getType(); - } else { - $userType = ""; - } - $view->headScript()->appendScript("var userType = '$userType';"); - } - - /** - * Create a global namespace to hold a session token for CSRF prevention - */ - protected function _initCsrfNamespace() - { - $csrf_namespace = new Zend_Session_Namespace('csrf_namespace'); - // Check if the token exists - if (!$csrf_namespace->authtoken) { - // If we don't have a token, regenerate it and set a 1 week timeout - // Should we log the user out here if the token is expired? - $csrf_namespace->authtoken = sha1(uniqid(rand(), 1)); - $csrf_namespace->setExpirationSeconds(168 * 60 * 60); - } - - //Here we are closing the session for writing because otherwise no requests - //in this session will be handled in parallel. This gives a major boost to the perceived performance - //of the application (page load times are more consistent, no lock contention). - session_write_close(); - } - - /** - * Ideally, globals should be written to a single js file once - * from a php init function. This will save us from having to - * reinitialize them every request - */ - private function _initTranslationGlobals() - { - $view = $this->getResource('view'); - $view->headScript()->appendScript("var PRODUCT_NAME = '" . PRODUCT_NAME . "';"); - $view->headScript()->appendScript("var USER_MANUAL_URL = '" . USER_MANUAL_URL . "';"); - $view->headScript()->appendScript("var COMPANY_NAME = '" . COMPANY_NAME . "';"); - } protected function _initTasks() { /* We need to wrap this here so that we aren't checking when we're running the unit test suite @@ -139,115 +93,7 @@ class Bootstrap extends Zend_Application_Bootstrap_Bootstrap } } - protected function _initHeadLink() - { - $CC_CONFIG = Config::getConfig(); - $view = $this->getResource('view'); - - $baseUrl = Application_Common_OsPath::getBaseDir(); - - $view->headLink(array('rel' => 'icon', 'href' => $baseUrl . 'favicon.ico?' . $CC_CONFIG['airtime_version'], 'type' => 'image/x-icon'), 'PREPEND') - ->appendStylesheet($baseUrl . 'css/bootstrap.css?' . $CC_CONFIG['airtime_version']) - ->appendStylesheet($baseUrl . 'css/redmond/jquery-ui-1.8.8.custom.css?' . $CC_CONFIG['airtime_version']) - ->appendStylesheet($baseUrl . 'css/pro_dropdown_3.css?' . $CC_CONFIG['airtime_version']) - ->appendStylesheet($baseUrl . 'css/qtip/jquery.qtip.min.css?' . $CC_CONFIG['airtime_version']) - ->appendStylesheet($baseUrl . 'css/styles.css?' . $CC_CONFIG['airtime_version']) - ->appendStylesheet($baseUrl . 'css/masterpanel.css?' . $CC_CONFIG['airtime_version']) - ->appendStylesheet($baseUrl . 'css/tipsy/jquery.tipsy.css?' . $CC_CONFIG['airtime_version']); - } - - protected function _initHeadScript() - { - $CC_CONFIG = Config::getConfig(); - - $view = $this->getResource('view'); - - $baseUrl = Application_Common_OsPath::getBaseDir(); - - $view->headScript()->appendFile($baseUrl . 'js/libs/jquery-1.8.3.min.js?' . $CC_CONFIG['airtime_version'], 'text/javascript') - ->appendFile($baseUrl . 'js/libs/jquery-ui-1.8.24.min.js?' . $CC_CONFIG['airtime_version'], 'text/javascript') - ->appendFile($baseUrl . 'js/bootstrap/bootstrap.js?' . $CC_CONFIG['airtime_version'], 'text/javascript') - ->appendFile($baseUrl . 'js/libs/underscore-min.js?' . $CC_CONFIG['airtime_version'], 'text/javascript') - - // ->appendFile($baseUrl . 'js/libs/jquery.stickyPanel.js?' . $CC_CONFIG['airtime_version'], 'text/javascript') - ->appendFile($baseUrl . 'js/qtip/jquery.qtip.js?' . $CC_CONFIG['airtime_version'], 'text/javascript') - ->appendFile($baseUrl . 'js/jplayer/jquery.jplayer.min.js?' . $CC_CONFIG['airtime_version'], 'text/javascript') - ->appendFile($baseUrl . 'js/sprintf/sprintf-0.7-beta1.js?' . $CC_CONFIG['airtime_version'], 'text/javascript') - ->appendFile($baseUrl . 'js/cookie/jquery.cookie.js?' . $CC_CONFIG['airtime_version'], 'text/javascript') - ->appendFile($baseUrl . 'js/i18n/jquery.i18n.js?' . $CC_CONFIG['airtime_version'], 'text/javascript') - ->appendFile($baseUrl . 'locale/general-translation-table?' . $CC_CONFIG['airtime_version'], 'text/javascript') - ->appendFile($baseUrl . 'locale/datatables-translation-table?' . $CC_CONFIG['airtime_version'], 'text/javascript') - - ->appendScript("$.i18n.setDictionary(general_dict)") - ->appendScript("var baseUrl='$baseUrl'"); - - //These timezones are needed to adjust javascript Date objects on the client to make sense to the user's set timezone - //or the server's set timezone. - $serverTimeZone = new DateTimeZone(Application_Model_Preference::GetDefaultTimezone()); - $now = new DateTime("now", $serverTimeZone); - $offset = $now->format("Z") * -1; - $view->headScript()->appendScript("var serverTimezoneOffset = {$offset}; //in seconds"); - - if (class_exists("Zend_Auth", false) && Zend_Auth::getInstance()->hasIdentity()) { - $userTimeZone = new DateTimeZone(Application_Model_Preference::GetUserTimezone()); - $now = new DateTime("now", $userTimeZone); - $offset = $now->format("Z") * -1; - $view->headScript()->appendScript("var userTimezoneOffset = {$offset}; //in seconds"); - } - - //scripts for now playing bar - $view->headScript()->appendFile($baseUrl . 'js/airtime/airtime_bootstrap.js?' . $CC_CONFIG['airtime_version'], 'text/javascript') - ->appendFile($baseUrl . 'js/airtime/dashboard/helperfunctions.js?' . $CC_CONFIG['airtime_version'], 'text/javascript') - ->appendFile($baseUrl . 'js/airtime/dashboard/dashboard.js?' . $CC_CONFIG['airtime_version'], 'text/javascript') - ->appendFile($baseUrl . 'js/airtime/dashboard/versiontooltip.js?' . $CC_CONFIG['airtime_version'], 'text/javascript') - ->appendFile($baseUrl . 'js/tipsy/jquery.tipsy.js?' . $CC_CONFIG['airtime_version'], 'text/javascript') - - ->appendFile($baseUrl . 'js/airtime/common/common.js?' . $CC_CONFIG['airtime_version'], 'text/javascript') - ->appendFile($baseUrl . 'js/airtime/common/audioplaytest.js?' . $CC_CONFIG['airtime_version'], 'text/javascript'); - - $user = Application_Model_User::getCurrentUser(); - if (!is_null($user)) { - $userType = $user->getType(); - } else { - $userType = ""; - } - - $view->headScript()->appendScript("var userType = '$userType';"); - if (array_key_exists('REQUEST_URI', $_SERVER) //Doesn't exist for unit tests - && strpos($_SERVER['REQUEST_URI'], 'Dashboard/stream-player') === false - && strpos($_SERVER['REQUEST_URI'], 'audiopreview') === false - && $_SERVER['REQUEST_URI'] != "/") { - $plan_level = strval(Application_Model_Preference::GetPlanLevel()); - // Since the Hobbyist plan doesn't come with Live Chat support, don't enable it - if (Application_Model_Preference::GetLiveChatEnabled() && $plan_level !== 'hobbyist') { - $client_id = strval(Application_Model_Preference::GetClientId()); - $station_url = $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI']; - $view->headScript()->appendScript("var livechat_client_id = '$client_id';\n" . - "var livechat_plan_type = '$plan_level';\n" . - "var livechat_station_url = 'http://$station_url';"); - $view->headScript()->appendFile($baseUrl . 'js/airtime/common/livechat.js?' . $CC_CONFIG['airtime_version'], 'text/javascript'); - } - } - - /* - if (isset($CC_CONFIG['demo']) && $CC_CONFIG['demo'] == 1) { - $view->headScript()->appendFile($baseUrl.'js/libs/google-analytics.js?'.$CC_CONFIG['airtime_version'],'text/javascript'); - }*/ - } - - protected function _initViewHelpers() - { - $view = $this->getResource('view'); - $view->addHelperPath(APPLICATION_PATH . 'views/helpers', 'Airtime_View_Helper'); - $view->assign('suspended', (Application_Model_Preference::getProvisioningStatus() == PROVISIONING_STATUS_SUSPENDED)); - } - - protected function _initTitle() - { - $view = $this->getResource('view'); - $view->headTitle(Application_Model_Preference::GetHeadTitle()); - } protected function _initZFDebug() { @@ -293,6 +139,7 @@ class Bootstrap extends Zend_Application_Bootstrap_Bootstrap { $front = Zend_Controller_Front::getInstance(); $front->registerPlugin(new Zend_Controller_Plugin_Maintenance()); + $front->registerPlugin(new PageLayoutInitPlugin($this)); } } diff --git a/airtime_mvc/application/common/SecurityHelper.php b/airtime_mvc/application/common/SecurityHelper.php index baf4ca46b..f36ae638a 100644 --- a/airtime_mvc/application/common/SecurityHelper.php +++ b/airtime_mvc/application/common/SecurityHelper.php @@ -13,16 +13,11 @@ class SecurityHelper { return $arr; } - public static function verifyAjaxCSRFToken($observedToken) { + public static function verifyCSRFToken($observedToken) { $current_namespace = new Zend_Session_Namespace('csrf_namespace'); $observed_csrf_token = $observedToken; $expected_csrf_token = $current_namespace->authtoken; - if ($observed_csrf_token == $expected_csrf_token){ - return true; - }else{ - return false; - } - + return ($observed_csrf_token == $expected_csrf_token); } } \ No newline at end of file diff --git a/airtime_mvc/application/common/TaskManager.php b/airtime_mvc/application/common/TaskManager.php index c1687defa..c44be2552 100644 --- a/airtime_mvc/application/common/TaskManager.php +++ b/airtime_mvc/application/common/TaskManager.php @@ -114,6 +114,9 @@ final class TaskManager { * otherwise false */ private function _isUserSessionRequest() { + if (!Zend_Session::isStarted()) { + return false; + } $auth = Zend_Auth::getInstance(); $data = $auth->getStorage()->read(); return !empty($data); diff --git a/airtime_mvc/application/controllers/ApiController.php b/airtime_mvc/application/controllers/ApiController.php index d30013d8d..ca0d182ef 100644 --- a/airtime_mvc/application/controllers/ApiController.php +++ b/airtime_mvc/application/controllers/ApiController.php @@ -11,6 +11,8 @@ class ApiController extends Zend_Controller_Action public function init() { + + //Ignore API key and session authentication for these APIs: $ignoreAuth = array("live-info", "live-info-v2", "week-info", @@ -25,6 +27,11 @@ class ApiController extends Zend_Controller_Action "show-logo" ); + if (Zend_Session::isStarted()) { + Logging::error("Session already started for an API request. Check your code because + this will negatively impact performance."); + } + $params = $this->getRequest()->getParams(); if (!in_array($params['action'], $ignoreAuth)) { $this->checkAuth(); @@ -73,13 +80,23 @@ class ApiController extends Zend_Controller_Action $CC_CONFIG = Config::getConfig(); $api_key = $this->_getParam('api_key'); - if (!in_array($api_key, $CC_CONFIG["apiKey"]) && - is_null(Zend_Auth::getInstance()->getStorage()->read())) { - header('HTTP/1.0 401 Unauthorized'); - print _('You are not allowed to access this resource.'); - exit; + if (in_array($api_key, $CC_CONFIG["apiKey"])) { + return true; } - return true; + + //Start the session so the authentication is + //enforced by the ACL plugin. + Zend_Session::start(); + $authAdapter = Zend_Auth::getInstance(); + Application_Model_Auth::pinSessionToClient($authAdapter); + + if ((Zend_Auth::getInstance()->hasIdentity())) { + return true; + } + + header('HTTP/1.0 401 Unauthorized'); + print _('You are not allowed to access this resource.'); + exit(); } public function versionAction() diff --git a/airtime_mvc/application/controllers/BillingController.php b/airtime_mvc/application/controllers/BillingController.php index 2be8bc7e4..eb8cd5e88 100644 --- a/airtime_mvc/application/controllers/BillingController.php +++ b/airtime_mvc/application/controllers/BillingController.php @@ -25,7 +25,10 @@ class BillingController extends Zend_Controller_Action { $baseUrl = Application_Common_OsPath::getBaseDir(); $this->view->headLink()->appendStylesheet($baseUrl.'css/billing.css?'.$CC_CONFIG['airtime_version']); Billing::ensureClientIdIsValid(); - + + //Zend's CSRF token element requires the session to be open for writing + session_start(); + $request = $this->getRequest(); $form = new Application_Form_BillingUpgradeDowngrade(); @@ -219,7 +222,10 @@ class BillingController extends Zend_Controller_Action { $CC_CONFIG = Config::getConfig(); $baseUrl = Application_Common_OsPath::getBaseDir(); $this->view->headLink()->appendStylesheet($baseUrl.'css/billing.css?'.$CC_CONFIG['airtime_version']); - + + //Zend's CSRF token element requires the session to be open for writing + session_start(); + $request = $this->getRequest(); $form = new Application_Form_BillingClient(); Billing::ensureClientIdIsValid(); diff --git a/airtime_mvc/application/controllers/LoginController.php b/airtime_mvc/application/controllers/LoginController.php index b40178526..60c9b27be 100644 --- a/airtime_mvc/application/controllers/LoginController.php +++ b/airtime_mvc/application/controllers/LoginController.php @@ -8,8 +8,14 @@ class LoginController extends Zend_Controller_Action public function init() { - //Open the session for writing, because we close it for writing by default in Bootstrap.php as an optimization. - session_start(); + $CC_CONFIG = Config::getConfig(); + $baseUrl = Application_Common_OsPath::getBaseDir(); + + $this->view->headLink(array('rel' => 'icon', 'href' => $baseUrl . 'favicon.ico?' . $CC_CONFIG['airtime_version'], 'type' => 'image/x-icon'), 'PREPEND') + ->appendStylesheet($baseUrl . 'css/bootstrap.css?' . $CC_CONFIG['airtime_version']) + ->appendStylesheet($baseUrl . 'css/redmond/jquery-ui-1.8.8.custom.css?' . $CC_CONFIG['airtime_version']) + ->appendStylesheet($baseUrl . 'css/styles.css?' . $CC_CONFIG['airtime_version']); + } public function indexAction() @@ -22,13 +28,20 @@ class LoginController extends Zend_Controller_Action //Enable AJAX requests from www.airtime.pro for the sign-in process. CORSHelper::enableATProCrossOriginRequests($request, $response); - + Application_Model_Locale::configureLocalization($request->getcookie('airtime_locale', $stationLocale)); - $auth = Zend_Auth::getInstance(); - - if ($auth->hasIdentity()) { - $this->_redirect('Showbuilder'); + + if (Zend_Session::isStarted()) { + //Open the session for writing, because we close it for writing by default in Bootstrap.php as an optimization. + session_start(); + + $auth = Zend_Auth::getInstance(); + $auth->getStorage(); + + if ($auth->hasIdentity()) { + $this->_redirect('Showbuilder'); + } } //uses separate layout without a navigation. @@ -43,6 +56,10 @@ class LoginController extends Zend_Controller_Action $message = _("Please enter your username and password."); if ($request->isPost()) { + + //Open the session for writing, because we close it for writing by default in Bootstrap.php as an optimization. + //session_start(); + // if the post contains recaptcha field, which means form had recaptcha field. // Hence add the element for validation. if (array_key_exists('recaptcha_response_field', $request->getPost())) { @@ -117,6 +134,9 @@ class LoginController extends Zend_Controller_Action public function logoutAction() { + //Open the session for writing, because we close it for writing by default in Bootstrap.php as an optimization. + session_start(); + $auth = Zend_Auth::getInstance(); $auth->clearIdentity(); // Unset all session variables relating to CSRF prevention on logout diff --git a/airtime_mvc/application/controllers/PreferenceController.php b/airtime_mvc/application/controllers/PreferenceController.php index 478d1d332..6e991ba24 100644 --- a/airtime_mvc/application/controllers/PreferenceController.php +++ b/airtime_mvc/application/controllers/PreferenceController.php @@ -134,7 +134,7 @@ class PreferenceController extends Zend_Controller_Action // Remove reliance on .phtml files to render requests $this->_helper->viewRenderer->setNoRender(true); - if (!SecurityHelper::verifyAjaxCSRFToken($this->_getParam('csrf_token'))) { + if (!SecurityHelper::verifyCSRFToken($this->_getParam('csrf_token'))) { Logging::error(__FILE__ . ': Invalid CSRF token'); $this->_helper->json->sendJson(array("jsonrpc" => "2.0", "valid" => false, "error" => "CSRF token did not match.")); return; @@ -486,7 +486,7 @@ class PreferenceController extends Zend_Controller_Action $this->view->layout()->disableLayout(); $this->_helper->viewRenderer->setNoRender(true); - if (!SecurityHelper::verifyAjaxCSRFToken($this->_getParam('csrf_token'))) { + if (!SecurityHelper::verifyCSRFToken($this->_getParam('csrf_token'))) { Logging::error(__FILE__ . ': Invalid CSRF token'); $this->_helper->json->sendJson(array("jsonrpc" => "2.0", "valid" => false, "error" => "CSRF token did not match.")); return; diff --git a/airtime_mvc/application/controllers/plugins/Acl_plugin.php b/airtime_mvc/application/controllers/plugins/Acl_plugin.php index c08533ab9..35df192d6 100644 --- a/airtime_mvc/application/controllers/plugins/Acl_plugin.php +++ b/airtime_mvc/application/controllers/plugins/Acl_plugin.php @@ -109,9 +109,10 @@ class Zend_Controller_Plugin_Acl extends Zend_Controller_Plugin_Abstract public function preDispatch(Zend_Controller_Request_Abstract $request) { $controller = strtolower($request->getControllerName()); - Application_Model_Auth::pinSessionToClient(Zend_Auth::getInstance()); if (in_array($controller, array( + "index", + "login", "api", "auth", "error", @@ -123,7 +124,10 @@ class Zend_Controller_Plugin_Acl extends Zend_Controller_Plugin_Abstract ))) { $this->setRoleName("G"); - } elseif (!Zend_Auth::getInstance()->hasIdentity()) { + } + elseif (Zend_Session::isStarted() && !Zend_Auth::getInstance()->hasIdentity()) { + + //The controller uses sessions but we don't have an identity yet. // If we don't have an identity and we're making a RESTful request, // we need to do API key verification @@ -165,6 +169,7 @@ class Zend_Controller_Plugin_Acl extends Zend_Controller_Plugin_Abstract } } } else { //We have a session/identity. + // If we have an identity and we're making a RESTful request, // we need to check the CSRF token if ($_SERVER['REQUEST_METHOD'] != "GET" && $request->getModuleName() == "rest") { @@ -222,11 +227,7 @@ class Zend_Controller_Plugin_Acl extends Zend_Controller_Plugin_Abstract } private function verifyCSRFToken($token) { - $current_namespace = new Zend_Session_Namespace('csrf_namespace'); - $observed_csrf_token = $token; - $expected_csrf_token = $current_namespace->authtoken; - - return ($observed_csrf_token == $expected_csrf_token); + SecurityHelper::verifyCSRFToken($token); } private function verifyAPIKey() { diff --git a/airtime_mvc/application/controllers/plugins/ConversionTracking.php b/airtime_mvc/application/controllers/plugins/ConversionTracking.php index 09904828d..ae0fc2781 100644 --- a/airtime_mvc/application/controllers/plugins/ConversionTracking.php +++ b/airtime_mvc/application/controllers/plugins/ConversionTracking.php @@ -4,6 +4,10 @@ class Zend_Controller_Plugin_ConversionTracking extends Zend_Controller_Plugin_A { public function preDispatch(Zend_Controller_Request_Abstract $request) { + if (!Zend_Session::isStarted()) { + return; + } + //If user is a super admin and old plan level is set to trial.... if (Application_Common_GoogleAnalytics::didPaidConversionOccur($request)) { diff --git a/airtime_mvc/application/controllers/plugins/PageLayoutInitPlugin.php b/airtime_mvc/application/controllers/plugins/PageLayoutInitPlugin.php new file mode 100644 index 000000000..091bdcfcd --- /dev/null +++ b/airtime_mvc/application/controllers/plugins/PageLayoutInitPlugin.php @@ -0,0 +1,232 @@ +_bootstrap = $boostrap; + } + + /** + * Start the session depending on which controller your request is going to. + * We start the session explicitly here so that we can avoid starting sessions + * needlessly for (stateless) requests to the API. + * @param Zend_Controller_Request_Abstract $request + * @throws Zend_Session_Exception + */ + public function routeShutdown(Zend_Controller_Request_Abstract $request) + { + $controller = strtolower($request->getControllerName()); + $action = strtolower($request->getActionName()); + + //List of controllers where we don't need a session, and we don't need + //all the standard HTML / JS boilerplate. + if (!in_array($controller, array( + "index", //Radio Page + "api", + "auth", + "error", + "locale", + "upgrade", + 'whmcs-login', + "provisioning", + "embed" + )) + ) { + //Start the session + Zend_Session::start(); + Application_Model_Auth::pinSessionToClient(Zend_Auth::getInstance()); + + //localization configuration + Application_Model_Locale::configureLocalization(); + + $this->_initGlobals(); + $this->_initCsrfNamespace(); + $this->_initHeadLink(); + $this->_initHeadScript(); + $this->_initTitle(); + $this->_initTranslationGlobals(); + $this->_initViewHelpers(); + } + } + + protected function _initGlobals() + { + if (!Zend_Session::isStarted()) { + return; + } + + $view = $this->_bootstrap->getResource('view'); + $baseUrl = Application_Common_OsPath::getBaseDir(); + + $view->headScript()->appendScript("var baseUrl = '$baseUrl';"); + $this->_initTranslationGlobals($view); + + $user = Application_Model_User::GetCurrentUser(); + if (!is_null($user)) { + $userType = $user->getType(); + } else { + $userType = ""; + } + $view->headScript()->appendScript("var userType = '$userType';"); + } + + /** + * Create a global namespace to hold a session token for CSRF prevention + */ + protected function _initCsrfNamespace() + { + /* + if (!Zend_Session::isStarted()) { + return; + }*/ + + $csrf_namespace = new Zend_Session_Namespace('csrf_namespace'); + // Check if the token exists + if (!$csrf_namespace->authtoken) { + // If we don't have a token, regenerate it and set a 1 week timeout + // Should we log the user out here if the token is expired? + $csrf_namespace->authtoken = sha1(uniqid(rand(), 1)); + $csrf_namespace->setExpirationSeconds(168 * 60 * 60); + } + + //Here we are closing the session for writing because otherwise no requests + //in this session will be handled in parallel. This gives a major boost to the perceived performance + //of the application (page load times are more consistent, no lock contention). + session_write_close(); + //Zend_Session::writeClose(true); + } + + /** + * Ideally, globals should be written to a single js file once + * from a php init function. This will save us from having to + * reinitialize them every request + */ + private function _initTranslationGlobals() + { + $view = $this->_bootstrap->getResource('view'); + $view->headScript()->appendScript("var PRODUCT_NAME = '" . PRODUCT_NAME . "';"); + $view->headScript()->appendScript("var USER_MANUAL_URL = '" . USER_MANUAL_URL . "';"); + $view->headScript()->appendScript("var COMPANY_NAME = '" . COMPANY_NAME . "';"); + } + + protected function _initHeadLink() + { + $CC_CONFIG = Config::getConfig(); + + $view = $this->_bootstrap->getResource('view'); + + $baseUrl = Application_Common_OsPath::getBaseDir(); + + $view->headLink(array('rel' => 'icon', 'href' => $baseUrl . 'favicon.ico?' . $CC_CONFIG['airtime_version'], 'type' => 'image/x-icon'), 'PREPEND') + ->appendStylesheet($baseUrl . 'css/bootstrap.css?' . $CC_CONFIG['airtime_version']) + ->appendStylesheet($baseUrl . 'css/redmond/jquery-ui-1.8.8.custom.css?' . $CC_CONFIG['airtime_version']) + ->appendStylesheet($baseUrl . 'css/pro_dropdown_3.css?' . $CC_CONFIG['airtime_version']) + ->appendStylesheet($baseUrl . 'css/qtip/jquery.qtip.min.css?' . $CC_CONFIG['airtime_version']) + ->appendStylesheet($baseUrl . 'css/styles.css?' . $CC_CONFIG['airtime_version']) + ->appendStylesheet($baseUrl . 'css/masterpanel.css?' . $CC_CONFIG['airtime_version']) + ->appendStylesheet($baseUrl . 'css/tipsy/jquery.tipsy.css?' . $CC_CONFIG['airtime_version']); + } + + protected function _initHeadScript() + { + if (!Zend_Session::isStarted()) { + return; + } + + $CC_CONFIG = Config::getConfig(); + + $view = $this->_bootstrap->getResource('view'); + + $baseUrl = Application_Common_OsPath::getBaseDir(); + + $view->headScript()->appendFile($baseUrl . 'js/libs/jquery-1.8.3.min.js?' . $CC_CONFIG['airtime_version'], 'text/javascript') + ->appendFile($baseUrl . 'js/libs/jquery-ui-1.8.24.min.js?' . $CC_CONFIG['airtime_version'], 'text/javascript') + ->appendFile($baseUrl . 'js/bootstrap/bootstrap.js?' . $CC_CONFIG['airtime_version'], 'text/javascript') + ->appendFile($baseUrl . 'js/libs/underscore-min.js?' . $CC_CONFIG['airtime_version'], 'text/javascript') + + // ->appendFile($baseUrl . 'js/libs/jquery.stickyPanel.js?' . $CC_CONFIG['airtime_version'], 'text/javascript') + ->appendFile($baseUrl . 'js/qtip/jquery.qtip.js?' . $CC_CONFIG['airtime_version'], 'text/javascript') + ->appendFile($baseUrl . 'js/jplayer/jquery.jplayer.min.js?' . $CC_CONFIG['airtime_version'], 'text/javascript') + ->appendFile($baseUrl . 'js/sprintf/sprintf-0.7-beta1.js?' . $CC_CONFIG['airtime_version'], 'text/javascript') + ->appendFile($baseUrl . 'js/cookie/jquery.cookie.js?' . $CC_CONFIG['airtime_version'], 'text/javascript') + ->appendFile($baseUrl . 'js/i18n/jquery.i18n.js?' . $CC_CONFIG['airtime_version'], 'text/javascript') + ->appendFile($baseUrl . 'locale/general-translation-table?' . $CC_CONFIG['airtime_version'], 'text/javascript') + ->appendFile($baseUrl . 'locale/datatables-translation-table?' . $CC_CONFIG['airtime_version'], 'text/javascript') + + ->appendScript("$.i18n.setDictionary(general_dict)") + ->appendScript("var baseUrl='$baseUrl'"); + + //These timezones are needed to adjust javascript Date objects on the client to make sense to the user's set timezone + //or the server's set timezone. + $serverTimeZone = new DateTimeZone(Application_Model_Preference::GetDefaultTimezone()); + $now = new DateTime("now", $serverTimeZone); + $offset = $now->format("Z") * -1; + $view->headScript()->appendScript("var serverTimezoneOffset = {$offset}; //in seconds"); + + if (class_exists("Zend_Auth", false) && Zend_Auth::getInstance()->hasIdentity()) { + $userTimeZone = new DateTimeZone(Application_Model_Preference::GetUserTimezone()); + $now = new DateTime("now", $userTimeZone); + $offset = $now->format("Z") * -1; + $view->headScript()->appendScript("var userTimezoneOffset = {$offset}; //in seconds"); + } + + //scripts for now playing bar + $view->headScript()->appendFile($baseUrl . 'js/airtime/airtime_bootstrap.js?' . $CC_CONFIG['airtime_version'], 'text/javascript') + ->appendFile($baseUrl . 'js/airtime/dashboard/helperfunctions.js?' . $CC_CONFIG['airtime_version'], 'text/javascript') + ->appendFile($baseUrl . 'js/airtime/dashboard/dashboard.js?' . $CC_CONFIG['airtime_version'], 'text/javascript') + ->appendFile($baseUrl . 'js/airtime/dashboard/versiontooltip.js?' . $CC_CONFIG['airtime_version'], 'text/javascript') + ->appendFile($baseUrl . 'js/tipsy/jquery.tipsy.js?' . $CC_CONFIG['airtime_version'], 'text/javascript') + + ->appendFile($baseUrl . 'js/airtime/common/common.js?' . $CC_CONFIG['airtime_version'], 'text/javascript') + ->appendFile($baseUrl . 'js/airtime/common/audioplaytest.js?' . $CC_CONFIG['airtime_version'], 'text/javascript'); + + $user = Application_Model_User::getCurrentUser(); + if (!is_null($user)) { + $userType = $user->getType(); + } else { + $userType = ""; + } + + $view->headScript()->appendScript("var userType = '$userType';"); + if (array_key_exists('REQUEST_URI', $_SERVER) //Doesn't exist for unit tests + && strpos($_SERVER['REQUEST_URI'], 'Dashboard/stream-player') === false + && strpos($_SERVER['REQUEST_URI'], 'audiopreview') === false + && $_SERVER['REQUEST_URI'] != "/") { + $plan_level = strval(Application_Model_Preference::GetPlanLevel()); + // Since the Hobbyist plan doesn't come with Live Chat support, don't enable it + if (Application_Model_Preference::GetLiveChatEnabled() && $plan_level !== 'hobbyist') { + $client_id = strval(Application_Model_Preference::GetClientId()); + $station_url = $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI']; + $view->headScript()->appendScript("var livechat_client_id = '$client_id';\n" . + "var livechat_plan_type = '$plan_level';\n" . + "var livechat_station_url = 'http://$station_url';"); + $view->headScript()->appendFile($baseUrl . 'js/airtime/common/livechat.js?' . $CC_CONFIG['airtime_version'], 'text/javascript'); + } + } + + /* + if (isset($CC_CONFIG['demo']) && $CC_CONFIG['demo'] == 1) { + $view->headScript()->appendFile($baseUrl.'js/libs/google-analytics.js?'.$CC_CONFIG['airtime_version'],'text/javascript'); + }*/ + } + + protected function _initViewHelpers() + { + $view = $this->_bootstrap->getResource('view'); + $view->addHelperPath(APPLICATION_PATH . 'views/helpers', 'Airtime_View_Helper'); + $view->assign('suspended', (Application_Model_Preference::getProvisioningStatus() == PROVISIONING_STATUS_SUSPENDED)); + } + + protected function _initTitle() + { + $view = $this->_bootstrap->getResource('view'); + $view->headTitle(Application_Model_Preference::GetHeadTitle()); + } +} \ No newline at end of file diff --git a/airtime_mvc/application/forms/BillingClient.php b/airtime_mvc/application/forms/BillingClient.php index 891cd4a95..7d604cad2 100644 --- a/airtime_mvc/application/forms/BillingClient.php +++ b/airtime_mvc/application/forms/BillingClient.php @@ -188,6 +188,10 @@ class Application_Form_BillingClient extends Zend_Form $passwordVerify->addValidator($notEmptyValidator); $this->addElement($passwordVerify); + $this->addElement('hash', 'csrf', array( + 'salt' => 'unique' + )); + $submit = new Zend_Form_Element_Submit("submit"); $submit->setIgnore(true) ->setLabel(_("Save")); diff --git a/airtime_mvc/application/forms/BillingUpgradeDowngrade.php b/airtime_mvc/application/forms/BillingUpgradeDowngrade.php index ecf9b4f50..5ff4ff4de 100644 --- a/airtime_mvc/application/forms/BillingUpgradeDowngrade.php +++ b/airtime_mvc/application/forms/BillingUpgradeDowngrade.php @@ -8,6 +8,10 @@ class Application_Form_BillingUpgradeDowngrade extends Zend_Form $csrf_element->setValue($csrf_namespace->authtoken)->setRequired('true')->removeDecorator('HtmlTag')->removeDecorator('Label'); $this->addElement($csrf_element); + $this->addElement('hash', 'csrf', array( + 'salt' => 'unique' + )); + $productPrices = array(); $productTypes = array(); list($productPrices, $productTypes) = Billing::getProductPricesAndTypes(); diff --git a/airtime_mvc/application/models/Preference.php b/airtime_mvc/application/models/Preference.php index c6e6fff49..cd439ddbe 100644 --- a/airtime_mvc/application/models/Preference.php +++ b/airtime_mvc/application/models/Preference.php @@ -10,7 +10,7 @@ class Application_Model_Preference { //pass in true so the check is made with the autoloader //we need this check because saas calls this function from outside Zend - if (!class_exists("Zend_Auth", true) || !Zend_Auth::getInstance()->hasIdentity()) { + if (!Zend_Session::isStarted() || !class_exists("Zend_Auth", true) || !Zend_Auth::getInstance()->hasIdentity()) { $userId = null; } else { $auth = Zend_Auth::getInstance(); @@ -142,10 +142,14 @@ class Application_Model_Preference try { - $userId = self::getUserId(); - - if ($isUserValue && is_null($userId)) - throw new Exception("User id can't be null for a user preference."); + $userId = null; + if ($isUserValue) { + //This is nested in here because so we can still use getValue() when the session hasn't started yet. + $userId = self::getUserId(); + if (is_null($userId)) { + throw new Exception("User id can't be null for a user preference."); + } + } // If the value is already cached, return it $res = $cache->fetch($key, $isUserValue, $userId); @@ -192,7 +196,7 @@ class Application_Model_Preference } catch (Exception $e) { header('HTTP/1.0 503 Service Unavailable'); - Logging::info("Could not connect to database: ".$e->getMessage()); + Logging::info("Could not connect to database: ".$e); exit; } } From 91c584ba164a06cd21075944986bb51cc3f975bc Mon Sep 17 00:00:00 2001 From: Albert Santoni Date: Fri, 25 Sep 2015 11:37:36 -0400 Subject: [PATCH 4/7] Test alternate session reopening code to alleviate double Set-Cookie header --- airtime_mvc/application/controllers/LoginController.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/airtime_mvc/application/controllers/LoginController.php b/airtime_mvc/application/controllers/LoginController.php index 60c9b27be..1090c312c 100644 --- a/airtime_mvc/application/controllers/LoginController.php +++ b/airtime_mvc/application/controllers/LoginController.php @@ -33,8 +33,15 @@ class LoginController extends Zend_Controller_Action Application_Model_Locale::configureLocalization($request->getcookie('airtime_locale', $stationLocale)); if (Zend_Session::isStarted()) { + + ini_set('session.use_only_cookies', false); + ini_set('session.use_cookies', false); + ini_set('session.use_trans_sid', false); + ini_set('session.cache_limiter', null); + session_start(); // second session_start + //Open the session for writing, because we close it for writing by default in Bootstrap.php as an optimization. - session_start(); + //session_start(); $auth = Zend_Auth::getInstance(); $auth->getStorage(); From 8b6833180d8a11b943044a8bc694f2bb901d1cb1 Mon Sep 17 00:00:00 2001 From: Albert Santoni Date: Fri, 25 Sep 2015 12:03:10 -0400 Subject: [PATCH 5/7] Refactored double Set-Cookie prevention code, and session reopening code --- airtime_mvc/application/Bootstrap.php | 1 + airtime_mvc/application/common/SessionHelper.php | 13 +++++++++++++ .../application/controllers/BillingController.php | 4 ++-- .../application/controllers/LoginController.php | 10 ++-------- .../application/controllers/PlaylistController.php | 2 +- .../controllers/PreferenceController.php | 12 ++++++------ .../application/controllers/UserController.php | 4 ++-- .../controllers/UsersettingsController.php | 6 +++--- 8 files changed, 30 insertions(+), 22 deletions(-) create mode 100644 airtime_mvc/application/common/SessionHelper.php diff --git a/airtime_mvc/application/Bootstrap.php b/airtime_mvc/application/Bootstrap.php index 274d38981..e6b23f947 100644 --- a/airtime_mvc/application/Bootstrap.php +++ b/airtime_mvc/application/Bootstrap.php @@ -25,6 +25,7 @@ require_once "OsPath.php"; require_once "Database.php"; require_once "ProvisioningHelper.php"; require_once "SecurityHelper.php"; +require_once "SessionHelper.php"; require_once "GoogleAnalytics.php"; require_once "Timezone.php"; require_once "Auth.php"; diff --git a/airtime_mvc/application/common/SessionHelper.php b/airtime_mvc/application/common/SessionHelper.php new file mode 100644 index 000000000..badfa1924 --- /dev/null +++ b/airtime_mvc/application/common/SessionHelper.php @@ -0,0 +1,13 @@ +getRequest(); $form = new Application_Form_BillingUpgradeDowngrade(); @@ -224,7 +224,7 @@ class BillingController extends Zend_Controller_Action { $this->view->headLink()->appendStylesheet($baseUrl.'css/billing.css?'.$CC_CONFIG['airtime_version']); //Zend's CSRF token element requires the session to be open for writing - session_start(); + SessionHelper::reopenSessionForWriting(); $request = $this->getRequest(); $form = new Application_Form_BillingClient(); diff --git a/airtime_mvc/application/controllers/LoginController.php b/airtime_mvc/application/controllers/LoginController.php index 1090c312c..af530a330 100644 --- a/airtime_mvc/application/controllers/LoginController.php +++ b/airtime_mvc/application/controllers/LoginController.php @@ -34,14 +34,8 @@ class LoginController extends Zend_Controller_Action if (Zend_Session::isStarted()) { - ini_set('session.use_only_cookies', false); - ini_set('session.use_cookies', false); - ini_set('session.use_trans_sid', false); - ini_set('session.cache_limiter', null); - session_start(); // second session_start - //Open the session for writing, because we close it for writing by default in Bootstrap.php as an optimization. - //session_start(); + SessionHelper::reopenSessionForWriting(); $auth = Zend_Auth::getInstance(); $auth->getStorage(); @@ -142,7 +136,7 @@ class LoginController extends Zend_Controller_Action public function logoutAction() { //Open the session for writing, because we close it for writing by default in Bootstrap.php as an optimization. - session_start(); + SessionHelper::reopenSessionForWriting(); $auth = Zend_Auth::getInstance(); $auth->clearIdentity(); diff --git a/airtime_mvc/application/controllers/PlaylistController.php b/airtime_mvc/application/controllers/PlaylistController.php index 2bbe691e1..59572e440 100644 --- a/airtime_mvc/application/controllers/PlaylistController.php +++ b/airtime_mvc/application/controllers/PlaylistController.php @@ -32,7 +32,7 @@ class PlaylistController extends Zend_Controller_Action ->initContext(); //This controller writes to the session all over the place, so we're going to reopen it for writing here. - session_start(); //Reopen the session for writing + SessionHelper::reopenSessionForWriting(); } private function getPlaylist($p_type) diff --git a/airtime_mvc/application/controllers/PreferenceController.php b/airtime_mvc/application/controllers/PreferenceController.php index 6e991ba24..d156d0490 100644 --- a/airtime_mvc/application/controllers/PreferenceController.php +++ b/airtime_mvc/application/controllers/PreferenceController.php @@ -32,7 +32,7 @@ class PreferenceController extends Zend_Controller_Action $form = new Application_Form_Preferences(); $values = array(); - session_start(); //Open session for writing. + SessionHelper::reopenSessionForWriting(); if ($request->isPost()) { $values = $request->getPost(); @@ -92,7 +92,7 @@ class PreferenceController extends Zend_Controller_Action $this->view->headScript()->appendFile($baseUrl.'js/airtime/preferences/support-setting.js?'.$CC_CONFIG['airtime_version'],'text/javascript'); $this->view->statusMsg = ""; - session_start(); //Open session for writing. + SessionHelper::reopenSessionForWriting(); $form = new Application_Form_SupportSettings(); if ($request->isPost()) { @@ -128,7 +128,7 @@ class PreferenceController extends Zend_Controller_Action public function removeLogoAction() { - session_start(); //Open session for writing. + SessionHelper::reopenSessionForWriting(); $this->view->layout()->disableLayout(); // Remove reliance on .phtml files to render requests @@ -153,7 +153,7 @@ class PreferenceController extends Zend_Controller_Action $this->view->headScript()->appendFile($baseUrl.'js/airtime/preferences/streamsetting.js?'.$CC_CONFIG['airtime_version'],'text/javascript'); - session_start(); //Open session for writing. + SessionHelper::reopenSessionForWriting(); $name_map = array( 'ogg' => 'Ogg Vorbis', @@ -447,7 +447,7 @@ class PreferenceController extends Zend_Controller_Action public function setSourceConnectionUrlAction() { - session_start(); //Open session for writing. + SessionHelper::reopenSessionForWriting(); $request = $this->getRequest(); $type = $request->getParam("type", null); @@ -467,7 +467,7 @@ class PreferenceController extends Zend_Controller_Action public function getAdminPasswordStatusAction() { - session_start(); //Open session for writing. + SessionHelper::reopenSessionForWriting(); $out = array(); $num_of_stream = intval(Application_Model_Preference::GetNumOfStreams()); diff --git a/airtime_mvc/application/controllers/UserController.php b/airtime_mvc/application/controllers/UserController.php index 264444562..10f86b73e 100644 --- a/airtime_mvc/application/controllers/UserController.php +++ b/airtime_mvc/application/controllers/UserController.php @@ -18,7 +18,7 @@ class UserController extends Zend_Controller_Action { // Start the session to re-open write permission to the session so we can // create the namespace for our csrf token verification - session_start(); + SessionHelper::reopenSessionForWriting(); $CC_CONFIG = Config::getConfig(); $request = $this->getRequest(); @@ -121,7 +121,7 @@ class UserController extends Zend_Controller_Action public function editUserAction() { - session_start(); //Reopen session for writing. + SessionHelper::reopenSessionForWriting(); $request = $this->getRequest(); $form = new Application_Form_EditUser(); if ($request->isPost()) { diff --git a/airtime_mvc/application/controllers/UsersettingsController.php b/airtime_mvc/application/controllers/UsersettingsController.php index 35fbb19e1..519e854b8 100644 --- a/airtime_mvc/application/controllers/UsersettingsController.php +++ b/airtime_mvc/application/controllers/UsersettingsController.php @@ -70,14 +70,14 @@ class UsersettingsController extends Zend_Controller_Action public function remindmeAction() { // unset session - session_start(); //open session for writing again + SessionHelper::reopenSessionForWriting(); Zend_Session::namespaceUnset('referrer'); Application_Model_Preference::SetRemindMeDate(); } public function remindmeNeverAction() { - session_start(); //open session for writing again + SessionHelper::reopenSessionForWriting(); Zend_Session::namespaceUnset('referrer'); //pass in true to indicate 'Remind me never' was clicked Application_Model_Preference::SetRemindMeDate(true); @@ -86,7 +86,7 @@ class UsersettingsController extends Zend_Controller_Action public function donotshowregistrationpopupAction() { // unset session - session_start(); //open session for writing again + SessionHelper::reopenSessionForWriting(); Zend_Session::namespaceUnset('referrer'); } From e03428327cf2a72e348d68c4483cc09ce3321dd5 Mon Sep 17 00:00:00 2001 From: Albert Santoni Date: Fri, 25 Sep 2015 15:54:26 -0400 Subject: [PATCH 6/7] Fixed missing return statement --- airtime_mvc/application/controllers/plugins/Acl_plugin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/airtime_mvc/application/controllers/plugins/Acl_plugin.php b/airtime_mvc/application/controllers/plugins/Acl_plugin.php index 35df192d6..693363c7c 100644 --- a/airtime_mvc/application/controllers/plugins/Acl_plugin.php +++ b/airtime_mvc/application/controllers/plugins/Acl_plugin.php @@ -227,7 +227,7 @@ class Zend_Controller_Plugin_Acl extends Zend_Controller_Plugin_Abstract } private function verifyCSRFToken($token) { - SecurityHelper::verifyCSRFToken($token); + return SecurityHelper::verifyCSRFToken($token); } private function verifyAPIKey() { From 943048dd878799163e4a86f15e0af2a0241931ba Mon Sep 17 00:00:00 2001 From: Albert Santoni Date: Mon, 28 Sep 2015 17:48:04 -0400 Subject: [PATCH 7/7] Hacky fix for SAAS-1090 - Allow airtime-system to work with session optimizations --- airtime_mvc/application/models/Preference.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/airtime_mvc/application/models/Preference.php b/airtime_mvc/application/models/Preference.php index cd439ddbe..d51c74c8f 100644 --- a/airtime_mvc/application/models/Preference.php +++ b/airtime_mvc/application/models/Preference.php @@ -10,7 +10,7 @@ class Application_Model_Preference { //pass in true so the check is made with the autoloader //we need this check because saas calls this function from outside Zend - if (!Zend_Session::isStarted() || !class_exists("Zend_Auth", true) || !Zend_Auth::getInstance()->hasIdentity()) { + if (!class_exists("Zend_Session", true) || !Zend_Session::isStarted() || !class_exists("Zend_Auth", true) || !Zend_Auth::getInstance()->hasIdentity()) { $userId = null; } else { $auth = Zend_Auth::getInstance();