This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
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 | * SuiteCRM is an extension to SugarCRM Community Edition developed by Salesagility Ltd. |
||
7 | * Copyright (C) 2011 - 2014 Salesagility Ltd. |
||
8 | * |
||
9 | * This program is free software; you can redistribute it and/or modify it under |
||
10 | * the terms of the GNU Affero General Public License version 3 as published by the |
||
11 | * Free Software Foundation with the addition of the following permission added |
||
12 | * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK |
||
13 | * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY |
||
14 | * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. |
||
15 | * |
||
16 | * This program is distributed in the hope that it will be useful, but WITHOUT |
||
17 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
||
18 | * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more |
||
19 | * details. |
||
20 | * |
||
21 | * You should have received a copy of the GNU Affero General Public License along with |
||
22 | * this program; if not, see http://www.gnu.org/licenses or write to the Free |
||
23 | * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
||
24 | * 02110-1301 USA. |
||
25 | * |
||
26 | * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road, |
||
27 | * SW2-130, Cupertino, CA 95014, USA. or at email address [email protected]. |
||
28 | * |
||
29 | * The interactive user interfaces in modified source and object code versions |
||
30 | * of this program must display Appropriate Legal Notices, as required under |
||
31 | * Section 5 of the GNU Affero General Public License version 3. |
||
32 | * |
||
33 | * In accordance with Section 7(b) of the GNU Affero General Public License version 3, |
||
34 | * these Appropriate Legal Notices must retain the display of the "Powered by |
||
35 | * SugarCRM" logo and "Supercharged by SuiteCRM" logo. If the display of the logos is not |
||
36 | * reasonably feasible for technical reasons, the Appropriate Legal Notices must |
||
37 | * display the words "Powered by SugarCRM" and "Supercharged by SuiteCRM". |
||
38 | ********************************************************************************/ |
||
39 | |||
40 | require_once('include/MVC/View/SugarView.php'); |
||
41 | |||
42 | /** |
||
43 | * Main SugarCRM controller |
||
44 | * @api |
||
45 | */ |
||
46 | class SugarController{ |
||
47 | /** |
||
48 | * remap actions in here |
||
49 | * e.g. make all detail views go to edit views |
||
50 | * $action_remap = array('detailview'=>'editview'); |
||
51 | */ |
||
52 | protected $action_remap = array('index'=>'listview'); |
||
53 | /** |
||
54 | * The name of the current module. |
||
55 | */ |
||
56 | public $module = 'Home'; |
||
57 | /** |
||
58 | * The name of the target module. |
||
59 | */ |
||
60 | public $target_module = null; |
||
61 | /** |
||
62 | * The name of the current action. |
||
63 | */ |
||
64 | public $action = 'index'; |
||
65 | /** |
||
66 | * The id of the current record. |
||
67 | */ |
||
68 | public $record = ''; |
||
69 | /** |
||
70 | * The name of the return module. |
||
71 | */ |
||
72 | public $return_module = null; |
||
73 | /** |
||
74 | * The name of the return action. |
||
75 | */ |
||
76 | public $return_action = null; |
||
77 | /** |
||
78 | * The id of the return record. |
||
79 | */ |
||
80 | public $return_id = null; |
||
81 | /** |
||
82 | * If the action was remapped it will be set to do_action and then we will just |
||
83 | * use do_action for the actual action to perform. |
||
84 | */ |
||
85 | protected $do_action = 'index'; |
||
86 | /** |
||
87 | * If a bean is present that set it. |
||
88 | */ |
||
89 | public $bean = null; |
||
90 | /** |
||
91 | * url to redirect to |
||
92 | */ |
||
93 | public $redirect_url = ''; |
||
94 | /** |
||
95 | * any subcontroller can modify this to change the view |
||
96 | */ |
||
97 | public $view = 'classic'; |
||
98 | /** |
||
99 | * this array will hold the mappings between a key and an object for use within the view. |
||
100 | */ |
||
101 | public $view_object_map = array(); |
||
102 | |||
103 | /** |
||
104 | * This array holds the methods that handleAction() will invoke, in sequence. |
||
105 | */ |
||
106 | protected $tasks = array( |
||
107 | 'pre_action', |
||
108 | 'do_action', |
||
109 | 'post_action' |
||
110 | ); |
||
111 | /** |
||
112 | * List of options to run through within the process() method. |
||
113 | * This list is meant to easily allow additions for new functionality as well as |
||
114 | * the ability to add a controller's own handling. |
||
115 | */ |
||
116 | public $process_tasks = array( |
||
117 | 'blockFileAccess', |
||
118 | 'handleEntryPoint', |
||
119 | 'callLegacyCode', |
||
120 | 'remapAction', |
||
121 | 'handle_action', |
||
122 | 'handleActionMaps', |
||
123 | ); |
||
124 | /** |
||
125 | * Whether or not the action has been handled by $process_tasks |
||
126 | * |
||
127 | * @var bool |
||
128 | */ |
||
129 | protected $_processed = false; |
||
130 | /** |
||
131 | * Map an action directly to a file |
||
132 | */ |
||
133 | /** |
||
134 | * Map an action directly to a file. This will be loaded from action_file_map.php |
||
135 | */ |
||
136 | protected $action_file_map = array(); |
||
137 | /** |
||
138 | * Map an action directly to a view |
||
139 | */ |
||
140 | /** |
||
141 | * Map an action directly to a view. This will be loaded from action_view_map.php |
||
142 | */ |
||
143 | protected $action_view_map = array(); |
||
144 | |||
145 | /** |
||
146 | * This can be set from the application to tell us whether we have authorization to |
||
147 | * process the action. If this is set we will default to the noaccess view. |
||
148 | */ |
||
149 | public $hasAccess = true; |
||
150 | |||
151 | /** |
||
152 | * Map case sensitive filenames to action. This is used for linux/unix systems |
||
153 | * where filenames are case sensitive |
||
154 | */ |
||
155 | public static $action_case_file = array( |
||
156 | 'editview'=>'EditView', |
||
157 | 'detailview'=>'DetailView', |
||
158 | 'listview'=>'ListView' |
||
159 | ); |
||
160 | |||
161 | /** |
||
162 | * Constructor. This ie meant tot load up the module, action, record as well |
||
163 | * as the mapping arrays. |
||
164 | */ |
||
165 | 16 | public function __construct(){ |
|
166 | 16 | } |
|
167 | |||
168 | /** |
||
169 | * @deprecated deprecated since version 7.6, PHP4 Style Constructors are deprecated and will be remove in 7.8, please update your code, use __construct instead |
||
170 | */ |
||
171 | public function SugarController(){ |
||
172 | $deprecatedMessage = 'PHP4 Style Constructors are deprecated and will be remove in 7.8, please update your code'; |
||
173 | if(isset($GLOBALS['log'])) { |
||
174 | $GLOBALS['log']->deprecated($deprecatedMessage); |
||
175 | } |
||
176 | else { |
||
177 | trigger_error($deprecatedMessage, E_USER_DEPRECATED); |
||
178 | } |
||
179 | self::__construct(); |
||
180 | } |
||
181 | |||
182 | |||
183 | /** |
||
184 | * Called from SugarApplication and is meant to perform the setup operations |
||
185 | * on the controller. |
||
186 | * |
||
187 | */ |
||
188 | 2 | public function setup($module = ''){ |
|
189 | 2 | if(empty($module) && !empty($_REQUEST['module'])) |
|
190 | $module = $_REQUEST['module']; |
||
191 | //set the module |
||
192 | 2 | if(!empty($module)) |
|
193 | 2 | $this->setModule($module); |
|
194 | |||
195 | 2 | if(!empty($_REQUEST['target_module']) && $_REQUEST['target_module'] != 'undefined') { |
|
196 | $this->target_module = $_REQUEST['target_module']; |
||
197 | } |
||
198 | //set properties on the controller from the $_REQUEST |
||
199 | 2 | $this->loadPropertiesFromRequest(); |
|
200 | //load the mapping files |
||
201 | 2 | $this->loadMappings(); |
|
202 | 2 | } |
|
203 | /** |
||
204 | * Set the module on the Controller |
||
205 | * |
||
206 | * @param object $module |
||
207 | */ |
||
208 | 6 | public function setModule($module){ |
|
209 | 6 | $this->module = $module; |
|
210 | 6 | } |
|
211 | |||
212 | /** |
||
213 | * Set properties on the Controller from the $_REQUEST |
||
214 | * |
||
215 | */ |
||
216 | 2 | private function loadPropertiesFromRequest(){ |
|
217 | 2 | if(!empty($_REQUEST['action'])) |
|
218 | $this->action = $_REQUEST['action']; |
||
219 | 2 | if(!empty($_REQUEST['record'])) |
|
220 | $this->record = $_REQUEST['record']; |
||
221 | 2 | if(!empty($_REQUEST['view'])) |
|
222 | $this->view = $_REQUEST['view']; |
||
223 | 2 | if(!empty($_REQUEST['return_module'])) |
|
224 | $this->return_module = $_REQUEST['return_module']; |
||
225 | 2 | if(!empty($_REQUEST['return_action'])) |
|
226 | $this->return_action = $_REQUEST['return_action']; |
||
227 | 2 | if(!empty($_REQUEST['return_id'])) |
|
228 | $this->return_id = $_REQUEST['return_id']; |
||
229 | 2 | } |
|
230 | |||
231 | /** |
||
232 | * Load map files for use within the Controller |
||
233 | * |
||
234 | */ |
||
235 | 2 | private function loadMappings(){ |
|
236 | 2 | $this->loadMapping('action_view_map'); |
|
237 | 2 | $this->loadMapping('action_file_map'); |
|
238 | 2 | $this->loadMapping('action_remap', true); |
|
239 | 2 | } |
|
240 | |||
241 | /** |
||
242 | * Given a record id load the bean. This bean is accessible from any sub controllers. |
||
243 | */ |
||
244 | 5 | public function loadBean() |
|
245 | { |
||
246 | 5 | if(!empty($GLOBALS['beanList'][$this->module])){ |
|
247 | 3 | $class = $GLOBALS['beanList'][$this->module]; |
|
248 | 3 | if(!empty($GLOBALS['beanFiles'][$class])){ |
|
249 | 3 | require_once($GLOBALS['beanFiles'][$class]); |
|
250 | 3 | $this->bean = new $class(); |
|
251 | 3 | if(!empty($this->record)){ |
|
252 | $this->bean->retrieve($this->record); |
||
253 | if($this->bean) |
||
254 | $GLOBALS['FOCUS'] = $this->bean; |
||
255 | } |
||
256 | } |
||
257 | } |
||
258 | 5 | } |
|
259 | |||
260 | /** |
||
261 | * Generic load method to load mapping arrays. |
||
262 | */ |
||
263 | 3 | private function loadMapping($var, $merge = false){ |
|
264 | 3 | $$var = sugar_cache_retrieve("CONTROLLER_". $var . "_".$this->module); |
|
265 | 3 | if(!$$var){ |
|
266 | 2 | if($merge && !empty($this->$var)){ |
|
267 | 1 | $$var = $this->$var; |
|
268 | }else{ |
||
269 | 2 | $$var = array(); |
|
270 | } |
||
271 | 2 | if(file_exists('include/MVC/Controller/'. $var . '.php')){ |
|
272 | 2 | require('include/MVC/Controller/'. $var . '.php'); |
|
273 | } |
||
274 | 2 | if(file_exists('modules/'.$this->module.'/'. $var . '.php')){ |
|
275 | 1 | require('modules/'.$this->module.'/'. $var . '.php'); |
|
276 | } |
||
277 | 2 | if(file_exists('custom/modules/'.$this->module.'/'. $var . '.php')){ |
|
278 | require('custom/modules/'.$this->module.'/'. $var . '.php'); |
||
279 | } |
||
280 | 2 | if(file_exists('custom/include/MVC/Controller/'. $var . '.php')){ |
|
281 | require('custom/include/MVC/Controller/'. $var . '.php'); |
||
282 | } |
||
283 | |||
284 | // entry_point_registry -> EntryPointRegistry |
||
285 | |||
286 | 2 | $varname = str_replace(" ","",ucwords(str_replace("_"," ", $var))); |
|
287 | 2 | if(file_exists("custom/application/Ext/$varname/$var.ext.php")){ |
|
288 | require("custom/application/Ext/$varname/$var.ext.php"); |
||
289 | } |
||
290 | 2 | if(file_exists("custom/modules/{$this->module}/Ext/$varname/$var.ext.php")){ |
|
291 | require("custom/modules/{$this->module}/Ext/$varname/$var.ext.php"); |
||
292 | } |
||
293 | |||
294 | 2 | sugar_cache_put("CONTROLLER_". $var . "_".$this->module, $$var); |
|
295 | } |
||
296 | 3 | $this->$var = $$var; |
|
297 | 3 | } |
|
298 | |||
299 | /** |
||
300 | * This method is called from SugarApplication->execute and it will bootstrap the entire controller process |
||
301 | */ |
||
302 | 1 | final public function execute() |
|
303 | { |
||
304 | |||
305 | try |
||
306 | { |
||
307 | 1 | $this->process(); |
|
308 | 1 | if(!empty($this->view)) |
|
309 | { |
||
310 | 1 | $this->processView(); |
|
311 | } |
||
312 | elseif(!empty($this->redirect_url)) |
||
313 | { |
||
314 | $this->redirect(); |
||
315 | } |
||
316 | } |
||
317 | 1 | catch (Exception $e) |
|
318 | { |
||
319 | 1 | $this->handleException($e); |
|
320 | } |
||
321 | |||
322 | |||
323 | |||
324 | 1 | } |
|
325 | |||
326 | /** |
||
327 | * Handle exception |
||
328 | * @param Exception $e |
||
329 | */ |
||
330 | 1 | protected function handleException(Exception $e) |
|
331 | { |
||
332 | 1 | $GLOBALS['log']->fatal('Exception in Controller: ' . $e->getMessage()); |
|
333 | 1 | $logicHook = new LogicHook(); |
|
334 | |||
335 | 1 | if (isset($this->bean)) |
|
336 | { |
||
337 | $logicHook->setBean($this->bean); |
||
338 | $logicHook->call_custom_logic($this->bean->module_dir, "handle_exception", $e); |
||
339 | } |
||
340 | else |
||
341 | { |
||
342 | 1 | $logicHook->call_custom_logic('', "handle_exception", $e); |
|
343 | } |
||
344 | 1 | } |
|
345 | |||
346 | /** |
||
347 | * Display the appropriate view. |
||
348 | */ |
||
349 | 1 | private function processView(){ |
|
350 | 1 | if(!isset($this->view_object_map['remap_action']) && isset($this->action_view_map[strtolower($this->action)])) |
|
351 | { |
||
352 | $this->view_object_map['remap_action'] = $this->action_view_map[strtolower($this->action)]; |
||
353 | } |
||
354 | 1 | $view = ViewFactory::loadView($this->view, $this->module, $this->bean, $this->view_object_map, $this->target_module); |
|
355 | $GLOBALS['current_view'] = $view; |
||
356 | if(!empty($this->bean) && !$this->bean->ACLAccess($view->type) && $view->type != 'list'){ |
||
357 | ACLController::displayNoAccess(true); |
||
358 | sugar_cleanup(true); |
||
359 | } |
||
360 | if(isset($this->errors)){ |
||
361 | $view->errors = $this->errors; |
||
362 | } |
||
363 | $view->process(); |
||
364 | } |
||
365 | |||
366 | /** |
||
367 | * Meant to be overridden by a subclass and allows for specific functionality to be |
||
368 | * injected prior to the process() method being called. |
||
369 | */ |
||
370 | public function preProcess() |
||
371 | {} |
||
372 | |||
373 | /** |
||
374 | * if we have a function to support the action use it otherwise use the default action |
||
375 | * |
||
376 | * 1) check for file |
||
377 | * 2) check for action |
||
378 | */ |
||
379 | 2 | public function process(){ |
|
380 | 2 | $GLOBALS['action'] = $this->action; |
|
381 | 2 | $GLOBALS['module'] = $this->module; |
|
382 | |||
383 | //check to ensure we have access to the module. |
||
384 | 2 | if($this->hasAccess){ |
|
385 | 2 | $this->do_action = $this->action; |
|
386 | |||
387 | 2 | $file = self::getActionFilename($this->do_action); |
|
388 | |||
389 | 2 | $this->loadBean(); |
|
390 | |||
391 | 2 | $processed = false; |
|
392 | 2 | if (!$this->_processed) { |
|
393 | 2 | foreach ($this->process_tasks as $process) { |
|
394 | 2 | $this->$process(); |
|
395 | 2 | if ($this->_processed) { |
|
396 | 2 | break; |
|
397 | } |
||
398 | } |
||
399 | } |
||
400 | |||
401 | 2 | $this->redirect(); |
|
402 | }else{ |
||
403 | $this->no_access(); |
||
404 | } |
||
405 | 2 | } |
|
406 | |||
407 | /** |
||
408 | * This method is called from the process method. I could also be called within an action_* method. |
||
409 | * It allows a developer to override any one of these methods contained within, |
||
410 | * or if the developer so chooses they can override the entire action_* method. |
||
411 | * |
||
412 | * @return true if any one of the pre_, do_, or post_ methods have been defined, |
||
413 | * false otherwise. This is important b/c if none of these methods exists, then we will run the |
||
414 | * action_default() method. |
||
415 | */ |
||
416 | 2 | protected function handle_action(){ |
|
417 | 2 | $processed = false; |
|
418 | 2 | foreach($this->tasks as $task){ |
|
419 | 2 | $processed = ($this->$task() || $processed); |
|
420 | } |
||
421 | 2 | $this->_processed = $processed; |
|
422 | 2 | } |
|
423 | |||
424 | /** |
||
425 | * Perform an action prior to the specified action. |
||
426 | * This can be overridde in a sub-class |
||
427 | */ |
||
428 | 2 | private function pre_action(){ |
|
429 | 2 | $function = 'pre_' . $this->action; |
|
430 | 2 | if($this->hasFunction($function)){ |
|
431 | $GLOBALS['log']->debug('Performing pre_action'); |
||
432 | $this->$function(); |
||
433 | return true; |
||
434 | } |
||
435 | 2 | return false; |
|
436 | } |
||
437 | |||
438 | /** |
||
439 | * Perform the specified action. |
||
440 | * This can be overridde in a sub-class |
||
441 | */ |
||
442 | 2 | private function do_action(){ |
|
443 | 2 | $function = 'action_'. strtolower($this->do_action); |
|
444 | 2 | if($this->hasFunction($function)){ |
|
445 | 2 | $GLOBALS['log']->debug('Performing action: '.$function.' MODULE: '.$this->module); |
|
446 | 2 | $this->$function(); |
|
447 | 2 | return true; |
|
448 | } |
||
449 | return false; |
||
450 | } |
||
451 | |||
452 | /** |
||
453 | * Perform an action after to the specified action has occurred. |
||
454 | * This can be overridde in a sub-class |
||
455 | */ |
||
456 | 2 | private function post_action(){ |
|
457 | 2 | $function = 'post_' . $this->action; |
|
458 | 2 | if($this->hasFunction($function)){ |
|
459 | $GLOBALS['log']->debug('Performing post_action'); |
||
460 | $this->$function(); |
||
461 | return true; |
||
462 | } |
||
463 | 2 | return false; |
|
464 | } |
||
465 | |||
466 | /** |
||
467 | * If there is no action found then display an error to the user. |
||
468 | */ |
||
469 | protected function no_action(){ |
||
470 | sugar_die($GLOBALS['app_strings']['LBL_NO_ACTION']); |
||
471 | } |
||
472 | |||
473 | /** |
||
474 | * The default action handler for instances where we do not have access to process. |
||
475 | */ |
||
476 | protected function no_access(){ |
||
477 | $this->view = 'noaccess'; |
||
478 | } |
||
479 | |||
480 | /////////////////////////////////////////////// |
||
481 | /////// HELPER FUNCTIONS |
||
482 | /////////////////////////////////////////////// |
||
483 | |||
484 | /** |
||
485 | * Determine if a given function exists on the objects |
||
486 | * @param function - the function to check |
||
487 | * @return true if the method exists on the object, false otherwise |
||
488 | */ |
||
489 | 2 | protected function hasFunction($function){ |
|
490 | 2 | return method_exists($this, $function); |
|
491 | } |
||
492 | |||
493 | |||
494 | /** |
||
495 | * Set the url to which we will want to redirect |
||
496 | * |
||
497 | * @param string url - the url to which we will want to redirect |
||
498 | */ |
||
499 | protected function set_redirect($url){ |
||
500 | $this->redirect_url = $url; |
||
501 | } |
||
502 | |||
503 | /** |
||
504 | * Perform redirection based on the redirect_url |
||
505 | * |
||
506 | */ |
||
507 | 2 | protected function redirect(){ |
|
508 | |||
509 | 2 | if(!empty($this->redirect_url)) |
|
510 | SugarApplication::redirect($this->redirect_url); |
||
511 | 2 | } |
|
512 | |||
513 | //////////////////////////////////////////////////////// |
||
514 | ////// DEFAULT ACTIONS |
||
515 | /////////////////////////////////////////////////////// |
||
516 | |||
517 | /* |
||
518 | * Save a bean |
||
519 | */ |
||
520 | |||
521 | /** |
||
522 | * Do some processing before saving the bean to the database. |
||
523 | */ |
||
524 | 1 | public function pre_save(){ |
|
525 | 1 | if(!empty($_POST['assigned_user_id']) && $_POST['assigned_user_id'] != $this->bean->assigned_user_id && $_POST['assigned_user_id'] != $GLOBALS['current_user']->id && empty($GLOBALS['sugar_config']['exclude_notifications'][$this->bean->module_dir])){ |
|
526 | $this->bean->notify_on_save = true; |
||
527 | } |
||
528 | 1 | $GLOBALS['log']->debug("SugarController:: performing pre_save."); |
|
529 | 1 | require_once('include/SugarFields/SugarFieldHandler.php'); |
|
530 | 1 | $sfh = new SugarFieldHandler(); |
|
531 | 1 | foreach($this->bean->field_defs as $field => $properties) { |
|
532 | 1 | $type = !empty($properties['custom_type']) ? $properties['custom_type'] : $properties['type']; |
|
533 | 1 | $sf = $sfh->getSugarField(ucfirst($type), true); |
|
534 | 1 | if(isset($_POST[$field])) { |
|
535 | if(is_array($_POST[$field]) && !empty($properties['isMultiSelect'])) { |
||
536 | if(empty($_POST[$field][0])) { |
||
537 | unset($_POST[$field][0]); |
||
538 | } |
||
539 | $_POST[$field] = encodeMultienumValue($_POST[$field]); |
||
540 | } |
||
541 | $this->bean->$field = $_POST[$field]; |
||
542 | 1 | } else if(!empty($properties['isMultiSelect']) && !isset($_POST[$field]) && isset($_POST[$field . '_multiselect'])) { |
|
543 | $this->bean->$field = ''; |
||
544 | } |
||
545 | 1 | if($sf != null){ |
|
546 | 1 | $sf->save($this->bean, $_POST, $field, $properties); |
|
547 | } |
||
548 | } |
||
549 | |||
550 | 1 | foreach($this->bean->relationship_fields as $field=>$link){ |
|
551 | if(!empty($_POST[$field])){ |
||
552 | $this->bean->$field = $_POST[$field]; |
||
553 | } |
||
554 | } |
||
555 | 1 | if(!$this->bean->ACLAccess('save')){ |
|
556 | ACLController::displayNoAccess(true); |
||
557 | sugar_cleanup(true); |
||
558 | } |
||
559 | 1 | } |
|
560 | |||
561 | /** |
||
562 | * Perform the actual save |
||
563 | */ |
||
564 | 1 | public function action_save(){ |
|
565 | 1 | $this->bean->save(!empty($this->bean->notify_on_save)); |
|
566 | 1 | } |
|
567 | |||
568 | |||
569 | 1 | public function action_spot() |
|
570 | { |
||
571 | 1 | $this->view = 'spot'; |
|
572 | 1 | } |
|
573 | |||
574 | |||
575 | /** |
||
576 | * Specify what happens after the save has occurred. |
||
577 | */ |
||
578 | protected function post_save(){ |
||
579 | $module = (!empty($this->return_module) ? $this->return_module : $this->module); |
||
580 | $action = (!empty($this->return_action) ? $this->return_action : 'DetailView'); |
||
581 | $id = (!empty($this->return_id) ? $this->return_id : $this->bean->id); |
||
582 | |||
583 | $url = "index.php?module=".$module."&action=".$action."&record=".$id; |
||
584 | $this->set_redirect($url); |
||
585 | } |
||
586 | |||
587 | /* |
||
588 | * Delete a bean |
||
589 | */ |
||
590 | |||
591 | /** |
||
592 | * Perform the actual deletion. |
||
593 | */ |
||
594 | protected function action_delete(){ |
||
595 | //do any pre delete processing |
||
596 | //if there is some custom logic for deletion. |
||
597 | if(!empty($_REQUEST['record'])){ |
||
598 | if(!$this->bean->ACLAccess('Delete')){ |
||
599 | ACLController::displayNoAccess(true); |
||
600 | sugar_cleanup(true); |
||
601 | } |
||
602 | $this->bean->mark_deleted($_REQUEST['record']); |
||
603 | }else{ |
||
604 | sugar_die("A record number must be specified to delete"); |
||
605 | } |
||
606 | } |
||
607 | |||
608 | /** |
||
609 | * Specify what happens after the deletion has occurred. |
||
610 | */ |
||
611 | protected function post_delete(){ |
||
612 | if (empty($_REQUEST['return_url'])) { |
||
613 | $return_module = isset($_REQUEST['return_module']) ? |
||
614 | $_REQUEST['return_module'] : |
||
615 | $GLOBALS['sugar_config']['default_module']; |
||
616 | $return_action = isset($_REQUEST['return_action']) ? |
||
617 | $_REQUEST['return_action'] : |
||
618 | $GLOBALS['sugar_config']['default_action']; |
||
619 | $return_id = isset($_REQUEST['return_id']) ? |
||
620 | $_REQUEST['return_id'] : |
||
621 | ''; |
||
622 | $url = "index.php?module=".$return_module."&action=".$return_action."&record=".$return_id; |
||
623 | } else { |
||
624 | $url = $_REQUEST['return_url']; |
||
625 | } |
||
626 | |||
627 | //eggsurplus Bug 23816: maintain VCR after an edit/save. If it is a duplicate then don't worry about it. The offset is now worthless. |
||
628 | if(isset($_REQUEST['offset']) && empty($_REQUEST['duplicateSave'])) { |
||
629 | $url .= "&offset=".$_REQUEST['offset']; |
||
630 | } |
||
631 | |||
632 | $this->set_redirect($url); |
||
633 | } |
||
634 | /** |
||
635 | * Perform the actual massupdate. |
||
636 | */ |
||
637 | protected function action_massupdate(){ |
||
638 | if(!empty($_REQUEST['massupdate']) && $_REQUEST['massupdate'] == 'true' && (!empty($_REQUEST['uid']) || !empty($_REQUEST['entire']))){ |
||
639 | if(!empty($_REQUEST['Delete']) && $_REQUEST['Delete']=='true' && !$this->bean->ACLAccess('delete') |
||
640 | || (empty($_REQUEST['Delete']) || $_REQUEST['Delete']!='true') && !$this->bean->ACLAccess('save')){ |
||
641 | ACLController::displayNoAccess(true); |
||
642 | sugar_cleanup(true); |
||
643 | } |
||
644 | |||
645 | set_time_limit(0);//I'm wondering if we will set it never goes timeout here. |
||
646 | // until we have more efficient way of handling MU, we have to disable the limit |
||
647 | $GLOBALS['db']->setQueryLimit(0); |
||
648 | require_once("include/MassUpdate.php"); |
||
649 | require_once('modules/MySettings/StoreQuery.php'); |
||
650 | $seed = loadBean($_REQUEST['module']); |
||
0 ignored issues
–
show
|
|||
651 | $mass = new MassUpdate(); |
||
652 | $mass->setSugarBean($seed); |
||
653 | if(isset($_REQUEST['entire']) && empty($_POST['mass'])) { |
||
654 | $mass->generateSearchWhere($_REQUEST['module'], $_REQUEST['current_query_by_page']); |
||
655 | } |
||
656 | $mass->handleMassUpdate(); |
||
657 | $storeQuery = new StoreQuery();//restore the current search. to solve bug 24722 for multi tabs massupdate. |
||
658 | $temp_req = array('current_query_by_page' => $_REQUEST['current_query_by_page'], 'return_module' => $_REQUEST['return_module'], 'return_action' => $_REQUEST['return_action']); |
||
659 | if($_REQUEST['return_module'] == 'Emails') { |
||
660 | if(!empty($_REQUEST['type']) && !empty($_REQUEST['ie_assigned_user_id'])) { |
||
661 | $this->req_for_email = array('type' => $_REQUEST['type'], 'ie_assigned_user_id' => $_REQUEST['ie_assigned_user_id']); // Specifically for My Achieves |
||
662 | } |
||
663 | } |
||
664 | $_REQUEST = array(); |
||
665 | $_REQUEST = sugar_unserialize(base64_decode($temp_req['current_query_by_page'])); |
||
666 | unset($_REQUEST[$seed->module_dir.'2_'.strtoupper($seed->object_name).'_offset']);//after massupdate, the page should redirect to no offset page |
||
667 | $storeQuery->saveFromRequest($_REQUEST['module']); |
||
668 | $_REQUEST = array('return_module' => $temp_req['return_module'], 'return_action' => $temp_req['return_action']);//for post_massupdate, to go back to original page. |
||
669 | }else{ |
||
670 | sugar_die("You must massupdate at least one record"); |
||
671 | } |
||
672 | } |
||
673 | /** |
||
674 | * Specify what happens after the massupdate has occurred. |
||
675 | */ |
||
676 | protected function post_massupdate(){ |
||
677 | $return_module = isset($_REQUEST['return_module']) ? |
||
678 | $_REQUEST['return_module'] : |
||
679 | $GLOBALS['sugar_config']['default_module']; |
||
680 | $return_action = isset($_REQUEST['return_action']) ? |
||
681 | $_REQUEST['return_action'] : |
||
682 | $GLOBALS['sugar_config']['default_action']; |
||
683 | $url = "index.php?module=".$return_module."&action=".$return_action; |
||
684 | if($return_module == 'Emails'){//specificly for My Achieves |
||
685 | if(!empty($this->req_for_email['type']) && !empty($this->req_for_email['ie_assigned_user_id'])) { |
||
686 | $url = $url . "&type=".$this->req_for_email['type']."&assigned_user_id=".$this->req_for_email['ie_assigned_user_id']; |
||
687 | } |
||
688 | } |
||
689 | $this->set_redirect($url); |
||
690 | } |
||
691 | /** |
||
692 | * Perform the listview action |
||
693 | */ |
||
694 | 2 | protected function action_listview(){ |
|
695 | 2 | $this->view_object_map['bean'] = $this->bean; |
|
696 | 2 | $this->view = 'list'; |
|
697 | 2 | } |
|
698 | |||
699 | /* |
||
700 | |||
701 | //THIS IS HANDLED IN ACTION_REMAP WHERE INDEX IS SET TO LISTVIEW |
||
702 | function action_index(){ |
||
703 | } |
||
704 | */ |
||
705 | |||
706 | /** |
||
707 | * Action to handle when using a file as was done in previous versions of Sugar. |
||
708 | */ |
||
709 | protected function action_default(){ |
||
710 | $this->view = 'classic'; |
||
711 | } |
||
712 | |||
713 | /** |
||
714 | * this method id used within a Dashlet when performing an ajax call |
||
715 | */ |
||
716 | protected function action_callmethoddashlet(){ |
||
717 | if(!empty($_REQUEST['id'])) { |
||
718 | $id = $_REQUEST['id']; |
||
719 | $requestedMethod = $_REQUEST['method']; |
||
720 | $dashletDefs = $GLOBALS['current_user']->getPreference('dashlets', 'Home'); // load user's dashlets config |
||
721 | if(!empty($dashletDefs[$id])) { |
||
722 | require_once($dashletDefs[$id]['fileLocation']); |
||
723 | |||
724 | $dashlet = new $dashletDefs[$id]['className']($id, (isset($dashletDefs[$id]['options']) ? $dashletDefs[$id]['options'] : array())); |
||
725 | |||
726 | if(method_exists($dashlet, $requestedMethod) || method_exists($dashlet, '__call')) { |
||
727 | echo $dashlet->$requestedMethod(); |
||
728 | } |
||
729 | else { |
||
730 | echo 'no method'; |
||
731 | } |
||
732 | } |
||
733 | } |
||
734 | } |
||
735 | |||
736 | /** |
||
737 | * this method is used within a Dashlet when the options configuration is posted |
||
738 | */ |
||
739 | protected function action_configuredashlet(){ |
||
740 | global $current_user, $mod_strings; |
||
741 | |||
742 | if(!empty($_REQUEST['id'])) { |
||
743 | $id = $_REQUEST['id']; |
||
744 | $dashletDefs = $current_user->getPreference('dashlets', $_REQUEST['module']); // load user's dashlets config |
||
745 | require_once($dashletDefs[$id]['fileLocation']); |
||
746 | |||
747 | $dashlet = new $dashletDefs[$id]['className']($id, (isset($dashletDefs[$id]['options']) ? $dashletDefs[$id]['options'] : array())); |
||
748 | if(!empty($_REQUEST['configure']) && $_REQUEST['configure']) { // save settings |
||
749 | $dashletDefs[$id]['options'] = $dashlet->saveOptions($_REQUEST); |
||
750 | $current_user->setPreference('dashlets', $dashletDefs, 0, $_REQUEST['module']); |
||
751 | } |
||
752 | else { // display options |
||
753 | $json = getJSONobj(); |
||
754 | return 'result = ' . $json->encode((array('header' => $dashlet->title . ' : ' . $mod_strings['LBL_OPTIONS'], |
||
755 | 'body' => $dashlet->displayOptions()))); |
||
756 | |||
757 | } |
||
758 | } |
||
759 | else { |
||
760 | return '0'; |
||
761 | } |
||
762 | } |
||
763 | |||
764 | /** |
||
765 | * Global method to delete an attachment |
||
766 | * |
||
767 | * If the bean does not have a deleteAttachment method it will return 'false' as a string |
||
768 | * |
||
769 | * @return void |
||
770 | */ |
||
771 | protected function action_deleteattachment() |
||
772 | { |
||
773 | $this->view = 'edit'; |
||
774 | $GLOBALS['view'] = $this->view; |
||
775 | ob_clean(); |
||
776 | $retval = false; |
||
777 | |||
778 | if(method_exists($this->bean, 'deleteAttachment')) { |
||
779 | $duplicate = "false"; |
||
780 | if (isset($_REQUEST['isDuplicate']) && $_REQUEST['isDuplicate'] == "true") { |
||
781 | $duplicate = "true"; |
||
782 | } |
||
783 | if (isset($_REQUEST['duplicateSave']) && $_REQUEST['duplicateSave'] == "true") { |
||
784 | $duplicate = "true"; |
||
785 | } |
||
786 | $retval = $this->bean->deleteAttachment($duplicate); |
||
787 | } |
||
788 | echo json_encode($retval); |
||
789 | sugar_cleanup(true); |
||
790 | } |
||
791 | |||
792 | /** |
||
793 | * getActionFilename |
||
794 | */ |
||
795 | 4 | public static function getActionFilename($action) { |
|
796 | 4 | if(isset(self::$action_case_file[$action])) { |
|
797 | 1 | return self::$action_case_file[$action]; |
|
798 | } |
||
799 | 4 | return $action; |
|
800 | } |
||
801 | |||
802 | /********************************************************************/ |
||
803 | // PROCESS TASKS |
||
804 | /********************************************************************/ |
||
805 | |||
806 | /** |
||
807 | * Given the module and action, determine whether the super/admin has prevented access |
||
808 | * to this url. In addition if any links specified for this module, load the links into |
||
809 | * GLOBALS |
||
810 | * |
||
811 | * @return true if we want to stop processing, false if processing should continue |
||
812 | */ |
||
813 | 2 | private function blockFileAccess(){ |
|
814 | //check if the we have enabled file_access_control and if so then check the mappings on the request; |
||
815 | 2 | if(!empty($GLOBALS['sugar_config']['admin_access_control']) && $GLOBALS['sugar_config']['admin_access_control']){ |
|
816 | $this->loadMapping('file_access_control_map'); |
||
817 | //since we have this turned on, check the mapping file |
||
818 | $module = strtolower($this->module); |
||
819 | $action = strtolower($this->do_action); |
||
820 | if(!empty($this->file_access_control_map['modules'][$module]['links'])){ |
||
821 | $GLOBALS['admin_access_control_links'] = $this->file_access_control_map['modules'][$module]['links']; |
||
822 | } |
||
823 | |||
824 | if(!empty($this->file_access_control_map['modules'][$module]['actions']) && (in_array($action, $this->file_access_control_map['modules'][$module]['actions']) || !empty($this->file_access_control_map['modules'][$module]['actions'][$action]))){ |
||
825 | //check params |
||
826 | if(!empty($this->file_access_control_map['modules'][$module]['actions'][$action]['params'])){ |
||
827 | $block = true; |
||
828 | $params = $this->file_access_control_map['modules'][$module]['actions'][$action]['params']; |
||
829 | foreach($params as $param => $paramVals){ |
||
830 | if(!empty($_REQUEST[$param])){ |
||
831 | if(!in_array($_REQUEST[$param], $paramVals)){ |
||
832 | $block = false; |
||
833 | break; |
||
834 | } |
||
835 | } |
||
836 | } |
||
837 | if($block){ |
||
838 | $this->_processed = true; |
||
839 | $this->no_access(); |
||
840 | } |
||
841 | }else{ |
||
842 | $this->_processed = true; |
||
843 | $this->no_access(); |
||
844 | } |
||
845 | } |
||
846 | }else |
||
847 | 2 | $this->_processed = false; |
|
848 | 2 | } |
|
849 | |||
850 | /** |
||
851 | * This code is part of the entry points reworking. We have consolidated all |
||
852 | * entry points to go through index.php. Now in order to bring up an entry point |
||
853 | * it will follow the format: |
||
854 | * 'index.php?entryPoint=download' |
||
855 | * the download entry point is mapped in the following file: entry_point_registry.php |
||
856 | * |
||
857 | */ |
||
858 | 2 | private function handleEntryPoint(){ |
|
859 | 2 | if(!empty($_REQUEST['entryPoint'])){ |
|
860 | $this->loadMapping('entry_point_registry'); |
||
861 | $entryPoint = $_REQUEST['entryPoint']; |
||
862 | |||
863 | if(!empty($this->entry_point_registry[$entryPoint])){ |
||
864 | require_once($this->entry_point_registry[$entryPoint]['file']); |
||
865 | $this->_processed = true; |
||
866 | $this->view = ''; |
||
867 | } |
||
868 | } |
||
869 | 2 | } |
|
870 | |||
871 | /** |
||
872 | * Checks to see if the requested entry point requires auth |
||
873 | * |
||
874 | * @param $entrypoint string name of the entrypoint |
||
875 | * @return bool true if auth is required, false if not |
||
876 | */ |
||
877 | 1 | public function checkEntryPointRequiresAuth($entryPoint) |
|
878 | { |
||
879 | 1 | $this->loadMapping('entry_point_registry'); |
|
880 | |||
881 | 1 | if ( isset($this->entry_point_registry[$entryPoint]['auth']) |
|
882 | 1 | && !$this->entry_point_registry[$entryPoint]['auth'] ) |
|
883 | 1 | return false; |
|
884 | 1 | return true; |
|
885 | } |
||
886 | |||
887 | /** |
||
888 | * Meant to handle old views e.g. DetailView.php. |
||
889 | * |
||
890 | */ |
||
891 | 2 | protected function callLegacyCode() |
|
892 | { |
||
893 | 2 | $file = self::getActionFilename($this->do_action); |
|
894 | 2 | if ( isset($this->action_view_map[strtolower($this->do_action)]) ) { |
|
895 | $action = $this->action_view_map[strtolower($this->do_action)]; |
||
896 | } |
||
897 | else { |
||
898 | 2 | $action = $this->do_action; |
|
899 | } |
||
900 | // index actions actually maps to the view.list.php view |
||
901 | 2 | if ( $action == 'index' ) { |
|
902 | 2 | $action = 'list'; |
|
903 | } |
||
904 | |||
905 | 2 | if ((file_exists('modules/' . $this->module . '/'. $file . '.php') |
|
906 | 2 | && !file_exists('modules/' . $this->module . '/views/view.'. $action . '.php')) |
|
907 | 2 | || (file_exists('custom/modules/' . $this->module . '/'. $file . '.php') |
|
908 | 2 | && !file_exists('custom/modules/' . $this->module . '/views/view.'. $action . '.php')) |
|
909 | ) { |
||
910 | // A 'classic' module, using the old pre-MVC display files |
||
911 | // We should now discard the bean we just obtained for tracking as the pre-MVC module will instantiate its own |
||
912 | unset($GLOBALS['FOCUS']); |
||
913 | $GLOBALS['log']->debug('Module:' . $this->module . ' using file: '. $file); |
||
914 | $this->action_default(); |
||
915 | $this->_processed = true; |
||
916 | } |
||
917 | 2 | } |
|
918 | |||
919 | /** |
||
920 | * If the action has been remapped to a different action as defined in |
||
921 | * action_file_map.php or action_view_map.php load those maps here. |
||
922 | * |
||
923 | */ |
||
924 | private function handleActionMaps(){ |
||
925 | if(!empty($this->action_file_map[strtolower($this->do_action)])){ |
||
926 | $this->view = ''; |
||
927 | $GLOBALS['log']->debug('Using Action File Map:' . $this->action_file_map[strtolower($this->do_action)]); |
||
928 | require_once($this->action_file_map[strtolower($this->do_action)]); |
||
929 | $this->_processed = true; |
||
930 | }elseif(!empty($this->action_view_map[strtolower($this->do_action)])){ |
||
931 | $GLOBALS['log']->debug('Using Action View Map:' . $this->action_view_map[strtolower($this->do_action)]); |
||
932 | $this->view = $this->action_view_map[strtolower($this->do_action)]; |
||
933 | $this->_processed = true; |
||
934 | }else |
||
935 | $this->no_action(); |
||
936 | } |
||
937 | |||
938 | /** |
||
939 | * Actually remap the action if required. |
||
940 | * |
||
941 | */ |
||
942 | 2 | protected function remapAction(){ |
|
943 | 2 | if(!empty($this->action_remap[$this->do_action])){ |
|
944 | 2 | $this->action = $this->action_remap[$this->do_action]; |
|
945 | 2 | $this->do_action = $this->action; |
|
946 | } |
||
947 | 2 | } |
|
948 | |||
949 | } |
||
950 | ?> |
||
951 |
This function has been deprecated. The supplier of the file has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.