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 - 2016 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 | |||
41 | /** |
||
42 | * Vardefs management |
||
43 | * @api |
||
44 | */ |
||
45 | class VardefManager{ |
||
46 | static $custom_disabled_modules = array(); |
||
47 | static $linkFields; |
||
48 | |||
49 | /** |
||
50 | * this method is called within a vardefs.php file which extends from a SugarObject. |
||
51 | * It is meant to load the vardefs from the SugarObject. |
||
52 | */ |
||
53 | 681 | static function createVardef($module, $object, $templates = array('default'), $object_name = false) |
|
54 | { |
||
55 | 681 | global $dictionary; |
|
56 | |||
57 | 681 | include_once('modules/TableDictionary.php'); |
|
58 | |||
59 | //reverse the sort order so priority goes highest to lowest; |
||
60 | 681 | $templates = array_reverse($templates); |
|
61 | 681 | foreach ($templates as $template) |
|
62 | { |
||
63 | 555 | VardefManager::addTemplate($module, $object, $template, $object_name); |
|
64 | } |
||
65 | 681 | LanguageManager::createLanguageFile($module, $templates); |
|
66 | |||
67 | 681 | if (isset(VardefManager::$custom_disabled_modules[$module])) |
|
68 | { |
||
69 | $vardef_paths = array( |
||
70 | 'custom/modules/' . $module . '/Ext/Vardefs/vardefs.ext.php', |
||
71 | 'custom/Extension/modules/' . $module . '/Ext/Vardefs/vardefs.php' |
||
72 | ); |
||
73 | |||
74 | //search a predefined set of locations for the vardef files |
||
75 | foreach ($vardef_paths as $path) |
||
76 | { |
||
77 | if (file_exists($path)) { |
||
78 | require($path); |
||
79 | } |
||
80 | } |
||
81 | } |
||
82 | 681 | } |
|
83 | |||
84 | /** |
||
85 | * Enables/Disables the loading of custom vardefs for a module. |
||
86 | * @param String $module Module to be enabled/disabled |
||
87 | * @param Boolean $enable true to enable, false to disable |
||
88 | * @return null |
||
89 | */ |
||
90 | public static function setCustomAllowedForModule($module, $enable) { |
||
91 | if ($enable && isset($custom_disabled_modules[$module])) { |
||
0 ignored issues
–
show
|
|||
92 | unset($custom_disabled_modules[$module]); |
||
93 | } else if (!$enable) { |
||
94 | $custom_disabled_modules[$module] = true; |
||
95 | } |
||
96 | } |
||
97 | |||
98 | 555 | static function addTemplate($module, $object, $template, $object_name=false){ |
|
99 | 555 | if($template == 'default')$template = 'basic'; |
|
100 | 555 | $templates = array(); |
|
101 | 555 | $fields = array(); |
|
102 | 555 | if(empty($object_name))$object_name = $object; |
|
103 | 555 | $_object_name = strtolower($object_name); |
|
104 | 555 | if(!empty($GLOBALS['dictionary'][$object]['table'])){ |
|
105 | 555 | $table_name = $GLOBALS['dictionary'][$object]['table']; |
|
106 | }else{ |
||
107 | $table_name = strtolower($module); |
||
108 | } |
||
109 | |||
110 | 555 | if(empty($templates[$template])){ |
|
111 | 555 | $path = 'include/SugarObjects/templates/' . $template . '/vardefs.php'; |
|
112 | 555 | if(file_exists($path)){ |
|
113 | 412 | require($path); |
|
114 | 412 | $templates[$template] = $vardefs; |
|
115 | }else{ |
||
116 | 548 | $path = 'include/SugarObjects/implements/' . $template . '/vardefs.php'; |
|
117 | 548 | if(file_exists($path)){ |
|
118 | 548 | require($path); |
|
119 | 548 | $templates[$template] = $vardefs; |
|
120 | } |
||
121 | } |
||
122 | } |
||
123 | |||
124 | 555 | if(!empty($templates[$template])){ |
|
125 | 555 | if(empty($GLOBALS['dictionary'][$object]['fields']))$GLOBALS['dictionary'][$object]['fields'] = array(); |
|
126 | 555 | if(empty($GLOBALS['dictionary'][$object]['relationships']))$GLOBALS['dictionary'][$object]['relationships'] = array(); |
|
127 | 555 | if(empty($GLOBALS['dictionary'][$object]['indices']))$GLOBALS['dictionary'][$object]['indices'] = array(); |
|
128 | 555 | $GLOBALS['dictionary'][$object]['fields'] = array_merge($templates[$template]['fields'], $GLOBALS['dictionary'][$object]['fields']); |
|
129 | 555 | if(!empty($templates[$template]['relationships']))$GLOBALS['dictionary'][$object]['relationships'] = array_merge($templates[$template]['relationships'], $GLOBALS['dictionary'][$object]['relationships']); |
|
130 | 555 | if(!empty($templates[$template]['indices']))$GLOBALS['dictionary'][$object]['indices'] = array_merge($templates[$template]['indices'], $GLOBALS['dictionary'][$object]['indices']); |
|
131 | // maintain a record of this objects inheritance from the SugarObject templates... |
||
132 | 555 | $GLOBALS['dictionary'][$object]['templates'][ $template ] = $template ; |
|
133 | } |
||
134 | 555 | } |
|
135 | |||
136 | |||
137 | /** |
||
138 | * Remove invalid field definitions |
||
139 | * @static |
||
140 | * @param array $fieldDefs |
||
141 | * @return array |
||
142 | */ |
||
143 | 868 | static function cleanVardefs($fieldDefs) |
|
144 | { |
||
145 | 868 | if(isset($fieldDefs['fields'])) { |
|
146 | 868 | foreach ($fieldDefs['fields'] as $field => $defs) { |
|
147 | 868 | if (empty($defs['name']) || empty($defs['type'])) { |
|
148 | 868 | unset($fieldDefs['fields'][$field]); |
|
149 | } |
||
150 | } |
||
151 | } |
||
152 | |||
153 | 868 | return $fieldDefs; |
|
154 | } |
||
155 | |||
156 | /** |
||
157 | * Save the dictionary object to the cache |
||
158 | * @param string $module the name of the module |
||
159 | * @param string $object the name of the object |
||
160 | */ |
||
161 | 868 | static function saveCache($module,$object, $additonal_objects= array()){ |
|
162 | |||
163 | 868 | if (empty($GLOBALS['dictionary'][$object])) |
|
164 | $object = BeanFactory::getObjectName($module); |
||
165 | |||
166 | //Sometimes bad definitions can get in from left over extensions or file system lag(caching). We need to clean those. |
||
167 | 868 | $data = self::cleanVardefs($GLOBALS['dictionary'][$object]); |
|
168 | |||
169 | 868 | $file = create_cache_directory('modules/' . $module . '/' . $object . 'vardefs.php'); |
|
170 | |||
171 | 868 | $out="<?php \n \$GLOBALS[\"dictionary\"][\"". $object . "\"]=" . var_export($data, true) .";"; |
|
172 | 868 | sugar_file_put_contents_atomic($file, $out); |
|
173 | 868 | if ( sugar_is_file($file) && is_readable($file)) { |
|
174 | 868 | include($file); |
|
175 | } |
||
176 | |||
177 | // put the item in the sugar cache. |
||
178 | 868 | $key = "VardefManager.$module.$object"; |
|
179 | 868 | sugar_cache_put($key,$data); |
|
180 | 868 | } |
|
181 | |||
182 | /** |
||
183 | * clear out the vardef cache. If we receive a module name then just clear the vardef cache for that module |
||
184 | * otherwise clear out the cache for every module |
||
185 | * @param string module_dir the module_dir to clear, if not specified then clear |
||
186 | * clear vardef cache for all modules. |
||
187 | * @param string object_name the name of the object we are clearing this is for sugar_cache |
||
188 | */ |
||
189 | static function clearVardef($module_dir = '', $object_name = ''){ |
||
190 | //if we have a module name specified then just remove that vardef file |
||
191 | //otherwise go through each module and remove the vardefs.php |
||
192 | if(!empty($module_dir) && !empty($object_name)){ |
||
193 | VardefManager::_clearCache($module_dir, $object_name); |
||
194 | }else{ |
||
195 | global $beanList; |
||
196 | foreach($beanList as $module_dir => $object_name){ |
||
197 | VardefManager::_clearCache($module_dir, $object_name); |
||
198 | } |
||
199 | } |
||
200 | } |
||
201 | |||
202 | /** |
||
203 | * PRIVATE function used within clearVardefCache so we do not repeat logic |
||
204 | * @param string module_dir the module_dir to clear |
||
205 | * @param string object_name the name of the object we are clearing this is for sugar_cache |
||
206 | */ |
||
207 | static function _clearCache($module_dir = '', $object_name = ''){ |
||
208 | if(!empty($module_dir) && !empty($object_name)){ |
||
209 | |||
210 | //Some modules like cases have a bean name that doesn't match the object name |
||
211 | if (empty($GLOBALS['dictionary'][$object_name])) { |
||
212 | $newName = BeanFactory::getObjectName($module_dir); |
||
213 | $object_name = $newName != false ? $newName : $object_name; |
||
0 ignored issues
–
show
|
|||
214 | } |
||
215 | |||
216 | $file = sugar_cached('modules/').$module_dir.'/' . $object_name . 'vardefs.php'; |
||
217 | |||
218 | if(file_exists($file)){ |
||
219 | unlink($file); |
||
220 | $key = "VardefManager.$module_dir.$object_name"; |
||
221 | sugar_cache_clear($key); |
||
222 | } |
||
223 | } |
||
224 | } |
||
225 | |||
226 | /** |
||
227 | * Given a module, search all of the specified locations, and any others as specified |
||
228 | * in order to refresh the cache file |
||
229 | * |
||
230 | * @param string $module the given module we want to load the vardefs for |
||
231 | * @param string $object the given object we wish to load the vardefs for |
||
232 | * @param array $additional_search_paths an array which allows a consumer to pass in additional vardef locations to search |
||
233 | */ |
||
234 | 848 | static function refreshVardefs($module, $object, $additional_search_paths = null, $cacheCustom = true, $params = array()){ |
|
235 | // Some of the vardefs do not correctly define dictionary as global. Declare it first. |
||
236 | 848 | global $dictionary, $beanList; |
|
237 | $vardef_paths = array( |
||
238 | 848 | 'modules/'.$module.'/vardefs.php', |
|
239 | 848 | 'custom/modules/'.$module.'/Ext/Vardefs/vardefs.ext.php', |
|
240 | 848 | 'custom/Extension/modules/'.$module.'/Ext/Vardefs/vardefs.php' |
|
241 | ); |
||
242 | |||
243 | // Add in additional search paths if they were provided. |
||
244 | 848 | if(!empty($additional_search_paths) && is_array($additional_search_paths)) |
|
245 | { |
||
246 | $vardef_paths = array_merge($vardef_paths, $additional_search_paths); |
||
247 | } |
||
248 | 848 | $found = false; |
|
249 | //search a predefined set of locations for the vardef files |
||
250 | 848 | foreach($vardef_paths as $path){ |
|
251 | 848 | if(file_exists($path)){ |
|
252 | 847 | require($path); |
|
253 | 848 | $found = true; |
|
254 | } |
||
255 | } |
||
256 | //Some modules have multiple beans, we need to see if this object has a module_dir that is different from its module_name |
||
257 | 848 | if(!$found){ |
|
258 | 10 | $temp = BeanFactory::newBean($module); |
|
259 | 10 | if ($temp) |
|
260 | { |
||
261 | 1 | $object_name = BeanFactory::getObjectName($temp->module_dir); |
|
262 | 1 | if ($temp && $temp->module_dir != $temp->module_name && !empty($object_name)) |
|
263 | { |
||
264 | self::refreshVardefs($temp->module_dir, $object_name, $additional_search_paths, $cacheCustom); |
||
265 | } |
||
266 | } |
||
267 | } |
||
268 | |||
269 | //Some modules like cases have a bean name that doesn't match the object name |
||
270 | 848 | if (empty($dictionary[$object])) { |
|
271 | 19 | $newName = BeanFactory::getObjectName($module); |
|
272 | 19 | $object = $newName != false ? $newName : $object; |
|
0 ignored issues
–
show
|
|||
273 | } |
||
274 | |||
275 | //load custom fields into the vardef cache |
||
276 | 848 | if($cacheCustom){ |
|
277 | 171 | require_once("modules/DynamicFields/DynamicField.php"); |
|
278 | 171 | $df = new DynamicField ($module) ; |
|
279 | 171 | $df->buildCache($module, false); |
|
280 | } |
||
281 | |||
282 | //great! now that we have loaded all of our vardefs. |
||
283 | //let's go save them to the cache file. |
||
284 | 848 | if(!empty($dictionary[$object])) { |
|
285 | 844 | VardefManager::saveCache($module, $object); |
|
0 ignored issues
–
show
It seems like
$object defined by $newName != false ? $newName : $object on line 272 can also be of type boolean ; however, VardefManager::saveCache() does only seem to accept string , maybe add an additional type check?
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check: /**
* @return array|string
*/
function returnsDifferentValues($x) {
if ($x) {
return 'foo';
}
return array();
}
$x = returnsDifferentValues($y);
if (is_array($x)) {
// $x is an array.
}
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue. ![]() |
|||
286 | } |
||
287 | 848 | } |
|
288 | |||
289 | /** |
||
290 | * @static |
||
291 | * @param $module |
||
292 | * @param $object |
||
293 | * @return array|bool returns a list of all fields in the module of type 'link'. |
||
294 | */ |
||
295 | 69 | protected static function getLinkFieldsForModule($module, $object) |
|
296 | { |
||
297 | 69 | global $dictionary; |
|
298 | //Some modules like cases have a bean name that doesn't match the object name |
||
299 | 69 | if (empty($dictionary[$object])) { |
|
300 | 39 | $newName = BeanFactory::getObjectName($module); |
|
301 | 39 | $object = $newName != false ? $newName : $object; |
|
0 ignored issues
–
show
|
|||
302 | } |
||
303 | 69 | if (empty($dictionary[$object])) { |
|
304 | 39 | self::loadVardef($module, $object, false, array('ignore_rel_calc_fields' => true)); |
|
305 | } |
||
306 | 69 | if (empty($dictionary[$object])) |
|
307 | { |
||
308 | 2 | $GLOBALS['log']->debug("Failed to load vardefs for $module:$object in linkFieldsForModule<br/>"); |
|
309 | 2 | return false; |
|
310 | } |
||
311 | |||
312 | //Cache link fields for this call in a static variable |
||
313 | 69 | if (!isset(self::$linkFields)) |
|
314 | 1 | self::$linkFields = array(); |
|
315 | |||
316 | 69 | if (isset(self::$linkFields[$object])) |
|
317 | 66 | return self::$linkFields[$object]; |
|
318 | |||
319 | 28 | $vardef = $dictionary[$object]; |
|
320 | 28 | $links = array(); |
|
321 | 28 | foreach($vardef['fields'] as $name => $def) |
|
322 | { |
||
323 | //Look through all link fields for related modules that have calculated fields that use that relationship |
||
324 | 28 | if(!empty($def['type']) && $def['type'] == 'link' && !empty($def['relationship'])) |
|
325 | { |
||
326 | 28 | $links[$name] = $def; |
|
327 | } |
||
328 | } |
||
329 | |||
330 | 28 | self::$linkFields[$object] = $links; |
|
331 | |||
332 | 28 | return $links; |
|
333 | } |
||
334 | |||
335 | |||
336 | 126 | public static function getLinkFieldForRelationship($module, $object, $relName) |
|
337 | { |
||
338 | 126 | $cacheKey = "LFR{$module}{$object}{$relName}"; |
|
339 | 126 | $cacheValue = sugar_cache_retrieve($cacheKey); |
|
340 | 126 | if(!empty($cacheValue)) |
|
341 | 108 | return $cacheValue; |
|
342 | |||
343 | 69 | $relLinkFields = self::getLinkFieldsForModule($module, $object); |
|
344 | 69 | $matches = array(); |
|
345 | 69 | if (!empty($relLinkFields)) |
|
346 | { |
||
347 | 68 | foreach($relLinkFields as $rfName => $rfDef) |
|
0 ignored issues
–
show
The expression
$relLinkFields of type array|boolean is not guaranteed to be traversable. How about adding an additional type check?
There are different options of fixing this problem.
![]() |
|||
348 | { |
||
349 | 68 | if ($rfDef['relationship'] == $relName) |
|
350 | { |
||
351 | 68 | $matches[] = $rfDef; |
|
352 | } |
||
353 | } |
||
354 | } |
||
355 | 69 | if (empty($matches)) |
|
356 | 59 | return false; |
|
357 | 49 | if (sizeof($matches) == 1) |
|
358 | 49 | $results = $matches[0]; |
|
359 | else |
||
360 | //For relationships where both sides are the same module, more than one link will be returned |
||
361 | 5 | $results = $matches; |
|
362 | |||
363 | 49 | sugar_cache_put($cacheKey, $results); |
|
364 | 49 | return $results ; |
|
365 | } |
||
366 | |||
367 | |||
368 | |||
369 | /** |
||
370 | * applyGlobalAccountRequirements |
||
371 | * |
||
372 | * This method ensures that the account_name relationships are set to always be required if the configuration file specifies |
||
373 | * so. For more information on this require_accounts parameter, please see the administrators guide or go to the |
||
374 | * developers.sugarcrm.com website to find articles relating to the use of this field. |
||
375 | * |
||
376 | * @param Array $vardef The vardefs of the module to apply the account_name field requirement to |
||
377 | * @return Array $vardef The vardefs of the module with the updated required setting based on the system configuration |
||
378 | */ |
||
379 | 228 | static function applyGlobalAccountRequirements($vardef) |
|
380 | { |
||
381 | 228 | if (isset($GLOBALS['sugar_config']['require_accounts'])) |
|
382 | { |
||
383 | 228 | if (isset($vardef['fields']) |
|
384 | 228 | && isset($vardef['fields']['account_name']) |
|
385 | 228 | && isset($vardef['fields']['account_name']['type']) |
|
386 | 228 | && $vardef['fields']['account_name']['type'] == 'relate' |
|
387 | 228 | && isset($vardef['fields']['account_name']['required'])) |
|
388 | { |
||
389 | 17 | $vardef['fields']['account_name']['required'] = $GLOBALS['sugar_config']['require_accounts']; |
|
390 | } |
||
391 | |||
392 | } |
||
393 | 228 | return $vardef; |
|
394 | } |
||
395 | |||
396 | |||
397 | /** |
||
398 | * load the vardefs for a given module and object |
||
399 | * @param string $module the given module we want to load the vardefs for |
||
400 | * @param string $object the given object we wish to load the vardefs for |
||
401 | * @param bool $refresh whether or not we wish to refresh the cache file. |
||
402 | */ |
||
403 | 228 | static function loadVardef($module, $object, $refresh=false, $params = array()){ |
|
404 | //here check if the cache file exists, if it does then load it, if it doesn't |
||
405 | //then call refreshVardef |
||
406 | //if either our session or the system is set to developerMode then refresh is set to true |
||
407 | 228 | if(inDeveloperMode() || !empty($_SESSION['developerMode'])){ |
|
408 | $refresh = true; |
||
409 | } |
||
410 | // Retrieve the vardefs from cache. |
||
411 | 228 | $key = "VardefManager.$module.$object"; |
|
412 | |||
413 | 228 | if(!$refresh) |
|
414 | { |
||
415 | 110 | $return_result = sugar_cache_retrieve($key); |
|
416 | 110 | $return_result = self::applyGlobalAccountRequirements($return_result); |
|
417 | |||
418 | 110 | if(!empty($return_result)) |
|
419 | { |
||
420 | 107 | $GLOBALS['dictionary'][$object] = $return_result; |
|
421 | 107 | return; |
|
422 | } |
||
423 | } |
||
424 | |||
425 | // Some of the vardefs do not correctly define dictionary as global. Declare it first. |
||
426 | 167 | global $dictionary; |
|
427 | 167 | if(empty($GLOBALS['dictionary'][$object]) || $refresh){ |
|
428 | //if the consumer has demanded a refresh or the cache/modules... file |
||
429 | //does not exist, then we should do out and try to reload things |
||
430 | |||
431 | 166 | $cachedfile = sugar_cached('modules/'). $module . '/' . $object . 'vardefs.php'; |
|
432 | 166 | if($refresh || !file_exists($cachedfile)){ |
|
433 | 166 | VardefManager::refreshVardefs($module, $object, null, true, $params); |
|
434 | } |
||
435 | |||
436 | //at this point we should have the cache/modules/... file |
||
437 | //which was created from the refreshVardefs so let's try to load it. |
||
438 | 166 | if(file_exists($cachedfile)) |
|
439 | { |
||
440 | 157 | if (is_readable($cachedfile)) |
|
441 | { |
||
442 | 157 | include($cachedfile); |
|
443 | } |
||
444 | // now that we hae loaded the data from disk, put it in the cache. |
||
445 | 157 | if(!empty($GLOBALS['dictionary'][$object])) |
|
446 | { |
||
447 | 157 | $GLOBALS['dictionary'][$object] = self::applyGlobalAccountRequirements($GLOBALS['dictionary'][$object]); |
|
448 | 157 | sugar_cache_put($key,$GLOBALS['dictionary'][$object]); |
|
449 | } |
||
450 | } |
||
451 | } |
||
452 | 167 | } |
|
453 | |||
454 | } |
||
455 |
This check marks calls to
isset(...)
orempty(...)
that are found before the variable itself is defined. These will always have the same result.This is likely the result of code being shifted around. Consider removing these calls.