Issues (4069)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

modules/UpgradeWizard/upgradeMetaHelper.php (16 issues)

Upgrade to new PHP Analysis Engine

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
41
42
class UpgradeMetaHelper{
43
44
	var $upgrade_dir;
45
	var $debug_mode;
46
	var $upgrade_modules;
47
	var $customized_modules;
48
	var $source_dir;
49
	var $dest_dir ;
50
	var $evparser;
51
	var $dvparser;
52
	var $path_to_master_copy;
53
	/**
54
	 * UpgradeMetaHelper
55
	 * This is the constructor for the UpgradeMetaHelper class
56
	 * @param $dir The root upgrade directory (where to copy working files)
57
	 * @param $masterCopyDirectory The root master directory (where SugarCRM 5.x files reside)
58
	 * @param $debugMode Debug mode, default is false
59
	 *
60
	 */
61
	function __construct($dir='upgrade', $masterCopyDirecotry='modules_50', $debugMode = false) {
62
		$this->upgrade_dir = $dir;
63
		$this->debug_mode = $debugMode;
64
		$this->upgrade_modules = $this->getModifiedModules();
65
66
		if(count($this->upgrade_modules) > 0) {
67
			$_SESSION['Upgraded_Modules'] = $this->upgrade_modules;
68
			$this->create_upgrade_directory();
69
			$this->path_to_master_copy = $masterCopyDirecotry;
70
		    $this->runParser();
71
		}
72
73
		$this->customized_modules = $this->getAllCustomizedModulesBeyondStudio();
74
		if(count($this->customized_modules) > 0) {
75
			$_SESSION['Customized_Modules'] = $this->customized_modules;
76
		}
77
	}
78
79
	/**
80
	 * @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
81
	 */
82
	function UpgradeMetaHelper($dir='upgrade', $masterCopyDirecotry='modules_50', $debugMode = false){
83
		$deprecatedMessage = 'PHP4 Style Constructors are deprecated and will be remove in 7.8, please update your code';
84
		if(isset($GLOBALS['log'])) {
85
			$GLOBALS['log']->deprecated($deprecatedMessage);
86
		}
87
		else {
88
			trigger_error($deprecatedMessage, E_USER_DEPRECATED);
89
		}
90
		self::__construct($dir, $masterCopyDirecotry, $debugMode);
91
	}
92
93
	/**
94
	 * getModifiedModules
95
	 * This method returns a two-dimensional Array of Studio enabled
96
	 * modules that have been modified.  The second Array index is an
97
	 * Array of files that do not match the md5 checksum for the module
98
	 * @return $return_array Two-dimensional Array of [module][modified file(s) Array]
0 ignored issues
show
The doc-type $return_array could not be parsed: Unknown type name "$return_array" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
99
	 */
100
		function getModifiedModules() {
101
102
		$md5_string = array();
103
		if(file_exists(clean_path(getcwd().'/files.md5'))){
104
			require(clean_path(getcwd().'/files.md5'));
105
		}
106
107
	    $return_array = array();
108
	    $modules = $this->loadStudioModules();
109
	    foreach($modules as $mod) {
110
111
	    	   $editView = "modules/$mod/EditView.html";
112
	    	   $detailView = "modules/$mod/DetailView.html";
113
	    	   $searchForm = "modules/$mod/SearchForm.html";
114
               if(file_exists($editView) && isset($md5_string['./' . $editView])) {
115
               	  $fileContents = file_get_contents($editView);
116
               	  if(md5($fileContents) != $md5_string['./' . $editView]) {
117
               	  	 $return_array[$mod][] = $editView;
118
               	  }
119
               }
120
121
               if(file_exists($detailView) && isset($md5_string['./' . $detailView])) {
122
               	  $fileContents = file_get_contents($detailView);
123
               	  if(md5($fileContents) != $md5_string['./' . $detailView]) {
124
               	  	 $return_array[$mod][] = $detailView;
125
               	  }
126
               }
127
128
               if(file_exists($searchForm) && isset($md5_string['./' . $searchForm])) {
129
               	  $fileContents = file_get_contents($searchForm);
130
               	  if(md5($fileContents) != $md5_string['./' . $searchForm]) {
131
               	  	 $return_array[$mod][] = $searchForm;
132
               	  }
133
               }
134
135
	    } //foreach
136
137
		return $return_array;
138
	}
139
140
function saveMatchingFilesQueries($currStep,$value){
141
	$upgrade_progress_dir = sugar_cached('upgrades/temp');
142
	if(!is_dir($upgrade_progress_dir)){
143
		mkdir($upgrade_progress_dir);
144
	}
145
	$file_queries_file = $upgrade_progress_dir.'/files_queries.php';
146
	if(file_exists($file_queries_file)){
147
		include($file_queries_file);
148
	}
149
	else{
150
		if(function_exists('sugar_fopen')){
151
			sugar_fopen($file_queries_file, 'w+');
152
		}
153
		else{
154
			fopen($file_queries_file, 'w+');
155
		}
156
	}
157
	if(!isset($files_queries) || $files_queries == NULL){
0 ignored issues
show
The variable $files_queries seems only to be defined at a later point. As such the call to isset() seems to always evaluate to false.

This check marks calls to isset(...) or empty(...) 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.

Loading history...
158
		$files_queries = array();
159
	}
160
	$files_queries[$currStep]=$value;
161
	if(is_writable($file_queries_file) && write_array_to_file( "file_queries", $file_queries,
0 ignored issues
show
The variable $file_queries does not exist. Did you mean $file_queries_file?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
162
		$file_queries_file)) {
163
	       //writing to the file
164
	}
165
}
166
167
function getAllCustomizedModulesBeyondStudio() {
168
169
	require_once('modules/UpgradeWizard/uw_utils.php');
170
	$md5_string = array();
171
	if(file_exists(clean_path(getcwd().'/files.md5'))){
172
		require(clean_path(getcwd().'/files.md5'));
173
	}
174
    $return_array = array();
175
    $modules = $this->loadStudioModules();
176
    $modulesAll = getAllModules(); //keep all modules as well
177
    $allOtherModules = array_diff($modulesAll,$modules);
178
    foreach($modules as $mod) {
179
	  if(!is_dir('modules/'.$mod)) continue;
180
	  $editView = "modules/$mod/EditView.html";
181
	  $detailView ="modules/$mod/DetailView.html";
182
	  $exclude_files[]=$editView;
183
	  $exclude_files[]=$detailView;
184
	  $allModFiles = array();
185
	  $allModFiles = findAllFiles('modules/'.$mod,$allModFiles);
186
	   foreach($allModFiles as $file){
187
	       //$file_md5_ref = str_replace(clean_path(getcwd()),'',$file);
188
		  if(file_exists($file) && !in_array($file,$exclude_files)){
189
			if(isset($md5_string['./'.$file])) {
190
		       	  $fileContents = file_get_contents($file);
191
		       	  if(md5($fileContents) != $md5_string['./'.$file]) {
192
		       	  	$return_array[$mod][] = $file;
193
		       	  }
194
		       	  else{
195
		       	  	//keep in the array to be deleted later
196
		       	  	$_SESSION['removeMd5MatchingFiles'][] = $file;
197
		               	  }
198
		           }
199
		      }
200
		  }
201
    } //foreach
202
    //also check out other non-studio modules by taking the difference between
203
    //allMOdules and
204
  foreach($allOtherModules as $mod) {
205
	  if(!is_dir('modules/'.$mod)) continue;
206
	  $allModFiles = array();
207
      $allModFiles = findAllFiles('modules/'.$mod,$allModFiles);
208
      foreach($allModFiles as $file){
209
           	//$file_md5_ref = str_replace(clean_path(getcwd()),'',$file);
210
           	if(file_exists($file)){
211
           		if(isset($md5_string['./'.$file])) {
212
	               	  $fileContents = file_get_contents($file);
213
	               	  if(md5($fileContents) == $md5_string['./'.$file]) {
214
	               	  	$_SESSION['removeMd5MatchingFiles'][] = $file;
215
	               	  }
216
               }
217
          }
218
      }
219
  }
220
   //Also store in a file
221
   //saveMatchingFilesQueries('removeMd5MatchingFiles',$_SESSION['removeMd5MatchingFiles']);
222
	return $return_array;
223
}
224
225
226
227
/**
228
 * Get all the customized modules. Compare the file md5s with the base md5s
229
 * If a file has been modified then put the module in the list of customized
230
 * modules. Show the list in the preflight check UI.
231
 */
232
function getAllCustomizedModules() {
233
234
		require_once('files.md5');
235
236
	    $return_array = array();
237
	    $modules = getAllModules();
238
	    foreach($modules as $mod) {
239
	    	   //find all files in each module if the files have been modified
240
	    	   //as compared to the base version then add the module to the
241
	    	   //customized modules array
242
	    	   $modFiles = findAllFiles(clean_path(getcwd())."/modules/$mod", array());
243
               foreach($modFiles as $file){
244
             	  $fileContents = file_get_contents($file);
245
             	   $file = str_replace(clean_path(getcwd()),'',$file);
246
               	  if($md5_string['./' . $file]){
247
	               	  if(md5($fileContents) != $md5_string['./' . $file]) {
248
	               	     //A file has been customized in the module. Put the module into the
249
	               	     // customized modules array.
250
	               	     echo 'Changed File'.$file;
251
	               	  	  $return_array[$mod];
252
	               	  	  break;
253
	               	  }
254
               	  }
255
               	  else{
256
               	  	// This is a new file in user's version and indicates that module has been
257
               	  	//customized. Put the module in the customized array.
258
                       echo 'New File'.$file;
259
                       $return_array[$mod];
260
                       break;
261
               	  }
262
               }
263
	    } //foreach
264
265
		return $return_array;
266
	}
267
268
    /**
269
     * loadStudioModules
270
     * This method returns an Array of all modules where a studio.php file is
271
     * present in the metadata directory of the module
272
     * @return $modules Array of modules that are studio enabled
0 ignored issues
show
The doc-type $modules could not be parsed: Unknown type name "$modules" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
273
     */
274
	function loadStudioModules() {
275
		$modules = array();
276
		$d = dir('modules');
277
		while($e = $d->read()){
278
			if(substr($e, 0, 1) == '.' || !is_dir('modules/' . $e))continue;
279
			if(file_exists('modules/' . $e . '/metadata/studio.php')){
280
			   $modules[] = $e;
281
			}
282
		}
283
		return $modules;
284
	}
285
286
287
	/**
288
	 * runParser
289
	 * This method creates the EditView and DetailView parser intances
290
	 * and runs the parsing for the modules to upgrade
291
	 *
292
	 */
293
	function runParser() {
294
		require_once('include/SugarFields/Parsers/EditViewMetaParser.php');
295
		require_once('include/SugarFields/Parsers/DetailViewMetaParser.php');
296
		require_once('include/SugarFields/Parsers/SearchFormMetaParser.php');
297
298
		$this->evparser = new EditViewMetaParser();
299
		$this->dvparser = new DetailViewMetaParser();
300
		$this->svparser = new SearchFormMetaParser();
301
302
		foreach($this->upgrade_modules as $module_name=>$files) {
303
			$this->parseFile($module_name, $files);
304
		} //foreach
305
	}
306
307
308
	/**
309
	 * parseFile
310
	 * Hanldes parsing the files for given module where Studio or manual
311
	 * changes have been detected.
312
	 * @param $module_name The module to parse
313
	 * @param $files Array of files found to parse
314
	 *
315
	 */
316
	function parseFile($module_name, $files) {
317
		global $beanList, $dictionary;
318
		foreach($files as $file) {
319
                if(preg_match('/(EditView|DetailView|SearchForm|QuickCreate)(\.html|\.tpl)$/s', $file, $matches)) {
320
                    $view = $matches[1];
321
322
                    switch($view) {
323
                       case 'EditView' : $parser = $this->evparser; break;
0 ignored issues
show
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
324
                       case 'DetailView' : $parser = $this->dvparser; break;
0 ignored issues
show
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
325
                       case 'SearchForm' : $parser = $this->svparser; break;
0 ignored issues
show
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
326
                    }
327
328
                    $lowerCaseView = $view == 'SearchForm' ? 'search' : strtolower($view);
329
330
					include('modules/'.$module_name.'/vardefs.php');
331
					$bean_name = $beanList[$module_name];
332
					$newFile = $this->upgrade_dir.'/modules/'.$module_name.'/metadata/'.$lowerCaseView.'defs.php';
333
					$evfp = fopen($newFile,'w');
334
335
					$bean_name = $bean_name == 'aCase' ? 'Case' : $bean_name;
336
					fwrite($evfp, $parser->parse($file,
337
											$dictionary[$bean_name]['fields'],
338
											$module_name,
339
											true,
340
											$this->path_to_master_copy.'/modules/'.$module_name.'/metadata/'.$lowerCaseView.'defs.php'));
341
					fclose($evfp);
342
                } //if
343
		} //foreach
344
	}
345
346
347
	/**
348
	 * create_upgrade_directory
349
	 * Creates a directory called upgrade to house all the modules that are studio enabled.
350
	 * Also creates subdirectories for all studio enabled modules.
351
	 *
352
	 */
353
	function create_upgrade_directory() {
354
355
		$dir = $this->upgrade_dir.'/modules';
356
		if(!file_exists($this->upgrade_dir)) {
357
			mkdir($this->upgrade_dir, 0755);
358
		}
359
		if(!file_exists($dir)) {
360
			mkdir($dir, 0755);
361
		}
362
363
		foreach($this->upgrade_modules as $module=>$files){
364
			if(!file_exists($dir.'/'.$module)) {
365
				mkdir($dir.'/'.$module, 0755);
366
			}
367
			if(!file_exists($dir.'/'.$module.'/metadata')) {
368
				mkdir($dir.'/'.$module.'/metadata', 0755);
369
			}
370
371
			foreach($files as $file) {
372
				if(file_exists($file) && is_file($file)) {
373
				   copy($file, $this->upgrade_dir.'/'.$file);
374
				} //if
375
			} //foreach
376
		}
377
	}
378
379
380
	/**
381
	 * verifyMetaData
382
	 * This function does some quick checks to make sure the metadataFile at
383
	 * least has an Array panel
384
	 *
385
	 * @param $metadataFile The path to the metadata file to verify
386
	 * @param $module The module to verify
387
	 * @param $view The view (EditView or DetailView)
388
	 * @return boolean true if verification check is okay; false otherwise
389
	 */
390
	function verifyMetaData($metadataFile, $module, $view) {
391
	    if(!file_exists($metadataFile) || !is_file($metadataFile)) {
392
	       return false;
393
	    }
394
395
	    include($metadataFile);
396
397
	    if(isset($viewdefs) && isset($viewdefs[$module][$view]['panels']) && is_array($viewdefs[$module][$view]['panels'])) {
0 ignored issues
show
The variable $viewdefs seems to never exist, and therefore isset should always return false. Did you maybe rename this variable?

This check looks for calls to isset(...) or empty() on variables that are yet undefined. These calls will always produce the same result and can be removed.

This is most likely caused by the renaming of a variable or the removal of a function/method parameter.

Loading history...
398
	       return true;
399
	    }
400
401
        if(isset($searchdefs) && isset($searchdefs[$module]) &&  is_array($searchdefs[$module])) {
0 ignored issues
show
The variable $searchdefs seems to never exist, and therefore isset should always return false. Did you maybe rename this variable?

This check looks for calls to isset(...) or empty() on variables that are yet undefined. These calls will always produce the same result and can be removed.

This is most likely caused by the renaming of a variable or the removal of a function/method parameter.

Loading history...
402
           return true;
403
        }
404
405
	    return false;
406
	}
407
}
408
409
?>