]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - include/MVC/SugarApplication.php
Release 6.5.16
[Github/sugarcrm.git] / include / MVC / SugarApplication.php
1 <?php
2 /*********************************************************************************
3  * SugarCRM Community Edition is a customer relationship management program developed by
4  * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
5  * 
6  * This program is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU Affero General Public License version 3 as published by the
8  * Free Software Foundation with the addition of the following permission added
9  * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
10  * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
11  * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
12  * 
13  * This program is distributed in the hope that it will be useful, but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15  * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
16  * details.
17  * 
18  * You should have received a copy of the GNU Affero General Public License along with
19  * this program; if not, see http://www.gnu.org/licenses or write to the Free
20  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21  * 02110-1301 USA.
22  * 
23  * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
24  * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
25  * 
26  * The interactive user interfaces in modified source and object code versions
27  * of this program must display Appropriate Legal Notices, as required under
28  * Section 5 of the GNU Affero General Public License version 3.
29  * 
30  * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
31  * these Appropriate Legal Notices must retain the display of the "Powered by
32  * SugarCRM" logo. If the display of the logo is not reasonably feasible for
33  * technical reasons, the Appropriate Legal Notices must display the words
34  * "Powered by SugarCRM".
35  ********************************************************************************/
36
37 /*
38  * Created on Mar 21, 2007
39  *
40  * To change the template for this generated file go to
41  * Window - Preferences - PHPeclipse - PHP - Code Templates
42  */
43 require_once('include/MVC/Controller/ControllerFactory.php');
44 require_once('include/MVC/View/ViewFactory.php');
45
46 /**
47  * SugarCRM application
48  * @api
49  */
50 class SugarApplication
51 {
52         var $controller = null;
53         var $headerDisplayed = false;
54         var $default_module = 'Home';
55         var $default_action = 'index';
56
57         function SugarApplication()
58         {}
59
60         /**
61          * Perform execution of the application. This method is called from index2.php
62          */
63         function execute(){
64                 global $sugar_config;
65                 if(!empty($sugar_config['default_module']))
66                         $this->default_module = $sugar_config['default_module'];
67                 $module = $this->default_module;
68                 if(!empty($_REQUEST['module']))$module = $_REQUEST['module'];
69                 insert_charset_header();
70                 $this->setupPrint();
71                 $this->controller = ControllerFactory::getController($module);
72         // If the entry point is defined to not need auth, then don't authenticate.
73                 if( empty($_REQUEST['entryPoint'])
74                 || $this->controller->checkEntryPointRequiresAuth($_REQUEST['entryPoint']) ){
75             $this->loadUser();
76             $this->ACLFilter();
77             $this->preProcess();
78             $this->controller->preProcess();
79             $this->checkHTTPReferer();
80         }
81
82         SugarThemeRegistry::buildRegistry();
83         $this->loadLanguages();
84                 $this->checkDatabaseVersion();
85                 $this->loadDisplaySettings();
86                 $this->loadLicense();
87                 $this->loadGlobals();
88                 $this->setupResourceManagement($module);
89                 $this->controller->execute();
90                 sugar_cleanup();
91         }
92
93         /**
94          * Load the authenticated user. If there is not an authenticated user then redirect to login screen.
95          */
96         function loadUser(){
97                 global $authController, $sugar_config;
98                 // Double check the server's unique key is in the session.  Make sure this is not an attempt to hijack a session
99                 $user_unique_key = (isset($_SESSION['unique_key'])) ? $_SESSION['unique_key'] : '';
100                 $server_unique_key = (isset($sugar_config['unique_key'])) ? $sugar_config['unique_key'] : '';
101                 $allowed_actions = (!empty($this->controller->allowed_actions)) ? $this->controller->allowed_actions : $allowed_actions = array('Authenticate', 'Login', 'LoggedOut');
102
103         $authController = new AuthenticationController();
104         
105                 if(($user_unique_key != $server_unique_key) && (!in_array($this->controller->action, $allowed_actions)) &&
106                    (!isset($_SESSION['login_error'])))
107                    {
108                         session_destroy();
109
110                         if(!empty($this->controller->action)){
111                             if(strtolower($this->controller->action) == 'delete')
112                                 $this->controller->action = 'DetailView';
113                             elseif(strtolower($this->controller->action) == 'save')
114                                 $this->controller->action = 'EditView';
115                 elseif(strtolower($this->controller->action) == 'quickcreate') {
116                     $this->controller->action = 'index';
117                     $this->controller->module = 'home';
118                 }
119                             elseif(isset($_REQUEST['massupdate'])|| isset($_GET['massupdate']) || isset($_POST['massupdate']))
120                                 $this->controller->action = 'index';
121                             elseif($this->isModifyAction())
122                                 $this->controller->action = 'index';
123                 elseif ($this->controller->action == $this->default_action 
124                     && $this->controller->module == $this->default_module) {
125                     $this->controller->action = '';
126                     $this->controller->module = '';
127                 }
128                         }
129
130             $authController->authController->redirectToLogin($this);
131                 }
132
133                 $GLOBALS['current_user'] = new User();
134                 if(isset($_SESSION['authenticated_user_id'])){
135                         // set in modules/Users/Authenticate.php
136                         if(!$authController->sessionAuthenticate()){
137                                  // if the object we get back is null for some reason, this will break - like user prefs are corrupted
138                                 $GLOBALS['log']->fatal('User retrieval for ID: ('.$_SESSION['authenticated_user_id'].') does not exist in database or retrieval failed catastrophically.  Calling session_destroy() and sending user to Login page.');
139                                 session_destroy();
140                                 SugarApplication::redirect('index.php?action=Login&module=Users');
141                                 die();
142                         }//fi
143                 }elseif(!($this->controller->module == 'Users' && in_array($this->controller->action, $allowed_actions))){
144                         session_destroy();
145                         SugarApplication::redirect('index.php?action=Login&module=Users');
146                         die();
147                 }
148                 $GLOBALS['log']->debug('Current user is: '.$GLOBALS['current_user']->user_name);
149
150                 //set cookies
151                 if(isset($_SESSION['authenticated_user_id'])){
152                         $GLOBALS['log']->debug("setting cookie ck_login_id_20 to ".$_SESSION['authenticated_user_id']);
153                         self::setCookie('ck_login_id_20', $_SESSION['authenticated_user_id'], time() + 86400 * 90);
154                 }
155                 if(isset($_SESSION['authenticated_user_theme'])){
156                         $GLOBALS['log']->debug("setting cookie ck_login_theme_20 to ".$_SESSION['authenticated_user_theme']);
157                         self::setCookie('ck_login_theme_20', $_SESSION['authenticated_user_theme'], time() + 86400 * 90);
158                 }
159                 if(isset($_SESSION['authenticated_user_theme_color'])){
160                         $GLOBALS['log']->debug("setting cookie ck_login_theme_color_20 to ".$_SESSION['authenticated_user_theme_color']);
161                         self::setCookie('ck_login_theme_color_20', $_SESSION['authenticated_user_theme_color'], time() + 86400 * 90);
162                 }
163                 if(isset($_SESSION['authenticated_user_theme_font'])){
164                         $GLOBALS['log']->debug("setting cookie ck_login_theme_font_20 to ".$_SESSION['authenticated_user_theme_font']);
165                         self::setCookie('ck_login_theme_font_20', $_SESSION['authenticated_user_theme_font'], time() + 86400 * 90);
166                 }
167                 if(isset($_SESSION['authenticated_user_language'])){
168                         $GLOBALS['log']->debug("setting cookie ck_login_language_20 to ".$_SESSION['authenticated_user_language']);
169                         self::setCookie('ck_login_language_20', $_SESSION['authenticated_user_language'], time() + 86400 * 90);
170                 }
171                 //check if user can access
172
173         }
174
175         function ACLFilter(){
176                 ACLController :: filterModuleList($GLOBALS['moduleList']);
177         }
178
179         /**
180          * setupResourceManagement
181          * This function initialize the ResourceManager and calls the setup method
182          * on the ResourceManager instance.
183          *
184          */
185         function setupResourceManagement($module) {
186                 require_once('include/resource/ResourceManager.php');
187                 $resourceManager = ResourceManager::getInstance();
188                 $resourceManager->setup($module);
189         }
190
191         function setupPrint() {
192                 $GLOBALS['request_string'] = '';
193
194                 // merge _GET and _POST, but keep the results local
195                 // this handles the issues where values come in one way or the other
196                 // without affecting the main super globals
197                 $merged = array_merge($_GET, $_POST);
198                 foreach ($merged as $key => $val)
199                 {
200                    if(is_array($val))
201                    {
202                        foreach ($val as $k => $v)
203                        {
204                            //If an array, then skip the urlencoding. This should be handled with stringify instead.
205                            if(is_array($v))
206                                 continue;
207
208                            $GLOBALS['request_string'] .= urlencode($key).'['.$k.']='.urlencode($v).'&';
209                        }
210                    }
211                    else
212                    {
213                        $GLOBALS['request_string'] .= urlencode($key).'='.urlencode($val).'&';
214                    }
215                 }
216                 $GLOBALS['request_string'] .= 'print=true';
217         }
218
219         function preProcess(){
220             $config = new Administration;
221             $config->retrieveSettings();
222                 if(!empty($_SESSION['authenticated_user_id'])){
223                         if(isset($_SESSION['hasExpiredPassword']) && $_SESSION['hasExpiredPassword'] == '1'){
224                                 if( $this->controller->action!= 'Save' && $this->controller->action != 'Logout') {
225                         $this->controller->module = 'Users';
226                         $this->controller->action = 'ChangePassword';
227                         $record = $GLOBALS['current_user']->id;
228                      }else{
229                                         $this->handleOfflineClient();
230                                  }
231                         }else{
232                                 $ut = $GLOBALS['current_user']->getPreference('ut');
233                             if(empty($ut)
234                                     && $this->controller->action != 'AdminWizard'
235                                     && $this->controller->action != 'EmailUIAjax'
236                                     && $this->controller->action != 'Wizard'
237                                     && $this->controller->action != 'SaveAdminWizard'
238                                     && $this->controller->action != 'SaveUserWizard'
239                                     && $this->controller->action != 'SaveTimezone'
240                                     && $this->controller->action != 'Logout') {
241                                         $this->controller->module = 'Users';
242                                         $this->controller->action = 'SetTimezone';
243                                         $record = $GLOBALS['current_user']->id;
244                                 }else{
245                                         if($this->controller->action != 'AdminWizard'
246                                     && $this->controller->action != 'EmailUIAjax'
247                                     && $this->controller->action != 'Wizard'
248                                     && $this->controller->action != 'SaveAdminWizard'
249                                     && $this->controller->action != 'SaveUserWizard'){
250                                                         $this->handleOfflineClient();
251                                     }
252                                 }
253                         }
254                 }
255                 $this->handleAccessControl();
256         }
257
258         function handleOfflineClient(){
259                 if(isset($GLOBALS['sugar_config']['disc_client']) && $GLOBALS['sugar_config']['disc_client']){
260                         if(isset($_REQUEST['action']) && $_REQUEST['action'] != 'SaveTimezone'){
261                                 if (!file_exists('modules/Sync/file_config.php')){
262                                         if($_REQUEST['action'] != 'InitialSync' && $_REQUEST['action'] != 'Logout' &&
263                                            ($_REQUEST['action'] != 'Popup' && $_REQUEST['module'] != 'Sync')){
264                                                 //echo $_REQUEST['action'];
265                                                 //die();
266                                                         $this->controller->module = 'Sync';
267                                                         $this->controller->action = 'InitialSync';
268                                                 }
269                         }else{
270                                 require_once ('modules/Sync/file_config.php');
271                                 if(isset($file_sync_info['is_first_sync']) && $file_sync_info['is_first_sync']){
272                                         if($_REQUEST['action'] != 'InitialSync' && $_REQUEST['action'] != 'Logout' &&
273                                            ( $_REQUEST['action'] != 'Popup' && $_REQUEST['module'] != 'Sync')){
274                                                                 $this->controller->module = 'Sync';
275                                                                 $this->controller->action = 'InitialSync';
276                                                 }
277                                 }
278                         }
279                         }
280                         global $moduleList, $sugar_config, $sync_modules;
281                         require_once('modules/Sync/SyncController.php');
282                         $GLOBALS['current_user']->is_admin = '0'; //No admins for disc client
283                 }
284         }
285
286         /**
287          * Handles everything related to authorization.
288          */
289         function handleAccessControl(){
290                 if($GLOBALS['current_user']->isDeveloperForAnyModule())
291                         return;
292             if(!empty($_REQUEST['action']) && $_REQUEST['action']=="RetrieveEmail")
293             return;
294                 if(!is_admin($GLOBALS['current_user']) && !empty($GLOBALS['adminOnlyList'][$this->controller->module])
295                 && !empty($GLOBALS['adminOnlyList'][$this->controller->module]['all'])
296                 && (empty($GLOBALS['adminOnlyList'][$this->controller->module][$this->controller->action]) || $GLOBALS['adminOnlyList'][$this->controller->module][$this->controller->action] != 'allow')) {
297                         $this->controller->hasAccess = false;
298                         return;
299                 }
300
301                 // Bug 20916 - Special case for check ACL access rights for Subpanel QuickCreates
302                 if(isset($_POST['action']) && $_POST['action'] == 'SubpanelCreates') {
303             $actual_module = $_POST['target_module'];
304             if(!empty($GLOBALS['modListHeader']) && !in_array($actual_module,$GLOBALS['modListHeader'])) {
305                 $this->controller->hasAccess = false;
306             }
307             return;
308         }
309
310
311                 if(!empty($GLOBALS['current_user']) && empty($GLOBALS['modListHeader']))
312                         $GLOBALS['modListHeader'] = query_module_access_list($GLOBALS['current_user']);
313
314                 if(in_array($this->controller->module, $GLOBALS['modInvisList']) &&
315                         ((in_array('Activities', $GLOBALS['moduleList'])              &&
316                         in_array('Calendar',$GLOBALS['moduleList']))                 &&
317                         in_array($this->controller->module, $GLOBALS['modInvisListActivities']))
318                         ){
319                                 $this->controller->hasAccess = false;
320                                 return;
321                 }
322         }
323
324         /**
325          * Load only bare minimum of language that can be done before user init and MVC stuff
326          */
327         static function preLoadLanguages()
328         {
329                 if(!empty($_SESSION['authenticated_user_language'])) {
330                         $GLOBALS['current_language'] = $_SESSION['authenticated_user_language'];
331                 }
332                 else {
333                         $GLOBALS['current_language'] = $GLOBALS['sugar_config']['default_language'];
334                 }
335                 $GLOBALS['log']->debug('current_language is: '.$GLOBALS['current_language']);
336                 //set module and application string arrays based upon selected language
337                 $GLOBALS['app_strings'] = return_application_language($GLOBALS['current_language']);
338         }
339
340         /**
341          * Load application wide languages as well as module based languages so they are accessible
342          * from the module.
343          */
344         function loadLanguages(){
345                 if(!empty($_SESSION['authenticated_user_language'])) {
346                         $GLOBALS['current_language'] = $_SESSION['authenticated_user_language'];
347                 }
348                 else {
349                         $GLOBALS['current_language'] = $GLOBALS['sugar_config']['default_language'];
350                 }
351                 $GLOBALS['log']->debug('current_language is: '.$GLOBALS['current_language']);
352                 //set module and application string arrays based upon selected language
353                 $GLOBALS['app_strings'] = return_application_language($GLOBALS['current_language']);
354                 if(empty($GLOBALS['current_user']->id))$GLOBALS['app_strings']['NTC_WELCOME'] = '';
355                 if(!empty($GLOBALS['system_config']->settings['system_name']))$GLOBALS['app_strings']['LBL_BROWSER_TITLE'] = $GLOBALS['system_config']->settings['system_name'];
356                 $GLOBALS['app_list_strings'] = return_app_list_strings_language($GLOBALS['current_language']);
357                 $GLOBALS['mod_strings'] = return_module_language($GLOBALS['current_language'], $this->controller->module);
358         }
359         /**
360         * checkDatabaseVersion
361         * Check the db version sugar_version.php and compare to what the version is stored in the config table.
362         * Ensure that both are the same.
363         */
364         function checkDatabaseVersion($dieOnFailure = true)
365         {
366             $row_count = sugar_cache_retrieve('checkDatabaseVersion_row_count');
367             if ( empty($row_count) )
368             {
369             $version_query = "SELECT count(*) as the_count FROM config WHERE category='info' AND name='sugar_version' AND ".
370             $GLOBALS['db']->convert('value', 'text2char')." = ".$GLOBALS['db']->quoted($GLOBALS['sugar_db_version']);
371
372             $result = $GLOBALS['db']->query($version_query);
373             $row = $GLOBALS['db']->fetchByAssoc($result);
374             $row_count = $row['the_count'];
375             sugar_cache_put('checkDatabaseVersion_row_count', $row_count);
376         }
377
378                 if ($row_count == 0 && empty($GLOBALS['sugar_config']['disc_client']))
379                 {
380                         if ( $dieOnFailure )
381                         {
382                                 $replacementStrings = array(
383                                         0 => $GLOBALS['sugar_version'],
384                                         1 => $GLOBALS['sugar_db_version'],
385                                 );
386                                 sugar_die(string_format($GLOBALS['app_strings']['ERR_DB_VERSION'], $replacementStrings));
387                         }
388                         else
389                         {
390                             return false;
391                         }
392                 }
393
394                 return true;
395         }
396
397         /**
398          * Load the themes/images.
399          */
400         function loadDisplaySettings()
401     {
402         global $theme;
403
404         // load the user's default theme
405         $theme = $GLOBALS['current_user']->getPreference('user_theme');
406
407         if (is_null($theme)) {
408             $theme = $GLOBALS['sugar_config']['default_theme'];
409             if(!empty($_SESSION['authenticated_user_theme'])){
410                 $theme = $_SESSION['authenticated_user_theme'];
411             }
412             else if(!empty($_COOKIE['sugar_user_theme'])){
413                 $theme = $_COOKIE['sugar_user_theme'];
414             }
415
416                         if(isset($_SESSION['authenticated_user_theme']) && $_SESSION['authenticated_user_theme'] != '') {
417                                 $_SESSION['theme_changed'] = false;
418                         }
419                 }
420
421         if(!is_null($theme) && !headers_sent())
422         {
423             setcookie('sugar_user_theme', $theme, time() + 31536000); // expires in a year
424         }
425
426         SugarThemeRegistry::set($theme);
427         require_once('include/utils/layout_utils.php');
428         $GLOBALS['image_path'] = SugarThemeRegistry::current()->getImagePath().'/';
429         if ( defined('TEMPLATE_URL') )
430             $GLOBALS['image_path'] = TEMPLATE_URL . '/'. $GLOBALS['image_path'];
431
432         if ( isset($GLOBALS['current_user']) ) {
433             $GLOBALS['gridline'] = (int) ($GLOBALS['current_user']->getPreference('gridline') == 'on');
434             $GLOBALS['current_user']->setPreference('user_theme', $theme, 0, 'global');
435         }
436         }
437
438         function loadLicense(){
439                 loadLicense();
440                 global $user_unique_key, $server_unique_key;
441                 $user_unique_key = (isset($_SESSION['unique_key'])) ? $_SESSION['unique_key'] : '';
442                 $server_unique_key = (isset($sugar_config['unique_key'])) ? $sugar_config['unique_key'] : '';
443         }
444
445         function loadGlobals(){
446                 global $currentModule;
447                 $currentModule = $this->controller->module;
448                 if($this->controller->module == $this->default_module){
449                         $_REQUEST['module'] = $this->controller->module;
450                         if(empty($_REQUEST['action']))
451                         $_REQUEST['action'] = $this->default_action;
452                 }
453         }
454
455         /**
456          * Actions that modify data in this controller's instance and thus require referrers
457          * @var array
458          */
459         protected $modifyActions = array();
460         /**
461          * Actions that always modify data and thus require referrers
462          * save* and delete* hardcoded as modified
463          * @var array
464          */
465         private $globalModifyActions = array(
466                 'massupdate', 'configuredashlet', 'import', 'importvcardsave', 'inlinefieldsave',
467             'wlsave', 'quicksave'
468         );
469
470         /**
471          * Modules that modify data and thus require referrers for all actions
472          */
473         private $modifyModules = array(
474                 'Administration' => true,
475                 'UpgradeWizard' => true,
476                 'Configurator' => true,
477                 'Studio' => true,
478                 'ModuleBuilder' => true,
479                 'Emails' => true,
480             'DCETemplates' => true,
481                 'DCEInstances' => true,
482                 'DCEActions' => true,
483                 'Trackers' => array('trackersettings'),
484             'SugarFavorites' => array('tag'),
485             'Import' => array('last', 'undo'),
486             'Users' => array('changepassword', "generatepassword"),
487         );
488
489         protected function isModifyAction()
490         {
491             $action = strtolower($this->controller->action);
492             if(substr($action, 0, 4) == "save" || substr($action, 0, 6) == "delete") {
493                 return true;
494             }
495             if(isset($this->modifyModules[$this->controller->module])) {
496                 if($this->modifyModules[$this->controller->module] === true) {
497                     return true;
498                 }
499                 if(in_array($this->controller->action, $this->modifyModules[$this->controller->module])) {
500                     return true;
501
502                 }
503             }
504             if(in_array($this->controller->action, $this->globalModifyActions)) {
505             return true;
506         }
507             if(in_array($this->controller->action, $this->modifyActions)) {
508             return true;
509         }
510         return false;
511         }
512
513     /**
514      * The list of the actions excepted from referer checks by default
515      * @var array
516      */
517         protected $whiteListActions = array('index', 'ListView', 'DetailView', 'EditView', 'oauth', 'authorize', 'Authenticate', 'Login', 'SupportPortal');
518
519         /**
520          *
521          * Checks a request to ensure the request is coming from a valid source or it is for one of the white listed actions
522          */
523         protected function checkHTTPReferer($dieIfInvalid = true)
524         {
525                 global $sugar_config;
526                 if(!empty($sugar_config['http_referer']['actions'])) {
527                     $this->whiteListActions = array_merge($sugar_config['http_referer']['actions'], $this->whiteListActions);
528                 }
529
530                 $strong = empty($sugar_config['http_referer']['weak']);
531
532                 // Bug 39691 - Make sure localhost and 127.0.0.1 are always valid HTTP referers
533                 $whiteListReferers = array('127.0.0.1','localhost');
534                 if(!empty($_SERVER['SERVER_ADDR']))$whiteListReferers[]  = $_SERVER['SERVER_ADDR'];
535                 if ( !empty($sugar_config['http_referer']['list']) ) {
536                         $whiteListReferers = array_merge($whiteListReferers,$sugar_config['http_referer']['list']);
537                 }
538
539                 if($strong && empty($_SERVER['HTTP_REFERER']) && !in_array($this->controller->action, $this->whiteListActions ) && $this->isModifyAction()) {
540                     $http_host = explode(':', $_SERVER['HTTP_HOST']);
541             $whiteListActions = $this->whiteListActions;
542                         $whiteListActions[] = $this->controller->action;
543                         $whiteListString = "'" . implode("', '", $whiteListActions) . "'";
544             if ( $dieIfInvalid ) {
545                 header("Cache-Control: no-cache, must-revalidate");
546                 $ss = new Sugar_Smarty;
547                 $ss->assign('host', $http_host[0]);
548                 $ss->assign('action',$this->controller->action);
549                 $ss->assign('whiteListString',$whiteListString);
550                 $ss->display('include/MVC/View/tpls/xsrf.tpl');
551                 sugar_cleanup(true);
552             }
553             return false;
554                 } else
555                 if(!empty($_SERVER['HTTP_REFERER']) && !empty($_SERVER['SERVER_NAME'])){
556                         $http_ref = parse_url($_SERVER['HTTP_REFERER']);
557                         if($http_ref['host'] !== $_SERVER['SERVER_NAME']  && !in_array($this->controller->action, $this->whiteListActions) &&
558
559                                 (empty($whiteListReferers) || !in_array($http_ref['host'], $whiteListReferers))){
560                 if ( $dieIfInvalid ) {
561                     header("Cache-Control: no-cache, must-revalidate");
562                     $whiteListActions = $this->whiteListActions;
563                     $whiteListActions[] = $this->controller->action;
564                     $whiteListString = "'" . implode("', '", $whiteListActions) . "'";
565
566                     $ss = new Sugar_Smarty;
567                     $ss->assign('host',$http_ref['host']);
568                     $ss->assign('action',$this->controller->action);
569                     $ss->assign('whiteListString',$whiteListString);
570                     $ss->display('include/MVC/View/tpls/xsrf.tpl');
571                     sugar_cleanup(true);
572                 }
573                 return false;
574                         }
575                 }
576          return true;
577         }
578         function startSession()
579         {
580             $sessionIdCookie = isset($_COOKIE['PHPSESSID']) ? $_COOKIE['PHPSESSID'] : null;
581             if(isset($_REQUEST['MSID'])) {
582                         session_id($_REQUEST['MSID']);
583                         session_start();
584             if(!isset($_SESSION['user_id'])){
585                                 if(isset($_COOKIE['PHPSESSID'])){
586                                 self::setCookie('PHPSESSID', '', time()-42000, '/');
587                         }
588                         sugar_cleanup(false);
589                         session_destroy();
590                         exit('Not a valid entry method');
591                         }
592                 }else{
593                         if(can_start_session()){
594                                 session_start();
595                         }
596                 }
597
598         //set the default module to either Home or specified default
599         $default_module = !empty($GLOBALS['sugar_config']['default_module'])?  $GLOBALS['sugar_config']['default_module'] : 'Home';
600
601         //set session expired message if login module and action are set to a non login default
602         //AND session id in cookie is set but super global session array is empty
603                 if ( isset($_REQUEST['login_module']) && isset($_REQUEST['login_action'])
604                         && !($_REQUEST['login_module'] == $default_module && $_REQUEST['login_action'] == 'index') ) {
605             if ( !is_null($sessionIdCookie) && empty($_SESSION) ) {
606                 self::setCookie('loginErrorMessage', 'LBL_SESSION_EXPIRED', time()+30, '/');
607             }
608         }
609
610
611         LogicHook::initialize()->call_custom_logic('', 'after_session_start');
612         }
613
614
615
616
617         function endSession(){
618                 session_destroy();
619         }
620         /**
621          * Redirect to another URL
622          *
623          * @access      public
624          * @param       string  $url    The URL to redirect to
625          */
626         function redirect(
627             $url
628             )
629         {
630                 /*
631                  * If the headers have been sent, then we cannot send an additional location header
632                  * so we will output a javascript redirect statement.
633                  */
634                 if (!empty($_REQUEST['ajax_load']))
635         {
636             ob_get_clean();
637             $ajax_ret = array(
638                  'content' => "<script>SUGAR.ajaxUI.loadContent('$url');</script>\n",
639                  'menu' => array(
640                      'module' => $_REQUEST['module'],
641                      'label' => translate($_REQUEST['module']),
642                  ),
643             );
644             $json = getJSONobj();
645             echo $json->encode($ajax_ret);
646         } else {
647             if (headers_sent()) {
648                 echo "<script>SUGAR.ajaxUI.loadContent('$url');</script>\n";
649             } else {
650                 //@ob_end_clean(); // clear output buffer
651                 session_write_close();
652                 header( 'HTTP/1.1 301 Moved Permanently' );
653                 header( "Location: ". $url );
654             }
655         }
656                 exit();
657         }
658
659     /**
660          * Redirect to another URL
661          *
662          * @access      public
663          * @param       string  $url    The URL to redirect to
664          */
665         public static function appendErrorMessage($error_message)
666         {
667         if (empty($_SESSION['user_error_message']) || !is_array($_SESSION['user_error_message'])){
668             $_SESSION['user_error_message'] = array();
669         }
670                 $_SESSION['user_error_message'][] = $error_message;
671         }
672
673     public static function getErrorMessages()
674         {
675                 if (isset($_SESSION['user_error_message']) && is_array($_SESSION['user_error_message']) ) {
676             $msgs = $_SESSION['user_error_message'];
677             unset($_SESSION['user_error_message']);
678             return $msgs;
679         }else{
680             return array();
681         }
682         }
683
684         /**
685          * Wrapper for the PHP setcookie() function, to handle cases where headers have
686          * already been sent
687          */
688         public static function setCookie(
689             $name,
690             $value,
691             $expire = 0,
692             $path = '/',
693             $domain = null,
694             $secure = false,
695             $httponly = false
696             )
697         {
698             if ( is_null($domain) )
699                 if ( isset($_SERVER["HTTP_HOST"]) )
700                     $domain = $_SERVER["HTTP_HOST"];
701                 else
702                     $domain = 'localhost';
703
704             if (!headers_sent())
705                 setcookie($name,$value,$expire,$path,$domain,$secure,$httponly);
706
707             $_COOKIE[$name] = $value;
708         }
709
710         protected $redirectVars = array('module', 'action', 'record', 'token', 'oauth_token', 'mobile');
711
712         /**
713          * Create string to attach to login URL with vars to preserve post-login
714          * @return string URL part with login vars
715          */
716         public function createLoginVars()
717         {
718             $ret = array();
719         foreach($this->redirectVars as $var) {
720             if(!empty($this->controller->$var)) {
721                 $ret["login_".$var] = $this->controller->$var;
722                 continue;
723             }
724             if(!empty($_REQUEST[$var])) {
725                 $ret["login_".$var] = $_REQUEST[$var];
726             }
727         }
728         if(isset($_REQUEST['mobile'])) {
729             $ret['mobile'] = $_REQUEST['mobile'];
730         }
731         if(isset($_REQUEST['no_saml'])) {
732             $ret['no_saml'] = $_REQUEST['no_saml'];
733         }
734         if(empty($ret)) return '';
735         return "&".http_build_query($ret);
736         }
737
738         /**
739          * Get the list of vars passed with login form
740          * @param bool $add_empty Add empty vars to the result?
741          * @return array List of vars passed with login
742          */
743         public function getLoginVars($add_empty = true)
744         {
745             $ret = array();
746         foreach($this->redirectVars as $var) {
747             if(!empty($_REQUEST['login_'.$var]) || $add_empty) {
748                 $ret["login_".$var] = isset($_REQUEST['login_'.$var])?$_REQUEST['login_'.$var]:'';
749             }
750         }
751             return $ret;
752         }
753
754         /**
755          * Get URL to redirect after the login
756          * @return string the URL to redirect to
757          */
758         public function getLoginRedirect()
759         {
760         $vars = array();
761         foreach($this->redirectVars as $var) {
762             if(!empty($_REQUEST['login_'.$var])) $vars[$var] = $_REQUEST['login_'.$var];
763         }
764         if(isset($_REQUEST['mobile'])) {
765             $vars['mobile'] = $_REQUEST['mobile'];
766         }
767
768         if(isset($_REQUEST['mobile']))
769         {
770                       $vars['mobile'] = $_REQUEST['mobile'];
771         }
772         if(empty($vars)) {
773             return "index.php?module=Home&action=index";
774         } else {
775             return "index.php?".http_build_query($vars);
776         }
777         }
778 }